2 Copyright © 1995-2012, 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
, const IPTR
* argarray
)
252 def
= GetStrFromCat(id
, def
);
253 VPrintf(def
, (IPTR
*)argarray
);
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
, "%b:", ndl
->dol_Name
);
339 if ((ndl
->dol_Type
> DLT_VOLUME
) || !(myMatchPatternNoCase(strray
, name
)))
344 switch (ndl
->dol_Type
)
347 taskName
= ((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
;
356 taskName
= ((struct Task
*)((struct FileLock
*)BADDR(ndl
->dol_Lock
))->fl_Task
->mp_SigTask
)->tc_Node
.ln_Name
;
358 D(bug("Found directory %s\n", taskName
));
362 *p
++ = ""; // TODO!!! ((struct Task *)((struct FileLock *)BADDR(al->al_Lock))->fl_Task->mp_SigTask)->tc_Node.ln_Name;
377 while((ndl
= NextDosEntry(ndl
, LDF_VOLUMES
| LDF_DEVICES
| LDF_READ
)) != NULL
)
380 UBYTE type
= ndl
->dol_Type
;
383 /* do not start non-started handlers or open CON: or RAW: windows.. */
384 if(type
== DLT_DEVICE
&& !ndl
->dol_Task
)
387 __sprintf(name
, "%b:", ndl
->dol_Name
);
388 D(bug("Found name %s\n", name
));
390 if((type
== DLT_DEVICE
) && (myMatchPatternNoCase(strray
, name
) == FALSE
))
394 D(bug("Failure! -- name = %s, strray = %p\n", name
, (void *)strray
));
396 for (i
= 0; strray
[i
] != NULL
; i
++)
398 D(bug("Strray %i = %s\n", i
, strray
[i
]));
404 idn
= (struct InfoDosNode
*)AllocPooled(Pool
, sizeof(struct InfoDosNode
));
412 idn
->Task
= ndl
->dol_Task
;
413 idn
->IsVolume
= type
== DLT_VOLUME
;
415 while((idn
->Name
[len
] = name
[len
]))
418 if(type
== DLT_VOLUME
)
420 idn
->VolumeDate
= ((struct DeviceList
*)ndl
)->dl_VolumeDate
;
421 idn
->Name
[len
- 1] = '\0'; /* remove ':' */
425 BPTR ptr
= ndl
->dol_misc
.dol_handler
.dol_Startup
;
426 struct FileSysStartupMsg
*fssm
= NULL
;
428 if (IsFileSystem(idn
->Name
))
430 // Only filesystems have a valid FileSysStartupMsg
431 fssm
= (struct FileSysStartupMsg
*)BADDR(ptr
);
434 idn
->DosType
= ID_DOS_DISK
;
443 de
= (struct DosEnvec
*)BADDR(fssm
->fssm_Environ
);
445 if (de
&& (de
->de_TableSize
& 0xffffff00) == 0)
447 idn
->DosType
= de
->de_DosType
;
451 /* kinda insert sort */
453 struct InfoDosNode
*work
= head
;
454 struct InfoDosNode
*prev
= NULL
;
456 while((work
!= NULL
) && (Stricmp(idn
->Name
, work
->Name
) > 0))
471 /* unlock list of devices and volumes */
472 UnLockDosList(LDF_ASSIGNS
| LDF_VOLUMES
| LDF_DEVICES
| LDF_READ
);
474 // strray freed at DeletePool
480 void PrintNum(ULONG num
)
495 num
= ExtUDivMod32(UMult32(num
, 100) >> 10, 100, &x
);
498 x
= ExtUDivMod32(x
, 10, &xx
);
509 IPTR args
[] = {num
, x
, fmt
};
510 VLPrintf(BIGNUMFMT
, "%5ld.%ld%lc", args
);
514 IPTR args
[] = { num
};
515 VLPrintf(SMALLNUMFMT
, "%7ldK", args
);
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 */
626 if(ParsePatternNoCase(*p
, matchstr
, sizeof(matchstr
)) == -1)
628 PrintFault(IoErr(), *p
);
636 /* avoid requesters */
637 proc
= (struct Process
*)FindTask(NULL
);
638 win
= (struct Window
*)proc
->pr_WindowPtr
;
639 proc
->pr_WindowPtr
= (struct Window
*)~0;
641 MaxLen
= strlen(unit
);
643 D(bug("Calling ScanDosList()\n"));
646 if(ScanDosList(devs
))
648 CONST_STRPTR dstate
[3] = { GetStrFromCat(READONLY
, "read only"),
649 GetStrFromCat(VALIDATING
, "validating"),
650 GetStrFromCat(READWRITE
, "read/write") };
651 STRPTR datetimeFmt
= NULL
;
656 D(bug("Printing stuff\n"));
658 /* get datetimefmt string */
659 if(loc
&& (GetVar("info_datetime", buf
, sizeof(buf
), 0L) > 0L))
664 /* calc format string for 'Unit' */
665 __sprintf(nfmtstr
, "%%-%lds", MaxLen
);
667 /* show device infomation */
668 if(devs
!= NULL
|| disks
|| !vols
)
670 for(idn
= head
; idn
; idn
= idn
->Next
)
673 STRPTR name
= idn
->Name
;
675 D(bug("Got name = %s\n", name
));
677 if(!idn
->IsVolume
&& IsFileSystem(name
))
679 BOOL gotinfo
= FALSE
;
680 /* if first device to print, print title */
686 D(bug("Printing device\n"));
688 VLPrintf(~0, nfmtstr
, (IPTR
*) &unit
);
689 VLPrintf(DEVTITLE
, " Size Used Free Full Errs State Type Name\n", NULL
);
694 VLPrintf(~0, nfmtstr
, (IPTR
*) &name
);
696 D(bug("Locking \"%s\"\n", name
));
697 lock
= Lock(name
, SHARED_LOCK
);
699 D(bug("Lock = %p\n", (APTR
)lock
));
703 D(bug("Got lock on %s\n", name
));
705 if(Info(lock
, id
) == DOSTRUE
)
707 D(bug("Calling NameFromLock()\n"));
709 if(NameFromLock(lock
, name
, 108L))
711 LONG len
= strlen(name
) - 1;
723 } else if (idn
->Task
) {
725 D(bug("Calling ACTION_DISK_INFO\n"));
726 if (DoPkt(idn
->Task
, ACTION_DISK_INFO
, (SIPTR
)MKBADDR(id
), (SIPTR
)BNULL
, (SIPTR
)BNULL
, (SIPTR
)BNULL
, (SIPTR
)BNULL
)) {
734 D(bug("Got info on %s\n", name
));
736 if (id
->id_DiskType
== ID_NO_DISK_PRESENT
) {
737 VLPrintf(~0, " No disk present\n", NULL
);
738 } else if (id
->id_DiskType
== ID_NOT_REALLY_DOS
) {
739 VLPrintf(~0, " Not a DOS disk\n", NULL
);
740 } else if (id
->id_DiskType
== ID_UNREADABLE_DISK
) {
741 VLPrintf(~0, " Unreadable disk\n", NULL
);
743 x
= ComputeKBytes(id
->id_NumBlocks
, id
->id_BytesPerBlock
);
744 y
= ComputeKBytes(id
->id_NumBlocksUsed
, id
->id_BytesPerBlock
);
758 x
= ExtUDivMod32(UDivMod32(UMult32(y
, 1000), x
), 10, &y
);
766 // y = ((struct DeviceList *)BADDR(id->id_VolumeNode))->dl_DiskType;
771 if((idn
->DosType
& ID_DOS_DISK
) != ID_DOS_DISK
)
777 id
->id_NumSoftErrors
,
778 ((id
->id_DiskState
>= ID_WRITE_PROTECTED
) && (id
->id_DiskState
<= ID_VALIDATED
)) ?
779 (IPTR
) dstate
[id
->id_DiskState
- ID_WRITE_PROTECTED
] : (IPTR
) "",
780 (IPTR
) GetFSysStr(y
),
782 VLPrintf(DEVFMTSTR
, "%4ld%% %4ld %-11s%-8s%s\n", args
);
789 id
->id_NumBlocksUsed
,
790 id
->id_NumBlocks
-id
->id_NumBlocksUsed
,
791 id
->id_BytesPerBlock
};
793 "\nTotal blocks: %-10ld Blocks used: %ld\n"
794 " Blocks free: %-10ld Blocksize: %ld\n",
801 D(bug("Info failure\n"));
802 VLPrintf(~0, "\n", NULL
);
808 /* just ignore PIPEFS */
809 if (err
== ERROR_ACTION_NOT_KNOWN
)
810 if (strcmp(name
, "PIPEFS:") == 0)
815 VLPrintf(~0, nfmtstr
, (IPTR
*) &name
);
816 PrintFault(err
, NULL
);
824 if(vols
|| (!devs
&& !disks
))
829 VLPrintf(DISKSTITLE
, "Volumes\n", NULL
);
831 for(MaxLen
= 15, idn
= head
; idn
; idn
= idn
->Next
)
835 LONG len
= strlen(idn
->Name
);
842 __sprintf(nfmtstr
, "%%-%lds%%-10s", MaxLen
+1);
844 for(idn
= head
; idn
; idn
= idn
->Next
)
850 (IPTR
) GetStrFromCat(MOUNTEDSTR
, "[Mounted]")};
851 // idn->Task ? GetStrFromCat(MOUNTEDSTR, "[Mounted]") : ""); TODO
852 VLPrintf(VOLNAMEFMTSTR
, nfmtstr
, args
);
857 static struct Hook hook
;
859 memset(&hook
, 0, sizeof(struct Hook
));
861 hook
.h_SubEntry
= (HOOKFUNC
)FmtProcedure
;
862 hook
.h_Data
= datestr
;
864 FormatDate(loc
, datetimeFmt
, &idn
->VolumeDate
, &hook
);
870 TEXT StrDay
[LEN_DATSTRING
];
871 TEXT StrDate
[LEN_DATSTRING
];
872 TEXT StrTime
[LEN_DATSTRING
];
876 dt
.dat_Flags
= DTF_SUBST
;
877 dt
.dat_Format
= FORMAT_DOS
;
878 dt
.dat_StrDay
= StrDay
;
879 dt
.dat_StrDate
= StrDate
;
880 dt
.dat_StrTime
= StrTime
;
881 dt
.dat_Stamp
= idn
->VolumeDate
;
885 if(Strnicmp(StrDate
, StrDay
, strlen(StrDay
)) == 0)
891 IPTR args
[] = {(IPTR
) StrDay
, (IPTR
) StrDate
, (IPTR
) StrTime
};
892 VLPrintf(DATEFMTSTR
, "created %.3s, %-10s %s", args
);
903 PrintFault( ERROR_NO_FREE_STORE
, NULL
);
906 /* reset window pointer of our process */
907 proc
->pr_WindowPtr
= win
;
914 end
: /* free allocated memory */
920 ULONG
ComputeKBytes(ULONG a
, ULONG b
)
922 // UQUAD result = UMult64(a, b);
924 UQUAD result
= (UQUAD
)a
* b
;
926 return (ULONG
)(result
>> 10);
930 void FmtProcedure(struct Hook
*hook
, char a
, struct Locale
*locale
)
932 *((STRPTR
)hook
->h_Data
) = a
;
933 hook
->h_Data
= (STRPTR
) hook
->h_Data
+ 1;
937 ULONG
ExtUDivMod32(ULONG a
, ULONG b
, ULONG
*mod
)