1*df69c215Sderaadt /* $OpenBSD: readlabel.c,v 1.15 2019/06/28 13:32:43 deraadt Exp $ */
29df802a6Sdownsj
39df802a6Sdownsj /*
49df802a6Sdownsj * Copyright (c) 1996, Jason Downs. All rights reserved.
59df802a6Sdownsj *
69df802a6Sdownsj * Redistribution and use in source and binary forms, with or without
79df802a6Sdownsj * modification, are permitted provided that the following conditions
89df802a6Sdownsj * are met:
99df802a6Sdownsj * 1. Redistributions of source code must retain the above copyright
109df802a6Sdownsj * notice, this list of conditions and the following disclaimer.
119df802a6Sdownsj * 2. Redistributions in binary form must reproduce the above copyright
129df802a6Sdownsj * notice, this list of conditions and the following disclaimer in the
139df802a6Sdownsj * documentation and/or other materials provided with the distribution.
149df802a6Sdownsj *
159df802a6Sdownsj * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS
169df802a6Sdownsj * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
179df802a6Sdownsj * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
189df802a6Sdownsj * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT,
199df802a6Sdownsj * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
209df802a6Sdownsj * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
219df802a6Sdownsj * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
229df802a6Sdownsj * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
239df802a6Sdownsj * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
249df802a6Sdownsj * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
259df802a6Sdownsj * SUCH DAMAGE.
269df802a6Sdownsj */
279df802a6Sdownsj
28aea60beeSderaadt #include <sys/types.h>
292e9a2e3eSderaadt #include <sys/disk.h>
302e9a2e3eSderaadt #include <sys/dkio.h>
312e9a2e3eSderaadt #define DKTYPENAMES
322e9a2e3eSderaadt #include <sys/disklabel.h>
332e9a2e3eSderaadt #include <sys/ioctl.h>
342e9a2e3eSderaadt #include <sys/stat.h>
359df802a6Sdownsj #include <stdio.h>
369df802a6Sdownsj #include <err.h>
379df802a6Sdownsj #include <errno.h>
38aea60beeSderaadt #include <limits.h>
399df802a6Sdownsj #include <fcntl.h>
409df802a6Sdownsj #include <paths.h>
419df802a6Sdownsj #include <string.h>
42abf39cbdSmillert #include <unistd.h>
439df802a6Sdownsj
4479822b59Smillert #include "util.h"
4579822b59Smillert
469df802a6Sdownsj /*
479df802a6Sdownsj * Try to get a disklabel for the specified device, and return mount_xxx
489df802a6Sdownsj * style filesystem type name for the specified partition.
499df802a6Sdownsj */
501477552aSderaadt char *
readlabelfs(char * device,int verbose)511477552aSderaadt readlabelfs(char *device, int verbose)
529df802a6Sdownsj {
53aea60beeSderaadt char rpath[PATH_MAX];
54e1569330Sjsing struct dk_diskmap dm;
551477552aSderaadt struct disklabel dk;
56743807c4Sdownsj char part, *type;
579df802a6Sdownsj struct stat sbuf;
58e1569330Sjsing int fd = -1;
59e1569330Sjsing
60e1569330Sjsing /* Perform disk mapping if device is given as a DUID. */
61e1569330Sjsing if (isduid(device, 0)) {
62478ad52bSguenther if ((fd = open("/dev/diskmap", O_RDONLY|O_CLOEXEC)) != -1) {
63e1569330Sjsing bzero(&dm, sizeof(struct dk_diskmap));
64e1569330Sjsing strlcpy(rpath, device, sizeof(rpath));
65e1569330Sjsing part = rpath[strlen(rpath) - 1];
66e1569330Sjsing dm.device = rpath;
67e1569330Sjsing dm.fd = fd;
68e1569330Sjsing dm.flags = DM_OPENPART;
69e1569330Sjsing if (ioctl(fd, DIOCMAP, &dm) == -1)
70e1569330Sjsing close(fd);
71e1569330Sjsing else
72e1569330Sjsing goto disklabel;
73e1569330Sjsing }
74e1569330Sjsing }
759df802a6Sdownsj
769df802a6Sdownsj /* Assuming device is of the form /dev/??p, build a raw partition. */
77*df69c215Sderaadt if (stat(device, &sbuf) == -1) {
789ae26e7fSdownsj if (verbose)
799df802a6Sdownsj warn("%s", device);
809df802a6Sdownsj return (NULL);
819df802a6Sdownsj }
829df802a6Sdownsj switch (sbuf.st_mode & S_IFMT) {
839df802a6Sdownsj case S_IFCHR:
849df802a6Sdownsj /* Ok... already a raw device. Hmm. */
85e1569330Sjsing strlcpy(rpath, device, sizeof(rpath));
869df802a6Sdownsj
879df802a6Sdownsj /* Change partition name. */
889df802a6Sdownsj part = rpath[strlen(rpath) - 1];
899df802a6Sdownsj rpath[strlen(rpath) - 1] = 'a' + getrawpartition();
909df802a6Sdownsj break;
919df802a6Sdownsj case S_IFBLK:
928f0e046dSderaadt if (strlen(device) > sizeof(_PATH_DEV) - 1) {
939df802a6Sdownsj snprintf(rpath, sizeof(rpath), "%sr%s", _PATH_DEV,
943332ec12Sfgsch &device[sizeof(_PATH_DEV) - 1]);
959df802a6Sdownsj /* Change partition name. */
969df802a6Sdownsj part = rpath[strlen(rpath) - 1];
979df802a6Sdownsj rpath[strlen(rpath) - 1] = 'a' + getrawpartition();
989df802a6Sdownsj break;
999df802a6Sdownsj }
1004e632a0cSderaadt /* FALLTHROUGH */
1019df802a6Sdownsj default:
1029ae26e7fSdownsj if (verbose)
1039df802a6Sdownsj warnx("%s: not a device node", device);
1049df802a6Sdownsj return (NULL);
1059df802a6Sdownsj }
1069df802a6Sdownsj
1079df802a6Sdownsj /* If rpath doesn't exist, change that partition back. */
108478ad52bSguenther fd = open(rpath, O_RDONLY|O_CLOEXEC);
109*df69c215Sderaadt if (fd == -1) {
1109df802a6Sdownsj if (errno == ENOENT) {
1119df802a6Sdownsj rpath[strlen(rpath) - 1] = part;
1129df802a6Sdownsj
113478ad52bSguenther fd = open(rpath, O_RDONLY|O_CLOEXEC);
114*df69c215Sderaadt if (fd == -1) {
1159ae26e7fSdownsj if (verbose)
1169df802a6Sdownsj warn("%s", rpath);
1179df802a6Sdownsj return (NULL);
1189df802a6Sdownsj }
1199df802a6Sdownsj } else {
1209ae26e7fSdownsj if (verbose)
1219df802a6Sdownsj warn("%s", rpath);
1229df802a6Sdownsj return (NULL);
1239df802a6Sdownsj }
1249df802a6Sdownsj }
125e1569330Sjsing
126e1569330Sjsing disklabel:
127e1569330Sjsing
128*df69c215Sderaadt if (ioctl(fd, DIOCGDINFO, &dk) == -1) {
1299ae26e7fSdownsj if (verbose)
1309df802a6Sdownsj warn("%s: couldn't read disklabel", rpath);
1319df802a6Sdownsj close(fd);
1329df802a6Sdownsj return (NULL);
1339df802a6Sdownsj }
1349df802a6Sdownsj close(fd);
1359df802a6Sdownsj
136d64f7975Skrw if (dk.d_partitions[part - 'a'].p_fstype >= FSMAXTYPES) {
1379ae26e7fSdownsj if (verbose)
1389df802a6Sdownsj warnx("%s: bad filesystem type in label", rpath);
1399df802a6Sdownsj return (NULL);
1409df802a6Sdownsj }
1419df802a6Sdownsj
142743807c4Sdownsj type = fstypesnames[dk.d_partitions[part - 'a'].p_fstype];
143743807c4Sdownsj return ((type[0] == '\0') ? NULL : type);
1449df802a6Sdownsj }
145