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_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 VLPrintf(ULONG id
, CONST_STRPTR def
, const IPTR
* argarray
)
249 def
= GetStrFromCat(id
, def
);
250 VPrintf(def
, (IPTR
*)argarray
);
254 BOOL
myMatchPatternNoCase(STRPTR
*array
, STRPTR str
)
258 while(*array
!= NULL
)
263 UBYTE len
= strlen(p
);
265 if(p
[len
- 1] != ':')
267 CopyMem(p
, name
, len
);
273 if(ParsePatternNoCase(p
, matchstr
, sizeof(matchstr
)) != -1)
275 if(MatchPatternNoCase(matchstr
, str
))
289 BOOL
ScanDosList(STRPTR
*filter
)
291 struct InfoDosNode
*idn
= 0L;
292 struct DosList
*ndl
, *dl
;
293 STRPTR
*strray
= NULL
, dummy
= NULL
;
296 D(bug("Entered ScanDosList()\n"));
298 if (filter
== NULL
) filter
= &dummy
;
302 strray
= AllocPooled(Pool
, sizeof(STRPTR
)*MAX_MULTIARGS
);
312 while(i
< MAX_MULTIARGS
)
319 /* lock list of devices & vols */
320 dl
= ndl
= LockDosList(LDF_ASSIGNS
| LDF_VOLUMES
| LDF_DEVICES
| LDF_READ
);
329 while((ndl
= NextDosEntry(ndl
, LDF_ASSIGNS
| LDF_VOLUMES
| LDF_READ
)) != NULL
)
332 STRPTR taskName
= NULL
; /* Initialized to avoid a warning */
334 __sprintf(name
, "%b:", ndl
->dol_Name
);
336 if ((ndl
->dol_Type
> DLT_VOLUME
) || !(myMatchPatternNoCase(strray
, name
)))
341 switch (ndl
->dol_Type
)
344 taskName
= ((struct Task
*)ndl
->dol_Task
->mp_SigTask
)->tc_Node
.ln_Name
;
346 D(bug("Found volume %s\n", taskName
));
351 struct AssignList
*al
= ndl
->dol_misc
.dol_assign
.dol_List
;
353 taskName
= ((struct Task
*)((struct FileLock
*)BADDR(ndl
->dol_Lock
))->fl_Task
->mp_SigTask
)->tc_Node
.ln_Name
;
355 D(bug("Found directory %s\n", taskName
));
359 *p
++ = ""; // TODO!!! ((struct Task *)((struct FileLock *)BADDR(al->al_Lock))->fl_Task->mp_SigTask)->tc_Node.ln_Name;
374 while((ndl
= NextDosEntry(ndl
, LDF_VOLUMES
| LDF_DEVICES
| LDF_READ
)) != NULL
)
377 UBYTE type
= ndl
->dol_Type
;
380 /* do not start non-started handlers or open CON: or RAW: windows.. */
381 if(type
== DLT_DEVICE
&& !ndl
->dol_Task
)
384 __sprintf(name
, "%b:", ndl
->dol_Name
);
385 D(bug("Found name %s\n", name
));
387 if((type
== DLT_DEVICE
) && (myMatchPatternNoCase(strray
, name
) == FALSE
))
391 D(bug("Failure! -- name = %s, strray = %p\n", name
, (void *)strray
));
393 for (i
= 0; strray
[i
] != NULL
; i
++)
395 D(bug("Strray %i = %s\n", i
, strray
[i
]));
401 idn
= (struct InfoDosNode
*)AllocPooled(Pool
, sizeof(struct InfoDosNode
));
409 idn
->Task
= ndl
->dol_Task
;
410 idn
->IsVolume
= type
== DLT_VOLUME
;
412 while((idn
->Name
[len
] = name
[len
]))
415 if(type
== DLT_VOLUME
)
417 idn
->VolumeDate
= ((struct DeviceList
*)ndl
)->dl_VolumeDate
;
418 idn
->Name
[len
- 1] = '\0'; /* remove ':' */
422 BPTR ptr
= ndl
->dol_misc
.dol_handler
.dol_Startup
;
423 struct FileSysStartupMsg
*fssm
= (struct FileSysStartupMsg
*)BADDR(ptr
);
425 idn
->DosType
= ID_DOS_DISK
;
434 de
= (struct DosEnvec
*)BADDR(fssm
->fssm_Environ
);
436 if (de
&& (de
->de_TableSize
& 0xffffff00) == 0)
438 idn
->DosType
= de
->de_DosType
;
442 /* kinda insert sort */
444 struct InfoDosNode
*work
= head
;
445 struct InfoDosNode
*prev
= NULL
;
447 while((work
!= NULL
) && (Stricmp(idn
->Name
, work
->Name
) > 0))
462 /* unlock list of devices and volumes */
463 UnLockDosList(LDF_ASSIGNS
| LDF_VOLUMES
| LDF_DEVICES
| LDF_READ
);
465 // strray freed at DeletePool
471 void PrintNum(ULONG num
)
486 num
= ExtUDivMod32(UMult32(num
, 100) >> 10, 100, &x
);
489 x
= ExtUDivMod32(x
, 10, &xx
);
500 IPTR args
[] = {num
, x
, fmt
};
501 VLPrintf(BIGNUMFMT
, "%5ld.%ld%lc", args
);
505 IPTR args
[] = { num
};
506 VLPrintf(SMALLNUMFMT
, "%7ldK", args
);
511 STRPTR
GetFSysStr(ULONG DiskType
)
513 struct DiskTypeList
*dtlptr
= dtl
;
518 if(dtlptr
->id
== DiskType
)
523 } while(*((ULONG
*)dtlptr
++));
527 static TEXT buffer
[5];
529 ptr
= (STRPTR
)buffer
;
530 *((ULONG
*)ptr
) = AROS_LONG2BE(DiskType
);
555 struct RDArgs
*rdargs
;
556 struct Process
*proc
;
558 struct InfoDosNode
*idn
;
560 struct InfoData
*id
= AllocVec(sizeof(struct InfoData
), MEMF_ANY
);
562 IPTR args
[] = { (IPTR
)FALSE
,
568 CONST_STRPTR unit
= GetStrFromCat(UNIT
, "Unit");
572 PrintFault(ERROR_NO_FREE_STORE
, NULL
);
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 BOOL gotinfo
= FALSE
;
671 /* if first device to print, print title */
677 D(bug("Printing device\n"));
679 VLPrintf(~0, nfmtstr
, (IPTR
*) &unit
);
680 VLPrintf(DEVTITLE
, " Size Used Free Full Errs State Type Name\n", NULL
);
685 VLPrintf(~0, nfmtstr
, (IPTR
*) &name
);
687 D(bug("Locking \"%s\"\n", name
));
688 lock
= Lock(name
, SHARED_LOCK
);
690 D(bug("Lock = %p\n", (APTR
)lock
));
694 D(bug("Got lock on %s\n", name
));
696 if(Info(lock
, id
) == DOSTRUE
)
698 D(bug("Calling NameFromLock()\n"));
700 if(NameFromLock(lock
, name
, 108L))
702 LONG len
= strlen(name
) - 1;
714 } else if (IoErr() == ERROR_NO_DISK
&& idn
->Task
) {
716 D(bug("Calling ACTION_DISK_INFO\n"));
717 if (DoPkt(idn
->Task
, ACTION_DISK_INFO
, (SIPTR
)MKBADDR(id
), (SIPTR
)BNULL
, (SIPTR
)BNULL
, (SIPTR
)BNULL
, (SIPTR
)BNULL
)) {
725 D(bug("Got info on %s\n", name
));
727 if (id
->id_DiskType
!= ID_NO_DISK_PRESENT
)
730 x
= ComputeKBytes(id
->id_NumBlocks
, id
->id_BytesPerBlock
);
731 y
= ComputeKBytes(id
->id_NumBlocksUsed
, id
->id_BytesPerBlock
);
745 x
= ExtUDivMod32(UDivMod32(UMult32(y
, 1000), x
), 10, &y
);
753 // y = ((struct DeviceList *)BADDR(id->id_VolumeNode))->dl_DiskType;
758 if((idn
->DosType
& ID_DOS_DISK
) != ID_DOS_DISK
)
764 id
->id_NumSoftErrors
,
765 ((id
->id_DiskState
>= ID_WRITE_PROTECTED
) && (id
->id_DiskState
<= ID_VALIDATED
)) ?
766 (IPTR
) dstate
[id
->id_DiskState
- ID_WRITE_PROTECTED
] : (IPTR
) "",
767 (IPTR
) GetFSysStr(y
),
769 VLPrintf(DEVFMTSTR
, "%4ld%% %4ld %-11s%-8s%s\n", args
);
776 id
->id_NumBlocksUsed
,
777 id
->id_NumBlocks
-id
->id_NumBlocksUsed
,
778 id
->id_BytesPerBlock
};
780 "\nTotal blocks: %-10ld Blocks used: %ld\n"
781 " Blocks free: %-10ld Blocksize: %ld\n",
786 VLPrintf(~0, " No disk present\n", NULL
);
792 D(bug("Info failure\n"));
793 VLPrintf(~0, "\n", NULL
);
799 /* just ignore PIPEFS */
800 if (err
== ERROR_ACTION_NOT_KNOWN
)
801 if (strcmp(name
, "PIPEFS:") == 0)
806 VLPrintf(~0, nfmtstr
, (IPTR
*) &name
);
807 PrintFault(err
, NULL
);
815 if(vols
|| (!devs
&& !disks
))
820 VLPrintf(DISKSTITLE
, "Volumes\n", NULL
);
822 for(MaxLen
= 15, idn
= head
; idn
; idn
= idn
->Next
)
826 LONG len
= strlen(idn
->Name
);
833 __sprintf(nfmtstr
, "%%-%lds%%-10s", MaxLen
+1);
835 for(idn
= head
; idn
; idn
= idn
->Next
)
841 (IPTR
) GetStrFromCat(MOUNTEDSTR
, "[Mounted]")};
842 // idn->Task ? GetStrFromCat(MOUNTEDSTR, "[Mounted]") : ""); TODO
843 VLPrintf(VOLNAMEFMTSTR
, nfmtstr
, args
);
848 static struct Hook hook
;
850 memset(&hook
, 0, sizeof(struct Hook
));
852 hook
.h_SubEntry
= (HOOKFUNC
)FmtProcedure
;
853 hook
.h_Data
= datestr
;
855 FormatDate(loc
, datetimeFmt
, &idn
->VolumeDate
, &hook
);
861 TEXT StrDay
[LEN_DATSTRING
];
862 TEXT StrDate
[LEN_DATSTRING
];
863 TEXT StrTime
[LEN_DATSTRING
];
867 dt
.dat_Flags
= DTF_SUBST
;
868 dt
.dat_Format
= FORMAT_DOS
;
869 dt
.dat_StrDay
= StrDay
;
870 dt
.dat_StrDate
= StrDate
;
871 dt
.dat_StrTime
= StrTime
;
872 dt
.dat_Stamp
= idn
->VolumeDate
;
876 if(Strnicmp(StrDate
, StrDay
, strlen(StrDay
)) == 0)
882 IPTR args
[] = {(IPTR
) StrDay
, (IPTR
) StrDate
, (IPTR
) StrTime
};
883 VLPrintf(DATEFMTSTR
, "created %.3s, %-10s %s", args
);
894 PrintFault( ERROR_NO_FREE_STORE
, NULL
);
897 /* reset window pointer of our process */
898 proc
->pr_WindowPtr
= win
;
905 end
: /* free allocated memory */
911 ULONG
ComputeKBytes(ULONG a
, ULONG b
)
913 // UQUAD result = UMult64(a, b);
915 UQUAD result
= (UQUAD
)a
* b
;
917 return (ULONG
)(result
>> 10);
921 void FmtProcedure(struct Hook
*hook
, char a
, struct Locale
*locale
)
923 *((STRPTR
)hook
->h_Data
) = a
;
924 hook
->h_Data
= (STRPTR
) hook
->h_Data
+ 1;
928 ULONG
ExtUDivMod32(ULONG a
, ULONG b
, ULONG
*mod
)