[mod_dirlisting] place vars closer to where used

allocate memory for PATH_MAX to avoid pathconf() for _PC_NAME_MAX
This commit is contained in:
Glenn Strauss 2020-12-29 08:56:01 -05:00
parent 2f303d8205
commit dfe471b77c
1 changed files with 41 additions and 60 deletions

View File

@ -813,45 +813,24 @@ static void http_list_directory_footer(const request_st * const r, plugin_data *
}
static int http_list_directory(request_st * const r, plugin_data * const p, buffer * const dir) {
DIR *dp;
buffer *out;
struct dirent *dent;
struct stat st;
char *path, *path_file;
size_t i;
int hide_dotfiles = p->conf.hide_dot_files;
dirls_list_t dirs, files, *list;
dirls_entry_t *tmp;
char sizebuf[sizeof("999.9K")];
const buffer *content_type;
long name_max;
log_error_st * const errh = r->conf.errh;
struct tm tm;
if (buffer_string_is_empty(dir)) return -1;
i = buffer_string_length(dir);
#ifdef HAVE_PATHCONF
if (0 >= (name_max = pathconf(dir->ptr, _PC_NAME_MAX))) {
/* some broken fs (fuse) return 0 instead of -1 */
#ifdef NAME_MAX
name_max = NAME_MAX;
const uint32_t dlen = buffer_string_length(dir);
#if defined __WIN32
const uint32_t name_max = FILENAME_MAX;
#else
name_max = 255; /* stupid default */
#ifndef PATH_MAX
#define PATH_MAX 4096
#endif
}
#elif defined __WIN32
name_max = FILENAME_MAX;
#else
name_max = NAME_MAX;
/* allocate based on PATH_MAX rather than pathconf() to get _PC_NAME_MAX */
const uint32_t name_max = PATH_MAX - dlen - 1;
#endif
path = malloc(i + name_max + 1);
char * const path = malloc(dlen + name_max + 1);
force_assert(NULL != path);
memcpy(path, dir->ptr, i+1);
path_file = path + i;
memcpy(path, dir->ptr, dlen+1);
char *path_file = path + dlen;
log_error_st * const errh = r->conf.errh;
DIR *dp;
struct dirent *dent;
if (NULL == (dp = opendir(path))) {
log_error(errh, __FILE__, __LINE__,
"opendir failed: %s", dir->ptr);
@ -860,6 +839,7 @@ static int http_list_directory(request_st * const r, plugin_data * const p, buff
return -1;
}
dirls_list_t dirs, files;
dirs.ent = (dirls_entry_t**) malloc(sizeof(dirls_entry_t*) * DIRLIST_BLOB_SIZE);
force_assert(dirs.ent);
dirs.size = DIRLIST_BLOB_SIZE;
@ -869,60 +849,58 @@ static int http_list_directory(request_st * const r, plugin_data * const p, buff
files.size = DIRLIST_BLOB_SIZE;
files.used = 0;
const int hide_dotfiles = p->conf.hide_dot_files;
struct stat st;
while ((dent = readdir(dp)) != NULL) {
if (dent->d_name[0] == '.') {
const char * const d_name = dent->d_name;
if (d_name[0] == '.') {
if (hide_dotfiles)
continue;
if (dent->d_name[1] == '\0')
if (d_name[1] == '\0')
continue;
if (dent->d_name[1] == '.' && dent->d_name[2] == '\0')
if (d_name[1] == '.' && d_name[2] == '\0')
continue;
}
if (p->conf.hide_readme_file && !buffer_string_is_empty(p->conf.show_readme)) {
if (strcmp(dent->d_name, p->conf.show_readme->ptr) == 0)
if (strcmp(d_name, p->conf.show_readme->ptr) == 0)
continue;
}
if (p->conf.hide_header_file && !buffer_string_is_empty(p->conf.show_header)) {
if (strcmp(dent->d_name, p->conf.show_header->ptr) == 0)
if (strcmp(d_name, p->conf.show_header->ptr) == 0)
continue;
}
i = strlen(dent->d_name);
const uint32_t dsz = (uint32_t)strlen(d_name);
/* compare d_name against excludes array
* elements, skipping any that match.
*/
if (p->conf.excludes
&& mod_dirlisting_exclude(errh, p->conf.excludes, dent->d_name, i))
&& mod_dirlisting_exclude(errh, p->conf.excludes, d_name, dsz))
continue;
/* NOTE: the manual says, d_name is never more than NAME_MAX
* so this should actually not be a buffer-overflow-risk
*/
if (i > (size_t)name_max) continue;
if (dsz > name_max) continue;
memcpy(path_file, dent->d_name, i + 1);
memcpy(path_file, d_name, dsz + 1);
if (stat(path, &st) != 0)
continue;
list = &files;
if (S_ISDIR(st.st_mode))
list = &dirs;
dirls_list_t * const list = !S_ISDIR(st.st_mode) ? &files : &dirs;
if (list->used == list->size) {
list->size += DIRLIST_BLOB_SIZE;
list->ent = (dirls_entry_t**) realloc(list->ent, sizeof(dirls_entry_t*) * list->size);
force_assert(list->ent);
}
tmp = (dirls_entry_t*) malloc(sizeof(dirls_entry_t) + 1 + i);
dirls_entry_t * const tmp = list->ent[list->used++] =
(dirls_entry_t*) malloc(sizeof(dirls_entry_t) + 1 + dsz);
tmp->mtime = st.st_mtime;
tmp->size = st.st_size;
tmp->namelen = (uint32_t)i;
memcpy(DIRLIST_ENT_NAME(tmp), dent->d_name, i + 1);
list->ent[list->used++] = tmp;
tmp->namelen = dsz;
memcpy(DIRLIST_ENT_NAME(tmp), d_name, dsz + 1);
}
closedir(dp);
@ -930,12 +908,15 @@ static int http_list_directory(request_st * const r, plugin_data * const p, buff
if (files.used) http_dirls_sort(files.ent, files.used);
out = chunkqueue_append_buffer_open(&r->write_queue);
char sizebuf[sizeof("999.9K")];
struct tm tm;
buffer * const out = chunkqueue_append_buffer_open(&r->write_queue);
http_list_directory_header(r, p, out);
/* directories */
for (i = 0; i < dirs.used; i++) {
tmp = dirs.ent[i];
for (uint32_t i = 0; i < dirs.used; ++i) {
dirls_entry_t * const tmp = dirs.ent[i];
buffer_append_string_len(out, CONST_STR_LEN("<tr class=\"d\"><td class=\"n\"><a href=\""));
buffer_append_string_encoded(out, DIRLIST_ENT_NAME(tmp), tmp->namelen, ENCODING_REL_URI_PART);
@ -950,9 +931,9 @@ static int http_list_directory(request_st * const r, plugin_data * const p, buff
/* files */
const array * const mimetypes = r->conf.mimetypes;
for (i = 0; i < files.used; i++) {
tmp = files.ent[i];
for (uint32_t i = 0; i < files.used; ++i) {
dirls_entry_t * const tmp = files.ent[i];
const buffer *content_type;
#if defined(HAVE_XATTR) || defined(HAVE_EXTATTR) /*(pass full path)*/
content_type = NULL;
if (r->conf.use_xattr) {
@ -1016,7 +997,7 @@ URIHANDLER_FUNC(mod_dirlisting_subrequest) {
if (buffer_string_is_empty(&r->uri.path)) return HANDLER_GO_ON;
if (r->uri.path.ptr[buffer_string_length(&r->uri.path) - 1] != '/') return HANDLER_GO_ON;
if (!http_method_get_or_head(r->http_method)) return HANDLER_GO_ON;
if (buffer_is_empty(&r->physical.path)) return HANDLER_GO_ON;
if (buffer_string_is_empty(&r->physical.path)) return HANDLER_GO_ON;
mod_dirlisting_patch_config(r, p);