X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=src%2Flharc.c;h=8f2894203f0cd9a911db60467e635ff72cebaf6b;hb=cac04476fbf56b8b99ea857ffde147e682f06ab8;hp=7317c17cc0b4f4ebe57a3218dc80bbf096ef15f5;hpb=5df18b2098d6211e92a1756a2e9ed4aba618649a;p=lha%2Flha.git diff --git a/src/lharc.c b/src/lharc.c index 7317c17..8f28942 100644 --- a/src/lharc.c +++ b/src/lharc.c @@ -1,45 +1,44 @@ /* ------------------------------------------------------------------------ */ -/* LHa for UNIX */ -/* lharc.c -- append to archive */ -/* */ -/* Copyright (C) MCMLXXXIX Yooichi.Tagawa */ -/* Modified Nobutaka Watazaki */ -/* Thanks to H.Yoshizaki. (MS-DOS LHarc) */ -/* */ -/* Ver. 0.00 Original 1988.05.23 Y.Tagawa */ -/* Ver. 0.01 Alpha Version (for 4.2BSD) 1989.05.28 Y.Tagawa */ -/* Ver. 0.02 Alpha Version Rel.2 1989.05.29 Y.Tagawa */ -/* Ver. 0.03 Release #3 Beta Version 1989.07.02 Y.Tagawa */ -/* Ver. 0.03a Debug 1989.07.03 Y.Tagawa */ -/* Ver. 0.03b Modified 1989.07.13 Y.Tagawa */ -/* Ver. 0.03c Debug (Thanks to void@rena.dit.junet) */ -/* 1989.08.09 Y.Tagawa */ -/* Ver. 0.03d Modified (quiet and verbose) 1989.09.14 Y.Tagawa */ -/* V1.00 Fixed 1989.09.22 Y.Tagawa */ -/* V1.01 Bug Fixed 1989.12.25 Y.Tagawa */ -/* */ -/* DOS-Version Original LHx V C2.01 (C) H.Yohizaki */ -/* */ -/* V2.00 UNIX Lharc + DOS LHx -> OSK LHx 1990.11.01 Momozou */ -/* V2.01 Minor Modified 1990.11.24 Momozou */ -/* */ -/* Ver. 0.02 LHx for UNIX 1991.11.18 M.Oki */ -/* Ver. 0.03 LHa for UNIX 1991.12.17 M.Oki */ -/* Ver. 0.04 LHa for UNIX beta version 1992.01.20 M.Oki */ -/* Ver. 1.00 LHa for UNIX Fixed 1992.03.19 M.Oki */ -/* */ -/* Ver. 1.10 for Symbolic Link 1993.06.25 N.Watazaki */ -/* Ver. 1.11 for Symbolic Link Bug Fixed 1993.08.18 N.Watazaki */ -/* Ver. 1.12 for File Date Check 1993.10.28 N.Watazaki */ -/* Ver. 1.13 Bug Fixed (Idicator calcurate) 1994.02.21 N.Watazaki */ -/* Ver. 1.13a Bug Fixed (Sym. Link delete) 1994.03.11 N.Watazaki */ -/* Ver. 1.13b Bug Fixed (Sym. Link delete) 1994.07.29 N.Watazaki */ -/* Ver. 1.14 Source All chagned 1995.01.14 N.Watazaki */ -/* Ver. 1.14b,c Bug Fixed 1996.03.07 t.okamoto */ +/* LHa for UNIX */ +/* lharc.c -- append to archive */ +/* */ +/* Copyright (C) MCMLXXXIX Yooichi.Tagawa */ +/* Modified Nobutaka Watazaki */ +/* Thanks to H.Yoshizaki. (MS-DOS LHarc) */ +/* */ +/* Ver. 0.00 Original 1988.05.23 Y.Tagawa */ +/* Ver. 0.01 Alpha Version (for 4.2BSD) 1989.05.28 Y.Tagawa */ +/* Ver. 0.02 Alpha Version Rel.2 1989.05.29 Y.Tagawa */ +/* Ver. 0.03 Release #3 Beta Version 1989.07.02 Y.Tagawa */ +/* Ver. 0.03a Debug 1989.07.03 Y.Tagawa */ +/* Ver. 0.03b Modified 1989.07.13 Y.Tagawa */ +/* Ver. 0.03c Debug (Thanks to void@rena.dit.junet) */ +/* 1989.08.09 Y.Tagawa */ +/* Ver. 0.03d Modified (quiet and verbose) 1989.09.14 Y.Tagawa */ +/* V1.00 Fixed 1989.09.22 Y.Tagawa */ +/* V1.01 Bug Fixed 1989.12.25 Y.Tagawa */ +/* */ +/* DOS-Version Original LHx V C2.01 (C) H.Yohizaki */ +/* */ +/* V2.00 UNIX Lharc + DOS LHx -> OSK LHx 1990.11.01 Momozou */ +/* V2.01 Minor Modified 1990.11.24 Momozou */ +/* */ +/* Ver. 0.02 LHx for UNIX 1991.11.18 M.Oki */ +/* Ver. 0.03 LHa for UNIX 1991.12.17 M.Oki */ +/* Ver. 0.04 LHa for UNIX beta version 1992.01.20 M.Oki */ +/* Ver. 1.00 LHa for UNIX Fixed 1992.03.19 M.Oki */ +/* */ +/* Ver. 1.10 for Symbolic Link 1993.06.25 N.Watazaki */ +/* Ver. 1.11 for Symbolic Link Bug Fixed 1993.08.18 N.Watazaki */ +/* Ver. 1.12 for File Date Check 1993.10.28 N.Watazaki */ +/* Ver. 1.13 Bug Fixed (Idicator calcurate) 1994.02.21 N.Watazaki */ +/* Ver. 1.13a Bug Fixed (Sym. Link delete) 1994.03.11 N.Watazaki */ +/* Ver. 1.13b Bug Fixed (Sym. Link delete) 1994.07.29 N.Watazaki */ +/* Ver. 1.14 Source All chagned 1995.01.14 N.Watazaki */ +/* Ver. 1.14b,c Bug Fixed 1996.03.07 t.okamoto */ /* Ver. 1.14d Version up 1997.01.12 t.okamoto */ /* Ver. 1.14g Bug Fixed 2000.05.06 t.okamoto */ /* Ver. 1.14i Modified 2000.10.06 t.okamoto */ -/* Modified for Mac OS X 2002.06.03 H.Sakai */ /* ------------------------------------------------------------------------ */ #define LHA_MAIN_SRC @@ -50,51 +49,54 @@ static int error_occurred; /* static functions */ static void sort_files(); -static void print_version(); +static void print_version(); + +extern int optional_archive_kanji_code; +extern int optional_system_kanji_code; /* ------------------------------------------------------------------------ */ static void -init_variable() /* Added N.Watazaki */ +init_variable() /* Added N.Watazaki */ { /* options */ - quiet = FALSE; - text_mode = FALSE; - verbose = 0; - noexec = FALSE; /* debugging option */ - force = FALSE; - prof = FALSE; + quiet = FALSE; + text_mode = FALSE; + verbose = 0; + noexec = FALSE; /* debugging option */ + force = FALSE; + timestamp_archive = FALSE; - compress_method = DEFAULT_LZHUFF_METHOD; /* defined in config.h */ + compress_method = DEFAULT_LZHUFF_METHOD; /* defined in config.h */ - header_level = HEADER_LEVEL1; - quiet_mode = 0; + header_level = 2; /* level 2 */ + quiet_mode = 0; #ifdef EUC - euc_mode = FALSE; + euc_mode = FALSE; #endif /* view command flags */ - verbose_listing = FALSE; + verbose_listing = FALSE; /* extract command flags */ - output_to_stdout = FALSE; + output_to_stdout = FALSE; /* append command flags */ - new_archive = FALSE; - update_if_newer = FALSE; - delete_after_append = FALSE; - generic_format = FALSE; + new_archive = FALSE; + update_if_newer = FALSE; + delete_after_append = FALSE; + generic_format = FALSE; - remove_temporary_at_error = FALSE; - recover_archive_when_interrupt = FALSE; - remove_extracting_file_when_interrupt = FALSE; - get_filename_from_stdin = FALSE; - ignore_directory = FALSE; - verify_mode = FALSE; + recover_archive_when_interrupt = FALSE; + remove_extracting_file_when_interrupt = FALSE; + get_filename_from_stdin = FALSE; + ignore_directory = FALSE; + exclude_files = NULL; + verify_mode = FALSE; - noconvertcase = FALSE; + convertcase = FALSE; - extract_directory = NULL; + extract_directory = NULL; temporary_fd = -1; #if BACKUP_OLD_ARCHIVE @@ -102,31 +104,68 @@ init_variable() /* Added N.Watazaki */ #else backup_old_archive = FALSE; #endif + + extract_broken_archive = FALSE; + decode_macbinary_contents = FALSE; + sort_contents = TRUE; + recursive_archiving = TRUE; + dump_lzss = FALSE; } /* ------------------------------------------------------------------------ */ -/* NOTES : Text File Format */ -/* GENERATOR NewLine */ -/* [generic] 0D 0A */ -/* [MS-DOS] 0D 0A */ -/* [OS9][MacOS] 0D */ -/* [UNIX] 0A */ +/* NOTES : Text File Format */ +/* GENERATOR NewLine */ +/* [generic] 0D 0A */ +/* [MS-DOS] 0D 0A */ +/* [OS9][MacOS] 0D */ +/* [UNIX] 0A */ /* ------------------------------------------------------------------------ */ static void print_tiny_usage() { - fprintf(stderr, "\ + fprintf(stdout, "\ +usage: lha [-][] [- ...] archive_file [file...]\n\ + commands: [axelvudmcpt]\n\ + options: [q[012]vnfto[567]dizg012%s%s[w=|x=]]\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(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\ - Modified 2002 Hiroto Sakai\n\ - Autoconfiscated 2001,2002 Koji Arai\n\ +LHA-PMA for UNIX V 2 PMA added 2000 Maarten ter Huurne\n\ + Autoconfiscated 2001-2008 Koji Arai\n\ "); - fprintf(stderr, "\ -usage: lha [-]{axelvudmcp[q[num]][vnfodizg012]}[w=] archive_file [file...]\n\ + + print_tiny_usage(); + + 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\ @@ -134,326 +173,538 @@ 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, "\ - m Move to archive (means 'ad') o[567] compression method (a/u)\n\ + fprintf(stdout, "\ + m Move to archive (means 'ad') o[567] compression method (a/u/c)\n\ "); #endif #ifndef SUPPORT_LH7 - fprintf(stderr, "\ - m Move to archive (means 'ad') o use LHarc compatible method (a/u)\n\ + fprintf(stdout, "\ + m Move to archive (means 'ad') o use LHarc compatible method (a/u/c)\n\ "); #endif - fprintf(stderr, "\ - c re-Construct new archive w= specify extract directory (a/u/m/x/e)\n\ - p Print to STDOUT from archive d delete FILES after (a/u/c)\n\ - t Test file CRC in archive i ignore directory path (x/e)\n\ - z files not compress (a/u)\n\ + 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)\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 +#if HAVE_LIBAPPLEFILE + fprintf(stdout, "\ + b decode MacBinary (x/e)\n\ +"); +#endif + fprintf(stdout, "\ + w= specify extract directory (x/e)\n\ + x= eXclude files (a/u/c)\n\ +"); +} + +#include "getopt_long.h" + +/* + Parse LHA options +*/ +static int +parse_suboption(int argc, char **argv) +{ + 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[] = { + /* These options set a flag. */ + {"help", no_argument, 0, HELP_OPTION}, + {"version", no_argument, 0, VERSION_OPTION}, + + {"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, ×tamp_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; + int c = getopt_long(argc, argv, + short_options, long_options, + &option_index); + + if (c == -1) break; /* end of options */ + + switch (c) { + case 0: + /* Already set a flag variable by the definition of the + long_options. */ + break; + case '?': + /* Invalid option */ + print_tiny_usage(); + exit(2); + case HELP_OPTION: + print_usage(); + exit(0); + case VERSION_OPTION: + print_version(); + exit(0); + case 'q': + if (!optarg) { + /* In quiet mode, no confirm to overwrite */ + force = TRUE; + quiet = TRUE; + break; + } + + switch (*optarg) { + case '0': /* no quiet */ + case '1': /* no use the incremental indicator */ + quiet_mode = *optarg - '0'; + break; + case '2': /* no output */ + /* fall through */ + default: + force = TRUE; + quiet = TRUE; + break; + } + break; + case 'f': + force = TRUE; + break; + case 'v': + verbose++; + break; + case 't': + text_mode = TRUE; + break; +#ifdef EUC + case 'e': + text_mode = TRUE; + 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; + header_level = 0; + break; + case 'd': + delete_after_append = TRUE; + break; + case 'o': + if (!optarg) { + compress_method = LZHUFF1_METHOD_NUM; + header_level = 0; + break; + } + switch (*optarg) { + case '5': + compress_method = LZHUFF5_METHOD_NUM; + break; +#ifdef SUPPORT_LH7 + case '6': + compress_method = LZHUFF6_METHOD_NUM; + break; + case '7': + compress_method = LZHUFF7_METHOD_NUM; + break; +#endif + default: + error("invalid compression method 'o%c'", *optarg); + return -1; + } + break; + case 'z': + compress_method = LZHUFF0_METHOD_NUM; /* Changed N.Watazaki */ + break; + case 'i': + ignore_directory = TRUE; + break; + case 'x': + if (!optarg) { + error("exclude files does not specified for `-x'"); + exit(2); + } + + for (i = 0; exclude_files && exclude_files[i]; i++) + ; + exclude_files = (char**)xrealloc(exclude_files, + sizeof(char*) * (i+2)); + + if (*optarg == '=') + optarg++; + exclude_files[i] = optarg; + exclude_files[i+1] = 0; + + break; + case 'w': + if (!optarg) { + error("working directory does not specified for `-w'"); + exit(2); + } + if (*optarg == '=') + optarg++; + + extract_directory = optarg; + break; + case '0': + header_level = 0; + break; + case '1': + header_level = 1; + break; + case '2': + header_level = 2; + break; + case SYSTEM_KANJI_CODE_OPTION: + if (!optarg) { + error("kanji code not specified for --%s", + long_options[option_index].name); + return -1; + } + if (strcmp(optarg, "euc") == 0) { + optional_system_kanji_code = CODE_EUC; + } + else if (strcmp(optarg, "sjis") == 0) { + optional_system_kanji_code = CODE_SJIS; + } + else if (strcmp(optarg, "utf8") == 0) { + optional_system_kanji_code = CODE_UTF8; + } + else if (strcmp(optarg, "cap") == 0) { + optional_system_kanji_code = CODE_CAP; + } + else { + error("unknown kanji code \"%s\"", optarg); + return -1; + } + break; + + case ARCHIVE_KANJI_CODE_OPTION: + if (!optarg) { + error("kanji code not specified for --%s", + long_options[option_index].name); + return -1; + } + if (strcmp(optarg, "euc") == 0) { + optional_archive_kanji_code = CODE_EUC; + } + else if (strcmp(optarg, "sjis") == 0) { + optional_archive_kanji_code = CODE_SJIS; + } + else if (strcmp(optarg, "utf8") == 0) { + optional_archive_kanji_code = CODE_UTF8; + } + else if (strcmp(optarg, "cap") == 0) { + optional_archive_kanji_code = CODE_CAP; + } + else { + error("unknown kanji code \"%s\"", optarg); + return -1; + } + 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++; + argc--; + } + + cmd_filec = argc; + cmd_filev = argv; + + return 0; +} + +/* + Parse LHA command and options. +*/ +static int +parse_option(int argc, char **argv) +{ + char *cmd_char; + + 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; + cmd_filec = 0; + cmd_filev = 0; + return 0; + } + + cmd_char = argv[1]; + + if (cmd_char[0] == '-') + cmd_char++; + + /* parse commands */ + switch (*cmd_char) { + case 'x': + case 'e': + cmd = CMD_EXTRACT; + break; + + case 'p': + output_to_stdout = TRUE; + cmd = CMD_EXTRACT; + break; + + case 'c': + new_archive = TRUE; + cmd = CMD_ADD; + break; + + case 'a': + cmd = CMD_ADD; + break; + + case 'd': + cmd = CMD_DELETE; + break; + + case 'u': + update_if_newer = TRUE; + cmd = CMD_ADD; + break; + + case 'm': + delete_after_append = TRUE; + cmd = CMD_ADD; + break; + + case 'v': + verbose_listing = TRUE; + cmd = CMD_LIST; + break; + + case 'l': + cmd = CMD_LIST; + break; + + case 't': + cmd = CMD_EXTRACT; + verify_mode = TRUE; + break; + + default: + error("unknown command `-%c'", *cmd_char); + return -1; + } + + if (cmd_char[1] == '\0') { + /* argv[1] is command name */ + argv[1] = argv[0]; + argv++; + argc--; + } + else { + /* Eliminate command character + e.g.) lha cv foo.lzh -> lha -v foo.lzh + lha -cv foo.lzh -> lha -v foo.lzh + */ + cmd_char[0] = '-'; + argv[1] = cmd_char; + } + + return parse_suboption(argc, argv); } /* ------------------------------------------------------------------------ */ int main(argc, argv) - int argc; - char *argv[]; + int argc; + char *argv[]; { - char *p; - - int i; - int ac; - char **av, *m; + char *p; - init_variable(); /* Added N.Watazaki */ + int i; - ac = argc; - av = (char **)xmalloc( sizeof(char*)*argc ); - for (i=0; i= xfilec) { - xfilec += 256; - xfilev = (char **) xrealloc(xfilev, - sizeof(char *) * xfilec); - } - if (strlen(inpbuf) < 1) - continue; - xfilev[cmd_filec++] = xstrdup(inpbuf); - } - xfilev[cmd_filec] = NULL; - cmd_filev = xfilev; - } else { - cmd_filec = ac - 3; - cmd_filev = av + 3; - } - sort_files(); - - /* make crc table */ - make_crctable(); - - switch (cmd) { - case CMD_EXTRACT: - cmd_extract(); - break; - case CMD_ADD: - cmd_add(); - break; - case CMD_LIST: - cmd_list(); - break; - case CMD_DELETE: - cmd_delete(); - break; - } - -#ifdef USE_PROF - if (!prof) - exit(0); -#endif + cmd_filec = 0; + xfilev = (char **)xmalloc(sizeof(char *) * xfilec); + while (fgets(inpbuf, sizeof(inpbuf), stdin)) { + /* delete \n if it exist */ + i=0; p=inpbuf; + while (i < sizeof(inpbuf) && p != 0) { + if (*p == '\n') { + *p = 0; + break; + } + p++; i++; + } + + if (cmd_filec >= xfilec) { + xfilec += 256; + xfilev = (char **) xrealloc(xfilev, + sizeof(char *) * xfilec); + } + if (strlen(inpbuf) < 1) + continue; + xfilev[cmd_filec++] = xstrdup(inpbuf); + } + xfilev[cmd_filec] = NULL; + cmd_filev = xfilev; + } + + sort_files(); + + /* make crc table */ + make_crctable(); + + switch (cmd) { + case CMD_EXTRACT: + cmd_extract(); + break; + case CMD_ADD: + cmd_add(); + break; + case CMD_LIST: + cmd_list(); + break; + case CMD_DELETE: + cmd_delete(); + break; + } if (error_occurred) return 1; - return 0; + return 0; } /* ------------------------------------------------------------------------ */ -/* */ -/* ------------------------------------------------------------------------ */ - -/* ------------------------------------------------------------------------ */ static void print_version() { /* macro PACKAGE_NAME, PACKAGE_VERSION and PLATFORM are defined in config.h by configure script */ - fprintf(stderr, "%s version %s (%s)\n", + fprintf(stderr, "%s version %s (%s)\n", PACKAGE_NAME, PACKAGE_VERSION, PLATFORM); + fprintf(stderr, " configure options: %s\n", LHA_CONFIGURE_OPTIONS); } void @@ -468,7 +719,7 @@ message(fmt, va_alist) int errno_sv = errno; va_list v; - fprintf(stderr, "LHa: "); + fprintf(stderr, "LHa: "); va_init(v, fmt); vfprintf(stderr, fmt, v); @@ -492,7 +743,7 @@ warning(fmt, va_alist) int errno_sv = errno; va_list v; - fprintf(stderr, "LHa: Warning: "); + fprintf(stderr, "LHa: Warning: "); va_init(v, fmt); vfprintf(stderr, fmt, v); @@ -516,7 +767,7 @@ error(fmt, va_alist) int errno_sv = errno; va_list v; - fprintf(stderr, "LHa: Error: "); + fprintf(stderr, "LHa: Error: "); va_init(v, fmt); vfprintf(stderr, fmt, v); @@ -541,87 +792,93 @@ fatal_error(fmt, va_alist) int errno_sv = errno; va_list v; - fprintf(stderr, "LHa: Fatal error: "); + fprintf(stderr, "LHa: Fatal error: "); va_init(v, fmt); vfprintf(stderr, fmt, v); va_end(v); - if (errno) + if (errno) fprintf(stderr, ": %s\n", strerror(errno_sv)); else fputs("\n", stderr); - if (remove_temporary_at_error) { - if (temporary_fd != -1) - close(temporary_fd); + exit(1); +} + +void +cleanup() +{ + if (temporary_fd != -1) { + close(temporary_fd); + temporary_fd = -1; unlink(temporary_name); } - exit(1); + if (recover_archive_when_interrupt) { + rename(backup_archive_name, archive_name); + recover_archive_when_interrupt = FALSE; + } + if (remove_extracting_file_when_interrupt) { + message("Removing: %s", writing_filename); + unlink(writing_filename); + remove_extracting_file_when_interrupt = FALSE; + } } -/* ------------------------------------------------------------------------ */ RETSIGTYPE interrupt(signo) - int signo; + int signo; { - message("Interrupted"); - - if (temporary_fd != -1) - close(temporary_fd); - unlink(temporary_name); - if (recover_archive_when_interrupt) - rename(backup_archive_name, archive_name); - if (remove_extracting_file_when_interrupt) { - message("Removing: %s", writing_filename); - unlink(writing_filename); - } - signal(SIGINT, SIG_DFL); + message("Interrupted"); + + cleanup(); + + signal(SIGINT, SIG_DFL); #ifdef SIGHUP - signal(SIGHUP, SIG_DFL); + signal(SIGHUP, SIG_DFL); #endif - kill(getpid(), signo); + kill(getpid(), signo); } /* ------------------------------------------------------------------------ */ -/* */ +/* */ /* ------------------------------------------------------------------------ */ static int sort_by_ascii(a, b) - char **a, **b; + char **a, **b; { - register char *p, *q; - register int c1, c2; - - p = *a, q = *b; - if (generic_format) { - do { - c1 = *(unsigned char *) p++; - c2 = *(unsigned char *) q++; - if (!c1 || !c2) - break; - if (islower(c1)) - c1 = toupper(c1); - if (islower(c2)) - c2 = toupper(c2); - } - while (c1 == c2); - return c1 - c2; - } - else { - while (*p == *q && *p != '\0') - p++, q++; - return *(unsigned char *) p - *(unsigned char *) q; - } + register char *p, *q; + register int c1, c2; + + p = *a, q = *b; + if (generic_format) { + do { + c1 = *(unsigned char *) p++; + c2 = *(unsigned char *) q++; + if (!c1 || !c2) + break; + if (islower(c1)) + c1 = toupper(c1); + if (islower(c2)) + c2 = toupper(c2); + } + while (c1 == c2); + return c1 - c2; + } + else { + while (*p == *q && *p != '\0') + p++, q++; + return *(unsigned char *) p - *(unsigned char *) q; + } } /* ------------------------------------------------------------------------ */ static void sort_files() { - if (cmd_filec > 1) - qsort(cmd_filev, cmd_filec, sizeof(char *), sort_by_ascii); + if (cmd_filec > 1 && sort_contents) + qsort(cmd_filev, cmd_filec, sizeof(char *), sort_by_ascii); } /* ------------------------------------------------------------------------ */ @@ -630,9 +887,9 @@ xmalloc(size) size_t size; { void *p = malloc(size); - if (!p) - fatal_error("Not enough memory"); - return p; + if (!p) + fatal_error("Not enough memory"); + return p; } /* ------------------------------------------------------------------------ */ @@ -641,298 +898,330 @@ xrealloc(old, size) void *old; size_t size; { - void *p = (char *) realloc(old, size); - if (!p) - fatal_error("Not enough memory"); - return p; + void *p = (char *) realloc(old, size); + if (!p) + fatal_error("Not enough memory"); + return p; } char * xstrdup(str) - char *str; + char *str; { int len = strlen(str); - char *p = (char *)xmalloc(len + 1); - strcpy(p, str); - return p; + char *p = (char *)xmalloc(len + 1); + strcpy(p, str); /* ok */ + return p; } /* ------------------------------------------------------------------------ */ -/* STRING POOL */ +/* STRING POOL */ /* ------------------------------------------------------------------------ */ /* string pool : - +-------------+-------------+------+-------------+----------+ - | N A M E 1 \0| N A M E 2 \0| .... | N A M E n \0| | - +-------------+-------------+------+-------------+----------+ - ^ ^ ^ buffer+0 buffer+used buffer+size + +-------------+-------------+------+-------------+----------+ + | N A M E 1 \0| N A M E 2 \0| .... | N A M E n \0| | + +-------------+-------------+------+-------------+----------+ + ^ ^ ^ buffer+0 buffer+used buffer+size vector : - +---------------+---------------+------------- -----------------+ - | pointer to | pointer to | pointer to ... pointer to | - | stringpool | N A M E 1 | N A M E 2 ... N A M E n | - +---------------+---------------+------------- -------------+ - ^ malloc base returned + +---------------+---------------+------------- -----------------+ + | pointer to | pointer to | pointer to ... pointer to | + | stringpool | N A M E 1 | N A M E 2 ... N A M E n | + +---------------+---------------+------------- -------------+ + ^ malloc base returned */ /* ------------------------------------------------------------------------ */ void init_sp(sp) - struct string_pool *sp; + struct string_pool *sp; { - sp->size = 1024 - 8; /* any ( >=0 ) */ - sp->used = 0; - sp->n = 0; - sp->buffer = (char *) xmalloc(sp->size * sizeof(char)); + sp->size = 1024 - 8; /* any ( >=0 ) */ + sp->used = 0; + sp->n = 0; + sp->buffer = (char *) xmalloc(sp->size * sizeof(char)); } /* ------------------------------------------------------------------------ */ void add_sp(sp, name, len) - struct string_pool *sp; - char *name; /* stored '\0' at tail */ - int len; /* include '\0' */ + struct string_pool *sp; + char *name; /* stored '\0' at tail */ + int len; /* include '\0' */ { - while (sp->used + len > sp->size) { - sp->size *= 2; - sp->buffer = (char *) xrealloc(sp->buffer, sp->size * sizeof(char)); - } - memmove(sp->buffer + sp->used, name, len); - sp->used += len; - sp->n++; + while (sp->used + len > sp->size) { + sp->size *= 2; + sp->buffer = (char *) xrealloc(sp->buffer, sp->size * sizeof(char)); + } + memmove(sp->buffer + sp->used, name, len); + sp->used += len; + sp->n++; } /* ------------------------------------------------------------------------ */ void finish_sp(sp, v_count, v_vector) - register struct string_pool *sp; - int *v_count; - char ***v_vector; + register struct string_pool *sp; + int *v_count; + char ***v_vector; { - int i; - register char *p; - char **v; - - v = (char **) xmalloc((sp->n + 1) * sizeof(char *)); - *v++ = sp->buffer; - *v_vector = v; - *v_count = sp->n; - p = sp->buffer; - for (i = sp->n; i; i--) { - *v++ = p; - if (i - 1) - p += strlen(p) + 1; - } + int i; + register char *p; + char **v; + + v = (char **) xmalloc((sp->n + 1) * sizeof(char *)); + *v++ = sp->buffer; + *v_vector = v; + *v_count = sp->n; + p = sp->buffer; + for (i = sp->n; i; i--) { + *v++ = p; + if (i - 1) + p += strlen(p) + 1; + } } /* ------------------------------------------------------------------------ */ void free_sp(vector) - char **vector; + char **vector; { - vector--; - free(*vector); /* free string pool */ - free(vector); + vector--; + free(*vector); /* free string pool */ + free(vector); } /* ------------------------------------------------------------------------ */ -/* READ DIRECTORY FILES */ +/* READ DIRECTORY FILES */ /* ------------------------------------------------------------------------ */ static boolean include_path_p(path, name) - char *path, *name; + char *path, *name; { - char *n = name; - while (*path) - if (*path++ != *n++) - return (path[-1] == '/' && *n == '\0'); - return (*n == '/' || (n != name && path[-1] == '/' && n[-1] == '/')); + char *n = name; + while (*path) + if (*path++ != *n++) + return (path[-1] == '/' && *n == '\0'); + return (*n == '/' || (n != name && path[-1] == '/' && n[-1] == '/')); } /* ------------------------------------------------------------------------ */ void cleaning_files(v_filec, v_filev) - int *v_filec; - char ***v_filev; + int *v_filec; + char ***v_filev; { - char *flags; - struct stat stbuf; - - register char **filev = *v_filev; - register int filec = *v_filec; - register char *p; - register int i, j; - - if (filec == 0) - return; - - flags = xmalloc(filec * sizeof(char)); - - /* flags & 0x01 : 1: ignore */ - /* flags & 0x02 : 1: directory, 0 : regular file */ - /* flags & 0x04 : 1: need delete */ - - - for (i = 0; i < filec; i++) - if (GETSTAT(filev[i], &stbuf) < 0) { - flags[i] = 0x04; - warning("Cannot access \"%s\", ignored.", filev[i]); - } - else { - if (is_regularfile(&stbuf)) - flags[i] = 0x00; - else if (is_directory(&stbuf)) - flags[i] = 0x02; + char *flags; + struct stat stbuf; + + register char **filev = *v_filev; + register int filec = *v_filec; + register char *p; + register int i, j; + + if (filec == 0) + return; + + flags = xmalloc(filec * sizeof(char)); + + /* flags & 0x01 : 1: ignore */ + /* flags & 0x02 : 1: directory, 0 : regular file */ + /* flags & 0x04 : 1: need delete */ + + for (i = 0; i < filec; i++) + if (GETSTAT(filev[i], &stbuf) < 0) { + flags[i] = 0x04; + warning("Cannot access \"%s\" : %s; ignored.", filev[i], + strerror(errno)); + } + else { + if (is_regularfile(&stbuf)) + flags[i] = 0x00; + else if (is_directory(&stbuf)) + flags[i] = 0x02; #ifdef S_IFLNK - else if (is_symlink(&stbuf)) /* t.okamoto */ - flags[i] = 0x00; -#endif - else { - flags[i] = 0x04; - warning("Cannot archive \"%s\", ignored.", filev[i]); - } - } - - for (i = 0; i < filec; i++) { - p = filev[i]; - if ((flags[i] & 0x07) == 0x00) { /* regular file, not - * deleted/ignored */ - for (j = i + 1; j < filec; j++) { - if ((flags[j] & 0x07) == 0x00) { /* regular file, not - * deleted/ignored */ - if (STREQU(p, filev[j])) - flags[j] = 0x04; /* delete */ - } - } - } - else if ((flags[i] & 0x07) == 0x02) { /* directory, not - * deleted/ignored */ - for (j = i + 1; j < filec; j++) { - if ((flags[j] & 0x07) == 0x00) { /* regular file, not - * deleted/ignored */ - if (include_path_p(p, filev[j])) - flags[j] = 0x04; /* delete */ - } - else if ((flags[j] & 0x07) == 0x02) { /* directory, not - * deleted/ignored */ - if (include_path_p(p, filev[j])) - flags[j] = 0x04; /* delete */ - } - } - } - } - - for (i = j = 0; i < filec; i++) { - if ((flags[i] & 0x04) == 0) { - if (i != j) - filev[j] = filev[i]; - j++; - } - } - *v_filec = j; - - free(flags); + else if (is_symlink(&stbuf)) /* t.okamoto */ + flags[i] = 0x00; +#endif + else { + flags[i] = 0x04; + warning("Cannot archive \"%s\", ignored.", filev[i]); + } + } + + for (i = 0; i < filec; i++) { + p = filev[i]; + if ((flags[i] & 0x07) == 0x00) { /* regular file, not + * deleted/ignored */ + for (j = i + 1; j < filec; j++) { + if ((flags[j] & 0x07) == 0x00) { /* regular file, not + * deleted/ignored */ + if (STREQU(p, filev[j])) + flags[j] = 0x04; /* delete */ + } + } + } + else if ((flags[i] & 0x07) == 0x02) { /* directory, not + * deleted/ignored */ + for (j = i + 1; j < filec; j++) { + if ((flags[j] & 0x07) == 0x00) { /* regular file, not + * deleted/ignored */ + if (include_path_p(p, filev[j])) + flags[j] = 0x04; /* delete */ + } + else if ((flags[j] & 0x07) == 0x02) { /* directory, not + * deleted/ignored */ + if (include_path_p(p, filev[j])) + flags[j] = 0x04; /* delete */ + } + } + } + } + + for (i = j = 0; i < filec; i++) { + if ((flags[i] & 0x04) == 0) { + if (i != j) + filev[j] = filev[i]; + j++; + } + } + *v_filec = j; + + free(flags); } /* ------------------------------------------------------------------------ */ boolean find_files(name, v_filec, v_filev) - char *name; - int *v_filec; - char ***v_filev; + char *name; + int *v_filec; + char ***v_filev; { - struct string_pool sp; - char newname[FILENAME_LENGTH]; - int len, n; - DIR *dirp; + struct string_pool sp; + char newname[FILENAME_LENGTH]; + int len, n, i; + DIR *dirp; struct dirent *dp; - struct stat tmp_stbuf, arc_stbuf, fil_stbuf; - - strcpy(newname, name); - len = strlen(name); - if (len > 0 && newname[len - 1] != '/') - newname[len++] = '/'; - - dirp = opendir(name); - if (!dirp) - return FALSE; - - init_sp(&sp); - - GETSTAT(temporary_name, &tmp_stbuf); - GETSTAT(archive_name, &arc_stbuf); - - for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) { - n = NAMLEN(dp); - strncpy(newname + len, dp->d_name, n); - newname[len + n] = '\0'; - if (GETSTAT(newname, &fil_stbuf) < 0) - continue; -#if !defined(HAVE_STRUCT_STAT_ST_INO) || __MINGW32__ - if ( dp->d_name[0] != '.' || - (n != 1 && - (dp->d_name[1] != '.' || - n != 2)) ) { - add_sp(&sp, newname, len+n+1); - } -#else - if ((dp->d_ino != 0) && - /* exclude '.' and '..' */ - ((dp->d_name[0] != '.') || - ((n != 1) && - ((dp->d_name[1] != '.') || - (n != 2)))) && - ((tmp_stbuf.st_dev != fil_stbuf.st_dev || - tmp_stbuf.st_ino != fil_stbuf.st_ino) && - (arc_stbuf.st_dev != fil_stbuf.st_dev || - arc_stbuf.st_ino != fil_stbuf.st_ino))) { - add_sp(&sp, newname, len + n + 1); - } + struct stat tmp_stbuf, arc_stbuf, fil_stbuf; + int exist_tmp = 1, exist_arc = 1; + + len = str_safe_copy(newname, name, sizeof(newname)); + if (len > 0 && newname[len - 1] != '/') { + if (len < sizeof(newname)-1) + strcpy(&newname[len++], "/"); /* ok */ + else + warning("the length of pathname \"%s\" is too long.", name); + } + + dirp = opendir(name); + if (!dirp) + return FALSE; + + init_sp(&sp); + + if (GETSTAT(temporary_name, &tmp_stbuf) == -1) + exist_tmp = 0; + if (GETSTAT(archive_name, &arc_stbuf) == -1) + exist_arc = 0; + + while ((dp = readdir(dirp)) != NULL) { + n = NAMLEN(dp); + + /* exclude '.' and '..' */ + if (strncmp(dp->d_name, ".", n) == 0 + || strncmp(dp->d_name, "..", n) == 0) + continue; + + /* exclude exclude_files supplied by user */ + for (i = 0; exclude_files && exclude_files[i]; i++) { + if (fnmatch(exclude_files[i], dp->d_name, + FNM_PATHNAME|FNM_NOESCAPE|FNM_PERIOD) == 0) + goto next; + } + + if (len + n >= sizeof(newname)) { + warning("filename is too long"); + continue; + } + + strncpy(newname + len, dp->d_name, n); + newname[len + n] = '\0'; + if (GETSTAT(newname, &fil_stbuf) < 0) + continue; + +#if defined(HAVE_STRUCT_STAT_ST_INO) && !__MINGW32__ + /* MinGW has meaningless st_ino */ + + /* exclude temporary file, archive file and these links */ + if (exist_tmp && + tmp_stbuf.st_dev == fil_stbuf.st_dev && + tmp_stbuf.st_ino == fil_stbuf.st_ino) + continue; + + if (exist_arc && + arc_stbuf.st_dev == fil_stbuf.st_dev && + arc_stbuf.st_ino == fil_stbuf.st_ino) + continue; #endif - } - closedir(dirp); - finish_sp(&sp, v_filec, v_filev); - if (*v_filec > 1) - qsort(*v_filev, *v_filec, sizeof(char *), sort_by_ascii); - cleaning_files(v_filec, v_filev); - - return TRUE; + add_sp(&sp, newname, len+n+1); + next: + ; + } + closedir(dirp); + finish_sp(&sp, v_filec, v_filev); + if (*v_filec > 1 && sort_contents) + qsort(*v_filev, *v_filec, sizeof(char *), sort_by_ascii); + cleaning_files(v_filec, v_filev); + + return TRUE; } /* ------------------------------------------------------------------------ */ void free_files(filec, filev) - int filec; - char **filev; + int filec; + char **filev; { - free_sp(filev); + free_sp(filev); } /* ------------------------------------------------------------------------ */ -/* */ +/* */ /* ------------------------------------------------------------------------ */ /* Build temporary file name and store to TEMPORARY_NAME */ int build_temporary_name() { #ifdef TMP_FILENAME_TEMPLATE - /* "/tmp/lhXXXXXX" etc. */ - if (extract_directory == NULL) { - strcpy(temporary_name, TMP_FILENAME_TEMPLATE); - } - else { - xsnprintf(temporary_name, sizeof(temporary_name), + /* "/tmp/lhXXXXXX" etc. */ + if (extract_directory == NULL) { + str_safe_copy(temporary_name, TMP_FILENAME_TEMPLATE, + sizeof(temporary_name)); + } + else { + xsnprintf(temporary_name, sizeof(temporary_name), "%s/lhXXXXXX", extract_directory); - } + } #else - char *p, *s; - - strcpy(temporary_name, archive_name); - for (p = temporary_name, s = (char *) 0; *p; p++) - if (*p == '/') - s = p; - strcpy((s ? s + 1 : temporary_name), "lhXXXXXX"); + char *s; + + str_safe_copy(temporary_name, archive_name, sizeof(temporary_name)); + s = strrchr(temporary_name, '/'); + if (s) { + int len; + len = s - temporary_name; + if (len + strlen("lhXXXXXX") < sizeof(temporary_name)) + /* use directory at archive file */ + strcpy(s, "lhXXXXXX"); /* ok */ + else + /* use current directory */ + str_safe_copy(temporary_name, "lhXXXXXX", sizeof(temporary_name)); + } + else + /* use current directory */ + str_safe_copy(temporary_name, "lhXXXXXX", sizeof(temporary_name)); #endif #ifdef HAVE_MKSTEMP { @@ -959,211 +1248,216 @@ build_temporary_name() /* ------------------------------------------------------------------------ */ static void -modify_filename_extention(buffer, ext) - char *buffer; - char *ext; +modify_filename_extention(buffer, ext, size) + char *buffer; + char *ext; + size_t size; { - register char *p, *dot; + register char *p, *dot; - for (p = buffer, dot = (char *) 0; *p; p++) { - if (*p == '.') - dot = p; - else if (*p == '/') - dot = (char *) 0; - } + for (p = buffer, dot = (char *) 0; *p; p++) { + if (*p == '.') + dot = p; + else if (*p == '/') + dot = (char *) 0; + } - if (dot) - p = dot; + if (dot) + p = dot; - strcpy(p, ext); + str_safe_copy(p, ext, size - (p - buffer)); } /* ------------------------------------------------------------------------ */ /* build backup file name */ void -build_backup_name(buffer, original) - char *buffer; - char *original; +build_backup_name(buffer, original, size) + char *buffer; + char *original; + size_t size; { - strcpy(buffer, original); - modify_filename_extention(buffer, BACKUPNAME_EXTENTION); /* ".bak" */ + str_safe_copy(buffer, original, size); + modify_filename_extention(buffer, BACKUPNAME_EXTENTION, size); /* ".bak" */ } /* ------------------------------------------------------------------------ */ void -build_standard_archive_name(buffer, orginal) - char *buffer; - char *orginal; +build_standard_archive_name(buffer, original, size) + char *buffer; + char *original; + size_t size; { - strcpy(buffer, orginal); - modify_filename_extention(buffer, ARCHIVENAME_EXTENTION); /* ".lzh" */ + str_safe_copy(buffer, original, size); + modify_filename_extention(buffer, ARCHIVENAME_EXTENTION, size); /* ".lzh" */ } /* ------------------------------------------------------------------------ */ -/* */ +/* */ /* ------------------------------------------------------------------------ */ boolean need_file(name) - char *name; + char *name; { - int i; + int i; - if (cmd_filec == 0) - return TRUE; + if (cmd_filec == 0) + return TRUE; - for (i = 0; i < cmd_filec; i++) { - if (patmatch(cmd_filev[i], name, 0)) - return TRUE; - } + for (i = 0; i < cmd_filec; i++) { + if (patmatch(cmd_filev[i], name, 0)) + return TRUE; + } - return FALSE; + return FALSE; } FILE * xfopen(name, mode) - char *name, *mode; + char *name, *mode; { - FILE *fp; + FILE *fp; - if ((fp = fopen(name, mode)) == NULL) - fatal_error("Cannot open file \"%s\"", name); + if ((fp = fopen(name, mode)) == NULL) + fatal_error("Cannot open file \"%s\"", name); - return fp; + return fp; } /* ------------------------------------------------------------------------ */ -/* */ +/* */ /* ------------------------------------------------------------------------ */ static boolean open_old_archive_1(name, v_fp) - char *name; - FILE **v_fp; + char *name; + FILE **v_fp; { - FILE *fp; - struct stat stbuf; - - if (stat(name, &stbuf) >= 0 && - is_regularfile(&stbuf) && - (fp = fopen(name, READ_BINARY)) != NULL) { - *v_fp = fp; - archive_file_gid = stbuf.st_gid; - archive_file_mode = stbuf.st_mode; - return TRUE; - } - - *v_fp = NULL; - archive_file_gid = -1; - return FALSE; + FILE *fp; + struct stat stbuf; + + if (stat(name, &stbuf) >= 0 && + is_regularfile(&stbuf) && + (fp = fopen(name, READ_BINARY)) != NULL) { + *v_fp = fp; + archive_file_gid = stbuf.st_gid; + archive_file_mode = stbuf.st_mode; + return TRUE; + } + + *v_fp = NULL; + archive_file_gid = -1; + return FALSE; } /* ------------------------------------------------------------------------ */ 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 (!strcmp(archive_name, "-")) { + if (cmd == CMD_EXTRACT || cmd == CMD_LIST) { +#if defined(__MINGW32__) || defined(__DJGPP__) setmode(fileno(stdin), O_BINARY); #endif - return stdin; + return stdin; + } + else + return NULL; + } + + 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 */ + } } - else - return NULL; - } - p = strrchr(archive_name, '.'); - if (p) { - if (strucmp(".LZH", p) == 0 - || strucmp(".LZS", p) == 0 - || strucmp(".COM", p) == 0 /* DOS SFX */ - || strucmp(".EXE", p) == 0 - || strucmp(".X", p) == 0 /* HUMAN SFX */ - || strucmp(".BAK", p) == 0) { /* for BackUp */ - open_old_archive_1(archive_name, &fp); - return fp; - } - } - - 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; - } - /* - * 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; + free(p); + p = NULL; + } + + /* Try to open file just specified filename */ + if (open_old_archive_1(archive_name, &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 */ + } + } + +ret: + if (p) free(p); + return fp; } /* ------------------------------------------------------------------------ */ int inquire(msg, name, selective) - char *msg, *name, *selective; + char *msg, *name, *selective; { - char buffer[1024]; - char *p; + char buffer[1024]; + char *p; - for (;;) { - fprintf(stderr, "%s %s ", name, msg); - fflush(stderr); + for (;;) { + fprintf(stderr, "%s %s ", name, msg); + fflush(stderr); - fgets(buffer, 1024, stdin); + fgets(buffer, 1024, stdin); - for (p = selective; *p; p++) - if (buffer[0] == *p) - return p - selective; - } - /* NOTREACHED */ + for (p = selective; *p; p++) + if (buffer[0] == *p) + return p - selective; + } + /* NOTREACHED */ } /* ------------------------------------------------------------------------ */ void write_archive_tail(nafp) - FILE *nafp; + FILE *nafp; { - putc(0x00, nafp); + putc(0x00, nafp); } /* ------------------------------------------------------------------------ */ +#undef exit + void -copy_old_one(oafp, nafp, hdr) - FILE *oafp, *nafp; - LzHeader *hdr; +lha_exit(status) + int status; { - if (noexec) { - fseek(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); - } + cleanup(); + exit(status); } - -/* Local Variables: */ -/* mode:c */ -/* tab-width:4 */ -/* compile-command:"gcc -c lharc.c" */ -/* End: */ -/* vi: set tabstop=4: */