home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Professional
/
OS2PRO194.ISO
/
os2
/
com
/
bbs
/
downsrt
/
source
/
downcol.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-06-06
|
21KB
|
463 lines
/* ============================================================= */
/* Rob Hamerling's MAXIMUS download file scan and sort utility. */
/* -> Functions to collect download file information. */
/* ============================================================= */
#define INCL_BASE
#include <os2.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>
#include "downsort.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
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(" 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=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
{
USHORT i,k,n,fc; // counters
struct _filechain *ca; // ptr to file info
ca = NULL; // empty chain!
fc = 0; // total file-counter
for (i=0; i<m; i++) { // all download paths
if (area[i].priv <= ABS_MAX_priv) { // within report privilege
// returns ptrs first/last active
if (oper_mode == VERBOSE)
printf("\n files in area %-.2s (Priv=%c) DL-dir=%s",
area[i].name,
priv_name[area[i].priv-TWIT][0],
area[i].pname);
k = fill_chn(&area[i],&ca); // files in area
if (oper_mode == VERBOSE)
printf("\r %5d",k);
if (k > 0) { // any files in this area?
if (first_element == NULL)
first_element = ca; // ptr to very first element
get_desc(k,ca,&area[i]); // obtain descriptions
n = 0; // suppose no orphans
if (lp[P_ORP].priv[0] > HIDDEN) { // orphan report not req'd
n = free_orphan(ca); // get rid of orphan-entries
if (n > 0 && oper_mode==VERBOSE)
printf("\n %5u orphans dropped",n);
}
fc += k - n; // total counter
}
if (ca != NULL) {
while (ca->next_element != NULL) // find last
ca = ca->next_element;
}
}
}
return(fc);
}
/* ---------------------------------------- */
/* Add all subdir-filenames to the chain, */
/* for further processing by mainline. */
/* NOTE: full path name assumed! */
/* ---------------------------------------- */
USHORT fill_chn(parea,cp)
struct _downpath *parea; // pointer to download-info
struct _filechain **cp; // 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
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
if (oper_mode==VERBOSE && (fc%25)==0) // every 25 files
cprintf("\r %5u",fc);
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->fseq = 65535; // max FILES.BBS line number
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
return(fc);
}
/* ---------------------------------------- */
/* Free memory occupied by orphan entries. */
/* ---------------------------------------- */
USHORT free_orphan(cp)
struct _filechain *cp; // ptr to first of chain-element
{
USHORT orp_cnt; // removed orphan counter
struct _filechain *ca,*cb; // current and next chain pointer
orp_cnt = 0; // orphan counter
ca = cp; // ptr to current element
while ((cb = ca->next_element) != NULL) { // all (but first)
if (cb->priv >= HIDDEN) { // probably orphan?
ca->next_element = cb->next_element; // new ptr in current element
free(cb); // free memory block
++orp_cnt; // one more dropped
} // note: do not shift current
else
ca = cb; // shift +1 current element
}
return(orp_cnt); // report # of removed orphans
}
/* ------------------------------ */
/* Add file description to chain */
/* ------------------------------ */
void get_desc(x,cp,parea)
USHORT 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
USHORT bbsseq; // record number of FILES.BBS
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(DESC_MISS,desc_spec);
return; // no: return to caller
}
if ((fi = fdopen(fih,"r")) == NULL) { // open stream with file handle
printf(DESC_MISS,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
bbsseq = 1; // init counter
while (rp != NULL) { // until end of file reached
m = strlen(buf); // length of input string
if (m <= 2) { // empty line
rp = fgets(buf,sizeof buf,fi); // get next record
bbsseq++; // next line number
}
else 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 if higher than area-priv
fpriv = TWIT + k; // new (higher) prilivege
rp = fgets(buf,sizeof buf,fi); // continue
bbsseq++; // next line number
}
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
bbsseq++; // next line number
}
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
}
}
bbsseq++; // next line number
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
bbsseq++;
}
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 != NULL) ? fd : NDS; // ptr to description
fa[n]->priv = fpriv; // copy privilege
fa[n]->fseq = bbsseq; // copy FILES.BBS line number
--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 != NULL) ? fd : NDS; // ptr to description
fa[n]->priv = fpriv; // copy privilege
fa[n]->fseq = bbsseq; // copy FILES.BBS line number
++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);
}