1 /* ------------------------------------------------------------------------ */
3 /* lharc.c -- append to archive */
5 /* Copyright (C) MCMLXXXIX Yooichi.Tagawa */
6 /* Modified Nobutaka Watazaki */
7 /* Thanks to H.Yoshizaki. (MS-DOS LHarc) */
9 /* Ver. 0.00 Original 1988.05.23 Y.Tagawa */
10 /* Ver. 0.01 Alpha Version (for 4.2BSD) 1989.05.28 Y.Tagawa */
11 /* Ver. 0.02 Alpha Version Rel.2 1989.05.29 Y.Tagawa */
12 /* Ver. 0.03 Release #3 Beta Version 1989.07.02 Y.Tagawa */
13 /* Ver. 0.03a Debug 1989.07.03 Y.Tagawa */
14 /* Ver. 0.03b Modified 1989.07.13 Y.Tagawa */
15 /* Ver. 0.03c Debug (Thanks to void@rena.dit.junet) */
16 /* 1989.08.09 Y.Tagawa */
17 /* Ver. 0.03d Modified (quiet and verbose) 1989.09.14 Y.Tagawa */
18 /* V1.00 Fixed 1989.09.22 Y.Tagawa */
19 /* V1.01 Bug Fixed 1989.12.25 Y.Tagawa */
21 /* DOS-Version Original LHx V C2.01 (C) H.Yohizaki */
23 /* V2.00 UNIX Lharc + DOS LHx -> OSK LHx 1990.11.01 Momozou */
24 /* V2.01 Minor Modified 1990.11.24 Momozou */
26 /* Ver. 0.02 LHx for UNIX 1991.11.18 M.Oki */
27 /* Ver. 0.03 LHa for UNIX 1991.12.17 M.Oki */
28 /* Ver. 0.04 LHa for UNIX beta version 1992.01.20 M.Oki */
29 /* Ver. 1.00 LHa for UNIX Fixed 1992.03.19 M.Oki */
31 /* Ver. 1.10 for Symbolic Link 1993.06.25 N.Watazaki */
32 /* Ver. 1.11 for Symbolic Link Bug Fixed 1993.08.18 N.Watazaki */
33 /* Ver. 1.12 for File Date Check 1993.10.28 N.Watazaki */
34 /* Ver. 1.13 Bug Fixed (Idicator calcurate) 1994.02.21 N.Watazaki */
35 /* Ver. 1.13a Bug Fixed (Sym. Link delete) 1994.03.11 N.Watazaki */
36 /* Ver. 1.13b Bug Fixed (Sym. Link delete) 1994.07.29 N.Watazaki */
37 /* Ver. 1.14 Source All chagned 1995.01.14 N.Watazaki */
38 /* Ver. 1.14b,c Bug Fixed 1996.03.07 t.okamoto */
39 /* Ver. 1.14d Version up 1997.01.12 t.okamoto */
40 /* Ver. 1.14g Bug Fixed 2000.05.06 t.okamoto */
41 /* Ver. 1.14i Modified 2000.10.06 t.okamoto */
42 /* ------------------------------------------------------------------------ */
47 static int cmd = CMD_UNKNOWN;
48 static int error_occurred;
50 /* static functions */
51 static void sort_files();
52 static void print_version();
54 extern int optional_archive_kanji_code;
55 extern int optional_system_kanji_code;
57 /* ------------------------------------------------------------------------ */
59 init_variable() /* Added N.Watazaki */
65 noexec = FALSE; /* debugging option */
69 compress_method = DEFAULT_LZHUFF_METHOD; /* defined in config.h */
71 header_level = 2; /* level 2 */
79 /* view command flags */
80 verbose_listing = FALSE;
82 /* extract command flags */
83 output_to_stdout = FALSE;
85 /* append command flags */
87 update_if_newer = FALSE;
88 delete_after_append = FALSE;
89 generic_format = FALSE;
91 recover_archive_when_interrupt = FALSE;
92 remove_extracting_file_when_interrupt = FALSE;
93 get_filename_from_stdin = FALSE;
94 ignore_directory = FALSE;
100 extract_directory = NULL;
103 #if BACKUP_OLD_ARCHIVE
104 backup_old_archive = TRUE;
106 backup_old_archive = FALSE;
109 extract_broken_archive = FALSE;
110 decode_macbinary_contents = FALSE;
111 sort_contents = TRUE;
112 recursive_archiving = TRUE;
116 /* ------------------------------------------------------------------------ */
117 /* NOTES : Text File Format */
118 /* GENERATOR NewLine */
119 /* [generic] 0D 0A */
121 /* [OS9][MacOS] 0D */
123 /* ------------------------------------------------------------------------ */
128 usage: lha [-]<commands>[<options>] [-<options> ...] archive_file [file...]\n\
129 commands: [axelvudmcpt]\n\
130 options: [q[012]vnfto[567]dizg012s%s%s[w=<dir>|x=<pattern>]]\n\
131 long options: --system-kanji-code={euc,sjis,utf8,cap}\n\
132 --archive-kanji-code={euc,sjis,utf8,cap}\n\
133 --extract-broken-archive\n\
134 --convert-filename-case\n\
135 --ignore-mac-files\n\
144 #if HAVE_LIBAPPLEFILE
145 ,"b" /* decode_macbinary_contents */
156 LHarc for UNIX V 1.02 Copyright(C) 1989 Y.Tagawa\n\
157 LHx for MSDOS V C2.01 Copyright(C) 1990 H.Yoshizaki\n\
158 LHx(arc) for OSK V 2.01 Modified 1990 Momozou\n\
159 LHa for UNIX V 1.00 Copyright(C) 1992 Masaru Oki\n\
160 LHa for UNIX V 1.14 Modified 1995 Nobutaka Watazaki\n\
161 LHa for UNIX V 1.14i Modified 2000 Tsugio Okamoto\n\
162 Autoconfiscated 2001-2008 Koji Arai\n\
168 commands: options:\n\
169 a Add(or replace) to archive q{num} quiet (num:quiet mode)\n\
170 x,e EXtract from archive v verbose\n\
171 l,v List / Verbose List n not execute\n\
172 u Update newer files to archive f force (over write at extract)\n\
173 d Delete from archive t FILES are TEXT file\n");
176 m Move to archive (means 'ad') o[567] compression method (a/u/c)\n\
181 m Move to archive (means 'ad') o use LHarc compatible method (a/u/c)\n\
185 c re-Construct new archive d delete FILES after (a/u/c)\n\
186 p Print to STDOUT from archive i ignore directory path (x/e)\n\
187 t Test file CRC in archive z files not compress (a/u/c)\n\
188 g Generic format (for compatibility)\n\
189 0/1/2 header level (a/u/c)\n\
193 e TEXT code convert from/to EUC\n\
196 #if HAVE_LIBAPPLEFILE
198 b decode MacBinary (x/e)\n\
202 s time-stamp archive (a)\n\
203 w=<dir> specify extract directory (x/e)\n\
204 x=<pattern> eXclude files (a/u/c)\n\
208 #include "getopt_long.h"
214 parse_suboption(int argc, char **argv)
219 SYSTEM_KANJI_CODE_OPTION,
220 ARCHIVE_KANJI_CODE_OPTION,
221 TRADITIONAL_BEHAVIOR,
226 struct option long_options[] = {
227 /* These options set a flag. */
228 {"help", no_argument, 0, HELP_OPTION},
229 {"version", no_argument, 0, VERSION_OPTION},
231 {"system-kanji-code", required_argument, 0, SYSTEM_KANJI_CODE_OPTION},
232 {"archive-kanji-code", required_argument, 0, ARCHIVE_KANJI_CODE_OPTION},
233 {"extract-broken-archive", no_argument, &extract_broken_archive, 1},
234 {"convert-filename-case", no_argument, &convertcase, TRUE},
235 {"traditional", no_argument, 0, TRADITIONAL_BEHAVIOR},
236 {"ignore-mac-files", no_argument, 0, IGNORE_MAC_FILES},
237 {"debug", required_argument, 0, DEBUG_OPTION},
242 char short_options[256] = "q[012]vnfto[567]dizg012esw:x:";
243 /* "[...]" means optional 1 byte argument (original extention) */
245 #if HAVE_LIBAPPLEFILE
246 strncat(short_options, "b", sizeof(short_options)-strlen(short_options)-1);
251 int option_index = 0;
252 int c = getopt_long(argc, argv,
253 short_options, long_options,
256 if (c == -1) break; /* end of options */
260 /* Already set a flag variable by the definition of the
275 /* In quiet mode, no confirm to overwrite */
282 case '0': /* no quiet */
283 case '1': /* no use the incremental indicator */
284 quiet_mode = *optarg - '0';
286 case '2': /* no output */
309 #if HAVE_LIBAPPLEFILE
311 decode_macbinary_contents = TRUE;
321 generic_format = TRUE;
325 delete_after_append = TRUE;
329 compress_method = LZHUFF1_METHOD_NUM;
335 compress_method = LZHUFF5_METHOD_NUM;
339 compress_method = LZHUFF6_METHOD_NUM;
342 compress_method = LZHUFF7_METHOD_NUM;
346 error("invalid compression method 'o%c'", *optarg);
351 compress_method = LZHUFF0_METHOD_NUM; /* Changed N.Watazaki */
354 ignore_directory = TRUE;
358 error("exclude files does not specified for `-x'");
362 for (i = 0; exclude_files && exclude_files[i]; i++)
364 exclude_files = (char**)xrealloc(exclude_files,
365 sizeof(char*) * (i+2));
369 exclude_files[i] = optarg;
370 exclude_files[i+1] = 0;
375 error("working directory does not specified for `-w'");
381 extract_directory = optarg;
392 case SYSTEM_KANJI_CODE_OPTION:
394 error("kanji code not specified for --%s",
395 long_options[option_index].name);
398 if (strcmp(optarg, "euc") == 0) {
399 optional_system_kanji_code = CODE_EUC;
401 else if (strcmp(optarg, "sjis") == 0) {
402 optional_system_kanji_code = CODE_SJIS;
404 else if (strcmp(optarg, "utf8") == 0) {
405 optional_system_kanji_code = CODE_UTF8;
407 else if (strcmp(optarg, "cap") == 0) {
408 optional_system_kanji_code = CODE_CAP;
411 error("unknown kanji code \"%s\"", optarg);
416 case ARCHIVE_KANJI_CODE_OPTION:
418 error("kanji code not specified for --%s",
419 long_options[option_index].name);
422 if (strcmp(optarg, "euc") == 0) {
423 optional_archive_kanji_code = CODE_EUC;
425 else if (strcmp(optarg, "sjis") == 0) {
426 optional_archive_kanji_code = CODE_SJIS;
428 else if (strcmp(optarg, "utf8") == 0) {
429 optional_archive_kanji_code = CODE_UTF8;
431 else if (strcmp(optarg, "cap") == 0) {
432 optional_archive_kanji_code = CODE_CAP;
435 error("unknown kanji code \"%s\"", optarg);
440 case TRADITIONAL_BEHAVIOR:
444 case IGNORE_MAC_FILES:
445 /* ignore Mac specific files (._*, .DS_Store and Icon\r)
447 for (i = 0; exclude_files && exclude_files[i]; i++)
449 exclude_files = (char**)xrealloc(exclude_files,
450 sizeof(char*) * (i+4));
452 exclude_files[i] = xstrdup("._*");
453 exclude_files[i+1] = xstrdup(".DS_Store");
454 exclude_files[i+2] = xstrdup("Icon\r");
455 exclude_files[i+3] = 0;
460 error("debugging item is not specified for --%s",
461 long_options[option_index].name);
464 if (strcmp(optarg, "nosort") == 0) {
465 sort_contents = FALSE;
467 else if (strcmp(optarg, "norecursion") == 0) {
468 recursive_archiving = FALSE;
470 else if (strcmp(optarg, "dumplzss") == 0) {
475 error("unknown debugging item \"%s\" for --%s",
476 optarg, long_options[option_index].name);
482 error("unknown option `-%c'.", c);
491 archive_name = *argv++;
502 Parse LHA command and options.
505 parse_option(int argc, char **argv)
509 if (argv[1] == NULL || strcmp(argv[1], "--help") == 0) {
514 if (strcmp(argv[1], "--version") == 0) {
519 if (argc == 2 && *argv[1] != '-') {
520 archive_name = argv[1];
529 if (cmd_char[0] == '-')
540 output_to_stdout = TRUE;
558 update_if_newer = TRUE;
563 delete_after_append = TRUE;
568 verbose_listing = TRUE;
582 error("unknown command `-%c'", *cmd_char);
586 if (cmd_char[1] == '\0') {
587 /* argv[1] is command name */
593 /* Eliminate command character
594 e.g.) lha cv foo.lzh -> lha -v foo.lzh
595 lha -cv foo.lzh -> lha -v foo.lzh
601 return parse_suboption(argc, argv);
604 /* ------------------------------------------------------------------------ */
614 init_variable(); /* Added N.Watazaki */
616 if (parse_option(argc, argv) == -1) {
623 error("archive file does not specified");
629 if (!strcmp(archive_name, "-")) {
630 if (!isatty(1) && cmd == CMD_ADD)
633 #if 0 /* Comment out; IMHO, this feature is useless. by Koji Arai */
635 if (argc == 3 && !isatty(0)) { /* 1999.7.18 */
636 /* Bug(?) on MinGW, isatty() return 0 on Cygwin console.
637 mingw-runtime-1.3-2 and Cygwin 1.3.10(0.51/3/2) on Win2000 */
638 get_filename_from_stdin = TRUE;
643 /* target file name */
644 if (get_filename_from_stdin) {
650 xfilev = (char **)xmalloc(sizeof(char *) * xfilec);
651 while (fgets(inpbuf, sizeof(inpbuf), stdin)) {
652 /* delete \n if it exist */
654 while (i < sizeof(inpbuf) && p != 0) {
662 if (cmd_filec >= xfilec) {
664 xfilev = (char **) xrealloc(xfilev,
665 sizeof(char *) * xfilec);
667 if (strlen(inpbuf) < 1)
669 xfilev[cmd_filec++] = xstrdup(inpbuf);
671 xfilev[cmd_filec] = NULL;
701 /* ------------------------------------------------------------------------ */
705 /* macro PACKAGE_NAME, PACKAGE_VERSION and PLATFORM are
706 defined in config.h by configure script */
707 fprintf(stderr, "%s version %s (%s)\n",
708 PACKAGE_NAME, PACKAGE_VERSION, PLATFORM);
709 fprintf(stderr, " configure options: %s\n", LHA_CONFIGURE_OPTIONS);
714 message(char *fmt, ...)
716 message(fmt, va_alist)
721 int errno_sv = errno;
724 fprintf(stderr, "LHa: ");
727 vfprintf(stderr, fmt, v);
735 /* ------------------------------------------------------------------------ */
738 warning(char *fmt, ...)
740 warning(fmt, va_alist)
745 int errno_sv = errno;
748 fprintf(stderr, "LHa: Warning: ");
751 vfprintf(stderr, fmt, v);
759 /* ------------------------------------------------------------------------ */
762 error(char *fmt, ...)
769 int errno_sv = errno;
772 fprintf(stderr, "LHa: Error: ");
775 vfprintf(stderr, fmt, v);
787 fatal_error(char *fmt, ...)
789 fatal_error(fmt, va_alist)
794 int errno_sv = errno;
797 fprintf(stderr, "LHa: Fatal error: ");
800 vfprintf(stderr, fmt, v);
804 fprintf(stderr, ": %s\n", strerror(errno_sv));
814 if (temporary_fd != -1) {
817 unlink(temporary_name);
820 if (recover_archive_when_interrupt) {
821 rename(backup_archive_name, archive_name);
822 recover_archive_when_interrupt = FALSE;
824 if (remove_extracting_file_when_interrupt) {
825 message("Removing: %s", writing_filename);
826 unlink(writing_filename);
827 remove_extracting_file_when_interrupt = FALSE;
835 message("Interrupted");
839 signal(SIGINT, SIG_DFL);
841 signal(SIGHUP, SIG_DFL);
843 kill(getpid(), signo);
846 /* ------------------------------------------------------------------------ */
848 /* ------------------------------------------------------------------------ */
853 register char *p, *q;
857 if (generic_format) {
859 c1 = *(unsigned char *) p++;
860 c2 = *(unsigned char *) q++;
872 while (*p == *q && *p != '\0')
874 return *(unsigned char *) p - *(unsigned char *) q;
878 /* ------------------------------------------------------------------------ */
882 if (cmd_filec > 1 && sort_contents)
883 qsort(cmd_filev, cmd_filec, sizeof(char *), sort_by_ascii);
886 /* ------------------------------------------------------------------------ */
891 void *p = malloc(size);
893 fatal_error("Not enough memory");
897 /* ------------------------------------------------------------------------ */
903 void *p = (char *) realloc(old, size);
905 fatal_error("Not enough memory");
913 int len = strlen(str);
914 char *p = (char *)xmalloc(len + 1);
915 strcpy(p, str); /* ok */
919 /* ------------------------------------------------------------------------ */
921 /* ------------------------------------------------------------------------ */
924 +-------------+-------------+------+-------------+----------+
925 | N A M E 1 \0| N A M E 2 \0| .... | N A M E n \0| |
926 +-------------+-------------+------+-------------+----------+
927 ^ ^ ^ buffer+0 buffer+used buffer+size
930 +---------------+---------------+------------- -----------------+
931 | pointer to | pointer to | pointer to ... pointer to |
932 | stringpool | N A M E 1 | N A M E 2 ... N A M E n |
933 +---------------+---------------+------------- -------------+
934 ^ malloc base returned
937 /* ------------------------------------------------------------------------ */
940 struct string_pool *sp;
942 sp->size = 1024 - 8; /* any ( >=0 ) */
945 sp->buffer = (char *) xmalloc(sp->size * sizeof(char));
948 /* ------------------------------------------------------------------------ */
950 add_sp(sp, name, len)
951 struct string_pool *sp;
952 char *name; /* stored '\0' at tail */
953 int len; /* include '\0' */
955 while (sp->used + len > sp->size) {
957 sp->buffer = (char *) xrealloc(sp->buffer, sp->size * sizeof(char));
959 memmove(sp->buffer + sp->used, name, len);
964 /* ------------------------------------------------------------------------ */
966 finish_sp(sp, v_count, v_vector)
967 register struct string_pool *sp;
975 v = (char **) xmalloc((sp->n + 1) * sizeof(char *));
980 for (i = sp->n; i; i--) {
987 /* ------------------------------------------------------------------------ */
993 free(*vector); /* free string pool */
998 /* ------------------------------------------------------------------------ */
999 /* READ DIRECTORY FILES */
1000 /* ------------------------------------------------------------------------ */
1002 include_path_p(path, name)
1007 if (*path++ != *n++)
1008 return (path[-1] == '/' && *n == '\0');
1009 return (*n == '/' || (n != name && path[-1] == '/' && n[-1] == '/'));
1012 /* ------------------------------------------------------------------------ */
1014 cleaning_files(v_filec, v_filev)
1021 register char **filev = *v_filev;
1022 register int filec = *v_filec;
1029 flags = xmalloc(filec * sizeof(char));
1031 /* flags & 0x01 : 1: ignore */
1032 /* flags & 0x02 : 1: directory, 0 : regular file */
1033 /* flags & 0x04 : 1: need delete */
1035 for (i = 0; i < filec; i++)
1036 if (GETSTAT(filev[i], &stbuf) < 0) {
1038 warning("Cannot access \"%s\" : %s; ignored.", filev[i],
1042 if (is_regularfile(&stbuf))
1044 else if (is_directory(&stbuf))
1047 else if (is_symlink(&stbuf)) /* t.okamoto */
1052 warning("Cannot archive \"%s\", ignored.", filev[i]);
1056 for (i = 0; i < filec; i++) {
1058 if ((flags[i] & 0x07) == 0x00) { /* regular file, not
1059 * deleted/ignored */
1060 for (j = i + 1; j < filec; j++) {
1061 if ((flags[j] & 0x07) == 0x00) { /* regular file, not
1062 * deleted/ignored */
1063 if (STREQU(p, filev[j]))
1064 flags[j] = 0x04; /* delete */
1068 else if ((flags[i] & 0x07) == 0x02) { /* directory, not
1069 * deleted/ignored */
1070 for (j = i + 1; j < filec; j++) {
1071 if ((flags[j] & 0x07) == 0x00) { /* regular file, not
1072 * deleted/ignored */
1073 if (include_path_p(p, filev[j]))
1074 flags[j] = 0x04; /* delete */
1076 else if ((flags[j] & 0x07) == 0x02) { /* directory, not
1077 * deleted/ignored */
1078 if (include_path_p(p, filev[j]))
1079 flags[j] = 0x04; /* delete */
1085 for (i = j = 0; i < filec; i++) {
1086 if ((flags[i] & 0x04) == 0) {
1088 filev[j] = filev[i];
1097 /* ------------------------------------------------------------------------ */
1099 find_files(name, v_filec, v_filev)
1104 struct string_pool sp;
1105 char newname[FILENAME_LENGTH];
1109 struct stat tmp_stbuf, arc_stbuf, fil_stbuf;
1110 int exist_tmp = 1, exist_arc = 1;
1112 len = str_safe_copy(newname, name, sizeof(newname));
1113 if (len > 0 && newname[len - 1] != '/') {
1114 if (len < sizeof(newname)-1)
1115 strcpy(&newname[len++], "/"); /* ok */
1117 warning("the length of pathname \"%s\" is too long.", name);
1120 dirp = opendir(name);
1126 if (GETSTAT(temporary_name, &tmp_stbuf) == -1)
1128 if (GETSTAT(archive_name, &arc_stbuf) == -1)
1131 while ((dp = readdir(dirp)) != NULL) {
1134 /* exclude '.' and '..' */
1135 if (strncmp(dp->d_name, ".", n) == 0
1136 || strncmp(dp->d_name, "..", n) == 0)
1139 /* exclude exclude_files supplied by user */
1140 for (i = 0; exclude_files && exclude_files[i]; i++) {
1141 if (fnmatch(exclude_files[i], dp->d_name,
1142 FNM_PATHNAME|FNM_NOESCAPE|FNM_PERIOD) == 0)
1146 if (len + n >= sizeof(newname)) {
1147 warning("filename is too long");
1151 strncpy(newname + len, dp->d_name, n);
1152 newname[len + n] = '\0';
1153 if (GETSTAT(newname, &fil_stbuf) < 0)
1156 #if defined(HAVE_STRUCT_STAT_ST_INO) && !__MINGW32__
1157 /* MinGW has meaningless st_ino */
1159 /* exclude temporary file, archive file and these links */
1161 tmp_stbuf.st_dev == fil_stbuf.st_dev &&
1162 tmp_stbuf.st_ino == fil_stbuf.st_ino)
1166 arc_stbuf.st_dev == fil_stbuf.st_dev &&
1167 arc_stbuf.st_ino == fil_stbuf.st_ino)
1170 add_sp(&sp, newname, len+n+1);
1175 finish_sp(&sp, v_filec, v_filev);
1176 if (*v_filec > 1 && sort_contents)
1177 qsort(*v_filev, *v_filec, sizeof(char *), sort_by_ascii);
1178 cleaning_files(v_filec, v_filev);
1183 /* ------------------------------------------------------------------------ */
1185 free_files(filec, filev)
1192 /* ------------------------------------------------------------------------ */
1194 /* ------------------------------------------------------------------------ */
1195 /* Build temporary file name and store to TEMPORARY_NAME */
1197 build_temporary_name()
1199 #ifdef TMP_FILENAME_TEMPLATE
1200 /* "/tmp/lhXXXXXX" etc. */
1201 if (extract_directory == NULL) {
1202 str_safe_copy(temporary_name, TMP_FILENAME_TEMPLATE,
1203 sizeof(temporary_name));
1206 xsnprintf(temporary_name, sizeof(temporary_name),
1207 "%s/lhXXXXXX", extract_directory);
1212 str_safe_copy(temporary_name, archive_name, sizeof(temporary_name));
1213 s = strrchr(temporary_name, '/');
1216 len = s - temporary_name;
1217 if (len + strlen("lhXXXXXX") < sizeof(temporary_name))
1218 /* use directory at archive file */
1219 strcpy(s, "lhXXXXXX"); /* ok */
1221 /* use current directory */
1222 str_safe_copy(temporary_name, "lhXXXXXX", sizeof(temporary_name));
1225 /* use current directory */
1226 str_safe_copy(temporary_name, "lhXXXXXX", sizeof(temporary_name));
1232 old_umask = umask(077);
1233 fd = mkstemp(temporary_name);
1241 mktemp(temporary_name);
1242 flags = O_CREAT|O_EXCL|O_RDWR;
1246 return open(temporary_name, flags, 0600);
1251 /* ------------------------------------------------------------------------ */
1253 modify_filename_extention(buffer, ext, size)
1258 register char *p, *dot;
1260 for (p = buffer, dot = (char *) 0; *p; p++) {
1270 str_safe_copy(p, ext, size - (p - buffer));
1273 /* ------------------------------------------------------------------------ */
1274 /* build backup file name */
1276 build_backup_name(buffer, original, size)
1281 str_safe_copy(buffer, original, size);
1282 modify_filename_extention(buffer, BACKUPNAME_EXTENTION, size); /* ".bak" */
1285 /* ------------------------------------------------------------------------ */
1287 build_standard_archive_name(buffer, original, size)
1292 str_safe_copy(buffer, original, size);
1293 modify_filename_extention(buffer, ARCHIVENAME_EXTENTION, size); /* ".lzh" */
1296 /* ------------------------------------------------------------------------ */
1298 /* ------------------------------------------------------------------------ */
1308 for (i = 0; i < cmd_filec; i++) {
1309 if (patmatch(cmd_filev[i], name, 0))
1322 if ((fp = fopen(name, mode)) == NULL)
1323 fatal_error("Cannot open file \"%s\"", name);
1328 /* ------------------------------------------------------------------------ */
1330 /* ------------------------------------------------------------------------ */
1332 open_old_archive_1(name, v_fp)
1339 if (stat(name, &stbuf) >= 0 &&
1340 is_regularfile(&stbuf) &&
1341 (fp = fopen(name, READ_BINARY)) != NULL) {
1343 archive_file_gid = stbuf.st_gid;
1344 archive_file_mode = stbuf.st_mode;
1349 archive_file_gid = -1;
1353 /* ------------------------------------------------------------------------ */
1358 char *p = NULL, *ext, *ext2;
1359 static char expanded_archive_name[FILENAME_LENGTH];
1361 if (!strcmp(archive_name, "-")) {
1362 if (cmd == CMD_EXTRACT || cmd == CMD_LIST) {
1363 #if defined(__MINGW32__) || defined(__DJGPP__)
1364 setmode(fileno(stdin), O_BINARY);
1372 ext2 = strrchr(archive_name, '.');
1381 p = xstrdup("lzh," ADDITIONAL_SUFFIXES);
1382 for (ext = strtok(p, ",");
1384 ext = strtok(NULL, ",")) {
1386 if (*ext == 0) continue;
1388 if (strcasecmp(ext, ext2)) {
1389 /* Try to open file just specified filename
1390 with usual suffixes.
1391 Return NULL if the file is not exist. */
1393 open_old_archive_1(archive_name, &fp);
1394 goto ret; /* found or not */
1401 /* Try to open file just specified filename */
1402 if (open_old_archive_1(archive_name, &fp))
1403 goto ret; /* found */
1405 /* Try to open file with implicit suffixes */
1406 p = xstrdup("lzh," ADDITIONAL_SUFFIXES);
1407 for (ext = strtok(p, ",");
1409 ext = strtok(NULL, ",")) {
1411 if (*ext == 0) continue;
1413 xsnprintf(expanded_archive_name, sizeof(expanded_archive_name),
1414 "%s.%s", archive_name, ext);
1416 if (open_old_archive_1(expanded_archive_name, &fp)) {
1417 archive_name = expanded_archive_name;
1418 goto ret; /* found */
1427 /* ------------------------------------------------------------------------ */
1429 inquire(msg, name, selective)
1430 char *msg, *name, *selective;
1436 fprintf(stderr, "%s %s ", name, msg);
1439 fgets(buffer, 1024, stdin);
1441 for (p = selective; *p; p++)
1442 if (buffer[0] == *p)
1443 return p - selective;
1448 /* ------------------------------------------------------------------------ */
1450 write_archive_tail(nafp)
1456 /* ------------------------------------------------------------------------ */
1458 copy_old_one(oafp, nafp, hdr)
1463 fseeko(oafp, hdr->header_size + hdr->packed_size, SEEK_CUR);
1466 reading_filename = archive_name;
1467 writing_filename = temporary_name;
1468 copyfile(oafp, nafp, hdr->header_size + hdr->packed_size, 0, 0);