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