home *** CD-ROM | disk | FTP | other *** search
/ DOS/V Power Report 1997 March / VPR9703A.ISO / OLS / Os2 / LHA2P205 / LHA2P205.LZH / lha2-2.05pre / source.lzh / src / extract.c < prev    next >
C/C++ Source or Header  |  1996-02-24  |  8KB  |  388 lines

  1. /*
  2.  * extract.c --- extract file from archive
  3.  *   Copyright (C) 1988-1992, Haruyasu YOSHIZAKI
  4.  *   Copyright (C) 1991-1996, Satoshi HIRAMATSU (OS/2 HPFS version)
  5.  *
  6.  * $Log$
  7.  */
  8.  
  9.  
  10. #include <sys/types.h>
  11. #include <stdio.h>
  12. #include <string.h>
  13. #include <stdlib.h>
  14. #include <io.h>
  15. #include <direct.h>
  16. #include <time.h>
  17. #include "typedef.h"
  18. #include "port2.h"
  19. #include "lh.h"
  20. #include "header.h"
  21. #include "intrface.h"
  22. #include "slidehuf.h"
  23. #include "disp.h"
  24. #include "errmes.h"
  25.  
  26.  
  27. /* test the file name which should be melted */
  28. static char
  29. tstdir(char *name)
  30. {
  31.   char *p, *q, yn;
  32.   int absent;
  33.   struct find_t srchbuf;
  34.  
  35.   p = name;
  36.   if(*p && p[1] == ':')        /* skip a drive name */
  37.     p += 2;
  38.   if(*p == DELIM)        /* skip a root mark('\') */
  39.     p++;
  40.   yn = flg_m ? 'Y' : 'N';
  41.   q = p;
  42.   while((p = strchr(p, DELIM)) != NULL)    /* skip to next '\' */
  43.     {
  44.       if(*q != '.')
  45.     {
  46.       *p = '\0';
  47.       absent = _dos_findfirst(name, 0x17, &srchbuf);
  48. #ifdef __SUPPORT_EA__
  49.       if(srchbuf.ea)
  50.         free(srchbuf.ea);
  51. #endif
  52.       if(absent)
  53.         {    
  54.           if(yn == 'N')
  55.         {
  56.           *p = DELIM;
  57.           eprintf("'%s' : %s", name, MKDIR);
  58.           *p = '\0';
  59.           yn = getyn();
  60.         }
  61.           if(yn == 'N')
  62.         return 'S';
  63.           else
  64.         {
  65. #ifdef __API16__
  66.           if(__version__ < 1020) /* for OS/2 v1.0 and v1.1. */
  67.             {
  68.               if (DosMkDir((PSZ) name, 0L)) /* make directory */
  69.             if((srchbuf.attrib & 0x10) == 0)
  70.               error(MKDIRERR, name);
  71.             }
  72.           else
  73.             {
  74.               if(DosMkDir2((PSZ) name, (PEAOP) NULL, 0L))
  75.             if((srchbuf.attrib & 0x10) == 0)
  76.               error(MKDIRERR, name);
  77.             }
  78. #else
  79.           if(mkdir(name))
  80.             if((srchbuf.attrib & 0x10) == 0)
  81.               error(MKDIRERR, name);
  82. #ifdef __SUPPORT_EA__
  83.           if(hpb.ea)
  84.             SetEA(name, hpb.ea);
  85. #endif /* __SUPPORT_EA__ */
  86. #endif
  87.         }
  88.         }
  89.       else
  90.         {
  91.           if((srchbuf.attrib & 0x10) == 0)
  92.         error(MKDIRERR, name); /* if the name isn't directory */
  93.         }
  94.       *p = DELIM;
  95.     }
  96.       q = ++p;
  97.     }
  98.   if(!_dos_findfirst(name, 0x17, &srchbuf))
  99.     {
  100. #ifdef __SUPPORT_EA__
  101.       if(srchbuf.ea)
  102.     free(srchbuf.ea);
  103. #endif
  104.       /* already exists */
  105.       if(flg_c == 0 &&
  106.      dos2unix((struct ftime *)&srchbuf.wr_time) >= hpb.mtime)
  107.     yn = 'S';
  108.       switch(flg_m)
  109.     {
  110.     case 0:
  111.       if(yn != 'S')
  112.         {
  113.           eprintf("'%s' %s", name, OVERWT);
  114.           yn = (getyn() == 'Y') ? 'O' : 'S';
  115.           break;
  116.         }
  117.  
  118.     case 1:
  119.       if(yn == 'S')
  120.         {
  121.           if(!flg_s)
  122.         skipdisp(NEWFILE);
  123.           break;
  124.         }
  125.       yn = 'O';
  126.       break;
  127.  
  128.     case 2:
  129.       yn = 'R';
  130.       break;
  131.     }
  132.  
  133.       if(yn != 'O')
  134.     return yn;
  135.  
  136.       if(srchbuf.attrib & 0x01 && srchbuf.attrib != hpb.attr && !flg_a)
  137.     {
  138.       /* if the file is read-only, */
  139.       /* attributes must match */
  140.       skipdisp(RDONLY);
  141.       return 'S';
  142.     }
  143.       if(srchbuf.attrib & 0x10)
  144.     {
  145.       skipdisp(SAMEDIR);
  146.       return 'S';
  147.     }
  148.       if(srchbuf.attrib & 0x07)
  149.     _dos_setfileattr(name, 0x20); /* reset attributes */
  150. #ifdef __SUPPORT_EA__
  151.       if(hpb.ea)
  152.     SetEA(name, hpb.ea);
  153. #endif /* __SUPPORT_EA__ */
  154.     }
  155.  
  156.   return 'O';
  157. }
  158.  
  159.  
  160. static int
  161. rename_ext(char *name)
  162. {
  163.   int i;
  164.   char *p, *q;
  165.   struct find_t srchbuf;
  166.  
  167.   p = strrchr(name, '.');
  168.   q = strrchr(name, DELIM);
  169.   if(p <= q)
  170.     p = name + strlen(name);
  171.   for(i = 0; i <= 999; i++)
  172.     {
  173.       sprintf(p, ".%03d", i);
  174.       if(_dos_findfirst(name, 0x17, &srchbuf))
  175.     return 1;
  176. #ifdef __SUPPORT_EA__
  177.       if(srchbuf.ea)
  178.     free(srchbuf.ea);
  179. #endif
  180.     }
  181.  
  182.   return 0;
  183. }
  184.  
  185.  
  186. void
  187. extract(char *bdir)
  188. {
  189.   char *path;
  190.   int method;
  191.   hword crc;
  192.  
  193.   dispflg = 0;
  194.   memcpy(methods[SENTINEL], hpb.method, 5);
  195.   for(method = 0; memcmp(hpb.method, methods[method], 5); method++)
  196.     ;
  197.   if(method == SENTINEL)
  198.     {
  199.       skipdisp(METHODERR);
  200.       return;
  201.     }
  202.  
  203.   switch(cmd)
  204.     {
  205.     case 'E':
  206.       if((hpb.attr & 0x06) && flg_a == 0)
  207.     {
  208.       skipdisp(SPECIALATTR);
  209.       return;
  210.     }
  211.       if(flg_i == 2)        /* change to lower charcter.  */
  212.     jstrlwr(hpb.pathname);
  213.       else if(flg_i == 0)
  214.     jstrupr(hpb.pathname);
  215.       form_path(hpb.pathname);
  216.       hpb.filename = getfilename(hpb.pathname);
  217.       path = (flg_x) ? hpb.pathname : hpb.filename;
  218.       strcpy(filename3, bdir);
  219.       if(path[1] == ':')
  220.     path += 2;
  221.       if(*(unsigned char *)path == DELIM)
  222.     {
  223.       if(filename3[1] == ':')
  224.         filename3[2] = '\0';
  225.       else
  226.         *filename3 = '\0';
  227.     }
  228.       strcat(filename3, path);
  229.  
  230.       switch(tstdir(filename3))
  231.     {
  232.     case 'R':
  233.       if(rename_ext(filename3))
  234.         break;
  235.       skipdisp(NOMOREEXT);
  236.  
  237.     case 'S':
  238.       return;
  239.     }
  240.  
  241.       if(!flg_f && (diskspace(filename3) < hpb.original))
  242.     {
  243.       skipdisp(DISKFULL);
  244.       return;
  245.     }
  246.       /* for UNIX version LHA directory archives.  */
  247.       /* for OS/2 version LHA directory archives with "-d" option. */
  248.       if(*(hpb.pathname + strlen(hpb.pathname) - 1) == DELIM)
  249.     {
  250.       regdisp("       ", hpb.pathname);
  251.       break;
  252.     }
  253.       file3 = mywopen(filename3, MKFILEERR);
  254.       regdisp("Melting ", filename3);
  255.       break;
  256.  
  257.     case 'P':
  258.       file3 = fdopen(dup(1), "wb");
  259.       regdisp("Melting", NULL);
  260.       if(!flg_n)
  261.     {
  262.       fprintf(file3, "\r\n<< %s >>\r\n\r\n", hpb.filename);
  263.       fflush(file3);
  264.     }
  265.       break;
  266.  
  267.     case 'T':
  268.       if(hpb.level < 0)
  269.     {
  270.       skipdisp(NOCRC);
  271.       return;
  272.     }
  273.       regdisp("Testing", NULL);
  274.       file3 = NULL;
  275.       break;
  276.     }
  277.  
  278.   interface.method = method;
  279.   interface.dicbit = 13;
  280.   interface.infile = file1;
  281.   interface.outfile = file3;
  282.   interface.original = hpb.original;
  283.   interface.packed = hpb.packed;
  284.  
  285.   switch(method)
  286.     {
  287.     case LH0:
  288.     case LZ4:
  289.     case LHD:
  290.       method = 0;
  291.       break;
  292.  
  293.     case LZS:
  294.       interface.dicbit = 11;
  295.       break;
  296.  
  297.     case LH1:
  298.     case LH4:
  299.     case LZ5:
  300.       interface.dicbit = 12;
  301.       break;
  302.     }
  303.  
  304.   if(!((flg_n == 2) && (cmd == 'P')))
  305.     disp(cmd == 'P' && !outredir, cmd != 'P' && outredir);
  306.   initdisp();
  307.  
  308.   if(method)
  309.     crc = decode(&interface);
  310.   else
  311.     crc = copyfile(file1, file3, hpb.original, 1);
  312.  
  313.   if(file3)
  314.     {
  315.       fflush(file3);
  316. #ifndef __SUPPORT_CTIME_ATIME__
  317.       setfiletime(file3, hpb.mtime);
  318. #else
  319.       setfiletime(file3, &hpb.mtime, &hpb.ctime, &hpb.atime);
  320. #endif
  321.       fclose(file3);
  322.       file3 = NULL;
  323.     }
  324.   if(hpb.level >= 0 && crc != hpb.filecrc)
  325.     {
  326.       errorlevel = 1;
  327.       eprintf("\rCRC err\n");
  328.       if(cmd == 'E')
  329.     {
  330.       if(flg_m == 0)
  331.         {
  332.           eprintf(MAYDELETE);
  333.           if(getyn() == 'Y')
  334.         remove(filename3);
  335.         }
  336.       else
  337.         remove(filename3);
  338.     }
  339.       if(flg_m == 0)
  340.     {
  341.       eprintf(MAYCONT);
  342.       if(getyn() != 'Y')
  343.         error(CTRLBRK, NULL);
  344.     }
  345.     }
  346.   else
  347.     {
  348.       if(cmd == 'T')
  349.     enddisp("Test OK");
  350.       else
  351.     {
  352.       /* for directory archive */
  353.       if(*(hpb.pathname + strlen(hpb.pathname) - 1) == DELIM)
  354.         {
  355.           if(cmd != 'P' || outredir)
  356.         enddisp("mkdir  ");
  357.         }
  358.       else
  359.         {
  360.           if(cmd != 'P' || outredir)
  361.         enddisp("Melted ");
  362.         }
  363.     }
  364.       if(cmd == 'E' && flg_a)
  365.     _dos_setfileattr(filename3, hpb.attr);
  366. #ifdef __SUPPORT_EA__
  367.       if(hpb.ea)
  368.     SetEA(filename3, hpb.ea);
  369. #endif /* __SUPPORT_EA__ */
  370.     }
  371. }
  372.  
  373.  
  374. void
  375. extract_internal(FILE *f, char *p)
  376. {
  377.   interface.method = 5;
  378.   interface.dicbit = 13;
  379.   interface.infile = NULL;
  380.   interface.outfile = f ? fdopen(dup(fileno(f)), "wb") : f;
  381.   interface.original = *(ulong *)(p + 4);
  382.   interface.packed = *(ulong *)p;
  383.   interface.blkcnt = -1;
  384.   interface.internal = (char *)(p + 8);
  385.   dispflg = 1;
  386.   decode(&interface);
  387. }
  388.