2 Copyright © 2008, The AROS Development Team. All rights reserved.
5 4.4BSD function flock().
10 #include <proto/exec.h>
11 #include <exec/exec.h>
12 #include <proto/dos.h>
14 #include <aros/debug.h>
15 #include <aros/startup.h>
16 #include <aros/symbolsets.h>
22 #include "__arosc_privdata.h"
27 struct SignalSemaphore
*sem
;
30 LONG
AddToList(struct SignalSemaphore
*sem
);
31 void RemoveFromList(struct SignalSemaphore
*sem
);
33 /*****************************************************************************
45 Apply or remove an advisory lock on open file descriptor fd. Operation
46 argument can be one of the following constants:
48 LOCK_SH - Place a shared lock on the file specified by fd. More that
49 one process can hold a shared lock on a given file at a
52 LOCK_EX - Place an exclusive lock on the file specified by fd. Only
53 one process can hold an exclusive lock on a given file at
56 LOCK_UN - Remove an existing lock from the file specified by fd.
58 LOCK_EX operation blocks if there is a lock already placed on the
59 file. LOCK_SH blocks if there is an exclusive lock already placed
60 on the file. If you want to do a non-blocking request, OR the
61 operation specifier with LOCK_NB constant. In this case flock() will
62 return -1 instead of blocking and set errno to EWOULDBLOCK.
64 Advisory locks created with flock() are shared among duplicated file
68 fd - File descriptor of the file you want to place or remove lock from.
69 operation - Lock operation to be performed.
72 0 on success, -1 on error. In case of error a global errno variable
76 Locks placed with flock() are only advisory, they place no
77 restrictions to any file or file descriptor operations.
82 It's currently possible to remove lock placed by another process.
87 Since advisory locks semantics is equal to exec.library semaphores
88 semantics, semaphores are used to implement locks. For a given file
89 a semaphore named FLOCK(path) is created where path is a full path to
90 the file. Locks held by a given process are stored on __flocks_list
91 and released during process exit.
93 ******************************************************************************/
95 fdesc
*fdesc
= __getfdesc(fd
);
98 struct SignalSemaphore
*sem
;
100 D(bug("flock(%d, %d)\n", fd
, operation
));
109 (operation
& ~LOCK_NB
) != LOCK_SH
&&
110 (operation
& ~LOCK_NB
) != LOCK_EX
&&
111 (operation
& ~LOCK_NB
) != LOCK_UN
118 /* Get the full path of the flocked filesystem object */
121 if(!(buffer
= AllocVec(buffersize
, MEMF_ANY
)))
123 errno
= IoErr2errno(IoErr());
127 if(NameFromLock(fdesc
->fcb
->fh
, (STRPTR
) ((IPTR
) buffer
+ 6), buffersize
- 7))
129 else if(IoErr() != ERROR_LINE_TOO_LONG
)
131 errno
= IoErr2errno(IoErr());
140 CopyMem("FLOCK(", buffer
, strlen("FLOCK("));
141 buffer
[strlen(buffer
) + 1] = '\0';
142 buffer
[strlen(buffer
)] = ')';
144 D(bug("[flock] Semaphore name: %s\n", buffer
));
146 /* Find semaphore named FLOCK(path), add a new one if not found any */
148 sem
= FindSemaphore((STRPTR
) buffer
);
151 D(bug("[flock] Semaphore %s not found, creating a new one\n", buffer
));
152 sem
= (struct SignalSemaphore
*)
153 AllocVec(sizeof(struct SignalSemaphore
), MEMF_PUBLIC
|MEMF_CLEAR
);
160 sem
->ss_Link
.ln_Name
= buffer
;
165 D(bug("[flock] Semaphore %s found, freeing buffer\n", buffer
));
169 if(operation
& LOCK_UN
)
171 D(bug("[flock] Releasing semaphore %s\n", sem
->ss_Link
.ln_Name
));
172 ReleaseSemaphore(sem
);
174 if(sem
->ss_Owner
== NULL
&& sem
->ss_QueueCount
== -1)
176 D(bug("[flock] All locks unlocked, removing semaphore %s\n", sem
->ss_Link
.ln_Name
));
177 /* All locks for this file were unlocked, we don't need semaphore
180 FreeVec(sem
->ss_Link
.ln_Name
);
188 switch(operation
& ~LOCK_NB
)
191 D(bug("[flock] Obtaining shared lock\n"));
192 if(operation
& LOCK_NB
)
194 if(!AttemptSemaphoreShared(sem
))
201 ObtainSemaphoreShared(sem
);
202 D(bug("[flock] Shared lock obtained\n"));
206 D(bug("[flock] Obtaining exclusive lock\n"));
207 if(operation
& LOCK_NB
)
209 if(!AttemptSemaphore(sem
))
216 ObtainSemaphore(sem
);
217 D(bug("[flock] Exclusive lock obtained\n"));
224 LONG
AddToList(struct SignalSemaphore
*sem
)
226 struct FlockNode
*node
;
227 node
= AllocMem(sizeof(struct FlockNode
), MEMF_ANY
| MEMF_CLEAR
);
231 AddHead((struct List
*)&__flocks_list
, (struct Node
*) node
);
235 void RemoveFromList(struct SignalSemaphore
*sem
)
237 struct FlockNode
*varNode
;
238 struct Node
*tmpNode
;
240 ForeachNodeSafe(&__flocks_list
, varNode
, tmpNode
)
242 if(varNode
->sem
== sem
)
244 Remove((struct Node
*) varNode
);
245 FreeMem(varNode
, sizeof(struct FlockNode
));
251 int __init_flocks(void)
253 NEWLIST((struct List
*)&__flocks_list
);
258 void __unlock_flocks(void)
261 struct FlockNode
*lock
;
262 struct SignalSemaphore
*sem
;
265 while ((lock
= (struct FlockNode
*) REMHEAD(
266 (struct List
*) &__flocks_list
)))
269 ReleaseSemaphore(sem
);
270 FreeMem(lock
, sizeof(struct FlockNode
));
272 if(sem
->ss_Owner
== NULL
&& sem
->ss_QueueCount
== -1)
274 D(bug("[flock] All locks unlocked, removing semaphore %s\n", sem
->ss_Link
.ln_Name
));
275 /* All locks for this file were unlocked, we don't need semaphore
278 FreeVec(sem
->ss_Link
.ln_Name
);
286 ADD2INIT(__init_flocks
, 1);
287 ADD2EXIT(__unlock_flocks
, 1);