]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
Callbacks are annoying. Change the callback-driven line processor
authorTim Kientzle <kientzle@gmail.com>
Wed, 28 May 2008 22:17:53 +0000 (18:17 -0400)
committerTim Kientzle <kientzle@gmail.com>
Wed, 28 May 2008 22:17:53 +0000 (18:17 -0400)
into a separate line reader that returns a line each time it's
called.

SVN-Revision: 101

cpio/cmdline.c
cpio/cpio.c
cpio/cpio.h
cpio/matching.c

index 4b33727927113c5a9fabb4624d653131529d007d..75857c1cd1eb0a417f17bc26d14039b16bf3cb2f 100644 (file)
@@ -66,7 +66,7 @@ struct option {
  */
 
 
-static const char *cpio_opts = "AaBC:F:O:cdE:f:H:hijLlmopR:rtuvW:yZz";
+static const char *cpio_opts = "0AaBC:F:O:cdE:f:H:hijLlmopR:rtuvW:yZz";
 
 /*
  * On systems that lack getopt_long, long options can be specified
@@ -86,6 +86,7 @@ static const struct option cpio_longopts[] = {
        { "format",             required_argument, NULL, 'H' },
        { "help",               no_argument,       NULL, 'h' },
        { "insecure",           no_argument,       NULL, OPTION_INSECURE },
+       { "null",               no_argument,       NULL, '0' },
        { "owner",              required_argument, NULL, 'R' },
        { "quiet",              no_argument,       NULL, OPTION_QUIET },
        { "verbose",            no_argument,       NULL, 'v' },
index 1d78ce1266f58908d99495b31cdcd090f2d9cf66..715fb953db937c0a6c47fe3f81264fe439e39920 100644 (file)
@@ -101,6 +101,7 @@ main(int argc, char *argv[])
        cpio->gid_override = -1;
        cpio->argv = argv;
        cpio->argc = argc;
+       cpio->line_separator = '\n';
        cpio->mode = '\0';
        cpio->verbose = 0;
        cpio->compress = '\0';
@@ -116,6 +117,9 @@ main(int argc, char *argv[])
 
        while ((opt = cpio_getopt(cpio)) != -1) {
                switch (opt) {
+               case '0': /* GNU convention: --null, -0 */
+                       cpio->line_separator = '\0';
+                       break;
                case 'A': /* NetBSD/OpenBSD */
                        cpio->option_append = 1;
                        break;
@@ -341,8 +345,10 @@ version(void)
 static void
 mode_out(struct cpio *cpio)
 {
-       struct archive_entry *entry, *spare;
        unsigned long blocks;
+       struct archive_entry *entry, *spare;
+       struct line_reader *lr;
+       const char *p;
        int r;
 
        if (cpio->option_append)
@@ -375,7 +381,10 @@ mode_out(struct cpio *cpio)
        r = archive_write_open_file(cpio->archive, cpio->filename);
        if (r != ARCHIVE_OK)
                cpio_errc(1, 0, archive_error_string(cpio->archive));
-       process_lines(cpio, "-", file_to_archive);
+       lr = process_lines_init("-", cpio->line_separator);
+       while ((p = process_lines_next(lr)) != NULL)
+               file_to_archive(cpio, p);
+       process_lines_free(lr);
 
        /*
         * The hardlink detection may have queued up a couple of entries
@@ -793,6 +802,8 @@ mode_list(struct cpio *cpio)
 static void
 mode_pass(struct cpio *cpio, const char *destdir)
 {
+       struct line_reader *lr;
+       const char *p;
        int r;
 
        /* Ensure target dir has a trailing '/' to simplify path surgery. */
@@ -809,7 +820,10 @@ mode_pass(struct cpio *cpio, const char *destdir)
                cpio_errc(1, 0, archive_error_string(cpio->archive));
        cpio->linkresolver = archive_entry_linkresolver_new();
        archive_write_disk_set_standard_lookup(cpio->archive);
-       process_lines(cpio, "-", file_to_archive);
+       lr = process_lines_init("-", cpio->line_separator);
+       while ((p = process_lines_next(lr)) != NULL)
+               file_to_archive(cpio, p);
+       process_lines_free(lr);
 
        archive_entry_linkresolver_free(cpio->linkresolver);
        r = archive_write_close(cpio->archive);
@@ -868,79 +882,119 @@ cpio_rename(const char *name)
  * terminated with newlines.
  *
  * This uses a self-sizing buffer to handle arbitrarily-long lines.
- * If the "process" function returns non-zero for any line, this
- * function will return non-zero after attempting to process all
- * remaining lines.
  */
-int
-process_lines(struct cpio *cpio, const char *pathname,
-    int (*process)(struct cpio *, const char *))
-{
+struct line_reader {
        FILE *f;
        char *buff, *buff_end, *line_start, *line_end, *p;
-       size_t buff_length, bytes_read, bytes_wanted;
+       char *pathname;
+       size_t buff_length;
        int separator;
        int ret;
+};
+
+struct line_reader *
+process_lines_init(const char *pathname, char separator)
+{
+       struct line_reader *lr;
+
+       lr = calloc(1, sizeof(*lr));
+       if (lr == NULL)
+               cpio_errc(1, ENOMEM, "Can't open %s", pathname);
 
-       separator = cpio->option_null ? '\0' : '\n';
-       ret = 0;
+       lr->separator = separator;
+       lr->pathname = strdup(pathname);
 
        if (strcmp(pathname, "-") == 0)
-               f = stdin;
+               lr->f = stdin;
        else
-               f = fopen(pathname, "r");
-       if (f == NULL)
+               lr->f = fopen(pathname, "r");
+       if (lr->f == NULL)
                cpio_errc(1, errno, "Couldn't open %s", pathname);
-       buff_length = 8192;
-       buff = malloc(buff_length);
-       if (buff == NULL)
+       lr->buff_length = 8192;
+       lr->buff = malloc(lr->buff_length);
+       if (lr->buff == NULL)
                cpio_errc(1, ENOMEM, "Can't read %s", pathname);
-       line_start = line_end = buff_end = buff;
+       lr->line_start = lr->line_end = lr->buff_end = lr->buff;
+
+       return (lr);
+}
+
+const char *
+process_lines_next(struct line_reader *lr)
+{
+       size_t bytes_wanted, bytes_read, new_buff_size;
+       char *line_start, *p;
+
        for (;;) {
-               /* Get some more data into the buffer. */
-               bytes_wanted = buff + buff_length - buff_end;
-               bytes_read = fread(buff_end, 1, bytes_wanted, f);
-               buff_end += bytes_read;
-               /* Process all complete lines in the buffer. */
-               while (line_end < buff_end) {
-                       if (*line_end == separator) {
-                               *line_end = '\0';
-                               if ((*process)(cpio, line_start) != 0)
-                                       ret = -1;
-                               line_start = line_end + 1;
-                               line_end = line_start;
+               /* If there's a line in the buffer, return it immediately. */
+               while (lr->line_end < lr->buff_end) {
+                       if (*lr->line_end == lr->separator) {
+                               *lr->line_end = '\0';
+                               line_start = lr->line_start;
+                               lr->line_start = lr->line_end + 1;
+                               lr->line_end = lr->line_start;
+                               return (line_start);
                        } else
-                               line_end++;
+                               lr->line_end++;
                }
-               if (feof(f))
-                       break;
-               if (ferror(f))
-                       cpio_errc(1, errno, "Can't read %s", pathname);
-               if (line_start > buff) {
+
+               /* If we're at end-of-file, process the final data. */
+               if (lr->f == NULL) {
+                       /* If there's more text, return one last line. */
+                       if (lr->line_end > lr->line_start) {
+                               *lr->line_end = '\0';
+                               line_start = lr->line_start;
+                               lr->line_start = lr->line_end + 1;
+                               lr->line_end = lr->line_start;
+                               return (line_start);
+                       }
+                       /* Otherwise, we're done. */
+                       return (NULL);
+               }
+
+               /* Buffer only has part of a line. */
+               if (lr->line_start > lr->buff) {
                        /* Move a leftover fractional line to the beginning. */
-                       memmove(buff, line_start, buff_end - line_start);
-                       buff_end -= line_start - buff;
-                       line_end -= line_start - buff;
-                       line_start = buff;
+                       memmove(lr->buff, lr->line_start,
+                           lr->buff_end - lr->line_start);
+                       lr->buff_end -= lr->line_start - lr->buff;
+                       lr->line_end -= lr->line_start - lr->buff;
+                       lr->line_start = lr->buff;
                } else {
                        /* Line is too big; enlarge the buffer. */
-                       p = realloc(buff, buff_length *= 2);
+                       new_buff_size = lr->buff_length * 2;
+                       if (new_buff_size <= lr->buff_length)
+                               cpio_errc(1, ENOMEM,
+                                   "Line too long in %s", lr->pathname);
+                       lr->buff_length = new_buff_size;
+                       p = realloc(lr->buff, new_buff_size);
                        if (p == NULL)
                                cpio_errc(1, ENOMEM,
-                                   "Line too long in %s", pathname);
-                       buff_end = p + (buff_end - buff);
-                       line_end = p + (line_end - buff);
-                       line_start = buff = p;
+                                   "Line too long in %s", lr->pathname);
+                       lr->buff_end = p + (lr->buff_end - lr->buff);
+                       lr->line_end = p + (lr->line_end - lr->buff);
+                       lr->line_start = lr->buff = p;
+               }
+
+               /* Get some more data into the buffer. */
+               bytes_wanted = lr->buff + lr->buff_length - lr->buff_end;
+               bytes_read = fread(lr->buff_end, 1, bytes_wanted, lr->f);
+               lr->buff_end += bytes_read;
+
+               if (ferror(lr->f))
+                       cpio_errc(1, errno, "Can't read %s", lr->pathname);
+               if (feof(lr->f)) {
+                       if (lr->f != stdin)
+                               fclose(lr->f);
+                       lr->f = NULL;
                }
        }
-       /* At end-of-file, handle the final line. */
-       if (line_end > line_start) {
-               *line_end = '\0';
-               if ((*process)(cpio, line_start) != 0)
-                       ret = -1;
-       }
-       free(buff);
-       if (f != stdin)
-               fclose(f);
-       return (ret);
+}
+
+void
+process_lines_free(struct line_reader *lr)
+{
+       free(lr->buff);
+       free(lr->pathname);
+       free(lr);
 }
index ecec2eeec8e80d1be810352f61022629743c230f..78086331bb0d23ebd164670a9399bd1cee6aac4f 100644 (file)
@@ -53,12 +53,12 @@ struct cpio {
        int               extract_flags; /* Flags for extract operation */
        char              symlink_mode; /* H or L, per BSD conventions */
        const char       *compress_program;
+       char              line_separator; /* --null ? '\0' : '\n' */
        int               option_append; /* -A, only relevant for -o */
        int               option_atime_restore; /* -a */
        int               option_follow_links; /* -L */
        int               option_link; /* -l */
        int               option_list; /* -t */
-       int               option_null; /* -0 --null */
        int               option_rename; /* -r */
        char             *destdir;
        size_t            pass_destpath_alloc;
@@ -98,9 +98,13 @@ enum {
        OPTION_VERSION
 };
 
+struct line_reader;
+
+struct line_reader *process_lines_init(const char *, char separator);
+const char *process_lines_next(struct line_reader *);
+void   process_lines_free(struct line_reader *);
+
 int    cpio_getopt(struct cpio *cpio);
-int    process_lines(struct cpio *cpio, const char *pathname,
-                   int (*process)(struct cpio *, const char *));
 int    include_from_file(struct cpio *, const char *);
 
 #endif
index f98421e2df48d999fdc029cea27a614ce8de11b9..8d1798fd50fffdbc6c0fb0db6aa4c6acf681949d 100644 (file)
@@ -107,7 +107,16 @@ include(struct cpio *cpio, const char *pattern)
 int
 include_from_file(struct cpio *cpio, const char *pathname)
 {
-       return (process_lines(cpio, pathname, &include));
+       struct line_reader *lr;
+       const char *p;
+       int ret = 0;
+
+       lr = process_lines_init(pathname, '\n');
+       while ((p = process_lines_next(lr)) != NULL)
+               if (include(cpio, p) != 0)
+                       ret = -1;
+       process_lines_free(lr);
+       return (ret);
 }
 
 static void