grub2: bring back build of aros-side grub2 tools
[AROS.git] / workbench / c / Info.c
blobab6a1146c6a34c85e64acb276f1a276443ed4ad0
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, ...)
252 CONST_STRPTR format = GetStrFromCat(id, def);
253 AROS_SLOWSTACKFORMAT_PRE_USING(def, format);
254 VPrintf(format, AROS_SLOWSTACKFORMAT_ARG(def));
255 AROS_SLOWSTACKFORMAT_POST(def);
259 BOOL myMatchPatternNoCase(STRPTR *array, STRPTR str)
261 if(*array != NULL)
263 while(*array != NULL)
265 UBYTE matchstr[128];
266 UBYTE name[32];
267 UBYTE *p = *array++;
268 UBYTE len = strlen(p);
270 if(p[len - 1] != ':')
272 CopyMem(p, name, len);
273 name[len] = ':';
274 name[len + 1] = 0;
275 p = name;
278 if(ParsePatternNoCase(p, matchstr, sizeof(matchstr)) != -1)
280 if(MatchPatternNoCase(matchstr, str))
282 return TRUE;
287 return FALSE;
290 return TRUE;
294 BOOL ScanDosList(STRPTR *filter)
296 struct InfoDosNode *idn = 0L;
297 struct DosList *ndl, *dl;
298 STRPTR *strray = NULL, dummy = NULL;
299 BOOL err = FALSE;
301 D(bug("Entered ScanDosList()\n"));
303 if (filter == NULL) filter = &dummy;
305 if(*filter != NULL)
307 strray = AllocPooled(Pool, sizeof(STRPTR)*MAX_MULTIARGS);
309 if(strray != NULL)
311 STRPTR *p = filter;
312 LONG i = 0;
314 while(*p)
315 strray[i++] = *p++;
317 while(i < MAX_MULTIARGS)
318 strray[i++] = NULL;
320 else
321 return FALSE;
324 /* lock list of devices & vols */
325 dl = ndl = LockDosList(LDF_ASSIGNS | LDF_VOLUMES | LDF_DEVICES | LDF_READ);
327 if(strray != NULL)
329 STRPTR *p = strray;
331 while(*p)
332 p++;
334 while((ndl = NextDosEntry(ndl, LDF_ASSIGNS | LDF_VOLUMES | LDF_READ)) != NULL)
336 TEXT name[108];
337 STRPTR taskName = NULL; /* Initialized to avoid a warning */
339 __sprintf(name, "%b:", ndl->dol_Name);
341 if ((ndl->dol_Type > DLT_VOLUME) || !(myMatchPatternNoCase(strray, name)))
343 continue;
346 switch (ndl->dol_Type)
348 case DLT_VOLUME:
349 taskName = ((struct Task *)ndl->dol_Task->mp_SigTask)->tc_Node.ln_Name;
351 D(bug("Found volume %s\n", taskName));
352 break;
354 case DLT_DIRECTORY:
356 struct AssignList *al = ndl->dol_misc.dol_assign.dol_List;
358 taskName = ((struct Task *)((struct FileLock *)BADDR(ndl->dol_Lock))->fl_Task->mp_SigTask)->tc_Node.ln_Name;
360 D(bug("Found directory %s\n", taskName));
362 while(al != NULL)
364 *p++ = ""; // TODO!!! ((struct Task *)((struct FileLock *)BADDR(al->al_Lock))->fl_Task->mp_SigTask)->tc_Node.ln_Name;
365 al = al->al_Next;
368 break;
371 *p++ = taskName;
374 else
375 strray = filter;
377 ndl = dl;
379 while((ndl = NextDosEntry(ndl, LDF_VOLUMES | LDF_DEVICES | LDF_READ)) != NULL)
381 UBYTE len = 0;
382 UBYTE type = ndl->dol_Type;
383 UBYTE name[108];
385 /* do not start non-started handlers or open CON: or RAW: windows */
386 if(type == DLT_DEVICE && !ndl->dol_Task)
387 continue;
389 __sprintf(name, "%b:", ndl->dol_Name);
390 D(bug("Found name %s\n", name));
392 if((type == DLT_DEVICE) && (myMatchPatternNoCase(strray, name) == FALSE))
394 D(int i);
396 D(bug("Failure! -- name = %s, strray = %p\n", name, (void *)strray));
398 D(for (i = 0; strray[i] != NULL; i++)
400 bug("Strray %i = %s\n", i, strray[i]);
403 continue;
406 idn = (struct InfoDosNode *)AllocPooled(Pool, sizeof(struct InfoDosNode));
408 if(idn == NULL)
410 err = TRUE;
411 break;
414 idn->Task = ndl->dol_Task;
415 idn->IsVolume = type == DLT_VOLUME;
417 while((idn->Name[len] = name[len]))
418 len++;
420 if(type == DLT_VOLUME)
422 idn->VolumeDate = ((struct DeviceList *)ndl)->dl_VolumeDate;
423 idn->Name[len - 1] = '\0'; /* remove ':' */
425 else
427 BPTR ptr = ndl->dol_misc.dol_handler.dol_Startup;
428 struct FileSysStartupMsg *fssm = NULL;
430 if (IsFileSystem(idn->Name))
432 // Only filesystems have a valid FileSysStartupMsg
433 fssm = (struct FileSysStartupMsg *)BADDR(ptr);
436 idn->DosType = ID_DOS_DISK;
438 // DLT_DEVICE
439 if (len > MaxLen)
440 MaxLen = len;
442 if (fssm)
444 struct DosEnvec *de;
445 de = (struct DosEnvec *)BADDR(fssm->fssm_Environ);
447 if (de && (de->de_TableSize & 0xffffff00) == 0)
448 if (de->de_DosType)
449 idn->DosType = de->de_DosType;
453 /* kinda insert sort */
455 struct InfoDosNode *work = head;
456 struct InfoDosNode *prev = NULL;
458 while((work != NULL) && (Stricmp(idn->Name, work->Name) > 0))
460 prev = work;
461 work = work->Next;
464 if(prev != NULL)
465 prev->Next = idn;
466 else
467 head = idn;
469 idn->Next = work;
473 /* unlock list of devices and volumes */
474 UnLockDosList(LDF_ASSIGNS | LDF_VOLUMES | LDF_DEVICES | LDF_READ);
476 // strray freed at DeletePool
478 return !err;
482 void PrintNum(ULONG num)
484 /* MBytes ? */
485 if(num > 1023)
487 ULONG x, xx;
488 char fmt = 'M';
490 /* GBytes ? */
491 if(num > 0xfffff)
493 num >>= 10;
494 fmt = 'G';
497 num = ExtUDivMod32(UMult32(num, 100) >> 10, 100, &x);
499 /* round */
500 x = ExtUDivMod32(x, 10, &xx);
502 if(xx > 4)
504 if(++x > 9)
506 x = 0;
507 num++;
511 VLPrintf(BIGNUMFMT, "%5ld.%ld%lc", num, x, fmt);
513 else
515 VLPrintf(SMALLNUMFMT, "%7ldK", num);
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, unit);
688 VLPrintf(DEVTITLE, " Size Used Free Full Errs State Type Name\n");
690 first = FALSE;
693 VLPrintf(~0, nfmtstr, 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");
737 } else if (id->id_DiskType == ID_NOT_REALLY_DOS) {
738 VLPrintf(~0, " Not a DOS disk\n");
739 } else if (id->id_DiskType == ID_UNREADABLE_DISK) {
740 VLPrintf(~0, " Unreadable disk\n");
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 VLPrintf(DEVFMTSTR, "%4ld%% %4ld %-11s%-8s%s\n",
775 x, id->id_NumSoftErrors,
776 ((id->id_DiskState >= ID_WRITE_PROTECTED) && (id->id_DiskState <= ID_VALIDATED)) ? (const char *)dstate[id->id_DiskState - ID_WRITE_PROTECTED] : (const char *)"",
777 GetFSysStr(y),
778 name);
781 if(blocks)
783 VLPrintf(BLOCKSSTR,
784 "\nTotal blocks: %-10ld Blocks used: %ld\n"
785 " Blocks free: %-10ld Blocksize: %ld\n",
786 id->id_NumBlocks,
787 id->id_NumBlocksUsed,
788 id->id_NumBlocks-id->id_NumBlocksUsed,
789 id->id_BytesPerBlock);
793 else
795 D(bug("Info failure\n"));
796 VLPrintf(~0, "\n");
800 LONG err = IoErr();
802 /* just ignore PIPEFS */
803 if (err == ERROR_ACTION_NOT_KNOWN)
804 if (strcmp(name, "PIPEFS:") == 0)
805 err = 0;
807 if (err && showall)
809 VLPrintf(~0, nfmtstr, name);
810 PrintFault(err, NULL);
817 /* show volumes */
818 if(vols || (!devs && !disks))
820 if(!first)
821 PutStr("\n");
823 VLPrintf(DISKSTITLE, "Volumes\n");
825 /* find the longest volume name */
826 for(MaxLen = 15, idn = head; idn; idn = idn->Next)
828 if(idn->IsVolume)
830 LONG len = strlen(idn->Name);
832 if(len > MaxLen)
833 MaxLen = len;
837 __sprintf(nfmtstr, "%%-%lds%%-10s", MaxLen+1);
839 for(idn = head; idn; idn = idn->Next)
841 if(idn->IsVolume)
843 VLPrintf(VOLNAMEFMTSTR, nfmtstr, idn->Name,
844 idn->Task ? (const char *)GetStrFromCat(MOUNTEDSTR, "[Mounted]") : (const char *)"");
846 if(idn->VolumeDate.ds_Days != 0)
848 if(datetimeFmt)
850 UBYTE datestr[128];
851 static struct Hook hook;
853 memset(&hook, 0, sizeof(struct Hook));
855 hook.h_SubEntry = (HOOKFUNC)FmtProcedure;
856 hook.h_Data = datestr;
858 FormatDate(loc, datetimeFmt, &idn->VolumeDate, &hook);
860 PutStr(datestr);
862 else
864 TEXT StrDay[LEN_DATSTRING];
865 TEXT StrDate[LEN_DATSTRING];
866 TEXT StrTime[LEN_DATSTRING];
868 struct DateTime dt;
870 dt.dat_Flags = DTF_SUBST;
871 dt.dat_Format = FORMAT_DOS;
872 dt.dat_StrDay = StrDay;
873 dt.dat_StrDate = StrDate;
874 dt.dat_StrTime = StrTime;
875 dt.dat_Stamp = idn->VolumeDate;
877 if(DateToStr(&dt))
879 if(Strnicmp(StrDate, StrDay, strlen(StrDay)) == 0)
881 dt.dat_Flags = 0L;
882 DateToStr(&dt);
885 VLPrintf(DATEFMTSTR, "created %.3s, %-10s %s", StrDay, StrDate, StrTime);
890 PutStr("\n");
895 else
897 PrintFault( ERROR_NO_FREE_STORE, NULL);
900 /* reset window pointer of our process */
901 proc->pr_WindowPtr = win;
903 /* free args */
904 FreeArgs(rdargs);
908 end: /* free allocated memory */
909 FreeVec(id);
910 DeletePool(Pool);
914 ULONG ComputeKBytes(ULONG a, ULONG b)
916 // UQUAD result = UMult64(a, b);
918 UQUAD result = (UQUAD)a * b;
920 return (ULONG)(result >> 10);
924 void FmtProcedure(struct Hook *hook, char a, struct Locale *locale)
926 *((STRPTR)hook->h_Data) = a;
927 hook->h_Data = (STRPTR) hook->h_Data + 1;
931 ULONG ExtUDivMod32(ULONG a, ULONG b, ULONG *mod)
933 *mod = a % b;
935 return a/b;