home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / ARCHIVERS / lha208src.lzh / LHA / SRC / lhadd.c < prev    next >
Text File  |  1994-02-14  |  17KB  |  654 lines

  1. /*----------------------------------------------------------------------*/
  2. /*                        LHarc Add Command                             */
  3. /*                This is part of LHarc UNIX Archiver Driver            */
  4. /*                                                                      */
  5. /*                Copyright(C) MCMLXXXIX  Yooichi.Tagawa                */
  6. /*                                                                      */
  7. /*  V0.00  Original                             1988.05.23  Y.Tagawa    */
  8. /*  V1.00  Fixed                                1989.09.22  Y.Tagawa    */
  9. /*  V1.02  Bug fix                              1990.01.19  Y.Tagawa    */
  10. /*  V0.03  LHa for UNIX                         1991.12.05  M.Oki       */
  11. /*----------------------------------------------------------------------*/
  12.  
  13. #include "lharc.h"
  14.  
  15. extern int encode_lzhuf ();
  16. extern int encode_stored_crc ();
  17.  
  18. static char new_archive_name_buffer [ FILENAME_LENGTH ];
  19. static char *new_archive_name;
  20. FILE *temporary_fp = NULL;
  21.  
  22. /*----------------------------------------------------------------------*/
  23. /*                                                                      */
  24. /*----------------------------------------------------------------------*/
  25.  
  26.  
  27.  
  28.  
  29. static void
  30. add_one (fp, nafp, hdr)
  31. FILE *fp, *nafp;
  32. LzHeader *hdr;
  33. {
  34.     long header_pos, next_pos, org_pos, data_pos;
  35.     long v_original_size, v_packed_size;
  36.  
  37.     reading_filename = hdr->name;
  38.     writting_filename = temporary_name;
  39.  
  40.     if (!fp && generic_format)    /* [generic] doesn't need directory info. */
  41.         return;
  42.     header_pos = ftell (nafp);
  43.     write_header (nafp, hdr);     /* DUMMY */
  44.  
  45.     if (hdr->original_size == 0)  /* empty file or directory */
  46.         return;                 /* previous write_header is not DUMMY. (^_^) */
  47.  
  48.     org_pos = ftell (fp);
  49.     data_pos = ftell (nafp);
  50.  
  51.     hdr->crc = encode_lzhuf (fp, nafp, hdr->original_size,
  52.         &v_original_size, &v_packed_size, hdr->name, hdr->method);
  53.  
  54.     if (v_packed_size < v_original_size)
  55.     {
  56.         next_pos = ftell (nafp);
  57.     }
  58.     else
  59.     {                                /* retry by stored method */
  60.         fseek (fp, org_pos, SEEK_SET);
  61.         fseek (nafp, data_pos, SEEK_SET);
  62.         hdr->crc = encode_stored_crc (fp, nafp, hdr->original_size,
  63.         &v_original_size, &v_packed_size);
  64.         fflush (nafp);
  65.         next_pos = ftell (nafp);
  66. #ifndef NOFTRUNCATE
  67.         ftruncate (fileno (nafp), next_pos);
  68. #endif
  69.         bcopy (LZHUFF0_METHOD, hdr->method, METHOD_TYPE_STRAGE);
  70.     }
  71.     hdr->original_size = v_original_size;
  72.     hdr->packed_size = v_packed_size;
  73.     fseek (nafp, header_pos, SEEK_SET);
  74.     write_header (nafp, hdr);
  75.     fseek (nafp, next_pos, SEEK_SET);
  76. }
  77.  
  78.  
  79. FILE *
  80. append_it (name, oafp, nafp)
  81. char *name;
  82. FILE *oafp, *nafp;
  83. {
  84.     LzHeader ahdr, hdr;
  85.     FILE *fp;
  86.     long old_header;
  87.     int cmp;
  88.     int filec;
  89.     char **filev;
  90.     int i;
  91.     STAT stbuf;
  92.     boolean directory;
  93.  
  94.     if (stat (name, &stbuf) < 0)
  95.     {
  96.         error ("cannot access", name); /* See cleaning_files, Why? */
  97.         return oafp;
  98.     }
  99.  
  100.     directory = is_directory (&stbuf);
  101.  
  102.     init_header (name, &stbuf, &hdr);
  103.  
  104.     if (!directory && !noexec)
  105.         fp = xfopen (name, READ_BINARY);
  106.     else
  107.         fp = NULL;
  108.  
  109.     while (oafp)
  110.     {
  111.         old_header = ftell (oafp);
  112.         if (!get_header (oafp, &ahdr))
  113.         {
  114.             fclose (oafp);
  115.             oafp = NULL;
  116.             break;
  117.         }
  118.         else
  119.         {
  120.             cmp = STRING_COMPARE (ahdr.name, hdr.name);
  121.             if (cmp < 0)
  122.             {                        /* SKIP */
  123.                 /* copy old to new */
  124.                 if (!noexec)
  125.                 {
  126.                     fseek (oafp, old_header, SEEK_SET);
  127.                     copy_old_one (oafp, nafp, &ahdr);
  128.                 }
  129.                 else
  130.                     fseek (oafp, ahdr.packed_size, SEEK_CUR);
  131.             }
  132.             else if (cmp == 0)
  133.             {                        /* REPLACE */
  134.                 /* drop old archive's */
  135.                 fseek (oafp, ahdr.packed_size, SEEK_CUR);
  136.                 break;
  137.             }
  138.             else                        /* cmp > 0, INSERT */
  139.             {
  140.                 fseek (oafp, old_header, SEEK_SET);
  141.                 break;
  142.             }
  143.         }
  144.     }
  145.  
  146.     if (update_if_newer)
  147.     {        /* not in archive || last_modified after copy in the archive */
  148.         if ( (! oafp) || (cmp > 0) || \
  149.             (ahdr.unix_last_modified_stamp < hdr.unix_last_modified_stamp))
  150.         {
  151.             if (noexec)
  152.             {
  153. #ifdef DEBUG
  154.                 printf ("ADD %s UPDATING - CMP = %d oafp = %s\n",
  155.                     name, cmp, (oafp) ? "OPEN" : "CLOSED");
  156.                 printf ("Old Date: %sNew Date: %s",
  157.                     ctime(&ahdr.unix_last_modified_stamp), /* archive's stamp */
  158.                     ctime(&hdr.unix_last_modified_stamp));
  159.                 printf ("Old Time: 0x%0.08X\nNew Time: 0x%0.08X\n",
  160.                     ahdr.unix_last_modified_stamp, /* archive's stamp */
  161.                     hdr.unix_last_modified_stamp);
  162. #else
  163.                 printf ("ADD %s\n", name);
  164. #endif
  165.             }
  166.             else
  167.                 add_one (fp, nafp, &hdr);
  168.         }
  169.         else /* cmp == 0 */
  170.         {                        /* copy old to new */
  171.             if (!noexec)
  172.             {
  173.                 fseek (oafp, old_header, SEEK_SET);
  174.                 copy_old_one (oafp, nafp, &ahdr);
  175.             }
  176.         }
  177.     }
  178.     else
  179.     {
  180.         if (!oafp || cmp > 0)        /* not in archive or dropped */
  181.         {
  182.             if (noexec)
  183.                 printf ("ADD %s\n", name);
  184.             else
  185.                 add_one (fp, nafp, &hdr);
  186.         }
  187.         else /* cmp == 0 */        /* replace */
  188.         {
  189.             if (noexec)
  190.                 printf ("REPLACE\n");
  191.             else
  192.                 add_one (fp, nafp, &hdr);
  193.         }
  194.     }
  195.  
  196.     if (!directory)
  197.     {
  198.         if (!noexec)
  199.             fclose (fp);
  200.     }
  201.     else
  202.         {                        /* recurcive call */
  203.         if (find_files (name, &filec, &filev))
  204.         {
  205.             for (i = 0; i < filec; i ++)
  206.                 oafp = append_it (filev[i], oafp, nafp);
  207.             free_files (filec, filev);
  208.         }
  209.     }
  210.     return oafp;
  211. }
  212.  
  213. static void
  214. find_update_files (oafp)
  215. FILE *oafp;                /* old archive */
  216. {
  217.     char name[FILENAME_LENGTH];
  218.     struct string_pool sp;
  219.     LzHeader hdr;
  220.     long pos;
  221.     STAT stbuf;
  222.     int len;
  223.  
  224.     pos = ftell (oafp);
  225.  
  226.     init_sp (&sp);
  227.     while (get_header (oafp, &hdr))
  228.     {
  229. #ifdef OSK
  230.         if ((hdr.unix_mode & OSK_DIRECTORY_PERM) != OSK_DIRECTORY_PERM)
  231. #else
  232.         if ((hdr.unix_mode & UNIX_FILE_TYPEMASK) == UNIX_FILE_REGULAR)
  233. #endif
  234.         {
  235.             if (stat (hdr.name, &stbuf) >= 0) /* exist ? */
  236.                 add_sp (&sp, hdr.name, strlen (hdr.name) + 1);
  237.         }
  238. #ifdef OSK
  239.         else if ((hdr.unix_mode & OSK_DIRECTORY_PERM) == OSK_DIRECTORY_PERM)
  240. #else
  241.         else if ((hdr.unix_mode & UNIX_FILE_TYPEMASK) == UNIX_FILE_DIRECTORY)
  242. #endif
  243.         {
  244.             strcpy (name, hdr.name);
  245.             len = strlen (name);
  246.             if (len > 0 && name[len - 1] == '/')
  247.                 name[--len] = '\0'; /* strip tail '/' */
  248.             if (stat (name, &stbuf) >= 0) /* exist ? */
  249.                 add_sp (&sp, name, len+1);
  250.         }
  251.         fseek (oafp, hdr.packed_size, SEEK_CUR);
  252.     }
  253.  
  254.     fseek (oafp, pos, SEEK_SET);
  255.  
  256.     finish_sp (&sp, &cmd_filec, &cmd_filev);
  257. }
  258.  
  259. static void
  260. delete (oafp, nafp)
  261. FILE *oafp, *nafp;
  262. {
  263.     LzHeader ahdr;
  264.     long old_header_pos;
  265.  
  266.     old_header_pos = ftell (oafp);
  267.     while (get_header (oafp, &ahdr))
  268.     {
  269.         if (need_file (ahdr.name))
  270.         {                        /* skip */
  271.             fseek (oafp, ahdr.packed_size, SEEK_CUR);
  272.             if (noexec)
  273.                 printf ("DELETE %s\n", ahdr.name);
  274.             else if (verbose)
  275.                 printf ("Delete %s\n", ahdr.name);
  276.         }
  277.         else
  278.             {                        /* copy */
  279.             if (noexec)
  280.             {
  281.                 fseek (oafp, ahdr.packed_size, SEEK_CUR);
  282.             }
  283.             else
  284.                 {
  285.                 fseek (oafp, old_header_pos, SEEK_SET);
  286.                 copy_old_one (oafp, nafp, &ahdr);
  287.             }
  288.         }
  289.         old_header_pos = ftell (oafp);
  290.     }
  291.     return;
  292. }
  293.  
  294.  
  295. /*----------------------------------------------------------------------*/
  296. /*                                                                      */
  297. /*----------------------------------------------------------------------*/
  298. static FILE *
  299. build_temporary_file ()
  300. {
  301.     int old_umask;
  302.     FILE *afp;
  303.  
  304.     build_temporary_name ();
  305.     signal (SIGINT, interrupt);
  306.     signal (SIGHUP, interrupt);
  307. #ifndef OSK
  308.     old_umask = umask (077);
  309. #endif
  310.     afp = xfopen (temporary_name, WRITE_BINARY);
  311.     remove_temporary_at_error = TRUE;
  312.     temporary_fp = afp;
  313. #ifndef OSK
  314.     umask (old_umask);
  315. #endif
  316.     return afp;
  317. }
  318.  
  319. static void
  320. build_backup_file ()
  321. {
  322.  
  323.     build_backup_name (backup_archive_name, archive_name);
  324.     if (!noexec)
  325.     {
  326.         signal (SIGINT, SIG_IGN);
  327.         signal (SIGHUP, SIG_IGN);
  328.         /* if old backup ".bak" archive exists, delete it first */
  329.         if (!access(backup_archive_name,0))
  330.             unlink(backup_archive_name);
  331.         if (rename (archive_name, backup_archive_name) < 0)
  332.             fatal_error (archive_name);
  333.         recover_archive_when_interrupt = TRUE;
  334.         signal (SIGINT, interrupt);
  335.         signal (SIGHUP, interrupt);
  336.     }
  337. }
  338.  
  339. static void
  340. report_archive_name_if_different ()
  341. {
  342.     if (!quiet && new_archive_name == new_archive_name_buffer)
  343.     {
  344.         /* warning at old archive is SFX */
  345.         printf ("New archive file is \"%s\"\n", new_archive_name);
  346.     }
  347. }
  348.  
  349. #ifdef TMP_FILENAME_TEMPLATE
  350. void
  351. temporary_to_new_archive_file (new_archive_size)
  352. long new_archive_size;
  353. {
  354.     FILE *oafp, *nafp;
  355.  
  356.     oafp = xfopen (temporary_name, READ_BINARY);
  357.     if (!strcmp(new_archive_name, "-"))
  358.     {
  359.         nafp = stdout;
  360.         writting_filename = "standard output";
  361.     }
  362.     else
  363.         {
  364.         nafp = xfopen (new_archive_name, WRITE_BINARY);
  365.         writting_filename = archive_name;
  366.     }
  367.     reading_filename = temporary_name;
  368.     copyfile (oafp, nafp, new_archive_size, 0);
  369.     if (nafp != stdout) fclose (nafp);
  370.     fclose (oafp);
  371.  
  372.     recover_archive_when_interrupt = FALSE;
  373.     unlink (temporary_name);
  374.  
  375.     remove_temporary_at_error = FALSE;
  376. }
  377. #else
  378. temporary_to_new_archive_file (new_archive_size)
  379. long new_archive_size;
  380. {
  381.     char *p;
  382.     p = (char *)rindex(new_archive_name,'/');
  383.     p = p ? p+1 : new_archive_name;
  384.     unlink ( new_archive_name );
  385.     if ( rename ( temporary_name , p )<0 ) {
  386.         fprintf(stderr, "Can't rename temporary_name '%s'\n", new_archive_name);
  387.         exit(1);
  388.     }
  389. }
  390. #endif
  391.  
  392. static void
  393. set_archive_file_mode ()
  394. {
  395.     int umask_value;
  396.     STAT stbuf;
  397. #ifndef OSK
  398.     if (archive_file_gid < 0)
  399.     {
  400.         umask (umask_value = umask (0));
  401.         archive_file_mode = (~umask_value) & 0666; /* rw-rw-rw- */
  402.         if (stat (".", &stbuf) >= 0)
  403.             archive_file_gid = stbuf.st_gid;
  404.     }
  405.     if (archive_file_gid >= 0)
  406.         chown (new_archive_name, getuid (), archive_file_gid);
  407.  
  408.     chmod (new_archive_name, archive_file_mode);
  409. #endif
  410. }
  411.  
  412.  
  413. /*----------------------------------------------------------------------*/
  414. /*                REMOVE FILE/DIRECTORY                                 */
  415. /*----------------------------------------------------------------------*/
  416.  
  417. static void remove_files ();
  418.  
  419. static void
  420. remove_one (name)
  421. char *name;
  422. {
  423.     STAT stbuf;
  424.     int filec;
  425.     char **filev;
  426.  
  427.     if (stat (name, &stbuf) < 0)
  428.     {
  429.         warning ("Cannot access", name);
  430.     }
  431.     else if (is_directory (&stbuf))
  432.     {
  433.         if (find_files (name, &filec, &filev))
  434.         {
  435.             remove_files (filec, filev);
  436.             free_files (filec, filev);
  437.         }
  438.         else
  439.             warning ("Cannot open directory", name);
  440.  
  441.         if (noexec)
  442.             printf ("REMOVE DIRECTORY %s\n", name);
  443. #ifndef OSK
  444.         else if (rmdir (name) < 0)
  445.             warning ("Cannot remove directory", name);
  446.         else if (verbose)
  447.             printf ("Removed %s.\n", name);
  448. #endif /* OSK */
  449.     }
  450.     else if (is_regularfile (&stbuf))
  451.     {
  452.         if (noexec)
  453.             printf ("REMOVE FILE %s.\n", name);
  454.         else if (unlink (name) < 0)
  455.             warning ("Cannot remove", name);
  456.         else if (verbose)
  457.             printf ("Removed %s.\n", name);
  458.     }
  459.     else
  460.         {
  461.         error ("Cannot remove (not a file or directory)", name);
  462.     }
  463. }
  464.  
  465. static void
  466. remove_files (filec, filev)
  467. int filec;
  468. char **filev;
  469. {
  470.     int i;
  471.  
  472.     for (i = 0; i < filec; i++)
  473.         remove_one (filev[i]);
  474. }
  475.  
  476.  
  477. /*----------------------------------------------------------------------*/
  478. /*                                                                      */
  479. /*----------------------------------------------------------------------*/
  480.  
  481. void
  482. cmd_add ()
  483. {
  484.     LzHeader ahdr;
  485.     FILE *oafp, *nafp;
  486.     int i;
  487.     long old_header;
  488.     boolean old_archive_exist;
  489.     long new_archive_size;
  490.  
  491.     /* exit if no operation */
  492.     if (!update_if_newer && cmd_filec == 0)
  493.     {
  494.         error ("No files given in argument, do nothing.", "");
  495.         return;
  496.     }
  497.  
  498.     /* open old archive if exist */
  499.     if ((oafp = open_old_archive ()) == NULL)
  500.         old_archive_exist = FALSE;
  501.     else
  502.         old_archive_exist = TRUE;
  503.  
  504.     if (update_if_newer && cmd_filec == 0 && !oafp)
  505.         fatal_error (archive_name); /* exit if cannot execute automatic update */
  506.     errno = 0;
  507.  
  508.     if (new_archive && old_archive_exist)
  509.     {
  510.         fclose (oafp);
  511.         oafp = NULL;
  512.     }
  513.  
  514.     if (oafp && archive_is_msdos_sfx1 (archive_name))
  515.     {
  516.         skip_msdos_sfx1_code (oafp);
  517.         build_standard_archive_name (new_archive_name_buffer, archive_name);
  518.         new_archive_name = new_archive_name_buffer;
  519.     }
  520.     else
  521.         {
  522.         new_archive_name = archive_name;
  523.     }
  524.  
  525.     /* build temporary file */
  526.     if (!noexec)
  527.         nafp = build_temporary_file ();
  528.  
  529.     /* find needed files when automatic update */
  530.     if (update_if_newer && cmd_filec == 0)
  531.         find_update_files (oafp);
  532.  
  533.     /* build new archive file */
  534.     /* cleaning arguments */
  535.     cleaning_files (&cmd_filec, &cmd_filev);
  536.     if (cmd_filec == 0)
  537.     {
  538.         if (oafp)
  539.             fclose (oafp);
  540.         if  (!noexec)
  541.             fclose (nafp);
  542.         /* added unlink to get rid of temp file */
  543.         unlink (temporary_name);
  544.  
  545.         return;
  546.     }
  547.  
  548.     for (i = 0; i < cmd_filec; i ++)
  549.         oafp = append_it (cmd_filev[i], oafp, nafp);
  550.     if (oafp)
  551.     {
  552.         old_header = ftell (oafp);
  553.         while (get_header (oafp, &ahdr))
  554.         {
  555.             if (noexec)
  556.                 fseek (oafp, ahdr.packed_size, SEEK_CUR);
  557.             else
  558.                 {
  559.                 fseek (oafp, old_header, SEEK_SET);
  560.                 copy_old_one (oafp, nafp, &ahdr);
  561.             }
  562.             old_header = ftell (oafp);
  563.         }
  564.         fclose (oafp);
  565.     }
  566.     if (!noexec)
  567.     {
  568.         write_archive_tail (nafp);
  569.         new_archive_size = ftell (nafp);
  570.         fclose (nafp);
  571.     }
  572.  
  573.     /* build backup archive file */
  574.     if (old_archive_exist)
  575.         build_backup_file ();
  576.  
  577.     report_archive_name_if_different ();
  578.  
  579.     /* copy temporary file to new archive file */
  580.     if (!noexec && (!strcmp(new_archive_name, "-") ||
  581.         rename (temporary_name, new_archive_name) < 0))
  582.         temporary_to_new_archive_file (new_archive_size);
  583.  
  584.     /* set new archive file mode/group */
  585.     set_archive_file_mode ();
  586.  
  587.     /* remove archived files */
  588.     if (delete_after_append)
  589.         remove_files (cmd_filec, cmd_filev);
  590.  
  591.     return;
  592. }
  593.  
  594.  
  595. void
  596. cmd_delete ()
  597. {
  598.     FILE *oafp, *nafp;
  599.     long new_archive_size;
  600.  
  601.     /* open old archive if exist */
  602.     if ((oafp = open_old_archive ()) == NULL)
  603.         fatal_error (archive_name);
  604.     errno = 0;
  605.  
  606.     /* exit if no operation */
  607.     if (cmd_filec == 0)
  608.     {
  609.         fclose (oafp);
  610.         warning ("No files given in argument, do nothing.", "");
  611.         return;
  612.     }
  613.  
  614.     if (archive_is_msdos_sfx1 (archive_name))
  615.     {
  616.         skip_msdos_sfx1_code (oafp);
  617.         build_standard_archive_name (new_archive_name_buffer, archive_name);
  618.         new_archive_name = new_archive_name_buffer;
  619.     }
  620.     else
  621.         {
  622.         new_archive_name = archive_name;
  623.     }
  624.  
  625.     /* build temporary file */
  626.     if (!noexec)
  627.         nafp = build_temporary_file ();
  628.  
  629.     /* build new archive file */
  630.     delete (oafp, nafp);
  631.     fclose (oafp);
  632.  
  633.     if (!noexec)
  634.     {
  635.         write_archive_tail (nafp);
  636.         new_archive_size = ftell (nafp);
  637.         fclose (nafp);
  638.     }
  639.  
  640.     /* build backup archive file */
  641.     build_backup_file ();
  642.  
  643.     report_archive_name_if_different ();
  644.  
  645.     /* copy temporary file to new archive file */
  646.     if (!noexec && rename (temporary_name, new_archive_name) < 0)
  647.         temporary_to_new_archive_file (new_archive_size);
  648.  
  649.     /* set new archive file mode/group */
  650.     set_archive_file_mode ();
  651.  
  652.     return;
  653. }
  654.