OSDN Git Service

ar.c was refined.
[lha/olha.git] / ar.c
diff --git a/ar.c b/ar.c
index 793cd43..7e42b8e 100644 (file)
--- a/ar.c
+++ b/ar.c
@@ -57,6 +57,7 @@ Structure of archive block (low order byte first):
 struct lha_method methods[] = {
     /* id, dicbit, pbit, maxmatch */
     /* note: dicbit == 0 means no compress */
+    /*       (1U << pbit) > np(dicbit+1) */
     {"-lh0-", 0,  0,  0},  /* 0: no compress */
     {"-lh1-", 12, 0, 60},  /* 1: 2^12 =  4KB dynamic huffman (LHarc) */
     {"-lh2-", 13, 0,256},  /* 2: 2^13 =  8KB dynamic huffman */
@@ -86,11 +87,6 @@ which_method(char *id)
     return NULL;
 }
 
-int unpackable;                 /* global, set in io.c */
-ulong compsize, origsize;       /* global */
-
-static char *temp_name = NULL;
-
 static void
 print_usage()
 {
@@ -200,13 +196,6 @@ search(int argc, char *argv[], struct lzh_header *h)
     return 0;
 }
 
-static void
-exitfunc(void)
-{
-    if (temp_name)
-        remove(temp_name);
-}
-
 #include "getopt_long.h"
 
 void
@@ -312,30 +301,291 @@ open_tempfile()
 {
     FILE *outfile;
 
-    temp_name = tmpnam(NULL);
-    outfile = fopen(temp_name, "wb");
+    outfile = tmpfile();
     if (outfile == NULL)
         error("Can't open temporary file");
-    atexit(exitfunc);
 
     return outfile;
 }
 
-int
-main(int argc, char *argv[])
+static void
+op_add(int cmd, char *archive_file, int argc, char **argv)
 {
-    int i, cmd, count, nfiles, found, done;
-    char *archive_file;
+    int i, count, found, done;
+    struct lzh_header h;
+    struct lzh_ostream w, *wp;
+    FILE *arcfile = NULL;
+    FILE *outfile = NULL;
+
+    wp = &w;
+
+    count = done = 0;
+
+    outfile = open_tempfile();
+    wp->fp = outfile;
+    wp->buf = 0;
+    if (*argv == 0)
+        error("archived files are not specified.");
+
+    arcfile = fopen(archive_file, "rb");
+    if (arcfile == NULL)
+        error("Can't open archive '%s'", archive_file);
+
+    while (!done && read_header(arcfile, &h)) {
+
+        found = search(argc, argv, &h);
+        if (found>0) {
+            argv[found-1] = 0;
+
+            if (cmd == 'u') {
+                time_t mtime;
+
+                if (file_mtime(h.filename, &mtime) == -1 || h.mtime > mtime) {
+                    copy(arcfile, outfile, &h);
+                    continue;
+                }
+            }
+
+            if (add(wp, 1, h.filename, h.namelen)) {
+                skip(arcfile, &h);
+                count++;
+            }
+            else
+                copy(arcfile, outfile, &h);
+        }
+        else
+            copy(arcfile, outfile, &h);
+    }
+
+    for (i = 0; i < argc; i++) {
+        if (argv[i]) {
+            count++;
+            add(wp, 0, argv[i], strlen(argv[i]));
+        }
+    }
+
+    if (opts.quiet < 2)
+        printf("  %d files\n", count);
+
+    if (count > 0) {
+        fputc(0, outfile);      /* end of archive */
+        if (ferror(outfile))
+            error("Can't write");
+        if (!opts.archive_to_stdio)
+            unlink(archive_file);
+
+        fclose(arcfile);
+        rewind(outfile);
+        if (copy_stream_to_file(outfile, archive_file) == -1)
+            error("fail to copy_stream_to_file(): temp -> %s",archive_file);
+    }
+}
+
+static void
+op_create(int cmd, char *archive_file, int argc, char **argv)
+{
+    int i;
+    struct lzh_ostream w, *wp;
+    FILE *outfile = NULL;
+
+    wp = &w;
+
+    outfile = open_tempfile();
+    wp->fp = outfile;
+    wp->buf = 0;
+    if (*argv == 0)
+        error("archived files are not specified.");
+
+    for (i = 0; i < argc; i++) {
+        add(wp, 0, argv[i], strlen(argv[i]));
+    }
+
+    fputc(0, outfile);      /* end of archive */
+    if (ferror(outfile))
+        error("Can't write");
+    rewind(outfile);
+    if (opts.archive_to_stdio) {
+        if (copy_stream(outfile, stdout) == -1)
+            error("fail to copy_stream_to_file(): temp -> %s","stdout");
+    }
+    else {
+        if (copy_stream_to_file(outfile, archive_file) == -1)
+            error("fail to copy_stream_to_file(): temp -> %s",archive_file);
+    }
+
+    return;
+}
+
+static void
+op_delete(int cmd, char *archive_file, int argc, char **argv)
+{
+    int count, found, done;
     struct lzh_header h;
     int arc_count;
-    struct lzh_istream r, *rp;
     struct lzh_ostream w, *wp;
     FILE *arcfile = NULL;
     FILE *outfile = NULL;
 
-    rp = &r;
     wp = &w;
 
+    count = done = 0;
+
+    if (argc == 0) {
+        message("No files given in argument, do nothing.");
+        return;
+    }
+    outfile = open_tempfile();
+
+    /* Open archive. */
+    if (opts.archive_to_stdio) {
+        arcfile = stdin;
+    }
+    else {
+        arcfile = fopen(archive_file, "rb");
+    }
+    if (arcfile == NULL)
+        error("Can't open archive '%s'", archive_file);
+
+    arc_count = 0;
+
+    while (!done && read_header(arcfile, &h)) {
+
+        arc_count++;
+
+        found = search(argc, argv, &h);
+        if (found) {
+            count++;
+            message("'%s' deleted", h.filename);
+            skip(arcfile, &h);
+        }
+        else
+            copy(arcfile, outfile, &h);
+    }
+
+    if (opts.quiet < 2)
+        printf("  %d files\n", count);
+
+    if (count > 0) {
+        fputc(0, outfile);      /* end of archive */
+        if (ferror(outfile))
+            error("Can't write");
+        if (!opts.archive_to_stdio)
+            unlink(archive_file);
+
+        fclose(arcfile);
+        rewind(outfile);
+
+        if (arc_count > count) {
+            if (copy_stream_to_file(outfile, archive_file) == -1)
+                error("fail to copy_stream_to_file(): temp -> %s",archive_file);
+        }
+        else {
+            message("The archive file \"%s\" was removed because it would be empty.", archive_file);
+        }
+    }
+}
+
+static void
+op_extract(int cmd, char *archive_file, int argc, char **argv)
+{
+    int count, nfiles, found, done;
+    struct lzh_header h;
+    struct lzh_istream r, *rp;
+    FILE *arcfile = NULL;
+
+    rp = &r;
+
+    count = done = nfiles = 0;
+
+    /* Open archive. */
+    if (opts.archive_to_stdio) {
+        arcfile = stdin;
+    }
+    else {
+        arcfile = fopen(archive_file, "rb");
+    }
+    if (arcfile == NULL)
+        error("Can't open archive '%s'", archive_file);
+
+    /* change directory to extract dir */
+    if (cmd == 'x') {
+        if (opts.outdir) {
+            if (mkdir(opts.outdir, 0777) == -1) {
+                if (errno != EEXIST)
+                    error("cannot make directory \"%s\"", opts.outdir);
+            }
+
+            if (chdir(opts.outdir) == -1)
+                error("cannot change directory \"%s\"", opts.outdir);
+        }
+    }
+
+    while (!done && read_header(arcfile, &h)) {
+
+        found = search(argc, argv, &h);
+        if (found != 0) {
+            rp->fp = arcfile;
+            rp->compsize = h.compsize;
+            extract(rp, cmd == 'x', &h);
+            if (++count == nfiles)
+                done = 1;
+        }
+        else
+            skip(arcfile, &h);
+    }
+
+    if (cmd != 'p') {
+        if (opts.quiet < 2)
+            printf("  %d files\n", count);
+    }
+}
+
+static void
+op_list(int cmd, char *archive_file, int argc, char **argv)
+{
+    int count, nfiles, found, done;
+    struct lzh_header h;
+    struct lzh_istream r, *rp;
+    FILE *arcfile = NULL;
+
+    rp = &r;
+
+    count = done = nfiles = 0;
+
+    /* Open archive. */
+    if (opts.archive_to_stdio) {
+        arcfile = stdin;
+    }
+    else {
+        arcfile = fopen(archive_file, "rb");
+    }
+    if (arcfile == NULL)
+        error("Can't open archive '%s'", archive_file);
+
+    while (!done && read_header(arcfile, &h)) {
+
+        found = search(argc, argv, &h);
+
+        if (found != 0) {
+            if (count == 0)
+                list_start();
+            list(&h);
+            if (++count == nfiles)
+                done = 1;
+        }
+        skip(arcfile, &h);
+    }
+
+    if (opts.quiet < 2)
+        printf("  %d files\n", count);
+}
+
+int
+main(int argc, char *argv[])
+{
+    int cmd;
+    char *archive_file;
+
     INITIALIZE_OPTS(opts);
 
     if (argv[1] == 0)
@@ -371,198 +621,46 @@ main(int argc, char *argv[])
 
     if (strcmp(archive_file, "-") == 0)
         opts.archive_to_stdio = 1;
+    if (opts.archive_to_stdio)
+        opts.quiet = 2;
 
     argv++;
     argc--;
 
     make_crctable();
-    count = done = nfiles = 0;
 
     switch (cmd) {
     case 'a':
     case 'u':
-    case 'c':
-        if (opts.archive_to_stdio)
-            opts.quiet = 2;
-
-        outfile = open_tempfile();
-        wp->fp = outfile;
-        if (*argv == 0)
-            error("archived files are not specified.");
-
-        if (!opts.archive_to_stdio && (cmd == 'a' || cmd == 'u')) {
-            if (file_exists(archive_file)) {
-                arcfile = fopen(archive_file, "rb");
-                if (arcfile == NULL)
-                    error("Can't open archive '%s'", archive_file);
-
-                break;
-            }
-        }
-        for (i = 0; i < argc; i++) {
-            add(wp, 0, argv[i], strlen(argv[i]));
-        }
-
-        fputc(0, outfile);      /* end of archive */
-        if (ferror(outfile))
-            error("Can't write");
-        fclose(outfile);
-        if (opts.archive_to_stdio) {
-            if (move_file_to_stream(temp_name, stdout) == -1)
-                error("fail to move_file_to_stream(): %s -> %s",temp_name,"stdout");
+        if (opts.archive_to_stdio || !file_exists(archive_file)) {
+            op_create(cmd, archive_file, argc, argv);
         }
         else {
-            unlink(archive_file);
-            if (xrename(temp_name, archive_file) == -1)
-                error("fail to rename(): %s -> %s",temp_name,archive_file);
+            op_add(cmd, archive_file, argc, argv);
         }
-        exit(0);
         break;
-    case 'r':
+
+    case 'c':
+        op_create(cmd, archive_file, argc, argv);
+        break;
+
     case 'd':
-        if (argc == 0) {
-            message("No files given in argument, do nothing.");
-            exit(0);
-        }
-        outfile = open_tempfile();
+        op_delete(cmd, archive_file, argc, argv);
+        break;
+
     case 'x':
     case 'p':
+        op_extract(cmd, archive_file, argc, argv);
+        break;
+
     case 'l':
     case 'v':
-        /* Open archive. */
-        if (opts.archive_to_stdio) {
-            arcfile = stdin;
-        }
-        else {
-            arcfile = fopen(archive_file, "rb");
-        }
-        if (arcfile == NULL)
-            error("Can't open archive '%s'", archive_file);
-
+        op_list(cmd, archive_file, argc, argv);
         break;
+
     default:
         print_usage();
         break;
     }
-
-    /* change directory to extract dir */
-    if (cmd == 'x') {
-        if (opts.outdir) {
-            if (mkdir(opts.outdir, 0777) == -1) {
-                if (errno != EEXIST)
-                    error("cannot make directory \"%s\"", opts.outdir);
-            }
-
-            if (chdir(opts.outdir) == -1)
-                error("cannot change directory \"%s\"", opts.outdir);
-        }
-    }
-
-    arc_count = 0;
-
-    while (!done && read_header(arcfile, &h)) {
-
-        arc_count++;
-
-        compsize = h.compsize;
-        origsize = h.origsize;
-
-        found = search(argc, argv, &h);
-        switch (cmd) {
-        case 'a':
-        case 'u':
-            if (found>0) {
-                argv[found-1] = 0;
-
-                if (cmd == 'u') {
-                    time_t mtime;
-
-                    if (file_mtime(h.filename, &mtime) == -1 || h.mtime > mtime) {
-                        copy(arcfile, outfile, &h);
-                        break;
-                    }
-                }
-
-                if (add(wp, 1, h.filename, h.namelen)) {
-                    skip(arcfile, &h);
-                    count++;
-                }
-                else
-                    copy(arcfile, outfile, &h);
-            }
-            else
-                copy(arcfile, outfile, &h);
-            break;
-        case 'd':
-            if (found) {
-                count++;
-                message("'%s' deleted", h.filename);
-                skip(arcfile, &h);
-            }
-            else
-                copy(arcfile, outfile, &h);
-            break;
-        case 'x':
-        case 'p':
-            if (found != 0) {
-                rp->fp = arcfile;
-                extract(rp, cmd == 'x', &h);
-                if (++count == nfiles)
-                    done = 1;
-            }
-            else
-                skip(arcfile, &h);
-            break;
-        case 'l':
-        case 'v':
-            if (found != 0) {
-                if (count == 0)
-                    list_start();
-                list(&h);
-                if (++count == nfiles)
-                    done = 1;
-            }
-            skip(arcfile, &h);
-            break;
-        }
-    }
-
-    if (cmd == 'a' || cmd == 'u') {
-        for (i = 0; i < argc; i++) {
-            if (argv[i]) {
-                count++;
-                add(wp, 0, argv[i], strlen(argv[i]));
-            }
-        }
-    }
-
-    if (cmd != 'p') {
-        if (opts.quiet < 2)
-            printf("  %d files\n", count);
-    }
-
-    if (count > 0 && (cmd == 'd' || cmd == 'a' || cmd == 'u')) {
-        fputc(0, outfile);      /* end of archive */
-        if (ferror(outfile))
-            error("Can't write");
-        if (!opts.archive_to_stdio)
-            unlink(archive_file);
-        fclose(outfile);
-        fclose(arcfile);
-        if (cmd == 'd') {
-            if (arc_count > count) {
-                if (xrename(temp_name, archive_file) == -1)
-                    error("fail to rename(): %s -> %s",temp_name,archive_file);
-            }
-            else {
-                message("The archive file \"%s\" was removed because it would be empty.", archive_file);
-            }
-        }
-        else {
-            if (xrename(temp_name, archive_file) == -1)
-                error("fail to rename(): %s -> %s",temp_name,archive_file);
-        }
-        exit(0);
-    }
     return EXIT_SUCCESS;
 }