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