Magellan Linux

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1297 - (hide 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 niro 532 #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 niro 1122 dprintf("kinit: trying to mount %s on %s with type %s\n",
35     source, target, type);
36 niro 532 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 niro 1122 dprintf("kinit: %s appears to be a %s filesystem\n",
54     source, type);
55 niro 532 type = mount_block(source, target, type, flags, data);
56     if (type)
57     return type;
58     }
59     }
60    
61 niro 1122 dprintf("kinit: failed to identify filesystem %s, trying all\n",
62     source);
63 niro 532
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 niro 1122 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 niro 532 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 niro 1122 dprintf("kinit: mounting root rw\n");
173 niro 532 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 niro 1122 dprintf("kinit: do_mounts\n");
209 niro 532
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 niro 1122 dprintf("kinit: root_dev = %s\n", bdevname(root_dev));
231 niro 532
232     if (initrd_load(argc, argv, root_dev)) {
233 niro 1122 dprintf("initrd loaded\n");
234 niro 532 return 0;
235     }
236    
237     if (load_ramdisk && atoi(load_ramdisk)) {
238 niro 1122 if (ramdisk_load(argc, argv))
239 niro 532 root_dev = Root_RAM0;
240     }
241    
242 niro 1122 if (root_dev == Root_MULTI)
243     return mount_roots(argc, argv, root_dev_name);
244 niro 532 return mount_root(argc, argv, root_dev, root_dev_name);
245     }