Whamcloud - gitweb
Merge branch 'maint' into next
[tools/e2fsprogs.git] / misc / e2initrd_helper.c
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
70 static 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
116 errout:
117         ext2fs_file_close(e2_file);
118         return retval;
119 }
120
121 static 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
144 static int mem_file_eof(struct mem_file *file)
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
282 static 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
296 static 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
331 static 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
361 int 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 }