e2initrd_helper.c revision efc6f628e15de95bcd13e4f0ee223cb42115d520
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 28extern int optind; 29extern 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 40const char * program_name = "get_fstab"; 41char * device_name; 42static int open_flag; 43static int root_type; 44static blkid_cache cache = NULL; 45 46struct mem_file { 47 char *buf; 48 int size; 49 int ptr; 50}; 51 52struct 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 63static void usage(void) 64{ 65 fprintf(stderr, 66 _("Usage: %s -r device\n"), program_name); 67 exit (1); 68} 69 70static errcode_t get_file(ext2_filsys fs, const char * filename, 71 struct mem_file *ret_file) 72{ 73 errcode_t retval; 74 char *buf; 75 ext2_file_t e2_file; 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 116errout: 117 ext2fs_file_close(e2_file); 118 return retval; 119} 120 121static char *get_line(struct mem_file *file) 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 144static int mem_file_eof(struct mem_file *file) 145{ 146 return (file->ptr >= file->size); 147} 148 149/* 150 * fstab parsing code 151 */ 152static 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 164static char *skip_over_blank(char *cp) 165{ 166 while (*cp && isspace(*cp)) 167 cp++; 168 return cp; 169} 170 171static char *skip_over_word(char *cp) 172{ 173 while (*cp && !isspace(*cp)) 174 cp++; 175 return cp; 176} 177 178static 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 194static 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 232static 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 282static void free_fstab_line(struct fs_info *fs) 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 296static void PRS(int argc, char **argv) 297{ 298 int c; 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 331static void get_root_type(ext2_filsys fs) 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 361int main (int argc, char ** argv) 362{ 363 errcode_t retval; 364 ext2_filsys fs; 365 io_manager io_ptr; 366 367 add_error_table(&et_ext2_error_table); 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 385 remove_error_table(&et_ext2_error_table); 386 return (ext2fs_close (fs) ? 1 : 0); 387} 388