FASTDIR ... faster DIR command for the Amiga Personal Computer
Robert A. Peck
robp at amiga.UUCP
Wed May 14 08:24:10 AEST 1986
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
# fastdir.doc
# fastdir.c
# tree.c
# treeprint.c
# filecurrent.c
# This archive created: Mon May 13, 1986
export PATH; PATH=/bin:$PATH
echo shar: extracting "'fastdir.doc'" '(2008 characters (and then some))'
if test -f 'fastdir.doc'
then
echo shar: will not over-write existing file "'fastdir.doc'"
else
cat << \SHAR_EOF > 'fastdir.doc'
This release made to V/internal/aug by Rob Peck 5/13/86.
/* fastdir.c */
/* *********************************************************************** */
/* Fastdir was designed to be a faster implementation of the "DIR" command
* for directories that have a large number of items in them, such as c:
*
* It is implemented as follows:
*
* command: FASTDIR
* or FASTDIR <pathname>
*
* If there is a file by the name ".dir" in the selected or current path
* name, fastdir checks the creation date of this .dir file (stored as the
* first line in the file itself) against the modification date of its
* parent directory. If they match exactly, it means that ".dir" contains
* the (near) equivalent of somebody doing a command "DIR > .dir" within this
* directory. If the creation/modification dates don't match, fastdir
* attempts to create such a file. After either finding or creating
* this file, it copies ".dir" to the standard output.
*
* Fastdir handles most known error conditions, such as:
*
* write-protected disk
* (outputs the generated listing equivalent to DIR without writing
* or rewriting the .dir file).
* trying to get a directory of a nonexistent file
* (responds "can't find <pathname>")
* trying to generate a directory listing of a file
* (responds "<pathname> is not a directory")
* trying to generate a listing of an empty directory
* (responds "Directory '<pathname>' is empty.)
*
* Could use some error checking around the Write commands to handle
* too-full disks, or a write error while generating ".dir". Anybody
* out there want to add these?
*
* Fastdir does not implement DIR's "OPT" option. (OPT A, OPT I)
*
* Fastdir modifies the DIR output slightly in that directories are NOT
* listed separately, but are merged alphabetically into the normal
* sorted alpha listing, still marked " (dir)" as they should be marked.
*
* Author: Rob Peck 5/13/86
*
* Lattice/Amiga C (3.03) linking information:
*
* compile with stack checking code disabled in pass 2 (lc2 -v file.q)
*
* FROM lib:Astartup.obj fastdir.o filecurrent.o tree.o treeprint.o
* TO fastdir
* LIBRARY lib:amiga.lib, lib:lc.lib
*
*/
SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'fastdir.c'" '(11003 characters)'
if test -f 'fastdir.c'
then
echo shar: will not over-write existing file "'fastdir.c'"
else
cat << \SHAR_EOF > 'fastdir.c'
/* fastdir.c */
/*
* Author: Rob Peck 5/13/86
*/
#include "libraries/dos.h"
#include "libraries/dosextens.h"
#include "exec/memory.h"
#define ABS(x) (x > 0 ? x : -x)
#define MAX(x,y) (x > y ? x : y)
extern struct FileHandle *stdout;
extern struct FileLock *Lock(),*DupLock();
extern struct FileLock *CurrentDir(), *ParentDir();
extern struct FileHandle *stdout, *Open();
char *blanks = " "; /* 35 blank spaces */
char linebuffer[80]; /* workspace for output formatting */
int leftright=0; /* start at left column */
struct tnode /* for quick alphabetizing */
{
struct tnode *left;
struct tnode *right;
char name[36]; /* space to store the name (30 + ' (dir)') max */
char dirflag; /* nonzero if it is a directory */
};
extern struct tnode *tree();
struct tnode *root; /* Pointer to the first one so we can deallocate */
struct FileInfoBlock *m; /* for getting write-protect information */
struct FileLock *newlock; /* Lock on current (or requested) dir */
struct FileLock *dirlock; /* Lock on the .dir file */
int maxlen=0; /* Maximum length of any string, provided
* for later change in formatting (more
* entries per line
*/
#define PROTECTED 1
#define WRITEABLE 0
main(argc, argv)
int argc;
char *argv[];
{
LONG myerror; /* place for error return filecurrent */
LONG success; /* work variables */
char *whichdir; /* which directory to get a lock on? */
struct FileLock *startlock; /* lock on the current directory */
struct FileLock *ignorlock; /* going back to original dir. */
struct InfoData *id; /* see if disk is write-protected */
struct FileLock *originallock; /* for "going home" again */
/* Save a lock to original directory so that before we exit, we
* can move the CLI back to where it started
*/
originallock = Lock("",ACCESS_READ);
id = NULL;
if(argc == 1)
{
/* No directory specified, use current one! */
/* Null string means use current dir */
whichdir = "";
}
else
{
whichdir = argv[1];
}
/* Get a lock on the user-specified directory */
newlock = Lock(whichdir,ACCESS_READ);
if(newlock == 0)
{
if(argc == 1)
printf("Can't get a lock on current dir!\n");
else
printf("Can't find %ls\n",argv[1]);
exit(100);
}
else
{
/* Move into this user selected directory */
startlock = CurrentDir(newlock);
}
/* Now see if there is a current copy of the ".dir" file here */
if(filecurrent(".dir",&myerror))
{
/* If its there and current, then output it */
output_dirfile(newlock);
}
else
{
/* If its not current, attempt to create or overwrite it */
/* InfoData MUST BE LONGWORD ALIGNED, so allocate it */
id = (struct InfoData *)
AllocMem(sizeof(struct InfoData),MEMF_CLEAR);
if(id)
{
/* Get info to see if disk is write protected */
success = Info(newlock, id);
if(success)
{
if(id->id_DiskState == ID_WRITE_PROTECTED)
{
DirList(newlock, PROTECTED, whichdir);
goto finish;
}
}
else
{
printf("Can't get Info about current directory\n");
goto finish; /* Info command failed */
}
if(DirList(newlock, WRITEABLE, whichdir))
{
/* If DirList returns nonzero, means the file
* got created (there was at least one entry
* in the directory and the disk wasn't write
* protected.)
*/
output_dirfile(newlock); /* copy ".dir" to stdout */
}
goto finish;
}
else
{
printf("Not enough memory for InfoData\n");
/* If this happens, there certainly isn't enough
* to generate a DirList either!
*/
}
finish:
}
if(id) FreeMem(id, sizeof(struct InfoData));
cleanup:
if(newlock) UnLock(newlock);
/* move into the original directory from whence you came */
ignorlock = CurrentDir(originallock);
/* if(originallock) UnLock(originallock); */
}
/* output_dirfile -- copy ".dir" to stdout */
output_dirfile(lock)
struct FileLock *lock; /* shows the current directory to use */
{
struct FileHandle *fh;
struct FileLock *ignoredlock;
UBYTE buffer[300];
int actualcount, outcount;
ignoredlock = CurrentDir(lock); /* make sure are in correct place */
fh = Open(".dir",MODE_OLDFILE);
if(fh)
{
while(1) /* forever, till EOF */
{
actualcount = Read(fh, buffer, 255); /* decent block size */
if(actualcount == 255)
{
/* ======================++++++++======================= */
/* NOTE: This assumes an AmigaDOS file handle for stdout */
/* ======================++++++++======================= */
outcount = Write(stdout, buffer, actualcount);
}
if(actualcount < 255)
{
outcount = Write(stdout, buffer, actualcount);
break;
}
if(actualcount == -1)
{
printf("Error ( %ld ) copying .dir to output\n",IoErr());
break;
}
}
Close(fh); /* close the file */
}
else
{
printf("'.dir' won't open! IoErr() = %ld\n", IoErr());
}
}
/* DirList -- Look through the binary tree listing that tree() produced
* and output the names in that tree in alphabetical order.
* If selected directory is writeable, create a file named
* .dir there, containing the formatted output. Current
* implementation puts two names on each line, just like DIR.
*/
DirList(lock, protectstatus, pathname)
struct FileLock *lock;
int protectstatus;
char *pathname; /* Pathname that user gave us. */
{
struct FileHandle *tfh;
LONG success;
struct tnode *allocated;
struct tnode *t;
LONG *ds;
/* if at the end of the road, don't print anything */
if(!lock) return(0);
root = (struct tnode *)
AllocMem(sizeof(struct tnode),MEMF_CLEAR);
if(!root) return(0);
/* allocate space for a FileInfoBlock */
m = (struct FileInfoBlock *)
AllocMem(sizeof(struct FileInfoBlock),MEMF_CLEAR);
if(!m) goto noentries;
success = Examine(lock,m);
if(!success)
{
printf("Can't examine directory for '%ls'\n",pathname);
goto noentries;
}
/* The first call to examine fills the FileInfoBlock with
* INFORMATION ABOUT THE DIRECTORY. If it is called at the
* root level, it contains the volume name of the disk. If
* we're building a directory listing, we won't want this
* entry to be in it, so we call ExNext before starting the
* listing itself.
*/
/* Three conditions to consider here...
* a. is NOT a directory.
* b. is an empty directory.
* c. has at least one entry.
*/
/* NOT A DIRECTORY */
if(m->fib_DirEntryType <= 0)
{
/* If this is true, we're dealing with a plain file.
* It should exit saying this is NOT a directory
*/
printf("'%ls' is not a directory.\n",pathname);
noentries:
if(root) FreeMem(root, sizeof(struct tnode));
/* treeprint normally frees all entries, including root, but
* we never get there so we have to free the memory here instead
*/
if(m) FreeMem(m, sizeof(struct FileInfoBlock));
return(0); /* didn't create a file, so don't print it. */
}
success = ExNext(lock,m);
/* EMPTY DIRECTORY */
if(!(success))
{
printf("Directory '%ls' is empty.\n", pathname);
goto noentries;
}
/* AT LEAST ONE ENTRY */
/* Initialize the very first node */
t = root;
strcpy( &(t->name[0]), &(m->fib_FileName[0]) );
if (m->fib_DirEntryType > 0)
{
strcat( &(t->name[0]), " (dir)" );
}
maxlen = MAX(maxlen, strlen( &(t->name[0])));
/* t->left and t->right pointers are already set to zero by AllocMem */
success = ExNext(lock,m);
while (success) /* was (success != 0) */
{
t = root; /* begin the search at the root */
/* Install it into the chain, recursively. Allocated is an
* indicator that there was still enough memory to build a
* new chain for this node. If allocated == 0, have to
* terminate prematurely.
*/
allocated = tree(t, &(m->fib_FileName[0]));
if(allocated == 0) break;
success = ExNext(lock,m);
}
if(allocated == 0) /* header for the premature termination */
{
printf("\nPARTIAL DIR LISTING ONLY....NOT ENOUGH MEMORY\n");
goto showlist;
}
/* "KLUGE".... we are trying to create a file named '.dir', but we
* don't have any (FileInfoBlock) info about it yet since the builder
* of the file hasn't yet even written it. So we'll take the very
* last entry in the file info block and modify its name field to
* be '.dir' so that this file name will actually appear in the listing.
* (this is ok since tree() is not using anything but the name field).
*/
if(protectstatus == WRITEABLE)
{
strcpy( &(m->fib_FileName[0]), ".dir" );
allocated = tree(root, ".dir"); /* install .dir */
}
showlist:
/* Now begin to build the output listing, two to a line */
sprintf(&linebuffer[0], "%ls", blanks); /* blank first 35 locations */
sprintf(&linebuffer[35], "%ls", blanks); /* blank next 35 locations */
linebuffer[67] = '\0'; /* null terminator */
tfh = 0; /* start out with no file open */
if(protectstatus == WRITEABLE) /* If seems to be unprotected ... */
{
tfh = Open(".dir",MODE_NEWFILE); /* if fails, tfh = 0 */
}
/* When this file is FIRST opened, the time of its parent directory
* modification is established. If we want to know if the file we
* have created is current, we have to store the change time of the
* parent directory in this file itself. Then no matter, with
* multi-tasking, how long it takes to create this .dir file
* (whose date is established when it CLOSES), we'll have the
* correct numbers to compare, and be zero time-ticks off.
* The .dir file will contain its parent's creation date and time as the
* first line, so you'll be able to see whether DIR gets generated
* fresh or if it came from the .dir file.
*/
success = Examine(newlock,m); /* Succeeded once already so it
* should also succeed here.
* Now the date has been changed
* to reflect the .dir file opened.
*/
ds = (LONG *)&(m->fib_Date); /* Pass along the address of the
* datestamp of the parent directory
*/
dotreeprint(root, tfh, ds);
if(tfh) Close(tfh);
if(m) FreeMem(m,sizeof(struct FileInfoBlock));
return(TRUE); /* Created a file, so its ok to print it later */
}
strcat( to, from )
register char *to, *from;
{
while( *to ) to++; /* find the end of the current string */
strcpy( to, from ); /* then overlay trailing null, with first char.
* of the string to be concatenated. */
}
strlen( s )
register char *s;
{
register i = 0;
while( *s++ ) i++;
return( i );
}
SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'tree.c'" '(3821 characters)'
if test -f 'tree.c'
then
echo shar: will not over-write existing file "'tree.c'"
else
cat << \SHAR_EOF > 'tree.c'
/* tree.c */
/* Author: Rob Peck 5/13/86 */
/* part of "fastdir" command */
#include "exec/types.h"
#include "libraries/dos.h"
#include "exec/memory.h"
#define MAX(x,y) (x > y ? x : y)
#define FASTDIR 1
#ifdef FASTDIR
extern struct FileInfoBlock *m;
#endif FASTDIR
extern int maxlen;
struct tnode /* for quick alphabetizing */
{
struct tnode *left;
struct tnode *right;
char name[36]; /* space to store the name (30 + ' (dir)') max */
char dirflag; /* nonzero if it is a directory */
};
/* tolower(c) -- Convert characters to lower case */
int tolower( b )
int b;
{
if( (b >= 'A') && (b <= 'Z') )
return(b - 'A' + 'a');
else
return( b );
}
/* tree -- Install a new named node at or below the one now pointed to
* RECURSIVELY CALLS ITSELF.... be careful not to run out of
* stack space if the strings nest too deeply.
*/
struct tnode *tree(t, name)
struct tnode *t;
char *name;
{
int cond; /* Condition code from return */
struct tnode *allocated;
if(t == NULL) /* If prior invocation has reached a null pointer,
* a new node must be allocated.
*/
{
t = (struct tnode *)
AllocMem(sizeof(struct tnode),MEMF_CLEAR);
if(t == 0)
{
/* NOT ENOUGH MEMORY TO FINISH THE TREE */
/* Make sure to STOP! */
return(0);
}
strcpy( &(t->name[0]), name );
#ifdef FASTDIR
if (m->fib_DirEntryType > 0)
{
strcat( &(t->name[0]), " (dir)" );
}
#endif FASTDIR
maxlen = MAX(maxlen, strlen( &(t->name[0])));
return(t);
}
/* compare two strings and decide where to install the new one */
cond = compLC(&(t->name[0]), name );
if(cond < 0)
{
if (t->left != NULL) /* search for a NULL entry */
{
return(tree(t->left, name));
}
else /* try to install at the null entry found */
{
allocated = tree(0, name);
/* If allocated == 0, then it passes a NULL all the
* way back to the caller, telling him the system has
* just run out of memory trying to build the chains.
* So it should consider the chain complete and try
* to output it, thereby freeing the memory along the way.
*/
t->left = allocated;
return(allocated);
}
}
else if(cond > 0)
{
if (t->right != NULL) /* search for a NULL entry */
{
return(tree(t->right, name));
}
else /* try to install at the null entry found */
{
allocated = tree(0, name);
t->right = allocated;
return(allocated);
}
}
else
{
/* If it EVER gets here, means entry of a duplicate item into tree.
* Is treated as an error. Upper and lower case are the same and only
* get listed once. Original application was for 'fastdir' and
* AmigaDOS cannot install duplicate file names into a single
* directory.
*/
return(0);
}
}
strcpy( to, from )
register char *to, *from;
{
do {
*to++ = *from;
} while( *from++ );
}
/* compLC -- Compare two strings, ignoring case.
* returns -1 if s<t, 1 if s>t, 0 if s=t.
*/
int compLC(s,t)
register char *s, *t;
{
register char test;
while(1)
{
test = tolower(*s)-tolower(*t); /* compare two characters */
if (test < 0)
{
return(-1); /* first less than second */
}
else
{
if (test > 0)
{
return(1); /* first greater than second */
}
else /* first equals second, so far */
{
if( *s == '\0') /* if nulls match also, strings are equal */
{
return(0);
}
t++;
s++;
}
}
}
}
SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'treeprint.c'" '(3624 characters)'
if test -f 'treeprint.c'
then
echo shar: will not over-write existing file "'treeprint.c'"
else
cat << \SHAR_EOF > 'treeprint.c'
/* treeprint.c */
/* author: Rob Peck 5/13/86 */
/* part of "fastdir" command */
#include "libraries/dos.h"
#include "libraries/dosextens.h"
#include "exec/memory.h"
#define SPRINTF 1
#define FPRINTF 0
extern int leftright;
extern char *blanks;
extern char linebuffer[];
extern int (*fprintf)();
struct tnode /* for quick alphabetizing */
{
struct tnode *left;
struct tnode *right;
char name[36]; /* space to store the name (30 + ' (dir)') max */
char dirflag; /* nonzero if it is a directory */
};
/* This SPECIAL VERSION of strcpy does NOT copy the trailing null */
mystrcpy( to, from )
register char *to, *from;
{
char *leadingfrom;
leadingfrom = from + 1;
do {
*to++ = *from++;
} while( *leadingfrom++ );
}
/* treeprint -- recursive output, to stdout or to a file, from the
* linked node list that tree() creates. tree() allocates
* memory; treeprint() deallocates it as it runs
*/
treeprint(t,tfh) /* print the tree recursively */
struct tnode *t;
struct FileHandle *tfh; /* if theres a file open, use it */
{
int actual;
if(t->right != NULL) treeprint(t->right,tfh);
if(leftright == 0)
{
mystrcpy(&linebuffer[2], blanks); /* blank the string */
mystrcpy(&linebuffer[2], &(t->name[0])); /* install the name */
mystrcpy(&linebuffer[35],blanks); /* blank out rest. */
leftright = 1;
}
else
{
mystrcpy(&linebuffer[35], &(t->name[0])); /* install the name */
leftright = 0;
if(tfh == 0)
{
printf("%ls\n", linebuffer);
}
else
{
actual = Write(tfh, linebuffer, 66);
actual = Write(tfh, "\n", 1);
}
}
if(t->left != NULL) treeprint(t->left,tfh);
FreeMem(t, sizeof(struct tnode));
return(0);
}
dotreeprint(root, tfh, ds)
struct tnode *root;
struct FileHandle *tfh;
LONG *ds; /* points to the datestamp */
{
char dummy[50]; /* When call for FPRINTF, dummy is not used. */
if(tfh)
{
DateToAscii(FPRINTF, dummy, ds, tfh);
}
treeprint(root, tfh); /* call does all except the final line */
if(leftright == 1)
{
if(tfh) /* if there is a file open, thats where the output goes. */
{
Write(tfh, linebuffer, 66);
Write(tfh, "\n", 1);
}
else /* otherwise print it to stdout */
{
printf("%ls\n",linebuffer);
}
}
}
/* This routine can accept either "FPRINTF", which expects whereto
* to be a file handle, or "SPRINTF", which expects whereto to be the
* address of a string.
*/
DateToAscii(routine, whereto, ds, tfh)
LONG routine; /* which routine to use */
char *whereto;
struct FileHandle *tfh;
LONG *ds; /* pointer to a datestamp */
{
char dateout[50]; /* only need about 41, but this is ok */
int actual;
LONG n ; /* number of days past 1/1/78 */
int m, d, y ; /* month, day, year */
int h, mn, sec; /* hours, minutes, seconds */
n = ds[0] - 2251 ;
y = (4 * n + 3) / 1461 ;
n -= 1461 * y / 4 ;
y += 84 ; /* was 1984 */
m = (5 * n + 2) / 153 ;
d = n - (153 * m + 2) / 5 + 1 ;
m += 3 ;
if (m > 12)
{
y++ ;
m -= 12 ;
}
h = ds[1] / 60; /* 60 minutes per hour */
mn = ds[1] - h * 60; /* remainder is the minutes */
sec = ds[2] / TICKS_PER_SECOND;
switch(routine)
{
case SPRINTF:
sprintf(whereto,
"<dir> Creation Date: %02ld/%02ld/%02ld %02ld:%02ld:%02ld.\n",m,d,y,h,mn,sec);
break;
case FPRINTF:
sprintf(dateout,
"<dir> Creation Date: %02ld/%02ld/%02ld %02ld:%02ld:%02ld.\n",m,d,y,h,mn,sec);
actual = Write(tfh, dateout, 41);
break;
default:
break;
}
return(0);
}
SHAR_EOF
fi # end of overwriting check
echo shar: extracting "'filecurrent.c'" '(4296 characters)'
if test -f 'filecurrent.c'
then
echo shar: will not over-write existing file "'filecurrent.c'"
else
cat << \SHAR_EOF > 'filecurrent.c'
/* filecurrent.c */
/* Author: Rob Peck 5/13/86 */
/* part of "fastdir" */
#include "libraries/dos.h"
#include "libraries/dosextens.h"
#include "exec/memory.h"
#define ABS(x) (x > 0 ? x : -x)
#define SPRINTF 1
#define FPRINTF 0
extern struct FileLock *Lock(),*DupLock();
extern struct FileLock *CurrentDir(), *ParentDir();
extern struct FileHandle *stdout, *Open();
/* filecurrent -- See if there is a "current" copy of a specified file name
* in the directory in which we now reside. Return FALSE if
* it is either nonexistent, or if it is non-current, based
* on the minutes and seconds information passed to this
* subroutine. (When a file is opened into a directory
* under AmigaDOS, both the file-written date and the
* directory-written date are modified. The file date
* itself gets written when it is closed.)
*/
int
filecurrent(name, error)
char *name; /* What is the name of the file to look for */
int *error; /* Where to put an error code, if and only if
* a value of FALSE is returned (TRUE is expected).
*/
{
LONG success, i;
LONG *parentdate;
struct FileHandle *fh;
char cbuffer[50]; /* creation date buffer */
char dbuffer[50]; /* .dir file contents */
int actual, status;
struct FileInfoBlock *fib; /* for getting date information */
struct FileLock *filelock; /* lock on the selected file */
struct FileLock *currentlock; /* lock on the selected file */
struct FileHandle *dummyfh;
dummyfh = NULL; /* not used anyhow */
fib = NULL;
currentlock = NULL;
filelock = NULL;
/* Try to lock this file, just to see if it exists */
filelock = Lock(name, ACCESS_READ);
if(!filelock)
{
*error = ERROR_OBJECT_NOT_FOUND;
return(FALSE); /* If non-existent, it is not current! */
}
UnLock(filelock);
filelock = NULL;
/* Once we get here, we know that the file exists, but we now
* have to determine whether it is current. If it didn't exist,
* the above return(FALSE) would have happened. Now read the
* last modified date of the directory the file is in to get
* something against which to compare. This particular date
* is stored as the first info within the file itself.
*/
/* FileInfoBlock MUST BE LONGWORD ALIGNED, so we have to
* dynamically allocate it.
*/
fib = (struct FileInfoBlock *)
AllocMem(sizeof(struct FileInfoBlock),MEMF_CLEAR);
if(fib == 0) /* no memory for file info block? */
{
*error = ERROR_NO_FREE_STORE;
return(FALSE); /* Cannot allocate memory */
}
/* initialize the buffers */
for(i=0; i<50; i++)
{
cbuffer[i] = 0x20; /* ascii blank */
dbuffer[i] = 0x20;
}
cbuffer[49] = 0; dbuffer[49] = 0; /* end of string nulls */
/* (Passing a null-string asks for a lock on the current directory) */
/* Look at the directory we've moved into, and check its mod date */
/* Start by getting a lock on the current directory */
currentlock = Lock("",ACCESS_READ);
if(!currentlock)
{
*error = ERROR_DIR_NOT_FOUND; /* Can't lock current directory */
status = FALSE;
goto cleanfinish;
}
/* Now using that lock, Examine current directory to get the date */
success = Examine(currentlock,fib);
if(success)
{
parentdate = (LONG *)&(fib->fib_Date);
DateToAscii(SPRINTF, cbuffer, parentdate, dummyfh);
}
status = FALSE; /* Start out assuming it is not the same */
*error = 0; /* A false return with 0 errors is valid....
* it means file found, but not up to date
*/
fh = Open(name,MODE_OLDFILE);
if(!fh) goto cleanfinish;
actual = Read(fh, dbuffer, 40); /* get the date from the file */
if(actual != 40)
{
printf("Error while reading %ls\n",name);
goto cleanfinish;
}
status = comparedates(cbuffer, dbuffer);
cleanfinish:
if(fh) Close(fh);
if(fib) FreeMem(fib, sizeof(struct FileInfoBlock));
if(currentlock) UnLock(currentlock);
return(status);
}
comparedates(s,t)
char *s, *t;
{
while( *s == *t )
{
if(*s == '.') /* both equal and reach a period, ok! */
{
return(TRUE);
}
if(*s == '\0') return(FALSE); /* error, hit end of string
* without finding '.'
*/
s++; t++;
}
return(FALSE); /* found an unequal character prior to the period */
}
SHAR_EOF
fi # end of overwriting check
# End of shell archive
exit 0
More information about the Comp.sources.unix
mailing list