1 /*
2  *	FreeBSD loop device support
3  *	Copyright © Jan Engelhardt, 2009
4  *
5  *	This file is part of pam_mount; you can redistribute it and/or
6  *	modify it under the terms of the GNU Lesser General Public License
7  *	as published by the Free Software Foundation; either version 2.1
8  *	of the License, or (at your option) any later version.
9  */
10 #include <sys/ioctl.h>
11 #include <sys/stat.h>
12 #include <errno.h>
13 #include <fcntl.h>
14 #include <stdbool.h>
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <unistd.h>
19 #include <libHX/defs.h>
20 #include <libHX/string.h>
21 #include <sys/mdioctl.h>
22 #include "pam_mount.h"
23 
pmt_loop_setup(const char * filename,char ** result,bool ro)24 int pmt_loop_setup(const char *filename, char **result, bool ro)
25 {
26 	struct stat sb;
27 	struct md_ioctl info = {
28 		.md_version = MDIOVERSION,
29 		.md_type    = MD_VNODE,
30 		.md_options = MD_CLUSTER | MD_AUTOUNIT | MD_COMPRESS |
31 		              (ro ? MD_READONLY : 0),
32 		.md_file    = const_cast1(char *, filename),
33 	};
34 	int ret, fd;
35 
36 	if (stat(filename, &sb) < 0)
37 		return -errno;
38 	info.md_mediasize = sb.st_size;
39 
40 	if ((fd = open("/dev/" MDCTL_NAME, O_RDWR)) < 0)
41 		return -errno;
42 	if ((ret = ioctl(fd, MDIOCATTACH, &info)) == 0) {
43 		char buf[64];
44 		snprintf(buf, sizeof(buf), "/dev/" MD_NAME "%u", info.md_unit);
45 		*result = HX_strdup(buf);
46 		ret = 1;
47 	} else {
48 		ret = -errno;
49 	}
50 	close(fd);
51 	return ret;
52 }
53 
pmt_loop_release(const char * device)54 int pmt_loop_release(const char *device)
55 {
56 	struct md_ioctl info = {.md_version = MDIOVERSION};
57 	int ret, fd;
58 	char *end;
59 
60 	if (strncmp(device, "/dev/", 5) == 0)
61 		device += 5;
62 	if (strncmp(device, "md", 2) == 0)
63 		device += 2;
64 	info.md_unit = strtol(device, &end, 0);
65 	if (device == end || *end != '\0')
66 		return -ENXIO;
67 
68 	if ((fd = open("/dev/" MDCTL_NAME, O_RDWR)) < 0)
69 		return -errno;
70 	if (ioctl(fd, MDIOCDETACH, &info) < 0)
71 		ret = -errno;
72 	else
73 		ret = 1;
74 	close(fd);
75 	return ret;
76 }
77