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