]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - libhandle/handle.c
9b635dcc2c9580a56271b1fbd4e08022bd14d44d
[thirdparty/xfsprogs-dev.git] / libhandle / handle.c
1 /*
2 * Copyright (c) 1995-2001 Silicon Graphics, Inc. All Rights Reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2.1 of the GNU Lesser General Public License
6 * as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it would be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 *
12 * Further, this software is distributed without any warranty that it is
13 * free of the rightful claim of any third person regarding infringement
14 * or the like. Any license provided herein, whether implied or
15 * otherwise, applies only to this software file. Patent licenses, if
16 * any, provided herein do not apply to combinations of this program with
17 * other software, or any other product whatsoever.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this program; if not, write the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307,
22 * USA.
23 *
24 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
25 * Mountain View, CA 94043, or:
26 *
27 * http://www.sgi.com
28 *
29 * For further information regarding this notice, see:
30 *
31 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
32 */
33
34 #include <libxfs.h>
35 #include <sys/stat.h>
36 #include <sys/ioctl.h>
37 #include "handle.h"
38
39 /* just pick a value we know is more than big enough */
40 #define MAXHANSIZ 64
41
42 /*
43 * The actual content of a handle is supposed to be opaque here.
44 * But, to do handle_to_fshandle, we need to know what it is. Sigh.
45 * However we can get by with knowing only that the first 8 bytes of
46 * a file handle are the file system ID, and that a file system handle
47 * consists of only those 8 bytes.
48 */
49
50 #define FSIDSIZE 8
51
52 typedef union {
53 int fd;
54 char *path;
55 } comarg_t;
56
57
58 int
59 obj_to_handle (
60 int fsfd,
61 unsigned int opcode,
62 comarg_t obj,
63 void **hanp,
64 size_t *hlen);
65
66
67 /*
68 * Filesystem Handle -> Open File Descriptor Cache
69 *
70 * Maps filesystem handles to a corresponding open file descriptor for that
71 * filesystem. We need this because we're doing handle operations via ioctl
72 * and we need to remember the open file descriptor for each filesystem.
73 */
74
75 struct fdhash {
76 int fsfd;
77 char fsh[FSIDSIZE];
78 struct fdhash *fnxt;
79 };
80
81 struct fdhash *fdhash_head = NULL;
82
83 int
84 path_to_fshandle (
85 char *path, /* input, path to convert */
86 void **hanp, /* output, pointer to data */
87 size_t *hlen) /* output, size of returned data */
88 {
89 int result;
90 int fd;
91 comarg_t obj;
92 struct fdhash *fdhp;
93
94 fd = open(path, O_RDONLY);
95
96 if (fd < 0) {
97 perror(path);
98 exit(1);
99 }
100
101 obj.path = path;
102
103 result = obj_to_handle (fd, XFS_IOC_PATH_TO_FSHANDLE,
104 obj, hanp, hlen);
105
106 if (result >= 0) {
107 fdhp = malloc(sizeof(struct fdhash));
108
109 if (fdhp == NULL) {
110 errno = ENOMEM;
111 return -1;
112 }
113
114 fdhp->fsfd = fd;
115 fdhp->fnxt = NULL;
116
117 memcpy(fdhp->fsh, *hanp, FSIDSIZE);
118
119 if (fdhash_head)
120 fdhash_head->fnxt = fdhp;
121 else
122 fdhash_head = fdhp;
123 }
124
125 return result;
126 }
127
128
129 int
130 path_to_handle (
131 char *path, /* input, path to convert */
132 void **hanp, /* output, pointer to data */
133 size_t *hlen) /* output, size of returned data */
134 {
135 int fd;
136 int result;
137 comarg_t obj;
138
139 fd = open(path, O_RDONLY);
140
141 if (fd < 0) {
142 perror(path);
143 exit(1);
144 }
145
146 obj.path = path;
147
148 result = obj_to_handle (fd, XFS_IOC_PATH_TO_HANDLE, obj, hanp, hlen);
149
150 close(fd);
151
152 return result;
153 }
154
155
156 int
157 fd_to_handle (
158 int fd, /* input, file descriptor */
159 void **hanp, /* output, pointer to data */
160 size_t *hlen) /* output, size of returned data */
161 {
162 comarg_t obj;
163
164 obj.fd = fd;
165
166 return obj_to_handle (fd, XFS_IOC_FD_TO_HANDLE, obj, hanp, hlen);
167 }
168
169
170 int
171 handle_to_fshandle (
172 void *hanp,
173 size_t hlen,
174 void **fshanp,
175 size_t *fshlen)
176 {
177 if (hlen < FSIDSIZE)
178 return EINVAL;
179
180 *fshanp = malloc (FSIDSIZE);
181
182 if (*fshanp == NULL)
183 return ENOMEM;
184
185 *fshlen = FSIDSIZE;
186
187 memcpy(*fshanp, hanp, FSIDSIZE);
188
189 return 0;
190 }
191
192
193 int
194 handle_to_fsfd(void *hanp)
195 {
196 struct fdhash *fdhp;
197
198 for (fdhp = fdhash_head; fdhp != NULL; fdhp = fdhp->fnxt) {
199 if (memcmp(fdhp->fsh, hanp, FSIDSIZE) == 0)
200 return fdhp->fsfd;
201 }
202 return -1;
203 }
204
205
206 int
207 obj_to_handle (
208 int fsfd,
209 unsigned int opcode,
210 comarg_t obj,
211 void **hanp,
212 size_t *hlen)
213 {
214 char hbuf [MAXHANSIZ];
215 int ret;
216 xfs_fsop_handlereq_t hreq;
217
218 if (opcode == XFS_IOC_FD_TO_HANDLE) {
219 hreq.fd = obj.fd;
220 hreq.path = NULL;
221 } else {
222 hreq.fd = 0;
223 hreq.path = obj.path;
224 }
225
226 hreq.oflags = 0;
227 hreq.ihandle = NULL;
228 hreq.ihandlen = 0;
229 hreq.ohandle = hbuf;
230 hreq.ohandlen = (__u32 *)hlen;
231
232 ret = (int) ioctl(fsfd, opcode, &hreq);
233
234 if (ret)
235 return ret;
236
237 *hanp = malloc(*hlen);
238
239 if (*hanp == NULL) {
240 errno = ENOMEM;
241 return -1;
242 }
243
244 memcpy(*hanp, hbuf, (int) *hlen);
245
246 return 0;
247 }
248
249
250
251 int
252 open_by_handle (
253 void *hanp,
254 size_t hlen,
255 int rw)
256 {
257 int fd;
258 int result;
259 xfs_fsop_handlereq_t hreq;
260
261 if ((fd = handle_to_fsfd(hanp)) < 0) {
262 errno = EBADF;
263 return -1;
264 }
265
266 hreq.fd = 0;
267 hreq.path = NULL;
268 hreq.oflags = rw;
269 hreq.ihandle = hanp;
270 hreq.ihandlen = hlen;
271 hreq.ohandle = NULL;
272 hreq.ohandlen = NULL;
273
274 result = ioctl(fd, XFS_IOC_OPEN_BY_HANDLE, &hreq);
275
276 return result;
277 }
278
279 int
280 readlink_by_handle (
281 void *hanp,
282 size_t hlen,
283 void *buf,
284 size_t bufsiz)
285 {
286 int fd;
287 xfs_fsop_handlereq_t hreq;
288
289
290 if ((fd = handle_to_fsfd(hanp)) < 0) {
291 errno = EBADF;
292 return -1;
293 }
294
295 hreq.fd = 0;
296 hreq.path = NULL;
297 hreq.oflags = 0;
298 hreq.ihandle = hanp;
299 hreq.ihandlen = hlen;
300 hreq.ohandle = buf;
301 hreq.ohandlen = (__u32 *)&bufsiz;
302
303 return (int) ioctl(fd, XFS_IOC_READLINK_BY_HANDLE, &hreq);
304 }
305
306 int
307 fssetdm_by_handle (
308 void *hanp,
309 size_t hlen,
310 struct fsdmidata *fsdmidata)
311 {
312 int fd;
313 xfs_fsop_setdm_handlereq_t dmhreq;
314
315
316 if ((fd = handle_to_fsfd(hanp)) < 0) {
317 errno = EBADF;
318 return -1;
319 }
320
321 dmhreq.hreq.fd = 0;
322 dmhreq.hreq.path = NULL;
323 dmhreq.hreq.oflags = 0;
324 dmhreq.hreq.ihandle = hanp;
325 dmhreq.hreq.ihandlen = hlen;
326 dmhreq.hreq.ohandle = NULL;
327 dmhreq.hreq.ohandlen = NULL;
328
329 dmhreq.data = fsdmidata;
330
331 return (int) ioctl(fd, XFS_IOC_FSSETDM_BY_HANDLE, &dmhreq);
332 }
333
334 /*ARGSUSED*/
335 void
336 free_handle (
337 void *hanp,
338 size_t hlen)
339 {
340 free (hanp);
341 }