home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 9 Archive / 09-Archive.zip / lha100bt.zip / lha-1.00 / src / lhadd.c < prev    next >
C/C++ Source or Header  |  1994-09-01  |  15KB  |  653 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.   struct 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.     {
  148.       if (!oafp ||        /* not in archive */
  149.       cmp > 0 ||        /* // */
  150.       ahdr.unix_last_modified_stamp < /* newer than archive's */
  151.       hdr.unix_last_modified_stamp)
  152.     {
  153.       if (noexec)
  154.         printf ("ADD %s\n", name);
  155.       else
  156.         add_one (fp, nafp, &hdr);
  157.     }
  158.       else /* cmp == 0 */
  159.     {            /* copy old to new */
  160.       if (!noexec)
  161.         {
  162.           fseek (oafp, old_header, SEEK_SET);
  163.           copy_old_one (oafp, nafp, &ahdr);
  164.         }
  165.     }
  166.     }
  167.   else
  168.     {
  169.       if (!oafp || cmp > 0)    /* not in archive or dropped */
  170.     {
  171.       if (noexec)
  172.         printf ("ADD %s\n", name);
  173.       else
  174.         add_one (fp, nafp, &hdr);
  175.     }
  176.       else /* cmp == 0 */    /* replace */
  177.     {
  178.       if (noexec)
  179.         printf ("REPLACE\n");
  180.       else
  181.         add_one (fp, nafp, &hdr);
  182.     }
  183.     }
  184.  
  185.   if (!directory)
  186.     {
  187.       if (!noexec)
  188.     fclose (fp);
  189.     }
  190.   else
  191.     {            /* recurcive call */
  192.       if (find_files (name, &filec, &filev))
  193.     {
  194.       for (i = 0; i < filec; i ++)
  195.         oafp = append_it (filev[i], oafp, nafp);
  196.       free_files (filec, filev);
  197.     }
  198.     }
  199.   return oafp;
  200. }
  201.  
  202. static void
  203. find_update_files (oafp)
  204.      FILE *oafp;        /* old archive */
  205. {
  206.   char name[FILENAME_LENGTH];
  207.   struct string_pool sp;
  208.   LzHeader hdr;
  209.   long pos;
  210.   struct stat stbuf;
  211.   int len;
  212.  
  213.   pos = ftell (oafp);
  214.  
  215.   init_sp (&sp);
  216.   while (get_header (oafp, &hdr))
  217.     {
  218.       if ((hdr.unix_mode & UNIX_FILE_TYPEMASK) == UNIX_FILE_REGULAR)
  219.     {
  220.       if (stat (hdr.name, &stbuf) >= 0) /* exist ? */
  221.         add_sp (&sp, hdr.name, strlen (hdr.name) + 1);
  222.     }
  223.       else if ((hdr.unix_mode & UNIX_FILE_TYPEMASK) == UNIX_FILE_DIRECTORY)
  224.     {
  225.       strcpy (name, hdr.name);
  226.       len = strlen (name);
  227.       if (len > 0 && name[len - 1] == '/')
  228.         name[--len] = '\0'; /* strip tail '/' */
  229.       if (stat (name, &stbuf) >= 0) /* exist ? */
  230.         add_sp (&sp, name, len+1);
  231.     }
  232.       fseek (oafp, hdr.packed_size, SEEK_CUR);
  233.     }
  234.  
  235.   fseek (oafp, pos, SEEK_SET);
  236.  
  237.   finish_sp (&sp, &cmd_filec, &cmd_filev);
  238. }
  239.  
  240. static void
  241. delete (oafp, nafp)
  242.      FILE *oafp, *nafp;
  243. {
  244.   LzHeader ahdr;
  245.   long old_header_pos;
  246.  
  247.   old_header_pos = ftell (oafp);
  248.   while (get_header (oafp, &ahdr))
  249.     {
  250.       if (need_file (ahdr.name))
  251.     {            /* skip */
  252.       fseek (oafp, ahdr.packed_size, SEEK_CUR);
  253.       if (noexec)
  254.         printf ("DELETE %s\n", ahdr.name);
  255.       else if (verbose)
  256.         printf ("Delete %s\n", ahdr.name);
  257.     }
  258.       else
  259.     {            /* copy */
  260.       if (noexec)
  261.         {
  262.           fseek (oafp, ahdr.packed_size, SEEK_CUR);
  263.         }
  264.       else
  265.         {
  266.           fseek (oafp, old_header_pos, SEEK_SET);
  267.           copy_old_one (oafp, nafp, &ahdr);
  268.         }
  269.     }
  270.       old_header_pos = ftell (oafp);
  271.     }
  272.   return;
  273. }
  274.  
  275.  
  276. /*----------------------------------------------------------------------*/
  277. /*                                    */
  278. /*----------------------------------------------------------------------*/
  279. static FILE *
  280. build_temporary_file ()
  281. {
  282.   int old_umask;
  283.   FILE *afp;
  284.  
  285.   build_temporary_name ();
  286.   signal (SIGINT, interrupt);
  287.   signal (SIGHUP, interrupt);
  288.  
  289.   old_umask = umask (077);
  290.   afp = xfopen (temporary_name, WRITE_BINARY);
  291.   remove_temporary_at_error = TRUE;
  292.   temporary_fp = afp;
  293.   umask (old_umask);
  294.  
  295.   return afp;
  296. }
  297.  
  298. static void
  299. build_backup_file ()
  300. {
  301.   
  302.   build_backup_name (backup_archive_name, archive_name);
  303.   if (!noexec)
  304.     {
  305.       signal (SIGINT, SIG_IGN);
  306.       signal (SIGHUP, SIG_IGN);
  307.       
  308.       if (rename (archive_name, backup_archive_name) < 0)
  309.       { 
  310.        unlink(backup_archive_name);
  311.        if (rename (archive_name, backup_archive_name) < 0)
  312.        { 
  313.       
  314.         fatal_error("Could not create backup archive !");
  315.         }
  316.       }    
  317.       recover_archive_when_interrupt = TRUE;
  318.       signal (SIGINT, interrupt);
  319.       signal (SIGHUP, interrupt);
  320.     }
  321. }
  322.  
  323. static void
  324. report_archive_name_if_different ()
  325. {
  326.   if (!quiet && new_archive_name == new_archive_name_buffer)
  327.     {
  328.       /* warning at old archive is SFX */
  329.       printf ("New archive file is \"%s\"\n", new_archive_name);
  330.     }
  331. }
  332.  
  333. #ifdef TMP_FILENAME_TEMPLATE
  334. void
  335. temporary_to_new_archive_file (new_archive_size)
  336.      long new_archive_size;
  337. {
  338.   FILE *oafp, *nafp;
  339.  
  340.   oafp = xfopen (temporary_name, READ_BINARY);
  341.   if (!strcmp(new_archive_name, "-"))
  342.     {
  343.       nafp = stdout;
  344.       writting_filename = "starndard output";
  345.     }
  346.   else
  347.     {
  348.       nafp = xfopen (new_archive_name, WRITE_BINARY);
  349.       writting_filename = archive_name;
  350.     }
  351.   reading_filename = temporary_name;
  352.   copyfile (oafp, nafp, new_archive_size, 0);
  353.   if (nafp != stdout) fclose (nafp);
  354.   fclose (oafp);
  355.  
  356.   recover_archive_when_interrupt = FALSE;
  357.   unlink (temporary_name);
  358.  
  359.   remove_temporary_at_error = FALSE;
  360. }
  361. #else
  362. temporary_to_new_archive_file (new_archive_size)
  363. long new_archive_size;
  364. {
  365.   char *p;
  366.   p = (char *)rindex(new_archive_name,'/');
  367.   p = p ? p+1 : new_archive_name;
  368.   unlink ( new_archive_name );
  369.   if ( rename ( temporary_name , p )<0 ) {
  370.     fprintf(stderr, "Can't rename temporary_name '%s'\n", new_archive_name);
  371.     exit(1);
  372.   }
  373. }
  374. #endif
  375.  
  376. static void
  377. set_archive_file_mode ()
  378. {
  379.   int umask_value;
  380.   struct stat stbuf;
  381.  
  382.   if (archive_file_gid < 0)
  383.     {
  384.       umask (umask_value = umask (0));
  385.       archive_file_mode = (~umask_value) & 0666; /* rw-rw-rw- */
  386.       if (stat (".", &stbuf) >= 0)
  387.     archive_file_gid = stbuf.st_gid;
  388.     }
  389.   /*if (archive_file_gid >= 0)
  390.     chown (new_archive_name, getuid (), archive_file_gid);
  391.     */
  392.   chmod (new_archive_name, archive_file_mode);
  393. }
  394.  
  395.  
  396. /*----------------------------------------------------------------------*/
  397. /*        REMOVE FILE/DIRECTORY                    */
  398. /*----------------------------------------------------------------------*/
  399.  
  400. static void remove_files ();
  401.  
  402. static void
  403. remove_one (name)
  404.      char *name;
  405. {
  406.   struct stat stbuf;
  407.   int filec;
  408.   char **filev;
  409.  
  410.   if (stat (name, &stbuf) < 0)
  411.     {
  412.       warning ("Cannot access", name);
  413.     }
  414.   else if (is_directory (&stbuf))
  415.     {
  416.       if (find_files (name, &filec, &filev))
  417.     {
  418.       remove_files (filec, filev);
  419.       free_files (filec, filev);
  420.     }
  421.       else
  422.     warning ("Cannot open directory", name);
  423.  
  424.       if (noexec)
  425.     printf ("REMOVE DIRECTORY %s\n", name);
  426.       else if (rmdir (name) < 0)
  427.     warning ("Cannot remove directory", name);
  428.       else if (verbose)
  429.     printf ("Removed %s.\n", name);
  430.     }
  431.   else if (is_regularfile (&stbuf))
  432.     {
  433.       if (noexec)
  434.     printf ("REMOVE FILE %s.\n", name);
  435.       else if (unlink (name) < 0)
  436.     warning ("Cannot remove", name);
  437.       else if (verbose)
  438.     printf ("Removed %s.\n", name);
  439.     }
  440.   else
  441.     {
  442.       error ("Cannot remove (not a file or directory)", name);
  443.     }
  444. }
  445.  
  446. static void
  447. remove_files (filec, filev)
  448.      int filec;
  449.      char **filev;
  450. {
  451.   int i;
  452.  
  453.   for (i = 0; i < filec; i++)
  454.     remove_one (filev[i]);
  455. }
  456.  
  457.  
  458. /*----------------------------------------------------------------------*/
  459. /*                                    */
  460. /*----------------------------------------------------------------------*/
  461.  
  462. void
  463. cmd_add ()
  464. {
  465.   LzHeader ahdr;
  466.   FILE *oafp, *nafp;
  467.   int i;
  468.   long old_header;
  469.   boolean old_archive_exist;
  470.   long new_archive_size;
  471.  
  472.   /* exit if no operation */
  473.   if (!update_if_newer && cmd_filec == 0)
  474.     {
  475.       error ("No files given in argument, do nothing.", "");
  476.       return;
  477.     }
  478.  
  479.   /* open old archive if exist */
  480.   if ((oafp = open_old_archive ()) == NULL)
  481.     old_archive_exist = FALSE;
  482.   else
  483.     old_archive_exist = TRUE;
  484.  
  485.   if (update_if_newer && cmd_filec == 0 && !oafp)
  486.     fatal_error (archive_name); /* exit if cannot execute automatic update */
  487.   errno = 0;
  488.  
  489.   if (new_archive && old_archive_exist)
  490.     {
  491.       fclose (oafp);
  492.       oafp = NULL;
  493.     }
  494.  
  495.   if (oafp && archive_is_msdos_sfx1 (archive_name))
  496.     {
  497.       skip_msdos_sfx1_code (oafp);
  498.       build_standard_archive_name (new_archive_name_buffer, archive_name);
  499.       new_archive_name = new_archive_name_buffer;
  500.     }
  501.   else
  502.     {
  503.     /**************************************************
  504.      Modified 31-8-1994 by Enrico Demarin
  505.     ***************************************************/
  506.     
  507.       if (!strchr(archive_name,'.'))
  508.       { 
  509.        strcpy(new_archive_name_buffer,archive_name);
  510.        strcat(new_archive_name_buffer,ARCHIVENAME_EXTENTION);
  511.        new_archive_name = new_archive_name_buffer;
  512.        } else 
  513.        
  514.     /**************************************************/
  515.     
  516.       new_archive_name = archive_name;
  517.     }
  518.  
  519.   /* build temporary file */
  520.   if (!noexec)
  521.     nafp = build_temporary_file ();
  522.  
  523.   /* find needed files when automatic update */
  524.   if (update_if_newer && cmd_filec == 0)
  525.     find_update_files (oafp);
  526.  
  527.   /* build new archive file */
  528.   /* cleaning arguments */
  529.   cleaning_files (&cmd_filec, &cmd_filev);
  530.   if (cmd_filec == 0)
  531.     {
  532.       if (oafp)
  533.     fclose (oafp);
  534.       if  (!noexec)
  535.     fclose (nafp);
  536.       return;
  537.     }
  538.  
  539.   for (i = 0; i < cmd_filec; i ++)
  540.     oafp = append_it (cmd_filev[i], oafp, nafp);
  541.   if (oafp)
  542.     {
  543.       old_header = ftell (oafp);
  544.       while (get_header (oafp, &ahdr))
  545.     {
  546.       if (noexec)
  547.         fseek (oafp, ahdr.packed_size, SEEK_CUR);
  548.       else
  549.         {
  550.           fseek (oafp, old_header, SEEK_SET);
  551.           copy_old_one (oafp, nafp, &ahdr);
  552.         }
  553.       old_header = ftell (oafp);
  554.     }
  555.       fclose (oafp);
  556.     }
  557.   if (!noexec)
  558.     {
  559.       write_archive_tail (nafp);
  560.       new_archive_size = ftell (nafp);
  561.       fclose (nafp);
  562.     }
  563.  
  564.   
  565.   /* build backup archive file */
  566.   if (old_archive_exist)
  567.   if (!make_backups)  unlink(archive_name);
  568.   else
  569.   {
  570.    build_backup_file ();
  571.   }
  572.    report_archive_name_if_different ();
  573.  
  574.   /* copy temporary file to new archive file */
  575.   if (!noexec && (!strcmp(new_archive_name, "-") ||
  576.           rename (temporary_name, new_archive_name) < 0))
  577.     temporary_to_new_archive_file (new_archive_size);
  578.  
  579.   /* set new archive file mode/group */
  580.   set_archive_file_mode ();
  581.  
  582.   /* remove archived files */
  583.   if (delete_after_append)
  584.     remove_files (cmd_filec, cmd_filev);
  585.  
  586.   return;
  587. }
  588.  
  589.  
  590. void
  591. cmd_delete ()
  592. {
  593.   FILE *oafp, *nafp;
  594.   long new_archive_size;
  595.  
  596.   /* open old archive if exist */
  597.   if ((oafp = open_old_archive ()) == NULL)
  598.     fatal_error (archive_name);
  599.   errno = 0;
  600.  
  601.   /* exit if no operation */
  602.   if (cmd_filec == 0)
  603.     {
  604.       fclose (oafp);
  605.       warning ("No files given in argument, do nothing.", "");
  606.       return;
  607.     }
  608.  
  609.   if (archive_is_msdos_sfx1 (archive_name))
  610.     {
  611.       skip_msdos_sfx1_code (oafp);
  612.       build_standard_archive_name (new_archive_name_buffer, archive_name);
  613.       new_archive_name = new_archive_name_buffer;
  614.     }
  615.   else
  616.     {  
  617.         new_archive_name = archive_name;
  618.     }
  619.  
  620.   /* build temporary file */
  621.   if (!noexec)
  622.     nafp = build_temporary_file ();
  623.  
  624.   /* build new archive file */
  625.   delete (oafp, nafp);
  626.   fclose (oafp);
  627.  
  628.   if (!noexec)
  629.     {
  630.       write_archive_tail (nafp);
  631.       new_archive_size = ftell (nafp);
  632.       fclose (nafp);
  633.     }
  634.  
  635.   /* build backup archive file */
  636.   if (!make_backups)  unlink(archive_name);
  637.   else
  638.   {
  639.    build_backup_file ();
  640.   }
  641.   
  642.   report_archive_name_if_different ();
  643.  
  644.   /* copy temporary file to new archive file */
  645.   if (!noexec && rename (temporary_name, new_archive_name) < 0)
  646.     temporary_to_new_archive_file (new_archive_size);
  647.  
  648.   /* set new archive file mode/group */
  649.   set_archive_file_mode ();
  650.  
  651.   return;
  652. }
  653.