Contents of /trunk/mkinitrd-magellan/klibc/usr/kinit/do_mounts.c
Parent Directory | Revision Log
Revision 1122 -
(show annotations)
(download)
Wed Aug 18 21:11:40 2010 UTC (13 years, 8 months ago) by niro
File MIME type: text/plain
File size: 5484 byte(s)
Wed Aug 18 21:11:40 2010 UTC (13 years, 8 months ago) by niro
File MIME type: text/plain
File size: 5484 byte(s)
-updated to klibc-1.5.19
1 | #include <ctype.h> |
2 | #include <errno.h> |
3 | #include <fcntl.h> |
4 | #include <sys/mount.h> |
5 | #include <sys/stat.h> |
6 | #include <stdio.h> |
7 | #include <stdlib.h> |
8 | #include <string.h> |
9 | #include <unistd.h> |
10 | #include <alloca.h> |
11 | #include <inttypes.h> |
12 | |
13 | #include "do_mounts.h" |
14 | #include "kinit.h" |
15 | #include "fstype.h" |
16 | #include "zlib.h" |
17 | |
18 | /* Create the device node "name" */ |
19 | int create_dev(const char *name, dev_t dev) |
20 | { |
21 | unlink(name); |
22 | return mknod(name, S_IFBLK | 0600, dev); |
23 | } |
24 | |
25 | /* mount a filesystem, possibly trying a set of different types */ |
26 | const char *mount_block(const char *source, const char *target, |
27 | const char *type, unsigned long flags, |
28 | const void *data) |
29 | { |
30 | char *fslist, *p, *ep; |
31 | const char *rp; |
32 | ssize_t fsbytes; |
33 | int fd; |
34 | |
35 | if (type) { |
36 | dprintf("kinit: trying to mount %s on %s with type %s\n", |
37 | source, target, type); |
38 | int rv = mount(source, target, type, flags, data); |
39 | /* Mount readonly if necessary */ |
40 | if (rv == -1 && errno == EACCES && !(flags & MS_RDONLY)) |
41 | rv = mount(source, target, type, flags | MS_RDONLY, |
42 | data); |
43 | return rv ? NULL : type; |
44 | } |
45 | |
46 | /* If no type given, try to identify the type first; this |
47 | also takes care of specific ordering requirements, like |
48 | ext3 before ext2... */ |
49 | fd = open(source, O_RDONLY); |
50 | if (fd >= 0) { |
51 | int err = identify_fs(fd, &type, NULL, 0); |
52 | close(fd); |
53 | |
54 | if (!err && type) { |
55 | dprintf("kinit: %s appears to be a %s filesystem\n", |
56 | source, type); |
57 | type = mount_block(source, target, type, flags, data); |
58 | if (type) |
59 | return type; |
60 | } |
61 | } |
62 | |
63 | dprintf("kinit: failed to identify filesystem %s, trying all\n", |
64 | source); |
65 | |
66 | fsbytes = readfile("/proc/filesystems", &fslist); |
67 | |
68 | errno = EINVAL; |
69 | if (fsbytes < 0) |
70 | return NULL; |
71 | |
72 | p = fslist; |
73 | ep = fslist + fsbytes; |
74 | |
75 | rp = NULL; |
76 | |
77 | while (p < ep) { |
78 | type = p; |
79 | p = strchr(p, '\n'); |
80 | if (!p) |
81 | break; |
82 | *p++ = '\0'; |
83 | if (*type != '\t') /* We can't mount a block device as a "nodev" fs */ |
84 | continue; |
85 | |
86 | type++; |
87 | rp = mount_block(source, target, type, flags, data); |
88 | if (rp) |
89 | break; |
90 | if (errno != EINVAL) |
91 | break; |
92 | } |
93 | |
94 | free(fslist); |
95 | return rp; |
96 | } |
97 | |
98 | /* mount the root filesystem from a block device */ |
99 | static int |
100 | mount_block_root(int argc, char *argv[], dev_t root_dev, |
101 | const char *type, unsigned long flags) |
102 | { |
103 | const char *data, *rp; |
104 | |
105 | data = get_arg(argc, argv, "rootflags="); |
106 | create_dev("/dev/root", root_dev); |
107 | |
108 | errno = 0; |
109 | |
110 | if (type) { |
111 | if ((rp = mount_block("/dev/root", "/root", type, flags, data))) |
112 | goto ok; |
113 | if (errno != EINVAL) |
114 | goto bad; |
115 | } |
116 | |
117 | if (!errno |
118 | && (rp = mount_block("/dev/root", "/root", NULL, flags, data))) |
119 | goto ok; |
120 | |
121 | bad: |
122 | if (errno != EINVAL) { |
123 | /* |
124 | * Allow the user to distinguish between failed open |
125 | * and bad superblock on root device. |
126 | */ |
127 | fprintf(stderr, "%s: Cannot open root device %s\n", |
128 | progname, bdevname(root_dev)); |
129 | return -errno; |
130 | } else { |
131 | fprintf(stderr, "%s: Unable to mount root fs on device %s\n", |
132 | progname, bdevname(root_dev)); |
133 | return -ESRCH; |
134 | } |
135 | |
136 | ok: |
137 | printf("%s: Mounted root (%s filesystem)%s.\n", |
138 | progname, rp, (flags & MS_RDONLY) ? " readonly" : ""); |
139 | return 0; |
140 | } |
141 | |
142 | static int |
143 | mount_roots(int argc, char *argv[], const char *root_dev_name) |
144 | { |
145 | char *roots = strdup(root_dev_name); |
146 | char *root; |
147 | const char *sep = ","; |
148 | char *saveptr; |
149 | int ret = -ESRCH; |
150 | |
151 | root = strtok_r(roots, sep, &saveptr); |
152 | while (root) { |
153 | dev_t root_dev; |
154 | |
155 | dprintf("kinit: trying to mount %s\n", root); |
156 | root_dev = name_to_dev_t(root); |
157 | ret = mount_root(argc, argv, root_dev, root); |
158 | if (!ret) |
159 | break; |
160 | root = strtok_r(NULL, sep, &saveptr); |
161 | } |
162 | free(roots); |
163 | return ret; |
164 | } |
165 | |
166 | int |
167 | mount_root(int argc, char *argv[], dev_t root_dev, const char *root_dev_name) |
168 | { |
169 | unsigned long flags = MS_RDONLY | MS_VERBOSE; |
170 | int ret; |
171 | const char *type = get_arg(argc, argv, "rootfstype="); |
172 | |
173 | if (get_flag(argc, argv, "rw") > get_flag(argc, argv, "ro")) { |
174 | dprintf("kinit: mounting root rw\n"); |
175 | flags &= ~MS_RDONLY; |
176 | } |
177 | |
178 | if (type) { |
179 | if (!strcmp(type, "nfs")) |
180 | root_dev = Root_NFS; |
181 | else if (!strcmp(type, "jffs2") && !major(root_dev)) |
182 | root_dev = Root_MTD; |
183 | } |
184 | |
185 | switch (root_dev) { |
186 | case Root_NFS: |
187 | ret = mount_nfs_root(argc, argv, flags); |
188 | break; |
189 | case Root_MTD: |
190 | ret = mount_mtd_root(argc, argv, root_dev_name, type, flags); |
191 | break; |
192 | default: |
193 | ret = mount_block_root(argc, argv, root_dev, type, flags); |
194 | break; |
195 | } |
196 | |
197 | if (!ret) |
198 | chdir("/root"); |
199 | |
200 | return ret; |
201 | } |
202 | |
203 | int do_mounts(int argc, char *argv[]) |
204 | { |
205 | const char *root_dev_name = get_arg(argc, argv, "root="); |
206 | const char *root_delay = get_arg(argc, argv, "rootdelay="); |
207 | const char *load_ramdisk = get_arg(argc, argv, "load_ramdisk="); |
208 | dev_t root_dev = 0; |
209 | |
210 | dprintf("kinit: do_mounts\n"); |
211 | |
212 | if (root_delay) { |
213 | int delay = atoi(root_delay); |
214 | fprintf(stderr, "Waiting %d s before mounting root device...\n", |
215 | delay); |
216 | sleep(delay); |
217 | } |
218 | |
219 | md_run(argc, argv); |
220 | |
221 | if (root_dev_name) { |
222 | root_dev = name_to_dev_t(root_dev_name); |
223 | } else if (get_arg(argc, argv, "nfsroot=") || |
224 | get_arg(argc, argv, "nfsaddrs=")) { |
225 | root_dev = Root_NFS; |
226 | } else { |
227 | long rootdev; |
228 | getintfile("/proc/sys/kernel/real-root-dev", &rootdev); |
229 | root_dev = (dev_t) rootdev; |
230 | } |
231 | |
232 | dprintf("kinit: root_dev = %s\n", bdevname(root_dev)); |
233 | |
234 | if (initrd_load(argc, argv, root_dev)) { |
235 | dprintf("initrd loaded\n"); |
236 | return 0; |
237 | } |
238 | |
239 | if (load_ramdisk && atoi(load_ramdisk)) { |
240 | if (ramdisk_load(argc, argv)) |
241 | root_dev = Root_RAM0; |
242 | } |
243 | |
244 | if (root_dev == Root_MULTI) |
245 | return mount_roots(argc, argv, root_dev_name); |
246 | return mount_root(argc, argv, root_dev, root_dev_name); |
247 | } |