1 /*
2 * (c) 2010 Adam Lackorzynski <adam@os.inf.tu-dresden.de>
3 * economic rights: Technische Universität Dresden (Germany)
4 * This file is part of TUD:OS and distributed under the terms of the
5 * GNU Lesser General Public License 2.1.
6 * Please see the COPYING-LGPL-2.1 file for details.
7 */
8
9 #include <fcntl.h>
10 #include <stdlib.h>
11 #include <cstdio>
12 #include <unistd.h>
13 #include <ctype.h>
14 #include <cstring>
15 #include <errno.h>
16 #include <sys/mman.h>
17 #include <sys/mount.h>
18
19 static bool verbose;
20
21 struct String
22 {
StringString23 String(const char *s, const char *e) : _s(s), _e(e), _p(s) {}
sString24 const char *s() const { return _s; }
eString25 const char *e() const { return _e; }
pString26 const char *p() const { return _p; }
lString27 unsigned l() const { return _e - _s; }
28
next_spaceString29 const char *next_space()
30 {
31 const char *i = _p;
32 while (i < _e && !isspace(*i))
33 i++;
34 _p = i;
35 return _p;
36 }
eat_spaceString37 void eat_space()
38 {
39 while (_p < e() && isspace(*_p))
40 _p++;
41 }
42
emptyString43 bool empty() const { return !(_e - _s); }
dupnultermstrString44 const char *dupnultermstr() const
45 { return strndup(s(), l()); }
46
47 const char *_s, *_e, *_p;
48 };
49
parse_fstab_line(const char * fn,int line_nr,const char * s,const char * end)50 static void parse_fstab_line(const char *fn, int line_nr,
51 const char *s, const char *end)
52 {
53 const char *i = s;
54 while (i < end && *i != '#')
55 ++i;
56 end = i;
57
58 if (s == end)
59 return;
60
61 String line(s, end);
62 String from(line.s(), line.next_space());
63
64 line.next_space();
65 line.eat_space();
66
67 const char *x = line.p();
68 String mountpoint(x, line.next_space());
69
70 line.next_space();
71 line.eat_space();
72
73 x = line.p();
74 String fsname(x, line.next_space());
75
76 line.next_space();
77 line.eat_space();
78
79 x = line.p();
80 String data(x, line.next_space());
81
82 if (from.empty() || mountpoint.empty() || fsname.empty())
83 {
84 if (verbose)
85 printf("libmount: Invalid line: %s.%d: %.*s\n",
86 fn, line_nr, line.l(), line.s());
87 return;
88 }
89
90 const char *s1 = from.dupnultermstr();
91 const char *s2 = mountpoint.dupnultermstr();
92 const char *s3 = fsname.dupnultermstr();
93 const char *s5 = data.dupnultermstr();
94 if (s1 && s2 && s3 && s5)
95 {
96 int r = mount(s1, *s2 == '/' ? s2 + 1 : s2, s3, 0, s5);
97 if (r < 0)
98 fprintf(stderr,
99 "libmount: %s.%d: mount(\"%s\", \"%s\", \"%s\", %d, \"%s\"): %s\n",
100 fn, line_nr, s1, s2, s3, 0, s5, strerror(errno));
101 else if (verbose)
102 printf("libmount: Mounted '%s' to '%s' with file-system '%s'\n",
103 s1, s2, s3);
104 }
105 else
106 fprintf(stderr, "libmount: %s.%d: memory allocation error\n", fn, line_nr);
107 free((void *)s5);
108 free((void *)s3);
109 free((void *)s2);
110 free((void *)s1);
111 }
112
parse_fstab(const char * fn,char * fstab,size_t sz)113 static void parse_fstab(const char *fn, char *fstab, size_t sz)
114 {
115 char *s = fstab;
116 char *end = fstab + sz;
117 int line_nr = 1;
118
119 if (verbose)
120 printf("libmount: Parsing '%s'\n", fn);
121
122 while (s != end)
123 {
124 while (s < end && *s != '\n')
125 s++;
126 parse_fstab_line(fn, line_nr, fstab, s);
127 if (s == end)
128 break;
129 fstab = ++s;
130 line_nr++;
131 }
132 }
133
134 static void libmount_init(void) __attribute__((constructor));
libmount_init()135 static void libmount_init()
136 {
137 verbose = getenv("FSTAB_DEBUG");
138
139 const char *fstab_path = getenv("FSTAB_FILE");
140 if (!fstab_path)
141 fstab_path = "/etc/fstab";
142
143 int fd = open(fstab_path, O_RDONLY);
144 if (fd < 0)
145 {
146 if (verbose)
147 printf("libmount: Could not open '%s': %s.\n", fstab_path, strerror(errno));
148 return;
149 }
150
151 struct stat st;
152 if (fstat(fd, &st) < 0)
153 {
154 if (verbose)
155 printf("libmount: Could not stat '%s'.\n", fstab_path);
156 close(fd);
157 return;
158 }
159
160 char *fstab = (char *)mmap(0, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
161 if (fstab == MAP_FAILED)
162 {
163 if (verbose)
164 printf("libmount: Could not mmap '%s'.\n", fstab_path);
165 close(fd);
166 return;
167 }
168
169 parse_fstab(fstab_path, fstab, st.st_size);
170
171 munmap(fstab, st.st_size);
172 close(fd);
173 }
174