OSDN Git Service

65c26123a8d016cc87dabfce5651e92e8bb54c4f
[lha/lha.git] / src / lharc.c
1 /* ------------------------------------------------------------------------ */
2 /* LHa for UNIX                                                                                                                         */
3 /*                              lharc.c -- append to archive                                                            */
4 /*                                                                                                                                                      */
5 /*              Copyright (C) MCMLXXXIX Yooichi.Tagawa                                                          */
6 /*              Modified                        Nobutaka Watazaki                                                       */
7 /*                                                      Thanks to H.Yoshizaki. (MS-DOS LHarc)                   */
8 /*                                                                                                                                                      */
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            */
20 /*                                                                                                                                                      */
21 /*  DOS-Version Original LHx V C2.01            (C) H.Yohizaki                                  */
22 /*                                                                                                                                                      */
23 /*  V2.00  UNIX Lharc + DOS LHx -> OSK LHx              1990.11.01  Momozou                     */
24 /*  V2.01  Minor Modified                                               1990.11.24  Momozou                     */
25 /*                                                                                                                                                      */
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                       */
30 /*                                                                                                                                                      */
31 /*  Ver. 1.10  for Symblic Link                                 1993.06.25  N.Watazaki          */
32 /*  Ver. 1.11  for Symblic 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 /* ------------------------------------------------------------------------ */
43 #define LHA_MAIN_SRC
44
45 #include "lha.h"
46
47 /* ------------------------------------------------------------------------ */
48 /*                                                              PROGRAM                                                                         */
49 /* ------------------------------------------------------------------------ */
50 static int      cmd = CMD_UNKNOWN;
51
52 /* 1996.8.13 t.okamoto */
53 #if 0
54 char          **cmd_filev;
55 int             cmd_filec;
56
57 char           *archive_name;
58 char            expanded_archive_name[FILENAME_LENGTH];
59 char            temporary_name[FILENAME_LENGTH];
60 char            backup_archive_name[FILENAME_LENGTH];
61 #endif
62
63 /* static functions */
64 static void     sort_files();
65 static void             print_version();
66
67 char                *extract_directory = NULL;
68 char              **xfilev;
69 int             xfilec = 257;
70
71 /* 1996.8.13 t.okamoto */
72 #if 0
73 char           *writting_filename;
74 char           *reading_filename;
75
76 int             archive_file_mode;
77 int             archive_file_gid;
78 #endif
79 /* ------------------------------------------------------------------------ */
80 static void
81 init_variable()         /* Added N.Watazaki */
82 {
83 /* options */
84         quiet                   = FALSE;
85         text_mode               = FALSE;
86         verbose                 = FALSE;
87         noexec                  = FALSE;        /* debugging option */
88         force                   = FALSE;
89         prof                    = FALSE;
90 #ifndef SUPPORT_LH7
91         compress_method = LZHUFF5_METHOD_NUM;
92 #endif
93 #ifdef SUPPORT_LH7
94         compress_method = LZHUFF7_METHOD_NUM;
95 #endif
96
97         compress_method = DEFAULT_LZHUFF_METHOD;
98
99         header_level    = HEADER_LEVEL1;
100         quiet_mode              = 0;
101
102 #ifdef EUC
103         euc_mode                = FALSE;
104 #endif
105
106 /* view command flags */
107         verbose_listing = FALSE;
108
109 /* extract command flags */
110         output_to_stdout = FALSE;
111
112 /* append command flags */
113         new_archive                     = FALSE;
114         update_if_newer         = FALSE;
115         delete_after_append = FALSE;
116         generic_format          = FALSE;
117
118         remove_temporary_at_error                               = FALSE;
119         recover_archive_when_interrupt                  = FALSE;
120         remove_extracting_file_when_interrupt   = FALSE;
121         get_filename_from_stdin                                 = FALSE;
122         ignore_directory                                                = FALSE;
123         verify_mode                                                             = FALSE;
124
125         noconvertcase                                                   = FALSE;
126
127         extract_directory = NULL;
128         xfilec = 257;
129 }
130
131 /* ------------------------------------------------------------------------ */
132 /* NOTES :                      Text File Format                                                                                */
133 /* GENERATOR            NewLine                                                                                                 */
134 /* [generic]            0D 0A                                                                                                   */
135 /* [MS-DOS]                     0D 0A                                                                                                   */
136 /* [OS9][MacOS]         0D                                                                                                              */
137 /* [UNIX]                       0A                                                                                                              */
138 /* ------------------------------------------------------------------------ */
139 static void
140 print_tiny_usage_and_exit()
141 {
142         fprintf(stderr, "\
143 LHarc    for UNIX  V 1.02  Copyright(C) 1989  Y.Tagawa\n\
144 LHx      for MSDOS V C2.01 Copyright(C) 1990  H.Yoshizaki\n\
145 LHx(arc) for OSK   V 2.01  Modified     1990  Momozou\n\
146 LHa      for UNIX  V 1.00  Copyright(C) 1992  Masaru Oki\n\
147 LHa      for UNIX  V 1.14  Modified     1995  Nobutaka Watazaki\n\
148 LHa      for UNIX  V 1.14i Modified     2000  Tsugio Okamoto\n\
149 ");
150         fprintf(stderr, "\
151 usage: lha [-]{axelvudmcp[q[num]][vnfodizg012]}[w=<dir>] archive_file [file...]\n\
152 commands:                           options:\n\
153  a   Add(or replace) to archive      q{num} quiet (num:quiet mode)\n\
154  x,e EXtract from archive            v  verbose\n\
155  l,v List / Verbose List             n  not execute\n\
156  u   Update newer files to archive   f  force (over write at extract)\n\
157  d   Delete from archive             t  FILES are TEXT file\n");
158 #ifdef SUPPORT_LH7
159         fprintf(stderr, "\
160  m   Move to archive (means 'ad')    o[567] compression method (a/u)\n\
161 ");
162 #endif
163 #ifndef SUPPORT_LH7
164         fprintf(stderr, "\
165  m   Move to archive (means 'ad')    o  use LHarc compatible method (a/u)\n\
166 ");
167 #endif
168         fprintf(stderr, "\
169  c   re-Construct new archive        w=<dir> specify extract directory (a/u/m/x/e)\n\
170  p   Print to STDOUT from archive    d  delete FILES after (a/u/c)\n\
171  t   Test file CRC in archive        i  ignore directory path (x/e)\n\
172                                      z  files not compress (a/u)\n\
173                                      g  Generic format (for compatibility)\n\
174                                         or not convert case when extracting\n\
175                                      0/1/2 header level (a/u)\n\
176 ");
177 #ifdef EUC
178         fprintf(stderr, "\
179                                      e  TEXT code convert from/to EUC\n\
180 ");
181 #endif
182         exit(1);
183 }
184
185 /* ------------------------------------------------------------------------ */
186 int
187 main(argc, argv)
188         int             argc;
189         char           *argv[];
190 {
191         char           *p, inpbuf[256];
192
193         int i;
194         int  ac;
195         char **av, *m;
196
197         init_variable();                /* Added N.Watazaki */
198
199         ac = argc;
200         av = (char **)xmalloc( sizeof(char*)*argc );
201         for (i=0; i<argc; i++) {
202           if ((av[i] = strdup( argv[i] )) == NULL)
203                 fatal_error("not enough memory\n");
204         }
205
206         if (ac < 2)
207                 print_tiny_usage_and_exit();
208
209         if (strcmp(av[1], "--version") == 0) {
210                 print_version();
211                 exit(1);
212         }
213
214         if (ac < 3) {
215                 cmd = CMD_LIST;
216                 av--; /* argv--; */ /* 1999.7.18 */
217                 ac++; /* argc++; */
218                 goto work;
219         }
220
221         m = av[1];
222
223         if (m[0] == '-')
224                 m++;
225         /* commands */
226         switch (*m) {
227         case 'x':
228         case 'e':
229                 cmd = CMD_EXTRACT;
230                 break;
231
232         case 'p':
233                 output_to_stdout = TRUE;
234                 cmd = CMD_EXTRACT;
235                 break;
236
237         case 'c':
238                 new_archive = TRUE;
239                 cmd = CMD_ADD;
240                 break;
241
242         case 'a':
243                 cmd = CMD_ADD;
244                 break;
245
246         case 'd':
247                 cmd = CMD_DELETE;
248                 break;
249
250         case 'u':
251                 update_if_newer = TRUE;
252                 cmd = CMD_ADD;
253                 break;
254
255         case 'm':
256                 delete_after_append = TRUE;
257                 cmd = CMD_ADD;
258                 break;
259
260         case 'v':
261                 verbose_listing = TRUE;
262                 cmd = CMD_LIST;
263                 break;
264
265         case 'l':
266                 cmd = CMD_LIST;
267                 break;
268
269         case 't':
270                 cmd = CMD_EXTRACT;
271                 verify_mode = TRUE;
272                 break;
273
274         default:
275                 print_tiny_usage_and_exit();
276
277         }
278
279         /* options */
280         /* p = &argv[1][1]; */
281         p = m+1;
282         while ( *p != 0 ) {
283                 switch ((*p++)) {
284                 case 'q':
285                         switch (*p) {
286                         case '0':
287                         case '1':
288                                 quiet_mode = *p - '0';
289                                 ++p;
290                                 break;
291                         case '2':
292                         default:
293                                 quiet = TRUE;
294                                 break;
295                         }
296                 case 'f':
297                         force = TRUE;
298                         break;
299                 case 'p':
300                         prof = TRUE;
301                         break;
302                 case 'v':
303                         verbose = TRUE;
304                         break;
305                 case 't':
306                         text_mode = TRUE;
307                         break;
308 #ifdef EUC
309                 case 'e':
310                         text_mode = TRUE;
311                         euc_mode = TRUE;
312                         break;
313 #endif
314                 case 'n':
315                         noexec = TRUE;
316                         break;
317                 case 'g':
318                         generic_format = TRUE;
319                         noconvertcase = TRUE;
320                         header_level = 0;
321                         break;
322                 case 'd':
323                         delete_after_append = TRUE;
324                         break;
325                 case 'o':
326                         switch (*p) {
327                         case 0:
328                                 compress_method = LZHUFF1_METHOD_NUM;
329                                 header_level = 0;
330                                 break;
331                         case '5':
332                                 compress_method = LZHUFF5_METHOD_NUM;
333                                 p++;
334                                 break;
335 #ifdef SUPPORT_LH7
336                         case '6':
337                                 compress_method = LZHUFF6_METHOD_NUM;
338                                 p++;
339                                 break;
340                         case '7':
341                                 compress_method = LZHUFF7_METHOD_NUM;
342                                 p++;
343                                 break;
344 #endif
345                         default:
346                                 fprintf(stderr, "LHa: error option o%c\n", p[-1]);
347                                 exit(1);
348                         }
349                         break;
350                 case 'z':
351                         compress_method = LZHUFF0_METHOD_NUM;   /* Changed N.Watazaki */
352                         break;
353                 case 'i':
354                         ignore_directory = TRUE;
355                         break;
356                 case 'w':
357                         if (*p == '=')
358                                 p++;
359                         extract_directory = p;
360                         while (*p)
361                                 p++;
362                         break;
363                 case '0':
364                         header_level = HEADER_LEVEL0;
365                         break;
366                 case '1':
367                         header_level = HEADER_LEVEL1;
368                         break;
369                 case '2':
370                         header_level = HEADER_LEVEL2;
371                         break;
372                 default:
373                         fprintf(stderr, "LHa: Unknown option '%c'.\n", p[-1]);
374                         exit(1);
375                 }
376         }
377
378 work:
379         /* archive file name */
380         archive_name = av[2];
381
382         if (!strcmp(archive_name, "-")) {
383                 if (!isatty(1) && cmd == CMD_ADD)
384                         quiet = TRUE;
385         }
386         else {
387                 if (ac == 3 && !isatty(0)) { /* 1999.7.18 */
388                         get_filename_from_stdin = TRUE;
389                 }
390         }
391
392         /* target file name */
393         if (get_filename_from_stdin) {
394                 cmd_filec = 0;
395                 xfilev = (char **)xmalloc(sizeof(char *) * xfilec);
396                 while (fgets(inpbuf, sizeof(inpbuf), stdin)) {
397                     /* delete \n if it exist */
398                         i=0; p=inpbuf;
399                         while (i < sizeof(inpbuf) && p != 0) {
400                             if (*p == '\n') {
401                                     *p = 0;
402                                         break;
403                                 }
404                                 p++; i++;
405                         }
406
407                         if (cmd_filec >= xfilec) {
408                                 xfilec += 256;
409                                 cmd_filev = (char **) realloc(xfilev,
410                                                    sizeof(char *) * xfilec);
411                                 if (cmd_filev == NULL)
412                                         fatal_error("Virtual memory exhausted\n");
413                                 xfilev = cmd_filev;
414                         }
415                         if (strlen(inpbuf) < 1)
416                                 continue;
417                         if ((xfilev[cmd_filec++] = (char *) strdup(inpbuf)) == NULL)
418                                 fatal_error("Virtual memory exhausted\n");
419                 }
420                 xfilev[cmd_filec] = NULL;
421                 cmd_filev = xfilev;
422         } else {
423                 cmd_filec = ac - 3;
424                 cmd_filev = av + 3;
425         }
426         sort_files();
427
428         /* make crc table */
429         make_crctable();
430
431         switch (cmd) {
432         case CMD_EXTRACT:
433                 cmd_extract();
434                 break;
435         case CMD_ADD:
436                 cmd_add();
437                 break;
438         case CMD_LIST:
439                 cmd_list();
440                 break;
441         case CMD_DELETE:
442                 cmd_delete();
443                 break;
444         }
445
446 #ifdef USE_PROF
447         if (!prof)
448                 exit(0);
449 #endif
450
451         return 0;
452 }
453
454
455 /* ------------------------------------------------------------------------ */
456 /* */
457 /* ------------------------------------------------------------------------ */
458
459 /* ------------------------------------------------------------------------ */
460 static void
461 print_version()
462 {
463         fprintf(stderr, "%s\n", LHA_VERSION);
464 }
465
466 /* ------------------------------------------------------------------------ */
467 static void
468 message_1(title, subject, name)
469         char           *title, *subject, *name;
470 {
471         fprintf(stderr, "LHa: %s%s ", title, subject);
472         fflush(stderr);
473
474         if (errno == 0)
475                 fprintf(stderr, "%s\n", name);
476         else
477                 perror(name);
478 }
479
480 /* ------------------------------------------------------------------------ */
481 void
482 message(subject, name)
483         char           *subject, *name;
484 {
485         message_1("", subject, name);
486 }
487
488 /* ------------------------------------------------------------------------ */
489 void
490 warning(subject, name)
491         char           *subject, *name;
492 {
493         message_1("Warning: ", subject, name);
494 }
495
496 /* ------------------------------------------------------------------------ */
497 void
498 error(subject, msg)
499         char           *subject, *msg;
500 {
501         message_1("Error: ", subject, msg);
502 }
503
504 /* ------------------------------------------------------------------------ */
505 void
506 fatal_error(msg)
507         char           *msg;
508 {
509         message_1("Fatal error:", "", msg);
510
511         if (remove_temporary_at_error)
512                 unlink(temporary_name);
513
514         exit(1);
515 }
516
517 /* ------------------------------------------------------------------------ */
518 void
519 write_error()
520 {
521         fatal_error(writting_filename);
522 }
523
524 /* ------------------------------------------------------------------------ */
525 void
526 read_error()
527 {
528         fatal_error(reading_filename);
529 }
530
531 /* ------------------------------------------------------------------------ */
532 void
533 interrupt(signo)
534         int             signo;
535 {
536         errno = 0;
537         message("Interrupted\n", "");
538
539         if (temporary_fp)
540                 fclose(temporary_fp);
541         unlink(temporary_name);
542         if (recover_archive_when_interrupt)
543                 rename(backup_archive_name, archive_name);
544         if (remove_extracting_file_when_interrupt) {
545                 errno = 0;
546                 message("Removing", writting_filename);
547                 unlink(writting_filename);
548         }
549         signal(SIGINT, SIG_DFL);
550 #ifdef SIGHUP
551         signal(SIGHUP, SIG_DFL);
552 #endif
553         kill(getpid(), signo);
554 }
555
556 /* ------------------------------------------------------------------------ */
557 /*                                                                                                                                                      */
558 /* ------------------------------------------------------------------------ */
559 static int
560 sort_by_ascii(a, b)
561         char          **a, **b;
562 {
563         register char  *p, *q;
564         register int    c1, c2;
565
566         p = *a, q = *b;
567         if (generic_format) {
568                 do {
569                         c1 = *(unsigned char *) p++;
570                         c2 = *(unsigned char *) q++;
571                         if (!c1 || !c2)
572                                 break;
573                         if (islower(c1))
574                                 c1 = toupper(c1);
575                         if (islower(c2))
576                                 c2 = toupper(c2);
577                 }
578                 while (c1 == c2);
579                 return c1 - c2;
580         }
581         else {
582                 while (*p == *q && *p != '\0')
583                         p++, q++;
584                 return *(unsigned char *) p - *(unsigned char *) q;
585         }
586 }
587
588 /* ------------------------------------------------------------------------ */
589 static void
590 sort_files()
591 {
592         if (cmd_filec > 1)
593                 qsort(cmd_filev, cmd_filec, sizeof(char *), sort_by_ascii);
594 }
595
596 /* ------------------------------------------------------------------------ */
597 char           *
598 xmalloc(size)
599         int             size;
600 {
601         char           *p = (char *) malloc(size);
602         if (!p)
603                 fatal_error("Not enough memory");
604         return p;
605 }
606
607 /* ------------------------------------------------------------------------ */
608 char           *
609 xrealloc(old, size)
610         char           *old;
611         int             size;
612 {
613         char           *p = (char *) realloc(old, size);
614         if (!p)
615                 fatal_error("Not enough memory");
616         return p;
617 }
618
619 /* ------------------------------------------------------------------------ */
620 /*                                                              STRING POOL                                                                     */
621 /* ------------------------------------------------------------------------ */
622 /*
623   string pool :
624         +-------------+-------------+------+-------------+----------+
625         | N A M E 1 \0| N A M E 2 \0| .... | N A M E n \0|                      |
626         +-------------+-------------+------+-------------+----------+
627           ^ ^            ^ buffer+0 buffer+used buffer+size
628
629   vector :
630         +---------------+---------------+------------- -----------------+
631         | pointer to    | pointer to    | pointer to   ...  pointer to  |
632         |  stringpool   |  N A M E 1    |  N A M E 2   ...   N A M E n  |
633         +---------------+---------------+-------------     -------------+
634         ^ malloc base      returned
635 */
636
637 /* ------------------------------------------------------------------------ */
638 void
639 init_sp(sp)
640         struct string_pool *sp;
641 {
642         sp->size = 1024 - 8;    /* any ( >=0 ) */
643         sp->used = 0;
644         sp->n = 0;
645         sp->buffer = (char *) xmalloc(sp->size * sizeof(char));
646 }
647
648 /* ------------------------------------------------------------------------ */
649 void
650 add_sp(sp, name, len)
651         struct string_pool *sp;
652         char           *name;   /* stored '\0' at tail */
653         int             len;    /* include '\0' */
654 {
655         while (sp->used + len > sp->size) {
656                 sp->size *= 2;
657                 sp->buffer = (char *) xrealloc(sp->buffer, sp->size * sizeof(char));
658         }
659         bcopy(name, sp->buffer + sp->used, len);
660         sp->used += len;
661         sp->n++;
662 }
663
664 /* ------------------------------------------------------------------------ */
665 void
666 finish_sp(sp, v_count, v_vector)
667         register struct string_pool *sp;
668         int            *v_count;
669         char         ***v_vector;
670 {
671         int             i;
672         register char  *p;
673         char          **v;
674
675         v = (char **) xmalloc((sp->n + 1) * sizeof(char *));
676         *v++ = sp->buffer;
677         *v_vector = v;
678         *v_count = sp->n;
679         p = sp->buffer;
680         for (i = sp->n; i; i--) {
681                 *v++ = p;
682                 if (i - 1)
683                         p += strlen(p) + 1;
684         }
685 }
686
687 /* ------------------------------------------------------------------------ */
688 void
689 free_sp(vector)
690         char          **vector;
691 {
692         vector--;
693         free(*vector);          /* free string pool */
694         free(vector);
695 }
696
697
698 /* ------------------------------------------------------------------------ */
699 /*                                                      READ DIRECTORY FILES                                                    */
700 /* ------------------------------------------------------------------------ */
701 static          boolean
702 include_path_p(path, name)
703         char           *path, *name;
704 {
705         char           *n = name;
706         while (*path)
707                 if (*path++ != *n++)
708                         return (path[-1] == '/' && *n == '\0');
709         return (*n == '/' || (n != name && path[-1] == '/' && n[-1] == '/'));
710 }
711
712 /* ------------------------------------------------------------------------ */
713 void
714 cleaning_files(v_filec, v_filev)
715         int            *v_filec;
716         char         ***v_filev;
717 {
718         char           *flags;
719         struct stat     stbuf;
720
721         register char **filev = *v_filev;
722         register int    filec = *v_filec;
723         register char  *p;
724         register int    i, j;
725
726         if (filec == 0)
727                 return;
728
729         flags = xmalloc(filec * sizeof(char));
730
731         /* flags & 0x01 :       1: ignore */
732         /* flags & 0x02 :       1: directory, 0 : regular file */
733         /* flags & 0x04 :       1: need delete */
734
735         
736         for (i = 0; i < filec; i++)
737                 if (GETSTAT(filev[i], &stbuf) < 0) {
738                         flags[i] = 0x04;
739                         fprintf(stderr,
740                          "LHa: Cannot access \"%s\", ignored.\n", filev[i]);
741                 }
742                 else {
743                         if (is_regularfile(&stbuf))
744                                 flags[i] = 0x00;
745                         else if (is_directory(&stbuf))
746                                 flags[i] = 0x02;
747 #ifdef S_IFLNK
748                         else if (is_symlink(&stbuf)) /* t.okamoto */
749                                 flags[i] = 0x00;
750 #endif                  
751                         else {
752                                 flags[i] = 0x04;
753                                 fprintf(stderr,
754                                         "LHa: Cannot archive \"%s\", ignored.\n", filev[i]);
755                         }
756                 }
757         errno = 0;
758
759         for (i = 0; i < filec; i++) {
760                 p = filev[i];
761                 if ((flags[i] & 0x07) == 0x00) {        /* regular file, not
762                                                          * deleted/ignored */
763                         for (j = i + 1; j < filec; j++) {
764                                 if ((flags[j] & 0x07) == 0x00) {        /* regular file, not
765                                                                          * deleted/ignored */
766                                         if (STREQU(p, filev[j]))
767                                                 flags[j] = 0x04;        /* delete */
768                                 }
769                         }
770                 }
771                 else if ((flags[i] & 0x07) == 0x02) {   /* directory, not
772                                                          * deleted/ignored */
773                         for (j = i + 1; j < filec; j++) {
774                                 if ((flags[j] & 0x07) == 0x00) {        /* regular file, not
775                                                                          * deleted/ignored */
776                                         if (include_path_p(p, filev[j]))
777                                                 flags[j] = 0x04;        /* delete */
778                                 }
779                                 else if ((flags[j] & 0x07) == 0x02) {   /* directory, not
780                                                                          * deleted/ignored */
781                                         if (include_path_p(p, filev[j]))
782                                                 flags[j] = 0x04;        /* delete */
783                                 }
784                         }
785                 }
786         }
787
788         for (i = j = 0; i < filec; i++) {
789                 if ((flags[i] & 0x04) == 0) {
790                         if (i != j)
791                                 filev[j] = filev[i];
792                         j++;
793                 }
794         }
795         *v_filec = j;
796
797         free(flags);
798 }
799
800 /* ------------------------------------------------------------------------ */
801 #ifdef NODIRECTORY
802 /* please need your imprementation */
803 boolean
804 find_files(name, v_filec, v_filev)
805         char           *name;
806         int            *v_filec;
807         char         ***v_filev;
808 {
809         return FALSE;           /* DUMMY */
810 }
811
812 /* ------------------------------------------------------------------------ */
813 void
814 free_files(filec, filev)
815         int             filec;
816         char          **filev;
817 {
818         /* do nothing */
819 }
820 /* ------------------------------------------------------------------------ */
821 #else
822 boolean
823 find_files(name, v_filec, v_filev)
824         char           *name;
825         int            *v_filec;
826         char         ***v_filev;
827 {
828         struct string_pool sp;
829         char            newname[FILENAME_LENGTH];
830         int             len, n;
831         DIR            *dirp;
832         DIRENTRY       *dp;
833         struct stat     tmp_stbuf, arc_stbuf, fil_stbuf;
834
835         strcpy(newname, name);
836         len = strlen(name);
837         if (len > 0 && newname[len - 1] != '/')
838                 newname[len++] = '/';
839
840         dirp = opendir(name);
841         if (!dirp)
842                 return FALSE;
843
844         init_sp(&sp);
845
846         GETSTAT(temporary_name, &tmp_stbuf);
847         GETSTAT(archive_name, &arc_stbuf);
848
849         for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
850                 n = NAMLEN(dp);
851                 strncpy(newname + len, dp->d_name, n);
852                 newname[len + n] = '\0';
853                 if (GETSTAT(newname, &fil_stbuf) < 0)
854                         continue;
855 #ifndef HAVE_ST_INO
856                 if ( dp->d_name[0] != '.' ||
857                         (n != 1 &&
858                          (dp->d_name[1] != '.' ||
859                           n != 2))  ) {
860                         add_sp(&sp, newname, len+n+1);
861                 }
862 #else           
863                 if ((dp->d_ino != 0) &&
864                 /* exclude '.' and '..' */
865                     ((dp->d_name[0] != '.') ||
866                      ((n != 1) &&
867                       ((dp->d_name[1] != '.') ||
868                        (n != 2)))) &&
869                     ((tmp_stbuf.st_dev != fil_stbuf.st_dev ||
870                       tmp_stbuf.st_ino != fil_stbuf.st_ino) &&
871                      (arc_stbuf.st_dev != fil_stbuf.st_dev ||
872                       arc_stbuf.st_ino != fil_stbuf.st_ino))) {
873                         add_sp(&sp, newname, len + n + 1);
874                 }
875 #endif
876         }
877         closedir(dirp);
878         finish_sp(&sp, v_filec, v_filev);
879         if (*v_filec > 1)
880                 qsort(*v_filev, *v_filec, sizeof(char *), sort_by_ascii);
881         cleaning_files(v_filec, v_filev);
882
883         return TRUE;
884 }
885
886 /* ------------------------------------------------------------------------ */
887 void
888 free_files(filec, filev)
889         int             filec;
890         char          **filev;
891 {
892         free_sp(filev);
893 }
894 #endif
895 /* ------------------------------------------------------------------------ */
896 /*                                                                                                                                                      */
897 /* ------------------------------------------------------------------------ */
898 /* Build temporary file name and store to TEMPORARY_NAME */
899 void
900 build_temporary_name()
901 {
902 #ifdef TMP_FILENAME_TEMPLATE
903         /* "/tmp/lhXXXXXX" etc. */
904         if (extract_directory == NULL) {
905                 strcpy(temporary_name, TMP_FILENAME_TEMPLATE);
906         }
907         else {
908                 sprintf(temporary_name, "%s/lhXXXXXX", extract_directory);
909         }
910 #ifdef HAVE_MKSTEMP
911         mkstemp(temporary_name);
912 #else
913         mktemp(temporary_name);
914 #endif
915 #else
916         char           *p, *s;
917
918         strcpy(temporary_name, archive_name);
919         for (p = temporary_name, s = (char *) 0; *p; p++)
920                 if (*p == '/')
921                         s = p;
922         strcpy((s ? s + 1 : temporary_name), "lhXXXXXX");
923 #ifdef HAVE_MKSTEMP
924         mkstemp(temporary_name);
925 #else
926         mktemp(temporary_name);
927 #endif
928 #endif
929 }
930
931 /* ------------------------------------------------------------------------ */
932 static void
933 modify_filename_extention(buffer, ext)
934         char           *buffer;
935         char           *ext;
936 {
937         register char  *p, *dot;
938
939         for (p = buffer, dot = (char *) 0; *p; p++) {
940                 if (*p == '.')
941                         dot = p;
942                 else if (*p == '/')
943                         dot = (char *) 0;
944         }
945
946         if (dot)
947                 p = dot;
948
949         strcpy(p, ext);
950 }
951
952 /* ------------------------------------------------------------------------ */
953 /* build backup file name */
954 void
955 build_backup_name(buffer, original)
956         char           *buffer;
957         char           *original;
958 {
959         strcpy(buffer, original);
960         modify_filename_extention(buffer, BACKUPNAME_EXTENTION);        /* ".bak" */
961 }
962
963 /* ------------------------------------------------------------------------ */
964 void
965 build_standard_archive_name(buffer, orginal)
966         char           *buffer;
967         char           *orginal;
968 {
969         strcpy(buffer, orginal);
970         modify_filename_extention(buffer, ARCHIVENAME_EXTENTION);       /* ".lzh" */
971 }
972
973 /* ------------------------------------------------------------------------ */
974 /*                                                                                                                                                      */
975 /* ------------------------------------------------------------------------ */
976 boolean
977 need_file(name)
978         char           *name;
979 {
980         int             i;
981
982         if (cmd_filec == 0)
983                 return TRUE;
984
985         for (i = 0; i < cmd_filec; i++) {
986                 if (patmatch(cmd_filev[i], name, 0))
987                         return TRUE;
988         }
989
990         return FALSE;
991 }
992
993 FILE           *
994 xfopen(name, mode)
995         char           *name, *mode;
996 {
997         FILE           *fp;
998
999         if ((fp = fopen(name, mode)) == NULL)
1000                 fatal_error(name);
1001
1002         return fp;
1003 }
1004
1005 /* ------------------------------------------------------------------------ */
1006 /*                                                                                                                                                      */
1007 /* ------------------------------------------------------------------------ */
1008 static          boolean
1009 open_old_archive_1(name, v_fp)
1010         char           *name;
1011         FILE          **v_fp;
1012 {
1013         FILE           *fp;
1014         struct stat     stbuf;
1015
1016         if (stat(name, &stbuf) >= 0 &&
1017             is_regularfile(&stbuf) &&
1018             (fp = fopen(name, READ_BINARY)) != NULL) {
1019                 *v_fp = fp;
1020                 archive_file_gid = stbuf.st_gid;
1021                 archive_file_mode = stbuf.st_mode;
1022                 return TRUE;
1023         }
1024
1025         *v_fp = NULL;
1026         archive_file_gid = -1;
1027         return FALSE;
1028 }
1029
1030 /* ------------------------------------------------------------------------ */
1031 FILE           *
1032 open_old_archive()
1033 {
1034         FILE           *fp;
1035         char           *p;
1036
1037         if (!strcmp(archive_name, "-")) {
1038                 if (cmd == CMD_EXTRACT || cmd == CMD_LIST)
1039                         return stdin;
1040                 else
1041                         return NULL;
1042         }
1043         if (p = (char *) strrchr(archive_name, '.')) {
1044                 if (strucmp(".LZH", p) == 0
1045                     || strucmp(".LZS", p) == 0
1046                     || strucmp(".COM", p) == 0  /* DOS SFX */
1047                     || strucmp(".EXE", p) == 0
1048                     || strucmp(".X", p) == 0    /* HUMAN SFX */
1049                     || strucmp(".BAK", p) == 0) {       /* for BackUp */
1050                         open_old_archive_1(archive_name, &fp);
1051                         return fp;
1052                 }
1053         }
1054
1055         if (open_old_archive_1(archive_name, &fp))
1056                 return fp;
1057         sprintf(expanded_archive_name, "%s.lzh", archive_name);
1058         if (open_old_archive_1(expanded_archive_name, &fp)) {
1059                 archive_name = expanded_archive_name;
1060                 return fp;
1061         }
1062         /*
1063          * if ( (errno&0xffff)!=E_PNNF ) { archive_name =
1064          * expanded_archive_name; return NULL; }
1065          */
1066         sprintf(expanded_archive_name, "%s.lzs", archive_name);
1067         if (open_old_archive_1(expanded_archive_name, &fp)) {
1068                 archive_name = expanded_archive_name;
1069                 return fp;
1070         }
1071         /*
1072          * if ( (errno&0xffff)!=E_PNNF ) { archive_name =
1073          * expanded_archive_name; return NULL; }
1074          */
1075         /*
1076          * sprintf( expanded_archive_name , "%s.lzh",archive_name);
1077          * archive_name = expanded_archive_name;
1078          */
1079         return NULL;
1080 }
1081
1082 /* ------------------------------------------------------------------------ */
1083 int
1084 inquire(msg, name, selective)
1085         char           *msg, *name, *selective;
1086 {
1087         char            buffer[1024];
1088         char           *p;
1089
1090         for (;;) {
1091                 fprintf(stderr, "%s %s ", name, msg);
1092                 fflush(stderr);
1093
1094                 fgets(buffer, 1024, stdin);
1095
1096                 for (p = selective; *p; p++)
1097                         if (buffer[0] == *p)
1098                                 return p - selective;
1099         }
1100         /* NOTREACHED */
1101 }
1102
1103 /* ------------------------------------------------------------------------ */
1104 void
1105 write_archive_tail(nafp)
1106         FILE           *nafp;
1107 {
1108         putc(0x00, nafp);
1109 }
1110
1111 /* ------------------------------------------------------------------------ */
1112 void
1113 copy_old_one(oafp, nafp, hdr)
1114         FILE           *oafp, *nafp;
1115         LzHeader       *hdr;
1116 {
1117         if (noexec) {
1118                 fseek(oafp, (long) (hdr->header_size + 2) + hdr->packed_size, SEEK_CUR);
1119         }
1120         else {
1121                 reading_filename = archive_name;
1122                 writting_filename = temporary_name;
1123                 if (hdr->header_level != 2) {
1124                         copyfile(oafp, nafp,
1125                                          (long) (hdr->header_size + 2) + hdr->packed_size, 0);
1126                 } else {
1127                         copyfile(oafp, nafp,
1128                                          (long) (hdr->header_size) + hdr->packed_size, 0);
1129                 }
1130         }
1131 }
1132
1133 /* Local Variables: */
1134 /* mode:c */
1135 /* tab-width:4 */
1136 /* compile-command:"gcc -c lharc.c" */
1137 /* End: */