Magellan Linux

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

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