Magellan Linux

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

Parent Directory Parent Directory | Revision Log Revision Log


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