From 09119a3e8fa5f206eb4254144a1c8e77bc6e587e Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Sat, 4 May 2019 11:51:56 -0400 Subject: bftw: Add a caching stat() API to struct BFTW --- printf.c | 305 +++++++++++++++++++++++++++++++++++---------------------------- 1 file changed, 172 insertions(+), 133 deletions(-) (limited to 'printf.c') diff --git a/printf.c b/printf.c index b2463e1..f77ff92 100644 --- a/printf.c +++ b/printf.c @@ -33,12 +33,9 @@ #include #include -typedef int bfs_printf_fn(FILE *file, const struct bfs_printf_directive *directive, const struct BFTW *ftwbuf); +typedef int bfs_printf_fn(FILE *file, const struct bfs_printf *directive, struct BFTW *ftwbuf); -/** - * A single directive in a printf command. - */ -struct bfs_printf_directive { +struct bfs_printf { /** The printing function to invoke. */ bfs_printf_fn *fn; /** String data associated with this directive. */ @@ -50,11 +47,11 @@ struct bfs_printf_directive { /** The current mount table. */ const struct bfs_mtab *mtab; /** The next printf directive in the chain. */ - struct bfs_printf_directive *next; + struct bfs_printf *next; }; /** Print some text as-is. */ -static int bfs_printf_literal(FILE *file, const struct bfs_printf_directive *directive, const struct BFTW *ftwbuf) { +static int bfs_printf_literal(FILE *file, const struct bfs_printf *directive, struct BFTW *ftwbuf) { size_t len = dstrlen(directive->str); if (fwrite(directive->str, 1, len, file) == len) { return 0; @@ -64,7 +61,7 @@ static int bfs_printf_literal(FILE *file, const struct bfs_printf_directive *dir } /** \c: flush */ -static int bfs_printf_flush(FILE *file, const struct bfs_printf_directive *directive, const struct BFTW *ftwbuf) { +static int bfs_printf_flush(FILE *file, const struct bfs_printf *directive, struct BFTW *ftwbuf) { return fflush(file); } @@ -78,12 +75,17 @@ static int bfs_printf_flush(FILE *file, const struct bfs_printf_directive *direc (void)ret /** %a, %c, %t: ctime() */ -static int bfs_printf_ctime(FILE *file, const struct bfs_printf_directive *directive, const struct BFTW *ftwbuf) { +static int bfs_printf_ctime(FILE *file, const struct bfs_printf *directive, struct BFTW *ftwbuf) { // Not using ctime() itself because GNU find adds nanoseconds static const char *days[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; static const char *months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; - const struct timespec *ts = bfs_stat_time(ftwbuf->statbuf, directive->stat_field); + const struct bfs_stat *statbuf = bftw_stat(ftwbuf, ftwbuf->stat_flags); + if (!statbuf) { + return -1; + } + + const struct timespec *ts = bfs_stat_time(statbuf, directive->stat_field); if (!ts) { return -1; } @@ -107,8 +109,13 @@ static int bfs_printf_ctime(FILE *file, const struct bfs_printf_directive *direc } /** %A, %B/%W, %C, %T: strftime() */ -static int bfs_printf_strftime(FILE *file, const struct bfs_printf_directive *directive, const struct BFTW *ftwbuf) { - const struct timespec *ts = bfs_stat_time(ftwbuf->statbuf, directive->stat_field); +static int bfs_printf_strftime(FILE *file, const struct bfs_printf *directive, struct BFTW *ftwbuf) { + const struct bfs_stat *statbuf = bftw_stat(ftwbuf, ftwbuf->stat_flags); + if (!statbuf) { + return -1; + } + + const struct timespec *ts = bfs_stat_time(statbuf, directive->stat_field); if (!ts) { return -1; } @@ -170,43 +177,68 @@ static int bfs_printf_strftime(FILE *file, const struct bfs_printf_directive *di } /** %b: blocks */ -static int bfs_printf_b(FILE *file, const struct bfs_printf_directive *directive, const struct BFTW *ftwbuf) { - uintmax_t blocks = ((uintmax_t)ftwbuf->statbuf->blocks*BFS_STAT_BLKSIZE + 511)/512; +static int bfs_printf_b(FILE *file, const struct bfs_printf *directive, struct BFTW *ftwbuf) { + const struct bfs_stat *statbuf = bftw_stat(ftwbuf, ftwbuf->stat_flags); + if (!statbuf) { + return -1; + } + + uintmax_t blocks = ((uintmax_t)statbuf->blocks*BFS_STAT_BLKSIZE + 511)/512; BFS_PRINTF_BUF(buf, "%ju", blocks); return fprintf(file, directive->str, buf); } /** %d: depth */ -static int bfs_printf_d(FILE *file, const struct bfs_printf_directive *directive, const struct BFTW *ftwbuf) { +static int bfs_printf_d(FILE *file, const struct bfs_printf *directive, struct BFTW *ftwbuf) { return fprintf(file, directive->str, (intmax_t)ftwbuf->depth); } /** %D: device */ -static int bfs_printf_D(FILE *file, const struct bfs_printf_directive *directive, const struct BFTW *ftwbuf) { - BFS_PRINTF_BUF(buf, "%ju", (uintmax_t)ftwbuf->statbuf->dev); +static int bfs_printf_D(FILE *file, const struct bfs_printf *directive, struct BFTW *ftwbuf) { + const struct bfs_stat *statbuf = bftw_stat(ftwbuf, ftwbuf->stat_flags); + if (!statbuf) { + return -1; + } + + BFS_PRINTF_BUF(buf, "%ju", (uintmax_t)statbuf->dev); return fprintf(file, directive->str, buf); } /** %f: file name */ -static int bfs_printf_f(FILE *file, const struct bfs_printf_directive *directive, const struct BFTW *ftwbuf) { +static int bfs_printf_f(FILE *file, const struct bfs_printf *directive, struct BFTW *ftwbuf) { return fprintf(file, directive->str, ftwbuf->path + ftwbuf->nameoff); } /** %F: file system type */ -static int bfs_printf_F(FILE *file, const struct bfs_printf_directive *directive, const struct BFTW *ftwbuf) { - const char *type = bfs_fstype(directive->mtab, ftwbuf->statbuf); +static int bfs_printf_F(FILE *file, const struct bfs_printf *directive, struct BFTW *ftwbuf) { + const struct bfs_stat *statbuf = bftw_stat(ftwbuf, ftwbuf->stat_flags); + if (!statbuf) { + return -1; + } + + const char *type = bfs_fstype(directive->mtab, statbuf); return fprintf(file, directive->str, type); } /** %G: gid */ -static int bfs_printf_G(FILE *file, const struct bfs_printf_directive *directive, const struct BFTW *ftwbuf) { - BFS_PRINTF_BUF(buf, "%ju", (uintmax_t)ftwbuf->statbuf->gid); +static int bfs_printf_G(FILE *file, const struct bfs_printf *directive, struct BFTW *ftwbuf) { + const struct bfs_stat *statbuf = bftw_stat(ftwbuf, ftwbuf->stat_flags); + if (!statbuf) { + return -1; + } + + BFS_PRINTF_BUF(buf, "%ju", (uintmax_t)statbuf->gid); return fprintf(file, directive->str, buf); } /** %g: group name */ -static int bfs_printf_g(FILE *file, const struct bfs_printf_directive *directive, const struct BFTW *ftwbuf) { - struct group *grp = getgrgid(ftwbuf->statbuf->gid); +static int bfs_printf_g(FILE *file, const struct bfs_printf *directive, struct BFTW *ftwbuf) { + const struct bfs_stat *statbuf = bftw_stat(ftwbuf, ftwbuf->stat_flags); + if (!statbuf) { + return -1; + } + + struct group *grp = getgrgid(statbuf->gid); if (!grp) { return bfs_printf_G(file, directive, ftwbuf); } @@ -215,7 +247,7 @@ static int bfs_printf_g(FILE *file, const struct bfs_printf_directive *directive } /** %h: leading directories */ -static int bfs_printf_h(FILE *file, const struct bfs_printf_directive *directive, const struct BFTW *ftwbuf) { +static int bfs_printf_h(FILE *file, const struct bfs_printf *directive, struct BFTW *ftwbuf) { char *copy = NULL; const char *buf; @@ -242,25 +274,35 @@ static int bfs_printf_h(FILE *file, const struct bfs_printf_directive *directive } /** %H: current root */ -static int bfs_printf_H(FILE *file, const struct bfs_printf_directive *directive, const struct BFTW *ftwbuf) { +static int bfs_printf_H(FILE *file, const struct bfs_printf *directive, struct BFTW *ftwbuf) { return fprintf(file, directive->str, ftwbuf->root); } /** %i: inode */ -static int bfs_printf_i(FILE *file, const struct bfs_printf_directive *directive, const struct BFTW *ftwbuf) { - BFS_PRINTF_BUF(buf, "%ju", (uintmax_t)ftwbuf->statbuf->ino); +static int bfs_printf_i(FILE *file, const struct bfs_printf *directive, struct BFTW *ftwbuf) { + const struct bfs_stat *statbuf = bftw_stat(ftwbuf, ftwbuf->stat_flags); + if (!statbuf) { + return -1; + } + + BFS_PRINTF_BUF(buf, "%ju", (uintmax_t)statbuf->ino); return fprintf(file, directive->str, buf); } /** %k: 1K blocks */ -static int bfs_printf_k(FILE *file, const struct bfs_printf_directive *directive, const struct BFTW *ftwbuf) { - uintmax_t blocks = ((uintmax_t)ftwbuf->statbuf->blocks*BFS_STAT_BLKSIZE + 1023)/1024; +static int bfs_printf_k(FILE *file, const struct bfs_printf *directive, struct BFTW *ftwbuf) { + const struct bfs_stat *statbuf = bftw_stat(ftwbuf, ftwbuf->stat_flags); + if (!statbuf) { + return -1; + } + + uintmax_t blocks = ((uintmax_t)statbuf->blocks*BFS_STAT_BLKSIZE + 1023)/1024; BFS_PRINTF_BUF(buf, "%ju", blocks); return fprintf(file, directive->str, buf); } /** %l: link target */ -static int bfs_printf_l(FILE *file, const struct bfs_printf_directive *directive, const struct BFTW *ftwbuf) { +static int bfs_printf_l(FILE *file, const struct bfs_printf *directive, struct BFTW *ftwbuf) { if (ftwbuf->typeflag != BFTW_LNK) { return 0; } @@ -276,30 +318,45 @@ static int bfs_printf_l(FILE *file, const struct bfs_printf_directive *directive } /** %m: mode */ -static int bfs_printf_m(FILE *file, const struct bfs_printf_directive *directive, const struct BFTW *ftwbuf) { - return fprintf(file, directive->str, (unsigned int)(ftwbuf->statbuf->mode & 07777)); +static int bfs_printf_m(FILE *file, const struct bfs_printf *directive, struct BFTW *ftwbuf) { + const struct bfs_stat *statbuf = bftw_stat(ftwbuf, ftwbuf->stat_flags); + if (!statbuf) { + return -1; + } + + return fprintf(file, directive->str, (unsigned int)(statbuf->mode & 07777)); } /** %M: symbolic mode */ -static int bfs_printf_M(FILE *file, const struct bfs_printf_directive *directive, const struct BFTW *ftwbuf) { +static int bfs_printf_M(FILE *file, const struct bfs_printf *directive, struct BFTW *ftwbuf) { + const struct bfs_stat *statbuf = bftw_stat(ftwbuf, ftwbuf->stat_flags); + if (!statbuf) { + return -1; + } + char buf[11]; - format_mode(ftwbuf->statbuf->mode, buf); + format_mode(statbuf->mode, buf); return fprintf(file, directive->str, buf); } /** %n: link count */ -static int bfs_printf_n(FILE *file, const struct bfs_printf_directive *directive, const struct BFTW *ftwbuf) { - BFS_PRINTF_BUF(buf, "%ju", (uintmax_t)ftwbuf->statbuf->nlink); +static int bfs_printf_n(FILE *file, const struct bfs_printf *directive, struct BFTW *ftwbuf) { + const struct bfs_stat *statbuf = bftw_stat(ftwbuf, ftwbuf->stat_flags); + if (!statbuf) { + return -1; + } + + BFS_PRINTF_BUF(buf, "%ju", (uintmax_t)statbuf->nlink); return fprintf(file, directive->str, buf); } /** %p: full path */ -static int bfs_printf_p(FILE *file, const struct bfs_printf_directive *directive, const struct BFTW *ftwbuf) { +static int bfs_printf_p(FILE *file, const struct bfs_printf *directive, struct BFTW *ftwbuf) { return fprintf(file, directive->str, ftwbuf->path); } /** %P: path after root */ -static int bfs_printf_P(FILE *file, const struct bfs_printf_directive *directive, const struct BFTW *ftwbuf) { +static int bfs_printf_P(FILE *file, const struct bfs_printf *directive, struct BFTW *ftwbuf) { const char *path = ftwbuf->path + strlen(ftwbuf->root); if (path[0] == '/') { ++path; @@ -308,32 +365,51 @@ static int bfs_printf_P(FILE *file, const struct bfs_printf_directive *directive } /** %s: size */ -static int bfs_printf_s(FILE *file, const struct bfs_printf_directive *directive, const struct BFTW *ftwbuf) { - BFS_PRINTF_BUF(buf, "%ju", (uintmax_t)ftwbuf->statbuf->size); +static int bfs_printf_s(FILE *file, const struct bfs_printf *directive, struct BFTW *ftwbuf) { + const struct bfs_stat *statbuf = bftw_stat(ftwbuf, ftwbuf->stat_flags); + if (!statbuf) { + return -1; + } + + BFS_PRINTF_BUF(buf, "%ju", (uintmax_t)statbuf->size); return fprintf(file, directive->str, buf); } /** %S: sparseness */ -static int bfs_printf_S(FILE *file, const struct bfs_printf_directive *directive, const struct BFTW *ftwbuf) { +static int bfs_printf_S(FILE *file, const struct bfs_printf *directive, struct BFTW *ftwbuf) { + const struct bfs_stat *statbuf = bftw_stat(ftwbuf, ftwbuf->stat_flags); + if (!statbuf) { + return -1; + } + double sparsity; - const struct bfs_stat *sb = ftwbuf->statbuf; - if (sb->size == 0 && sb->blocks == 0) { + if (statbuf->size == 0 && statbuf->blocks == 0) { sparsity = 1.0; } else { - sparsity = (double)BFS_STAT_BLKSIZE*sb->blocks/sb->size; + sparsity = (double)BFS_STAT_BLKSIZE*statbuf->blocks/statbuf->size; } return fprintf(file, directive->str, sparsity); } /** %U: uid */ -static int bfs_printf_U(FILE *file, const struct bfs_printf_directive *directive, const struct BFTW *ftwbuf) { - BFS_PRINTF_BUF(buf, "%ju", (uintmax_t)ftwbuf->statbuf->uid); +static int bfs_printf_U(FILE *file, const struct bfs_printf *directive, struct BFTW *ftwbuf) { + const struct bfs_stat *statbuf = bftw_stat(ftwbuf, ftwbuf->stat_flags); + if (!statbuf) { + return -1; + } + + BFS_PRINTF_BUF(buf, "%ju", (uintmax_t)statbuf->uid); return fprintf(file, directive->str, buf); } /** %u: user name */ -static int bfs_printf_u(FILE *file, const struct bfs_printf_directive *directive, const struct BFTW *ftwbuf) { - struct passwd *pwd = getpwuid(ftwbuf->statbuf->uid); +static int bfs_printf_u(FILE *file, const struct bfs_printf *directive, struct BFTW *ftwbuf) { + const struct bfs_stat *statbuf = bftw_stat(ftwbuf, ftwbuf->stat_flags); + if (!statbuf) { + return -1; + } + + struct passwd *pwd = getpwuid(statbuf->uid); if (!pwd) { return bfs_printf_U(file, directive, ftwbuf); } @@ -365,13 +441,13 @@ static const char *bfs_printf_type(enum bftw_typeflag typeflag) { } /** %y: type */ -static int bfs_printf_y(FILE *file, const struct bfs_printf_directive *directive, const struct BFTW *ftwbuf) { +static int bfs_printf_y(FILE *file, const struct bfs_printf *directive, struct BFTW *ftwbuf) { const char *type = bfs_printf_type(ftwbuf->typeflag); return fprintf(file, directive->str, type); } /** %Y: target type */ -static int bfs_printf_Y(FILE *file, const struct bfs_printf_directive *directive, const struct BFTW *ftwbuf) { +static int bfs_printf_Y(FILE *file, const struct bfs_printf *directive, struct BFTW *ftwbuf) { int error = 0; if (ftwbuf->typeflag != BFTW_LNK) { @@ -380,9 +456,9 @@ static int bfs_printf_Y(FILE *file, const struct bfs_printf_directive *directive const char *type = "U"; - struct bfs_stat sb; - if (bfs_stat(ftwbuf->at_fd, ftwbuf->at_path, BFS_STAT_FOLLOW, &sb) == 0) { - type = bfs_printf_type(bftw_mode_typeflag(sb.mode)); + const struct bfs_stat *statbuf = bftw_stat(ftwbuf, BFS_STAT_FOLLOW); + if (statbuf) { + type = bfs_printf_type(bftw_mode_typeflag(statbuf->mode)); } else { switch (errno) { case ELOOP: @@ -410,7 +486,7 @@ static int bfs_printf_Y(FILE *file, const struct bfs_printf_directive *directive /** * Free a printf directive. */ -static void free_directive(struct bfs_printf_directive *directive) { +static void free_directive(struct bfs_printf *directive) { if (directive) { dstrfree(directive->str); free(directive); @@ -420,14 +496,14 @@ static void free_directive(struct bfs_printf_directive *directive) { /** * Create a new printf directive. */ -static struct bfs_printf_directive *new_directive(void) { - struct bfs_printf_directive *directive = malloc(sizeof(*directive)); +static struct bfs_printf *new_directive(bfs_printf_fn *fn) { + struct bfs_printf *directive = malloc(sizeof(*directive)); if (!directive) { perror("malloc()"); goto error; } - directive->fn = NULL; + directive->fn = fn; directive->str = dstralloc(2); if (!directive->str) { perror("dstralloc()"); @@ -447,47 +523,30 @@ error: /** * Append a printf directive to the chain. */ -static void append_directive(struct bfs_printf_directive ***tail, struct bfs_printf_directive *directive) { - **tail = directive; - *tail = &directive->next; +static struct bfs_printf **append_directive(struct bfs_printf **tail, struct bfs_printf *directive) { + assert(directive); + *tail = directive; + return &directive->next; } /** * Append a literal string to the chain. */ -static int append_literal(struct bfs_printf_directive ***tail, struct bfs_printf_directive **literal, bool last) { - struct bfs_printf_directive *directive = *literal; - if (!directive || dstrlen(directive->str) == 0) { - return 0; - } - - directive->fn = bfs_printf_literal; - append_directive(tail, directive); - - if (last) { +static struct bfs_printf **append_literal(struct bfs_printf **tail, struct bfs_printf **literal) { + struct bfs_printf *directive = *literal; + if (directive && dstrlen(directive->str) > 0) { *literal = NULL; + return append_directive(tail, directive); } else { - *literal = new_directive(); - if (!*literal) { - return -1; - } + return tail; } - - return 0; } struct bfs_printf *parse_bfs_printf(const char *format, struct cmdline *cmdline) { - struct bfs_printf *command = malloc(sizeof(*command)); - if (!command) { - perror("malloc()"); - return NULL; - } + struct bfs_printf *head = NULL; + struct bfs_printf **tail = &head; - command->directives = NULL; - command->needs_stat = false; - struct bfs_printf_directive **tail = &command->directives; - - struct bfs_printf_directive *literal = new_directive(); + struct bfs_printf *literal = new_directive(bfs_printf_literal); if (!literal) { goto error; } @@ -519,15 +578,12 @@ struct bfs_printf *parse_bfs_printf(const char *format, struct cmdline *cmdline) case '\\': c = '\\'; break; case 'c': - if (append_literal(&tail, &literal, true) != 0) { - goto error; - } - struct bfs_printf_directive *directive = new_directive(); + tail = append_literal(tail, &literal); + struct bfs_printf *directive = new_directive(bfs_printf_flush); if (!directive) { goto error; } - directive->fn = bfs_printf_flush; - append_directive(&tail, directive); + tail = append_directive(tail, directive); goto done; case '\0': @@ -544,7 +600,7 @@ struct bfs_printf *parse_bfs_printf(const char *format, struct cmdline *cmdline) goto one_char; } - struct bfs_printf_directive *directive = new_directive(); + struct bfs_printf *directive = new_directive(NULL); if (!directive) { goto directive_error; } @@ -606,16 +662,13 @@ struct bfs_printf *parse_bfs_printf(const char *format, struct cmdline *cmdline) case 'a': directive->fn = bfs_printf_ctime; directive->stat_field = BFS_STAT_ATIME; - command->needs_stat = true; break; case 'b': directive->fn = bfs_printf_b; - command->needs_stat = true; break; case 'c': directive->fn = bfs_printf_ctime; directive->stat_field = BFS_STAT_CTIME; - command->needs_stat = true; break; case 'd': directive->fn = bfs_printf_d; @@ -623,7 +676,6 @@ struct bfs_printf *parse_bfs_printf(const char *format, struct cmdline *cmdline) break; case 'D': directive->fn = bfs_printf_D; - command->needs_stat = true; break; case 'f': directive->fn = bfs_printf_f; @@ -635,15 +687,12 @@ struct bfs_printf *parse_bfs_printf(const char *format, struct cmdline *cmdline) } directive->fn = bfs_printf_F; directive->mtab = cmdline->mtab; - command->needs_stat = true; break; case 'g': directive->fn = bfs_printf_g; - command->needs_stat = true; break; case 'G': directive->fn = bfs_printf_G; - command->needs_stat = true; break; case 'h': directive->fn = bfs_printf_h; @@ -653,11 +702,9 @@ struct bfs_printf *parse_bfs_printf(const char *format, struct cmdline *cmdline) break; case 'i': directive->fn = bfs_printf_i; - command->needs_stat = true; break; case 'k': directive->fn = bfs_printf_k; - command->needs_stat = true; break; case 'l': directive->fn = bfs_printf_l; @@ -665,15 +712,12 @@ struct bfs_printf *parse_bfs_printf(const char *format, struct cmdline *cmdline) case 'm': directive->fn = bfs_printf_m; specifier = "o"; - command->needs_stat = true; break; case 'M': directive->fn = bfs_printf_M; - command->needs_stat = true; break; case 'n': directive->fn = bfs_printf_n; - command->needs_stat = true; break; case 'p': directive->fn = bfs_printf_p; @@ -683,30 +727,24 @@ struct bfs_printf *parse_bfs_printf(const char *format, struct cmdline *cmdline) break; case 's': directive->fn = bfs_printf_s; - command->needs_stat = true; break; case 'S': directive->fn = bfs_printf_S; specifier = "g"; - command->needs_stat = true; break; case 't': directive->fn = bfs_printf_ctime; directive->stat_field = BFS_STAT_MTIME; - command->needs_stat = true; break; case 'u': directive->fn = bfs_printf_u; - command->needs_stat = true; break; case 'U': directive->fn = bfs_printf_U; - command->needs_stat = true; break; case 'w': directive->fn = bfs_printf_ctime; directive->stat_field = BFS_STAT_BTIME; - command->needs_stat = true; break; case 'y': directive->fn = bfs_printf_y; @@ -731,7 +769,6 @@ struct bfs_printf *parse_bfs_printf(const char *format, struct cmdline *cmdline) directive_strftime: directive->fn = bfs_printf_strftime; - command->needs_stat = true; c = *++i; if (!c) { bfs_error(cmdline, "'%s': Incomplete time specifier '%s%c'.\n", format, directive->str, i[-1]); @@ -763,10 +800,16 @@ struct bfs_printf *parse_bfs_printf(const char *format, struct cmdline *cmdline) goto directive_error; } - if (append_literal(&tail, &literal, false) != 0) { - goto directive_error; + tail = append_literal(tail, &literal); + tail = append_directive(tail, directive); + + if (!literal) { + literal = new_directive(bfs_printf_literal); + if (!literal) { + goto error; + } } - append_directive(&tail, directive); + continue; directive_error: @@ -782,23 +825,24 @@ struct bfs_printf *parse_bfs_printf(const char *format, struct cmdline *cmdline) } done: - if (append_literal(&tail, &literal, true) != 0) { - goto error; + tail = append_literal(tail, &literal); + if (head) { + free_directive(literal); + return head; + } else { + return literal; } - free_directive(literal); - return command; - error: free_directive(literal); - free_bfs_printf(command); + free_bfs_printf(head); return NULL; } -int bfs_printf(FILE *file, const struct bfs_printf *command, const struct BFTW *ftwbuf) { +int bfs_printf(FILE *file, const struct bfs_printf *command, struct BFTW *ftwbuf) { int ret = 0, error = 0; - for (struct bfs_printf_directive *directive = command->directives; directive; directive = directive->next) { + for (const struct bfs_printf *directive = command; directive; directive = directive->next) { if (directive->fn(file, directive, ftwbuf) < 0) { ret = -1; error = errno; @@ -810,14 +854,9 @@ int bfs_printf(FILE *file, const struct bfs_printf *command, const struct BFTW * } void free_bfs_printf(struct bfs_printf *command) { - if (command) { - struct bfs_printf_directive *directive = command->directives; - while (directive) { - struct bfs_printf_directive *next = directive->next; - free_directive(directive); - directive = next; - } - - free(command); + while (command) { + struct bfs_printf *next = command->next; + free_directive(command); + command = next; } } -- cgit v1.2.3