Fix missing vdev names in zpool status output
[zfs.git] / lib / libzfs / libzfs_util.c
index da1b9bc..de4bb72 100644 (file)
@@ -20,6 +20,7 @@
  */
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011 by Delphix. All rights reserved.
  */
 
 /*
@@ -346,6 +347,7 @@ zfs_standard_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...)
        switch (error) {
        case ENXIO:
        case ENODEV:
+       case EPIPE:
                zfs_verror(hdl, EZFS_IO, fmt, ap);
                break;
 
@@ -608,42 +610,35 @@ libzfs_print_on_error(libzfs_handle_t *hdl, boolean_t printerr)
 static int
 libzfs_module_loaded(const char *module)
 {
-       FILE *f;
-       int result = 0;
-       char name[256];
+       const char path_prefix[] = "/sys/module/";
+       char path[256];
 
-       f = fopen("/proc/modules", "r");
-       if (f == NULL)
-               return -1;
+       memcpy(path, path_prefix, sizeof(path_prefix) - 1);
+       strcpy(path + sizeof(path_prefix) - 1, module);
 
-       while (fgets(name, sizeof(name), f)) {
-               char *c = strchr(name, ' ');
-               if (!c)
-                       continue;
-               *c = 0;
-               if (strcmp(module, name) == 0) {
-                       result = 1;
-                       break;
-               }
-       }
-       fclose(f);
-
-       return result;
+       return (access(path, F_OK) == 0);
 }
 
 int
 libzfs_run_process(const char *path, char *argv[], int flags)
 {
        pid_t pid;
-       int rc;
+       int rc, devnull_fd;
 
        pid = vfork();
        if (pid == 0) {
+               devnull_fd = open("/dev/null", O_WRONLY);
+
+               if (devnull_fd < 0)
+                       _exit(-1);
+
                if (!(flags & STDOUT_VERBOSE))
-                       close(STDOUT_FILENO);
+                       (void) dup2(devnull_fd, STDOUT_FILENO);
 
                if (!(flags & STDERR_VERBOSE))
-                       close(STDERR_FILENO);
+                       (void) dup2(devnull_fd, STDERR_FILENO);
+
+               close(devnull_fd);
 
                (void) execvp(path, argv);
                _exit(-1);
@@ -814,16 +809,29 @@ int
 zfs_resolve_shortname(const char *name, char *path, size_t pathlen)
 {
        int i, err;
-       char dirs[5][9] = {"by-id", "by-label", "by-path", "by-uuid", "zpool"};
+       char dirs[6][9] = {"by-id", "by-label", "by-path", "by-uuid", "zpool",
+                          "by-vdev"};
 
+       /* /dev/ */
        (void) snprintf(path, pathlen, "%s/%s", DISK_ROOT, name);
        err = access(path, F_OK);
-       for (i = 0; i < 5 && err < 0; i++) {
+       if (err == 0)
+               return (err);
+
+       /* /dev/mapper/ */
+       (void) snprintf(path, pathlen, "%s/mapper/%s", DISK_ROOT, name);
+       err = access(path, F_OK);
+       if (err == 0)
+               return (err);
+
+       /* /dev/disk/<dirs>/ */
+       for (i = 0; i < 6 && err < 0; i++) {
                (void) snprintf(path, pathlen, "%s/%s/%s",
                    UDISK_ROOT, dirs[i], name);
                err = access(path, F_OK);
        }
-       return err;
+
+       return (err);
 }
 
 /*
@@ -1186,11 +1194,14 @@ str2shift(libzfs_handle_t *hdl, const char *buf)
        }
 
        /*
-        * We want to allow trailing 'b' characters for 'GB' or 'Mb'.  But don't
-        * allow 'BB' - that's just weird.
+        * Allow 'G' = 'GB' = 'GiB', case-insensitively.
+        * However, 'BB' and 'BiB' are disallowed.
         */
-       if (buf[1] == '\0' || (toupper(buf[1]) == 'B' && buf[2] == '\0' &&
-           toupper(buf[0]) != 'B'))
+       if (buf[1] == '\0' ||
+           (toupper(buf[0]) != 'B' &&
+            ((toupper(buf[1]) == 'B' && buf[2] == '\0') ||
+             (toupper(buf[1]) == 'I' && toupper(buf[2]) == 'B' &&
+              buf[3] == '\0'))))
                return (10*i);
 
        zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
@@ -1411,7 +1422,8 @@ addlist(libzfs_handle_t *hdl, char *propname, zprop_list_t **listp,
         * dataset property,
         */
        if (prop == ZPROP_INVAL && (type == ZFS_TYPE_POOL ||
-           (!zfs_prop_user(propname) && !zfs_prop_userquota(propname)))) {
+           (!zfs_prop_user(propname) && !zfs_prop_userquota(propname) &&
+           !zfs_prop_written(propname)))) {
                zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
                    "invalid property '%s'"), propname);
                return (zfs_error(hdl, EZFS_BADPROP,