home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / MISC / OS2 / DWNSRT47.ZIP / DOWNCOL.C < prev    next >
Encoding:
C/C++ Source or Header  |  1990-12-01  |  18.1 KB  |  412 lines

  1. /* ============================================================= */
  2. /*  Rob Hamerling's MAXIMUS download file scan and sort utility. */
  3. /*  -> Functions to collect download file information.           */
  4. /* ============================================================= */
  5.  
  6. #define INCL_BASE
  7. #include <os2.h>
  8.  
  9. #include "downsort.h"
  10.  
  11. #include <conio.h>
  12. #include <fcntl.h>
  13. #include <io.h>
  14. #include <share.h>
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #include <string.h>
  18. #include <sys\types.h>
  19. #include <sys\stat.h>
  20.  
  21. /* ---------------------------- */
  22. /* Collect download file area's */
  23. /* ---------------------------- */
  24. USHORT collect_down(area)
  25. struct _downpath **area;                // pointer to area-info pointer array
  26. {
  27.   USHORT af,oaction;                    // file handle, open_action
  28.   int    i,j,m,rc;                      // counters, returncode
  29.   unsigned int k;                       // #area's
  30.   union  _areamax u;                    // MAXIMUS area-file record(s)
  31.   struct _downpath *d;                  // ptrs to array of area-info
  32.   struct stat fs;                       // file status buffer
  33.  
  34.   rc = DosOpen(areadat_path,            // Open 'carefully'
  35.           &af,                          // pointer to File Handle
  36.           &oaction,                     // pointer to action field
  37.           0L,                           // new filesize (N/A)
  38.           FILE_NORMAL,                  // attributes
  39.           FILE_OPEN,                    // open flags
  40.           OPEN_ACCESS_READONLY   |      // access flags
  41.             OPEN_SHARE_DENYWRITE |
  42.             OPEN_FLAGS_RANDOMSEQUENTIAL |
  43.             OPEN_FLAGS_NOINHERIT,
  44.           0L);                          // reserved
  45.   if (rc != NO_ERROR) {                 // open error
  46.     printf(OPEN_FAIL,areadat_path);
  47.     exit(rc);
  48.     }
  49.   if (oaction != FILE_EXISTED) {        // not found
  50.     printf(OPEN_FAIL,areadat_path);
  51.     exit(5);
  52.     }
  53.   else {
  54.     if (oper_mode == VERBOSE)
  55.       printf("\nReading file-area information from %s",areadat_path);
  56.     stat(areadat_path,&fs);             // get status of AREA.DAT
  57.     read(af,(char *)&u,sizeof(struct _area)); // obtain first record
  58.     if (u.a.id == AREA_id) {
  59.       MAX_level = 102;                  // looks like version 1.02
  60.       k = (int)(fs.st_size / u.a.struct_len);
  61.       }
  62.     else if (u.a1.struct_len == sizeof(struct _area100)) {
  63.       MAX_level = 100;                  // looks like version 1.00
  64.       k = (int)(fs.st_size / u.a1.struct_len);
  65.       }
  66.     else {
  67.       printf("\nSorry, unsupported format of %s-file!",areadat_path);
  68.       printf("\n%s %d.%d%c works for %s version 1.00 and 1.02!",
  69.                  PROGNAME,VERSION,SUBVERS,SUFFIX,MAX);
  70.       exit(8);                          // wrong version of AREA.DATA
  71.       }
  72.  
  73.     d = (struct _downpath *)calloc(k,sizeof(struct _downpath));
  74.     if (d == NULL) {                    // memory not obtained?
  75.       printf(MSG_MEM,PROGNAME);
  76.       exit(6);
  77.       }
  78.     else {
  79.       *area = d;                        // return pointer to caller
  80.       for (i=0,m=0; i<k; i++) {         // all area records
  81.         if (MAX_level == 102) {         // use version 1.02 layout
  82.           lseek(af,i*(long)u.a.struct_len,SEEK_SET);  // locate to next
  83.           read(af,(char *)&u,sizeof(struct _area));
  84.           if (u.a.filepath[0] != '\0' && u.a.filepath[0] != ' ') {
  85.             d[m].priv      = u.a.filepriv;       // download privilege
  86.             strcpy(d[m].name,u.a.name);          // area name
  87.             strcpy(d[m].pname,u.a.filepath);     // download path
  88.             strcpy(d[m].filesbbs,u.a.filesbbs);  // files.bbs
  89.             strcpy(d[m].adesc,u.a.fileinfo);     // filearea title
  90.             ++m;                        // active filearea count
  91.             }
  92.           }
  93.         else {                          // use version 1.00 layout
  94.           lseek(af,i*(long)u.a1.struct_len,SEEK_SET);  // locate to next
  95.           read(af,(char *)&u,sizeof(struct _area100));
  96.           if (u.a1.filepath[0] != '\0' && u.a1.filepath[0] != ' ') {
  97.             d[m].priv      = u.a1.filepriv;      // download privilege
  98.             strcpy(d[m].name,u.a1.name);         // area name
  99.             strcpy(d[m].pname,u.a1.filepath);    //download path
  100.             strcpy(d[m].filesbbs,u.a1.filesbbs); // files.bbs
  101.             strcpy(d[m].adesc,u.a1.fileinfo);    // filearea title
  102.             ++m;                        // active filearea count
  103.             }
  104.           }
  105.         if (d[m-1].name[0] != '\0' && d[m-1].name[1] == '\0') { // single char?
  106.           d[m-1].name[1] = d[m-1].name[0];  // shift right 1
  107.           d[m-1].name[0] = ' ';         // leading blank
  108.           }
  109.         j = strlen(d[m-1].pname);
  110.         if (j>0 && d[m-1].pname[j-1] != '\\')
  111.           d[m-1].pname[j] = '\\';       // add backslash if needed
  112.         }
  113.       }
  114.     DosClose(af);                       // close area.dat-file
  115.     return(m);                          // report number of downloadarea's
  116.     }
  117.   }
  118.  
  119. /* ---------------------------- */
  120. /* Collect all file information */
  121. /* ---------------------------- */
  122. USHORT collect_file(m,area)
  123. USHORT m;                               // number of download area's
  124. struct _downpath *area;                 // pointer to download path array
  125. {
  126.   unsigned int i,k,fc;                  // counters
  127.   struct _filechain *ca,*ce;            // ptrs to file info
  128.  
  129.   ca = NULL;                            // empty chain!
  130.   fc = 0;                               // total file-counter
  131.   for (i=0; i<m; i++) {                 // all download paths
  132.     k = fill_chn(&area[i],&ca,&ce);     // files in area
  133.                                         // returns ptrs first/last active
  134.     if (oper_mode == VERBOSE)
  135.       printf("\n %5d files in area %-.2s (Priv=%c) DL-dir=%s",
  136.            k,area[i].name,
  137.            priv_name[area[i].priv-TWIT][0],
  138.            area[i].pname);
  139.     if (k > 0) {                        // any files in this area?
  140.       if (first_element == NULL)
  141.         first_element = ca;             // pointer to very first
  142.       get_desc(k,ca,&area[i]);          // obtain descriptions
  143.       fc += k;                          // total counter
  144.       }
  145.     ca = ce;                            // for next area
  146.     }
  147.   return(fc);
  148.   }
  149.  
  150. /* ---------------------------------------- */
  151. /* Add all subdir-filenames to the chain,   */
  152. /* for further processing by mainline.      */
  153. /* NOTE: full path name assumed!            */
  154. /* ---------------------------------------- */
  155. USHORT fill_chn(parea,cp,cq)
  156. struct _downpath *parea;                // pointer to download-info
  157. struct _filechain **cp,**cq;            // ptrs to ptr first/last element
  158. {
  159.   int    rc;                            // returncode of DOS-calls
  160.   USHORT fc;                            // area-file counter
  161.   struct _filechain *ca,*ce,*tp;        // new curr temp chain pointers
  162.   struct _FILEFINDBUF cf;               // OS file-info buffer
  163.   char   down_spec[MAXPATH];            // file specification buffer
  164.   HDIR   fhandle;                       // FindFirst/Last handle
  165.   USHORT fentries;                      // # entries to be retrieved
  166.  
  167.   fc = 0;                               // init filecount of this area
  168.   ce = ca = *cp;                        // ptr to last active element
  169.   strcpy(down_spec,parea->pname);       // path
  170.   strcat(down_spec,"*.*");              // file-spec
  171.   fentries = 1;                         // one at a time!
  172.   fhandle  = HDIR_CREATE;               // new file handle
  173. // #define FILE_NORMAL 0                   // not defined in TOOLKIT 1.1
  174.   rc = DosFindFirst(down_spec,&fhandle,FILE_NORMAL,&cf,
  175.               sizeof(struct _FILEFINDBUF),&fentries,0L);
  176.   while (rc == 0) {
  177.     if ((wild_comp(0,cf.achName,"FILES.?BS")   != 0) &&
  178.         (wild_comp(0,cf.achName,"*.BAK")       != 0) &&
  179.         (wild_comp(0,cf.achName,"SYSTEM*.?BS") != 0) &&
  180.         (wild_comp(0,cf.achName,"DIR.?BS")     != 0)) {
  181.       tp = (struct _filechain *)malloc(sizeof(struct _filechain));
  182.       if (tp == NULL) {
  183.         printf(MSG_MEM,PROGNAME);       // not enough memory
  184.         exit(11);
  185.         }
  186.       if (ca == NULL)                   // very first element
  187.         ca = ce = tp;                   // ptr to first and last active!
  188.       else {                            // not very first
  189.         if (fc == 0)                    // first in this area
  190.           ca = tp;                      // ptr to first active this area
  191.         ce->next_element = tp;          // chain-ptr in current element
  192.         ce = tp;                        // ptr to last active
  193.         }
  194.       ++fc;                             // update filecount this area
  195.       ce->next_element = NULL;          // copy/init fields
  196.       ce->parea = parea;
  197.       ce->wdate = cf.fdateLastWrite;
  198.       ce->wtime = cf.ftimeLastWrite;
  199.       if (file_time(cf.fdateCreation,cf.ftimeCreation) >
  200.           file_time(cf.fdateLastWrite,cf.ftimeLastWrite) ) {
  201.         ce->cdate = cf.fdateCreation;   // creation most recent
  202.         ce->ctime = cf.ftimeCreation;
  203.         }
  204.       else {                            // otherwise and non-HPFS volumes
  205.         ce->cdate = cf.fdateLastWrite;
  206.         ce->ctime = cf.ftimeLastWrite;
  207.         }
  208.       ce->size  = cf.cbFile;
  209.       byte_count += cf.cbFile;
  210.       ce->attr  = cf.attrFile;
  211.       ce->priv  = HIDDEN;               // unless FILES.BBS proves otherwise
  212.       strncpy(ce->fname,cf.achName,MAXFN);
  213.       ce->fdesc = NULL;                 // unless later found in FILES.BBS
  214.       }
  215.     rc = DosFindNext(fhandle,&cf,sizeof(struct _FILEFINDBUF),&fentries);
  216.     }
  217.   DosFindClose(fhandle);                // close directory association
  218.   *cp = ca;                             // pointer to first new this area
  219.   *cq = ce;                             // pointer to last new this area
  220.   return(fc);
  221.   }
  222.  
  223. /* ------------------------------ */
  224. /* Add file description to chain  */
  225. /* ------------------------------ */
  226. void get_desc(x,cp,parea)
  227. int    x;                               // number of file-entries
  228. struct _filechain *cp;                  // ptr to ptr to first of group
  229. struct _downpath *parea;                // pointer to area-info
  230. {
  231.   FILE   *fi;                           // file pointer
  232.   USHORT fih,oaction;                   // file handle, open-action
  233.   struct _filechain *ce;                // ptrs to file-info
  234.   char   buf[MAXRCD];                   // read-buffer for FILES.BBS
  235.   char   filename[MAXFN];               // filename from FILES.BBS buf
  236.   char   *desc,*rp;                     // ptr to desc / return val gets()
  237.   char   buf2[MAXDESC];                 // cumulated (multiline) desc.
  238.   int    b,i,j,k,m,n,p;                 // counters
  239.   int    low,high,index;                // indexes
  240.   int    fpriv, rc;                     // file privilege, returncode
  241.   char   desc_spec[MAXPATH];
  242.   char   *fd;                           // pointer to file description
  243.   struct _filechain **fa;               // pointer to file sort-array
  244.   static char prop[4]    = "/─\\|";     // rotating propeller
  245.  
  246.   if (strlen(parea->filesbbs) > 0)      // explicit specification?
  247.     strcpy(desc_spec,parea->filesbbs);  // explicitly specified FileList
  248.   else {                                // no
  249.     strcpy(desc_spec,parea->pname);     // get path to download directory
  250.     strcat(desc_spec,lp[P_FIL].name);   // add filename
  251.     strcat(desc_spec,".");              // add separator
  252.     strcat(desc_spec,lp[P_FIL].ext);    // add extension
  253.     }
  254.  
  255.   fpriv = parea->priv;                  // area-priv is default file priv
  256.  
  257.                                         // FILES.BBS may be in use!!!
  258.   rc = DosOpen(desc_spec,               // Open 'carefully'
  259.           &fih,                         // pointer to File Handle
  260.           &oaction,                     // pointer to action field
  261.           0L,                           // new filesize (N/A)
  262.           FILE_NORMAL,                  // attributes
  263.           FILE_OPEN,                    // open flags
  264.           OPEN_ACCESS_READONLY  |       // access flags
  265.             OPEN_SHARE_DENYNONE |
  266.             OPEN_FLAGS_SEQUENTIAL |
  267.             OPEN_FLAGS_NOINHERIT,
  268.           0L);                          // reserved
  269.   if (rc != NO_ERROR || oaction != FILE_EXISTED) {  // not found
  270.     printf("\n       Description file %s not found,",desc_spec);
  271.     return;                             // no: return to caller
  272.     }
  273.   if ((fi = fdopen(fih,"r")) == NULL) { // open stream with file handle
  274.     printf("\n       Description file %s not found,",desc_spec);
  275.     return;                             // no: return to caller
  276.     }
  277.  
  278.   fa = (struct _filechain **)malloc(x*sizeof(struct _filechain *));
  279.   if (fa == NULL) {                     // not enough memory
  280.     printf(MSG_MEM,PROGNAME);
  281.     exit(11);
  282.     }
  283.   ce = cp;                              // ptr to first file-info
  284.   for (i=0; i<x; i++) {                 // init sort array
  285.     fa[i] = ce;
  286.     ce = ce->next_element;
  287.     }
  288.   qsort(fa,x,sizeof(struct _filechain *),sort_gbl); // sort file pointers
  289.  
  290.   rp = fgets(buf,sizeof buf,fi);        // get first record
  291.   while (rp != NULL) {                  // until end of file reached
  292.     m = strlen(buf);                    // length of input string
  293.     if (buf[0] == '\20') {              // privilege change (^P?)
  294.       for (k=0; k<HIDDEN-TWIT && priv_name[k][0]!=buf[1]; k++);
  295.       if (TWIT + k > parea->priv)       // only higher accepted
  296.         fpriv = TWIT + k;               // new (higher) prilivege
  297.       rp = fgets(buf,sizeof buf,fi);    // continue
  298.       }
  299.     else if ( buf[0] <= ' '  ||
  300.               buf[0] == '\"' ||
  301.              (buf[0] >= '+'  && buf[0] <= '/')  ||
  302.              (buf[0] >= ':'  && buf[0] <= '>')  ||
  303.              (buf[0] >= '['  && buf[0] <= ']')  ||
  304.               buf[0] == '|'  ||
  305.               buf[0] >= 128)            // non-filename: ignore line
  306.       rp = fgets(buf,sizeof buf,fi);    // continue
  307.     else {                              // probably file descr record
  308.       for (i=0; i < MAXFN-1     &&      // maximum filename length (8.3)
  309.                 i < m           &&      // input string length
  310.                 buf[i] != ' '   &&
  311.                 buf[i] != '\n'; i++);   // scan for filespec
  312.       strncpy(filename,buf,i);          // save filename
  313.       filename[i] = '\0';               // end of string
  314.  
  315.       desc = next_word(buf);            // locate description
  316.       if (desc != NULL) {               // start of description found
  317.         for (k=0; desc[k]; ++k)
  318.           if (desc[k]=='\r' || desc[k]=='\n') {
  319.             desc[k] = '\0';
  320.             break;
  321.             }
  322.         strcpy(buf2,desc);              // save desc in buf2
  323.         while (((rp = fgets(buf,sizeof buf,fi)) != NULL) &&  // next rcd
  324.                (buf[0] == ' ') &&        // probably desc continuation
  325.                ((desc = next_word(buf)) != NULL)) {  // locate desc
  326.           for (k=0; desc[k]!='\0'; ++k)
  327.             if (desc[k]=='\r' || desc[k]=='\n') {
  328.               desc[k] = '\0';
  329.               break;
  330.               }
  331.           if ((strlen(buf2) + k + 1) <= sizeof(buf2)) {  // not too long
  332.             strcat(buf2," ");           // single space
  333.             strcat(buf2,desc);          // concat desc to buf2
  334.             }
  335.           }
  336.         fd = malloc(strlen(buf2)+1);    // obtain memory
  337.         if (fd == NULL) {
  338.           printf(MSG_MEM,PROGNAME);     // not enough memory
  339.           exit(12);
  340.           }
  341.         else
  342.           strcpy(fd,buf2);              // store description
  343.         }
  344.       else
  345.         rp = fgets(buf,sizeof buf,fi);  // no desc: continue
  346.  
  347.       j = 0;                            // first wild-compare
  348.       low  = 0;                         // index of first entry
  349.       high = x-1;                       // index of last entry
  350.       while (low <= high) {             // binary search in array
  351.         index = (high + low) / 2;       // middle of interval
  352.         if ((b = wild_comp(j,fa[index]->fname,filename)) < 0)
  353.           low = index + 1;              // new low boundary
  354.         else if (b > 0)
  355.           high = index - 1;             // new high boundary
  356.         else
  357.           break;                        // equal: found
  358.         j = 1;                          // subsequent wild-compares
  359.         }
  360.  
  361.       n = index;
  362.       while (n>=0 && wild_comp(0,fa[n]->fname,filename) == 0) {
  363.         if (fa[n]->fdesc == NULL)       // no description assigned yet
  364.           fa[n]->fdesc = (desc) ? fd : NDS;  // ptr to description
  365.         fa[n]->priv = fpriv;            // copy privilege
  366.         --n;                            // next lower
  367.         }
  368.  
  369.       n = index + 1;
  370.       while (n<x && wild_comp(0,fa[n]->fname,filename) == 0) {
  371.         if (fa[n]->fdesc == NULL)       // no description assigned yet
  372.           fa[n]->fdesc = (desc) ? fd : NDS;    // ptr to description
  373.         fa[n]->priv = fpriv;            // copy privilege
  374.         ++n;                            // next higher
  375.         }
  376.       }
  377.  
  378.     if (oper_mode == VERBOSE)
  379.       cprintf("\r%c",prop[p=(++p)&3]);  // propeller
  380.     }
  381.   if (oper_mode == VERBOSE)
  382.     cprintf("\r ");                     // clear propeller
  383.   free(fa);                             // free temp sort array
  384.   fclose(fi);                           // finished with this FILES.BBS
  385.   DosClose(fih);                        // close the handle
  386.   }
  387.  
  388. /* ------------------------------ */
  389. /* Build pointer-array for sorts  */
  390. /* ------------------------------ */
  391. struct _filechain **prep_sort(cnt,chn)
  392. USHORT  cnt;                            // file count
  393. struct  _filechain *chn;                // pointer to fileinfo struct
  394. {
  395.   USHORT  i;                            // counter
  396.   struct  _filechain **dm;              // pointer to file-sort array
  397.   struct  _filechain *ca;               // pointer to fileinfo (chain)
  398.  
  399.   dm = (struct _filechain **)malloc(cnt*sizeof(struct _filechain *));
  400.   if (dm == NULL) {                     // not enough memory
  401.     printf(MSG_MEM,PROGNAME);
  402.     exit(11);
  403.     }
  404.   ca = chn;                             // ptr to first file-info
  405.   for (i=0; ca != NULL; i++) {          // init sort array
  406.     dm[i] = ca;
  407.     ca = ca->next_element;
  408.     }
  409.   return(dm);
  410.   }
  411.  
  412.