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