home *** CD-ROM | disk | FTP | other *** search
- /* ============================================================= */
- /* Rob Hamerling's MAXIMUS download file scan and sort utility. */
- /* -> Functions to collect download file information. */
- /* ============================================================= */
-
- #define INCL_BASE
- #include <os2.h>
-
- #include "downsort.h"
-
- #include <conio.h>
- #include <fcntl.h>
- #include <io.h>
- #include <share.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <sys\types.h>
- #include <sys\stat.h>
-
- /* ---------------------------- */
- /* Collect download file area's */
- /* ---------------------------- */
- USHORT collect_down(area)
- struct _downpath **area; // pointer to area-info pointer array
- {
- USHORT af,oaction; // file handle, open_action
- int i,j,m,rc; // counters, returncode
- unsigned int k; // #area's
- union _areamax u; // MAXIMUS area-file record(s)
- struct _downpath *d; // ptrs to array of area-info
- struct stat fs; // file status buffer
-
- rc = DosOpen(areadat_path, // Open 'carefully'
- &af, // pointer to File Handle
- &oaction, // pointer to action field
- 0L, // new filesize (N/A)
- FILE_NORMAL, // attributes
- FILE_OPEN, // open flags
- OPEN_ACCESS_READONLY | // access flags
- OPEN_SHARE_DENYWRITE |
- OPEN_FLAGS_RANDOMSEQUENTIAL |
- OPEN_FLAGS_NOINHERIT,
- 0L); // reserved
- if (rc != NO_ERROR) { // open error
- printf(OPEN_FAIL,areadat_path);
- exit(rc);
- }
- if (oaction != FILE_EXISTED) { // not found
- printf(OPEN_FAIL,areadat_path);
- exit(5);
- }
- else {
- if (oper_mode == VERBOSE)
- printf("\nReading file-area information from %s",areadat_path);
- stat(areadat_path,&fs); // get status of AREA.DAT
- read(af,(char *)&u,sizeof(struct _area)); // obtain first record
- if (u.a.id == AREA_id) {
- MAX_level = 102; // looks like version 1.02
- k = (int)(fs.st_size / u.a.struct_len);
- }
- else if (u.a1.struct_len == sizeof(struct _area100)) {
- MAX_level = 100; // looks like version 1.00
- k = (int)(fs.st_size / u.a1.struct_len);
- }
- else {
- printf("\nSorry, unsupported format of %s-file!",areadat_path);
- printf("\n%s %d.%d%c works for %s version 1.00 and 1.02!",
- PROGNAME,VERSION,SUBVERS,SUFFIX,MAX);
- exit(8); // wrong version of AREA.DATA
- }
-
- d = (struct _downpath *)calloc(k,sizeof(struct _downpath));
- if (d == NULL) { // memory not obtained?
- printf(MSG_MEM,PROGNAME);
- exit(6);
- }
- else {
- *area = d; // return pointer to caller
- for (i=0,m=0; i<k; i++) { // all area records
- if (MAX_level == 102) { // use version 1.02 layout
- lseek(af,i*(long)u.a.struct_len,SEEK_SET); // locate to next
- read(af,(char *)&u,sizeof(struct _area));
- if (u.a.filepath[0] != '\0' && u.a.filepath[0] != ' ') {
- d[m].priv = u.a.filepriv; // download privilege
- strcpy(d[m].name,u.a.name); // area name
- strcpy(d[m].pname,u.a.filepath); // download path
- strcpy(d[m].filesbbs,u.a.filesbbs); // files.bbs
- strcpy(d[m].adesc,u.a.fileinfo); // filearea title
- ++m; // active filearea count
- }
- }
- else { // use version 1.00 layout
- lseek(af,i*(long)u.a1.struct_len,SEEK_SET); // locate to next
- read(af,(char *)&u,sizeof(struct _area100));
- if (u.a1.filepath[0] != '\0' && u.a1.filepath[0] != ' ') {
- d[m].priv = u.a1.filepriv; // download privilege
- strcpy(d[m].name,u.a1.name); // area name
- strcpy(d[m].pname,u.a1.filepath); //download path
- strcpy(d[m].filesbbs,u.a1.filesbbs); // files.bbs
- strcpy(d[m].adesc,u.a1.fileinfo); // filearea title
- ++m; // active filearea count
- }
- }
- if (d[m-1].name[0] != '\0' && d[m-1].name[1] == '\0') { // single char?
- d[m-1].name[1] = d[m-1].name[0]; // shift right 1
- d[m-1].name[0] = ' '; // leading blank
- }
- j = strlen(d[m-1].pname);
- if (j>0 && d[m-1].pname[j-1] != '\\')
- d[m-1].pname[j] = '\\'; // add backslash if needed
- }
- }
- DosClose(af); // close area.dat-file
- return(m); // report number of downloadarea's
- }
- }
-
- /* ---------------------------- */
- /* Collect all file information */
- /* ---------------------------- */
- USHORT collect_file(m,area)
- USHORT m; // number of download area's
- struct _downpath *area; // pointer to download path array
- {
- unsigned int i,k,fc; // counters
- struct _filechain *ca,*ce; // ptrs to file info
-
- ca = NULL; // empty chain!
- fc = 0; // total file-counter
- for (i=0; i<m; i++) { // all download paths
- k = fill_chn(&area[i],&ca,&ce); // files in area
- // returns ptrs first/last active
- if (oper_mode == VERBOSE)
- printf("\n %5d files in area %-.2s (Priv=%c) DL-dir=%s",
- k,area[i].name,
- priv_name[area[i].priv-TWIT][0],
- area[i].pname);
- if (k > 0) { // any files in this area?
- if (first_element == NULL)
- first_element = ca; // pointer to very first
- get_desc(k,ca,&area[i]); // obtain descriptions
- fc += k; // total counter
- }
- ca = ce; // for next area
- }
- return(fc);
- }
-
- /* ---------------------------------------- */
- /* Add all subdir-filenames to the chain, */
- /* for further processing by mainline. */
- /* NOTE: full path name assumed! */
- /* ---------------------------------------- */
- USHORT fill_chn(parea,cp,cq)
- struct _downpath *parea; // pointer to download-info
- struct _filechain **cp,**cq; // ptrs to ptr first/last element
- {
- int rc; // returncode of DOS-calls
- USHORT fc; // area-file counter
- struct _filechain *ca,*ce,*tp; // new curr temp chain pointers
- struct _FILEFINDBUF cf; // OS file-info buffer
- char down_spec[MAXPATH]; // file specification buffer
- HDIR fhandle; // FindFirst/Last handle
- USHORT fentries; // # entries to be retrieved
-
- fc = 0; // init filecount of this area
- ce = ca = *cp; // ptr to last active element
- strcpy(down_spec,parea->pname); // path
- strcat(down_spec,"*.*"); // file-spec
- fentries = 1; // one at a time!
- fhandle = HDIR_CREATE; // new file handle
- // #define FILE_NORMAL 0 // not defined in TOOLKIT 1.1
- rc = DosFindFirst(down_spec,&fhandle,FILE_NORMAL,&cf,
- sizeof(struct _FILEFINDBUF),&fentries,0L);
- while (rc == 0) {
- if ((wild_comp(0,cf.achName,"FILES.?BS") != 0) &&
- (wild_comp(0,cf.achName,"*.BAK") != 0) &&
- (wild_comp(0,cf.achName,"SYSTEM*.?BS") != 0) &&
- (wild_comp(0,cf.achName,"DIR.?BS") != 0)) {
- tp = (struct _filechain *)malloc(sizeof(struct _filechain));
- if (tp == NULL) {
- printf(MSG_MEM,PROGNAME); // not enough memory
- exit(11);
- }
- if (ca == NULL) // very first element
- ca = ce = tp; // ptr to first and last active!
- else { // not very first
- if (fc == 0) // first in this area
- ca = tp; // ptr to first active this area
- ce->next_element = tp; // chain-ptr in current element
- ce = tp; // ptr to last active
- }
- ++fc; // update filecount this area
- ce->next_element = NULL; // copy/init fields
- ce->parea = parea;
- ce->wdate = cf.fdateLastWrite;
- ce->wtime = cf.ftimeLastWrite;
- if (file_time(cf.fdateCreation,cf.ftimeCreation) >
- file_time(cf.fdateLastWrite,cf.ftimeLastWrite) ) {
- ce->cdate = cf.fdateCreation; // creation most recent
- ce->ctime = cf.ftimeCreation;
- }
- else { // otherwise and non-HPFS volumes
- ce->cdate = cf.fdateLastWrite;
- ce->ctime = cf.ftimeLastWrite;
- }
- ce->size = cf.cbFile;
- byte_count += cf.cbFile;
- ce->attr = cf.attrFile;
- ce->priv = HIDDEN; // unless FILES.BBS proves otherwise
- strncpy(ce->fname,cf.achName,MAXFN);
- ce->fdesc = NULL; // unless later found in FILES.BBS
- }
- rc = DosFindNext(fhandle,&cf,sizeof(struct _FILEFINDBUF),&fentries);
- }
- DosFindClose(fhandle); // close directory association
- *cp = ca; // pointer to first new this area
- *cq = ce; // pointer to last new this area
- return(fc);
- }
-
- /* ------------------------------ */
- /* Add file description to chain */
- /* ------------------------------ */
- void get_desc(x,cp,parea)
- int x; // number of file-entries
- struct _filechain *cp; // ptr to ptr to first of group
- struct _downpath *parea; // pointer to area-info
- {
- FILE *fi; // file pointer
- USHORT fih,oaction; // file handle, open-action
- struct _filechain *ce; // ptrs to file-info
- char buf[MAXRCD]; // read-buffer for FILES.BBS
- char filename[MAXFN]; // filename from FILES.BBS buf
- char *desc,*rp; // ptr to desc / return val gets()
- char buf2[MAXDESC]; // cumulated (multiline) desc.
- int b,i,j,k,m,n,p; // counters
- int low,high,index; // indexes
- int fpriv, rc; // file privilege, returncode
- char desc_spec[MAXPATH];
- char *fd; // pointer to file description
- struct _filechain **fa; // pointer to file sort-array
- static char prop[4] = "/─\\|"; // rotating propeller
-
- if (strlen(parea->filesbbs) > 0) // explicit specification?
- strcpy(desc_spec,parea->filesbbs); // explicitly specified FileList
- else { // no
- strcpy(desc_spec,parea->pname); // get path to download directory
- strcat(desc_spec,lp[P_FIL].name); // add filename
- strcat(desc_spec,"."); // add separator
- strcat(desc_spec,lp[P_FIL].ext); // add extension
- }
-
- fpriv = parea->priv; // area-priv is default file priv
-
- // FILES.BBS may be in use!!!
- rc = DosOpen(desc_spec, // Open 'carefully'
- &fih, // pointer to File Handle
- &oaction, // pointer to action field
- 0L, // new filesize (N/A)
- FILE_NORMAL, // attributes
- FILE_OPEN, // open flags
- OPEN_ACCESS_READONLY | // access flags
- OPEN_SHARE_DENYNONE |
- OPEN_FLAGS_SEQUENTIAL |
- OPEN_FLAGS_NOINHERIT,
- 0L); // reserved
- if (rc != NO_ERROR || oaction != FILE_EXISTED) { // not found
- printf("\n Description file %s not found,",desc_spec);
- return; // no: return to caller
- }
- if ((fi = fdopen(fih,"r")) == NULL) { // open stream with file handle
- printf("\n Description file %s not found,",desc_spec);
- return; // no: return to caller
- }
-
- fa = (struct _filechain **)malloc(x*sizeof(struct _filechain *));
- if (fa == NULL) { // not enough memory
- printf(MSG_MEM,PROGNAME);
- exit(11);
- }
- ce = cp; // ptr to first file-info
- for (i=0; i<x; i++) { // init sort array
- fa[i] = ce;
- ce = ce->next_element;
- }
- qsort(fa,x,sizeof(struct _filechain *),sort_gbl); // sort file pointers
-
- rp = fgets(buf,sizeof buf,fi); // get first record
- while (rp != NULL) { // until end of file reached
- m = strlen(buf); // length of input string
- if (buf[0] == '\20') { // privilege change (^P?)
- for (k=0; k<HIDDEN-TWIT && priv_name[k][0]!=buf[1]; k++);
- if (TWIT + k > parea->priv) // only higher accepted
- fpriv = TWIT + k; // new (higher) prilivege
- rp = fgets(buf,sizeof buf,fi); // continue
- }
- else if ( buf[0] <= ' ' ||
- buf[0] == '\"' ||
- (buf[0] >= '+' && buf[0] <= '/') ||
- (buf[0] >= ':' && buf[0] <= '>') ||
- (buf[0] >= '[' && buf[0] <= ']') ||
- buf[0] == '|' ||
- buf[0] >= 128) // non-filename: ignore line
- rp = fgets(buf,sizeof buf,fi); // continue
- else { // probably file descr record
- for (i=0; i < MAXFN-1 && // maximum filename length (8.3)
- i < m && // input string length
- buf[i] != ' ' &&
- buf[i] != '\n'; i++); // scan for filespec
- strncpy(filename,buf,i); // save filename
- filename[i] = '\0'; // end of string
-
- desc = next_word(buf); // locate description
- if (desc != NULL) { // start of description found
- for (k=0; desc[k]; ++k)
- if (desc[k]=='\r' || desc[k]=='\n') {
- desc[k] = '\0';
- break;
- }
- strcpy(buf2,desc); // save desc in buf2
- while (((rp = fgets(buf,sizeof buf,fi)) != NULL) && // next rcd
- (buf[0] == ' ') && // probably desc continuation
- ((desc = next_word(buf)) != NULL)) { // locate desc
- for (k=0; desc[k]!='\0'; ++k)
- if (desc[k]=='\r' || desc[k]=='\n') {
- desc[k] = '\0';
- break;
- }
- if ((strlen(buf2) + k + 1) <= sizeof(buf2)) { // not too long
- strcat(buf2," "); // single space
- strcat(buf2,desc); // concat desc to buf2
- }
- }
- fd = malloc(strlen(buf2)+1); // obtain memory
- if (fd == NULL) {
- printf(MSG_MEM,PROGNAME); // not enough memory
- exit(12);
- }
- else
- strcpy(fd,buf2); // store description
- }
- else
- rp = fgets(buf,sizeof buf,fi); // no desc: continue
-
- j = 0; // first wild-compare
- low = 0; // index of first entry
- high = x-1; // index of last entry
- while (low <= high) { // binary search in array
- index = (high + low) / 2; // middle of interval
- if ((b = wild_comp(j,fa[index]->fname,filename)) < 0)
- low = index + 1; // new low boundary
- else if (b > 0)
- high = index - 1; // new high boundary
- else
- break; // equal: found
- j = 1; // subsequent wild-compares
- }
-
- n = index;
- while (n>=0 && wild_comp(0,fa[n]->fname,filename) == 0) {
- if (fa[n]->fdesc == NULL) // no description assigned yet
- fa[n]->fdesc = (desc) ? fd : NDS; // ptr to description
- fa[n]->priv = fpriv; // copy privilege
- --n; // next lower
- }
-
- n = index + 1;
- while (n<x && wild_comp(0,fa[n]->fname,filename) == 0) {
- if (fa[n]->fdesc == NULL) // no description assigned yet
- fa[n]->fdesc = (desc) ? fd : NDS; // ptr to description
- fa[n]->priv = fpriv; // copy privilege
- ++n; // next higher
- }
- }
-
- if (oper_mode == VERBOSE)
- cprintf("\r%c",prop[p=(++p)&3]); // propeller
- }
- if (oper_mode == VERBOSE)
- cprintf("\r "); // clear propeller
- free(fa); // free temp sort array
- fclose(fi); // finished with this FILES.BBS
- DosClose(fih); // close the handle
- }
-
- /* ------------------------------ */
- /* Build pointer-array for sorts */
- /* ------------------------------ */
- struct _filechain **prep_sort(cnt,chn)
- USHORT cnt; // file count
- struct _filechain *chn; // pointer to fileinfo struct
- {
- USHORT i; // counter
- struct _filechain **dm; // pointer to file-sort array
- struct _filechain *ca; // pointer to fileinfo (chain)
-
- dm = (struct _filechain **)malloc(cnt*sizeof(struct _filechain *));
- if (dm == NULL) { // not enough memory
- printf(MSG_MEM,PROGNAME);
- exit(11);
- }
- ca = chn; // ptr to first file-info
- for (i=0; ca != NULL; i++) { // init sort array
- dm[i] = ca;
- ca = ca->next_element;
- }
- return(dm);
- }
-
-