2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
5 Desc: Locks a file or directory.
12 #include <aros/debug.h>
13 #include <proto/exec.h>
14 #include <utility/tagitem.h>
15 #include <dos/dosextens.h>
16 #include <dos/filesystem.h>
17 #include <proto/dos.h>
18 #include <proto/utility.h>
20 #include "dos_intern.h"
21 #include "fs_driver.h"
23 static LONG
InternalLock(CONST_STRPTR name
, LONG accessMode
,
24 BPTR
*handle
, LONG soft_nesting
, struct DosLibrary
*DOSBase
);
26 #define MAX_SOFT_LINK_NESTING 16 /* Maximum level of soft links nesting */
28 /*****************************************************************************
31 #include <proto/dos.h>
36 AROS_LHA(CONST_STRPTR
, name
, D1
),
37 AROS_LHA(LONG
, accessMode
, D2
),
40 struct DosLibrary
*, DOSBase
, 14, Dos
)
43 Gets a lock on a file or directory. There may be more than one
44 shared lock on a file but only one if it is an exclusive one.
45 Locked files or directories may not be deleted.
48 name - NUL terminated name of the file or directory.
49 accessMode - One of SHARED_LOCK
53 Handle to the file or directory or 0 if the object couldn't be locked.
54 IoErr() gives additional information in that case.
57 The lock structure returned by this function is different
58 from that of AmigaOS (in fact it is identical to a filehandle).
59 Do not try to read any internal fields.
61 *****************************************************************************/
72 ASSERT_VALID_PTR(name
);
74 D(bug("[Lock] '%s':%d\n", name
, accessMode
));
76 if (InternalLock(name
, accessMode
, &fl
, MAX_SOFT_LINK_NESTING
, DOSBase
))
78 D(bug("[Lock] returned 0x%p\n", fl
));
82 D(bug("[Lock] failed, err=%d\n", IoErr()));
88 /* Try to lock name recursively calling itself in case it's a soft link.
89 Store result in handle. Return boolean value indicating result. */
90 static LONG
InternalLock(CONST_STRPTR name
, LONG accessMode
,
91 BPTR
*handle
, LONG soft_nesting
, struct DosLibrary
*DOSBase
)
93 /* Get pointer to process structure */
94 struct Process
*me
= (struct Process
*)FindTask(NULL
);
96 struct DevProc
*dvp
= NULL
;
101 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
));
103 if(soft_nesting
== 0)
105 SetIoErr(ERROR_TOO_MANY_LEVELS
);
109 filename
= strchr(name
, ':');
112 /* No ':' in the pathname, path is relative to current directory */
113 cur
= me
->pr_CurrentDir
;
115 cur
= DOSBase
->dl_SYSLock
;
117 if (cur
&& (cur
!= (BPTR
)-1))
118 error
= fs_LocateObject(handle
, cur
, NULL
, name
, accessMode
, DOSBase
);
120 error
= ERROR_OBJECT_NOT_FOUND
;
129 if ((dvp
= GetDeviceProc(name
, dvp
)) == NULL
)
135 error
= fs_LocateObject(handle
, BNULL
, dvp
, filename
, accessMode
, DOSBase
);
137 } while (error
== ERROR_OBJECT_NOT_FOUND
);
139 /* FIXME: On Linux hosted we sometimes get ERROR_IS_SOFTLINK with dvp == NULL,
140 * which causes segfaults below if we don't change "error". Adding !dvp below
143 if (error
== ERROR_NO_MORE_ENTRIES
|| !dvp
)
144 error
= me
->pr_Result2
= ERROR_OBJECT_NOT_FOUND
;
147 if (error
== ERROR_IS_SOFT_LINK
)
149 STRPTR softname
= ResolveSoftlink(cur
, dvp
, name
, DOSBase
);
156 * ResolveSoftLink() gives us path relative to either 'cur' lock
157 * (if on current volume), or 'dvp' volume root (if on different volume).
158 * In the latter case we need to change current directory to volume's root
159 * in order to follow the link correctly.
163 olddir
= me
->pr_CurrentDir
;
164 error
= RootDir(dvp
, DOSBase
);
171 ret
= InternalLock(softname
, accessMode
, handle
, soft_nesting
- 1, DOSBase
);
172 error
= ret
? 0 : IoErr();
173 D(bug("[Lock] Resolve error %d\n", error
));
176 UnLock(CurrentDir(olddir
));
199 * Resolve a softlink.
200 * Returns AllocVec()ed buffer with softlink contents.
202 STRPTR
ResolveSoftlink(BPTR cur
, struct DevProc
*dvp
, CONST_STRPTR name
, struct DosLibrary
*DOSBase
)
204 ULONG buffer_size
= 256;
209 DLINK(bug("[Softlink] Resolving softlink %s...\n", name
));
213 continue_loop
= FALSE
;
215 if (!(softname
= AllocVec(buffer_size
, MEMF_PUBLIC
|MEMF_CLEAR
)))
217 SetIoErr(ERROR_NO_FREE_STORE
);
221 written
= fs_ReadLink(cur
, dvp
, name
, softname
, buffer_size
, DOSBase
);
226 /* An error occured */
227 DLINK(bug("[Softlink] Error %d reading softlink\n", IoErr()));
231 /* If there's not enough space in the buffer, increase it and try again */
232 continue_loop
= TRUE
;
235 DLINK(bug("[Softlink] Increased buffer size up to %u\n", buffer_size
));
240 DLINK(bug("[Softlink] Resolved path: %s\n", softname
));
246 while(continue_loop
);
251 /* Change to root directory of the specified device */
252 LONG
RootDir(struct DevProc
*dvp
, struct DosLibrary
*DOSBase
)
257 /* We already have a DeviceProc structure, so just use internal routine. */
258 error
= fs_LocateObject(&lock
, BNULL
, dvp
, "", SHARED_LOCK
, DOSBase
);