OSDN Git Service

ar.c was refined.
[lha/olha.git] / ar.c
diff --git a/ar.c b/ar.c
index fb0aae1..7e42b8e 100644 (file)
--- a/ar.c
+++ b/ar.c
@@ -2,6 +2,8 @@
        ar.c -- main file
 ***********************************************************/
 
+static char *version = "0.01";
+
 static char *usage =
     "ar -- compression archiver -- written by Haruhiko Okumura\n"
     "  PC-VAN:SCIENCE        CompuServe:74050,1022\n"
@@ -45,22 +47,61 @@ Structure of archive block (low order byte first):
 #include <stdlib.h>
 #include <string.h>
 #include <ctype.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <time.h>
+#include <utime.h>
+#include <unistd.h>
 #include "ar.h"
 
-#define FNAME_MAX (255 - 25)    /* max strlen(filename) */
-#define namelen  header[19]
-#define filename ((char *)&header[20])
+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 */
+    {"-lh3-", 13, 0,256},  /* 3: 2^13 =  8KB static huffman */
+    {"-lh4-", 12, 4,256},  /* 4: 2^12 =  4KB static huffman (pos and len)*/
+    {"-lh5-", 13, 4,256},  /* 5: 2^13 =  8KB static huffman (pos and len)*/
+    {"-lh6-", 15, 5,256},  /* 6: 2^15 = 32KB static huffman (pos and len)*/
+    {"-lh7-", 16, 5,256},  /* 7: 2^16 = 64KB static huffman (pos and len)*/
+    {"-lzs-", 11, 0, 17},  /* 8: 2^11 =  2KB (LArc) */
+    {"-lz5-", 12, 0, 17},  /* 9: 2^12 =  4KB (LArc) */
+    {"-lz4-", 0,  0,  0},  /*10: no compress (LArc) */
+    {"-lhd-", 0,  0,  0},  /*11: directory */
+};
+
+struct lha_opts opts;
+
+struct lha_method *
+which_method(char *id)
+{
+    int i;
+
+    for (i = 0; i < sizeof(methods)/sizeof(methods[0]); i++) {
+        if (strncmp(id, methods[i].id, sizeof(methods[0].id)) == 0) {
+            return &methods[i];
+        }
+    }
+    return NULL;
+}
 
-int unpackable;                 /* global, set in io.c */
-ulong compsize, origsize;       /* global */
+static void
+print_usage()
+{
+    printf("%s", usage);
+    exit(0);
+}
 
-static uchar buffer[DICSIZ];
-static uchar header[255];
-static uchar headersize, headersum;
-static uint file_crc;
-static char *temp_name;
+static void
+print_version()
+{
+    printf("version %s\n", version);
+    exit(0);
+}
 
-static uint
+uint
 ratio(ulong a, ulong b)
 {                               /* [(1000a + [b/2]) / b] */
     int i;
@@ -79,145 +120,32 @@ ratio(ulong a, ulong b)
     return (uint) ((a + (b >> 1)) / b);
 }
 
-static void
-put_to_header(int i, int n, ulong x)
-{
-    while (--n >= 0) {
-        header[i++] = (uchar) ((uint) x & 0xFF);
-        x >>= 8;
-    }
-}
-
-static ulong
-get_from_header(int i, int n)
-{
-    ulong s;
-
-    s = 0;
-    while (--n >= 0)
-        s = (s << 8) + header[i + n];   /* little endian */
-    return s;
-}
-
-static uint
-calc_headersum(void)
+void
+skip(FILE *fp, struct lzh_header *h)
 {
     int i;
-    uint s;
-
-    s = 0;
-    for (i = 0; i < headersize; i++)
-        s += header[i];
-    return s & 0xFF;
-}
-
-static int
-read_header(void)
-{
-    headersize = (uchar) fgetc(arcfile);
-    if (headersize == 0)
-        return 0;               /* end of archive */
-    headersum = (uchar) fgetc(arcfile);
-    fread_crc(header, headersize, arcfile);     /* CRC not used */
-    if (calc_headersum() != headersum)
-        error("Header sum error");
-    compsize = get_from_header(5, 4);
-    origsize = get_from_header(9, 4);
-    file_crc = (uint) get_from_header(headersize - 5, 2);
-    filename[namelen] = '\0';
-    return 1;                   /* success */
-}
-
-static void
-write_header(void)
-{
-    fputc(headersize, outfile);
-    /* We've destroyed file_crc by null-terminating filename. */
-    put_to_header(headersize - 5, 2, (ulong) file_crc);
-    fputc(calc_headersum(), outfile);
-    fwrite_crc(header, headersize, outfile);    /* CRC not used */
-}
-
-static void
-skip(void)
-{
-    fseek(arcfile, compsize, SEEK_CUR);
+    if (opts.archive_to_stdio)
+        for (i = 0; i < h->compsize; i++)
+            fgetc(fp);
+    else
+        fseek(fp, h->compsize, SEEK_CUR);
 }
 
 static void
-copy(void)
+copy(FILE *arcfile, FILE *outfile, struct lzh_header *h)
 {
     uint n;
+    uchar buffer[MAXDICSIZ];
 
-    write_header();
-    while (compsize != 0) {
-        n = (uint) ((compsize > DICSIZ) ? DICSIZ : compsize);
+    write_header(outfile, h);
+    while (h->compsize != 0) {
+        n = (uint) ((h->compsize > sizeof(buffer)) ? sizeof(buffer) : h->compsize);
         if (fread((char *) buffer, 1, n, arcfile) != n)
             error("Can't read");
         if (fwrite((char *) buffer, 1, n, outfile) != n)
             error("Can't write");
-        compsize -= n;
-    }
-}
-
-static void
-store(void)
-{
-    uint n;
-
-    origsize = 0;
-    crc = INIT_CRC;
-    while ((n = fread((char *) buffer, 1, DICSIZ, infile)) != 0) {
-        fwrite_crc(buffer, n, outfile);
-        origsize += n;
-    }
-    compsize = origsize;
-}
-
-static int
-add(int replace_flag)
-{
-    long headerpos, arcpos;
-    uint r;
-
-    if ((infile = fopen(filename, "rb")) == NULL) {
-        fprintf(stderr, "Can't open %s\n", filename);
-        return 0;               /* failure */
-    }
-    if (replace_flag) {
-        printf("Replacing %s ", filename);
-        skip();
+        h->compsize -= n;
     }
-    else
-        printf("Adding %s ", filename);
-    headerpos = ftell(outfile);
-    namelen = strlen(filename);
-    headersize = 25 + namelen;
-    memcpy(header, "-lh5-", 5); /* compress */
-    write_header();             /* temporarily */
-    arcpos = ftell(outfile);
-    origsize = compsize = 0;
-    unpackable = 0;
-    crc = INIT_CRC;
-    encode();
-    if (unpackable) {
-        header[3] = '0';        /* store */
-        rewind(infile);
-        fseek(outfile, arcpos, SEEK_SET);
-        store();
-    }
-    file_crc = crc ^ INIT_CRC;
-    fclose(infile);
-    put_to_header(5, 4, compsize);
-    put_to_header(9, 4, origsize);
-    memcpy(header + 13, "\0\0\0\0\x20\x01", 6);
-    memcpy(header + headersize - 3, "\x20\0\0", 3);
-    fseek(outfile, headerpos, SEEK_SET);
-    write_header();             /* true header */
-    fseek(outfile, 0L, SEEK_END);
-    r = ratio(compsize, origsize);
-    printf(" %d.%d%%\n", r / 10, r % 10);
-    return 1;                   /* success */
 }
 
 int
@@ -233,89 +161,6 @@ get_line(char *s, int n)
     return i;
 }
 
-static void
-extract(int to_file)
-{
-    int n, method;
-    uint ext_headersize;
-
-    if (to_file) {
-        while ((outfile = fopen(filename, "wb")) == NULL) {
-            fprintf(stderr, "Can't open %s\nNew filename: ", filename);
-            if (get_line(filename, FNAME_MAX) == 0) {
-                fprintf(stderr, "Not extracted\n");
-                skip();
-                return;
-            }
-            namelen = strlen(filename);
-        }
-        printf("Extracting %s ", filename);
-    }
-    else {
-        outfile = stdout;
-        printf("===== %s =====\n", filename);
-    }
-    crc = INIT_CRC;
-    method = header[3];
-    header[3] = ' ';
-    if (!strchr("045", method) || memcmp("-lh -", header, 5)) {
-        fprintf(stderr, "Unknown method: %u\n", method);
-        skip();
-    }
-    else {
-        ext_headersize = (uint) get_from_header(headersize - 2, 2);
-        while (ext_headersize != 0) {
-            fprintf(stderr, "There's an extended header of size %u.\n",
-                    ext_headersize);
-            compsize -= ext_headersize;
-            if (fseek(arcfile, ext_headersize - 2, SEEK_CUR))
-                error("Can't read");
-            ext_headersize = fgetc(arcfile);
-            ext_headersize += (uint) fgetc(arcfile) << 8;
-        }
-        crc = INIT_CRC;
-        if (method != '0')
-            decode_start();
-        while (origsize != 0) {
-            n = (uint) ((origsize > DICSIZ) ? DICSIZ : origsize);
-            if (method != '0')
-                decode(n, buffer);
-            else if (fread((char *) buffer, 1, n, arcfile) != n)
-                error("Can't read");
-            fwrite_crc(buffer, n, outfile);
-            if (outfile != stdout)
-                putc('.', stderr);
-            origsize -= n;
-        }
-    }
-    if (to_file)
-        fclose(outfile);
-    else
-        outfile = NULL;
-    printf("\n");
-    if ((crc ^ INIT_CRC) != file_crc)
-        fprintf(stderr, "CRC error\n");
-}
-
-static void
-list_start(void)
-{
-    printf("Filename         Original Compressed Ratio CRC Method\n");
-}
-
-static void
-list(void)
-{
-    uint r;
-
-    printf("%-14s", filename);
-    if (namelen > 14)
-        printf("\n              ");
-    r = ratio(compsize, origsize);
-    printf(" %10lu %10lu %u.%03u %04X %5.5s\n",
-           origsize, compsize, r / 1000, r % 1000, file_crc, header);
-}
-
 static int
 match(char *s1, char *s2)
 {
@@ -339,138 +184,483 @@ match(char *s1, char *s2)
 }
 
 static int
-search(int argc, char *argv[])
+search(int argc, char *argv[], struct lzh_header *h)
 {
     int i;
 
-    if (argc == 3)
-        return 1;
-    for (i = 3; i < argc; i++)
-        if (match(filename, argv[i]))
-            return 1;
+    if (argc == 0)
+        return -1;
+    for (i = 0; i < argc; i++)
+        if (argv[i] && match(h->filename, argv[i]))
+            return i+1;
     return 0;
 }
 
-static void
-exitfunc(void)
-{
-    fclose(outfile);
-    remove(temp_name);
-}
+#include "getopt_long.h"
 
-int
-main(int argc, char *argv[])
+void
+parse_args(int argc, char **argv)
 {
-    int i, j, cmd, count, nfiles, found, done;
+    int c;
 
-    /* Check command line arguments. */
-    if (argc < 3
-        || argv[1][1] != '\0' || !strchr("AXRDPL", cmd = toupper(argv[1][0]))
-        || (argc == 3 && strchr("AD", cmd)))
-        error(usage);
+    for (;;) {
+        /* int this_option_optind = optind ? optind : 1; */
+        int option_index = 0;
+
+        enum {
+            LHA_OPT_HELP = 128,
+            LHA_OPT_VERSION,
+        };
+
+        static struct option long_options[] = {
+            /* name, has_arg, *flag, val */
+            /* has_arg:
+               no_argument (0)
+               required_argument (1)
+               optional_argument (2)
+               flag:
+               NULL: getopt_long() return val
+               non-NULL: getopt_long() return 0, and *flag set val.
+            */
+            {"help", no_argument, NULL, LHA_OPT_HELP},
+            {"version", no_argument, NULL, LHA_OPT_VERSION},
+            {0, 0, 0, 0}
+        };
+
+        c = getopt_long(argc, argv, "012fgo[567]q[012]vw:z",
+                        long_options, &option_index);
+
+        if (c == -1) break;     /* end of parsing options */
+
+        switch (c) {
+        case '?':
+            print_usage();
+            break;
+        case 0:
+            /* set value by long option */
+            break;
+        case '0': case '1': case '2':
+            /* header level */
+            opts.header_level = c - '0';
+            break;
+        case 'f':
+            opts.force_extract = 1;
+            break;
+        case 'g':
+            opts.generic = 1;
+            opts.header_level = 0;
+            break;
+        case 'o':
+            /* compress method */
+            {
+                int idx = 1;    /* -o means -lh1- method */
 
-    /* Wildcards used? */
-    for (i = 3; i < argc; i++)
-        if (strpbrk(argv[i], "*?"))
+                if (optarg)
+                    idx = *optarg - '0'; /* -lh[567]- method */
+
+                opts.method   = &methods[idx];
+            }
+            break;
+        case 'q':
+            /* quiet mode */
+            opts.quiet = 2;     /* -q is equivalent to -q2 */
+            if (optarg)
+                opts.quiet = *optarg - '0';
+            break;
+        case 'v':
+            /* verbose mode */
+            opts.verbose = 1;
             break;
-    if (cmd == 'A' && i < argc)
-        error("Filenames may not contain '*' and '?'");
-    if (i < argc)
-        nfiles = -1;            /* contains wildcards */
-    else
-        nfiles = argc - 3;      /* number of files to process */
 
-    /* Open archive. */
-    arcfile = fopen(argv[2], "rb");
-    if (arcfile == NULL && cmd != 'A')
-        error("Can't open archive '%s'", argv[2]);
-
-    /* Open temporary file. */
-    if (strchr("ARD", cmd)) {
-        temp_name = tmpnam(NULL);
-        outfile = fopen(temp_name, "wb");
-        if (outfile == NULL)
-            error("Can't open temporary file");
-        atexit(exitfunc);
+        case 'w':
+            /* extract directory */
+            if (!optarg)
+                error("extract directory does not specified for `-w'");
+            if (*optarg == '=')
+                optarg++;
+
+            opts.outdir = optarg;
+            break;
+        case 'z':               /* no compress */
+            opts.nocompress = 1;
+            break;
+        case LHA_OPT_HELP:
+            print_usage();
+            break;
+        case LHA_OPT_VERSION:
+            print_version();
+            break;
+        default:
+            break;
+        }
     }
-    else
-        temp_name = NULL;
+}
+
+FILE *
+open_tempfile()
+{
+    FILE *outfile;
+
+    outfile = tmpfile();
+    if (outfile == NULL)
+        error("Can't open temporary file");
+
+    return outfile;
+}
+
+static void
+op_add(int cmd, char *archive_file, int argc, char **argv)
+{
+    int i, count, found, done;
+    struct lzh_header h;
+    struct lzh_ostream w, *wp;
+    FILE *arcfile = NULL;
+    FILE *outfile = NULL;
+
+    wp = &w;
 
-    make_crctable();
     count = done = 0;
 
-    if (cmd == 'A') {
-        for (i = 3; i < argc; i++) {
-            for (j = 3; j < i; j++)
-                if (strcmp(argv[j], argv[i]) == 0)
-                    break;
-            if (j == i) {
-                strcpy(filename, argv[i]);
-                if (add(0))
-                    count++;
-                else
-                    argv[i][0] = 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
-                nfiles--;
+                copy(arcfile, outfile, &h);
         }
-        if (count == 0 || arcfile == NULL)
-            done = 1;
+        else
+            copy(arcfile, outfile, &h);
     }
 
-    while (!done && read_header()) {
-        found = search(argc, argv);
-        switch (cmd) {
-        case 'R':
-            if (found) {
-                if (add(1))
-                    count++;
-                else
-                    copy();
-            }
-            else
-                copy();
-            break;
-        case 'A':
-        case 'D':
-            if (found) {
-                count += (cmd == 'D');
-                skip();
-            }
-            else
-                copy();
-            break;
-        case 'X':
-        case 'P':
-            if (found) {
-                extract(cmd == 'X');
-                if (++count == nfiles)
-                    done = 1;
-            }
-            else
-                skip();
-            break;
-        case 'L':
-            if (found) {
-                if (count == 0)
-                    list_start();
-                list();
-                if (++count == nfiles)
-                    done = 1;
-            }
-            skip();
-            break;
+    for (i = 0; i < argc; i++) {
+        if (argv[i]) {
+            count++;
+            add(wp, 0, argv[i], strlen(argv[i]));
         }
     }
 
-    if (temp_name != NULL && count != 0) {
+    if (opts.quiet < 2)
+        printf("  %d files\n", count);
+
+    if (count > 0) {
         fputc(0, outfile);      /* end of archive */
-        if (ferror(outfile) || fclose(outfile) == EOF)
+        if (ferror(outfile))
             error("Can't write");
-        remove(argv[2]);
-        rename(temp_name, argv[2]);
+        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_ostream w, *wp;
+    FILE *arcfile = NULL;
+    FILE *outfile = NULL;
+
+    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;
 
-    printf("  %d files\n", count);
+    /* 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)
+        print_usage();
+
+    /*take a command character */
+    {
+        char *arg1;
+
+        arg1 = argv[1];
+        if (arg1[0] == '-')
+            arg1++;
+        if (arg1[0] == 0)
+            print_usage();
+
+        cmd = *arg1;
+        if (arg1[1] == 0) {
+            /* -<cmd> -<opts> ... */
+            argv++;
+            argc--;
+        }
+        else {
+            /* -<cmd><opts> => -<opts> */
+            *arg1 = '-';
+        }
+    }
+
+    parse_args(argc, argv);
+    argv += optind;
+    argc -= optind;
+
+    archive_file = argv[0];
+
+    if (strcmp(archive_file, "-") == 0)
+        opts.archive_to_stdio = 1;
+    if (opts.archive_to_stdio)
+        opts.quiet = 2;
+
+    argv++;
+    argc--;
+
+    make_crctable();
+
+    switch (cmd) {
+    case 'a':
+    case 'u':
+        if (opts.archive_to_stdio || !file_exists(archive_file)) {
+            op_create(cmd, archive_file, argc, argv);
+        }
+        else {
+            op_add(cmd, archive_file, argc, argv);
+        }
+        break;
+
+    case 'c':
+        op_create(cmd, archive_file, argc, argv);
+        break;
+
+    case 'd':
+        op_delete(cmd, archive_file, argc, argv);
+        break;
+
+    case 'x':
+    case 'p':
+        op_extract(cmd, archive_file, argc, argv);
+        break;
+
+    case 'l':
+    case 'v':
+        op_list(cmd, archive_file, argc, argv);
+        break;
+
+    default:
+        print_usage();
+        break;
+    }
     return EXIT_SUCCESS;
 }