15d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o/*
25d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o * e2initrd_helper.c - Get the filesystem table
35d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o *
45d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o * Copyright 2004 by Theodore Ts'o.
55d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o *
65d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o * %Begin-Header%
75d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o * This file may be redistributed under the terms of the GNU Public
85d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o * License.
95d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o * %End-Header%
105d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o */
115d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o
125d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o#include <stdio.h>
135d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o#include <unistd.h>
14f38cf3cb34addaa53d1f855d7607b151082a4229Theodore Ts'o#ifdef HAVE_STDLIB_H
155d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o#include <stdlib.h>
16f38cf3cb34addaa53d1f855d7607b151082a4229Theodore Ts'o#endif
175d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o#include <ctype.h>
185d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o#include <string.h>
195d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o#include <time.h>
205d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o#ifdef HAVE_ERRNO_H
215d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o#include <errno.h>
225d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o#endif
235d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o#include <sys/types.h>
245d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o#include <sys/stat.h>
255d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o#include <fcntl.h>
265d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o#include <utime.h>
275d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o#ifdef HAVE_GETOPT_H
285d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o#include <getopt.h>
29efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o#else
305d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'oextern int optind;
315d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'oextern char *optarg;
325d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o#endif
335d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o
345d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o#include "ext2fs/ext2_fs.h"
355d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o#include "ext2fs/ext2fs.h"
365d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o#include "blkid/blkid.h"
375d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o
385d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o#include "../version.h"
395d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o#include "nls-enable.h"
405d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o
41e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic const char * program_name = "e2initrd_helper";
42e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic char * device_name;
435d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'ostatic int open_flag;
445d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'ostatic int root_type;
455d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'ostatic blkid_cache cache = NULL;
465d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o
475d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'ostruct mem_file {
485d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	char	*buf;
495d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	int	size;
505d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	int	ptr;
515d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o};
525d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o
535d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'ostruct fs_info {
545d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	char  *device;
555d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	char  *mountpt;
565d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	char  *type;
575d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	char  *opts;
585d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	int   freq;
595d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	int   passno;
605d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	int   flags;
615d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	struct fs_info *next;
625d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o};
635d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o
645d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'ostatic void usage(void)
655d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o{
665d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	fprintf(stderr,
675d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o		_("Usage: %s -r device\n"), program_name);
685d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	exit (1);
695d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o}
705d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o
71efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'ostatic errcode_t get_file(ext2_filsys fs, const char * filename,
725d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o		   struct mem_file *ret_file)
735d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o{
745d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	errcode_t	retval;
755d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	char 		*buf;
76e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	ext2_file_t	e2_file = NULL;
775d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	unsigned int	got;
785d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	struct ext2_inode inode;
795d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	ext2_ino_t	ino;
805d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o
815d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	ret_file->buf = 0;
825d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	ret_file->size = 0;
835d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	ret_file->ptr = 0;
845d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o
85efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o	retval = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO,
865d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o			      filename, &ino);
875d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	if (retval)
885d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o		return retval;
895d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o
905d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	retval = ext2fs_read_inode(fs, ino, &inode);
915d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	if (retval)
925d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o		return retval;
935d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o
945d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	if (inode.i_size_high || (inode.i_size > 65536))
955d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o		return EFBIG;
965d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o
975d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	buf = malloc(inode.i_size + 1);
985d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	if (!buf)
995d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o		return ENOMEM;
1005d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	memset(buf, 0, inode.i_size+1);
1015d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o
1025d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	retval = ext2fs_file_open(fs, ino, 0, &e2_file);
1035d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	if (retval)
104e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		goto errout;
1055d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o
1065d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	retval = ext2fs_file_read(e2_file, buf, inode.i_size, &got);
107efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o	if (retval)
1085d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o		goto errout;
1095d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o
1105d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	retval = ext2fs_file_close(e2_file);
1115d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	if (retval)
112e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		goto errout;
1135d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o
1145d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	ret_file->buf = buf;
1155d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	ret_file->size = (int) got;
116e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	return 0;
1175d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o
1185d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'oerrout:
119e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	free(buf);
120e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (e2_file)
121e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		ext2fs_file_close(e2_file);
1225d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	return retval;
1235d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o}
1245d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o
1256e82cd7e953bc6f00c47ca8f29c61d61fb39d3d3Theodore Ts'ostatic char *get_line(struct mem_file *file)
1265d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o{
1275d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	char	*cp, *ret;
1285d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	int	s = 0;
1295d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o
1305d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	cp = file->buf + file->ptr;
1315d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	while (*cp && *cp != '\n') {
1325d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o		cp++;
1335d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o		s++;
1345d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	}
1355d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	ret = malloc(s+1);
1365d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	if (!ret)
1375d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o		return 0;
1385d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	ret[s]=0;
1395d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	memcpy(ret, file->buf + file->ptr, s);
1405d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	while (*cp && (*cp == '\n' || *cp == '\r')) {
1415d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o		cp++;
1425d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o		s++;
1435d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	}
1445d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	file->ptr += s;
1455d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	return ret;
1465d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o}
1475d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o
1486e82cd7e953bc6f00c47ca8f29c61d61fb39d3d3Theodore Ts'ostatic int mem_file_eof(struct mem_file *file)
1495d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o{
1505d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	return (file->ptr >= file->size);
1515d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o}
1525d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o
1535d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o/*
1545d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o * fstab parsing code
1555d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o */
1565d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'ostatic char *string_copy(const char *s)
1575d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o{
1585d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	char	*ret;
1595d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o
1605d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	if (!s)
1615d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o		return 0;
1625d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	ret = malloc(strlen(s)+1);
1635d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	if (ret)
1645d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o		strcpy(ret, s);
1655d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	return ret;
1665d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o}
1675d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o
1685d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'ostatic char *skip_over_blank(char *cp)
1695d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o{
1705d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	while (*cp && isspace(*cp))
1715d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o		cp++;
1725d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	return cp;
1735d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o}
1745d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o
1755d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'ostatic char *skip_over_word(char *cp)
1765d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o{
1775d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	while (*cp && !isspace(*cp))
1785d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o		cp++;
1795d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	return cp;
1805d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o}
1815d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o
1825d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'ostatic char *parse_word(char **buf)
1835d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o{
1845d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	char *word, *next;
1855d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o
1865d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	word = *buf;
1875d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	if (*word == 0)
1885d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o		return 0;
1895d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o
1905d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	word = skip_over_blank(word);
1915d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	next = skip_over_word(word);
1925d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	if (*next)
1935d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o		*next++ = 0;
1945d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	*buf = next;
1955d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	return word;
1965d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o}
1975d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o
1985d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'ostatic void parse_escape(char *word)
1995d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o{
2005d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	char	*p, *q;
2015d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	int	ac, i;
2025d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o
2035d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	if (!word)
2045d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o		return;
2055d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o
2065d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	for (p = word, q = word; *p; p++, q++) {
2075d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o		*q = *p;
2085d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o		if (*p != '\\')
2095d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o			continue;
2105d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o		if (*++p == 0)
2115d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o			break;
2125d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o		if (*p == 't') {
2135d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o			*q = '\t';
2145d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o			continue;
2155d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o		}
2165d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o		if (*p == 'n') {
2175d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o			*q = '\n';
2185d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o			continue;
2195d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o		}
2205d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o		if (!isdigit(*p)) {
2215d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o			*q = *p;
2225d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o			continue;
2235d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o		}
2245d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o		ac = 0;
2255d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o		for (i = 0; i < 3; i++, p++) {
2265d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o			if (!isdigit(*p))
2275d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o				break;
2285d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o			ac = (ac * 8) + (*p - '0');
2295d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o		}
2305d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o		*q = ac;
2315d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o		p--;
2325d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	}
2335d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	*q = 0;
2345d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o}
2355d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o
2365d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'ostatic int parse_fstab_line(char *line, struct fs_info *fs)
2375d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o{
2385d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	char	*dev, *device, *mntpnt, *type, *opts, *freq, *passno, *cp;
2395d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o
2405d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	if ((cp = strchr(line, '#')))
2415d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o		*cp = 0;	/* Ignore everything after the comment char */
2425d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	cp = line;
2435d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o
2445d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	device = parse_word(&cp);
2455d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	mntpnt = parse_word(&cp);
2465d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	type = parse_word(&cp);
2475d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	opts = parse_word(&cp);
2485d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	freq = parse_word(&cp);
2495d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	passno = parse_word(&cp);
2505d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o
2515d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	if (!device)
2525d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o		return -1;	/* Allow blank lines */
253efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
2545d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	if (!mntpnt || !type)
2555d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o		return -1;
2565d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o
2575d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	parse_escape(device);
2585d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	parse_escape(mntpnt);
2595d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	parse_escape(type);
2605d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	parse_escape(opts);
2615d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	parse_escape(freq);
2625d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	parse_escape(passno);
2635d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o
2645d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	dev = blkid_get_devname(cache, device, NULL);
2655d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	if (dev)
2665d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o		device = dev;
2675d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o
2685d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	if (strchr(type, ','))
2695d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o		type = 0;
2705d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o
2715d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	fs->device = string_copy(device);
2725d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	fs->mountpt = string_copy(mntpnt);
2735d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	fs->type = string_copy(type);
2745d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	fs->opts = string_copy(opts ? opts : "");
2755d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	fs->freq = freq ? atoi(freq) : -1;
2765d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	fs->passno = passno ? atoi(passno) : -1;
2775d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	fs->flags = 0;
2785d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	fs->next = NULL;
2795d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o
28045e338f5332a54295893dba2e32cc093d1316f60Jim Meyering	free(dev);
281efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
2825d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	return 0;
2835d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o}
2845d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o
2856e82cd7e953bc6f00c47ca8f29c61d61fb39d3d3Theodore Ts'ostatic void free_fstab_line(struct fs_info *fs)
2865d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o{
2875d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	if (fs->device)
2885d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o		fs->device = 0;
2895d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	if (fs->mountpt)
2905d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o		fs->mountpt = 0;
2915d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	if (fs->type)
2925d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o		fs->type = 0;
2935d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	if (fs->opts)
2945d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o		fs->opts = 0;
2955d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	memset(fs, 0, sizeof(struct fs_info));
2965d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o}
2975d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o
2985d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o
2995d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'ostatic void PRS(int argc, char **argv)
3005d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o{
3015d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	int c;
3025d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o
3035d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o#ifdef ENABLE_NLS
3045d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	setlocale(LC_MESSAGES, "");
3055d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	setlocale(LC_CTYPE, "");
3065d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
3075d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	textdomain(NLS_CAT_NAME);
308e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	set_com_err_gettext(gettext);
3095d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o#endif
3105d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o
3115d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	while ((c = getopt(argc, argv, "rv")) != EOF) {
3125d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o		switch (c) {
3135d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o		case 'r':
3145d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o			root_type++;
3155d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o			break;
3165d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o
3175d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o		case 'v':
318efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o			printf("%s %s (%s)\n", program_name,
3195d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o			       E2FSPROGS_VERSION, E2FSPROGS_DATE);
3205d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o			break;
3215d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o		default:
3225d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o			usage();
3235d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o		}
3245d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	}
3255d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	if (optind < argc - 1 || optind == argc)
3265d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o		usage();
3275d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	device_name = blkid_get_devname(NULL, argv[optind], NULL);
3285d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	if (!device_name) {
329e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		com_err(program_name, 0, _("Unable to resolve '%s'"),
3305d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o			argv[optind]);
3315d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o		exit(1);
3325d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	}
3335d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o}
3345d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o
3356e82cd7e953bc6f00c47ca8f29c61d61fb39d3d3Theodore Ts'ostatic void get_root_type(ext2_filsys fs)
3365d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o{
3375d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	errcode_t retval;
3385d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	struct mem_file file;
3395d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	char 		*buf;
3405d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	struct fs_info fs_info;
3415d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	int		ret;
3425d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o
3435d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	retval = get_file(fs, "/etc/fstab", &file);
344e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (retval) {
345e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		com_err(program_name, retval, "couldn't open /etc/fstab");
346e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		exit(1);
347e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	}
3485d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o
3495d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	while (!mem_file_eof(&file)) {
3505d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o		buf = get_line(&file);
3515d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o		if (!buf)
3525d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o			continue;
353efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
3545d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o		ret = parse_fstab_line(buf, &fs_info);
355efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o		if (ret < 0)
3565d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o			goto next_line;
3575d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o
3585d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o		if (!strcmp(fs_info.mountpt, "/"))
3595d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o			printf("%s\n", fs_info.type);
3605d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o
3615d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o		free_fstab_line(&fs_info);
3625d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o
3635d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	next_line:
3645d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o		free(buf);
3655d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	}
3665d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o}
3675d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o
3685d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o
3695d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'oint main (int argc, char ** argv)
3705d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o{
3715d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	errcode_t retval;
3725d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	ext2_filsys fs;
3735d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	io_manager io_ptr;
3745d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o
375a6d8302b4873527798a77c1ba3106a04b71dfeacTheodore Ts'o	add_error_table(&et_ext2_error_table);
3765d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o
3775d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	blkid_get_cache(&cache, NULL);
3785d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	PRS(argc, argv);
379efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
3805d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o#ifdef CONFIG_TESTIO_DEBUG
381f38cf3cb34addaa53d1f855d7607b151082a4229Theodore Ts'o	if (getenv("TEST_IO_FLAGS") || getenv("TEST_IO_BLOCK")) {
382f38cf3cb34addaa53d1f855d7607b151082a4229Theodore Ts'o		io_ptr = test_io_manager;
383f38cf3cb34addaa53d1f855d7607b151082a4229Theodore Ts'o		test_io_backing_manager = unix_io_manager;
384f38cf3cb34addaa53d1f855d7607b151082a4229Theodore Ts'o	} else
3855d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o#endif
386f38cf3cb34addaa53d1f855d7607b151082a4229Theodore Ts'o		io_ptr = unix_io_manager;
3875d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	retval = ext2fs_open (device_name, open_flag, 0, 0, io_ptr, &fs);
3885d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o        if (retval)
3895d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o		exit(1);
3905d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o
391efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o	if (root_type)
3925d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o		get_root_type(fs);
3935d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o
394a6d8302b4873527798a77c1ba3106a04b71dfeacTheodore Ts'o	remove_error_table(&et_ext2_error_table);
3955d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o	return (ext2fs_close (fs) ? 1 : 0);
3965d40773ba8447640a5aeaaa2e98bc7feecd61698Theodore Ts'o}
397