2 Copyright © 1995-2007, The AROS Development Team. All rights reserved.
9 /******************************************************************************
18 DISKS/S, VOLS=VOLUMES/S, ALL/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 ALL -- show 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 Harddisk: 964.1M 776.7M 187.4M 81% 0 read/write OFS AROS
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
72 ******************************************************************************/
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>
91 #define ID_MAC_DISK2 (0x4d414300L) /* MAC\0 - xfs mac disk */
92 #define ID_MNX1_DISK (0x4d4e5801L) /* MNX\1 - xfs minix disk */
93 #define ID_MNX2_DISK (0x4d4e5802L) /* MNX\2 - xfs minix disk */
94 #define ID_QL5A_DISK (0x514c3541L) /* QL5A - xfs ql 720k / ed disk */
95 #define ID_QL5B_DISK (0x514c3542L) /* QL5B - xfs ql 1440k disk */
96 #define ID_ZXS0_DISK (0x5a585300L) /* Spectrum Disciple - xfs */
97 #define ID_ZXS1_DISK (0x5a585301L) /* Spectrum UniDos - xfs */
98 #define ID_ZXS2_DISK (0x5a585302L) /* Spectrum SamDos - xfs */
99 #define ID_ZXS4_DISK (0x5a585304L) /* Spectrum Opus 180k - xfs */
100 #define ID_ARME_DISK (0x41524d44L) /* Archimedes - xfs */
101 #define ID_ARMD_DISK (0x41524d43L) /* Archimedes - xfs */
102 #define ID_CPM_DISK (0x43505c4dL) /* CP/M - xfs */
103 #define ID_ZXS3_DISK (0x5a585303L) /* ZXS\3 - Plus3Dos xfs */
104 #define ID_1541_DISK (0x31353431L) /* 1541 - xfs */
105 #define ID_1581_DISK (0x31353831L) /* 1581 - xfs */
106 #define ID_MAC_DISK (0x4d534800L) /* MSH\0 - CrossDos MACDisk ?! */
107 #define ID_ACD0_DISK (0x41434400L) /* ACD\0 - AmiCDFS disk */
108 #define ID_CDFS_DISK (0x43444653L) /* CDFS - AmiCDFS disk */
109 #define ID_CACHECDFS_DISK (0x43443031L)
110 #define ID_ASIMCDFS_DISK (0x662dabacL)
111 #define ID_PFS2_DISK (0x50465302L)
112 #define ID_PFS2_SCSI_DISK (0x50445300L)
113 #define ID_PFS2_muFS_DISK (0x6d755046L)
114 #define ID_FLOPPY_PFS_DISK (0x50465300L)
115 #define ID_P2A0_DISK (0x50324130L)
116 #define ID_AFS0_DISK (0x41465300L) /* AFS\0 */
117 #define ID_muFS_DISK (0x6d754653L) /* muFS - Mulituserfsys */
118 #define ID_FAT12_DISK (0x46415400L) /* FAT12 */
119 #define ID_FAT16_DISK (0x46415401L) /* FAT16 */
120 #define ID_FAT32_DISK (0x46415402L) /* FAT32 */
125 ULONG
ComputeKBytes(ULONG a
, ULONG b
);
126 void FmtProcedure(struct Hook
*hook
, char a
, struct Locale
*locale
);
127 ULONG
ExtUDivMod32(ULONG a
, ULONG b
, ULONG
*mod
);
131 const TEXT VersionStr
[] = "$VER: Info 41.1 (16.11.2000)";
134 struct Locale
*loc
= NULL
;
140 /* catalog string id:s */
161 struct InfoDosNode
*Next
;
164 struct MsgPort
*Task
;
165 struct DateStamp VolumeDate
;
169 struct InfoDosNode
*head
= NULL
;
177 struct DiskTypeList dtl
[] =
179 { ID_DOS_DISK
, "OFS" },
180 { ID_FFS_DISK
, "FFS" },
181 { ID_INTER_DOS_DISK
, "OFS-INT" },
182 { ID_INTER_FFS_DISK
, "FFS-INT" },
183 { ID_FASTDIR_DOS_DISK
, "OFS-DC" },
184 { ID_FASTDIR_FFS_DISK
, "FFS-DC" },
185 { ID_MSDOS_DISK
, "MS-DOS" },
186 { ID_ACD0_DISK
, "CDFS" },
187 { ID_CACHECDFS_DISK
, "CDFS" },
188 { ID_ASIMCDFS_DISK
, "CDFS" },
189 { ID_NOT_REALLY_DOS
, "NO DOS" },
190 { ID_MAC_DISK2
, "MAC" },
191 { ID_MNX1_DISK
, "Minix" },
192 { ID_QL5A_DISK
, "QL720k" },
193 { ID_QL5B_DISK
, "QL1.4M" },
194 { ID_CPM_DISK
, "CP/M" },
195 { ID_ZXS3_DISK
, "+3Dos" },
196 { ID_ZXS0_DISK
, "Disciple " },
197 { ID_ZXS1_DISK
, "UniDos" },
198 { ID_ZXS2_DISK
, "SamDos" },
199 { ID_ZXS4_DISK
, "Opus" },
200 { ID_P2A0_DISK
, "NETWORK" },
201 { ID_FAT12_DISK
, "FAT12" },
202 { ID_FAT16_DISK
, "FAT16" },
203 { ID_FAT32_DISK
, "FAT32" },
204 { ID_FAT32_DISK
, "FAT32" },
205 { ID_SFS_BE_DISK
, "SFS" },
206 { ID_SFS_LE_DISK
, "sfs" },
211 /****************************************************************************/
213 int UtilityBase_version
= 0;
214 int LocaleBase_version
= 0;
220 static struct TagItem loctags
[] = { { OC_Version
, 1 },
222 cat
= OpenCatalogA(NULL
, "info_com.catalog", loctags
);
223 loc
= OpenLocale(NULL
);
225 D(bug("Calling doInfo()\n"));
232 return RETURN_OK
; /* TODO: Fix this */
236 CONST_STRPTR
GetStrFromCat(ULONG id
, CONST_STRPTR def
)
240 def
= GetCatalogStr(cat
, id
, def
);
247 void LPrintf(ULONG id
, CONST_STRPTR def
, ...) __stackparm
;
249 void LPrintf(ULONG id
, CONST_STRPTR def
, ...)
251 def
= GetStrFromCat(id
, def
);
253 VPrintf(def
, ((IPTR
*)(&def
))+1);
257 BOOL
myMatchPatternNoCase(STRPTR
*array
, STRPTR str
)
261 while(*array
!= NULL
)
266 UBYTE len
= strlen(p
);
268 if(p
[len
- 1] != ':')
270 CopyMem(p
, name
, len
);
276 if(ParsePatternNoCase(p
, matchstr
, sizeof(matchstr
)) != -1)
278 if(MatchPatternNoCase(matchstr
, str
))
292 BOOL
ScanDosList(STRPTR
*filter
)
294 struct InfoDosNode
*idn
= 0L;
295 struct DosList
*ndl
, *dl
;
296 STRPTR
*strray
= NULL
, dummy
= NULL
;
299 D(bug("Entered ScanDosList()\n"));
301 if (filter
== NULL
) filter
= &dummy
;
305 strray
= AllocPooled(Pool
, sizeof(STRPTR
)*MAX_MULTIARGS
);
315 while(i
< MAX_MULTIARGS
)
322 /* lock list of devices & vols */
323 dl
= ndl
= LockDosList(LDF_ASSIGNS
| LDF_VOLUMES
| LDF_DEVICES
| LDF_READ
);
332 while((ndl
= NextDosEntry(ndl
, LDF_ASSIGNS
| LDF_VOLUMES
| LDF_READ
)) != NULL
)
335 STRPTR taskName
= NULL
; /* Initialized to avoid a warning */
337 __sprintf(name
, "%s:", ndl
->dol_Ext
.dol_AROS
.dol_DevName
);
339 if ((ndl
->dol_Type
> DLT_VOLUME
) || !(myMatchPatternNoCase(strray
, name
)))
344 switch (ndl
->dol_Type
)
347 taskName
= ndl
->dol_Ext
.dol_AROS
.dol_DevName
; // ((struct Task *)ndl->dol_Task->mp_SigTask)->tc_Node.ln_Name;
349 D(bug("Found volume %s\n", taskName
));
354 struct AssignList
*al
= ndl
->dol_misc
.dol_assign
.dol_List
;
357 taskName
= ndl
->dol_Ext
.dol_AROS
.dol_DevName
; // ((struct Task *)((struct FileLock *)BADDR(ndl->dol_Lock))->fl_Task->mp_SigTask)->tc_Node.ln_Name;
359 D(bug("Found directory %s\n", taskName
));
363 *p
++ = ""; // TODO!!! ((struct Task *)((struct FileLock *)BADDR(al->al_Lock))->fl_Task->mp_SigTask)->tc_Node.ln_Name;
378 while((ndl
= NextDosEntry(ndl
, LDF_VOLUMES
| LDF_DEVICES
| LDF_READ
)) != NULL
)
381 UBYTE type
= ndl
->dol_Type
;
384 // if(((type == DLT_DEVICE))) // && (!ndl->dol_Task) TODO Check this!
387 __sprintf(name
, "%s:", ndl
->dol_Ext
.dol_AROS
.dol_DevName
);
389 D(bug("Found name %s\n", ndl
->dol_Ext
.dol_AROS
.dol_DevName
));
391 if((type
== DLT_DEVICE
) && (myMatchPatternNoCase(strray
, name
) == FALSE
))
395 D(bug("Failure! -- name = %s, strray = %p\n", name
, (void *)strray
));
397 for (i
= 0; strray
[i
] != NULL
; i
++)
399 D(bug("Strray %i = %s\n", i
, strray
[i
]));
405 idn
= (struct InfoDosNode
*)AllocPooled(Pool
, sizeof(struct InfoDosNode
));
413 // idn->Task = (struct MsgPort *)ndl->dol_Task;
414 idn
->IsVolume
= type
== DLT_VOLUME
;
416 while((idn
->Name
[len
] = name
[len
]))
419 if(type
== DLT_VOLUME
)
421 idn
->VolumeDate
= ((struct DeviceList
*)ndl
)->dl_VolumeDate
;
422 idn
->Name
[len
- 1] = '\0'; /* remove ':' */
426 BPTR ptr
= BADDR(ndl
->dol_misc
.dol_handler
.dol_Startup
);
427 struct FileSysStartupMsg
*fssm
= (struct FileSysStartupMsg
*)ptr
;
429 idn
->DosType
= ID_DOS_DISK
;
438 de
= (struct DosEnvec
*)BADDR(fssm
->fssm_Environ
);
440 if (de
&& (de
->de_TableSize
& 0xffffff00) == 0)
442 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,ALL/S,BLOCKS/S,DEVICES/M",
588 BOOL disks
= (BOOL
)args
[ARG_DISKS
];
589 BOOL vols
= (BOOL
)args
[ARG_VOLS
];
590 BOOL showall
= (BOOL
)args
[ARG_ALL
];
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) && showall
)
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
)