1 /* $OpenBSD: opendev.c,v 1.17 2022/08/26 21:47:16 kn Exp $ */ 2 3 /* 4 * Copyright (c) 2000, Todd C. Miller. All rights reserved. 5 * Copyright (c) 1996, Jason Downs. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS 17 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, 20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include <errno.h> 30 #include <fcntl.h> 31 #include <limits.h> 32 #include <paths.h> 33 #include <stdio.h> 34 #include <string.h> 35 #include <unistd.h> 36 37 #include <sys/ioctl.h> 38 #include <sys/limits.h> 39 #include <sys/disk.h> 40 #include <sys/dkio.h> 41 42 #include "util.h" 43 44 /* 45 * This routine is a generic rewrite of the original code found in 46 * disklabel(8). 47 */ 48 int 49 opendev(const char *path, int oflags, int dflags, char **realpath) 50 { 51 static char namebuf[PATH_MAX]; 52 struct dk_diskmap dm; 53 char *slash, *prefix; 54 int fd; 55 56 /* Initial state */ 57 fd = -1; 58 errno = ENOENT; 59 60 if (dflags & OPENDEV_BLCK) 61 prefix = ""; /* block device */ 62 else 63 prefix = "r"; /* character device */ 64 65 if ((slash = strchr(path, '/'))) { 66 strlcpy(namebuf, path, sizeof(namebuf)); 67 fd = open(namebuf, oflags); 68 } else if (isduid(path, dflags)) { 69 strlcpy(namebuf, path, sizeof(namebuf)); 70 if ((fd = open("/dev/diskmap", oflags)) != -1) { 71 bzero(&dm, sizeof(struct dk_diskmap)); 72 dm.device = namebuf; 73 dm.fd = fd; 74 if (dflags & OPENDEV_PART) 75 dm.flags |= DM_OPENPART; 76 if (dflags & OPENDEV_BLCK) 77 dm.flags |= DM_OPENBLCK; 78 79 if (ioctl(fd, DIOCMAP, &dm) == -1) { 80 close(fd); 81 fd = -1; 82 errno = ENOENT; 83 } 84 } 85 } 86 if (!slash && fd == -1 && errno == ENOENT) { 87 if (dflags & OPENDEV_PART) { 88 /* 89 * First try raw partition (for removable drives) 90 */ 91 if (snprintf(namebuf, sizeof(namebuf), "%s%s%s%c", 92 _PATH_DEV, prefix, path, 'a' + getrawpartition()) 93 < sizeof(namebuf)) { 94 fd = open(namebuf, oflags); 95 } else 96 errno = ENAMETOOLONG; 97 } 98 if (fd == -1 && errno == ENOENT) { 99 if (snprintf(namebuf, sizeof(namebuf), "%s%s%s", 100 _PATH_DEV, prefix, path) < sizeof(namebuf)) { 101 fd = open(namebuf, oflags); 102 } else 103 errno = ENAMETOOLONG; 104 } 105 } 106 if (realpath) 107 *realpath = namebuf; 108 109 return (fd); 110 } 111