source: trunk/athena/bin/attach/attachtab.c @ 6261

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