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 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 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 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