+++ /dev/null
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <sys/mount.h>
-
-#include "common/module.h"
-#include "common/secret.h"
-#include "include/addr_parsing.h"
-
-#ifndef MS_RELATIME
-# define MS_RELATIME (1<<21)
-#endif
-
-#define MAX_SECRET_LEN 1000
-#define MAX_SECRET_OPTION_LEN (MAX_SECRET_LEN + 7)
-
-int verboseflag = 0;
-int skip_mtab_flag = 0;
-static const char * const EMPTY_STRING = "";
-
-/* TODO duplicates logic from kernel */
-#define CEPH_AUTH_NAME_DEFAULT "guest"
-
-#include "mtab.c"
-
-static void block_signals (int how)
-{
- sigset_t sigs;
-
- sigfillset (&sigs);
- sigdelset(&sigs, SIGTRAP);
- sigdelset(&sigs, SIGSEGV);
- sigprocmask (how, &sigs, (sigset_t *) 0);
-}
-
-static char *mount_resolve_src(const char *orig_str)
-{
- int len, pos;
- char *mount_path;
- char *src;
- char *buf = strdup(orig_str);
-
- mount_path = strstr(buf, ":/");
- if (!mount_path) {
- printf("source mount path was not specified\n");
- free(buf);
- return NULL;
- }
- if (mount_path == buf) {
- printf("server address expected\n");
- free(buf);
- return NULL;
- }
-
- *mount_path = '\0';
- mount_path++;
-
- if (!*mount_path) {
- printf("incorrect source mount path\n");
- free(buf);
- return NULL;
- }
-
- src = resolve_addrs(buf);
- if (!src) {
- free(buf);
- return NULL;
- }
-
- len = strlen(src);
- pos = safe_cat(&src, &len, len, ":");
- safe_cat(&src, &len, pos, mount_path);
-
- free(buf);
- return src;
-}
-
-/*
- * this one is partialy based on parse_options() from cifs.mount.c
- */
-static char *parse_options(const char *data, int *filesys_flags)
-{
- char * next_keyword = NULL;
- char * out = NULL;
- int out_len = 0;
- int pos = 0;
- char *name = NULL;
- int name_len = 0;
- int name_pos = 0;
- char secret[MAX_SECRET_LEN];
- char *saw_name = NULL;
- char *saw_secret = NULL;
-
- if(verboseflag)
- printf("parsing options: %s\n", data);
-
- do {
- char * value = NULL;
- /* check if ends with trailing comma */
- if(*data == 0)
- break;
- next_keyword = strchr(data,',');
-
- /* temporarily null terminate end of keyword=value pair */
- if(next_keyword)
- *next_keyword++ = 0;
-
- /* temporarily null terminate keyword to make keyword and value distinct */
- if ((value = strchr(data, '=')) != NULL) {
- *value = '\0';
- value++;
- }
-
- int skip = 1;
-
- if (strncmp(data, "ro", 2) == 0) {
- *filesys_flags |= MS_RDONLY;
- } else if (strncmp(data, "rw", 2) == 0) {
- *filesys_flags &= ~MS_RDONLY;
- } else if (strncmp(data, "nosuid", 6) == 0) {
- *filesys_flags |= MS_NOSUID;
- } else if (strncmp(data, "suid", 4) == 0) {
- *filesys_flags &= ~MS_NOSUID;
- } else if (strncmp(data, "dev", 3) == 0) {
- *filesys_flags &= ~MS_NODEV;
- } else if (strncmp(data, "nodev", 5) == 0) {
- *filesys_flags |= MS_NODEV;
- } else if (strncmp(data, "noexec", 6) == 0) {
- *filesys_flags |= MS_NOEXEC;
- } else if (strncmp(data, "exec", 4) == 0) {
- *filesys_flags &= ~MS_NOEXEC;
- } else if (strncmp(data, "sync", 4) == 0) {
- *filesys_flags |= MS_SYNCHRONOUS;
- } else if (strncmp(data, "remount", 7) == 0) {
- *filesys_flags |= MS_REMOUNT;
- } else if (strncmp(data, "mandlock", 8) == 0) {
- *filesys_flags |= MS_MANDLOCK;
- } else if ((strncmp(data, "nobrl", 5) == 0) ||
- (strncmp(data, "nolock", 6) == 0)) {
- *filesys_flags &= ~MS_MANDLOCK;
- } else if (strncmp(data, "noatime", 7) == 0) {
- *filesys_flags |= MS_NOATIME;
- } else if (strncmp(data, "nodiratime", 10) == 0) {
- *filesys_flags |= MS_NODIRATIME;
- } else if (strncmp(data, "relatime", 8) == 0) {
- *filesys_flags |= MS_RELATIME;
-
- } else if (strncmp(data, "noauto", 6) == 0) {
- skip = 1; /* ignore */
- } else if (strncmp(data, "_netdev", 7) == 0) {
- skip = 1; /* ignore */
-
- } else if (strncmp(data, "secretfile", 10) == 0) {
- if (!value || !*value) {
- printf("keyword secretfile found, but no secret file specified\n");
- free(saw_name);
- return NULL;
- }
-
- if (read_secret_from_file(value, secret, sizeof(secret)) < 0) {
- printf("error reading secret file\n");
- return NULL;
- }
-
- /* see comment for "secret" */
- saw_secret = secret;
- skip = 1;
- } else if (strncmp(data, "secret", 6) == 0) {
- if (!value || !*value) {
- printf("mount option secret requires a value.\n");
- free(saw_name);
- return NULL;
- }
-
- /* secret is only added to kernel options as
- backwards compatibility, if add_key doesn't
- recognize our keytype; hence, it is skipped
- here and appended to options on add_key
- failure */
- size_t len = sizeof(secret);
- strncpy(secret, value, len-1);
- secret[len-1] = '\0';
- saw_secret = secret;
- skip = 1;
- } else if (strncmp(data, "name", 4) == 0) {
- if (!value || !*value) {
- printf("mount option name requires a value.\n");
- return NULL;
- }
-
- /* take a copy of the name, to be used for
- naming the keys that we add to kernel; */
- free(saw_name);
- saw_name = strdup(value);
- if (!saw_name) {
- printf("out of memory.\n");
- return NULL;
- }
- skip = 0;
- } else {
- skip = 0;
- if (verboseflag) {
- fprintf(stderr, "mount.ceph: unrecognized mount option \"%s\", "
- "passing to kernel.\n", data);
- }
- }
-
- /* Copy (possibly modified) option to out */
- if (!skip) {
- if (pos)
- pos = safe_cat(&out, &out_len, pos, ",");
-
- if (value) {
- pos = safe_cat(&out, &out_len, pos, data);
- pos = safe_cat(&out, &out_len, pos, "=");
- pos = safe_cat(&out, &out_len, pos, value);
- } else {
- pos = safe_cat(&out, &out_len, pos, data);
- }
-
- }
- data = next_keyword;
- } while (data);
-
- name_pos = safe_cat(&name, &name_len, name_pos, "client.");
- if (!saw_name) {
- name_pos = safe_cat(&name, &name_len, name_pos, CEPH_AUTH_NAME_DEFAULT);
- } else {
- name_pos = safe_cat(&name, &name_len, name_pos, saw_name);
- }
- if (saw_secret || is_kernel_secret(name)) {
- int ret;
- char secret_option[MAX_SECRET_OPTION_LEN];
- ret = get_secret_option(saw_secret, name, secret_option, sizeof(secret_option));
- if (ret < 0) {
- free(saw_name);
- return NULL;
- } else {
- if (pos) {
- pos = safe_cat(&out, &out_len, pos, ",");
- }
- pos = safe_cat(&out, &out_len, pos, secret_option);
- }
- }
-
- free(saw_name);
- if (!out)
- return strdup(EMPTY_STRING);
- return out;
-}
-
-
-static int parse_arguments(int argc, char *const *const argv,
- const char **src, const char **node, const char **opts)
-{
- int i;
-
- if (argc < 2) {
- // There were no arguments. Just show the usage.
- return 1;
- }
- if ((!strcmp(argv[1], "-h")) || (!strcmp(argv[1], "--help"))) {
- // The user asked for help.
- return 1;
- }
-
- // The first two arguments are positional
- if (argc < 3)
- return -EINVAL;
- *src = argv[1];
- *node = argv[2];
-
- // Parse the remaining options
- *opts = EMPTY_STRING;
- for (i = 3; i < argc; ++i) {
- if (!strcmp("-h", argv[i]))
- return 1;
- else if (!strcmp("-n", argv[i]))
- skip_mtab_flag = 1;
- else if (!strcmp("-v", argv[i]))
- verboseflag = 1;
- else if (!strcmp("-o", argv[i])) {
- ++i;
- if (i >= argc) {
- printf("Option -o requires an argument.\n\n");
- return -EINVAL;
- }
- *opts = argv[i];
- }
- else {
- printf("Can't understand option: '%s'\n\n", argv[i]);
- return -EINVAL;
- }
- }
- return 0;
-}
-
-/* modprobe failing doesn't necessarily prevent from working, so this
- returns void */
-static void modprobe(void)
-{
- int r;
-
- r = module_load("ceph", NULL);
- if (r)
- printf("failed to load ceph kernel module (%d)\n", r);
-}
-
-static void usage(const char *prog_name)
-{
- printf("usage: %s [src] [mount-point] [-n] [-v] [-o ceph-options]\n",
- prog_name);
- printf("options:\n");
- printf("\t-h: Print this help\n");
- printf("\t-n: Do not update /etc/mtab\n");
- printf("\t-v: Verbose\n");
- printf("\tceph-options: refer to mount.ceph(8)\n");
- printf("\n");
-}
-
-int main(int argc, char *argv[])
-{
- const char *src, *node, *opts;
- char *rsrc = NULL;
- char *popts = NULL;
- int flags = 0;
- int retval = 0;
-
- retval = parse_arguments(argc, argv, &src, &node, &opts);
- if (retval) {
- usage(argv[0]);
- exit((retval > 0) ? EXIT_SUCCESS : EXIT_FAILURE);
- }
-
- rsrc = mount_resolve_src(src);
- if (!rsrc) {
- printf("failed to resolve source\n");
- exit(1);
- }
-
- modprobe();
-
- popts = parse_options(opts, &flags);
- if (!popts) {
- printf("failed to parse ceph_options\n");
- exit(1);
- }
-
- block_signals(SIG_BLOCK);
-
- if (mount(rsrc, node, "ceph", flags, popts)) {
- retval = errno;
- switch (errno) {
- case ENODEV:
- printf("mount error: ceph filesystem not supported by the system\n");
- break;
- default:
- printf("mount error %d = %s\n",errno,strerror(errno));
- }
- } else {
- if (!skip_mtab_flag) {
- update_mtab_entry(rsrc, node, "ceph", popts, flags, 0, 0);
- }
- }
-
- block_signals(SIG_UNBLOCK);
-
- free(popts);
- free(rsrc);
- exit(retval);
-}
-