2 * Copyright (c) 1995, 2001-2003, 2005 Silicon Graphics, Inc.
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
7 * as published by the Free Software Foundation.
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.
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
20 #include <xfs/handle.h>
21 #include <xfs/parent.h>
23 /* just pick a value we know is more than big enough */
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.
41 static int obj_to_handle(char *, int, unsigned int, comarg_t
, void**, size_t*);
42 static int handle_to_fsfd(void *, char **);
46 * Filesystem Handle -> Open File Descriptor Cache
48 * Maps filesystem handles to a corresponding open file descriptor for that
49 * filesystem. We need this because we're doing handle operations via xfsctl
50 * and we need to remember the open file descriptor for each filesystem.
57 char fspath
[MAXPATHLEN
];
60 static struct fdhash
*fdhash_head
= NULL
;
64 char *path
, /* input, path to convert */
65 void **fshanp
, /* output, pointer to data */
66 size_t *fshlen
) /* output, size of returned data */
74 fd
= open(path
, O_RDONLY
);
79 result
= obj_to_handle(path
, fd
, XFS_IOC_PATH_TO_FSHANDLE
,
86 if (handle_to_fsfd(*fshanp
, &tmppath
) >= 0) {
87 /* this filesystem is already in the cache */
90 /* new filesystem. add it to the cache */
91 fdhp
= malloc(sizeof(struct fdhash
));
98 strncpy(fdhp
->fspath
, path
, sizeof(fdhp
->fspath
));
99 memcpy(fdhp
->fsh
, *fshanp
, FSIDSIZE
);
101 fdhp
->fnxt
= fdhash_head
;
110 char *path
, /* input, path to convert */
111 void **hanp
, /* output, pointer to data */
112 size_t *hlen
) /* output, size of returned data */
118 fd
= open(path
, O_RDONLY
);
123 result
= obj_to_handle(path
, fd
, XFS_IOC_PATH_TO_HANDLE
,
132 int fd
, /* input, file descriptor */
133 void **hanp
, /* output, pointer to data */
134 size_t *hlen
) /* output, size of returned data */
139 return obj_to_handle(NULL
, fd
, XFS_IOC_FD_TO_HANDLE
, obj
, hanp
, hlen
);
150 if (hlen
< FSIDSIZE
) {
154 *fshanp
= malloc(FSIDSIZE
);
155 if (*fshanp
== NULL
) {
160 memcpy(*fshanp
, hanp
, FSIDSIZE
);
165 handle_to_fsfd(void *hanp
, char **path
)
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.
175 for (fdhp
= fdhash_head
; fdhp
!= NULL
; fdhp
= fdhp
->fnxt
) {
176 if (memcmp(fdhp
->fsh
, hanp
, FSIDSIZE
) == 0) {
177 *path
= fdhp
->fspath
;
194 char hbuf
[MAXHANSIZ
];
197 xfs_fsop_handlereq_t hreq
;
199 if (opcode
== XFS_IOC_FD_TO_HANDLE
) {
204 hreq
.path
= obj
.path
;
207 hreq
.oflags
= O_LARGEFILE
;
211 hreq
.ohandlen
= &handlen
;
213 ret
= xfsctl(fspath
, fsfd
, opcode
, &hreq
);
217 *hanp
= malloc(handlen
);
223 memcpy(*hanp
, hbuf
, handlen
);
236 xfs_fsop_handlereq_t hreq
;
238 if ((fsfd
= handle_to_fsfd(fshanp
, &path
)) < 0)
243 hreq
.oflags
= rw
| O_LARGEFILE
;
244 hreq
.ihandle
= fshanp
;
245 hreq
.ihandlen
= fshlen
;
247 hreq
.ohandlen
= NULL
;
249 return xfsctl(path
, fsfd
, XFS_IOC_OPEN_BY_HANDLE
, &hreq
);
262 xfs_fsop_handlereq_t hreq
;
264 if (handle_to_fshandle(hanp
, hlen
, &fshanp
, &fshlen
) != 0)
267 if ((fsfd
= handle_to_fsfd(fshanp
, &path
)) < 0)
272 hreq
.oflags
= rw
| O_LARGEFILE
;
274 hreq
.ihandlen
= hlen
;
276 hreq
.ohandlen
= NULL
;
278 return xfsctl(path
, fsfd
, XFS_IOC_OPEN_BY_HANDLE
, &hreq
);
289 __u32 buflen
= (__u32
)bufsiz
;
291 xfs_fsop_handlereq_t hreq
;
293 if ((fd
= handle_to_fsfd(hanp
, &path
)) < 0)
298 hreq
.oflags
= O_LARGEFILE
;
300 hreq
.ihandlen
= hlen
;
302 hreq
.ohandlen
= &buflen
;
304 return xfsctl(path
, fd
, XFS_IOC_READLINK_BY_HANDLE
, &hreq
);
309 attr_multi_by_handle(
318 xfs_fsop_attrmulti_handlereq_t amhreq
;
320 if ((fd
= handle_to_fsfd(hanp
, &path
)) < 0)
324 amhreq
.hreq
.path
= NULL
;
325 amhreq
.hreq
.oflags
= O_LARGEFILE
;
326 amhreq
.hreq
.ihandle
= hanp
;
327 amhreq
.hreq
.ihandlen
= hlen
;
328 amhreq
.hreq
.ohandle
= NULL
;
329 amhreq
.hreq
.ohandlen
= NULL
;
331 amhreq
.opcount
= rtrvcnt
;
334 return xfsctl(path
, fd
, XFS_IOC_ATTRMULTI_BY_HANDLE
, &amhreq
);
344 struct attrlist_cursor
*cursor
)
348 xfs_fsop_attrlist_handlereq_t alhreq
;
350 if ((fd
= handle_to_fsfd(hanp
, &path
)) < 0)
354 alhreq
.hreq
.path
= NULL
;
355 alhreq
.hreq
.oflags
= O_LARGEFILE
;
356 alhreq
.hreq
.ihandle
= hanp
;
357 alhreq
.hreq
.ihandlen
= hlen
;
358 alhreq
.hreq
.ohandle
= NULL
;
359 alhreq
.hreq
.ohandlen
= NULL
;
361 memcpy(&alhreq
.pos
, cursor
, sizeof(alhreq
.pos
));
362 alhreq
.flags
= flags
;
363 alhreq
.buflen
= bufsize
;
366 error
= xfsctl(path
, fd
, XFS_IOC_ATTRLIST_BY_HANDLE
, &alhreq
);
368 memcpy(cursor
, &alhreq
.pos
, sizeof(alhreq
.pos
));
373 getparents_by_handle(
378 parent_cursor_t
*cursor
,
382 #if !defined(__sgi__)
389 xfs_fsop_getparents_handlereq_t gphreq
;
391 if ((fd
= handle_to_fsfd(hanp
, &path
)) < 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
;
404 gphreq
.ocount
= count
;
407 error
= xfsctl(path
, fd
, XFS_IOC_GETPARENTS
, &gphreq
);
409 memcpy(cursor
, &gphreq
.pos
, sizeof(gphreq
.pos
));
415 getparentpaths_by_handle(
420 parent_cursor_t
*cursor
,
424 #if !defined(__sgi__)
430 xfs_fsop_getparents_handlereq_t gphreq
;
432 if ((fd
= handle_to_fsfd(hanp
, &path
)) < 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
;
445 gphreq
.ocount
= count
;
448 error
= xfsctl(path
, fd
, XFS_IOC_GETPARENTPATHS
, &gphreq
);
450 memcpy(cursor
, &gphreq
.pos
, sizeof(gphreq
.pos
));
459 struct fsdmidata
*fsdmidata
)
463 xfs_fsop_setdm_handlereq_t dmhreq
;
465 if ((fd
= handle_to_fsfd(hanp
, &path
)) < 0)
469 dmhreq
.hreq
.path
= NULL
;
470 dmhreq
.hreq
.oflags
= O_LARGEFILE
;
471 dmhreq
.hreq
.ihandle
= hanp
;
472 dmhreq
.hreq
.ihandlen
= hlen
;
473 dmhreq
.hreq
.ohandle
= NULL
;
474 dmhreq
.hreq
.ohandlen
= NULL
;
476 dmhreq
.data
= fsdmidata
;
478 return xfsctl(path
, fd
, XFS_IOC_FSSETDM_BY_HANDLE
, &dmhreq
);