2 Copyright © 1995-2011, 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.1 (16.11.2000)";
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
= (struct FileSysStartupMsg
*)BADDR(ptr
);
428 idn
->DosType
= ID_DOS_DISK
;
437 de
= (struct DosEnvec
*)BADDR(fssm
->fssm_Environ
);
439 if (de
&& (de
->de_TableSize
& 0xffffff00) == 0)
441 idn
->DosType
= de
->de_DosType
;
445 /* kinda insert sort */
447 struct InfoDosNode
*work
= head
;
448 struct InfoDosNode
*prev
= NULL
;
450 while((work
!= NULL
) && (Stricmp(idn
->Name
, work
->Name
) > 0))
465 /* unlock list of devices and volumes */
466 UnLockDosList(LDF_ASSIGNS
| LDF_VOLUMES
| LDF_DEVICES
| LDF_READ
);
468 // strray freed at DeletePool
474 void PrintNum(ULONG num
)
489 num
= ExtUDivMod32(UMult32(num
, 100) >> 10, 100, &x
);
492 x
= ExtUDivMod32(x
, 10, &xx
);
503 IPTR args
[] = {num
, x
, fmt
};
504 VLPrintf(BIGNUMFMT
, "%5ld.%ld%lc", args
);
508 IPTR args
[] = { num
};
509 VLPrintf(SMALLNUMFMT
, "%7ldK", args
);
514 STRPTR
GetFSysStr(ULONG DiskType
)
516 struct DiskTypeList
*dtlptr
= dtl
;
521 if(dtlptr
->id
== DiskType
)
526 } while(*((ULONG
*)dtlptr
++));
530 static TEXT buffer
[5];
532 ptr
= (STRPTR
)buffer
;
533 *((ULONG
*)ptr
) = AROS_LONG2BE(DiskType
);
558 struct RDArgs
*rdargs
;
559 struct Process
*proc
;
561 struct InfoDosNode
*idn
;
563 struct InfoData
*id
= AllocVec(sizeof(struct InfoData
), MEMF_ANY
);
565 IPTR args
[] = { (IPTR
)FALSE
,
571 CONST_STRPTR unit
= GetStrFromCat(UNIT
, "Unit");
575 PrintFault(ERROR_NO_FREE_STORE
, NULL
);
579 Pool
= CreatePool(MEMF_ANY
, 1024, 1024);
583 PrintFault(ERROR_NO_FREE_STORE
, NULL
);
587 D(bug("Calling ReadArgs()\n"));
590 rdargs
= ReadArgs("DISKS/S,VOLS=VOLUMES/S,ALL/S,BLOCKS/S,DEVICES/M",
595 BOOL disks
= (BOOL
)args
[ARG_DISKS
];
596 BOOL vols
= (BOOL
)args
[ARG_VOLS
];
597 BOOL showall
= (BOOL
)args
[ARG_ALL
];
598 BOOL blocks
= (BOOL
)args
[ARG_BLOCKS
];
599 STRPTR
*devs
= (STRPTR
*)args
[ARG_DEVS
];
601 if (devs
&& (*devs
== NULL
)) devs
= NULL
;
603 /* If nothing is specified, show everything we got */
604 if(devs
== NULL
&& !disks
&& !vols
)
610 /* check pattern strings */
620 if(ParsePatternNoCase(*p
, matchstr
, sizeof(matchstr
)) == -1)
622 PrintFault(IoErr(), *p
);
630 /* avoid requesters */
631 proc
= (struct Process
*)FindTask(NULL
);
632 win
= (struct Window
*)proc
->pr_WindowPtr
;
633 proc
->pr_WindowPtr
= (struct Window
*)~0;
635 MaxLen
= strlen(unit
);
637 D(bug("Calling ScanDosList()\n"));
640 if(ScanDosList(devs
))
642 CONST_STRPTR dstate
[3] = { GetStrFromCat(READONLY
, "read only"),
643 GetStrFromCat(VALIDATING
, "validating"),
644 GetStrFromCat(READWRITE
, "read/write") };
645 STRPTR datetimeFmt
= NULL
;
650 D(bug("Printing stuff\n"));
652 /* get datetimefmt string */
653 if(loc
&& (GetVar("info_datetime", buf
, sizeof(buf
), 0L) > 0L))
658 /* calc format string for 'Unit' */
659 __sprintf(nfmtstr
, "%%-%lds", MaxLen
);
661 /* show device infomation */
662 if(devs
!= NULL
|| disks
|| !vols
)
664 for(idn
= head
; idn
; idn
= idn
->Next
)
667 STRPTR name
= idn
->Name
;
669 D(bug("Got name = %s\n", name
));
671 if(!idn
->IsVolume
&& IsFileSystem(name
))
673 BOOL gotinfo
= FALSE
;
674 /* if first device to print, print title */
680 D(bug("Printing device\n"));
682 VLPrintf(~0, nfmtstr
, (IPTR
*) &unit
);
683 VLPrintf(DEVTITLE
, " Size Used Free Full Errs State Type Name\n", NULL
);
688 VLPrintf(~0, nfmtstr
, (IPTR
*) &name
);
690 D(bug("Locking \"%s\"\n", name
));
691 lock
= Lock(name
, SHARED_LOCK
);
693 D(bug("Lock = %p\n", (APTR
)lock
));
697 D(bug("Got lock on %s\n", name
));
699 if(Info(lock
, id
) == DOSTRUE
)
701 D(bug("Calling NameFromLock()\n"));
703 if(NameFromLock(lock
, name
, 108L))
705 LONG len
= strlen(name
) - 1;
717 } else if (idn
->Task
) {
719 D(bug("Calling ACTION_DISK_INFO\n"));
720 if (DoPkt(idn
->Task
, ACTION_DISK_INFO
, (SIPTR
)MKBADDR(id
), (SIPTR
)BNULL
, (SIPTR
)BNULL
, (SIPTR
)BNULL
, (SIPTR
)BNULL
)) {
728 D(bug("Got info on %s\n", name
));
730 if (id
->id_DiskType
== ID_NO_DISK_PRESENT
) {
731 VLPrintf(~0, " No disk present\n", NULL
);
732 } else if (id
->id_DiskType
== ID_NOT_REALLY_DOS
) {
733 VLPrintf(~0, " Not a DOS disk\n", NULL
);
734 } else if (id
->id_DiskType
== ID_UNREADABLE_DISK
) {
735 VLPrintf(~0, " Unreadable disk\n", NULL
);
737 x
= ComputeKBytes(id
->id_NumBlocks
, id
->id_BytesPerBlock
);
738 y
= ComputeKBytes(id
->id_NumBlocksUsed
, id
->id_BytesPerBlock
);
752 x
= ExtUDivMod32(UDivMod32(UMult32(y
, 1000), x
), 10, &y
);
760 // y = ((struct DeviceList *)BADDR(id->id_VolumeNode))->dl_DiskType;
765 if((idn
->DosType
& ID_DOS_DISK
) != ID_DOS_DISK
)
771 id
->id_NumSoftErrors
,
772 ((id
->id_DiskState
>= ID_WRITE_PROTECTED
) && (id
->id_DiskState
<= ID_VALIDATED
)) ?
773 (IPTR
) dstate
[id
->id_DiskState
- ID_WRITE_PROTECTED
] : (IPTR
) "",
774 (IPTR
) GetFSysStr(y
),
776 VLPrintf(DEVFMTSTR
, "%4ld%% %4ld %-11s%-8s%s\n", args
);
783 id
->id_NumBlocksUsed
,
784 id
->id_NumBlocks
-id
->id_NumBlocksUsed
,
785 id
->id_BytesPerBlock
};
787 "\nTotal blocks: %-10ld Blocks used: %ld\n"
788 " Blocks free: %-10ld Blocksize: %ld\n",
795 D(bug("Info failure\n"));
796 VLPrintf(~0, "\n", NULL
);
802 /* just ignore PIPEFS */
803 if (err
== ERROR_ACTION_NOT_KNOWN
)
804 if (strcmp(name
, "PIPEFS:") == 0)
809 VLPrintf(~0, nfmtstr
, (IPTR
*) &name
);
810 PrintFault(err
, NULL
);
818 if(vols
|| (!devs
&& !disks
))
823 VLPrintf(DISKSTITLE
, "Volumes\n", NULL
);
825 for(MaxLen
= 15, idn
= head
; idn
; idn
= idn
->Next
)
829 LONG len
= strlen(idn
->Name
);
836 __sprintf(nfmtstr
, "%%-%lds%%-10s", MaxLen
+1);
838 for(idn
= head
; idn
; idn
= idn
->Next
)
844 (IPTR
) GetStrFromCat(MOUNTEDSTR
, "[Mounted]")};
845 // idn->Task ? GetStrFromCat(MOUNTEDSTR, "[Mounted]") : ""); TODO
846 VLPrintf(VOLNAMEFMTSTR
, nfmtstr
, args
);
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 IPTR args
[] = {(IPTR
) StrDay
, (IPTR
) StrDate
, (IPTR
) StrTime
};
886 VLPrintf(DATEFMTSTR
, "created %.3s, %-10s %s", args
);
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
)