2 Copyright © 1995-2001, The AROS Development Team. All rights reserved.
9 /******************************************************************************
18 DISKS/S, VOLS=VOLUMES/S, GOODONLY/S, BLOCKS/S, DEVICES/M
26 Show information on file system devices and volumes. When given no
27 arguments, information on all devices and volumes found in the system
28 is displayed. If information is wanted only for some specific devices,
29 these names may be given as arguments.
33 DISKS -- show information on file system devices
34 VOLS -- show information on volumes
35 GOODONLY -- don't show any information on bad devices or volumes
36 BLOCKS -- show additional block size and usage information
37 DEVICES -- device names to show information about
47 Unit Size Used Free Full Errs State Type Name
48 Foreign harddisk: 964.1M 776.7M 187.4M 81% 0 read/write OFS Workbench
49 RAM: 8.0M 7.1M 7.1M 12% 0 read/write OFS Ram Disk
57 The original source showed that AROS version of ReadArgs() handles
58 the /M switch with zero arguments differently from AmigaOS. While AROS
59 returns an array where the first pointer is NULL, AmigaOS just returns
64 16.11.2000 SDuvan -- converted to AROS
65 23.12.2000 SDuvan -- changed semantics and updated
66 (now fully functional)
67 17.02.2005 Joe Fenton -- fixed 64bit calculation
69 Based on the original by:
70 © 1997-1998 by Stephan Rupprecht
75 #include <aros/debug.h>
78 #include <dos/dosextens.h>
79 #include <dos/filehandler.h>
80 #include <exec/memory.h>
81 #include <libraries/locale.h>
83 #include <proto/dos.h>
84 #include <proto/exec.h>
85 #include <proto/utility.h>
86 #include <proto/locale.h>
87 #include <proto/alib.h>
92 #define ID_MAC_DISK2 (0x4d414300L) /* MAC\0 - xfs mac disk */
93 #define ID_MNX1_DISK (0x4d4e5801L) /* MNX\1 - xfs minix disk */
94 #define ID_MNX2_DISK (0x4d4e5802L) /* MNX\2 - xfs minix disk */
95 #define ID_QL5A_DISK (0x514c3541L) /* QL5A - xfs ql 720k / ed disk */
96 #define ID_QL5B_DISK (0x514c3542L) /* QL5B - xfs ql 1440k disk */
97 #define ID_ZXS0_DISK (0x5a585300L) /* Spectrum Disciple - xfs */
98 #define ID_ZXS1_DISK (0x5a585301L) /* Spectrum UniDos - xfs */
99 #define ID_ZXS2_DISK (0x5a585302L) /* Spectrum SamDos - xfs */
100 #define ID_ZXS4_DISK (0x5a585304L) /* Spectrum Opus 180k - xfs */
101 #define ID_ARME_DISK (0x41524d44L) /* Archimedes - xfs */
102 #define ID_ARMD_DISK (0x41524d43L) /* Archimedes - xfs */
103 #define ID_CPM_DISK (0x43505c4dL) /* CP/M - xfs */
104 #define ID_ZXS3_DISK (0x5a585303L) /* ZXS\3 - Plus3Dos xfs */
105 #define ID_1541_DISK (0x31353431L) /* 1541 - xfs */
106 #define ID_1581_DISK (0x31353831L) /* 1581 - xfs */
107 #define ID_MAC_DISK (0x4d534800L) /* MSH\0 - CrossDos MACDisk ?! */
108 #define ID_ACD0_DISK (0x41434400L) /* ACD\0 - AmiCDFS disk */
109 #define ID_CDFS_DISK (0x43444653L) /* CDFS - AmiCDFS disk */
110 #define ID_CACHECDFS_DISK (0x43443031L)
111 #define ID_ASIMCDFS_DISK (0x662dabacL)
112 #define ID_PFS2_DISK (0x50465302L)
113 #define ID_PFS2_SCSI_DISK (0x50445300L)
114 #define ID_PFS2_muFS_DISK (0x6d755046L)
115 #define ID_FLOPPY_PFS_DISK (0x50465300L)
116 #define ID_P2A0_DISK (0x50324130L)
117 #define ID_AFS0_DISK (0x41465300L) /* AFS\0 */
118 #define ID_muFS_DISK (0x6d754653L) /* muFS - Mulituserfsys */
119 #define ID_FAT_DISK (0x46415400L) /* FAT12/16/32 */
124 ULONG
ComputeKBytes(ULONG a
, ULONG b
);
125 void FmtProcedure(struct Hook
*hook
, char a
, struct Locale
*locale
);
126 ULONG
ExtUDivMod32(ULONG a
, ULONG b
, ULONG
*mod
);
130 STRPTR VersionStr
= "$VER: Info 41.1 (16.11.2000)";
133 struct Locale
*loc
= NULL
;
139 /* catalog string id:s */
160 struct InfoDosNode
*Next
;
163 struct MsgPort
*Task
;
164 struct DateStamp VolumeDate
;
168 struct InfoDosNode
*head
= NULL
;
176 struct DiskTypeList dtl
[] =
178 { ID_DOS_DISK
, "OFS" },
179 { ID_FFS_DISK
, "FFS" },
180 { ID_INTER_DOS_DISK
, "OFS-INT" },
181 { ID_INTER_FFS_DISK
, "FFS-INT" },
182 { ID_FASTDIR_DOS_DISK
, "OFS-DC" },
183 { ID_FASTDIR_FFS_DISK
, "FFS-DC" },
184 { ID_MSDOS_DISK
, "MS-DOS" },
185 { ID_ACD0_DISK
, "CDFS" },
186 { ID_CACHECDFS_DISK
, "CDFS" },
187 { ID_ASIMCDFS_DISK
, "CDFS" },
188 { ID_NOT_REALLY_DOS
, "NO DOS" },
189 { ID_MAC_DISK2
, "MAC" },
190 { ID_MNX1_DISK
, "Minix" },
191 { ID_QL5A_DISK
, "QL720k" },
192 { ID_QL5B_DISK
, "QL1.4M" },
193 { ID_CPM_DISK
, "CP/M" },
194 { ID_ZXS3_DISK
, "+3Dos" },
195 { ID_ZXS0_DISK
, "Disciple " },
196 { ID_ZXS1_DISK
, "UniDos" },
197 { ID_ZXS2_DISK
, "SamDos" },
198 { ID_ZXS4_DISK
, "Opus" },
199 { ID_P2A0_DISK
, "NETWORK" },
200 { ID_FAT_DISK
, "FAT" },
205 /****************************************************************************/
207 int UtilityBase_version
= 0;
208 int LocaleBase_version
= 0;
214 static struct TagItem loctags
[] = { { OC_Version
, 1 },
216 cat
= OpenCatalogA(NULL
, "info_com.catalog", loctags
);
217 loc
= OpenLocale(NULL
);
219 D(bug("Calling doInfo()\n"));
226 return RETURN_OK
; /* TODO: Fix this */
230 CONST_STRPTR
GetStrFromCat(ULONG id
, CONST_STRPTR def
)
234 def
= GetCatalogStr(cat
, id
, def
);
241 void LPrintf(ULONG id
, CONST_STRPTR def
, ...) __stackparm
;
243 void LPrintf(ULONG id
, CONST_STRPTR def
, ...)
245 def
= GetStrFromCat(id
, def
);
247 VPrintf(def
, ((IPTR
*)(&def
))+1);
251 BOOL
myMatchPatternNoCase(STRPTR
*array
, STRPTR str
)
255 while(*array
!= NULL
)
260 UBYTE len
= strlen(p
);
262 if(p
[len
- 1] != ':')
264 CopyMem(p
, name
, len
);
270 if(ParsePatternNoCase(p
, matchstr
, sizeof(matchstr
)) != -1)
272 if(MatchPatternNoCase(matchstr
, str
))
286 BOOL
ScanDosList(STRPTR
*filter
)
288 struct InfoDosNode
*idn
= 0L;
289 struct DosList
*ndl
, *dl
;
290 STRPTR
*strray
= NULL
, dummy
= NULL
;
293 D(bug("Entered ScanDosList()\n"));
295 if (filter
== NULL
) filter
= &dummy
;
299 strray
= AllocPooled(Pool
, sizeof(STRPTR
)*MAX_MULTIARGS
);
309 while(i
< MAX_MULTIARGS
)
316 /* lock list of devices & vols */
317 dl
= ndl
= LockDosList(LDF_ASSIGNS
| LDF_VOLUMES
| LDF_DEVICES
| LDF_READ
);
326 while((ndl
= NextDosEntry(ndl
, LDF_ASSIGNS
| LDF_VOLUMES
| LDF_READ
)) != NULL
)
329 STRPTR taskName
= NULL
; /* Initialized to avoid a warning */
331 __sprintf(name
, "%s:", ndl
->dol_DevName
);
333 if ((ndl
->dol_Type
> DLT_VOLUME
) || !(myMatchPatternNoCase(strray
, name
)))
338 switch (ndl
->dol_Type
)
341 taskName
= ndl
->dol_DevName
; // ((struct Task *)ndl->dol_Task->mp_SigTask)->tc_Node.ln_Name;
343 D(bug("Found volume %s\n", taskName
));
348 struct AssignList
*al
= ndl
->dol_misc
.dol_assign
.dol_List
;
351 taskName
= ndl
->dol_DevName
; // ((struct Task *)((struct FileLock *)BADDR(ndl->dol_Lock))->fl_Task->mp_SigTask)->tc_Node.ln_Name;
353 D(bug("Found directory %s\n", taskName
));
357 *p
++ = ""; // TODO!!! ((struct Task *)((struct FileLock *)BADDR(al->al_Lock))->fl_Task->mp_SigTask)->tc_Node.ln_Name;
372 while((ndl
= NextDosEntry(ndl
, LDF_VOLUMES
| LDF_DEVICES
| LDF_READ
)) != NULL
)
375 UBYTE type
= ndl
->dol_Type
;
378 // if(((type == DLT_DEVICE))) // && (!ndl->dol_Task) TODO Check this!
381 __sprintf(name
, "%s:", ndl
->dol_DevName
);
383 D(bug("Found name %s\n", ndl
->dol_DevName
));
385 if((type
== DLT_DEVICE
) && (myMatchPatternNoCase(strray
, name
) == FALSE
))
389 D(bug("Failure! -- name = %s, strray = %p\n", name
, (void *)strray
));
391 for (i
= 0; strray
[i
] != NULL
; i
++)
393 D(bug("Strray %i = %s\n", i
, strray
[i
]));
399 idn
= (struct InfoDosNode
*)AllocPooled(Pool
, sizeof(struct InfoDosNode
));
407 // idn->Task = (struct MsgPort *)ndl->dol_Task;
408 idn
->IsVolume
= type
== DLT_VOLUME
;
410 while((idn
->Name
[len
] = name
[len
]))
413 if(type
== DLT_VOLUME
)
415 idn
->VolumeDate
= ((struct DeviceList
*)ndl
)->dl_VolumeDate
;
416 idn
->Name
[len
- 1] = '\0'; /* remove ':' */
420 // struct FileSysStartupMsg *fssm = (struct FileSysStartupMsg *)BADDR(ndl->dol_misc.dol_handler.dol_Startup);
422 idn
->DosType
= ID_DOS_DISK
;
431 if(*(UBYTE
*)fssm
== 0 || *(UBYTE
*)BADDR(fssm
->fssm_Device
) != 0)
433 struct DosEnvec
*de
= (struct DosEnvec
*)BADDR(fssm
->fssm_Environ
);
435 if(de
!= NULL
&& (de
->de_TableSize
& 0xffffff00) == 0L)
438 idn
->DosType
= de
->de_DosType
;
446 /* kinda insert sort */
448 struct InfoDosNode
*work
= head
;
449 struct InfoDosNode
*prev
= NULL
;
451 while((work
!= NULL
) && (Stricmp(idn
->Name
, work
->Name
) > 0))
466 /* unlock list of devices and volumes */
467 UnLockDosList(LDF_ASSIGNS
| LDF_VOLUMES
| LDF_DEVICES
| LDF_READ
);
469 // strray freed at DeletePool
475 void PrintNum(ULONG num
)
490 num
= ExtUDivMod32(UMult32(num
, 100) >> 10, 100, &x
);
493 x
= ExtUDivMod32(x
, 10, &xx
);
504 LPrintf(BIGNUMFMT
, "%5ld.%ld%lc", num
, x
, fmt
);
508 LPrintf(SMALLNUMFMT
, "%7ldK", num
);
513 STRPTR
GetFSysStr(ULONG DiskType
)
515 struct DiskTypeList
*dtlptr
= dtl
;
520 if(dtlptr
->id
== DiskType
)
525 } while(*((ULONG
*)dtlptr
++));
529 static TEXT buffer
[5];
531 ptr
= (STRPTR
)buffer
;
532 *((ULONG
*)ptr
) = DiskType
;
557 struct RDArgs
*rdargs
;
558 struct Process
*proc
;
560 struct InfoDosNode
*idn
;
562 static struct InfoData id
;
564 IPTR args
[] = { (IPTR
)FALSE
,
570 CONST_STRPTR unit
= GetStrFromCat(UNIT
, "Unit");
572 Pool
= CreatePool(MEMF_ANY
, 1024, 1024);
576 PrintFault(ERROR_NO_FREE_STORE
, NULL
);
580 D(bug("Calling ReadArgs()\n"));
583 rdargs
= ReadArgs("DISKS/S,VOLS=VOLUMES/S,GOODONLY/S,BLOCKS/S,DEVICES/M",
588 BOOL disks
= (BOOL
)args
[ARG_DISKS
];
589 BOOL vols
= (BOOL
)args
[ARG_VOLS
];
590 BOOL goodOnly
= (BOOL
)args
[ARG_GOODONLY
];
591 BOOL blocks
= (BOOL
)args
[ARG_BLOCKS
];
592 STRPTR
*devs
= (STRPTR
*)args
[ARG_DEVS
];
594 if (devs
&& (*devs
== NULL
)) devs
= NULL
;
596 /* If nothing is specified, show everything we got */
597 if(devs
== NULL
&& !disks
&& !vols
)
603 /* check pattern strings */
613 if(ParsePatternNoCase(*p
, matchstr
, sizeof(matchstr
)) == -1)
615 PrintFault(IoErr(), *p
);
623 /* avoid requesters */
624 proc
= (struct Process
*)FindTask(NULL
);
625 win
= (struct Window
*)proc
->pr_WindowPtr
;
626 proc
->pr_WindowPtr
= (struct Window
*)~0;
628 MaxLen
= strlen(unit
);
630 D(bug("Calling ScanDosList()\n"));
633 if(ScanDosList(devs
))
635 CONST_STRPTR dstate
[3] = { GetStrFromCat(READONLY
, "read only"),
636 GetStrFromCat(VALIDATING
, "validating"),
637 GetStrFromCat(READWRITE
, "read/write") };
638 STRPTR datetimeFmt
= NULL
;
643 D(bug("Printing stuff\n"));
645 /* get datetimefmt string */
646 if(loc
&& (GetVar("info_datetime", buf
, sizeof(buf
), 0L) > 0L))
651 /* calc format string for 'Unit' */
652 __sprintf(nfmtstr
, "%%-%lds", MaxLen
);
654 /* show device infomation */
655 if(devs
!= NULL
|| disks
|| !vols
)
657 for(idn
= head
; idn
; idn
= idn
->Next
)
660 STRPTR name
= idn
->Name
;
662 D(bug("Got name = %s\n", name
));
664 if(!idn
->IsVolume
&& IsFileSystem(name
))
666 /* if first device to print, print title */
672 D(bug("Printing device\n"));
674 LPrintf(~0, nfmtstr
, unit
);
675 LPrintf(DEVTITLE
, " Size Used Free Full Errs State Type Name\n");
680 D(bug("Locking \"%s\"\n", name
));
681 lock
= Lock(name
, SHARED_LOCK
);
683 D(bug("Lock = %p\n", lock
));
687 D(bug("Got lock on %s\n", name
));
689 if(Info(lock
, &id
) == DOSTRUE
)
693 D(bug("Got info on %s\n", name
));
695 LPrintf(~0, nfmtstr
, name
);
697 x
= ComputeKBytes(id
.id_NumBlocks
, id
.id_BytesPerBlock
);
698 y
= ComputeKBytes(id
.id_NumBlocksUsed
, id
.id_BytesPerBlock
);
704 D(bug("Calling NameFromLock()\n"));
706 if(NameFromLock(lock
, name
, 108L))
708 LONG len
= strlen(name
) - 1;
724 x
= ExtUDivMod32(UDivMod32(UMult32(y
, 1000), x
), 10, &y
);
732 // y = ((struct DeviceList *)BADDR(id.id_VolumeNode))->dl_DiskType;
737 if((idn
->DosType
& ID_DOS_DISK
) != ID_DOS_DISK
)
740 LPrintf(DEVFMTSTR
, "%4ld%% %4ld %-11s%-8s%s\n",
741 x
, id
.id_NumSoftErrors
,
742 ((id
.id_DiskState
>= ID_WRITE_PROTECTED
) && (id
.id_DiskState
<= ID_VALIDATED
)) ?
743 dstate
[id
.id_DiskState
- ID_WRITE_PROTECTED
] : (STRPTR
)"", GetFSysStr(y
), name
);
748 "\nTotal blocks: %-10ld Blocks used: %ld\n"
749 " Blocks free: %-10ld Blocksize: %ld\n",
750 id
.id_NumBlocks
, id
.id_NumBlocksUsed
,
751 id
.id_NumBlocks
-id
.id_NumBlocksUsed
, id
.id_BytesPerBlock
);
755 D(bug("Info failure\n"));
763 if((err
!= 0) && !goodOnly
)
765 LPrintf(~0, nfmtstr
, name
);
766 PrintFault(err
, NULL
);
774 if(vols
|| (!devs
&& !disks
))
779 LPrintf(DISKSTITLE
, "Volumes\n");
781 for(MaxLen
= 15, idn
= head
; idn
; idn
= idn
->Next
)
785 LONG len
= strlen(idn
->Name
);
792 __sprintf(nfmtstr
, "%%-%lds%%-10s", MaxLen
+1);
794 for(idn
= head
; idn
; idn
= idn
->Next
)
798 LPrintf(VOLNAMEFMTSTR
, nfmtstr
, idn
->Name
,
799 GetStrFromCat(MOUNTEDSTR
, "[Mounted]"));
800 // idn->Task ? GetStrFromCat(MOUNTEDSTR, "[Mounted]") : ""); TODO
805 static struct Hook hook
;
807 memset(&hook
, 0, sizeof(struct Hook
));
809 hook
.h_SubEntry
= (HOOKFUNC
)FmtProcedure
;
810 hook
.h_Data
= datestr
;
812 FormatDate(loc
, datetimeFmt
, &idn
->VolumeDate
, &hook
);
818 TEXT StrDay
[LEN_DATSTRING
];
819 TEXT StrDate
[LEN_DATSTRING
];
820 TEXT StrTime
[LEN_DATSTRING
];
824 dt
.dat_Flags
= DTF_SUBST
;
825 dt
.dat_Format
= FORMAT_DOS
;
826 dt
.dat_StrDay
= StrDay
;
827 dt
.dat_StrDate
= StrDate
;
828 dt
.dat_StrTime
= StrTime
;
829 dt
.dat_Stamp
= idn
->VolumeDate
;
833 if(Strnicmp(StrDate
, StrDay
, strlen(StrDay
)) == 0)
839 LPrintf(DATEFMTSTR
, "created %.3s, %-10s %s",
840 StrDay
, StrDate
, StrTime
);
851 PrintFault( ERROR_NO_FREE_STORE
, NULL
);
854 /* reset window pointer of our process */
855 proc
->pr_WindowPtr
= win
;
862 end
: /* free allocated memory */
868 ULONG
ComputeKBytes(ULONG a
, ULONG b
)
870 // UQUAD result = UMult64(a, b);
872 UQUAD result
= (UQUAD
)a
* b
;
874 return (ULONG
)(result
>> 10);
878 void FmtProcedure(struct Hook
*hook
, char a
, struct Locale
*locale
)
880 *((STRPTR
)hook
->h_Data
) = a
;
881 hook
->h_Data
= (STRPTR
) hook
->h_Data
+ 1;
885 ULONG
ExtUDivMod32(ULONG a
, ULONG b
, ULONG
*mod
)