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