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