dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / lib / libadm / common / fulldevnm.c
blobf22035342edb7aa6e6d786f24f963689d8f9c9e2
1 /*
2 * CDDL HEADER START
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.
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.
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]
20 * CDDL HEADER END
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
28 /*LINTLIBRARY*/
30 #include <sys/types.h>
31 #include <stdio.h>
32 #include <errno.h>
33 #include <string.h>
34 #include <unistd.h>
35 #include <stdlib.h>
36 #include <sys/param.h>
37 #include <sys/stat.h>
38 #include <sys/sysmacros.h>
39 #include <sys/vfstab.h>
40 #include <sys/lofi.h>
41 #include <sys/ramdisk.h>
42 #include <sys/fssnap_if.h>
43 #include "libadm.h"
46 * Globals:
47 * getfullrawname - returns a fully-qualified raw device name
48 * getfullblkname - returns a fully-qualified block device name
50 * These two routines take a device pathname and return corresponding
51 * the raw or block device name.
53 * First the device name is fully qualified:
54 * If the device name does not start with a '/' or starts with
55 * './' then the current working directory is added to the beginning
56 * of the pathname.
58 * If the device name starts with a '../' then all but the last
59 * sub-directory of the current working directory is added to the
60 * the beginning of the pathname.
62 * Second if the fully-qualified device name given is the raw/block
63 * device that is being asked for then the fully-qualified device name is
64 * returned.
66 * Third if an entry is found in /etc/vfstab which matches the given name
67 * then the corresponding raw/block device is returned. This allows
68 * non-standard names to be converted (.i.e., block device "/dev/joe" can
69 * be converted to raw device "/dev/fred", via this mechanism).
71 * Last standard names are converted. Standard names are those
72 * with a '/dsk/' for block or '/rdsk/' for raw sub-directory components
73 * in the device name. Or, the filename component has an 'r' for raw or
74 * no 'r' for block (e.g., rsd0a <=> sd0a).
76 * Caveat:
77 * It is assumed that the block and raw devices have the
78 * same device number, and this is used to verify the conversion
79 * happened corretly. If this happens not to be true, due to mapping
80 * of minor numbers or sometheing, then entries can be put in the
81 * the '/etc/vfstab' file to over-ride this checking.
84 * Return Values:
85 * raw/block device name - (depending on which routine is used)
86 * null string - When the conversion failed
87 * null pointer - malloc problems
89 * It is up to the user of these routines to free the memory, of
90 * the device name or null string returned by these library routines,
91 * when appropriate by the application.
93 #define GET_BLK 0
94 #define GET_RAW 1
96 static int test_if_blk(char *, dev_t);
97 static int test_if_raw(char *, dev_t);
98 static char *getblkcomplete(char *, struct stat64 *);
99 static char *getrawcomplete(char *, struct stat64 *);
102 * getfullname() - Builds a fully qualified pathname.
103 * This handles . and .. as well.
104 * NOTE: This is different from realpath(3C) because
105 * it does not follow links.
107 static char *
108 getfullname(char *path)
110 char cwd[MAXPATHLEN];
111 char *c;
112 char *wa;
113 size_t len;
115 if (*path == '/')
116 return (strdup(path));
118 if (getcwd(cwd, sizeof (cwd)) == NULL)
119 return (strdup(""));
121 /* handle . and .. */
122 if (strncmp(path, "./", 2) == 0) {
123 /* strip the ./ from the given path */
124 path += 2;
125 } else if (strncmp(path, "../", 3) == 0) {
126 /* strip the last directory component from cwd */
127 c = strrchr(cwd, '/');
128 *c = '\0';
130 /* strip the ../ from the given path */
131 path += 3;
135 * Adding 2 takes care of slash and null terminator.
137 len = strlen(cwd) + strlen(path) + 2;
138 if ((wa = malloc(len)) == NULL)
139 return (NULL);
141 (void) strcpy(wa, cwd);
142 (void) strcat(wa, "/");
143 (void) strcat(wa, path);
145 return (wa);
149 * test the path/fname to see if is blk special
151 static int
152 test_if_blk(char *new_path, dev_t raw_dev)
154 struct stat64 buf;
156 /* check if we got a char special file */
157 if (stat64(new_path, &buf) != 0)
158 return (0);
160 if (!S_ISBLK(buf.st_mode))
161 return (0);
163 if (raw_dev != buf.st_rdev)
164 return (0);
166 return (1);
170 * test the path/fname to see if is char special
172 static int
173 test_if_raw(char *new_path, dev_t blk_dev)
175 struct stat64 buf;
177 /* check if we got a char special file */
178 if (stat64(new_path, &buf) != 0)
179 return (0);
181 if (!S_ISCHR(buf.st_mode))
182 return (0);
184 if (blk_dev != buf.st_rdev)
185 return (0);
187 return (1);
191 * complete getblkrawname() for blk->raw to handle volmgt devices
194 static char *
195 getblkcomplete(char *cp, struct stat64 *dat)
197 char *dp;
198 char *new_path;
199 char c;
201 /* ok, so we either have a bad device or a floppy */
203 /* try the rfd# form */
204 if ((dp = strstr(cp, "/rfd")) != NULL) {
205 if ((new_path = malloc(strlen(cp))) == NULL)
206 return (NULL);
208 c = *++dp; /* save the 'r' */
209 *dp = '\0'; /* replace it with a null */
210 (void) strcpy(new_path, cp); /* save first part of it */
211 *dp++ = c; /* give the 'r' back */
212 (void) strcat(new_path, dp); /* copy, skipping the 'r' */
214 if (test_if_blk(new_path, dat->st_rdev))
215 return (new_path);
217 free(new_path);
218 return (strdup(""));
221 /* try the rdiskette form */
222 if ((dp = strstr(cp, "/rdiskette")) != NULL) {
223 if ((new_path = malloc(strlen(cp))) == NULL)
224 return (NULL);
226 c = *++dp; /* save the 'r' */
227 *dp = '\0'; /* replace it with a null */
228 (void) strcpy(new_path, cp); /* save first part of it */
229 *dp++ = c; /* give the 'r' back */
230 (void) strcat(new_path, dp); /* copy, skipping the 'r' */
232 if (test_if_blk(new_path, dat->st_rdev))
233 return (new_path);
235 free(new_path);
236 return (strdup(""));
239 /* no match found */
240 return (strdup(""));
244 * complete getfullrawname() for raw->blk to handle volmgt devices
247 static char *
248 getrawcomplete(char *cp, struct stat64 *dat)
250 char *dp;
251 char *new_path;
252 char c;
254 /* ok, so we either have a bad device or a floppy */
256 /* try the fd# form */
257 if ((dp = strstr(cp, "/fd")) != NULL) {
258 /* malloc path for new_path to hold raw */
259 if ((new_path = malloc(strlen(cp)+2)) == NULL)
260 return (NULL);
262 c = *++dp; /* save the 'f' */
263 *dp = '\0'; /* replace it with a null */
264 (void) strcpy(new_path, cp); /* save first part of it */
265 *dp = c; /* put the 'f' back */
266 (void) strcat(new_path, "r"); /* insert an 'r' */
267 (void) strcat(new_path, dp); /* copy the rest */
269 if (test_if_raw(new_path, dat->st_rdev))
270 return (new_path);
272 free(new_path);
275 /* try the diskette form */
276 if ((dp = strstr(cp, "/diskette")) != NULL) {
277 /* malloc path for new_path to hold raw */
278 if ((new_path = malloc(strlen(cp)+2)) == NULL)
279 return (NULL);
281 c = *++dp; /* save at 'd' */
282 *dp = '\0'; /* replace it with a null */
283 (void) strcpy(new_path, cp); /* save first part */
284 *dp = c; /* put the 'd' back */
285 (void) strcat(new_path, "r"); /* insert an 'r' */
286 (void) strcat(new_path, dp); /* copy the rest */
288 if (test_if_raw(new_path, dat->st_rdev))
289 return (new_path);
291 free(new_path);
292 return (strdup(""));
295 /* failed to build raw name, return null string */
296 return (strdup(""));
302 static char *
303 getvfsspecial(char *path, int raw_special)
305 FILE *fp;
306 struct vfstab vp;
307 struct vfstab ref_vp;
309 if ((fp = fopen("/etc/vfstab", "r")) == NULL)
310 return (NULL);
312 (void) memset(&ref_vp, 0, sizeof (struct vfstab));
314 if (raw_special)
315 ref_vp.vfs_special = path;
316 else
317 ref_vp.vfs_fsckdev = path;
319 if (getvfsany(fp, &vp, &ref_vp)) {
320 (void) fclose(fp);
321 return (NULL);
324 (void) fclose(fp);
326 if (raw_special)
327 return (vp.vfs_fsckdev);
329 return (vp.vfs_special);
333 * change the device name to a block device name
335 char *
336 getfullblkname(char *cp)
338 struct stat64 buf;
339 char *dp;
340 char *new_path;
341 dev_t raw_dev;
343 if (cp == NULL)
344 return (strdup(""));
347 * Create a fully qualified name.
349 if ((cp = getfullname(cp)) == NULL)
350 return (NULL);
352 if (*cp == '\0')
353 return (cp);
355 if (stat64(cp, &buf) != 0) {
356 free(cp);
357 return (strdup(""));
360 if (S_ISBLK(buf.st_mode))
361 return (cp);
363 if (!S_ISCHR(buf.st_mode)) {
364 free(cp);
365 return (strdup(""));
368 if ((dp = getvfsspecial(cp, GET_BLK)) != NULL) {
369 free(cp);
370 return (strdup(dp));
373 raw_dev = buf.st_rdev;
376 * We have a raw device name, go find the block name.
378 if ((dp = strstr(cp, "/rdsk/")) == NULL &&
379 (dp = strstr(cp, "/" LOFI_CHAR_NAME "/")) == NULL &&
380 (dp = strstr(cp, "/" RD_CHAR_NAME "/")) == NULL &&
381 (dp = strstr(cp, "/" SNAP_CHAR_NAME "/")) == NULL &&
382 (dp = strrchr(cp, '/')) == NULL) {
383 /* this is not really possible */
384 free(cp);
385 return (strdup(""));
387 dp++;
388 if (*dp != 'r') {
389 dp = getblkcomplete(cp, &buf);
390 free(cp);
391 return (dp);
393 if ((new_path = malloc(strlen(cp))) == NULL) {
394 free(cp);
395 return (NULL);
397 (void) strncpy(new_path, cp, dp - cp);
399 /* fill in the rest of the unraw name */
400 (void) strcpy(new_path + (dp - cp), dp + 1);
402 if (test_if_blk(new_path, raw_dev)) {
403 free(cp);
404 /* block name was found, return it here */
405 return (new_path);
407 free(new_path);
409 dp = getblkcomplete(cp, &buf);
410 free(cp);
411 return (dp);
415 * change the device name to a raw devname
417 char *
418 getfullrawname(char *cp)
420 struct stat64 buf;
421 char *dp;
422 char *new_path;
423 dev_t blk_dev;
425 if (cp == NULL)
426 return (strdup(""));
429 * Create a fully qualified name.
431 if ((cp = getfullname(cp)) == NULL)
432 return (NULL);
434 if (*cp == '\0')
435 return (cp);
437 if (stat64(cp, &buf) != 0) {
438 free(cp);
439 return (strdup(""));
442 if (S_ISCHR(buf.st_mode))
443 return (cp);
445 if (!S_ISBLK(buf.st_mode)) {
446 free(cp);
447 return (strdup(""));
450 blk_dev = buf.st_rdev;
452 if ((dp = getvfsspecial(cp, GET_RAW)) != NULL) {
453 free(cp);
454 return (strdup(dp));
458 * We have a block device name, go find the raw name.
460 if ((dp = strstr(cp, "/dsk/")) == NULL &&
461 (dp = strstr(cp, "/" LOFI_BLOCK_NAME "/")) == NULL &&
462 (dp = strstr(cp, "/" RD_BLOCK_NAME "/")) == NULL &&
463 (dp = strstr(cp, "/" SNAP_BLOCK_NAME "/")) == NULL &&
464 (dp = strrchr(cp, '/')) == NULL) {
465 /* this is not really possible */
466 free(cp);
467 return (strdup(""));
469 dp++;
471 if ((new_path = malloc(strlen(cp)+2)) == NULL) {
472 free(cp);
473 return (NULL);
475 (void) strncpy(new_path, cp, dp - cp);
476 /* fill in the rest of the raw name */
477 new_path[dp - cp] = 'r';
478 (void) strcpy(new_path + (dp - cp) + 1, dp);
480 if (test_if_raw(new_path, blk_dev)) {
481 free(cp);
482 return (new_path);
484 free(new_path);
486 dp = getrawcomplete(cp, &buf);
487 free(cp);
488 return (dp);