/*
- * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Further, this software is distributed without any warranty that it is
- * free of the rightful claim of any third person regarding infringement
- * or the like. Any license provided herein, whether implied or
- * otherwise, applies only to this software file. Patent licenses, if
- * any, provided herein do not apply to combinations of this program with
- * other software, or any other product whatsoever.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write the Free Software Foundation, Inc., 59
- * Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
- * Mountain View, CA 94043, or:
- *
- * http://www.sgi.com
- *
- * For further information regarding this notice, see:
- *
- * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+ * Copyright (c) 1995, 2001-2003, 2005 Silicon Graphics, Inc.
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/errno.h>
-#include <sys/ioctl.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <unistd.h>
-
-#include "handle.h"
-#include <libxfs.h>
+#include <xfs/xfs.h>
+#include <xfs/handle.h>
+#include <xfs/parent.h>
/* just pick a value we know is more than big enough */
#define MAXHANSIZ 64
char *path;
} comarg_t;
-
-int
-obj_to_handle (
- int fsfd,
- unsigned int opcode,
- comarg_t obj,
- void **hanp,
- size_t *hlen);
+static int obj_to_handle(char *, int, unsigned int, comarg_t, void**, size_t*);
+static int handle_to_fsfd(void *, char **);
/*
* Filesystem Handle -> Open File Descriptor Cache
*
* Maps filesystem handles to a corresponding open file descriptor for that
- * filesystem. We need this because we're doing handle operations via ioctl
+ * filesystem. We need this because we're doing handle operations via xfsctl
* and we need to remember the open file descriptor for each filesystem.
*/
int fsfd;
char fsh[FSIDSIZE];
struct fdhash *fnxt;
+ char fspath[MAXPATHLEN];
};
-struct fdhash *fdhash_head = NULL;
+static struct fdhash *fdhash_head = NULL;
int
-path_to_fshandle (
+path_to_fshandle(
char *path, /* input, path to convert */
- void **hanp, /* output, pointer to data */
- size_t *hlen) /* output, size of returned data */
+ void **fshanp, /* output, pointer to data */
+ size_t *fshlen) /* output, size of returned data */
{
int result;
int fd;
comarg_t obj;
struct fdhash *fdhp;
+ char *tmppath;
fd = open(path, O_RDONLY);
-
- if (fd < 0) {
- perror(path);
- exit(1);
- }
+ if (fd < 0)
+ return -1;
obj.path = path;
+ result = obj_to_handle(path, fd, XFS_IOC_PATH_TO_FSHANDLE,
+ obj, fshanp, fshlen);
+ if (result < 0) {
+ close(fd);
+ return result;
+ }
- result = obj_to_handle (fd, XFS_IOC_PATH_TO_FSHANDLE,
- obj, hanp, hlen);
-
- if (result >= 0) {
+ if (handle_to_fsfd(*fshanp, &tmppath) >= 0) {
+ /* this filesystem is already in the cache */
+ close(fd);
+ } else {
+ /* new filesystem. add it to the cache */
fdhp = malloc(sizeof(struct fdhash));
-
if (fdhp == NULL) {
errno = ENOMEM;
return -1;
}
fdhp->fsfd = fd;
- fdhp->fnxt = NULL;
-
- memcpy(fdhp->fsh, *hanp, FSIDSIZE);
+ strncpy(fdhp->fspath, path, sizeof(fdhp->fspath));
+ memcpy(fdhp->fsh, *fshanp, FSIDSIZE);
- if (fdhash_head)
- fdhash_head->fnxt = fdhp;
- else
- fdhash_head = fdhp;
+ fdhp->fnxt = fdhash_head;
+ fdhash_head = fdhp;
}
return result;
}
+int
+path_to_handle(
+ char *path, /* input, path to convert */
+ void **hanp, /* output, pointer to data */
+ size_t *hlen) /* output, size of returned data */
+{
+ return lpath_to_handle(path, path, hanp, hlen);
+}
+/* Like path_to_handle, but reliable for paths which are either dangling
+ * symlinks or symlinks whose targets are not in XFS filesystems.
+ */
int
-path_to_handle (
+lpath_to_handle(
+ char *fspath, /* input, path in filesystem */
char *path, /* input, path to convert */
void **hanp, /* output, pointer to data */
size_t *hlen) /* output, size of returned data */
int result;
comarg_t obj;
- fd = open(path, O_RDONLY);
-
- if (fd < 0) {
- perror(path);
- exit(1);
- }
+ fd = open(fspath, O_RDONLY);
+ if (fd < 0)
+ return -1;
obj.path = path;
-
- result = obj_to_handle (fd, XFS_IOC_PATH_TO_HANDLE, obj, hanp, hlen);
-
+ result = obj_to_handle(fspath, fd, XFS_IOC_PATH_TO_HANDLE,
+ obj, hanp, hlen);
close(fd);
-
return result;
}
comarg_t obj;
obj.fd = fd;
-
- return obj_to_handle (fd, XFS_IOC_FD_TO_HANDLE, obj, hanp, hlen);
+ return obj_to_handle(NULL, fd, XFS_IOC_FD_TO_HANDLE, obj, hanp, hlen);
}
int
-handle_to_fshandle (
+handle_to_fshandle(
void *hanp,
size_t hlen,
void **fshanp,
size_t *fshlen)
{
- if (hlen < FSIDSIZE)
- return EINVAL;
-
- *fshanp = malloc (FSIDSIZE);
-
- if (*fshanp == NULL)
- return ENOMEM;
-
+ if (hlen < FSIDSIZE) {
+ errno = EINVAL;
+ return -1;
+ }
+ *fshanp = malloc(FSIDSIZE);
+ if (*fshanp == NULL) {
+ errno = ENOMEM;
+ return -1;
+ }
*fshlen = FSIDSIZE;
-
memcpy(*fshanp, hanp, FSIDSIZE);
-
return 0;
}
-
-int
-handle_to_fsfd(void *hanp)
+static int
+handle_to_fsfd(void *hanp, char **path)
{
struct fdhash *fdhp;
+ /*
+ * Look in cache for matching fsid field in the handle
+ * (which is at the start of the handle).
+ * When found return the file descriptor and path that
+ * we have in the cache.
+ */
for (fdhp = fdhash_head; fdhp != NULL; fdhp = fdhp->fnxt) {
- if (memcmp(fdhp->fsh, hanp, FSIDSIZE) == 0)
+ if (memcmp(fdhp->fsh, hanp, FSIDSIZE) == 0) {
+ *path = fdhp->fspath;
return fdhp->fsfd;
+ }
}
+ errno = EBADF;
return -1;
}
-
-int
-obj_to_handle (
+static int
+obj_to_handle(
+ char *fspath,
int fsfd,
unsigned int opcode,
comarg_t obj,
{
char hbuf [MAXHANSIZ];
int ret;
+ __uint32_t handlen;
xfs_fsop_handlereq_t hreq;
if (opcode == XFS_IOC_FD_TO_HANDLE) {
hreq.path = obj.path;
}
- hreq.oflags = 0;
+ hreq.oflags = O_LARGEFILE;
hreq.ihandle = NULL;
hreq.ihandlen = 0;
hreq.ohandle = hbuf;
- hreq.ohandlen = (__u32 *)hlen;
-
- ret = (int) ioctl(fsfd, opcode, &hreq);
+ hreq.ohandlen = &handlen;
+ ret = xfsctl(fspath, fsfd, opcode, &hreq);
if (ret)
return ret;
- *hanp = malloc(*hlen);
-
+ *hanp = malloc(handlen);
if (*hanp == NULL) {
errno = ENOMEM;
return -1;
}
- memcpy(*hanp, hbuf, (int) *hlen);
-
+ memcpy(*hanp, hbuf, handlen);
+ *hlen = handlen;
return 0;
}
+int
+open_by_fshandle(
+ void *fshanp,
+ size_t fshlen,
+ int rw)
+{
+ int fsfd;
+ char *path;
+ xfs_fsop_handlereq_t hreq;
+
+ if ((fsfd = handle_to_fsfd(fshanp, &path)) < 0)
+ return -1;
+
+ hreq.fd = 0;
+ hreq.path = NULL;
+ hreq.oflags = rw | O_LARGEFILE;
+ hreq.ihandle = fshanp;
+ hreq.ihandlen = fshlen;
+ hreq.ohandle = NULL;
+ hreq.ohandlen = NULL;
+ return xfsctl(path, fsfd, XFS_IOC_OPEN_BY_HANDLE, &hreq);
+}
int
-open_by_handle (
+open_by_handle(
void *hanp,
size_t hlen,
int rw)
{
- int fd;
- int result;
+ int fsfd;
+ char *path;
+ void *fshanp;
+ size_t fshlen;
xfs_fsop_handlereq_t hreq;
- if ((fd = handle_to_fsfd(hanp)) < 0) {
- errno = EBADF;
+ if (handle_to_fshandle(hanp, hlen, &fshanp, &fshlen) != 0)
+ return -1;
+
+ if ((fsfd = handle_to_fsfd(fshanp, &path)) < 0)
return -1;
- }
hreq.fd = 0;
hreq.path = NULL;
- hreq.oflags = rw;
+ hreq.oflags = rw | O_LARGEFILE;
hreq.ihandle = hanp;
hreq.ihandlen = hlen;
hreq.ohandle = NULL;
hreq.ohandlen = NULL;
- result = ioctl(fd, XFS_IOC_OPEN_BY_HANDLE, &hreq);
-
- return result;
+ return xfsctl(path, fsfd, XFS_IOC_OPEN_BY_HANDLE, &hreq);
}
int
-readlink_by_handle (
+readlink_by_handle(
void *hanp,
size_t hlen,
void *buf,
size_t bufsiz)
{
int fd;
+ __u32 buflen = (__u32)bufsiz;
+ char *path;
xfs_fsop_handlereq_t hreq;
-
- if ((fd = handle_to_fsfd(hanp)) < 0) {
- errno = EBADF;
+ if ((fd = handle_to_fsfd(hanp, &path)) < 0)
return -1;
- }
hreq.fd = 0;
hreq.path = NULL;
- hreq.oflags = 0;
+ hreq.oflags = O_LARGEFILE;
hreq.ihandle = hanp;
hreq.ihandlen = hlen;
hreq.ohandle = buf;
- hreq.ohandlen = (__u32 *)&bufsiz;
+ hreq.ohandlen = &buflen;
+
+ return xfsctl(path, fd, XFS_IOC_READLINK_BY_HANDLE, &hreq);
+}
+
+/*ARGSUSED4*/
+int
+attr_multi_by_handle(
+ void *hanp,
+ size_t hlen,
+ void *buf,
+ int rtrvcnt,
+ int flags)
+{
+ int fd;
+ char *path;
+ xfs_fsop_attrmulti_handlereq_t amhreq;
+
+ if ((fd = handle_to_fsfd(hanp, &path)) < 0)
+ return -1;
+
+ amhreq.hreq.fd = 0;
+ amhreq.hreq.path = NULL;
+ amhreq.hreq.oflags = O_LARGEFILE;
+ amhreq.hreq.ihandle = hanp;
+ amhreq.hreq.ihandlen = hlen;
+ amhreq.hreq.ohandle = NULL;
+ amhreq.hreq.ohandlen = NULL;
+
+ amhreq.opcount = rtrvcnt;
+ amhreq.ops = buf;
+
+ return xfsctl(path, fd, XFS_IOC_ATTRMULTI_BY_HANDLE, &amhreq);
+}
+
+int
+attr_list_by_handle(
+ void *hanp,
+ size_t hlen,
+ void *buf,
+ size_t bufsize,
+ int flags,
+ struct attrlist_cursor *cursor)
+{
+ int error, fd;
+ char *path;
+ xfs_fsop_attrlist_handlereq_t alhreq;
+
+ if ((fd = handle_to_fsfd(hanp, &path)) < 0)
+ return -1;
+
+ alhreq.hreq.fd = 0;
+ alhreq.hreq.path = NULL;
+ alhreq.hreq.oflags = O_LARGEFILE;
+ alhreq.hreq.ihandle = hanp;
+ alhreq.hreq.ihandlen = hlen;
+ alhreq.hreq.ohandle = NULL;
+ alhreq.hreq.ohandlen = NULL;
+
+ memcpy(&alhreq.pos, cursor, sizeof(alhreq.pos));
+ alhreq.flags = flags;
+ alhreq.buffer = buf;
+ alhreq.buflen = bufsize;
+ /* prevent needless EINVAL from the kernel */
+ if (alhreq.buflen > XATTR_LIST_MAX)
+ alhreq.buflen = XATTR_LIST_MAX;
+
+ error = xfsctl(path, fd, XFS_IOC_ATTRLIST_BY_HANDLE, &alhreq);
+
+ memcpy(cursor, &alhreq.pos, sizeof(alhreq.pos));
+ return error;
+}
+
+int
+parents_by_handle(
+ void *hanp,
+ size_t hlen,
+ parent_t *buf,
+ size_t bufsiz,
+ unsigned int *count)
+
+{
+ errno = EOPNOTSUPP;
+ return -1;
+}
+
+int
+parentpaths_by_handle(
+ void *hanp,
+ size_t hlen,
+ parent_t *buf,
+ size_t bufsiz,
+ unsigned int *count)
+{
+ errno = EOPNOTSUPP;
+ return -1;
+}
+
+int
+fssetdm_by_handle(
+ void *hanp,
+ size_t hlen,
+ struct fsdmidata *fsdmidata)
+{
+ int fd;
+ char *path;
+ xfs_fsop_setdm_handlereq_t dmhreq;
+
+ if ((fd = handle_to_fsfd(hanp, &path)) < 0)
+ return -1;
+
+ dmhreq.hreq.fd = 0;
+ dmhreq.hreq.path = NULL;
+ dmhreq.hreq.oflags = O_LARGEFILE;
+ dmhreq.hreq.ihandle = hanp;
+ dmhreq.hreq.ihandlen = hlen;
+ dmhreq.hreq.ohandle = NULL;
+ dmhreq.hreq.ohandlen = NULL;
+
+ dmhreq.data = fsdmidata;
- return (int) ioctl(fd, XFS_IOC_READLINK_BY_HANDLE, &hreq);
+ return xfsctl(path, fd, XFS_IOC_FSSETDM_BY_HANDLE, &dmhreq);
}
-/*ARGSUSED*/
+/*ARGSUSED1*/
void
-free_handle (
+free_handle(
void *hanp,
size_t hlen)
{
- free (hanp);
+ free(hanp);
}