summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/cmd/allocate/mkdevalloc.c13
-rw-r--r--usr/src/cmd/devfsadm/devalloc.c133
-rw-r--r--usr/src/cmd/devfsadm/devfsadm.c31
-rw-r--r--usr/src/lib/Makefile2
-rw-r--r--usr/src/lib/libbsm/Makefile.com6
-rw-r--r--usr/src/lib/libbsm/common/devalloc.c391
-rw-r--r--usr/src/lib/libbsm/common/devalloc.h9
-rw-r--r--usr/src/lib/libbsm/common/getdment.c75
-rw-r--r--usr/src/lib/libbsm/common/mapfile-vers3
-rw-r--r--usr/src/lib/libdevinfo/device_info.h8
-rw-r--r--usr/src/lib/libdevinfo/devinfo_devperm.c10
-rw-r--r--usr/src/lib/libdevinfo/mapfile-vers3
12 files changed, 594 insertions, 90 deletions
diff --git a/usr/src/cmd/allocate/mkdevalloc.c b/usr/src/cmd/allocate/mkdevalloc.c
index 750b1eeb9a..508f5961c4 100644
--- a/usr/src/cmd/allocate/mkdevalloc.c
+++ b/usr/src/cmd/allocate/mkdevalloc.c
@@ -20,12 +20,10 @@
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* scan /dev directory for mountable objects and construct device_allocate
* file for allocate....
@@ -94,7 +92,7 @@ struct tape {
#define DFLT_NTAPE 10 /* size of initial array */
#define SIZE_OF_RST 3 /* |rmt| */
#define SIZE_OF_NRST 4 /* |nrmt| */
-#define SIZE_OF_TMP 4 /* |/tmp| */
+#define SIZE_OF_TMP 4 /* |/tmp| */
#define SIZE_OF_RMT 8 /* |/dev/rmt| */
#define TAPE_CLEAN SECLIB"/st_clean"
@@ -909,7 +907,7 @@ docd()
continue;
/* get device # (disk #) */
- if (sscanf(dep->d_name, "c%dt%d", &ctrl, &id) <= 0)
+ if (sscanf(dep->d_name, "c%dt%d", &ctrl, &id) != 2)
continue;
/* see if this is one of the cd special devices */
@@ -1117,7 +1115,7 @@ dormdisk(int cd_count)
continue;
/* get device # (disk #) */
- if (sscanf(dep->d_name, "c%dt%d", &ctrl, &id) <= 0)
+ if (sscanf(dep->d_name, "c%dt%d", &ctrl, &id) != 2)
continue;
/* see if we've already examined this device */
@@ -1165,6 +1163,9 @@ dormdisk(int cd_count)
/* will exit(1) if insufficient memory */
nrmdisk = expandmem(i, (void **)&rmdisk,
sizeof (struct rmdisk));
+ /* When we expand rmdisk, need to expand rmdisk_r */
+ (void) expandmem(i, (void **)&rmdisk_r,
+ sizeof (struct rmdisk));
}
nm = (char *)malloc(SIZE_OF_DSK + 1 + strlen(dep->d_name) + 1);
if (nm == NULL)
diff --git a/usr/src/cmd/devfsadm/devalloc.c b/usr/src/cmd/devfsadm/devalloc.c
index 1f0f6a8e77..11147269cb 100644
--- a/usr/src/cmd/devfsadm/devalloc.c
+++ b/usr/src/cmd/devfsadm/devalloc.c
@@ -20,12 +20,10 @@
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* Device allocation related work.
*/
@@ -46,8 +44,9 @@
#define DEALLOCATE "/usr/sbin/deallocate"
#define MKDEVALLOC "/usr/sbin/mkdevalloc"
-static void _update_dev(deventry_t *, int, char *);
+static char *_update_dev(deventry_t *, int, const char *, char *, char *);
static int _make_db();
+extern int event_driven;
/*
@@ -167,6 +166,10 @@ _make_db()
* _update_devalloc_db
* Forms allocatable device entries to be written to device_allocate and
* device_maps.
+ *
+ * Or finds the correct entry to remove, and removes it.
+ *
+ * Note: devname is a /devices link in the REMOVE case.
*/
/* ARGSUSED */
void
@@ -175,6 +178,8 @@ _update_devalloc_db(devlist_t *devlist, int devflag, int action, char *devname,
{
int i;
deventry_t *entry = NULL, *dentry = NULL;
+ char *typestring;
+ char *nickname; /* typestring + instance */
if (action == DA_ADD) {
for (i = 0; i < DA_COUNT; i++) {
@@ -198,61 +203,147 @@ _update_devalloc_db(devlist_t *devlist, int devflag, int action, char *devname,
return;
}
if (dentry)
- _update_dev(dentry, action, NULL);
+ (void) _update_dev(dentry, action, NULL, NULL,
+ NULL);
}
} else if (action == DA_REMOVE) {
- if (devflag & DA_AUDIO)
+ if (devflag & DA_AUDIO) {
dentry = devlist->audio;
- else if (devflag & DA_CD)
+ typestring = DA_AUDIO_TYPE;
+ } else if (devflag & DA_CD) {
dentry = devlist->cd;
- else if (devflag & DA_FLOPPY)
+ typestring = DA_CD_TYPE;
+ } else if (devflag & DA_FLOPPY) {
dentry = devlist->floppy;
- else if (devflag & DA_TAPE)
+ typestring = DA_FLOPPY_TYPE;
+ } else if (devflag & DA_TAPE) {
dentry = devlist->tape;
- else if (devflag & DA_RMDISK)
+ typestring = DA_TAPE_TYPE;
+ } else if (devflag & DA_RMDISK) {
dentry = devlist->rmdisk;
- else
+ typestring = DA_RMDISK_TYPE;
+ } else
return;
+ if (event_driven) {
+ nickname = _update_dev(NULL, action, typestring, NULL,
+ devname);
+
+ if (nickname != NULL) {
+ (void) da_rm_list_entry(devlist, devname,
+ devflag, nickname);
+ free(nickname);
+ }
+ return;
+ }
+ /*
+ * Not reached as of now, could be reached if devfsadm is
+ * enhanced to clean up devalloc database more thoroughly.
+ * Will not reliably match for event-driven removes
+ */
for (entry = dentry; entry != NULL; entry = entry->next) {
if (strcmp(entry->devinfo.devname, devname) == 0)
break;
}
- _update_dev(entry, action, devname);
+ (void) _update_dev(entry, action, NULL, devname, NULL);
}
}
-static void
-_update_dev(deventry_t *dentry, int action, char *devname)
+/*
+ * _update_dev: Update device_allocate and/or device_maps files
+ *
+ * If adding a device:
+ * dentry: A linked list of allocatable devices
+ * action: DA_ADD or DA_REMOVE
+ * devtype: type of device linked list to update on removal
+ * devname: short name (i.e. rmdisk5, cdrom0) of device if known
+ * rm_link: name of real /device from hot_cleanup
+ *
+ * If the action is ADD or if the action is triggered by an event
+ * from syseventd, read the files FIRST and treat their data as
+ * more-accurate than the dentry list, adjusting dentry contents if needed.
+ *
+ * For DA_ADD, try to add each device in the list to the files.
+ *
+ * If the action is DA_REMOVE and not a hotplug remove, adjust the files
+ * as indicated by the linked list.
+ *
+ * RETURNS:
+ * If we successfully remove a device from the files, returns
+ * a char * to strdup'd devname of the device removed.
+ *
+ * The caller is responsible for freeing the return value.
+ *
+ * NULL for all other cases, both success and failure.
+ *
+ */
+static char *
+_update_dev(deventry_t *dentry, int action, const char *devtype, char *devname,
+ char *rm_link)
{
da_args dargs;
deventry_t newentry, *entry;
+ int status;
dargs.rootdir = NULL;
dargs.devnames = NULL;
+ if (event_driven)
+ dargs.optflag = DA_EVENT;
+ else
+ dargs.optflag = 0;
+
if (action == DA_ADD) {
- dargs.optflag = DA_ADD | DA_FORCE;
+ dargs.optflag |= DA_ADD;
+ /*
+ * Add Events do not have enough information to overrride the
+ * existing file contents.
+ */
+
for (entry = dentry; entry != NULL; entry = entry->next) {
dargs.devinfo = &(entry->devinfo);
(void) da_update_device(&dargs);
}
} else if (action == DA_REMOVE) {
- dargs.optflag = DA_REMOVE;
+ dargs.optflag |= DA_REMOVE;
if (dentry) {
entry = dentry;
+ } else if (dargs.optflag & DA_EVENT) {
+ if (devname == NULL)
+ newentry.devinfo.devname = NULL;
+ else
+ newentry.devinfo.devname = strdup(devname);
+ newentry.devinfo.devtype = (char *)devtype;
+ newentry.devinfo.devauths =
+ newentry.devinfo.devopts =
+ newentry.devinfo.devexec = NULL;
+ newentry.devinfo.devlist = strdup(rm_link);
+ newentry.devinfo.instance = 0;
+ newentry.next = NULL;
+ entry = &newentry;
} else {
newentry.devinfo.devname = strdup(devname);
- newentry.devinfo.devtype =
+ newentry.devinfo.devtype = (char *)devtype;
newentry.devinfo.devauths =
- newentry.devinfo.devexec =
- newentry.devinfo.devopts =
- newentry.devinfo.devlist = NULL;
+ newentry.devinfo.devexec =
+ newentry.devinfo.devopts =
+ newentry.devinfo.devlist = NULL;
newentry.devinfo.instance = 0;
newentry.next = NULL;
entry = &newentry;
}
dargs.devinfo = &(entry->devinfo);
- (void) da_update_device(&dargs);
+ /*
+ * da_update_device will fill in entry devname if
+ * event_driven is true and device is in the file
+ */
+ status = da_update_device(&dargs);
+ if (event_driven)
+ if (newentry.devinfo.devlist != NULL)
+ free(newentry.devinfo.devlist);
+ if (status == 0)
+ return (dargs.devinfo->devname);
+ else free(dargs.devinfo->devname);
}
+ return (NULL);
}
diff --git a/usr/src/cmd/devfsadm/devfsadm.c b/usr/src/cmd/devfsadm/devfsadm.c
index 11e25b3071..523924b3c4 100644
--- a/usr/src/cmd/devfsadm/devfsadm.c
+++ b/usr/src/cmd/devfsadm/devfsadm.c
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -96,6 +96,9 @@ static int update_all_drivers = FALSE;
/* set if invoked via /usr/lib/devfsadm/devfsadmd */
static int daemon_mode = FALSE;
+/* set if event_handler triggered */
+int event_driven = FALSE;
+
/* output directed to syslog during daemon mode if set */
static int logflag = FALSE;
@@ -1645,6 +1648,12 @@ event_handler(sysevent_t *ev)
int instance;
int branch_event = 0;
+ /*
+ * If this is event-driven, then we cannot trust the static devlist
+ * to be correct.
+ */
+
+ event_driven = TRUE;
subclass = sysevent_get_subclass_name(ev);
vprint(EVENT_MID, "event_handler: %s id:0X%llx\n",
subclass, sysevent_get_seq(ev));
@@ -4307,22 +4316,22 @@ hot_cleanup(char *node_path, char *minor_name, char *ev_subclass,
/* update device allocation database */
if (system_labeled) {
- int ret = 0;
int devtype = 0;
- char devname[MAXNAMELEN];
- devname[0] = '\0';
- if (strstr(node_path, DA_SOUND_NAME))
+ if (strstr(path, DA_SOUND_NAME))
devtype = DA_AUDIO;
- else if (strstr(node_path, "disk"))
+ else if (strstr(path, "storage"))
+ devtype = DA_RMDISK;
+ else if (strstr(path, "disk"))
+ devtype = DA_RMDISK;
+ else if (strstr(path, "floppy"))
+ /* TODO: detect usb cds and floppies at insert time */
devtype = DA_RMDISK;
else
goto out;
- ret = da_remove_list(&devlist, NULL, devtype, devname,
- sizeof (devname));
- if (ret != -1)
- (void) _update_devalloc_db(&devlist, devtype, DA_REMOVE,
- devname, root_dir);
+
+ (void) _update_devalloc_db(&devlist, devtype, DA_REMOVE,
+ node_path, root_dir);
}
out:
diff --git a/usr/src/lib/Makefile b/usr/src/lib/Makefile
index 033931fb88..a4e59dbd14 100644
--- a/usr/src/lib/Makefile
+++ b/usr/src/lib/Makefile
@@ -568,7 +568,7 @@ $(CLOSED_BUILD)libc: $(CLOSED)/lib/libc_i18n
libast: libsocket
libadutils: libldap5 libresolv libsocket libnsl
nsswitch: libadutils libidmap
-libbsm: libtsol
+libbsm: libtsol libdevinfo
libcmd: libsum libast libsocket libnsl
libcmdutils: libavl
libcontract: libnvpair
diff --git a/usr/src/lib/libbsm/Makefile.com b/usr/src/lib/libbsm/Makefile.com
index 367586ba90..2858c32102 100644
--- a/usr/src/lib/libbsm/Makefile.com
+++ b/usr/src/lib/libbsm/Makefile.com
@@ -19,11 +19,9 @@
# CDDL HEADER END
#
#
-# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2010 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-# ident "%Z%%M% %I% %E% SMI"
-#
LIBRARY = libbsm.a
VERS = .1
@@ -88,7 +86,7 @@ ROOTLINT= $(LINTSRC:%=$(ROOTLINTDIR)/%)
CLEANFILES += $(LINTOUT) $(LINTLIB)
CFLAGS += $(CCVERBOSE)
-LDLIBS += -lsocket -lnsl -lmd -lc -lsecdb -ltsol -linetutil
+LDLIBS += -lsocket -lnsl -lmd -lc -ldevinfo -lsecdb -ltsol -linetutil
COMDIR= ../common
diff --git a/usr/src/lib/libbsm/common/devalloc.c b/usr/src/lib/libbsm/common/devalloc.c
index e39b57fa23..cdeaf322f3 100644
--- a/usr/src/lib/libbsm/common/devalloc.c
+++ b/usr/src/lib/libbsm/common/devalloc.c
@@ -20,12 +20,10 @@
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <stdlib.h>
#include <ctype.h>
#include <unistd.h>
@@ -40,6 +38,7 @@
#include <libintl.h>
#include <errno.h>
#include <auth_list.h>
+#include <syslog.h>
#include <bsm/devices.h>
#include <bsm/devalloc.h>
@@ -53,6 +52,10 @@ extern int da_matchname(devalloc_t *, char *);
extern int da_match(devalloc_t *, da_args *);
extern int dmap_matchname(devmap_t *, char *);
extern int dm_match(devmap_t *, da_args *);
+extern int dmap_matchtype(devmap_t *dmap, char *type);
+extern int dmap_matchdev(devmap_t *dmap, char *dev);
+extern int dmap_exact_dev(devmap_t *dmap, char *dev, int *num);
+extern char *dmap_physname(devmap_t *dmap);
/*
* The following structure is for recording old entries to be retained.
@@ -332,7 +335,7 @@ _update_zonename(da_args *dargs, devalloc_t *dap)
*/
/*ARGSUSED*/
static int
-_dmap2str(da_args *dargs, devmap_t *dmp, char *buf, int size, const char *sep)
+_dmap2str(devmap_t *dmp, char *buf, int size, const char *sep)
{
int length;
@@ -356,13 +359,13 @@ _dmap2str(da_args *dargs, devmap_t *dmp, char *buf, int size, const char *sep)
* returns pointer to decoded entry, NULL on error.
*/
static strentry_t *
-_dmap2strentry(da_args *dargs, devmap_t *devmapp)
+_dmap2strentry(devmap_t *devmapp)
{
strentry_t *sep;
if ((sep = (strentry_t *)malloc(sizeof (strentry_t))) == NULL)
return (NULL);
- if (_dmap2str(dargs, devmapp, sep->se_str, sizeof (sep->se_str),
+ if (_dmap2str(devmapp, sep->se_str, sizeof (sep->se_str),
KV_TOKEN_DELIMIT"\\\n\t") != 0) {
free(sep);
return (NULL);
@@ -562,8 +565,216 @@ _build_defattrs(da_args *dargs, strentry_t **head_defent)
}
/*
+ * _rebuild_lists -
+ *
+ * If dargs->optflag & DA_EVENT, does not assume the dargs list is
+ * complete or completely believable, since devfsadm caches
+ * ONLY what it has been exposed to via syseventd.
+ *
+ * Cycles through all the entries in the /etc files, stores them
+ * in memory, takes note of device->dname numbers (i.e. rmdisk0,
+ * rmdisk12)
+ *
+ * Cycles through again, adds dargs entry
+ * with the name tname%d (lowest unused number for the device type)
+ * to the list of things for the caller to write out to a file,
+ * IFF it is a new entry.
+ *
+ * It is an error for it to already be there.
+ *
+ * Add:
+ * Returns 0 if successful and 2 on error.
+ * Remove:
+ * Returns 0 if not found, 1 if found, 2 on error.
+ */
+static int
+_rebuild_lists(da_args *dargs, strentry_t **head_devallocp,
+ strentry_t **head_devmapp)
+{
+ int rc = 0;
+ devalloc_t *devallocp;
+ devmap_t *devmapp;
+ strentry_t *tail_str;
+ strentry_t *tmp_str;
+ uint64_t tmp_bitmap = 0;
+ int tmp = 0;
+ char new_devname[DA_MAXNAME + 1];
+ char errmsg[DA_MAXNAME + 1 + (PATH_MAX * 2) + 80];
+ char *realname;
+ int suffix = DA_MAX_DEVNO + 1;
+ int found = 0;
+
+ if (dargs->optflag & (DA_MAPS_ONLY | DA_ALLOC_ONLY))
+ return (2);
+
+ if (dargs->optflag & DA_FORCE)
+ return (2);
+
+ /* read both files, maps first so we can compare actual devices */
+
+ /* build device_maps */
+ setdmapent();
+ while ((devmapp = getdmapent()) != NULL) {
+ if ((rc = dmap_matchtype(devmapp, dargs->devinfo->devtype))
+ == 1) {
+ if (dargs->optflag & DA_REMOVE) {
+ if ((devmapp->dmap_devarray == NULL) ||
+ (devmapp->dmap_devarray[0] == NULL)) {
+ freedmapent(devmapp);
+ enddmapent();
+ return (2);
+ }
+ realname = dmap_physname(devmapp);
+ if (realname == NULL) {
+ freedmapent(devmapp);
+ enddmapent();
+ return (2);
+ }
+ if (strstr(realname, dargs->devinfo->devlist)
+ != NULL) {
+ if (dargs->devinfo->devname != NULL)
+ free(dargs->devinfo->devname);
+ dargs->devinfo->devname =
+ strdup(devmapp->dmap_devname);
+ found = 1;
+ freedmapent(devmapp);
+ continue; /* don't retain */
+ }
+ } else if (dargs->optflag & DA_ADD) {
+ /*
+ * Need to know which suffixes are in use
+ */
+ rc = (dmap_exact_dev(devmapp,
+ dargs->devinfo->devlist, &suffix));
+
+ if (rc == 0) {
+ /*
+ * Same type, different device. Record
+ * device suffix already in use.
+ */
+ if (suffix > DA_MAX_DEVNO) {
+ freedmapent(devmapp);
+ enddmapent();
+ return (2);
+ }
+ tmp_bitmap |= (uint64_t)(1LL << suffix);
+ } else {
+ /*
+ * Match on add is an error
+ * or mapping attempt returned error
+ */
+ freedmapent(devmapp);
+ enddmapent();
+ return (2);
+ }
+ } else
+ /* add other transaction types as needed */
+ return (2);
+
+ } /* if same type */
+
+ tmp_str = _dmap2strentry(devmapp);
+ if (tmp_str == NULL) {
+ freedmapent(devmapp);
+ enddmapent();
+ return (2);
+ }
+ /* retaining devmap entry: tmp_str->se_str */
+ tmp_str->se_next = NULL;
+ if (*head_devmapp == NULL) {
+ *head_devmapp = tail_str = tmp_str;
+ } else {
+ tail_str->se_next = tmp_str;
+ tail_str = tmp_str;
+ }
+ freedmapent(devmapp);
+ }
+ enddmapent();
+
+ /*
+ * No need to rewrite the files if the item to be removed is not
+ * in the files -- wait for another call on another darg.
+ */
+ if ((dargs->optflag & DA_REMOVE) && !found)
+ return (0);
+
+
+ if (dargs->optflag & DA_ADD) {
+ /*
+ * Since we got here from an event, we know the stored
+ * devname is a useless guess, since the files had not
+ * been read when the name was chosen, and we don't keep
+ * them anywhere else that is sufficiently definitive.
+ */
+
+ for (tmp = 0; tmp <= DA_MAX_DEVNO; tmp++)
+ if (!(tmp_bitmap & (1LL << tmp)))
+ break;
+ /* Future: support more than 64 hotplug devices per type? */
+ if (tmp > DA_MAX_DEVNO)
+ return (2);
+
+ (void) snprintf(new_devname, DA_MAXNAME + 1, "%s%u",
+ dargs->devinfo->devtype, tmp);
+ if (dargs->devinfo->devname != NULL)
+ free(dargs->devinfo->devname);
+ dargs->devinfo->devname = strdup(new_devname);
+ }
+
+ /*
+ * Now adjust devalloc list to match devmaps
+ * Note we now have the correct devname for da_match to use.
+ */
+ setdaent();
+ while ((devallocp = getdaent()) != NULL) {
+ rc = da_match(devallocp, dargs);
+ if (rc == 1) {
+ if (dargs->optflag & DA_ADD) {
+ /* logging is on if DA_EVENT is set */
+ if (dargs->optflag & DA_EVENT) {
+ (void) snprintf(errmsg, sizeof (errmsg),
+ "%s and %s out of sync,"
+ "%s only in %s.",
+ DEVALLOC, DEVMAP,
+ devallocp->da_devname, DEVALLOC);
+ syslog(LOG_ERR, "%s", errmsg);
+ }
+ freedaent(devallocp);
+ enddaent();
+ return (2);
+ } else if (dargs->optflag & DA_REMOVE) {
+ /* make list w/o this entry */
+ freedaent(devallocp);
+ continue;
+ }
+ }
+ tmp_str = _da2strentry(dargs, devallocp);
+ if (tmp_str == NULL) {
+ freedaent(devallocp);
+ enddaent();
+ return (2);
+ }
+ /* retaining devalloc entry: tmp_str->se_str */
+ tmp_str->se_next = NULL;
+ if (*head_devallocp == NULL) {
+ *head_devallocp = tail_str = tmp_str;
+ } else {
+ tail_str->se_next = tmp_str;
+ tail_str = tmp_str;
+ }
+ freedaent(devallocp);
+ }
+ enddaent();
+
+ /* the caller needs to know if a remove needs to rewrite files */
+ if (dargs->optflag & DA_REMOVE)
+ return (1); /* 0 and 2 cases returned earlier */
+
+ return (0); /* Successful DA_ADD */
+}
+/*
* _build_lists -
- * cycles through all the entries, stores them in memory. removes entries
+ * Cycles through all the entries, stores them in memory. removes entries
* with the given search_key (device name or type).
* returns 0 if given entry not found, 1 if given entry removed, 2 on
* error.
@@ -633,7 +844,7 @@ dmap_only:
rc = 0;
}
if (rc == 0) {
- tmp_str = _dmap2strentry(dargs, devmapp);
+ tmp_str = _dmap2strentry(devmapp);
if (tmp_str == NULL) {
freedmapent(devmapp);
enddmapent();
@@ -675,12 +886,13 @@ _write_defattrs(FILE *fp, strentry_t *head_defent)
/*
* _write_device_allocate -
* writes current entries in the list to device_allocate.
+ * frees the strings
*/
static void
_write_device_allocate(char *odevalloc, FILE *dafp, strentry_t *head_devallocp)
{
int is_on = -1;
- strentry_t *tmp_str;
+ strentry_t *tmp_str, *old_str;
struct stat dastat;
(void) fseek(dafp, (off_t)0, SEEK_SET);
@@ -702,18 +914,21 @@ _write_device_allocate(char *odevalloc, FILE *dafp, strentry_t *head_devallocp)
while (tmp_str) {
(void) fputs(tmp_str->se_str, dafp);
(void) fputs("\n", dafp);
+ old_str = tmp_str;
tmp_str = tmp_str->se_next;
+ free(old_str);
}
}
/*
* _write_device_maps -
* writes current entries in the list to device_maps.
+ * and frees the strings
*/
static void
_write_device_maps(FILE *dmfp, strentry_t *head_devmapp)
{
- strentry_t *tmp_str;
+ strentry_t *tmp_str, *old_str;
(void) fseek(dmfp, (off_t)0, SEEK_SET);
@@ -721,7 +936,9 @@ _write_device_maps(FILE *dmfp, strentry_t *head_devmapp)
while (tmp_str) {
(void) fputs(tmp_str->se_str, dmfp);
(void) fputs("\n", dmfp);
+ old_str = tmp_str;
tmp_str = tmp_str->se_next;
+ free(old_str);
}
}
@@ -744,7 +961,7 @@ _write_new_defattrs(FILE *fp, da_args *dargs)
return (0);
(void) fprintf(fp, "%s%s", (devinfo->devtype ? devinfo->devtype : ""),
KV_TOKEN_DELIMIT);
- if ((tokp = (char *)malloc(strlen(devinfo->devopts))) != NULL) {
+ if ((tokp = (char *)malloc(strlen(devinfo->devopts) +1)) != NULL) {
(void) strcpy(tokp, devinfo->devopts);
if ((tok = strtok_r(tokp, KV_DELIMITER, &lasts)) != NULL) {
(void) fprintf(fp, "%s", tok);
@@ -791,7 +1008,8 @@ _write_new_entry(FILE *fp, da_args *dargs, int flag)
(void) fprintf(fp, "%s%s\\\n\t", DA_RESERVED,
KV_DELIMITER);
} else {
- if ((tokp = (char *)malloc(strlen(devinfo->devopts))) != NULL) {
+ if ((tokp = (char *)malloc(strlen(devinfo->devopts) + 1))
+ != NULL) {
(void) strcpy(tokp, devinfo->devopts);
if ((tok = strtok_r(tokp, KV_TOKEN_DELIMIT, &lasts)) !=
NULL) {
@@ -1058,7 +1276,7 @@ _record_on_off(da_args *dargs, FILE *tafp, FILE *dafp)
str_found = 0;
nsize = dastat.st_size + actionlen + 1;
}
- if ((nbuf = (char *)malloc(nsize)) == NULL)
+ if ((nbuf = (char *)malloc(nsize + 1)) == NULL)
return (-1);
nbuf[0] = '\0';
/* put the on/off string */
@@ -1168,8 +1386,9 @@ da_update_defattrs(da_args *dargs)
/*
* da_update_device -
- * writes devices entries to device_allocate and device_maps.
- * returns 0 on success, -1 on error.
+ * Writes existing entries and the SINGLE change requested by da_args,
+ * to device_allocate and device_maps.
+ * Returns 0 on success, -1 on error.
*/
int
da_update_device(da_args *dargs)
@@ -1288,25 +1507,58 @@ da_update_device(da_args *dargs)
}
/*
- * examine all the entries, remove an old one if forced to,
- * and check that they are suitable for updating.
- * we need to do this only if the file exists already.
+ * If reacting to a hotplug, read the file entries,
+ * figure out what dname (tname + a new number) goes to the
+ * device being added/removed, and create a good head_devallocp and
+ * head_devmapp with everything good still in it (_rebuild_lists)
+ *
+ * Else examine all the entries, remove an old one if it is
+ * a duplicate with a device being added, returning the
+ * remaining list (_build_lists.)
+ *
+ * We need to do this only if the file exists already.
+ *
+ * Once we have built these lists, we need to free the strings
+ * in the head_* arrays before returning.
*/
if (stat(dapathp, &dastat) == 0) {
- if ((rc = _build_lists(dargs, &head_devallocp,
- &head_devmapp)) != 0) {
- if (rc != 1) {
- (void) close(tafd);
- (void) unlink(apathp);
- (void) close(lockfd);
- return (rc);
- }
+ /* for device allocation, the /etc files are the "master" */
+ if ((dargs->optflag & (DA_ADD| DA_EVENT)) &&
+ (!(dargs->optflag & DA_FORCE)))
+ rc = _rebuild_lists(dargs, &head_devallocp,
+ &head_devmapp);
+ else
+ rc = _build_lists(dargs, &head_devallocp,
+ &head_devmapp);
+
+ if (rc != 0 && rc != 1) {
+ (void) close(tafd);
+ (void) unlink(apathp);
+ (void) close(lockfd);
+ return (-1);
}
+ } else
+ rc = 0;
+
+ if ((dargs->optflag & DA_REMOVE) && (rc == 0)) {
+ (void) close(tafd);
+ (void) unlink(apathp);
+ (void) close(lockfd);
+ return (0);
}
+ /*
+ * TODO: clean up the workings of DA_UPDATE.
+ * Due to da_match looking at fields that are missing
+ * in dargs for DA_UPDATE, the da_match call returns no match,
+ * but due to the way _da2str combines the devalloc_t info with
+ * the *dargs info, the DA_ADD_ZONE and DA_REMOVE_ZONE work.
+ *
+ * This would not scale if any type of update was ever needed
+ * from the daemon.
+ */
/*
- * write back any existing devalloc entries, along with
- * the devalloc on/off string.
+ * Write out devallocp along with the devalloc on/off string.
*/
_write_device_allocate(dapathp, tafp, head_devallocp);
@@ -1330,11 +1582,16 @@ dmap_only:
return (-1);
}
- /* write back any existing devmap entries */
+ /*
+ * Write back any non-removed pre-existing entries.
+ */
if (head_devmapp != NULL)
_write_device_maps(tmfp, head_devmapp);
out:
+ /*
+ * Add any new entries here.
+ */
if (dargs->optflag & DA_ADD && !(dargs->optflag & DA_NO_OVERRIDE)) {
/* add any new entries */
rc = _write_new_entry(tafp, dargs, DA_ALLOC_ONLY);
@@ -1382,7 +1639,7 @@ da_add_list(devlist_t *dlist, char *link, int new_instance, int flag)
int new_entry = 0;
char *dtype, *dexec, *tname, *kval;
char *minstr = NULL, *maxstr = NULL;
- char dname[DA_MAXNAME];
+ char dname[DA_MAXNAME + 1];
kva_t *kva;
deventry_t *dentry = NULL, *nentry = NULL, *pentry = NULL;
da_defs_t *da_defs;
@@ -1500,9 +1757,7 @@ da_add_list(devlist_t *dlist, char *link, int new_instance, int flag)
if ((nentry->devinfo.devlist =
(char *)realloc(nentry->devinfo.devlist, nlen)) == NULL) {
if (new_entry) {
- nentry->devinfo.devname = NULL;
free(nentry->devinfo.devname);
- nentry = NULL;
free(nentry);
if (pentry != NULL)
pentry->next = NULL;
@@ -1693,6 +1948,78 @@ remove_dev:
}
/*
+ * da_rm_list_entry -
+ *
+ * The adding of devnames to a devlist and the removal of a
+ * device are not symmetrical -- hot_cleanup gives a /devices
+ * name which is used to remove the dentry whose links all point to
+ * that /devices entry.
+ *
+ * The link argument is present if available to make debugging
+ * easier.
+ *
+ * da_rm_list_entry removes an entry from the linked list of devices.
+ *
+ * Returns 1 if the devname was removed successfully,
+ * 0 if not found, -1 for error.
+ */
+/*ARGSUSED*/
+int
+da_rm_list_entry(devlist_t *dlist, char *link, int type, char *devname)
+{
+ int retval = 0;
+ deventry_t **dentry, *current, *prev;
+
+ switch (type) {
+ case DA_AUDIO:
+ dentry = &(dlist->audio);
+ break;
+ case DA_CD:
+ dentry = &(dlist->cd);
+ break;
+ case DA_FLOPPY:
+ dentry = &(dlist->floppy);
+ break;
+ case DA_TAPE:
+ dentry = &(dlist->tape);
+ break;
+ case DA_RMDISK:
+ dentry = &(dlist->rmdisk);
+ break;
+ default:
+ return (-1);
+ }
+
+ /* Presumably in daemon mode, no need to remove entry, list is empty */
+ if (*dentry == (deventry_t *)NULL)
+ return (0);
+
+ prev = NULL;
+ for (current = *dentry; current != NULL;
+ prev = current, current = current->next) {
+ if (strcmp(devname, current->devinfo.devname))
+ continue;
+ retval = 1;
+ break;
+ }
+ if (retval == 0)
+ return (0);
+ free(current->devinfo.devname);
+ if (current->devinfo.devlist != NULL)
+ free(current->devinfo.devlist);
+ if (current->devinfo.devopts != NULL)
+ free(current->devinfo.devopts);
+
+ if (prev == NULL)
+ *dentry = current->next;
+ else
+ prev->next = current->next;
+
+ free(current);
+ return (retval);
+}
+
+/*
* da_is_on -
* checks if device allocation feature is turned on.
* returns 1 if on, 0 if off, -1 if status string not
diff --git a/usr/src/lib/libbsm/common/devalloc.h b/usr/src/lib/libbsm/common/devalloc.h
index 6755f94001..303be1aa45 100644
--- a/usr/src/lib/libbsm/common/devalloc.h
+++ b/usr/src/lib/libbsm/common/devalloc.h
@@ -20,15 +20,13 @@
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#ifndef _DEVALLOC_H
#define _DEVALLOC_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#ifdef __cplusplus
extern "C" {
#endif
@@ -45,7 +43,7 @@ extern "C" {
#define DA_UID (uid_t)0 /* root */
#define DA_GID (gid_t)3 /* sys */
#define ALLOC_MODE 0600
-#define DEALLOC_MODE 0000
+#define DEALLOC_MODE 0000
#define LOGINDEVPERM "/etc/logindevperm"
#define DA_DB_LOCK "/etc/security/.da_db_lock"
@@ -73,6 +71,7 @@ extern "C" {
#define DA_AUTHLEN MAX_CANON /* approx. sum of strlen of all */
/* device auths in auth_list.h */
#define DA_MAXNAME 80
+#define DA_MAX_DEVNO ((8 * sizeof (uint64_t)) - 1)
#define DA_BUFSIZE 4096
#define DA_RDWR O_RDWR|O_CREAT|O_NONBLOCK
@@ -95,6 +94,7 @@ extern "C" {
#define DA_OFF 0x00000800
#define DA_NO_OVERRIDE 0x00001000
#define DA_DEFATTRS 0x00002000
+#define DA_EVENT 0x00004000
#define DA_AUDIO 0x00001000
#define DA_CD 0x00002000
@@ -171,6 +171,7 @@ int da_update_device(da_args *);
int da_update_defattrs(da_args *);
int da_add_list(devlist_t *, char *, int, int);
int da_remove_list(devlist_t *, char *, int, char *, int);
+int da_rm_list_entry(devlist_t *, char *, int, char *);
void da_print_device(int, devlist_t *);
diff --git a/usr/src/lib/libbsm/common/getdment.c b/usr/src/lib/libbsm/common/getdment.c
index 0bf82e86e3..33256cbf39 100644
--- a/usr/src/lib/libbsm/common/getdment.c
+++ b/usr/src/lib/libbsm/common/getdment.c
@@ -19,14 +19,16 @@
* CDDL HEADER END
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <string.h>
+#include <strings.h>
#include <stdlib.h>
+#include <unistd.h>
+#include <limits.h>
+#include <device_info.h>
#include <bsm/devices.h>
#include <bsm/devalloc.h>
@@ -281,6 +283,31 @@ getdmaptype(char *type)
}
/*
+ * dmap_match_one_dev -
+ * Checks if the specified devmap_t contains strings
+ * for the same logical link as the device specified.
+ * This guarantees that the beginnings of a devlist build
+ * match a more-complete devlist for the same device.
+ *
+ * Returns 1 for a match, else returns 0.
+ */
+static int
+dmap_match_one_dev(devmap_t *dmap, char *dev)
+{
+ char **dva;
+ char *dv;
+
+ if (dmap->dmap_devarray == NULL)
+ return (0);
+
+ for (dva = dmap->dmap_devarray; (dv = *dva) != NULL; dva++) {
+ if (strstr(dev, dv) != NULL)
+ return (1);
+ }
+ return (0);
+}
+
+/*
* dmap_matchdev -
* checks if the specified devmap_t is for the device specified.
* returns 1 if it is, else returns 0.
@@ -302,6 +329,25 @@ dmap_matchdev(devmap_t *dmap, char *dev)
}
/*
+ * Requires a match of the /dev/?dsk links, not just the logical devname
+ * Returns 1 for match found, 0 for match not found, 2 for invalid arguments.
+ */
+int
+dmap_exact_dev(devmap_t *dmap, char *dev, int *num)
+{
+ char *dv;
+
+ if ((dev == NULL) || (dmap->dmap_devname == NULL))
+ return (2);
+ dv = dmap->dmap_devname;
+ dv += strcspn(dmap->dmap_devname, "0123456789");
+ if (sscanf(dv, "%d", num) != 1)
+ return (2);
+ /* during some add processes, dev can be shorter than dmap */
+ return (dmap_match_one_dev(dmap, dev));
+}
+
+/*
* dmap_matchtype -
* checks if the specified devmap_t is for the device specified.
* returns 1 if it is, else returns 0.
@@ -330,6 +376,29 @@ dmap_matchname(devmap_t *dmap, char *name)
}
/*
+ * dmap_physname: path to /devices device
+ * Returns:
+ * strdup'd (i.e. malloc'd) real device file if successful
+ * NULL on error
+ */
+char *
+dmap_physname(devmap_t *dmap)
+{
+ char *oldlink;
+ char stage_link[PATH_MAX + 1];
+
+ if ((dmap == NULL) || (dmap->dmap_devarray == NULL) ||
+ (dmap->dmap_devarray[0] == NULL))
+ return (NULL);
+
+ (void) strncpy(stage_link, dmap->dmap_devarray[0], sizeof (stage_link));
+
+ if (devfs_resolve_link(stage_link, &oldlink) == 0)
+ return (oldlink);
+ return (NULL);
+}
+
+/*
* dm_match -
* calls dmap_matchname or dmap_matchtype as appropriate.
*/
diff --git a/usr/src/lib/libbsm/common/mapfile-vers b/usr/src/lib/libbsm/common/mapfile-vers
index 7007eff427..41922451a7 100644
--- a/usr/src/lib/libbsm/common/mapfile-vers
+++ b/usr/src/lib/libbsm/common/mapfile-vers
@@ -19,7 +19,7 @@
# CDDL HEADER END
#
#
-# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2010 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
@@ -297,6 +297,7 @@ SUNWprivate_1.1 {
da_open_devdb;
da_print_device;
da_remove_list;
+ da_rm_list_entry;
da_update_defattrs;
da_update_device;
_endac;
diff --git a/usr/src/lib/libdevinfo/device_info.h b/usr/src/lib/libdevinfo/device_info.h
index 32e65ac8d8..62087d1ba3 100644
--- a/usr/src/lib/libdevinfo/device_info.h
+++ b/usr/src/lib/libdevinfo/device_info.h
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -129,6 +129,12 @@ extern int devfs_get_all_prom_names(const char *, uint_t,
extern void devfs_free_all_prom_names(struct devfs_prom_path *);
/*
+ * Interpret a /dev link to its /devices path (does not require path to
+ * still exist, as long as the links exist)
+ */
+extern int devfs_resolve_link(char *, char **);
+
+/*
* map a device name from install OS environment to target OS environment or
* vice-versa.
*/
diff --git a/usr/src/lib/libdevinfo/devinfo_devperm.c b/usr/src/lib/libdevinfo/devinfo_devperm.c
index e2716af8d3..d802783def 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 2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -269,8 +269,8 @@ logindevperm(const char *ttyn, uid_t uid, gid_t gid, void (*errmsg)(char *))
* devpath: Absolute path to /dev link
* devfs_path: Returns malloced string: /devices path w/out "/devices"
*/
-static int
-resolve_link(char *devpath, char **devfs_path)
+int
+devfs_resolve_link(char *devpath, char **devfs_path)
{
char contents[PATH_MAX + 1];
char stage_link[PATH_MAX + 1];
@@ -313,7 +313,7 @@ resolve_link(char *devpath, char **devfs_path)
(void) strcat(stage_link, contents);
}
- return (resolve_link(stage_link, devfs_path));
+ return (devfs_resolve_link(stage_link, devfs_path));
}
if (devfs_path) {
@@ -339,7 +339,7 @@ check_driver_match(char *path, char *line)
char saveline[MAX_LINELEN];
char *p;
- if (resolve_link(path, &devfs_path) == 0) {
+ if (devfs_resolve_link(path, &devfs_path) == 0) {
char *p;
char pwd_buf[PATH_MAX];
di_node_t node;
diff --git a/usr/src/lib/libdevinfo/mapfile-vers b/usr/src/lib/libdevinfo/mapfile-vers
index bf0c6caf21..bfad2642f2 100644
--- a/usr/src/lib/libdevinfo/mapfile-vers
+++ b/usr/src/lib/libdevinfo/mapfile-vers
@@ -19,7 +19,7 @@
# CDDL HEADER END
#
#
-# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2010 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
@@ -152,6 +152,7 @@ SUNW_1.1 {
SUNWprivate_1.1 {
global:
devfs_add_minor_perm;
+ devfs_resolve_link;
devfs_bootdev_free_list;
devfs_bootdev_get_list;
devfs_bootdev_modifiable;