1*0a6a1f1dSLionel Sambuc /* $NetBSD: getfsspecname.c,v 1.5 2014/05/25 13:46:07 christos Exp $ */
2dba3562dSLionel Sambuc
3dba3562dSLionel Sambuc /*-
4dba3562dSLionel Sambuc * Copyright (c) 2012 The NetBSD Foundation, Inc.
5dba3562dSLionel Sambuc * All rights reserved.
6dba3562dSLionel Sambuc *
7dba3562dSLionel Sambuc * This code is derived from software contributed to The NetBSD Foundation
8dba3562dSLionel Sambuc * by Christos Zoulas.
9dba3562dSLionel Sambuc *
10dba3562dSLionel Sambuc * Redistribution and use in source and binary forms, with or without
11dba3562dSLionel Sambuc * modification, are permitted provided that the following conditions
12dba3562dSLionel Sambuc * are met:
13dba3562dSLionel Sambuc * 1. Redistributions of source code must retain the above copyright
14dba3562dSLionel Sambuc * notice, this list of conditions and the following disclaimer.
15dba3562dSLionel Sambuc * 2. Redistributions in binary form must reproduce the above copyright
16dba3562dSLionel Sambuc * notice, this list of conditions and the following disclaimer in the
17dba3562dSLionel Sambuc * documentation and/or other materials provided with the distribution.
18dba3562dSLionel Sambuc *
19dba3562dSLionel Sambuc * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20dba3562dSLionel Sambuc * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21dba3562dSLionel Sambuc * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22dba3562dSLionel Sambuc * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23dba3562dSLionel Sambuc * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24dba3562dSLionel Sambuc * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25dba3562dSLionel Sambuc * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26dba3562dSLionel Sambuc * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27dba3562dSLionel Sambuc * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28dba3562dSLionel Sambuc * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29dba3562dSLionel Sambuc * POSSIBILITY OF SUCH DAMAGE.
30dba3562dSLionel Sambuc */
31dba3562dSLionel Sambuc #include <sys/cdefs.h>
32*0a6a1f1dSLionel Sambuc __RCSID("$NetBSD: getfsspecname.c,v 1.5 2014/05/25 13:46:07 christos Exp $");
33dba3562dSLionel Sambuc
34dba3562dSLionel Sambuc #include <sys/types.h>
3584d9c625SLionel Sambuc #include <sys/ioctl.h>
36dba3562dSLionel Sambuc #include <sys/sysctl.h>
37dba3562dSLionel Sambuc #include <sys/disk.h>
38dba3562dSLionel Sambuc
39dba3562dSLionel Sambuc #include <stdio.h>
40dba3562dSLionel Sambuc #include <vis.h>
41dba3562dSLionel Sambuc #include <string.h>
42dba3562dSLionel Sambuc #include <fstab.h>
43dba3562dSLionel Sambuc #include <fcntl.h>
44dba3562dSLionel Sambuc #include <stdlib.h>
45dba3562dSLionel Sambuc #include <errno.h>
46dba3562dSLionel Sambuc #include <unistd.h>
47dba3562dSLionel Sambuc #include <util.h>
48dba3562dSLionel Sambuc
4984d9c625SLionel Sambuc #if !defined(__minix)
50dba3562dSLionel Sambuc #define COMPAT_DKWEDGE /* To be removed */
5184d9c625SLionel Sambuc #endif /* !defined(__minix) */
52dba3562dSLionel Sambuc
53dba3562dSLionel Sambuc const char *
getfsspecname(char * buf,size_t bufsiz,const char * name)54dba3562dSLionel Sambuc getfsspecname(char *buf, size_t bufsiz, const char *name)
55dba3562dSLionel Sambuc {
56dba3562dSLionel Sambuc static const int mib[] = { CTL_HW, HW_DISKNAMES };
57dba3562dSLionel Sambuc static const unsigned int miblen = __arraycount(mib);
58*0a6a1f1dSLionel Sambuc char *drives, *dk, *p;
59dba3562dSLionel Sambuc size_t len;
60*0a6a1f1dSLionel Sambuc int fd, savee = errno;
61dba3562dSLionel Sambuc char *vname;
62dba3562dSLionel Sambuc
63*0a6a1f1dSLionel Sambuc p = drives = vname = NULL;
64dba3562dSLionel Sambuc if (strncasecmp(name, "NAME=", 5) != 0) {
65dba3562dSLionel Sambuc #ifdef COMPAT_DKWEDGE
66dba3562dSLionel Sambuc /*
67dba3562dSLionel Sambuc * We try to open the disk name, and if we fail with EBUSY
68dba3562dSLionel Sambuc * we use the name as the label to find the wedge.
69dba3562dSLionel Sambuc */
70dba3562dSLionel Sambuc char rbuf[MAXPATHLEN];
71dba3562dSLionel Sambuc if (name[0] == '/') {
72dba3562dSLionel Sambuc if (getdiskrawname(rbuf, sizeof(rbuf), name) != NULL) {
73dba3562dSLionel Sambuc if ((fd = open(rbuf, O_RDONLY)) == -1) {
74dba3562dSLionel Sambuc if (errno == EBUSY) {
75dba3562dSLionel Sambuc name = strrchr(name, '/') + 1;
76dba3562dSLionel Sambuc goto search;
77dba3562dSLionel Sambuc }
78dba3562dSLionel Sambuc } else
79dba3562dSLionel Sambuc close(fd);
80dba3562dSLionel Sambuc }
81dba3562dSLionel Sambuc }
82dba3562dSLionel Sambuc #endif
83dba3562dSLionel Sambuc strlcpy(buf, name, bufsiz);
84dba3562dSLionel Sambuc return buf;
85dba3562dSLionel Sambuc } else
86dba3562dSLionel Sambuc name += 5;
87dba3562dSLionel Sambuc
88dba3562dSLionel Sambuc #ifdef COMPAT_DKWEDGE
89dba3562dSLionel Sambuc search:
90dba3562dSLionel Sambuc #endif
91dba3562dSLionel Sambuc vname = malloc(strlen(name) * 4 + 1);
92dba3562dSLionel Sambuc if (vname == NULL) {
93dba3562dSLionel Sambuc savee = errno;
94dba3562dSLionel Sambuc strlcpy(buf, "malloc failed", bufsiz);
95dba3562dSLionel Sambuc goto out;
96dba3562dSLionel Sambuc }
97dba3562dSLionel Sambuc
98dba3562dSLionel Sambuc strunvis(vname, name);
99dba3562dSLionel Sambuc
100dba3562dSLionel Sambuc if (sysctl(mib, miblen, NULL, &len, NULL, 0) == -1) {
101dba3562dSLionel Sambuc savee = errno;
102dba3562dSLionel Sambuc strlcpy(buf, "sysctl hw.disknames failed", bufsiz);
103dba3562dSLionel Sambuc goto out;
104dba3562dSLionel Sambuc }
105dba3562dSLionel Sambuc
106dba3562dSLionel Sambuc drives = malloc(len);
107dba3562dSLionel Sambuc if (drives == NULL) {
108dba3562dSLionel Sambuc savee = errno;
109dba3562dSLionel Sambuc strlcpy(buf, "malloc failed", bufsiz);
110dba3562dSLionel Sambuc goto out;
111dba3562dSLionel Sambuc }
112dba3562dSLionel Sambuc if (sysctl(mib, miblen, drives, &len, NULL, 0) == -1) {
113dba3562dSLionel Sambuc savee = errno;
114dba3562dSLionel Sambuc strlcpy(buf, "sysctl hw.disknames failed", bufsiz);
115dba3562dSLionel Sambuc goto out;
116dba3562dSLionel Sambuc }
117dba3562dSLionel Sambuc
118dba3562dSLionel Sambuc for (dk = strtok(drives, " "); dk != NULL; dk = strtok(NULL, " ")) {
119dba3562dSLionel Sambuc struct dkwedge_info dkw;
120dba3562dSLionel Sambuc if (strncmp(dk, "dk", 2) != 0)
121dba3562dSLionel Sambuc continue;
122dba3562dSLionel Sambuc fd = opendisk(dk, O_RDONLY, buf, bufsiz, 0);
123dba3562dSLionel Sambuc if (fd == -1)
124dba3562dSLionel Sambuc continue;
125dba3562dSLionel Sambuc if (ioctl(fd, DIOCGWEDGEINFO, &dkw) == -1) {
126dba3562dSLionel Sambuc savee = errno;
127dba3562dSLionel Sambuc snprintf(buf, bufsiz, "%s: getwedgeinfo", dk);
128dba3562dSLionel Sambuc (void)close(fd);
129dba3562dSLionel Sambuc goto out;
130dba3562dSLionel Sambuc }
131dba3562dSLionel Sambuc (void)close(fd);
132dba3562dSLionel Sambuc if (strcmp(vname, (char *)dkw.dkw_wname) == 0) {
133*0a6a1f1dSLionel Sambuc p = strstr(buf, "/rdk");
134*0a6a1f1dSLionel Sambuc goto good;
135dba3562dSLionel Sambuc }
136dba3562dSLionel Sambuc }
137*0a6a1f1dSLionel Sambuc #ifdef COMPAT_DKWEDGE
138*0a6a1f1dSLionel Sambuc /* Last ditch effort assuming NAME=label, and label is a disk name */
139*0a6a1f1dSLionel Sambuc fd = opendisk(name, O_RDONLY, buf, bufsiz, 0);
140*0a6a1f1dSLionel Sambuc if (fd != -1) {
141*0a6a1f1dSLionel Sambuc close(fd);
142*0a6a1f1dSLionel Sambuc p = strstr(buf, "/r");
143*0a6a1f1dSLionel Sambuc goto good;
144*0a6a1f1dSLionel Sambuc }
145*0a6a1f1dSLionel Sambuc #endif
146dba3562dSLionel Sambuc savee = ESRCH;
147dba3562dSLionel Sambuc snprintf(buf, bufsiz, "no match for `%s'", vname);
148dba3562dSLionel Sambuc out:
149*0a6a1f1dSLionel Sambuc buf = NULL;
150*0a6a1f1dSLionel Sambuc good:
151*0a6a1f1dSLionel Sambuc if (p++ != NULL)
152*0a6a1f1dSLionel Sambuc strcpy(p, p + 1);
153dba3562dSLionel Sambuc free(drives);
154dba3562dSLionel Sambuc free(vname);
155dba3562dSLionel Sambuc errno = savee;
156*0a6a1f1dSLionel Sambuc return buf;
157dba3562dSLionel Sambuc }
158