Add new strings.
[AROS.git] / rom / dos / lock.c
bloba1c1ea3b9409e583c5d9df8ac099b5a71c463a81
1 /*
2 Copyright © 1995-2010, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Locks a file or directory.
6 Lang: English
7 */
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"
17 #define DEBUG 0
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 /*****************************************************************************
27 NAME */
28 #include <proto/dos.h>
30 AROS_LH2(BPTR, Lock,
32 /* SYNOPSIS */
33 AROS_LHA(CONST_STRPTR, name, D1),
34 AROS_LHA(LONG, accessMode, D2),
36 /* LOCATION */
37 struct DosLibrary *, DOSBase, 14, Dos)
39 /* FUNCTION
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.
44 INPUTS
45 name - NUL terminated name of the file or directory.
46 accessMode - One of SHARED_LOCK
47 EXCLUSIVE_LOCK
49 RESULT
50 Handle to the file or directory or 0 if the object couldn't be locked.
51 IoErr() gives additional information in that case.
53 NOTES
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 *****************************************************************************/
61 AROS_LIBFUNC_INIT
63 LONG error;
65 ASSERT_VALID_PTR(name);
67 /* Sanity check */
68 if (name == NULL)
69 return NULL;
71 /* Create filehandle */
72 struct FileHandle *ret = (struct FileHandle *)AllocDosObject(DOS_FILEHANDLE, NULL);
74 if (ret != NULL)
76 if(InternalLock(name, accessMode, ret, MAX_SOFT_LINK_NESTING, DOSBase))
78 return MKBADDR(ret);
80 else
82 error = IoErr();
83 FreeDosObject(DOS_FILEHANDLE, ret);
86 else
88 error = ERROR_NO_FREE_STORE;
91 SetIoErr(error);
92 return NULL;
94 AROS_LIBFUNC_EXIT
95 } /* Lock */
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);
106 struct DevProc *dvp;
107 LONG ret = DOSFALSE;
108 LONG error = 0;
109 LONG error2 = 0;
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);
116 return DOSFALSE;
119 /* Prepare I/O request. */
120 InitIOFS(&iofs, FSA_OPEN, DOSBase);
122 switch (accessMode)
124 case EXCLUSIVE_LOCK:
125 iofs.io_Union.io_OPEN.io_FileMode = FMF_LOCK | FMF_READ;
126 break;
128 case SHARED_LOCK:
129 iofs.io_Union.io_OPEN.io_FileMode = FMF_READ;
130 break;
132 default:
133 D(bug("[Lock] incompatible mode %d\n", accessMode));
134 SetIoErr(ERROR_ACTION_NOT_KNOWN);
135 return DOSFALSE;
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 */
141 if (*name == '\0') {
142 BPTR cur;
143 struct FileHandle *fh;
145 cur = me->pr_CurrentDir;
146 if (!cur)
147 cur = DOSBase->dl_SYSLock;
149 if (cur)
151 fh = BADDR(cur);
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;
158 DosDoIO(&iofs.IOFS);
160 error = me->pr_Result2 = iofs.io_DosError;
162 else
164 error = ERROR_OBJECT_NOT_FOUND;
165 SetIoErr(error);
168 else
170 iofs.io_Union.io_OPEN.io_Filename = StripVolume(name);
171 dvp = NULL;
175 if ((dvp = GetDeviceProc(name, dvp)) == NULL)
177 error = IoErr();
178 break;
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;
190 STRPTR softname;
191 LONG continue_loop;
192 LONG written;
196 continue_loop = FALSE;
197 if(!(softname = AllocVec(buffer_size, MEMF_PUBLIC)))
199 error2 = ERROR_NO_FREE_STORE;
200 break;
203 written = ReadLink(dvp->dvp_Port, dvp->dvp_Lock, name, softname, buffer_size);
204 if(written == -1)
206 /* An error occured */
207 error2 = IoErr();
209 else if(written == -2)
211 /* If there's not enough space in the buffer, increase
212 it and try again */
213 continue_loop = TRUE;
214 buffer_size *= 2;
216 else if(written >= 0)
218 /* All OK */
219 BPTR olddir;
220 olddir = CurrentDir(dvp->dvp_Lock);
221 ret = InternalLock(softname, accessMode, handle, soft_nesting - 1, DOSBase);
222 error2 = IoErr();
223 CurrentDir(olddir);
225 else
226 error2 = ERROR_UNKNOWN;
228 FreeVec(softname);
230 while(continue_loop);
233 FreeDeviceProc(dvp);
236 if(!error)
238 handle->fh_Device = iofs.IOFS.io_Device;
239 handle->fh_Unit = iofs.IOFS.io_Unit;
240 return DOSTRUE;
242 else if(error == ERROR_IS_SOFT_LINK)
244 if(!ret)
245 SetIoErr(error2);
246 else
247 SetIoErr(0);
248 return ret;
250 else
252 SetIoErr(error);
253 return DOSFALSE;