From 292d27556238d4b2e970d020d8e6251f54e5cf34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rob=20N=20=E2=98=85?= Date: Fri, 23 Apr 2021 23:08:01 +1000 Subject: [PATCH 1/8] dos: add LockRelative With a little shuffling of shared functions --- developer/debug/test/dos/lockrelative.c | 41 +++ developer/debug/test/dos/mmakefile.src | 1 + rom/dos/dos.conf | 2 + rom/dos/dos_intern.h | 1 - rom/dos/lock.c | 296 +------------------- rom/dos/lockrelative.c | 343 ++++++++++++++++++++++++ rom/dos/mmakefile.src | 2 +- rom/dos/open.c | 13 + 8 files changed, 402 insertions(+), 297 deletions(-) create mode 100644 developer/debug/test/dos/lockrelative.c create mode 100644 rom/dos/lockrelative.c diff --git a/developer/debug/test/dos/lockrelative.c b/developer/debug/test/dos/lockrelative.c new file mode 100644 index 00000000000..0404790e2f3 --- /dev/null +++ b/developer/debug/test/dos/lockrelative.c @@ -0,0 +1,41 @@ +/* + Copyright (C) 1995-2021, The AROS Development Team. All rights reserved. +*/ + +#include +#include + +int main (int argc, char **argv) { + if (argc < 3) { + printf("usage: lockrelative \n"); + return 1; + } + + BPTR baselock = Lock(argv[1], ACCESS_READ); + if (baselock == BNULL) { + PrintFault(IoErr(), "lockrelative: base lock"); + return 1; + } + + BPTR filelock = LockRelative(baselock, argv[2], ACCESS_READ); + if (filelock == BNULL) { + PrintFault(IoErr(), "lockrelative: file lock"); + UnLock(baselock); + return 1; + } + + char path[256]; + if (NameFromLock(filelock, path, sizeof(path)) == 0) { + PrintFault(IoErr(), "lockrelative: name from lock"); + UnLock(filelock); + UnLock(baselock); + return 1; + } + + printf("%s\n", path); + + UnLock(filelock); + UnLock(baselock); + return 0; +} + diff --git a/developer/debug/test/dos/mmakefile.src b/developer/debug/test/dos/mmakefile.src index bd766940a6a..9c4e43b63a8 100644 --- a/developer/debug/test/dos/mmakefile.src +++ b/developer/debug/test/dos/mmakefile.src @@ -22,6 +22,7 @@ FILES := \ getenv \ inhibit \ isinteractive \ + lockrelative \ match \ matchtest \ minicat \ diff --git a/rom/dos/dos.conf b/rom/dos/dos.conf index 08bb4ad7c1b..c3f6c29c2c2 100644 --- a/rom/dos/dos.conf +++ b/rom/dos/dos.conf @@ -255,4 +255,6 @@ LONG ScanVars(struct Hook * hook, ULONG flags, APTR userdata) (D1,D2,D3) LONG GetSegListInfo(BPTR seglist, const struct TagItem *taglist) (D0, A0) .skip 29 BOOL AssignAddToList(CONST_STRPTR name, BPTR lock, ULONG position) (D1, D2, D3) +# AROS-specific +BPTR LockRelative(BPTR lock, CONST_STRPTR name, LONG accessMode) (D1,D2,D3) ##end functionlist diff --git a/rom/dos/dos_intern.h b/rom/dos/dos_intern.h index ad7ec22a065..56dedc527a4 100644 --- a/rom/dos/dos_intern.h +++ b/rom/dos/dos_intern.h @@ -96,7 +96,6 @@ struct vfp /* Softlink handling */ STRPTR ResolveSoftlink(BPTR cur, struct DevProc *dvp, CONST_STRPTR name, struct DosLibrary *DOSBase); -LONG RootDir(struct DevProc *dvp, struct DosLibrary *DOSBase); /* Packet I/O */ struct DosPacket *allocdospacket(void); diff --git a/rom/dos/lock.c b/rom/dos/lock.c index b9f4979b939..1ef3703d587 100644 --- a/rom/dos/lock.c +++ b/rom/dos/lock.c @@ -4,24 +4,7 @@ Desc: Locks a file or directory. */ -#define DLINK(x) - -#include -#include -#include -#include -#include -#include - -#include - #include "dos_intern.h" -#include "fs_driver.h" - -static LONG InternalLock(CONST_STRPTR name, LONG accessMode, - BPTR *handle, LONG soft_nesting, struct DosLibrary *DOSBase); - -#define MAX_SOFT_LINK_NESTING 16 /* Maximum level of soft links nesting */ /***************************************************************************** @@ -61,284 +44,7 @@ static LONG InternalLock(CONST_STRPTR name, LONG accessMode, { AROS_LIBFUNC_INIT - BPTR fl; - - /* Sanity check */ - if (name == NULL) - return BNULL; - - ASSERT_VALID_PTR(name); - - D(bug("[Lock] '%s':%d\n", name, accessMode)); - - if (InternalLock(name, accessMode, &fl, MAX_SOFT_LINK_NESTING, DOSBase)) - { - D(bug("[Lock] returned 0x%p\n", fl)); - return fl; - } - - D(bug("[Lock] failed, err=%d\n", IoErr())); - return BNULL; + return LockRelative(NULL, name, accessMode); AROS_LIBFUNC_EXIT } /* Lock */ - - -/* Attempt to create a synthetic IN:, OUT:, ERR:, - * STDIN:, STDOUT, or STDERR: lock - */ -BOOL pseudoLock(CONST_STRPTR name, LONG lockMode, BPTR *lock, LONG *ret, struct DosLibrary *DOSBase) -{ - struct Process *me = (struct Process *)FindTask(NULL); - BPTR fh = (BPTR)-1; - - ASSERT_VALID_PROCESS(me); - - /* IN:, STDIN: */ - if (!Stricmp(name, "IN:") || !Stricmp(name, "STDIN:")) { - if (lockMode != ACCESS_READ) { - SetIoErr(ERROR_OBJECT_IN_USE); - *ret = DOSFALSE; - return TRUE; - } - - fh = me->pr_CIS; - } - - /* OUT:, STDOUT: */ - if (!Stricmp(name, "OUT:") || !Stricmp(name, "STDOUT:")) { - if (lockMode != ACCESS_WRITE) { - SetIoErr(ERROR_OBJECT_IN_USE); - *ret = DOSFALSE; - return TRUE; - } - - fh = me->pr_COS; - } - - - /* ERR:, STDERR: */ - if (!Stricmp(name, "ERR:") || !Stricmp(name, "STDERR:")) { - if (lockMode != ACCESS_WRITE) { - SetIoErr(ERROR_OBJECT_IN_USE); - *ret = DOSFALSE; - return TRUE; - } - - fh = me->pr_CES; - } - - if (fh == (BPTR)-1) - return FALSE; - - if (fh == BNULL) { - SetIoErr(ERROR_OBJECT_NOT_FOUND); - *ret = DOSFALSE; - return TRUE; - } - - *lock = DupLockFromFH(fh); - if (*lock) { - struct FileLock *fl = BADDR(*lock); - fl->fl_Access = lockMode; - } - *ret = (*lock != BNULL) ? DOSTRUE : DOSFALSE; - return TRUE; -} - - -/* Try to lock name recursively calling itself in case it's a soft link. - Store result in handle. Return boolean value indicating result. */ -static LONG InternalLock(CONST_STRPTR name, LONG accessMode, - BPTR *handle, LONG soft_nesting, struct DosLibrary *DOSBase) -{ - /* Get pointer to process structure */ - struct Process *me = (struct Process *)FindTask(NULL); - BPTR cur = BNULL; - struct DevProc *dvp = NULL; - LONG ret = DOSFALSE; - LONG error = 0; - STRPTR filename; - - ASSERT_VALID_PROCESS(me); - D(bug("[Lock] Process: 0x%p \"%s\", Window: 0x%p, Name: \"%s\", \n", me, me->pr_Task.tc_Node.ln_Name, me->pr_WindowPtr, name)); - - if(soft_nesting == 0) - { - SetIoErr(ERROR_TOO_MANY_LEVELS); - return DOSFALSE; - } - - /* Check for a pseudo-file lock - * (ie IN:, STDOUT:, ERR:, etc) - */ - if (pseudoLock(name, accessMode, handle, &ret, DOSBase)) - return ret; - - filename = strchr(name, ':'); - if (!filename) - { - struct MsgPort *port; - BPTR lock; - - /* No ':' in the pathname, path is relative to current directory */ - cur = me->pr_CurrentDir; - if (cur && cur != (BPTR)-1) { - port = ((struct FileLock *)BADDR(cur))->fl_Task; - lock = cur; - } else { - port = DOSBase->dl_Root->rn_BootProc; - lock = BNULL; - } - - error = fs_LocateObject(handle, port, lock, name, accessMode, DOSBase); - SetIoErr(error); - } - else - { - filename++; - do - { - if ((dvp = GetDeviceProc(name, dvp)) == NULL) - { - error = IoErr(); - break; - } - - error = fs_LocateObject(handle, dvp->dvp_Port, dvp->dvp_Lock, filename, accessMode, DOSBase); - - } while (error == ERROR_OBJECT_NOT_FOUND); - - if (error == ERROR_NO_MORE_ENTRIES) - error = me->pr_Result2 = ERROR_OBJECT_NOT_FOUND; - -#ifndef __mc68000 - /* FIXME: On Linux hosted we sometimes get ERROR_IS_SOFTLINK with dvp == NULL, - * which causes segfaults below if we don't change "error". Adding !dvp below - * is probably a hack. - * - * This is wrong, GetDeviceProc() can return other errors than ERROR_OBJECT_NOT_FOUND. - */ - if (!dvp) - error = me->pr_Result2 = ERROR_OBJECT_NOT_FOUND; -#endif - } - - if (error == ERROR_IS_SOFT_LINK) - { - STRPTR softname = ResolveSoftlink(cur, dvp, name, DOSBase); - - if (softname) - { - BPTR olddir = BNULL; - - /* - * ResolveSoftlink() gives us path relative to either 'cur' lock - * (if on current volume), or 'dvp' volume root (if on different volume). - * In the latter case we need to change current directory to volume's root - * in order to follow the link correctly. - */ - if (dvp) - { - olddir = me->pr_CurrentDir; - error = RootDir(dvp, DOSBase); - } - else - error = 0; - - if (!error) - { - ret = InternalLock(softname, accessMode, handle, soft_nesting - 1, DOSBase); - error = ret ? 0 : IoErr(); - D(bug("[Lock] Resolve error %d\n", error)); - - if (olddir) - UnLock(CurrentDir(olddir)); - } - - FreeVec(softname); - } - else - error = IoErr(); - } - - FreeDeviceProc(dvp); - - if (error) - { - SetIoErr(error); - ret = DOSFALSE; - } - else - ret = DOSTRUE; - - return ret; -} - -/* - * Resolve a softlink. - * Returns AllocVec()ed buffer with softlink contents. - */ -STRPTR ResolveSoftlink(BPTR cur, struct DevProc *dvp, CONST_STRPTR name, struct DosLibrary *DOSBase) -{ - ULONG buffer_size = 256; - STRPTR softname; - LONG continue_loop; - LONG written; - - DLINK(bug("[Softlink] Resolving softlink %s...\n", name)); - - do - { - continue_loop = FALSE; - - if (!(softname = AllocVec(buffer_size, MEMF_PUBLIC|MEMF_CLEAR))) - { - SetIoErr(ERROR_NO_FREE_STORE); - break; - } - - written = fs_ReadLink(cur, dvp, name, softname, buffer_size, DOSBase); - - switch (written) - { - case -1: - /* An error occured */ - DLINK(bug("[Softlink] Error %d reading softlink\n", IoErr())); - break; - - case -2: - /* If there's not enough space in the buffer, increase it and try again */ - continue_loop = TRUE; - buffer_size <<= 1; - - DLINK(bug("[Softlink] Increased buffer size up to %u\n", buffer_size)); - break; - - default: - /* All OK */ - DLINK(bug("[Softlink] Resolved path: %s\n", softname)); - return softname; - } - - FreeVec(softname); - } - while(continue_loop); - - return NULL; -} - -/* Change to root directory of the specified device */ -LONG RootDir(struct DevProc *dvp, struct DosLibrary *DOSBase) -{ - BPTR lock = BNULL; - LONG error; - - /* We already have a DeviceProc structure, so just use internal routine. */ - error = fs_LocateObject(&lock, dvp->dvp_Port, dvp->dvp_Lock, "", SHARED_LOCK, DOSBase); - - if (!error) - CurrentDir(lock); - - return error; -} diff --git a/rom/dos/lockrelative.c b/rom/dos/lockrelative.c new file mode 100644 index 00000000000..16a3e7ccb96 --- /dev/null +++ b/rom/dos/lockrelative.c @@ -0,0 +1,343 @@ +/* + Copyright (C) 1995-2021, The AROS Development Team. All rights reserved. + + Desc: Locks a file or directory. +*/ + +#define DLINK(x) + +#include +#include +#include +#include +#include +#include + +#include + +#include "dos_intern.h" +#include "fs_driver.h" + +static LONG InternalLockRelative( + BPTR baselock, + CONST_STRPTR name, + LONG accessMode, + BPTR *retlock, + LONG soft_nesting, + struct DosLibrary *DOSBase); + +#define MAX_SOFT_LINK_NESTING 16 /* Maximum level of soft links nesting */ + +/***************************************************************************** + + NAME */ +#include + + AROS_LH3(BPTR, LockRelative, + +/* SYNOPSIS */ + AROS_LHA(BPTR, lock, D1), + AROS_LHA(CONST_STRPTR, name, D2), + AROS_LHA(LONG, accessMode, D3), + +/* LOCATION */ + struct DosLibrary *, DOSBase, 227, Dos) + +/* FUNCTION + Gets a lock on a file or directory relative to another lock. If name is + absolute, lock is ignored. If name is relative and lock is NULL, the + current directory is used. Otherwise, the name is computed relative to + the given lock. + + There may be more than one shared lock on a file but only one if it is + an exclusive one Locked files or directories may not be deleted. + + INPUTS + lock - existing lock to compute filename from + name - NUL terminated name of the file or directory. + accessMode - One of SHARED_LOCK + EXCLUSIVE_LOCK + + RESULT + Handle to the file or directory or 0 if the object couldn't be locked. + IoErr() gives additional information in that case. + + NOTES + This call is AROS-specific. + +*****************************************************************************/ + +{ + AROS_LIBFUNC_INIT + + BPTR retlock; + + /* Sanity check */ + if (name == NULL) + return BNULL; + + ASSERT_VALID_PTR(name); + + D(bug("[LockRelative] baselock=0x%p name=%s mode=%d\n", lock, name, accessMode)); + + if (InternalLockRelative(lock, name, accessMode, &retlock, MAX_SOFT_LINK_NESTING, DOSBase)) + { + D(bug("[LockRelative] returned 0x%p\n", retlock)); + return retlock; + } + + D(bug("[LockRelative] failed, err=%d\n", IoErr())); + return BNULL; + + AROS_LIBFUNC_EXIT +} /* LockRelative */ + + +/* Attempt to create a synthetic IN:, OUT:, ERR:, + * STDIN:, STDOUT, or STDERR: lock + */ +BOOL pseudoLock(CONST_STRPTR name, LONG lockMode, BPTR *retlock, LONG *ret, struct DosLibrary *DOSBase) +{ + struct Process *me = (struct Process *)FindTask(NULL); + BPTR fh = (BPTR)-1; + + ASSERT_VALID_PROCESS(me); + + /* IN:, STDIN: */ + if (!Stricmp(name, "IN:") || !Stricmp(name, "STDIN:")) { + if (lockMode != ACCESS_READ) { + SetIoErr(ERROR_OBJECT_IN_USE); + *ret = DOSFALSE; + return TRUE; + } + + fh = me->pr_CIS; + } + + /* OUT:, STDOUT: */ + if (!Stricmp(name, "OUT:") || !Stricmp(name, "STDOUT:")) { + if (lockMode != ACCESS_WRITE) { + SetIoErr(ERROR_OBJECT_IN_USE); + *ret = DOSFALSE; + return TRUE; + } + + fh = me->pr_COS; + } + + + /* ERR:, STDERR: */ + if (!Stricmp(name, "ERR:") || !Stricmp(name, "STDERR:")) { + if (lockMode != ACCESS_WRITE) { + SetIoErr(ERROR_OBJECT_IN_USE); + *ret = DOSFALSE; + return TRUE; + } + + fh = me->pr_CES; + } + + if (fh == (BPTR)-1) + return FALSE; + + if (fh == BNULL) { + SetIoErr(ERROR_OBJECT_NOT_FOUND); + *ret = DOSFALSE; + return TRUE; + } + + *retlock = DupLockFromFH(fh); + if (*retlock) { + struct FileLock *fl = BADDR(*retlock); + fl->fl_Access = lockMode; + } + *ret = (*retlock != BNULL) ? DOSTRUE : DOSFALSE; + return TRUE; +} + + +/* Try to lock name recursively calling itself in case it's a soft link. + Store result in handle. Return boolean value indicating result. */ +static LONG InternalLockRelative( + BPTR baselock, + CONST_STRPTR name, + LONG accessMode, + BPTR *retlock, + LONG soft_nesting, + struct DosLibrary *DOSBase) +{ + /* Get pointer to process structure */ + struct Process *me = (struct Process *)FindTask(NULL); + BPTR lock = BNULL; + struct DevProc *dvp = NULL; + LONG ret = DOSFALSE; + LONG error = 0; + STRPTR filename; + + ASSERT_VALID_PROCESS(me); + D(bug("[LockRelative] Process: 0x%p \"%s\", Window: 0x%p, Name: \"%s\", \n", me, me->pr_Task.tc_Node.ln_Name, me->pr_WindowPtr, name)); + + if(soft_nesting == 0) + { + SetIoErr(ERROR_TOO_MANY_LEVELS); + return DOSFALSE; + } + + /* Check for a pseudo-file lock + * (ie IN:, STDOUT:, ERR:, etc) + */ + if (pseudoLock(name, accessMode, retlock, &ret, DOSBase)) + return ret; + + filename = strchr(name, ':'); + if (!filename) + { + /* No ':' in the pathname, path is relative */ + struct MsgPort *port; + + if (baselock) { + /* baselock provided; relative to it */ + port = ((struct FileLock *)BADDR(baselock))->fl_Task; + lock = baselock; + } + else { + /* no lock provided; relative to current directory */ + lock = me->pr_CurrentDir; + if (lock && lock != (BPTR)-1) { + port = ((struct FileLock *)BADDR(lock))->fl_Task; + } + else { + /* no current directory? go from the root */ + port = DOSBase->dl_Root->rn_BootProc; + lock = BNULL; + } + } + + error = fs_LocateObject(retlock, port, lock, name, accessMode, DOSBase); + } + else + { + /* absolute path; get the device and look it up against that */ + filename++; + do + { + if ((dvp = GetDeviceProc(name, dvp)) == NULL) + { + error = IoErr(); + break; + } + + error = fs_LocateObject(retlock, dvp->dvp_Port, dvp->dvp_Lock, filename, accessMode, DOSBase); + + } while (error == ERROR_OBJECT_NOT_FOUND); + + if (error == ERROR_NO_MORE_ENTRIES) + error = me->pr_Result2 = ERROR_OBJECT_NOT_FOUND; + +#ifndef __mc68000 + /* FIXME: On Linux hosted we sometimes get ERROR_IS_SOFTLINK with dvp == NULL, + * which causes segfaults below if we don't change "error". Adding !dvp below + * is probably a hack. + * + * This is wrong, GetDeviceProc() can return other errors than ERROR_OBJECT_NOT_FOUND. + */ + if (!dvp) + error = me->pr_Result2 = ERROR_OBJECT_NOT_FOUND; +#endif + } + + if (error == ERROR_IS_SOFT_LINK) + { + STRPTR softname = ResolveSoftlink(lock, dvp, name, DOSBase); + + if (softname) + { + if (dvp) + { + /* + * ResolveSoftlink() gives us path relative to either 'lock' lock + * (if on current volume), or 'dvp' volume root (if on different volume). + * In the latter case we need to do the lookup against the volume root lock. + */ + lock = dvp->dvp_Lock; + } + + ret = InternalLockRelative(lock, softname, accessMode, retlock, soft_nesting - 1, DOSBase); + if (ret) { + error = 0; + } + else { + error = IoErr(); + D(bug("[LockRelative] Resolve error %d\n", error)); + } + + FreeVec(softname); + } + else { + error = IoErr(); + } + } + + FreeDeviceProc(dvp); + + if (error) + { + SetIoErr(error); + return DOSFALSE; + } + + return DOSTRUE; +} + +/* + * Resolve a softlink. + * Returns AllocVec()ed buffer with softlink contents. + */ +STRPTR ResolveSoftlink(BPTR cur, struct DevProc *dvp, CONST_STRPTR name, struct DosLibrary *DOSBase) +{ + ULONG buffer_size = 256; + STRPTR softname; + LONG continue_loop; + LONG written; + + DLINK(bug("[Softlink] Resolving softlink %s...\n", name)); + + do + { + continue_loop = FALSE; + + if (!(softname = AllocVec(buffer_size, MEMF_PUBLIC|MEMF_CLEAR))) + { + SetIoErr(ERROR_NO_FREE_STORE); + break; + } + + written = fs_ReadLink(cur, dvp, name, softname, buffer_size, DOSBase); + + switch (written) + { + case -1: + /* An error occured */ + DLINK(bug("[Softlink] Error %d reading softlink\n", IoErr())); + break; + + case -2: + /* If there's not enough space in the buffer, increase it and try again */ + continue_loop = TRUE; + buffer_size <<= 1; + + DLINK(bug("[Softlink] Increased buffer size up to %u\n", buffer_size)); + break; + + default: + /* All OK */ + DLINK(bug("[Softlink] Resolved path: %s\n", softname)); + return softname; + } + + FreeVec(softname); + } + while(continue_loop); + + return NULL; +} diff --git a/rom/dos/mmakefile.src b/rom/dos/mmakefile.src index 131722be5f0..aaafa2e9f08 100644 --- a/rom/dos/mmakefile.src +++ b/rom/dos/mmakefile.src @@ -50,7 +50,7 @@ FUNCTIONS := abortpkt addbuffers adddosentry addpart addsegment \ getcurrentdirname getdeviceproc getfilesystask getprogramdir \ getprogramname getprompt getseglistinfo getvar info inhibit \ input internalunloadseg ioerr isfilesystem \ - isinteractive loadseg lock lockdoslist lockrecord lockrecords \ + isinteractive loadseg lock lockdoslist lockrelative lockrecord lockrecords \ makedosentry makelink matchend matchfirst matchnext matchpattern \ matchpatternnocase maxcli namefromfh namefromlock newloadseg nextdosentry nil \ open openfromlock output parentdir parentoffh parsepattern \ diff --git a/rom/dos/open.c b/rom/dos/open.c index 6323d5237e2..2b1caff9446 100644 --- a/rom/dos/open.c +++ b/rom/dos/open.c @@ -123,6 +123,19 @@ static LONG dupHandle(struct FileHandle *fh, BPTR lock, struct DosLibrary *DOSBa return err; } +LONG RootDir(struct DevProc *dvp, struct DosLibrary *DOSBase) +{ + BPTR lock = BNULL; + LONG error; + + /* We already have a DeviceProc structure, so just use internal routine. */ + error = fs_LocateObject(&lock, dvp->dvp_Port, dvp->dvp_Lock, "", SHARED_LOCK, DOSBase); + + if (!error) + CurrentDir(lock); + + return error; +} /* Try to open name recursively calling itself in case it's a soft link. Store result in handle. Return boolean value indicating result. */ From 72a2f5f2bac534601c4816361f8263b65558414b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rob=20N=20=E2=98=85?= Date: Sun, 25 Apr 2021 12:07:16 +1000 Subject: [PATCH 2/8] dos: add OpenRelative --- rom/dos/dos.conf | 1 + rom/dos/mmakefile.src | 2 +- rom/dos/open.c | 233 +-------------------------------- rom/dos/openrelative.c | 286 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 289 insertions(+), 233 deletions(-) create mode 100644 rom/dos/openrelative.c diff --git a/rom/dos/dos.conf b/rom/dos/dos.conf index c3f6c29c2c2..8a36b79d78c 100644 --- a/rom/dos/dos.conf +++ b/rom/dos/dos.conf @@ -257,4 +257,5 @@ LONG GetSegListInfo(BPTR seglist, const struct TagItem *taglist) (D0, A0) BOOL AssignAddToList(CONST_STRPTR name, BPTR lock, ULONG position) (D1, D2, D3) # AROS-specific BPTR LockRelative(BPTR lock, CONST_STRPTR name, LONG accessMode) (D1,D2,D3) +BPTR OpenRelative(BPTR lock, CONST_STRPTR name, LONG accessMode) (D1,D2,D3) ##end functionlist diff --git a/rom/dos/mmakefile.src b/rom/dos/mmakefile.src index aaafa2e9f08..282deecfdbe 100644 --- a/rom/dos/mmakefile.src +++ b/rom/dos/mmakefile.src @@ -53,7 +53,7 @@ FUNCTIONS := abortpkt addbuffers adddosentry addpart addsegment \ isinteractive loadseg lock lockdoslist lockrelative lockrecord lockrecords \ makedosentry makelink matchend matchfirst matchnext matchpattern \ matchpatternnocase maxcli namefromfh namefromlock newloadseg nextdosentry nil \ - open openfromlock output parentdir parentoffh parsepattern \ + open openfromlock openrelative output parentdir parentoffh parsepattern \ parsepatternnocase pathpart printfault putstr read readargs \ readitem relabel readlink remassignlist remdosentry remsegment rename \ replypkt runcommand samedevice samelock scanvars seek \ diff --git a/rom/dos/open.c b/rom/dos/open.c index 2b1caff9446..bfa276518a1 100644 --- a/rom/dos/open.c +++ b/rom/dos/open.c @@ -4,25 +4,8 @@ Desc: Open a file with the specified mode. */ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - #include "dos_intern.h" -static LONG InternalOpen(CONST_STRPTR name, LONG accessMode, - struct FileHandle *handle, LONG soft_nesting, struct DosLibrary *DOSBase); - -#define MAX_SOFT_LINK_NESTING 16 /* Maximum level of soft links nesting */ - /***************************************************************************** NAME */ @@ -65,221 +48,7 @@ static LONG InternalOpen(CONST_STRPTR name, LONG accessMode, { AROS_LIBFUNC_INIT - struct FileHandle *ret; - LONG error; - - /* Sanity check */ - if (name == NULL) return BNULL; - - /* Create filehandle */ - ret = (struct FileHandle *)AllocDosObject(DOS_FILEHANDLE,NULL); - - if (ret != NULL) - { - LONG ok = InternalOpen(name, accessMode, ret, MAX_SOFT_LINK_NESTING, DOSBase); - D(bug("[Open] = %p, Error = %d\n", ok ? MKBADDR(ret) : BNULL, IoErr())); - if (ok) - { - return MKBADDR(ret); - } - else - { - error = IoErr(); - FreeDosObject(DOS_FILEHANDLE,ret); - } - } - else - error = ERROR_NO_FREE_STORE; - - SetIoErr(error); - return BNULL; + return OpenRelative(NULL, name, accessMode); AROS_LIBFUNC_EXIT -} /* Open */ - - -static LONG dupHandle(struct FileHandle *fh, BPTR lock, struct DosLibrary *DOSBase) -{ - LONG err; - struct MsgPort *port; - struct FileLock *fl; - - if (lock == BNULL) - return DOSFALSE; - - fl = BADDR(lock); - port = fl->fl_Task; - - err = dopacket2(DOSBase, NULL, port, ACTION_FH_FROM_LOCK, MKBADDR(fh), lock); - - if (err != DOSFALSE) { - fh->fh_Type = port; - if (fh->fh_Interactive) - SetVBuf(MKBADDR(fh), NULL, BUF_LINE, -1); - else - SetVBuf(MKBADDR(fh), NULL, BUF_NONE, -1); - } - - return err; -} - -LONG RootDir(struct DevProc *dvp, struct DosLibrary *DOSBase) -{ - BPTR lock = BNULL; - LONG error; - - /* We already have a DeviceProc structure, so just use internal routine. */ - error = fs_LocateObject(&lock, dvp->dvp_Port, dvp->dvp_Lock, "", SHARED_LOCK, DOSBase); - - if (!error) - CurrentDir(lock); - - return error; -} - -/* Try to open name recursively calling itself in case it's a soft link. - Store result in handle. Return boolean value indicating result. */ -static LONG InternalOpen(CONST_STRPTR name, LONG accessMode, - struct FileHandle *handle, LONG soft_nesting, struct DosLibrary *DOSBase) -{ - /* Get pointer to process structure */ - struct Process *me = (struct Process *)FindTask(NULL); - LONG ret = DOSFALSE; - LONG error = 0; - BPTR con, ast; - - ASSERT_VALID_PROCESS(me); - - D(bug("[Open] %s: 0x%p \"%s\", Name: \"%s\" File: %p\n", - __is_process(me) ? "Process" : "Task", me, me->pr_Task.tc_Node.ln_Name, - name, MKBADDR(handle))); - - if(soft_nesting == 0) - { - SetIoErr(ERROR_TOO_MANY_LEVELS); - return DOSFALSE; - } - - /* IN:, OUT:, ERR: pseudodevices - */ - if (pseudoLock(name, (accessMode == MODE_OLDFILE) ? ACCESS_READ : - ((accessMode == MODE_NEWFILE) ? ACCESS_WRITE : 0), - &ast, &ret, DOSBase)) { - return dupHandle(handle, ast, DOSBase); - } - - switch(accessMode) - { - case MODE_NEWFILE: - case MODE_READWRITE: - con = me->pr_COS; - ast = me->pr_CES ? me->pr_CES : me->pr_COS; - - break; - - case MODE_OLDFILE: - ast = con = me->pr_CIS; - break; - - default: - SetIoErr(ERROR_NOT_IMPLEMENTED); - return DOSFALSE; - } - - if (!Stricmp(name, "CONSOLE:")) - error = fs_Open(handle, me->pr_ConsoleTask, con, accessMode, name, DOSBase); - else if (!Stricmp(name, "*")) - error = fs_Open(handle, me->pr_ConsoleTask, ast, accessMode, name, DOSBase); - else if (!Stricmp(name, "NIL:")) - { - error = fs_Open(handle, BNULL, BNULL, accessMode, name, DOSBase); - SetIoErr(0); - } - else - { - BPTR cur = BNULL; - struct DevProc *dvp = NULL; - STRPTR filename = strchr(name, ':'); - - if (!filename) - { - struct MsgPort *port; - - /* No ':', pathname relative to current dir */ - cur = me->pr_CurrentDir; - - if (cur && cur != (BPTR)-1) { - port = ((struct FileLock *)BADDR(cur))->fl_Task; - } else { - port = DOSBase->dl_Root->rn_BootProc; - cur = BNULL; - } - - error = fs_Open(handle, port, cur, accessMode, name, DOSBase); - } - else - { - filename++; - do - { - if ((dvp = GetDeviceProc(name, dvp)) == NULL) - { - error = IoErr(); - break; - } - - error = fs_Open(handle, dvp->dvp_Port, dvp->dvp_Lock, accessMode, filename, DOSBase); - } while(error == ERROR_OBJECT_NOT_FOUND && accessMode != MODE_NEWFILE); - - if (error == ERROR_NO_MORE_ENTRIES) - error = ERROR_OBJECT_NOT_FOUND; - } - - if (error == ERROR_IS_SOFT_LINK) - { - STRPTR softname = ResolveSoftlink(cur, dvp, name, DOSBase); - - if (softname) - { - /* All OK */ - BPTR olddir = BNULL; - - if (dvp) - { - olddir = me->pr_CurrentDir; - error = RootDir(dvp, DOSBase); - } - else - error = 0; - - if (!error) - { - ret = InternalOpen(softname, accessMode, handle, soft_nesting - 1, DOSBase); - error = ret ? 0 : IoErr(); - - if (olddir) - UnLock(CurrentDir(olddir)); - } - - FreeVec(softname); - } - else - error = IoErr(); - } - - FreeDeviceProc(dvp); - } - - if (!error) - { - if (IsInteractive(MKBADDR(handle))) - SetVBuf(MKBADDR(handle), NULL, BUF_LINE, -1); - - return DOSTRUE; - } - else - { - SetIoErr(error); - return DOSFALSE; - } } diff --git a/rom/dos/openrelative.c b/rom/dos/openrelative.c new file mode 100644 index 00000000000..17590e10358 --- /dev/null +++ b/rom/dos/openrelative.c @@ -0,0 +1,286 @@ +/* + Copyright (C) 1995-2011, The AROS Development Team. All rights reserved. + + Desc: Open a file with the specified mode. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "dos_intern.h" + +static LONG InternalOpenRelative( + BPTR baselock, + CONST_STRPTR name, + LONG accessMode, + struct FileHandle *handle, + LONG soft_nesting, + struct DosLibrary *DOSBase); + +#define MAX_SOFT_LINK_NESTING 16 /* Maximum level of soft links nesting */ + +/***************************************************************************** + + NAME */ +#include + + AROS_LH3(BPTR, OpenRelative, + +/* SYNOPSIS */ + AROS_LHA(BPTR, lock, D1), + AROS_LHA(CONST_STRPTR, name, D2), + AROS_LHA(LONG, accessMode, D3), + +/* LOCATION */ + struct DosLibrary *, DOSBase, 228, Dos) + +/* FUNCTION + Opens a file for read and/or write depending on the accessmode given. + + INPUTS + lock - existing lock to compute filename from + name - NUL terminated name of the file. + accessMode - One of MODE_OLDFILE - open existing file + MODE_NEWFILE - delete old, create new file + exclusive lock + MODE_READWRITE - open new one if it doesn't exist + + RESULT + Handle to the file or 0 if the file couldn't be opened. + IoErr() gives additional information in that case. + + NOTES + This call is AROS-specific. + +*****************************************************************************/ +{ + AROS_LIBFUNC_INIT + + struct FileHandle *ret; + LONG error; + + /* Sanity check */ + if (name == NULL) + return BNULL; + + ASSERT_VALID_PTR(name); + + D(bug("[OpenRelative] baselock=0x%p name=%s mode=%d\n", lock, name, accessMode)); + + ret = (struct FileHandle *) AllocDosObject(DOS_FILEHANDLE, NULL); + if (ret == NULL) + { + SetIoErr(ERROR_NO_FREE_STORE); + return BNULL; + } + + if (InternalOpenRelative(lock, name, accessMode, ret, MAX_SOFT_LINK_NESTING, DOSBase)) + { + D(bug("[OpenRelative] returned 0x%p\n", MKBADDR(ret))); + return MKBADDR(ret); + } + + D(bug("[OpenRelative] failed, err=%d\n", IoErr())); + + FreeDosObject(DOS_FILEHANDLE, ret); + return BNULL; + + AROS_LIBFUNC_EXIT +} /* OpenRelative */ + + +static LONG dupHandle(struct FileHandle *fh, BPTR lock, struct DosLibrary *DOSBase) +{ + LONG err; + struct MsgPort *port; + struct FileLock *fl; + + if (lock == BNULL) + return DOSFALSE; + + fl = BADDR(lock); + port = fl->fl_Task; + + err = dopacket2(DOSBase, NULL, port, ACTION_FH_FROM_LOCK, MKBADDR(fh), lock); + + if (err != DOSFALSE) { + fh->fh_Type = port; + if (fh->fh_Interactive) + SetVBuf(MKBADDR(fh), NULL, BUF_LINE, -1); + else + SetVBuf(MKBADDR(fh), NULL, BUF_NONE, -1); + } + + return err; +} + + +/* Try to open name recursively calling itself in case it's a soft link. + Store result in handle. Return boolean value indicating result. */ +static LONG InternalOpenRelative( + BPTR baselock, + CONST_STRPTR name, + LONG accessMode, + struct FileHandle *handle, + LONG soft_nesting, + struct DosLibrary *DOSBase) +{ + /* Get pointer to process structure */ + struct Process *me = (struct Process *)FindTask(NULL); + LONG ret = DOSFALSE; + LONG error = 0; + BPTR con, ast; + + ASSERT_VALID_PROCESS(me); + + D(bug("[OpenRelative] %s: 0x%p \"%s\", Name: \"%s\" File: %p\n", + __is_process(me) ? "Process" : "Task", me, me->pr_Task.tc_Node.ln_Name, + name, MKBADDR(handle))); + + if(soft_nesting == 0) + { + SetIoErr(ERROR_TOO_MANY_LEVELS); + return DOSFALSE; + } + + /* IN:, OUT:, ERR: pseudodevices + */ + if (pseudoLock(name, (accessMode == MODE_OLDFILE) ? ACCESS_READ : + ((accessMode == MODE_NEWFILE) ? ACCESS_WRITE : 0), + &ast, &ret, DOSBase)) { + return dupHandle(handle, ast, DOSBase); + } + + switch(accessMode) + { + case MODE_NEWFILE: + case MODE_READWRITE: + con = me->pr_COS; + ast = me->pr_CES ? me->pr_CES : me->pr_COS; + + break; + + case MODE_OLDFILE: + ast = con = me->pr_CIS; + break; + + default: + SetIoErr(ERROR_NOT_IMPLEMENTED); + return DOSFALSE; + } + + if (!Stricmp(name, "CONSOLE:")) + error = fs_Open(handle, me->pr_ConsoleTask, con, accessMode, name, DOSBase); + else if (!Stricmp(name, "*")) + error = fs_Open(handle, me->pr_ConsoleTask, ast, accessMode, name, DOSBase); + else if (!Stricmp(name, "NIL:")) + { + error = fs_Open(handle, BNULL, BNULL, accessMode, name, DOSBase); + SetIoErr(0); + } + else + { + BPTR lock = BNULL; + struct DevProc *dvp = NULL; + STRPTR filename = strchr(name, ':'); + + if (!filename) + { + /* No ':', pathname relative to current dir */ + struct MsgPort *port; + + if (baselock) { + /* baselock provided; relative to it */ + port = ((struct FileLock *)BADDR(baselock))->fl_Task; + lock = baselock; + } + else { + /* no lock provided; relative to current directory */ + lock = me->pr_CurrentDir; + if (lock && lock != (BPTR)-1) { + port = ((struct FileLock *)BADDR(lock))->fl_Task; + } + else { + /* no current directory? go from the root */ + port = DOSBase->dl_Root->rn_BootProc; + lock = BNULL; + } + } + + error = fs_Open(handle, port, lock, accessMode, name, DOSBase); + } + else + { + /* absolute path; get the device and look it up against that */ + filename++; + do + { + if ((dvp = GetDeviceProc(name, dvp)) == NULL) + { + error = IoErr(); + break; + } + + error = fs_Open(handle, dvp->dvp_Port, dvp->dvp_Lock, accessMode, filename, DOSBase); + + } while(error == ERROR_OBJECT_NOT_FOUND && accessMode != MODE_NEWFILE); + + if (error == ERROR_NO_MORE_ENTRIES) + error = ERROR_OBJECT_NOT_FOUND; + } + + if (error == ERROR_IS_SOFT_LINK) + { + STRPTR softname = ResolveSoftlink(lock, dvp, name, DOSBase); + + if (softname) + { + if (dvp) + { + /* + * ResolveSoftlink() gives us path relative to either 'lock lock + * (if on current volume), or 'dvp' volume root (if on different volume) + * In the latter case we need to do the lookup against the volume root lock. + */ + lock = dvp->dvp_Lock; + } + + ret = InternalOpenRelative(lock, softname, accessMode, handle, soft_nesting - 1, DOSBase); + if (ret) { + error = 0; + } + else { + error = IoErr(); + D(bug("[OpenRelative] Resolve error %d\n", error)); + } + + FreeVec(softname); + } + else { + error = IoErr(); + } + } + + FreeDeviceProc(dvp); + } + + if (error) + { + SetIoErr(error); + return DOSFALSE; + } + + if (IsInteractive(MKBADDR(handle))) + SetVBuf(MKBADDR(handle), NULL, BUF_LINE, -1); + + return DOSTRUE; +} From 5651a88d6443b7c62d29a3c739e1f72c3819f8f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rob=20N=20=E2=98=85?= Date: Sun, 25 Apr 2021 12:45:01 +1000 Subject: [PATCH 3/8] dos: remove fs_ReadLink, lift ResolveSoftLink This is really just fiddling around the edges. I don't love that heap allocation there, but eh, its a rarely-hit codepath anyway. At least now its tidier and out of the way. --- rom/dos/dos_intern.h | 3 ++ rom/dos/fs_driver.c | 19 ----------- rom/dos/fs_driver.h | 1 - rom/dos/lockrelative.c | 55 ------------------------------ rom/dos/mmakefile.src | 2 +- rom/dos/resolvesoftlink.c | 72 +++++++++++++++++++++++++++++++++++++++ 6 files changed, 76 insertions(+), 76 deletions(-) create mode 100644 rom/dos/resolvesoftlink.c diff --git a/rom/dos/dos_intern.h b/rom/dos/dos_intern.h index 56dedc527a4..f420ebc4a89 100644 --- a/rom/dos/dos_intern.h +++ b/rom/dos/dos_intern.h @@ -337,4 +337,7 @@ BPTR findseg_shell(BOOL isBoot, struct DosLibrary *DOSBase); */ BOOL pseudoLock(CONST_STRPTR name, LONG lockMode, BPTR *lock, LONG *ret, struct DosLibrary *DOSBase); +/* helper for recursively resolving softlinks */ +STRPTR ResolveSoftlink(BPTR lock, struct DevProc *dvp, CONST_STRPTR name, struct DosLibrary *DOSBase); + #endif /* DOS_INTERN_H */ diff --git a/rom/dos/fs_driver.c b/rom/dos/fs_driver.c index ba1c3ee9836..d694f515c9f 100644 --- a/rom/dos/fs_driver.c +++ b/rom/dos/fs_driver.c @@ -61,25 +61,6 @@ LONG fs_Open(struct FileHandle *handle, struct MsgPort *port, BPTR lock, LONG mo return status ? 0 : error; } -LONG fs_ReadLink(BPTR parent, struct DevProc *dvp, CONST_STRPTR path, STRPTR buffer, ULONG size, struct DosLibrary *DOSBase) -{ - struct MsgPort *port; - - if (parent) - { - struct FileLock *fl = BADDR(parent); - - port = fl->fl_Task; - } - else - { - port = dvp->dvp_Port; - parent = dvp->dvp_Lock; - } - - return ReadLink(port, parent, path, buffer, size); -} - LONG fs_ChangeSignal(BPTR handle, struct Process *task, struct DosLibrary *DOSBase) { SIPTR error = 0; diff --git a/rom/dos/fs_driver.h b/rom/dos/fs_driver.h index ef872865a5c..ecc902193be 100644 --- a/rom/dos/fs_driver.h +++ b/rom/dos/fs_driver.h @@ -5,7 +5,6 @@ LONG fs_LocateObject(BPTR *ret, struct MsgPort *port, BPTR parent, CONST_STRPTR name, LONG accessMode, struct DosLibrary *DOSBase); LONG fs_Open(struct FileHandle *fh, struct MsgPort *port, BPTR lock, LONG accessMode, CONST_STRPTR name, struct DosLibrary *DOSBase); -LONG fs_ReadLink(BPTR parent, struct DevProc *dvp, CONST_STRPTR path, STRPTR buffer, ULONG size, struct DosLibrary *DOSBase); LONG fs_ChangeSignal(BPTR handle, struct Process *task, struct DosLibrary *DOSBase); LONG fs_AddNotify(struct NotifyRequest *notify, struct DevProc *dvp, BPTR lock, struct DosLibrary *DOSBase); BYTE DosDoIO(struct IORequest *iORequest); diff --git a/rom/dos/lockrelative.c b/rom/dos/lockrelative.c index 16a3e7ccb96..bf6ac3757ca 100644 --- a/rom/dos/lockrelative.c +++ b/rom/dos/lockrelative.c @@ -4,8 +4,6 @@ Desc: Locks a file or directory. */ -#define DLINK(x) - #include #include #include @@ -288,56 +286,3 @@ static LONG InternalLockRelative( return DOSTRUE; } - -/* - * Resolve a softlink. - * Returns AllocVec()ed buffer with softlink contents. - */ -STRPTR ResolveSoftlink(BPTR cur, struct DevProc *dvp, CONST_STRPTR name, struct DosLibrary *DOSBase) -{ - ULONG buffer_size = 256; - STRPTR softname; - LONG continue_loop; - LONG written; - - DLINK(bug("[Softlink] Resolving softlink %s...\n", name)); - - do - { - continue_loop = FALSE; - - if (!(softname = AllocVec(buffer_size, MEMF_PUBLIC|MEMF_CLEAR))) - { - SetIoErr(ERROR_NO_FREE_STORE); - break; - } - - written = fs_ReadLink(cur, dvp, name, softname, buffer_size, DOSBase); - - switch (written) - { - case -1: - /* An error occured */ - DLINK(bug("[Softlink] Error %d reading softlink\n", IoErr())); - break; - - case -2: - /* If there's not enough space in the buffer, increase it and try again */ - continue_loop = TRUE; - buffer_size <<= 1; - - DLINK(bug("[Softlink] Increased buffer size up to %u\n", buffer_size)); - break; - - default: - /* All OK */ - DLINK(bug("[Softlink] Resolved path: %s\n", softname)); - return softname; - } - - FreeVec(softname); - } - while(continue_loop); - - return NULL; -} diff --git a/rom/dos/mmakefile.src b/rom/dos/mmakefile.src index 282deecfdbe..ec6e099bc87 100644 --- a/rom/dos/mmakefile.src +++ b/rom/dos/mmakefile.src @@ -30,7 +30,7 @@ FILES := bstr_helper errorlist \ match_misc newcliproc rootnode fs_driver \ patternmatching internalseek internalflush \ packethelper namefrom internalloadseg_support \ - shell_helper + shell_helper resolvesoftlink LOADSEG_FILES := internalloadseg \ $(foreach img, $(IMAGE_TYPES), internalloadseg_$(img)) diff --git a/rom/dos/resolvesoftlink.c b/rom/dos/resolvesoftlink.c new file mode 100644 index 00000000000..4e7c13f5a33 --- /dev/null +++ b/rom/dos/resolvesoftlink.c @@ -0,0 +1,72 @@ +/* + Copyright (C) 1995-2011, The AROS Development Team. All rights reserved. + + Desc: +*/ + +#define DLINK(x) + +#include +#include + +#include "dos_intern.h" + +/* + * Resolve a softlink. + * Returns AllocVec()ed buffer with softlink contents. + */ +STRPTR ResolveSoftlink(BPTR lock, struct DevProc *dvp, CONST_STRPTR name, struct DosLibrary *DOSBase) +{ + ULONG buffer_size = 256; + STRPTR softname; + LONG continue_loop; + LONG written; + + DLINK(bug("[Softlink] Resolving softlink %s...\n", name)); + + do + { + continue_loop = FALSE; + + if (!(softname = AllocVec(buffer_size, MEMF_PUBLIC|MEMF_CLEAR))) + { + SetIoErr(ERROR_NO_FREE_STORE); + break; + } + + if (lock) { + struct FileLock *fl = BADDR(lock); + written = ReadLink(fl->fl_Task, lock, name, softname, buffer_size); + } + else { + written = ReadLink(dvp->dvp_Port, dvp->dvp_Lock, name, softname, buffer_size); + } + + switch (written) + { + case -1: + /* An error occured */ + DLINK(bug("[Softlink] Error %d reading softlink\n", IoErr())); + break; + + case -2: + /* If there's not enough space in the buffer, increase it and try again */ + continue_loop = TRUE; + buffer_size <<= 1; + + DLINK(bug("[Softlink] Increased buffer size up to %u\n", buffer_size)); + break; + + default: + /* All OK */ + DLINK(bug("[Softlink] Resolved path: %s\n", softname)); + return softname; + } + + FreeVec(softname); + } + while(continue_loop); + + return NULL; +} + From 071ed1c0439f8523f745cb73a200d05b75ad05a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rob=20N=20=E2=98=85?= Date: Mon, 26 Apr 2021 14:18:16 +1000 Subject: [PATCH 4/8] dos: getpacketinfo: relative lock --- rom/dos/createdir.c | 2 +- rom/dos/deletefile.c | 2 +- rom/dos/dos_intern.h | 2 +- rom/dos/errorreport.c | 2 +- rom/dos/makelink.c | 2 +- rom/dos/packethelper.c | 59 ++++++++++++++++++++++++----------------- rom/dos/setcomment.c | 2 +- rom/dos/setfiledate.c | 2 +- rom/dos/setowner.c | 2 +- rom/dos/setprotection.c | 2 +- 10 files changed, 44 insertions(+), 33 deletions(-) diff --git a/rom/dos/createdir.c b/rom/dos/createdir.c index b624e8018ee..460dd3dbe14 100644 --- a/rom/dos/createdir.c +++ b/rom/dos/createdir.c @@ -56,7 +56,7 @@ D(bug("[CreateDir] '%s'\n", name)); - if (getpacketinfo(DOSBase, name, &phs)) { + if (getpacketinfo(DOSBase, BNULL, name, &phs)) { lock = (BPTR)dopacket2(DOSBase, NULL, phs.port, ACTION_CREATE_DIR, phs.lock, phs.name); freepacketinfo(DOSBase, &phs); } diff --git a/rom/dos/deletefile.c b/rom/dos/deletefile.c index ec61cfef21e..6ec34602c3b 100644 --- a/rom/dos/deletefile.c +++ b/rom/dos/deletefile.c @@ -55,7 +55,7 @@ D(bug("[DeleteFile] '%s'\n", name)); - if (getpacketinfo(DOSBase, name, &phs)) { + if (getpacketinfo(DOSBase, BNULL, name, &phs)) { status = dopacket2(DOSBase, NULL, phs.port, ACTION_DELETE_OBJECT, phs.lock, phs.name); freepacketinfo(DOSBase, &phs); } diff --git a/rom/dos/dos_intern.h b/rom/dos/dos_intern.h index f420ebc4a89..0a0a9321830 100644 --- a/rom/dos/dos_intern.h +++ b/rom/dos/dos_intern.h @@ -312,7 +312,7 @@ struct PacketHelperStruct struct DevProc *dp; }; -BOOL getpacketinfo(struct DosLibrary *DOSBase, CONST_STRPTR, struct PacketHelperStruct*); +BOOL getpacketinfo(struct DosLibrary *DOSBase, BPTR, CONST_STRPTR, struct PacketHelperStruct*); BOOL getdevpacketinfo(struct DosLibrary *DOSBase, CONST_STRPTR devname, CONST_STRPTR name, struct PacketHelperStruct *phs); void freepacketinfo(struct DosLibrary *DOSBase, struct PacketHelperStruct*); diff --git a/rom/dos/errorreport.c b/rom/dos/errorreport.c index 0740c4706d2..a45bfc6accf 100644 --- a/rom/dos/errorreport.c +++ b/rom/dos/errorreport.c @@ -218,7 +218,7 @@ case REPORT_INSERT: if (arg1 == (IPTR)NULL) return DOSTRUE; - if (!getpacketinfo(DOSBase, (STRPTR)arg1, &phs)) + if (!getpacketinfo(DOSBase, BNULL, (STRPTR)arg1, &phs)) return DOSTRUE; msgport = phs.port; volname = (STRPTR) arg1; diff --git a/rom/dos/makelink.c b/rom/dos/makelink.c index cadf0816617..4233f3a525f 100644 --- a/rom/dos/makelink.c +++ b/rom/dos/makelink.c @@ -64,7 +64,7 @@ LONG status; status = DOSFALSE; - if (getpacketinfo(DOSBase, name, &phs)) + if (getpacketinfo(DOSBase, BNULL, name, &phs)) { status = dopacket4(DOSBase, NULL, phs.port, ACTION_MAKE_LINK, phs.lock, phs.name, (SIPTR)dest, soft ? LINK_SOFT: LINK_HARD); diff --git a/rom/dos/packethelper.c b/rom/dos/packethelper.c index 21d3f6dc69a..8abadfcd3b3 100644 --- a/rom/dos/packethelper.c +++ b/rom/dos/packethelper.c @@ -12,41 +12,52 @@ #include "dos_intern.h" -BOOL getpacketinfo(struct DosLibrary *DOSBase, CONST_STRPTR name, struct PacketHelperStruct *phs) +BOOL getpacketinfo(struct DosLibrary *DOSBase, BPTR baselock, CONST_STRPTR name, struct PacketHelperStruct *phs) { + BSTR bstrname = C2BSTR(name); + if (!strchr(name, ':')) { - /* no ":" */ - struct Process *me = (struct Process *)FindTask(NULL); - BPTR cur; - BSTR bstrname = C2BSTR(name); + /* relative path */ struct FileLock *fl; - ASSERT_VALID_PROCESS(me); - - cur = me->pr_CurrentDir; - if (cur && cur != (BPTR)-1) { - fl = BADDR(cur); + if (baselock) { + /* baselock provided; relative to it */ + fl = BADDR(baselock); phs->port = fl->fl_Task; - phs->lock = cur; - } else { - phs->port = DOSBase->dl_Root->rn_BootProc; - phs->lock = BNULL; + phs->lock = baselock; + } + else { + /* no lock provided; relative to current directory */ + struct Process *me = (struct Process *)FindTask(NULL); + ASSERT_VALID_PROCESS(me); + + BPTR lock = me->pr_CurrentDir; + if (lock && lock != (BPTR)-1) { + fl = BADDR(lock); + phs->port = fl->fl_Task; + phs->lock = lock; + } else { + phs->port = DOSBase->dl_Root->rn_BootProc; + phs->lock = BNULL; + } } + phs->dp = NULL; phs->name = bstrname; return TRUE; - } else { /* ":" */ - BSTR bstrname = C2BSTR(name); - struct DevProc *dvp = NULL; - if ((dvp = GetDeviceProc(name, dvp))) { - phs->name = bstrname; - phs->port = dvp->dvp_Port; - phs->lock = dvp->dvp_Lock; - phs->dp = dvp; - return TRUE; - } } + + /* absolute path */ + struct DevProc *dvp = NULL; + if ((dvp = GetDeviceProc(name, dvp))) { + phs->name = bstrname; + phs->port = dvp->dvp_Port; + phs->lock = dvp->dvp_Lock; + phs->dp = dvp; + return TRUE; + } + return FALSE; } diff --git a/rom/dos/setcomment.c b/rom/dos/setcomment.c index e5368150450..dd6e9b43eff 100644 --- a/rom/dos/setcomment.c +++ b/rom/dos/setcomment.c @@ -65,7 +65,7 @@ SetIoErr(ERROR_COMMENT_TOO_BIG); return status; } - if (getpacketinfo(DOSBase, name, &phs)) { + if (getpacketinfo(DOSBase, BNULL, name, &phs)) { BSTR com = C2BSTR(comment); if (com) { status = dopacket4(DOSBase, NULL, phs.port, ACTION_SET_COMMENT, (SIPTR)NULL, phs.lock, phs.name, com); diff --git a/rom/dos/setfiledate.c b/rom/dos/setfiledate.c index f9b891a6ef6..88d8fbc8093 100644 --- a/rom/dos/setfiledate.c +++ b/rom/dos/setfiledate.c @@ -56,7 +56,7 @@ D(bug("[SetFileDate] '%s' %x\n", name, date)); - if (getpacketinfo(DOSBase, name, &phs)) { + if (getpacketinfo(DOSBase, BNULL, name, &phs)) { status = dopacket4(DOSBase, NULL, phs.port, ACTION_SET_DATE, (IPTR)NULL, phs.lock, phs.name, (IPTR)date); freepacketinfo(DOSBase, &phs); } diff --git a/rom/dos/setowner.c b/rom/dos/setowner.c index 6a75f769c0f..2a3ae481717 100644 --- a/rom/dos/setowner.c +++ b/rom/dos/setowner.c @@ -52,7 +52,7 @@ D(bug("[SetOwner] '%s' %x\n", name, owner_info)); - if (getpacketinfo(DOSBase, name, &phs)) { + if (getpacketinfo(DOSBase, BNULL, name, &phs)) { status = dopacket4(DOSBase, NULL, phs.port, ACTION_SET_OWNER, (IPTR)NULL, phs.lock, phs.name, (IPTR)owner_info); freepacketinfo(DOSBase, &phs); } diff --git a/rom/dos/setprotection.c b/rom/dos/setprotection.c index dbe49c347fc..43612d0ea92 100644 --- a/rom/dos/setprotection.c +++ b/rom/dos/setprotection.c @@ -52,7 +52,7 @@ D(bug("[SetProtection] '%s':%x\n", name, protect)); - if (getpacketinfo(DOSBase, name, &phs)) { + if (getpacketinfo(DOSBase, BNULL, name, &phs)) { status = dopacket4(DOSBase, NULL, phs.port, ACTION_SET_PROTECT, BNULL, phs.lock, phs.name, protect); freepacketinfo(DOSBase, &phs); } From 161da30f3ad714ed117cca3830dcef3248da7bd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rob=20N=20=E2=98=85?= Date: Mon, 26 Apr 2021 16:54:08 +1000 Subject: [PATCH 5/8] dos: add GetDeviceProcRelative --- rom/dos/dos.conf | 1 + rom/dos/getdeviceproc.c | 318 +-------------------------- rom/dos/getdeviceprocrelative.c | 376 ++++++++++++++++++++++++++++++++ rom/dos/mmakefile.src | 4 +- 4 files changed, 380 insertions(+), 319 deletions(-) create mode 100644 rom/dos/getdeviceprocrelative.c diff --git a/rom/dos/dos.conf b/rom/dos/dos.conf index 8a36b79d78c..25b38650bb0 100644 --- a/rom/dos/dos.conf +++ b/rom/dos/dos.conf @@ -258,4 +258,5 @@ BOOL AssignAddToList(CONST_STRPTR name, BPTR lock, ULONG position) (D1, D2, D3) # AROS-specific BPTR LockRelative(BPTR lock, CONST_STRPTR name, LONG accessMode) (D1,D2,D3) BPTR OpenRelative(BPTR lock, CONST_STRPTR name, LONG accessMode) (D1,D2,D3) +struct DevProc *GetDeviceProcRelative(BPTR lock, CONST_STRPTR name, struct DevProc *dp) (D1,D2,D3) ##end functionlist diff --git a/rom/dos/getdeviceproc.c b/rom/dos/getdeviceproc.c index 7ebd5e2e107..a1373523647 100644 --- a/rom/dos/getdeviceproc.c +++ b/rom/dos/getdeviceproc.c @@ -6,14 +6,8 @@ #include -#include -#include - #include "dos_intern.h" -extern struct Process *r(struct DeviceNode *dn, struct DosLibrary *DOSBase); -static struct DevProc *deviceproc_internal(struct DosLibrary *DOSBase, CONST_STRPTR name, struct DevProc *dp); - /***************************************************************************** NAME */ @@ -63,317 +57,7 @@ static struct DevProc *deviceproc_internal(struct DosLibrary *DOSBase, CONST_STR { AROS_LIBFUNC_INIT - struct DevProc *dp2; - - D(bug("[GetDeviceProc] '%s':0x%p\n", name, dp)); - dp2 = deviceproc_internal(DOSBase, name, dp); - -#if DEBUG - bug("[GetDeviceProc] = 0x%p", dp2); - if (dp2) - bug(", port=0x%p lock=0x%p dv=0x%p\n", dp2->dvp_Port, dp2->dvp_Lock, dp2->dvp_DevNode); - RawPutChar('\n'); -#endif - - return dp2; + return GetDeviceProcRelative(BNULL, name, dp); AROS_LIBFUNC_EXIT - } /* GetDeviceProc */ - -static struct DevProc *deviceproc_internal(struct DosLibrary *DOSBase, CONST_STRPTR name, struct DevProc *dp) -{ - struct Process *pr = (struct Process *)FindTask(NULL); - struct DosList *dl = NULL; - char vol[32]; - LONG len; - BPTR lock = BNULL; - BOOL res; - CONST_STRPTR origname = name; - struct FileLock *fl; - - ASSERT_VALID_PROCESS(pr); - - /* if they passed us the result of a previous call, then they want to - * loop over the targets of a multidirectory assign */ - if (dp != NULL) { - - /* if what they passed us is not a multidirectory assign, then there's - * nothing for us to do */ - if (dp->dvp_DevNode != NULL && - (dp->dvp_DevNode->dol_Type != DLT_DIRECTORY || !(dp->dvp_Flags & DVPF_ASSIGN))) { - - /* cleanup */ - if (dp->dvp_Flags & DVPF_UNLOCK) - UnLock(dp->dvp_Lock); - - FreeMem(dp, sizeof(struct DevProc)); - SetIoErr(ERROR_NO_MORE_ENTRIES); - return NULL; - } - - /* it's fine, we'll start from here */ - dl = dp->dvp_DevNode; - - /* lock the dos list here, to match the result of the next block */ - LockDosList(LDF_ALL | LDF_READ); - } - - /* otherwise we need to find a place to start in the doslist based on the - * name they passed in */ - else { - if (name == NULL || Strnicmp(name, "NIL:", 4) == 0) { - SetIoErr(ERROR_DEVICE_NOT_MOUNTED); - return NULL; - } - - /* allocate structure for return */ - if ((dp = AllocMem(sizeof(struct DevProc), MEMF_ANY | MEMF_CLEAR)) == NULL) { - SetIoErr(ERROR_NO_FREE_STORE); - return NULL; - } - - /* something real, work out what it's relative to */ - if (Strnicmp(name, "PROGDIR:", 8) == 0) { - lock = pr->pr_HomeDir; - /* I am not sure if these are correct but AOS does return - * non-NULL PROGDIR: handle even if pr_HomeDir is cleared */ - if (!lock) - lock = pr->pr_CurrentDir; - if (lock) { - fl = BADDR(lock); - dp->dvp_Port = fl->fl_Task; - dp->dvp_Lock = lock; - dp->dvp_DevNode = BADDR(fl->fl_Volume); - } else { - dp->dvp_Port = DOSBase->dl_Root->rn_BootProc; - dp->dvp_Lock = BNULL; - dp->dvp_DevNode = NULL; - } - dp->dvp_Flags = 0; - return dp; - } - - /* extract the volume name */ - len = SplitName(name, ':', vol, 0, sizeof(vol) - 1); - - /* if there wasn't one (or we found a lone ':') -> current dir */ - if (len <= 1) { - lock = pr->pr_CurrentDir; - /* if we got NULL, then it's relative to the system root lock */ - if (lock != BNULL) { - fl = BADDR(lock); - dp->dvp_Port = fl->fl_Task; - dp->dvp_Lock = lock; - dp->dvp_DevNode = BADDR(fl->fl_Volume); - } else { - dp->dvp_Port = DOSBase->dl_Root->rn_BootProc; - dp->dvp_Lock = BNULL; - dp->dvp_DevNode = NULL; - } - - /* Jump to the root directory if name[0] == ':' */ - if (name[0] == ':') - dp->dvp_Lock = (dp->dvp_DevNode) ? dp->dvp_DevNode->dol_Lock : BNULL; - - dp->dvp_Flags = 0; - return dp; - } - - do { - /* now find the doslist entry for the named volume */ - dl = LockDosList(LDF_ALL | LDF_READ); - dl = FindDosEntry(dl, vol, LDF_ALL); - - /* not found, bail out */ - if (dl == NULL) { - UnLockDosList(LDF_ALL | LDF_READ); - - if (ErrorReport(ERROR_DEVICE_NOT_MOUNTED, REPORT_INSERT, (IPTR)vol, NULL) == DOSTRUE) { - FreeMem(dp, sizeof(struct DevProc)); - return NULL; - } - } - } while(dl == NULL); - } - - /* at this point, we have an allocated devproc in dp, the doslist is - * locked for read, and we have the entry for the named "volume" - * (device, assign, etc) in dl and a filename relative to that in name */ - - /* late assign. we resolve the target and then promote the doslist entry - * to full assign */ - if (dl->dol_Type == DLT_LATE) { - /* obtain a lock on the target */ - lock = Lock(dl->dol_misc.dol_assign.dol_AssignName, SHARED_LOCK); - - /* didn't find the target */ - if (lock == BNULL) { - UnLockDosList(LDF_ALL | LDF_READ); - FreeMem(dp, sizeof(struct DevProc)); - return NULL; - } - - /* Directly change assign type without calling AssignXXX(), - * mimics AOS behavior, AOS programs assume it is safe to - * keep LDF_WRITE lock while calling Lock("late assign:"); - */ - dl->dol_Type = DLT_DIRECTORY; - dl->dol_Lock = lock; - dl->dol_Task = ((struct FileLock*)BADDR(lock))->fl_Task; - FreeVec(dl->dol_misc.dol_assign.dol_AssignName); - dl->dol_misc.dol_assign.dol_AssignName = NULL; - - /* the added entry will be a DLT_DIRECTORY, so we can just copy the - * details in and get out of here */ - dp->dvp_Port = dl->dol_Task; - dp->dvp_Lock = dl->dol_Lock; - dp->dvp_Flags = 0; - dp->dvp_DevNode = dl; - - UnLockDosList(LDF_ALL | LDF_READ); - - return dp; - } - - /* nonbinding assign. like a late assign, but with no doslist promotion */ - if (dl->dol_Type == DLT_NONBINDING) { - lock = Lock(dl->dol_misc.dol_assign.dol_AssignName, SHARED_LOCK); - - /* just fill out the dp and return */ - dp->dvp_Port = ((struct FileLock *) BADDR(lock))->fl_Task; - dp->dvp_Lock = lock; - dp->dvp_Flags = DVPF_UNLOCK; /* remember to unlock in FreeDeviceNode() */ - dp->dvp_DevNode = dl; - - UnLockDosList(LDF_ALL | LDF_READ); - - return dp; - } - - /* devices and volumes are easy */ - if (dl->dol_Type == DLT_DEVICE || dl->dol_Type == DLT_VOLUME) - { - struct MsgPort *newhandler = NULL; - - if (dl->dol_Type == DLT_DEVICE) - { - /* Check if the handler is not started */ - newhandler = dl->dol_Task; - if (!newhandler) - { - D(bug("[GetDeviceProc] Accessing device '%b', path='%s'\n", dl->dol_Name, origname)); - - /* - * Unlock before starting handler, handler may internally - * require dos list locks, for example to add volume node. - */ - UnLockDosList(LDF_ALL | LDF_READ); - - newhandler = RunHandler((struct DeviceNode *)dl, origname, DOSBase); - if (!newhandler) - { - FreeMem(dp, sizeof(struct DevProc)); - SetIoErr(ERROR_DEVICE_NOT_MOUNTED); - return NULL; - } - - LockDosList(LDF_ALL | LDF_READ); - } - } - else - { - res = TRUE; - - while (res && !dl->dol_Task) - { - D(bug("[GetDeviceProc] Accessing offline volume '%b'\n", dl->dol_Name)); - res = !ErrorReport(ERROR_DEVICE_NOT_MOUNTED, REPORT_VOLUME, (IPTR)dl, NULL); - } - - if (!res) - { - UnLockDosList(LDF_ALL | LDF_READ); - FreeMem(dp, sizeof(struct DevProc)); - SetIoErr(ERROR_DEVICE_NOT_MOUNTED); - return NULL; - } - } - - /* - * A handler theoretically may choose to use custom MsgPort for communications. - * Pick up its preference if specified. - */ - dp->dvp_Port = dl->dol_Task ? dl->dol_Task : newhandler; - dp->dvp_Lock = BNULL; - dp->dvp_Flags = 0; - dp->dvp_DevNode = dl; - - UnLockDosList(LDF_ALL | LDF_READ); - - return dp; - } - - /* sanity check */ - if (dl->dol_Type != DLT_DIRECTORY) { - UnLockDosList(LDF_ALL | LDF_READ); - FreeMem(dp, sizeof(struct DevProc)); - kprintf("%s:%d: DosList entry 0x%p has unknown type %d. Probably a bug, report it!\n" - " GetDeviceProc() called for '%s'\n", - __SRCFILENAME__, __LINE__, dl, dl->dol_Type, name); - SetIoErr(ERROR_BAD_NUMBER); - return NULL; - } - - /* real assigns. first, see if it's just pointing to a single dir */ - if (dp->dvp_Flags != DVPF_ASSIGN) { - /* just a plain assign, easy */ - dp->dvp_Port = dl->dol_Task; - dp->dvp_Lock = dl->dol_Lock; - dp->dvp_DevNode = dl; - - /* note multidirectory assigns so the caller knows to loop */ - dp->dvp_Flags = dl->dol_misc.dol_assign.dol_List != NULL ? DVPF_ASSIGN : 0; - - UnLockDosList(LDF_ALL | LDF_READ); - return dp; - } - - /* finally the tricky bit - multidirectory assigns */ - - /* if we're pointing at the "primary" lock, then we just take the first - * one in the list */ - if (dp->dvp_Lock == dl->dol_Lock) - dp->dvp_Lock = dl->dol_misc.dol_assign.dol_List->al_Lock; - - /* otherwise we're finding the next */ - else { - struct AssignList *al = dl->dol_misc.dol_assign.dol_List; - - /* find our current lock (ie the one we returned last time) */ - for (; al != NULL && al->al_Lock != dp->dvp_Lock; al = al->al_Next); - - /* if we didn't find it, or we didn't but there's none after it, then - * we've run out */ - if (al == NULL || (al = al->al_Next) == NULL) { - UnLockDosList(LDF_ALL | LDF_READ); - FreeMem(dp, sizeof(struct DevProc)); - - SetIoErr(ERROR_NO_MORE_ENTRIES); - return NULL; - } - - /* fill out the lock from the new entry */ - dp->dvp_Lock = al->al_Lock; - } - - /* final pieces */ - dp->dvp_Port = ((struct FileLock *) BADDR(dp->dvp_Lock))->fl_Task; - dp->dvp_Flags = DVPF_ASSIGN; - dp->dvp_DevNode = dl; - - UnLockDosList(LDF_READ|LDF_ALL); - /* phew */ - SetIoErr(0); - return dp; -} diff --git a/rom/dos/getdeviceprocrelative.c b/rom/dos/getdeviceprocrelative.c new file mode 100644 index 00000000000..d4b421cd85d --- /dev/null +++ b/rom/dos/getdeviceprocrelative.c @@ -0,0 +1,376 @@ +/* + Copyright (C) 1995-2021, The AROS Development Team. All rights reserved. + + Desc: GetDeviceProcRelative() - Find the filesystem for a path. +*/ + +#include + +#include +#include + +#include "dos_intern.h" + +extern struct Process *r(struct DeviceNode *dn, struct DosLibrary *DOSBase); +static struct DevProc *deviceproc_internal(struct DosLibrary *DOSBase, BPTR baselock, CONST_STRPTR name, struct DevProc *dp); + +/***************************************************************************** + + NAME */ +#include + + AROS_LH3(struct DevProc *, GetDeviceProcRelative, + +/* SYNOPSIS */ + AROS_LHA(BPTR, lock, D1), + AROS_LHA(CONST_STRPTR, name, D2), + AROS_LHA(struct DevProc *, dp, D3), + +/* LOCATION */ + struct DosLibrary *, DOSBase, 229, Dos) + +/* FUNCTION + GetDeviceProcRelative() will search for the filesystem handler which + you should send a command to for a specific path. + + By calling GetDeviceProcRelative() multiple times, the caller will be + able to handle multi-assign paths. + + The first call to GetDeviceProcRelative() should have the |dp| + parameter as NULL. + + INPUTS + lock - existing lock to compute filename from + name - Name of the object to find. + dp - Previous result of GetDeviceProcRelative() or NULL. + + RESULT + A pointer to a DevProc structure containing the information + required to send a command to a filesystem. + + NOTES + This call is AROS-specific. + + SEE ALSO + FreeDeviceProc() + +*****************************************************************************/ +{ + AROS_LIBFUNC_INIT + + struct DevProc *dp2; + + D(bug("[GetDeviceProcRelative] lock=0x%p name='%s' dp=0x%p\n", lock, name, dp)); + dp2 = deviceproc_internal(DOSBase, lock, name, dp); + +#if DEBUG + bug("[GetDeviceProcRelative] = 0x%p", dp2); + if (dp2) + bug(", port=0x%p lock=0x%p dv=0x%p\n", dp2->dvp_Port, dp2->dvp_Lock, dp2->dvp_DevNode); + RawPutChar('\n'); +#endif + + return dp2; + + AROS_LIBFUNC_EXIT + +} /* GetDeviceProcRelative */ + +static struct DevProc *deviceproc_internal(struct DosLibrary *DOSBase, BPTR baselock, CONST_STRPTR name, struct DevProc *dp) +{ + struct Process *pr = (struct Process *)FindTask(NULL); + struct DosList *dl = NULL; + char vol[32]; + LONG len; + BPTR lock = BNULL; + BOOL res; + CONST_STRPTR origname = name; + struct FileLock *fl; + + ASSERT_VALID_PROCESS(pr); + + /* if they passed us the result of a previous call, then they want to + * loop over the targets of a multidirectory assign */ + if (dp != NULL) { + + /* if what they passed us is not a multidirectory assign, then there's + * nothing for us to do */ + if (dp->dvp_DevNode != NULL && + (dp->dvp_DevNode->dol_Type != DLT_DIRECTORY || !(dp->dvp_Flags & DVPF_ASSIGN))) { + + /* cleanup */ + if (dp->dvp_Flags & DVPF_UNLOCK) + UnLock(dp->dvp_Lock); + + FreeMem(dp, sizeof(struct DevProc)); + SetIoErr(ERROR_NO_MORE_ENTRIES); + return NULL; + } + + /* it's fine, we'll start from here */ + dl = dp->dvp_DevNode; + + /* lock the dos list here, to match the result of the next block */ + LockDosList(LDF_ALL | LDF_READ); + } + + /* otherwise we need to find a place to start in the doslist based on the + * name they passed in */ + else { + if (name == NULL || Strnicmp(name, "NIL:", 4) == 0) { + SetIoErr(ERROR_DEVICE_NOT_MOUNTED); + return NULL; + } + + /* allocate structure for return */ + if ((dp = AllocMem(sizeof(struct DevProc), MEMF_ANY | MEMF_CLEAR)) == NULL) { + SetIoErr(ERROR_NO_FREE_STORE); + return NULL; + } + + /* something real, work out what it's relative to */ + if (Strnicmp(name, "PROGDIR:", 8) == 0) { + lock = pr->pr_HomeDir; + /* I am not sure if these are correct but AOS does return + * non-NULL PROGDIR: handle even if pr_HomeDir is cleared */ + if (!lock) + lock = pr->pr_CurrentDir; + if (lock) { + fl = BADDR(lock); + dp->dvp_Port = fl->fl_Task; + dp->dvp_Lock = lock; + dp->dvp_DevNode = BADDR(fl->fl_Volume); + } else { + dp->dvp_Port = DOSBase->dl_Root->rn_BootProc; + dp->dvp_Lock = BNULL; + dp->dvp_DevNode = NULL; + } + dp->dvp_Flags = 0; + return dp; + } + + /* extract the volume name */ + len = SplitName(name, ':', vol, 0, sizeof(vol) - 1); + + /* if there wasn't one (or we found a lone ':') -> current dir */ + if (len <= 1) { + lock = baselock; + if (!lock) + lock = pr->pr_CurrentDir; + /* if we got NULL, then it's relative to the system root lock */ + if (lock != BNULL) { + fl = BADDR(lock); + dp->dvp_Port = fl->fl_Task; + dp->dvp_Lock = lock; + dp->dvp_DevNode = BADDR(fl->fl_Volume); + } else { + dp->dvp_Port = DOSBase->dl_Root->rn_BootProc; + dp->dvp_Lock = BNULL; + dp->dvp_DevNode = NULL; + } + + /* Jump to the root directory if name[0] == ':' */ + if (name[0] == ':') + dp->dvp_Lock = (dp->dvp_DevNode) ? dp->dvp_DevNode->dol_Lock : BNULL; + + dp->dvp_Flags = 0; + return dp; + } + + do { + /* now find the doslist entry for the named volume */ + dl = LockDosList(LDF_ALL | LDF_READ); + dl = FindDosEntry(dl, vol, LDF_ALL); + + /* not found, bail out */ + if (dl == NULL) { + UnLockDosList(LDF_ALL | LDF_READ); + + if (ErrorReport(ERROR_DEVICE_NOT_MOUNTED, REPORT_INSERT, (IPTR)vol, NULL) == DOSTRUE) { + FreeMem(dp, sizeof(struct DevProc)); + return NULL; + } + } + } while(dl == NULL); + } + + /* at this point, we have an allocated devproc in dp, the doslist is + * locked for read, and we have the entry for the named "volume" + * (device, assign, etc) in dl and a filename relative to that in name */ + + /* late assign. we resolve the target and then promote the doslist entry + * to full assign */ + if (dl->dol_Type == DLT_LATE) { + /* obtain a lock on the target */ + lock = Lock(dl->dol_misc.dol_assign.dol_AssignName, SHARED_LOCK); + + /* didn't find the target */ + if (lock == BNULL) { + UnLockDosList(LDF_ALL | LDF_READ); + FreeMem(dp, sizeof(struct DevProc)); + return NULL; + } + + /* Directly change assign type without calling AssignXXX(), + * mimics AOS behavior, AOS programs assume it is safe to + * keep LDF_WRITE lock while calling Lock("late assign:"); + */ + dl->dol_Type = DLT_DIRECTORY; + dl->dol_Lock = lock; + dl->dol_Task = ((struct FileLock*)BADDR(lock))->fl_Task; + FreeVec(dl->dol_misc.dol_assign.dol_AssignName); + dl->dol_misc.dol_assign.dol_AssignName = NULL; + + /* the added entry will be a DLT_DIRECTORY, so we can just copy the + * details in and get out of here */ + dp->dvp_Port = dl->dol_Task; + dp->dvp_Lock = dl->dol_Lock; + dp->dvp_Flags = 0; + dp->dvp_DevNode = dl; + + UnLockDosList(LDF_ALL | LDF_READ); + + return dp; + } + + /* nonbinding assign. like a late assign, but with no doslist promotion */ + if (dl->dol_Type == DLT_NONBINDING) { + lock = Lock(dl->dol_misc.dol_assign.dol_AssignName, SHARED_LOCK); + + /* just fill out the dp and return */ + dp->dvp_Port = ((struct FileLock *) BADDR(lock))->fl_Task; + dp->dvp_Lock = lock; + dp->dvp_Flags = DVPF_UNLOCK; /* remember to unlock in FreeDeviceNode() */ + dp->dvp_DevNode = dl; + + UnLockDosList(LDF_ALL | LDF_READ); + + return dp; + } + + /* devices and volumes are easy */ + if (dl->dol_Type == DLT_DEVICE || dl->dol_Type == DLT_VOLUME) + { + struct MsgPort *newhandler = NULL; + + if (dl->dol_Type == DLT_DEVICE) + { + /* Check if the handler is not started */ + newhandler = dl->dol_Task; + if (!newhandler) + { + D(bug("[GetDeviceProcRelative] Accessing device '%b', path='%s'\n", dl->dol_Name, origname)); + + /* + * Unlock before starting handler, handler may internally + * require dos list locks, for example to add volume node. + */ + UnLockDosList(LDF_ALL | LDF_READ); + + newhandler = RunHandler((struct DeviceNode *)dl, origname, DOSBase); + if (!newhandler) + { + FreeMem(dp, sizeof(struct DevProc)); + SetIoErr(ERROR_DEVICE_NOT_MOUNTED); + return NULL; + } + + LockDosList(LDF_ALL | LDF_READ); + } + } + else + { + res = TRUE; + + while (res && !dl->dol_Task) + { + D(bug("[GetDeviceProcRelative] Accessing offline volume '%b'\n", dl->dol_Name)); + res = !ErrorReport(ERROR_DEVICE_NOT_MOUNTED, REPORT_VOLUME, (IPTR)dl, NULL); + } + + if (!res) + { + UnLockDosList(LDF_ALL | LDF_READ); + FreeMem(dp, sizeof(struct DevProc)); + SetIoErr(ERROR_DEVICE_NOT_MOUNTED); + return NULL; + } + } + + /* + * A handler theoretically may choose to use custom MsgPort for communications. + * Pick up its preference if specified. + */ + dp->dvp_Port = dl->dol_Task ? dl->dol_Task : newhandler; + dp->dvp_Lock = BNULL; + dp->dvp_Flags = 0; + dp->dvp_DevNode = dl; + + UnLockDosList(LDF_ALL | LDF_READ); + + return dp; + } + + /* sanity check */ + if (dl->dol_Type != DLT_DIRECTORY) { + UnLockDosList(LDF_ALL | LDF_READ); + FreeMem(dp, sizeof(struct DevProc)); + kprintf("%s:%d: DosList entry 0x%p has unknown type %d. Probably a bug, report it!\n" + " GetDeviceProcRelative() called for '%s'\n", + __SRCFILENAME__, __LINE__, dl, dl->dol_Type, name); + SetIoErr(ERROR_BAD_NUMBER); + return NULL; + } + + /* real assigns. first, see if it's just pointing to a single dir */ + if (dp->dvp_Flags != DVPF_ASSIGN) { + /* just a plain assign, easy */ + dp->dvp_Port = dl->dol_Task; + dp->dvp_Lock = dl->dol_Lock; + dp->dvp_DevNode = dl; + + /* note multidirectory assigns so the caller knows to loop */ + dp->dvp_Flags = dl->dol_misc.dol_assign.dol_List != NULL ? DVPF_ASSIGN : 0; + + UnLockDosList(LDF_ALL | LDF_READ); + return dp; + } + + /* finally the tricky bit - multidirectory assigns */ + + /* if we're pointing at the "primary" lock, then we just take the first + * one in the list */ + if (dp->dvp_Lock == dl->dol_Lock) + dp->dvp_Lock = dl->dol_misc.dol_assign.dol_List->al_Lock; + + /* otherwise we're finding the next */ + else { + struct AssignList *al = dl->dol_misc.dol_assign.dol_List; + + /* find our current lock (ie the one we returned last time) */ + for (; al != NULL && al->al_Lock != dp->dvp_Lock; al = al->al_Next); + + /* if we didn't find it, or we didn't but there's none after it, then + * we've run out */ + if (al == NULL || (al = al->al_Next) == NULL) { + UnLockDosList(LDF_ALL | LDF_READ); + FreeMem(dp, sizeof(struct DevProc)); + + SetIoErr(ERROR_NO_MORE_ENTRIES); + return NULL; + } + + /* fill out the lock from the new entry */ + dp->dvp_Lock = al->al_Lock; + } + + /* final pieces */ + dp->dvp_Port = ((struct FileLock *) BADDR(dp->dvp_Lock))->fl_Task; + dp->dvp_Flags = DVPF_ASSIGN; + dp->dvp_DevNode = dl; + + UnLockDosList(LDF_READ|LDF_ALL); + /* phew */ + SetIoErr(0); + return dp; +} diff --git a/rom/dos/mmakefile.src b/rom/dos/mmakefile.src index ec6e099bc87..3c3353b1a95 100644 --- a/rom/dos/mmakefile.src +++ b/rom/dos/mmakefile.src @@ -47,8 +47,8 @@ FUNCTIONS := abortpkt addbuffers adddosentry addpart addsegment \ fault fgetc fgets filepart findarg findcliproc finddosentry findsegment \ findvar flush format fputc fputs fread freeargs freedeviceproc \ freedosentry freedosobject fwrite getargstr getconsoletask \ - getcurrentdirname getdeviceproc getfilesystask getprogramdir \ - getprogramname getprompt getseglistinfo getvar info inhibit \ + getcurrentdirname getdeviceproc getdeviceprocrelative getfilesystask \ + getprogramdir getprogramname getprompt getseglistinfo getvar info inhibit \ input internalunloadseg ioerr isfilesystem \ isinteractive loadseg lock lockdoslist lockrelative lockrecord lockrecords \ makedosentry makelink matchend matchfirst matchnext matchpattern \ From 8dbff393dd7da6dfe6e693245df05b9021adfe17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rob=20N=20=E2=98=85?= Date: Mon, 26 Apr 2021 17:12:12 +1000 Subject: [PATCH 6/8] dos: add IsFileSystemRelative --- rom/dos/dos.conf | 1 + rom/dos/isfilesystem.c | 41 +--------------- rom/dos/isfilesystemrelative.c | 87 ++++++++++++++++++++++++++++++++++ rom/dos/mmakefile.src | 2 +- 4 files changed, 91 insertions(+), 40 deletions(-) create mode 100644 rom/dos/isfilesystemrelative.c diff --git a/rom/dos/dos.conf b/rom/dos/dos.conf index 25b38650bb0..a6499cc50b1 100644 --- a/rom/dos/dos.conf +++ b/rom/dos/dos.conf @@ -259,4 +259,5 @@ BOOL AssignAddToList(CONST_STRPTR name, BPTR lock, ULONG position) (D1, D2, D3) BPTR LockRelative(BPTR lock, CONST_STRPTR name, LONG accessMode) (D1,D2,D3) BPTR OpenRelative(BPTR lock, CONST_STRPTR name, LONG accessMode) (D1,D2,D3) struct DevProc *GetDeviceProcRelative(BPTR lock, CONST_STRPTR name, struct DevProc *dp) (D1,D2,D3) +BOOL IsFileSystemRelative(BPTR lock, CONST_STRPTR devicename) (D1,D2) ##end functionlist diff --git a/rom/dos/isfilesystem.c b/rom/dos/isfilesystem.c index cbc54834105..40624646ed3 100644 --- a/rom/dos/isfilesystem.c +++ b/rom/dos/isfilesystem.c @@ -4,12 +4,7 @@ Desc: Check if a device is a filesystem. */ -#include -#include -#include -#include #include "dos_intern.h" -#include /***************************************************************************** @@ -53,39 +48,7 @@ { AROS_LIBFUNC_INIT - LONG err = ERROR_OBJECT_NOT_FOUND; - LONG code = DOSFALSE; - struct DevProc *dvp = NULL; - - /* The Open() aliases '*' and 'CONSOLE:' - * are never filesystems - */ - if (Stricmp(devicename, "*") == 0 || - Stricmp(devicename, "CONSOLE:") == 0) { - SetIoErr(err); - return code; - } - - /* We can't call GetDeviceProc() on CON: nor RAW:, - * since that will (implicitly) cause a window to - * open. - */ - if (Stricmp(devicename, "CON:") == 0 || - Stricmp(devicename, "RAW:") == 0) { - SetIoErr(err); - return code; - } - - - if ((dvp = GetDeviceProc(devicename, dvp))) { - if (dvp->dvp_Port != NULL) // No port? Not a filesystem - code = dopacket0(DOSBase, NULL, dvp->dvp_Port, ACTION_IS_FILESYSTEM); - FreeDeviceProc(dvp); - } else { - SetIoErr(err); - } - - return code; + return IsFileSystemRelative(NULL, devicename); AROS_LIBFUNC_EXIT -} /* IsFilesystem */ +} /* IsFileSystem */ diff --git a/rom/dos/isfilesystemrelative.c b/rom/dos/isfilesystemrelative.c new file mode 100644 index 00000000000..4a273cd39b9 --- /dev/null +++ b/rom/dos/isfilesystemrelative.c @@ -0,0 +1,87 @@ +/* + Copyright (C) 1995-2008, The AROS Development Team. All rights reserved. + + Desc: Check if a device is a filesystem. +*/ + +#include +#include +#include +#include +#include "dos_intern.h" +#include + +/***************************************************************************** + + NAME */ +#include + + AROS_LH2(BOOL, IsFileSystemRelative, + +/* SYNOPSIS */ + AROS_LHA(BPTR, lock, D1), + AROS_LHA(CONST_STRPTR, devicename, D2), + +/* LOCATION */ + struct DosLibrary *, DOSBase, 230, Dos) + +/* FUNCTION + Query the device whether it is a filesystem. + + INPUTS + lock - existing lock to compute filename from + devicename - Name of the device to query. + + RESULT + TRUE if the device is a filesystem, FALSE otherwise. + + NOTES + DF0:, HD0:, ... are filesystems. + CON:, PIPE:, AUX:, ... are not + + In AmigaOS if devicename contains no ":" then result + is always TRUE. Also volume and assign names return + TRUE. + + This call is AROS-specific. + +*****************************************************************************/ +{ + AROS_LIBFUNC_INIT + + LONG err = ERROR_OBJECT_NOT_FOUND; + LONG code = DOSFALSE; + struct DevProc *dvp = NULL; + + /* The Open() aliases '*' and 'CONSOLE:' + * are never filesystems + */ + if (Stricmp(devicename, "*") == 0 || + Stricmp(devicename, "CONSOLE:") == 0) { + SetIoErr(err); + return code; + } + + /* We can't call GetDeviceProc() on CON: nor RAW:, + * since that will (implicitly) cause a window to + * open. + */ + if (Stricmp(devicename, "CON:") == 0 || + Stricmp(devicename, "RAW:") == 0) { + SetIoErr(err); + return code; + } + + + if ((dvp = GetDeviceProcRelative(lock, devicename, dvp))) { + if (dvp->dvp_Port != NULL) // No port? Not a filesystem + code = dopacket0(DOSBase, NULL, dvp->dvp_Port, ACTION_IS_FILESYSTEM); + FreeDeviceProc(dvp); + } else { + SetIoErr(err); + } + + return code; + + AROS_LIBFUNC_EXIT +} /* IsFileSystemRelative */ diff --git a/rom/dos/mmakefile.src b/rom/dos/mmakefile.src index 3c3353b1a95..a04d3f4373b 100644 --- a/rom/dos/mmakefile.src +++ b/rom/dos/mmakefile.src @@ -49,7 +49,7 @@ FUNCTIONS := abortpkt addbuffers adddosentry addpart addsegment \ freedosentry freedosobject fwrite getargstr getconsoletask \ getcurrentdirname getdeviceproc getdeviceprocrelative getfilesystask \ getprogramdir getprogramname getprompt getseglistinfo getvar info inhibit \ - input internalunloadseg ioerr isfilesystem \ + input internalunloadseg ioerr isfilesystem isfilesystemrelative \ isinteractive loadseg lock lockdoslist lockrelative lockrecord lockrecords \ makedosentry makelink matchend matchfirst matchnext matchpattern \ matchpatternnocase maxcli namefromfh namefromlock newloadseg nextdosentry nil \ From 924cd21a8d3aaa4d006466e49b59c602991fdd36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rob=20N=20=E2=98=85?= Date: Tue, 27 Apr 2021 20:49:35 +1000 Subject: [PATCH 7/8] dos: relative variants for a variety of simple calls These all just wrap getpacketinfo in a nice easy dumb way. --- rom/dos/createdir.c | 19 +-------- rom/dos/createdirrelative.c | 62 +++++++++++++++++++++++++++ rom/dos/deletefile.c | 19 +-------- rom/dos/deletefilerelative.c | 60 ++++++++++++++++++++++++++ rom/dos/dos.conf | 7 +++ rom/dos/makelink.c | 16 +------ rom/dos/makelinkrelative.c | 70 ++++++++++++++++++++++++++++++ rom/dos/mmakefile.src | 16 ++++--- rom/dos/setcomment.c | 30 +------------ rom/dos/setcommentrelative.c | 76 +++++++++++++++++++++++++++++++++ rom/dos/setfiledate.c | 12 +----- rom/dos/setfiledaterelative.c | 61 ++++++++++++++++++++++++++ rom/dos/setowner.c | 16 +------ rom/dos/setownerrelative.c | 57 +++++++++++++++++++++++++ rom/dos/setprotection.c | 18 +------- rom/dos/setprotectionrelative.c | 57 +++++++++++++++++++++++++ 16 files changed, 467 insertions(+), 129 deletions(-) create mode 100644 rom/dos/createdirrelative.c create mode 100644 rom/dos/deletefilerelative.c create mode 100644 rom/dos/makelinkrelative.c create mode 100644 rom/dos/setcommentrelative.c create mode 100644 rom/dos/setfiledaterelative.c create mode 100644 rom/dos/setownerrelative.c create mode 100644 rom/dos/setprotectionrelative.c diff --git a/rom/dos/createdir.c b/rom/dos/createdir.c index 460dd3dbe14..b4ace50c422 100644 --- a/rom/dos/createdir.c +++ b/rom/dos/createdir.c @@ -4,13 +4,6 @@ Desc: Create a new directory. */ -#include -#include -#include -#include -#include -#include -#include #include "dos_intern.h" /***************************************************************************** @@ -51,17 +44,7 @@ { AROS_LIBFUNC_INIT - BPTR lock = BNULL; - struct PacketHelperStruct phs; - - D(bug("[CreateDir] '%s'\n", name)); - - if (getpacketinfo(DOSBase, BNULL, name, &phs)) { - lock = (BPTR)dopacket2(DOSBase, NULL, phs.port, ACTION_CREATE_DIR, phs.lock, phs.name); - freepacketinfo(DOSBase, &phs); - } - - return lock; + return CreateDirRelative(BNULL, name); AROS_LIBFUNC_EXIT } /* CreateDir */ diff --git a/rom/dos/createdirrelative.c b/rom/dos/createdirrelative.c new file mode 100644 index 00000000000..dc561b5eb4e --- /dev/null +++ b/rom/dos/createdirrelative.c @@ -0,0 +1,62 @@ +/* + Copyright (C) 1995-2013, The AROS Development Team. All rights reserved. + + Desc: Create a new directory. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include "dos_intern.h" + +/***************************************************************************** + + NAME */ +#include + + AROS_LH2(BPTR, CreateDirRelative, + +/* SYNOPSIS */ + AROS_LHA(BPTR, lock, D1), + AROS_LHA(CONST_STRPTR, name, D2), + +/* LOCATION */ + struct DosLibrary *, DOSBase, 231, Dos) + +/* FUNCTION + Creates a new directory under the given name. If all went well, an + exclusive lock on the new diretory is returned. + + INPUTS + name - NUL terminated name. + + RESULT + Exclusive lock to the new directory or 0 if it couldn't be created. + IoErr() gives additional information in that case. + + NOTES + This call is AROS-specific. + +*****************************************************************************/ +{ + AROS_LIBFUNC_INIT + + BPTR lock = BNULL; + struct PacketHelperStruct phs; + + D(bug("[CreateDirRelative] lock=0x%p '%s'\n", lock, name)); + + if (getpacketinfo(DOSBase, lock, name, &phs)) { + lock = (BPTR)dopacket2(DOSBase, NULL, phs.port, ACTION_CREATE_DIR, phs.lock, phs.name); + freepacketinfo(DOSBase, &phs); + } + + return lock; + + AROS_LIBFUNC_EXIT +} /* CreateDirRelative */ + diff --git a/rom/dos/deletefile.c b/rom/dos/deletefile.c index 6ec34602c3b..6c0404ef647 100644 --- a/rom/dos/deletefile.c +++ b/rom/dos/deletefile.c @@ -3,13 +3,6 @@ Desc: Delete a file or directory. */ -#include -#include -#include -#include -#include -#include -#include #include "dos_intern.h" /***************************************************************************** @@ -50,17 +43,7 @@ { AROS_LIBFUNC_INIT - LONG status = 0; - struct PacketHelperStruct phs; - - D(bug("[DeleteFile] '%s'\n", name)); - - if (getpacketinfo(DOSBase, BNULL, name, &phs)) { - status = dopacket2(DOSBase, NULL, phs.port, ACTION_DELETE_OBJECT, phs.lock, phs.name); - freepacketinfo(DOSBase, &phs); - } - - return status; + return DeleteFileRelative(BNULL, name); AROS_LIBFUNC_EXIT } /* DeleteFile */ diff --git a/rom/dos/deletefilerelative.c b/rom/dos/deletefilerelative.c new file mode 100644 index 00000000000..df243b79369 --- /dev/null +++ b/rom/dos/deletefilerelative.c @@ -0,0 +1,60 @@ +/* + Copyright (C) 1995-2013, The AROS Development Team. All rights reserved. + + Desc: Delete a file or directory. +*/ +#include +#include +#include +#include +#include +#include +#include +#include "dos_intern.h" + +/***************************************************************************** + + NAME */ +#include + + AROS_LH2(BOOL, DeleteFileRelative, + +/* SYNOPSIS */ + AROS_LHA(BPTR, lock, D1), + AROS_LHA(CONST_STRPTR, name, D2), + +/* LOCATION */ + struct DosLibrary *, DOSBase, 232, Dos) + +/* FUNCTION + Tries to delete a file or directory by a given name. + May fail if the file is in use or protected from deletion. + + INPUTS + name - NUL terminated name. + + RESULT + != 0 if the file is gone, 0 if is still there. + IoErr() gives additional information in that case. + + NOTES + This call is AROS-specific. + +*****************************************************************************/ +{ + AROS_LIBFUNC_INIT + + LONG status = 0; + struct PacketHelperStruct phs; + + D(bug("[DeleteFileRelative] lock=0x%p '%s'\n", lock, name)); + + if (getpacketinfo(DOSBase, lock, name, &phs)) { + status = dopacket2(DOSBase, NULL, phs.port, ACTION_DELETE_OBJECT, phs.lock, phs.name); + freepacketinfo(DOSBase, &phs); + } + + return status; + + AROS_LIBFUNC_EXIT +} /* DeleteFileRelative */ diff --git a/rom/dos/dos.conf b/rom/dos/dos.conf index a6499cc50b1..4587ab7dbdc 100644 --- a/rom/dos/dos.conf +++ b/rom/dos/dos.conf @@ -260,4 +260,11 @@ BPTR LockRelative(BPTR lock, CONST_STRPTR name, LONG accessMode) (D1,D2,D3) BPTR OpenRelative(BPTR lock, CONST_STRPTR name, LONG accessMode) (D1,D2,D3) struct DevProc *GetDeviceProcRelative(BPTR lock, CONST_STRPTR name, struct DevProc *dp) (D1,D2,D3) BOOL IsFileSystemRelative(BPTR lock, CONST_STRPTR devicename) (D1,D2) +BPTR CreateDirRelative(BPTR lock, CONST_STRPTR name) (D1,D2) +BOOL DeleteFileRelative(BPTR lock, CONST_STRPTR name) (D1,D2) +LONG SetCommentRelative(BPTR lock, CONST_STRPTR name, CONST_STRPTR comment) (D1,D2,D3) +BOOL SetFileDateRelative(BPTR lock, CONST_STRPTR name, const struct DateStamp *date) (D1,D2,D3) +BOOL SetOwnerRelative(BPTR lock, CONST_STRPTR name, ULONG owner_info) (D1,D2,D3) +LONG SetProtectionRelative(BPTR lock, CONST_STRPTR name, ULONG protect) (D1,D2,D3) +LONG MakeLinkRelative(BPTR lock, CONST_STRPTR name, SIPTR dest, LONG soft) (D1,D2,D3,D4) ##end functionlist diff --git a/rom/dos/makelink.c b/rom/dos/makelink.c index 4233f3a525f..af2254bab07 100644 --- a/rom/dos/makelink.c +++ b/rom/dos/makelink.c @@ -3,14 +3,11 @@ Desc: Create a hard or soft link. */ -#include #include "dos_intern.h" -#include /***************************************************************************** NAME */ -#include #include AROS_LH3(LONG, MakeLink, @@ -60,18 +57,7 @@ { AROS_LIBFUNC_INIT - struct PacketHelperStruct phs; - LONG status; - - status = DOSFALSE; - if (getpacketinfo(DOSBase, BNULL, name, &phs)) - { - status = dopacket4(DOSBase, NULL, phs.port, ACTION_MAKE_LINK, - phs.lock, phs.name, (SIPTR)dest, soft ? LINK_SOFT: LINK_HARD); - freepacketinfo(DOSBase, &phs); - } - - return status; + return MakeLinkRelative(BNULL, name, dest, soft); AROS_LIBFUNC_EXIT } /* MakeLink */ diff --git a/rom/dos/makelinkrelative.c b/rom/dos/makelinkrelative.c new file mode 100644 index 00000000000..0b284f696ec --- /dev/null +++ b/rom/dos/makelinkrelative.c @@ -0,0 +1,70 @@ +/* + Copyright (C) 1995-2013, The AROS Development Team. All rights reserved. + + Desc: Create a hard or soft link. +*/ +#include +#include "dos_intern.h" +#include + +/***************************************************************************** + + NAME */ +#include +#include + + AROS_LH4(LONG, MakeLinkRelative, + +/* SYNOPSIS */ + AROS_LHA(BPTR, lock, D1), + AROS_LHA(CONST_STRPTR, name, D2), + AROS_LHA(SIPTR, dest, D3), + AROS_LHA(LONG, soft, D4), + +/* LOCATION */ + struct DosLibrary *, DOSBase, 237, Dos) + +/* FUNCTION + MakeLink() will create a link between two files or directories. + A link is a filesystem object that refers to another file. + + A soft link refers to another file or directory by name, and is + resolved by the filesystem and the caller. Soft links are not + restricted to the same volume and the target does not have to exist. + + A hard link refers to another file by the location on a disk, and + is resolved by the filesystem. Hard links are restricted to files + or directories on the same volume. + + INPUTS + name - The name of the link to create + dest - If 'soft' is TRUE this must be a filename; if it is FALSE a lock + pointing to the file to be hard-linked must be provided + soft - TRUE, if a soft link is to be created, FALSE for a hard link + + RESULT + boolean - DOSTRUE or DOSFALSE. On error, IoErr() will contain more + information. + + NOTES + This call is AROS-specific. + +*****************************************************************************/ +{ + AROS_LIBFUNC_INIT + + struct PacketHelperStruct phs; + LONG status; + + status = DOSFALSE; + if (getpacketinfo(DOSBase, lock, name, &phs)) + { + status = dopacket4(DOSBase, NULL, phs.port, ACTION_MAKE_LINK, + phs.lock, phs.name, (SIPTR)dest, soft ? LINK_SOFT: LINK_HARD); + freepacketinfo(DOSBase, &phs); + } + + return status; + + AROS_LIBFUNC_EXIT +} /* MakeLinkRelative */ diff --git a/rom/dos/mmakefile.src b/rom/dos/mmakefile.src index a04d3f4373b..d1c554858c1 100644 --- a/rom/dos/mmakefile.src +++ b/rom/dos/mmakefile.src @@ -39,9 +39,9 @@ FUNCTIONS := abortpkt addbuffers adddosentry addpart addsegment \ allocdosobject assignadd assignaddtolist assignlate assignlock \ assignpath attemptlockdoslist changemode checksignal \ cli cliinit cliinitnewcli cliinitrun \ - close comparedates createdir createnewproc \ + close comparedates createdir createdirrelative createnewproc \ createproc currentdir datestamp datetostr delay deletefile \ - deletevar deviceproc displayerror dopkt dosgetstring \ + deletefilerelative deletevar deviceproc displayerror dopkt dosgetstring \ duplock duplockfromfh endnotify errorreport \ exall exallend examine examinefh execute exit exnext \ fault fgetc fgets filepart findarg findcliproc finddosentry findsegment \ @@ -51,16 +51,18 @@ FUNCTIONS := abortpkt addbuffers adddosentry addpart addsegment \ getprogramdir getprogramname getprompt getseglistinfo getvar info inhibit \ input internalunloadseg ioerr isfilesystem isfilesystemrelative \ isinteractive loadseg lock lockdoslist lockrelative lockrecord lockrecords \ - makedosentry makelink matchend matchfirst matchnext matchpattern \ + makedosentry makelink makelinkrelative \ + matchend matchfirst matchnext matchpattern \ matchpatternnocase maxcli namefromfh namefromlock newloadseg nextdosentry nil \ open openfromlock openrelative output parentdir parentoffh parsepattern \ parsepatternnocase pathpart printfault putstr read readargs \ readitem relabel readlink remassignlist remdosentry remsegment rename \ replypkt runcommand samedevice samelock scanvars seek \ - selectinput selectoutput sendpkt setargstr setcomment setconsoletask \ - setcurrentdirname setfiledate setfilesize setfilesystask \ - setioerr setmode setowner setprogramdir setprogramname \ - setprompt setprotection setvar setvbuf splitname startnotify \ + selectinput selectoutput sendpkt setargstr setcomment setcommentrelative \ + setconsoletask setcurrentdirname setfiledate setfiledaterelative \ + setfilesize setfilesystask setioerr setmode setowner setownerrelative \ + setprogramdir setprogramname setprompt setprotection setprotectionrelative \ + setvar setvbuf splitname startnotify \ strtodate strtolong systemtaglist ungetc unloadseg unlock \ unlockdoslist unlockrecord unlockrecords vfprintf vfwritef \ vprintf waitforchar waitpkt write writechars runhandler diff --git a/rom/dos/setcomment.c b/rom/dos/setcomment.c index dd6e9b43eff..94f47797e6c 100644 --- a/rom/dos/setcomment.c +++ b/rom/dos/setcomment.c @@ -4,14 +4,6 @@ Desc: Set a filecomment. */ -#include -#include -#include -#include -#include - -#include - #include "dos_intern.h" /***************************************************************************** @@ -56,27 +48,7 @@ { AROS_LIBFUNC_INIT - struct PacketHelperStruct phs; - LONG status = DOSFALSE; - - D(bug("[SetComment] '%s' '%s'\n", name, comment)); - if (strlen(comment)>MAXCOMMENTLENGTH) - { - SetIoErr(ERROR_COMMENT_TOO_BIG); - return status; - } - if (getpacketinfo(DOSBase, BNULL, name, &phs)) { - BSTR com = C2BSTR(comment); - if (com) { - status = dopacket4(DOSBase, NULL, phs.port, ACTION_SET_COMMENT, (SIPTR)NULL, phs.lock, phs.name, com); - FREEC2BSTR(com); - } else { - SetIoErr(ERROR_NO_FREE_STORE); - } - freepacketinfo(DOSBase, &phs); - } - - return status; + return SetCommentRelative(BNULL, name, comment); AROS_LIBFUNC_EXIT } /* SetComment */ diff --git a/rom/dos/setcommentrelative.c b/rom/dos/setcommentrelative.c new file mode 100644 index 00000000000..83759cbad18 --- /dev/null +++ b/rom/dos/setcommentrelative.c @@ -0,0 +1,76 @@ +/* + Copyright (C) 1995-2008, The AROS Development Team. All rights reserved. + + Desc: Set a filecomment. +*/ + +#include +#include +#include +#include +#include + +#include + +#include "dos_intern.h" + +/***************************************************************************** + + NAME */ +#include + + AROS_LH3(LONG, SetCommentRelative, + +/* SYNOPSIS */ + AROS_LHA(BPTR, lock, D1), + AROS_LHA(CONST_STRPTR, name, D2), + AROS_LHA(CONST_STRPTR, comment, D3), + +/* LOCATION */ + struct DosLibrary *, DOSBase, 233, Dos) + +/* FUNCTION + Change the comment on a file or directory. The comment may be any + NUL-terminated string. The supported size varies from filesystem + to filesystem. In order to clear an existing comment, an empty + string should be specified. + + INPUTS + name - name of the file + comment - new comment for the file. + + RESULT + Boolean success indicator. IoErr() gives additional information upon + failure. + + NOTES + This call is AROS-specific. + +*****************************************************************************/ +{ + AROS_LIBFUNC_INIT + + struct PacketHelperStruct phs; + LONG status = DOSFALSE; + + D(bug("[SetCommentRelative] lock=0x%p '%s' '%s'\n", lock, name, comment)); + if (strlen(comment)>MAXCOMMENTLENGTH) + { + SetIoErr(ERROR_COMMENT_TOO_BIG); + return status; + } + if (getpacketinfo(DOSBase, lock, name, &phs)) { + BSTR com = C2BSTR(comment); + if (com) { + status = dopacket4(DOSBase, NULL, phs.port, ACTION_SET_COMMENT, (SIPTR)NULL, phs.lock, phs.name, com); + FREEC2BSTR(com); + } else { + SetIoErr(ERROR_NO_FREE_STORE); + } + freepacketinfo(DOSBase, &phs); + } + + return status; + + AROS_LIBFUNC_EXIT +} /* SetCommentRelative */ diff --git a/rom/dos/setfiledate.c b/rom/dos/setfiledate.c index 88d8fbc8093..4ccd5957c63 100644 --- a/rom/dos/setfiledate.c +++ b/rom/dos/setfiledate.c @@ -51,17 +51,7 @@ { AROS_LIBFUNC_INIT - struct PacketHelperStruct phs; - LONG status = DOSFALSE; - - D(bug("[SetFileDate] '%s' %x\n", name, date)); - - if (getpacketinfo(DOSBase, BNULL, name, &phs)) { - status = dopacket4(DOSBase, NULL, phs.port, ACTION_SET_DATE, (IPTR)NULL, phs.lock, phs.name, (IPTR)date); - freepacketinfo(DOSBase, &phs); - } - - return status; + return SetFileDateRelative(BNULL, name, date); AROS_LIBFUNC_EXIT } /* SetFileDate */ diff --git a/rom/dos/setfiledaterelative.c b/rom/dos/setfiledaterelative.c new file mode 100644 index 00000000000..1ba8ae18f7a --- /dev/null +++ b/rom/dos/setfiledaterelative.c @@ -0,0 +1,61 @@ +/* + Copyright (C) 1995-2008, The AROS Development Team. All rights reserved. + + Desc: Change the date of a file. +*/ + +#include +#include +#include +#include +#include +#include "dos_intern.h" + +/***************************************************************************** + + NAME */ +#include +#include + + AROS_LH3(BOOL, SetFileDateRelative, + +/* SYNOPSIS */ + AROS_LHA(BPTR, lock, D1), + AROS_LHA(CONST_STRPTR, name, D2), + AROS_LHA(const struct DateStamp *, date, D3), + +/* LOCATION */ + struct DosLibrary *, DOSBase, 234, Dos) + +/* FUNCTION + Change the modification time of a file or directory. + + INPUTS + name - name of the file + date - new file time + + RESULT + Boolean success indicator. IoErr() gives additional information upon + failure. + + NOTES + This call is AROS-specific. + +*****************************************************************************/ +{ + AROS_LIBFUNC_INIT + + struct PacketHelperStruct phs; + LONG status = DOSFALSE; + + D(bug("[SetFileDateRelative] lock=0x%p '%s' %x\n", lock, name, date)); + + if (getpacketinfo(DOSBase, lock, name, &phs)) { + status = dopacket4(DOSBase, NULL, phs.port, ACTION_SET_DATE, (IPTR)NULL, phs.lock, phs.name, (IPTR)date); + freepacketinfo(DOSBase, &phs); + } + + return status; + + AROS_LIBFUNC_EXIT +} /* SetFileDateRelative */ diff --git a/rom/dos/setowner.c b/rom/dos/setowner.c index 2a3ae481717..bdae44db606 100644 --- a/rom/dos/setowner.c +++ b/rom/dos/setowner.c @@ -3,10 +3,6 @@ Desc: Set the owner of a file. */ -#include -#include -#include -#include #include "dos_intern.h" /***************************************************************************** @@ -47,17 +43,7 @@ { AROS_LIBFUNC_INIT - struct PacketHelperStruct phs; - LONG status = DOSFALSE; - - D(bug("[SetOwner] '%s' %x\n", name, owner_info)); - - if (getpacketinfo(DOSBase, BNULL, name, &phs)) { - status = dopacket4(DOSBase, NULL, phs.port, ACTION_SET_OWNER, (IPTR)NULL, phs.lock, phs.name, (IPTR)owner_info); - freepacketinfo(DOSBase, &phs); - } - - return status; + return SetOwnerRelative(BNULL, name, owner_info); AROS_LIBFUNC_EXIT } /* SetOwner */ diff --git a/rom/dos/setownerrelative.c b/rom/dos/setownerrelative.c new file mode 100644 index 00000000000..1ba9de3f5e4 --- /dev/null +++ b/rom/dos/setownerrelative.c @@ -0,0 +1,57 @@ +/* + Copyright (C) 1995-2013, The AROS Development Team. All rights reserved. + + Desc: Set the owner of a file. +*/ +#include +#include +#include +#include +#include "dos_intern.h" + +/***************************************************************************** + + NAME */ +#include + + AROS_LH3(BOOL, SetOwnerRelative, + +/* SYNOPSIS */ + AROS_LHA(BPTR, lock, D1), + AROS_LHA(STRPTR, name, D2), + AROS_LHA(ULONG, owner_info, D3), + +/* LOCATION */ + struct DosLibrary *, DOSBase, 235, Dos) + +/* FUNCTION + + INPUTS + name - name of the file + owner_info - (UID << 16) + GID + + RESULT + != 0 if all went well, 0 else. IoErr() gives additional + information in that case. + + NOTES + This call is AROS-specific. + +*****************************************************************************/ +{ + AROS_LIBFUNC_INIT + + struct PacketHelperStruct phs; + LONG status = DOSFALSE; + + D(bug("[SetOwnerRelative] lock=0x%p '%s' %x\n", lock, name, owner_info)); + + if (getpacketinfo(DOSBase, lock, name, &phs)) { + status = dopacket4(DOSBase, NULL, phs.port, ACTION_SET_OWNER, (IPTR)NULL, phs.lock, phs.name, (IPTR)owner_info); + freepacketinfo(DOSBase, &phs); + } + + return status; + + AROS_LIBFUNC_EXIT +} /* SetOwnerRelative */ diff --git a/rom/dos/setprotection.c b/rom/dos/setprotection.c index 43612d0ea92..9bd09060ad2 100644 --- a/rom/dos/setprotection.c +++ b/rom/dos/setprotection.c @@ -3,10 +3,6 @@ Desc: Set the protection bits of a file. */ -#include -#include -#include -#include #include "dos_intern.h" /***************************************************************************** @@ -46,18 +42,8 @@ *****************************************************************************/ { AROS_LIBFUNC_INIT - - LONG status = 0; - struct PacketHelperStruct phs; - - D(bug("[SetProtection] '%s':%x\n", name, protect)); - - if (getpacketinfo(DOSBase, BNULL, name, &phs)) { - status = dopacket4(DOSBase, NULL, phs.port, ACTION_SET_PROTECT, BNULL, phs.lock, phs.name, protect); - freepacketinfo(DOSBase, &phs); - } - - return status; + + return SetProtectionRelative(BNULL, name, protect); AROS_LIBFUNC_EXIT } /* SetProtection */ diff --git a/rom/dos/setprotectionrelative.c b/rom/dos/setprotectionrelative.c new file mode 100644 index 00000000000..a2421da5ed0 --- /dev/null +++ b/rom/dos/setprotectionrelative.c @@ -0,0 +1,57 @@ +/* + Copyright (C) 1995-2007, The AROS Development Team. All rights reserved. + + Desc: Set the protection bits of a file. +*/ +#include +#include +#include +#include +#include "dos_intern.h" + +/***************************************************************************** + + NAME */ +#include + + AROS_LH3(LONG, SetProtectionRelative, + +/* SYNOPSIS */ + AROS_LHA(BPTR, lock, D1), + AROS_LHA(CONST_STRPTR, name, D2), + AROS_LHA(ULONG, protect, D3), + +/* LOCATION */ + struct DosLibrary *, DOSBase, 236, Dos) + +/* FUNCTION + + INPUTS + name - name of the file + protect - new protection bits + + RESULT + != 0 if all went well, 0 else. IoErr() gives additional + information in that case. + + NOTES + This call is AROS-specific. + +*****************************************************************************/ +{ + AROS_LIBFUNC_INIT + + LONG status = 0; + struct PacketHelperStruct phs; + + D(bug("[SetProtectionRelative] lock=0x%p '%s':%x\n", lock, name, protect)); + + if (getpacketinfo(DOSBase, lock, name, &phs)) { + status = dopacket4(DOSBase, NULL, phs.port, ACTION_SET_PROTECT, BNULL, phs.lock, phs.name, protect); + freepacketinfo(DOSBase, &phs); + } + + return status; + + AROS_LIBFUNC_EXIT +} /* SetProtectionRelative */ From 91d6b17cf81856fd01b8d75998f7d26bedcb8c26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rob=20N=20=E2=98=85?= Date: Wed, 28 Apr 2021 12:02:27 +1000 Subject: [PATCH 8/8] dos: add RenameRelative --- rom/dos/dos.conf | 1 + rom/dos/mmakefile.src | 3 +- rom/dos/rename.c | 128 +------------------------ rom/dos/renamerelative.c | 197 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 201 insertions(+), 128 deletions(-) create mode 100644 rom/dos/renamerelative.c diff --git a/rom/dos/dos.conf b/rom/dos/dos.conf index 4587ab7dbdc..14a89501ac7 100644 --- a/rom/dos/dos.conf +++ b/rom/dos/dos.conf @@ -267,4 +267,5 @@ BOOL SetFileDateRelative(BPTR lock, CONST_STRPTR name, const struct DateStamp *d BOOL SetOwnerRelative(BPTR lock, CONST_STRPTR name, ULONG owner_info) (D1,D2,D3) LONG SetProtectionRelative(BPTR lock, CONST_STRPTR name, ULONG protect) (D1,D2,D3) LONG MakeLinkRelative(BPTR lock, CONST_STRPTR name, SIPTR dest, LONG soft) (D1,D2,D3,D4) +LONG RenameRelative(BPTR oldLock, CONST_STRPTR oldName, BPTR newLock, CONST_STRPTR newName) (D1,D2,D3,D4) ##end functionlist diff --git a/rom/dos/mmakefile.src b/rom/dos/mmakefile.src index d1c554858c1..a5b02d3d5be 100644 --- a/rom/dos/mmakefile.src +++ b/rom/dos/mmakefile.src @@ -56,7 +56,8 @@ FUNCTIONS := abortpkt addbuffers adddosentry addpart addsegment \ matchpatternnocase maxcli namefromfh namefromlock newloadseg nextdosentry nil \ open openfromlock openrelative output parentdir parentoffh parsepattern \ parsepatternnocase pathpart printfault putstr read readargs \ - readitem relabel readlink remassignlist remdosentry remsegment rename \ + readitem relabel readlink remassignlist remdosentry remsegment \ + rename renamerelative \ replypkt runcommand samedevice samelock scanvars seek \ selectinput selectoutput sendpkt setargstr setcomment setcommentrelative \ setconsoletask setcurrentdirname setfiledate setfiledaterelative \ diff --git a/rom/dos/rename.c b/rom/dos/rename.c index 71281a49a76..11185587cbf 100644 --- a/rom/dos/rename.c +++ b/rom/dos/rename.c @@ -4,10 +4,7 @@ Desc: Rename a file */ -#include -#include #include "dos_intern.h" -#include /***************************************************************************** @@ -50,130 +47,7 @@ { AROS_LIBFUNC_INIT - struct DevProc *olddvp, *newdvp; - LONG status; - struct Process *me = (struct Process *)FindTask(NULL); - char buf1[256], vol[32]; - char buf2[256]; - int len; - BSTR bstrNewName, bstrOldName; - - ASSERT_VALID_PROCESS(me); - - len = SplitName(oldName, ':', vol, 0, sizeof(vol) - 1); - - if (len > 0) - { - /* get real name */ - BPTR lock = Lock(oldName, SHARED_LOCK); - if (lock) - { - if (NameFromLock(lock, buf1, sizeof(buf1) - 1)) - oldName = buf1; - UnLock(lock); - } - } - else - { - /* convert to absolute path */ - if (NameFromLock(me->pr_CurrentDir, buf1, sizeof(buf1) - 1)) - { - int namelen = strlen(oldName); - len = strlen(buf1); - if (len + namelen < sizeof(buf1) - 1) - { - if (buf1[len - 1] != ':') - buf1[len++] = '/'; - CopyMem(oldName, buf1 + len, namelen + 1); - oldName = buf1; - } - } - } - - len = SplitName(newName, ':', vol, 0, sizeof(vol) - 1); - - if (len > 0) - { - /* get real name of destination path */ - BPTR lock; - char *pos; - const char *pos2; - - strcpy(buf2, newName); - pos = strrchr(buf2, '/'); - if (!pos) - { - pos = buf2 + len; - *pos = '\0'; - } - else - *(++pos) = '\0'; /* Keep slashes in name, to support a/b//c => a/c case */ - - lock = Lock(buf2, SHARED_LOCK); - if (lock) - { - if (NameFromLock(lock, buf2, sizeof(buf2) - 1)) - { - int namelen; - len = strlen(buf2); - pos2 = newName + (int)(pos - buf2); - namelen = strlen(pos2); - if (len + namelen < sizeof(buf2) - 1) - { - if (buf2[len - 1] != ':') - buf2[len++] = '/'; - CopyMem(pos2, buf2 + len, namelen + 1); - newName = buf2; - } - } - UnLock(lock); - } - } - else - { - /* convert to absolute path */ - if (NameFromLock(me->pr_CurrentDir, buf2, sizeof(buf2) - 1)) - { - int namelen = strlen(newName); - len = strlen(buf2); - if (len + namelen < sizeof(buf2) - 1) - { - if (buf2[len - 1] != ':') - buf2[len++] = '/'; - CopyMem(newName, buf2 + len, namelen + 1); - newName = buf2; - } - } - } - - D(bug("[Dos] rename %s %s\n", oldName, newName)); - - /* get device pointers */ - if ((olddvp = GetDeviceProc(oldName, NULL)) == NULL || - (newdvp = GetDeviceProc(newName, NULL)) == NULL) { - FreeDeviceProc(olddvp); - return DOSFALSE; - } - - /* make sure they're on the same device - * XXX this is insufficient, see comments in samedevice.c */ - if (olddvp->dvp_Port != newdvp->dvp_Port) { - FreeDeviceProc(olddvp); - FreeDeviceProc(newdvp); - SetIoErr(ERROR_RENAME_ACROSS_DEVICES); - return DOSFALSE; - } - - bstrNewName = C2BSTR(newName); - bstrOldName = C2BSTR(oldName); - status = dopacket4(DOSBase, NULL, olddvp->dvp_Port, ACTION_RENAME_OBJECT, olddvp->dvp_Lock, bstrOldName, newdvp->dvp_Lock, bstrNewName); - FREEC2BSTR(bstrOldName); - FREEC2BSTR(bstrNewName); - - FreeDeviceProc(olddvp); - FreeDeviceProc(newdvp); - - return status; + return RenameRelative(BNULL, oldName, BNULL, newName); AROS_LIBFUNC_EXIT } /* Rename */ diff --git a/rom/dos/renamerelative.c b/rom/dos/renamerelative.c new file mode 100644 index 00000000000..1a420d2a8d7 --- /dev/null +++ b/rom/dos/renamerelative.c @@ -0,0 +1,197 @@ +/* + Copyright (C) 1995-2013, The AROS Development Team. All rights reserved. + + Desc: Rename a file +*/ + +#include +#include +#include "dos_intern.h" +#include + +/***************************************************************************** + + NAME */ +#include +#include + + AROS_LH4(LONG, RenameRelative, + +/* SYNOPSIS */ + AROS_LHA(BPTR, oldLock, D1), + AROS_LHA(CONST_STRPTR, oldName, D2), + AROS_LHA(BPTR, newLock, D3), + AROS_LHA(CONST_STRPTR, newName, D4), + +/* LOCATION */ + struct DosLibrary *, DOSBase, 238, Dos) + +/* FUNCTION + Renames a given file. The old name and the new name must point to the + same volume. + + INPUTS + oldLock - Lock to compute old name relative to + oldName - Name of the file to rename + newLock - Lock to compute new name relative to + newName - New name of the file to rename + + RESULT + boolean - DOSTRUE or DOSFALSE. IoErr() provides additional information + on DOSFALSE. + + NOTES + + EXAMPLE + + BUGS + + SEE ALSO + + INTERNALS + +*****************************************************************************/ +{ + AROS_LIBFUNC_INIT + + struct DevProc *olddvp, *newdvp; + LONG status; + struct Process *me = (struct Process *)FindTask(NULL); + char buf1[256], vol[32]; + char buf2[256]; + int len; + BSTR bstrNewName, bstrOldName; + + ASSERT_VALID_PROCESS(me); + + /* This could be made simpler since ACTION_RENAME_OBJECT can take + * the lock & relative name as we want, but since we can't get a + * lock on a nonexistent file we'd still have to do filename + * building for it. But also, this is well tested code so lets not + * break any assumptions help by handlers that they're going to + * receive a device lock. -- robn, 2021-04-28 + */ + + len = SplitName(oldName, ':', vol, 0, sizeof(vol) - 1); + + if (len > 0) + { + /* get real name */ + BPTR lock = Lock(oldName, SHARED_LOCK); + if (lock) + { + if (NameFromLock(lock, buf1, sizeof(buf1) - 1)) + oldName = buf1; + UnLock(lock); + } + } + else + { + if (oldLock == BNULL) + oldLock = me->pr_CurrentDir; + + /* convert to absolute path */ + if (NameFromLock(oldLock, buf1, sizeof(buf1) - 1)) + { + int namelen = strlen(oldName); + len = strlen(buf1); + if (len + namelen < sizeof(buf1) - 1) + { + if (buf1[len - 1] != ':') + buf1[len++] = '/'; + CopyMem(oldName, buf1 + len, namelen + 1); + oldName = buf1; + } + } + } + + len = SplitName(newName, ':', vol, 0, sizeof(vol) - 1); + + if (len > 0) + { + /* get real name of destination path */ + BPTR lock; + char *pos; + const char *pos2; + + strcpy(buf2, newName); + pos = strrchr(buf2, '/'); + if (!pos) + { + pos = buf2 + len; + *pos = '\0'; + } + else + *(++pos) = '\0'; /* Keep slashes in name, to support a/b//c => a/c case */ + + lock = Lock(buf2, SHARED_LOCK); + if (lock) + { + if (NameFromLock(lock, buf2, sizeof(buf2) - 1)) + { + int namelen; + len = strlen(buf2); + pos2 = newName + (int)(pos - buf2); + namelen = strlen(pos2); + if (len + namelen < sizeof(buf2) - 1) + { + if (buf2[len - 1] != ':') + buf2[len++] = '/'; + CopyMem(pos2, buf2 + len, namelen + 1); + newName = buf2; + } + } + UnLock(lock); + } + } + else + { + /* convert to absolute path */ + if (newLock == BNULL) + newLock = me->pr_CurrentDir; + + if (NameFromLock(newLock, buf2, sizeof(buf2) - 1)) + { + int namelen = strlen(newName); + len = strlen(buf2); + if (len + namelen < sizeof(buf2) - 1) + { + if (buf2[len - 1] != ':') + buf2[len++] = '/'; + CopyMem(newName, buf2 + len, namelen + 1); + newName = buf2; + } + } + } + + D(bug("[Dos] rename %s %s\n", oldName, newName)); + + /* get device pointers */ + if ((olddvp = GetDeviceProc(oldName, NULL)) == NULL || + (newdvp = GetDeviceProc(newName, NULL)) == NULL) { + FreeDeviceProc(olddvp); + return DOSFALSE; + } + + /* make sure they're on the same device + * XXX this is insufficient, see comments in samedevice.c */ + if (olddvp->dvp_Port != newdvp->dvp_Port) { + FreeDeviceProc(olddvp); + FreeDeviceProc(newdvp); + SetIoErr(ERROR_RENAME_ACROSS_DEVICES); + return DOSFALSE; + } + + bstrNewName = C2BSTR(newName); + bstrOldName = C2BSTR(oldName); + status = dopacket4(DOSBase, NULL, olddvp->dvp_Port, ACTION_RENAME_OBJECT, olddvp->dvp_Lock, bstrOldName, newdvp->dvp_Lock, bstrNewName); + FREEC2BSTR(bstrOldName); + FREEC2BSTR(bstrNewName); + + FreeDeviceProc(olddvp); + FreeDeviceProc(newdvp); + + return status; + + AROS_LIBFUNC_EXIT +} /* RenameRelative */