4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
28 * Device allocation related work.
38 #include <sys/types.h>
42 #include <bsm/devalloc.h>
44 #define DEALLOCATE "/usr/sbin/deallocate"
45 #define MKDEVALLOC "/usr/sbin/mkdevalloc"
47 static char *_update_dev(deventry_t
*, int, const char *, char *, char *);
48 static int _make_db();
49 extern int event_driven
;
54 * returns 1 if device pointed by 'link' is a removable hotplugged disk,
58 _da_check_for_usb(char *link
, char *root_dir
)
65 char path
[MAXPATHLEN
+ 4];
66 char rpath
[MAXPATHLEN
+ 4]; /* for ",raw" */
68 dstsize
= sizeof (path
);
69 if (strcmp(root_dir
, "") != 0) {
70 if (strlcat(path
, root_dir
, dstsize
) >= dstsize
)
76 (void) snprintf(path
, dstsize
- len
, "%s", link
);
77 if ((p
= realpath(path
, rpath
)) == NULL
) {
80 if (strstr(link
, "rdsk")) {
83 (void) snprintf(path
, dstsize
, "%s%s", rpath
, ",raw");
87 if ((fd
= open(p
, O_RDONLY
| O_NONBLOCK
)) < 0)
89 (void) ioctl(fd
, DKIOCREMOVABLE
, &removable
);
90 (void) ioctl(fd
, DKIOCHOTPLUGGABLE
, &hotpluggable
);
93 if (removable
&& hotpluggable
)
101 * If device allocation is being turned on, creates device_allocate
102 * device_maps if they do not exist.
103 * Puts DEVICE_ALLOCATION=ON/OFF in device_allocate to indicate if
104 * device allocation is on/off.
107 _reset_devalloc(int action
)
113 else if ((action
== DA_OFF
) && (open(DEVALLOC
, O_RDONLY
) == -1))
117 dargs
.optflag
= DA_ON
;
118 else if (action
== DA_OFF
)
119 dargs
.optflag
= DA_OFF
| DA_ALLOC_ONLY
;
121 dargs
.rootdir
= NULL
;
122 dargs
.devnames
= NULL
;
123 dargs
.devinfo
= NULL
;
125 (void) da_update_device(&dargs
);
130 * execs /usr/sbin/mkdevalloc to create device_allocate and
144 if (execl(MKDEVALLOC
, MKDEVALLOC
, DA_IS_LABELED
, NULL
) == -1)
145 exit((errno
== ENOENT
) ? 0 : 1);
149 wpid
= waitpid(pid
, &status
, 0);
150 if (wpid
== (pid_t
)-1) {
162 return ((WIFEXITED(status
) == 0) ? 1 : WEXITSTATUS(status
));
167 * _update_devalloc_db
168 * Forms allocatable device entries to be written to device_allocate and
171 * Or finds the correct entry to remove, and removes it.
173 * Note: devname is a /devices link in the REMOVE case.
177 _update_devalloc_db(devlist_t
*devlist
, int devflag
, int action
, char *devname
,
181 deventry_t
*entry
= NULL
, *dentry
= NULL
;
183 char *nickname
; /* typestring + instance */
185 if (action
== DA_ADD
) {
186 for (i
= 0; i
< DA_COUNT
; i
++) {
189 dentry
= devlist
->audio
;
192 dentry
= devlist
->cd
;
195 dentry
= devlist
->floppy
;
198 dentry
= devlist
->tape
;
201 dentry
= devlist
->rmdisk
;
207 (void) _update_dev(dentry
, action
, NULL
, NULL
,
210 } else if (action
== DA_REMOVE
) {
211 if (devflag
& DA_AUDIO
) {
212 dentry
= devlist
->audio
;
213 typestring
= DA_AUDIO_TYPE
;
214 } else if (devflag
& DA_CD
) {
215 dentry
= devlist
->cd
;
216 typestring
= DA_CD_TYPE
;
217 } else if (devflag
& DA_FLOPPY
) {
218 dentry
= devlist
->floppy
;
219 typestring
= DA_FLOPPY_TYPE
;
220 } else if (devflag
& DA_TAPE
) {
221 dentry
= devlist
->tape
;
222 typestring
= DA_TAPE_TYPE
;
223 } else if (devflag
& DA_RMDISK
) {
224 dentry
= devlist
->rmdisk
;
225 typestring
= DA_RMDISK_TYPE
;
230 nickname
= _update_dev(NULL
, action
, typestring
, NULL
,
233 if (nickname
!= NULL
) {
234 (void) da_rm_list_entry(devlist
, devname
,
241 * Not reached as of now, could be reached if devfsadm is
242 * enhanced to clean up devalloc database more thoroughly.
243 * Will not reliably match for event-driven removes
245 for (entry
= dentry
; entry
!= NULL
; entry
= entry
->next
) {
246 if (strcmp(entry
->devinfo
.devname
, devname
) == 0)
249 (void) _update_dev(entry
, action
, NULL
, devname
, NULL
);
254 * _update_dev: Update device_allocate and/or device_maps files
256 * If adding a device:
257 * dentry: A linked list of allocatable devices
258 * action: DA_ADD or DA_REMOVE
259 * devtype: type of device linked list to update on removal
260 * devname: short name (i.e. rmdisk5, cdrom0) of device if known
261 * rm_link: name of real /device from hot_cleanup
263 * If the action is ADD or if the action is triggered by an event
264 * from syseventd, read the files FIRST and treat their data as
265 * more-accurate than the dentry list, adjusting dentry contents if needed.
267 * For DA_ADD, try to add each device in the list to the files.
269 * If the action is DA_REMOVE and not a hotplug remove, adjust the files
270 * as indicated by the linked list.
273 * If we successfully remove a device from the files, returns
274 * a char * to strdup'd devname of the device removed.
276 * The caller is responsible for freeing the return value.
278 * NULL for all other cases, both success and failure.
282 _update_dev(deventry_t
*dentry
, int action
, const char *devtype
, char *devname
,
286 deventry_t newentry
, *entry
;
289 dargs
.rootdir
= NULL
;
290 dargs
.devnames
= NULL
;
293 dargs
.optflag
= DA_EVENT
;
297 if (action
== DA_ADD
) {
298 dargs
.optflag
|= DA_ADD
;
300 * Add Events do not have enough information to overrride the
301 * existing file contents.
304 for (entry
= dentry
; entry
!= NULL
; entry
= entry
->next
) {
305 dargs
.devinfo
= &(entry
->devinfo
);
306 (void) da_update_device(&dargs
);
308 } else if (action
== DA_REMOVE
) {
309 dargs
.optflag
|= DA_REMOVE
;
312 } else if (dargs
.optflag
& DA_EVENT
) {
314 newentry
.devinfo
.devname
= NULL
;
316 newentry
.devinfo
.devname
= strdup(devname
);
317 newentry
.devinfo
.devtype
= (char *)devtype
;
318 newentry
.devinfo
.devauths
=
319 newentry
.devinfo
.devopts
=
320 newentry
.devinfo
.devexec
= NULL
;
321 newentry
.devinfo
.devlist
= strdup(rm_link
);
322 newentry
.devinfo
.instance
= 0;
323 newentry
.next
= NULL
;
326 newentry
.devinfo
.devname
= strdup(devname
);
327 newentry
.devinfo
.devtype
= (char *)devtype
;
328 newentry
.devinfo
.devauths
=
329 newentry
.devinfo
.devexec
=
330 newentry
.devinfo
.devopts
=
331 newentry
.devinfo
.devlist
= NULL
;
332 newentry
.devinfo
.instance
= 0;
333 newentry
.next
= NULL
;
336 dargs
.devinfo
= &(entry
->devinfo
);
338 * da_update_device will fill in entry devname if
339 * event_driven is true and device is in the file
341 status
= da_update_device(&dargs
);
343 if (newentry
.devinfo
.devlist
!= NULL
)
344 free(newentry
.devinfo
.devlist
);
346 return (dargs
.devinfo
->devname
);
347 else free(dargs
.devinfo
->devname
);