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