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
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]
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
30 #include <sys/types.h>
36 #include <sys/param.h>
38 #include <sys/sysmacros.h>
39 #include <sys/vfstab.h>
41 #include <sys/ramdisk.h>
42 #include <sys/fssnap_if.h>
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
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
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).
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.
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.
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.
108 getfullname(char *path
)
110 char cwd
[MAXPATHLEN
];
116 return (strdup(path
));
118 if (getcwd(cwd
, sizeof (cwd
)) == NULL
)
121 /* handle . and .. */
122 if (strncmp(path
, "./", 2) == 0) {
123 /* strip the ./ from the given path */
125 } else if (strncmp(path
, "../", 3) == 0) {
126 /* strip the last directory component from cwd */
127 c
= strrchr(cwd
, '/');
130 /* strip the ../ from the given path */
135 * Adding 2 takes care of slash and null terminator.
137 len
= strlen(cwd
) + strlen(path
) + 2;
138 if ((wa
= malloc(len
)) == NULL
)
141 (void) strcpy(wa
, cwd
);
142 (void) strcat(wa
, "/");
143 (void) strcat(wa
, path
);
149 * test the path/fname to see if is blk special
152 test_if_blk(char *new_path
, dev_t raw_dev
)
156 /* check if we got a char special file */
157 if (stat64(new_path
, &buf
) != 0)
160 if (!S_ISBLK(buf
.st_mode
))
163 if (raw_dev
!= buf
.st_rdev
)
170 * test the path/fname to see if is char special
173 test_if_raw(char *new_path
, dev_t blk_dev
)
177 /* check if we got a char special file */
178 if (stat64(new_path
, &buf
) != 0)
181 if (!S_ISCHR(buf
.st_mode
))
184 if (blk_dev
!= buf
.st_rdev
)
191 * complete getblkrawname() for blk->raw to handle volmgt devices
195 getblkcomplete(char *cp
, struct stat64
*dat
)
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
)
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
))
221 /* try the rdiskette form */
222 if ((dp
= strstr(cp
, "/rdiskette")) != NULL
) {
223 if ((new_path
= malloc(strlen(cp
))) == 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
))
244 * complete getfullrawname() for raw->blk to handle volmgt devices
248 getrawcomplete(char *cp
, struct stat64
*dat
)
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
)
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
))
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
)
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
))
295 /* failed to build raw name, return null string */
303 getvfsspecial(char *path
, int raw_special
)
307 struct vfstab ref_vp
;
309 if ((fp
= fopen("/etc/vfstab", "r")) == NULL
)
312 (void) memset(&ref_vp
, 0, sizeof (struct vfstab
));
315 ref_vp
.vfs_special
= path
;
317 ref_vp
.vfs_fsckdev
= path
;
319 if (getvfsany(fp
, &vp
, &ref_vp
)) {
327 return (vp
.vfs_fsckdev
);
329 return (vp
.vfs_special
);
333 * change the device name to a block device name
336 getfullblkname(char *cp
)
347 * Create a fully qualified name.
349 if ((cp
= getfullname(cp
)) == NULL
)
355 if (stat64(cp
, &buf
) != 0) {
360 if (S_ISBLK(buf
.st_mode
))
363 if (!S_ISCHR(buf
.st_mode
)) {
368 if ((dp
= getvfsspecial(cp
, GET_BLK
)) != NULL
) {
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 */
389 dp
= getblkcomplete(cp
, &buf
);
393 if ((new_path
= malloc(strlen(cp
))) == 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
)) {
404 /* block name was found, return it here */
409 dp
= getblkcomplete(cp
, &buf
);
415 * change the device name to a raw devname
418 getfullrawname(char *cp
)
429 * Create a fully qualified name.
431 if ((cp
= getfullname(cp
)) == NULL
)
437 if (stat64(cp
, &buf
) != 0) {
442 if (S_ISCHR(buf
.st_mode
))
445 if (!S_ISBLK(buf
.st_mode
)) {
450 blk_dev
= buf
.st_rdev
;
452 if ((dp
= getvfsspecial(cp
, GET_RAW
)) != NULL
) {
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 */
471 if ((new_path
= malloc(strlen(cp
)+2)) == 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
)) {
486 dp
= getrawcomplete(cp
, &buf
);