]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - libhandle/handle.c
Rearrange some struct/typedef declarations to work with more compiler variants.
[thirdparty/xfsprogs-dev.git] / libhandle / handle.c
CommitLineData
e9688c1d 1/*
da23017d
NS
2 * Copyright (c) 1995, 2001-2003, 2005 Silicon Graphics, Inc.
3 * All Rights Reserved.
7c49c48b 4 *
da23017d
NS
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public License
7c49c48b
DR
7 * as published by the Free Software Foundation.
8 *
da23017d
NS
9 * This program is distributed in the hope that it would be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU Lesser General Public License for more details.
7c49c48b 13 *
da23017d
NS
14 * You should have received a copy of the GNU Lesser General Public License
15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
e9688c1d
NS
17 */
18
2a1888c5 19#include <xfs/xfs.h>
1d7e80ee 20#include <xfs/handle.h>
258b00ea 21#include <xfs/parent.h>
e9688c1d 22
e9688c1d
NS
23/* just pick a value we know is more than big enough */
24#define MAXHANSIZ 64
25
26/*
27 * The actual content of a handle is supposed to be opaque here.
28 * But, to do handle_to_fshandle, we need to know what it is. Sigh.
29 * However we can get by with knowing only that the first 8 bytes of
30 * a file handle are the file system ID, and that a file system handle
31 * consists of only those 8 bytes.
32 */
33
34#define FSIDSIZE 8
35
36typedef union {
37 int fd;
38 char *path;
39} comarg_t;
40
3fbbdc85
NS
41static int obj_to_handle(char *, int, unsigned int, comarg_t, void**, size_t*);
42static int handle_to_fsfd(void *, char **);
93d9f139 43
89184fbc
AG
44
45/*
46 * Filesystem Handle -> Open File Descriptor Cache
47 *
48 * Maps filesystem handles to a corresponding open file descriptor for that
93d9f139 49 * filesystem. We need this because we're doing handle operations via xfsctl
89184fbc
AG
50 * and we need to remember the open file descriptor for each filesystem.
51 */
e9688c1d
NS
52
53struct fdhash {
54 int fsfd;
55 char fsh[FSIDSIZE];
56 struct fdhash *fnxt;
93d9f139 57 char fspath[MAXPATHLEN];
e9688c1d
NS
58};
59
dc987226 60static struct fdhash *fdhash_head = NULL;
e9688c1d
NS
61
62int
3fbbdc85 63path_to_fshandle(
e9688c1d 64 char *path, /* input, path to convert */
a3cbe7cd
MK
65 void **fshanp, /* output, pointer to data */
66 size_t *fshlen) /* output, size of returned data */
e9688c1d
NS
67{
68 int result;
69 int fd;
70 comarg_t obj;
71 struct fdhash *fdhp;
dc987226 72 char *tmppath;
e9688c1d
NS
73
74 fd = open(path, O_RDONLY);
3fbbdc85
NS
75 if (fd < 0)
76 return -1;
e9688c1d
NS
77
78 obj.path = path;
93d9f139 79 result = obj_to_handle(path, fd, XFS_IOC_PATH_TO_FSHANDLE,
a3cbe7cd 80 obj, fshanp, fshlen);
dc987226
BK
81 if (result < 0) {
82 close(fd);
83 return result;
84 }
da23017d 85
dc987226
BK
86 if (handle_to_fsfd(*fshanp, &tmppath) >= 0) {
87 /* this filesystem is already in the cache */
88 close(fd);
89 } else {
90 /* new filesystem. add it to the cache */
e9688c1d 91 fdhp = malloc(sizeof(struct fdhash));
e9688c1d
NS
92 if (fdhp == NULL) {
93 errno = ENOMEM;
94 return -1;
95 }
96
97 fdhp->fsfd = fd;
93d9f139 98 strncpy(fdhp->fspath, path, sizeof(fdhp->fspath));
a3cbe7cd
MK
99 memcpy(fdhp->fsh, *fshanp, FSIDSIZE);
100
dc987226
BK
101 fdhp->fnxt = fdhash_head;
102 fdhash_head = fdhp;
e9688c1d
NS
103 }
104
105 return result;
106}
107
e9688c1d 108int
3fbbdc85 109path_to_handle(
e9688c1d
NS
110 char *path, /* input, path to convert */
111 void **hanp, /* output, pointer to data */
112 size_t *hlen) /* output, size of returned data */
113{
114 int fd;
115 int result;
116 comarg_t obj;
117
118 fd = open(path, O_RDONLY);
3fbbdc85
NS
119 if (fd < 0)
120 return -1;
e9688c1d
NS
121
122 obj.path = path;
3fbbdc85
NS
123 result = obj_to_handle(path, fd, XFS_IOC_PATH_TO_HANDLE,
124 obj, hanp, hlen);
e9688c1d 125 close(fd);
e9688c1d
NS
126 return result;
127}
128
8967ee43
TS
129
130int
131fd_to_handle (
132 int fd, /* input, file descriptor */
133 void **hanp, /* output, pointer to data */
134 size_t *hlen) /* output, size of returned data */
135{
136 comarg_t obj;
137
138 obj.fd = fd;
139 return obj_to_handle(NULL, fd, XFS_IOC_FD_TO_HANDLE, obj, hanp, hlen);
140}
141
142
e9688c1d 143int
3fbbdc85 144handle_to_fshandle(
e9688c1d
NS
145 void *hanp,
146 size_t hlen,
147 void **fshanp,
148 size_t *fshlen)
149{
dc987226
BK
150 if (hlen < FSIDSIZE) {
151 errno = EINVAL;
152 return -1;
153 }
3fbbdc85 154 *fshanp = malloc(FSIDSIZE);
dc987226
BK
155 if (*fshanp == NULL) {
156 errno = ENOMEM;
157 return -1;
158 }
e9688c1d 159 *fshlen = FSIDSIZE;
e9688c1d 160 memcpy(*fshanp, hanp, FSIDSIZE);
e9688c1d
NS
161 return 0;
162}
163
93d9f139
NS
164static int
165handle_to_fsfd(void *hanp, char **path)
89184fbc
AG
166{
167 struct fdhash *fdhp;
168
8967ee43
TS
169 /*
170 * Look in cache for matching fsid field in the handle
171 * (which is at the start of the handle).
172 * When found return the file descriptor and path that
173 * we have in the cache.
174 */
89184fbc 175 for (fdhp = fdhash_head; fdhp != NULL; fdhp = fdhp->fnxt) {
93d9f139
NS
176 if (memcmp(fdhp->fsh, hanp, FSIDSIZE) == 0) {
177 *path = fdhp->fspath;
89184fbc 178 return fdhp->fsfd;
93d9f139 179 }
89184fbc 180 }
3fbbdc85 181 errno = EBADF;
89184fbc
AG
182 return -1;
183}
184
93d9f139 185static int
3fbbdc85 186obj_to_handle(
93d9f139 187 char *fspath,
e9688c1d 188 int fsfd,
5b64e00a 189 unsigned int opcode,
e9688c1d
NS
190 comarg_t obj,
191 void **hanp,
192 size_t *hlen)
193{
194 char hbuf [MAXHANSIZ];
195 int ret;
ace4c158 196 __uint32_t handlen;
e9688c1d
NS
197 xfs_fsop_handlereq_t hreq;
198
199 if (opcode == XFS_IOC_FD_TO_HANDLE) {
200 hreq.fd = obj.fd;
201 hreq.path = NULL;
202 } else {
203 hreq.fd = 0;
204 hreq.path = obj.path;
205 }
206
489aaf4d 207 hreq.oflags = O_LARGEFILE;
e9688c1d
NS
208 hreq.ihandle = NULL;
209 hreq.ihandlen = 0;
210 hreq.ohandle = hbuf;
ace4c158 211 hreq.ohandlen = &handlen;
fe37ab57 212
93d9f139 213 ret = xfsctl(fspath, fsfd, opcode, &hreq);
e9688c1d
NS
214 if (ret)
215 return ret;
216
ace4c158 217 *hanp = malloc(handlen);
e9688c1d
NS
218 if (*hanp == NULL) {
219 errno = ENOMEM;
220 return -1;
221 }
222
ace4c158
CH
223 memcpy(*hanp, hbuf, handlen);
224 *hlen = handlen;
e9688c1d
NS
225 return 0;
226}
227
a3cbe7cd
MK
228int
229open_by_fshandle(
230 void *fshanp,
231 size_t fshlen,
232 int rw)
233{
234 int fsfd;
235 char *path;
236 xfs_fsop_handlereq_t hreq;
237
238 if ((fsfd = handle_to_fsfd(fshanp, &path)) < 0)
239 return -1;
240
241 hreq.fd = 0;
242 hreq.path = NULL;
243 hreq.oflags = rw | O_LARGEFILE;
244 hreq.ihandle = fshanp;
245 hreq.ihandlen = fshlen;
246 hreq.ohandle = NULL;
247 hreq.ohandlen = NULL;
248
249 return xfsctl(path, fsfd, XFS_IOC_OPEN_BY_HANDLE, &hreq);
250}
251
e9688c1d 252int
3fbbdc85 253open_by_handle(
e9688c1d
NS
254 void *hanp,
255 size_t hlen,
256 int rw)
257{
a3cbe7cd 258 int fsfd;
93d9f139 259 char *path;
a3cbe7cd
MK
260 void *fshanp;
261 size_t fshlen;
e9688c1d
NS
262 xfs_fsop_handlereq_t hreq;
263
a3cbe7cd
MK
264 if (handle_to_fshandle(hanp, hlen, &fshanp, &fshlen) != 0)
265 return -1;
266
267 if ((fsfd = handle_to_fsfd(fshanp, &path)) < 0)
e9688c1d 268 return -1;
e9688c1d
NS
269
270 hreq.fd = 0;
271 hreq.path = NULL;
489aaf4d 272 hreq.oflags = rw | O_LARGEFILE;
e9688c1d
NS
273 hreq.ihandle = hanp;
274 hreq.ihandlen = hlen;
275 hreq.ohandle = NULL;
276 hreq.ohandlen = NULL;
277
a3cbe7cd 278 return xfsctl(path, fsfd, XFS_IOC_OPEN_BY_HANDLE, &hreq);
e9688c1d
NS
279}
280
281int
3fbbdc85 282readlink_by_handle(
e9688c1d
NS
283 void *hanp,
284 size_t hlen,
285 void *buf,
286 size_t bufsiz)
287{
288 int fd;
1771a6dd 289 __u32 buflen = (__u32)bufsiz;
93d9f139 290 char *path;
e9688c1d
NS
291 xfs_fsop_handlereq_t hreq;
292
3fbbdc85 293 if ((fd = handle_to_fsfd(hanp, &path)) < 0)
e9688c1d 294 return -1;
e9688c1d
NS
295
296 hreq.fd = 0;
297 hreq.path = NULL;
489aaf4d 298 hreq.oflags = O_LARGEFILE;
e9688c1d
NS
299 hreq.ihandle = hanp;
300 hreq.ihandlen = hlen;
301 hreq.ohandle = buf;
1771a6dd 302 hreq.ohandlen = &buflen;
e9688c1d 303
93d9f139 304 return xfsctl(path, fd, XFS_IOC_READLINK_BY_HANDLE, &hreq);
e9688c1d
NS
305}
306
8967ee43 307/*ARGSUSED4*/
14290264
NS
308int
309attr_multi_by_handle(
310 void *hanp,
311 size_t hlen,
312 void *buf,
313 int rtrvcnt,
314 int flags)
315{
316 int fd;
93d9f139 317 char *path;
14290264
NS
318 xfs_fsop_attrmulti_handlereq_t amhreq;
319
3fbbdc85 320 if ((fd = handle_to_fsfd(hanp, &path)) < 0)
14290264 321 return -1;
14290264
NS
322
323 amhreq.hreq.fd = 0;
324 amhreq.hreq.path = NULL;
489aaf4d 325 amhreq.hreq.oflags = O_LARGEFILE;
14290264
NS
326 amhreq.hreq.ihandle = hanp;
327 amhreq.hreq.ihandlen = hlen;
328 amhreq.hreq.ohandle = NULL;
329 amhreq.hreq.ohandlen = NULL;
330
331 amhreq.opcount = rtrvcnt;
332 amhreq.ops = buf;
333
93d9f139 334 return xfsctl(path, fd, XFS_IOC_ATTRMULTI_BY_HANDLE, &amhreq);
14290264
NS
335}
336
337int
338attr_list_by_handle(
339 void *hanp,
340 size_t hlen,
341 void *buf,
342 size_t bufsize,
343 int flags,
344 struct attrlist_cursor *cursor)
345{
258b00ea 346 int error, fd;
93d9f139 347 char *path;
14290264
NS
348 xfs_fsop_attrlist_handlereq_t alhreq;
349
3fbbdc85 350 if ((fd = handle_to_fsfd(hanp, &path)) < 0)
14290264 351 return -1;
14290264
NS
352
353 alhreq.hreq.fd = 0;
354 alhreq.hreq.path = NULL;
489aaf4d 355 alhreq.hreq.oflags = O_LARGEFILE;
14290264
NS
356 alhreq.hreq.ihandle = hanp;
357 alhreq.hreq.ihandlen = hlen;
358 alhreq.hreq.ohandle = NULL;
359 alhreq.hreq.ohandlen = NULL;
360
361 memcpy(&alhreq.pos, cursor, sizeof(alhreq.pos));
362 alhreq.flags = flags;
363 alhreq.buflen = bufsize;
364 alhreq.buffer = buf;
365
258b00ea
TS
366 error = xfsctl(path, fd, XFS_IOC_ATTRLIST_BY_HANDLE, &alhreq);
367
368 memcpy(cursor, &alhreq.pos, sizeof(alhreq.pos));
369 return error;
370}
371
372int
373getparents_by_handle(
374 void *hanp,
375 size_t hlen,
376 parent_t *buf,
377 size_t bufsiz,
378 parent_cursor_t *cursor,
379 unsigned int *count,
380 unsigned int *more)
381{
382#if !defined(__sgi__)
383 errno = EOPNOTSUPP;
384 return -1;
385#else
386
387 int error, fd;
388 char *path;
389 xfs_fsop_getparents_handlereq_t gphreq;
390
391 if ((fd = handle_to_fsfd(hanp, &path)) < 0)
392 return -1;
393
394 gphreq.hreq.fd = 0;
395 gphreq.hreq.path = NULL;
396 gphreq.hreq.oflags = O_LARGEFILE;
397 gphreq.hreq.ihandle = hanp;
398 gphreq.hreq.ihandlen = hlen;
399 gphreq.hreq.ohandle = NULL;
400 gphreq.hreq.ohandlen = NULL;
401 memcpy(&gphreq.pos, cursor, sizeof(gphreq.pos));
402 gphreq.buflen = bufsiz;
403 gphreq.buffer = buf;
404 gphreq.ocount = count;
405 gphreq.omore = more;
406
407 error = xfsctl(path, fd, XFS_IOC_GETPARENTS, &gphreq);
408
409 memcpy(cursor, &gphreq.pos, sizeof(gphreq.pos));
410 return error;
411#endif
412}
413
414int
415getparentpaths_by_handle(
416 void *hanp,
417 size_t hlen,
418 parent_t *buf,
419 size_t bufsiz,
420 parent_cursor_t *cursor,
421 unsigned int *count,
422 unsigned int *more)
423{
424#if !defined(__sgi__)
425 errno = EOPNOTSUPP;
426 return -1;
427#else
428 int error, fd;
429 char *path;
430 xfs_fsop_getparents_handlereq_t gphreq;
431
432 if ((fd = handle_to_fsfd(hanp, &path)) < 0)
433 return -1;
434
435 gphreq.hreq.fd = 0;
436 gphreq.hreq.path = NULL;
437 gphreq.hreq.oflags = O_LARGEFILE;
438 gphreq.hreq.ihandle = hanp;
439 gphreq.hreq.ihandlen = hlen;
440 gphreq.hreq.ohandle = NULL;
441 gphreq.hreq.ohandlen = NULL;
442 memcpy(&gphreq.pos, cursor, sizeof(gphreq.pos));
443 gphreq.buflen = bufsiz;
444 gphreq.buffer = buf;
445 gphreq.ocount = count;
446 gphreq.omore = more;
447
448 error = xfsctl(path, fd, XFS_IOC_GETPARENTPATHS, &gphreq);
449
450 memcpy(cursor, &gphreq.pos, sizeof(gphreq.pos));
451 return error;
452#endif
14290264
NS
453}
454
e1864286 455int
3fbbdc85 456fssetdm_by_handle(
e1864286
DR
457 void *hanp,
458 size_t hlen,
459 struct fsdmidata *fsdmidata)
460{
461 int fd;
93d9f139 462 char *path;
e1864286
DR
463 xfs_fsop_setdm_handlereq_t dmhreq;
464
3fbbdc85 465 if ((fd = handle_to_fsfd(hanp, &path)) < 0)
e1864286 466 return -1;
e1864286
DR
467
468 dmhreq.hreq.fd = 0;
469 dmhreq.hreq.path = NULL;
489aaf4d 470 dmhreq.hreq.oflags = O_LARGEFILE;
e1864286
DR
471 dmhreq.hreq.ihandle = hanp;
472 dmhreq.hreq.ihandlen = hlen;
473 dmhreq.hreq.ohandle = NULL;
474 dmhreq.hreq.ohandlen = NULL;
475
476 dmhreq.data = fsdmidata;
477
93d9f139 478 return xfsctl(path, fd, XFS_IOC_FSSETDM_BY_HANDLE, &dmhreq);
e1864286
DR
479}
480
8967ee43 481/*ARGSUSED1*/
e9688c1d 482void
3fbbdc85 483free_handle(
e9688c1d
NS
484 void *hanp,
485 size_t hlen)
486{
3fbbdc85 487 free(hanp);
e9688c1d 488}