2 Copyright © 1995-2008, 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
, "%s:", ndl
->dol_Ext
.dol_AROS
.dol_DevName
);
336 if ((ndl
->dol_Type
> DLT_VOLUME
) || !(myMatchPatternNoCase(strray
, name
)))
341 switch (ndl
->dol_Type
)
344 taskName
= ndl
->dol_Ext
.dol_AROS
.dol_DevName
; // ((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
;
354 taskName
= ndl
->dol_Ext
.dol_AROS
.dol_DevName
; // ((struct Task *)((struct FileLock *)BADDR(ndl->dol_Lock))->fl_Task->mp_SigTask)->tc_Node.ln_Name;
356 D(bug("Found directory %s\n", taskName
));
360 *p
++ = ""; // TODO!!! ((struct Task *)((struct FileLock *)BADDR(al->al_Lock))->fl_Task->mp_SigTask)->tc_Node.ln_Name;
375 while((ndl
= NextDosEntry(ndl
, LDF_VOLUMES
| LDF_DEVICES
| LDF_READ
)) != NULL
)
378 UBYTE type
= ndl
->dol_Type
;
381 // if(((type == DLT_DEVICE))) // && (!ndl->dol_Task) TODO Check this!
384 __sprintf(name
, "%s:", ndl
->dol_Ext
.dol_AROS
.dol_DevName
);
386 D(bug("Found name %s\n", ndl
->dol_Ext
.dol_AROS
.dol_DevName
));
388 if((type
== DLT_DEVICE
) && (myMatchPatternNoCase(strray
, name
) == FALSE
))
392 D(bug("Failure! -- name = %s, strray = %p\n", name
, (void *)strray
));
394 for (i
= 0; strray
[i
] != NULL
; i
++)
396 D(bug("Strray %i = %s\n", i
, strray
[i
]));
402 idn
= (struct InfoDosNode
*)AllocPooled(Pool
, sizeof(struct InfoDosNode
));
410 // idn->Task = (struct MsgPort *)ndl->dol_Task;
411 idn
->IsVolume
= type
== DLT_VOLUME
;
413 while((idn
->Name
[len
] = name
[len
]))
416 if(type
== DLT_VOLUME
)
418 idn
->VolumeDate
= ((struct DeviceList
*)ndl
)->dl_VolumeDate
;
419 idn
->Name
[len
- 1] = '\0'; /* remove ':' */
423 BPTR ptr
= BADDR(ndl
->dol_misc
.dol_handler
.dol_Startup
);
424 struct FileSysStartupMsg
*fssm
= (struct FileSysStartupMsg
*)ptr
;
426 idn
->DosType
= ID_DOS_DISK
;
435 de
= (struct DosEnvec
*)BADDR(fssm
->fssm_Environ
);
437 if (de
&& (de
->de_TableSize
& 0xffffff00) == 0)
439 idn
->DosType
= de
->de_DosType
;
443 /* kinda insert sort */
445 struct InfoDosNode
*work
= head
;
446 struct InfoDosNode
*prev
= NULL
;
448 while((work
!= NULL
) && (Stricmp(idn
->Name
, work
->Name
) > 0))
463 /* unlock list of devices and volumes */
464 UnLockDosList(LDF_ASSIGNS
| LDF_VOLUMES
| LDF_DEVICES
| LDF_READ
);
466 // strray freed at DeletePool
472 void PrintNum(ULONG num
)
487 num
= ExtUDivMod32(UMult32(num
, 100) >> 10, 100, &x
);
490 x
= ExtUDivMod32(x
, 10, &xx
);
501 IPTR args
[] = {num
, x
, fmt
};
502 VLPrintf(BIGNUMFMT
, "%5ld.%ld%lc", args
);
506 VLPrintf(SMALLNUMFMT
, "%7ldK", (IPTR
*) &num
);
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 static struct InfoData id
;
562 IPTR args
[] = { (IPTR
)FALSE
,
568 CONST_STRPTR unit
= GetStrFromCat(UNIT
, "Unit");
570 Pool
= CreatePool(MEMF_ANY
, 1024, 1024);
574 PrintFault(ERROR_NO_FREE_STORE
, NULL
);
578 D(bug("Calling ReadArgs()\n"));
581 rdargs
= ReadArgs("DISKS/S,VOLS=VOLUMES/S,ALL/S,BLOCKS/S,DEVICES/M",
586 BOOL disks
= (BOOL
)args
[ARG_DISKS
];
587 BOOL vols
= (BOOL
)args
[ARG_VOLS
];
588 BOOL showall
= (BOOL
)args
[ARG_ALL
];
589 BOOL blocks
= (BOOL
)args
[ARG_BLOCKS
];
590 STRPTR
*devs
= (STRPTR
*)args
[ARG_DEVS
];
592 if (devs
&& (*devs
== NULL
)) devs
= NULL
;
594 /* If nothing is specified, show everything we got */
595 if(devs
== NULL
&& !disks
&& !vols
)
601 /* check pattern strings */
611 if(ParsePatternNoCase(*p
, matchstr
, sizeof(matchstr
)) == -1)
613 PrintFault(IoErr(), *p
);
621 /* avoid requesters */
622 proc
= (struct Process
*)FindTask(NULL
);
623 win
= (struct Window
*)proc
->pr_WindowPtr
;
624 proc
->pr_WindowPtr
= (struct Window
*)~0;
626 MaxLen
= strlen(unit
);
628 D(bug("Calling ScanDosList()\n"));
631 if(ScanDosList(devs
))
633 CONST_STRPTR dstate
[3] = { GetStrFromCat(READONLY
, "read only"),
634 GetStrFromCat(VALIDATING
, "validating"),
635 GetStrFromCat(READWRITE
, "read/write") };
636 STRPTR datetimeFmt
= NULL
;
641 D(bug("Printing stuff\n"));
643 /* get datetimefmt string */
644 if(loc
&& (GetVar("info_datetime", buf
, sizeof(buf
), 0L) > 0L))
649 /* calc format string for 'Unit' */
650 __sprintf(nfmtstr
, "%%-%lds", MaxLen
);
652 /* show device infomation */
653 if(devs
!= NULL
|| disks
|| !vols
)
655 for(idn
= head
; idn
; idn
= idn
->Next
)
658 STRPTR name
= idn
->Name
;
660 D(bug("Got name = %s\n", name
));
662 if(!idn
->IsVolume
&& IsFileSystem(name
))
664 /* if first device to print, print title */
670 D(bug("Printing device\n"));
672 VLPrintf(~0, nfmtstr
, (IPTR
*) &unit
);
673 VLPrintf(DEVTITLE
, " Size Used Free Full Errs State Type Name\n", NULL
);
678 D(bug("Locking \"%s\"\n", name
));
679 lock
= Lock(name
, SHARED_LOCK
);
681 D(bug("Lock = %p\n", lock
));
685 D(bug("Got lock on %s\n", name
));
687 if(Info(lock
, &id
) == DOSTRUE
)
691 D(bug("Got info on %s\n", name
));
693 VLPrintf(~0, nfmtstr
, (IPTR
*) &name
);
695 x
= ComputeKBytes(id
.id_NumBlocks
, id
.id_BytesPerBlock
);
696 y
= ComputeKBytes(id
.id_NumBlocksUsed
, id
.id_BytesPerBlock
);
702 D(bug("Calling NameFromLock()\n"));
704 if(NameFromLock(lock
, name
, 108L))
706 LONG len
= strlen(name
) - 1;
722 x
= ExtUDivMod32(UDivMod32(UMult32(y
, 1000), x
), 10, &y
);
730 // y = ((struct DeviceList *)BADDR(id.id_VolumeNode))->dl_DiskType;
735 if((idn
->DosType
& ID_DOS_DISK
) != ID_DOS_DISK
)
741 ((id
.id_DiskState
>= ID_WRITE_PROTECTED
) && (id
.id_DiskState
<= ID_VALIDATED
)) ?
742 (IPTR
) dstate
[id
.id_DiskState
- ID_WRITE_PROTECTED
] : (IPTR
) "",
743 (IPTR
) GetFSysStr(y
),
745 VLPrintf(DEVFMTSTR
, "%4ld%% %4ld %-11s%-8s%s\n", args
);
752 id
.id_NumBlocks
-id
.id_NumBlocksUsed
,
753 id
.id_BytesPerBlock
};
755 "\nTotal blocks: %-10ld Blocks used: %ld\n"
756 " Blocks free: %-10ld Blocksize: %ld\n",
761 D(bug("Info failure\n"));
769 if((err
!= 0) && showall
)
771 VLPrintf(~0, nfmtstr
, (IPTR
*) &name
);
772 PrintFault(err
, NULL
);
780 if(vols
|| (!devs
&& !disks
))
785 VLPrintf(DISKSTITLE
, "Volumes\n", NULL
);
787 for(MaxLen
= 15, idn
= head
; idn
; idn
= idn
->Next
)
791 LONG len
= strlen(idn
->Name
);
798 __sprintf(nfmtstr
, "%%-%lds%%-10s", MaxLen
+1);
800 for(idn
= head
; idn
; idn
= idn
->Next
)
806 (IPTR
) GetStrFromCat(MOUNTEDSTR
, "[Mounted]")};
807 // idn->Task ? GetStrFromCat(MOUNTEDSTR, "[Mounted]") : ""); TODO
808 VLPrintf(VOLNAMEFMTSTR
, nfmtstr
, args
);
813 static struct Hook hook
;
815 memset(&hook
, 0, sizeof(struct Hook
));
817 hook
.h_SubEntry
= (HOOKFUNC
)FmtProcedure
;
818 hook
.h_Data
= datestr
;
820 FormatDate(loc
, datetimeFmt
, &idn
->VolumeDate
, &hook
);
826 TEXT StrDay
[LEN_DATSTRING
];
827 TEXT StrDate
[LEN_DATSTRING
];
828 TEXT StrTime
[LEN_DATSTRING
];
832 dt
.dat_Flags
= DTF_SUBST
;
833 dt
.dat_Format
= FORMAT_DOS
;
834 dt
.dat_StrDay
= StrDay
;
835 dt
.dat_StrDate
= StrDate
;
836 dt
.dat_StrTime
= StrTime
;
837 dt
.dat_Stamp
= idn
->VolumeDate
;
841 if(Strnicmp(StrDate
, StrDay
, strlen(StrDay
)) == 0)
847 IPTR args
[] = {(IPTR
) StrDay
, (IPTR
) StrDate
, (IPTR
) StrTime
};
848 VLPrintf(DATEFMTSTR
, "created %.3s, %-10s %s", args
);
859 PrintFault( ERROR_NO_FREE_STORE
, NULL
);
862 /* reset window pointer of our process */
863 proc
->pr_WindowPtr
= win
;
870 end
: /* free allocated memory */
876 ULONG
ComputeKBytes(ULONG a
, ULONG b
)
878 // UQUAD result = UMult64(a, b);
880 UQUAD result
= (UQUAD
)a
* b
;
882 return (ULONG
)(result
>> 10);
886 void FmtProcedure(struct Hook
*hook
, char a
, struct Locale
*locale
)
888 *((STRPTR
)hook
->h_Data
) = a
;
889 hook
->h_Data
= (STRPTR
) hook
->h_Data
+ 1;
893 ULONG
ExtUDivMod32(ULONG a
, ULONG b
, ULONG
*mod
)