OSDN Git Service

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