summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/cmd/devfsadm/devfsadm.c118
-rw-r--r--usr/src/cmd/devfsadm/devfsadm_impl.h1
-rw-r--r--usr/src/lib/libdevinfo/devinfo_devperm.c46
-rw-r--r--usr/src/lib/libdevinfo/devinfo_finddev.c136
-rw-r--r--usr/src/lib/libdevinfo/libdevinfo.h6
5 files changed, 169 insertions, 138 deletions
diff --git a/usr/src/cmd/devfsadm/devfsadm.c b/usr/src/cmd/devfsadm/devfsadm.c
index 3ae1e8275b..63d88dad62 100644
--- a/usr/src/cmd/devfsadm/devfsadm.c
+++ b/usr/src/cmd/devfsadm/devfsadm.c
@@ -3103,8 +3103,9 @@ rm_parent_dir_if_empty(char *pathname)
{
char *ptr, path[PATH_MAX + 1];
char *fcn = "rm_parent_dir_if_empty: ";
- char *pathlist;
- int len;
+ finddevhdl_t fhandle;
+ const char *f;
+ int rv;
vprint(REMOVE_MID, "%schecking %s if empty\n", fcn, pathname);
@@ -3122,17 +3123,17 @@ rm_parent_dir_if_empty(char *pathname)
*ptr = '\0';
- if ((pathlist = dev_readdir(path)) == NULL) {
- err_print(OPENDIR_FAILED, path, strerror(errno));
+ if ((rv = finddev_readdir(path, &fhandle)) != 0) {
+ err_print(OPENDIR_FAILED, path, strerror(rv));
return;
}
/*
* An empty pathlist implies an empty directory
*/
- len = strlen(pathlist);
- free(pathlist);
- if (len == 0) {
+ f = finddev_next(fhandle);
+ finddev_close(fhandle);
+ if (f == NULL) {
if (s_rmdir(path) == 0) {
vprint(REMOVE_MID,
"%sremoving empty dir %s\n", fcn, path);
@@ -4219,13 +4220,13 @@ recurse_dev_re(char *current_dir, char *path_re, recurse_dev_t *rd)
char new_path[PATH_MAX + 1];
char *anchored_path_re;
size_t len;
- char *pathlist;
- char *listp;
+ finddevhdl_t fhandle;
+ const char *fp;
vprint(RECURSEDEV_MID, "recurse_dev_re: curr = %s path=%s\n",
current_dir, path_re);
- if ((pathlist = dev_readdir(current_dir)) == NULL)
+ if (finddev_readdir(current_dir, &fhandle) != 0)
return;
len = strlen(path_re);
@@ -4243,13 +4244,13 @@ recurse_dev_re(char *current_dir, char *path_re, recurse_dev_t *rd)
free(anchored_path_re);
- for (listp = pathlist; (len = strlen(listp)) > 0; listp += len+1) {
+ while ((fp = finddev_next(fhandle)) != NULL) {
- if (regexec(&re1, listp, 0, NULL, 0) == 0) {
+ if (regexec(&re1, fp, 0, NULL, 0) == 0) {
/* match */
(void) strcpy(new_path, current_dir);
(void) strcat(new_path, "/");
- (void) strcat(new_path, listp);
+ (void) strcat(new_path, fp);
vprint(RECURSEDEV_MID, "recurse_dev_re: match, new "
"path = %s\n", new_path);
@@ -4268,7 +4269,7 @@ recurse_dev_re(char *current_dir, char *path_re, recurse_dev_t *rd)
regfree(&re1);
out:
- free(pathlist);
+ finddev_close(fhandle);
}
/*
@@ -5016,9 +5017,8 @@ int
get_stat_info(char *namebuf, struct stat *sb)
{
char *cp;
- char *pathlist;
- char *listp;
- int len;
+ finddevhdl_t fhandle;
+ const char *fp;
if (lstat(namebuf, sb) < 0) {
(void) err_print(LSTAT_FAILED, namebuf, strerror(errno));
@@ -5035,7 +5035,7 @@ get_stat_info(char *namebuf, struct stat *sb)
*/
if ((sb->st_mode & S_IFMT) == S_IFDIR) {
- if ((pathlist = dev_readdir(namebuf)) == NULL) {
+ if (finddev_readdir(namebuf, &fhandle) != 0) {
return (DEVFSADM_FAILURE);
}
@@ -5043,21 +5043,21 @@ get_stat_info(char *namebuf, struct stat *sb)
* Search each dir entry looking for a symlink. Return
* the first symlink found in namebuf. Recurse dirs.
*/
- for (listp = pathlist;
- (len = strlen(listp)) > 0; listp += len+1) {
+ while ((fp = finddev_next(fhandle)) != NULL) {
cp = namebuf + strlen(namebuf);
if ((strlcat(namebuf, "/", PATH_MAX) >= PATH_MAX) ||
- (strlcat(namebuf, listp, PATH_MAX) >= PATH_MAX)) {
+ (strlcat(namebuf, fp, PATH_MAX) >= PATH_MAX)) {
*cp = '\0';
+ finddev_close(fhandle);
return (DEVFSADM_FAILURE);
}
if (get_stat_info(namebuf, sb) == DEVFSADM_SUCCESS) {
- free(pathlist);
+ finddev_close(fhandle);
return (DEVFSADM_SUCCESS);
}
*cp = '\0';
}
- free(pathlist);
+ finddev_close(fhandle);
}
/* no symlink found, so return error */
@@ -5182,11 +5182,10 @@ enumerate_recurse(char *current_dir, char *path_left, numeral_set_t *setp,
char *slash;
char *new_path;
char *numeral_id;
- char *pathlist;
- char *listp;
- int len;
+ finddevhdl_t fhandle;
+ const char *fp;
- if ((pathlist = dev_readdir(current_dir)) == NULL) {
+ if (finddev_readdir(current_dir, &fhandle) != 0) {
return;
}
@@ -5199,7 +5198,7 @@ enumerate_recurse(char *current_dir, char *path_left, numeral_set_t *setp,
*slash = '\0';
}
- for (listp = pathlist; (len = strlen(listp)) > 0; listp += len+1) {
+ while ((fp = finddev_next(fhandle)) != NULL) {
/*
* Returns true if path_left matches the list entry.
@@ -5208,15 +5207,15 @@ enumerate_recurse(char *current_dir, char *path_left, numeral_set_t *setp,
* numeral_id.
*/
numeral_id = NULL;
- if (match_path_component(path_left, listp, &numeral_id,
+ if (match_path_component(path_left, (char *)fp, &numeral_id,
slash ? 0 : rules[index].subexp)) {
new_path = s_malloc(strlen(current_dir) +
- strlen(listp) + 2);
+ strlen(fp) + 2);
(void) strcpy(new_path, current_dir);
(void) strcat(new_path, "/");
- (void) strcat(new_path, listp);
+ (void) strcat(new_path, fp);
if (slash != NULL) {
enumerate_recurse(new_path, slash + 1,
@@ -5235,7 +5234,7 @@ enumerate_recurse(char *current_dir, char *path_left, numeral_set_t *setp,
if (slash != NULL) {
*slash = '/';
}
- free(pathlist);
+ finddev_close(fhandle);
}
@@ -8372,58 +8371,3 @@ done:
(void) door_return((char *)&res, sizeof (struct sdev_door_res),
NULL, 0);
}
-
-/*
- * Use of the dev filesystem's private readdir does not trigger
- * the implicit device reconfiguration.
- *
- * Note: only useable with paths mounted on an instance of the
- * dev filesystem.
- *
- * Does not return the . and .. entries.
- * Empty directories are returned as an zero-length list.
- * ENOENT is returned as a NULL list pointer.
- */
-static char *
-dev_readdir(char *path)
-{
- int rv;
- int64_t bufsiz;
- char *pathlist;
- char *p;
- int len;
-
- assert((strcmp(path, "/dev") == 0) ||
- (strncmp(path, "/dev/", 4) == 0));
-
- rv = modctl(MODDEVREADDIR, path, strlen(path), NULL, &bufsiz);
- if (rv != 0) {
- vprint(READDIR_MID, "%s: %s\n", path, strerror(errno));
- return (NULL);
- }
-
- for (;;) {
- assert(bufsiz != 0);
- pathlist = s_malloc(bufsiz);
-
- rv = modctl(MODDEVREADDIR, path, strlen(path),
- pathlist, &bufsiz);
- if (rv == 0) {
- vprint(READDIR_MID, "%s\n", path);
- vprint(READDIR_ALL_MID, "%s:\n", path);
- for (p = pathlist; (len = strlen(p)) > 0; p += len+1) {
- vprint(READDIR_ALL_MID, " %s\n", p);
- }
- return (pathlist);
- }
- free(pathlist);
- switch (errno) {
- case EAGAIN:
- break;
- case ENOENT:
- default:
- vprint(READDIR_MID, "%s: %s\n", path, strerror(errno));
- return (NULL);
- }
- }
-}
diff --git a/usr/src/cmd/devfsadm/devfsadm_impl.h b/usr/src/cmd/devfsadm/devfsadm_impl.h
index 5217649e7b..71f167d230 100644
--- a/usr/src/cmd/devfsadm/devfsadm_impl.h
+++ b/usr/src/cmd/devfsadm/devfsadm_impl.h
@@ -494,7 +494,6 @@ static nvlist_t *build_event_attributes(char *, char *, char *,
di_node_t, char *, int);
static void log_event(char *, char *, nvlist_t *);
static void build_and_log_event(char *, char *, char *, di_node_t);
-static char *dev_readdir(char *);
static void read_logindevperm_file(void);
static void set_logindev_perms(char *devlink);
diff --git a/usr/src/lib/libdevinfo/devinfo_devperm.c b/usr/src/lib/libdevinfo/devinfo_devperm.c
index 18e2409065..e9a9ea1696 100644
--- a/usr/src/lib/libdevinfo/devinfo_devperm.c
+++ b/usr/src/lib/libdevinfo/devinfo_devperm.c
@@ -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.
*/
@@ -384,8 +384,6 @@ dir_dev_acc(char *path, char *left_to_do, uid_t uid, gid_t gid, mode_t mode,
{
struct stat stat_buf;
int err = 0;
- DIR *dirp;
- struct dirent *direntp;
char errstring[MAX_LINELEN];
char *p;
regex_t regex;
@@ -393,7 +391,6 @@ dir_dev_acc(char *path, char *left_to_do, uid_t uid, gid_t gid, mode_t mode,
char *match;
char *name, *newpath, *remainder_path;
finddevhdl_t handle;
- int find_method;
/*
* Determine if the search needs to be performed via finddev,
@@ -403,13 +400,7 @@ dir_dev_acc(char *path, char *left_to_do, uid_t uid, gid_t gid, mode_t mode,
* reconfig for names managed by logindevperm but not present
* on the system.
*/
- find_method = ((getzoneid() == GLOBAL_ZONEID) &&
- ((strcmp(path, "/dev") == 0) ||
- (strncmp(path, "/dev/", 5) == 0))) ?
- FLAG_USE_FINDDEV : FLAG_USE_READDIR;
-
- /* path must be a valid name */
- if (find_method == FLAG_USE_FINDDEV && !device_exists(path)) {
+ if (!device_exists(path)) {
return (-1);
}
if (stat(path, &stat_buf) == -1) {
@@ -444,24 +435,20 @@ dir_dev_acc(char *path, char *left_to_do, uid_t uid, gid_t gid, mode_t mode,
}
}
- if (find_method == FLAG_USE_READDIR) {
- dirp = opendir(path);
- if (dirp == NULL)
- return (0);
- } else {
- if (finddev_readdir(path, &handle) != 0)
- return (0);
- }
+ if (finddev_readdir(path, &handle) != 0)
+ return (0);
p = strchr(left_to_do, '/');
alwaysmatch = 0;
newpath = (char *)malloc(MAXPATHLEN);
if (newpath == NULL) {
+ finddev_close(handle);
return (-1);
}
match = (char *)calloc(MAXPATHLEN, 1);
if (match == NULL) {
+ finddev_close(handle);
free(newpath);
return (-1);
}
@@ -478,23 +465,12 @@ dir_dev_acc(char *path, char *left_to_do, uid_t uid, gid_t gid, mode_t mode,
if (regcomp(&regex, match, REG_EXTENDED) != 0) {
free(newpath);
free(match);
+ finddev_close(handle);
return (-1);
}
}
- for (;;) {
- if (find_method == FLAG_USE_READDIR) {
- if ((direntp = readdir(dirp)) == NULL)
- break;
- name = direntp->d_name;
- if ((strcmp(name, ".") == 0) ||
- (strcmp(name, "..") == 0))
- continue;
- } else {
- if ((name = (char *)finddev_next(handle)) == NULL)
- break;
- }
-
+ while ((name = (char *)finddev_next(handle)) != NULL) {
if (alwaysmatch ||
regexec(&regex, name, 0, NULL, 0) == 0) {
if (strcmp(path, "/") == 0) {
@@ -518,11 +494,7 @@ dir_dev_acc(char *path, char *left_to_do, uid_t uid, gid_t gid, mode_t mode,
}
}
- if (find_method == FLAG_USE_READDIR) {
- (void) closedir(dirp);
- } else {
- finddev_close(handle);
- }
+ finddev_close(handle);
free(newpath);
free(match);
if (!alwaysmatch) {
diff --git a/usr/src/lib/libdevinfo/devinfo_finddev.c b/usr/src/lib/libdevinfo/devinfo_finddev.c
index 1b89afb7b3..28ce5e3f1b 100644
--- a/usr/src/lib/libdevinfo/devinfo_finddev.c
+++ b/usr/src/lib/libdevinfo/devinfo_finddev.c
@@ -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.
*/
@@ -40,9 +40,10 @@
#include <errno.h>
#include <stdarg.h>
#include <libdevinfo.h>
+#include <zone.h>
#include <sys/modctl.h>
#include <syslog.h>
-
+#include <sys/stat.h>
#include <assert.h>
@@ -53,17 +54,125 @@ struct finddevhdl {
};
+/*
+ * Return true if a device exists
+ * If the path refers into the /dev filesystem, use a
+ * private interface to query if the device exists but
+ * without triggering an implicit reconfig if it does not.
+ * Note: can only function properly with absolute pathnames
+ * and only functions for persisted global /dev names, ie
+ * those managed by devfsadm. For paths other than
+ * /dev, stat(2) is sufficient.
+ */
int
device_exists(const char *devname)
{
int rv;
+ struct stat st;
- rv = modctl(MODDEVEXISTS, devname, strlen(devname));
- return ((rv == 0) ? 1 : 0);
+ if ((getzoneid() == GLOBAL_ZONEID) &&
+ ((strcmp(devname, "/dev") == 0) ||
+ (strncmp(devname, "/dev/", 5) == 0))) {
+ rv = modctl(MODDEVEXISTS, devname, strlen(devname));
+ return ((rv == 0) ? 1 : 0);
+ }
+ if (stat(devname, &st) == 0)
+ return (1);
+ return (0);
}
-int
-finddev_readdir(const char *dir, finddevhdl_t *handlep)
+
+/*
+ * Use the standard library readdir to read the contents of
+ * directories on alternate root mounted filesystems.
+ * Return results as per dev_readdir_devfs().
+ *
+ * The directory is traversed twice. First, to calculate
+ * the size of the buffer required; second, to copy the
+ * directory contents into the buffer. If the directory
+ * contents grow in between passes, which should almost
+ * never happen, start over again.
+ */
+static int
+finddev_readdir_alt(const char *path, finddevhdl_t *handlep)
+{
+ struct finddevhdl *handle;
+ DIR *dir;
+ struct dirent *dp;
+ size_t n;
+
+ *handlep = NULL;
+ if ((dir = opendir(path)) == NULL)
+ return (ENOENT);
+
+restart:
+ handle = calloc(1, sizeof (struct finddevhdl));
+ if (handle == NULL) {
+ (void) closedir(dir);
+ return (ENOMEM);
+ }
+
+ handle->npaths = 0;
+ handle->curpath = 0;
+ handle->paths = NULL;
+
+ n = 0;
+ rewinddir(dir);
+ while ((dp = readdir(dir)) != NULL) {
+ if ((strcmp(dp->d_name, ".") == 0) ||
+ (strcmp(dp->d_name, "..") == 0))
+ continue;
+ n++;
+ }
+
+ handle->npaths = n;
+ handle->paths = calloc(n, sizeof (char *));
+ if (handle->paths == NULL) {
+ free(handle);
+ (void) closedir(dir);
+ return (ENOMEM);
+ }
+
+ n = 0;
+ rewinddir(dir);
+ while ((dp = readdir(dir)) != NULL) {
+ if ((strcmp(dp->d_name, ".") == 0) ||
+ (strcmp(dp->d_name, "..") == 0))
+ continue;
+ if (n == handle->npaths) {
+ /*
+ * restart if directory contents have out-grown
+ * buffer allocated in the first pass.
+ */
+ finddev_close((finddevhdl_t)handle);
+ goto restart;
+ }
+ handle->paths[n] = strdup(dp->d_name);
+ if (handle->paths[n] == NULL) {
+ (void) closedir(dir);
+ finddev_close((finddevhdl_t)handle);
+ return (ENOMEM);
+ }
+ n++;
+ }
+ (void) closedir(dir);
+ *handlep = (finddevhdl_t)handle;
+ return (0);
+}
+
+/*
+ * Use of the dev filesystem's private readdir does not trigger
+ * the implicit device reconfiguration.
+ *
+ * Note: only useable with paths mounted on an instance of the
+ * dev filesystem.
+ *
+ * Does not return the . and .. entries.
+ * Empty directories are returned as an zero-length list.
+ * ENOENT is returned as a NULL list pointer.
+ */
+static int
+finddev_readdir_devfs(const char *path, finddevhdl_t *handlep)
{
struct finddevhdl *handle;
int n;
@@ -82,7 +191,7 @@ finddev_readdir(const char *dir, finddevhdl_t *handlep)
handle->curpath = 0;
handle->paths = NULL;
- rv = modctl(MODDEVREADDIR, dir, strlen(dir), NULL, &bufsiz);
+ rv = modctl(MODDEVREADDIR, path, strlen(path), NULL, &bufsiz);
if (rv != 0) {
free(handle);
return (rv);
@@ -95,7 +204,7 @@ finddev_readdir(const char *dir, finddevhdl_t *handlep)
return (ENOMEM);
}
- rv = modctl(MODDEVREADDIR, dir, strlen(dir),
+ rv = modctl(MODDEVREADDIR, path, strlen(path),
pathlist, &bufsiz);
if (rv == 0) {
for (n = 0, p = pathlist;
@@ -135,6 +244,17 @@ finddev_readdir(const char *dir, finddevhdl_t *handlep)
/*NOTREACHED*/
}
+int
+finddev_readdir(const char *path, finddevhdl_t *handlep)
+{
+ if ((getzoneid() == GLOBAL_ZONEID) &&
+ ((strcmp(path, "/dev") == 0) ||
+ (strncmp(path, "/dev/", 4) == 0))) {
+ return (finddev_readdir_devfs(path, handlep));
+ }
+ return (finddev_readdir_alt(path, handlep));
+}
+
void
finddev_close(finddevhdl_t arg)
{
diff --git a/usr/src/lib/libdevinfo/libdevinfo.h b/usr/src/lib/libdevinfo/libdevinfo.h
index 56c4b4982c..d570e8e714 100644
--- a/usr/src/lib/libdevinfo/libdevinfo.h
+++ b/usr/src/lib/libdevinfo/libdevinfo.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.
*/
@@ -413,10 +413,6 @@ extern int finddev_readdir(const char *, finddevhdl_t *);
extern void finddev_close(finddevhdl_t);
extern const char *finddev_next(finddevhdl_t);
-/* For interfaces implementing search either by readdir or finddev */
-#define FLAG_USE_READDIR 0
-#define FLAG_USE_FINDDEV 1
-
/*
* Private interfaces for non-global /dev profile