1 /*
2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
5 * 1.0 of the CDDL.
6 *
7 * A full copy of the text of the CDDL should have accompanied this
8 * source. A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
10 */
11
12 /*
13 * Copyright 2013 Damian Bogel. All rights reserved.
14 */
15
16 /*
17 * Library used to drive the fsd pseudo-device driver.
18 */
19
20 #include <fcntl.h>
21 #include <libfsd.h>
22 #include <string.h>
23 #include <stropts.h>
24 #include <sys/errno.h>
25 #include <sys/fsd.h>
26 #include <sys/stat.h>
27 #include <sys/types.h>
28 #include <unistd.h>
29
30 __thread int fsd_errno;
31
32 const char *
33 fsd_strerr(int e)
34 {
35 switch (e) {
36 case EFSD_NOERROR:
37 return ("no error");
38 case EFSD_BAD_STAT:
39 return ("incorrect disturbance parameters");
40 case EFSD_INTERNAL:
41 return ("internal library error");
42 case EFSD_CANT_OPEN_DRIVER:
43 return ("cannot open fsd device");
44 case EFSD_CANT_OPEN_MOUNTPOINT:
45 return ("cannot open mountpoint");
46 case EFSD_ENTRY_NOT_FOUND:
47 return ("this vfs is not being disturbed");
48 case EFSD_FAULT:
49 return ("bad pointer");
50 case EFSD_UNKNOWN_ERROR:
51 default:
52 return ("unknown error");
53 }
54 }
55
56 static int
57 fsd_ioctl_set_errno(int ioctl_ret)
58 {
59 extern int errno;
60 int e;
61
62 switch (ioctl_ret) {
63 case 0:
64 fsd_errno = EFSD_NOERROR;
65 return (0);
66
67 case (-1):
68 e = errno;
69 switch (e) {
70 case 0:
71 fsd_errno = EFSD_NOERROR;
72 break;
73 case EFAULT:
74 fsd_errno = EFSD_FAULT;
75 break;
76 case EINVAL:
77 fsd_errno = EFSD_INTERNAL;
78 break;
79 default:
80 fsd_errno = EFSD_UNKNOWN_ERROR;
81 break;
82 }
83 break;
84 case FSD_ENTRY_NOT_FOUND:
85 fsd_errno = EFSD_ENTRY_NOT_FOUND;
86 break;
87 case FSD_BAD_STAT:
88 fsd_errno = EFSD_BAD_STAT;
89 break;
90 case FSD_BAD_FD:
91 fsd_errno = EFSD_CANT_OPEN_MOUNTPOINT;
92 break;
93 default:
94 fsd_errno = EFSD_UNKNOWN_ERROR;
95 break;
96 }
97
98 return (-1);
99
100 }
101
102 int
103 fsd_open()
104 {
105 int fd;
106
107 if ((fd = open(FSD_DEV_PATH, O_RDWR)) == -1) {
108 fsd_errno = EFSD_CANT_OPEN_DRIVER;
109 return (-1);
110 }
111 return (fd);
112 }
113
114 void
115 fsd_close(int fd)
116 {
117 (void) close(fd);
118 }
119
120 int
121 fsd_enable(int fd)
122 {
123 return (fsd_ioctl_set_errno(ioctl(fd, FSD_ENABLE)));
124 }
125
126 int
127 fsd_disable(int fd)
128 {
129 return (fsd_ioctl_set_errno(ioctl(fd, FSD_DISABLE)));
130 }
131
132 int
133 fsd_disturb(int fd, const char *mntpt_path, fsd_stat_t *stat)
134 {
135 fsd_ioc_stat_t iocs;
136 int error;
137
138 if ((iocs.fsdis_mnt = open(mntpt_path, O_RDONLY)) == -1) {
139 fsd_errno = EFSD_CANT_OPEN_MOUNTPOINT;
140 return (-1);
141 }
142
143 (void) memcpy(&iocs.fsdis_stat, stat, sizeof (iocs.fsdis_stat));
144
145 error = ioctl(fd, FSD_DISTURB, &iocs);
146 (void) close(iocs.fsdis_mnt);
147 return (fsd_ioctl_set_errno(error));
148 }
149
150 int
151 fsd_disturb_off(int fd, const char *mntpt_path)
152 {
153 int error;
154 int64_t mntfd;
155
156 if ((mntfd = open(mntpt_path, O_RDONLY)) == -1) {
157 fsd_errno = EFSD_CANT_OPEN_MOUNTPOINT;
158 return (-1);
159 }
160
161 error = ioctl(fd, FSD_NODISTURB, &mntfd);
162 (void) close(mntfd);
163 return (fsd_ioctl_set_errno(error));
164 }
165
166 int
167 fsd_newdisturb(int fd, fsd_stat_t *stat)
168 {
169 return (fsd_ioctl_set_errno(ioctl(fd, FSD_DISTURB_NEW, stat)));
170 }
171
172 int
173 fsd_newdisturb_off(int fd)
174 {
175 return (fsd_ioctl_set_errno(ioctl(fd, FSD_NODISTURB_NEW)));
176 }