Added memory-stored debug output to safe mode.
[cake.git] / workbench / c / Info.c
blobfe1e352217e81b8bc634d607144fc8bd1dcb9d9d
1 /*
2 Copyright © 1995-2008, 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
22 Sys:C
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_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 */
123 /* Prototypes */
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);
128 void doInfo();
131 const TEXT VersionStr[] = "$VER: Info 41.1 (16.11.2000)";
133 struct Catalog *cat;
134 struct Locale *loc = NULL;
135 ULONG MaxLen;
137 APTR Pool;
140 /* catalog string id:s */
141 enum
143 UNIT,
144 DEVTITLE,
145 DISKSTITLE,
146 DEVFMTSTR,
147 DATEFMTSTR,
148 READONLY,
149 READWRITE,
150 VALIDATING,
151 MOUNTEDSTR,
152 SMALLNUMFMT,
153 BIGNUMFMT,
154 VOLNAMEFMTSTR,
155 BLOCKSSTR
159 struct InfoDosNode
161 struct InfoDosNode *Next;
162 ULONG IsVolume;
163 ULONG DosType;
164 struct MsgPort *Task;
165 struct DateStamp VolumeDate;
166 TEXT Name[108];
169 struct InfoDosNode *head = NULL;
172 struct DiskTypeList
173 { ULONG id;
174 STRPTR str;
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" },
207 { 0L, 0L }
211 /****************************************************************************/
213 int UtilityBase_version = 0;
214 int LocaleBase_version = 0;
216 int __nocommandline;
218 int main(void)
220 static struct TagItem loctags[] = { { OC_Version, 1 },
221 { TAG_END , 0 } };
222 cat = OpenCatalogA(NULL, "info_com.catalog", loctags);
223 loc = OpenLocale(NULL);
225 D(bug("Calling doInfo()\n"));
227 doInfo();
229 CloseLocale(loc);
230 CloseCatalog(cat);
232 return RETURN_OK; /* TODO: Fix this */
236 CONST_STRPTR GetStrFromCat(ULONG id, CONST_STRPTR def)
238 if(cat != NULL)
240 def = GetCatalogStr(cat, id, def);
243 return 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)
256 if(*array != NULL)
258 while(*array != NULL)
260 UBYTE matchstr[128];
261 UBYTE name[32];
262 UBYTE *p = *array++;
263 UBYTE len = strlen(p);
265 if(p[len - 1] != ':')
267 CopyMem(p, name, len);
268 name[len] = ':';
269 name[len + 1] = 0;
270 p = name;
273 if(ParsePatternNoCase(p, matchstr, sizeof(matchstr)) != -1)
275 if(MatchPatternNoCase(matchstr, str))
277 return TRUE;
282 return FALSE;
285 return TRUE;
289 BOOL ScanDosList(STRPTR *filter)
291 struct InfoDosNode *idn = 0L;
292 struct DosList *ndl, *dl;
293 STRPTR *strray = NULL, dummy = NULL;
294 BOOL err = FALSE;
296 D(bug("Entered ScanDosList()\n"));
298 if (filter == NULL) filter = &dummy;
300 if(*filter != NULL)
302 strray = AllocPooled(Pool, sizeof(STRPTR)*MAX_MULTIARGS);
304 if(strray != NULL)
306 STRPTR *p = filter;
307 LONG i = 0;
309 while(*p)
310 strray[i++] = *p++;
312 while(i < MAX_MULTIARGS)
313 strray[i++] = NULL;
315 else
316 return FALSE;
319 /* lock list of devices & vols */
320 dl = ndl = LockDosList(LDF_ASSIGNS | LDF_VOLUMES | LDF_DEVICES | LDF_READ);
322 if(strray != NULL)
324 STRPTR *p = strray;
326 while(*p)
327 p++;
329 while((ndl = NextDosEntry(ndl, LDF_ASSIGNS | LDF_VOLUMES | LDF_READ)) != NULL)
331 TEXT name[108];
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)))
338 continue;
341 switch (ndl->dol_Type)
343 case DLT_VOLUME:
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));
347 break;
349 case DLT_DIRECTORY:
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));
358 while(al != NULL)
360 *p++ = ""; // TODO!!! ((struct Task *)((struct FileLock *)BADDR(al->al_Lock))->fl_Task->mp_SigTask)->tc_Node.ln_Name;
361 al = al->al_Next;
364 break;
367 *p++ = taskName;
370 else
371 strray = filter;
373 ndl = dl;
375 while((ndl = NextDosEntry(ndl, LDF_VOLUMES | LDF_DEVICES | LDF_READ)) != NULL)
377 UBYTE len = 0;
378 UBYTE type = ndl->dol_Type;
379 UBYTE name[108];
381 // if(((type == DLT_DEVICE))) // && (!ndl->dol_Task) TODO Check this!
382 // continue;
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))
390 int i;
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]));
399 continue;
402 idn = (struct InfoDosNode *)AllocPooled(Pool, sizeof(struct InfoDosNode));
404 if(idn == NULL)
406 err = TRUE;
407 break;
410 // idn->Task = (struct MsgPort *)ndl->dol_Task;
411 idn->IsVolume = type == DLT_VOLUME;
413 while((idn->Name[len] = name[len]))
414 len++;
416 if(type == DLT_VOLUME)
418 idn->VolumeDate = ((struct DeviceList *)ndl)->dl_VolumeDate;
419 idn->Name[len - 1] = '\0'; /* remove ':' */
421 else
423 BPTR ptr = BADDR(ndl->dol_misc.dol_handler.dol_Startup);
424 struct FileSysStartupMsg *fssm = (struct FileSysStartupMsg *)ptr;
426 idn->DosType = ID_DOS_DISK;
428 // DLT_DEVICE
429 if (len > MaxLen)
430 MaxLen = len;
432 if (fssm)
434 struct DosEnvec *de;
435 de = (struct DosEnvec *)BADDR(fssm->fssm_Environ);
437 if (de && (de->de_TableSize & 0xffffff00) == 0)
438 if (de->de_DosType)
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))
450 prev = work;
451 work = work->Next;
454 if(prev != NULL)
455 prev->Next = idn;
456 else
457 head = idn;
459 idn->Next = work;
463 /* unlock list of devices and volumes */
464 UnLockDosList(LDF_ASSIGNS | LDF_VOLUMES | LDF_DEVICES | LDF_READ);
466 // strray freed at DeletePool
468 return !err;
472 void PrintNum(ULONG num)
474 /* MBytes ? */
475 if(num > 1023)
477 ULONG x, xx;
478 char fmt = 'M';
480 /* GBytes ? */
481 if(num > 0xfffff)
483 num >>= 10;
484 fmt = 'G';
487 num = ExtUDivMod32(UMult32(num, 100) >> 10, 100, &x);
489 /* round */
490 x = ExtUDivMod32(x, 10, &xx);
492 if(xx > 4)
494 if(++x > 9)
496 x = 0;
497 num++;
501 IPTR args[] = {num, x, fmt};
502 VLPrintf(BIGNUMFMT, "%5ld.%ld%lc", args);
504 else
506 VLPrintf(SMALLNUMFMT, "%7ldK", (IPTR*) &num);
511 STRPTR GetFSysStr(ULONG DiskType)
513 struct DiskTypeList *dtlptr = dtl;
515 STRPTR ptr = NULL;
517 do {
518 if(dtlptr->id == DiskType)
520 ptr = dtlptr->str;
521 break;
523 } while(*((ULONG *)dtlptr++));
525 if(ptr == NULL)
527 static TEXT buffer[5];
529 ptr = (STRPTR)buffer;
530 *((ULONG *)ptr) = AROS_LONG2BE(DiskType);
532 if(ptr[3] < ' ')
533 ptr[3] += '0';
535 ptr[4] = '\0';
538 return ptr;
542 enum
544 ARG_DISKS,
545 ARG_VOLS,
546 ARG_ALL,
547 ARG_BLOCKS,
548 ARG_DEVS,
549 NOOFARGS
553 void doInfo()
555 struct RDArgs *rdargs;
556 struct Process *proc;
557 struct Window *win;
558 struct InfoDosNode *idn;
560 static struct InfoData id;
562 IPTR args[] = { (IPTR)FALSE,
563 (IPTR)FALSE,
564 (IPTR)FALSE,
565 (IPTR)FALSE,
566 (IPTR)NULL };
568 CONST_STRPTR unit = GetStrFromCat(UNIT, "Unit");
570 Pool = CreatePool(MEMF_ANY, 1024, 1024);
572 if(Pool == NULL)
574 PrintFault(ERROR_NO_FREE_STORE, NULL);
575 return; /* ??? */
578 D(bug("Calling ReadArgs()\n"));
580 /* read arguments */
581 rdargs = ReadArgs("DISKS/S,VOLS=VOLUMES/S,ALL/S,BLOCKS/S,DEVICES/M",
582 args, NULL);
584 if(rdargs != NULL)
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)
597 vols = TRUE;
598 disks = TRUE;
601 /* check pattern strings */
603 if(devs != NULL)
605 STRPTR *p = devs;
607 while(*p != NULL)
609 TEXT matchstr[128];
611 if(ParsePatternNoCase(*p, matchstr, sizeof(matchstr)) == -1)
613 PrintFault(IoErr(), *p);
614 goto end;
617 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"));
630 /* scan doslist */
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;
637 BOOL first = TRUE;
638 TEXT nfmtstr[16];
639 TEXT buf[64];
641 D(bug("Printing stuff\n"));
643 /* get datetimefmt string */
644 if(loc && (GetVar("info_datetime", buf, sizeof(buf), 0L) > 0L))
646 datetimeFmt = buf;
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)
657 BPTR lock;
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 */
665 if(first || blocks)
667 if(!first)
668 Printf("\n");
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);
675 first = FALSE;
678 D(bug("Locking \"%s\"\n", name));
679 lock = Lock(name, SHARED_LOCK);
681 D(bug("Lock = %p\n", lock));
683 if(lock != NULL)
685 D(bug("Got lock on %s\n", name));
687 if(Info(lock, &id) == DOSTRUE)
689 ULONG x, y;
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);
698 PrintNum(x);
699 PrintNum(y);
700 PrintNum(x - y);
702 D(bug("Calling NameFromLock()\n"));
704 if(NameFromLock(lock, name, 108L))
706 LONG len = strlen(name) - 1;
708 if(name[len] == ':')
710 name[len] = '\0';
714 if(x > 0xfffff)
716 x >>= 10;
717 y >>= 10;
720 if(x)
722 x = ExtUDivMod32(UDivMod32(UMult32(y, 1000), x), 10, &y);
724 if(y > 4)
725 x++;
727 else
728 x = 0;
730 // y = ((struct DeviceList *)BADDR(id.id_VolumeNode))->dl_DiskType;
732 // if(!y)
733 y = id.id_DiskType;
735 if((idn->DosType & ID_DOS_DISK) != ID_DOS_DISK)
736 y = idn->DosType;
738 IPTR args[] = {
740 id.id_NumSoftErrors,
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),
744 (IPTR) name};
745 VLPrintf(DEVFMTSTR, "%4ld%% %4ld %-11s%-8s%s\n", args);
747 if(blocks)
749 IPTR args[] = {
750 id.id_NumBlocks,
751 id.id_NumBlocksUsed,
752 id.id_NumBlocks-id.id_NumBlocksUsed,
753 id.id_BytesPerBlock};
754 VLPrintf(BLOCKSSTR,
755 "\nTotal blocks: %-10ld Blocks used: %ld\n"
756 " Blocks free: %-10ld Blocksize: %ld\n",
757 args);
760 else
761 D(bug("Info failure\n"));
763 UnLock(lock);
767 LONG err = IoErr();
769 if((err != 0) && showall)
771 VLPrintf(~0, nfmtstr, (IPTR*) &name);
772 PrintFault(err, NULL);
779 /* show volumes */
780 if(vols || (!devs && !disks))
782 if(!first)
783 PutStr("\n");
785 VLPrintf(DISKSTITLE, "Volumes\n", NULL);
787 for(MaxLen = 15, idn = head; idn; idn = idn->Next)
789 if(idn->IsVolume)
791 LONG len = strlen(idn->Name);
793 if(len > MaxLen)
794 MaxLen = len;
798 __sprintf(nfmtstr, "%%-%lds%%-10s", MaxLen+1);
800 for(idn = head; idn; idn = idn->Next)
802 if(idn->IsVolume)
804 IPTR args[] = {
805 (IPTR) idn->Name,
806 (IPTR) GetStrFromCat(MOUNTEDSTR, "[Mounted]")};
807 // idn->Task ? GetStrFromCat(MOUNTEDSTR, "[Mounted]") : ""); TODO
808 VLPrintf(VOLNAMEFMTSTR, nfmtstr, args);
810 if(datetimeFmt)
812 UBYTE datestr[128];
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);
822 PutStr(datestr);
824 else
826 TEXT StrDay[LEN_DATSTRING];
827 TEXT StrDate[LEN_DATSTRING];
828 TEXT StrTime[LEN_DATSTRING];
830 struct DateTime dt;
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;
839 if(DateToStr(&dt))
841 if(Strnicmp(StrDate, StrDay, strlen(StrDay)) == 0)
843 dt.dat_Flags = 0L;
844 DateToStr(&dt);
847 IPTR args[] = {(IPTR) StrDay, (IPTR) StrDate, (IPTR) StrTime};
848 VLPrintf(DATEFMTSTR, "created %.3s, %-10s %s", args);
852 PutStr("\n");
857 else
859 PrintFault( ERROR_NO_FREE_STORE, NULL);
862 /* reset window pointer of our process */
863 proc->pr_WindowPtr = win;
865 /* free args */
866 FreeArgs(rdargs);
870 end: /* free allocated memory */
872 DeletePool(Pool);
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)
895 *mod = a % b;
897 return a/b;