1*1676Sjpk /*
2*1676Sjpk  * CDDL HEADER START
3*1676Sjpk  *
4*1676Sjpk  * The contents of this file are subject to the terms of the
5*1676Sjpk  * Common Development and Distribution License (the "License").
6*1676Sjpk  * You may not use this file except in compliance with the License.
7*1676Sjpk  *
8*1676Sjpk  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*1676Sjpk  * or http://www.opensolaris.org/os/licensing.
10*1676Sjpk  * See the License for the specific language governing permissions
11*1676Sjpk  * and limitations under the License.
12*1676Sjpk  *
13*1676Sjpk  * When distributing Covered Code, include this CDDL HEADER in each
14*1676Sjpk  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*1676Sjpk  * If applicable, add the following below this CDDL HEADER, with the
16*1676Sjpk  * fields enclosed by brackets "[]" replaced with your own identifying
17*1676Sjpk  * information: Portions Copyright [yyyy] [name of copyright owner]
18*1676Sjpk  *
19*1676Sjpk  * CDDL HEADER END
20*1676Sjpk  */
21*1676Sjpk 
22*1676Sjpk /*
23*1676Sjpk  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
24*1676Sjpk  * Use is subject to license terms.
25*1676Sjpk  */
26*1676Sjpk 
27*1676Sjpk #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*1676Sjpk 
29*1676Sjpk /*
30*1676Sjpk  * Device allocation related work.
31*1676Sjpk  */
32*1676Sjpk 
33*1676Sjpk #include <stdio.h>
34*1676Sjpk #include <stdlib.h>
35*1676Sjpk #include <errno.h>
36*1676Sjpk #include <string.h>
37*1676Sjpk #include <strings.h>
38*1676Sjpk #include <unistd.h>
39*1676Sjpk #include <fcntl.h>
40*1676Sjpk #include <sys/types.h>
41*1676Sjpk #include <sys/stat.h>
42*1676Sjpk #include <sys/dkio.h>
43*1676Sjpk #include <sys/wait.h>
44*1676Sjpk #include <bsm/devalloc.h>
45*1676Sjpk 
46*1676Sjpk #define	DEALLOCATE	 "/usr/sbin/deallocate"
47*1676Sjpk #define	MKDEVALLOC	"/usr/sbin/mkdevalloc"
48*1676Sjpk 
49*1676Sjpk static void _update_dev(deventry_t *, int, char *);
50*1676Sjpk static int _make_db();
51*1676Sjpk 
52*1676Sjpk 
53*1676Sjpk /*
54*1676Sjpk  * _da_check_for_usb
55*1676Sjpk  *	returns 1 if device pointed by 'link' is a removable hotplugged
56*1676Sjpk  *	else returns 0.
57*1676Sjpk  */
58*1676Sjpk int
59*1676Sjpk _da_check_for_usb(char *link, char *root_dir)
60*1676Sjpk {
61*1676Sjpk 	int		fd = -1;
62*1676Sjpk 	int		len, dstsize;
63*1676Sjpk 	int		removable = 0;
64*1676Sjpk 	char		*p = NULL;
65*1676Sjpk 	char		path[MAXPATHLEN];
66*1676Sjpk 
67*1676Sjpk 	dstsize = sizeof (path);
68*1676Sjpk 	if (strcmp(root_dir, "") != 0) {
69*1676Sjpk 		if (strlcat(path, root_dir, dstsize) >= dstsize)
70*1676Sjpk 			return (0);
71*1676Sjpk 		len = strlen(path);
72*1676Sjpk 	} else {
73*1676Sjpk 		len = 0;
74*1676Sjpk 	}
75*1676Sjpk 	if (strstr(link, "rdsk")) {
76*1676Sjpk 		(void) snprintf(path, dstsize - len, "%s", link);
77*1676Sjpk 	} else if (strstr(link, "dsk")) {
78*1676Sjpk 		p = rindex(link, '/');
79*1676Sjpk 		if (p == NULL)
80*1676Sjpk 			return (0);
81*1676Sjpk 		p++;
82*1676Sjpk 		(void) snprintf(path, dstsize - len, "%s%s", "/dev/rdsk/", p);
83*1676Sjpk 	} else {
84*1676Sjpk 		return (0);
85*1676Sjpk 	}
86*1676Sjpk 
87*1676Sjpk 	if ((fd = open(path, O_RDONLY | O_NONBLOCK)) < 0)
88*1676Sjpk 		return (0);
89*1676Sjpk 	(void) ioctl(fd, DKIOCREMOVABLE, &removable);
90*1676Sjpk 	(void) close(fd);
91*1676Sjpk 
92*1676Sjpk 	return (removable);
93*1676Sjpk }
94*1676Sjpk 
95*1676Sjpk /*
96*1676Sjpk  * _reset_devalloc
97*1676Sjpk  *	If device allocation is being turned on, creates device_allocate
98*1676Sjpk  *	device_maps if they do not exist.
99*1676Sjpk  *	Puts DEVICE_ALLOCATION=ON/OFF in device_allocate to indicate if
100*1676Sjpk  *	device allocation is on/off.
101*1676Sjpk  */
102*1676Sjpk void
103*1676Sjpk _reset_devalloc(int action)
104*1676Sjpk {
105*1676Sjpk 	da_args	dargs;
106*1676Sjpk 
107*1676Sjpk 	if (action == DA_ON)
108*1676Sjpk 		(void) _make_db();
109*1676Sjpk 	else if ((action == DA_OFF) && (open(DEVALLOC, O_RDONLY) == -1))
110*1676Sjpk 		return;
111*1676Sjpk 
112*1676Sjpk 	if (action == DA_ON)
113*1676Sjpk 		dargs.optflag = DA_ON;
114*1676Sjpk 	else if (action == DA_OFF)
115*1676Sjpk 		dargs.optflag = DA_OFF | DA_ALLOC_ONLY;
116*1676Sjpk 
117*1676Sjpk 	dargs.rootdir = NULL;
118*1676Sjpk 	dargs.devnames = NULL;
119*1676Sjpk 	dargs.devinfo = NULL;
120*1676Sjpk 
121*1676Sjpk 	(void) da_update_device(&dargs);
122*1676Sjpk }
123*1676Sjpk 
124*1676Sjpk /*
125*1676Sjpk  * _make_db
126*1676Sjpk  *	execs /usr/sbin/mkdevalloc to create device_allocate and
127*1676Sjpk  *	device_maps.
128*1676Sjpk  */
129*1676Sjpk static int
130*1676Sjpk _make_db()
131*1676Sjpk {
132*1676Sjpk 	int	status;
133*1676Sjpk 	pid_t	pid, wpid;
134*1676Sjpk 
135*1676Sjpk 	pid = vfork();
136*1676Sjpk 	switch (pid) {
137*1676Sjpk 	case -1:
138*1676Sjpk 		return (1);
139*1676Sjpk 	case 0:
140*1676Sjpk 		if (execl(MKDEVALLOC, MKDEVALLOC, DA_IS_LABELED, NULL) == -1)
141*1676Sjpk 			exit((errno == ENOENT) ? 0 : 1);
142*1676Sjpk 	default:
143*1676Sjpk 		for (;;) {
144*1676Sjpk 			wpid = waitpid(pid, &status, 0);
145*1676Sjpk 			if (wpid == (pid_t)-1) {
146*1676Sjpk 				if (errno == EINTR)
147*1676Sjpk 					continue;
148*1676Sjpk 				else
149*1676Sjpk 					return (1);
150*1676Sjpk 			} else {
151*1676Sjpk 				break;
152*1676Sjpk 			}
153*1676Sjpk 		}
154*1676Sjpk 		break;
155*1676Sjpk 	}
156*1676Sjpk 
157*1676Sjpk 	return ((WIFEXITED(status) == 0) ? 1 : WEXITSTATUS(status));
158*1676Sjpk }
159*1676Sjpk 
160*1676Sjpk 
161*1676Sjpk /*
162*1676Sjpk  * _update_devalloc_db
163*1676Sjpk  * 	Forms allocatable device entries to be written to device_allocate and
164*1676Sjpk  *	device_maps.
165*1676Sjpk  */
166*1676Sjpk /* ARGSUSED */
167*1676Sjpk void
168*1676Sjpk _update_devalloc_db(devlist_t *devlist, int devflag, int action, char *devname,
169*1676Sjpk     char *root_dir)
170*1676Sjpk {
171*1676Sjpk 	int		i;
172*1676Sjpk 	deventry_t	*entry = NULL, *dentry = NULL;
173*1676Sjpk 
174*1676Sjpk 	if (action == DA_ADD) {
175*1676Sjpk 		for (i = 0; i < DA_COUNT; i++) {
176*1676Sjpk 			switch (i) {
177*1676Sjpk 			case 0:
178*1676Sjpk 				dentry = devlist->audio;
179*1676Sjpk 				break;
180*1676Sjpk 			case 1:
181*1676Sjpk 				dentry = devlist->cd;
182*1676Sjpk 				break;
183*1676Sjpk 			case 2:
184*1676Sjpk 				dentry = devlist->floppy;
185*1676Sjpk 				break;
186*1676Sjpk 			case 3:
187*1676Sjpk 				dentry = devlist->tape;
188*1676Sjpk 				break;
189*1676Sjpk 			case 4:
190*1676Sjpk 				dentry = devlist->rmdisk;
191*1676Sjpk 				break;
192*1676Sjpk 			default:
193*1676Sjpk 				return;
194*1676Sjpk 			}
195*1676Sjpk 			if (dentry)
196*1676Sjpk 				_update_dev(dentry, action, NULL);
197*1676Sjpk 		}
198*1676Sjpk 	} else if (action == DA_REMOVE) {
199*1676Sjpk 		if (devflag & DA_AUDIO)
200*1676Sjpk 			dentry = devlist->audio;
201*1676Sjpk 		else if (devflag & DA_CD)
202*1676Sjpk 			dentry = devlist->cd;
203*1676Sjpk 		else if (devflag & DA_FLOPPY)
204*1676Sjpk 			dentry = devlist->floppy;
205*1676Sjpk 		else if (devflag & DA_TAPE)
206*1676Sjpk 			dentry = devlist->tape;
207*1676Sjpk 		else if (devflag & DA_RMDISK)
208*1676Sjpk 			dentry = devlist->rmdisk;
209*1676Sjpk 		else
210*1676Sjpk 			return;
211*1676Sjpk 
212*1676Sjpk 		for (entry = dentry; entry != NULL; entry = entry->next) {
213*1676Sjpk 			if (strcmp(entry->devinfo.devname, devname) == 0)
214*1676Sjpk 				break;
215*1676Sjpk 		}
216*1676Sjpk 		_update_dev(entry, action, devname);
217*1676Sjpk 	}
218*1676Sjpk }
219*1676Sjpk 
220*1676Sjpk static void
221*1676Sjpk _update_dev(deventry_t *dentry, int action, char *devname)
222*1676Sjpk {
223*1676Sjpk 	da_args		dargs;
224*1676Sjpk 	deventry_t	newentry, *entry;
225*1676Sjpk 
226*1676Sjpk 	dargs.rootdir = NULL;
227*1676Sjpk 	dargs.devnames = NULL;
228*1676Sjpk 
229*1676Sjpk 	if (action == DA_ADD) {
230*1676Sjpk 		dargs.optflag = DA_ADD | DA_FORCE;
231*1676Sjpk 		for (entry = dentry; entry != NULL; entry = entry->next) {
232*1676Sjpk 			dargs.devinfo = &(entry->devinfo);
233*1676Sjpk 			(void) da_update_device(&dargs);
234*1676Sjpk 		}
235*1676Sjpk 	} else if (action == DA_REMOVE) {
236*1676Sjpk 		dargs.optflag = DA_REMOVE;
237*1676Sjpk 		if (dentry) {
238*1676Sjpk 			entry = dentry;
239*1676Sjpk 		} else {
240*1676Sjpk 			newentry.devinfo.devname = strdup(devname);
241*1676Sjpk 			newentry.devinfo.devtype =
242*1676Sjpk 			newentry.devinfo.devauths =
243*1676Sjpk 			newentry.devinfo.devexec =
244*1676Sjpk 			newentry.devinfo.devopts =
245*1676Sjpk 			newentry.devinfo.devlist = NULL;
246*1676Sjpk 			newentry.devinfo.instance = 0;
247*1676Sjpk 			newentry.next = NULL;
248*1676Sjpk 			entry = &newentry;
249*1676Sjpk 		}
250*1676Sjpk 		dargs.devinfo = &(entry->devinfo);
251*1676Sjpk 		(void) da_update_device(&dargs);
252*1676Sjpk 	}
253*1676Sjpk }
254