home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / ARCHIVERS / lha205.lzh / lharc.c < prev    next >
Text File  |  1993-02-05  |  30KB  |  1,089 lines

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