]> git.proxmox.com Git - ceph.git/blob - ceph/src/mount/mount.ceph.c
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / mount / mount.ceph.c
1 #include <stdio.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #include <errno.h>
5 #include <sys/mount.h>
6
7 #include "common/module.h"
8 #include "common/secret.h"
9 #include "include/addr_parsing.h"
10
11 #ifndef MS_RELATIME
12 # define MS_RELATIME (1<<21)
13 #endif
14
15 #define MAX_SECRET_LEN 1000
16 #define MAX_SECRET_OPTION_LEN (MAX_SECRET_LEN + 7)
17
18 int verboseflag = 0;
19 int skip_mtab_flag = 0;
20 static const char * const EMPTY_STRING = "";
21
22 /* TODO duplicates logic from kernel */
23 #define CEPH_AUTH_NAME_DEFAULT "guest"
24
25 #include "mtab.c"
26
27 static void block_signals (int how)
28 {
29 sigset_t sigs;
30
31 sigfillset (&sigs);
32 sigdelset(&sigs, SIGTRAP);
33 sigdelset(&sigs, SIGSEGV);
34 sigprocmask (how, &sigs, (sigset_t *) 0);
35 }
36
37 static char *mount_resolve_src(const char *orig_str)
38 {
39 int len, pos;
40 char *mount_path;
41 char *src;
42 char *buf = strdup(orig_str);
43
44 mount_path = strstr(buf, ":/");
45 if (!mount_path) {
46 printf("source mount path was not specified\n");
47 free(buf);
48 return NULL;
49 }
50 if (mount_path == buf) {
51 printf("server address expected\n");
52 free(buf);
53 return NULL;
54 }
55
56 *mount_path = '\0';
57 mount_path++;
58
59 if (!*mount_path) {
60 printf("incorrect source mount path\n");
61 free(buf);
62 return NULL;
63 }
64
65 src = resolve_addrs(buf);
66 if (!src) {
67 free(buf);
68 return NULL;
69 }
70
71 len = strlen(src);
72 pos = safe_cat(&src, &len, len, ":");
73 safe_cat(&src, &len, pos, mount_path);
74
75 free(buf);
76 return src;
77 }
78
79 /*
80 * this one is partialy based on parse_options() from cifs.mount.c
81 */
82 static char *parse_options(const char *data, int *filesys_flags)
83 {
84 char * next_keyword = NULL;
85 char * out = NULL;
86 int out_len = 0;
87 int pos = 0;
88 char *name = NULL;
89 int name_len = 0;
90 int name_pos = 0;
91 char secret[MAX_SECRET_LEN];
92 char *saw_name = NULL;
93 char *saw_secret = NULL;
94
95 if(verboseflag)
96 printf("parsing options: %s\n", data);
97
98 do {
99 char * value = NULL;
100 /* check if ends with trailing comma */
101 if(*data == 0)
102 break;
103 next_keyword = strchr(data,',');
104
105 /* temporarily null terminate end of keyword=value pair */
106 if(next_keyword)
107 *next_keyword++ = 0;
108
109 /* temporarily null terminate keyword to make keyword and value distinct */
110 if ((value = strchr(data, '=')) != NULL) {
111 *value = '\0';
112 value++;
113 }
114
115 int skip = 1;
116
117 if (strncmp(data, "ro", 2) == 0) {
118 *filesys_flags |= MS_RDONLY;
119 } else if (strncmp(data, "rw", 2) == 0) {
120 *filesys_flags &= ~MS_RDONLY;
121 } else if (strncmp(data, "nosuid", 6) == 0) {
122 *filesys_flags |= MS_NOSUID;
123 } else if (strncmp(data, "suid", 4) == 0) {
124 *filesys_flags &= ~MS_NOSUID;
125 } else if (strncmp(data, "dev", 3) == 0) {
126 *filesys_flags &= ~MS_NODEV;
127 } else if (strncmp(data, "nodev", 5) == 0) {
128 *filesys_flags |= MS_NODEV;
129 } else if (strncmp(data, "noexec", 6) == 0) {
130 *filesys_flags |= MS_NOEXEC;
131 } else if (strncmp(data, "exec", 4) == 0) {
132 *filesys_flags &= ~MS_NOEXEC;
133 } else if (strncmp(data, "sync", 4) == 0) {
134 *filesys_flags |= MS_SYNCHRONOUS;
135 } else if (strncmp(data, "remount", 7) == 0) {
136 *filesys_flags |= MS_REMOUNT;
137 } else if (strncmp(data, "mandlock", 8) == 0) {
138 *filesys_flags |= MS_MANDLOCK;
139 } else if ((strncmp(data, "nobrl", 5) == 0) ||
140 (strncmp(data, "nolock", 6) == 0)) {
141 *filesys_flags &= ~MS_MANDLOCK;
142 } else if (strncmp(data, "noatime", 7) == 0) {
143 *filesys_flags |= MS_NOATIME;
144 } else if (strncmp(data, "nodiratime", 10) == 0) {
145 *filesys_flags |= MS_NODIRATIME;
146 } else if (strncmp(data, "relatime", 8) == 0) {
147 *filesys_flags |= MS_RELATIME;
148
149 } else if (strncmp(data, "noauto", 6) == 0) {
150 skip = 1; /* ignore */
151 } else if (strncmp(data, "_netdev", 7) == 0) {
152 skip = 1; /* ignore */
153
154 } else if (strncmp(data, "secretfile", 10) == 0) {
155 if (!value || !*value) {
156 printf("keyword secretfile found, but no secret file specified\n");
157 free(saw_name);
158 return NULL;
159 }
160
161 if (read_secret_from_file(value, secret, sizeof(secret)) < 0) {
162 printf("error reading secret file\n");
163 return NULL;
164 }
165
166 /* see comment for "secret" */
167 saw_secret = secret;
168 skip = 1;
169 } else if (strncmp(data, "secret", 6) == 0) {
170 if (!value || !*value) {
171 printf("mount option secret requires a value.\n");
172 free(saw_name);
173 return NULL;
174 }
175
176 /* secret is only added to kernel options as
177 backwards compatibility, if add_key doesn't
178 recognize our keytype; hence, it is skipped
179 here and appended to options on add_key
180 failure */
181 size_t len = sizeof(secret);
182 strncpy(secret, value, len-1);
183 secret[len-1] = '\0';
184 saw_secret = secret;
185 skip = 1;
186 } else if (strncmp(data, "name", 4) == 0) {
187 if (!value || !*value) {
188 printf("mount option name requires a value.\n");
189 return NULL;
190 }
191
192 /* take a copy of the name, to be used for
193 naming the keys that we add to kernel; */
194 free(saw_name);
195 saw_name = strdup(value);
196 if (!saw_name) {
197 printf("out of memory.\n");
198 return NULL;
199 }
200 skip = 0;
201 } else {
202 skip = 0;
203 if (verboseflag) {
204 fprintf(stderr, "mount.ceph: unrecognized mount option \"%s\", "
205 "passing to kernel.\n", data);
206 }
207 }
208
209 /* Copy (possibly modified) option to out */
210 if (!skip) {
211 if (pos)
212 pos = safe_cat(&out, &out_len, pos, ",");
213
214 if (value) {
215 pos = safe_cat(&out, &out_len, pos, data);
216 pos = safe_cat(&out, &out_len, pos, "=");
217 pos = safe_cat(&out, &out_len, pos, value);
218 } else {
219 pos = safe_cat(&out, &out_len, pos, data);
220 }
221
222 }
223 data = next_keyword;
224 } while (data);
225
226 name_pos = safe_cat(&name, &name_len, name_pos, "client.");
227 if (!saw_name) {
228 name_pos = safe_cat(&name, &name_len, name_pos, CEPH_AUTH_NAME_DEFAULT);
229 } else {
230 name_pos = safe_cat(&name, &name_len, name_pos, saw_name);
231 }
232 if (saw_secret || is_kernel_secret(name)) {
233 int ret;
234 char secret_option[MAX_SECRET_OPTION_LEN];
235 ret = get_secret_option(saw_secret, name, secret_option, sizeof(secret_option));
236 if (ret < 0) {
237 free(saw_name);
238 return NULL;
239 } else {
240 if (pos) {
241 pos = safe_cat(&out, &out_len, pos, ",");
242 }
243 pos = safe_cat(&out, &out_len, pos, secret_option);
244 }
245 }
246
247 free(saw_name);
248 if (!out)
249 return strdup(EMPTY_STRING);
250 return out;
251 }
252
253
254 static int parse_arguments(int argc, char *const *const argv,
255 const char **src, const char **node, const char **opts)
256 {
257 int i;
258
259 if (argc < 2) {
260 // There were no arguments. Just show the usage.
261 return 1;
262 }
263 if ((!strcmp(argv[1], "-h")) || (!strcmp(argv[1], "--help"))) {
264 // The user asked for help.
265 return 1;
266 }
267
268 // The first two arguments are positional
269 if (argc < 3)
270 return -EINVAL;
271 *src = argv[1];
272 *node = argv[2];
273
274 // Parse the remaining options
275 *opts = EMPTY_STRING;
276 for (i = 3; i < argc; ++i) {
277 if (!strcmp("-h", argv[i]))
278 return 1;
279 else if (!strcmp("-n", argv[i]))
280 skip_mtab_flag = 1;
281 else if (!strcmp("-v", argv[i]))
282 verboseflag = 1;
283 else if (!strcmp("-o", argv[i])) {
284 ++i;
285 if (i >= argc) {
286 printf("Option -o requires an argument.\n\n");
287 return -EINVAL;
288 }
289 *opts = argv[i];
290 }
291 else {
292 printf("Can't understand option: '%s'\n\n", argv[i]);
293 return -EINVAL;
294 }
295 }
296 return 0;
297 }
298
299 /* modprobe failing doesn't necessarily prevent from working, so this
300 returns void */
301 static void modprobe(void)
302 {
303 int r;
304
305 r = module_load("ceph", NULL);
306 if (r)
307 printf("failed to load ceph kernel module (%d)\n", r);
308 }
309
310 static void usage(const char *prog_name)
311 {
312 printf("usage: %s [src] [mount-point] [-n] [-v] [-o ceph-options]\n",
313 prog_name);
314 printf("options:\n");
315 printf("\t-h: Print this help\n");
316 printf("\t-n: Do not update /etc/mtab\n");
317 printf("\t-v: Verbose\n");
318 printf("\tceph-options: refer to mount.ceph(8)\n");
319 printf("\n");
320 }
321
322 int main(int argc, char *argv[])
323 {
324 const char *src, *node, *opts;
325 char *rsrc = NULL;
326 char *popts = NULL;
327 int flags = 0;
328 int retval = 0;
329
330 retval = parse_arguments(argc, argv, &src, &node, &opts);
331 if (retval) {
332 usage(argv[0]);
333 exit((retval > 0) ? EXIT_SUCCESS : EXIT_FAILURE);
334 }
335
336 rsrc = mount_resolve_src(src);
337 if (!rsrc) {
338 printf("failed to resolve source\n");
339 exit(1);
340 }
341
342 modprobe();
343
344 popts = parse_options(opts, &flags);
345 if (!popts) {
346 printf("failed to parse ceph_options\n");
347 exit(1);
348 }
349
350 block_signals(SIG_BLOCK);
351
352 if (mount(rsrc, node, "ceph", flags, popts)) {
353 retval = errno;
354 switch (errno) {
355 case ENODEV:
356 printf("mount error: ceph filesystem not supported by the system\n");
357 break;
358 default:
359 printf("mount error %d = %s\n",errno,strerror(errno));
360 }
361 } else {
362 if (!skip_mtab_flag) {
363 update_mtab_entry(rsrc, node, "ceph", popts, flags, 0, 0);
364 }
365 }
366
367 block_signals(SIG_UNBLOCK);
368
369 free(popts);
370 free(rsrc);
371 exit(retval);
372 }
373