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 | |
| 12 | #include <stdio.h> |
| 13 | #include <unistd.h> |
Theodore Ts'o | f38cf3c | 2008-09-01 11:17:29 -0400 | [diff] [blame] | 14 | #ifdef HAVE_STDLIB_H |
Theodore Ts'o | 5d40773 | 2004-09-18 14:53:14 -0400 | [diff] [blame] | 15 | #include <stdlib.h> |
Theodore Ts'o | f38cf3c | 2008-09-01 11:17:29 -0400 | [diff] [blame] | 16 | #endif |
Theodore Ts'o | 5d40773 | 2004-09-18 14:53:14 -0400 | [diff] [blame] | 17 | #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'o | efc6f62 | 2008-08-27 23:07:54 -0400 | [diff] [blame] | 29 | #else |
Theodore Ts'o | 5d40773 | 2004-09-18 14:53:14 -0400 | [diff] [blame] | 30 | extern int optind; |
| 31 | extern char *optarg; |
| 32 | #endif |
| 33 | |
| 34 | #include "ext2fs/ext2_fs.h" |
| 35 | #include "ext2fs/ext2fs.h" |
Theodore Ts'o | 5d40773 | 2004-09-18 14:53:14 -0400 | [diff] [blame] | 36 | #include "blkid/blkid.h" |
| 37 | |
| 38 | #include "../version.h" |
| 39 | #include "nls-enable.h" |
| 40 | |
JP Abgrall | e0ed740 | 2014-03-19 19:08:39 -0700 | [diff] [blame] | 41 | static const char * program_name = "e2initrd_helper"; |
| 42 | static char * device_name; |
Theodore Ts'o | 5d40773 | 2004-09-18 14:53:14 -0400 | [diff] [blame] | 43 | static int open_flag; |
| 44 | static int root_type; |
| 45 | static blkid_cache cache = NULL; |
| 46 | |
| 47 | struct mem_file { |
| 48 | char *buf; |
| 49 | int size; |
| 50 | int ptr; |
| 51 | }; |
| 52 | |
| 53 | struct 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 | |
| 64 | static void usage(void) |
| 65 | { |
| 66 | fprintf(stderr, |
| 67 | _("Usage: %s -r device\n"), program_name); |
| 68 | exit (1); |
| 69 | } |
| 70 | |
Theodore Ts'o | efc6f62 | 2008-08-27 23:07:54 -0400 | [diff] [blame] | 71 | static errcode_t get_file(ext2_filsys fs, const char * filename, |
Theodore Ts'o | 5d40773 | 2004-09-18 14:53:14 -0400 | [diff] [blame] | 72 | struct mem_file *ret_file) |
| 73 | { |
| 74 | errcode_t retval; |
| 75 | char *buf; |
JP Abgrall | e0ed740 | 2014-03-19 19:08:39 -0700 | [diff] [blame] | 76 | ext2_file_t e2_file = NULL; |
Theodore Ts'o | 5d40773 | 2004-09-18 14:53:14 -0400 | [diff] [blame] | 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 | |
Theodore Ts'o | efc6f62 | 2008-08-27 23:07:54 -0400 | [diff] [blame] | 85 | retval = ext2fs_namei(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, |
Theodore Ts'o | 5d40773 | 2004-09-18 14:53:14 -0400 | [diff] [blame] | 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) |
JP Abgrall | e0ed740 | 2014-03-19 19:08:39 -0700 | [diff] [blame] | 104 | goto errout; |
Theodore Ts'o | 5d40773 | 2004-09-18 14:53:14 -0400 | [diff] [blame] | 105 | |
| 106 | retval = ext2fs_file_read(e2_file, buf, inode.i_size, &got); |
Theodore Ts'o | efc6f62 | 2008-08-27 23:07:54 -0400 | [diff] [blame] | 107 | if (retval) |
Theodore Ts'o | 5d40773 | 2004-09-18 14:53:14 -0400 | [diff] [blame] | 108 | goto errout; |
| 109 | |
| 110 | retval = ext2fs_file_close(e2_file); |
| 111 | if (retval) |
JP Abgrall | e0ed740 | 2014-03-19 19:08:39 -0700 | [diff] [blame] | 112 | goto errout; |
Theodore Ts'o | 5d40773 | 2004-09-18 14:53:14 -0400 | [diff] [blame] | 113 | |
| 114 | ret_file->buf = buf; |
| 115 | ret_file->size = (int) got; |
JP Abgrall | e0ed740 | 2014-03-19 19:08:39 -0700 | [diff] [blame] | 116 | return 0; |
Theodore Ts'o | 5d40773 | 2004-09-18 14:53:14 -0400 | [diff] [blame] | 117 | |
| 118 | errout: |
JP Abgrall | e0ed740 | 2014-03-19 19:08:39 -0700 | [diff] [blame] | 119 | free(buf); |
| 120 | if (e2_file) |
| 121 | ext2fs_file_close(e2_file); |
Theodore Ts'o | 5d40773 | 2004-09-18 14:53:14 -0400 | [diff] [blame] | 122 | return retval; |
| 123 | } |
| 124 | |
Theodore Ts'o | 6e82cd7 | 2005-01-05 03:02:54 -0500 | [diff] [blame] | 125 | static char *get_line(struct mem_file *file) |
Theodore Ts'o | 5d40773 | 2004-09-18 14:53:14 -0400 | [diff] [blame] | 126 | { |
| 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'o | 6e82cd7 | 2005-01-05 03:02:54 -0500 | [diff] [blame] | 148 | static int mem_file_eof(struct mem_file *file) |
Theodore Ts'o | 5d40773 | 2004-09-18 14:53:14 -0400 | [diff] [blame] | 149 | { |
| 150 | return (file->ptr >= file->size); |
| 151 | } |
| 152 | |
| 153 | /* |
| 154 | * fstab parsing code |
| 155 | */ |
| 156 | static 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 | |
| 168 | static char *skip_over_blank(char *cp) |
| 169 | { |
| 170 | while (*cp && isspace(*cp)) |
| 171 | cp++; |
| 172 | return cp; |
| 173 | } |
| 174 | |
| 175 | static char *skip_over_word(char *cp) |
| 176 | { |
| 177 | while (*cp && !isspace(*cp)) |
| 178 | cp++; |
| 179 | return cp; |
| 180 | } |
| 181 | |
| 182 | static 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 | |
| 198 | static 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 | |
| 236 | static 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'o | efc6f62 | 2008-08-27 23:07:54 -0400 | [diff] [blame] | 253 | |
Theodore Ts'o | 5d40773 | 2004-09-18 14:53:14 -0400 | [diff] [blame] | 254 | 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 Meyering | 45e338f | 2009-02-23 18:07:50 +0100 | [diff] [blame] | 280 | free(dev); |
Theodore Ts'o | efc6f62 | 2008-08-27 23:07:54 -0400 | [diff] [blame] | 281 | |
Theodore Ts'o | 5d40773 | 2004-09-18 14:53:14 -0400 | [diff] [blame] | 282 | return 0; |
| 283 | } |
| 284 | |
Theodore Ts'o | 6e82cd7 | 2005-01-05 03:02:54 -0500 | [diff] [blame] | 285 | static void free_fstab_line(struct fs_info *fs) |
Theodore Ts'o | 5d40773 | 2004-09-18 14:53:14 -0400 | [diff] [blame] | 286 | { |
| 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 | |
| 299 | static void PRS(int argc, char **argv) |
| 300 | { |
| 301 | int c; |
Theodore Ts'o | 5d40773 | 2004-09-18 14:53:14 -0400 | [diff] [blame] | 302 | |
| 303 | #ifdef ENABLE_NLS |
| 304 | setlocale(LC_MESSAGES, ""); |
| 305 | setlocale(LC_CTYPE, ""); |
| 306 | bindtextdomain(NLS_CAT_NAME, LOCALEDIR); |
| 307 | textdomain(NLS_CAT_NAME); |
JP Abgrall | e0ed740 | 2014-03-19 19:08:39 -0700 | [diff] [blame] | 308 | set_com_err_gettext(gettext); |
Theodore Ts'o | 5d40773 | 2004-09-18 14:53:14 -0400 | [diff] [blame] | 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': |
Theodore Ts'o | efc6f62 | 2008-08-27 23:07:54 -0400 | [diff] [blame] | 318 | printf("%s %s (%s)\n", program_name, |
Theodore Ts'o | 5d40773 | 2004-09-18 14:53:14 -0400 | [diff] [blame] | 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) { |
JP Abgrall | e0ed740 | 2014-03-19 19:08:39 -0700 | [diff] [blame] | 329 | com_err(program_name, 0, _("Unable to resolve '%s'"), |
Theodore Ts'o | 5d40773 | 2004-09-18 14:53:14 -0400 | [diff] [blame] | 330 | argv[optind]); |
| 331 | exit(1); |
| 332 | } |
| 333 | } |
| 334 | |
Theodore Ts'o | 6e82cd7 | 2005-01-05 03:02:54 -0500 | [diff] [blame] | 335 | static void get_root_type(ext2_filsys fs) |
Theodore Ts'o | 5d40773 | 2004-09-18 14:53:14 -0400 | [diff] [blame] | 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); |
JP Abgrall | e0ed740 | 2014-03-19 19:08:39 -0700 | [diff] [blame] | 344 | if (retval) { |
| 345 | com_err(program_name, retval, "couldn't open /etc/fstab"); |
| 346 | exit(1); |
| 347 | } |
Theodore Ts'o | 5d40773 | 2004-09-18 14:53:14 -0400 | [diff] [blame] | 348 | |
| 349 | while (!mem_file_eof(&file)) { |
| 350 | buf = get_line(&file); |
| 351 | if (!buf) |
| 352 | continue; |
Theodore Ts'o | efc6f62 | 2008-08-27 23:07:54 -0400 | [diff] [blame] | 353 | |
Theodore Ts'o | 5d40773 | 2004-09-18 14:53:14 -0400 | [diff] [blame] | 354 | ret = parse_fstab_line(buf, &fs_info); |
Theodore Ts'o | efc6f62 | 2008-08-27 23:07:54 -0400 | [diff] [blame] | 355 | if (ret < 0) |
Theodore Ts'o | 5d40773 | 2004-09-18 14:53:14 -0400 | [diff] [blame] | 356 | 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 | |
| 369 | int main (int argc, char ** argv) |
| 370 | { |
| 371 | errcode_t retval; |
| 372 | ext2_filsys fs; |
Theodore Ts'o | 5d40773 | 2004-09-18 14:53:14 -0400 | [diff] [blame] | 373 | io_manager io_ptr; |
Theodore Ts'o | 5d40773 | 2004-09-18 14:53:14 -0400 | [diff] [blame] | 374 | |
Theodore Ts'o | a6d8302 | 2006-12-26 03:38:07 -0500 | [diff] [blame] | 375 | add_error_table(&et_ext2_error_table); |
Theodore Ts'o | 5d40773 | 2004-09-18 14:53:14 -0400 | [diff] [blame] | 376 | |
| 377 | blkid_get_cache(&cache, NULL); |
| 378 | PRS(argc, argv); |
Theodore Ts'o | efc6f62 | 2008-08-27 23:07:54 -0400 | [diff] [blame] | 379 | |
Theodore Ts'o | 5d40773 | 2004-09-18 14:53:14 -0400 | [diff] [blame] | 380 | #ifdef CONFIG_TESTIO_DEBUG |
Theodore Ts'o | f38cf3c | 2008-09-01 11:17:29 -0400 | [diff] [blame] | 381 | 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'o | 5d40773 | 2004-09-18 14:53:14 -0400 | [diff] [blame] | 385 | #endif |
Theodore Ts'o | f38cf3c | 2008-09-01 11:17:29 -0400 | [diff] [blame] | 386 | io_ptr = unix_io_manager; |
Theodore Ts'o | 5d40773 | 2004-09-18 14:53:14 -0400 | [diff] [blame] | 387 | retval = ext2fs_open (device_name, open_flag, 0, 0, io_ptr, &fs); |
| 388 | if (retval) |
| 389 | exit(1); |
| 390 | |
Theodore Ts'o | efc6f62 | 2008-08-27 23:07:54 -0400 | [diff] [blame] | 391 | if (root_type) |
Theodore Ts'o | 5d40773 | 2004-09-18 14:53:14 -0400 | [diff] [blame] | 392 | get_root_type(fs); |
| 393 | |
Theodore Ts'o | a6d8302 | 2006-12-26 03:38:07 -0500 | [diff] [blame] | 394 | remove_error_table(&et_ext2_error_table); |
Theodore Ts'o | 5d40773 | 2004-09-18 14:53:14 -0400 | [diff] [blame] | 395 | return (ext2fs_close (fs) ? 1 : 0); |
| 396 | } |