1 /* $OpenBSD: readlabel.c,v 1.9 2004/09/18 19:24:14 deraadt Exp $ */
2
3 /*
4 * Copyright (c) 1996, Jason Downs. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS
16 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT,
19 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28 #include <sys/types.h>
29 #include <stdio.h>
30 #include <err.h>
31 #include <errno.h>
32 #include <fcntl.h>
33 #include <paths.h>
34 #include <string.h>
35 #include <unistd.h>
36 #include <sys/dkio.h>
37 #define DKTYPENAMES
38 #include <sys/disklabel.h>
39 #include <sys/ioctl.h>
40 #include <sys/param.h>
41 #include <sys/stat.h>
42
43 #include "util.h"
44
45 /*
46 * Try to get a disklabel for the specified device, and return mount_xxx
47 * style filesystem type name for the specified partition.
48 */
49 char *
readlabelfs(char * device,int verbose)50 readlabelfs(char *device, int verbose)
51 {
52 char rpath[MAXPATHLEN];
53 struct disklabel dk;
54 char part, *type;
55 struct stat sbuf;
56 int fd;
57
58 /* Assuming device is of the form /dev/??p, build a raw partition. */
59 if (stat(device, &sbuf) < 0) {
60 if (verbose)
61 warn("%s", device);
62 return (NULL);
63 }
64 switch (sbuf.st_mode & S_IFMT) {
65 case S_IFCHR:
66 /* Ok... already a raw device. Hmm. */
67 strncpy(rpath, device, sizeof(rpath));
68 rpath[sizeof(rpath) - 1] = '\0';
69
70 /* Change partition name. */
71 part = rpath[strlen(rpath) - 1];
72 rpath[strlen(rpath) - 1] = 'a' + getrawpartition();
73 break;
74 case S_IFBLK:
75 if (strlen(device) > sizeof(_PATH_DEV) - 1) {
76 snprintf(rpath, sizeof(rpath), "%sr%s", _PATH_DEV,
77 &device[sizeof(_PATH_DEV) - 1]);
78 /* Change partition name. */
79 part = rpath[strlen(rpath) - 1];
80 rpath[strlen(rpath) - 1] = 'a' + getrawpartition();
81 break;
82 }
83 /* FALLTHROUGH */
84 default:
85 if (verbose)
86 warnx("%s: not a device node", device);
87 return (NULL);
88 }
89
90 /* If rpath doesn't exist, change that partition back. */
91 fd = open(rpath, O_RDONLY);
92 if (fd < 0) {
93 if (errno == ENOENT) {
94 rpath[strlen(rpath) - 1] = part;
95
96 fd = open(rpath, O_RDONLY);
97 if (fd < 0) {
98 if (verbose)
99 warn("%s", rpath);
100 return (NULL);
101 }
102 } else {
103 if (verbose)
104 warn("%s", rpath);
105 return (NULL);
106 }
107 }
108 if (ioctl(fd, DIOCGDINFO, &dk) < 0) {
109 if (verbose)
110 warn("%s: couldn't read disklabel", rpath);
111 close(fd);
112 return (NULL);
113 }
114 close(fd);
115
116 if (dk.d_partitions[part - 'a'].p_fstype > FSMAXTYPES) {
117 if (verbose)
118 warnx("%s: bad filesystem type in label", rpath);
119 return (NULL);
120 }
121
122 type = fstypesnames[dk.d_partitions[part - 'a'].p_fstype];
123 return ((type[0] == '\0') ? NULL : type);
124 }
125