home *** CD-ROM | disk | FTP | other *** search
/ Dream 51 / Amiga_Dream_51.iso / Atari / Desktops / nodsk302.lzh / SRC / ARCDRV / W_LHARC.C < prev    next >
C/C++ Source or Header  |  1994-12-22  |  9KB  |  385 lines

  1. /*==================================================================*/
  2. /*                                                                    */
  3. /*                              noDesk                                */
  4. /*                                                                    */
  5. /*                            Version 3.0                                */
  6. /*                                                                    */
  7. /*                         written 1989-1994 by                        */
  8. /*          Andreas Fahrig   Ralph Mertens    Christian Stamm            */
  9. /*                                                                  */
  10. /*         (c)1989-93 by DesaSoft GbR, all Rights reserved            */
  11. /*         (c)1994-   by no|Soft GmbH, all Rights reserved            */
  12. /*                                                                  */
  13. /*==================================================================*/
  14. /*                                                                    */
  15. /*                Archiv-Treiber für LHARC-Dateien                    */
  16. /*                                                                    */
  17. /*==================================================================*/
  18. #include <types.h>
  19. #include <string.h>
  20. #include <stdlib.h>
  21. #include <stdio.h>
  22. #include <ctype.h>
  23. #include <ext.h>
  24. #include <tos.h>
  25.  
  26. #include "warc.h"
  27.  
  28.  
  29. /*-------------------------------------------------------------------
  30.     Konstanten und Makros
  31. --------------------------------------------------------------------*/
  32. /*
  33. #define DR_DEBUG
  34. */
  35.  
  36. #ifdef DR_DEBUG
  37. # define DebugAlert(SS) {printf("\033H\n\n%s\n", SS); Cnecin(); }
  38. #else
  39. # define DebugAlert(SS)
  40. #endif
  41.  
  42.  
  43. /*-------------------------------------------------------------------
  44.     Typen und Strukturen
  45. --------------------------------------------------------------------*/
  46. union stamp {                        /* time stamp */
  47.     struct ftime    s;
  48.     unsigned long    u;
  49. };
  50.  
  51. struct Lzh_Head {                    /* file header */
  52.     unsigned char    head_chk;
  53.     unsigned char    head_id[5];
  54.     unsigned long    pac_siz;
  55.     unsigned long    org_siz;
  56.     union stamp        file_time;
  57.     unsigned word    file_attr;
  58.     unsigned char    file_name[MAXPATHLEN];
  59. } Hdr1;
  60.  
  61.  
  62. /*-------------------------------------------------------------------
  63.     Variablen
  64. --------------------------------------------------------------------*/
  65. char        arcProg[MAXPATHLEN],
  66.             tmpFile[MAXPATHLEN];
  67.  
  68. Warc_File    *fileBuf;
  69.  
  70. int            maxFiles,
  71.             fileAnz;
  72. char        *envBuff;
  73.  
  74. uchar         HeadSiz;
  75. uchar        buf2[2048];
  76. char        filename[MAXPATHLEN];
  77.  
  78.  
  79. /*-------------------------------------------------------------------
  80.     Funktionen
  81. --------------------------------------------------------------------*/
  82. /*
  83.  * calculate check-sum of header
  84.  */
  85. uchar _CalcCRC(struct Lzh_Head *h, uchar headsize) {
  86.     uchar *p, *q;
  87.     uchar i;
  88.  
  89.     p = (uchar *)h + 1;
  90.     q = p + headsize;
  91.     for (i = 0; p < q; p++)
  92.         i += *p;
  93.     return i;
  94. } /* _CalcCRC */
  95.  
  96.  
  97. /*
  98.  * open an old archive
  99.  */
  100. FILE *_OpenArc1(char *fname) {
  101.     uchar    *p, *q;
  102.     FILE    *fP;
  103.  
  104.     if ((fP = fopen(fname, "rb")) == NULL)
  105.         return NULL;
  106.         
  107.     q = buf2 - 5 + fread(buf2, 1, 2048, fP);
  108.     for (p = buf2; p < q; p++) {
  109.         if (p[0] == '-' && p[1] == 'l' && p[4] == '-') break;
  110.     }
  111.     if (p >= q) {
  112.         fclose(fP);
  113.         return NULL;
  114.     }
  115.     fseek(fP, (long)(p - buf2 - 2), SEEK_SET);
  116.     return(fP);
  117. } /* _OpenArc1 */
  118.  
  119.  
  120. void _Swap(void *vP, int size) {
  121.     int        i;
  122.     char    buf[4];
  123.     
  124.     for(i = 0; i < size; i++) buf[size - i - 1] = *((char *)vP + i);
  125.     if (size == 4) *(ulong *)vP = *(ulong *)buf;
  126.     if (size == 2) *(uword *)vP = *(uword *)buf;
  127. } /* _Swap */
  128.  
  129.  
  130. /*
  131.  * get a file header
  132.  */
  133. uchar *_GetHdr(FILE *fP, struct Lzh_Head *h) {
  134.     uchar     *q, i;
  135.     
  136.     if (((HeadSiz = getc(fP)) <= 0) ||
  137.          (HeadSiz > sizeof(struct Lzh_Head) - 3) ||
  138.          (fread(h, HeadSiz + 1, 1, fP) == 0))
  139.     {                                /* read file header */
  140.         return NULL;
  141.     }
  142.  
  143.     if (_CalcCRC(h, HeadSiz) != h->head_chk)    /* if sum is wrong */
  144.         return NULL;
  145.  
  146.     _Swap(&h->org_siz, 4);
  147.     _Swap(&h->pac_siz, 4);
  148.     _Swap((int *)&h->file_time.u, 2);
  149.     _Swap((int *)&h->file_time.u + 1, 2);
  150.     _Swap(&h->file_attr, 2);
  151.     i = h->file_name[0];
  152.     strncpy(filename, (char *)&h->file_name[1], i);
  153.     *(filename + i) = '\0';
  154.     if ((q = (uchar *)strrchr(filename, '\\')) == NULL &&
  155.         (q = (uchar *)strchr(filename, ':')) == NULL)
  156.         q = (uchar *)filename;
  157.     else
  158.         q++;
  159.     return q;                    /* return the portion of file name */
  160. } /* _GetHdr */
  161.  
  162.  
  163. /*
  164.  * _Ratio * 1000
  165.  */
  166. static uword _Ratio(ulong a, ulong b) {
  167.     int i;
  168.  
  169.     if (!b) return 0;            /* if diviser == 0 */
  170.     for (i = 0; i < 3 && a < 0x19999999UL; i++) {
  171.         a *= 10;                /* while not overflow */
  172.     }                            /* upto 1000 times */
  173.     for (; i < 3; i++) {        /* the case of overflow */
  174.         b /= 10;
  175.     }
  176.     a += b / 2;                    /* for round up */
  177.     return ((uword)(a / b));    /* return (a * 1000 / b) */
  178. } /* _Ratio */
  179.  
  180.  
  181. static void _FillLE(Warc_File *wfP) {
  182.     wfP->orig_len    = Hdr1.org_siz;
  183.     wfP->packed_len = Hdr1.pac_siz;
  184. /* AFA 7.12.94: ----------------------
  185.     wfP->t_d.td.jar = (Hdr1.file_time.s.ft_year + 80) % 100;
  186. ------------------------------------*/
  187.     wfP->t_d.td.jar = Hdr1.file_time.s.ft_year;
  188.     wfP->t_d.td.mon = Hdr1.file_time.s.ft_month;
  189.     wfP->t_d.td.tag = Hdr1.file_time.s.ft_day;
  190.     wfP->t_d.td.std = Hdr1.file_time.s.ft_hour;
  191.     wfP->t_d.td.min = Hdr1.file_time.s.ft_min;
  192.     wfP->t_d.td.sek = Hdr1.file_time.s.ft_tsec * 2;
  193.     wfP->attrib        = Hdr1.file_attr;
  194. } /* _FillLE */
  195.  
  196.  
  197. static Warc_File *_AddLEDir(uchar level, int ref_no, char *dirname) {
  198.     static Warc_File *_AddLE(uchar, int, char *, Warc_File *);
  199.     Warc_File        wf;
  200.  
  201.     wf.orig_len        = 0L;
  202.     wf.packed_len    = 0L;
  203.     wf.t_d.td.jar     = 0;
  204.     wf.t_d.td.mon     = 1;
  205.     wf.t_d.td.tag     = 1;
  206.     wf.t_d.td.std    = 0;
  207.     wf.t_d.td.min    = 0;
  208.     wf.t_d.td.sek    = 0;
  209.     wf.attrib        = FA_SUBDIR;
  210.  
  211.     return(_AddLE(level, ref_no, dirname, &wf));
  212. } /* _AddLEDir */
  213.  
  214.  
  215. static Warc_File *_AddLE(uchar level, int ref_no, char *fname, Warc_File *newwfP) {
  216.     char        *cP;
  217.     Warc_File    *wfP;
  218.     int            i;
  219.  
  220.     if (fileAnz >= maxFiles) {
  221.         DebugAlert("too much");
  222.         return(NULL);
  223.     }
  224.  
  225.     cP = strchr(fname, '\\');
  226.     if (cP) {
  227.         *cP = '\0';
  228.  
  229.         for (i=0, wfP = fileBuf; i<fileAnz; i++, wfP++) {
  230.             if (!(wfP->attrib & FA_SUBDIR)) continue;
  231.             if (wfP->level!=level || wfP->ref_no!=ref_no) continue;
  232.             if (!strcmp(wfP->fname, fname)) break;
  233.         }
  234.         if (i >= fileAnz) wfP = _AddLEDir(level, ref_no, fname);
  235.         *cP = '\\';
  236.         if (!wfP) return(NULL);
  237.         fname = cP+1;
  238.         return (_AddLE(level+1, wfP->physcnt, fname, newwfP));
  239.     }
  240.  
  241.     if (newwfP->attrib & FA_SUBDIR) {
  242.         for (i=0, wfP = fileBuf; i<fileAnz; i++, wfP++) {
  243.             if (!(wfP->attrib & FA_SUBDIR)) continue;
  244.             if (wfP->level!=level || wfP->ref_no!=ref_no) continue;
  245.             if (!strcmp(wfP->fname, fname)) return(wfP);
  246.         }
  247.     }
  248.  
  249.     wfP = &fileBuf[fileAnz++];
  250.     wfP->physcnt        = fileAnz;
  251.     wfP->ref_no            = ref_no;
  252.     wfP->level            = level;
  253.     wfP->attrib            = newwfP->attrib;
  254.     wfP->t_d.ul            = newwfP->t_d.ul;
  255.     wfP->orig_len        = newwfP->orig_len;
  256.     wfP->packed_len        = newwfP->packed_len;
  257.     strncpy(wfP->fname, fname, 13);
  258.     wfP->fname[13]        = '\0';
  259.  
  260.     while (level > 0) {
  261.         if (fileBuf[ref_no].t_d.ul >= wfP->t_d.ul) break;
  262.         fileBuf[ref_no].t_d.ul = wfP->t_d.ul;
  263.         wfP = &fileBuf[ref_no];
  264.         level--;
  265.     }
  266.     return(wfP);
  267. } /* _AddLE */
  268.  
  269.  
  270. int DoConvertArc(Warc_Info *aiP) {
  271.     FILE            *fP;
  272.     Warc_File        wf;
  273.     char            *cP;
  274.     int                err = DE_DRERROR;
  275.     
  276.     if ((fP = _OpenArc1(aiP->arc_name)) == NULL) {     /* open archive */
  277.         err = DE_BADFILE;
  278.         goto arc_read_err;
  279.     }
  280.  
  281.     maxFiles    = aiP->buf_size;
  282.     fileBuf        = aiP->buf;
  283.     fileAnz        = 0;
  284.  
  285.     while (_GetHdr(fP, &Hdr1) != NULL) {
  286.         filename[MAXPATHLEN-1] = '\0';
  287.         if (!filename[0]) continue;
  288.         for (cP = filename; *cP; cP++);
  289.         cP--;
  290.         if (*cP == '\\') *cP = '\0';
  291.         if (!filename[0]) continue;
  292.         if (filename[1] == ':') {
  293.             sprintf((char *)aiP->buf,
  294.                                 "Das Archiv enthält absolute\n"
  295.                                 "Pfade incl. Laufwerksangaben!");
  296.             err = DE_TXTERROR;
  297.             goto arc_read_err;
  298.         }
  299.  
  300.         _FillLE(&wf);
  301.         if (!_AddLE(0, 0, filename, &wf)) {
  302.             err = DE_DRERROR;
  303.             goto arc_read_err;
  304.         }
  305.  
  306.         if (fseek(fP, Hdr1.pac_siz, 1) || feof(fP))
  307.             break;
  308.     }
  309.  
  310.     fclose(fP);
  311.     aiP->buf_size = fileAnz;
  312.     return(DE_OK);
  313.  
  314. arc_read_err:
  315.     if (fP) fclose(fP);
  316.     if (err == DE_DRERROR) {
  317.         if (fileAnz >= maxFiles) err = DE_TOOMUCH;
  318.         else {
  319.             sprintf((char *)aiP->buf,
  320.                                 "Fehler beim Lesen von\n%s",aiP->arc_name);
  321.             err = DE_TXTERROR;
  322.         }
  323.     }
  324.     fileAnz = 0;
  325.     return (err);
  326. } /* DoConvertArc */
  327.  
  328.  
  329. int ReadArchive(Warc_Info *aiP) {
  330.     if (Fattrib(aiP->arc_name, 0, 0) < 0) {
  331.         DebugAlert("Archiv");
  332.         strcpy((char *)aiP->buf, "Das Archiv ist vom\n"
  333.                                 "Treiber nicht zu finden!");
  334.         return(DE_TXTERROR);
  335.     }
  336.  
  337.     return (DoConvertArc(aiP));
  338. } /* ReadArchive */
  339.  
  340.  
  341. static Warc_Info *_ScanArg(char *arg) {
  342.     int                    i = 0;
  343.     long                l = 0L;
  344.     Warc_Info            *aiP;
  345.  
  346.     while ((i < 8) && isxdigit(*arg)) {
  347.         if ((*arg >= '0')&&(*arg <= '9')) l = (l << 4) + (*arg - '0');
  348.         else if ((*arg >= 'A')&&(*arg <= 'F')) l = (l << 4) + (*arg - 'A'+10);
  349.         else                             l = (l << 4) + (*arg - 'a'+10);
  350.         arg++;
  351.         i++;
  352.     }
  353.  
  354.     if ((i != 8) || (*arg != 0)) return(NULL);
  355.  
  356.     aiP = (Warc_Info *)l;
  357.  
  358.     if (strncmp(aiP->magic, WARC_MAGIC, 8)) return(NULL);
  359.  
  360.     return(aiP);
  361. } /* _ScanArg */
  362.  
  363.  
  364. int main(int ac, char **av, char **env) {
  365.     Warc_Info        *aiP;
  366.     int                ret;
  367.  
  368.     envBuff = *env;
  369.     if (ac != 2) return(DE_DRERROR);
  370.  
  371.     if ((aiP = _ScanArg(av[1])) == NULL) {
  372.         DebugAlert("Arguments");
  373.         return(DE_DRERROR);
  374.     }
  375.  
  376.     ret = ReadArchive(aiP);
  377.     if (ret == DE_TOOMUCH) {
  378.         sprintf((char *)aiP->buf,
  379.                 "Das Archiv enthält mehr\nals %d Dateien.\n"
  380.                 "Bitte die Optionen für\nLS-Fenster ändern!", aiP->buf_size);
  381.         ret = DE_TXTERROR;        
  382.     }
  383.     return (ret);
  384. } /* main */
  385.