xref: /titanic_53/usr/src/lib/libdevinfo/devinfo_finddev.c (revision facf4a8d7b59fde89a8662b4f4c73a758e6c402c)
1*facf4a8dSllai1 /*
2*facf4a8dSllai1  * CDDL HEADER START
3*facf4a8dSllai1  *
4*facf4a8dSllai1  * The contents of this file are subject to the terms of the
5*facf4a8dSllai1  * Common Development and Distribution License (the "License").
6*facf4a8dSllai1  * You may not use this file except in compliance with the License.
7*facf4a8dSllai1  *
8*facf4a8dSllai1  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*facf4a8dSllai1  * or http://www.opensolaris.org/os/licensing.
10*facf4a8dSllai1  * See the License for the specific language governing permissions
11*facf4a8dSllai1  * and limitations under the License.
12*facf4a8dSllai1  *
13*facf4a8dSllai1  * When distributing Covered Code, include this CDDL HEADER in each
14*facf4a8dSllai1  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*facf4a8dSllai1  * If applicable, add the following below this CDDL HEADER, with the
16*facf4a8dSllai1  * fields enclosed by brackets "[]" replaced with your own identifying
17*facf4a8dSllai1  * information: Portions Copyright [yyyy] [name of copyright owner]
18*facf4a8dSllai1  *
19*facf4a8dSllai1  * CDDL HEADER END
20*facf4a8dSllai1  */
21*facf4a8dSllai1 /*
22*facf4a8dSllai1  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23*facf4a8dSllai1  * Use is subject to license terms.
24*facf4a8dSllai1  */
25*facf4a8dSllai1 
26*facf4a8dSllai1 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27*facf4a8dSllai1 
28*facf4a8dSllai1 #include <stdio.h>
29*facf4a8dSllai1 #include <unistd.h>
30*facf4a8dSllai1 #include <fcntl.h>
31*facf4a8dSllai1 #include <string.h>
32*facf4a8dSllai1 #include <thread.h>
33*facf4a8dSllai1 #include <synch.h>
34*facf4a8dSllai1 #include <limits.h>
35*facf4a8dSllai1 #include <stdlib.h>
36*facf4a8dSllai1 #include <string.h>
37*facf4a8dSllai1 #include <strings.h>
38*facf4a8dSllai1 #include <dirent.h>
39*facf4a8dSllai1 #include <regex.h>
40*facf4a8dSllai1 #include <errno.h>
41*facf4a8dSllai1 #include <stdarg.h>
42*facf4a8dSllai1 #include <libdevinfo.h>
43*facf4a8dSllai1 #include <sys/modctl.h>
44*facf4a8dSllai1 #include <syslog.h>
45*facf4a8dSllai1 
46*facf4a8dSllai1 #include <assert.h>
47*facf4a8dSllai1 
48*facf4a8dSllai1 
49*facf4a8dSllai1 struct finddevhdl {
50*facf4a8dSllai1 	int	npaths;
51*facf4a8dSllai1 	int	curpath;
52*facf4a8dSllai1 	char	**paths;
53*facf4a8dSllai1 };
54*facf4a8dSllai1 
55*facf4a8dSllai1 
56*facf4a8dSllai1 int
57*facf4a8dSllai1 device_exists(const char *devname)
58*facf4a8dSllai1 {
59*facf4a8dSllai1 	int	rv;
60*facf4a8dSllai1 
61*facf4a8dSllai1 	rv = modctl(MODDEVEXISTS, devname, strlen(devname));
62*facf4a8dSllai1 	return ((rv == 0) ? 1 : 0);
63*facf4a8dSllai1 }
64*facf4a8dSllai1 
65*facf4a8dSllai1 int
66*facf4a8dSllai1 finddev_readdir(const char *dir, finddevhdl_t *handlep)
67*facf4a8dSllai1 {
68*facf4a8dSllai1 	struct finddevhdl	*handle;
69*facf4a8dSllai1 	int			n;
70*facf4a8dSllai1 	int			rv;
71*facf4a8dSllai1 	int64_t			bufsiz;
72*facf4a8dSllai1 	char			*pathlist;
73*facf4a8dSllai1 	char			*p;
74*facf4a8dSllai1 	int			len;
75*facf4a8dSllai1 
76*facf4a8dSllai1 	*handlep = NULL;
77*facf4a8dSllai1 	handle = calloc(1, sizeof (struct finddevhdl));
78*facf4a8dSllai1 	if (handle == NULL)
79*facf4a8dSllai1 		return (ENOMEM);
80*facf4a8dSllai1 
81*facf4a8dSllai1 	handle->npaths = 0;
82*facf4a8dSllai1 	handle->curpath = 0;
83*facf4a8dSllai1 	handle->paths = NULL;
84*facf4a8dSllai1 
85*facf4a8dSllai1 	rv = modctl(MODDEVREADDIR, dir, strlen(dir), NULL, &bufsiz);
86*facf4a8dSllai1 	if (rv != 0) {
87*facf4a8dSllai1 		free(handle);
88*facf4a8dSllai1 		return (rv);
89*facf4a8dSllai1 	}
90*facf4a8dSllai1 
91*facf4a8dSllai1 	for (;;) {
92*facf4a8dSllai1 		assert(bufsiz != 0);
93*facf4a8dSllai1 		if ((pathlist = malloc(bufsiz)) == NULL) {
94*facf4a8dSllai1 			free(handle);
95*facf4a8dSllai1 			return (ENOMEM);
96*facf4a8dSllai1 		}
97*facf4a8dSllai1 
98*facf4a8dSllai1 		rv = modctl(MODDEVREADDIR, dir, strlen(dir),
99*facf4a8dSllai1 		    pathlist, &bufsiz);
100*facf4a8dSllai1 		if (rv == 0) {
101*facf4a8dSllai1 			for (n = 0, p = pathlist;
102*facf4a8dSllai1 			    (len = strlen(p)) > 0; p += len+1) {
103*facf4a8dSllai1 				n++;
104*facf4a8dSllai1 			}
105*facf4a8dSllai1 			handle->npaths = n;
106*facf4a8dSllai1 			handle->paths = calloc(n, sizeof (char *));
107*facf4a8dSllai1 			if (handle->paths == NULL) {
108*facf4a8dSllai1 				free(handle);
109*facf4a8dSllai1 				free(pathlist);
110*facf4a8dSllai1 				return (ENOMEM);
111*facf4a8dSllai1 			}
112*facf4a8dSllai1 			for (n = 0, p = pathlist;
113*facf4a8dSllai1 			    (len = strlen(p)) > 0; p += len+1, n++) {
114*facf4a8dSllai1 				handle->paths[n] = strdup(p);
115*facf4a8dSllai1 				if (handle->paths[n] == NULL) {
116*facf4a8dSllai1 					finddev_close((finddevhdl_t)handle);
117*facf4a8dSllai1 					free(pathlist);
118*facf4a8dSllai1 					return (ENOMEM);
119*facf4a8dSllai1 				}
120*facf4a8dSllai1 			}
121*facf4a8dSllai1 			*handlep = (finddevhdl_t)handle;
122*facf4a8dSllai1 			free(pathlist);
123*facf4a8dSllai1 			return (0);
124*facf4a8dSllai1 		}
125*facf4a8dSllai1 		free(pathlist);
126*facf4a8dSllai1 		switch (errno) {
127*facf4a8dSllai1 		case EAGAIN:
128*facf4a8dSllai1 			break;
129*facf4a8dSllai1 		case ENOENT:
130*facf4a8dSllai1 		default:
131*facf4a8dSllai1 			free(handle);
132*facf4a8dSllai1 			return (errno);
133*facf4a8dSllai1 		}
134*facf4a8dSllai1 	}
135*facf4a8dSllai1 	/*NOTREACHED*/
136*facf4a8dSllai1 }
137*facf4a8dSllai1 
138*facf4a8dSllai1 void
139*facf4a8dSllai1 finddev_close(finddevhdl_t arg)
140*facf4a8dSllai1 {
141*facf4a8dSllai1 	struct finddevhdl *handle = (struct finddevhdl *)arg;
142*facf4a8dSllai1 	int i;
143*facf4a8dSllai1 
144*facf4a8dSllai1 	for (i = 0; i < handle->npaths; i++) {
145*facf4a8dSllai1 		if (handle->paths[i])
146*facf4a8dSllai1 			free(handle->paths[i]);
147*facf4a8dSllai1 	}
148*facf4a8dSllai1 	free(handle->paths);
149*facf4a8dSllai1 	free(handle);
150*facf4a8dSllai1 }
151*facf4a8dSllai1 
152*facf4a8dSllai1 const char *
153*facf4a8dSllai1 finddev_next(finddevhdl_t arg)
154*facf4a8dSllai1 {
155*facf4a8dSllai1 	struct finddevhdl *handle = (struct finddevhdl *)arg;
156*facf4a8dSllai1 	const char *path = NULL;
157*facf4a8dSllai1 
158*facf4a8dSllai1 	if (handle->curpath < handle->npaths) {
159*facf4a8dSllai1 		path = handle->paths[handle->curpath];
160*facf4a8dSllai1 		handle->curpath++;
161*facf4a8dSllai1 	}
162*facf4a8dSllai1 	return (path);
163*facf4a8dSllai1 }
164