home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Gold Fish 1
/
GoldFishApril1994_CD1.img
/
d1xx
/
d108
/
alist
/
alist.c
< prev
next >
Wrap
C/C++ Source or Header
|
1987-10-31
|
24KB
|
786 lines
/* "AList" 0.06 ... Disk Directory (catalog) Utility by Ed Kivi */
/* This command is designed to get an AmigaDOS directory and display the
full contents to the screen. Later it will create an AmigaDOS file
of PathNames to be used as a Library of files on disk storage. */
#include <exec/types.h> /* order is important, else "NULL" */
#include <stdio.h>
#include <ctype.h> /* will be 'redefined' in compiler's eye */
#include <time.h>
#include <libraries/dosextens.h>
#include <exec/memory.h>
/* #define AEKfilenote -* long version of aekDC desired */
#undef AEKfilenote /* short version of aekDC desired */
#undef DEBUG /* [dis|en]able de-bugging printf statements */
#ifndef HIGHVALUE
#define HIGHVALUE 127
#endif
#define AmigaFIB struct FileInfoBlock
#define aekDC struct DCatalog /* A. E. Kivi Disk Catalog */
#define volsize 31 /* maximum length of volume name (31) */
#ifndef AEKfilenote
#define pathsize 36 /* maximum length of path name */
#else
#define pathsize 61 /* maximum length of path name */
#endif
#define filesize 31 /* maximum length of file name (31) */
#define extsize 11 /* maximum length of file name extension */
extern struct FileLock *Lock();
/* preliminary disk catalog record layout, growing from Ram: to file */
aekDC
{
aekDC *DC_next; /* pointer to next record */
aekDC *DC_prior; /* pointer to prior record */
#ifdef AEKfilenote
aekDC *DC_altnext; /* pointer to next record (alt seq) */
aekDC *DC_altprior; /* pointer to prior record (alt seq) */
#endif
long DC_key; /* Ram: address, Disk: track */
long DC_size; /* 0, or size in bytes of a file */
long DC_blocks; /* number of blocks required */
char DC_type; /* V= Volume, D= Directory, F= File */
char DC_volume[volsize]; /* disk name, as "WorkBench_1.2" */
char DC_path[pathsize]; /* first 'n' chars of the Path Name */
char DC_file[filesize]; /* file name, as "DLibrary" */
char DC_ext[extsize]; /* extension, as ".c" (without .) */
char DC_icon; /* Y = has .info, N = no .info */
char DC_dmy[12]; /* Date, as "05-Sep-1987 " */
char DC_time[9]; /* Time-of-day, as "14:45:13" */
#ifdef AEKfilenote
char DC_filenote[71]; /* Comments about the file */
#endif
} ;
/* This is probably unnecessary, but nothing obvious in AmigaDOS */
struct Calendar
{
int yearday; /* number of days in prior months, as "243" */
int lastday; /* last day in the month, as "30" */
char monname[4]; /* month name, as "Sep " */
} ;
/* This is the format used by gmtime() and localtime() */
struct DateTime
{
char DT_wday[4]; /* Day-of-the-week, as "Sat" */
char DT_month[4]; /* month name, as "Sep " */
char DT_mday[3]; /* Day-of-the-month, as "05" */
char DT_time[9]; /* Time-of-day, as "14:45:13" */
char DT_year[5]; /* Year, as "1987" */
char DT_filler[1]; /* NewLine */
} ;
/* replace/rename above when (if?) found in AmigaDOS */
AmigaFIB *fb; /* File Info from locked directory */
struct FileLock *dir; /* Locked AmigaDOS directory */
struct FileLock *olddir; /* AmigaDOS directory to be restored */
struct DateTime *ud; /* Date stamp info from FileInfoBlock */
aekDC *pdc; /* Disk Catalog record to be inserted */
aekDC *pdc1; /* Root (Volume) Disk Catalog record */
aekDC *pdEnd; /* End-of-List Disk Catalog record */
aekDC *pdTop; /* Directory record #1 (Volume Name only) */
int nestedDir; /* number of sub-directories found */
aekDC *pdirn; /* last Directory record (Path only) */
aekDC *pdir; /* Directory record (Path Name only) */
aekDC *getDCmem(aekDC *); /* storage for Disk Catalog record */
char *append( char *, char *, int ); /* string concatenation */
char *copyn( char *, char *, int ); /* Copy n chars. */
char *copy( char *, char * ); /* Copy string of chars. */
char *fill_area( char *, unsigned char, int ); /* string (area) fill */
char *ign; /* throw-away pointer from memset */
char DiskName[volsize]; /* name of the disk from FileInfoBlock */
char dirname[volsize]; /* name of the disk: from FileInfoBlock */
char work[108]; /* volume/path/file name work area */
int compareci( char *, char * ); /* string compare, case insensitive */
static int keyed = 0; /* return from 'getchar' */
static int calls = 0; /* number of entries in core */
static int passno = 0; /* number of directory passes made */
static int fullpage = 22; /* number of lines displayed per page */
static int thispage = 0; /* number of lines displayed so far */
static int bytes = 0; /* number of bytes stored on disk */
static int blocks = 0; /* number of blocks on disk used */
static int mask = 0; /* clean-up requirement indicators */
#define allocud 0x00000001 /* allocated storage for DateTime */
#define allocfb 0x00000002 /* allocated storage for FileInfoBlock */
#define svolddir 0x00000004 /* saved old directory */
#define allocpdTop 0x00000010 /* allocated storage for Head-of-List */
#define allocpdEnd 0x00000020 /* allocated storage for Tail-of-List */
#define allocpdc 0x00000040 /* allocated storage for at least 1 record */
BOOL fail; /* Directory Access Failure */
BOOL noargs = FALSE; /* TRUE if argument(s) supplied */
BOOL color = FALSE; /* TRUE if color display desired */
BOOL verbose = FALSE; /* TRUE if Version, count, etc. */
BOOL redirect = FALSE; /* TRUE if >prt: being used */
void close_things(); /* clean-up memory, etc. */
void Delay(); /* delay for de-bugging */
void usage(); /* invalid argument(s), display usage */
void options( char *, int ); /* parse options */
void Traverse( aekDC *, int, struct FileLock * );
void MergeDC( aekDC * , aekDC * , aekDC * ); /* Filer */
void print_headings(); /* headings over column data */
void
main(argc,argv)
int argc;
char *argv[];
{
int ai = 0;
if ( argc >= 7 )
usage();
if (argc == 1)
{
ign = copy( dirname, "" );
noargs = TRUE;
}
else
{
while ( argv [ai + 1] && ai++ <= argc - 1 )
{
ign = copy( work, argv [ai] );
if ( work[0] == '?' )
usage();
if ( ( work[0] == 'o' || work[0] == 'O') && (work[1] == 'p' || work[1] == 'P') && ( work[2] == 't' || work[2] == 'T') )
{
ign = copy( work, argv [++ai] );
options( work, 0);
}
else
{
if ( work[0] == '-' )
options( work, 1);
else
{
ign = copy( dirname, work );
if ( dirname == '\0' )
usage();
}
}
}
}
if ( fullpage < 3 )
fullpage = 22;
ud = (struct DateTime *) AllocMem( sizeof( struct DateTime ), MEMF_CLEAR | MEMF_PUBLIC );
mask |= allocud;
fb = (AmigaFIB *) AllocMem( sizeof( AmigaFIB ), MEMF_CLEAR | MEMF_PUBLIC );
mask |= allocfb;
dir = Lock(dirname, ACCESS_READ);
if ( !dir )
{
printf( "Could not Lock '%s'.\n", dirname );
close_things();
}
olddir = CurrentDir( dir );
mask |= svolddir;
/* Read "Root" directory FileInfoBlock */
fail = (dir == NULL) | !Examine(dir,fb);
if (fail) {
printf("Sorry, '%s' is not a directory\n", dirname);
close_things();
}
ign = copy( work, fb->fib_FileName );
ign = append( work, ":", sizeof(work) );
if ( work[0] == ':' )
ign = copy( work, dirname );
work[volsize-1] = '\0';
ign = copy( DiskName, work );
/* Build specified Root directory name and information */
pdTop = getDCmem( NULL ); /* get memory for top-of-list */
if ( !pdTop )
close_things();
mask |= allocpdTop;
pdTop->DC_key = fb->fib_DiskKey;
pdTop->DC_size = 0;
pdTop->DC_blocks = fb->fib_NumBlocks;
pdTop->DC_type = 'V' ;
ign = copy( pdc->DC_volume, DiskName );
ign = fill_area( pdTop->DC_path, (unsigned char) '\0', sizeof(pdTop->DC_path) );
ign = fill_area( pdTop->DC_file, (unsigned char) '\0', sizeof(pdTop->DC_file) );
ign = fill_area( pdTop->DC_ext, (unsigned char) '\0', sizeof(pdTop->DC_ext) );
pdTop->DC_icon = 'N' ;
/* Root entry has been initialized */
pdEnd = getDCmem( pdTop ); /* get memory for end-of-list */
if ( !pdEnd )
close_things();
mask |= allocpdTop;
pdTop->DC_prior = NULL;
pdEnd->DC_next = NULL;
pdTop->DC_next = pdEnd;
pdEnd->DC_prior = pdTop;
ign = fill_area( pdEnd->DC_volume, (unsigned char) HIGHVALUE, sizeof(pdEnd->DC_volume) );
ign = fill_area( pdEnd->DC_path, (unsigned char) HIGHVALUE, sizeof(pdEnd->DC_path) );
ign = fill_area( pdEnd->DC_file, (unsigned char) HIGHVALUE, sizeof(pdEnd->DC_file) );
ign = fill_area( pdEnd->DC_ext, (unsigned char) HIGHVALUE, sizeof(pdEnd->DC_ext) );
/* End-of-list entry has been initialized */
pdc1 = pdTop; /* This one gets changed */
pdc = pdc1; /* set generic pointer to root */
calls--; /* do not count end-of-list */
/* Build File and Directory records, Print from record */
if ( redirect ) /* form feed and indent for printer */
printf( "\f " );
if ( verbose )
{
printf( "\033[1mAList V0.06\033[0m compiled at 14:45:13 on Sat 05-Sep-1987.\n" );
thispage = 2;
}
Traverse( pdc1, passno, dir );
print_headings();
pdc = pdTop;
/* Print specified directory name and information */
while ( pdc != pdEnd)
{
if ( !redirect && verbose && thispage >= fullpage )
{
printf( "Press \033[37m\033[3menter\033[0m to continue." );
keyed = getchar();
thispage = 0;
print_headings();
}
if ( redirect )
printf( " " ); /* indent for printer */
if ( pdc->DC_type == 'V' )
printf( "\033[1m%-30s ", pdc->DC_volume );
else
{
if ( pdc->DC_type == 'D' )
{
if ( color )
printf( "\033[37m" );
printf( "\033[3m%-30s ", pdc->DC_path );
}
else
{
if ( pdc->DC_path[0] == '\0' )
ign = copy( work, pdc->DC_file );
else
{
ign = copy( work, " " );
ign = append( work, pdc->DC_file, sizeof(work) );
}
work[volsize-1] = '\0';
printf( "%-30s ", work);
}
}
printf( "%7d ", pdc->DC_key );
if ( pdc->DC_type == 'V' )
printf( " Root ");
else if ( pdc->DC_type == 'D' )
printf( " Dir " );
else
{
bytes += pdc->DC_size;
printf( "%6d ", pdc->DC_size );
}
blocks += pdc->DC_blocks;
printf( "%4d ", pdc->DC_blocks );
printf( "%s ", pdc->DC_dmy );
printf( "%s\033[0m\n", pdc->DC_time );
thispage++;
pdc1 = pdc;
pdc = pdc->DC_next;
pdTop->DC_next = pdc; /* remove record from the linked-list */
if ( pdc1 != pdTop )
FreeMem( pdc1, sizeof(aekDC) ); /* Free memory for 2 -> n-1 */
}
mask ^= allocpdc; /* freed all file/directory records */
if ( redirect )
printf( " " ); /* indent for printer */
printf( "%d members in %d blocks, storing %d bytes.\n", calls, blocks, bytes );
close_things();
} /* end of main-line of program "DLibrary" */
/* Append a string to the end of a string up to 'limit' characters. */
char *append( to, from, limit )
char *to;
char *from;
int limit;
{
char *temp = to;
if ( !to )
return( temp );
while ( *to && limit > 1 ) /* find current end-of-string */
{
to++;
limit--;
}
while ( *from && limit > 1 ) /* extend string */
{
*to = *from++;
to++;
limit--;
}
*to++ = '\0'; /* ensure NULL terminated */
return( temp );
}
/* Close off (as friendly as possible) */
void close_things()
{
if ( mask & allocud ) /* FreeMem for date work area */
FreeMem( ud, sizeof(struct DateTime) );
if ( mask & allocfb ) /* FreeMem for FileInfoBlock */
FreeMem( fb, sizeof(AmigaFIB) );
if ( mask & allocpdTop ) /* at least 1 record allocated */
{
if ( mask & allocpdc ) /* FreeMem for 2 -> n-1 */
{
pdc = pdTop->DC_next;
while ( pdc != pdEnd)
{
pdc1 = pdc;
pdc = pdc->DC_next;
pdTop->DC_next = pdc; /* maintain the linked-list */
if ( pdc1 != pdTop )
FreeMem( pdc1, sizeof(aekDC) );
}
}
FreeMem( pdTop, sizeof(aekDC) ); /* FreeMem for record 1 */
}
if ( mask & allocpdEnd )
FreeMem( pdEnd, sizeof(aekDC) ); /* FreeMem for record n */
if ( mask & svolddir )
dir = CurrentDir( olddir );
Exit();
}
/* Compares string to string (case insensitive). */
int compareci( to, from )
char *to;
char *from;
{
char a;
char b;
int c;
for ( ; ; *to++, *from++ )
{
a = *to;
b = *from;
if ( a >= 'A' && a <= 'Z' )
a = a - 'A' + 'a';
if ( b >= 'A' && b <= 'Z' )
b = b - 'A' + 'a';
c = ( int ) a - ( int) b;
if ( c || !a || !b )
return( c );
}
}
/* Copy string of characters (ending with NULL terminator) */
char *copy( to, from )
char *to; /* destination string */
char *from; /* source string */
{
char *temp = to;
while ( to && *from ) /* no zero destination allowed */
*to++ = *from++;
*to++ = '\0';
return(temp);
}
/* Copy exactly "n" characters (regardless of NULL terminator) */
char *copyn(to, from, n)
char *to; /* destination string */
char *from; /* source string */
int n; /* number of characters to be copied */
{
char *temp = to;
while ( n-- && to ) /* no zero destination allowed */
( *to++ = *from++ );
return(temp);
}
/* Fills a string with the specified character. */
char *fill_area( to, what, howmany)
char *to;
unsigned char what;
int howmany;
{
char *temp = to;
while ( howmany-- > 1 )
{
*to++ = what;
}
*to = '\0';
return(temp);
}
/* get memory to use as Disk Catalog record */
aekDC *getDCmem(source)
aekDC *source;
{
pdc = (aekDC *) AllocMem( sizeof( aekDC ), MEMF_CLEAR | MEMF_PUBLIC );
if ( !pdc )
{
printf( "Out of memory large enough for another record.\n" );
return( pdc );
}
calls++;
if ( source )
ign = copyn( (char *) pdc, (char *) source, sizeof(aekDC) );
UnDateStamp(ud, fb);
return(pdc);
}
/* Find proper location for "New", given ("Top", "End", "New"). */
void MergeDC(top, end, new)
aekDC *top;
aekDC *end;
aekDC *new;
{
int HiLo;
while (top != end) /* someone created a highvalues disk/path/file */
{
HiLo = compareci( top->DC_volume, new->DC_volume );
if (HiLo > 0)
break;
if (!HiLo)
{
HiLo = compareci( top->DC_path, new->DC_path );
if (HiLo > 0)
break;
if (!HiLo)
{
HiLo = compareci( top->DC_file, new->DC_file );
if (HiLo > 0)
break;
if (!HiLo)
{
HiLo = compareci( top->DC_ext, new->DC_ext );
if (HiLo > 0)
break;
}
}
}
top = top->DC_next;
}
top = top->DC_prior;
end = top->DC_next;
new->DC_next = top->DC_next;
new->DC_prior = top;
top->DC_next = new;
end->DC_prior = new;
}
/* Parse option string(s) and set indicators */
void options( array, oi )
char array[];
int oi;
{
int i = 0, j = 0;
while ( array[ oi + i ] )
{
if ( array[ oi + i ] == 'c' || array[ oi + i ] == 'C' )
{
color = TRUE;
i++;
}
else if ( array[ oi + i ] == 'v' || array[ oi + i ] == 'V' )
{
verbose = TRUE;
i++;
}
else if ( array[ oi + i ] == 'p' || array[ oi + i ] == 'P' )
{
redirect = TRUE;
i++;
}
else
{
if ( array[ oi + i ] == 'l' || array[ oi + i ] == 'L' )
{
fullpage = 0;
for ( j = 0; j = 2; j++ )
{
i++;
if ( array[ oi + i ] >= '0' && array[ oi + i ] <= '9' )
{
fullpage *= 10;
fullpage += array[ oi + i ] - '0';
}
else
break;
}
}
else
usage();
}
}
}
/* Print "Headings" for information display */
void print_headings()
{
printf( "\n" );
if ( redirect )
printf( " " ); /* indent for printer */
printf("F_i_l_e___N_a_m_e_____________ ");
printf("__Keys_ ");
printf("_Size_ ");
printf("Blks ");
printf("DD-MMM-YYYY ");
printf("__Time__\n");
thispage++;
}
/* Traverse a Directory until ERROR_NO_MORE_ENTRIES
* parent points to the directory record in core
* level is the number of ancestors in core */
void Traverse( parent, Level, pasdir )
aekDC *parent; /* Parent record to be cloned */
int Level; /* Number of branches from the trunk */
struct FileLock *pasdir; /* AmigaDOS directory I am examining */
{
struct FileLock *mydir; /* AmigaDOS directory my child will examine */
char mydirname[volsize+pathsize]; /* Selected AmigaDOS directory */
int subs = 0; /* number of sub-directories I found */
Level++;
while ( ExNext( dir, fb) != 0 || IoErr() != ERROR_NO_MORE_ENTRIES )
{
pdc = getDCmem( parent );
if ( pdc )
mask |= allocpdc;
else
break;
if ( verbose && !redirect )
printf( "%02d Files/Directories in Level %02d.\r", calls, Level);
pdc->DC_key = fb->fib_DiskKey;
pdc->DC_size = 0;
pdc->DC_blocks = fb->fib_NumBlocks;
if ( fb->fib_DirEntryType > 0 )
{
subs++;
pdc->DC_type = 'D' ;
pdc->DC_size = ( long ) Level;
if ( pdc->DC_path[0] == ' ' || !pdc->DC_path[0] )
{
ign = copy( pdc->DC_path, "" );
}
else
{
ign = append( pdc->DC_path, "/", sizeof(pdc->DC_path) );
}
ign = append( pdc->DC_path, fb->fib_FileName, sizeof(pdc->DC_path) );
}
else
{
pdc->DC_size = fb->fib_Size;
pdc->DC_type = 'F' ;
ign = copy( pdc->DC_file, fb->fib_FileName );
}
MergeDC( parent, pdEnd, pdc );
}
UnLock( pasdir ); /* release parent directory */
while ( subs-- > 0 )
{
pdc = parent;
while ( pdc->DC_type != 'D' || pdc->DC_size == 0 )
{ if ( pdc->DC_volume[0] == HIGHVALUE )
break;
else
pdc = pdc->DC_next;
}
pdc->DC_size = 0;
ign = copy( mydirname, pdc->DC_volume );
ign = append( mydirname, pdc->DC_path, sizeof(mydirname) );
mydir = Lock( mydirname, ACCESS_READ );
if ( !mydir | !Examine( mydir, fb ) )
{
printf( "Program error, '%s' is not a directory\n", mydirname );
close_things();
}
Traverse( pdc, Level, mydir ); /* follow limb thru branches to leaves */
}
}
/* Translate DateStamp to "Sat Sep 05 14:45:13 1987 !" */
UnDateStamp( o, i )
struct DateTime *o;
AmigaFIB *i;
{
static struct Calendar Mon_table[] =
{
0, 0, " ", /* null entry for month number "00" */
0, 31, "Jan", /* non-leap year calendar */
31, 28, "Feb",
59, 31, "Mar",
90, 30, "Apr",
120, 31, "May",
151, 30, "Jun",
181, 31, "Jul",
212, 31, "Aug",
243, 30, "Sep",
273, 31, "Oct",
304, 30, "Nov",
334, 31, "Dec",
0, 31, "Jan", /* leap year calendar */
31, 29, "Feb",
60, 31, "Mar",
91, 30, "Apr",
121, 31, "May",
152, 30, "Jun",
182, 31, "Jul",
213, 31, "Aug",
244, 30, "Sep",
274, 31, "Oct",
305, 30, "Nov",
335, 31, "Dec"
} ;
/* Day-of-the-week array */
static char WeekDays[][4] =
{
"Sun",
"Mon",
"Tue",
"Wed",
"Thu",
"Fri",
"Sat"
} ;
int h, m, s, d, mm, y, ly, wd, j; /* work fields */
d = i->fib_Date.ds_Days - 1; /* days since 12/31/1977 */
wd = i->fib_Date.ds_Days % 7; /* day-of-the-week */
y = 1978; /* years (base was 1978) */
for (;;)
{
h = y % 4;
if (h = 0)
ly = 12;
else
ly = 0;
j = Mon_table[12+ly].yearday + Mon_table[12+ly].lastday;
if (d >= j)
{
y++;
d = d - j;
}
else
break;
}
for (mm = 1; mm < 13; mm++)
if (d > Mon_table[mm+ly].lastday)
d = d - Mon_table[mm+ly].lastday;
else break;
h = i->fib_Date.ds_Minute / 60; /* hours */
m = i->fib_Date.ds_Minute % 60; /* minutes */
s = i->fib_Date.ds_Tick / TICKS_PER_SECOND; /* seconds */
ign = copy(o->DT_wday, WeekDays[wd]);
ign = copy(o->DT_month, Mon_table[mm].monname);
sprintf(o->DT_mday, "%02d", d);
sprintf(o->DT_time, "%02d:%02d:%02d", h, m, s);
sprintf(o->DT_year, "%04d", y);
ign = copy( pdc->DC_dmy, o->DT_mday );
ign = append( pdc->DC_dmy, "-", sizeof(pdc->DC_dmy) );
ign = append( pdc->DC_dmy, o->DT_month, sizeof(pdc->DC_dmy) );
ign = append( pdc->DC_dmy, "-", sizeof(pdc->DC_dmy) );
ign = append( pdc->DC_dmy, o->DT_year, sizeof(pdc->DC_dmy) );
ign = copy( pdc->DC_time, o->DT_time );
return(0);
}
/* Display format of AList command */
void usage()
{
printf("Usage: AList [>prt:] [dirname] [opt pcvl19 | -c -v -l45 -p]\n");
printf( " where: c=color display\n" );
printf( " p=printer re-direction [>prt:] used\n" );
printf( " v=verbose\n" );
printf( " and l=lines/'page' (22 = full med-res CLI)\n");
Exit();
}