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