Whamcloud - gitweb
Only use the test_io manager if the right environment variables are set
[tools/e2fsprogs.git] / misc / e2initrd_helper.c
1 /*
2  * e2initrd_helper.c - Get the filesystem table
3  *
4  * Copyright 2004 by Theodore Ts'o.
5  *
6  * %Begin-Header%
7  * This file may be redistributed under the terms of the GNU Public
8  * License.
9  * %End-Header%
10  */
11
12 #include <stdio.h>
13 #include <unistd.h>
14 #ifdef HAVE_STDLIB_H
15 #include <stdlib.h>
16 #endif
17 #include <ctype.h>
18 #include <string.h>
19 #include <time.h>
20 #ifdef HAVE_ERRNO_H
21 #include <errno.h>
22 #endif
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 #include <fcntl.h>
26 #include <utime.h>
27 #ifdef HAVE_GETOPT_H
28 #include <getopt.h>
29 #else
30 extern int optind;
31 extern char *optarg;
32 #endif
33
34 #include "ext2fs/ext2_fs.h"
35 #include "ext2fs/ext2fs.h"
36 #include "e2p/e2p.h"
37 #include "blkid/blkid.h"
38
39 #include "../version.h"
40 #include "nls-enable.h"
41
42 const char * program_name = "get_fstab";
43 char * device_name;
44 static int open_flag;
45 static int root_type;
46 static blkid_cache cache = NULL;
47
48 struct mem_file {
49         char    *buf;
50         int     size;
51         int     ptr;
52 };
53
54 struct fs_info {
55         char  *device;
56         char  *mountpt;
57         char  *type;
58         char  *opts;
59         int   freq;
60         int   passno;
61         int   flags;
62         struct fs_info *next;
63 };
64
65 static void usage(void)
66 {
67         fprintf(stderr,
68                 _("Usage: %s -r device\n"), program_name);
69         exit (1);
70 }
71
72 static errcode_t get_file(ext2_filsys fs, const char * filename,
73                    struct mem_file *ret_file)
74 {
75         errcode_t       retval;
76         char            *buf;
77         ext2_file_t     e2_file;
78         unsigned int    got;
79         struct ext2_inode inode;
80         ext2_ino_t      ino;
81
82         ret_file->buf = 0;
83         ret_file->size = 0;
84         ret_file->ptr = 0;
85
86         retval = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO,
87                               filename, &ino);
88         if (retval)
89                 return retval;
90
91         retval = ext2fs_read_inode(fs, ino, &inode);
92         if (retval)
93                 return retval;
94
95         if (inode.i_size_high || (inode.i_size > 65536))
96                 return EFBIG;
97
98         buf = malloc(inode.i_size + 1);
99         if (!buf)
100                 return ENOMEM;
101         memset(buf, 0, inode.i_size+1);
102
103         retval = ext2fs_file_open(fs, ino, 0, &e2_file);
104         if (retval)
105                 return retval;
106
107         retval = ext2fs_file_read(e2_file, buf, inode.i_size, &got);
108         if (retval)
109                 goto errout;
110
111         retval = ext2fs_file_close(e2_file);
112         if (retval)
113                 return retval;
114
115         ret_file->buf = buf;
116         ret_file->size = (int) got;
117
118 errout:
119         ext2fs_file_close(e2_file);
120         return retval;
121 }
122
123 static char *get_line(struct mem_file *file)
124 {
125         char    *cp, *ret;
126         int     s = 0;
127
128         cp = file->buf + file->ptr;
129         while (*cp && *cp != '\n') {
130                 cp++;
131                 s++;
132         }
133         ret = malloc(s+1);
134         if (!ret)
135                 return 0;
136         ret[s]=0;
137         memcpy(ret, file->buf + file->ptr, s);
138         while (*cp && (*cp == '\n' || *cp == '\r')) {
139                 cp++;
140                 s++;
141         }
142         file->ptr += s;
143         return ret;
144 }
145
146 static int mem_file_eof(struct mem_file *file)
147 {
148         return (file->ptr >= file->size);
149 }
150
151 /*
152  * fstab parsing code
153  */
154 static char *string_copy(const char *s)
155 {
156         char    *ret;
157
158         if (!s)
159                 return 0;
160         ret = malloc(strlen(s)+1);
161         if (ret)
162                 strcpy(ret, s);
163         return ret;
164 }
165
166 static char *skip_over_blank(char *cp)
167 {
168         while (*cp && isspace(*cp))
169                 cp++;
170         return cp;
171 }
172
173 static char *skip_over_word(char *cp)
174 {
175         while (*cp && !isspace(*cp))
176                 cp++;
177         return cp;
178 }
179
180 static char *parse_word(char **buf)
181 {
182         char *word, *next;
183
184         word = *buf;
185         if (*word == 0)
186                 return 0;
187
188         word = skip_over_blank(word);
189         next = skip_over_word(word);
190         if (*next)
191                 *next++ = 0;
192         *buf = next;
193         return word;
194 }
195
196 static void parse_escape(char *word)
197 {
198         char    *p, *q;
199         int     ac, i;
200
201         if (!word)
202                 return;
203
204         for (p = word, q = word; *p; p++, q++) {
205                 *q = *p;
206                 if (*p != '\\')
207                         continue;
208                 if (*++p == 0)
209                         break;
210                 if (*p == 't') {
211                         *q = '\t';
212                         continue;
213                 }
214                 if (*p == 'n') {
215                         *q = '\n';
216                         continue;
217                 }
218                 if (!isdigit(*p)) {
219                         *q = *p;
220                         continue;
221                 }
222                 ac = 0;
223                 for (i = 0; i < 3; i++, p++) {
224                         if (!isdigit(*p))
225                                 break;
226                         ac = (ac * 8) + (*p - '0');
227                 }
228                 *q = ac;
229                 p--;
230         }
231         *q = 0;
232 }
233
234 static int parse_fstab_line(char *line, struct fs_info *fs)
235 {
236         char    *dev, *device, *mntpnt, *type, *opts, *freq, *passno, *cp;
237
238         if ((cp = strchr(line, '#')))
239                 *cp = 0;        /* Ignore everything after the comment char */
240         cp = line;
241
242         device = parse_word(&cp);
243         mntpnt = parse_word(&cp);
244         type = parse_word(&cp);
245         opts = parse_word(&cp);
246         freq = parse_word(&cp);
247         passno = parse_word(&cp);
248
249         if (!device)
250                 return -1;      /* Allow blank lines */
251
252         if (!mntpnt || !type)
253                 return -1;
254
255         parse_escape(device);
256         parse_escape(mntpnt);
257         parse_escape(type);
258         parse_escape(opts);
259         parse_escape(freq);
260         parse_escape(passno);
261
262         dev = blkid_get_devname(cache, device, NULL);
263         if (dev)
264                 device = dev;
265
266         if (strchr(type, ','))
267                 type = 0;
268
269         fs->device = string_copy(device);
270         fs->mountpt = string_copy(mntpnt);
271         fs->type = string_copy(type);
272         fs->opts = string_copy(opts ? opts : "");
273         fs->freq = freq ? atoi(freq) : -1;
274         fs->passno = passno ? atoi(passno) : -1;
275         fs->flags = 0;
276         fs->next = NULL;
277
278         if (dev)
279                 free(dev);
280
281         return 0;
282 }
283
284 static void free_fstab_line(struct fs_info *fs)
285 {
286         if (fs->device)
287                 fs->device = 0;
288         if (fs->mountpt)
289                 fs->mountpt = 0;
290         if (fs->type)
291                 fs->type = 0;
292         if (fs->opts)
293                 fs->opts = 0;
294         memset(fs, 0, sizeof(struct fs_info));
295 }
296
297
298 static void PRS(int argc, char **argv)
299 {
300         int c;
301
302 #ifdef ENABLE_NLS
303         setlocale(LC_MESSAGES, "");
304         setlocale(LC_CTYPE, "");
305         bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
306         textdomain(NLS_CAT_NAME);
307 #endif
308
309         while ((c = getopt(argc, argv, "rv")) != EOF) {
310                 switch (c) {
311                 case 'r':
312                         root_type++;
313                         break;
314
315                 case 'v':
316                         printf("%s %s (%s)\n", program_name,
317                                E2FSPROGS_VERSION, E2FSPROGS_DATE);
318                         break;
319                 default:
320                         usage();
321                 }
322         }
323         if (optind < argc - 1 || optind == argc)
324                 usage();
325         device_name = blkid_get_devname(NULL, argv[optind], NULL);
326         if (!device_name) {
327                 com_err("tune2fs", 0, _("Unable to resolve '%s'"),
328                         argv[optind]);
329                 exit(1);
330         }
331 }
332
333 static void get_root_type(ext2_filsys fs)
334 {
335         errcode_t retval;
336         struct mem_file file;
337         char            *buf;
338         struct fs_info fs_info;
339         int             ret;
340
341         retval = get_file(fs, "/etc/fstab", &file);
342
343         while (!mem_file_eof(&file)) {
344                 buf = get_line(&file);
345                 if (!buf)
346                         continue;
347
348                 ret = parse_fstab_line(buf, &fs_info);
349                 if (ret < 0)
350                         goto next_line;
351
352                 if (!strcmp(fs_info.mountpt, "/"))
353                         printf("%s\n", fs_info.type);
354
355                 free_fstab_line(&fs_info);
356
357         next_line:
358                 free(buf);
359         }
360 }
361
362
363 int main (int argc, char ** argv)
364 {
365         errcode_t retval;
366         ext2_filsys fs;
367         io_manager io_ptr;
368
369         add_error_table(&et_ext2_error_table);
370
371         blkid_get_cache(&cache, NULL);
372         PRS(argc, argv);
373
374 #ifdef CONFIG_TESTIO_DEBUG
375         if (getenv("TEST_IO_FLAGS") || getenv("TEST_IO_BLOCK")) {
376                 io_ptr = test_io_manager;
377                 test_io_backing_manager = unix_io_manager;
378         } else
379 #endif
380                 io_ptr = unix_io_manager;
381         retval = ext2fs_open (device_name, open_flag, 0, 0, io_ptr, &fs);
382         if (retval)
383                 exit(1);
384
385         if (root_type)
386                 get_root_type(fs);
387
388         remove_error_table(&et_ext2_error_table);
389         return (ext2fs_close (fs) ? 1 : 0);
390 }