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>
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 */
119 #define ID_FAT12_DISK (0x46415400L) /* FAT12 */
120 #define ID_FAT16_DISK (0x46415401L) /* FAT16 */
121 #define ID_FAT32_DISK (0x46415402L) /* FAT32 */
126 ULONG
ComputeKBytes(ULONG a
, ULONG b
);
127 void FmtProcedure(struct Hook
*hook
, char a
, struct Locale
*locale
);
128 ULONG
ExtUDivMod32(ULONG a
, ULONG b
, ULONG
*mod
);
132 const TEXT VersionStr
[] = "$VER: Info 41.1 (16.11.2000)";
135 struct Locale
*loc
= NULL
;
141 /* catalog string id:s */
162 struct InfoDosNode
*Next
;
165 struct MsgPort
*Task
;
166 struct DateStamp VolumeDate
;
170 struct InfoDosNode
*head
= NULL
;
178 struct DiskTypeList dtl
[] =
180 { ID_DOS_DISK
, "OFS" },
181 { ID_FFS_DISK
, "FFS" },
182 { ID_INTER_DOS_DISK
, "OFS-INT" },
183 { ID_INTER_FFS_DISK
, "FFS-INT" },
184 { ID_FASTDIR_DOS_DISK
, "OFS-DC" },
185 { ID_FASTDIR_FFS_DISK
, "FFS-DC" },
186 { ID_MSDOS_DISK
, "MS-DOS" },
187 { ID_ACD0_DISK
, "CDFS" },
188 { ID_CACHECDFS_DISK
, "CDFS" },
189 { ID_ASIMCDFS_DISK
, "CDFS" },
190 { ID_NOT_REALLY_DOS
, "NO DOS" },
191 { ID_MAC_DISK2
, "MAC" },
192 { ID_MNX1_DISK
, "Minix" },
193 { ID_QL5A_DISK
, "QL720k" },
194 { ID_QL5B_DISK
, "QL1.4M" },
195 { ID_CPM_DISK
, "CP/M" },
196 { ID_ZXS3_DISK
, "+3Dos" },
197 { ID_ZXS0_DISK
, "Disciple " },
198 { ID_ZXS1_DISK
, "UniDos" },
199 { ID_ZXS2_DISK
, "SamDos" },
200 { ID_ZXS4_DISK
, "Opus" },
201 { ID_P2A0_DISK
, "NETWORK" },
202 { ID_FAT12_DISK
, "FAT12" },
203 { ID_FAT16_DISK
, "FAT16" },
204 { ID_FAT32_DISK
, "FAT32" },
209 /****************************************************************************/
211 int UtilityBase_version
= 0;
212 int LocaleBase_version
= 0;
218 static struct TagItem loctags
[] = { { OC_Version
, 1 },
220 cat
= OpenCatalogA(NULL
, "info_com.catalog", loctags
);
221 loc
= OpenLocale(NULL
);
223 D(bug("Calling doInfo()\n"));
230 return RETURN_OK
; /* TODO: Fix this */
234 CONST_STRPTR
GetStrFromCat(ULONG id
, CONST_STRPTR def
)
238 def
= GetCatalogStr(cat
, id
, def
);
245 void LPrintf(ULONG id
, CONST_STRPTR def
, ...) __stackparm
;
247 void LPrintf(ULONG id
, CONST_STRPTR def
, ...)
249 def
= GetStrFromCat(id
, def
);
251 VPrintf(def
, ((IPTR
*)(&def
))+1);
255 BOOL
myMatchPatternNoCase(STRPTR
*array
, STRPTR str
)
259 while(*array
!= NULL
)
264 UBYTE len
= strlen(p
);
266 if(p
[len
- 1] != ':')
268 CopyMem(p
, name
, len
);
274 if(ParsePatternNoCase(p
, matchstr
, sizeof(matchstr
)) != -1)
276 if(MatchPatternNoCase(matchstr
, str
))
290 BOOL
ScanDosList(STRPTR
*filter
)
292 struct InfoDosNode
*idn
= 0L;
293 struct DosList
*ndl
, *dl
;
294 STRPTR
*strray
= NULL
, dummy
= NULL
;
297 D(bug("Entered ScanDosList()\n"));
299 if (filter
== NULL
) filter
= &dummy
;
303 strray
= AllocPooled(Pool
, sizeof(STRPTR
)*MAX_MULTIARGS
);
313 while(i
< MAX_MULTIARGS
)
320 /* lock list of devices & vols */
321 dl
= ndl
= LockDosList(LDF_ASSIGNS
| LDF_VOLUMES
| LDF_DEVICES
| LDF_READ
);
330 while((ndl
= NextDosEntry(ndl
, LDF_ASSIGNS
| LDF_VOLUMES
| LDF_READ
)) != NULL
)
333 STRPTR taskName
= NULL
; /* Initialized to avoid a warning */
335 __sprintf(name
, "%s:", ndl
->dol_Ext
.dol_AROS
.dol_DevName
);
337 if ((ndl
->dol_Type
> DLT_VOLUME
) || !(myMatchPatternNoCase(strray
, name
)))
342 switch (ndl
->dol_Type
)
345 taskName
= ndl
->dol_Ext
.dol_AROS
.dol_DevName
; // ((struct Task *)ndl->dol_Task->mp_SigTask)->tc_Node.ln_Name;
347 D(bug("Found volume %s\n", taskName
));
352 struct AssignList
*al
= ndl
->dol_misc
.dol_assign
.dol_List
;
355 taskName
= ndl
->dol_Ext
.dol_AROS
.dol_DevName
; // ((struct Task *)((struct FileLock *)BADDR(ndl->dol_Lock))->fl_Task->mp_SigTask)->tc_Node.ln_Name;
357 D(bug("Found directory %s\n", taskName
));
361 *p
++ = ""; // TODO!!! ((struct Task *)((struct FileLock *)BADDR(al->al_Lock))->fl_Task->mp_SigTask)->tc_Node.ln_Name;
376 while((ndl
= NextDosEntry(ndl
, LDF_VOLUMES
| LDF_DEVICES
| LDF_READ
)) != NULL
)
379 UBYTE type
= ndl
->dol_Type
;
382 // if(((type == DLT_DEVICE))) // && (!ndl->dol_Task) TODO Check this!
385 __sprintf(name
, "%s:", ndl
->dol_Ext
.dol_AROS
.dol_DevName
);
387 D(bug("Found name %s\n", ndl
->dol_Ext
.dol_AROS
.dol_DevName
));
389 if((type
== DLT_DEVICE
) && (myMatchPatternNoCase(strray
, name
) == FALSE
))
393 D(bug("Failure! -- name = %s, strray = %p\n", name
, (void *)strray
));
395 for (i
= 0; strray
[i
] != NULL
; i
++)
397 D(bug("Strray %i = %s\n", i
, strray
[i
]));
403 idn
= (struct InfoDosNode
*)AllocPooled(Pool
, sizeof(struct InfoDosNode
));
411 // idn->Task = (struct MsgPort *)ndl->dol_Task;
412 idn
->IsVolume
= type
== DLT_VOLUME
;
414 while((idn
->Name
[len
] = name
[len
]))
417 if(type
== DLT_VOLUME
)
419 idn
->VolumeDate
= ((struct DeviceList
*)ndl
)->dl_VolumeDate
;
420 idn
->Name
[len
- 1] = '\0'; /* remove ':' */
424 // struct FileSysStartupMsg *fssm = (struct FileSysStartupMsg *)BADDR(ndl->dol_misc.dol_handler.dol_Startup);
426 idn
->DosType
= ID_DOS_DISK
;
435 if(*(UBYTE
*)fssm
== 0 || *(UBYTE
*)BADDR(fssm
->fssm_Device
) != 0)
437 struct DosEnvec
*de
= (struct DosEnvec
*)BADDR(fssm
->fssm_Environ
);
439 if(de
!= NULL
&& (de
->de_TableSize
& 0xffffff00) == 0L)
442 idn
->DosType
= de
->de_DosType
;
450 /* kinda insert sort */
452 struct InfoDosNode
*work
= head
;
453 struct InfoDosNode
*prev
= NULL
;
455 while((work
!= NULL
) && (Stricmp(idn
->Name
, work
->Name
) > 0))
470 /* unlock list of devices and volumes */
471 UnLockDosList(LDF_ASSIGNS
| LDF_VOLUMES
| LDF_DEVICES
| LDF_READ
);
473 // strray freed at DeletePool
479 void PrintNum(ULONG num
)
494 num
= ExtUDivMod32(UMult32(num
, 100) >> 10, 100, &x
);
497 x
= ExtUDivMod32(x
, 10, &xx
);
508 LPrintf(BIGNUMFMT
, "%5ld.%ld%lc", num
, x
, fmt
);
512 LPrintf(SMALLNUMFMT
, "%7ldK", num
);
517 STRPTR
GetFSysStr(ULONG DiskType
)
519 struct DiskTypeList
*dtlptr
= dtl
;
524 if(dtlptr
->id
== DiskType
)
529 } while(*((ULONG
*)dtlptr
++));
533 static TEXT buffer
[5];
535 ptr
= (STRPTR
)buffer
;
536 *((ULONG
*)ptr
) = DiskType
;
561 struct RDArgs
*rdargs
;
562 struct Process
*proc
;
564 struct InfoDosNode
*idn
;
566 static struct InfoData id
;
568 IPTR args
[] = { (IPTR
)FALSE
,
574 CONST_STRPTR unit
= GetStrFromCat(UNIT
, "Unit");
576 Pool
= CreatePool(MEMF_ANY
, 1024, 1024);
580 PrintFault(ERROR_NO_FREE_STORE
, NULL
);
584 D(bug("Calling ReadArgs()\n"));
587 rdargs
= ReadArgs("DISKS/S,VOLS=VOLUMES/S,ALL/S,BLOCKS/S,DEVICES/M",
592 BOOL disks
= (BOOL
)args
[ARG_DISKS
];
593 BOOL vols
= (BOOL
)args
[ARG_VOLS
];
594 BOOL showall
= (BOOL
)args
[ARG_ALL
];
595 BOOL blocks
= (BOOL
)args
[ARG_BLOCKS
];
596 STRPTR
*devs
= (STRPTR
*)args
[ARG_DEVS
];
598 if (devs
&& (*devs
== NULL
)) devs
= NULL
;
600 /* If nothing is specified, show everything we got */
601 if(devs
== NULL
&& !disks
&& !vols
)
607 /* check pattern strings */
617 if(ParsePatternNoCase(*p
, matchstr
, sizeof(matchstr
)) == -1)
619 PrintFault(IoErr(), *p
);
627 /* avoid requesters */
628 proc
= (struct Process
*)FindTask(NULL
);
629 win
= (struct Window
*)proc
->pr_WindowPtr
;
630 proc
->pr_WindowPtr
= (struct Window
*)~0;
632 MaxLen
= strlen(unit
);
634 D(bug("Calling ScanDosList()\n"));
637 if(ScanDosList(devs
))
639 CONST_STRPTR dstate
[3] = { GetStrFromCat(READONLY
, "read only"),
640 GetStrFromCat(VALIDATING
, "validating"),
641 GetStrFromCat(READWRITE
, "read/write") };
642 STRPTR datetimeFmt
= NULL
;
647 D(bug("Printing stuff\n"));
649 /* get datetimefmt string */
650 if(loc
&& (GetVar("info_datetime", buf
, sizeof(buf
), 0L) > 0L))
655 /* calc format string for 'Unit' */
656 __sprintf(nfmtstr
, "%%-%lds", MaxLen
);
658 /* show device infomation */
659 if(devs
!= NULL
|| disks
|| !vols
)
661 for(idn
= head
; idn
; idn
= idn
->Next
)
664 STRPTR name
= idn
->Name
;
666 D(bug("Got name = %s\n", name
));
668 if(!idn
->IsVolume
&& IsFileSystem(name
))
670 /* if first device to print, print title */
676 D(bug("Printing device\n"));
678 LPrintf(~0, nfmtstr
, unit
);
679 LPrintf(DEVTITLE
, " Size Used Free Full Errs State Type Name\n");
684 D(bug("Locking \"%s\"\n", name
));
685 lock
= Lock(name
, SHARED_LOCK
);
687 D(bug("Lock = %p\n", lock
));
691 D(bug("Got lock on %s\n", name
));
693 if(Info(lock
, &id
) == DOSTRUE
)
697 D(bug("Got info on %s\n", name
));
699 LPrintf(~0, nfmtstr
, name
);
701 x
= ComputeKBytes(id
.id_NumBlocks
, id
.id_BytesPerBlock
);
702 y
= ComputeKBytes(id
.id_NumBlocksUsed
, id
.id_BytesPerBlock
);
708 D(bug("Calling NameFromLock()\n"));
710 if(NameFromLock(lock
, name
, 108L))
712 LONG len
= strlen(name
) - 1;
728 x
= ExtUDivMod32(UDivMod32(UMult32(y
, 1000), x
), 10, &y
);
736 // y = ((struct DeviceList *)BADDR(id.id_VolumeNode))->dl_DiskType;
741 if((idn
->DosType
& ID_DOS_DISK
) != ID_DOS_DISK
)
744 LPrintf(DEVFMTSTR
, "%4ld%% %4ld %-11s%-8s%s\n",
745 x
, id
.id_NumSoftErrors
,
746 ((id
.id_DiskState
>= ID_WRITE_PROTECTED
) && (id
.id_DiskState
<= ID_VALIDATED
)) ?
747 dstate
[id
.id_DiskState
- ID_WRITE_PROTECTED
] : (STRPTR
)"", GetFSysStr(y
), name
);
752 "\nTotal blocks: %-10ld Blocks used: %ld\n"
753 " Blocks free: %-10ld Blocksize: %ld\n",
754 id
.id_NumBlocks
, id
.id_NumBlocksUsed
,
755 id
.id_NumBlocks
-id
.id_NumBlocksUsed
, id
.id_BytesPerBlock
);
759 D(bug("Info failure\n"));
767 if((err
!= 0) && showall
)
769 LPrintf(~0, nfmtstr
, name
);
770 PrintFault(err
, NULL
);
778 if(vols
|| (!devs
&& !disks
))
783 LPrintf(DISKSTITLE
, "Volumes\n");
785 for(MaxLen
= 15, idn
= head
; idn
; idn
= idn
->Next
)
789 LONG len
= strlen(idn
->Name
);
796 __sprintf(nfmtstr
, "%%-%lds%%-10s", MaxLen
+1);
798 for(idn
= head
; idn
; idn
= idn
->Next
)
802 LPrintf(VOLNAMEFMTSTR
, nfmtstr
, idn
->Name
,
803 GetStrFromCat(MOUNTEDSTR
, "[Mounted]"));
804 // idn->Task ? GetStrFromCat(MOUNTEDSTR, "[Mounted]") : ""); TODO
809 static struct Hook hook
;
811 memset(&hook
, 0, sizeof(struct Hook
));
813 hook
.h_SubEntry
= (HOOKFUNC
)FmtProcedure
;
814 hook
.h_Data
= datestr
;
816 FormatDate(loc
, datetimeFmt
, &idn
->VolumeDate
, &hook
);
822 TEXT StrDay
[LEN_DATSTRING
];
823 TEXT StrDate
[LEN_DATSTRING
];
824 TEXT StrTime
[LEN_DATSTRING
];
828 dt
.dat_Flags
= DTF_SUBST
;
829 dt
.dat_Format
= FORMAT_DOS
;
830 dt
.dat_StrDay
= StrDay
;
831 dt
.dat_StrDate
= StrDate
;
832 dt
.dat_StrTime
= StrTime
;
833 dt
.dat_Stamp
= idn
->VolumeDate
;
837 if(Strnicmp(StrDate
, StrDay
, strlen(StrDay
)) == 0)
843 LPrintf(DATEFMTSTR
, "created %.3s, %-10s %s",
844 StrDay
, StrDate
, StrTime
);
855 PrintFault( ERROR_NO_FREE_STORE
, NULL
);
858 /* reset window pointer of our process */
859 proc
->pr_WindowPtr
= win
;
866 end
: /* free allocated memory */
872 ULONG
ComputeKBytes(ULONG a
, ULONG b
)
874 // UQUAD result = UMult64(a, b);
876 UQUAD result
= (UQUAD
)a
* b
;
878 return (ULONG
)(result
>> 10);
882 void FmtProcedure(struct Hook
*hook
, char a
, struct Locale
*locale
)
884 *((STRPTR
)hook
->h_Data
) = a
;
885 hook
->h_Data
= (STRPTR
) hook
->h_Data
+ 1;
889 ULONG
ExtUDivMod32(ULONG a
, ULONG b
, ULONG
*mod
)