OSDN Git Service

Fix path check
[lha/lha.git] / src / lharc.c
index 0840ae7..64e60db 100644 (file)
@@ -64,6 +64,7 @@ init_variable()     /* Added N.Watazaki */
     verbose         = 0;
     noexec          = FALSE;    /* debugging option */
     force           = FALSE;
+    timestamp_archive = FALSE;
 
     compress_method = DEFAULT_LZHUFF_METHOD; /* defined in config.h */
 
@@ -93,7 +94,7 @@ init_variable()     /* Added N.Watazaki */
     exclude_files                           = NULL;
     verify_mode                             = FALSE;
 
-    noconvertcase                           = FALSE;
+    convertcase                             = FALSE;
 
     extract_directory = NULL;
     temporary_fd = -1;
@@ -105,6 +106,10 @@ init_variable()     /* Added N.Watazaki */
 #endif
 
     extract_broken_archive = FALSE;
+    decode_macbinary_contents = FALSE;
+    sort_contents = TRUE;
+    recursive_archiving = TRUE;
+    dump_lzss = FALSE;
 }
 
 /* ------------------------------------------------------------------------ */
@@ -118,28 +123,49 @@ init_variable()     /* Added N.Watazaki */
 static void
 print_tiny_usage()
 {
-    fprintf(stderr, "\
+    fprintf(stdout, "\
 usage: lha [-]<commands>[<options>] [-<options> ...] archive_file [file...]\n\
   commands:  [axelvudmcpt]\n\
-  options:   [q[012]vnfto[567]dizg012e[w=<dir>|x=<pattern>]]\n");
+  options:   [q[012]vnfto[567]dizg012%s%s[w=<dir>|x=<pattern>]]\n\
+  long options: --system-kanji-code={euc,sjis,utf8,cap}\n\
+                --archive-kanji-code={euc,sjis,utf8,cap}\n\
+                --extract-broken-archive\n\
+                --convert-filename-case\n\
+                --ignore-mac-files\n\
+                --timestamp-archive\n\
+                --traditional\n\
+                --help\n\
+                --version\n"
+#ifdef EUC
+            ,"e"
+#else
+            ,""
+#endif
+#if HAVE_LIBAPPLEFILE
+            ,"b"                 /* decode_macbinary_contents */
+#else
+            ,""
+#endif
+            );
 }
 
 static void
 print_usage()
 {
-    fprintf(stderr, "\
+    fprintf(stdout, "\
 LHarc    for UNIX  V 1.02  Copyright(C) 1989  Y.Tagawa\n\
 LHx      for MSDOS V C2.01 Copyright(C) 1990  H.Yoshizaki\n\
 LHx(arc) for OSK   V 2.01  Modified     1990  Momozou\n\
 LHa      for UNIX  V 1.00  Copyright(C) 1992  Masaru Oki\n\
 LHa      for UNIX  V 1.14  Modified     1995  Nobutaka Watazaki\n\
 LHa      for UNIX  V 1.14i Modified     2000  Tsugio Okamoto\n\
-                   Autoconfiscated 2001-2004  Koji Arai\n\
+LHA-PMA  for UNIX  V 2     PMA added    2000  Maarten ter Huurne\n\
+                   Autoconfiscated 2001-2008  Koji Arai\n\
 ");
 
     print_tiny_usage();
 
-    fprintf(stderr, "\
+    fprintf(stdout, "\
 commands:                           options:\n\
  a   Add(or replace) to archive      q{num} quiet (num:quiet mode)\n\
  x,e EXtract from archive            v  verbose\n\
@@ -147,37 +173,36 @@ commands:                           options:\n\
  u   Update newer files to archive   f  force (over write at extract)\n\
  d   Delete from archive             t  FILES are TEXT file\n");
 #ifdef SUPPORT_LH7
-    fprintf(stderr, "\
+    fprintf(stdout, "\
  m   Move to archive (means 'ad')    o[567] compression method (a/u/c)\n\
 ");
 #endif
 #ifndef SUPPORT_LH7
-    fprintf(stderr, "\
+    fprintf(stdout, "\
  m   Move to archive (means 'ad')    o  use LHarc compatible method (a/u/c)\n\
 ");
 #endif
-    fprintf(stderr, "\
+    fprintf(stdout, "\
  c   re-Construct new archive        d  delete FILES after (a/u/c)\n\
  p   Print to STDOUT from archive    i  ignore directory path (x/e)\n\
  t   Test file CRC in archive        z  files not compress (a/u/c)\n\
                                      g  Generic format (for compatibility)\n\
-                                        or not convert case when extracting\n\
                                      0/1/2 header level (a/u/c)\n\
 ");
 #ifdef EUC
-    fprintf(stderr, "\
+    fprintf(stdout, "\
                                      e  TEXT code convert from/to EUC\n\
 ");
 #endif
-    fprintf(stderr, "\
+#if HAVE_LIBAPPLEFILE
+    fprintf(stdout, "\
+                                     b  decode MacBinary (x/e)\n\
+");
+#endif
+    fprintf(stdout, "\
                                      w=<dir> specify extract directory (x/e)\n\
                                      x=<pattern>  eXclude files (a/u/c)\n\
 ");
-#if IGNORE_DOT_FILES            /* experimental feature */
-    fprintf(stderr, "\
-                                     X ignore dot files (a/u/c)\n\
-");
-#endif
 }
 
 #include "getopt_long.h"
@@ -188,13 +213,14 @@ commands:                           options:\n\
 static int
 parse_suboption(int argc, char **argv)
 {
-    char *short_options = "q[012]vnfto[567]dizg012ew:x:";
-    /* "[...]" means optional 1 byte argument (original extention) */
     enum {
         HELP_OPTION = 256,
         VERSION_OPTION,
         SYSTEM_KANJI_CODE_OPTION,
         ARCHIVE_KANJI_CODE_OPTION,
+        TRADITIONAL_BEHAVIOR,
+        IGNORE_MAC_FILES,
+        DEBUG_OPTION,
     };
 
     struct option long_options[] = {
@@ -205,10 +231,22 @@ parse_suboption(int argc, char **argv)
         {"system-kanji-code", required_argument, 0, SYSTEM_KANJI_CODE_OPTION},
         {"archive-kanji-code", required_argument, 0, ARCHIVE_KANJI_CODE_OPTION},
         {"extract-broken-archive", no_argument, &extract_broken_archive, 1},
+        {"convert-filename-case", no_argument, &convertcase, TRUE},
+        {"traditional", no_argument, 0, TRADITIONAL_BEHAVIOR},
+        {"ignore-mac-files", no_argument, 0, IGNORE_MAC_FILES},
+        {"timestamp-archive", no_argument, &timestamp_archive, 1},
+        {"debug", required_argument, 0, DEBUG_OPTION},
         {0, 0, 0, 0}
     };
     int i;
 
+    char short_options[256] = "q[012]vnfto[567]dizg012ew:x:";
+    /* "[...]" means optional 1 byte argument (original extention) */
+
+#if HAVE_LIBAPPLEFILE
+    strncat(short_options, "b", sizeof(short_options)-strlen(short_options)-1);
+#endif
+
     /* parse option */
     while (1) {
         int option_index = 0;
@@ -269,12 +307,16 @@ parse_suboption(int argc, char **argv)
             euc_mode = TRUE;
             break;
 #endif
+#if HAVE_LIBAPPLEFILE
+        case 'b':
+            decode_macbinary_contents = TRUE;
+            break;
+#endif
         case 'n':
             noexec = TRUE;
             break;
         case 'g':
             generic_format = TRUE;
-            noconvertcase = TRUE;
             header_level = 0;
             break;
         case 'd':
@@ -326,17 +368,6 @@ parse_suboption(int argc, char **argv)
             exclude_files[i+1] = 0;
 
             break;
-#if IGNORE_DOT_FILES            /* experimental feature */
-        case 'X':
-            for (i = 0; exclude_files && exclude_files[i]; i++)
-                ;
-            exclude_files = (char**)xrealloc(exclude_files,
-                                             sizeof(char*) * (i+2));
-
-            exclude_files[i] = xstrdup(".*");
-            exclude_files[i+1] = 0;
-            break;
-#endif
         case 'w':
             if (!optarg) {
                 error("working directory does not specified for `-w'");
@@ -378,6 +409,8 @@ parse_suboption(int argc, char **argv)
                 error("unknown kanji code \"%s\"", optarg);
                 return -1;
             }
+            break;
+
         case ARCHIVE_KANJI_CODE_OPTION:
             if (!optarg) {
                 error("kanji code not specified for --%s",
@@ -402,20 +435,63 @@ parse_suboption(int argc, char **argv)
             }
             break;
 
+        case TRADITIONAL_BEHAVIOR:
+            convertcase = TRUE;
+            break;
+
+        case IGNORE_MAC_FILES:
+            /* ignore Mac specific files (._*, .DS_Store and Icon\r)
+               when archiving */
+            for (i = 0; exclude_files && exclude_files[i]; i++)
+                ;
+            exclude_files = (char**)xrealloc(exclude_files,
+                                             sizeof(char*) * (i+4));
+
+            exclude_files[i] = xstrdup("._*");
+            exclude_files[i+1] = xstrdup(".DS_Store");
+            exclude_files[i+2] = xstrdup("Icon\r");
+            exclude_files[i+3] = 0;
+            break;
+
+        case DEBUG_OPTION:
+            if (!optarg) {
+                error("debugging item is not specified for --%s",
+                      long_options[option_index].name);
+                return -1;
+            }
+            if (strcmp(optarg, "nosort") == 0) {
+                sort_contents = FALSE;
+            }
+            else if (strcmp(optarg, "norecursion") == 0) {
+                recursive_archiving = FALSE;
+            }
+            else if (strcmp(optarg, "dumplzss") == 0) {
+                dump_lzss = TRUE;
+                quiet = TRUE;
+            }
+            else {
+                error("unknown debugging item \"%s\" for --%s",
+                      optarg, long_options[option_index].name);
+                return -1;
+            }
+            break;
+
         default:
             error("unknown option `-%c'.", c);
             return -1;
         }
     }
 
+    argc -= optind;
+    argv += optind;
+
     if (!archive_name) {
-        archive_name = argv[optind];
-        argv++;
+        archive_name = *argv++;
         argc--;
     }
 
-    cmd_filec = argc - optind;
-    cmd_filev = argv + optind;
+    cmd_filec = argc;
+    cmd_filev = argv;
 
     return 0;
 }
@@ -428,11 +504,16 @@ parse_option(int argc, char **argv)
 {
     char *cmd_char;
 
-    if (argc == 1) {
+    if (argv[1] == NULL || strcmp(argv[1], "--help") == 0) {
         print_usage();
         exit(0);
     }
 
+    if (strcmp(argv[1], "--version") == 0) {
+        print_version();
+        exit(0);
+    }
+
     if (argc == 2 && *argv[1] != '-') {
         archive_name = argv[1];
         cmd = CMD_LIST;
@@ -623,6 +704,7 @@ print_version()
        defined in config.h by configure script */
     fprintf(stderr, "%s version %s (%s)\n",
             PACKAGE_NAME, PACKAGE_VERSION, PLATFORM);
+    fprintf(stderr, "  configure options: %s\n", LHA_CONFIGURE_OPTIONS);
 }
 
 void
@@ -795,7 +877,7 @@ sort_by_ascii(a, b)
 static void
 sort_files()
 {
-    if (cmd_filec > 1)
+    if (cmd_filec > 1 && sort_contents)
         qsort(cmd_filev, cmd_filec, sizeof(char *), sort_by_ascii);
 }
 
@@ -921,7 +1003,7 @@ include_path_p(path, name)
     char           *n = name;
     while (*path)
         if (*path++ != *n++)
-            return (path[-1] == '/' && *n == '\0');
+            return (path[-1] == '/' && n[-1] == '\0');
     return (*n == '/' || (n != name && path[-1] == '/' && n[-1] == '/'));
 }
 
@@ -1089,7 +1171,7 @@ find_files(name, v_filec, v_filev)
     }
     closedir(dirp);
     finish_sp(&sp, v_filec, v_filev);
-    if (*v_filec > 1)
+    if (*v_filec > 1 && sort_contents)
         qsort(*v_filev, *v_filec, sizeof(char *), sort_by_ascii);
     cleaning_files(v_filec, v_filev);
 
@@ -1270,13 +1352,13 @@ open_old_archive_1(name, v_fp)
 FILE           *
 open_old_archive()
 {
-    FILE           *fp;
-    char           *p;
+    FILE           *fp = NULL;
+    char           *p = NULL, *ext, *ext2;
     static char expanded_archive_name[FILENAME_LENGTH];
 
     if (!strcmp(archive_name, "-")) {
         if (cmd == CMD_EXTRACT || cmd == CMD_LIST) {
-#if __MINGW32__
+#if defined(__MINGW32__) || defined(__DJGPP__)
             setmode(fileno(stdin), O_BINARY);
 #endif
             return stdin;
@@ -1284,46 +1366,60 @@ open_old_archive()
         else
             return NULL;
     }
-    p = strrchr(archive_name, '.');
-    if (p) {
-        if (strcasecmp(".LZH", p) == 0
-            || strcasecmp(".LZS", p) == 0
-            || strcasecmp(".COM", p) == 0  /* DOS SFX */
-            || strcasecmp(".EXE", p) == 0
-            || strcasecmp(".X", p) == 0    /* HUMAN SFX */
-            || strcasecmp(".BAK", p) == 0) {   /* for BackUp */
-            open_old_archive_1(archive_name, &fp);
-            return fp;
+
+    ext2 = strrchr(archive_name, '.');
+    if (ext2) {
+        ext2++;
+
+        /* .com: DOS SFX
+           .exe: DOS SFX
+           .x:   HUMAN SFX
+           .bak: Backup file
+           .lha: Amiga(?) */
+        p = xstrdup("lzh," ADDITIONAL_SUFFIXES);
+        for (ext = strtok(p, ",");
+             ext;
+             ext = strtok(NULL, ",")) {
+
+            if (*ext == 0) continue;
+
+            if (strcasecmp(ext, ext2)) {
+                /* Try to open file just specified filename
+                   with usual suffixes.
+                   Return NULL if the file is not exist. */
+
+                open_old_archive_1(archive_name, &fp);
+                goto ret;       /* found or not */
+            }
         }
+        free(p);
+        p = NULL;
     }
 
+    /* Try to open file just specified filename */
     if (open_old_archive_1(archive_name, &fp))
-        return fp;
-    xsnprintf(expanded_archive_name, sizeof(expanded_archive_name),
-              "%s.lzh", archive_name);
-    if (open_old_archive_1(expanded_archive_name, &fp)) {
-        archive_name = expanded_archive_name;
-        return fp;
-    }
-    /*
-     * if ( (errno&0xffff)!=E_PNNF ) { archive_name =
-     * expanded_archive_name; return NULL; }
-     */
-    xsnprintf(expanded_archive_name, sizeof(expanded_archive_name),
-              "%s.lzs", archive_name);
-    if (open_old_archive_1(expanded_archive_name, &fp)) {
-        archive_name = expanded_archive_name;
-        return fp;
+        goto ret;               /* found */
+
+    /* Try to open file with implicit suffixes */
+    p = xstrdup("lzh," ADDITIONAL_SUFFIXES);
+    for (ext = strtok(p, ",");
+         ext;
+         ext = strtok(NULL, ",")) {
+
+        if (*ext == 0) continue;
+
+        xsnprintf(expanded_archive_name, sizeof(expanded_archive_name),
+                  "%s.%s", archive_name, ext);
+
+        if (open_old_archive_1(expanded_archive_name, &fp)) {
+            archive_name = expanded_archive_name;
+            goto ret;           /* found */
+        }
     }
-    /*
-     * if ( (errno&0xffff)!=E_PNNF ) { archive_name =
-     * expanded_archive_name; return NULL; }
-     */
-    /*
-     * sprintf( expanded_archive_name , "%s.lzh",archive_name);
-     * archive_name = expanded_archive_name;
-     */
-    return NULL;
+
+ret:
+    if (p) free(p);
+    return fp;
 }
 
 /* ------------------------------------------------------------------------ */
@@ -1356,21 +1452,6 @@ write_archive_tail(nafp)
 }
 
 /* ------------------------------------------------------------------------ */
-void
-copy_old_one(oafp, nafp, hdr)
-    FILE           *oafp, *nafp;
-    LzHeader       *hdr;
-{
-    if (noexec) {
-        fseeko(oafp, hdr->header_size + hdr->packed_size, SEEK_CUR);
-    }
-    else {
-        reading_filename = archive_name;
-        writing_filename = temporary_name;
-        copyfile(oafp, nafp, hdr->header_size + hdr->packed_size, 0, 0);
-    }
-}
-
 #undef exit
 
 void