2 Copyright © 1995-2015, 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_PFS_DISK (0x50465301L) /* PFS */
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 - Multiuserfsys */
119 #define ID_FAT12_DISK (0x46415400L) /* FAT12 */
120 #define ID_FAT16_DISK (0x46415401L) /* FAT16 */
121 #define ID_FAT32_DISK (0x46415402L) /* FAT32 */
122 #define ID_EXT2_DISK (0x45585432L) /* Extended 2 - Linux */
127 ULONG
ComputeKBytes(ULONG a
, ULONG b
);
128 void FmtProcedure(struct Hook
*hook
, char a
, struct Locale
*locale
);
129 ULONG
ExtUDivMod32(ULONG a
, ULONG b
, ULONG
*mod
);
133 const TEXT VersionStr
[] = "$VER: Info 41.2 (26.05.2012)";
136 struct Locale
*loc
= NULL
;
142 /* catalog string id:s */
163 struct InfoDosNode
*Next
;
166 struct MsgPort
*Task
;
167 struct DateStamp VolumeDate
;
171 struct InfoDosNode
*head
= NULL
;
179 struct DiskTypeList dtl
[] =
181 { ID_DOS_DISK
, "OFS" },
182 { ID_FFS_DISK
, "FFS" },
183 { ID_INTER_DOS_DISK
, "OFS-INT" },
184 { ID_INTER_FFS_DISK
, "FFS-INT" },
185 { ID_FASTDIR_DOS_DISK
, "OFS-DC" },
186 { ID_FASTDIR_FFS_DISK
, "FFS-DC" },
187 { ID_MSDOS_DISK
, "MS-DOS" },
188 { ID_ACD0_DISK
, "CDFS" },
189 { ID_CACHECDFS_DISK
, "CDFS" },
190 { ID_ASIMCDFS_DISK
, "CDFS" },
191 { ID_NOT_REALLY_DOS
, "NO DOS" },
192 { ID_MAC_DISK2
, "MAC" },
193 { ID_MNX1_DISK
, "Minix" },
194 { ID_QL5A_DISK
, "QL720k" },
195 { ID_QL5B_DISK
, "QL1.4M" },
196 { ID_CPM_DISK
, "CP/M" },
197 { ID_ZXS3_DISK
, "+3Dos" },
198 { ID_ZXS0_DISK
, "Disciple " },
199 { ID_ZXS1_DISK
, "UniDos" },
200 { ID_ZXS2_DISK
, "SamDos" },
201 { ID_ZXS4_DISK
, "Opus" },
202 { ID_P2A0_DISK
, "NETWORK" },
203 { ID_FAT12_DISK
, "FAT12" },
204 { ID_FAT16_DISK
, "FAT16" },
205 { ID_FAT32_DISK
, "FAT32" },
206 { ID_SFS_BE_DISK
, "SFS" },
207 { ID_SFS_LE_DISK
, "sfs" },
208 { ID_PFS_DISK
, "PFS" },
209 { ID_EXT2_DISK
, "EXT2" },
214 /****************************************************************************/
216 int UtilityBase_version
= 0;
217 int LocaleBase_version
= 0;
223 static struct TagItem loctags
[] = { { OC_Version
, 1 },
225 cat
= OpenCatalogA(NULL
, "info_com.catalog", loctags
);
226 loc
= OpenLocale(NULL
);
228 D(bug("Calling doInfo()\n"));
235 return RETURN_OK
; /* TODO: Fix this */
239 CONST_STRPTR
GetStrFromCat(ULONG id
, CONST_STRPTR def
)
243 def
= GetCatalogStr(cat
, id
, def
);
250 void VLPrintf(ULONG id
, CONST_STRPTR def
, ...)
252 CONST_STRPTR format
= GetStrFromCat(id
, def
);
253 AROS_SLOWSTACKFORMAT_PRE_USING(def
, format
);
254 VPrintf(format
, AROS_SLOWSTACKFORMAT_ARG(def
));
255 AROS_SLOWSTACKFORMAT_POST(def
);
259 BOOL
myMatchPatternNoCase(STRPTR
*array
, STRPTR str
)
263 while(*array
!= NULL
)
268 UBYTE len
= strlen(p
);
270 if(p
[len
- 1] != ':')
272 CopyMem(p
, name
, len
);
278 if(ParsePatternNoCase(p
, matchstr
, sizeof(matchstr
)) != -1)
280 if(MatchPatternNoCase(matchstr
, str
))
294 BOOL
ScanDosList(STRPTR
*filter
)
296 struct InfoDosNode
*idn
= 0L;
297 struct DosList
*ndl
, *dl
;
298 STRPTR
*strray
= NULL
, dummy
= NULL
;
301 D(bug("Entered ScanDosList()\n"));
303 if (filter
== NULL
) filter
= &dummy
;
307 strray
= AllocPooled(Pool
, sizeof(STRPTR
)*MAX_MULTIARGS
);
317 while(i
< MAX_MULTIARGS
)
324 /* lock list of devices & vols */
325 dl
= ndl
= LockDosList(LDF_ASSIGNS
| LDF_VOLUMES
| LDF_DEVICES
| LDF_READ
);
334 while((ndl
= NextDosEntry(ndl
, LDF_ASSIGNS
| LDF_VOLUMES
| LDF_READ
)) != NULL
)
337 STRPTR taskName
= NULL
; /* Initialized to avoid a warning */
339 __sprintf(name
, "%b:", ndl
->dol_Name
);
341 if ((ndl
->dol_Type
> DLT_VOLUME
) || !(myMatchPatternNoCase(strray
, name
)))
346 switch (ndl
->dol_Type
)
349 taskName
= ((struct Task
*)ndl
->dol_Task
->mp_SigTask
)->tc_Node
.ln_Name
;
351 D(bug("Found volume %s\n", taskName
));
356 struct AssignList
*al
= ndl
->dol_misc
.dol_assign
.dol_List
;
358 taskName
= ((struct Task
*)((struct FileLock
*)BADDR(ndl
->dol_Lock
))->fl_Task
->mp_SigTask
)->tc_Node
.ln_Name
;
360 D(bug("Found directory %s\n", taskName
));
364 *p
++ = ""; // TODO!!! ((struct Task *)((struct FileLock *)BADDR(al->al_Lock))->fl_Task->mp_SigTask)->tc_Node.ln_Name;
379 while((ndl
= NextDosEntry(ndl
, LDF_VOLUMES
| LDF_DEVICES
| LDF_READ
)) != NULL
)
382 UBYTE type
= ndl
->dol_Type
;
385 /* do not start non-started handlers or open CON: or RAW: windows */
386 if(type
== DLT_DEVICE
&& !ndl
->dol_Task
)
389 __sprintf(name
, "%b:", ndl
->dol_Name
);
390 D(bug("Found name %s\n", name
));
392 if((type
== DLT_DEVICE
) && (myMatchPatternNoCase(strray
, name
) == FALSE
))
396 D(bug("Failure! -- name = %s, strray = %p\n", name
, (void *)strray
));
398 D(for (i
= 0; strray
[i
] != NULL
; i
++)
400 bug("Strray %i = %s\n", i
, strray
[i
]);
406 idn
= (struct InfoDosNode
*)AllocPooled(Pool
, sizeof(struct InfoDosNode
));
414 idn
->Task
= ndl
->dol_Task
;
415 idn
->IsVolume
= type
== DLT_VOLUME
;
417 while((idn
->Name
[len
] = name
[len
]))
420 if(type
== DLT_VOLUME
)
422 idn
->VolumeDate
= ((struct DeviceList
*)ndl
)->dl_VolumeDate
;
423 idn
->Name
[len
- 1] = '\0'; /* remove ':' */
427 BPTR ptr
= ndl
->dol_misc
.dol_handler
.dol_Startup
;
428 struct FileSysStartupMsg
*fssm
= NULL
;
430 if (IsFileSystem(idn
->Name
))
432 // Only filesystems have a valid FileSysStartupMsg
433 fssm
= (struct FileSysStartupMsg
*)BADDR(ptr
);
436 idn
->DosType
= ID_DOS_DISK
;
445 de
= (struct DosEnvec
*)BADDR(fssm
->fssm_Environ
);
447 if (de
&& (de
->de_TableSize
& 0xffffff00) == 0)
449 idn
->DosType
= de
->de_DosType
;
453 /* kinda insert sort */
455 struct InfoDosNode
*work
= head
;
456 struct InfoDosNode
*prev
= NULL
;
458 while((work
!= NULL
) && (Stricmp(idn
->Name
, work
->Name
) > 0))
473 /* unlock list of devices and volumes */
474 UnLockDosList(LDF_ASSIGNS
| LDF_VOLUMES
| LDF_DEVICES
| LDF_READ
);
476 // strray freed at DeletePool
482 void PrintNum(ULONG num
)
497 num
= ExtUDivMod32(UMult32(num
, 100) >> 10, 100, &x
);
500 x
= ExtUDivMod32(x
, 10, &xx
);
511 VLPrintf(BIGNUMFMT
, "%5ld.%ld%lc", num
, x
, fmt
);
515 VLPrintf(SMALLNUMFMT
, "%7ldK", num
);
520 STRPTR
GetFSysStr(ULONG DiskType
)
522 struct DiskTypeList
*dtlptr
= dtl
;
527 if(dtlptr
->id
== DiskType
)
532 } while(*((ULONG
*)dtlptr
++));
536 static TEXT buffer
[5];
538 ptr
= (STRPTR
)buffer
;
539 *((ULONG
*)ptr
) = AROS_LONG2BE(DiskType
);
564 struct RDArgs
*rdargs
;
565 struct Process
*proc
;
567 struct InfoDosNode
*idn
;
569 struct InfoData
*id
= AllocVec(sizeof(struct InfoData
), MEMF_ANY
);
571 IPTR args
[] = { (IPTR
)FALSE
,
577 CONST_STRPTR unit
= GetStrFromCat(UNIT
, "Unit");
581 PrintFault(ERROR_NO_FREE_STORE
, NULL
);
585 Pool
= CreatePool(MEMF_ANY
, 1024, 1024);
589 PrintFault(ERROR_NO_FREE_STORE
, NULL
);
593 D(bug("Calling ReadArgs()\n"));
596 rdargs
= ReadArgs("DISKS/S,VOLS=VOLUMES/S,ALL/S,BLOCKS/S,DEVICES/M",
601 BOOL disks
= (BOOL
)args
[ARG_DISKS
];
602 BOOL vols
= (BOOL
)args
[ARG_VOLS
];
603 BOOL showall
= (BOOL
)args
[ARG_ALL
];
604 BOOL blocks
= (BOOL
)args
[ARG_BLOCKS
];
605 STRPTR
*devs
= (STRPTR
*)args
[ARG_DEVS
];
607 if (devs
&& (*devs
== NULL
)) devs
= NULL
;
609 /* If nothing is specified, show everything we got */
610 if(devs
== NULL
&& !disks
&& !vols
)
616 /* check pattern strings */
625 if(ParsePatternNoCase(*p
, matchstr
, sizeof(matchstr
)) == -1)
627 PrintFault(IoErr(), *p
);
635 /* avoid requesters */
636 proc
= (struct Process
*)FindTask(NULL
);
637 win
= (struct Window
*)proc
->pr_WindowPtr
;
638 proc
->pr_WindowPtr
= (struct Window
*)~0;
640 MaxLen
= strlen(unit
);
642 D(bug("Calling ScanDosList()\n"));
645 if(ScanDosList(devs
))
647 CONST_STRPTR dstate
[3] = { GetStrFromCat(READONLY
, "read only"),
648 GetStrFromCat(VALIDATING
, "validating"),
649 GetStrFromCat(READWRITE
, "read/write") };
650 STRPTR datetimeFmt
= NULL
;
655 D(bug("Printing stuff\n"));
657 /* get datetimefmt string */
658 if(loc
&& (GetVar("info_datetime", buf
, sizeof(buf
), 0L) > 0L))
663 /* calc format string for 'Unit' */
664 __sprintf(nfmtstr
, "%%-%lds", MaxLen
);
666 /* show device infomation */
667 if(devs
!= NULL
|| disks
|| !vols
)
669 for(idn
= head
; idn
; idn
= idn
->Next
)
672 STRPTR name
= idn
->Name
;
674 D(bug("Got name = %s\n", name
));
676 if(!idn
->IsVolume
&& IsFileSystem(name
))
678 BOOL gotinfo
= FALSE
;
679 /* if first device to print, print title */
685 D(bug("Printing device\n"));
687 VLPrintf(~0, nfmtstr
, unit
);
688 VLPrintf(DEVTITLE
, " Size Used Free Full Errs State Type Name\n");
693 VLPrintf(~0, nfmtstr
, name
);
695 D(bug("Locking \"%s\"\n", name
));
696 lock
= Lock(name
, SHARED_LOCK
);
698 D(bug("Lock = %p\n", (APTR
)lock
));
702 D(bug("Got lock on %s\n", name
));
704 if(Info(lock
, id
) == DOSTRUE
)
706 D(bug("Calling NameFromLock()\n"));
708 if(NameFromLock(lock
, name
, 108L))
710 LONG len
= strlen(name
) - 1;
722 } else if (idn
->Task
) {
724 D(bug("Calling ACTION_DISK_INFO\n"));
725 if (DoPkt(idn
->Task
, ACTION_DISK_INFO
, (SIPTR
)MKBADDR(id
), (SIPTR
)BNULL
, (SIPTR
)BNULL
, (SIPTR
)BNULL
, (SIPTR
)BNULL
)) {
733 D(bug("Got info on %s\n", name
));
735 if (id
->id_DiskType
== ID_NO_DISK_PRESENT
) {
736 VLPrintf(~0, " No disk present\n");
737 } else if (id
->id_DiskType
== ID_NOT_REALLY_DOS
) {
738 VLPrintf(~0, " Not a DOS disk\n");
739 } else if (id
->id_DiskType
== ID_UNREADABLE_DISK
) {
740 VLPrintf(~0, " Unreadable disk\n");
742 x
= ComputeKBytes(id
->id_NumBlocks
, id
->id_BytesPerBlock
);
743 y
= ComputeKBytes(id
->id_NumBlocksUsed
, id
->id_BytesPerBlock
);
757 x
= ExtUDivMod32(UDivMod32(UMult32(y
, 1000), x
), 10, &y
);
765 // y = ((struct DeviceList *)BADDR(id->id_VolumeNode))->dl_DiskType;
770 if((idn
->DosType
& ID_DOS_DISK
) != ID_DOS_DISK
)
774 VLPrintf(DEVFMTSTR
, "%4ld%% %4ld %-11s%-8s%s\n",
775 x
, id
->id_NumSoftErrors
,
776 ((id
->id_DiskState
>= ID_WRITE_PROTECTED
) && (id
->id_DiskState
<= ID_VALIDATED
)) ? (const char *)dstate
[id
->id_DiskState
- ID_WRITE_PROTECTED
] : (const char *)"",
784 "\nTotal blocks: %-10ld Blocks used: %ld\n"
785 " Blocks free: %-10ld Blocksize: %ld\n",
787 id
->id_NumBlocksUsed
,
788 id
->id_NumBlocks
-id
->id_NumBlocksUsed
,
789 id
->id_BytesPerBlock
);
795 D(bug("Info failure\n"));
802 /* just ignore PIPEFS */
803 if (err
== ERROR_ACTION_NOT_KNOWN
)
804 if (strcmp(name
, "PIPEFS:") == 0)
809 VLPrintf(~0, nfmtstr
, name
);
810 PrintFault(err
, NULL
);
818 if(vols
|| (!devs
&& !disks
))
823 VLPrintf(DISKSTITLE
, "Volumes\n");
825 /* find the longest volume name */
826 for(MaxLen
= 15, idn
= head
; idn
; idn
= idn
->Next
)
830 LONG len
= strlen(idn
->Name
);
837 __sprintf(nfmtstr
, "%%-%lds%%-10s", MaxLen
+1);
839 for(idn
= head
; idn
; idn
= idn
->Next
)
843 VLPrintf(VOLNAMEFMTSTR
, nfmtstr
, idn
->Name
,
844 idn
->Task
? (const char *)GetStrFromCat(MOUNTEDSTR
, "[Mounted]") : (const char *)"");
846 if(idn
->VolumeDate
.ds_Days
!= 0)
851 static struct Hook hook
;
853 memset(&hook
, 0, sizeof(struct Hook
));
855 hook
.h_SubEntry
= (HOOKFUNC
)FmtProcedure
;
856 hook
.h_Data
= datestr
;
858 FormatDate(loc
, datetimeFmt
, &idn
->VolumeDate
, &hook
);
864 TEXT StrDay
[LEN_DATSTRING
];
865 TEXT StrDate
[LEN_DATSTRING
];
866 TEXT StrTime
[LEN_DATSTRING
];
870 dt
.dat_Flags
= DTF_SUBST
;
871 dt
.dat_Format
= FORMAT_DOS
;
872 dt
.dat_StrDay
= StrDay
;
873 dt
.dat_StrDate
= StrDate
;
874 dt
.dat_StrTime
= StrTime
;
875 dt
.dat_Stamp
= idn
->VolumeDate
;
879 if(Strnicmp(StrDate
, StrDay
, strlen(StrDay
)) == 0)
885 VLPrintf(DATEFMTSTR
, "created %.3s, %-10s %s", StrDay
, StrDate
, StrTime
);
897 PrintFault( ERROR_NO_FREE_STORE
, NULL
);
900 /* reset window pointer of our process */
901 proc
->pr_WindowPtr
= win
;
908 end
: /* free allocated memory */
914 ULONG
ComputeKBytes(ULONG a
, ULONG b
)
916 // UQUAD result = UMult64(a, b);
918 UQUAD result
= (UQUAD
)a
* b
;
920 return (ULONG
)(result
>> 10);
924 void FmtProcedure(struct Hook
*hook
, char a
, struct Locale
*locale
)
926 *((STRPTR
)hook
->h_Data
) = a
;
927 hook
->h_Data
= (STRPTR
) hook
->h_Data
+ 1;
931 ULONG
ExtUDivMod32(ULONG a
, ULONG b
, ULONG
*mod
)