Magellan Linux

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 532 - (show annotations) (download)
Sat Sep 1 22:45:15 2007 UTC (16 years, 8 months ago) by niro
File MIME type: text/plain
File size: 4947 byte(s)
-import if magellan mkinitrd; it is a fork of redhats mkinitrd-5.0.8 with all magellan patches and features; deprecates magellan-src/mkinitrd

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 DEBUG(("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 DEBUG(("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 DEBUG(("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 int
143 mount_root(int argc, char *argv[], dev_t root_dev, const char *root_dev_name)
144 {
145 unsigned long flags = MS_RDONLY | MS_VERBOSE;
146 int ret;
147 const char *type = get_arg(argc, argv, "rootfstype=");
148
149 if (get_flag(argc, argv, "rw") > get_flag(argc, argv, "ro")) {
150 DEBUG(("kinit: mounting root rw\n"));
151 flags &= ~MS_RDONLY;
152 }
153
154 if (type) {
155 if (!strcmp(type, "nfs"))
156 root_dev = Root_NFS;
157 else if (!strcmp(type, "jffs2") && !major(root_dev))
158 root_dev = Root_MTD;
159 }
160
161 switch (root_dev) {
162 case Root_NFS:
163 ret = mount_nfs_root(argc, argv, flags);
164 break;
165 case Root_MTD:
166 ret = mount_mtd_root(argc, argv, root_dev_name, type, flags);
167 break;
168 default:
169 ret = mount_block_root(argc, argv, root_dev, type, flags);
170 break;
171 }
172
173 if (!ret)
174 chdir("/root");
175
176 return ret;
177 }
178
179 int do_mounts(int argc, char *argv[])
180 {
181 const char *root_dev_name = get_arg(argc, argv, "root=");
182 const char *root_delay = get_arg(argc, argv, "rootdelay=");
183 const char *load_ramdisk = get_arg(argc, argv, "load_ramdisk=");
184 dev_t root_dev = 0;
185
186 DEBUG(("kinit: do_mounts\n"));
187
188 if (root_delay) {
189 int delay = atoi(root_delay);
190 fprintf(stderr, "Waiting %d s before mounting root device...\n",
191 delay);
192 sleep(delay);
193 }
194
195 md_run(argc, argv);
196
197 if (root_dev_name) {
198 root_dev = name_to_dev_t(root_dev_name);
199 } else if (get_arg(argc, argv, "nfsroot=") ||
200 get_arg(argc, argv, "nfsaddrs=")) {
201 root_dev = Root_NFS;
202 } else {
203 long rootdev;
204 getintfile("/proc/sys/kernel/real-root-dev", &rootdev);
205 root_dev = (dev_t) rootdev;
206 }
207
208 DEBUG(("kinit: root_dev = %s\n", bdevname(root_dev)));
209
210 if (initrd_load(argc, argv, root_dev)) {
211 DEBUG(("initrd loaded\n"));
212 return 0;
213 }
214
215 if (load_ramdisk && atoi(load_ramdisk)) {
216 if (ramdisk_load(argc, argv, root_dev))
217 root_dev = Root_RAM0;
218 }
219
220 return mount_root(argc, argv, root_dev, root_dev_name);
221 }