source: trunk/athena/bin/quota/attachtab.c @ 12014

Revision 12014, 11.7 KB checked in by danw, 26 years ago (diff)
block SIGTSTP around attachtab lock so we don't get stopped while holding the lock
Line 
1/*
2 * $Id: attachtab.c,v 1.11 1998-09-29 19:52:04 danw Exp $
3 *
4 * Copyright (c) 1989,1991 by the Massachusetts Institute of Technology.
5 *
6 * Contains the routines which access the attachtab file.
7 */
8
9#ifndef lint
10static char rcsid_attachtab_c[] = "$Id: attachtab.c,v 1.11 1998-09-29 19:52:04 danw Exp $";
11#endif lint
12
13#include "attach.h"
14#include <fcntl.h>
15#include <sys/file.h>
16#include <pwd.h>
17#include <string.h>
18#include <signal.h>
19
20#define TOKSEP " \t\r\n"
21
22static int parse_attach();
23
24struct  _attachtab      *attachtab_first, *attachtab_last;
25
26static int debug_flag = 0;
27static char attachtab_fn[512];
28static char *abort_msg = "quota: aborting\n";
29static sigset_t omask;
30
31/*
32 * LOCK the attachtab - wait for it if it's already locked
33 */
34static int attach_lock_fd = -1;
35static int attach_lock_count = 0;
36
37void lock_attachtab()
38{
39    register char *lockfn;
40    register FILE *fp;
41    register int status;
42    static char buf[512];
43    static int initd = 0;
44#ifdef POSIX
45    struct flock fl;
46#endif
47    sigset_t blocked;
48
49    if (!initd) {
50        if (fp = fopen("/etc/athena/attach.conf","r")) {
51            while (fgets(buf, sizeof(buf), fp)) {
52                if (sscanf(buf, "attachtab %s", attachtab_fn) == 1) {
53                    initd = 1;
54                    break;
55                }
56            }
57            fclose(fp);
58        }
59        if (!initd) {
60            strcpy(attachtab_fn, "/var/athena/attachtab");
61            initd = 1;
62        }
63    }
64   
65    sigemptyset(&blocked);
66    sigaddset(&blocked, SIGTSTP);
67    sigprocmask(SIG_BLOCK, &blocked, &omask);
68
69    if (debug_flag)
70        printf("Locking attachtab....");
71    if (attach_lock_count == 0) {
72        if (!(lockfn = malloc(strlen(attachtab_fn)+6))) {
73            fprintf(stderr,
74                    "Can't malloc for lockfile filename\n");
75            fprintf(stderr, abort_msg);
76            exit(ERR_FATAL);
77        }
78        (void) strcpy(lockfn, attachtab_fn);
79        (void) strcat(lockfn, ".lock");
80       
81        if (attach_lock_fd < 0) {
82            attach_lock_fd = open(lockfn, O_CREAT|O_RDWR, 0644);
83            if (attach_lock_fd < 0) {
84                fprintf(stderr,"Can't open %s: %s\n", lockfn, strerror(errno));
85                fprintf(stderr, abort_msg);
86                exit(ERR_FATAL);
87            }
88        }
89#ifdef POSIX
90        fl.l_type = F_WRLCK;
91        fl.l_whence = SEEK_SET;
92        fl.l_start = 0;
93        fl.l_len = 0;
94        fl.l_pid = getpid();
95        status = fcntl(attach_lock_fd, F_SETLKW, &fl);
96#else
97        status = flock(attach_lock_fd, LOCK_EX);
98#endif
99        if (status == -1) {
100            fprintf(stderr, "Unable to lock attachtab: %s\n", strerror(errno));
101            fprintf(stderr, abort_msg);
102            exit(ERR_FATAL);
103        }
104        free(lockfn);
105    }
106    attach_lock_count++;
107}
108
109
110/*
111 * UNLOCK the attachtab
112 */
113void unlock_attachtab()
114{
115    if (debug_flag)
116        printf("Unlocking attachtab\n");
117    attach_lock_count--;
118    if (attach_lock_count == 0) {
119        close(attach_lock_fd);
120        attach_lock_fd = -1;
121    } else if (attach_lock_count < 0) {
122        fprintf(stderr,
123                "Programming botch!  Tried to unlock unlocked attachtab\n");
124    }
125
126    sigprocmask(SIG_SETMASK, &omask, NULL);
127}
128
129/*
130 * get_attachtab - Reads in the attachtab file and sets up the doubly
131 *      linked list of attachtab entries.  Assumes attachtab is
132 *      already locked.
133 */
134void get_attachtab()
135{
136    register struct _attachtab  *atprev = NULL;
137    register struct _attachtab  *at = NULL;
138    register FILE                       *f;
139    char                                attach_buf[BUFSIZ];
140       
141    free_attachtab();
142    if ((f = fopen(attachtab_fn, "r")) == NULL) {
143        fprintf(stderr, "Unable to open %s: %s\n",
144                attachtab_fn, strerror(errno));
145        return;
146    }
147       
148    while (fgets(attach_buf, sizeof attach_buf, f)) {
149        if (!(at = (struct _attachtab *) malloc(sizeof(*at)))) {
150            fprintf(stderr,
151                    "Can't malloc while parsing attachtab\n");
152            fprintf(stderr, abort_msg);
153            exit(ERR_FATAL);
154        }
155        if (parse_attach(attach_buf, at, 0) != SUCCESS) {
156            free(at);
157            continue;
158        }
159        at->prev = atprev;
160        if (atprev)
161            atprev->next = at;
162        else
163            attachtab_first = at;
164        atprev = at;
165    }
166    attachtab_last = at;
167    fclose(f);
168}
169
170/*
171 * free the linked list of attachtab entries
172 */
173void free_attachtab()
174{
175    register struct _attachtab          *at, *next;
176       
177    if (!(at = attachtab_first))
178        return;
179    while (at) {
180        next = at->next;
181        free(at);
182        at = next;
183    }
184    attachtab_first = attachtab_last = NULL;
185}       
186
187#if 0
188/*
189 * put_attachtab - write out attachtab file from linked list and
190 *      unlocks attachtab
191 */
192put_attachtab()
193{
194    register FILE       *f;
195    register struct     _attachtab      *at;
196    register char       *tempfn;
197       
198    if (!(tempfn = malloc(strlen(attachtab_fn)+6))) {
199        fprintf(stderr,
200                "Can't malloc while writing attachtab.\n");
201        fprintf(stderr, abort_msg);
202        exit(ERR_FATAL);
203    }
204    (void) strcpy(tempfn, attachtab_fn);
205    (void) strcat(tempfn, ".temp");
206    if (!(f = fopen(tempfn, "w"))) {
207        fprintf(stderr,"Can't open %s for write: %s\n", attachtab_fn,
208                strerror(errno));
209        fprintf(stderr, abort_msg);
210        exit(ERR_FATAL);
211    }
212    at = attachtab_first;
213    while (at) {
214        register int i;
215
216        fprintf(f, "%s %c%c%s %s %s %s %s",
217                at->version, at->explicit ? '1' : '0',
218                at->status, (at->fs) ? at->fs->name : "---",
219                at->hesiodname, at->host, at->hostdir,
220                inet_ntoa(at->hostaddr[0]));
221        for (i=1; i<MAXHOSTS && at->hostaddr[i].s_addr; i++)
222            fprintf(f, ",%s", inet_ntoa(at->hostaddr[i]));
223        fprintf(f, " %d %s %d ",
224                at->rmdir, at->mntpt, at->flags);
225        if (at->nowners)
226            fprintf(f, "%d", at->owners[0]);
227        else
228            fprintf(f, ",");
229        for (i=1; i < at->nowners; i++)
230            fprintf(f, ",%d", at->owners[i]);
231        fprintf(f, " %d %c\n", at->drivenum, at->mode);
232
233        at = at->next;
234    }
235    fclose(f);
236
237    if (rename(tempfn, attachtab_fn)) {
238        fprintf(stderr,"Can't rename %s to %s\n", tempfn,
239                attachtab_fn);
240        fprintf(stderr, abort_msg);
241        exit(ERR_FATAL);
242    }
243}
244
245void lint_attachtab()
246{
247    register struct _attachtab  *atprev = NULL;
248    register struct _attachtab  *at = NULL;
249    FILE                                *f;
250    char                                attach_buf[BUFSIZ];
251       
252    free_attachtab();
253    if ((f = fopen(attachtab_fn, "r")) == NULL)
254        return;
255       
256    while (fgets(attach_buf, sizeof attach_buf, f)) {
257        if (!(at = (struct _attachtab *) malloc(sizeof(*at)))) {
258            fprintf(stderr,
259                    "Can't malloc while parsing attachtab\n");
260            fprintf(stderr, abort_msg);
261            exit(ERR_FATAL);
262        }
263        if(parse_attach(attach_buf, at, 1) == FAILURE)
264            continue;                           /* bad line -- ignore */
265        at->prev = atprev;
266        if (atprev)
267            atprev->next = at;
268        else
269            attachtab_first = at;
270        atprev = at;
271    }
272    attachtab_last = at;
273    fclose(f);
274    put_attachtab();
275    free_attachtab();
276}
277#endif
278
279/*
280 * Convert an attachtab line to an attachtab structure
281 */
282static int parse_attach(bfr, at, lintflag)
283    register char *bfr;
284    register struct _attachtab *at;
285    int lintflag;
286{
287    register char *cp;
288    register int i;
289
290    if (!*bfr)
291        goto bad_line;
292       
293    if (bfr[strlen(bfr)-1] < ' ')
294        bfr[strlen(bfr)-1] = '\0';
295       
296    if (!(cp = strtok(bfr, TOKSEP)))
297        goto bad_line;
298
299    if (strcmp(cp, ATTACH_VERSION)) {
300        fprintf(stderr, "Bad version number in %s\n", attachtab_fn);
301        if(lintflag)
302            return FAILURE;
303        fprintf(stderr, abort_msg);
304        exit(ERR_FATAL);
305    }
306    strcpy(at->version, cp);
307   
308    if (!(cp = strtok(NULL, TOKSEP)))
309        goto bad_line;
310
311    if (*cp != '0' && *cp != '1')
312        goto bad_line;
313    at->explicit = *cp++-'0';
314   
315    at->status = *cp++;
316    if (at->status != STATUS_ATTACHED && at->status != STATUS_ATTACHING &&
317        at->status != STATUS_DETACHING)
318        goto bad_line;
319    /* Quota doesn't care about this entry */
320    if (at->status != STATUS_ATTACHED)
321        return FAILURE;
322
323    at->fs = get_fs(cp);
324    if (at->fs == NULL)
325        goto bad_line;
326
327    if (!(cp = strtok(NULL, TOKSEP)))
328        goto bad_line;
329    (void) strcpy(at->hesiodname, cp);
330
331    if (!(cp = strtok(NULL, TOKSEP)))
332        goto bad_line;
333    (void) strcpy(at->host, cp);
334
335    if (!(cp = strtok(NULL, TOKSEP)))
336        goto bad_line;
337    (void) strcpy(at->hostdir, cp);
338
339    if (!(cp = strtok(NULL, TOKSEP)))
340        goto bad_line;
341
342    for (i=0; cp; i++) {
343        register char *dp;
344
345        if (dp = index(cp, ','))
346            *dp++ = '\0';
347        at->hostaddr[i].s_addr = inet_addr(cp);
348        cp = dp;
349    }
350
351    if (!(cp = strtok(NULL, TOKSEP)))
352        goto bad_line;
353    at->rmdir = atoi(cp);
354
355    if (!(cp = strtok(NULL, TOKSEP)))
356        goto bad_line;
357    (void) strcpy(at->mntpt, cp);
358
359    if (!(cp = strtok(NULL, TOKSEP)))
360        goto bad_line;
361    at->flags = atoi(cp);
362   
363    if (!(cp = strtok(NULL, TOKSEP)))
364        goto bad_line;
365    at->nowners = 0;
366    if (*cp == ',')                             /* If heading character is comma */
367        cp = 0;                                 /* we have a null list*/
368    while (cp) {
369        register char *dp;
370           
371        if (dp = index(cp, ','))
372            *dp++ = '\0';
373        at->owners[at->nowners++] = atoi(cp);
374        cp = dp;
375    }
376   
377    if (!(cp = strtok(NULL, TOKSEP)))
378        goto bad_line;
379   
380    at->drivenum = atoi(cp);
381   
382    if (!(cp = strtok(NULL, TOKSEP)))
383        goto bad_line;
384    at->mode = *cp;
385#if 0
386    if (at->fs->good_flags) {
387        if (!index(at->fs->good_flags, at->mode))
388            goto bad_line;                      /* Bad attach mode */
389    }
390#endif
391   
392    at->next = NULL;
393    at->prev = NULL;
394    return SUCCESS;
395   
396 bad_line:
397    fprintf(stderr,"Badly formatted entry in %s\n", attachtab_fn);
398    if (lintflag)
399        return FAILURE;
400    fprintf(stderr, abort_msg);
401    exit(ERR_FATAL);
402    /* NOTREACHED */
403}
404
405#if 0
406/*
407 * Routine to see if a host is in the attachtab - uses the linked list
408 * attachtab in memory
409 */
410host_occurs(name)
411    register char *name;
412{
413    register struct _attachtab  *p;
414
415    p = attachtab_first;
416    while (p) {
417        if (!strcasecmp(p->host, name))
418            return(1);
419        p = p->next;
420    }
421    return (0);
422}
423#endif
424
425/*
426 * Lookup an entry in attachtab  --- uses the linked list stored in memory
427 */
428struct _attachtab *attachtab_lookup(hesiod)
429    register char *hesiod;
430{
431    register struct _attachtab  *p;
432
433    p = attachtab_first;
434    while (p) {
435        if (!strcmp(p->hesiodname, hesiod))
436            return(p);
437        p = p->next;
438    }
439    return (NULL);
440}
441
442/*
443 * Lookup an entry in attachtab by mountpoint --- uses the linked list
444 *      stored in memory
445 */
446struct _attachtab *attachtab_lookup_mntpt(pt)
447    register char *pt;
448{
449    register struct _attachtab  *p;
450
451    p = attachtab_first;
452    while (p) {
453        if (!strcmp(p->mntpt, pt))
454            return(p);
455        p = p->next;
456    }
457    return (NULL);
458}
459
460#if 0
461/*
462 * Delete an entry from the attachtab --- unlinks the passed attachtab
463 *      record in the in-core linked list; assumes attachtab is locked.
464 *      You must call put_attachtab to actually affect the copy on disk.
465 */
466attachtab_delete(at)
467    register struct _attachtab  *at;
468{
469    if (!at)
470        return;
471       
472    if (at->prev)
473        at->prev->next = at->next;
474    else
475        attachtab_first = at->next;
476    if (at->next)
477        at->next->prev = at->prev;
478    else
479        attachtab_last = at->prev;
480    free(at);
481}
482
483/*
484 * Append an entry to the linked list database in attachtab
485 */
486attachtab_append(at)
487    register struct _attachtab *at;
488{
489
490    register struct _attachtab *atnew;
491
492    if (!(atnew = (struct _attachtab *)
493          malloc(sizeof(struct _attachtab)))) {
494        fprintf(stderr, "Can't malloc while adding to attachtab\n");
495        fprintf(stderr, abort_msg);
496        exit(ERR_FATAL);
497    }
498    *atnew = *at;
499
500    strcpy(atnew->version, ATTACH_VERSION);
501       
502    if (attachtab_last)
503        attachtab_last ->next = atnew;
504    else
505        attachtab_first = atnew;
506    atnew->prev = attachtab_last;
507    atnew->next = NULL;
508    attachtab_last = atnew;
509}
510
511/*
512 * Replace an entry in the linked list
513 */
514attachtab_replace(at)
515    register struct _attachtab *at;
516{
517    register struct _attachtab *p, *next, *prev;
518
519    strcpy(at->version, ATTACH_VERSION);
520       
521    p = attachtab_first;
522
523    while (p) {
524        if (!hescmp(p, at->hesiodname) && p->explicit == explicit) {
525            next = p->next;
526            prev = p->prev;
527            *p = *at;
528            p->next = next;
529            p->prev = prev;
530        }
531        p = p->next;
532    }
533}
534#endif
535
536
537struct _fstypes fstypes[] = {
538    "NFS", TYPE_NFS,
539    "RVD", TYPE_RVD,
540    "UFS", TYPE_UFS,
541    "ERR", TYPE_ERR,
542    "AFS", TYPE_AFS,
543    "MUL", TYPE_MUL,
544    0, 0 };
545
546/*
547 * Convert a string type to a filesystem type entry
548 */
549struct _fstypes *get_fs(s)
550    char *s;
551{
552    int i;
553
554    if (s && *s) {
555        for (i=0;fstypes[i].name;i++) {
556            if (!strcasecmp(fstypes[i].name, s))
557                return (&fstypes[i]);
558        }
559    }
560    return (NULL);
561}
Note: See TracBrowser for help on using the repository browser.