+ return rc;
+}
+
+static void set_defaults(struct mount_opts *mop)
+{
+ memset(mop, 0, sizeof(*mop));
+ mop->mo_usource = NULL;
+ mop->mo_source = NULL;
+ mop->mo_nomtab = 0;
+ mop->mo_fake = 0;
+ mop->mo_force = 0;
+ mop->mo_retry = 0;
+ mop->mo_have_mgsnid = 0;
+ mop->mo_md_stripe_cache_size = 16384;
+ mop->mo_orig_options = "";
+}
+
+static int parse_opts(int argc, char *const argv[], struct mount_opts *mop)
+{
+ static struct option long_opt[] = {
+ {"fake", 0, 0, 'f'},
+ {"force", 0, 0, 1},
+ {"help", 0, 0, 'h'},
+ {"nomtab", 0, 0, 'n'},
+ {"options", 1, 0, 'o'},
+ {"verbose", 0, 0, 'v'},
+ {0, 0, 0, 0}
+ };
+ char real_path[PATH_MAX] = {'\0'};
+ FILE *f;
+ char path[256], name[256];
+ size_t sz;
+ char *ptr;
+ int opt, rc;
+
+ while ((opt = getopt_long(argc, argv, "fhno:v",
+ long_opt, NULL)) != EOF){
+ switch (opt) {
+ case 1:
+ ++mop->mo_force;
+ printf("force: %d\n", mop->mo_force);
+ break;
+ case 'f':
+ ++mop->mo_fake;
+ printf("fake: %d\n", mop->mo_fake);
+ break;
+ case 'h':
+ usage(stdout);
+ break;
+ case 'n':
+ ++mop->mo_nomtab;
+ printf("nomtab: %d\n", mop->mo_nomtab);
+ break;
+ case 'o':
+ mop->mo_orig_options = optarg;
+ break;
+ case 'v':
+ ++verbose;
+ break;
+ default:
+ fprintf(stderr, "%s: unknown option '%c'\n",
+ progname, opt);
+ usage(stderr);
+ break;
+ }
+ }
+
+ if (optind + 2 > argc) {
+ fprintf(stderr, "%s: too few arguments\n", progname);
+ usage(stderr);
+ }
+
+ mop->mo_usource = argv[optind];
+ if (!mop->mo_usource) {
+ usage(stderr);
+ }
+
+ /**
+ * Try to get the real path to the device, in case it is a
+ * symbolic link for instance
+ */
+ if (realpath(mop->mo_usource, real_path) != NULL) {
+ mop->mo_usource = strdup(real_path);
+
+ ptr = strrchr(real_path, '/');
+ if (ptr && strncmp(ptr, "/dm-", 4) == 0 && isdigit(*(ptr + 4))) {
+ snprintf(path, sizeof(path), "/sys/block/%s/dm/name", ptr+1);
+ if ((f = fopen(path, "r"))) {
+ /* read "<name>\n" from sysfs */
+ if (fgets(name, sizeof(name), f) && (sz = strlen(name)) > 1) {
+ name[sz - 1] = '\0';
+ snprintf(real_path, sizeof(real_path), "/dev/mapper/%s", name);
+ }
+ fclose(f);
+ }
+ }
+ }
+
+ mop->mo_source = convert_hostnames(mop->mo_usource);
+ if (!mop->mo_source) {
+ usage(stderr);
+ }
+
+ if (realpath(argv[optind + 1], mop->mo_target) == NULL) {
+ rc = errno;
+ fprintf(stderr, "warning: %s: cannot resolve: %s\n",
+ argv[optind + 1], strerror(errno));
+ return rc;
+ }
+
+ return 0;
+}
+
+int main(int argc, char *const argv[])
+{
+ struct mount_opts mop;
+ char *options, *optcopy;
+ int i, rc, flags, optlen;
+
+ progname = strrchr(argv[0], '/');
+ progname = progname ? progname + 1 : argv[0];
+
+ set_defaults(&mop);
+
+ rc = parse_opts(argc, argv, &mop);
+ if (rc)
+ return rc;
+