X-Git-Url: http://git.annexia.org/?p=libguestfs.git;a=blobdiff_plain;f=fuse%2Fguestmount.c;h=67a746f5ac2eb214009f7b4c5383d9056e900dfa;hp=3d3da39d0c38ca7330d845baa67869168b628723;hb=b0eabcca60da8fec55cbeaf83e17320281ed75b8;hpb=85c0bf53085e78b257cf71455a55924fe6e3943b diff --git a/fuse/guestmount.c b/fuse/guestmount.c index 3d3da39..67a746f 100644 --- a/fuse/guestmount.c +++ b/fuse/guestmount.c @@ -1,5 +1,5 @@ /* guestmount - mount guests using libguestfs and FUSE - * Copyright (C) 2009-2010 Red Hat Inc. + * Copyright (C) 2009-2011 Red Hat Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -42,6 +42,7 @@ #include #include #include +#include #include #include @@ -59,6 +60,7 @@ guestfs_h *g = NULL; int read_only = 0; +int live = 0; int verbose = 0; int inspector = 0; int keys_from_stdin = 0; @@ -744,19 +746,41 @@ fg_getxattr (const char *path, const char *name, char *value, free_attrs = 1; } + /* Find the matching attribute (index in 'i'). */ + ssize_t r; size_t i; - int r = -ENOATTR; for (i = 0; i < xattrs->len; ++i) { - if (STREQ (xattrs->val[i].attrname, name)) { - size_t sz = xattrs->val[i].attrval_len; - if (sz > size) - sz = size; - memcpy (value, xattrs->val[i].attrval, sz); - r = 0; + if (STREQ (xattrs->val[i].attrname, name)) break; - } } + if (i == xattrs->len) { /* not found */ + r = -ENOATTR; + goto out; + } + + /* The getxattr man page is unclear, but if value == NULL then we + * return the space required (the caller then makes a second syscall + * after allocating the required amount of space). If value != NULL + * then it's not clear what we should do, but it appears we should + * copy as much as possible and return -ERANGE if there's not enough + * space in the buffer. + */ + size_t sz = xattrs->val[i].attrval_len; + if (value == NULL) { + r = sz; + goto out; + } + + if (sz <= size) + r = sz; + else { + r = -ERANGE; + sz = size; + } + memcpy (value, xattrs->val[i].attrval, sz); + +out: if (free_attrs) guestfs_free_xattr_list ((struct guestfs_xattr_list *) xattrs); @@ -780,25 +804,47 @@ fg_listxattr (const char *path, char *list, size_t size) free_attrs = 1; } + /* Calculate how much space is required to hold the result. */ + size_t space = 0; + size_t len; size_t i; - ssize_t copied = 0; for (i = 0; i < xattrs->len; ++i) { - size_t len = strlen (xattrs->val[i].attrname) + 1; + len = strlen (xattrs->val[i].attrname) + 1; + space += len; + } + + /* The listxattr man page is unclear, but if list == NULL then we + * return the space required (the caller then makes a second syscall + * after allocating the required amount of space). If list != NULL + * then it's not clear what we should do, but it appears we should + * copy as much as possible and return -ERANGE if there's not enough + * space in the buffer. + */ + ssize_t r; + if (list == NULL) { + r = space; + goto out; + } + + r = 0; + for (i = 0; i < xattrs->len; ++i) { + len = strlen (xattrs->val[i].attrname) + 1; if (size >= len) { memcpy (list, xattrs->val[i].attrname, len); size -= len; list += len; - copied += len; + r += len; } else { - copied = -ERANGE; + r = -ERANGE; break; } } + out: if (free_attrs) guestfs_free_xattr_list ((struct guestfs_xattr_list *) xattrs); - return copied; + return r; } static int @@ -879,13 +925,15 @@ usage (int status) " -i|--inspector Automatically mount filesystems\n" " --help Display help message and exit\n" " --keys-from-stdin Read passphrases from stdin\n" - " -m|--mount dev[:mnt] Mount dev on mnt (if omitted, /)\n" + " --live Connect to a live virtual machine\n" + " -m|--mount dev[:mnt[:opts]] Mount dev on mnt (if omitted, /)\n" " -n|--no-sync Don't autosync\n" " -o|--option opt Pass extra option to FUSE\n" " -r|--ro Mount read-only\n" " --selinux Enable SELinux support\n" " -v|--verbose Verbose messages\n" " -V|--version Display version and exit\n" + " -w|--rw Mount read-write\n" " -x|--trace Trace guestfs API calls\n" ), program_name, program_name, program_name); @@ -900,6 +948,8 @@ main (int argc, char *argv[]) bindtextdomain (PACKAGE, LOCALEBASEDIR); textdomain (PACKAGE); + parse_config (); + enum { HELP_OPTION = CHAR_MAX + 1 }; /* The command line arguments are broadly compatible with (a subset @@ -917,6 +967,7 @@ main (int argc, char *argv[]) { "help", 0, 0, HELP_OPTION }, { "inspector", 0, 0, 'i' }, { "keys-from-stdin", 0, 0, 0 }, + { "live", 0, 0, 0 }, { "mount", 1, 0, 'm' }, { "no-sync", 0, 0, 'n' }, { "option", 1, 0, 'o' }, @@ -983,19 +1034,6 @@ main (int argc, char *argv[]) */ ADD_FUSE_ARG ("-s"); - /* If developing, add ./appliance to the path. Note that libtools - * interferes with this because uninstalled guestfish is a shell - * script that runs the real program with an absolute path. Detect - * that too. - * - * BUT if LIBGUESTFS_PATH environment variable is already set by - * the user, then don't override it. - */ - if (getenv ("LIBGUESTFS_PATH") == NULL && - argv[0] && - (argv[0][0] != '/' || strstr (argv[0], "/.libs/lt-") != NULL)) - guestfs_set_path (g, "appliance:" GUESTFS_DEFAULT_PATH); - for (;;) { c = getopt_long (argc, argv, options, long_options, &option_index); if (c == -1) break; @@ -1017,6 +1055,8 @@ main (int argc, char *argv[]) keys_from_stdin = 1; } else if (STREQ (long_options[option_index].name, "echo-keys")) { echo_keys = 1; + } else if (STREQ (long_options[option_index].name, "live")) { + live = 1; } else { fprintf (stderr, _("%s: unknown long option: %s (%d)\n"), program_name, long_options[option_index].name, option_index); @@ -1085,11 +1125,52 @@ main (int argc, char *argv[]) } /* Check we have the right options. */ - if (!drvs || !(mps || inspector)) { - fprintf (stderr, - _("%s: must have at least one -a/-d and at least one -m/-i option\n"), - program_name); - exit (EXIT_FAILURE); + if (!live) { + if (!drvs || !(mps || inspector)) { + fprintf (stderr, + _("%s: must have at least one -a/-d and at least one -m/-i option\n"), + program_name); + exit (EXIT_FAILURE); + } + } else { + size_t count_d = 0, count_other = 0; + struct drv *drv; + + if (read_only) { + fprintf (stderr, + _("%s: --live is not compatible with --ro option\n"), + program_name); + exit (EXIT_FAILURE); + } + + if (inspector) { + fprintf (stderr, + _("%s: --live is not compatible with -i option\n"), + program_name); + exit (EXIT_FAILURE); + } + + /* --live: make sure there was one -d option and no -a options */ + for (drv = drvs; drv; drv = drv->next) { + if (drv->type == drv_d) + count_d++; + else + count_other++; + } + + if (count_d != 1) { + fprintf (stderr, + _("%s: with --live, you must use exactly one -d option\n"), + program_name); + exit (EXIT_FAILURE); + } + + if (count_other != 0) { + fprintf (stderr, + _("%s: --live is not compatible with -a option\n"), + program_name); + exit (EXIT_FAILURE); + } } /* We'd better have a mountpoint. */