2 Copyright © 1995-2008, 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 if(soft_nesting
== 0)
113 SetIoErr(ERROR_TOO_MANY_LEVELS
);
117 /* Prepare I/O request. */
118 InitIOFS(&iofs
, FSA_OPEN
, DOSBase
);
123 iofs
.io_Union
.io_OPEN
.io_FileMode
= FMF_LOCK
| FMF_READ
;
127 iofs
.io_Union
.io_OPEN
.io_FileMode
= FMF_READ
;
131 D(bug("[Lock] incompatible mode %d\n", accessMode
));
132 SetIoErr(ERROR_ACTION_NOT_KNOWN
);
136 /* catch the zero-length special case. we can't (currently) call
137 * GetDeviceProc(), as it will call NameFromLock(), which will
138 * DupLock(), which will end up here */
141 struct FileHandle
*fh
;
143 cur
= me
->pr_CurrentDir
;
145 cur
= DOSBase
->dl_SYSLock
;
151 iofs
.io_Union
.io_OPEN
.io_Filename
= (STRPTR
) "";
153 iofs
.IOFS
.io_Device
= fh
->fh_Device
;
154 iofs
.IOFS
.io_Unit
= fh
->fh_Unit
;
158 error
= me
->pr_Result2
= iofs
.io_DosError
;
162 error
= ERROR_OBJECT_NOT_FOUND
;
168 iofs
.io_Union
.io_OPEN
.io_Filename
= StripVolume(name
);
173 if ((dvp
= GetDeviceProc(name
, dvp
)) == NULL
)
179 error
= DoIOFS(&iofs
, dvp
, NULL
, DOSBase
);
180 } while (error
== ERROR_OBJECT_NOT_FOUND
);
182 if (error
== ERROR_NO_MORE_ENTRIES
)
183 error
= me
->pr_Result2
= ERROR_OBJECT_NOT_FOUND
;
185 if(error
== ERROR_IS_SOFT_LINK
)
187 ULONG buffer_size
= 256;
194 continue_loop
= FALSE
;
195 if(!(softname
= AllocVec(buffer_size
, MEMF_PUBLIC
)))
197 error2
= ERROR_NO_FREE_STORE
;
201 written
= ReadLink(dvp
->dvp_Port
, dvp
->dvp_Lock
, name
, softname
, buffer_size
);
204 /* An error occured */
207 else if(written
== -2)
209 /* If there's not enough space in the buffer, increase
211 continue_loop
= TRUE
;
214 else if(written
>= 0)
218 olddir
= CurrentDir(dvp
->dvp_Lock
);
219 ret
= InternalLock(softname
, accessMode
, handle
, soft_nesting
- 1, DOSBase
);
224 error2
= ERROR_UNKNOWN
;
228 while(continue_loop
);
236 handle
->fh_Device
= iofs
.IOFS
.io_Device
;
237 handle
->fh_Unit
= iofs
.IOFS
.io_Unit
;
240 else if(error
== ERROR_IS_SOFT_LINK
)