rezize2fs: fix memory leak when fixing up the orphan file inode
[e2fsprogs.git] / misc / e2initrd_helper.c
blobb39fe15d7ed882d1fe2378b7759b8e4b488bc9e3
1 /*
2 * e2initrd_helper.c - Get the filesystem table
4 * Copyright 2004 by Theodore Ts'o.
6 * %Begin-Header%
7 * This file may be redistributed under the terms of the GNU Public
8 * License.
9 * %End-Header%
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
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"
41 #include "../version.h"
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;
49 struct mem_file {
50 char *buf;
51 int size;
52 int ptr;
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;
66 static void usage(void)
68 fprintf(stderr,
69 _("Usage: %s -r device\n"), program_name);
70 exit (1);
73 static errcode_t get_file(ext2_filsys fs, const char * filename,
74 struct mem_file *ret_file)
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;
83 ret_file->buf = 0;
84 ret_file->size = 0;
85 ret_file->ptr = 0;
87 retval = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO,
88 filename, &ino);
89 if (retval)
90 return retval;
92 retval = ext2fs_read_inode(fs, ino, &inode);
93 if (retval)
94 return retval;
96 if (inode.i_size_high || (inode.i_size > 65536))
97 return EFBIG;
99 buf = malloc(inode.i_size + 1);
100 if (!buf)
101 return ENOMEM;
102 memset(buf, 0, inode.i_size+1);
104 retval = ext2fs_file_open(fs, ino, 0, &e2_file);
105 if (retval)
106 goto errout;
108 retval = ext2fs_file_read(e2_file, buf, inode.i_size, &got);
109 if (retval)
110 goto errout;
112 retval = ext2fs_file_close(e2_file);
113 if (retval)
114 goto errout;
116 ret_file->buf = buf;
117 ret_file->size = (int) got;
118 return 0;
120 errout:
121 free(buf);
122 if (e2_file)
123 ext2fs_file_close(e2_file);
124 return retval;
127 static char *get_line(struct mem_file *file)
129 char *cp, *ret;
130 int s = 0;
132 cp = file->buf + file->ptr;
133 while (*cp && *cp != '\n') {
134 cp++;
135 s++;
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++;
146 file->ptr += s;
147 return ret;
150 static int mem_file_eof(struct mem_file *file)
152 return (file->ptr >= file->size);
156 * fstab parsing code
158 static char *string_copy(const char *s)
160 char *ret;
162 if (!s)
163 return 0;
164 ret = malloc(strlen(s)+1);
165 if (ret)
166 strcpy(ret, s);
167 return ret;
170 static char *skip_over_blank(char *cp)
172 while (*cp && isspace(*cp))
173 cp++;
174 return cp;
177 static char *skip_over_word(char *cp)
179 while (*cp && !isspace(*cp))
180 cp++;
181 return cp;
184 static char *parse_word(char **buf)
186 char *word, *next;
188 word = *buf;
189 if (*word == 0)
190 return 0;
192 word = skip_over_blank(word);
193 next = skip_over_word(word);
194 if (*next)
195 *next++ = 0;
196 *buf = next;
197 return word;
200 static void parse_escape(char *word)
202 char *p, *q;
203 int ac, i;
205 if (!word)
206 return;
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;
218 if (*p == 'n') {
219 *q = '\n';
220 continue;
222 if (!isdigit(*p)) {
223 *q = *p;
224 continue;
226 ac = 0;
227 for (i = 0; i < 3; i++, p++) {
228 if (!isdigit(*p))
229 break;
230 ac = (ac * 8) + (*p - '0');
232 *q = ac;
233 p--;
235 *q = 0;
238 static int parse_fstab_line(char *line, struct fs_info *fs)
240 char *dev, *device, *mntpnt, *type, *opts, *freq, *passno, *cp;
242 if ((cp = strchr(line, '#')))
243 *cp = 0; /* Ignore everything after the comment char */
244 cp = line;
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);
253 if (!device)
254 return -1; /* Allow blank lines */
256 if (!mntpnt || !type)
257 return -1;
259 parse_escape(device);
260 parse_escape(mntpnt);
261 parse_escape(type);
262 parse_escape(opts);
263 parse_escape(freq);
264 parse_escape(passno);
266 dev = get_devname(cache, device, NULL);
267 if (dev)
268 device = dev;
270 if (strchr(type, ','))
271 type = 0;
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;
282 free(dev);
284 return 0;
287 static void free_fstab_line(struct fs_info *fs)
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));
301 static void PRS(int argc, char **argv)
303 int c;
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
313 while ((c = getopt(argc, argv, "rv")) != EOF) {
314 switch (c) {
315 case 'r':
316 root_type++;
317 break;
319 case 'v':
320 printf("%s %s (%s)\n", program_name,
321 E2FSPROGS_VERSION, E2FSPROGS_DATE);
322 break;
323 default:
324 usage();
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);
337 static void get_root_type(ext2_filsys fs)
339 errcode_t retval;
340 struct mem_file file;
341 char *buf;
342 struct fs_info fs_info;
343 int ret;
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);
351 while (!mem_file_eof(&file)) {
352 buf = get_line(&file);
353 if (!buf)
354 continue;
356 ret = parse_fstab_line(buf, &fs_info);
357 if (ret < 0)
358 goto next_line;
360 if (!strcmp(fs_info.mountpt, "/"))
361 printf("%s\n", fs_info.type);
363 free_fstab_line(&fs_info);
365 next_line:
366 free(buf);
371 int main (int argc, char ** argv)
373 errcode_t retval;
374 ext2_filsys fs;
375 io_manager io_ptr;
377 add_error_table(&et_ext2_error_table);
379 blkid_get_cache(&cache, NULL);
380 PRS(argc, argv);
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);
393 if (root_type)
394 get_root_type(fs);
396 remove_error_table(&et_ext2_error_table);
397 return (ext2fs_close (fs) ? 1 : 0);