home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 9 Archive / 09-Archive.zip / lha100bt.zip / lha-1.00 / src / lhext.c < prev    next >
C/C++ Source or Header  |  1994-08-31  |  7KB  |  352 lines

  1. /*----------------------------------------------------------------------*/
  2. /*            LHarc Extract 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. /*  V0.03  LHa for UNIX                1991.12.17  M.Oki    */
  10. /*----------------------------------------------------------------------*/
  11.  
  12. #include "lharc.h"
  13.  
  14. extern int decode_lzhuf ();
  15.  
  16. static boolean
  17. inquire_extract (name)
  18. char *name;
  19. {
  20.   struct stat stbuf;
  21.  
  22.   if (stat (name, &stbuf) >= 0)
  23.     {
  24.       if (!is_regularfile (&stbuf))
  25.     {
  26.       error ("Already exist (not a file)", name);
  27.       return FALSE;
  28.     }
  29.  
  30.       if (noexec)
  31.     {
  32.       printf ("EXTRACT %s but file is exist.\n", name);
  33.       return FALSE;
  34.     }
  35.       else if (!force)
  36.     {
  37.       if (!isatty(0)) return FALSE;
  38.       switch (inquire ("OverWrite ?(Yes/No/All)", name, "YyNnAa"))
  39.         {
  40.         case 0:
  41.         case 1:        /* Y/y */
  42.           break;
  43.         case 2:
  44.         case 3:        /* N/n */
  45.           return FALSE;
  46.         case 4:
  47.         case 5:        /* A/a */
  48.           force = TRUE;
  49.           break;
  50.         }
  51.     }
  52.     }
  53.  
  54.   if (noexec)
  55.     printf ("EXTRACT %s\n", name);
  56.  
  57.   return TRUE;
  58. }
  59.  
  60. static boolean
  61. make_parent_path (name)
  62. char *name;
  63. {
  64.   char path[FILENAME_LENGTH];
  65.   struct stat stbuf;
  66.   register char *p;
  67.  
  68.   /* make parent directory name into PATH for recursive call */
  69.   strcpy (path, name);
  70.   for (p = path + strlen (path); p > path; p--)
  71.     if (p[-1] == '/')
  72.       {
  73.     *--p = '\0';
  74.     break;
  75.       }
  76.  
  77.   if (p == path)
  78.     {
  79.       message ("Why?", "ROOT");
  80.       return FALSE;            /* no more parent. */
  81.     }
  82.  
  83.   if (stat (path, &stbuf) >= 0)
  84.     {
  85.       if (is_directory (&stbuf))
  86.     return TRUE;
  87.       error ("Not a directory", path);
  88.       return FALSE;
  89.     }
  90.   errno = 0;
  91.  
  92.   if (verbose)
  93.     printf ("Making directory \"%s\".", path);
  94.  
  95.   if (mkdir (path, 0777) >= 0)/* try */
  96.     return TRUE;            /* successful done. */
  97.   errno = 0;
  98.  
  99.   if (!make_parent_path (path))
  100.     return FALSE;
  101.  
  102.   if (mkdir (path, 0777) < 0)    /* try again */
  103.     {
  104.       message ("Cannot make directory", path);
  105.       return FALSE;
  106.     }
  107.  
  108.   return TRUE;
  109. }
  110.  
  111. static FILE *
  112. open_with_make_path (name)
  113. char *name;
  114. {
  115.   FILE *fp;
  116.  
  117.   if ((fp = fopen (name, WRITE_BINARY)) == NULL)
  118.     {
  119.       errno = 0;
  120.       if (!make_parent_path (name) ||
  121.       (fp = fopen (name, WRITE_BINARY)) == NULL)
  122.       error ("Cannot extract", name);
  123.       errno = 0;
  124.     }
  125.   return fp;
  126. }
  127.  
  128. static void
  129. adjust_info (name,hdr)
  130. char *name;
  131. LzHeader *hdr;
  132. {
  133.   time_t utimebuf[2];
  134.  
  135.   /* adjust file stamp */
  136.   utimebuf[0] = utimebuf[1] = hdr->unix_last_modified_stamp;
  137.   utime (name, utimebuf);
  138.  
  139.   if (hdr->extend_type == EXTEND_UNIX
  140.       || hdr->extend_type == EXTEND_OS68K
  141.       || hdr->extend_type == EXTEND_XOSK)
  142.     {
  143. #ifdef NOT_COMPATIBLE_MODE
  144.       Please need your modification in this space.
  145. #else
  146.       chmod (name, hdr->unix_mode);
  147. #endif
  148.     /*  if(!getuid())
  149.         chown (name, hdr->unix_uid, hdr->unix_gid); */
  150.       errno = 0;
  151.     }
  152. }
  153.  
  154. static char *methods[10] =
  155. {
  156.     "-lh0-", "-lh1-", "-lh2-", "-lh3-", "-lh4-",
  157.     "-lh5-", "-lzs-", "-lz5-", "-lz4-", NULL
  158. };
  159.  
  160. static void
  161. extract_one (afp, hdr)
  162. FILE *afp;                    /* archive file */
  163. LzHeader *hdr;
  164. {
  165.   FILE *fp;                    /* output file */
  166.   char name[257];
  167.   int crc;
  168.   int method;
  169.   boolean save_quiet, save_verbose;
  170.   char *q = hdr->name , c;
  171.  
  172.   if ( ignore_directory && rindex(hdr->name,'/') )
  173.     {
  174.       q = (char *)rindex(hdr->name,'/') + 1;
  175.     }
  176.   else
  177.     {
  178.       if ( *q=='/' )
  179.     {
  180.       q++;
  181.       /*
  182.        *    if OSK then strip device name
  183.        */
  184.       if (hdr->extend_type == EXTEND_OS68K
  185.           || hdr->extend_type == EXTEND_XOSK )
  186.         {
  187.           do c=(*q++); while ( c && c!='/' );
  188.           if ( !c || !*q ) q = ".";    /* if device name only */
  189.         }
  190.     }
  191.     }
  192.  
  193.   if (extract_directory)
  194.     sprintf (name, "%s/%s", extract_directory, q);
  195.   else
  196.     strcpy (name, q);
  197.  
  198.   if ((hdr->unix_mode & UNIX_FILE_TYPEMASK) == UNIX_FILE_REGULAR)
  199.     {
  200.       for (method = 0; ; method++)
  201.     {
  202.       if (methods[method] == NULL)
  203.         {
  204.           error ("Unknown method skipped ...", name);
  205.           return;
  206.         }
  207.       if (bcmp (hdr->method, methods[method], 5) == 0)
  208.         break;
  209.     }
  210.  
  211.       reading_filename = archive_name;
  212.       writting_filename = name;
  213.       if (output_to_stdout || verify_mode)
  214.     {
  215.       if (noexec)
  216.         {
  217.           printf ("%s %s\n", verify_mode ? "VERIFY" : "EXTRACT",name);
  218.           if (afp == stdin)
  219.         {
  220.           int i = hdr->packed_size;
  221.           while(i--) fgetc(afp);
  222.         }
  223.           return;
  224.         }
  225.  
  226.       save_quiet = quiet;
  227.       save_verbose = verbose;
  228.       if (!quiet && output_to_stdout)
  229.         {
  230.           printf ("::::::::\n%s\n::::::::\n", name);
  231.           quiet = TRUE;
  232.           verbose = FALSE;
  233.         }
  234.       else if (verify_mode)
  235.         {
  236.           quiet = FALSE;
  237.           verbose = TRUE;
  238.         }
  239.  
  240.       crc = decode_lzhuf
  241.         (afp, stdout, hdr->original_size, hdr->packed_size, name, method);
  242.       quiet = save_quiet;
  243.       verbose = save_verbose;
  244.     }
  245.       else
  246.     {
  247.       if (!inquire_extract (name))
  248.         return;
  249.  
  250.       if (noexec)
  251.         {
  252.           if (afp == stdin)
  253.         {
  254.           int i = hdr->packed_size;
  255.           while(i--) fgetc(afp);
  256.         }
  257.           return;
  258.         }
  259.  
  260.       signal (SIGINT, interrupt);
  261.       signal (SIGHUP, interrupt);
  262.  
  263.       unlink (name);
  264.       errno = 0;
  265.       remove_extracting_file_when_interrupt = TRUE;
  266.       if ((fp = open_with_make_path (name)) != NULL)
  267.         {
  268.           crc = decode_lzhuf
  269.         (afp, fp, hdr->original_size, hdr->packed_size, name, method);
  270.           fclose (fp);
  271.         }
  272.       remove_extracting_file_when_interrupt = FALSE;
  273.       signal (SIGINT, SIG_DFL);
  274.       signal (SIGHUP, SIG_DFL);
  275.  
  276.       if (!fp)
  277.         return;
  278.     }
  279.  
  280.       errno = 0;
  281.       if (hdr->has_crc && crc != hdr->crc)
  282.     error ("CRC error", name);
  283.  
  284.     }
  285.   else if ((hdr->unix_mode & UNIX_FILE_TYPEMASK) == UNIX_FILE_DIRECTORY)
  286.     {
  287.       if (!ignore_directory && !verify_mode)
  288.     {
  289.       if (noexec)
  290.         {
  291.           printf ("EXTRACT %s (directory)\n", name);
  292.           return;
  293.         }
  294.       /* NAME has trailing SLASH '/', (^_^) */
  295.       if (!output_to_stdout && !make_parent_path (name))
  296.         return;
  297.     }
  298.     }
  299.   else
  300.     {
  301.       error ("Unknown information", name);
  302.     }
  303.  
  304.   if (!output_to_stdout)
  305.     adjust_info (name,hdr);
  306. }
  307.  
  308.  
  309. /*----------------------------------------------------------------------*/
  310. /*            EXTRACT COMMAND MAIN                */
  311. /*----------------------------------------------------------------------*/
  312.  
  313. void
  314. cmd_extract ()
  315. {
  316.   LzHeader hdr;
  317.   long pos;
  318.   FILE *afp;
  319.  
  320.   /* open archive file */
  321.   if ((afp = open_old_archive ()) == NULL)
  322.     fatal_error (archive_name);
  323.   if (archive_is_msdos_sfx1 (archive_name))
  324.     skip_msdos_sfx1_code (afp);
  325.  
  326.   /* extract each files */
  327.   while (get_header (afp, &hdr))
  328.     {
  329.       if (need_file (hdr.name))
  330.     {
  331.       pos = ftell (afp);
  332.       extract_one (afp, &hdr);
  333.       fseek (afp, pos + hdr.packed_size, SEEK_SET);
  334.     }
  335.       else
  336.     {
  337.       if (afp != stdin)
  338.         fseek (afp, hdr.packed_size, SEEK_CUR);
  339.       else
  340.         {
  341.           int i = hdr.packed_size;
  342.           while(i--) fgetc(afp);
  343.         }
  344.     }
  345.     }
  346.  
  347.   /* close archive file */
  348.   fclose (afp);
  349.  
  350.   return;
  351. }
  352.