home *** CD-ROM | disk | FTP | other *** search
- static char *copyright = "findfile.c: Copyright (c) 1990. Stephen J Doyle";
- /*
- * findfile: Copyright (c) 1990. Stephen J Doyle.
- *
- * This software remains the property of the author Stephen J Doyle.
- * This software is supplied 'as is' and without express or implied
- * warranty.
- * Permission is granted to copy, distribute or modify this program
- * provided this copyright message is included with the modified program
- * and any modifications are commented or highlighted in the program text.
- *
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <dir.h>
- #include <dos.h>
- #include <assert.h>
- #include <ctype.h>
-
- typedef int int16;
- typedef long int32;
- typedef unsigned int uint16;
-
- static char *spec="*.*";
- static char *prune=NULL;
- static char **prunedirs;
- static int nprunes=0;
- static char *root=NULL;
- static int32 minsize=0, maxsize=0;
- static unsigned int spacing;
- static int attrib=0;
- static int extsort=0;
- static int ls=0;
- static char *LS=NULL;
- static int LSlen;
- static int dirsep;
- static int switchar;
- static int reversesort=0;
-
- /*
- * Directory entry information recorded for sorting
- */
- struct dent {
- char name[13];
- char attrib;
- int32 size;
- uint16 date, time;
- };
-
- typedef struct dent *Dentptr;
-
- /*
- * Simple boolean type
- */
- typedef enum {
- True = 1,
- False = 0
- } Boolean;
-
- /*
- * Comparison types
- */
- typedef enum {
- None,
- GreaterThan,
- LessThan,
- Equal,
- GreaterOrEqual,
- LessThanOrEqual,
- UnEqual
- } Comparison;
-
- /*
- * Date/time held as individual and composite values
- * with comaprison/masking details for checking time/date
- * of file against user defined value
- */
- struct mytime {
- Comparison comparison;
- uint16 year;
- unsigned char
- month,
- day,
- hour,
- mins,
- sec;
- uint16 date, time;
- uint16 datemask, timemask;
- } DateTime = {None};
-
- typedef struct mytime Mytime, *MytimePtr;
-
- /*
- * Allocation multiple when allocating directory entries, this avoids
- * too frequent calls to realloc
- */
- #define ALLOCSIZE 32
-
- /*
- * In the interests of internationalization, country specific data
- */
- struct country countrydata;
- char dtsep, tmsep;
- typedef enum {
- DateAmerica = 0,
- DateEurope = 1,
- DateJapan = 2
- } DateFormat;
-
- DateFormat dateformat;
-
- /*
- * Check that the program keeps proper track of all requests to
- * allocate, adjust or free memory.
- */
- int32 mallocspace=0;
-
- void *mymalloc(size_t size){
-
- void *t=(void *)malloc(size+sizeof(size_t));
- if (!t){
- fprintf(stderr, "Out of memory in malloc\n");
- abort();
- } else {
- *((size_t *)t)=size;
- mallocspace+=size;
- t=(void *)(((char *)t)+sizeof(size_t));
- }
- return(t);
- }
-
- void *myrealloc(void *ptr, size_t newsize){
- void *t=(void *)(((char *)ptr)-sizeof(size_t));
-
- mallocspace-= *((size_t *)t);
-
- t=(void *)realloc(t, newsize);
-
- if (!t){
- fprintf(stderr, "Out of memory in realloc\n");
- abort();
- } else {
- *((size_t *)t)=newsize;
- mallocspace+=newsize;
- t=(void *)(((char *)t)+sizeof(size_t));
- }
- return(t);
- }
-
- void myfree(void *ptr){
- void *t=(void *)(((char *)ptr)-sizeof(size_t));
-
- mallocspace-= *((size_t *)t);
- free(t);
- }
-
- /*
- * Check the time stamp of a file against the user defined value
- */
- Boolean TimeMatch(uint16 date, uint16 time){
- Boolean result;
- date&=DateTime.datemask;
- time&=DateTime.timemask;
- switch(DateTime.comparison){
- case None:
- result=True;
- break;
- case Equal:
- result=((date==DateTime.date)&&
- (time==DateTime.time))?True:False;
- break;
- case UnEqual:
- result=((date!=DateTime.date)||
- (time!=DateTime.time))?True:False;
- break;
- case LessThan:
- result=((date<DateTime.date)||
- ((date==DateTime.date)&&
- (time<DateTime.time)))?True:False;
- break;
- case LessThanOrEqual:
- result=((date<DateTime.date)||
- ((date==DateTime.date)&&
- (time<=DateTime.time)))?True:False;
- break;
- case GreaterThan:
- result=((date>DateTime.date)||
- ((date==DateTime.date)&&
- (time>DateTime.time)))?True:False;
- break;
- case GreaterOrEqual:
- result=((date>DateTime.date)||
- ((date==DateTime.date)&&
- (time>=DateTime.time)))?True:False;
- break;
- default:
- fprintf(stderr, "Invalid time comparison case. Internal error\n");
- abort();
- break;
- }
- return(result);
- }
-
- /*
- * Check a filename against a given specification (which may contain * or ?
- * wildcards in any position) to see if the name matches the specification.
- */
- Boolean matchspec(char *spec, char *name, int len){
- Boolean res;
- int i;
- if (spec[0]=='\0'){
- res=(name[0]=='\0')?True:False;
- } else if (spec[0]=='?') {
- res = ((len>0) && (matchspec(&spec[1], &name[1], len-1)==True))
- ?True:False;
- } else if (spec[0]=='*'){
- if ((len==0) || (spec[1]=='\0')) res=True;
- else {
- for (i=len-1; i>=0; i--) {
- if (matchspec(&spec[1], &name[i], len-i)==True)
- break;
- }
- res=(i>=0)?True:False;
- }
- } else {
- res= ((spec[0]==name[0])&&(len>0)&&(matchspec(&spec[1], &name[1], len-1)==True))?True:False;
- }
- return(res);
- }
-
- /*
- * Search out the files of the current directory to try and display
- * those matching the users search criterion.
- */
- void displaydir(char *parent)
- {
- struct ffblk entry;
- int i, lt, j, finished, len, sl;
- char *path;
- char extra[40]={'\0'};
- int extraptr=0;
- Dentptr dents;
- Dentptr *sortarr=NULL, swaptmp;
- int dentcount=0;
-
- dents=(Dentptr)mymalloc(sizeof(struct dent)*ALLOCSIZE);
-
- /*
- * From the parent directory workk out the file specification used in
- * the file search
- */
- if (parent==NULL) {
- len=0;
- path=(char *)mymalloc(len+13);
- } else {
- int addsep;
- len=strlen(parent);
- addsep=(parent[len-1]!=dirsep);
- if (addsep) ++len;
- path=(char *)mymalloc(len+13);
- strcpy(path, parent);
- if (addsep) path[len-1]=dirsep;
- }
- sprintf(&path[len], "*.*");
- strlwr(path);
-
- /*
- * Make a first pass to find all none directory files matching the
- * specification
- */
- if (findfirst(path, &entry, attrib & ~FA_DIREC)==0){
- do {
- strlwr(entry.ff_name);
-
- /*
- * Check file name against spec, size against min and max values
- * and time stamp
- */
- if ((matchspec(spec, entry.ff_name, strlen(entry.ff_name))==True)&&
- ((minsize==0)||
- (entry.ff_fsize>=minsize))&&
- ((maxsize==0)||
- (entry.ff_fsize<=maxsize))&&
- TimeMatch(entry.ff_fdate, entry.ff_ftime)){
- struct dent *dp= &dents[dentcount];
-
- /*
- * Store the file details
- */
- dp->attrib=entry.ff_attrib;
- dp->size=entry.ff_fsize;
- dp->date=entry.ff_fdate;
- dp->time=entry.ff_ftime;
- strcpy(dp->name, entry.ff_name);
-
- /*
- * If used up all current block of entries, append a further
- * block
- */
- if (((++dentcount)%ALLOCSIZE)==0){
- dents=(struct dent *)myrealloc(dents,
- (dentcount+ALLOCSIZE)*sizeof(struct dent));
- }
- }
- } while (findnext(&entry)==0);
- }
-
- /*
- * Now make another search to find the directories
- */
- sprintf(&path[len], "*.*");
- if (findfirst(path, &entry, FA_DIREC)==0){
- do {
-
- /*
- * Discard entries which are not directories or are the
- * entries for the current/parent directories or are
- * directories that the user wants to exclude
- */
- if ((entry.ff_attrib&FA_DIREC)&&
- (strcmp(entry.ff_name, ".")!=0)&&
- (strcmp(entry.ff_name, "..")!=0)){
- int discard=0;
- int elen=strlen(entry.ff_name);
- strlwr(entry.ff_name);
- if (prune){
- for (i=0; i<nprunes; i++){
- if (matchspec(prunedirs[i], entry.ff_name, elen)){
- discard=1;
- break;
- }
- }
- }
- if (!discard){
- struct dent *dp= &dents[dentcount];
-
- /*
- * Store the directory details
- */
- dp->attrib=entry.ff_attrib;
- dp->size=entry.ff_fsize;
- dp->date=entry.ff_fdate;
- dp->time=entry.ff_ftime;
-
- strcpy(dp->name, entry.ff_name);
-
- /*
- * If used up all current block of entries, append a further
- * block
- */
- if (((++dentcount)%ALLOCSIZE)==0){
- dents=(struct dent *)myrealloc(dents,
- (dentcount+ALLOCSIZE)*sizeof(struct dent));
- }
- }
- }
- } while (findnext(&entry)==0);
- }
-
- path[len]='\0';
-
- /*
- * If anything found, proceed
- */
- if (dentcount){
-
- /*
- * The filename table now has to be sorted. To enable this to
- * be reasonably fast a binary chop algorithm is used to swap
- * pointers.
- */
- sortarr=(Dentptr *)mymalloc(dentcount*sizeof(Dentptr));
- for (j=0; j<dentcount; j++)
- sortarr[j]= &dents[j];
-
- spacing=((dentcount)/2);
- for (i=(sizeof(spacing)*8-1); i>0; i--)
- if (spacing&(1<<i)) break;
-
- for (spacing=1<<i; spacing>0; spacing/=2)
- for (j=0; j<(dentcount-spacing); j++)
- if (extsort) {
- int m, n, s1, s2;
-
- /*
- * Extension precedence sort, check file extensions
- * first then the file name portion
- */
- for (m=0; sortarr[j]->name[m]!='\0'&&
- sortarr[j]->name[m]!='.'; m++);
- for (n=0; sortarr[j+spacing]->name[n]!='\0'&&
- sortarr[j+spacing]->name[n]!='.'; n++);
- if (((s1=strcmp(&sortarr[j]->name[m],
- &sortarr[j+spacing]->name[n]))>0)||
- ((s1==0)&&
- ((s2=strncmp(sortarr[j]->name, sortarr[j+spacing]->name,
- min(m, n)))>0)||
- ((s2==0)&&(m>n)))){
- swaptmp=sortarr[j];
- sortarr[j]=sortarr[j+spacing];
- sortarr[j+spacing]=swaptmp;
- }
- } else {
-
- /*
- * Sort by file name then extension, this is much simpler
- */
- if (strcmp(sortarr[j]->name, sortarr[j+spacing]->name)>0){
- swaptmp=sortarr[j];
- sortarr[j]=sortarr[j+spacing];
- sortarr[j+spacing]=swaptmp;
- }
- }
-
- /*
- * Now, display the entries
- */
- if (reversesort) j=dentcount-1;
- else j=0;
- finished=0;
- while (!finished){
-
- /*
- * Display if directories are selected or the file is any other
- * file type
- */
- if ((!(sortarr[j]->attrib&FA_DIREC))||
- ((attrib&FA_DIREC)&&
- TimeMatch(sortarr[j]->date, sortarr[j]->time))){
-
- /*
- * The LS option takes precedence over the ls option.
- * For the ls option the file attributes and size (in K)
- * are displayed
- */
- if (ls & !LS) {
- char att=sortarr[j]->attrib;
- sprintf(extra, " %cr%c%c%c%c %5ldK",
- (att&FA_DIREC)?'d':'-',
- (att&FA_RDONLY)?'-':'w',
- (att&FA_HIDDEN)?'h':'-',
- (att&FA_SYSTEM)?'s':'-',
- (att&FA_ARCH)?'m':'-',
- sortarr[j]->size/1000L);
-
- /*
- * For the LS option, work through the LS argument in turn
- * so that fields are displayed in the order the user
- * specifies
- */
- } else if (LS){
- int16 date=sortarr[j]->date;
- int16 time=sortarr[j]->time;
- int32 size=sortarr[j]->size;
- char att=sortarr[j]->attrib;
- extraptr=0;
- for (i=0; i<LSlen; i++){
- switch(LS[i]){
-
- /*
- * Attribute display
- */
- case 'a':
- sprintf(&extra[extraptr], " %cr%c%c%c%c",
- (att&FA_DIREC)?'d':'-',
- (att&FA_RDONLY)?'-':'w',
- (att&FA_HIDDEN)?'h':'-',
- (att&FA_SYSTEM)?'s':'-',
- (att&FA_ARCH)?'m':'-');
- break;
-
- /*
- * File size in M bytes
- */
- case 'm':
- sprintf(&extra[extraptr], " %5ldM", size/1000000L);
- break;
-
- /*
- * File size in K bytes
- */
- case 'k':
- sprintf(&extra[extraptr], " %5ldK", size/1000L);
- break;
-
- /*
- * File size in bytes
- */
- case 's':
- sprintf(&extra[extraptr], " %6ld", size);
- break;
-
- /*
- * File time
- */
- case 't':
- sprintf(&extra[extraptr],
- " %02d%c%02d%c%02d",
- (time>>11)&0x1f,
- tmsep,
- (time>>5)&0x3f,
- tmsep,
- (time&0x1f)<<1);
- break;
-
- /*
- * Date (display in format defined
- * by country specific data).
- */
- case 'd':
- switch(dateformat){
- case DateAmerica:
- sprintf(&extra[extraptr],
- " %02d%c%02d%c%04d",
- (date>>5)&0xf,
- dtsep,
- (date&0x1f),
- dtsep,
- ((date>>9)&0x7f)+1980);
- break;
- case DateEurope:
- sprintf(&extra[extraptr],
- " %02d%c%02d%c%04d",
- (date&0x1f),
- dtsep,
- (date>>5)&0xf,
- dtsep,
- ((date>>9)&0x7f)+1980);
- break;
- case DateJapan:
- sprintf(&extra[extraptr],
- " %04d%c%02d%c%02d",
- ((date>>9)&0x7f)+1980,
- dtsep,
- (date>>5)&0xf,
- dtsep,
- (date&0x1f));
- break;
- }
- break;
- }
- extraptr=strlen(extra);
- }
- }
-
- printf("%s%s%s\n", path, sortarr[j]->name, extra);
- }
-
- /*
- * If directory, now descend into the directory to see what
- * is in it
- */
- if (sortarr[j]->attrib&FA_DIREC){
- sprintf(&path[len], "%s", sortarr[j]->name);
- displaydir(path);
- path[len]='\0';
- }
-
- /*
- * End of loop increment/decrement
- */
- if (reversesort){
- if (--j<0) finished=1;
- } else {
- if (++j>=dentcount) finished=1;
- }
- }
- myfree(sortarr);
- }
-
- myfree(dents);
- myfree(path);
- }
-
- /*
- * Display how the program is used
- */
- void usage(name, error)
- char *name;
- char *error;
- {
- struct date date;
- struct time time;
- if (error) {
- fprintf(stderr, "Illegal argument %s\n", error);
- }
- fprintf(stderr, "Usage: %s [[directory] [%coption ...] [%cp] ...]\n",
- strlwr(name), switchar, switchar);
- fprintf(stderr, "\tFile finding utility. Copyright (c) 1990 Stephen J Doyle.\n");
- fprintf(stderr, "\t (steved@inmos.co.uk)\n");
- fprintf(stderr, "Options:\n");
- fprintf(stderr, "\t%cn (%cname) - Wildcard file specification to find\n",
- switchar, switchar);
- fprintf(stderr, "\t%cx (%cxd) - Comma separated list of subdirectories not searched\n",
- switchar, switchar);
- fprintf(stderr, "\t%cs (%csort) - Sort by file extension before name\n",
- switchar, switchar);
- fprintf(stderr, "\t%cr (%crev) - Reverse order of sort\n",
- switchar, switchar);
- fprintf(stderr, "\t%ct (%ctype) ftype - Also search for files with 'ftype' attributes\n",
- switchar, switchar);
- fprintf(stderr, "\t\t[ftype can contain h(idden), s(ystem), d(irectory) or * (all)]\n");
- fprintf(stderr, "\t%cd (%cdate) datex - Search for files matching date/time expression\n",
- switchar, switchar);
- fprintf(stderr, "\t%cmin size[km] - Search for files >= size[km] bytes\n",
- switchar);
- fprintf(stderr, "\t%cmax size[km] - Search for files <= size[km] bytes\n",
- switchar);
- fprintf(stderr, "\t%cp (%cprint) - Print all files matching search criteria\n",
- switchar, switchar);
- fprintf(stderr, "\t%cls - Display file attributes and size (in K bytes)\n",
- switchar);
- fprintf(stderr, "\t%cLS listoptions - Display file details given by listoptions\n",
- switchar);
- fprintf(stderr, "\t\t[listoptions can contain d(ate), t(ime), s(ize in bytes),\n");
- fprintf(stderr, "\t\t k (size in Kbytes), m (size in Mbytes) or a(ttributes)]\n");
- fprintf(stderr, "\t%c? (%chelp) - Display (this) help text\n",
- switchar, switchar);
-
- fprintf(stderr, "\toptions can be switched off using a trailing %c e.g. %csort%c\n\n",
- switchar, switchar, switchar);
- if (isatty(fileno(stdin))){
- fprintf(stderr, "- More -");
- fflush(stderr);
- while (!kbhit());
- getch();
- fprintf(stderr, "\n\n");
- }
- fprintf(stderr, "\tOptions can be used multiple times overriding previous settings.\n");
- fprintf(stderr, "\tMultiple use of %cprint causes multiple file finding operations.\n\n",
- switchar);
- fprintf(stderr, "A file specification (using %cname) or directory specification (using %cxd)\n",
- switchar, switchar);
- fprintf(stderr, "may contain * or ? wildcard characters in any position.\n\n");
- fprintf(stderr, "A date expression (datex) is a string of the form [comp]datetime\n");
- fprintf(stderr, "\tcomp specifies a comparison operation on the file date/time\n");
- fprintf(stderr, "\tcomp is one of: !=, ne, not equal\n");
- fprintf(stderr, "\t ge, greater or equal(default)\n");
- fprintf(stderr, "\t le, less than or equal\n");
- fprintf(stderr, "\t gt, g, greater than\n");
- fprintf(stderr, "\t lt, l, less than\n");
- fprintf(stderr, "\t ==, eq, =, e. equal\n");
- fprintf(stderr, "\n\tdatetime is of the form ");
- getdate(&date);
- gettime(&time);
- switch(dateformat){
- case DateAmerica:
- fprintf(stderr, "%02d%c%02d%c%04d%c%02d%c%02d%c%02d",
- date.da_mon, dtsep,
- date.da_day, dtsep,
- date.da_year, dtsep,
- time.ti_hour, tmsep,
- time.ti_min, tmsep,
- time.ti_sec);
- break;
- case DateEurope:
- fprintf(stderr, "%02d%c%02d%c%04d%c%02d%c%02d%c%02d",
- date.da_day, dtsep,
- date.da_mon, dtsep,
- date.da_year, dtsep,
- time.ti_hour, tmsep,
- time.ti_min, tmsep,
- time.ti_sec);
- break;
- case DateJapan:
- fprintf(stderr, "%04d%c%02d%c%02d%c%02d%c%02d%c%02d",
- date.da_year, dtsep,
- date.da_mon, dtsep,
- date.da_day, dtsep,
- time.ti_hour, tmsep,
- time.ti_min, tmsep,
- time.ti_sec);
- break;
- }
- fprintf(stderr, "\n\n\tIf no value is given between field seperators the value\n");
- fprintf(stderr, "\tdefaults to the equivalent current date/time value.\n");
- fprintf(stderr, "\t'*' for a field matches any value.\n\n");
- exit(2);
- }
-
- /*
- * Comparison strings used in date/time specification by the user
- */
- struct {
- char *type;
- Comparison match;
- } comparisons[]={
- {"!=", UnEqual},
- {"=!", UnEqual},
- {"ne", UnEqual},
- {"ge", GreaterOrEqual},
- {"le", LessThanOrEqual},
- {"gt", GreaterThan},
- {"lt", LessThan},
- {"==", Equal},
- {"eq", Equal},
- {"=", Equal},
- {"e", Equal},
- {"g", GreaterThan},
- {"l", LessThan},
- {"!", None},
- {"", GreaterOrEqual},
- };
-
- /*
- * Details for date validation
- */
- int monlen []={0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
- #define isleap(y) ((y)%4==0 && (y) % 100 !=0 || (y) %400 ==0)
-
- /*
- * Parse an individual field
- */
- void checkf(char **p, int *d, int *got, int sep){
- char *cp= *p;
- if (*cp=='*'){
- cp++;
- if (*cp==sep)
- cp++;
- } else {
- if (isdigit(*cp)) {
- *d=(*cp++)-'0';
- while (isdigit(*cp))
- *d=10* *d+(*cp++)-'0';
- *got=1;
- }
- if (*cp==sep){
- *got=1;
- cp++;
- }
- }
- *p=cp;
- }
-
- /*
- * Convert a string specified by the user into a date/time structure
- */
- Boolean CvtStringToTime(char *string, MytimePtr rval){
- char *wptr=string;
- Comparison ctype=GreaterOrEqual;
- int i;
- struct date dateblk;
- struct time timeblk;
- int d1, d2, d3, h, m, s;
- int d1got=0, d2got=0, d3got=0, hgot=0,
- mgot=0, sgot=0, yeargot=0, mongot=0, daygot=0;
-
- /*
- * FIrst, establish the default values
- */
- getdate(&dateblk);
- switch(dateformat){
- case DateAmerica:
- d1=dateblk.da_mon;
- d2=dateblk.da_day;
- d3=dateblk.da_year;
- break;
- case DateEurope:
- d1=dateblk.da_day;
- d2=dateblk.da_mon;
- d3=dateblk.da_year;
- break;
- case DateJapan:
- d1=dateblk.da_year;
- d2=dateblk.da_mon;
- d3=dateblk.da_day;
- break;
- }
- gettime(&timeblk);
- h=timeblk.ti_hour;
- m=timeblk.ti_min;
- s=timeblk.ti_sec;
-
- /*
- * See if the user has selected one of the above comparisons
- */
- for (i=0; i<(sizeof(comparisons)/sizeof(comparisons[0])); i++){
- if (strncmp(wptr, comparisons[i].type,
- strlen(comparisons[i].type))==0){
- ctype=comparisons[i].match;
- wptr+=strlen(comparisons[i].type);
- break;
- }
- }
-
- checkf (&wptr, &d1, &d1got, dtsep);
- checkf (&wptr, &d2, &d2got, dtsep);
- checkf (&wptr, &d3, &d3got, dtsep);
- checkf (&wptr, &h, &hgot, tmsep);
- checkf (&wptr, &m, &mgot, tmsep);
- checkf (&wptr, &s, &sgot, tmsep);
-
- /*
- * Store the hours, minutes, seconds then date according to the country
- * specifier
- */
- rval->comparison=ctype;
- rval->hour=h;
- rval->mins=m;
- rval->sec=s;
- switch(dateformat){
- case DateAmerica:
- rval->month=d1;
- rval->day=d2;
- rval->year=d3;
- mongot=d1got;
- daygot=d2got;
- yeargot=d3got;
- break;
- case DateEurope:
- rval->day=d1;
- rval->month=d2;
- rval->year=d3;
- daygot=d1got;
- mongot=d2got;
- yeargot=d3got;
- break;
- case DateJapan:
- rval->year=d1;
- rval->month=d2;
- rval->day=d3;
- yeargot=d1got;
- mongot=d2got;
- daygot=d3got;
- break;
- }
-
- /*
- * If the user specified a short year form, add on the current century.
- * Check the month for being valid and the day for being within the
- * month (even if a leap year).
- */
- if (rval->year<100) rval->year+=((dateblk.da_year/100)*100);
- if ((rval->year<1980)||(rval->year>(1980+128))) return(False);
- if ((rval->month<1)||(rval->month>12)) return(False);
- if (rval->month==2){
- if (isleap(rval->year)) {
- if (rval->day>29) return(False);
- } else if (rval->day>monlen[rval->month]) return(False);
- } else if (rval->day>monlen[rval->month]) return(False);
-
- /*
- * Check the range of the hour, minute and second
- */
- if ((rval->hour<0)||(rval->hour>23)) return(False);
- if ((rval->mins<0)||(rval->mins>59)) return(False);
- if ((rval->sec<0)||(rval->sec>59)) return(False);
-
- /*
- * Finally, compact the data into 16 bit integer format and
- * store the mask value used to select user data
- */
- rval->year-=1980;
- rval->datemask=(yeargot?0xfe00:0)|(mongot?0x1e0:0)|(daygot?0x1f:0);
- rval->timemask=(hgot?0xf800:0)|(mgot?0x7e0:0)|(sgot?0x1f:0);
- rval->date=((rval->year<<9)|(rval->month<<5)|(rval->day))&
- rval->datemask;
- rval->time=((rval->hour<<11)|(rval->mins<<5)|(rval->sec>>1))&
- rval->timemask;
- return(True);
- }
-
- /*
- * This is where it alll starts.
- */
- main(int argc, char *argv[])
- {
- int i, j, k;
- int done=0;
- int enable;
- char *option;
-
- /*
- * FInd out what the switch character is and set the switch and
- * directory seperator for use in this program accordingly
- */
- _AH=0x37;
- _AL=0;
- __int__(0x21);
- switchar=_DL;
- if (switchar=='/')
- dirsep='\\';
- else
- dirsep='/';
-
- /*
- * Retrieve the country specific data
- */
- country(0, &countrydata);
- dtsep=countrydata.co_dtsep[0];
- tmsep=countrydata.co_tmsep[0];
- dateformat=countrydata.co_date;
-
- /*
- * Process options
- */
- for (i=1; i<argc; i++){
- if (argv[i][0]==switchar){
- option= &argv[i][1];
- enable=argv[i][strlen(argv[i])-1]!=switchar;
-
- /*
- * Search for a particular named file
- */
- if ((strcmp(option, "n")==0)||
- (strcmp(option, "name")==0)){
-
- if (enable) {
- if (++i>=argc) usage(argv[0], argv[i-1]);
- spec=argv[i];
- } else {
- spec = "*.*";
- }
-
- /*
- * Terminate search at specified subdirectories
- */
- } else if ((strcmp(option, "x")==0)||
- (strcmp(option, "xd")==0)){
-
- if (prune!=NULL){
- for (k=0; k<nprunes; k++)
- myfree(prunedirs[k]);
- myfree(prunedirs);
- }
-
- if (enable) {
- if (++i>=argc) usage(argv[0], argv[i-1]);
- prune=argv[i];
- strlwr(prune);
- for (nprunes=1, k=0; prune[k]!='\0'; k++)
- if (prune[k]==',') ++nprunes;
- prunedirs=(char **)mymalloc(sizeof(char *)*nprunes);
- for (nprunes=0, j=0, k=0; prune[k]!='\0'; k++)
- if (prune[k]==','){
- prunedirs[nprunes]=(char *)mymalloc(k-j+1);
- strncpy(prunedirs[nprunes], &prune[j], k-j);
- prunedirs[nprunes++][k-j]='\0';
- j=k+1;
- }
- prunedirs[nprunes]=(char *)mymalloc(k-j+1);
- strncpy(prunedirs[nprunes], &prune[j], k-j);
- prunedirs[nprunes++][k-j]='\0';
- } else {
- prune = NULL;
- }
-
- /*
- * Display the program help
- */
- } else if ((strcmp(option, "?")==0)||
- (strcmp(option, "help")==0)){
-
- usage(argv[0], NULL);
-
- /*
- * Sort by extension then file name rather than the
- * other way round
- */
- } else if ((strcmp(option, "s")==0)||
- (strcmp(option, "sort")==0)){
-
- if (enable) {
- extsort=1;
- } else {
- extsort=0;
- }
-
- /*
- * Sort in reverse order
- */
- } else if ((strcmp(option, "r")==0)||
- (strcmp(option, "rev")==0)||
- (strcmp(option, "reverse")==0)){
-
- if (enable) {
- reversesort=1;
- } else {
- reversesort=0;
- }
-
- /*
- * Display the additional file types hidden, system
- * or directories
- */
- } else if ((strcmp(option, "t")==0)||
- (strcmp(option, "type")==0)){
-
- if (enable){
- if (++i>=argc) usage(argv[0], argv[i-1]);
- attrib=0;
- for (j=0; j<strlen(argv[i]); j++)
- switch(argv[i][j]){
- case 'h': attrib|=FA_HIDDEN; break;
- case 's': attrib|=FA_SYSTEM; break;
- case 'd': attrib|=FA_DIREC; break;
- case '*': attrib|=FA_HIDDEN|FA_SYSTEM|FA_DIREC; break;
- default: usage(argv[0], argv[i]);
- }
- } else {
- attrib=0;
- }
-
- /*
- * Specify a date search criterion
- */
- } else if ((strcmp(option, "d")==0)||
- (strcmp(option, "date")==0)){
-
- if (enable){
- if (++i>=argc) usage(argv[0], argv[i-1]);
- if (!CvtStringToTime(argv[i], &DateTime))
- usage(argv[0], argv[i]);
- } else {
- DateTime.comparison=None;
- }
-
- /*
- * Specify a minimum file size to select
- */
- } else if (strcmp(option, "min")==0){
- char factor;
- if (enable){
- if (++i>=argc) usage(argv[0], argv[i-1]);
- if (sscanf(argv[i], "%ld%c", &minsize, &factor)==0)
- usage(argv[0], argv[i]);
- if ((factor=='k')||(factor=='K'))
- minsize*=1024;
- else if ((factor=='m')||(factor=='M'))
- minsize*=1024*1024;
- } else {
- minsize=0;
- }
-
- /*
- * Specify a maximum file size to select
- */
- } else if (strcmp(option, "max")==0){
- char factor;
- if (enable){
- if (++i>=argc) usage(argv[0], argv[i-1]);
- if (sscanf(argv[i], "%ld%c", &maxsize, &factor)==0)
- usage(argv[0], argv[i]);
- if ((factor=='k')||(factor=='K'))
- maxsize*=1024;
- else if ((factor=='m')||(factor=='M'))
- maxsize*=1024*1024;
- } else {
- maxsize=0;
- }
-
- /*
- * Do something
- */
- } else if ((strcmp(option, "p")==0)||
- (strcmp(option, "print")==0)){
-
- displaydir(root);
- done=1;
-
- /*
- * Enable the display of file attribute/size
- */
- } else if ((strcmp(option, "l")==0)||
- (strcmp(option, "ls")==0)){
- if (enable) {
- ls=1;
- } else {
- ls=0;
- }
-
- /*
- * User selectable file details
- */
- } else if ((strcmp(option, "L")==0)||
- (strcmp(option, "LS")==0)){
- if (enable) {
- if (++i>=argc) usage(argv[0], argv[i-1]);
- for (j=0; j<strlen(argv[i]); j++)
- switch(argv[i][j]){
- case 'd': case 't': case 's':
- case 'k': case 'm': case 'a':
- case 'D': case 'T': case 'S':
- case 'K': case 'M': case 'A':
- break;
- default:
- usage(argv[i], argv[i]);
- break;
- }
- strlwr(argv[i]);
- LS=argv[i];
- LSlen=strlen(argv[i]);
- } else {
- LS=NULL;
- }
-
- /*
- * Unrecognised option
- */
- } else {
- usage(argv[0], argv[i]);
- }
-
- /*
- * No option, this is the directory to start the search at
- */
- } else {
- root=argv[i];
- }
- }
-
- /*
- * If the program has completed without an attempt by the user at
- * doing something, display the help.
- */
- if (!done) usage(argv[0], NULL);
-
- /*
- * Last bit of freeing up necessary to enable correct memory
- * usage accounting to work
- */
- if (prune!=NULL){
- for (i=0; i<nprunes; i++)
- myfree(prunedirs[i]);
- myfree(prunedirs);
- }
-
- /*
- * Check the use of memory by the program
- */
- if (mallocspace){
- fprintf(stderr, "Memory leak. Internal failure\n");
- abort();
- }
- }
-
-
-