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