2 * $Id: parse_mtab.c,v 1.6 2001-12-10 20:16:54 srittau Exp $
4 * afpd_mtab_parse & support. -- rgr, 9-Apr-01.
9 #endif /* HAVE_CONFIG_H */
18 #else /* STDC_HEADERS */
22 #endif /* HAVE_STRCHR */
23 char *strchr (), *strrchr ();
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 */
32 #include "directory.h"
33 #include "parse_mtab.h"
35 #define MAX_AFPD_MTAB_ENTRIES 256 /* unreasonably large number */
36 #define MTAB_DELIM_CHARS " \t\n" /* delimiters for parsing */
39 #define COPY_STRING(lval, str) \
40 (lval) = malloc(1+strlen(str)), strcpy((lval), (str))
41 #endif /* COPY_STRING */
43 /* global mount table; afpd_st_cnid uses this to lookup the right entry. */
44 static struct afpd_mount_table *afpd_mount_table;
47 ceil_log_2 __P((int n))
48 /* Return the number of bits required to represent n. Only works for
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. */
66 struct afpd_mtab_entry *entry;
68 if (afpd_mount_table != NULL) {
69 for (id = 0; id < afpd_mount_table->size; id++) {
70 entry = afpd_mount_table->table[id];
72 && entry->dev_major == major(st->st_dev)
73 && entry->dev_minor == minor(st->st_dev)) {
74 return(entry->bit_value | st->st_ino);
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.
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.]
93 struct afpd_mtab_entry *entries[MAX_AFPD_MTAB_ENTRIES]; /* temp */
94 int id, max_id = 0, n_errors = 0;
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");
101 fprintf(stderr, "Error: Can't open %s: code %d\n",
105 for (id = 0; id < MAX_AFPD_MTAB_ENTRIES; id++)
107 while (fgets(line, sizeof(line), f) != NULL) {
110 if ((p = strchr(line, '#')) != NULL)
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.] */
119 else if (id = strtol(index_tok, &p, 10),
121 fprintf(stderr, "afpd:%s:%d: Non-integer device index value '%s'.\n",
122 file_name, line_number, index_tok);
125 else if (id < 1 || id > MAX_AFPD_MTAB_ENTRIES) {
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);
131 else if (entries[id] != NULL) {
134 "afpd:%s:%d: Id %d is already taken for %s.\n",
135 file_name, line_number, id, entries[id]->device);
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);
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);
149 /* make a new entry */
150 struct afpd_mtab_entry *entry
151 = (struct afpd_mtab_entry *) malloc(sizeof(struct afpd_mtab_entry));
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);
166 fprintf(stderr, "Got %d errors while reading %s; exiting.\n",
167 n_errors, file_name);
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);
176 struct afpd_mtab_entry **new_entries;
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];
191 mount_table->table = new_entries;
193 afpd_mount_table = mount_table;