xref: /openbsd-src/lib/libutil/readlabel.c (revision df69c215c7c66baf660f3f65414fd34796c96152)
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