1*531ea1fdSkn /* $OpenBSD: opendev.c,v 1.17 2022/08/26 21:47:16 kn Exp $ */
2c10c62f6Sdownsj
3c10c62f6Sdownsj /*
472ac04f0Smillert * Copyright (c) 2000, Todd C. Miller. All rights reserved.
5c10c62f6Sdownsj * Copyright (c) 1996, Jason Downs. All rights reserved.
6c10c62f6Sdownsj *
7c10c62f6Sdownsj * Redistribution and use in source and binary forms, with or without
8c10c62f6Sdownsj * modification, are permitted provided that the following conditions
9c10c62f6Sdownsj * are met:
10c10c62f6Sdownsj * 1. Redistributions of source code must retain the above copyright
11c10c62f6Sdownsj * notice, this list of conditions and the following disclaimer.
12c10c62f6Sdownsj * 2. Redistributions in binary form must reproduce the above copyright
13c10c62f6Sdownsj * notice, this list of conditions and the following disclaimer in the
14c10c62f6Sdownsj * documentation and/or other materials provided with the distribution.
15c10c62f6Sdownsj *
16c10c62f6Sdownsj * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS
17c10c62f6Sdownsj * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18c10c62f6Sdownsj * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19c10c62f6Sdownsj * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT,
20c10c62f6Sdownsj * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21c10c62f6Sdownsj * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22c10c62f6Sdownsj * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23c10c62f6Sdownsj * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24c10c62f6Sdownsj * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25c10c62f6Sdownsj * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26c10c62f6Sdownsj * SUCH DAMAGE.
27c10c62f6Sdownsj */
28c10c62f6Sdownsj
29c10c62f6Sdownsj #include <errno.h>
30c10c62f6Sdownsj #include <fcntl.h>
3172ac04f0Smillert #include <limits.h>
32c10c62f6Sdownsj #include <paths.h>
3372ac04f0Smillert #include <stdio.h>
3472ac04f0Smillert #include <string.h>
359e5245ddSchl #include <unistd.h>
36c10c62f6Sdownsj
379e5245ddSchl #include <sys/ioctl.h>
389006fa7fSjsing #include <sys/limits.h>
399006fa7fSjsing #include <sys/disk.h>
409006fa7fSjsing #include <sys/dkio.h>
419006fa7fSjsing
42ad69070aSdownsj #include "util.h"
43c10c62f6Sdownsj
44c10c62f6Sdownsj /*
45c10c62f6Sdownsj * This routine is a generic rewrite of the original code found in
46c10c62f6Sdownsj * disklabel(8).
47c10c62f6Sdownsj */
48c10c62f6Sdownsj int
opendev(const char * path,int oflags,int dflags,char ** realpath)4927ad9b61Smillert opendev(const char *path, int oflags, int dflags, char **realpath)
50c10c62f6Sdownsj {
5172ac04f0Smillert static char namebuf[PATH_MAX];
529006fa7fSjsing struct dk_diskmap dm;
531477552aSderaadt char *slash, *prefix;
541477552aSderaadt int fd;
55c10c62f6Sdownsj
5672ac04f0Smillert /* Initial state */
5772ac04f0Smillert fd = -1;
5872ac04f0Smillert errno = ENOENT;
59c10c62f6Sdownsj
6072ac04f0Smillert if (dflags & OPENDEV_BLCK)
6172ac04f0Smillert prefix = ""; /* block device */
6272ac04f0Smillert else
6372ac04f0Smillert prefix = "r"; /* character device */
6472ac04f0Smillert
65557697c5Smillert if ((slash = strchr(path, '/'))) {
66557697c5Smillert strlcpy(namebuf, path, sizeof(namebuf));
67557697c5Smillert fd = open(namebuf, oflags);
68557697c5Smillert } else if (isduid(path, dflags)) {
69557697c5Smillert strlcpy(namebuf, path, sizeof(namebuf));
709006fa7fSjsing if ((fd = open("/dev/diskmap", oflags)) != -1) {
719006fa7fSjsing bzero(&dm, sizeof(struct dk_diskmap));
729006fa7fSjsing dm.device = namebuf;
739006fa7fSjsing dm.fd = fd;
749006fa7fSjsing if (dflags & OPENDEV_PART)
759006fa7fSjsing dm.flags |= DM_OPENPART;
769006fa7fSjsing if (dflags & OPENDEV_BLCK)
779006fa7fSjsing dm.flags |= DM_OPENBLCK;
789006fa7fSjsing
799006fa7fSjsing if (ioctl(fd, DIOCMAP, &dm) == -1) {
809006fa7fSjsing close(fd);
819006fa7fSjsing fd = -1;
829006fa7fSjsing errno = ENOENT;
83557697c5Smillert }
849006fa7fSjsing }
859006fa7fSjsing }
86849ab3f9Smillert if (!slash && fd == -1 && errno == ENOENT) {
87849ab3f9Smillert if (dflags & OPENDEV_PART) {
88c10c62f6Sdownsj /*
8972ac04f0Smillert * First try raw partition (for removable drives)
90c10c62f6Sdownsj */
9172ac04f0Smillert if (snprintf(namebuf, sizeof(namebuf), "%s%s%s%c",
9272ac04f0Smillert _PATH_DEV, prefix, path, 'a' + getrawpartition())
9372ac04f0Smillert < sizeof(namebuf)) {
94ad69070aSdownsj fd = open(namebuf, oflags);
9572ac04f0Smillert } else
9672ac04f0Smillert errno = ENAMETOOLONG;
97c10c62f6Sdownsj }
98849ab3f9Smillert if (fd == -1 && errno == ENOENT) {
9972ac04f0Smillert if (snprintf(namebuf, sizeof(namebuf), "%s%s%s",
10072ac04f0Smillert _PATH_DEV, prefix, path) < sizeof(namebuf)) {
101ad69070aSdownsj fd = open(namebuf, oflags);
10272ac04f0Smillert } else
10372ac04f0Smillert errno = ENAMETOOLONG;
104c10c62f6Sdownsj }
105849ab3f9Smillert }
106557697c5Smillert if (realpath)
107557697c5Smillert *realpath = namebuf;
108557697c5Smillert
109c10c62f6Sdownsj return (fd);
110c10c62f6Sdownsj }
111