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 */
123 ULONG
ComputeKBytes(ULONG a
, ULONG b
);
124 void FmtProcedure(struct Hook
*hook
, char a
, struct Locale
*locale
);
125 ULONG
ExtUDivMod32(ULONG a
, ULONG b
, ULONG
*mod
);
129 STRPTR VersionStr
= "$VER: Info 41.1 (16.11.2000)";
132 struct Locale
*loc
= NULL
;
138 /* catalog string id:s */
159 struct InfoDosNode
*Next
;
162 struct MsgPort
*Task
;
163 struct DateStamp VolumeDate
;
167 struct InfoDosNode
*head
= NULL
;
175 struct DiskTypeList dtl
[] =
177 { ID_DOS_DISK
, "OFS" },
178 { ID_FFS_DISK
, "FFS" },
179 { ID_INTER_DOS_DISK
, "OFS-INT" },
180 { ID_INTER_FFS_DISK
, "FFS-INT" },
181 { ID_FASTDIR_DOS_DISK
, "OFS-DC" },
182 { ID_FASTDIR_FFS_DISK
, "FFS-DC" },
183 { ID_MSDOS_DISK
, "MS-DOS" },
184 { ID_ACD0_DISK
, "CDFS" },
185 { ID_CACHECDFS_DISK
, "CDFS" },
186 { ID_ASIMCDFS_DISK
, "CDFS" },
187 { ID_NOT_REALLY_DOS
, "NO DOS" },
188 { ID_MAC_DISK2
, "MAC" },
189 { ID_MNX1_DISK
, "Minix" },
190 { ID_QL5A_DISK
, "QL720k" },
191 { ID_QL5B_DISK
, "QL1.4M" },
192 { ID_CPM_DISK
, "CP/M" },
193 { ID_ZXS3_DISK
, "+3Dos" },
194 { ID_ZXS0_DISK
, "Disciple " },
195 { ID_ZXS1_DISK
, "UniDos" },
196 { ID_ZXS2_DISK
, "SamDos" },
197 { ID_ZXS4_DISK
, "Opus" },
198 { ID_P2A0_DISK
, "NETWORK" },
203 /****************************************************************************/
205 int UtilityBase_version
= 0;
206 int LocaleBase_version
= 0;
212 static struct TagItem loctags
[] = { { OC_Version
, 1 },
214 cat
= OpenCatalogA(NULL
, "info_com.catalog", loctags
);
215 loc
= OpenLocale(NULL
);
217 D(bug("Calling doInfo()\n"));
224 return RETURN_OK
; /* TODO: Fix this */
228 CONST_STRPTR
GetStrFromCat(ULONG id
, CONST_STRPTR def
)
232 def
= GetCatalogStr(cat
, id
, def
);
239 void LPrintf(ULONG id
, CONST_STRPTR def
, ...) __stackparm
;
241 void LPrintf(ULONG id
, CONST_STRPTR def
, ...)
243 def
= GetStrFromCat(id
, def
);
245 VPrintf(def
, ((IPTR
*)(&def
))+1);
249 BOOL
myMatchPatternNoCase(STRPTR
*array
, STRPTR str
)
253 while(*array
!= NULL
)
258 UBYTE len
= strlen(p
);
260 if(p
[len
- 1] != ':')
262 CopyMem(p
, name
, len
);
268 if(ParsePatternNoCase(p
, matchstr
, sizeof(matchstr
)) != -1)
270 if(MatchPatternNoCase(matchstr
, str
))
284 BOOL
ScanDosList(STRPTR
*filter
)
286 struct InfoDosNode
*idn
= 0L;
287 struct DosList
*ndl
, *dl
;
288 STRPTR
*strray
= NULL
, dummy
= NULL
;
291 D(bug("Entered ScanDosList()\n"));
293 if (filter
== NULL
) filter
= &dummy
;
297 strray
= AllocPooled(Pool
, sizeof(STRPTR
)*MAX_MULTIARGS
);
307 while(i
< MAX_MULTIARGS
)
314 /* lock list of devices & vols */
315 dl
= ndl
= LockDosList(LDF_ASSIGNS
| LDF_VOLUMES
| LDF_DEVICES
| LDF_READ
);
324 while((ndl
= NextDosEntry(ndl
, LDF_ASSIGNS
| LDF_VOLUMES
| LDF_READ
)) != NULL
)
327 STRPTR taskName
= NULL
; /* Initialized to avoid a warning */
329 __sprintf(name
, "%s:", ndl
->dol_DevName
);
331 if ((ndl
->dol_Type
> DLT_VOLUME
) || !(myMatchPatternNoCase(strray
, name
)))
336 switch (ndl
->dol_Type
)
339 taskName
= ndl
->dol_DevName
; // ((struct Task *)ndl->dol_Task->mp_SigTask)->tc_Node.ln_Name;
341 D(bug("Found volume %s\n", taskName
));
346 struct AssignList
*al
= ndl
->dol_misc
.dol_assign
.dol_List
;
349 taskName
= ndl
->dol_DevName
; // ((struct Task *)((struct FileLock *)BADDR(ndl->dol_Lock))->fl_Task->mp_SigTask)->tc_Node.ln_Name;
351 D(bug("Found directory %s\n", taskName
));
355 *p
++ = ""; // TODO!!! ((struct Task *)((struct FileLock *)BADDR(al->al_Lock))->fl_Task->mp_SigTask)->tc_Node.ln_Name;
370 while((ndl
= NextDosEntry(ndl
, LDF_VOLUMES
| LDF_DEVICES
| LDF_READ
)) != NULL
)
373 UBYTE type
= ndl
->dol_Type
;
376 // if(((type == DLT_DEVICE))) // && (!ndl->dol_Task) TODO Check this!
379 __sprintf(name
, "%s:", ndl
->dol_DevName
);
381 D(bug("Found name %s\n", ndl
->dol_DevName
));
383 if((type
== DLT_DEVICE
) && (myMatchPatternNoCase(strray
, name
) == FALSE
))
387 D(bug("Failure! -- name = %s, strray = %p\n", name
, (void *)strray
));
389 for (i
= 0; strray
[i
] != NULL
; i
++)
391 D(bug("Strray %i = %s\n", i
, strray
[i
]));
397 idn
= (struct InfoDosNode
*)AllocPooled(Pool
, sizeof(struct InfoDosNode
));
405 // idn->Task = (struct MsgPort *)ndl->dol_Task;
406 idn
->IsVolume
= type
== DLT_VOLUME
;
408 while((idn
->Name
[len
] = name
[len
]))
411 if(type
== DLT_VOLUME
)
413 idn
->VolumeDate
= ((struct DeviceList
*)ndl
)->dl_VolumeDate
;
414 idn
->Name
[len
- 1] = '\0'; /* remove ':' */
418 // struct FileSysStartupMsg *fssm = (struct FileSysStartupMsg *)BADDR(ndl->dol_misc.dol_handler.dol_Startup);
420 idn
->DosType
= ID_DOS_DISK
;
429 if(*(UBYTE
*)fssm
== 0 || *(UBYTE
*)BADDR(fssm
->fssm_Device
) != 0)
431 struct DosEnvec
*de
= (struct DosEnvec
*)BADDR(fssm
->fssm_Environ
);
433 if(de
!= NULL
&& (de
->de_TableSize
& 0xffffff00) == 0L)
436 idn
->DosType
= de
->de_DosType
;
444 /* kinda insert sort */
446 struct InfoDosNode
*work
= head
;
447 struct InfoDosNode
*prev
= NULL
;
449 while((work
!= NULL
) && (Stricmp(idn
->Name
, work
->Name
) > 0))
464 /* unlock list of devices and volumes */
465 UnLockDosList(LDF_ASSIGNS
| LDF_VOLUMES
| LDF_DEVICES
| LDF_READ
);
467 // strray freed at DeletePool
473 void PrintNum(ULONG num
)
488 num
= ExtUDivMod32(UMult32(num
, 100) >> 10, 100, &x
);
491 x
= ExtUDivMod32(x
, 10, &xx
);
502 LPrintf(BIGNUMFMT
, "%5ld.%ld%lc", num
, x
, fmt
);
506 LPrintf(SMALLNUMFMT
, "%7ldK", num
);
511 STRPTR
GetFSysStr(ULONG DiskType
)
513 struct DiskTypeList
*dtlptr
= dtl
;
518 if(dtlptr
->id
== DiskType
)
523 } while(*((ULONG
*)dtlptr
++));
527 static TEXT buffer
[5];
529 ptr
= (STRPTR
)buffer
;
530 *((ULONG
*)ptr
) = DiskType
;
555 struct RDArgs
*rdargs
;
556 struct Process
*proc
;
558 struct InfoDosNode
*idn
;
560 static struct InfoData id
;
562 IPTR args
[] = { (IPTR
)FALSE
,
568 CONST_STRPTR unit
= GetStrFromCat(UNIT
, "Unit");
570 Pool
= CreatePool(MEMF_ANY
, 1024, 1024);
574 PrintFault(ERROR_NO_FREE_STORE
, NULL
);
578 D(bug("Calling ReadArgs()\n"));
581 rdargs
= ReadArgs("DISKS/S,VOLS=VOLUMES/S,GOODONLY/S,BLOCKS/S,DEVICES/M",
586 BOOL disks
= (BOOL
)args
[ARG_DISKS
];
587 BOOL vols
= (BOOL
)args
[ARG_VOLS
];
588 BOOL goodOnly
= (BOOL
)args
[ARG_GOODONLY
];
589 BOOL blocks
= (BOOL
)args
[ARG_BLOCKS
];
590 STRPTR
*devs
= (STRPTR
*)args
[ARG_DEVS
];
592 if (devs
&& (*devs
== NULL
)) devs
= NULL
;
594 /* If nothing is specified, show everything we got */
595 if(devs
== NULL
&& !disks
&& !vols
)
601 /* check pattern strings */
611 if(ParsePatternNoCase(*p
, matchstr
, sizeof(matchstr
)) == -1)
613 PrintFault(IoErr(), *p
);
621 /* avoid requesters */
622 proc
= (struct Process
*)FindTask(NULL
);
623 win
= (struct Window
*)proc
->pr_WindowPtr
;
624 proc
->pr_WindowPtr
= (struct Window
*)~0;
626 MaxLen
= strlen(unit
);
628 D(bug("Calling ScanDosList()\n"));
631 if(ScanDosList(devs
))
633 CONST_STRPTR dstate
[3] = { GetStrFromCat(READONLY
, "read only"),
634 GetStrFromCat(VALIDATING
, "validating"),
635 GetStrFromCat(READWRITE
, "read/write") };
636 STRPTR datetimeFmt
= NULL
;
641 D(bug("Printing stuff\n"));
643 /* get datetimefmt string */
644 if(loc
&& (GetVar("info_datetime", buf
, sizeof(buf
), 0L) > 0L))
649 /* calc format string for 'Unit' */
650 __sprintf(nfmtstr
, "%%-%lds", MaxLen
);
652 /* show device infomation */
653 if(devs
!= NULL
|| disks
|| !vols
)
655 for(idn
= head
; idn
; idn
= idn
->Next
)
658 STRPTR name
= idn
->Name
;
660 D(bug("Got name = %s\n", name
));
662 if(!idn
->IsVolume
&& IsFileSystem(name
))
664 /* if first device to print, print title */
670 D(bug("Printing device\n"));
672 LPrintf(~0, nfmtstr
, unit
);
673 LPrintf(DEVTITLE
, " Size Used Free Full Errs State Type Name\n");
678 D(bug("Locking \"%s\"\n", name
));
679 lock
= Lock(name
, SHARED_LOCK
);
681 D(bug("Lock = %p\n", lock
));
685 D(bug("Got lock on %s\n", name
));
687 if(Info(lock
, &id
) == DOSTRUE
)
691 D(bug("Got info on %s\n", name
));
693 LPrintf(~0, nfmtstr
, name
);
695 x
= ComputeKBytes(id
.id_NumBlocks
, id
.id_BytesPerBlock
);
696 y
= ComputeKBytes(id
.id_NumBlocksUsed
, id
.id_BytesPerBlock
);
702 D(bug("Calling NameFromLock()\n"));
704 if(NameFromLock(lock
, name
, 108L))
706 LONG len
= strlen(name
) - 1;
722 x
= ExtUDivMod32(UDivMod32(UMult32(y
, 1000), x
), 10, &y
);
730 // y = ((struct DeviceList *)BADDR(id.id_VolumeNode))->dl_DiskType;
735 if((idn
->DosType
& ID_DOS_DISK
) != ID_DOS_DISK
)
738 LPrintf(DEVFMTSTR
, "%4ld%% %4ld %-11s%-8s%s\n",
739 x
, id
.id_NumSoftErrors
,
740 ((id
.id_DiskState
>= ID_WRITE_PROTECTED
) && (id
.id_DiskState
<= ID_VALIDATED
)) ?
741 dstate
[id
.id_DiskState
- ID_WRITE_PROTECTED
] : (STRPTR
)"", GetFSysStr(y
), name
);
746 "\nTotal blocks: %-10ld Blocks used: %ld\n"
747 " Blocks free: %-10ld Blocksize: %ld\n",
748 id
.id_NumBlocks
, id
.id_NumBlocksUsed
,
749 id
.id_NumBlocks
-id
.id_NumBlocksUsed
, id
.id_BytesPerBlock
);
753 D(bug("Info failure\n"));
761 if((err
!= 0) && !goodOnly
)
763 LPrintf(~0, nfmtstr
, name
);
764 PrintFault(err
, NULL
);
772 if(vols
|| (!devs
&& !disks
))
777 LPrintf(DISKSTITLE
, "Volumes\n");
779 for(MaxLen
= 15, idn
= head
; idn
; idn
= idn
->Next
)
783 LONG len
= strlen(idn
->Name
);
790 __sprintf(nfmtstr
, "%%-%lds%%-10s", MaxLen
+1);
792 for(idn
= head
; idn
; idn
= idn
->Next
)
796 LPrintf(VOLNAMEFMTSTR
, nfmtstr
, idn
->Name
,
797 GetStrFromCat(MOUNTEDSTR
, "[Mounted]"));
798 // idn->Task ? GetStrFromCat(MOUNTEDSTR, "[Mounted]") : ""); TODO
803 static struct Hook hook
;
805 memset(&hook
, 0, sizeof(struct Hook
));
807 hook
.h_SubEntry
= (HOOKFUNC
)FmtProcedure
;
808 hook
.h_Data
= datestr
;
810 FormatDate(loc
, datetimeFmt
, &idn
->VolumeDate
, &hook
);
816 TEXT StrDay
[LEN_DATSTRING
];
817 TEXT StrDate
[LEN_DATSTRING
];
818 TEXT StrTime
[LEN_DATSTRING
];
822 dt
.dat_Flags
= DTF_SUBST
;
823 dt
.dat_Format
= FORMAT_DOS
;
824 dt
.dat_StrDay
= StrDay
;
825 dt
.dat_StrDate
= StrDate
;
826 dt
.dat_StrTime
= StrTime
;
827 dt
.dat_Stamp
= idn
->VolumeDate
;
831 if(Strnicmp(StrDate
, StrDay
, strlen(StrDay
)) == 0)
837 LPrintf(DATEFMTSTR
, "created %.3s, %-10s %s",
838 StrDay
, StrDate
, StrTime
);
849 PrintFault( ERROR_NO_FREE_STORE
, NULL
);
852 /* reset window pointer of our process */
853 proc
->pr_WindowPtr
= win
;
860 end
: /* free allocated memory */
866 ULONG
ComputeKBytes(ULONG a
, ULONG b
)
868 // UQUAD result = UMult64(a, b);
870 UQUAD result
= (UQUAD
)a
* b
;
872 return (ULONG
)(result
>> 10);
876 void FmtProcedure(struct Hook
*hook
, char a
, struct Locale
*locale
)
878 *((STRPTR
)hook
->h_Data
) = a
;
879 hook
->h_Data
= (STRPTR
) hook
->h_Data
+ 1;
883 ULONG
ExtUDivMod32(ULONG a
, ULONG b
, ULONG
*mod
)