1 /*
2 * CDDL HEADER START
3 *
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.
7 *
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.
12 *
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]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 #include <stdio.h>
27 #include <ctype.h>
28 #include <sys/types.h>
29 #include <sys/mkdev.h>
30 #include <sys/stat.h>
31 #include <unistd.h>
32 #include <dirent.h>
33 #include <limits.h>
34 #include <string.h>
35 #include <libsvm.h>
36 #include <svm.h>
37 #include <errno.h>
38
39
40 #define VERSION "1.0"
41 #define DISK_DIR "/dev/rdsk"
42
43 extern int _map_to_effective_dev();
44
45 static int is_blank(char *);
46
47 /*
48 * is_blank() returns 1 (true) if a line specified is composed of
49 * whitespace characters only. otherwise, it returns 0 (false).
50 *
51 * Note. the argument (line) must be null-terminated.
52 */
53 static int
is_blank(char * line)54 is_blank(char *line)
55 {
56 for (/* nothing */; *line != '\0'; line++)
57 if (!isspace(*line))
58 return (0);
59 return (1);
60 }
61
62 /*
63 * FUNCTION: write_targ_nm_table
64 * creates a tuple table of <driver name, major number > in md.conf
65 * INPUT: rootpath
66 *
67 * RETURN VALUES:
68 * RET_SUCCESS
69 * RET_ERROR
70 */
71
72 int
write_targ_nm_table(char * path)73 write_targ_nm_table(char *path)
74 {
75 FILE *targfp = NULL;
76 FILE *mdfp = NULL;
77 char buf[PATH_MAX], *cp;
78 int retval = RET_SUCCESS;
79 int first_entry = 1;
80
81 if ((mdfp = fopen(MD_CONF, "a")) == NULL)
82 return (RET_ERROR);
83
84 (void) snprintf(buf, sizeof (buf), "%s%s", path, NAME_TO_MAJOR);
85
86 if ((targfp = fopen(buf, "r")) == NULL) {
87 (void) fclose(mdfp);
88 return (RET_ERROR);
89 }
90
91 while (fgets(buf, PATH_MAX, targfp) != NULL &&
92 (retval == RET_SUCCESS)) {
93 /* remove a new-line character for md_targ_nm_table */
94 if ((cp = strchr(buf, '\n')) != NULL)
95 *cp = 0;
96 /* cut off comments starting with '#' */
97 if ((cp = strchr(buf, '#')) != NULL)
98 *cp = 0;
99 /* ignore comment or blank lines */
100 if (is_blank(buf))
101 continue;
102 if (first_entry) {
103 if (fprintf(mdfp, "md_targ_nm_table=\"%s\"", buf) < 0)
104 retval = RET_ERROR;
105 first_entry = 0;
106 } else {
107 if (fprintf(mdfp, ",\"%s\"", buf) < 0)
108 retval = RET_ERROR;
109 }
110 }
111 if (!first_entry)
112 if (fprintf(mdfp, ";\n") < 0)
113 retval = RET_ERROR;
114 (void) fclose(mdfp);
115 (void) fclose(targfp);
116 return (retval);
117 }
118
119 /*
120 * FUNCTION: write_xlate_to_mdconf
121 * creates a tuple table of <miniroot devt, target devt> in md.conf
122 * INPUT: rootpath
123 *
124 * RETURN VALUES:
125 * RET_SUCCESS
126 * RET_ERROR
127 */
128
129 int
write_xlate_to_mdconf(char * path)130 write_xlate_to_mdconf(char *path)
131 {
132 FILE *fptr = NULL;
133 struct dirent *dp;
134 DIR *dirp;
135 struct stat statb_dev;
136 struct stat statb_edev;
137 char *devname;
138 char edevname[PATH_MAX];
139 char targname[PATH_MAX];
140 char diskdir[PATH_MAX];
141 char linkpath[PATH_MAX];
142 int first_devid = 1;
143 int ret = RET_SUCCESS;
144
145 if ((fptr = fopen(MD_CONF, "a")) == NULL) {
146 return (RET_ERROR);
147 }
148
149
150 (void) snprintf(diskdir, sizeof (diskdir), "%s%s", path, DISK_DIR);
151 if ((dirp = opendir(diskdir)) == NULL) {
152 (void) fclose(fptr);
153 return (RET_ERROR);
154 }
155
156 /* special case to write the first tuple in the table */
157 while (((dp = readdir(dirp)) != (struct dirent *)0) &&
158 (ret != RET_ERROR)) {
159 if ((strcmp(dp->d_name, ".") == 0) ||
160 (strcmp(dp->d_name, "..") == 0))
161 continue;
162
163 if ((strlen(diskdir) + strlen(dp->d_name) + 2) > PATH_MAX) {
164 continue;
165 }
166
167 (void) snprintf(targname, sizeof (targname), "%s/%s",
168 diskdir, dp->d_name);
169
170 /*
171 * stat /devices to see if it's a devfs based file system
172 * On Solaris 10 and up, the devfs has been built on the
173 * fly for the mini-root. We need to adjust the path
174 * accordingly.
175 * If it's not devfs, just use the targname as it is.
176 */
177
178 if (stat("/devices", &statb_dev) != 0) {
179 continue;
180 }
181
182 if (strncmp("devfs", statb_dev.st_fstype, 5) == 0) {
183 if (readlink(targname, linkpath,
184 sizeof (linkpath)) == -1) {
185 continue;
186 }
187 /*
188 * turn ../../devices/<path> into /devices/<path>
189 * and stat that into statb_dev
190 */
191 if (stat(strstr(linkpath, "/devices"),
192 &statb_dev) != 0) {
193 continue;
194 }
195 } else {
196 if (stat(targname, &statb_dev) != 0) {
197 continue;
198 }
199 }
200
201 if ((devname = strstr(targname, DISK_DIR)) == NULL) {
202 continue;
203 }
204
205 if (_map_to_effective_dev((char *)devname, (char *)&edevname)
206 != 0) {
207 continue;
208 }
209
210 if (stat(edevname, &statb_edev) != 0) {
211 continue;
212 }
213
214 if (first_devid) {
215 if (fprintf(fptr, "md_xlate_ver=\"%s\";\n"
216 "md_xlate=%lu,%lu", VERSION,
217 statb_edev.st_rdev, statb_dev.st_rdev) < 0)
218 ret = RET_ERROR;
219 first_devid = 0;
220 }
221 if (fprintf(fptr, ",%lu,%lu", statb_edev.st_rdev,
222 statb_dev.st_rdev) < 0)
223 ret = RET_ERROR;
224 } /* end while */
225
226 if (!first_devid)
227 if (fprintf(fptr, ";\n") < 0)
228 ret = RET_ERROR;
229 (void) fclose(fptr);
230 (void) closedir(dirp);
231 return (ret);
232 }
233