diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2018-02-17 23:06:10 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2018-02-17 23:23:52 +0200 |
commit | 1d89e35c9305cd235a0d645dae4212db14c0baf1 (patch) | |
tree | b5f317d6cbea610762c3345df75c3af8aae63e71 /src | |
parent | c93a6c17a2af32dd15c09adb926088d353ff800d (diff) | |
download | fileserv-1d89e35c9305cd235a0d645dae4212db14c0baf1.tar.gz fileserv-1d89e35c9305cd235a0d645dae4212db14c0baf1.tar.bz2 |
Don't bail out on out-of-memory errors in daemon mode.
* src/catfile.c: Use malloc instead of xmalloc.
* src/config.c (dirconfig): Change signature. Return FSE_ constant.
(config_init): Use calloc instead of xcalloc.
(set_index_files,set_hidden_files): Use nrealloc instead of
xnrealloc.
(all setters): Use string_copy instead of xstrdup.
(config_parse): Return meaningful FSE_ constant.
* src/fileserv.c (fse_to_http_code): New function.
(find_index_files,get_file_resp): Handle out-of-memory
errors.
* src/fileserv.h (fileserv_error): New enum.
(alloc_warn,nrealloc): New protos.
(dirconfig): Change prototype and return value.
* src/mem.c (alloc_warn)
(nrealloc): New functions.
Diffstat (limited to 'src')
-rw-r--r-- | src/catfile.c | 25 | ||||
-rw-r--r-- | src/config.c | 240 | ||||
-rw-r--r-- | src/dirls.h | 6 | ||||
-rw-r--r-- | src/fileserv.c | 41 | ||||
-rw-r--r-- | src/fileserv.h | 12 | ||||
-rw-r--r-- | src/idx.c | 61 | ||||
-rw-r--r-- | src/mem.c | 18 |
7 files changed, 269 insertions, 134 deletions
diff --git a/src/catfile.c b/src/catfile.c index 929e15e..37aee62 100644 --- a/src/catfile.c +++ b/src/catfile.c @@ -6,7 +6,7 @@ char * catfile_n(char const *dir, size_t len, char const *file) { size_t flen; - char *res, *p; + char *res; while (len > 0 && dir[len-1] == '/') len--; @@ -15,15 +15,20 @@ catfile_n(char const *dir, size_t len, char const *file) flen = strlen(file); while (flen && file[flen-1] == '/') --flen; - res = xmalloc(len + flen + 2); - memcpy(res, dir, len); - p = res + len; - if (flen) { - *p++ = '/'; - memcpy(p, file, flen); - p += flen; - } - *p = 0; + res = malloc(len + flen + 2); + if (res) { + char *p; + + memcpy(res, dir, len); + p = res + len; + if (flen) { + *p++ = '/'; + memcpy(p, file, flen); + p += flen; + } + *p = 0; + } else + alloc_warn(); return res; } diff --git a/src/config.c b/src/config.c index adcc677..7e50819 100644 --- a/src/config.c +++ b/src/config.c @@ -22,6 +22,8 @@ readconfig(void) { if (!config_file) { config_file = catfile(SYSCONFDIR, DEFAULT_CONF_FILE); + if (!config_file) + xmalloc_fail(); if (access(config_file, F_OK)) { if (verbose) error("warning: no configuration file %s", @@ -32,32 +34,55 @@ readconfig(void) } } global_config = config_init(); + if (!global_config) + exit(1); if (config_parse(config_file, global_config, CTXGLOB)) exit(1); } -CONFIG * -dirconfig(char const *path, size_t prefix_len) +int +dirconfig(char const *path, size_t prefix_len, CONFIG **ret) { - CONFIG *conf = config_clone(global_config); + CONFIG *conf; char *tmp = NULL; struct stat st; - + int rc = FSE_SUCCESS; + if (stat(path, &st) == 0 && S_ISDIR(st.st_mode)) { tmp = catfile(path, "."); + if (!tmp) + return FSE_ERROR; path = tmp; } - while (path[prefix_len]) { - char *name = catfile_n(path, prefix_len, dotfile); - config_parse(name, conf, CTXDIR); - free(name); - if (path[prefix_len] == '/') - prefix_len++; - while (path[prefix_len] && path[prefix_len] != '/') - prefix_len++; - } + + conf = config_clone(global_config); + if (conf) { + while (path[prefix_len]) { + char *name = catfile_n(path, prefix_len, dotfile); + if (!name) { + rc = FSE_ERROR; + break; + } + if (access(name, F_OK) == 0) { + rc = config_parse(name, conf, CTXDIR); + free(name); + if (rc) + break; + } + if (path[prefix_len] == '/') + prefix_len++; + while (path[prefix_len] && path[prefix_len] != '/') + prefix_len++; + } + } else + rc = FSE_ERROR; + free(tmp); - return conf; + if (rc == FSE_SUCCESS) + *ret = conf; + else + config_free(conf); + return rc; } static void @@ -89,8 +114,11 @@ hidden_files_free(CONFIG *conf) CONFIG * config_init(void) { - CONFIG *p = xcalloc(1, sizeof(*p)); - p->list_unreadable = 1; + CONFIG *p = calloc(1, sizeof(*p)); + if (p) + p->list_unreadable = 1; + else + alloc_warn(); return p; } @@ -99,7 +127,9 @@ config_clone(CONFIG const *source) { size_t i; CONFIG *p = config_init(); - + + if (!p) + return NULL; if (!source) return p; p->follow = source->follow; @@ -163,17 +193,28 @@ static int bad_argc(const char *file, int line, char const *id) { error("%s:%d: bad number of arguments to '%s'", file, line, id); - return 1; + return FSE_SYNTAX; } static int not_a_bool(const char *file, int line) { error("%s:%d: invalid boolean value", file, line); - return 1; + return FSE_SYNTAX; } static int +string_copy(char **dst, char const *src) +{ + *dst = strdup(src); + if (!*dst) { + alloc_warn(); + return FSE_ERROR; + } + return FSE_SUCCESS; +} + +static int set_follow(size_t argc, char **argv, CONFIG *conf, char const *file, int line) { @@ -184,7 +225,7 @@ set_follow(size_t argc, char **argv, CONFIG *conf, if (n == -1) return not_a_bool(file, line); conf->follow = n; - return 0; + return FSE_SUCCESS; } static int @@ -198,7 +239,7 @@ set_listing(size_t argc, char **argv, CONFIG *conf, if (n == -1) return not_a_bool(file, line); conf->listing = n; - return 0; + return FSE_SUCCESS; } static int @@ -212,7 +253,7 @@ set_list_unreadable(size_t argc, char **argv, CONFIG *conf, if (n == -1) return not_a_bool(file, line); conf->list_unreadable = n; - return 0; + return FSE_SUCCESS; } static int @@ -220,6 +261,7 @@ set_index_files(size_t argc, char **argv, CONFIG *conf, char const *file, int line) { size_t i; + void *p; if (argc < 2) return bad_argc(file, line, argv[0]); @@ -230,20 +272,28 @@ set_index_files(size_t argc, char **argv, CONFIG *conf, else index_files_free(conf); - conf->index_files_v = xnrealloc(conf->index_files_v, - argc + conf->index_files_c, - sizeof(conf->index_files_v[0])); + p = nrealloc(conf->index_files_v, + argc + conf->index_files_c, + sizeof(conf->index_files_v[0])); + if (!p) { + alloc_warn(); + return FSE_ERROR; + } + conf->index_files_v = p; + for (; argv[i]; i++) conf->index_files_v[conf->index_files_c++] = xstrdup(argv[i]); conf->index_files_v[conf->index_files_c] = NULL; - return 0; + return FSE_SUCCESS; } static int set_hidden_files(size_t argc, char **argv, CONFIG *conf, - char const *file, int line) + char const *file, int line) { size_t i; + void *p; + int rc; if (argc < 2) return bad_argc(file, line, argv[0]); @@ -254,9 +304,16 @@ set_hidden_files(size_t argc, char **argv, CONFIG *conf, else hidden_files_free(conf); - conf->hidden_files_rxv = xnrealloc(conf->hidden_files_rxv, - argc + conf->hidden_files_rxc, - sizeof(conf->hidden_files_rxv[0])); + p = nrealloc(conf->hidden_files_rxv, + argc + conf->hidden_files_rxc, + sizeof(conf->hidden_files_rxv[0])); + if (!p) { + alloc_warn(); + return FSE_ERROR; + } + conf->hidden_files_rxv = p; + + rc = FSE_SUCCESS; for (; argv[i]; i++) { int ec; ec = regcomp(&conf->hidden_files_rxv[conf->hidden_files_rxc], @@ -267,10 +324,12 @@ set_hidden_files(size_t argc, char **argv, CONFIG *conf, &conf->hidden_files_rxv[conf->hidden_files_rxc], buf, sizeof buf); error("%s: %s", argv[i], buf); + rc = FSE_ERROR; + break; } else conf->hidden_files_rxc++; } - return 0; + return rc; } static int @@ -279,10 +338,9 @@ set_user(size_t argc, char **argv, CONFIG *conf, { if (argc != 2) { error("%s:%d: expected exactly one argument", file, line); - return 1; + return FSE_SYNTAX; } - user = xstrdup(argv[1]); - return 0; + return string_copy(&user, argv[1]); } static int @@ -291,10 +349,9 @@ set_group(size_t argc, char **argv, CONFIG *conf, { if (argc != 2) { error("%s:%d: expected exactly one argument", file, line); - return 1; + return FSE_SYNTAX; } - group = xstrdup(argv[1]); - return 0; + return string_copy(&group, argv[1]); } static int @@ -303,10 +360,9 @@ set_listen(size_t argc, char **argv, CONFIG *conf, { if (argc != 2) { error("%s:%d: expected exactly one argument", file, line); - return 1; + return FSE_SYNTAX; } - address = xstrdup(argv[1]); - return 0; + return string_copy(&address, argv[1]); } static int @@ -315,13 +371,13 @@ set_index_template(size_t argc, char **argv, CONFIG *conf, { if (argc != 2) { error("%s:%d: expected exactly one argument", file, line); - return 1; + return FSE_SYNTAX; } if (parse_template_file(argv[1])) { error("%s:%d: invalid template", file, line); - return 1; + return FSE_SYNTAX; } - return 0; + return FSE_SUCCESS; } static int @@ -330,10 +386,9 @@ set_index_css(size_t argc, char **argv, CONFIG *conf, { if (argc != 2) { error("%s:%d: expected exactly one argument", file, line); - return 1; + return FSE_SYNTAX; } - index_css = xstrdup(argv[1]); - return 0; + return string_copy(&index_css, argv[1]); } static int @@ -342,10 +397,9 @@ set_dotfile(size_t argc, char **argv, CONFIG *conf, { if (argc != 2) { error("%s:%d: expected exactly one argument", file, line); - return 1; + return FSE_SYNTAX; } - dotfile = xstrdup(argv[1]); - return 0; + return string_copy(&dotfile, argv[1]); } static int @@ -354,10 +408,9 @@ set_forwarded_header(size_t argc, char **argv, CONFIG *conf, { if (argc != 2) { error("%s:%d: expected exactly one argument", file, line); - return 1; + return FSE_SYNTAX; } - forwarded_header = xstrdup(argv[1]); - return 0; + return string_copy(&forwarded_header, argv[1]); } static int @@ -366,10 +419,9 @@ set_temp_dir(size_t argc, char **argv, CONFIG *conf, { if (argc != 2) { error("%s:%d: expected exactly one argument", file, line); - return 1; + return FSE_SYNTAX; } - tmpdir = xstrdup(argv[1]); - return 0; + return string_copy(&tmpdir, argv[1]); } static int @@ -378,10 +430,9 @@ set_mime_magic_file(size_t argc, char **argv, CONFIG *conf, { if (argc != 2) { error("%s:%d: expected exactly one argument", file, line); - return 1; + return FSE_SYNTAX; } - mime_types_file = xstrdup(argv[1]); - return 0; + return string_copy(&mime_types_file, argv[1]); } static int @@ -392,11 +443,11 @@ set_trusted_proxy(size_t argc, char **argv, CONFIG *conf, if (argc == 1) { error("%s:%d: expected one or more arguments", file, line); - return 1; + return FSE_SYNTAX; } for (i = 1; i < argc; i++) trusted_ip_add(argv[i]); - return 0; + return FSE_SUCCESS; } static int @@ -405,10 +456,9 @@ set_pidfile(size_t argc, char **argv, CONFIG *conf, { if (argc != 2) { error("%s:%d: expected exactly one argument", file, line); - return 1; + return FSE_SYNTAX; } - pidfile = xstrdup(argv[1]); - return 0; + return string_copy(&pidfile, argv[1]); } static int @@ -417,13 +467,13 @@ set_syslog(size_t argc, char **argv, CONFIG *conf, { if (argc != 2) { error("%s:%d: expected exactly one argument", file, line); - return 1; + return FSE_SYNTAX; } if (set_log_facility(argv[1])) { error("%s:%d: not a valid syslog facility", file, line); - return 1; + return FSE_SYNTAX; } - return 0; + return FSE_SUCCESS; } static int @@ -434,11 +484,11 @@ set_mapping(size_t argc, char **argv, CONFIG *conf, if (argc == 1) { error("%s:%d: expected one or more arguments", file, line); - return 1; + return FSE_SYNTAX; } for (i = 1; i < argc; i++) urimap_add(argv[i]); - return 0; + return FSE_SUCCESS; } /* set-mime-icon icon [ALT=X] mime-type ... @@ -453,7 +503,7 @@ set_mime_icon(size_t argc, char **argv, CONFIG *conf, if (argc < 3) { error("%s:%d: expected two or more arguments", file, line); - return 1; + return FSE_SYNTAX; } icon = argv[1]; @@ -466,14 +516,14 @@ set_mime_icon(size_t argc, char **argv, CONFIG *conf, if (i == argc) { error("%s:%d: expected one or more mime types", file, line); - return 1; + return FSE_SYNTAX; } for (; i < argc; i++) add_icon_by_mime(argv[i], icon, alt); - return 0; + return FSE_SUCCESS; } static int @@ -486,7 +536,7 @@ set_name_icon(size_t argc, char **argv, CONFIG *conf, if (argc < 3) { error("%s:%d: expected two or more arguments", file, line); - return 1; + return FSE_SYNTAX; } icon = argv[1]; @@ -499,14 +549,14 @@ set_name_icon(size_t argc, char **argv, CONFIG *conf, if (i == argc) { error("%s:%d: expected one or more mime types", file, line); - return 1; + return FSE_SYNTAX; } for (; i < argc; i++) add_icon_by_name(argv[i], icon, alt); - return 0; + return FSE_SUCCESS; } static int @@ -519,7 +569,7 @@ set_type_icon(size_t argc, char **argv, CONFIG *conf, if (argc < 3) { error("%s:%d: expected two or three arguments", file, line); - return 1; + return FSE_SYNTAX; } icon = argv[1]; @@ -532,11 +582,11 @@ set_type_icon(size_t argc, char **argv, CONFIG *conf, if (i == argc) { error("%s:%d: expected file type", file, line); - return 1; + return FSE_SYNTAX; } add_icon_by_type(argv[i], icon, alt); - return 0; + return FSE_SUCCESS; } @@ -584,7 +634,28 @@ line_interpret(struct wordsplit const *ws, conf, file, line); } error("%s:%d: unrecognized keyword", file, line); - return 1; + return FSE_SYNTAX; +} + +int +wrdse_to_fse(int wse) +{ + switch (wse) { + case WRDSE_OK: + return FSE_SUCCESS; + + case WRDSE_NOSPACE: + case WRDSE_USAGE: + return FSE_ERROR; + + case WRDSE_USERERR: + /* FIXME: This one can map to any FSE_ code. In the + lack of more specific information, it is mapped to + syntax error */ + + default: + return FSE_SYNTAX; + } } int @@ -602,7 +673,7 @@ config_parse(const char *file, CONFIG *conf, int ctx) if (ctx == CTXGLOB || errno != ENOENT) error("can't open file %s: %s", file, strerror(errno)); - return 1; + return FSE_ERROR; } ws.ws_comment = "#"; @@ -619,30 +690,29 @@ config_parse(const char *file, CONFIG *conf, int ctx) buf[--len] = 0; else if (!feof(fp)) { error("%s:%d: line too long", file, ln); - err = 1; + err = FSE_SYNTAX; break; } if (wordsplit(buf, &ws, wsflags)) { error("%s:%d: %s", file, ln, wordsplit_strerror(&ws)); - err = 1; + err = wrdse_to_fse(ws.ws_errno); break; } wsflags |= WRDSF_REUSE; if (ws.ws_wordc == 0) continue; - if (line_interpret(&ws, conf, ctx, file, ln)) { - err = 1; + err = line_interpret(&ws, conf, ctx, file, ln); + if (err) break; - } } if (wsflags & WRDSF_REUSE) wordsplit_free(&ws); if (ferror(fp)) { - err = 1; + err = FSE_ERROR; error("%s: %s", file, strerror(errno)); } fclose(fp); diff --git a/src/dirls.h b/src/dirls.h index 0067bff..7ec2f3e 100644 --- a/src/dirls.h +++ b/src/dirls.h @@ -1,7 +1,7 @@ typedef struct dirlsent { - char *name; - struct stat st; - char const *type; + char *name; /* File name */ + struct stat st; /* Meta-data */ + char const *type; /* Mime type */ STAILQ_ENTRY(dirlsent) next; } DIRLSENT; diff --git a/src/fileserv.c b/src/fileserv.c index ae1599d..4bf6e8e 100644 --- a/src/fileserv.c +++ b/src/fileserv.c @@ -65,6 +65,21 @@ fileserv_panic(void *cls, const char *file, unsigned int line, } static inline int +fse_to_http_code(int ec) +{ + switch (ec) { + case FSE_SUCCESS: + return MHD_HTTP_OK; + case FSE_SYNTAX: + case FSE_ACCESS: + return MHD_HTTP_FORBIDDEN; + case FSE_ERROR: + break; + } + return MHD_HTTP_INTERNAL_SERVER_ERROR; +} + +static inline int errno_to_http_code(int ec) { switch (ec) { @@ -272,6 +287,10 @@ find_index_file(char const *dir, CONFIG *conf, char **index_file, for (i = 0; conf->index_files_v[i]; i++) { struct stat st; cf = catfile(dir, conf->index_files_v[i]); + if (!cf) { + lasterr = errno; + break; + } if (access(cf, F_OK) || lstat(cf, &st)) { free(cf); lasterr = errno; @@ -372,7 +391,8 @@ get_file_resp(struct MHD_Connection *conn, char const *url, FILE_RESP *resp) char const *host = MHD_lookup_connection_value(conn, MHD_HEADER_KIND, MHD_HTTP_HEADER_HOST); - + int rc; + file_resp_init(resp); if (!filename_is_valid(url)) @@ -383,11 +403,15 @@ get_file_resp(struct MHD_Connection *conn, char const *url, FILE_RESP *resp) return MHD_HTTP_NOT_FOUND; resp->file_name = catfile_n(map->dir, map->dir_len, url + map->uri_len); + if (!resp->file_name) + return MHD_HTTP_INTERNAL_SERVER_ERROR; if (lstat(resp->file_name, &resp->st)) return errno_to_http_code(errno); - resp->conf = dirconfig(resp->file_name, map->dir_len); - + rc = dirconfig(resp->file_name, map->dir_len, &resp->conf); + if (rc) + return fse_to_http_code(rc); + if (filename_is_hidden(basename(resp->file_name), resp->conf)) return MHD_HTTP_NOT_FOUND; @@ -430,6 +454,9 @@ get_file_resp(struct MHD_Connection *conn, char const *url, FILE_RESP *resp) int fd; template = catfile(tmpdir, "idxXXXXXX"); + if (!template) + return MHD_HTTP_INTERNAL_SERVER_ERROR; + fd = mkstemp(template); if (fd == -1) { error("can't create temporary file name: %s", @@ -528,11 +555,11 @@ http_redirect(struct MHD_Connection *connection, { int ret; struct MHD_Response *response; - + http_log(connection, method, url, status, NULL); - response = MHD_create_response_from_buffer (strlen(loc), - xstrdup(loc), - MHD_RESPMEM_MUST_FREE); + response = MHD_create_response_from_buffer(0, + "", + MHD_RESPMEM_PERSISTENT); MHD_add_response_header(response, MHD_HTTP_HEADER_LOCATION, loc); diff --git a/src/fileserv.h b/src/fileserv.h index cf72b39..a79cf28 100644 --- a/src/fileserv.h +++ b/src/fileserv.h @@ -37,6 +37,13 @@ extern char *address; extern char *index_css; extern int verbose; +enum fileserv_error { + FSE_SUCCESS, /* Processing successful */ + FSE_SYNTAX, /* Syntax error encountered */ + FSE_ACCESS, /* Access denied */ + FSE_ERROR /* System error encountered */ +}; + void error(char const *fmt, ...); void info(char const *fmt, ...); void syslog_enable(void); @@ -44,6 +51,9 @@ int set_log_facility(char const *arg); void fileserv_logger(void *arg, const char *fmt, va_list ap); +void alloc_warn(void); +void *nrealloc(void *ptr, size_t nmemb, size_t size); + void xmalloc_fail(void); void *xmalloc(size_t s); void *xcalloc(size_t nmemb, size_t size); @@ -88,7 +98,7 @@ enum { void readconfig(void); -CONFIG *dirconfig(char const *path, size_t prefix_len); +int dirconfig(char const *path, size_t prefix_len, CONFIG **); int config_parse(const char *file, CONFIG *conf, int ctx); CONFIG *config_init(void); CONFIG *config_clone(CONFIG const *source); @@ -157,7 +157,7 @@ node_cond_free(TMPL_NODE *node) } /* Parser error codes */ -enum { +enum template_error { TMPL_NOERR, TMPL_ERR_LOOP_NESTING, TMPL_ERR_ENDLOOP_WITHOUT_LOOP, @@ -185,18 +185,18 @@ static char const *tmpl_err_str[] = { }; /* Template parser state */ -struct template_state { - int escape:1; - int loop:1; - COND_LIST cond; - char const *start; - char const *cur; - int error; -}; +typedef struct template_parser_state { + int escape:1; /* True if in a {% %} construct */ + int loop:1; /* True if within a loop / endloop block */ + COND_LIST cond; /* Stack of nested conditionals */ + char const *start; /* Start of text fragment being parsed */ + char const *cur; /* Current position in the text */ + int error; /* Error state */ +} TEMPLATE_PARSER_STATE; /* Allocate and initialize single node */ static inline TMPL_NODE * -node_alloc(struct template_state *st, int type, size_t extra) +node_alloc(TEMPLATE_PARSER_STATE *st, int type, size_t extra) { TMPL_NODE *np = calloc(1, sizeof(*np) + extra); if (np) @@ -208,10 +208,10 @@ node_alloc(struct template_state *st, int type, size_t extra) } /* Template parser */ -static void parse_template(TMPL_NODE_LIST *nodes, struct template_state *st); +static void parse_template(TMPL_NODE_LIST *nodes, TEMPLATE_PARSER_STATE *st); static TMPL_NODE * -new_text_node(struct template_state *st, int type, size_t len) +new_text_node(TEMPLATE_PARSER_STATE *st, int type, size_t len) { TMPL_NODE *np = node_alloc(st, type, len + 1); if (np) { @@ -223,7 +223,7 @@ new_text_node(struct template_state *st, int type, size_t len) } static TMPL_NODE * -next_text_node(struct template_state *st) +next_text_node(TEMPLATE_PARSER_STATE *st) { st->start = st->cur; while (*st->cur) { @@ -238,7 +238,7 @@ next_text_node(struct template_state *st) } static TMPL_NODE * -parse_cond(struct template_state *st, int brn, size_t off, size_t len) +parse_cond(TEMPLATE_PARSER_STATE *st, int brn, size_t off, size_t len) { struct condition cond; TMPL_NODE *np; @@ -263,7 +263,7 @@ parse_cond(struct template_state *st, int brn, size_t off, size_t len) } static TMPL_NODE * -next_escape_node(struct template_state *st) +next_escape_node(TEMPLATE_PARSER_STATE *st) { size_t len; @@ -350,7 +350,7 @@ next_escape_node(struct template_state *st) } static TMPL_NODE * -next_node(struct template_state *st) +next_node(TEMPLATE_PARSER_STATE *st) { if (st->error) return NULL; @@ -360,7 +360,7 @@ next_node(struct template_state *st) } static void -parse_template(TMPL_NODE_LIST *nodes, struct template_state *st) +parse_template(TMPL_NODE_LIST *nodes, TEMPLATE_PARSER_STATE *st) { TMPL_NODE *np; @@ -371,11 +371,15 @@ parse_template(TMPL_NODE_LIST *nodes, struct template_state *st) } TMPL_NODE_LIST node_list = STAILQ_HEAD_INITIALIZER(node_list); +/* index_disabled inhibits creation of directory indexes. It is set only + if the built-in index template cannot be compiled and the custom template + was not supplied or failed to compile too. */ +static int index_disabled; int parse_template_string(char const *str) { - struct template_state state; + TEMPLATE_PARSER_STATE state; state.escape = 0; state.loop = 0; @@ -454,15 +458,15 @@ parse_template_file(char const *file_name) /* Run-time template evaluator */ typedef struct eval_env { - int fd; - CONFIG const *conf; - DIRLSENT *ent; - int n; - struct wordsplit ws; - int wsflags; - INDEX_SORT_COL col; - INDEX_SORT_ORD ord; - ICON const *icon; + int fd; /* Output file descriptor */ + CONFIG const *conf; /* Associated configuration settings */ + DIRLSENT *ent; /* Current listing entry */ + int n; /* Ordinal number of the entry in the listing */ + ICON const *icon; /* Icon associated with the entry */ + struct wordsplit ws; /* Word-splitter tool */ + int wsflags; /* Its flags */ + INDEX_SORT_COL col; /* Sorting column */ + INDEX_SORT_ORD ord; /* Sorting order */ #define expansion ws.ws_wordv[0] } EVAL_ENV; @@ -751,9 +755,12 @@ directory_index(int fd, CONFIG const *conf, EVAL_ENV env; char const *varenv[5]; + if (index_disabled) + return ENOSYS; if (STAILQ_EMPTY(&node_list)) { if (parse_template_string(defidx) == 0) { error("error compiling built-in template!"); + index_disabled = 1; return ENOSYS; } } @@ -1,8 +1,17 @@ #include <stdio.h> #include <string.h> +#include <errno.h> #include "fileserv.h" void +alloc_warn(void) +{ + int ec = errno; + error("not enough memory"); + errno = ec; +} + +void xmalloc_fail(void) { error("not enough memory"); @@ -32,12 +41,19 @@ xcalloc(size_t nmemb, size_t size) } void * -xnrealloc(void *ptr, size_t nmemb, size_t size) +nrealloc(void *ptr, size_t nmemb, size_t size) { if (size < SIZE_T_MAX / nmemb) ptr = realloc(ptr, nmemb * size); else ptr = NULL; + return ptr; +} + +void * +xnrealloc(void *ptr, size_t nmemb, size_t size) +{ + ptr = nrealloc(ptr, nmemb, size); if (!ptr) xmalloc_fail(); return ptr; |