home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
454.lha
/
fsi
/
fsi.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-12-08
|
18KB
|
715 lines
/*
fsi - a comprehensive File System Information utility for the Amiga
Usage: fsi [-x] [device|volume|assign|file|directory name] [...]
Include -x if you want extended device information
*/
#include <stdio.h>
#include <string.h>
#include <dos.h>
#include <libraries/dos.h>
#include <libraries/dosextens.h>
#include <libraries/filehandler.h>
#include <exec/tasks.h>
#include <exec/nodes.h>
#include <exec/ports.h>
#include <exec/memory.h>
#include <proto/exec.h>
#include <proto/dos.h>
#define toAPTR(b) (void *)((LONG)(b)<<2)
#define toBPTR(a) (BPTR)((LONG)(a)>>2)
#define ID_OFS_DISK 0x444F5300
#define ID_FFS_DISK 0x444F5301
byte extended = 0; /* Captain! I see a flag in the distance! */
char *c;
char name[FMSIZE+1];
APTR old_pr_WindowPtr;
BPTR lock = NULL;
struct Process *process = NULL;
struct InfoData *info = NULL;
struct FileInfoBlock *fib = NULL;
void clean_exit(int xcode)
{
if (lock) UnLock(lock);
if (info) FreeMem(info,sizeof(struct InfoData));
if (fib) FreeMem(fib,sizeof(struct FileInfoBlock));
if (process)
{
Forbid();
process->pr_WindowPtr = old_pr_WindowPtr;
Permit();
}
printf("\n");
exit(xcode);
}
int strsam(char *str1, char *str2)
{
while( (*str1) && (*str2) )
{
if ( toupper(*str1) != toupper(*str2) ) return(0);
str1++;
str2++;
}
if ( (!*str1) && (!*str2) ) return(1);
return(0);
}
int bstrsam(char *str1, BSTR bstr)
{
register char *str2 = toAPTR(bstr);
if (strlen(str1) != (int)*str2) return(0);
str2++;
while(*str1)
{
if ( toupper(*str1) != toupper(*str2) ) return(0);
str1++;
str2++;
}
return(1);
}
void bstrcpy(char *str, BSTR bstr)
{
register char *c = toAPTR(bstr);
register int len = (int)*c;
stccpy(str, ++c, ++len);
}
void get_bcplname(char *str, BSTR bstr)
{
register char *c = toAPTR(bstr);
if ( (!c) || (!*c) )
{
strcpy(str,"3munknown0m");
}
else
{
bstrcpy(str,bstr);
}
}
struct DeviceList *DevList(void)
{
register struct DosInfo *dos;
register struct RootNode *root;
root = (struct RootNode *)DOSBase->dl_Root;
dos = toAPTR(root->rn_Info);
return(toAPTR(dos->di_DevInfo));
}
/*
** this function will search for a node which has the specified task
** pointer and type -- although one trackdisk.device task can handle
** two or more drives, each FileSystem handler can only handle one drive.
** therefore, each drive in your system (DF0:,DF1:,DF2:,DF3:,etc.) gets
** its own FileSystem task. to put it another way, each DLT_DEVICE has a
** unique dn_Task field. When a volume is mounted in a drive, the
** volume's DLT_VOLUME node contains a pointer in the dn_Task field which
** identifies the handler task for the drive that the volume is mounted
** on. you can search the device list for that drive/device if you wish.
** likewise, to find what volume is mounted on a particular device,
** search the list for a DLT_VOLUME that has the same dn_Task pointer.
** this function is meant to be used in both situations. note that if a
** DLT_VOLUME node has a NULL dn_Task field that means that the volume is
** NOT currently mounted in any drive. likewise, if you have a device
** node but fail to find a volume node with the same dn_Task, there is no
** volume currently mounted in that device.
*/
struct DeviceNode *find_obj(struct MsgPort *task, ULONG type)
{
register struct DeviceNode *dn;
if (!task) return(NULL);
Forbid();
for(dn = (struct DeviceNode *)DevList(); dn; dn = toAPTR(dn->dn_Next))
{
if ( (dn->dn_Type == type) && (dn->dn_Task == task) ) break;
}
Permit();
return(dn);
}
/*
** this function will search the device list for a node with the given name
*/
struct DeviceNode *lookup_name(char *name)
{
register struct DeviceNode *dn;
register char *colon;
if ( (!name) || (!*name) ) return(NULL);
for(colon = name; *colon; colon++);
colon--;
if (*colon == ':') *colon = '\0'; /* it should... */
Forbid();
for(dn = (struct DeviceNode *)DevList(); dn; dn = toAPTR(dn->dn_Next))
{
if (bstrsam(name,dn->dn_Name)) break;
}
Permit();
if (*colon == '\0') *colon = ':';
return(dn);
}
void show_datestamp(struct DateStamp *ds)
{
char time_date[26];
ULONG secs;
/* calculate time & date in seconds */
secs=(
(ds->ds_Days*86400L) /* days since 1978 * secs per day */
+(ds->ds_Minute*60) /* minutes since midnite * 60 secs */
+(ds->ds_Tick/TICKS_PER_SECOND) /* seconds since minute */
+252460800L /* number of seconds between 1970 &1978 (2 leap years) */
+21600L /* correction factor of six hours (for DST)... */
/* obviously this will not work properly everywhere */
/* (can you say K-L-U-D-G-E ??) */
);
strcpy(time_date,(char *)ctime(&secs));
time_date[24]='\0';
printf("Last modified: %s\n",time_date);
}
void show_protection(ULONG p)
{
char protection[9];
/* build protection string */
protection[8]='\0';
protection[7]=(p&1L) ?'-':'d';
protection[6]=(p&2L) ?'-':'e';
protection[5]=(p&4L) ?'-':'w';
protection[4]=(p&8L) ?'-':'r';
protection[3]=(p&16L)?'a':'-';
protection[2]=(p&32L)?'p':'-';
protection[1]=(p&64L)?'s':'-';
protection[0]='-';
printf("Protection bits: %s\n",protection);
}
void extended_devinfo(struct DeviceNode *dev)
{
struct FileSysStartupMsg *startup;
struct DosEnvec *env;
struct Task *task;
char temp[FMSIZE+1];
if (!extended) return; /* user hasn't requested this stuff */
if (!dev)
{
printf("\n3mNo extended device information is available0m\n");
return;
}
printf("\n3mExtended device information:0m\n");
printf("(note: the following information is not consistently\n");
printf(" used by all AmigaDOS devices, and therefore may be\n");
printf(" partially or wholly invalid for this particular device)\n\n");
get_bcplname(temp,dev->dn_Handler);
printf("FS handler:\t%s\n",temp);
if (dev->dn_Task)
{
task = dev->dn_Task->mp_SigTask;
if (task)
{
c = task->tc_Node.ln_Name;
if ( (c) && (*c) )
{
strcpy(temp,c);
}
else
{
goto notaskname;
}
}
else
{
notaskname:
strcpy(temp,"3munknown0m");
}
printf("Task name:\t%s\n",temp);
}
startup = toAPTR(dev->dn_Startup);
if (startup)
{
get_bcplname(temp,startup->fssm_Device);
printf("Device name:\t%s\n",temp);
printf("Unit number:\t%lu\n",startup->fssm_Unit);
env = toAPTR(startup->fssm_Environ);
if (env)
{
switch(env->de_DosType)
{
case ID_OFS_DISK:
{
strcpy(temp,"Old file system");
break;
}
case ID_FFS_DISK:
{
strcpy(temp,"Fast file system");
break;
}
default:
{
sprintf(temp,"3munknown0m (0x%08X)",env->de_DosType);
break;
}
}
printf("File System:\t%s\n",temp);
printf("Bytes/Block:\t%lu\n",(env->de_SizeBlock * sizeof(long)));
printf("Surfaces:\t%lu\n",env->de_Surfaces);
printf("Blocks/Track:\t%lu\n",env->de_BlocksPerTrack);
printf("Low Cylinder:\t%lu\n",env->de_LowCyl);
printf("High Cylinder:\t%lu\n",env->de_HighCyl);
printf("Reserved:\t%lu\n",env->de_Reserved);
printf("Interleave:\t%lu\n",env->de_Interleave);
printf("Buffers:\t%lu\n",env->de_NumBuffers);
printf("Boot Priority:\t%ld\n",env->de_BootPri);
}
}
}
void extra_volinfo(char *volname)
{
BPTR vlock;
int rc;
LONG blocks, bytes;
char temp[FMSIZE+1];
vlock = Lock(name,ACCESS_READ);
if (!vlock) return;
rc = Info(vlock,info);
UnLock(vlock);
if (rc == DOSFALSE) return;
/* disk type */
switch(info->id_DiskType)
{
case ID_UNREADABLE_DISK:
{
strcpy(temp,"Unreadable");
break;
}
case ID_DOS_DISK:
{
strcpy(temp,"Normal DOS disk");
break;
}
case ID_NOT_REALLY_DOS:
{
strcpy(temp,"Not DOS");
break;
}
case ID_KICKSTART_DISK:
{
strcpy(temp,"Kickstart");
break;
}
default:
{
strcpy(temp,"3munknown0m");
break;
}
}
printf("Disk type:\t%s\n",temp);
/* disk status */
switch(info->id_DiskState)
{
case ID_WRITE_PROTECTED:
{
strcpy(temp,"Write protected (read only)");
break;
}
case ID_VALIDATING:
{
strcpy(temp,"Not validated (currently unusable)");
break;
}
case ID_VALIDATED:
{
strcpy(temp,"Read/Write (validated)");
break;
}
default:
{
strcpy(temp,"3munknown0m");
break;
}
}
printf("Status:\t\t%s",temp);
if (info->id_InUse == DOSTRUE) printf(" (disk is busy)");
printf("\n");
/* disk capacity info */
printf("Bytes/Block:\t%ld\n",info->id_BytesPerBlock);
printf("Soft errors:\t%ld\n",info->id_NumSoftErrors);
blocks = info->id_NumBlocks;
bytes = (blocks * info->id_BytesPerBlock);
printf("Capacity:\t%ld blocks;\t%ld bytes\n",blocks,bytes);
blocks = info->id_NumBlocksUsed;
bytes = (blocks * info->id_BytesPerBlock);
printf("Space used:\t%ld blocks;\t%ld bytes\n",blocks,bytes);
blocks = (info->id_NumBlocks - blocks);
bytes = (blocks * info->id_BytesPerBlock);
printf("Space free:\t%ld blocks;\t%ld bytes\n",blocks,bytes);
}
void show_volinfo(char *name, struct DeviceList *vol)
{
register struct DeviceNode *dev;
char temp[FMSIZE+1];
printf("Volume \"%s\" is ",name);
dev = find_obj(vol->dl_Task,DLT_DEVICE);
if (!dev)
{
printf("not mounted\n");
printf("Additional information is unavailable\n");
return;
}
bstrcpy(temp,dev->dn_Name);
strcat(temp,":");
printf("mounted on device \"%s\"\n",temp);
extra_volinfo(name);
extended_devinfo(dev);
}
void show_fileinfo(char *name, BPTR lock, struct FileInfoBlock *fib)
{
char temp[FMSIZE+1];
getpath(lock,temp);
if (!strchr(temp,':')) strcat(temp,":");
printf("Full path name: \"%s\"\n",temp);
printf("File size: %lu bytes\n",fib->fib_Size);
show_datestamp(&fib->fib_Date);
show_protection(fib->fib_Protection);
if (fib->fib_Comment[0])
{
printf("Comment: %s\n",fib->fib_Comment);
}
printf("\n");
c = strchr(temp,':');
*++c = '\0';
show_volinfo(temp,(struct DeviceList *)lookup_name(temp));
}
void show_dirinfo(char *name, BPTR lock, struct FileInfoBlock *fib)
{
char temp[FMSIZE+1];
getpath(lock,temp);
if (!strchr(temp,':')) strcat(temp,":");
for(c = temp; *c; c++);
c--;
if ( (*c != ':') && (*c != '/') ) strcat(temp,"/");
printf("Full path name: \"%s\"\n",temp);
show_datestamp(&fib->fib_Date);
if (fib->fib_DirEntryType > 0) show_protection(fib->fib_Protection);
printf("\n");
c = strchr(temp,':');
*++c = '\0';
show_volinfo(temp,(struct DeviceList *)lookup_name(temp));
}
void show_devinfo(char *name, struct DeviceNode *dev)
{
struct DeviceList *dl;
char temp[FMSIZE+1];
if (!dev->dn_Task)
{
printf("non-filing system device\n");
get_bcplname(temp,dev->dn_Handler);
printf("FS handler:\t%s\n",temp);
return;
}
printf("filing system device\n");
dl = (struct DeviceList *)find_obj(dev->dn_Task,DLT_VOLUME);
if (!dl)
{
printf("There is no volume presently mounted in this device\n");
}
else
{
bstrcpy(temp,dl->dl_Name);
strcat(temp,":");
printf("\nVolume \"%s\" is currently mounted in this device\n",temp);
extra_volinfo(temp);
}
extended_devinfo(dev);
}
void show_assigninfo(char *name, struct DeviceList *dev)
{
BPTR alock;
struct FileLock *fl;
struct DeviceList *dl;
char volname[FMSIZE+1];
/* get volume name */
alock = dev->dl_Lock;
if (!alock) return;
fl = toAPTR(alock);
dl = toAPTR(fl->fl_Volume);
bstrcpy(volname,dl->dl_Name);
/* check if volume is mounted */
dl = (struct DeviceList *)find_obj(fl->fl_Task,DLT_VOLUME);
/* no, just show name of volume */
if (!dl)
{
printf("It identifies a directory or file on volume: \"%s:\"\n",volname);
printf("The volume is not mounted\n");
printf("Additional information is unavailable\n");
return;
}
/* yes, get all info for this object */
Examine(alock,fib);
if (fib->fib_DirEntryType > 0) /* a directory */
{
if (strsam(fib->fib_FileName,volname))
{
printf("It identifies the root directory of volume: \"%s\"\n",fib->fib_FileName);
fib->fib_DirEntryType = 0L; /* prevents show_dirinfo() from
** attempting to display protection
** bits for this volume name */
}
else
{
printf("It identifies a directory: \"%s\"\n",fib->fib_FileName);
}
show_dirinfo(fib->fib_FileName,alock,fib);
}
else
{
printf("It identifies a file: \"%s\"\n",fib->fib_FileName);
show_fileinfo(fib->fib_FileName,alock,fib);
}
}
void handle_switch(char *arg)
{
switch(toupper(arg[1]))
{
case 'X': /* extended info on */
{
extended = 1;
break;
}
default:
{
printf("\nUnrecognized switch: \"%s\"\n",arg);
break;
}
}
}
void add_colon(char *name)
{
printf("\nYou forgot to postfix a colon to this name.\n");
printf("Remember that AmigaDOS will not recognize it\n");
printf("without a colon attached.\n");
strcat(name,":");
}
main(int argc, char *argv[])
{
int arg;
register struct DeviceNode *dn;
if (argc == 0) exit(0); /* We're men here, we don't do Workbench! */
printf("\n3;33;40mFile System Info v1.0 0m- created by Ray Lambert\n");
if (argc == 1)
{
printf("\nCLI usage: fsi [-x] <name>\n");
printf(" where <name> is the name of any filing system object\n");
printf(" and -x is an optional switch to request extended\n");
printf(" device information\n\n");
exit(0);
}
/* get memory for a struct InfoData */
info = AllocMem(sizeof(struct InfoData),MEMF_PUBLIC|MEMF_CLEAR);
if (!info)
{
nomem:
printf("\nSorry, not enough memory\n\n");
clean_exit(20);
}
/* get memory for a struct FileInfoBlock */
fib = AllocMem(sizeof(struct FileInfoBlock),MEMF_PUBLIC|MEMF_CLEAR);
if (!fib) goto nomem;
/* disable DOS requesters */
Forbid();
process = (struct Process *)FindTask(NULL);
old_pr_WindowPtr = process->pr_WindowPtr;
process->pr_WindowPtr = (void *)-1L;
Permit();
/* look at all args */
for(arg = 1; arg < argc; arg++)
{
if (argv[arg][0] == '-') /* a switch */
{
handle_switch(argv[arg]);
continue;
}
strcpy(name,argv[arg]);
/* is this a device/volume/assign name? */
c = strchr(name,':');
if (c) c++;
if ( (!c) || (!*c) )
/* apparently not, but it may still be... */
{
dn = lookup_name(name);
if (!dn) goto tryalock; /* not in the device list, trying getting a lock */
if ( (!c) || (*c) ) add_colon(name);
switch(dn->dn_Type)
{
case DLT_DEVICE:
{
printf("\n\"%s\" is a ",name);
show_devinfo(name,dn);
break;
}
case DLT_VOLUME:
{
printf("\n\"%s\" is a volume name\n",name);
show_volinfo(name,(struct DeviceList *)dn);
break;
}
case DLT_DIRECTORY:
{
printf("\n\"%s\" is a logical name\n",name);
show_assigninfo(name,(struct DeviceList *)dn);
break;
}
default:
{
goto noinfo;
}
}
}
else
/* it is (presumably) a file or directory */
{
tryalock:
lock = Lock(name,ACCESS_READ);
if (!lock)
{
noinfo:
if (strsam("NIL",name)) add_colon(name);
if (strsam("NIL:",name))
{
printf("\n\"NIL:\" is a 'fake' filing system device which\n");
printf("is normally used to suppress unwanted output\n");
printf("from programs which write to the CLI...\n");
printf("Additional information is unavailable\n");
continue;
}
printf("\nSorry, can't get any information for \"%s\"\n",argv[arg]);
continue;
}
Examine(lock,fib);
if (fib->fib_DirEntryType > 0) /* a directory */
{
printf("\n\"%s\" is a directory name\n",name);
show_dirinfo(name,lock,fib);
}
else
{
printf("\n\"%s\" is a file name\n",name);
show_fileinfo(name,lock,fib);
}
UnLock(lock);
lock = NULL;
}
}
clean_exit(0);
}