Don't show unset volume creation dates (represented as 01-01-1978).
[AROS.git] / workbench / c / Info.c
blobaa7d723f714b071a8b4f883a610261c836197e72
1 /*
2 Copyright © 1995-2015, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Info Cli Command
6 Lang: English
7 */
9 /******************************************************************************
12 NAME
14 Info
16 SYNOPSIS
18 DISKS/S, VOLS=VOLUMES/S, ALL/S, BLOCKS/S, DEVICES/M
20 LOCATION
24 FUNCTION
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.
31 INPUTS
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
39 RESULT
41 NOTES
43 EXAMPLE
45 Info
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
51 BUGS
53 SEE ALSO
55 INTERNALS
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
60 NULL.
62 HISTORY
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
71 All rights resevered
72 ******************************************************************************/
74 #define DEBUG 0
75 #include <aros/debug.h>
77 #include <dos/dos.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>
89 #include <string.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 */
125 /* Prototypes */
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);
130 void doInfo();
133 const TEXT VersionStr[] = "$VER: Info 41.2 (26.05.2012)";
135 struct Catalog *cat;
136 struct Locale *loc = NULL;
137 ULONG MaxLen;
139 APTR Pool;
142 /* catalog string id:s */
143 enum
145 UNIT,
146 DEVTITLE,
147 DISKSTITLE,
148 DEVFMTSTR,
149 DATEFMTSTR,
150 READONLY,
151 READWRITE,
152 VALIDATING,
153 MOUNTEDSTR,
154 SMALLNUMFMT,
155 BIGNUMFMT,
156 VOLNAMEFMTSTR,
157 BLOCKSSTR
161 struct InfoDosNode
163 struct InfoDosNode *Next;
164 ULONG IsVolume;
165 ULONG DosType;
166 struct MsgPort *Task;
167 struct DateStamp VolumeDate;
168 TEXT Name[108];
171 struct InfoDosNode *head = NULL;
174 struct DiskTypeList
175 { ULONG id;
176 STRPTR str;
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" },
210 { 0L, 0L }
214 /****************************************************************************/
216 int UtilityBase_version = 0;
217 int LocaleBase_version = 0;
219 int __nocommandline;
221 int main(void)
223 static struct TagItem loctags[] = { { OC_Version, 1 },
224 { TAG_END , 0 } };
225 cat = OpenCatalogA(NULL, "info_com.catalog", loctags);
226 loc = OpenLocale(NULL);
228 D(bug("Calling doInfo()\n"));
230 doInfo();
232 CloseLocale(loc);
233 CloseCatalog(cat);
235 return RETURN_OK; /* TODO: Fix this */
239 CONST_STRPTR GetStrFromCat(ULONG id, CONST_STRPTR def)
241 if(cat != NULL)
243 def = GetCatalogStr(cat, id, def);
246 return 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)
259 if(*array != NULL)
261 while(*array != NULL)
263 UBYTE matchstr[128];
264 UBYTE name[32];
265 UBYTE *p = *array++;
266 UBYTE len = strlen(p);
268 if(p[len - 1] != ':')
270 CopyMem(p, name, len);
271 name[len] = ':';
272 name[len + 1] = 0;
273 p = name;
276 if(ParsePatternNoCase(p, matchstr, sizeof(matchstr)) != -1)
278 if(MatchPatternNoCase(matchstr, str))
280 return TRUE;
285 return FALSE;
288 return TRUE;
292 BOOL ScanDosList(STRPTR *filter)
294 struct InfoDosNode *idn = 0L;
295 struct DosList *ndl, *dl;
296 STRPTR *strray = NULL, dummy = NULL;
297 BOOL err = FALSE;
299 D(bug("Entered ScanDosList()\n"));
301 if (filter == NULL) filter = &dummy;
303 if(*filter != NULL)
305 strray = AllocPooled(Pool, sizeof(STRPTR)*MAX_MULTIARGS);
307 if(strray != NULL)
309 STRPTR *p = filter;
310 LONG i = 0;
312 while(*p)
313 strray[i++] = *p++;
315 while(i < MAX_MULTIARGS)
316 strray[i++] = NULL;
318 else
319 return FALSE;
322 /* lock list of devices & vols */
323 dl = ndl = LockDosList(LDF_ASSIGNS | LDF_VOLUMES | LDF_DEVICES | LDF_READ);
325 if(strray != NULL)
327 STRPTR *p = strray;
329 while(*p)
330 p++;
332 while((ndl = NextDosEntry(ndl, LDF_ASSIGNS | LDF_VOLUMES | LDF_READ)) != NULL)
334 TEXT name[108];
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)))
341 continue;
344 switch (ndl->dol_Type)
346 case DLT_VOLUME:
347 taskName = ((struct Task *)ndl->dol_Task->mp_SigTask)->tc_Node.ln_Name;
349 D(bug("Found volume %s\n", taskName));
350 break;
352 case DLT_DIRECTORY:
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));
360 while(al != NULL)
362 *p++ = ""; // TODO!!! ((struct Task *)((struct FileLock *)BADDR(al->al_Lock))->fl_Task->mp_SigTask)->tc_Node.ln_Name;
363 al = al->al_Next;
366 break;
369 *p++ = taskName;
372 else
373 strray = filter;
375 ndl = dl;
377 while((ndl = NextDosEntry(ndl, LDF_VOLUMES | LDF_DEVICES | LDF_READ)) != NULL)
379 UBYTE len = 0;
380 UBYTE type = ndl->dol_Type;
381 UBYTE name[108];
383 /* do not start non-started handlers or open CON: or RAW: windows */
384 if(type == DLT_DEVICE && !ndl->dol_Task)
385 continue;
387 __sprintf(name, "%b:", ndl->dol_Name);
388 D(bug("Found name %s\n", name));
390 if((type == DLT_DEVICE) && (myMatchPatternNoCase(strray, name) == FALSE))
392 D(int i);
394 D(bug("Failure! -- name = %s, strray = %p\n", name, (void *)strray));
396 D(for (i = 0; strray[i] != NULL; i++)
398 bug("Strray %i = %s\n", i, strray[i]);
401 continue;
404 idn = (struct InfoDosNode *)AllocPooled(Pool, sizeof(struct InfoDosNode));
406 if(idn == NULL)
408 err = TRUE;
409 break;
412 idn->Task = ndl->dol_Task;
413 idn->IsVolume = type == DLT_VOLUME;
415 while((idn->Name[len] = name[len]))
416 len++;
418 if(type == DLT_VOLUME)
420 idn->VolumeDate = ((struct DeviceList *)ndl)->dl_VolumeDate;
421 idn->Name[len - 1] = '\0'; /* remove ':' */
423 else
425 BPTR ptr = ndl->dol_misc.dol_handler.dol_Startup;
426 struct FileSysStartupMsg *fssm = NULL;
428 if (IsFileSystem(idn->Name))
430 // Only filesystems have a valid FileSysStartupMsg
431 fssm = (struct FileSysStartupMsg *)BADDR(ptr);
434 idn->DosType = ID_DOS_DISK;
436 // DLT_DEVICE
437 if (len > MaxLen)
438 MaxLen = len;
440 if (fssm)
442 struct DosEnvec *de;
443 de = (struct DosEnvec *)BADDR(fssm->fssm_Environ);
445 if (de && (de->de_TableSize & 0xffffff00) == 0)
446 if (de->de_DosType)
447 idn->DosType = de->de_DosType;
451 /* kinda insert sort */
453 struct InfoDosNode *work = head;
454 struct InfoDosNode *prev = NULL;
456 while((work != NULL) && (Stricmp(idn->Name, work->Name) > 0))
458 prev = work;
459 work = work->Next;
462 if(prev != NULL)
463 prev->Next = idn;
464 else
465 head = idn;
467 idn->Next = work;
471 /* unlock list of devices and volumes */
472 UnLockDosList(LDF_ASSIGNS | LDF_VOLUMES | LDF_DEVICES | LDF_READ);
474 // strray freed at DeletePool
476 return !err;
480 void PrintNum(ULONG num)
482 /* MBytes ? */
483 if(num > 1023)
485 ULONG x, xx;
486 char fmt = 'M';
488 /* GBytes ? */
489 if(num > 0xfffff)
491 num >>= 10;
492 fmt = 'G';
495 num = ExtUDivMod32(UMult32(num, 100) >> 10, 100, &x);
497 /* round */
498 x = ExtUDivMod32(x, 10, &xx);
500 if(xx > 4)
502 if(++x > 9)
504 x = 0;
505 num++;
509 IPTR args[] = {num, x, fmt};
510 VLPrintf(BIGNUMFMT, "%5ld.%ld%lc", args);
512 else
514 IPTR args[] = { num };
515 VLPrintf(SMALLNUMFMT, "%7ldK", args);
520 STRPTR GetFSysStr(ULONG DiskType)
522 struct DiskTypeList *dtlptr = dtl;
524 STRPTR ptr = NULL;
526 do {
527 if(dtlptr->id == DiskType)
529 ptr = dtlptr->str;
530 break;
532 } while(*((ULONG *)dtlptr++));
534 if(ptr == NULL)
536 static TEXT buffer[5];
538 ptr = (STRPTR)buffer;
539 *((ULONG *)ptr) = AROS_LONG2BE(DiskType);
541 if(ptr[3] < ' ')
542 ptr[3] += '0';
544 ptr[4] = '\0';
547 return ptr;
551 enum
553 ARG_DISKS,
554 ARG_VOLS,
555 ARG_ALL,
556 ARG_BLOCKS,
557 ARG_DEVS,
558 NOOFARGS
562 void doInfo()
564 struct RDArgs *rdargs;
565 struct Process *proc;
566 struct Window *win;
567 struct InfoDosNode *idn;
569 struct InfoData *id = AllocVec(sizeof(struct InfoData), MEMF_ANY);
571 IPTR args[] = { (IPTR)FALSE,
572 (IPTR)FALSE,
573 (IPTR)FALSE,
574 (IPTR)FALSE,
575 (IPTR)NULL };
577 CONST_STRPTR unit = GetStrFromCat(UNIT, "Unit");
579 if(id == NULL)
581 PrintFault(ERROR_NO_FREE_STORE, NULL);
582 return;
585 Pool = CreatePool(MEMF_ANY, 1024, 1024);
587 if(Pool == NULL)
589 PrintFault(ERROR_NO_FREE_STORE, NULL);
590 return; /* ??? */
593 D(bug("Calling ReadArgs()\n"));
595 /* read arguments */
596 rdargs = ReadArgs("DISKS/S,VOLS=VOLUMES/S,ALL/S,BLOCKS/S,DEVICES/M",
597 args, NULL);
599 if(rdargs != NULL)
601 BOOL disks = (BOOL)args[ARG_DISKS];
602 BOOL vols = (BOOL)args[ARG_VOLS];
603 BOOL showall = (BOOL)args[ARG_ALL];
604 BOOL blocks = (BOOL)args[ARG_BLOCKS];
605 STRPTR *devs = (STRPTR *)args[ARG_DEVS];
607 if (devs && (*devs == NULL)) devs = NULL;
609 /* If nothing is specified, show everything we got */
610 if(devs == NULL && !disks && !vols)
612 vols = TRUE;
613 disks = TRUE;
616 /* check pattern strings */
617 if(devs != NULL)
619 STRPTR *p = devs;
621 while(*p != NULL)
623 TEXT matchstr[128];
625 if(ParsePatternNoCase(*p, matchstr, sizeof(matchstr)) == -1)
627 PrintFault(IoErr(), *p);
628 goto end;
631 p++;
635 /* avoid requesters */
636 proc = (struct Process *)FindTask(NULL);
637 win = (struct Window *)proc->pr_WindowPtr;
638 proc->pr_WindowPtr = (struct Window *)~0;
640 MaxLen = strlen(unit);
642 D(bug("Calling ScanDosList()\n"));
644 /* scan doslist */
645 if(ScanDosList(devs))
647 CONST_STRPTR dstate[3] = { GetStrFromCat(READONLY, "read only"),
648 GetStrFromCat(VALIDATING, "validating"),
649 GetStrFromCat(READWRITE, "read/write") };
650 STRPTR datetimeFmt = NULL;
651 BOOL first = TRUE;
652 TEXT nfmtstr[16];
653 TEXT buf[64];
655 D(bug("Printing stuff\n"));
657 /* get datetimefmt string */
658 if(loc && (GetVar("info_datetime", buf, sizeof(buf), 0L) > 0L))
660 datetimeFmt = buf;
663 /* calc format string for 'Unit' */
664 __sprintf(nfmtstr, "%%-%lds", MaxLen);
666 /* show device infomation */
667 if(devs != NULL || disks || !vols)
669 for(idn = head; idn; idn = idn->Next)
671 BPTR lock;
672 STRPTR name = idn->Name;
674 D(bug("Got name = %s\n", name));
676 if(!idn->IsVolume && IsFileSystem(name))
678 BOOL gotinfo = FALSE;
679 /* if first device to print, print title */
680 if(first || blocks)
682 if(!first)
683 Printf("\n");
685 D(bug("Printing device\n"));
687 VLPrintf(~0, nfmtstr, (IPTR*) &unit);
688 VLPrintf(DEVTITLE, " Size Used Free Full Errs State Type Name\n", NULL);
690 first = FALSE;
693 VLPrintf(~0, nfmtstr, (IPTR*) &name);
695 D(bug("Locking \"%s\"\n", name));
696 lock = Lock(name, SHARED_LOCK);
698 D(bug("Lock = %p\n", (APTR)lock));
700 if(lock != BNULL)
702 D(bug("Got lock on %s\n", name));
704 if(Info(lock, id) == DOSTRUE)
706 D(bug("Calling NameFromLock()\n"));
708 if(NameFromLock(lock, name, 108L))
710 LONG len = strlen(name) - 1;
712 if(name[len] == ':')
714 name[len] = '\0';
718 gotinfo = TRUE;
720 UnLock(lock);
722 } else if (idn->Task) {
723 name = NULL;
724 D(bug("Calling ACTION_DISK_INFO\n"));
725 if (DoPkt(idn->Task, ACTION_DISK_INFO, (SIPTR)MKBADDR(id), (SIPTR)BNULL, (SIPTR)BNULL, (SIPTR)BNULL, (SIPTR)BNULL)) {
726 gotinfo = TRUE;
730 if (gotinfo) {
731 ULONG x, y;
733 D(bug("Got info on %s\n", name));
735 if (id->id_DiskType == ID_NO_DISK_PRESENT) {
736 VLPrintf(~0, " No disk present\n", NULL);
737 } else if (id->id_DiskType == ID_NOT_REALLY_DOS) {
738 VLPrintf(~0, " Not a DOS disk\n", NULL);
739 } else if (id->id_DiskType == ID_UNREADABLE_DISK) {
740 VLPrintf(~0, " Unreadable disk\n", NULL);
741 } else {
742 x = ComputeKBytes(id->id_NumBlocks, id->id_BytesPerBlock);
743 y = ComputeKBytes(id->id_NumBlocksUsed, id->id_BytesPerBlock);
745 PrintNum(x);
746 PrintNum(y);
747 PrintNum(x - y);
749 if(x > 0xfffff)
751 x >>= 10;
752 y >>= 10;
755 if(x)
757 x = ExtUDivMod32(UDivMod32(UMult32(y, 1000), x), 10, &y);
759 if(y > 4)
760 x++;
762 else
763 x = 0;
765 // y = ((struct DeviceList *)BADDR(id->id_VolumeNode))->dl_DiskType;
767 // if(!y)
768 y = id->id_DiskType;
770 if((idn->DosType & ID_DOS_DISK) != ID_DOS_DISK)
771 y = idn->DosType;
774 IPTR args[] = {
776 id->id_NumSoftErrors,
777 ((id->id_DiskState >= ID_WRITE_PROTECTED) && (id->id_DiskState <= ID_VALIDATED)) ?
778 (IPTR) dstate[id->id_DiskState - ID_WRITE_PROTECTED] : (IPTR) "",
779 (IPTR) GetFSysStr(y),
780 (IPTR) name};
781 VLPrintf(DEVFMTSTR, "%4ld%% %4ld %-11s%-8s%s\n", args);
784 if(blocks)
786 IPTR args[] = {
787 id->id_NumBlocks,
788 id->id_NumBlocksUsed,
789 id->id_NumBlocks-id->id_NumBlocksUsed,
790 id->id_BytesPerBlock};
791 VLPrintf(BLOCKSSTR,
792 "\nTotal blocks: %-10ld Blocks used: %ld\n"
793 " Blocks free: %-10ld Blocksize: %ld\n",
794 args);
798 else
800 D(bug("Info failure\n"));
801 VLPrintf(~0, "\n", NULL);
805 LONG err = IoErr();
807 /* just ignore PIPEFS */
808 if (err == ERROR_ACTION_NOT_KNOWN)
809 if (strcmp(name, "PIPEFS:") == 0)
810 err = 0;
812 if (err && showall)
814 VLPrintf(~0, nfmtstr, (IPTR*) &name);
815 PrintFault(err, NULL);
822 /* show volumes */
823 if(vols || (!devs && !disks))
825 if(!first)
826 PutStr("\n");
828 VLPrintf(DISKSTITLE, "Volumes\n", NULL);
830 /* find the longest volume name */
831 for(MaxLen = 15, idn = head; idn; idn = idn->Next)
833 if(idn->IsVolume)
835 LONG len = strlen(idn->Name);
837 if(len > MaxLen)
838 MaxLen = len;
842 __sprintf(nfmtstr, "%%-%lds%%-10s", MaxLen+1);
844 for(idn = head; idn; idn = idn->Next)
846 if(idn->IsVolume)
848 IPTR args[] = {
849 (IPTR) idn->Name,
850 (IPTR) GetStrFromCat(MOUNTEDSTR, "[Mounted]")};
851 // idn->Task ? GetStrFromCat(MOUNTEDSTR, "[Mounted]") : ""); TODO
852 VLPrintf(VOLNAMEFMTSTR, nfmtstr, args);
854 if(idn->VolumeDate.ds_Days != 0)
856 if(datetimeFmt)
858 UBYTE datestr[128];
859 static struct Hook hook;
861 memset(&hook, 0, sizeof(struct Hook));
863 hook.h_SubEntry = (HOOKFUNC)FmtProcedure;
864 hook.h_Data = datestr;
866 FormatDate(loc, datetimeFmt, &idn->VolumeDate, &hook);
868 PutStr(datestr);
870 else
872 TEXT StrDay[LEN_DATSTRING];
873 TEXT StrDate[LEN_DATSTRING];
874 TEXT StrTime[LEN_DATSTRING];
876 struct DateTime dt;
878 dt.dat_Flags = DTF_SUBST;
879 dt.dat_Format = FORMAT_DOS;
880 dt.dat_StrDay = StrDay;
881 dt.dat_StrDate = StrDate;
882 dt.dat_StrTime = StrTime;
883 dt.dat_Stamp = idn->VolumeDate;
885 if(DateToStr(&dt))
887 if(Strnicmp(StrDate, StrDay, strlen(StrDay)) == 0)
889 dt.dat_Flags = 0L;
890 DateToStr(&dt);
893 IPTR args[] = {(IPTR) StrDay, (IPTR) StrDate, (IPTR) StrTime};
894 VLPrintf(DATEFMTSTR, "created %.3s, %-10s %s", args);
899 PutStr("\n");
904 else
906 PrintFault( ERROR_NO_FREE_STORE, NULL);
909 /* reset window pointer of our process */
910 proc->pr_WindowPtr = win;
912 /* free args */
913 FreeArgs(rdargs);
917 end: /* free allocated memory */
918 FreeVec(id);
919 DeletePool(Pool);
923 ULONG ComputeKBytes(ULONG a, ULONG b)
925 // UQUAD result = UMult64(a, b);
927 UQUAD result = (UQUAD)a * b;
929 return (ULONG)(result >> 10);
933 void FmtProcedure(struct Hook *hook, char a, struct Locale *locale)
935 *((STRPTR)hook->h_Data) = a;
936 hook->h_Data = (STRPTR) hook->h_Data + 1;
940 ULONG ExtUDivMod32(ULONG a, ULONG b, ULONG *mod)
942 *mod = a % b;
944 return a/b;