@@ -576,7 +576,7 @@ void respond(Request request, ResponseBuilder *b)
576576 return ;
577577 }
578578
579- if (serve_file_or_dir (b , LIT ("/ " ), LIT ("docroot/ " ), request .path , NULLSTR , false))
579+ if (serve_file_or_dir (b , LIT ("" ), LIT ("docroot" ), request .path , NULLSTR , false))
580580 return ;
581581
582582 status_line (b , 404 );
@@ -1885,10 +1885,50 @@ string mimetype_from_filename(string name)
18851885 return NULLSTR ;
18861886}
18871887
1888+ void serve_file (string path , size_t size , string mime , ResponseBuilder * b )
1889+ {
1890+ int fd ;
1891+ do
1892+ fd = open (path .data , O_RDONLY );
1893+ while (fd < 0 && errno == EINTR );
1894+
1895+ if (fd < 0 ) {
1896+ status_line (b , 500 );
1897+ close (fd );
1898+ return ;
1899+ }
1900+
1901+ status_line (b , 200 );
1902+
1903+ if (mime .size == 0 ) mime = mimetype_from_filename (path );
1904+ if (mime .size > 0 ) add_header_f (b , "Content-Type: %.*s" , (int ) mime .size , mime .data );
1905+
1906+ string dst = append_content_start (b , size );
1907+ if (dst .size == 0 ) {
1908+ status_line (b , 500 );
1909+ close (fd );
1910+ return ;
1911+ }
1912+ assert (dst .size >= size );
1913+
1914+ size_t copied = 0 ;
1915+ while (copied < size ) {
1916+ int num = read (fd , dst .data + copied , size - copied );
1917+ if (num <= 0 ) {
1918+ if (num < 0 )
1919+ log_format ("Failed reading from '%.*s'\n" , (int ) path .size , path .data );
1920+ break ;
1921+ }
1922+ copied += num ;
1923+ }
1924+
1925+ append_content_end (b , copied );
1926+ close (fd );
1927+ }
1928+
18881929bool serve_file_or_dir (ResponseBuilder * b , string prefix , string docroot ,
18891930 string reqpath , string mime , bool enable_dir_listing )
18901931{
1891-
18921932 // Sanitize the request path
18931933 char pathmem [1 <<10 ];
18941934 string path ;
@@ -1927,77 +1967,66 @@ bool serve_file_or_dir(ResponseBuilder *b, string prefix, string docroot,
19271967 return true;
19281968 }
19291969
1930- if (S_ISREG (buf .st_mode )) {
1970+ if (S_ISDIR (buf .st_mode )) {
19311971
1932- int fd ;
1933- do
1934- fd = open (path .data , O_RDONLY );
1935- while (fd < 0 && errno == EINTR );
1972+ if (enable_dir_listing ) {
19361973
1937- if ( fd < 0 ) {
1938- status_line ( b , 500 );
1939- close ( fd );
1940- return true;
1941- }
1974+ DIR * d = opendir ( path . data );
1975+ if ( d == NULL ) {
1976+ status_line ( b , 500 );
1977+ return true;
1978+ }
19421979
1943- status_line (b , 200 );
1980+ status_line (b , 200 );
1981+ append_content_s (b , LIT (
1982+ "<html>\n"
1983+ " <head>\n"
1984+ " </head>\n"
1985+ " <body>\n"
1986+ " <ul>\n"
1987+ " <li><a href=\"\">(parent)</a></li>" )); // TODO: Add links
1988+
1989+ struct dirent * dir ;
1990+ while ((dir = readdir (d ))) {
1991+ if (!strcmp (dir -> d_name , "." ) || !strcmp (dir -> d_name , ".." ))
1992+ continue ;
1993+ append_content_f (b , "<li><a href=\"\">%s</a></li>\n" , dir -> d_name ); // TODO: Add links
1994+ }
19441995
1945- if (mime .size == 0 ) mime = mimetype_from_filename (path );
1946- if (mime .size > 0 ) add_header_f (b , "Content-Type: %.*s" , (int ) mime .size , mime .data );
1996+ append_content_s (b , LIT (
1997+ " </ul>\n"
1998+ " </body>\n"
1999+ "</html>\n" ));
2000+ closedir (d );
2001+ } else {
19472002
1948- string dst = append_content_start (b , (size_t ) buf .st_size );
1949- if (dst .size == 0 ) {
1950- status_line (b , 500 );
1951- close (fd );
1952- return true;
1953- }
1954- assert (dst .size >= (size_t ) buf .st_size );
2003+ // Append /index.html to the path
2004+ if (path .size + SIZEOF ("/index.html" )- 1 >= sizeof (pathmem )) {
2005+ status_line (b , 500 );
2006+ return true;
2007+ }
2008+ memcpy (path .data + path .size , "/index.html" , SIZEOF ("/index.html" )- 1 );
2009+ path .size += SIZEOF ("/index.html" )- 1 ;
2010+ path .data [path .size ] = '\0' ;
19552011
1956- size_t copied = 0 ;
1957- while (copied < (size_t ) buf .st_size ) {
1958- int num = read (fd , dst .data + copied , (size_t ) buf .st_size - copied );
1959- if (num <= 0 ) {
1960- if (num < 0 )
1961- log_format ("Failed reading from '%.*s'\n" , (int ) path .size , path .data );
1962- break ;
2012+ if (stat (path .data , & buf )) {
2013+ if (errno == ENOENT )
2014+ return false;
2015+ status_line (b , 500 );
2016+ return true;
2017+ }
2018+ if (!S_ISREG (buf .st_mode )) {
2019+ status_line (b , 500 );
2020+ return true;
19632021 }
1964- copied += num ;
1965- }
19662022
1967- append_content_end ( b , copied );
1968- close ( fd );
2023+ serve_file ( path , ( size_t ) buf . st_size , mime , b );
2024+ }
19692025 return true;
19702026 }
19712027
1972- if (enable_dir_listing && S_ISDIR (buf .st_mode )) {
1973-
1974- DIR * d = opendir (path .data );
1975- if (d == NULL ) {
1976- status_line (b , 500 );
1977- return true;
1978- }
1979-
1980- status_line (b , 200 );
1981- append_content_s (b , LIT (
1982- "<html>\n"
1983- " <head>\n"
1984- " </head>\n"
1985- " <body>\n"
1986- " <ul>\n"
1987- " <li><a href=\"\">(parent)</a></li>" )); // TODO: Add links
1988-
1989- struct dirent * dir ;
1990- while ((dir = readdir (d ))) {
1991- if (!strcmp (dir -> d_name , "." ) || !strcmp (dir -> d_name , ".." ))
1992- continue ;
1993- append_content_f (b , "<li><a href=\"\">%s</a></li>\n" , dir -> d_name ); // TODO: Add links
1994- }
1995-
1996- append_content_s (b , LIT (
1997- " </ul>\n"
1998- " </body>\n"
1999- "</html>\n" ));
2000- closedir (d );
2028+ if (S_ISREG (buf .st_mode )) {
2029+ serve_file (path , (size_t ) buf .st_size , mime , b );
20012030 return true;
20022031 }
20032032
0 commit comments