|
|
1.1 root 1: /* lock.c - universal locking routines */
2:
3: #ifndef MMDFONLY
4: #include "../h/strings.h"
5: #else MMDFONLY
6: #include "strings.h"
7: #include "mmdfonly.h"
8: #endif MMDFONLY
9: #include <stdio.h>
10: #include "mts.h"
11: #include <sys/types.h>
12: #include <sys/stat.h>
13:
14:
15: #define NOTOK (-1)
16: #define OK 0
17:
18: #define NULLCP ((char *) 0)
19:
20: #ifdef SYS5
21: #define index strchr
22: #define rindex strrchr
23: #endif SYS5
24:
25:
26: extern int errno;
27:
28: /* */
29:
30: int lkopen (file, access)
31: register char *file;
32: register int access;
33: {
34: mts_init ("mts");
35: switch (lockstyle) {
36: case LOK_UNIX:
37: #ifdef BSD42
38: return f_lkopen (file, access);
39: #endif BSD42
40:
41: default:
42: return b_lkopen (file, access);
43: }
44: }
45:
46: /* */
47:
48: static int b_lkopen (file, access)
49: register char *file;
50: register int access;
51: {
52: register int i,
53: j;
54: long curtime;
55: char curlock[BUFSIZ],
56: tmplock[BUFSIZ];
57: struct stat st;
58:
59: if (stat (file, &st) == NOTOK)
60: return NOTOK;
61: lockname (curlock, tmplock, file, (int) st.st_dev, (int) st.st_ino);
62:
63: for (i = 0;;)
64: switch (lockit (tmplock, curlock)) {
65: case OK:
66: if ((i = open (file, access)) == NOTOK) {
67: j = errno;
68: (void) unlink (curlock);
69: errno = j;
70: }
71: timerON (curlock, i);
72: return i;
73:
74: case NOTOK:
75: if (stat (curlock, &st) == NOTOK) {
76: if (i++ > 5)
77: return NOTOK;
78: sleep (5);
79: break;
80: }
81:
82: i = 0;
83: (void) time (&curtime);
84: if (curtime < st.st_ctime + 60L)
85: sleep (5);
86: else
87: (void) unlink (curlock);
88: break;
89: }
90: }
91:
92:
93: static int lockit (tmp, file)
94: register char *tmp,
95: *file;
96: {
97: register int fd;
98:
99: if ((fd = creat (tmp, 0400)) == NOTOK)
100: return NOTOK;
101: (void) close (fd);
102:
103: fd = link (tmp, file);
104: (void) unlink (tmp);
105:
106: return (fd != NOTOK ? OK : NOTOK);
107: }
108:
109: /* */
110:
111: static lockname (curlock, tmplock, file, dev, ino)
112: register char *curlock,
113: *tmplock,
114: *file;
115: register int dev,
116: ino;
117: {
118: register char *bp,
119: *cp;
120:
121: bp = curlock;
122: if ((cp = rindex (file, '/')) == NULL || *++cp == NULL)
123: cp = file;
124: if (lockldir == NULL || *lockldir == NULL) {
125: if (cp != file) {
126: (void) sprintf (bp, "%.*s", cp - file, file);
127: bp += strlen (bp);
128: }
129: }
130: else {
131: (void) sprintf (bp, "%s/", lockldir);
132: bp += strlen (bp);
133: }
134:
135: switch (lockstyle) {
136: case LOK_BELL:
137: default:
138: (void) sprintf (bp, "%s.lock", cp);
139: break;
140:
141: case LOK_MMDF:
142: (void) sprintf (bp, "LCK%05d.%05d", dev, ino);
143: break;
144: }
145:
146: if (tmplock) {
147: if ((cp = rindex (curlock, '/')) == NULL || *++cp == NULL)
148: (void) strcpy (tmplock, ",LCK.XXXXXX");
149: else
150: (void) sprintf (tmplock, "%.*s,LCK.XXXXXX",
151: cp - curlock, curlock);
152: (void) unlink (mktemp (tmplock));
153: }
154: }
155:
156: /* */
157:
158: #ifdef BSD42
159:
160: #include <sys/file.h>
161:
162: static int f_lkopen (file, access)
163: register char *file;
164: register int access;
165: {
166: register int fd,
167: i,
168: j;
169:
170: for (i = 0; i < 5; i++) {
171: if ((fd = open (file, access | O_NDELAY)) == NOTOK)
172: return NOTOK;
173: if (flock (fd, LOCK_EX | LOCK_NB) != NOTOK)
174: return fd;
175: j = errno;
176: (void) close (fd);
177:
178: sleep (5);
179: }
180:
181: (void) close (fd);
182: errno = j;
183: return NOTOK;
184: }
185: #endif BSD42
186:
187: /* */
188:
189: /* ARGSUSED */
190:
191: int lkclose (fd, file)
192: register int fd;
193: register char *file;
194: {
195: char curlock[BUFSIZ];
196: struct stat st;
197:
198: if (fd == NOTOK)
199: return OK;
200: switch (lockstyle) {
201: case LOK_UNIX:
202: #ifdef BSD42
203: break;
204: #endif BSD42
205:
206: default:
207: if (fstat (fd, &st) != NOTOK) {
208: lockname (curlock, NULLCP, file, (int) st.st_dev, (int) st.st_ino);
209: (void) unlink (curlock);
210: timerOFF (fd);
211: }
212: }
213:
214: return (close (fd));
215: }
216:
217:
218: /* */
219:
220: FILE *lkfopen (file, mode)
221: register char *file,
222: *mode;
223: {
224: register int fd;
225: register FILE *fp;
226:
227: if ((fd = lkopen (file, strcmp (mode, "r") ? 2 : 0)) == NOTOK)
228: return NULL;
229:
230: if ((fp = fdopen (fd, mode)) == NULL) {
231: (void) close (fd);
232: return NULL;
233: }
234:
235: return fp;
236: }
237:
238:
239: /* ARGSUSED */
240:
241: int lkfclose (fp, file)
242: register FILE *fp;
243: register char *file;
244: {
245: char curlock[BUFSIZ];
246: struct stat st;
247:
248: if (fp == NULL)
249: return OK;
250:
251: switch (lockstyle) {
252: case LOK_UNIX:
253: #ifdef BSD42
254: break;
255: #endif BSD42
256:
257: default:
258: if (fstat (fileno (fp), &st) != NOTOK) {
259: lockname (curlock, NULLCP, file, (int) st.st_dev, (int) st.st_ino);
260: (void) unlink (curlock);
261: }
262: }
263:
264: return (fclose (fp));
265: }
266:
267: /* */
268:
269: #include <signal.h>
270:
271: #define NSECS ((unsigned) 20)
272:
273:
274: struct lock {
275: int l_fd;
276: char *l_lock;
277: struct lock *l_next;
278: };
279: #define NULLP ((struct lock *) 0)
280:
281: static struct lock *l_top = NULLP;
282:
283:
284: /* ARGSUSED */
285:
286: static alrmser (sig)
287: int sig;
288: {
289: register int j;
290: register char *cp;
291: register struct lock *lp;
292:
293: #ifndef BSD42
294: (void) signal (SIGALRM, alrmser);
295: #endif BSD42
296:
297: for (lp = l_top; lp; lp = lp -> l_next)
298: if (*(cp = lp -> l_lock) && (j = creat (cp, 0400)) != NOTOK)
299: (void) close (j);
300:
301: (void) alarm (NSECS);
302: }
303:
304: /* */
305:
306: static timerON (lock, fd)
307: char *lock;
308: int fd;
309: {
310: register struct lock *lp;
311:
312: if ((lp = (struct lock *) malloc ((unsigned) (sizeof *lp))) == NULLP)
313: return; /* XXX */
314:
315: lp -> l_fd = fd;
316: if ((lp -> l_lock = malloc ((unsigned) (strlen (lock) + 1))) == NULLCP) {
317: free ((char *) lp);
318: return; /* XXX */
319: }
320: (void) strcpy (lp -> l_lock, lock);
321: lp -> l_next = NULLP;
322:
323: if (l_top)
324: lp -> l_next = l_top -> l_next;
325: else {
326: (void) signal (SIGALRM, alrmser);/* perhaps SIGT{STP,TIN,TOU} */
327: (void) alarm (NSECS);
328: }
329: l_top = lp;
330: }
331:
332:
333: static timerOFF (fd)
334: int fd;
335: {
336: register struct lock *pp,
337: *lp;
338:
339: (void) alarm (0);
340:
341: if (l_top) {
342: for (pp = lp = l_top; lp; pp = lp, lp = lp -> l_next)
343: if (lp -> l_fd == fd)
344: break;
345: if (lp) {
346: if (lp == l_top)
347: l_top = lp -> l_next;
348: else
349: pp -> l_next = lp -> l_next;
350:
351: free (lp -> l_lock);
352: free ((char *) lp);
353: }
354: }
355:
356: if (l_top)
357: (void) alarm (NSECS);
358: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.