Radix cross Linux

The main Radix cross Linux repository contains the build scripts of packages, which have the most complete and common functionality for desktop machines

452 Commits   2 Branches   1 Tag
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
+*~