1eda14cbcSMatt Macy /* 2eda14cbcSMatt Macy * CDDL HEADER START 3eda14cbcSMatt Macy * 4eda14cbcSMatt Macy * The contents of this file are subject to the terms of the 5eda14cbcSMatt Macy * Common Development and Distribution License (the "License"). 6eda14cbcSMatt Macy * You may not use this file except in compliance with the License. 7eda14cbcSMatt Macy * 8eda14cbcSMatt Macy * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9eda14cbcSMatt Macy * or http://www.opensolaris.org/os/licensing. 10eda14cbcSMatt Macy * See the License for the specific language governing permissions 11eda14cbcSMatt Macy * and limitations under the License. 12eda14cbcSMatt Macy * 13eda14cbcSMatt Macy * When distributing Covered Code, include this CDDL HEADER in each 14eda14cbcSMatt Macy * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15eda14cbcSMatt Macy * If applicable, add the following below this CDDL HEADER, with the 16eda14cbcSMatt Macy * fields enclosed by brackets "[]" replaced with your own identifying 17eda14cbcSMatt Macy * information: Portions Copyright [yyyy] [name of copyright owner] 18eda14cbcSMatt Macy * 19eda14cbcSMatt Macy * CDDL HEADER END 20eda14cbcSMatt Macy */ 21eda14cbcSMatt Macy 22eda14cbcSMatt Macy /* 23eda14cbcSMatt Macy * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 24eda14cbcSMatt Macy */ 25eda14cbcSMatt Macy 26eda14cbcSMatt Macy #include <errno.h> 27eda14cbcSMatt Macy #include <stdio.h> 28eda14cbcSMatt Macy #include <stdlib.h> 29eda14cbcSMatt Macy #include <string.h> 30eda14cbcSMatt Macy #include <unistd.h> 31eda14cbcSMatt Macy 32eda14cbcSMatt Macy #include <libzutil.h> 33eda14cbcSMatt Macy 343ff01b23SMartin Matuska /* Substring from after the last slash, or the string itself if none */ 353ff01b23SMartin Matuska const char * 363ff01b23SMartin Matuska zfs_basename(const char *path) 373ff01b23SMartin Matuska { 383ff01b23SMartin Matuska const char *bn = strrchr(path, '/'); 393ff01b23SMartin Matuska return (bn ? bn + 1 : path); 403ff01b23SMartin Matuska } 413ff01b23SMartin Matuska 423ff01b23SMartin Matuska /* Return index of last slash or -1 if none */ 433ff01b23SMartin Matuska ssize_t 443ff01b23SMartin Matuska zfs_dirnamelen(const char *path) 453ff01b23SMartin Matuska { 463ff01b23SMartin Matuska const char *end = strrchr(path, '/'); 473ff01b23SMartin Matuska return (end ? end - path : -1); 483ff01b23SMartin Matuska } 493ff01b23SMartin Matuska 50eda14cbcSMatt Macy /* 51eda14cbcSMatt Macy * Given a shorthand device name check if a file by that name exists in any 52eda14cbcSMatt Macy * of the 'zpool_default_import_path' or ZPOOL_IMPORT_PATH directories. If 53eda14cbcSMatt Macy * one is found, store its fully qualified path in the 'path' buffer passed 54eda14cbcSMatt Macy * by the caller and return 0, otherwise return an error. 55eda14cbcSMatt Macy */ 56eda14cbcSMatt Macy int 57eda14cbcSMatt Macy zfs_resolve_shortname(const char *name, char *path, size_t len) 58eda14cbcSMatt Macy { 59*da5137abSMartin Matuska const char *env = getenv("ZPOOL_IMPORT_PATH"); 60eda14cbcSMatt Macy 61eda14cbcSMatt Macy if (env) { 62*da5137abSMartin Matuska for (;;) { 63*da5137abSMartin Matuska env += strspn(env, ":"); 64*da5137abSMartin Matuska size_t dirlen = strcspn(env, ":"); 65*da5137abSMartin Matuska if (dirlen) { 66*da5137abSMartin Matuska (void) snprintf(path, len, "%.*s/%s", 67*da5137abSMartin Matuska (int)dirlen, env, name); 68*da5137abSMartin Matuska if (access(path, F_OK) == 0) 69*da5137abSMartin Matuska return (0); 70*da5137abSMartin Matuska 71*da5137abSMartin Matuska env += dirlen; 72*da5137abSMartin Matuska } else 73*da5137abSMartin Matuska break; 74eda14cbcSMatt Macy } 75eda14cbcSMatt Macy } else { 76eda14cbcSMatt Macy size_t count; 77*da5137abSMartin Matuska const char *const *zpool_default_import_path = 78*da5137abSMartin Matuska zpool_default_search_paths(&count); 79eda14cbcSMatt Macy 80*da5137abSMartin Matuska for (size_t i = 0; i < count; ++i) { 81eda14cbcSMatt Macy (void) snprintf(path, len, "%s/%s", 82eda14cbcSMatt Macy zpool_default_import_path[i], name); 83*da5137abSMartin Matuska if (access(path, F_OK) == 0) 84*da5137abSMartin Matuska return (0); 85eda14cbcSMatt Macy } 86eda14cbcSMatt Macy } 87eda14cbcSMatt Macy 88*da5137abSMartin Matuska return (errno = ENOENT); 89eda14cbcSMatt Macy } 90eda14cbcSMatt Macy 91eda14cbcSMatt Macy /* 92eda14cbcSMatt Macy * Given a shorthand device name look for a match against 'cmp_name'. This 93eda14cbcSMatt Macy * is done by checking all prefix expansions using either the default 94eda14cbcSMatt Macy * 'zpool_default_import_paths' or the ZPOOL_IMPORT_PATH environment 95eda14cbcSMatt Macy * variable. Proper partition suffixes will be appended if this is a 96eda14cbcSMatt Macy * whole disk. When a match is found 0 is returned otherwise ENOENT. 97eda14cbcSMatt Macy */ 98eda14cbcSMatt Macy static int 99eda14cbcSMatt Macy zfs_strcmp_shortname(const char *name, const char *cmp_name, int wholedisk) 100eda14cbcSMatt Macy { 101eda14cbcSMatt Macy int path_len, cmp_len, i = 0, error = ENOENT; 10216038816SMartin Matuska char *dir, *env, *envdup = NULL, *tmp = NULL; 103eda14cbcSMatt Macy char path_name[MAXPATHLEN]; 10416038816SMartin Matuska const char *const *zpool_default_import_path = NULL; 105eda14cbcSMatt Macy size_t count; 106eda14cbcSMatt Macy 107eda14cbcSMatt Macy cmp_len = strlen(cmp_name); 108eda14cbcSMatt Macy env = getenv("ZPOOL_IMPORT_PATH"); 109eda14cbcSMatt Macy 110eda14cbcSMatt Macy if (env) { 111eda14cbcSMatt Macy envdup = strdup(env); 11216038816SMartin Matuska dir = strtok_r(envdup, ":", &tmp); 113eda14cbcSMatt Macy } else { 11416038816SMartin Matuska zpool_default_import_path = zpool_default_search_paths(&count); 115eda14cbcSMatt Macy dir = (char *)zpool_default_import_path[i]; 116eda14cbcSMatt Macy } 117eda14cbcSMatt Macy 118eda14cbcSMatt Macy while (dir) { 119eda14cbcSMatt Macy /* Trim trailing directory slashes from ZPOOL_IMPORT_PATH */ 120eda14cbcSMatt Macy if (env) { 121eda14cbcSMatt Macy while (dir[strlen(dir)-1] == '/') 122eda14cbcSMatt Macy dir[strlen(dir)-1] = '\0'; 123eda14cbcSMatt Macy } 124eda14cbcSMatt Macy 125eda14cbcSMatt Macy path_len = snprintf(path_name, MAXPATHLEN, "%s/%s", dir, name); 126eda14cbcSMatt Macy if (wholedisk) 127eda14cbcSMatt Macy path_len = zfs_append_partition(path_name, MAXPATHLEN); 128eda14cbcSMatt Macy 129eda14cbcSMatt Macy if ((path_len == cmp_len) && strcmp(path_name, cmp_name) == 0) { 130eda14cbcSMatt Macy error = 0; 131eda14cbcSMatt Macy break; 132eda14cbcSMatt Macy } 133eda14cbcSMatt Macy 134eda14cbcSMatt Macy if (env) { 13516038816SMartin Matuska dir = strtok_r(NULL, ":", &tmp); 136eda14cbcSMatt Macy } else if (++i < count) { 137eda14cbcSMatt Macy dir = (char *)zpool_default_import_path[i]; 138eda14cbcSMatt Macy } else { 139eda14cbcSMatt Macy dir = NULL; 140eda14cbcSMatt Macy } 141eda14cbcSMatt Macy } 142eda14cbcSMatt Macy 143eda14cbcSMatt Macy if (env) 144eda14cbcSMatt Macy free(envdup); 145eda14cbcSMatt Macy 146eda14cbcSMatt Macy return (error); 147eda14cbcSMatt Macy } 148eda14cbcSMatt Macy 149eda14cbcSMatt Macy /* 150eda14cbcSMatt Macy * Given either a shorthand or fully qualified path name look for a match 151eda14cbcSMatt Macy * against 'cmp'. The passed name will be expanded as needed for comparison 152eda14cbcSMatt Macy * purposes and redundant slashes stripped to ensure an accurate match. 153eda14cbcSMatt Macy */ 154eda14cbcSMatt Macy int 155eda14cbcSMatt Macy zfs_strcmp_pathname(const char *name, const char *cmp, int wholedisk) 156eda14cbcSMatt Macy { 157eda14cbcSMatt Macy int path_len, cmp_len; 158eda14cbcSMatt Macy char path_name[MAXPATHLEN]; 159eda14cbcSMatt Macy char cmp_name[MAXPATHLEN]; 16016038816SMartin Matuska char *dir, *tmp = NULL; 161eda14cbcSMatt Macy 16216038816SMartin Matuska /* Strip redundant slashes if they exist due to ZPOOL_IMPORT_PATH */ 16316038816SMartin Matuska cmp_name[0] = '\0'; 16416038816SMartin Matuska (void) strlcpy(path_name, cmp, sizeof (path_name)); 16516038816SMartin Matuska for (dir = strtok_r(path_name, "/", &tmp); 16616038816SMartin Matuska dir != NULL; 16716038816SMartin Matuska dir = strtok_r(NULL, "/", &tmp)) { 168eda14cbcSMatt Macy strlcat(cmp_name, "/", sizeof (cmp_name)); 169eda14cbcSMatt Macy strlcat(cmp_name, dir, sizeof (cmp_name)); 170eda14cbcSMatt Macy } 171eda14cbcSMatt Macy 172eda14cbcSMatt Macy if (name[0] != '/') 173eda14cbcSMatt Macy return (zfs_strcmp_shortname(name, cmp_name, wholedisk)); 174eda14cbcSMatt Macy 175eda14cbcSMatt Macy (void) strlcpy(path_name, name, MAXPATHLEN); 176eda14cbcSMatt Macy path_len = strlen(path_name); 177eda14cbcSMatt Macy cmp_len = strlen(cmp_name); 178eda14cbcSMatt Macy 179eda14cbcSMatt Macy if (wholedisk) { 180eda14cbcSMatt Macy path_len = zfs_append_partition(path_name, MAXPATHLEN); 181eda14cbcSMatt Macy if (path_len == -1) 182eda14cbcSMatt Macy return (ENOMEM); 183eda14cbcSMatt Macy } 184eda14cbcSMatt Macy 185eda14cbcSMatt Macy if ((path_len != cmp_len) || strcmp(path_name, cmp_name)) 186eda14cbcSMatt Macy return (ENOENT); 187eda14cbcSMatt Macy 188eda14cbcSMatt Macy return (0); 189eda14cbcSMatt Macy } 190