[Contents] [Index] [Help] [Retrace] [Browse <] [Browse >]

Handling Multiple Assigns with Conventional Directories

Staff


One of the features introduced by Release 2 is Multiple Assigning. This
feature allows an AmigaDOS assign to carry over several directories which can
be on different volumes. This makes it possible to split up assigns such as
libs: and fonts:.

The article ``Directory Scanning'' on page II-49 contains an example called
find.c that illustrates scanning a path that can contain a multiassign.
However, besides being rather complicated, find.c makes a special case of
scanning assigns, which isn't necessary (find.c also did something
evil--find.c uses DOSBase's private pointer to the utility.library,
essentially using the utility.library without opening it). The method needed
to scan a multiassign directory also works on conventional directories.

Scanning a multiassign requires calling the dos.library function
GetDeviceProc() in a loop to see each directory of the multiassign. Using
GetDeviceProc(), the application doesn't have to concern itself with the
differences between assigns, multiassigns, and volumes. The application just
keeps calling GetDeviceProc() until it gets back a NULL.

struct DevProc *GetDeviceProc( STRPTR name, struct DevProc *dp );

The name can be any valid dos path. If there is a device name present,
GetDeviceProc() will find the device's entry in the dos list and copy some
information into a DevProc structure:

struct DevProc {
    struct MsgPort *dvp_Port;   /* Device's Message port, also called a Process identifier */
    BPTR            dvp_Lock;   /* Lock on root of assign or lock on root of volume */
    ULONG           dvp_Flags;
    struct DosList *dvp_DevNode;/* DON'T TOUCH OR USE! */
};

The important fields here are dvp_Lock and dvp_Port. The dvp_Lock field is a
lock on the root of the object named in GetDeviceProc(). It serves as a
starting point in locating the named object. If the object name contains an
assign (i.e. ``libs:''), dvp_Lock is the root of the assign. For example, on a
typical Release 2 system, the libs: assign refers to the libs directory on the
System2.0: volume. Calling GetDeviceProc() on ``libs:'' in this case will
yield a lock on System2.0:libs.

If the named object contains a dos volume, dvp_Lock is either a lock on the
root of the dos volume or NULL. If the object named in GetDeviceProc()
contains a non-filesystem device (i.e., ``ser:'', ``par:'', ``prt:'', etc.) or
it does not contain a device name, dvp_Lock is NULL.

The dvp_Port field points to a message port. This message port is connected to
the handler process of a DOS device. The handler process controls a DOS
device. DOS functions (like the Lock() function) use this message port to talk
to the handler process of the named object. For example, from the ``libs:''
example above, the dvp_Port field refers to the message port of the handler
process for the System2.0: volume.

Note that dvp_Lock is only a lock on the root of the named object. If the
named object is a path several directories deep (for example,
libs:gadgets/colorwheel.gadget), it's up to the application to handle the rest
of the path. The application also has to handle the case where the named
object is a path without a device name.

Although an application can send DOS packets directly to the message port
(dvp_Port) of a handler process, normally it is easier to use functions from
dos.library. The multilist.c example uses the Lock() function to lock the
named object. Multilist has to do something a little unorthodox to use Lock().
Lock() accepts a path name to the object to lock. Lock() understands absolute
paths (i.e. paths with a logical device name like ``df1:'' or ``libs:'') and
relative paths. If Lock() receives an absolute path name, Lock() can find the
device's handler process using the logical device name in the absolute path.
For a relative path, Lock() does not have enough information to find the named
object, so it assumes the path is relative to the current directory and file
system (each process has a current directory and file system).

This makes Lock() a little more difficult to use in multilist.c because, when
processing an absolute path, multilist has to process the logical device name
separately from the rest of the path. It has to use GetDeviceProc() to find
the root of a logical device name (which can be an assign, multiassign, volume
name, etc.) then it has to strip the logical device name from the absolute
path. Without a logical device name, the path has become relative rather than
absolute. The path is now relative to dvp_Lock and dvp_Port. In order for
Lock() to work with this relative path, multilist must temporarily set the
current directory and file system to the values in dvp_Lock and dvp_Port,
respectively.

Note that the Autodoc for GetDeviceProc() says to check IoErr() for
ERROR_NO_MORE_ENTRIES after receiving a NULL from GetDeviceProc(). Due to a
bug, DOS does not set the error value correctly. Also note that the Autodoc
says to check the DevProc structure's dvp_Flags field for the DVPF_ASSIGN
flag. This was necessary in the 2.00 and 2.01 releases of the operating system
due to a bug in DOS, but is no longer necessary.

The following example, multilist.c, accepts an arbitrary path name and lists
the contents of it. The function DoAllAssigns() does all of the multiassign
work. DoAllAssigns() accepts a path and a function pointer. It gets a lock on
the object named in the path, and passes the lock to the function. This
example is based on a Usenet posting by Randell Jesup.

 multilist.c