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 34*3ff01b23SMartin Matuska /* Substring from after the last slash, or the string itself if none */ 35*3ff01b23SMartin Matuska const char * 36*3ff01b23SMartin Matuska zfs_basename(const char *path) 37*3ff01b23SMartin Matuska { 38*3ff01b23SMartin Matuska const char *bn = strrchr(path, '/'); 39*3ff01b23SMartin Matuska return (bn ? bn + 1 : path); 40*3ff01b23SMartin Matuska } 41*3ff01b23SMartin Matuska 42*3ff01b23SMartin Matuska /* Return index of last slash or -1 if none */ 43*3ff01b23SMartin Matuska ssize_t 44*3ff01b23SMartin Matuska zfs_dirnamelen(const char *path) 45*3ff01b23SMartin Matuska { 46*3ff01b23SMartin Matuska const char *end = strrchr(path, '/'); 47*3ff01b23SMartin Matuska return (end ? end - path : -1); 48*3ff01b23SMartin Matuska } 49*3ff01b23SMartin 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 { 59eda14cbcSMatt Macy int i, error = -1; 6016038816SMartin Matuska char *dir, *env, *envdup, *tmp = NULL; 61eda14cbcSMatt Macy 62eda14cbcSMatt Macy env = getenv("ZPOOL_IMPORT_PATH"); 63eda14cbcSMatt Macy errno = ENOENT; 64eda14cbcSMatt Macy 65eda14cbcSMatt Macy if (env) { 66eda14cbcSMatt Macy envdup = strdup(env); 6716038816SMartin Matuska for (dir = strtok_r(envdup, ":", &tmp); 6816038816SMartin Matuska dir != NULL && error != 0; 6916038816SMartin Matuska dir = strtok_r(NULL, ":", &tmp)) { 70eda14cbcSMatt Macy (void) snprintf(path, len, "%s/%s", dir, name); 71eda14cbcSMatt Macy error = access(path, F_OK); 72eda14cbcSMatt Macy } 73eda14cbcSMatt Macy free(envdup); 74eda14cbcSMatt Macy } else { 75eda14cbcSMatt Macy const char * const *zpool_default_import_path; 76eda14cbcSMatt Macy size_t count; 77eda14cbcSMatt Macy 78eda14cbcSMatt Macy zpool_default_import_path = zpool_default_search_paths(&count); 79eda14cbcSMatt Macy 80eda14cbcSMatt Macy for (i = 0; i < count && error < 0; i++) { 81eda14cbcSMatt Macy (void) snprintf(path, len, "%s/%s", 82eda14cbcSMatt Macy zpool_default_import_path[i], name); 83eda14cbcSMatt Macy error = access(path, F_OK); 84eda14cbcSMatt Macy } 85eda14cbcSMatt Macy } 86eda14cbcSMatt Macy 87eda14cbcSMatt Macy return (error ? ENOENT : 0); 88eda14cbcSMatt Macy } 89eda14cbcSMatt Macy 90eda14cbcSMatt Macy /* 91eda14cbcSMatt Macy * Given a shorthand device name look for a match against 'cmp_name'. This 92eda14cbcSMatt Macy * is done by checking all prefix expansions using either the default 93eda14cbcSMatt Macy * 'zpool_default_import_paths' or the ZPOOL_IMPORT_PATH environment 94eda14cbcSMatt Macy * variable. Proper partition suffixes will be appended if this is a 95eda14cbcSMatt Macy * whole disk. When a match is found 0 is returned otherwise ENOENT. 96eda14cbcSMatt Macy */ 97eda14cbcSMatt Macy static int 98eda14cbcSMatt Macy zfs_strcmp_shortname(const char *name, const char *cmp_name, int wholedisk) 99eda14cbcSMatt Macy { 100eda14cbcSMatt Macy int path_len, cmp_len, i = 0, error = ENOENT; 10116038816SMartin Matuska char *dir, *env, *envdup = NULL, *tmp = NULL; 102eda14cbcSMatt Macy char path_name[MAXPATHLEN]; 10316038816SMartin Matuska const char * const *zpool_default_import_path = NULL; 104eda14cbcSMatt Macy size_t count; 105eda14cbcSMatt Macy 106eda14cbcSMatt Macy cmp_len = strlen(cmp_name); 107eda14cbcSMatt Macy env = getenv("ZPOOL_IMPORT_PATH"); 108eda14cbcSMatt Macy 109eda14cbcSMatt Macy if (env) { 110eda14cbcSMatt Macy envdup = strdup(env); 11116038816SMartin Matuska dir = strtok_r(envdup, ":", &tmp); 112eda14cbcSMatt Macy } else { 11316038816SMartin Matuska zpool_default_import_path = zpool_default_search_paths(&count); 114eda14cbcSMatt Macy dir = (char *)zpool_default_import_path[i]; 115eda14cbcSMatt Macy } 116eda14cbcSMatt Macy 117eda14cbcSMatt Macy while (dir) { 118eda14cbcSMatt Macy /* Trim trailing directory slashes from ZPOOL_IMPORT_PATH */ 119eda14cbcSMatt Macy if (env) { 120eda14cbcSMatt Macy while (dir[strlen(dir)-1] == '/') 121eda14cbcSMatt Macy dir[strlen(dir)-1] = '\0'; 122eda14cbcSMatt Macy } 123eda14cbcSMatt Macy 124eda14cbcSMatt Macy path_len = snprintf(path_name, MAXPATHLEN, "%s/%s", dir, name); 125eda14cbcSMatt Macy if (wholedisk) 126eda14cbcSMatt Macy path_len = zfs_append_partition(path_name, MAXPATHLEN); 127eda14cbcSMatt Macy 128eda14cbcSMatt Macy if ((path_len == cmp_len) && strcmp(path_name, cmp_name) == 0) { 129eda14cbcSMatt Macy error = 0; 130eda14cbcSMatt Macy break; 131eda14cbcSMatt Macy } 132eda14cbcSMatt Macy 133eda14cbcSMatt Macy if (env) { 13416038816SMartin Matuska dir = strtok_r(NULL, ":", &tmp); 135eda14cbcSMatt Macy } else if (++i < count) { 136eda14cbcSMatt Macy dir = (char *)zpool_default_import_path[i]; 137eda14cbcSMatt Macy } else { 138eda14cbcSMatt Macy dir = NULL; 139eda14cbcSMatt Macy } 140eda14cbcSMatt Macy } 141eda14cbcSMatt Macy 142eda14cbcSMatt Macy if (env) 143eda14cbcSMatt Macy free(envdup); 144eda14cbcSMatt Macy 145eda14cbcSMatt Macy return (error); 146eda14cbcSMatt Macy } 147eda14cbcSMatt Macy 148eda14cbcSMatt Macy /* 149eda14cbcSMatt Macy * Given either a shorthand or fully qualified path name look for a match 150eda14cbcSMatt Macy * against 'cmp'. The passed name will be expanded as needed for comparison 151eda14cbcSMatt Macy * purposes and redundant slashes stripped to ensure an accurate match. 152eda14cbcSMatt Macy */ 153eda14cbcSMatt Macy int 154eda14cbcSMatt Macy zfs_strcmp_pathname(const char *name, const char *cmp, int wholedisk) 155eda14cbcSMatt Macy { 156eda14cbcSMatt Macy int path_len, cmp_len; 157eda14cbcSMatt Macy char path_name[MAXPATHLEN]; 158eda14cbcSMatt Macy char cmp_name[MAXPATHLEN]; 15916038816SMartin Matuska char *dir, *tmp = NULL; 160eda14cbcSMatt Macy 16116038816SMartin Matuska /* Strip redundant slashes if they exist due to ZPOOL_IMPORT_PATH */ 16216038816SMartin Matuska cmp_name[0] = '\0'; 16316038816SMartin Matuska (void) strlcpy(path_name, cmp, sizeof (path_name)); 16416038816SMartin Matuska for (dir = strtok_r(path_name, "/", &tmp); 16516038816SMartin Matuska dir != NULL; 16616038816SMartin Matuska dir = strtok_r(NULL, "/", &tmp)) { 167eda14cbcSMatt Macy strlcat(cmp_name, "/", sizeof (cmp_name)); 168eda14cbcSMatt Macy strlcat(cmp_name, dir, sizeof (cmp_name)); 169eda14cbcSMatt Macy } 170eda14cbcSMatt Macy 171eda14cbcSMatt Macy if (name[0] != '/') 172eda14cbcSMatt Macy return (zfs_strcmp_shortname(name, cmp_name, wholedisk)); 173eda14cbcSMatt Macy 174eda14cbcSMatt Macy (void) strlcpy(path_name, name, MAXPATHLEN); 175eda14cbcSMatt Macy path_len = strlen(path_name); 176eda14cbcSMatt Macy cmp_len = strlen(cmp_name); 177eda14cbcSMatt Macy 178eda14cbcSMatt Macy if (wholedisk) { 179eda14cbcSMatt Macy path_len = zfs_append_partition(path_name, MAXPATHLEN); 180eda14cbcSMatt Macy if (path_len == -1) 181eda14cbcSMatt Macy return (ENOMEM); 182eda14cbcSMatt Macy } 183eda14cbcSMatt Macy 184eda14cbcSMatt Macy if ((path_len != cmp_len) || strcmp(path_name, cmp_name)) 185eda14cbcSMatt Macy return (ENOENT); 186eda14cbcSMatt Macy 187eda14cbcSMatt Macy return (0); 188eda14cbcSMatt Macy } 189