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
, NULL
) == -1)
145 exit((errno
== ENOENT
) ? 0 : 1);
148 wpid
= waitpid(pid
, &status
, 0);
149 if (wpid
== (pid_t
)-1) {
161 return ((WIFEXITED(status
) == 0) ? 1 : WEXITSTATUS(status
));
166 * _update_devalloc_db
167 * Forms allocatable device entries to be written to device_allocate and
170 * Or finds the correct entry to remove, and removes it.
172 * Note: devname is a /devices link in the REMOVE case.
176 _update_devalloc_db(devlist_t
*devlist
, int devflag
, int action
, char *devname
,
180 deventry_t
*entry
= NULL
, *dentry
= NULL
;
182 char *nickname
; /* typestring + instance */
184 if (action
== DA_ADD
) {
185 for (i
= 0; i
< DA_COUNT
; i
++) {
188 dentry
= devlist
->audio
;
191 dentry
= devlist
->cd
;
194 dentry
= devlist
->floppy
;
197 dentry
= devlist
->tape
;
200 dentry
= devlist
->rmdisk
;
206 (void) _update_dev(dentry
, action
, NULL
, NULL
,
209 } else if (action
== DA_REMOVE
) {
210 if (devflag
& DA_AUDIO
) {
211 dentry
= devlist
->audio
;
212 typestring
= DA_AUDIO_TYPE
;
213 } else if (devflag
& DA_CD
) {
214 dentry
= devlist
->cd
;
215 typestring
= DA_CD_TYPE
;
216 } else if (devflag
& DA_FLOPPY
) {
217 dentry
= devlist
->floppy
;
218 typestring
= DA_FLOPPY_TYPE
;
219 } else if (devflag
& DA_TAPE
) {
220 dentry
= devlist
->tape
;
221 typestring
= DA_TAPE_TYPE
;
222 } else if (devflag
& DA_RMDISK
) {
223 dentry
= devlist
->rmdisk
;
224 typestring
= DA_RMDISK_TYPE
;
229 nickname
= _update_dev(NULL
, action
, typestring
, NULL
,
232 if (nickname
!= NULL
) {
233 (void) da_rm_list_entry(devlist
, devname
,
240 * Not reached as of now, could be reached if devfsadm is
241 * enhanced to clean up devalloc database more thoroughly.
242 * Will not reliably match for event-driven removes
244 for (entry
= dentry
; entry
!= NULL
; entry
= entry
->next
) {
245 if (strcmp(entry
->devinfo
.devname
, devname
) == 0)
248 (void) _update_dev(entry
, action
, NULL
, devname
, NULL
);
253 * _update_dev: Update device_allocate and/or device_maps files
255 * If adding a device:
256 * dentry: A linked list of allocatable devices
257 * action: DA_ADD or DA_REMOVE
258 * devtype: type of device linked list to update on removal
259 * devname: short name (i.e. rmdisk5, cdrom0) of device if known
260 * rm_link: name of real /device from hot_cleanup
262 * If the action is ADD or if the action is triggered by an event
263 * from syseventd, read the files FIRST and treat their data as
264 * more-accurate than the dentry list, adjusting dentry contents if needed.
266 * For DA_ADD, try to add each device in the list to the files.
268 * If the action is DA_REMOVE and not a hotplug remove, adjust the files
269 * as indicated by the linked list.
272 * If we successfully remove a device from the files, returns
273 * a char * to strdup'd devname of the device removed.
275 * The caller is responsible for freeing the return value.
277 * NULL for all other cases, both success and failure.
281 _update_dev(deventry_t
*dentry
, int action
, const char *devtype
, char *devname
,
285 deventry_t newentry
, *entry
;
288 dargs
.rootdir
= NULL
;
289 dargs
.devnames
= NULL
;
292 dargs
.optflag
= DA_EVENT
;
296 if (action
== DA_ADD
) {
297 dargs
.optflag
|= DA_ADD
;
299 * Add Events do not have enough information to overrride the
300 * existing file contents.
303 for (entry
= dentry
; entry
!= NULL
; entry
= entry
->next
) {
304 dargs
.devinfo
= &(entry
->devinfo
);
305 (void) da_update_device(&dargs
);
307 } else if (action
== DA_REMOVE
) {
308 dargs
.optflag
|= DA_REMOVE
;
311 } else if (dargs
.optflag
& DA_EVENT
) {
313 newentry
.devinfo
.devname
= NULL
;
315 newentry
.devinfo
.devname
= strdup(devname
);
316 newentry
.devinfo
.devtype
= (char *)devtype
;
317 newentry
.devinfo
.devauths
=
318 newentry
.devinfo
.devopts
=
319 newentry
.devinfo
.devexec
= NULL
;
320 newentry
.devinfo
.devlist
= strdup(rm_link
);
321 newentry
.devinfo
.instance
= 0;
322 newentry
.next
= NULL
;
325 newentry
.devinfo
.devname
= strdup(devname
);
326 newentry
.devinfo
.devtype
= (char *)devtype
;
327 newentry
.devinfo
.devauths
=
328 newentry
.devinfo
.devexec
=
329 newentry
.devinfo
.devopts
=
330 newentry
.devinfo
.devlist
= NULL
;
331 newentry
.devinfo
.instance
= 0;
332 newentry
.next
= NULL
;
335 dargs
.devinfo
= &(entry
->devinfo
);
337 * da_update_device will fill in entry devname if
338 * event_driven is true and device is in the file
340 status
= da_update_device(&dargs
);
342 free(newentry
.devinfo
.devlist
);
344 return (dargs
.devinfo
->devname
);
345 else free(dargs
.devinfo
->devname
);