Magellan Linux

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 532 - (show annotations) (download)
Sat Sep 1 22:45:15 2007 UTC (16 years, 9 months ago) by niro
File MIME type: text/plain
File size: 5598 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 <errno.h>
2 #include <sys/types.h>
3 #include <sys/stat.h>
4 #include <arpa/inet.h>
5 #include <limits.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <signal.h>
10 #include <setjmp.h>
11 #include <sys/wait.h>
12 #include <unistd.h>
13 #include <klibc/sysconfig.h> /* For _KLIBC_NO_MMU */
14
15 #include <linux/nfs_mount.h>
16
17 #include "nfsmount.h"
18 #include "sunrpc.h"
19 #include "dummypmap.h"
20
21 const char *progname;
22 static jmp_buf abort_buf;
23
24 static struct nfs_mount_data mount_data = {
25 .version = NFS_MOUNT_VERSION,
26 .flags = NFS_MOUNT_NONLM | NFS_MOUNT_VER3 | NFS_MOUNT_TCP,
27 .rsize = 0, /* Server's choice */
28 .wsize = 0, /* Server's choice */
29 .timeo = 7,
30 .retrans = 3,
31 .acregmin = 3,
32 .acregmax = 60,
33 .acdirmin = 30,
34 .acdirmax = 60,
35 .namlen = NAME_MAX,
36 };
37
38 int nfs_port;
39
40 static struct int_opts {
41 char *name;
42 int *val;
43 } int_opts[] = {
44 {"port", &nfs_port},
45 {"rsize", &mount_data.rsize},
46 {"wsize", &mount_data.wsize},
47 {"timeo", &mount_data.timeo},
48 {"retrans", &mount_data.retrans},
49 {"acregmin", &mount_data.acregmin},
50 {"acregmax", &mount_data.acregmax},
51 {"acdirmin", &mount_data.acdirmin},
52 {"acdirmax", &mount_data.acdirmax},
53 {NULL, NULL}
54 };
55
56 static struct bool_opts {
57 char *name;
58 int and_mask;
59 int or_mask;
60 } bool_opts[] = {
61 {"soft", ~NFS_MOUNT_SOFT, NFS_MOUNT_SOFT},
62 {"hard", ~NFS_MOUNT_SOFT, 0},
63 {"intr", ~NFS_MOUNT_INTR, NFS_MOUNT_INTR},
64 {"nointr", ~NFS_MOUNT_INTR, 0},
65 {"posix", ~NFS_MOUNT_POSIX, NFS_MOUNT_POSIX},
66 {"noposix", ~NFS_MOUNT_POSIX, 0},
67 {"cto", ~NFS_MOUNT_NOCTO, 0},
68 {"nocto", ~NFS_MOUNT_NOCTO, NFS_MOUNT_NOCTO},
69 {"ac", ~NFS_MOUNT_NOAC, 0},
70 {"noac", ~NFS_MOUNT_NOAC, NFS_MOUNT_NOAC},
71 {"lock", ~NFS_MOUNT_NONLM, 0},
72 {"nolock", ~NFS_MOUNT_NONLM, NFS_MOUNT_NONLM},
73 {"v2", ~NFS_MOUNT_VER3, 0},
74 {"v3", ~NFS_MOUNT_VER3, NFS_MOUNT_VER3},
75 {"udp", ~NFS_MOUNT_TCP, 0},
76 {"tcp", ~NFS_MOUNT_TCP, NFS_MOUNT_TCP},
77 {"broken_suid", ~NFS_MOUNT_BROKEN_SUID, NFS_MOUNT_BROKEN_SUID},
78 {"ro", ~NFS_MOUNT_KLIBC_RONLY, NFS_MOUNT_KLIBC_RONLY},
79 {"rw", ~NFS_MOUNT_KLIBC_RONLY, 0},
80 {NULL, 0, 0}
81 };
82
83 static int parse_int(const char *val, const char *ctx)
84 {
85 char *end;
86 int ret;
87
88 ret = (int)strtoul(val, &end, 0);
89 if (*val == '\0' || *end != '\0') {
90 fprintf(stderr, "%s: invalid value for %s\n", val, ctx);
91 longjmp(abort_buf, 1);
92 }
93 return ret;
94 }
95
96 static void parse_opts(char *opts)
97 {
98 char *cp, *val;
99
100 while ((cp = strsep(&opts, ",")) != NULL) {
101 if (*cp == '\0')
102 continue;
103 if ((val = strchr(cp, '=')) != NULL) {
104 struct int_opts *opts = int_opts;
105 *val++ = '\0';
106 while (opts->name && strcmp(opts->name, cp) != 0)
107 opts++;
108 if (opts->name)
109 *(opts->val) = parse_int(val, opts->name);
110 else {
111 fprintf(stderr, "%s: bad option '%s'\n",
112 progname, cp);
113 longjmp(abort_buf, 1);
114 }
115 } else {
116 struct bool_opts *opts = bool_opts;
117 while (opts->name && strcmp(opts->name, cp) != 0)
118 opts++;
119 if (opts->name) {
120 mount_data.flags &= opts->and_mask;
121 mount_data.flags |= opts->or_mask;
122 } else {
123 fprintf(stderr, "%s: bad option '%s'\n",
124 progname, cp);
125 longjmp(abort_buf, 1);
126 }
127 }
128 }
129 }
130
131 static uint32_t parse_addr(const char *ip)
132 {
133 struct in_addr in;
134 if (inet_aton(ip, &in) == 0) {
135 fprintf(stderr, "%s: can't parse IP address '%s'\n",
136 progname, ip);
137 longjmp(abort_buf, 1);
138 }
139 return in.s_addr;
140 }
141
142 static void check_path(const char *path)
143 {
144 struct stat st;
145
146 if (stat(path, &st) == -1) {
147 perror("stat");
148 longjmp(abort_buf, 1);
149 } else if (!S_ISDIR(st.st_mode)) {
150 fprintf(stderr, "%s: '%s' not a directory\n", progname, path);
151 longjmp(abort_buf, 1);
152 }
153 }
154
155 int main(int argc, char *argv[])
156 __attribute__ ((weak, alias("nfsmount_main")));
157
158 int nfsmount_main(int argc, char *argv[])
159 {
160 uint32_t server;
161 char *rem_name;
162 char *rem_path;
163 char *hostname;
164 char *path;
165 int c;
166 const char *portmap_file;
167 pid_t spoof_portmap;
168 int err;
169
170 if ((err = setjmp(abort_buf)))
171 return err;
172
173 /* Set these here to avoid longjmp warning */
174 portmap_file = NULL;
175 spoof_portmap = 0;
176 server = 0;
177
178 /* If progname is set we're invoked from another program */
179 if (!progname) {
180 struct timeval now;
181 progname = argv[0];
182 gettimeofday(&now, NULL);
183 srand48(now.tv_usec ^ (now.tv_sec << 24));
184 }
185
186 while ((c = getopt(argc, argv, "o:p:")) != EOF) {
187 switch (c) {
188 case 'o':
189 parse_opts(optarg);
190 break;
191 case 'p':
192 portmap_file = optarg;
193 break;
194 case '?':
195 fprintf(stderr, "%s: invalid option -%c\n",
196 progname, optopt);
197 return 1;
198 }
199 }
200
201 if (optind == argc) {
202 fprintf(stderr, "%s: need a path\n", progname);
203 return 1;
204 }
205
206 hostname = rem_path = argv[optind];
207
208 if ((rem_name = strdup(rem_path)) == NULL) {
209 perror("strdup");
210 return 1;
211 }
212
213 if ((rem_path = strchr(rem_path, ':')) == NULL) {
214 fprintf(stderr, "%s: need a server\n", progname);
215 return 1;
216 }
217
218 *rem_path++ = '\0';
219
220 if (*rem_path != '/') {
221 fprintf(stderr, "%s: need a path\n", progname);
222 return 1;
223 }
224
225 server = parse_addr(hostname);
226
227 if (optind <= argc - 2)
228 path = argv[optind + 1];
229 else
230 path = "/nfs_root";
231
232 check_path(path);
233
234 #if! _KLIBC_NO_MMU
235 /* Note: uClinux can't fork(), so the spoof portmapper is not
236 available on uClinux. */
237 if (portmap_file)
238 spoof_portmap = start_dummy_portmap(portmap_file);
239
240 if (spoof_portmap == -1)
241 return 1;
242 #endif
243
244 if (nfs_mount(rem_name, hostname, server, rem_path, path,
245 &mount_data) != 0)
246 return 1;
247
248 /* If we set up the spoofer, tear it down now */
249 if (spoof_portmap) {
250 kill(SIGTERM, spoof_portmap);
251 while (waitpid(spoof_portmap, NULL, 0) == -1 &&
252 errno == EINTR)
253 ;
254 }
255
256 free(rem_name);
257
258 return 0;
259 }