Removed double entry.
[AROS.git] / workbench / c / Info.c
blobd80217a0a0c869fba3ffc979e3a644c107afdb69
1 /*
2 Copyright © 1995-2011, 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.1 (16.11.2000)";
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 int i;
394 D(bug("Failure! -- name = %s, strray = %p\n", name, (void *)strray));
396 for (i = 0; strray[i] != NULL; i++)
398 D(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 = (struct FileSysStartupMsg *)BADDR(ptr);
428 idn->DosType = ID_DOS_DISK;
430 // DLT_DEVICE
431 if (len > MaxLen)
432 MaxLen = len;
434 if (fssm)
436 struct DosEnvec *de;
437 de = (struct DosEnvec *)BADDR(fssm->fssm_Environ);
439 if (de && (de->de_TableSize & 0xffffff00) == 0)
440 if (de->de_DosType)
441 idn->DosType = de->de_DosType;
445 /* kinda insert sort */
447 struct InfoDosNode *work = head;
448 struct InfoDosNode *prev = NULL;
450 while((work != NULL) && (Stricmp(idn->Name, work->Name) > 0))
452 prev = work;
453 work = work->Next;
456 if(prev != NULL)
457 prev->Next = idn;
458 else
459 head = idn;
461 idn->Next = work;
465 /* unlock list of devices and volumes */
466 UnLockDosList(LDF_ASSIGNS | LDF_VOLUMES | LDF_DEVICES | LDF_READ);
468 // strray freed at DeletePool
470 return !err;
474 void PrintNum(ULONG num)
476 /* MBytes ? */
477 if(num > 1023)
479 ULONG x, xx;
480 char fmt = 'M';
482 /* GBytes ? */
483 if(num > 0xfffff)
485 num >>= 10;
486 fmt = 'G';
489 num = ExtUDivMod32(UMult32(num, 100) >> 10, 100, &x);
491 /* round */
492 x = ExtUDivMod32(x, 10, &xx);
494 if(xx > 4)
496 if(++x > 9)
498 x = 0;
499 num++;
503 IPTR args[] = {num, x, fmt};
504 VLPrintf(BIGNUMFMT, "%5ld.%ld%lc", args);
506 else
508 IPTR args[] = { num };
509 VLPrintf(SMALLNUMFMT, "%7ldK", args);
514 STRPTR GetFSysStr(ULONG DiskType)
516 struct DiskTypeList *dtlptr = dtl;
518 STRPTR ptr = NULL;
520 do {
521 if(dtlptr->id == DiskType)
523 ptr = dtlptr->str;
524 break;
526 } while(*((ULONG *)dtlptr++));
528 if(ptr == NULL)
530 static TEXT buffer[5];
532 ptr = (STRPTR)buffer;
533 *((ULONG *)ptr) = AROS_LONG2BE(DiskType);
535 if(ptr[3] < ' ')
536 ptr[3] += '0';
538 ptr[4] = '\0';
541 return ptr;
545 enum
547 ARG_DISKS,
548 ARG_VOLS,
549 ARG_ALL,
550 ARG_BLOCKS,
551 ARG_DEVS,
552 NOOFARGS
556 void doInfo()
558 struct RDArgs *rdargs;
559 struct Process *proc;
560 struct Window *win;
561 struct InfoDosNode *idn;
563 struct InfoData *id = AllocVec(sizeof(struct InfoData), MEMF_ANY);
565 IPTR args[] = { (IPTR)FALSE,
566 (IPTR)FALSE,
567 (IPTR)FALSE,
568 (IPTR)FALSE,
569 (IPTR)NULL };
571 CONST_STRPTR unit = GetStrFromCat(UNIT, "Unit");
573 if(id == NULL)
575 PrintFault(ERROR_NO_FREE_STORE, NULL);
576 return;
579 Pool = CreatePool(MEMF_ANY, 1024, 1024);
581 if(Pool == NULL)
583 PrintFault(ERROR_NO_FREE_STORE, NULL);
584 return; /* ??? */
587 D(bug("Calling ReadArgs()\n"));
589 /* read arguments */
590 rdargs = ReadArgs("DISKS/S,VOLS=VOLUMES/S,ALL/S,BLOCKS/S,DEVICES/M",
591 args, NULL);
593 if(rdargs != NULL)
595 BOOL disks = (BOOL)args[ARG_DISKS];
596 BOOL vols = (BOOL)args[ARG_VOLS];
597 BOOL showall = (BOOL)args[ARG_ALL];
598 BOOL blocks = (BOOL)args[ARG_BLOCKS];
599 STRPTR *devs = (STRPTR *)args[ARG_DEVS];
601 if (devs && (*devs == NULL)) devs = NULL;
603 /* If nothing is specified, show everything we got */
604 if(devs == NULL && !disks && !vols)
606 vols = TRUE;
607 disks = TRUE;
610 /* check pattern strings */
612 if(devs != NULL)
614 STRPTR *p = devs;
616 while(*p != NULL)
618 TEXT matchstr[128];
620 if(ParsePatternNoCase(*p, matchstr, sizeof(matchstr)) == -1)
622 PrintFault(IoErr(), *p);
623 goto end;
626 p++;
630 /* avoid requesters */
631 proc = (struct Process *)FindTask(NULL);
632 win = (struct Window *)proc->pr_WindowPtr;
633 proc->pr_WindowPtr = (struct Window *)~0;
635 MaxLen = strlen(unit);
637 D(bug("Calling ScanDosList()\n"));
639 /* scan doslist */
640 if(ScanDosList(devs))
642 CONST_STRPTR dstate[3] = { GetStrFromCat(READONLY, "read only"),
643 GetStrFromCat(VALIDATING, "validating"),
644 GetStrFromCat(READWRITE, "read/write") };
645 STRPTR datetimeFmt = NULL;
646 BOOL first = TRUE;
647 TEXT nfmtstr[16];
648 TEXT buf[64];
650 D(bug("Printing stuff\n"));
652 /* get datetimefmt string */
653 if(loc && (GetVar("info_datetime", buf, sizeof(buf), 0L) > 0L))
655 datetimeFmt = buf;
658 /* calc format string for 'Unit' */
659 __sprintf(nfmtstr, "%%-%lds", MaxLen);
661 /* show device infomation */
662 if(devs != NULL || disks || !vols)
664 for(idn = head; idn; idn = idn->Next)
666 BPTR lock;
667 STRPTR name = idn->Name;
669 D(bug("Got name = %s\n", name));
671 if(!idn->IsVolume && IsFileSystem(name))
673 BOOL gotinfo = FALSE;
674 /* if first device to print, print title */
675 if(first || blocks)
677 if(!first)
678 Printf("\n");
680 D(bug("Printing device\n"));
682 VLPrintf(~0, nfmtstr, (IPTR*) &unit);
683 VLPrintf(DEVTITLE, " Size Used Free Full Errs State Type Name\n", NULL);
685 first = FALSE;
688 VLPrintf(~0, nfmtstr, (IPTR*) &name);
690 D(bug("Locking \"%s\"\n", name));
691 lock = Lock(name, SHARED_LOCK);
693 D(bug("Lock = %p\n", (APTR)lock));
695 if(lock != BNULL)
697 D(bug("Got lock on %s\n", name));
699 if(Info(lock, id) == DOSTRUE)
701 D(bug("Calling NameFromLock()\n"));
703 if(NameFromLock(lock, name, 108L))
705 LONG len = strlen(name) - 1;
707 if(name[len] == ':')
709 name[len] = '\0';
713 gotinfo = TRUE;
715 UnLock(lock);
717 } else if (idn->Task) {
718 name = NULL;
719 D(bug("Calling ACTION_DISK_INFO\n"));
720 if (DoPkt(idn->Task, ACTION_DISK_INFO, (SIPTR)MKBADDR(id), (SIPTR)BNULL, (SIPTR)BNULL, (SIPTR)BNULL, (SIPTR)BNULL)) {
721 gotinfo = TRUE;
725 if (gotinfo) {
726 ULONG x, y;
728 D(bug("Got info on %s\n", name));
730 if (id->id_DiskType == ID_NO_DISK_PRESENT) {
731 VLPrintf(~0, " No disk present\n", NULL);
732 } else if (id->id_DiskType == ID_NOT_REALLY_DOS) {
733 VLPrintf(~0, " Not a DOS disk\n", NULL);
734 } else if (id->id_DiskType == ID_UNREADABLE_DISK) {
735 VLPrintf(~0, " Unreadable disk\n", NULL);
736 } else {
737 x = ComputeKBytes(id->id_NumBlocks, id->id_BytesPerBlock);
738 y = ComputeKBytes(id->id_NumBlocksUsed, id->id_BytesPerBlock);
740 PrintNum(x);
741 PrintNum(y);
742 PrintNum(x - y);
744 if(x > 0xfffff)
746 x >>= 10;
747 y >>= 10;
750 if(x)
752 x = ExtUDivMod32(UDivMod32(UMult32(y, 1000), x), 10, &y);
754 if(y > 4)
755 x++;
757 else
758 x = 0;
760 // y = ((struct DeviceList *)BADDR(id->id_VolumeNode))->dl_DiskType;
762 // if(!y)
763 y = id->id_DiskType;
765 if((idn->DosType & ID_DOS_DISK) != ID_DOS_DISK)
766 y = idn->DosType;
769 IPTR args[] = {
771 id->id_NumSoftErrors,
772 ((id->id_DiskState >= ID_WRITE_PROTECTED) && (id->id_DiskState <= ID_VALIDATED)) ?
773 (IPTR) dstate[id->id_DiskState - ID_WRITE_PROTECTED] : (IPTR) "",
774 (IPTR) GetFSysStr(y),
775 (IPTR) name};
776 VLPrintf(DEVFMTSTR, "%4ld%% %4ld %-11s%-8s%s\n", args);
779 if(blocks)
781 IPTR args[] = {
782 id->id_NumBlocks,
783 id->id_NumBlocksUsed,
784 id->id_NumBlocks-id->id_NumBlocksUsed,
785 id->id_BytesPerBlock};
786 VLPrintf(BLOCKSSTR,
787 "\nTotal blocks: %-10ld Blocks used: %ld\n"
788 " Blocks free: %-10ld Blocksize: %ld\n",
789 args);
793 else
795 D(bug("Info failure\n"));
796 VLPrintf(~0, "\n", NULL);
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, (IPTR*) &name);
810 PrintFault(err, NULL);
817 /* show volumes */
818 if(vols || (!devs && !disks))
820 if(!first)
821 PutStr("\n");
823 VLPrintf(DISKSTITLE, "Volumes\n", NULL);
825 for(MaxLen = 15, idn = head; idn; idn = idn->Next)
827 if(idn->IsVolume)
829 LONG len = strlen(idn->Name);
831 if(len > MaxLen)
832 MaxLen = len;
836 __sprintf(nfmtstr, "%%-%lds%%-10s", MaxLen+1);
838 for(idn = head; idn; idn = idn->Next)
840 if(idn->IsVolume)
842 IPTR args[] = {
843 (IPTR) idn->Name,
844 (IPTR) GetStrFromCat(MOUNTEDSTR, "[Mounted]")};
845 // idn->Task ? GetStrFromCat(MOUNTEDSTR, "[Mounted]") : ""); TODO
846 VLPrintf(VOLNAMEFMTSTR, nfmtstr, args);
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 IPTR args[] = {(IPTR) StrDay, (IPTR) StrDate, (IPTR) StrTime};
886 VLPrintf(DATEFMTSTR, "created %.3s, %-10s %s", args);
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;