diff options
author | vikram <none@none> | 2007-03-19 18:02:35 -0700 |
---|---|---|
committer | vikram <none@none> | 2007-03-19 18:02:35 -0700 |
commit | 568e756a1c7e2218f16f91d883b56e54636081f7 (patch) | |
tree | 92fde0bc59604461e5507bb694da71dbc8066e2f | |
parent | 5e45752a44935a6b2445ae1c763867d868fa3fbb (diff) | |
download | illumos-gate-568e756a1c7e2218f16f91d883b56e54636081f7.tar.gz |
6527366 di_devlink_open() fails in the miniroot after devname integration
-rw-r--r-- | usr/src/cmd/devfsadm/devfsadm.c | 3 | ||||
-rw-r--r-- | usr/src/cmd/devfsadm/message.h | 4 | ||||
-rw-r--r-- | usr/src/lib/libdevinfo/devinfo_devlink.c | 59 |
3 files changed, 65 insertions, 1 deletions
diff --git a/usr/src/cmd/devfsadm/devfsadm.c b/usr/src/cmd/devfsadm/devfsadm.c index d443b88a20..2cee988b13 100644 --- a/usr/src/cmd/devfsadm/devfsadm.c +++ b/usr/src/cmd/devfsadm/devfsadm.c @@ -1397,6 +1397,9 @@ unlock_dev(int flag) if (build_dev == FALSE) return; + if (devlink_cache == NULL) { + err_print(NO_DEVLINK_CACHE); + } assert(devlink_cache); if (flag == SYNC_STATE) { diff --git a/usr/src/cmd/devfsadm/message.h b/usr/src/cmd/devfsadm/message.h index 8d1436f38d..60f790293d 100644 --- a/usr/src/cmd/devfsadm/message.h +++ b/usr/src/cmd/devfsadm/message.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -273,6 +273,8 @@ major_number ]\n\t\t[ -n ]\n\t\t[ -r rootdir ]\n\t\t[ -v ]\n") #define NOT_DIR gettext("file is not a directory: %s\n") +#define NO_DEVLINK_CACHE gettext("devlink cache does not exist\n") + #ifdef __cplusplus } #endif diff --git a/usr/src/lib/libdevinfo/devinfo_devlink.c b/usr/src/lib/libdevinfo/devinfo_devlink.c index 34dad1c59b..6f53830b0c 100644 --- a/usr/src/lib/libdevinfo/devinfo_devlink.c +++ b/usr/src/lib/libdevinfo/devinfo_devlink.c @@ -39,6 +39,7 @@ #include <assert.h> static mutex_t update_mutex = DEFAULTMUTEX; /* Protects update record lock */ +static mutex_t temp_file_mutex = DEFAULTMUTEX; /* for file creation tests */ static const size_t elem_sizes[DB_TYPES] = { sizeof (struct db_node), @@ -61,6 +62,8 @@ static const char *skip_files[] = { #define N_SKIP_DIRS (sizeof (skip_dirs) / sizeof (skip_dirs[0])) #define N_SKIP_FILES (sizeof (skip_files) / sizeof (skip_files[0])) +#define DI_TEST_DB ETCDEV "di_test_db" + /* * * This file contains two sets of interfaces which operate on the reverse @@ -311,6 +314,10 @@ handle_alloc(const char *root_dir, uint_t flags) { char dev_dir[PATH_MAX], path[PATH_MAX], db_dir[PATH_MAX]; struct di_devlink_handle *hdp, proto = {0}; + int install = 0; + int isroot = 0; + struct stat sb; + char can_path[PATH_MAX]; assert(flags == OPEN_RDWR || flags == OPEN_RDONLY); @@ -335,6 +342,11 @@ handle_alloc(const char *root_dir, uint_t flags) (realpath(root_dir, db_dir) == NULL)) { return (NULL); } + } else { + /* + * The dev dir is at /dev i.e. we are not doing a -r /altroot + */ + isroot = 1; } if (strcmp(dev_dir, "/") == 0) { @@ -347,6 +359,53 @@ handle_alloc(const char *root_dir, uint_t flags) (void) strlcat(dev_dir, DEV, sizeof (dev_dir)); (void) strlcat(db_dir, ETCDEV, sizeof (db_dir)); + /* + * The following code is for install. Readers and writers need + * to be redirected to /tmp/etc/dev for the database file. + * Note that we test for readonly /etc by actually creating a + * file since statvfs is not a reliable method for determining + * readonly filesystems. + */ + install = 0; + (void) snprintf(can_path, sizeof (can_path), "%s/%s", ETCDEV, DB_FILE); + if (flags == OPEN_RDWR && isroot) { + char di_test_db[PATH_MAX]; + int fd; + (void) mutex_lock(&temp_file_mutex); + (void) snprintf(di_test_db, sizeof (di_test_db), "%s.%d", + DI_TEST_DB, getpid()); + fd = open(di_test_db, O_CREAT|O_RDWR|O_EXCL, 0644); + if (fd == -1 && errno == EROFS && stat(can_path, &sb) == -1) + install = 1; + if (fd != -1) { + (void) close(fd); + (void) unlink(di_test_db); + } + (void) mutex_unlock(&temp_file_mutex); + } else if (isroot) { + /* + * Readers can be non-privileged so we cannot test by creating + * a file in /etc/dev. Instead we check if the database + * file is missing in /etc/dev and is present in /tmp/etc/dev + * and is owned by root. + */ + char install_path[PATH_MAX]; + + (void) snprintf(install_path, sizeof (install_path), + "/tmp%s/%s", ETCDEV, DB_FILE); + if (stat(can_path, &sb) == -1 && stat(install_path, &sb) + != -1 && sb.st_uid == 0) { + install = 1; + } + } + + /* + * Check if we are in install. If we are, the database will be in + * /tmp/etc/dev + */ + if (install) + (void) snprintf(db_dir, sizeof (db_dir), "/tmp%s", ETCDEV); + proto.dev_dir = dev_dir; proto.db_dir = db_dir; proto.flags = flags; |