]> arthur.barton.de Git - netatalk.git/blob - etc/afpd/parse_mtab.c
Warning fixes.
[netatalk.git] / etc / afpd / parse_mtab.c
1 /*
2  * $Id: parse_mtab.c,v 1.6 2001-12-10 20:16:54 srittau Exp $
3  *
4  * afpd_mtab_parse & support.  -- rgr, 9-Apr-01.
5  */
6
7 #ifdef HAVE_CONFIG_H
8 #include "config.h"
9 #endif /* HAVE_CONFIG_H */
10
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <errno.h>
14
15 /* STDC check */
16 #if STDC_HEADERS
17 #include <string.h>
18 #else /* STDC_HEADERS */
19 #ifndef HAVE_STRCHR
20 #define strchr index
21 #define strrchr index
22 #endif /* HAVE_STRCHR */
23 char *strchr (), *strrchr ();
24 #ifndef HAVE_MEMCPY
25 #define memcpy(d,s,n) bcopy ((s), (d), (n))
26 #define memmove(d,s,n) bcopy ((s), (d), (n))
27 #endif /* ! HAVE_MEMCPY */
28 #endif /* STDC_HEADERS */
29
30 #include <sys/stat.h>
31
32 #include "directory.h"
33 #include "parse_mtab.h"
34
35 #define MAX_AFPD_MTAB_ENTRIES 256       /* unreasonably large number */
36 #define MTAB_DELIM_CHARS " \t\n"        /* delimiters for parsing */
37
38 #ifndef COPY_STRING
39 #define COPY_STRING(lval, str) \
40           (lval) = malloc(1+strlen(str)), strcpy((lval), (str))
41 #endif /* COPY_STRING */
42
43 /* global mount table; afpd_st_cnid uses this to lookup the right entry.  */
44 static struct afpd_mount_table *afpd_mount_table;
45         
46 static int
47 ceil_log_2 __P((int n))
48 /* Return the number of bits required to represent n.  Only works for
49 positive n.  */
50 {
51     int n_bits = 0;
52
53     while (n) {
54         n >>= 1;
55         n_bits += 1;
56     }
57     return(n_bits);
58 }
59
60 unsigned int
61 afpd_st_cnid __P((struct stat *st))
62 /* Given a stat structure, look up the device in afpd_mount_table, and
63    compute and return a CNID.  */
64 {
65     int id;
66     struct afpd_mtab_entry *entry;
67
68     if (afpd_mount_table != NULL) {
69         for (id = 0; id < afpd_mount_table->size; id++) {
70             entry = afpd_mount_table->table[id];
71             if (entry != NULL
72                     && entry->dev_major == major(st->st_dev)
73                     && entry->dev_minor == minor(st->st_dev)) {
74                 return(entry->bit_value | st->st_ino);
75             }
76         }
77     }
78
79     /* Fallback. */
80     return(st->st_ino);
81 }
82
83 struct afpd_mount_table *
84             afpd_mtab_parse __P((char *file_name))
85             /* Parse the given mtab file, returning a new afpd_mount_table structure.
86             Also saves it in the afpd_mount_table static variable for use by the
87             afpd_st_cnid function.  Returns NULL if it encounters an error.
88
89                [It would be great if this could generate a warning for any device that
90                allows more inodes than we can allocate bits for.  -- rgr, 9-Apr-01.]
91                */
92 {
93     struct afpd_mtab_entry *entries[MAX_AFPD_MTAB_ENTRIES];     /* temp */
94     int id, max_id = 0, n_errors = 0;
95     struct stat st;
96     char line[1000], *p, *index_tok, *dev_tok, *mount_tok;
97     int line_number = 0;                /* one-based */
98     FILE *f = fopen(file_name, "r");
99
100     if (f == NULL) {
101         fprintf(stderr, "Error:  Can't open %s:  code %d\n",
102                 file_name, errno);
103         return(NULL);
104     }
105     for (id = 0; id < MAX_AFPD_MTAB_ENTRIES; id++)
106         entries[id] = NULL;
107     while (fgets(line, sizeof(line), f) != NULL) {
108         line_number++;
109         /* flush comment */
110         if ((p = strchr(line, '#')) != NULL)
111             *p = '\0';
112         /* get fields */
113         index_tok = strtok(line, MTAB_DELIM_CHARS);
114         dev_tok = strtok(NULL, MTAB_DELIM_CHARS);
115         mount_tok = strtok(NULL, MTAB_DELIM_CHARS);
116         if (mount_tok == NULL) {
117             /* [warning here if index_tok nonempty?  -- rgr, 9-Apr-01.]  */
118         }
119         else if (id = strtol(index_tok, &p, 10),
120                  *p != '\0') {
121             fprintf(stderr, "afpd:%s:%d:  Non-integer device index value '%s'.\n",
122                     file_name, line_number, index_tok);
123             n_errors++;
124         }
125         else if (id < 1 || id > MAX_AFPD_MTAB_ENTRIES) {
126             fprintf(stderr,
127                     "afpd:%s:%d:  Expected an integer from 1 to %d, but got '%s'.\n",
128                     file_name, line_number, MAX_AFPD_MTAB_ENTRIES-1, index_tok);
129             n_errors++;
130         }
131         else if (entries[id] != NULL) {
132             /* not unique. */
133             fprintf(stderr,
134                     "afpd:%s:%d:  Id %d is already taken for %s.\n",
135                     file_name, line_number, id, entries[id]->device);
136             n_errors++;
137         }
138         else if (stat(dev_tok, &st) != 0) {
139             fprintf(stderr, "afpd:%s:%d:  Can't stat '%s':  code %d\n",
140                     file_name, line_number, dev_tok, errno);
141             n_errors++;
142         }
143         else if (! S_ISBLK(st.st_mode)) {
144             fprintf(stderr, "afpd:%s:%d:  '%s' is not a block device.\n",
145                     file_name, line_number, dev_tok);
146             n_errors++;
147         }
148         else {
149             /* make a new entry */
150             struct afpd_mtab_entry *entry
151                         = (struct afpd_mtab_entry *) malloc(sizeof(struct afpd_mtab_entry));
152
153             entry->id = id;
154             entry->dev_major = major(st.st_rdev);
155             entry->dev_minor = minor(st.st_rdev);
156             COPY_STRING(entry->device, dev_tok);
157             COPY_STRING(entry->mount_point, mount_tok);
158             entries[id] = entry;
159             if (id > max_id)
160                 max_id = id;
161         }
162     } /* next line */
163
164     fclose(f);
165 if (n_errors) {
166         fprintf(stderr, "Got %d errors while reading %s; exiting.\n",
167                 n_errors, file_name);
168         return(NULL);
169     }
170     else {
171         /* make the table. */
172         struct afpd_mount_table *mount_table    /* return value */
173                     = (struct afpd_mount_table *) malloc(sizeof(struct afpd_mount_table));
174         int n_bits = ceil_log_2(max_id);
175         int table_size;
176         struct afpd_mtab_entry **new_entries;
177
178         if (n_bits < AFPD_MTAB_MIN_DEV_BITS)
179             n_bits = AFPD_MTAB_MIN_DEV_BITS;
180         table_size = 1 << n_bits;
181         new_entries = (struct afpd_mtab_entry **)
182                       malloc(table_size*sizeof(struct afpd_mtab_entry *));
183         mount_table->size = table_size;
184         mount_table->bits = n_bits;
185         mount_table->shift = AFPD_MTAB_DEV_AND_INODE_BITS-n_bits;
186 for (id = 0; id < table_size; id++) {
187             if (entries[id] != NULL)
188                 entries[id]->bit_value = entries[id]->id << mount_table->shift;
189             new_entries[id] = entries[id];
190         }
191         mount_table->table = new_entries;
192
193         afpd_mount_table = mount_table;
194         return(mount_table);
195     }
196 }