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