home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Professional / OS2PRO194.ISO / os2 / packer / lharc / sources / lharc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-02-03  |  50.8 KB  |  2,187 lines

  1. /*----------------------------------------------------------------------*/
  2. /*        LHarc Archiver Driver for UNIX                */
  3. /*                                    */
  4. /*        Copyright(C) MCMLXXXIX  Yooichi.Tagawa            */
  5. /*        Thanks to H.Yoshizaki. (MS-DOS LHarc)            */
  6. /*                                    */
  7. /*  V0.00  Original                1988.05.23  Y.Tagawa    */
  8. /*  V0.01  Alpha Version (for 4.2BSD)        1989.05.28  Y.Tagawa    */
  9. /*  V0.02  Alpha Version Rel.2            1989.05.29  Y.Tagawa    */
  10. /*  V0.03  Release #3  Beta Version        1989.07.02  Y.Tagawa    */
  11. /*  V0.03a Fix few bug                          1989.07.03  Y.Tagawa    */
  12. /*  V0.04  A lot of bugs fixed, strict mode     1990.01.13  Kai Uwe Rommel */
  13. /*  V1.00  f and t commands, v option added     1990.01.27  Kai Uwe Rommel */
  14. /*  V1.01  bug for zero length files fixed      1990.05.04  Kai Uwe Rommel */
  15. /*  V1.02  80x86 small model memory usage fixed 1990.08.02  Kai Uwe Rommel */
  16. /*  V1.03  integrated patches by Bill Davidsen  1991.01.22  Kai Uwe Rommel */
  17. /*----------------------------------------------------------------------*/
  18.  
  19. #define VERSION "1.03"
  20.  
  21. #include <stdio.h>
  22. #include <ctype.h>
  23. #include <signal.h>
  24. #include <sys/types.h>
  25. #include <sys/stat.h>
  26.  
  27. #ifdef PROF
  28. #include <profile.h>
  29. #endif
  30.  
  31. #ifdef M_XENIX
  32. #include <sys/fcntl.h>
  33. #define ftruncate chsize
  34. #endif
  35.  
  36. #define STRICT
  37. #define FASTCOPY
  38.  
  39. #ifdef MSDOS
  40. #include <fcntl.h>
  41. extern unsigned char _osmode;
  42. extern FILE *popen();
  43. extern pclose();
  44. #define ftruncate chsize
  45. #define mktemp Mktemp
  46. #define SYSTIME_HAS_NO_TM
  47. #define NOBSTRING
  48. #define SYSNAME (_osmode ? "OS/2" : "MS-DOS")
  49. #define OUR_EXTEND (_osmode ? EXTEND_OS2 : EXTEND_MSDOS)
  50. #define FILENAME_LENGTH 256
  51. #define NULLFILE "nul"
  52. #define TMP_FILENAME_TEMPLATE "lhXXXXXX"
  53. #define NOT_COMPATIBLE_MODE
  54. #define RMODE "rb"
  55. #define WMODE "wb"
  56. #else
  57. #include <sys/file.h>
  58. #include <sys/time.h>
  59. #define SYSNAME "UNIX"
  60. #define OUR_EXTEND EXTEND_UNIX
  61. #define FILENAME_LENGTH    1024
  62. #define NULLFILE "/dev/null"
  63. #define RMODE "r"
  64. #define WMODE "w"
  65. #endif
  66.  
  67. #ifdef SYSTIME_HAS_NO_TM
  68. /* most of System V,  define SYSTIME_HAS_NO_TM */
  69. #include <time.h>
  70. #endif
  71.  
  72. /* #include <strings.h> */
  73. #include <string.h>
  74.  
  75.  
  76. /*----------------------------------------------------------------------*/
  77. /*            DIRECTORY ACCESS STUFF                */
  78. /*----------------------------------------------------------------------*/
  79. #ifndef NODIRECTORY
  80. #ifdef SYSV_SYSTEM_DIR
  81.  
  82. #include <dirent.h>
  83. #define DIRENTRY    struct dirent
  84. #define NAMLEN(p)    strlen(p->d_name)
  85.  
  86. #else    /* not SYSV_SYSTEM_DIR */
  87.  
  88. #ifdef NONSYSTEM_DIR_LIBRARY
  89. #include "lhdir.h"
  90. #else    /* not NONSYSTEM_DIR_LIBRARY */
  91. #include <sys/dir.h>
  92. #endif    /* not NONSYSTEM_DIR_LIBRARY */
  93.  
  94. #define DIRENTRY    struct direct
  95. #define NAMLEN(p)    (p->d_namlen)
  96.  
  97. extern DIR *opendir ();
  98. extern struct direct *readdir ();
  99.  
  100. #endif    /* not SYSV_SYSTEM_DIR */
  101. #endif
  102.  
  103. /*----------------------------------------------------------------------*/
  104. /*            FILE ATTRIBUTES                    */
  105. /*----------------------------------------------------------------------*/
  106.  
  107. /* If file mode is not compatible between your Machine/OS and
  108.    LHarc standard UNIX file mode.
  109.    (See UNIX Manual stat(1), <sys/stat.h>,
  110.    and/or below UNIX_* difinitions. ) */
  111. /* #define NOT_COMPATIBLE_MODE */
  112.  
  113.  
  114. /*----------------------------------------------------------------------*/
  115. /*            MEMORY FUNCTIONS                 */
  116. /*----------------------------------------------------------------------*/
  117.  
  118. #ifdef NOBSTRING
  119. #ifdef __ANSI__
  120. #include "mem.h"
  121. #define bcmp(a,b,n) memcmp ((a),(b),(n))
  122. #define bcopy(s,d,n) memmove((d),(s),(n))
  123. #define bzero(d,n) memset((d),0,(n))
  124. #else    /* not __ANSI__ */
  125. #include "memory.h"
  126. #define bcmp(a,b,n) memcmp ((a),(b),(n))
  127. #define bcopy(s,d,n) memcpy ((d),(s),(n))    /* movmem((s),(d),(n)) */
  128. #define bzero(d,n) memset((d),0,(n))
  129. #endif    /* not __ANSI__ */
  130. #endif    /* NOBSTRING */
  131.  
  132.  
  133. /*----------------------------------------------------------------------*/
  134. /*            YOUR CUSTOMIZIES                */
  135. /*----------------------------------------------------------------------*/
  136. /* These difinitions are changable to you like. */
  137. /* #define ARCHIVENAME_EXTENTION    ".LZH"        */
  138. /* #define TMP_FILENAME_TEMPLATE    "/tmp/lhXXXXXX"    */
  139. /* #define BACKUPNAME_EXTENTION        ".BAK"        */
  140. /* #define MULTIBYTE_CHAR                */
  141.  
  142.  
  143.  
  144. #define SJC_FIRST_P(c)            \
  145.   (((unsigned char)(c) >= 0x80) &&    \
  146.    (((unsigned char)(c) < 0xa0) ||    \
  147.     ((unsigned char)(c) >= 0xe0) &&    \
  148.     ((unsigned char)(c) < 0xfd)))
  149. #define SJC_SECOND_P(c)            \
  150.   (((unsigned char)(c) >= 0x40) &&    \
  151.    ((unsigned char)(c) < 0xfd) &&    \
  152.    ((ungigned char)(c) != 0x7f))
  153.  
  154. #ifdef MULTIBYTE_CHAR
  155. #define MULTIBYTE_FIRST_P    SJC_FIRST_P
  156. #define MULTIBYTE_SECOND_P    SJC_SECOND_P
  157. #endif
  158.  
  159. /*----------------------------------------------------------------------*/
  160. /*            OTHER DIFINITIONS                */
  161. /*----------------------------------------------------------------------*/
  162.  
  163. #ifndef SEEK_SET
  164. #define SEEK_SET    0
  165. #define SEEK_CUR    1
  166. #define SEEK_END    2
  167. #endif
  168.  
  169.  
  170. /* non-integral functions */
  171. extern struct tm *localtime ();
  172. extern char *getenv ();
  173. extern char *malloc ();
  174. extern char *realloc ();
  175.  
  176. extern int rson[];
  177.  
  178. /* external variables */
  179. extern int errno;
  180.  
  181.  
  182. #define    FALSE    0
  183. #define TRUE    1
  184. typedef int boolean;
  185.  
  186.  
  187. /*----------------------------------------------------------------------*/
  188. /*        LHarc FILE DIFINITIONS                    */
  189. /*----------------------------------------------------------------------*/
  190. #define METHOD_TYPE_STRAGE    5
  191. #define LZHUFF0_METHOD        "-lh0-"
  192. #define LZHUFF1_METHOD        "-lh1-"
  193. #define LARC4_METHOD        "-lz4-"
  194. #define LARC5_METHOD        "-lz5-"
  195.  
  196. #define I_HEADER_SIZE            0
  197. #define I_HEADER_CHECKSUM        1
  198. #define I_METHOD            2
  199. #define I_PACKED_SIZE            7
  200. #define I_ORIGINAL_SIZE            11
  201. #define I_LAST_MODIFIED_STAMP        15
  202. #define I_ATTRIBUTE            19
  203. #define I_NAME_LENGTH            21
  204. #define I_NAME                22
  205.  
  206. #define I_CRC                22 /* + name_length */
  207. #define I_EXTEND_TYPE            24 /* + name_length */
  208. #define I_MINOR_VERSION            25 /* + name_length */
  209. #define I_UNIX_LAST_MODIFIED_STAMP    26 /* + name_length */
  210. #define I_UNIX_MODE            30 /* + name_length */
  211. #define I_UNIX_UID            32 /* + name_length */
  212. #define I_UNIX_GID            34 /* + name_length */
  213. #define I_UNIX_EXTEND_BOTTOM        36 /* + name_length */
  214.  
  215.  
  216.  
  217. #define EXTEND_GENERIC  0
  218. #define EXTEND_UNIX    'U'
  219. #define EXTEND_MSDOS    'M'
  220. #define EXTEND_MACOS    'm'
  221. #define EXTEND_OS9    '9'
  222. #define EXTEND_OS2    '2'
  223. #define EXTEND_OS68K    'K'
  224. #define EXTEND_OS386    '3'
  225. #define EXTEND_HUMAN    'H'
  226. #define EXTEND_CPM    'C'
  227. #define EXTEND_FLEX    'F'
  228.  
  229. #define GENERIC_ATTRIBUTE        0x20
  230. #define GENERIC_DIRECTORY_ATTRIBUTE    0x10
  231.  
  232. #define CURRENT_UNIX_MINOR_VERSION    0x00
  233.  
  234.  
  235.  
  236. typedef struct LzHeader {
  237.   unsigned char        header_size;
  238.   char            method[METHOD_TYPE_STRAGE];
  239.   long            packed_size;
  240.   long            original_size;
  241.   long            last_modified_stamp;
  242.   unsigned short    attribute;
  243.   char            name[256];
  244.   unsigned short    crc;
  245.   boolean        has_crc;
  246.   unsigned char        extend_type;
  247.   unsigned char        minor_version;
  248.   /*  extend_type == EXTEND_UNIX  and convert from other type. */
  249.   time_t        unix_last_modified_stamp;
  250.   unsigned short    unix_mode;
  251.   unsigned short    unix_uid;
  252.   unsigned short    unix_gid;
  253. } LzHeader;
  254.  
  255. #define UNIX_FILE_TYPEMASK    0170000
  256. #define UNIX_FILE_REGULAR    0100000
  257. #define UNIX_FILE_DIRECTORY    0040000
  258. #define UNIX_SETUID        0004000
  259. #define UNIX_SETGID        0002000
  260. #define UNIX_STYCKYBIT        0001000
  261. #define UNIX_OWNER_READ_PERM    0000400
  262. #define UNIX_OWNER_WRITE_PERM    0000200
  263. #define UNIX_OWNER_EXEC_PERM    0000100
  264. #define UNIX_GROUP_READ_PERM    0000040
  265. #define UNIX_GROUP_WRITE_PERM    0000020
  266. #define UNIX_GROUP_EXEC_PERM    0000010
  267. #define UNIX_OTHER_READ_PERM    0000004
  268. #define UNIX_OTHER_WRITE_PERM    0000002
  269. #define UNIX_OTHER_EXEC_PERM    0000001
  270. #define UNIX_RW_RW_RW        0000666
  271.  
  272. #define LZHEADER_STRAGE        256
  273.  
  274. /*----------------------------------------------------------------------*/
  275. /*        PROGRAM                         */
  276. /*----------------------------------------------------------------------*/
  277.  
  278.  
  279. #define CMD_UNKNOWN    0
  280. #define CMD_EXTRACT    1
  281. #define CMD_APPEND    2
  282. #define CMD_VIEW    3
  283.  
  284. int      cmd = CMD_UNKNOWN;
  285. char     **cmd_filev;
  286. int      cmd_filec;
  287. char     *archive_name;
  288.  
  289. char     expanded_archive_name[FILENAME_LENGTH];
  290. char     temporary_name[FILENAME_LENGTH];
  291. char     pager[FILENAME_LENGTH];
  292.  
  293.  
  294. /* options */
  295. boolean    quiet = FALSE;
  296. boolean    text_mode = FALSE;
  297. /*boolean  verbose = FALSE; */
  298. boolean  noexec = FALSE; /* debugging option */
  299. boolean  force = FALSE;
  300. boolean  prof = FALSE;
  301.  
  302.  
  303. /* view flags */
  304. boolean  long_format_listing = FALSE;
  305.  
  306. /* extract flags */
  307. boolean  output_to_test = FALSE;
  308. boolean  output_to_stdout = FALSE;
  309.  
  310. /* append flags */
  311. boolean  new_archive = FALSE;
  312. boolean  update_if_newer = FALSE;
  313. boolean  update_freshen = FALSE;
  314. boolean  delete_after_append = FALSE;
  315. boolean  delete_from_archive = FALSE;
  316.  
  317. boolean  remove_temporary_at_error = FALSE;
  318.  
  319.  
  320. /*----------------------------------------------------------------------*/
  321. /* NOTES :    Text File Format                    */
  322. /*    GENERATOR        NewLine                    */
  323. /*    [generic]        0D 0A                    */
  324. /*    [MS-DOS]        0D 0A                    */
  325. /*    [MacOS]            0D                    */
  326. /*    [UNIX]            0A                    */
  327. /*----------------------------------------------------------------------*/
  328.  
  329. char *myname;
  330.  
  331.  
  332. void userbreak()
  333. {
  334.     error("Interrupt.");
  335. }
  336.  
  337.  
  338. main (argc, argv)
  339.      int argc;
  340.      char *argv[];
  341. {
  342.   char *p;
  343.  
  344.   myname = argv[0];
  345.   signal(SIGINT, userbreak);
  346.  
  347. #ifdef PROF
  348.   PROFINIT(PT_USER|PT_USEKP, NULL);
  349.   PROFCLEAR(PT_USER);
  350.   PROFON(PT_USER);
  351. #endif
  352.  
  353.   if (argc < 3)
  354.     print_tiny_usage_and_exit ();
  355.  
  356.   /* commands */
  357. #ifdef MSDOS
  358.   switch (tolower(argv[1][0]))
  359. #else
  360.   switch (argv[1][0])
  361. #endif
  362.     {
  363.     case 'x':
  364.     case 'e':
  365.       cmd = CMD_EXTRACT;
  366.       break;
  367.  
  368.     case 't':
  369.       output_to_test = TRUE;
  370.       cmd = CMD_EXTRACT;
  371.       break;
  372.  
  373.     case 'p':
  374.       output_to_stdout = TRUE;
  375.       cmd = CMD_EXTRACT;
  376.       break;
  377.  
  378.     case 'c':
  379.       new_archive = TRUE;
  380.       cmd = CMD_APPEND;
  381.       break;
  382.  
  383.     case 'a':
  384.       cmd = CMD_APPEND;
  385.       break;
  386.  
  387.     case 'd':
  388.       delete_from_archive = TRUE;
  389.       cmd = CMD_APPEND;
  390.       break;
  391.  
  392.     case 'u':
  393.       update_if_newer = TRUE;
  394.       cmd = CMD_APPEND;
  395.       break;
  396.  
  397.     case 'f':
  398.       update_if_newer = update_freshen = TRUE;
  399.       cmd = CMD_APPEND;
  400.       break;
  401.  
  402.     case 'm':
  403.       delete_after_append = TRUE;
  404.       cmd = CMD_APPEND;
  405.       break;
  406.  
  407.     case 'v':
  408.       long_format_listing = TRUE;
  409.       cmd = CMD_VIEW;
  410.       break;
  411.  
  412.     case 'l':
  413.       cmd = CMD_VIEW;
  414.       break;
  415.  
  416.     case 'h':
  417.     default:
  418.       print_tiny_usage_and_exit ();
  419.     }
  420.  
  421.   /* options */
  422.   p = &argv[1][1];
  423.   for (p = &argv[1][1]; *p; p++)
  424.     {
  425. #ifdef MSDOS
  426.       switch (tolower(*p))
  427. #else
  428.       switch (*p)
  429. #endif
  430.     {
  431.     case 'q':    quiet = TRUE; break;
  432.     case 'f':    force = TRUE; break;
  433. /*      case 'p':       prof = TRUE; break; */
  434. /*      case 'v':       verbose = TRUE; break; */
  435.         case 'p':       if (p[1]) {
  436.                 strcpy(pager, p + 1);
  437.                 p[1] = 0;
  438.             }
  439.             else strcpy(pager, "less");
  440.             break;
  441.     case 't':    text_mode = TRUE; break;
  442.     case 'n':    noexec = TRUE; break;
  443.  
  444.     default:
  445.           fprintf (stderr, "unknown option '%c'.\n", *p);
  446.       exit (1);
  447.         }
  448.     }
  449.  
  450.   /* archive file name */
  451.   archive_name = argv[2];
  452.  
  453.   /* target file name */
  454.   cmd_filec = argc - 3;
  455.   cmd_filev = argv + 3;
  456.   sort_files ();
  457.  
  458.   switch (cmd)
  459.     {
  460.     case CMD_EXTRACT:    cmd_extract ();    break;
  461.     case CMD_APPEND:    cmd_append ();    break;
  462.     case CMD_VIEW:    cmd_view ();    break;
  463.     }
  464.  
  465. #ifdef PROF
  466.   PROFOFF(PT_USER);
  467.   PROFDUMP(PT_USER, "profile.out");
  468.   PROFFREE(PT_USER);
  469. #endif
  470.  
  471.   exit (0);
  472. }
  473.  
  474. print_tiny_usage_and_exit ()
  475. {
  476.   printf(
  477. "\nC-LHarc for %s Version %s   (C) 1989-1990 Y.Tagawa, Kai Uwe Rommel\n\n\
  478. Usage: %s {axevlufdmctp}[qnft][p[<pager>]] archive_file [files or directories...]\n",
  479.          SYSNAME, VERSION, myname);
  480.   printf(
  481. "\nCommands:                    Options:\n\
  482.   a   Append                   q   quiet\n\
  483.   x,e EXtract                  n   no execute\n\
  484.   v,l View/List                f   force (over write at extract)\n\
  485.   u   Update                   t   files are TEXT files\n\
  486.   f   Freshen                  p[<pager>]  use file pager for p command\n\
  487.   d   Delete                               (use less if unspecified)\n\
  488.   m   Move\n\
  489.   c   re-Construct new archive\n\
  490.   t   Test archive\n\
  491.   p   Print to STDOUT\n");
  492.   exit (1);
  493. }
  494.  
  495. message (title, msg)
  496.      char *title, *msg;
  497. {
  498.   fprintf (stderr, "%s ", myname);
  499.   if (errno == 0)
  500.     fprintf (stderr, "%s %s\n", title, msg);
  501.   else
  502.     perror (msg);
  503. }
  504.  
  505. warning (msg)
  506.      char *msg;
  507. {
  508.   message ("Warning:", msg);
  509. }
  510.  
  511. error (msg)
  512.      char *msg;
  513. {
  514.   message ("Error:", msg);
  515.  
  516.   if (remove_temporary_at_error)
  517.   {
  518. #ifdef MSDOS
  519.     fcloseall();
  520. #endif
  521.     unlink (temporary_name);
  522.   }
  523.  
  524.   exit (1);
  525. }
  526.  
  527. char *writting_filename;
  528. char *reading_filename;
  529.  
  530. write_error ()
  531. {
  532.   error (writting_filename);
  533. }
  534.  
  535. read_error ()
  536. {
  537.   error (reading_filename);
  538. }
  539.  
  540.  
  541.  
  542. /*----------------------------------------------------------------------*/
  543. /*                                    */
  544. /*----------------------------------------------------------------------*/
  545.  
  546. boolean expand_archive_name (dst, src)
  547.      char *dst, *src;
  548. {
  549.   register char *p, *dot;
  550.  
  551.   strcpy (dst, src);
  552.  
  553.   for (p = dst, dot = (char*)0; *p; p++)
  554.     if (*p == '.')
  555.       dot = p;
  556.     else if (*p == '/' || *p == '\\')
  557.       dot = (char*)0;
  558.  
  559.   if (dot)
  560.     p = dot;
  561.  
  562. #ifdef ARCHIVENAME_EXTENTION
  563.   strcpy (p, ARCHIVENAME_EXTENTION);
  564. #else
  565.   strcpy (p, ".lzh");
  566. #endif
  567.   return (strcmp (dst, src) != 0);
  568. }
  569.  
  570. #ifdef MSDOS
  571. #define STRING_COMPARE(a,b) stricmp((a),(b))
  572. #else
  573. #define STRING_COMPARE(a,b) strcmp((a),(b))
  574. #endif
  575.  
  576. int sort_by_ascii (a, b)
  577.      char **a, **b;
  578. {
  579.   return STRING_COMPARE (*a, *b);
  580. }
  581.  
  582. sort_files ()
  583. {
  584.   qsort (cmd_filev, cmd_filec, sizeof (char*), sort_by_ascii);
  585. }
  586.  
  587. #ifndef MSDOS
  588. char *strdup (string)
  589.      char *string;
  590. {
  591.   int    len = strlen (string) + 1;
  592.   char    *p = malloc (len);
  593.   bcopy (string, p, len);
  594.   return p;
  595. }
  596. #endif
  597.  
  598. #ifdef NODIRECTORY
  599. /* please need your imprementation */
  600. boolean find_files (name, v_filec, v_filev)
  601.      char    *name;
  602.      int    *v_filec;
  603.      char    ***v_filev;
  604. {
  605.   return FALSE;            /* DUMMY */
  606. }
  607. #else
  608. boolean find_files (name, v_filec, v_filev)
  609.      char    *name;
  610.      int    *v_filec;
  611.      char    ***v_filev;
  612. {
  613.   char        newname[FILENAME_LENGTH];
  614.   int         len, n;
  615.   DIR        *dirp;
  616.   DIRENTRY    *dp;
  617.   int           alloc_size = 64; /* any (^_^) */
  618.   char        **filev;
  619.   int        filec = 0;
  620.  
  621.   if ( strcmp(name, ".") == 0 )
  622.     newname[0] = 0;
  623.   else
  624.     strcpy (newname, name);
  625.  
  626.   len = strlen (newname);
  627.   dirp = opendir (name);
  628.  
  629.   if (dirp)
  630.     {
  631.       filev = (char**)malloc (alloc_size * sizeof(char *));
  632.       if (!filev)
  633.     error ("not enough memory");
  634.  
  635.       for (dp = readdir (dirp); dp != NULL; dp = readdir (dirp))
  636.     {
  637.       n = NAMLEN (dp);
  638.           if (
  639. #ifndef MSDOS
  640.               (dp->d_ino != 0) &&
  641. #endif
  642.               ((dp->d_name[0] != '.') ||
  643.                  ((n != 1) &&
  644.                  ((dp->d_name[1] != '.') ||
  645.          (n != 2)))) &&            /* exclude '.' and '..' */
  646.           (strcmp (dp->d_name, temporary_name) != 0) &&
  647.           (strcmp (dp->d_name, archive_name) != 0))
  648.         {
  649.               if ((len != 0) && (newname[len-1] != '/') && (newname[len-1] != '\\'))
  650.                 {
  651. #ifdef MSDOS
  652.                   newname[len] = '\\';
  653. #else
  654.                   newname[len] = '/';
  655. #endif
  656.           strncpy (newname+len+1, dp->d_name, n);
  657.           newname[len+n+1] = '\0';
  658.         }
  659.           else
  660.         {
  661.           strncpy (newname+len, dp->d_name, n);
  662.           newname[len+n] = '\0';
  663.         }
  664.  
  665.           filev[filec++] = strdup (newname);
  666.           if (filec == alloc_size)
  667.         {
  668.                   alloc_size += 64;
  669.                   filev = (char**)realloc (filev, alloc_size * sizeof(char *));
  670.         }
  671.         }
  672.     }
  673.       closedir (dirp);
  674.     }
  675.  
  676.   *v_filev = filev;
  677.   *v_filec = filec;
  678.   if (dirp)
  679.     {
  680.       qsort (filev, filec, sizeof (char*), sort_by_ascii);
  681.       return TRUE;
  682.     }
  683.   else
  684.     return FALSE;
  685. }
  686. #endif
  687.  
  688. free_files (filec, filev)
  689.      int    filec;
  690.      char    **filev;
  691. {
  692.   int        i;
  693.  
  694.   for (i = 0; i < filec; i ++)
  695.     free (filev[i]);
  696.  
  697.   free (filev);
  698. }
  699.  
  700.  
  701. /*----------------------------------------------------------------------*/
  702. /*                                    */
  703. /*----------------------------------------------------------------------*/
  704.  
  705. int calc_sum (p, len)
  706.      register char *p;
  707.      register int len;
  708. {
  709.   register int sum;
  710.  
  711.   for (sum = 0; len; len--)
  712.     sum += *p++;
  713.  
  714.   return sum & 0xff;
  715. }
  716.  
  717. unsigned char *get_ptr;
  718. #define setup_get(PTR) get_ptr = (unsigned char*)(PTR)
  719. #define get_byte() (*get_ptr++)
  720. #define put_ptr    get_ptr
  721. #define setup_put(PTR) put_ptr = (unsigned char*)(PTR)
  722. #define put_byte(c) *put_ptr++ = (unsigned char)(c)
  723.  
  724. unsigned short get_word ()
  725. {
  726.   int b0, b1;
  727.  
  728.   b0 = get_byte ();
  729.   b1 = get_byte ();
  730.   return (b1 << 8) + b0;
  731. }
  732.  
  733. put_word (v)
  734.      unsigned int    v;
  735. {
  736.   put_byte (v);
  737.   put_byte (v >> 8);
  738. }
  739.  
  740. long get_longword ()
  741. {
  742.   long b0, b1, b2, b3;
  743.  
  744.   b0 = get_byte ();
  745.   b1 = get_byte ();
  746.   b2 = get_byte ();
  747.   b3 = get_byte ();
  748.   return (b3 << 24) + (b2 << 16) + (b1 << 8) + b0;
  749. }
  750.  
  751. put_longword (v)
  752.      long v;
  753. {
  754.   put_byte (v);
  755.   put_byte (v >> 8);
  756.   put_byte (v >> 16);
  757.   put_byte (v >> 24);
  758. }
  759.  
  760.  
  761. msdos_to_unix_filename (name, len)
  762.      register char *name;
  763.      register int len;
  764. {
  765.   register int i;
  766.  
  767. #ifdef MULTIBYTE_CHAR
  768.   for (i = 0; i < len; i ++)
  769.     {
  770.       if (MULTIBYTE_FIRST_P (name[i]) &&
  771.       MULTIBYTE_SECOND_P (name[i+1]))
  772.         i ++;
  773. #ifndef MSDOS
  774.       else if (name[i] == '\\')
  775.         name[i] = '/';
  776. #endif
  777.       else if (isupper (name[i]))
  778.     name[i] = tolower (name[i]);
  779.     }
  780. #else
  781.   for (i = 0; i < len; i ++)
  782.     {
  783. #ifndef MSDOS
  784.       if (name[i] == '\\')
  785.     name[i] = '/';
  786.       else
  787. #endif
  788.         if (isupper (name[i]))
  789.           name[i] = tolower (name[i]);
  790.     }
  791. #endif
  792. }
  793.  
  794. generic_to_unix_filename (name, len)
  795.      register char *name;
  796.      register int len;
  797. {
  798.   register int i;
  799. #ifdef MSDOS
  800.   boolean    lower_case_used = FALSE;
  801. #else
  802.   boolean    lower_case_used = TRUE;
  803. #endif
  804.  
  805. #ifdef MULTIBYTE_CHAR
  806.   for (i = 0; i < len; i ++)
  807.     {
  808.       if (MULTIBYTE_FIRST_P (name[i]) &&
  809.       MULTIBYTE_SECOND_P (name[i+1]))
  810.     i ++;
  811.       else if (islower (name[i]))
  812.     {
  813.       lower_case_used = TRUE;
  814.       break;
  815.     }
  816.     }
  817.   for (i = 0; i < len; i ++)
  818.     {
  819.       if (MULTIBYTE_FIRST_P (name[i]) &&
  820.       MULTIBYTE_SECOND_P (name[i+1]))
  821.         i ++;
  822. #ifndef MSDOS
  823.       else if (name[i] == '\\')
  824.         name[i] = '/';
  825. #endif
  826.       else if (!lower_case_used && isupper (name[i]))
  827.     name[i] = tolower (name[i]);
  828.     }
  829. #else
  830.   for (i = 0; i < len; i ++)
  831.     if (islower (name[i]))
  832.       {
  833.     lower_case_used = TRUE;
  834.     break;
  835.       }
  836.   for (i = 0; i < len; i ++)
  837.     {
  838. #ifndef MSDOS
  839.       if (name[i] == '\\')
  840.     name[i] = '/';
  841.       else
  842. #endif
  843.         if (!lower_case_used && isupper (name[i]))
  844.           name[i] = tolower (name[i]);
  845.     }
  846. #endif
  847. }
  848.  
  849. macos_to_unix_filename (name, len)
  850.      register char *name;
  851.      register int len;
  852. {
  853.   register int i;
  854.  
  855.   for (i = 0; i < len; i ++)
  856.     {
  857.       if (name[i] == ':')
  858.     name[i] = '/';
  859.       else if (name[i] == '/')
  860.     name[i] = ':';
  861.     }
  862. }
  863.  
  864. /*----------------------------------------------------------------------*/
  865. /*                                    */
  866. /*    Generic stamp format:                        */
  867. /*                                    */
  868. /*     31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16        */
  869. /*    |<-------- year ------->|<- month ->|<-- day -->|        */
  870. /*                                    */
  871. /*     15 14 13 12 11 10  9  8  7  6  5  4  3  2  1  0        */
  872. /*    |<--- hour --->|<---- minute --->|<- second*2 ->|        */
  873. /*                                    */
  874. /*----------------------------------------------------------------------*/
  875.  
  876.  
  877. long gettz ()
  878. {
  879. #ifdef MSDOS
  880.    return timezone;
  881. #else
  882. #ifdef    BSD
  883.    struct timeval    tp;
  884.    struct timezone    tzp;
  885.    gettimeofday (&tp, &tzp);    /* specific to 4.3BSD */
  886. /* return (tzp.tz_minuteswest * 60 + (tzp.tz_dsttime != 0 ? 60L * 60L : 0));*/
  887.    return (tzp.tz_minuteswest * 60);
  888. #else    /* SYSV */
  889.    struct tm *timep;
  890.    long dummytime;
  891.  
  892.    time(&dummytime);
  893.    timep = localtime(&dummytime);
  894.    return timep -> tm_tzadj;
  895. #endif
  896. #endif
  897. }
  898.  
  899. #ifdef NOT_USED
  900. struct tm *msdos_to_unix_stamp_tm (a)
  901.      long a;
  902. {
  903.   static struct tm t;
  904.   t.tm_sec    = ( a          & 0x1f) * 2;
  905.   t.tm_min    =  (a >>    5) & 0x3f;
  906.   t.tm_hour    =  (a >>   11) & 0x1f;
  907.   t.tm_mday    =  (a >>   16) & 0x1f;
  908.   t.tm_mon    =  (a >> 16+5) & 0x0f - 1;
  909.   t.tm_year    = ((a >> 16+9) & 0x7f) + 80;
  910.   return &t;
  911. }
  912. #endif
  913.  
  914. time_t generic_to_unix_stamp (t)
  915.      long t;
  916. {
  917.   struct tm tm;
  918.   long longtime;
  919.   static unsigned int dsboy[12] =
  920.     { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
  921.   unsigned long days;
  922.  
  923.   tm.tm_year =  ((int)(t >> 25) & 0x7f) + 80;
  924.   tm.tm_mon  =  ((int)(t >> 21) & 0x0f) - 1;     /* 0..11 means Jan..Dec */
  925.   tm.tm_mday =  (int)(t >> 16) & 0x1f;         /* 1..31 means 1st,...31st */
  926.  
  927.   tm.tm_hour =  ((int)t >> 11) & 0x1f;
  928.   tm.tm_min  =  ((int)t >> 5)  & 0x3f;
  929.   tm.tm_sec  =  ((int)t        & 0x1f) * 2;
  930.  
  931. #ifdef MSDOS
  932.   longtime = mktime(&tm);
  933. #else
  934.                                       /* Calculate days since 1970.01.01 */
  935.   days = (365 * (tm.tm_year - 70) +   /* days due to whole years */
  936.           (tm.tm_year - 70 + 1) / 4 + /* days due to leap years */
  937.           dsboy[tm.tm_mon] +          /* days since beginning of this year */
  938.           tm.tm_mday-1);              /* days since beginning of month */
  939.  
  940.   if ((tm.tm_year % 4 == 0) &&
  941.       (tm.tm_year % 400 != 0) &&
  942.       (tm.tm_mon >= 2))         /* if this is a leap year and month */
  943.     days++;            /* is March or later, add a day */
  944.  
  945.   /* Knowing the days, we can find seconds */
  946.   longtime = (((days * 24) + tm.tm_hour) * 60 + tm.tm_min) * 60 + tm.tm_sec;
  947.   longtime += gettz ();      /* adjust for timezone */
  948. #endif
  949.  
  950.   /* special case:  if MSDOS format date and time were zero, then we set
  951.      time to be zero here too. */
  952.   if (t == 0)
  953.     longtime = 0;
  954.  
  955.   /* LONGTIME is now the time in seconds, since 1970/01/01 00:00:00.  */
  956.   return (time_t)longtime;
  957. }
  958.  
  959. long unix_to_generic_stamp (t)
  960.      time_t t;
  961. {
  962.   struct tm *tm = localtime (&t);
  963.   unsigned long stamp;
  964.  
  965.   stamp =  ( ((long)(tm->tm_year - 80)) << 25 );
  966.   stamp += ( ((long)(tm->tm_mon + 1))   << 21 );
  967.   stamp += ( ((long)(tm->tm_mday))      << 16 );
  968.   stamp += ( ((long)(tm->tm_hour))      << 11 );
  969.   stamp += ( ((long)(tm->tm_min))       << 5 );
  970.   stamp += ( ((long)(tm->tm_sec))       >> 1 );
  971.  
  972.   return stamp;
  973. }
  974.  
  975. /*----------------------------------------------------------------------*/
  976. /*                                    */
  977. /*----------------------------------------------------------------------*/
  978.  
  979. boolean get_header (fp, hdr)
  980.      FILE *fp;
  981.      register LzHeader *hdr;
  982. {
  983.   int        header_size;
  984.   int        name_length;
  985.   char        data[LZHEADER_STRAGE];
  986.   int        checksum;
  987.   int        i;
  988.  
  989.   bzero ((char *)hdr, sizeof (LzHeader));
  990.  
  991.   if (((header_size = getc (fp)) == EOF) || (header_size == 0))
  992.     {
  993.       return FALSE;        /* finish */
  994.     }
  995.  
  996.   if (fread (data + I_HEADER_CHECKSUM,
  997.           sizeof (char), header_size + 1, fp) < header_size + 1)
  998.     {
  999.       error ("Invalid header (LHarc file ?)\a");
  1000.       return FALSE;        /* finish */
  1001.     }
  1002.  
  1003.   setup_get (data + I_HEADER_CHECKSUM);
  1004.   checksum = calc_sum (data + I_METHOD, header_size);
  1005.   if (get_byte () != checksum)
  1006.     warning ("Checksum error (LHarc file?)\a");
  1007.  
  1008.   hdr->header_size = header_size;
  1009.   bcopy (data + I_METHOD, hdr->method, METHOD_TYPE_STRAGE);
  1010. #ifdef OLD
  1011.   if ((bcmp (hdr->method, LZHUFF1_METHOD, METHOD_TYPE_STRAGE) != 0) &&
  1012.       (bcmp (hdr->method, LZHUFF0_METHOD, METHOD_TYPE_STRAGE) != 0) &&
  1013.       (bcmp (hdr->method, LARC5_METHOD, METHOD_TYPE_STRAGE) != 0) &&
  1014.       (bcmp (hdr->method, LARC4_METHOD, METHOD_TYPE_STRAGE) != 0))
  1015.     {
  1016.       warning ("Unknown method (LHarc file ?)");
  1017.       return FALSE;        /* invalid method */
  1018.     }
  1019. #endif
  1020.   setup_get (data + I_PACKED_SIZE);
  1021.   hdr->packed_size    = get_longword ();
  1022.   hdr->original_size    = get_longword ();
  1023.   hdr->last_modified_stamp = get_longword ();
  1024.   hdr->attribute    = get_word ();
  1025.   name_length        = get_byte ();
  1026.   for (i = 0; i < name_length; i ++)
  1027.     hdr->name[i] =(char)get_byte ();
  1028.   hdr->name[name_length] = '\0';
  1029.  
  1030.   /* defaults for other type */
  1031.   hdr->unix_mode    = UNIX_FILE_REGULAR | UNIX_RW_RW_RW;
  1032.   hdr->unix_gid     = 0;
  1033.   hdr->unix_uid        = 0;
  1034.  
  1035.   if (header_size - name_length >= 24)
  1036.     {                /* EXTEND FORMAT */
  1037.       hdr->crc                = get_word ();
  1038.       hdr->extend_type            = get_byte ();
  1039.       hdr->minor_version        = get_byte ();
  1040.       hdr->has_crc = TRUE;
  1041.     }
  1042.   else if (header_size - name_length == 22)
  1043.     {                /* Generic with CRC */
  1044.       hdr->crc                = get_word ();
  1045.       hdr->extend_type            = EXTEND_GENERIC;
  1046.       hdr->has_crc = TRUE;
  1047.     }
  1048.   else if (header_size - name_length == 20)
  1049.     {                /* Generic no CRC */
  1050.       hdr->extend_type            = EXTEND_GENERIC;
  1051.       hdr->has_crc = FALSE;
  1052.     }
  1053.   else
  1054.     {
  1055.       warning ("Unknown header (LHarc file ?)");
  1056.       return FALSE;
  1057.     }
  1058.  
  1059.   switch (hdr->extend_type)
  1060.     {
  1061.     case EXTEND_MSDOS:
  1062.       msdos_to_unix_filename (hdr->name, name_length);
  1063.       hdr->unix_last_modified_stamp    =
  1064.     generic_to_unix_stamp (hdr->last_modified_stamp);
  1065.       break;
  1066.  
  1067.     case EXTEND_UNIX:
  1068.       hdr->unix_last_modified_stamp    = (time_t)get_longword ();
  1069.       hdr->unix_mode            = get_word ();
  1070.       hdr->unix_uid            = get_word ();
  1071.       hdr->unix_gid            = get_word ();
  1072.       break;
  1073.  
  1074.     case EXTEND_MACOS:
  1075.       macos_to_unix_filename (hdr->name, name_length);
  1076.       hdr->unix_last_modified_stamp    =
  1077.     generic_to_unix_stamp (hdr->last_modified_stamp);
  1078.       break;
  1079.  
  1080.     default:
  1081.       generic_to_unix_filename (hdr->name, name_length);
  1082.       hdr->unix_last_modified_stamp    =
  1083.     generic_to_unix_stamp (hdr->last_modified_stamp);
  1084.     }
  1085.  
  1086.   return TRUE;
  1087. }
  1088.  
  1089. init_header (name, v_stat, hdr)
  1090.      char *name;
  1091.      struct stat *v_stat;
  1092.      LzHeader *hdr;
  1093. {
  1094.   bcopy (LZHUFF1_METHOD, hdr->method, METHOD_TYPE_STRAGE);
  1095.   hdr->packed_size        = 0;
  1096.   hdr->original_size        = v_stat->st_size;
  1097.   hdr->last_modified_stamp      = unix_to_generic_stamp (v_stat->st_mtime);
  1098. #ifdef MSDOS
  1099.   hdr->attribute                = getfmode(name);
  1100. #else
  1101.   hdr->attribute                = GENERIC_ATTRIBUTE;
  1102. #endif
  1103.   strcpy (hdr->name, name);
  1104.   hdr->crc            = 0x0000;
  1105.   hdr->extend_type              = OUR_EXTEND;
  1106.   hdr->unix_last_modified_stamp    = v_stat->st_mtime;
  1107.                 /* 00:00:00 since JAN.1.1970 */
  1108. #ifdef NOT_COMPATIBLE_MODE
  1109.   hdr->unix_mode        = v_stat->st_mode;
  1110. #else
  1111.   hdr->unix_mode        = v_stat->st_mode;
  1112. #endif
  1113.  
  1114.   hdr->unix_uid            = v_stat->st_uid;
  1115.   hdr->unix_gid            = v_stat->st_gid;
  1116.  
  1117.   if ((v_stat->st_mode & S_IFMT) == S_IFDIR)
  1118.     {
  1119.       bcopy (LZHUFF0_METHOD, hdr->method, METHOD_TYPE_STRAGE);
  1120.       hdr->attribute = GENERIC_DIRECTORY_ATTRIBUTE;
  1121.       hdr->original_size = 0;
  1122.       strcat (hdr->name, "/");
  1123.     }
  1124. }
  1125.  
  1126. /* Write only unix extended header. */
  1127. write_header (nafp, hdr)
  1128.      FILE *nafp;
  1129.      LzHeader *hdr;
  1130. {
  1131.   int        header_size;
  1132.   int        name_length;
  1133.   char          data[LZHEADER_STRAGE], *ptr;
  1134.   int           cnt;
  1135.  
  1136.   bzero (data, LZHEADER_STRAGE);
  1137.   bcopy (hdr->method, data + I_METHOD, METHOD_TYPE_STRAGE);
  1138.   setup_put (data + I_PACKED_SIZE);
  1139.   put_longword (hdr->packed_size);
  1140.   put_longword (hdr->original_size);
  1141.   put_longword (hdr->last_modified_stamp);
  1142.   put_word (hdr->attribute);
  1143.  
  1144. #ifdef STRICT
  1145.  
  1146.   if ( hdr->name[1] == ':' )
  1147.   {
  1148.     name_length = strlen(hdr->name + 2);
  1149.     put_byte (name_length);
  1150.     bcopy (hdr->name + 2, data + I_NAME, name_length);
  1151.   }
  1152.   else
  1153.   {
  1154.     name_length = strlen(hdr->name);
  1155.     put_byte (name_length);
  1156.     bcopy (hdr->name, data + I_NAME, name_length);
  1157.   }
  1158.  
  1159.   for ( ptr = data + I_NAME, cnt = 0; cnt < name_length; ptr++, cnt++ )
  1160.   {
  1161.     /* *ptr = toupper(*ptr); */
  1162.  
  1163.     if ( *ptr == '/' )
  1164.       *ptr = '\\';
  1165.   }
  1166. #else
  1167.   name_length = strlen (hdr->name);
  1168.   put_byte (name_length);
  1169.   bcopy (hdr->name, data + I_NAME, name_length);
  1170. #endif
  1171.  
  1172.   setup_put (data + I_NAME + name_length);
  1173.   put_word (hdr->crc);
  1174. #ifdef STRICT
  1175.   header_size = I_EXTEND_TYPE - 2 + name_length;
  1176. #else
  1177.   put_byte (OUR_EXTEND);
  1178.   put_byte (CURRENT_UNIX_MINOR_VERSION);
  1179.   put_longword ((long)hdr->unix_last_modified_stamp);
  1180.   put_word (hdr->unix_mode);
  1181.   put_word (hdr->unix_uid);
  1182.   put_word (hdr->unix_gid);
  1183.   header_size = I_UNIX_EXTEND_BOTTOM - 2 + name_length;
  1184. #endif
  1185.   data[I_HEADER_SIZE] = header_size;
  1186.   data[I_HEADER_CHECKSUM] = calc_sum (data + I_METHOD, header_size);
  1187.  
  1188.   if (fwrite (data, sizeof (char), header_size + 2, nafp) == 0)
  1189.     error ("cannot write to temporary file");
  1190. }
  1191.  
  1192. boolean archive_is_msdos_sfx1 (name)
  1193.      char *name;
  1194. {
  1195.   int    len = strlen (name);
  1196.   return ((len >= 4) &&
  1197.       (strcmp (name + len - 4, ".com") == 0 ||
  1198.        strcmp (name + len - 4, ".exe") == 0));
  1199. }
  1200.  
  1201. boolean skip_msdos_sfx1_code (fp)
  1202.      FILE *fp;
  1203. {
  1204.   unsigned char buffer[2048];
  1205.   unsigned char *p, *q;
  1206.   int    n;
  1207.  
  1208.   n = fread (buffer, sizeof (char), 2048, fp);
  1209.  
  1210.   for (p = buffer + 2, q = buffer + n - 5; p < q; p ++)
  1211.     {
  1212.       /* found "-l??-" keyword (as METHOD type string) */
  1213.       if (p[0] == '-' && p[1] == 'l' && p[4] == '-')
  1214.     {
  1215.       /* size and checksum validate check */
  1216.       if (p[-2] > 20 && p[-1] == calc_sum (p, p[-2]))
  1217.         {
  1218.               fseek (fp, (long) ((p - 2) - buffer) - n, SEEK_CUR);
  1219.           return TRUE;
  1220.         }
  1221.     }
  1222.     }
  1223.  
  1224.   fseek (fp, (long) -n, SEEK_CUR);
  1225.   return FALSE;
  1226. }
  1227.  
  1228.  
  1229. /*----------------------------------------------------------------------*/
  1230. /*                                    */
  1231. /*----------------------------------------------------------------------*/
  1232.  
  1233. make_tmp_name (original, name)
  1234.      char *original;
  1235.      char *name;
  1236. {
  1237. #ifdef TMP_FILENAME_TEMPLATE
  1238.   /* "/tmp/lhXXXXXX" etc. */
  1239.   strcpy (name, TMP_FILENAME_TEMPLATE);
  1240. #else
  1241.   char *p, *s;
  1242.  
  1243.   strcpy (name, original);
  1244.   for (p = name, s = (char*)0; *p; p++)
  1245.     if (*p == '/' || *p == '\\')
  1246.       s = p;
  1247.  
  1248.   strcpy ((s ? s+1 : name), "lhXXXXXX");
  1249. #endif
  1250.  
  1251.   mktemp (name);
  1252. }
  1253.  
  1254. make_backup_name (name, orginal)
  1255.      char *name;
  1256.      char *orginal;
  1257. {
  1258.   register char *p, *dot;
  1259.  
  1260.   strcpy (name, orginal);
  1261.   for (p = name, dot = (char*)0; *p; p ++)
  1262.     {
  1263.       if (*p == '.')
  1264.     dot = p;
  1265.       else if (*p == '/' || *p == '\\')
  1266.     dot = (char*)0;
  1267.     }
  1268.  
  1269.   if (dot)
  1270.     p = dot;
  1271.  
  1272. #ifdef BACKUPNAME_EXTENTION
  1273.   strcpy (p, BACKUPNAME_EXTENTION)
  1274. #else
  1275.   strcpy (p, ".bak");
  1276. #endif
  1277. }
  1278.  
  1279. make_standard_archive_name (name, orginal)
  1280.      char *name;
  1281.      char *orginal;
  1282. {
  1283.   register char *p, *dot;
  1284.  
  1285.   strcpy (name, orginal);
  1286.   for (p = name, dot = (char*)0; *p; p ++)
  1287.     {
  1288.       if (*p == '.')
  1289.     dot = p;
  1290.       else if (*p == '/' || *p == '\\')
  1291.     dot = (char*)0;
  1292.     }
  1293.  
  1294.   if (dot)
  1295.     p = dot;
  1296.  
  1297. #ifdef ARCHIVENAME_EXTENTION
  1298.   strcpy (p, ARCHIVENAME_EXTENTION);
  1299. #else
  1300.   strcpy (p, ".lzh");
  1301. #endif
  1302. }
  1303.  
  1304. /*----------------------------------------------------------------------*/
  1305. /*                                    */
  1306. /*----------------------------------------------------------------------*/
  1307.  
  1308.  
  1309. boolean need_file (name)
  1310.      char *name;
  1311. {
  1312.   int    i;
  1313.  
  1314.   if (cmd_filec == 0)
  1315.     return TRUE;
  1316.  
  1317.   for (i = 0; i < cmd_filec; i ++)
  1318.     {
  1319.       if (STRING_COMPARE (cmd_filev[i], name) == 0)
  1320.     return TRUE;
  1321.     }
  1322.  
  1323.   return FALSE;
  1324. }
  1325.  
  1326. FILE *xfopen (name, mode)
  1327.      char *name, *mode;
  1328. {
  1329.   FILE *fp;
  1330.  
  1331.   if ((fp = fopen (name, mode)) == NULL)
  1332.     error (name);
  1333.  
  1334.   return fp;
  1335. }
  1336.  
  1337.  
  1338. /*----------------------------------------------------------------------*/
  1339. /*        Listing Stuff                        */
  1340. /*----------------------------------------------------------------------*/
  1341.  
  1342. /* need 14 or 22 (when long_format_listing is TRUE) column spaces */
  1343. print_size (packed_size, original_size)
  1344.      long packed_size, original_size;
  1345. {
  1346.   if (long_format_listing)
  1347.     printf ("%7ld ", packed_size);
  1348.  
  1349.   printf ("%7ld ", original_size);
  1350.  
  1351.   if (original_size == 0L)
  1352.     printf ("******");
  1353.   else
  1354.     printf ("%3d.%1d%%",
  1355.         (int)((packed_size * 100L) / original_size),
  1356.         (int)((packed_size * 1000L) / original_size) % 10);
  1357. }
  1358.  
  1359. /* need 12 or 17 (when long_format_listing is TRUE) column spaces */
  1360. print_stamp (t)
  1361.      time_t t;
  1362. {
  1363.   static boolean    got_now = FALSE;
  1364.   static time_t        now;
  1365.   static unsigned int    threshold;
  1366.   static char   t_month[12*3+1] = "JanFebMarAprMayJunJulAugSepOctNovDec";
  1367.   struct tm        *p;
  1368.  
  1369.   if (t == 0)
  1370.     {
  1371.       if (long_format_listing)
  1372.     printf ("                 "); /* 17 spaces */
  1373.       else
  1374.     printf ("            ");    /* 12 spaces */
  1375.  
  1376.       return;
  1377.     }
  1378.  
  1379.   if (!got_now)
  1380.     {
  1381.       time (&now);
  1382.       p = localtime (&now);
  1383.       threshold = p->tm_year * 12 + p->tm_mon - 6;
  1384.       got_now = TRUE;
  1385.     }
  1386.  
  1387.   p = localtime (&t);
  1388.  
  1389.   if (long_format_listing)
  1390.     printf ("%.3s %2d %02d:%02d %04d",
  1391.         &t_month[p->tm_mon * 3], p->tm_mday,
  1392.         p->tm_hour, p->tm_min, p->tm_year + 1900);
  1393.   else
  1394.     if (p->tm_year * 12 + p->tm_mon > threshold)
  1395.       printf ("%.3s %2d %02d:%02d",
  1396.           &t_month[p->tm_mon * 3], p->tm_mday, p->tm_hour, p->tm_min);
  1397.     else
  1398.       printf ("%.3s %2d  %04d",
  1399.           &t_month[p->tm_mon * 3], p->tm_mday, p->tm_year + 1900);
  1400. }
  1401.  
  1402. print_bar ()
  1403. {
  1404.   /* 17+1+(0 or 7+1)+7+1+6+1+(0 or 1+4)+(12 or 17)+1+20 */
  1405.   /*       12345678901234567_  1234567_123456  _123456789012   1234      */
  1406.   if (long_format_listing)
  1407. #ifdef STRICT
  1408.     printf ("------- ------- ------ ---- ----------------- -------------\n");
  1409. #else
  1410.     printf ("----------------- ------- ------- ------ ---- ----------------- -------------\n");
  1411. #endif
  1412.   else
  1413. #ifdef STRICT
  1414.     printf ("------- ------ ------------ --------------------\n");
  1415. #else
  1416.     printf ("----------------- ------- ------ ------------ --------------------\n");
  1417. #endif
  1418. }
  1419.  
  1420.  
  1421. /*
  1422.   view
  1423.  */
  1424. cmd_view ()
  1425. {
  1426.   FILE        *fp;
  1427.   LzHeader    hdr;
  1428.   register char    *p;
  1429.   long        a_packed_size = 0L;
  1430.   long        a_original_size = 0L;
  1431.   int        n_files = 0;
  1432.   struct stat    v_stat;
  1433.  
  1434.   if ((fp = fopen (archive_name, RMODE)) == NULL)
  1435.     if (!expand_archive_name (expanded_archive_name, archive_name))
  1436.       error (archive_name);
  1437.     else
  1438.       {
  1439.     errno = 0;
  1440.         fp = xfopen (expanded_archive_name, RMODE);
  1441.     archive_name = expanded_archive_name;
  1442.       }
  1443.  
  1444.   if (archive_is_msdos_sfx1 (archive_name))
  1445.     {
  1446.       skip_msdos_sfx1_code (fp);
  1447.     }
  1448.  
  1449.   if (!quiet)
  1450.     {
  1451.       /*       12345678901234567_  1234567_123456  _  123456789012  1234 */
  1452. #ifdef STRICT
  1453.       printf ("%s   SIZE  RATIO%s %s    STAMP   %s NAME\n",
  1454. #else
  1455.       printf (" PERMSSN  UID GID %s   SIZE  RATIO%s %s    STAMP   %s NAME\n",
  1456. #endif
  1457.           long_format_listing ? " PACKED " : "", /* 8,0 */
  1458.           long_format_listing ? "  CRC" : "", /* 5,0 */
  1459.           long_format_listing ? "  " : "", /* 2,0 */
  1460.           long_format_listing ? "   " : ""); /* 3,0 */
  1461.       print_bar ();
  1462.     }
  1463.  
  1464.   while (get_header (fp, &hdr))
  1465.     {
  1466.       if (need_file (hdr.name))
  1467.     {
  1468.       if (hdr.extend_type == EXTEND_UNIX)
  1469.             {
  1470. #ifndef STRICT
  1471.               printf ("%c%c%c%c%c%c%c%c%c%4d/%-4d",
  1472.           ((hdr.unix_mode & UNIX_OWNER_READ_PERM)  ? 'r' : '-'),
  1473.           ((hdr.unix_mode & UNIX_OWNER_WRITE_PERM) ? 'w' : '-'),
  1474.           ((hdr.unix_mode & UNIX_OWNER_EXEC_PERM)  ? 'x' : '-'),
  1475.           ((hdr.unix_mode & UNIX_GROUP_READ_PERM)  ? 'r' : '-'),
  1476.           ((hdr.unix_mode & UNIX_GROUP_WRITE_PERM) ? 'w' : '-'),
  1477.           ((hdr.unix_mode & UNIX_GROUP_EXEC_PERM)  ? 'x' : '-'),
  1478.           ((hdr.unix_mode & UNIX_OTHER_READ_PERM)  ? 'r' : '-'),
  1479.           ((hdr.unix_mode & UNIX_OTHER_WRITE_PERM) ? 'w' : '-'),
  1480.           ((hdr.unix_mode & UNIX_OTHER_EXEC_PERM)  ? 'x' : '-'),
  1481.           hdr.unix_uid, hdr.unix_gid);
  1482. #endif
  1483.         }
  1484.       else
  1485.         {
  1486.           switch (hdr.extend_type)
  1487.         {            /* max 18 characters */
  1488.                 case EXTEND_GENERIC:    p = "[Generic]"; break;
  1489.  
  1490.         case EXTEND_CPM:    p = "[CP/M]"; break;
  1491.  
  1492.           /* OS-9 and FLEX's CPU is MC-6809. I like it. :-)  */
  1493.         case EXTEND_FLEX:    p = "[FLEX]"; break;
  1494.  
  1495.         case EXTEND_OS9:    p = "[OS-9]"; break;
  1496.  
  1497.           /* I guessed from this ID.  Is this right? */
  1498.         case EXTEND_OS68K:    p = "[OS-9/68K]"; break;
  1499.  
  1500.         case EXTEND_MSDOS:    p = "[MS-DOS]"; break;
  1501.  
  1502.           /* I have Macintosh. :-)  */
  1503.         case EXTEND_MACOS:    p = "[Mac OS]"; break;
  1504.  
  1505.         case EXTEND_OS2:    p = "[OS/2]"; break;
  1506.  
  1507.         case EXTEND_HUMAN:    p = "[Human68K]"; break;
  1508.  
  1509.         case EXTEND_OS386:    p = "[OS-386]"; break;
  1510.  
  1511. #ifdef EXTEND_TOWNSOS
  1512.           /* This ID isn't fixed */
  1513.         case EXTEND_TOWNSOS:    p = "[TownsOS]"; break;
  1514. #endif
  1515.  
  1516.           /* Ouch!  Please customize it's ID.  */
  1517.                 default:                p = "[Unknown]"; break;
  1518.                 }
  1519. #ifndef STRICT
  1520.               printf ("%-18.18s", p);
  1521. #endif
  1522.         }
  1523.  
  1524.       print_size (hdr.packed_size, hdr.original_size);
  1525.  
  1526.       if (long_format_listing)
  1527.         if (hdr.has_crc)
  1528.           printf (" %04x", hdr.crc);
  1529.         else
  1530.           printf (" ****");
  1531.  
  1532.       printf (" ");
  1533.       print_stamp (hdr.unix_last_modified_stamp);
  1534.       printf (" %s\n", hdr.name);
  1535.       n_files ++;
  1536.       a_packed_size += hdr.packed_size;
  1537.       a_original_size += hdr.original_size;
  1538.     }
  1539.       fseek (fp, hdr.packed_size, SEEK_CUR);
  1540.     }
  1541.  
  1542.   fclose (fp);
  1543.   if (!quiet)
  1544.     {
  1545.       print_bar ();
  1546.  
  1547. #ifndef STRICT
  1548.       printf (" Total %4d file%c ",
  1549.           n_files, (n_files == 1) ? ' ' : 's');
  1550. #endif
  1551.       print_size (a_packed_size, a_original_size);
  1552.       printf (" ");
  1553.  
  1554.       if (long_format_listing)
  1555.     printf ("     ");
  1556.  
  1557.       if (stat (archive_name, &v_stat) < 0)
  1558.     print_stamp ((time_t)0);
  1559.       else
  1560.     print_stamp (v_stat.st_mtime);
  1561.  
  1562. #ifdef STRICT
  1563.       printf (" %4d file%c ",
  1564.           n_files, (n_files == 1) ? ' ' : 's');
  1565. #endif
  1566.       printf ("\n");
  1567.     }
  1568.  
  1569.   return;
  1570. }
  1571.  
  1572.  
  1573. boolean make_parent_path (name)
  1574.      char *name;
  1575. {
  1576.   char        path[FILENAME_LENGTH];
  1577.   struct stat    v_stat;
  1578.   register char    *p;
  1579.  
  1580.  /* make parent directory name into PATH for recursive call */
  1581.   strcpy (path, name);
  1582.   for (p = path + strlen (path); p > path; p --)
  1583.     if (p[-1] == '/' || p[-1] == '\\')
  1584.       {
  1585.     p[-1] = '\0';
  1586.     break;
  1587.       }
  1588.  
  1589.   if (p == path)
  1590.     return FALSE;        /* no more parent. */
  1591.  
  1592.   if (stat (path, &v_stat) >= 0)
  1593.     {
  1594.       if ((v_stat.st_mode & S_IFMT) != S_IFDIR)
  1595.     return FALSE;        /* already exist. but it isn't directory. */
  1596.       return TRUE;        /* already exist its directory. */
  1597.     }
  1598.  
  1599.   errno = 0;
  1600.  
  1601.   if (!quiet)
  1602.     message ("Making Directory", path);
  1603.  
  1604.   if (mkdir (path, 0777) >= 0)    /* try */
  1605.     return TRUE;        /* successful done. */
  1606.  
  1607.   errno = 0;
  1608.  
  1609.   if (!make_parent_path (path))
  1610.     return FALSE;
  1611.  
  1612.   if (mkdir (path, 0777) < 0)        /* try again */
  1613.     return FALSE;
  1614.  
  1615.   return TRUE;
  1616. }
  1617.  
  1618. FILE *open_with_make_path (name)
  1619.      char *name;
  1620. {
  1621.   FILE        *fp;
  1622.   struct stat    v_stat;
  1623.   char        buffer[1024];
  1624.  
  1625.   if (stat (name, &v_stat) >= 0)
  1626.     {
  1627.       if ((v_stat.st_mode & S_IFMT) != S_IFREG)
  1628.     return NULL;
  1629.  
  1630.       if (!force)
  1631.     {
  1632.       for (;;)
  1633.         {
  1634.           fprintf (stderr, "%s OverWrite ?(Yes/No/All) ", name);
  1635.           fflush (stderr);
  1636.           gets (buffer);
  1637.           if (buffer[0] == 'N' || buffer[0] == 'n')
  1638.         return NULL;
  1639.           if (buffer[0] == 'Y' || buffer[0] == 'y')
  1640.         break;
  1641.           if (buffer[0] == 'A' || buffer[0] == 'a')
  1642.         {
  1643.           force = TRUE;
  1644.           break;
  1645.         }
  1646.         }
  1647.     }
  1648.     }
  1649.  
  1650.   fp = fopen (name, WMODE);
  1651.   if (!fp)
  1652.     {
  1653.       errno = 0;
  1654.       if (!make_parent_path (name))
  1655.     return NULL;
  1656.  
  1657.       fp = fopen (name, WMODE);
  1658.       if (!fp)
  1659.         message ("Error:", name);
  1660.     }
  1661.   return fp;
  1662. }
  1663.  
  1664. extern int decode_lzhuf (), decode_larc ();
  1665. extern int decode_stored_crc (), decode_stored_nocrc ();
  1666.  
  1667. extract_one (fp, hdr)
  1668.      FILE *fp;
  1669.      LzHeader *hdr;
  1670. {
  1671.   FILE        *ofp;        /* output file */
  1672.   char        name[1024];
  1673.   time_t    utimebuf[2];
  1674.   int        crc;
  1675.   int        (*decode_proc)(); /* (ifp,ofp,original_size,name) */
  1676.   int        save_quiet;
  1677.  
  1678.   strcpy (name, hdr->name);
  1679.   if ((hdr->unix_mode & UNIX_FILE_TYPEMASK) == UNIX_FILE_REGULAR)
  1680.     {
  1681.       if (bcmp (hdr->method, LZHUFF1_METHOD, METHOD_TYPE_STRAGE) == 0)
  1682.     decode_proc = decode_lzhuf;
  1683.       else if ((bcmp (hdr->method, LZHUFF0_METHOD, METHOD_TYPE_STRAGE) == 0) ||
  1684.            (bcmp (hdr->method, LARC4_METHOD, METHOD_TYPE_STRAGE) == 0))
  1685.     decode_proc = (hdr->has_crc) ? decode_stored_crc : decode_stored_nocrc;
  1686.       else if (bcmp (hdr->method, LARC5_METHOD, METHOD_TYPE_STRAGE) == 0)
  1687.     decode_proc = decode_larc;
  1688.       else
  1689.         message ("Error:", "Sorry, Cannot Extract this method.");
  1690.  
  1691.       reading_filename = archive_name;
  1692.       writting_filename = name;
  1693.       if (output_to_stdout)
  1694.     {
  1695.           if (!quiet)
  1696.             printf ("::::::::\r\n%s\r\n::::::::\r\n", name);
  1697.  
  1698.           if ( strlen(pager) != 0 )
  1699.             ofp = popen(pager, WMODE);
  1700.           else
  1701.             ofp = stdout;
  1702.  
  1703.       save_quiet = quiet;
  1704.           quiet = TRUE;
  1705.           crc = (*decode_proc) (fp, ofp, hdr->original_size, name);
  1706.           quiet = save_quiet;
  1707.  
  1708.           if ( strlen(pager) != 0 )
  1709.             pclose(ofp);
  1710.     }
  1711.       else if (output_to_test)
  1712.         {
  1713.           ofp = fopen(NULLFILE, WMODE);
  1714.           crc = (*decode_proc) (fp, ofp, hdr->original_size, name);
  1715.           fclose(ofp);
  1716.         }
  1717.       else
  1718.         {
  1719. #ifdef MSDOS
  1720.           if ( !IsFileNameValid(name) )
  1721.             ChangeNameForFAT(name);
  1722. #endif
  1723.       if ((ofp = open_with_make_path (name)) == NULL)
  1724.         return;
  1725.       else
  1726.         {
  1727.           crc = (*decode_proc) (fp, ofp, hdr->original_size, name);
  1728.           fclose (ofp);
  1729.         }
  1730.     }
  1731.  
  1732.       if (hdr->has_crc && (crc != hdr->crc))
  1733.         if (output_to_test)
  1734.           message ("Error:", "CRC failed\a");
  1735.         else
  1736.           error ("CRC failed\a");
  1737.     }
  1738.   else
  1739.     {
  1740.       /* NAME has trailing SLASH '/', (^_^) */
  1741.       if (!output_to_stdout &&
  1742.       !make_parent_path (name))
  1743.     error (name);
  1744.     }
  1745.  
  1746.   if (!output_to_stdout && !output_to_test)
  1747.     {
  1748.       utimebuf[0] = utimebuf[1] = hdr->unix_last_modified_stamp;
  1749.       utime (name, utimebuf);
  1750.  
  1751. #ifdef NOT_COMPATIBLE_MODE
  1752.       setfmode(name, hdr->attribute);
  1753. #else
  1754.       chmod (name, hdr->unix_mode);
  1755. #endif
  1756.  
  1757. #ifndef MSDOS
  1758.       chown (name, hdr->unix_uid, hdr->unix_gid);
  1759. #endif
  1760.       errno = 0;
  1761.     }
  1762. }
  1763.  
  1764.  
  1765. /*
  1766.   extract
  1767.  */
  1768. cmd_extract ()
  1769. {
  1770.   LzHeader    hdr;
  1771.   long        pos;
  1772.   FILE        *fp;
  1773.  
  1774.   if ((fp = fopen (archive_name, RMODE)) == NULL)
  1775.     if (!expand_archive_name (expanded_archive_name, archive_name))
  1776.       error (archive_name);
  1777.     else
  1778.       {
  1779.     errno = 0;
  1780.         fp = xfopen (expanded_archive_name, RMODE);
  1781.     archive_name = expanded_archive_name;
  1782.       }
  1783.  
  1784.   if (archive_is_msdos_sfx1 (archive_name))
  1785.     {
  1786.       skip_msdos_sfx1_code (fp);
  1787.     }
  1788.  
  1789.   while (get_header (fp, &hdr))
  1790.     {
  1791.       if (need_file (hdr.name))
  1792.     {
  1793.       pos = ftell (fp);
  1794.       extract_one (fp, &hdr);
  1795.       fseek (fp, pos + hdr.packed_size, SEEK_SET);
  1796.     } else {
  1797.       fseek (fp, hdr.packed_size, SEEK_CUR);
  1798.     }
  1799.     }
  1800.  
  1801.   fclose (fp);
  1802.  
  1803.   return;
  1804. }
  1805.  
  1806. /*----------------------------------------------------------------------*/
  1807. /*                                    */
  1808. /*----------------------------------------------------------------------*/
  1809.  
  1810. extern int encode_lzhuf ();
  1811. extern int encode_storerd_crc ();
  1812.  
  1813. append_one (fp, nafp, hdr)
  1814.      FILE *fp, *nafp;
  1815.      LzHeader *hdr;
  1816. {
  1817.   long    header_pos, next_pos, org_pos, data_pos;
  1818.   long    v_original_size, v_packed_size;
  1819.  
  1820.   reading_filename = hdr->name;
  1821.   writting_filename = temporary_name;
  1822.  
  1823.   org_pos = ftell (fp);
  1824.   header_pos = ftell (nafp);
  1825.   write_header (nafp, hdr);    /* DUMMY */
  1826.  
  1827.   if (hdr->original_size == 0)
  1828.     {
  1829.       printf("%s - not frozen\n",hdr->name);
  1830.       return;            /* previous write_header is not DUMMY. (^_^) */
  1831.     }
  1832.  
  1833.   data_pos = ftell (nafp);
  1834.   hdr->crc = encode_lzhuf (fp, nafp, hdr->original_size,
  1835.                &v_original_size, &v_packed_size, hdr->name);
  1836.   if (v_packed_size < v_original_size)
  1837.     {
  1838.       next_pos = ftell (nafp);
  1839.     }
  1840.   else
  1841.     {                /* retry by stored method */
  1842.       fseek (fp, org_pos, SEEK_SET);
  1843.       fseek (nafp, data_pos, SEEK_SET);
  1844.       hdr->crc = encode_stored_crc (fp, nafp, hdr->original_size,
  1845.                     &v_original_size, &v_packed_size);
  1846.       fflush (nafp);
  1847.       next_pos = ftell (nafp);
  1848.       ftruncate (fileno (nafp), next_pos);
  1849.       bcopy (LZHUFF0_METHOD, hdr->method, METHOD_TYPE_STRAGE);
  1850.     }
  1851.   hdr->original_size = v_original_size;
  1852.   hdr->packed_size = v_packed_size;
  1853.   fseek (nafp, header_pos, SEEK_SET);
  1854.   write_header (nafp, hdr);
  1855.   fseek (nafp, next_pos, SEEK_SET);
  1856. }
  1857.  
  1858. write_tail (nafp)
  1859.      FILE *nafp;
  1860. {
  1861.   putc (0x00, nafp);
  1862. }
  1863.  
  1864. copy_old_one (oafp, nafp, hdr)
  1865.      FILE *oafp, *nafp;
  1866.      LzHeader *hdr;
  1867. {
  1868.   if (noexec)
  1869.     {
  1870.       fseek (oafp, (long)(hdr->header_size + 2) + hdr->packed_size, SEEK_CUR);
  1871.     }
  1872.   else
  1873.     {
  1874.       reading_filename = archive_name;
  1875.       writting_filename = temporary_name;
  1876.       copy_file (oafp, nafp, (long)(hdr->header_size + 2) + hdr->packed_size);
  1877.     }
  1878. }
  1879.  
  1880.  
  1881. FILE *append_it (name, oafp, nafp)
  1882.      char *name;
  1883.      FILE *oafp, *nafp;
  1884. {
  1885.   LzHeader    ahdr, hdr;
  1886.   FILE        *fp;
  1887.   long        old_header;
  1888.   int        cmp;
  1889.   int        filec;
  1890.   char        **filev;
  1891.   int        i;
  1892.  
  1893.   struct stat    v_stat;
  1894.   boolean    directory;
  1895.  
  1896.   /* check that any added name is not the same as the archive name */
  1897.   if (strcmp(name, archive_name) == 0) return oafp;
  1898.  
  1899.   if (!delete_from_archive)
  1900.     if (stat (name, &v_stat) < 0)
  1901.       {
  1902.         message ("Error:", name);
  1903.         return oafp;
  1904.       }
  1905.  
  1906.   directory = ((v_stat.st_mode & S_IFMT) == S_IFDIR);
  1907.  
  1908.   init_header (name, &v_stat, &hdr);
  1909.  
  1910.   if (!delete_from_archive && !directory && !noexec)
  1911.     fp = xfopen (name, RMODE);
  1912.  
  1913.   while (oafp)
  1914.     {
  1915.       old_header = ftell (oafp);
  1916.       if (!get_header (oafp, &ahdr))
  1917.     {
  1918.       fclose (oafp);
  1919.       oafp = NULL;
  1920.       break;
  1921.     }
  1922.       else
  1923.     {
  1924.       cmp = STRING_COMPARE (ahdr.name, hdr.name);
  1925.       if (cmp < 0)
  1926.         {        /* SKIP */
  1927.           fseek (oafp, old_header, SEEK_SET);
  1928.           copy_old_one (oafp, nafp, &ahdr);
  1929.         }
  1930.       else if (cmp == 0)
  1931.         {        /* REPLACE */
  1932.           fseek (oafp, ahdr.packed_size, SEEK_CUR);
  1933.           break;
  1934.         }
  1935.       else        /* cmp > 0, INSERT */
  1936.         {
  1937.           fseek (oafp, old_header, SEEK_SET);
  1938.           break;
  1939.         }
  1940.     }
  1941.     }
  1942.  
  1943.   if (delete_from_archive)
  1944.     {
  1945.       if (noexec)
  1946.         fprintf (stderr, "DELETE %s\n", name);
  1947.       else
  1948.         printf ("%s - Deleted\n", name);
  1949.     }
  1950.   else
  1951.     {
  1952.       if ( !oafp || (cmp > 0) || !update_if_newer
  1953.            || (ahdr.unix_last_modified_stamp < hdr.unix_last_modified_stamp) )
  1954.     {
  1955.       if (noexec)
  1956.         fprintf (stderr, "APPEND %s\n", name);
  1957.           else
  1958. #ifdef STRICT
  1959.             if ( !directory )
  1960. #endif
  1961.               if ( !update_freshen || (cmp == 0) )
  1962.                 append_one (fp, nafp, &hdr);
  1963.     }
  1964.       else
  1965.     {                    /* archive has old one */
  1966.       fseek (oafp, old_header, SEEK_SET);
  1967.       copy_old_one (oafp, nafp, &ahdr);
  1968.     }
  1969.  
  1970.       if (!directory)
  1971.     {
  1972.       if (!noexec)
  1973.         fclose (fp);
  1974.     }
  1975.       else
  1976.     {            /* recurcive call */
  1977.       if (find_files (name, &filec, &filev))
  1978.         {
  1979.           for (i = 0; i < filec; i ++)
  1980.         oafp = append_it (filev[i], oafp, nafp);
  1981.           free_files (filec, filev);
  1982.         }
  1983.       return oafp;
  1984.     }
  1985.     }
  1986.  
  1987.   return oafp;
  1988. }
  1989.  
  1990.  
  1991. remove_it (name)
  1992.      char *name;
  1993. {
  1994.   struct stat    v_stat;
  1995.   int        i;
  1996.   char        **filev;
  1997.   int        filec;
  1998.  
  1999.   if (stat (name, &v_stat) < 0)
  2000.     {
  2001.       fprintf (stderr, "Cannot access \"%s\".\n", name);
  2002.       return;
  2003.     }
  2004.  
  2005.   if ((v_stat.st_mode & S_IFMT) == S_IFDIR)
  2006.     {
  2007.       if (!find_files (name, &filec, &filev))
  2008.     {
  2009.           fprintf (stderr, "Cannot open directory \"%s\".\n", name);
  2010.       return;
  2011.     }
  2012.  
  2013.       for (i = 0; i < filec; i ++)
  2014.     remove_it (filev[i]);
  2015.  
  2016.       free_files (filec, filev);
  2017.  
  2018.       if (noexec)
  2019.         printf ("REMOVE DIR %s\n", name);
  2020.       else if (rmdir (name) < 0)
  2021.         fprintf (stderr, "Cannot remove directory \"%s\".\n", name);
  2022.       else if (!quiet)
  2023.         printf ("%s - Removed\n", name);
  2024.     }
  2025.   else
  2026.     {
  2027.       if (noexec)
  2028.         printf ("REMOVE %s\n", name);
  2029.       else if (unlink (name) < 0)
  2030.         fprintf (stderr, "Cannot delete \"%s\".\n", name);
  2031.       else if (!quiet)
  2032.         printf ("%s - Removed\n", name);
  2033.     }
  2034. }
  2035.  
  2036. #ifdef FASTCOPY
  2037. #define BUFFER_SIZE 16384
  2038.  
  2039. #ifndef O_BINARY
  2040. #define O_BINARY 0
  2041. #endif
  2042.  
  2043. copy_archive(src, dst)
  2044. char *src, *dst;
  2045. {
  2046.   int ih, oh;
  2047.   unsigned chunk;
  2048.   char *buffer = (char *) rson;
  2049.  
  2050.   printf ("Copying temp to archive ... ");
  2051.  
  2052.   ih = open (src, O_RDONLY | O_BINARY);
  2053.   if ( ih == -1 )
  2054.     error(src);
  2055.   oh = open (dst, O_WRONLY | O_BINARY | O_CREAT | O_TRUNC, S_IREAD | S_IWRITE);
  2056.   if ( oh == -1 )
  2057.     error(dst);
  2058.  
  2059.   while ( (chunk = read(ih, buffer, BUFFER_SIZE)) > 0 )
  2060.     if ( write(oh, buffer, chunk) != chunk )
  2061.       error(dst);
  2062.  
  2063.   close (ih);
  2064.   close (oh);
  2065.  
  2066.   printf("\b\b\b\b   \b\b\b\b.\n");
  2067. }
  2068. #endif
  2069.  
  2070. cmd_append ()
  2071. {
  2072.   LzHeader    ahdr;
  2073.   FILE        *oafp, *nafp;
  2074.   char        backup_archive_name [ FILENAME_LENGTH ];
  2075.   char        new_archive_name_buffer [ FILENAME_LENGTH ];
  2076.   char        *new_archive_name;
  2077.   int        i;
  2078.   long        old_header;
  2079.   struct stat    v_stat;
  2080.   boolean    old_archive_exist;
  2081.  
  2082.   if (cmd_filec == 0)
  2083.     return;
  2084.  
  2085.   make_tmp_name (archive_name, temporary_name);
  2086.  
  2087.   if ((oafp = fopen (archive_name, RMODE)) == NULL)
  2088.     if (expand_archive_name (expanded_archive_name, archive_name))
  2089.       {
  2090.     errno = 0;
  2091.         oafp = fopen (expanded_archive_name, RMODE);
  2092.     archive_name = expanded_archive_name;
  2093.       }
  2094.  
  2095.   old_archive_exist = (oafp) ? TRUE : FALSE;
  2096.   if (new_archive && oafp)
  2097.     {
  2098.       fclose (oafp);
  2099.       oafp = NULL;
  2100.     }
  2101.  
  2102.   if (oafp && archive_is_msdos_sfx1 (archive_name))
  2103.     {
  2104.       skip_msdos_sfx1_code (oafp);
  2105.       make_standard_archive_name (new_archive_name_buffer, archive_name);
  2106.       new_archive_name = new_archive_name_buffer;
  2107.     }
  2108.   else
  2109.     {
  2110.       new_archive_name = archive_name;
  2111.     }
  2112.  
  2113.   errno = 0;
  2114.   if (!noexec)
  2115.     {
  2116.       nafp = xfopen (temporary_name, WMODE);
  2117.       remove_temporary_at_error = TRUE;
  2118.     }
  2119.  
  2120.   for (i = 0; i < cmd_filec; i ++)
  2121.     oafp = append_it (cmd_filev[i], oafp, nafp);
  2122.  
  2123.   if (oafp)
  2124.     {
  2125.       old_header = ftell (oafp);
  2126.       while (get_header (oafp, &ahdr))
  2127.     {
  2128.       fseek (oafp, old_header, SEEK_SET);
  2129.       copy_old_one (oafp, nafp, &ahdr);
  2130.       old_header = ftell (oafp);
  2131.     }
  2132.       fclose (oafp);
  2133.     }
  2134.  
  2135.   if (!noexec)
  2136.     {
  2137.       write_tail (nafp);
  2138.       fclose (nafp);
  2139.     }
  2140.  
  2141.   make_backup_name (backup_archive_name, archive_name);
  2142.  
  2143.   if (!noexec && old_archive_exist)
  2144.   {
  2145.     unlink(backup_archive_name);
  2146.  
  2147.     if (rename (archive_name, backup_archive_name) < 0)
  2148.       error (archive_name);
  2149.   }
  2150.  
  2151.   if (!quiet && new_archive_name == new_archive_name_buffer)
  2152.     {                /* warning at old archive is SFX */
  2153.       printf ("New Archive File is \"%s\"\n", new_archive_name);
  2154.     }
  2155.  
  2156.   if (!noexec && rename (temporary_name, new_archive_name) < 0)
  2157.     {
  2158.       if (stat (temporary_name, &v_stat) < 0)
  2159.     error (temporary_name);
  2160.  
  2161. #ifdef FASTCOPY
  2162.       copy_archive(temporary_name, archive_name);
  2163. #else
  2164.       oafp = xfopen (temporary_name, RMODE);
  2165.       nafp = xfopen (archive_name, WMODE);
  2166.       reading_filename = temporary_name;
  2167.       writting_filename = archive_name;
  2168.       copy_file (oafp, nafp, (long)v_stat.st_size);
  2169.       fclose (nafp);
  2170.       fclose (oafp);
  2171. #endif
  2172.  
  2173.       unlink (temporary_name);
  2174.     }
  2175.   remove_temporary_at_error = FALSE;
  2176.  
  2177.   if (delete_after_append)
  2178.     {
  2179.       if (!quiet && !noexec)
  2180.     printf ("Erasing...\n");
  2181.       for (i = 0; i < cmd_filec; i ++)
  2182.     remove_it (cmd_filev[i]);
  2183.     }
  2184.  
  2185.   return;
  2186. }
  2187.