home *** CD-ROM | disk | FTP | other *** search
- /*
-
- 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);
- }
-