2 Copyright © 1995-2019, 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>
93 ULONG
ComputeKBytes(ULONG a
, ULONG b
);
94 void FmtProcedure(struct Hook
*hook
, char a
, struct Locale
*locale
);
95 ULONG
ExtUDivMod32(ULONG a
, ULONG b
, ULONG
*mod
);
99 const TEXT VersionStr
[] = "$VER: Info 41.2 (26.05.2012)";
102 struct Locale
*loc
= NULL
;
108 /* catalog string id:s */
129 struct InfoDosNode
*Next
;
132 struct MsgPort
*Task
;
133 struct DateStamp VolumeDate
;
137 struct InfoDosNode
*head
= NULL
;
145 struct DiskTypeList dtl
[] =
147 { ID_DOS_DISK
, "OFS" },
148 { ID_FFS_DISK
, "FFS" },
149 { ID_INTER_DOS_DISK
, "OFS-INT" },
150 { ID_INTER_FFS_DISK
, "FFS-INT" },
151 { ID_FASTDIR_DOS_DISK
, "OFS-DC" },
152 { ID_FASTDIR_FFS_DISK
, "FFS-DC" },
153 { ID_MSDOS_DISK
, "MS-DOS" },
154 { ID_ACD0_DISK
, "CDFS" },
155 { ID_CACHECDFS_DISK
, "CDFS" },
156 { ID_ASIMCDFS_DISK
, "CDFS" },
157 { ID_NOT_REALLY_DOS
, "NO DOS" },
158 { ID_MAC_DISK2
, "MAC" },
159 { ID_MNX1_DISK
, "Minix" },
160 { ID_QL5A_DISK
, "QL720k" },
161 { ID_QL5B_DISK
, "QL1.4M" },
162 { ID_CPM_DISK
, "CP/M" },
163 { ID_ZXS3_DISK
, "+3Dos" },
164 { ID_ZXS0_DISK
, "Disciple " },
165 { ID_ZXS1_DISK
, "UniDos" },
166 { ID_ZXS2_DISK
, "SamDos" },
167 { ID_ZXS4_DISK
, "Opus" },
168 { ID_P2A0_DISK
, "NETWORK" },
169 { ID_FAT12_DISK
, "FAT12" },
170 { ID_FAT16_DISK
, "FAT16" },
171 { ID_FAT32_DISK
, "FAT32" },
172 { ID_SFS_BE_DISK
, "SFS" },
173 { ID_SFS_LE_DISK
, "sfs" },
174 { ID_PFS_DISK
, "PFS" },
175 { ID_EXT2_DISK
, "EXT2" },
180 /****************************************************************************/
182 int UtilityBase_version
= 0;
183 int LocaleBase_version
= 0;
189 static struct TagItem loctags
[] = { { OC_Version
, 1 },
191 cat
= OpenCatalogA(NULL
, "info_com.catalog", loctags
);
192 loc
= OpenLocale(NULL
);
194 D(bug("Calling doInfo()\n"));
201 return RETURN_OK
; /* TODO: Fix this */
205 CONST_STRPTR
GetStrFromCat(ULONG id
, CONST_STRPTR def
)
209 def
= GetCatalogStr(cat
, id
, def
);
216 void VLPrintf(ULONG id
, CONST_STRPTR def
, ...)
218 CONST_STRPTR format
= GetStrFromCat(id
, def
);
219 AROS_SLOWSTACKFORMAT_PRE_USING(def
, format
);
220 VPrintf(format
, AROS_SLOWSTACKFORMAT_ARG(def
));
221 AROS_SLOWSTACKFORMAT_POST(def
);
225 BOOL
myMatchPatternNoCase(STRPTR
*array
, STRPTR str
)
229 while(*array
!= NULL
)
234 UBYTE len
= strlen(p
);
236 if(p
[len
- 1] != ':')
238 CopyMem(p
, name
, len
);
244 if(ParsePatternNoCase(p
, matchstr
, sizeof(matchstr
)) != -1)
246 if(MatchPatternNoCase(matchstr
, str
))
260 BOOL
ScanDosList(STRPTR
*filter
)
262 struct InfoDosNode
*idn
= 0L;
263 struct DosList
*ndl
, *dl
;
264 STRPTR
*strray
= NULL
, dummy
= NULL
;
267 D(bug("Entered ScanDosList()\n"));
269 if (filter
== NULL
) filter
= &dummy
;
273 strray
= AllocPooled(Pool
, sizeof(STRPTR
)*MAX_MULTIARGS
);
283 while(i
< MAX_MULTIARGS
)
290 /* lock list of devices & vols */
291 dl
= ndl
= LockDosList(LDF_ASSIGNS
| LDF_VOLUMES
| LDF_DEVICES
| LDF_READ
);
300 while((ndl
= NextDosEntry(ndl
, LDF_ASSIGNS
| LDF_VOLUMES
| LDF_READ
)) != NULL
)
303 STRPTR taskName
= NULL
; /* Initialized to avoid a warning */
305 __sprintf(name
, "%b:", ndl
->dol_Name
);
307 if ((ndl
->dol_Type
> DLT_VOLUME
) || !(myMatchPatternNoCase(strray
, name
)))
312 switch (ndl
->dol_Type
)
315 taskName
= ((struct Task
*)ndl
->dol_Task
->mp_SigTask
)->tc_Node
.ln_Name
;
317 D(bug("Found volume %s\n", taskName
));
322 struct AssignList
*al
= ndl
->dol_misc
.dol_assign
.dol_List
;
324 taskName
= ((struct Task
*)((struct FileLock
*)BADDR(ndl
->dol_Lock
))->fl_Task
->mp_SigTask
)->tc_Node
.ln_Name
;
326 D(bug("Found directory %s\n", taskName
));
330 *p
++ = ""; // TODO!!! ((struct Task *)((struct FileLock *)BADDR(al->al_Lock))->fl_Task->mp_SigTask)->tc_Node.ln_Name;
345 while((ndl
= NextDosEntry(ndl
, LDF_VOLUMES
| LDF_DEVICES
| LDF_READ
)) != NULL
)
348 UBYTE type
= ndl
->dol_Type
;
351 /* do not start non-started handlers or open CON: or RAW: windows */
352 if(type
== DLT_DEVICE
&& !ndl
->dol_Task
)
355 __sprintf(name
, "%b:", ndl
->dol_Name
);
356 D(bug("Found name %s\n", name
));
358 if((type
== DLT_DEVICE
) && (myMatchPatternNoCase(strray
, name
) == FALSE
))
362 D(bug("Failure! -- name = %s, strray = %p\n", name
, (void *)strray
));
364 D(for (i
= 0; strray
[i
] != NULL
; i
++)
366 bug("Strray %i = %s\n", i
, strray
[i
]);
372 idn
= (struct InfoDosNode
*)AllocPooled(Pool
, sizeof(struct InfoDosNode
));
380 idn
->Task
= ndl
->dol_Task
;
381 idn
->IsVolume
= type
== DLT_VOLUME
;
383 while((idn
->Name
[len
] = name
[len
]))
386 if(type
== DLT_VOLUME
)
388 idn
->VolumeDate
= ((struct DeviceList
*)ndl
)->dl_VolumeDate
;
389 idn
->Name
[len
- 1] = '\0'; /* remove ':' */
393 BPTR ptr
= ndl
->dol_misc
.dol_handler
.dol_Startup
;
394 struct FileSysStartupMsg
*fssm
= NULL
;
396 if (IsFileSystem(idn
->Name
))
398 // Only filesystems have a valid FileSysStartupMsg
399 fssm
= (struct FileSysStartupMsg
*)BADDR(ptr
);
402 idn
->DosType
= ID_DOS_DISK
;
411 de
= (struct DosEnvec
*)BADDR(fssm
->fssm_Environ
);
413 if (de
&& (de
->de_TableSize
& 0xffffff00) == 0)
415 idn
->DosType
= de
->de_DosType
;
419 /* kinda insert sort */
421 struct InfoDosNode
*work
= head
;
422 struct InfoDosNode
*prev
= NULL
;
424 while((work
!= NULL
) && (Stricmp(idn
->Name
, work
->Name
) > 0))
439 /* unlock list of devices and volumes */
440 UnLockDosList(LDF_ASSIGNS
| LDF_VOLUMES
| LDF_DEVICES
| LDF_READ
);
442 // strray freed at DeletePool
448 void PrintNum(ULONG num
)
463 num
= ExtUDivMod32(UMult32(num
, 100) >> 10, 100, &x
);
466 x
= ExtUDivMod32(x
, 10, &xx
);
477 VLPrintf(BIGNUMFMT
, "%5ld.%ld%lc", num
, x
, fmt
);
481 VLPrintf(SMALLNUMFMT
, "%7ldK", num
);
486 STRPTR
GetFSysStr(ULONG DiskType
)
488 struct DiskTypeList
*dtlptr
= dtl
;
493 if(dtlptr
->id
== DiskType
)
498 } while(*((ULONG
*)dtlptr
++));
502 static TEXT buffer
[5];
504 ptr
= (STRPTR
)buffer
;
505 *((ULONG
*)ptr
) = AROS_LONG2BE(DiskType
);
530 struct RDArgs
*rdargs
;
531 struct Process
*proc
;
533 struct InfoDosNode
*idn
;
535 struct InfoData
*id
= AllocVec(sizeof(struct InfoData
), MEMF_ANY
);
537 IPTR args
[] = { (IPTR
)FALSE
,
543 CONST_STRPTR unit
= GetStrFromCat(UNIT
, "Unit");
547 PrintFault(ERROR_NO_FREE_STORE
, NULL
);
551 Pool
= CreatePool(MEMF_ANY
, 1024, 1024);
555 PrintFault(ERROR_NO_FREE_STORE
, NULL
);
559 D(bug("Calling ReadArgs()\n"));
562 rdargs
= ReadArgs("DISKS/S,VOLS=VOLUMES/S,ALL/S,BLOCKS/S,DEVICES/M",
567 BOOL disks
= (BOOL
)args
[ARG_DISKS
];
568 BOOL vols
= (BOOL
)args
[ARG_VOLS
];
569 BOOL showall
= (BOOL
)args
[ARG_ALL
];
570 BOOL blocks
= (BOOL
)args
[ARG_BLOCKS
];
571 STRPTR
*devs
= (STRPTR
*)args
[ARG_DEVS
];
573 if (devs
&& (*devs
== NULL
)) devs
= NULL
;
575 /* If nothing is specified, show everything we got */
576 if(devs
== NULL
&& !disks
&& !vols
)
582 /* check pattern strings */
591 if(ParsePatternNoCase(*p
, matchstr
, sizeof(matchstr
)) == -1)
593 PrintFault(IoErr(), *p
);
601 /* avoid requesters */
602 proc
= (struct Process
*)FindTask(NULL
);
603 win
= (struct Window
*)proc
->pr_WindowPtr
;
604 proc
->pr_WindowPtr
= (struct Window
*)~0;
606 MaxLen
= strlen(unit
);
608 D(bug("Calling ScanDosList()\n"));
611 if(ScanDosList(devs
))
613 CONST_STRPTR dstate
[3] = { GetStrFromCat(READONLY
, "read only"),
614 GetStrFromCat(VALIDATING
, "validating"),
615 GetStrFromCat(READWRITE
, "read/write") };
616 STRPTR datetimeFmt
= NULL
;
621 D(bug("Printing stuff\n"));
623 /* get datetimefmt string */
624 if(loc
&& (GetVar("info_datetime", buf
, sizeof(buf
), 0L) > 0L))
629 /* calc format string for 'Unit' */
630 __sprintf(nfmtstr
, "%%-%lds", MaxLen
);
632 /* show device infomation */
633 if(devs
!= NULL
|| disks
|| !vols
)
635 for(idn
= head
; idn
; idn
= idn
->Next
)
638 STRPTR name
= idn
->Name
;
640 D(bug("Got name = %s\n", name
));
642 if(!idn
->IsVolume
&& IsFileSystem(name
))
644 BOOL gotinfo
= FALSE
;
645 /* if first device to print, print title */
651 D(bug("Printing device\n"));
653 VLPrintf(~0, nfmtstr
, unit
);
654 VLPrintf(DEVTITLE
, " Size Used Free Full Errs State Type Name\n");
659 VLPrintf(~0, nfmtstr
, name
);
661 D(bug("Locking \"%s\"\n", name
));
662 lock
= Lock(name
, SHARED_LOCK
);
664 D(bug("Lock = %p\n", (APTR
)lock
));
668 D(bug("Got lock on %s\n", name
));
670 if(Info(lock
, id
) == DOSTRUE
)
672 D(bug("Calling NameFromLock()\n"));
674 if(NameFromLock(lock
, name
, 108L))
676 LONG len
= strlen(name
) - 1;
688 } else if (idn
->Task
) {
690 D(bug("Calling ACTION_DISK_INFO\n"));
691 if (DoPkt(idn
->Task
, ACTION_DISK_INFO
, (SIPTR
)MKBADDR(id
), (SIPTR
)BNULL
, (SIPTR
)BNULL
, (SIPTR
)BNULL
, (SIPTR
)BNULL
)) {
699 D(bug("Got info on %s\n", name
));
701 if (id
->id_DiskType
== ID_NO_DISK_PRESENT
) {
702 VLPrintf(~0, " No disk present\n");
703 } else if (id
->id_DiskType
== ID_NOT_REALLY_DOS
) {
704 VLPrintf(~0, " Not a DOS disk\n");
705 } else if (id
->id_DiskType
== ID_UNREADABLE_DISK
) {
706 VLPrintf(~0, " Unreadable disk\n");
708 x
= ComputeKBytes(id
->id_NumBlocks
, id
->id_BytesPerBlock
);
709 y
= ComputeKBytes(id
->id_NumBlocksUsed
, id
->id_BytesPerBlock
);
723 x
= ExtUDivMod32(UDivMod32(UMult32(y
, 1000), x
), 10, &y
);
731 // y = ((struct DeviceList *)BADDR(id->id_VolumeNode))->dl_DiskType;
736 if((idn
->DosType
& ID_DOS_DISK
) != ID_DOS_DISK
)
740 VLPrintf(DEVFMTSTR
, "%4ld%% %4ld %-11s%-8s%s\n",
741 x
, id
->id_NumSoftErrors
,
742 ((id
->id_DiskState
>= ID_WRITE_PROTECTED
) && (id
->id_DiskState
<= ID_VALIDATED
)) ? (const char *)dstate
[id
->id_DiskState
- ID_WRITE_PROTECTED
] : (const char *)"",
750 "\nTotal blocks: %-10ld Blocks used: %ld\n"
751 " Blocks free: %-10ld Blocksize: %ld\n",
753 id
->id_NumBlocksUsed
,
754 id
->id_NumBlocks
-id
->id_NumBlocksUsed
,
755 id
->id_BytesPerBlock
);
761 D(bug("Info failure\n"));
768 /* just ignore PIPEFS */
769 if (err
== ERROR_ACTION_NOT_KNOWN
)
770 if (strcmp(name
, "PIPEFS:") == 0)
775 VLPrintf(~0, nfmtstr
, name
);
776 PrintFault(err
, NULL
);
784 if(vols
|| (!devs
&& !disks
))
789 VLPrintf(DISKSTITLE
, "Volumes\n");
791 /* find the longest volume name */
792 for(MaxLen
= 15, idn
= head
; idn
; idn
= idn
->Next
)
796 LONG len
= strlen(idn
->Name
);
803 __sprintf(nfmtstr
, "%%-%lds%%-10s", MaxLen
+1);
805 for(idn
= head
; idn
; idn
= idn
->Next
)
809 VLPrintf(VOLNAMEFMTSTR
, nfmtstr
, idn
->Name
,
810 idn
->Task
? (const char *)GetStrFromCat(MOUNTEDSTR
, "[Mounted]") : (const char *)"");
812 if(idn
->VolumeDate
.ds_Days
!= 0)
817 static struct Hook hook
;
819 memset(&hook
, 0, sizeof(struct Hook
));
821 hook
.h_SubEntry
= (HOOKFUNC
)FmtProcedure
;
822 hook
.h_Data
= datestr
;
824 FormatDate(loc
, datetimeFmt
, &idn
->VolumeDate
, &hook
);
830 TEXT StrDay
[LEN_DATSTRING
];
831 TEXT StrDate
[LEN_DATSTRING
];
832 TEXT StrTime
[LEN_DATSTRING
];
836 dt
.dat_Flags
= DTF_SUBST
;
837 dt
.dat_Format
= FORMAT_DOS
;
838 dt
.dat_StrDay
= StrDay
;
839 dt
.dat_StrDate
= StrDate
;
840 dt
.dat_StrTime
= StrTime
;
841 dt
.dat_Stamp
= idn
->VolumeDate
;
845 if(Strnicmp(StrDate
, StrDay
, strlen(StrDay
)) == 0)
851 VLPrintf(DATEFMTSTR
, "created %.3s, %-10s %s", StrDay
, StrDate
, StrTime
);
863 PrintFault( ERROR_NO_FREE_STORE
, NULL
);
866 /* reset window pointer of our process */
867 proc
->pr_WindowPtr
= win
;
874 end
: /* free allocated memory */
880 ULONG
ComputeKBytes(ULONG a
, ULONG b
)
882 // UQUAD result = UMult64(a, b);
884 UQUAD result
= (UQUAD
)a
* b
;
886 return (ULONG
)(result
>> 10);
890 void FmtProcedure(struct Hook
*hook
, char a
, struct Locale
*locale
)
892 *((STRPTR
)hook
->h_Data
) = a
;
893 hook
->h_Data
= (STRPTR
) hook
->h_Data
+ 1;
897 ULONG
ExtUDivMod32(ULONG a
, ULONG b
, ULONG
*mod
)