chris@genly.UUCP (Chris Hind Genly) (11/19/90)
I posted a message a few days ago asking how to determine what disk devices are on a system. This is the kind of problem you need to solve if you're writing a file requester and want to put up buttons with disk device names on them. I received one answer. I was pointed towards the fish disk with the info command. I thought I'd post the results since I imagine there are readers that would be interested. The info replacement walked through the dos device list looking for a device with an associated task. There is a comment in the info source to the effect that only disks will have an associated task. I don't think this is correct. It appears that disk devices have a task, but other devices do too. The info replacement shows all the disks on my system plus null:. The Commodore info command doesn't show null:. I have a good solution now. The magic I needed came from the info replacement command. It showed me how to suppress requesters. The requester is suppressed by setting the window pointer in the process structure to 0. Once a device is found with a non-zero task entry, it can be tested to see if it is really a disk device by trying to lock it. If you can lock it, its a disk. If you can't it still might be a disk. If its df0: for example and there is no disk in df0: I don't want a requester to pop up, so I suppress them. If there's no disk, the lock operation will fail. If the device is a disk device the lock will fail with an error such as: ERROR_NO_DISK. This tells me the device is a disk device. Here is my current solution. You are free to do with the code as you wish. static void FindDiskNames( char *DiskNames[], int DiskNamesMax ) { extern struct DosLibrary *DOSBase; struct RootNode *RootNode; struct DosInfo *DosInfo; struct DosList *Device, *Devices; struct Process *Process; char *DiskName, *t; APTR OldWindow; char *Name; int ADisk; BPTR lk; int i; DiskNames[0] = 0; if (DOSBase == 0) return; RootNode = (struct RootNode *)DOSBase->dl_Root; DosInfo = (struct DosInfo *)BADDR(RootNode->rn_Info); Devices = (struct DosList *)BADDR(DosInfo->di_DevInfo); for(Device = Devices; Device; Device = (struct DosList *)BADDR(Device->dol_Next)) { /* Look for a device, not a volume */ if (Device->dol_Type != 0) continue; /* A disk device has a task associated with it */ if (Device->dol_Task == 0) continue; /* Get the device name */ Name = (char *)BADDR(Device->dol_Name); Name++; /* Make a copy with a colon at the end */ DiskName = smalloc(strlen(Name)+2); strcpy(DiskName, Name); strcat(DiskName, ":"); /* Disable requesters in case there's no disk present */ Process = (struct Process *) FindTask(NULL); OldWindow = Process->pr_WindowPtr; Process->pr_WindowPtr = (APTR) -1; /* Attempt to create a lock to verify that its a disk */ lk = Lock(DiskName, ACCESS_READ); if (lk) UnLock(lk); ADisk = lk != 0 || IoErr() == ERROR_NOT_A_DOS_DISK || IoErr() == ERROR_NO_DISK; /* Allow requesters */ Process->pr_WindowPtr = OldWindow; /* If its a disk, add it to the list of disk names */ if (ADisk) { for(i=0; i<DiskNamesMax; ++i) { if (DiskNames[i] == 0) break; if (stricmp(DiskName, DiskNames[i]) < 0) break; } for(; i<DiskNamesMax; ++i) { t = DiskNames[i]; if (t == 0 && i == DiskNamesMax-1) { sfree(DiskName); break; } else { DiskNames[i] = DiskName; if (DiskName == 0) break; DiskName = t; } } } else sfree(DiskName); } } sfree(), sstrdup(), and smalloc() are strict versions of free(), strdup(), and malloc(). In addition to performing their normal function they check the integrity of the memory pool. * * * \|/ * _______ --O-- ____/ KC1VP \____ * /|\ * ______/ (203) 389-8680 \______ ______/ Eggplant Software Tools \________ ______/ 95 Fountain Terr., New Haven, CT, USA, 06515 \_______ / Chris Hind Genly chris@genly.uucp uunet!hsi!genly!chris \ ----------------------------------------------------------------
ridder@elvira.enet.dec.com (Hans Ridder) (11/20/90)
In article <chris.11172988@genly.UUCP> chris@genly.UUCP (Chris Hind Genly) writes: >I posted a message a few days ago asking how to determine what disk >devices are on a system. This is the kind of problem you need to >solve if you're writing a file requester and want to put up buttons >with disk device names on them. >The info replacement walked through the dos device list looking for a >device with an associated task. >Once a device is found with a non-zero task entry, it can be tested to >see if it is really a disk device by trying to lock it. If you can >lock it, its a disk. I don't think it's a good idea to write code which depends on side effects like this. (Unless it's written down somewhere that only "disk devices" know how to Lock() -- I've never seen it.) As you pointed out, the Info replacment depended on the perceived effect that only devices have tasks, which later turned out to be wrong. There's always a danger in depending on undocumented side effects. IMHO, requesters should list *volumes*, not *devices*. Volume names are (or can be) much more descriptive to users than are names like "DH0" or "DF1". If device names are used, the user might have to click on every button to find a file, if the right disk is even in a drive. Devices (i.e. disk drives) don't have files on them, volumes do. Notice that the Workbench uses volume names, not devices names. It'll be much easier for the user to find the desired file if the names shown on the requester are consistent with the names he/she just saw on the Workbench screen. It's also much easier to find volumes in the device list. -hans ------------------------------------------------------------------------ Hans-Gabriel Ridder Digital Equipment Corporation ridder@elvira.enet.dec.com Customer Support Center ...decwrl!elvira.enet!ridder Colorado Springs, CO
ggk@tirith.UUCP (Gregory Kritsch) (11/21/20)
chris@genly.UUCP (Chris Hind Genly) writes: >Once a device is found with a non-zero task entry, it can be tested to >see if it is really a disk device by trying to lock it. If you can >lock it, its a disk. If you can't it still might be a disk. If its >df0: for example and there is no disk in df0: I don't want a requester >to pop up, so I suppress them. If there's no disk, the lock operation >will fail. If the device is a disk device the lock will fail with an >error such as: ERROR_NO_DISK. This tells me the device is a disk >device. >Here is my current solution. You are free to do with the code as you wish. >static >void >FindDiskNames( > char *DiskNames[], > int DiskNamesMax >) >{ > /* Look for a device, not a volume */ > if (Device->dol_Type != 0) > continue; Hmm, so you assume that there is a device for every volume, which is not neccesarily the case. Case in point, my network file system from last year. It created only volume nodes for network volumes, the idea of trying to dynamically allocate device names scared me, and didn't seem very logical either (there was an ND0: entry used basically to find the handler, it only supported certain custom packets though). I wasn't aware at that time that it would break a good number of file requesters, as well as some Workbench replacement type programs that assumed device entries as well. > /* A disk device has a task associated with it */ > if (Device->dol_Task == 0) > continue; > /* Get the device name */ > Name = (char *)BADDR(Device->dol_Name); > Name++; > > /* Make a copy with a colon at the end */ > DiskName = smalloc(strlen(Name)+2); > strcpy(DiskName, Name); > strcat(DiskName, ":"); > > /* Disable requesters in case there's no disk present */ > Process = (struct Process *) FindTask(NULL); > OldWindow = Process->pr_WindowPtr; > Process->pr_WindowPtr = (APTR) -1; > > /* Attempt to create a lock to verify that its a disk */ > lk = Lock(DiskName, ACCESS_READ); > if (lk) UnLock(lk); > ADisk = lk != 0 > || IoErr() == ERROR_NOT_A_DOS_DISK > || IoErr() == ERROR_NO_DISK; Two thoughts here: It might be more prudent to send the packet directly to the file process, rather than go through all the mumbo jumbo converting the BSTR and adding the colon and so on. This also has the advantage of not having to play with pr_WindowPtr, since the dos requestor generator mechanism can't get in the way. Also, the test "IoErr() != ERROR_ACTION_NOT_KNOWN" might be better - all disk handlers will understand ACTION_LOCK, but almost all non-disk handlers won't understand it (and should return ERROR_ACTION_NOT_KNOWN). >/ Chris Hind Genly chris@genly.uucp uunet!hsi!genly!chris \ -- Gregory Kritsch | University of Waterloo Fido: 1:221/208.11110 [1:163/109.30] | 1A Computer Engineering OCUG: ggk@tirith.ocug.on.ca |---------------------------- UUCP: ggk@tirith.UUCP | The University doesn't get ...!watmath!xenitec!tirith!ggk | a chance to censor me!