2 Copyright © 1995-2010, The AROS Development Team. All rights reserved.
5 Desc: Locks a file or directory.
9 #include <proto/exec.h>
10 #include <utility/tagitem.h>
11 #include <dos/dosextens.h>
12 #include <dos/filesystem.h>
13 #include <proto/dos.h>
14 #include <proto/utility.h>
15 #include "dos_intern.h"
18 #include <aros/debug.h>
20 LONG
InternalLock(CONST_STRPTR name
, LONG accessMode
,
21 struct FileHandle
*handle
, LONG soft_nesting
, struct DosLibrary
*DOSBase
);
23 #define MAX_SOFT_LINK_NESTING 16 /* Maximum level of soft links nesting */
25 /*****************************************************************************
28 #include <proto/dos.h>
33 AROS_LHA(CONST_STRPTR
, name
, D1
),
34 AROS_LHA(LONG
, accessMode
, D2
),
37 struct DosLibrary
*, DOSBase
, 14, Dos
)
40 Gets a lock on a file or directory. There may be more than one
41 shared lock on a file but only one if it is an exclusive one.
42 Locked files or directories may not be deleted.
45 name - NUL terminated name of the file or directory.
46 accessMode - One of SHARED_LOCK
50 Handle to the file or directory or 0 if the object couldn't be locked.
51 IoErr() gives additional information in that case.
54 The lock structure returned by this function is different
55 from that of AmigaOS (in fact it is identical to a filehandle).
56 Do not try to read any internal fields.
58 *****************************************************************************/
65 ASSERT_VALID_PTR(name
);
71 /* Create filehandle */
72 struct FileHandle
*ret
= (struct FileHandle
*)AllocDosObject(DOS_FILEHANDLE
, NULL
);
76 if(InternalLock(name
, accessMode
, ret
, MAX_SOFT_LINK_NESTING
, DOSBase
))
83 FreeDosObject(DOS_FILEHANDLE
, ret
);
88 error
= ERROR_NO_FREE_STORE
;
97 /* Try to lock name recursively calling itself in case it's a soft link.
98 Store result in handle. Return boolean value indicating result. */
99 LONG
InternalLock(CONST_STRPTR name
, LONG accessMode
,
100 struct FileHandle
*handle
, LONG soft_nesting
, struct DosLibrary
*DOSBase
)
102 /* Get pointer to I/O request. Use stackspace for now. */
103 struct IOFileSys iofs
;
104 /* Get pointer to process structure */
105 struct Process
*me
= (struct Process
*)FindTask(NULL
);
111 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
));
113 if(soft_nesting
== 0)
115 SetIoErr(ERROR_TOO_MANY_LEVELS
);
119 /* Prepare I/O request. */
120 InitIOFS(&iofs
, FSA_OPEN
, DOSBase
);
125 iofs
.io_Union
.io_OPEN
.io_FileMode
= FMF_LOCK
| FMF_READ
;
129 iofs
.io_Union
.io_OPEN
.io_FileMode
= FMF_READ
;
133 D(bug("[Lock] incompatible mode %d\n", accessMode
));
134 SetIoErr(ERROR_ACTION_NOT_KNOWN
);
138 /* catch the zero-length special case. we can't (currently) call
139 * GetDeviceProc(), as it will call NameFromLock(), which will
140 * DupLock(), which will end up here */
143 struct FileHandle
*fh
;
145 cur
= me
->pr_CurrentDir
;
147 cur
= DOSBase
->dl_SYSLock
;
153 iofs
.io_Union
.io_OPEN
.io_Filename
= (STRPTR
) "";
155 iofs
.IOFS
.io_Device
= fh
->fh_Device
;
156 iofs
.IOFS
.io_Unit
= fh
->fh_Unit
;
160 error
= me
->pr_Result2
= iofs
.io_DosError
;
164 error
= ERROR_OBJECT_NOT_FOUND
;
170 iofs
.io_Union
.io_OPEN
.io_Filename
= StripVolume(name
);
175 if ((dvp
= GetDeviceProc(name
, dvp
)) == NULL
)
181 error
= DoIOFS(&iofs
, dvp
, NULL
, DOSBase
);
182 } while (error
== ERROR_OBJECT_NOT_FOUND
);
184 if (error
== ERROR_NO_MORE_ENTRIES
)
185 error
= me
->pr_Result2
= ERROR_OBJECT_NOT_FOUND
;
187 if(error
== ERROR_IS_SOFT_LINK
)
189 ULONG buffer_size
= 256;
196 continue_loop
= FALSE
;
197 if(!(softname
= AllocVec(buffer_size
, MEMF_PUBLIC
)))
199 error2
= ERROR_NO_FREE_STORE
;
203 written
= ReadLink(dvp
->dvp_Port
, dvp
->dvp_Lock
, name
, softname
, buffer_size
);
206 /* An error occured */
209 else if(written
== -2)
211 /* If there's not enough space in the buffer, increase
213 continue_loop
= TRUE
;
216 else if(written
>= 0)
220 olddir
= CurrentDir(dvp
->dvp_Lock
);
221 ret
= InternalLock(softname
, accessMode
, handle
, soft_nesting
- 1, DOSBase
);
226 error2
= ERROR_UNKNOWN
;
230 while(continue_loop
);
238 handle
->fh_Device
= iofs
.IOFS
.io_Device
;
239 handle
->fh_Unit
= iofs
.IOFS
.io_Unit
;
242 else if(error
== ERROR_IS_SOFT_LINK
)