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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright (c) 1995-1997 by Sun Microsystems, Inc. 24 * All rights reserved. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * routines in this module are meant to be called by other libvolmgt 31 * routines only 32 */ 33 34 #include <stdio.h> 35 #include <string.h> 36 #include <dirent.h> 37 #include <string.h> 38 #include <libintl.h> 39 #include <limits.h> 40 #include <unistd.h> 41 #include <stdlib.h> 42 #include <sys/types.h> 43 #include <sys/stat.h> 44 #include <sys/param.h> 45 #include <sys/vol.h> 46 #ifdef DEBUG 47 #include <sys/varargs.h> 48 #endif 49 #include "volmgt_private.h" 50 51 52 53 /* 54 * We have been passed a path which (presumably) is a volume. 55 * We look through the directory until we find a name which is 56 * a character device. 57 */ 58 char * 59 getrawpart0(char *path) 60 { 61 DIR *dirp = NULL; 62 struct dirent64 *dp; 63 static char fname[MAXPATHLEN+1]; 64 struct stat64 sb; 65 char *res; 66 int len; 67 68 69 70 /* open the directory */ 71 if ((dirp = opendir(path)) == NULL) { 72 res = NULL; 73 goto dun; 74 } 75 76 /* get length of directory part */ 77 len = strlen(path); 78 79 /* scan the directory */ 80 while (dp = readdir64(dirp)) { 81 82 /* skip "." and ".." */ 83 if (strcmp(dp->d_name, ".") == 0) { 84 continue; 85 } 86 if (strcmp(dp->d_name, "..") == 0) { 87 continue; 88 } 89 90 /* ensure we have room for this name */ 91 if ((len + strlen(dp->d_name) + 1) > MAXPATHLEN) { 92 /* XXX: just give up? */ 93 continue; 94 } 95 96 /* create a pathname for this device */ 97 (void) concat_paths(fname, path, dp->d_name, NULL); 98 if (stat64(fname, &sb) < 0) { 99 continue; /* this shouldn't happen */ 100 } 101 /* check for a char-spcl device */ 102 if (S_ISCHR(sb.st_mode)) { 103 res = strdup(fname); 104 goto dun; 105 } 106 } 107 108 /* raw part not found */ 109 res = NULL; 110 dun: 111 if (dirp != NULL) { 112 (void) closedir(dirp); 113 } 114 return (res); 115 } 116 117 118 /* 119 * fix the getfull{raw,blk}name problem for the fd and diskette case 120 * 121 * return value is malloc'ed, and must be free'd 122 * 123 * no match gets a malloc'ed null string 124 */ 125 126 char * 127 volmgt_getfullblkname(char *n) 128 { 129 extern char *getfullblkname(char *); 130 char *rval; 131 char namebuf[MAXPATHLEN+1]; 132 char *s; 133 char c; 134 char *res; 135 136 137 138 /* try to get full block-spcl device name */ 139 rval = getfullblkname(n); 140 if ((rval != NULL) && (*rval != NULLC)) { 141 /* found it */ 142 res = rval; 143 goto dun; 144 } 145 146 /* we have a null-string result */ 147 if (rval != NULL) { 148 /* free null string */ 149 free(rval); 150 } 151 152 /* ok, so we either have a bad device or a floppy */ 153 154 /* try the rfd# or rdiskette forms */ 155 if (((s = strstr(n, "/rfd")) != NULL) || 156 ((s = strstr(n, "/rdiskette")) != NULL) || 157 ((s = strstr(n, "/rdsk/")) != NULL)) { 158 /* 159 * we do not have to check for room here, since we will 160 * be making the string one shorter 161 */ 162 c = *++s; /* save the first char */ 163 *s = NULLC; /* replace it with a null */ 164 (void) strcpy(namebuf, n); /* save first part of it */ 165 *s++ = c; /* give the first char back */ 166 (void) strcat(namebuf, s); /* copy the rest */ 167 res = strdup(namebuf); 168 goto dun; 169 } 170 171 /* no match found */ 172 res = strdup(""); 173 174 dun: 175 return (res); 176 } 177 178 179 char * 180 volmgt_getfullrawname(char *n) 181 { 182 extern char *getfullrawname(char *); 183 char *rval; 184 char namebuf[MAXPATHLEN+1]; 185 char *s; 186 char c; 187 char *res; 188 189 190 #ifdef DEBUG 191 denter("volmgt_getfullrawname(%s): entering\n", n); 192 #endif 193 /* try to get full char-spcl device name */ 194 rval = getfullrawname(n); 195 if ((rval != NULL) && (*rval != NULLC)) { 196 /* found it */ 197 res = rval; 198 goto dun; 199 } 200 201 /* we have a null-string result */ 202 if (rval != NULL) { 203 /* free null string */ 204 free(rval); 205 } 206 207 /* ok, so we either have a bad device or a floppy */ 208 209 /* try the "fd", "diskette", and the "dsk" form */ 210 if (((s = strstr(n, "/fd")) != NULL) || 211 ((s = strstr(n, "/diskette")) != NULL) || 212 ((s = strstr(n, "/dsk/")) != NULL)) { 213 /* 214 * ensure we have room to add one more char 215 */ 216 if (strlen(n) < (MAXPATHLEN - 1)) { 217 c = *++s; /* save the first char */ 218 *s = NULLC; /* replace it with a null */ 219 (void) strcpy(namebuf, n); /* save first part of str */ 220 *s = c; /* put first charback */ 221 (void) strcat(namebuf, "r"); /* insert an 'r' */ 222 (void) strcat(namebuf, s); /* copy rest of str */ 223 res = strdup(namebuf); 224 goto dun; 225 } 226 } 227 228 /* no match found */ 229 res = strdup(""); 230 dun: 231 #ifdef DEBUG 232 dexit("volmgt_getfullrawname: returning %s\n", 233 res ? res : "<null ptr>"); 234 #endif 235 return (res); 236 } 237 238 239 /* 240 * volctl_name -- return name of volctl device 241 */ 242 const char * 243 volctl_name(void) 244 { 245 static char dev_name[] = "/dev/" VOLCTLNAME; 246 247 return (dev_name); 248 } 249 250 251 /* 252 * concat_paths -- create a pathname from two (or three) components 253 * 254 * truncate the result if it is too large 255 * 256 * assume that res has a defined length of MAXPATHLEN+1 257 * 258 * ("head" and "tail" are required, but "tail2" is optional) 259 */ 260 char * 261 concat_paths(char *res, char *head, char *tail, char *tail2) 262 { 263 int head_len = strlen(head); 264 int len_avail = MAXPATHLEN; 265 266 267 268 /* put in as much of the head as will fit */ 269 (void) strncpy(res, head, len_avail); 270 len_avail -= head_len; 271 272 /* see if there is room to proceed */ 273 if (len_avail > 0) { 274 char *cp = res + head_len; 275 276 /* there is room to append a slash */ 277 *cp++ = '/'; 278 len_avail--; 279 280 /* see if there is room to proceed */ 281 if (len_avail > 0) { 282 int tail_len = strlen(tail); 283 284 /* there is room to append the tail */ 285 (void) strncpy(cp, tail, len_avail); 286 cp += tail_len; 287 len_avail -= tail_len; 288 289 /* see if there is room to proceed */ 290 if ((len_avail > 0) && (tail2 != NULL)) { 291 292 /* there is room to add tail2 (and need) */ 293 (void) strncpy(cp, tail2, len_avail); 294 } 295 } 296 } 297 298 /* null terminate result (just in case) and return */ 299 res[MAXPATHLEN] = NULLC; 300 return (res); 301 } 302 303 304 305 #ifdef DEBUG 306 307 /* 308 * debug print routines -- private to libvolmgt 309 */ 310 311 #define DEBUG_INDENT_SPACES " " 312 313 int debug_level = 0; 314 315 316 static void 317 derrprint(char *fmt, va_list ap) 318 { 319 int i; 320 int j; 321 char date_buf[256]; 322 time_t t; 323 struct tm *tm; 324 325 326 (void) time(&t); 327 tm = localtime(&t); 328 (void) fprintf(stderr, "%02d/%02d/%02d %02d:%02d:%02d ", 329 tm->tm_mon+1, tm->tm_mday, tm->tm_year % 100, 330 tm->tm_hour, tm->tm_min, tm->tm_sec); 331 for (i = 0; i < debug_level; i++) { 332 (void) fprintf(stderr, DEBUG_INDENT_SPACES); 333 } 334 (void) vfprintf(stderr, fmt, ap); 335 } 336 337 /* 338 * denter -- do a derrprint(), then increment debug level 339 */ 340 void 341 denter(char *fmt, ...) 342 { 343 va_list ap; 344 345 va_start(ap, fmt); 346 derrprint(fmt, ap); 347 va_end(ap); 348 debug_level++; 349 } 350 351 /* 352 * dexit -- decrement debug level then do a derrprint() 353 */ 354 void 355 dexit(char *fmt, ...) 356 { 357 va_list ap; 358 359 if (--debug_level < 0) { 360 debug_level = 0; 361 } 362 va_start(ap, fmt); 363 derrprint(fmt, ap); 364 va_end(ap); 365 } 366 367 /* 368 * dprintf -- print debug info, indenting based on debug level 369 */ 370 void 371 dprintf(char *fmt, ...) 372 { 373 va_list ap; 374 375 va_start(ap, fmt); 376 derrprint(fmt, ap); 377 va_end(ap); 378 } 379 380 #endif /* DEBUG */ 381