/* GETDIR.C - Does some simple lock and device-list manipulation * * Copywrite (c) 1987 by Davide P. Cervone * This code may be used so long as this copywrite notice is left in tact. */ #include "exec/types.h" #include "exec/memory.h" #include "libraries/dos.h" #include "libraries/dosextens.h" #define BCPL(x,y) ((struct x *)(BADDR(y))) #define BCPL_TO_CHAR(y) ((char *)(BADDR(y))) #define FILELOCK(x) BCPL(FileLock,x) #define DEVLIST(x) BCPL(DeviceList,x) #define FIBSIZE ((ULONG)sizeof(struct FileInfoBlock)) #define RETURN(dir) return((*dir == '\0')? NULL: dir) /* * BSTRcopy() * * Copies a BCPL string into a C string and returns the length of the * string. */ BSTRcpy(to,BCPLfrom) char *to, *BCPLfrom; { char *from = BCPL_TO_CHAR(BCPLfrom); strncpy(to,from+1,(int)(*from)); *(to+(*from)) = '\0'; return((int) *from); } /* * GetPathFromLock() * * GetPathFromLock looks up the path name to the file or directory specified * by the lock. The volume name is included in the returned string. * If an error occurs, the function returns NULL, and the path name is set * to an empty string (a null byte). The lock remains intact (it is not * UnLocked). * * dir a pointer to a string area where the path name * will be stored. No check is made to be sure that * the path name fits. * lock a lock on the file or directory whose path is to * be found. * * Note: there seems to be a problem with the RAM: device (AmigaDOS v1.1). * ParentDir() always returns NULL for a lock on the RAM-disk; Therefore, * GetPathFromLock() always returns "RAM:" for any lock on the RAM: device. * * Note: this function finds the complete path name to the locked object, * including the volume name. ASSIGNed names will be translated to their * physical names. For instance, if you CD to the C: directory, and * C: is ASSIGNed as SYS:C, and SYS: is ASSIGNed as your boot disk, and * your boot disk is named "WorkBench", then if you call GetPathFromLock() * with a lock in the C: directory, you will get back the string * "WorkBench:c", not "C:". */ char *GetPathFromLock(dir,lock) char *dir; struct FileLock *lock; { struct FileLock *CurDir, *OldDir, *DupLock(), *ParentDir(); struct FileInfoBlock *fib, *AllocMem(); char *subdir = dir, *s, *s1, c; int len; /* * Clear the path name, and duplicate the lock (so we can UnLock our * duplicate without destroying the user's lock). If DupLock returned * NULL, then there was an error. (An exclusive write lock, perhaps?) */ *dir = '\0'; CurDir = DupLock(lock); if (CurDir == NULL) return(NULL); /* * the FileInfoBlock must be longword alligned, so use AllocMem */ fib = AllocMem(FIBSIZE,MEMF_CLEAR | MEMF_PUBLIC); if (fib != NULL) { /* * Get the device name from the volume entry in the device list * that is pointed to by the file lock. Since the device list is * a shared list, use Forbid() and Permit() so it doesn't change while * we are looking at it. Add a colon, and set the subdir pointer to * the character following the volume name. Subdirectory names will be * added starting there. */ Forbid(); subdir += BSTRcpy(dir,DEVLIST(FILELOCK(CurDir)->fl_Volume)->dl_Name); Permit(); *subdir++ = ':'; *subdir = '\0'; /* * While we have a valid lock (ParentDir() will return a NULL pointer * when we reach the root of the disk), examine the directory (or file) * that we have locked. If we can't examine it, give an error, otherwise * move up to the parent dir and unlock the old directory lock. If we haven't * moved up past the root, then we want to add the directory name (found * in the FileInfoBlock structure returned by Examine()) to the path name. * To do so, we shift any existing sub-directory names to the right leaving * enough room for the new directory name (plus a slash, if needed). * * Note: the highest directory on a disk (the root), seems to have the same * name as the disk itself (look at the ASSIGN list, for instance), so * ParentDir() does not return NULL until we move past the root, that's why * the ParentDir() call comes before we add the directory name into the * string. * * For instance, if the current directory is "disk:a/b/c/d", and * the CurDir lock is on "d", then the calls to ParentDir() will * produce locks on "c", "b", "a", "disk", and then NULL. */ while (CurDir != NULL) { if (!Examine(CurDir,fib)) { *dir = '\0'; UnLock(CurDir); CurDir = NULL; } else { OldDir = CurDir; CurDir = ParentDir(OldDir); UnLock(OldDir); if (CurDir != NULL) { len = strlen(fib->fib_FileName); for (s=subdir+strlen(subdir), s1=s+len+1; s >= subdir; *s1-- = *s--); c = *subdir; strcpy(subdir,fib->fib_FileName); *s1 = (c != '\0')? '/': c; } } } FreeMem(fib,FIBSIZE); } RETURN(dir); } /* * GetInfoVolume() * * GetInfoVolume looks up the volume name from an InfoData structure and * returns a C string containing the name. * * name a pointer to a string area where the volume name * will be stored. No check is made to be sure that * the name fits. * info an InfoData structure that has been filed in by a call * to Info(). * */ void GetInfoVolume(name,info) char *name; struct InfoData *info; { /* * Get the device name from the volume entry in the device list * that is pointed to by the InfoData. Since the device list is * a shared list, use Forbid() and Permit() so it doesn't change while * we are looking at it. Add a colon for looks. */ Forbid(); name += BSTRcpy(name,DEVLIST(info->id_VolumeNode)->dl_Name); Permit(); *name++ = ':'; *name = '\0'; }