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