Magellan Linux

Contents of /trunk/mkinitrd-magellan/klibc/usr/kinit/do_mounts.c

Parent Directory Parent Directory | Revision Log 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)
-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 }