Index: dm_handle2path.c
===================================================================
--- dm_handle2path.c (nonexistent)
+++ dm_handle2path.c (revision 5)
@@ -0,0 +1,323 @@
+/*
+ * Copyright (c) 1995, 2001-2002 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 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU 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 <dmapi.h>
+#include <dmapi_kern.h>
+#include "dmapi_lib.h"
+
+#include <mntent.h>
+#include <dirent.h>
+#include <string.h>
+#ifdef linux
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include "getdents.h"
+#endif
+
+static int getcomp(int dirfd, void *targhanp, size_t targhlen,
+ char *bufp, size_t buflen, size_t *rlenp);
+static char *get_mnt(void *fshanp, size_t fshlen);
+
+
+extern int
+dm_handle_to_path(
+ void *dirhanp, /* parent directory handle and length */
+ size_t dirhlen,
+ void *targhanp, /* target object handle and length */
+ size_t targhlen,
+ size_t buflen, /* length of pathbufp */
+ char *pathbufp, /* buffer in which name is returned */
+ size_t *rlenp) /* length of resultant pathname */
+{
+ int dirfd = -1; /* fd for parent directory */
+ int origfd = -1; /* fd for current working directory */
+ int err; /* a place to save errno */
+ int mfd;
+ char *mtpt = NULL;
+ void *fshanp;
+ size_t fshlen;
+
+ if (buflen == 0) {
+ errno = EINVAL;
+ return -1;
+ }
+ if (pathbufp == NULL || rlenp == NULL) {
+ errno = EFAULT;
+ return -1;
+ }
+ if (dm_handle_to_fshandle(dirhanp, dirhlen, &fshanp, &fshlen)) {
+ errno = EINVAL;
+ return -1;
+ }
+ if ((origfd = open(".", O_RDONLY)) < 0) {
+ dm_handle_free(fshanp, fshlen);
+ return -1; /* leave errno set from open */
+ }
+
+ if ((mtpt = get_mnt(fshanp, fshlen)) == NULL) {
+ errno = EINVAL;
+ dm_handle_free(fshanp, fshlen);
+ close(origfd);
+ return -1;
+ }
+
+ if((mfd = open(mtpt, O_RDONLY)) < 0) {
+ dm_handle_free(fshanp, fshlen);
+ close(origfd);
+ free(mtpt);
+ return -1;
+ }
+
+ dirfd = dmi(DM_OPEN_BY_HANDLE, mfd, dirhanp, dirhlen, O_RDONLY);
+
+ if (dirfd < 0) {
+ err = errno;
+ } else if (fchdir(dirfd)) {
+ err = errno;
+ } else {
+ /* From here on the fchdir must always be undone! */
+
+ if (!getcwd(pathbufp, buflen)) {
+ if ((err = errno) == ERANGE) /* buffer too small */
+ err = E2BIG;
+ } else {
+ char hbuf[DM_MAX_HANDLE_SIZE];
+ size_t hlen;
+
+ /* Check that we're in the correct directory.
+ * If the dir we wanted has not been accessed
+ * then the kernel would have put us into the
+ * filesystem's root directory--but at least
+ * we'll be on the correct filesystem.
+ */
+
+ err = 0;
+ if (dmi(DM_PATH_TO_HANDLE, pathbufp, hbuf, &hlen)) {
+ err = ENOENT;
+ }
+ else {
+ if (dm_handle_cmp(dirhanp, dirhlen, hbuf, hlen)) {
+ /* The dir we want has never been
+ * accessed, so we'll have to find
+ * it.
+ */
+
+ /* XXX -- need something to march
+ through all the dirs, trying to
+ find the right one. Something
+ like a recursive version of
+ getcomp().
+ In practice, are we ever going
+ to need this? */
+
+ err = ENOENT;
+ }
+ }
+
+ /* Now march through the dir to find the target. */
+ if (!err) {
+ err = getcomp(dirfd, targhanp, targhlen, pathbufp,
+ buflen, rlenp);
+ }
+ }
+ (void) fchdir(origfd); /* can't do anything about a failure */
+ }
+
+ dm_handle_free(fshanp, fshlen);
+ free(mtpt);
+ close(mfd);
+ if (origfd >= 0)
+ (void)close(origfd);
+ if (dirfd >= 0)
+ (void)close(dirfd);
+ if (!err)
+ return(0);
+
+ if (err == E2BIG)
+ *rlenp = 2 * buflen; /* guess since we don't know */
+ errno = err;
+ return(-1);
+}
+
+
+/* Append the basename of the open file referenced by targfd found in the
+ directory dirfd to dirfd's pathname in bufp. The length of the entire
+ path (including the NULL) is returned in *rlenp.
+
+ Returns zero if successful, an appropriate errno if not.
+*/
+
+#define READDIRSZ 16384
+
+static int
+getcomp(
+ int dirfd,
+ void *targhanp,
+ size_t targhlen,
+ char *bufp,
+ size_t buflen,
+ size_t *rlenp)
+{
+ char buf[READDIRSZ]; /* directory entry data buffer */
+ int loc = 0; /* byte offset of entry in the buffer */
+ int size = 0; /* number of bytes of data in buffer */
+ int eof = 0; /* did last ngetdents exhaust dir.? */
+ struct dirent64 *dp; /* pointer to directory entry */
+ char hbuf[DM_MAX_HANDLE_SIZE];
+ size_t hlen;
+ size_t dirlen; /* length of dirfd's pathname */
+ size_t totlen; /* length of targfd's pathname */
+ dm_ino_t ino; /* target object's inode # */
+
+ if (dm_handle_to_ino(targhanp, targhlen, &ino))
+ return -1; /* leave errno set from dm_handle_to_ino */
+
+ /* Append a "/" to the directory name unless the directory is root. */
+
+ dirlen = strlen(bufp);
+ if (dirlen > 1) {
+ if (buflen < dirlen + 1 + 1)
+ return(E2BIG);
+ bufp[dirlen++] = '/';
+ }
+
+ /* Examine each entry in the directory looking for one with a
+ matching target handle.
+ */
+
+ for(;;) {
+ if (size > 0) {
+ dp = (struct dirent64 *)&buf[loc];
+ loc += dp->d_reclen;
+ }
+ if (loc >= size) {
+ if (eof) {
+ return(ENOENT);
+ }
+ loc = size = 0;
+ }
+ if (size == 0) { /* refill buffer */
+#ifdef linux
+ size = __getdents_wrap(dirfd, (char *)buf, sizeof(buf));
+#else
+ size = ngetdents64(dirfd, (struct dirent64 *)buf,
+ sizeof(buf), &eof);
+#endif
+ if (size == 0) { /* This also means EOF */
+ return(ENOENT);
+ }
+ if (size < 0) { /* error */
+ return(errno);
+ }
+ }
+ dp = (struct dirent64 *)&buf[loc];
+
+ if (dp->d_ino != ino)
+ continue; /* wrong inode; try again */
+ totlen = dirlen + strlen(dp->d_name) + 1;
+ if (buflen < totlen)
+ return(E2BIG);
+ (void)strcpy(bufp + dirlen, dp->d_name);
+
+ if (dmi(DM_PATH_TO_HANDLE, bufp, hbuf, &hlen))
+ continue; /* must have been removed/renamed */
+ if (!dm_handle_cmp(targhanp, targhlen, hbuf, hlen))
+ break;
+ }
+
+ /* We have a match based upon the target handle. Clean up the end
+ cases before returning the path to the caller.
+ */
+
+ if (!strcmp(dp->d_name, ".")) { /* the directory itself */
+ if (dirlen > 1)
+ dirlen--;
+ bufp[dirlen] = '\0'; /* trim the trailing "/." */
+ *rlenp = dirlen + 1;
+ return(0);
+ }
+ if (!strcmp(dp->d_name, "..")) { /* the parent directory */
+ char *slash;
+
+ if (dirlen > 1)
+ dirlen--;
+ bufp[dirlen] = '\0';
+ if ((slash = strrchr(bufp, '/')) == NULL)
+ return(ENXIO); /* getcwd screwed up */
+ if (slash == bufp) /* don't whack "/" */
+ slash++;
+ *slash = '\0'; /* remove the last component */
+ *rlenp = strlen(bufp) + 1;
+ return(0);
+ }
+
+ *rlenp = totlen; /* success! */
+ return(0);
+}
+
+
+static char *
+get_mnt(
+ void *fshanp,
+ size_t fshlen)
+{
+ FILE *file;
+ struct mntent *mntent;
+ char *mtpt = NULL;
+ void *hanp;
+ size_t hlen;
+
+ if ((file = setmntent("/etc/mtab", "r")) == NULL)
+ return NULL;
+
+ while((mntent = getmntent(file)) != NULL) {
+
+ /* skip anything that isn't xfs */
+ if (strcmp("xfs", mntent->mnt_type) != 0)
+ continue;
+
+ /* skip root dir */
+ if (strcmp("/", mntent->mnt_dir) == 0)
+ continue;
+
+ /* skip anything that isn't dmapi */
+ if ((hasmntopt(mntent, "dmapi") == 0) &&
+ (hasmntopt(mntent, "dmi") == 0) &&
+ (hasmntopt(mntent, "xdsm") == 0)) {
+ continue;
+ }
+
+ /* skip anything that won't report a handle */
+ if (dm_path_to_fshandle(mntent->mnt_dir, &hanp, &hlen))
+ continue;
+
+ /* is this a match? */
+ if (dm_handle_cmp(fshanp, fshlen, hanp, hlen) == 0) {
+ /* yes */
+ mtpt = strdup(mntent->mnt_dir);
+ }
+ dm_handle_free(hanp, hlen);
+
+ if (mtpt)
+ break;
+ }
+ endmntent(file);
+ return mtpt;
+}
Index: getdents.c
===================================================================
--- getdents.c (nonexistent)
+++ getdents.c (revision 5)
@@ -0,0 +1,275 @@
+/*
+ * Copyright (c) 2000-2001 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 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU 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
+ */
+
+/*
+ * Copyright (C) 1993, 95, 96, 97, 98, 99,2000,2001 Free Software Foundation, Inc.
+ * This file is based almost entirely on getdents.c in the GNU C Library.
+ */
+
+#include <alloca.h>
+#include <assert.h>
+#include <errno.h>
+#include <dirent.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/syscall.h>
+
+#include <linux/posix_types.h>
+
+/* Copied from kernel-features.h for __ASSUME_GETDENTS64_SYSCALL */
+#ifndef __LINUX_KERNEL_VERSION
+/* We assume the worst; all kernels should be supported. */
+# define __LINUX_KERNEL_VERSION 0
+#endif
+/* The getdents64 syscall was introduced in 2.4.0-test7. We test for
+ 2.4.1 for the earliest version we know the syscall is available. */
+#if __LINUX_KERNEL_VERSION >= 132097
+# define __ASSUME_GETDENTS64_SYSCALL 1
+#endif
+/* There are an infinite number of PA-RISC kernel versions numbered
+ 2.4.0. But they've not really been released as such. We require
+ and expect the final version here. */
+#ifdef __hppa__
+# define __ASSUME_GETDENTS64_SYSCALL 1
+#endif
+
+#ifndef __set_errno
+#define __set_errno(e) (errno = (e))
+#endif
+
+
+#ifdef __NR_getdents64
+# ifndef __ASSUME_GETDENTS64_SYSCALL
+# ifndef __GETDENTS
+/* The variable is shared between all *getdents* calls. */
+int __have_no_getdents64;
+# else
+extern int __have_no_getdents64;
+# endif
+# endif
+/* Earlier versions of glibc don't define SYS_getdents64 at all */
+# ifndef SYS_getdents64
+# define SYS_getdents64 __NR_getdents64
+# endif
+#endif
+
+#ifndef offsetof
+# define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+#endif /* ! offsetof */
+
+
+/* For Linux we need a special version of this file since the
+ definition of `struct dirent' is not the same for the kernel and
+ the libc. There is one additional field which might be introduced
+ in the kernel structure in the future.
+
+ Here is the kernel definition of `struct dirent' as of 2.1.20: */
+
+struct kernel_dirent
+ {
+ long int d_ino;
+ __kernel_off_t d_off;
+ unsigned short int d_reclen;
+ char d_name[256];
+ };
+
+struct kernel_dirent64
+ {
+ uint64_t d_ino;
+ int64_t d_off;
+ unsigned short int d_reclen;
+ unsigned char d_type;
+ char d_name[256];
+ };
+
+#ifndef DIRENT_TYPE
+# define DIRENT_TYPE struct dirent
+#endif
+#ifndef DIRENT_SET_DP_INO
+# define DIRENT_SET_DP_INO(dp, value) (dp)->d_ino = (value)
+#endif
+
+/* The problem here is that we cannot simply read the next NBYTES
+ bytes. We need to take the additional field into account. We use
+ some heuristic. Assuming the directory contains names with 14
+ characters on average we can compute an estimated number of entries
+ which fit in the buffer. Taking this number allows us to specify a
+ reasonable number of bytes to read. If we should be wrong, we can
+ reset the file descriptor. In practice the kernel is limiting the
+ amount of data returned much more then the reduced buffer size. */
+int
+__getdents_wrap (int fd, char *buf, size_t nbytes)
+{
+ DIRENT_TYPE *dp = (DIRENT_TYPE *)buf;
+ off64_t last_offset = -1;
+ ssize_t retval;
+
+#ifdef __NR_getdents64
+# ifndef __ASSUME_GETDENTS64_SYSCALL
+ if (!__have_no_getdents64)
+# endif
+ {
+# ifndef __ASSUME_GETDENTS64_SYSCALL
+ int saved_errno = errno;
+# endif
+ char *kbuf = buf;
+ size_t kbytes = nbytes;
+ if (offsetof (DIRENT_TYPE, d_name)
+ < offsetof (struct kernel_dirent64, d_name)
+ && nbytes <= sizeof (DIRENT_TYPE))
+ {
+ kbytes = nbytes + offsetof (struct kernel_dirent64, d_name)
+ - offsetof (DIRENT_TYPE, d_name);
+ kbuf = alloca(kbytes);
+ }
+ retval = syscall(SYS_getdents64, fd, kbuf, kbytes);
+# ifndef __ASSUME_GETDENTS64_SYSCALL
+ if (retval != -1 && errno != -EINVAL)
+# endif
+ {
+ struct kernel_dirent64 *kdp;
+ const size_t size_diff = (offsetof (struct kernel_dirent64, d_name)
+ - offsetof (DIRENT_TYPE, d_name));
+
+ /* If the structure returned by the kernel is identical to what we
+ need, don't do any conversions. */
+ if (offsetof (DIRENT_TYPE, d_name)
+ == offsetof (struct kernel_dirent64, d_name)
+ && sizeof (dp->d_ino) == sizeof (kdp->d_ino)
+ && sizeof (dp->d_off) == sizeof (kdp->d_off))
+ return retval;
+
+ dp = (DIRENT_TYPE *)buf;
+ kdp = (struct kernel_dirent64 *) kbuf;
+ while ((char *) kdp < kbuf + retval)
+ {
+ const size_t alignment = __alignof__ (DIRENT_TYPE);
+ /* Since kdp->d_reclen is already aligned for the kernel
+ structure this may compute a value that is bigger
+ than necessary. */
+ size_t old_reclen = kdp->d_reclen;
+ size_t new_reclen = ((old_reclen - size_diff + alignment - 1)
+ & ~(alignment - 1));
+ uint64_t d_ino = kdp->d_ino;
+ int64_t d_off = kdp->d_off;
+ unsigned char d_type = kdp->d_type;
+
+ DIRENT_SET_DP_INO (dp, d_ino);
+ dp->d_off = d_off;
+ if ((sizeof (dp->d_ino) != sizeof (kdp->d_ino)
+ && dp->d_ino != d_ino)
+ || (sizeof (dp->d_off) != sizeof (kdp->d_off)
+ && dp->d_off != d_off))
+ {
+ /* Overflow. If there was at least one entry
+ before this one, return them without error,
+ otherwise signal overflow. */
+ if (last_offset != -1)
+ {
+ lseek64 (fd, last_offset, SEEK_SET);
+ return (char *) dp - buf;
+ }
+ __set_errno (EOVERFLOW);
+ return -1;
+ }
+
+ last_offset = d_off;
+ dp->d_reclen = new_reclen;
+ dp->d_type = d_type;
+ memmove (dp->d_name, kdp->d_name,
+ old_reclen - offsetof (struct kernel_dirent64, d_name));
+
+ dp = (DIRENT_TYPE *) ((char *) dp + new_reclen);
+ kdp = (struct kernel_dirent64 *) ((char *) kdp + old_reclen);
+ }
+
+ return (char *) dp - buf;
+ }
+
+# ifndef __ASSUME_GETDENTS64_SYSCALL
+ __set_errno (saved_errno);
+ __have_no_getdents64 = 1;
+# endif
+ }
+#endif
+
+#ifdef __NR_getdents
+ {
+ size_t red_nbytes;
+ struct kernel_dirent *skdp, *kdp;
+ const size_t size_diff = (offsetof (DIRENT_TYPE, d_name)
+ - offsetof (struct kernel_dirent, d_name));
+
+ red_nbytes = MIN (nbytes
+ - ((nbytes / (offsetof (DIRENT_TYPE, d_name) + 14))
+ * size_diff),
+ nbytes - size_diff);
+
+ dp = (DIRENT_TYPE *) buf;
+ skdp = kdp = alloca (red_nbytes);
+
+ retval = syscall(SYS_getdents, fd, kdp, red_nbytes);
+
+ if (retval == -1)
+ return -1;
+
+ while ((char *) kdp < (char *) skdp + retval)
+ {
+ const size_t alignment = __alignof__ (DIRENT_TYPE);
+ /* Since kdp->d_reclen is already aligned for the kernel structure
+ this may compute a value that is bigger than necessary. */
+ size_t new_reclen = ((kdp->d_reclen + size_diff + alignment - 1)
+ & ~(alignment - 1));
+ if ((char *) dp + new_reclen > buf + nbytes)
+ {
+ /* Our heuristic failed. We read too many entries. Reset
+ the stream. */
+ assert (last_offset != -1);
+ lseek64 (fd, last_offset, SEEK_SET);
+
+ if ((char *) dp == buf)
+ {
+ /* The buffer the user passed in is too small to hold even
+ one entry. */
+ __set_errno (EINVAL);
+ return -1;
+ }
+
+ break;
+ }
+
+ last_offset = kdp->d_off;
+ DIRENT_SET_DP_INO(dp, kdp->d_ino);
+ dp->d_off = kdp->d_off;
+ dp->d_reclen = new_reclen;
+ dp->d_type = DT_UNKNOWN;
+ memcpy (dp->d_name, kdp->d_name,
+ kdp->d_reclen - offsetof (struct kernel_dirent, d_name));
+
+ dp = (DIRENT_TYPE *) ((char *) dp + new_reclen);
+ kdp = (struct kernel_dirent *) (((char *) kdp) + kdp->d_reclen);
+ }
+ }
+#endif
+
+ return (char *) dp - buf;
+}
Index: .
===================================================================
--- . (nonexistent)
+++ . (revision 5)
Property changes on: .
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~