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