blob: 22672a3db19a4ba4bb3dcc8a32d3846c93b985f7 [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>
Theodore Ts'of38cf3c2008-09-01 11:17:29 -040014#ifdef HAVE_STDLIB_H
Theodore Ts'o5d407732004-09-18 14:53:14 -040015#include <stdlib.h>
Theodore Ts'of38cf3c2008-09-01 11:17:29 -040016#endif
Theodore Ts'o5d407732004-09-18 14:53:14 -040017#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>
Theodore Ts'oefc6f622008-08-27 23:07:54 -040029#else
Theodore Ts'o5d407732004-09-18 14:53:14 -040030extern int optind;
31extern char *optarg;
32#endif
33
34#include "ext2fs/ext2_fs.h"
35#include "ext2fs/ext2fs.h"
Theodore Ts'o5d407732004-09-18 14:53:14 -040036#include "blkid/blkid.h"
37
38#include "../version.h"
39#include "nls-enable.h"
40
JP Abgralle0ed7402014-03-19 19:08:39 -070041static const char * program_name = "e2initrd_helper";
42static char * device_name;
Theodore Ts'o5d407732004-09-18 14:53:14 -040043static int open_flag;
44static int root_type;
45static blkid_cache cache = NULL;
46
47struct mem_file {
48 char *buf;
49 int size;
50 int ptr;
51};
52
53struct fs_info {
54 char *device;
55 char *mountpt;
56 char *type;
57 char *opts;
58 int freq;
59 int passno;
60 int flags;
61 struct fs_info *next;
62};
63
64static void usage(void)
65{
66 fprintf(stderr,
67 _("Usage: %s -r device\n"), program_name);
68 exit (1);
69}
70
Theodore Ts'oefc6f622008-08-27 23:07:54 -040071static errcode_t get_file(ext2_filsys fs, const char * filename,
Theodore Ts'o5d407732004-09-18 14:53:14 -040072 struct mem_file *ret_file)
73{
74 errcode_t retval;
75 char *buf;
JP Abgralle0ed7402014-03-19 19:08:39 -070076 ext2_file_t e2_file = NULL;
Theodore Ts'o5d407732004-09-18 14:53:14 -040077 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
Theodore Ts'oefc6f622008-08-27 23:07:54 -040085 retval = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO,
Theodore Ts'o5d407732004-09-18 14:53:14 -040086 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)
JP Abgralle0ed7402014-03-19 19:08:39 -0700104 goto errout;
Theodore Ts'o5d407732004-09-18 14:53:14 -0400105
106 retval = ext2fs_file_read(e2_file, buf, inode.i_size, &got);
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400107 if (retval)
Theodore Ts'o5d407732004-09-18 14:53:14 -0400108 goto errout;
109
110 retval = ext2fs_file_close(e2_file);
111 if (retval)
JP Abgralle0ed7402014-03-19 19:08:39 -0700112 goto errout;
Theodore Ts'o5d407732004-09-18 14:53:14 -0400113
114 ret_file->buf = buf;
115 ret_file->size = (int) got;
JP Abgralle0ed7402014-03-19 19:08:39 -0700116 return 0;
Theodore Ts'o5d407732004-09-18 14:53:14 -0400117
118errout:
JP Abgralle0ed7402014-03-19 19:08:39 -0700119 free(buf);
120 if (e2_file)
121 ext2fs_file_close(e2_file);
Theodore Ts'o5d407732004-09-18 14:53:14 -0400122 return retval;
123}
124
Theodore Ts'o6e82cd72005-01-05 03:02:54 -0500125static char *get_line(struct mem_file *file)
Theodore Ts'o5d407732004-09-18 14:53:14 -0400126{
127 char *cp, *ret;
128 int s = 0;
129
130 cp = file->buf + file->ptr;
131 while (*cp && *cp != '\n') {
132 cp++;
133 s++;
134 }
135 ret = malloc(s+1);
136 if (!ret)
137 return 0;
138 ret[s]=0;
139 memcpy(ret, file->buf + file->ptr, s);
140 while (*cp && (*cp == '\n' || *cp == '\r')) {
141 cp++;
142 s++;
143 }
144 file->ptr += s;
145 return ret;
146}
147
Theodore Ts'o6e82cd72005-01-05 03:02:54 -0500148static int mem_file_eof(struct mem_file *file)
Theodore Ts'o5d407732004-09-18 14:53:14 -0400149{
150 return (file->ptr >= file->size);
151}
152
153/*
154 * fstab parsing code
155 */
156static char *string_copy(const char *s)
157{
158 char *ret;
159
160 if (!s)
161 return 0;
162 ret = malloc(strlen(s)+1);
163 if (ret)
164 strcpy(ret, s);
165 return ret;
166}
167
168static char *skip_over_blank(char *cp)
169{
170 while (*cp && isspace(*cp))
171 cp++;
172 return cp;
173}
174
175static char *skip_over_word(char *cp)
176{
177 while (*cp && !isspace(*cp))
178 cp++;
179 return cp;
180}
181
182static char *parse_word(char **buf)
183{
184 char *word, *next;
185
186 word = *buf;
187 if (*word == 0)
188 return 0;
189
190 word = skip_over_blank(word);
191 next = skip_over_word(word);
192 if (*next)
193 *next++ = 0;
194 *buf = next;
195 return word;
196}
197
198static void parse_escape(char *word)
199{
200 char *p, *q;
201 int ac, i;
202
203 if (!word)
204 return;
205
206 for (p = word, q = word; *p; p++, q++) {
207 *q = *p;
208 if (*p != '\\')
209 continue;
210 if (*++p == 0)
211 break;
212 if (*p == 't') {
213 *q = '\t';
214 continue;
215 }
216 if (*p == 'n') {
217 *q = '\n';
218 continue;
219 }
220 if (!isdigit(*p)) {
221 *q = *p;
222 continue;
223 }
224 ac = 0;
225 for (i = 0; i < 3; i++, p++) {
226 if (!isdigit(*p))
227 break;
228 ac = (ac * 8) + (*p - '0');
229 }
230 *q = ac;
231 p--;
232 }
233 *q = 0;
234}
235
236static int parse_fstab_line(char *line, struct fs_info *fs)
237{
238 char *dev, *device, *mntpnt, *type, *opts, *freq, *passno, *cp;
239
240 if ((cp = strchr(line, '#')))
241 *cp = 0; /* Ignore everything after the comment char */
242 cp = line;
243
244 device = parse_word(&cp);
245 mntpnt = parse_word(&cp);
246 type = parse_word(&cp);
247 opts = parse_word(&cp);
248 freq = parse_word(&cp);
249 passno = parse_word(&cp);
250
251 if (!device)
252 return -1; /* Allow blank lines */
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400253
Theodore Ts'o5d407732004-09-18 14:53:14 -0400254 if (!mntpnt || !type)
255 return -1;
256
257 parse_escape(device);
258 parse_escape(mntpnt);
259 parse_escape(type);
260 parse_escape(opts);
261 parse_escape(freq);
262 parse_escape(passno);
263
264 dev = blkid_get_devname(cache, device, NULL);
265 if (dev)
266 device = dev;
267
268 if (strchr(type, ','))
269 type = 0;
270
271 fs->device = string_copy(device);
272 fs->mountpt = string_copy(mntpnt);
273 fs->type = string_copy(type);
274 fs->opts = string_copy(opts ? opts : "");
275 fs->freq = freq ? atoi(freq) : -1;
276 fs->passno = passno ? atoi(passno) : -1;
277 fs->flags = 0;
278 fs->next = NULL;
279
Jim Meyering45e338f2009-02-23 18:07:50 +0100280 free(dev);
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400281
Theodore Ts'o5d407732004-09-18 14:53:14 -0400282 return 0;
283}
284
Theodore Ts'o6e82cd72005-01-05 03:02:54 -0500285static void free_fstab_line(struct fs_info *fs)
Theodore Ts'o5d407732004-09-18 14:53:14 -0400286{
287 if (fs->device)
288 fs->device = 0;
289 if (fs->mountpt)
290 fs->mountpt = 0;
291 if (fs->type)
292 fs->type = 0;
293 if (fs->opts)
294 fs->opts = 0;
295 memset(fs, 0, sizeof(struct fs_info));
296}
297
298
299static void PRS(int argc, char **argv)
300{
301 int c;
Theodore Ts'o5d407732004-09-18 14:53:14 -0400302
303#ifdef ENABLE_NLS
304 setlocale(LC_MESSAGES, "");
305 setlocale(LC_CTYPE, "");
306 bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
307 textdomain(NLS_CAT_NAME);
JP Abgralle0ed7402014-03-19 19:08:39 -0700308 set_com_err_gettext(gettext);
Theodore Ts'o5d407732004-09-18 14:53:14 -0400309#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':
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400318 printf("%s %s (%s)\n", program_name,
Theodore Ts'o5d407732004-09-18 14:53:14 -0400319 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) {
JP Abgralle0ed7402014-03-19 19:08:39 -0700329 com_err(program_name, 0, _("Unable to resolve '%s'"),
Theodore Ts'o5d407732004-09-18 14:53:14 -0400330 argv[optind]);
331 exit(1);
332 }
333}
334
Theodore Ts'o6e82cd72005-01-05 03:02:54 -0500335static void get_root_type(ext2_filsys fs)
Theodore Ts'o5d407732004-09-18 14:53:14 -0400336{
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);
JP Abgralle0ed7402014-03-19 19:08:39 -0700344 if (retval) {
345 com_err(program_name, retval, "couldn't open /etc/fstab");
346 exit(1);
347 }
Theodore Ts'o5d407732004-09-18 14:53:14 -0400348
349 while (!mem_file_eof(&file)) {
350 buf = get_line(&file);
351 if (!buf)
352 continue;
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400353
Theodore Ts'o5d407732004-09-18 14:53:14 -0400354 ret = parse_fstab_line(buf, &fs_info);
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400355 if (ret < 0)
Theodore Ts'o5d407732004-09-18 14:53:14 -0400356 goto next_line;
357
358 if (!strcmp(fs_info.mountpt, "/"))
359 printf("%s\n", fs_info.type);
360
361 free_fstab_line(&fs_info);
362
363 next_line:
364 free(buf);
365 }
366}
367
368
369int main (int argc, char ** argv)
370{
371 errcode_t retval;
372 ext2_filsys fs;
Theodore Ts'o5d407732004-09-18 14:53:14 -0400373 io_manager io_ptr;
Theodore Ts'o5d407732004-09-18 14:53:14 -0400374
Theodore Ts'oa6d83022006-12-26 03:38:07 -0500375 add_error_table(&et_ext2_error_table);
Theodore Ts'o5d407732004-09-18 14:53:14 -0400376
377 blkid_get_cache(&cache, NULL);
378 PRS(argc, argv);
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400379
Theodore Ts'o5d407732004-09-18 14:53:14 -0400380#ifdef CONFIG_TESTIO_DEBUG
Theodore Ts'of38cf3c2008-09-01 11:17:29 -0400381 if (getenv("TEST_IO_FLAGS") || getenv("TEST_IO_BLOCK")) {
382 io_ptr = test_io_manager;
383 test_io_backing_manager = unix_io_manager;
384 } else
Theodore Ts'o5d407732004-09-18 14:53:14 -0400385#endif
Theodore Ts'of38cf3c2008-09-01 11:17:29 -0400386 io_ptr = unix_io_manager;
Theodore Ts'o5d407732004-09-18 14:53:14 -0400387 retval = ext2fs_open (device_name, open_flag, 0, 0, io_ptr, &fs);
388 if (retval)
389 exit(1);
390
Theodore Ts'oefc6f622008-08-27 23:07:54 -0400391 if (root_type)
Theodore Ts'o5d407732004-09-18 14:53:14 -0400392 get_root_type(fs);
393
Theodore Ts'oa6d83022006-12-26 03:38:07 -0500394 remove_error_table(&et_ext2_error_table);
Theodore Ts'o5d407732004-09-18 14:53:14 -0400395 return (ext2fs_close (fs) ? 1 : 0);
396}