Annotation of /trunk/mkinitrd-magellan/klibc/usr/kinit/do_mounts.c
Parent Directory | Revision Log
Revision 1122 -
(hide 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 | niro | 532 | #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 | niro | 1122 | dprintf("kinit: trying to mount %s on %s with type %s\n", |
37 | source, target, type); | ||
38 | niro | 532 | 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 | niro | 1122 | dprintf("kinit: %s appears to be a %s filesystem\n", |
56 | source, type); | ||
57 | niro | 532 | type = mount_block(source, target, type, flags, data); |
58 | if (type) | ||
59 | return type; | ||
60 | } | ||
61 | } | ||
62 | |||
63 | niro | 1122 | dprintf("kinit: failed to identify filesystem %s, trying all\n", |
64 | source); | ||
65 | niro | 532 | |
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 | niro | 1122 | 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 | niro | 532 | 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 | niro | 1122 | dprintf("kinit: mounting root rw\n"); |
175 | niro | 532 | 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 | niro | 1122 | dprintf("kinit: do_mounts\n"); |
211 | niro | 532 | |
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 | niro | 1122 | dprintf("kinit: root_dev = %s\n", bdevname(root_dev)); |
233 | niro | 532 | |
234 | if (initrd_load(argc, argv, root_dev)) { | ||
235 | niro | 1122 | dprintf("initrd loaded\n"); |
236 | niro | 532 | return 0; |
237 | } | ||
238 | |||
239 | if (load_ramdisk && atoi(load_ramdisk)) { | ||
240 | niro | 1122 | if (ramdisk_load(argc, argv)) |
241 | niro | 532 | root_dev = Root_RAM0; |
242 | } | ||
243 | |||
244 | niro | 1122 | if (root_dev == Root_MULTI) |
245 | return mount_roots(argc, argv, root_dev_name); | ||
246 | niro | 532 | return mount_root(argc, argv, root_dev, root_dev_name); |
247 | } |