home *** CD-ROM | disk | FTP | other *** search
/ Amiga MA Magazine 1998 #3 / amigamamagazinepolishissue1998.iso / ppc / lha_ppc / orig_src / lhadd.c < prev    next >
C/C++ Source or Header  |  1992-05-08  |  14KB  |  624 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.       if (rename (archive_name, backup_archive_name) < 0)
  308.         fatal_error (archive_name);
  309.       recover_archive_when_interrupt = TRUE;
  310.       signal (SIGINT, interrupt);
  311.       signal (SIGHUP, interrupt);
  312.     }
  313. }
  314.  
  315. static void
  316. report_archive_name_if_different ()
  317. {
  318.   if (!quiet && new_archive_name == new_archive_name_buffer)
  319.     {
  320.       /* warning at old archive is SFX */
  321.       printf ("New archive file is \"%s\"\n", new_archive_name);
  322.     }
  323. }
  324.  
  325. #ifdef TMP_FILENAME_TEMPLATE
  326. void
  327. temporary_to_new_archive_file (new_archive_size)
  328.      long new_archive_size;
  329. {
  330.   FILE *oafp, *nafp;
  331.  
  332.   oafp = xfopen (temporary_name, READ_BINARY);
  333.   if (!strcmp(new_archive_name, "-"))
  334.     {
  335.       nafp = stdout;
  336.       writting_filename = "starndard output";
  337.     }
  338.   else
  339.     {
  340.       nafp = xfopen (new_archive_name, WRITE_BINARY);
  341.       writting_filename = archive_name;
  342.     }
  343.   reading_filename = temporary_name;
  344.   copyfile (oafp, nafp, new_archive_size, 0);
  345.   if (nafp != stdout) fclose (nafp);
  346.   fclose (oafp);
  347.  
  348.   recover_archive_when_interrupt = FALSE;
  349.   unlink (temporary_name);
  350.  
  351.   remove_temporary_at_error = FALSE;
  352. }
  353. #else
  354. temporary_to_new_archive_file (new_archive_size)
  355. long new_archive_size;
  356. {
  357.   char *p;
  358.   p = (char *)rindex(new_archive_name,'/');
  359.   p = p ? p+1 : new_archive_name;
  360.   unlink ( new_archive_name );
  361.   if ( rename ( temporary_name , p )<0 ) {
  362.     fprintf(stderr, "Can't rename temporary_name '%s'\n", new_archive_name);
  363.     exit(1);
  364.   }
  365. }
  366. #endif
  367.  
  368. static void
  369. set_archive_file_mode ()
  370. {
  371.   int umask_value;
  372.   struct stat stbuf;
  373.  
  374.   if (archive_file_gid < 0)
  375.     {
  376.       umask (umask_value = umask (0));
  377.       archive_file_mode = (~umask_value) & 0666; /* rw-rw-rw- */
  378.       if (stat (".", &stbuf) >= 0)
  379.     archive_file_gid = stbuf.st_gid;
  380.     }
  381.   if (archive_file_gid >= 0)
  382.     chown (new_archive_name, getuid (), archive_file_gid);
  383.  
  384.   chmod (new_archive_name, archive_file_mode);
  385. }
  386.  
  387.  
  388. /*----------------------------------------------------------------------*/
  389. /*        REMOVE FILE/DIRECTORY                    */
  390. /*----------------------------------------------------------------------*/
  391.  
  392. static void remove_files ();
  393.  
  394. static void
  395. remove_one (name)
  396.      char *name;
  397. {
  398.   struct stat stbuf;
  399.   int filec;
  400.   char **filev;
  401.  
  402.   if (stat (name, &stbuf) < 0)
  403.     {
  404.       warning ("Cannot access", name);
  405.     }
  406.   else if (is_directory (&stbuf))
  407.     {
  408.       if (find_files (name, &filec, &filev))
  409.     {
  410.       remove_files (filec, filev);
  411.       free_files (filec, filev);
  412.     }
  413.       else
  414.     warning ("Cannot open directory", name);
  415.  
  416.       if (noexec)
  417.     printf ("REMOVE DIRECTORY %s\n", name);
  418.       else if (rmdir (name) < 0)
  419.     warning ("Cannot remove directory", name);
  420.       else if (verbose)
  421.     printf ("Removed %s.\n", name);
  422.     }
  423.   else if (is_regularfile (&stbuf))
  424.     {
  425.       if (noexec)
  426.     printf ("REMOVE FILE %s.\n", name);
  427.       else if (unlink (name) < 0)
  428.     warning ("Cannot remove", name);
  429.       else if (verbose)
  430.     printf ("Removed %s.\n", name);
  431.     }
  432.   else
  433.     {
  434.       error ("Cannot remove (not a file or directory)", name);
  435.     }
  436. }
  437.  
  438. static void
  439. remove_files (filec, filev)
  440.      int filec;
  441.      char **filev;
  442. {
  443.   int i;
  444.  
  445.   for (i = 0; i < filec; i++)
  446.     remove_one (filev[i]);
  447. }
  448.  
  449.  
  450. /*----------------------------------------------------------------------*/
  451. /*                                    */
  452. /*----------------------------------------------------------------------*/
  453.  
  454. void
  455. cmd_add ()
  456. {
  457.   LzHeader ahdr;
  458.   FILE *oafp, *nafp;
  459.   int i;
  460.   long old_header;
  461.   boolean old_archive_exist;
  462.   long new_archive_size;
  463.  
  464.   /* exit if no operation */
  465.   if (!update_if_newer && cmd_filec == 0)
  466.     {
  467.       error ("No files given in argument, do nothing.", "");
  468.       return;
  469.     }
  470.  
  471.   /* open old archive if exist */
  472.   if ((oafp = open_old_archive ()) == NULL)
  473.     old_archive_exist = FALSE;
  474.   else
  475.     old_archive_exist = TRUE;
  476.  
  477.   if (update_if_newer && cmd_filec == 0 && !oafp)
  478.     fatal_error (archive_name); /* exit if cannot execute automatic update */
  479.   errno = 0;
  480.  
  481.   if (new_archive && old_archive_exist)
  482.     {
  483.       fclose (oafp);
  484.       oafp = NULL;
  485.     }
  486.  
  487.   if (oafp && archive_is_msdos_sfx1 (archive_name))
  488.     {
  489.       skip_msdos_sfx1_code (oafp);
  490.       build_standard_archive_name (new_archive_name_buffer, archive_name);
  491.       new_archive_name = new_archive_name_buffer;
  492.     }
  493.   else
  494.     {
  495.       new_archive_name = archive_name;
  496.     }
  497.  
  498.   /* build temporary file */
  499.   if (!noexec)
  500.     nafp = build_temporary_file ();
  501.  
  502.   /* find needed files when automatic update */
  503.   if (update_if_newer && cmd_filec == 0)
  504.     find_update_files (oafp);
  505.  
  506.   /* build new archive file */
  507.   /* cleaning arguments */
  508.   cleaning_files (&cmd_filec, &cmd_filev);
  509.   if (cmd_filec == 0)
  510.     {
  511.       if (oafp)
  512.     fclose (oafp);
  513.       if  (!noexec)
  514.     fclose (nafp);
  515.       return;
  516.     }
  517.  
  518.   for (i = 0; i < cmd_filec; i ++)
  519.     oafp = append_it (cmd_filev[i], oafp, nafp);
  520.   if (oafp)
  521.     {
  522.       old_header = ftell (oafp);
  523.       while (get_header (oafp, &ahdr))
  524.     {
  525.       if (noexec)
  526.         fseek (oafp, ahdr.packed_size, SEEK_CUR);
  527.       else
  528.         {
  529.           fseek (oafp, old_header, SEEK_SET);
  530.           copy_old_one (oafp, nafp, &ahdr);
  531.         }
  532.       old_header = ftell (oafp);
  533.     }
  534.       fclose (oafp);
  535.     }
  536.   if (!noexec)
  537.     {
  538.       write_archive_tail (nafp);
  539.       new_archive_size = ftell (nafp);
  540.       fclose (nafp);
  541.     }
  542.  
  543.   /* build backup archive file */
  544.   if (old_archive_exist)
  545.     build_backup_file ();
  546.  
  547.   report_archive_name_if_different ();
  548.  
  549.   /* copy temporary file to new archive file */
  550.   if (!noexec && (!strcmp(new_archive_name, "-") ||
  551.           rename (temporary_name, new_archive_name) < 0))
  552.     temporary_to_new_archive_file (new_archive_size);
  553.  
  554.   /* set new archive file mode/group */
  555.   set_archive_file_mode ();
  556.  
  557.   /* remove archived files */
  558.   if (delete_after_append)
  559.     remove_files (cmd_filec, cmd_filev);
  560.  
  561.   return;
  562. }
  563.  
  564.  
  565. void
  566. cmd_delete ()
  567. {
  568.   FILE *oafp, *nafp;
  569.   long new_archive_size;
  570.  
  571.   /* open old archive if exist */
  572.   if ((oafp = open_old_archive ()) == NULL)
  573.     fatal_error (archive_name);
  574.   errno = 0;
  575.  
  576.   /* exit if no operation */
  577.   if (cmd_filec == 0)
  578.     {
  579.       fclose (oafp);
  580.       warning ("No files given in argument, do nothing.", "");
  581.       return;
  582.     }
  583.  
  584.   if (archive_is_msdos_sfx1 (archive_name))
  585.     {
  586.       skip_msdos_sfx1_code (oafp);
  587.       build_standard_archive_name (new_archive_name_buffer, archive_name);
  588.       new_archive_name = new_archive_name_buffer;
  589.     }
  590.   else
  591.     {
  592.       new_archive_name = archive_name;
  593.     }
  594.  
  595.   /* build temporary file */
  596.   if (!noexec)
  597.     nafp = build_temporary_file ();
  598.  
  599.   /* build new archive file */
  600.   delete (oafp, nafp);
  601.   fclose (oafp);
  602.  
  603.   if (!noexec)
  604.     {
  605.       write_archive_tail (nafp);
  606.       new_archive_size = ftell (nafp);
  607.       fclose (nafp);
  608.     }
  609.  
  610.   /* build backup archive file */
  611.   build_backup_file ();
  612.  
  613.   report_archive_name_if_different ();
  614.  
  615.   /* copy temporary file to new archive file */
  616.   if (!noexec && rename (temporary_name, new_archive_name) < 0)
  617.     temporary_to_new_archive_file (new_archive_size);
  618.  
  619.   /* set new archive file mode/group */
  620.   set_archive_file_mode ();
  621.  
  622.   return;
  623. }
  624.