mirror of
https://git.yoctoproject.org/poky
synced 2026-04-04 23:02:22 +02:00
pseudo: Wrap renameat and opendir
(From OE-Core rev: f6056cf0e7c76f2f3df650b088ce84df41ec14ca) Signed-off-by: Khem Raj <raj.khem@gmail.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
This commit is contained in:
94
meta/recipes-devtools/pseudo/pseudo/opendir.patch
Normal file
94
meta/recipes-devtools/pseudo/pseudo/opendir.patch
Normal file
@@ -0,0 +1,94 @@
|
||||
commit 162f2692c399b93311652201a940fdaf9c9e6924
|
||||
Author: Peter Seebach <peter.seebach@windriver.com>
|
||||
Date: Thu Feb 2 11:45:42 2012 -0600
|
||||
|
||||
Make opendir/closedir stash and forget directory names.
|
||||
|
||||
The dirfd(DIR *) interface allows you to get the fd for a DIR *,
|
||||
meaning you can use it with openat(), meaning you can need its
|
||||
path. This causes a segfault. Also gonna fix the base_path
|
||||
code not to segfault in that case, but first fix the underlying
|
||||
problem.
|
||||
|
||||
Upstream-Status: Backport
|
||||
|
||||
diff --git a/ChangeLog.txt b/ChangeLog.txt
|
||||
index 4de488c..9625b38 100644
|
||||
--- a/ChangeLog.txt
|
||||
+++ b/ChangeLog.txt
|
||||
@@ -1,3 +1,7 @@
|
||||
+2012-02-02:
|
||||
+ * (seebs) stash dir name for DIR * from opendir using dirfd.
|
||||
+ * (seebs) add closedir.
|
||||
+
|
||||
2011-11-02:
|
||||
* (seebs) Call this 1.2 because the UNLOAD change is moderately
|
||||
significant, and so's the clone change.
|
||||
diff --git a/ports/unix/guts/closedir.c b/ports/unix/guts/closedir.c
|
||||
new file mode 100644
|
||||
index 0000000..1085361
|
||||
--- /dev/null
|
||||
+++ b/ports/unix/guts/closedir.c
|
||||
@@ -0,0 +1,20 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2012 Wind River Systems; see
|
||||
+ * guts/COPYRIGHT for information.
|
||||
+ *
|
||||
+ * static int
|
||||
+ * wrap_closedir(DIR *dirp) {
|
||||
+ * int rc = -1;
|
||||
+ */
|
||||
+ if (!dirp) {
|
||||
+ errno = EFAULT;
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ int fd = dirfd(dirp);
|
||||
+ pseudo_client_op(OP_CLOSE, 0, fd, -1, 0, 0);
|
||||
+ rc = real_closedir(dirp);
|
||||
+
|
||||
+/* return rc;
|
||||
+ * }
|
||||
+ */
|
||||
diff --git a/ports/unix/guts/opendir.c b/ports/unix/guts/opendir.c
|
||||
index 8eaa71f..e69717e 100644
|
||||
--- a/ports/unix/guts/opendir.c
|
||||
+++ b/ports/unix/guts/opendir.c
|
||||
@@ -6,8 +6,25 @@
|
||||
* wrap_opendir(const char *path) {
|
||||
* DIR * rc = NULL;
|
||||
*/
|
||||
+ struct stat buf;
|
||||
+ int save_errno;
|
||||
|
||||
rc = real_opendir(path);
|
||||
+ if (rc) {
|
||||
+ int fd;
|
||||
+ save_errno = errno;
|
||||
+ fd = dirfd(rc);
|
||||
+ if (real_fstat(fd, &buf) == -1) {
|
||||
+ pseudo_debug(1, "diropen (fd %d) succeeded, but fstat failed (%s).\n",
|
||||
+ fd, strerror(errno));
|
||||
+ pseudo_client_op_plain(OP_OPEN, PSA_READ, fd, -1, path, 0);
|
||||
+ } else {
|
||||
+ pseudo_client_op_plain(OP_OPEN, PSA_READ, fd, -1, path, &buf);
|
||||
+ }
|
||||
+
|
||||
+
|
||||
+ errno = save_errno;
|
||||
+ }
|
||||
|
||||
/* return rc;
|
||||
* }
|
||||
diff --git a/ports/unix/wrapfuncs.in b/ports/unix/wrapfuncs.in
|
||||
index e06e404..32250c4 100644
|
||||
--- a/ports/unix/wrapfuncs.in
|
||||
+++ b/ports/unix/wrapfuncs.in
|
||||
@@ -21,6 +21,7 @@ long pathconf(const char *path, int name);
|
||||
char *realpath(const char *name, char *resolved_name); /* version="GLIBC_2.3" */
|
||||
int remove(const char *path); /* flags=AT_SYMLINK_NOFOLLOW */
|
||||
DIR *opendir(const char *path);
|
||||
+int closedir(DIR *dirp);
|
||||
char *tempnam(const char *template, const char *pfx);
|
||||
char *tmpnam(char *s);
|
||||
int truncate(const char *path, off_t length);
|
||||
229
meta/recipes-devtools/pseudo/pseudo/renameat.patch
Normal file
229
meta/recipes-devtools/pseudo/pseudo/renameat.patch
Normal file
@@ -0,0 +1,229 @@
|
||||
commit 795f2b44b7f692151556782f142a4a6e7d45d892
|
||||
Author: Peter Seebach <peter.seebach@windriver.com>
|
||||
Date: Thu Feb 2 15:49:21 2012 -0600
|
||||
|
||||
Implement renameat()
|
||||
|
||||
After three long years, someone tried to use this. This was impossibly
|
||||
hard back when pseudo was written, because there was only one dirfd
|
||||
provided for. Thing is, now, the canonicalization happens in wrapfuncs,
|
||||
so a small tweak to makewrappers to recognize that oldpath should use
|
||||
olddirfd if it exists is enough to get us fully canonicalized paths
|
||||
when needed.
|
||||
|
||||
Also fix the crash if base_path gets called with an fd for which we have
|
||||
no path.
|
||||
|
||||
Upstream-Status: Backport
|
||||
|
||||
diff --git a/ChangeLog.txt b/ChangeLog.txt
|
||||
index 9625b38..25bd463 100644
|
||||
--- a/ChangeLog.txt
|
||||
+++ b/ChangeLog.txt
|
||||
@@ -1,6 +1,9 @@
|
||||
2012-02-02:
|
||||
* (seebs) stash dir name for DIR * from opendir using dirfd.
|
||||
* (seebs) add closedir.
|
||||
+ * (seebs) add initial pass at renameat()
|
||||
+ * (seebs) in base_path, don't try to strlen the result if
|
||||
+ fd_path() returns NULL.
|
||||
|
||||
2011-11-02:
|
||||
* (seebs) Call this 1.2 because the UNLOAD change is moderately
|
||||
diff --git a/makewrappers b/makewrappers
|
||||
index 20bbf2b..bf344d6 100755
|
||||
--- a/makewrappers
|
||||
+++ b/makewrappers
|
||||
@@ -211,12 +211,13 @@ class Function:
|
||||
self.flags = '0'
|
||||
self.port = port
|
||||
self.directory = ''
|
||||
- self.version = 'NULL'
|
||||
+ self.version = 'NULL'
|
||||
# On Darwin, some functions are SECRETLY converted to foo$INODE64
|
||||
# when called. So we have to look those up for real_*
|
||||
self.inode64 = None
|
||||
self.real_func = None
|
||||
self.paths_to_munge = []
|
||||
+ self.dirfds = {}
|
||||
self.hand_wrapped = None
|
||||
# used for the copyright date when creating stub functions
|
||||
self.date = datetime.date.today().year
|
||||
@@ -239,6 +240,7 @@ class Function:
|
||||
# * If the arg has a name ending in 'path', we will canonicalize it.
|
||||
# * If the arg is named 'dirfd' or 'flags', it becomes the default
|
||||
# values for the dirfd and flags arguments when canonicalizing.
|
||||
+ # * If the name ends in dirfd, we do the same fancy stuff.
|
||||
# * Note that the "comments" field (/* ... */ after the decl) can
|
||||
# override the dirfd/flags values.
|
||||
self.args = ArgumentList(bits.group(2))
|
||||
@@ -246,7 +248,9 @@ class Function:
|
||||
# ignore varargs, they never get these special treatments
|
||||
if arg.vararg:
|
||||
pass
|
||||
- elif arg.name == 'dirfd':
|
||||
+ elif arg.name[-5:] == 'dirfd':
|
||||
+ if len(arg.name) > 5:
|
||||
+ self.dirfds[arg.name[:-5]] = True
|
||||
self.dirfd = 'dirfd'
|
||||
elif arg.name == 'flags':
|
||||
self.flags = 'flags'
|
||||
@@ -325,9 +329,13 @@ class Function:
|
||||
"""create/allocate canonical paths"""
|
||||
alloc_paths = []
|
||||
for path in self.paths_to_munge:
|
||||
+ prefix = path[:-4]
|
||||
+ if not prefix in self.dirfds:
|
||||
+ prefix = ''
|
||||
+ print "for path %s: prefix <%s>" % ( path, prefix )
|
||||
alloc_paths.append(
|
||||
- "%s = pseudo_root_path(__func__, __LINE__, %s, %s, %s);" %
|
||||
- (path, self.dirfd, path, self.flags))
|
||||
+ "%s = pseudo_root_path(__func__, __LINE__, %s%s, %s, %s);" %
|
||||
+ (path, prefix, self.dirfd, path, self.flags))
|
||||
return "\n\t\t\t".join(alloc_paths)
|
||||
|
||||
def free_paths(self):
|
||||
diff --git a/ports/unix/guts/renameat.c b/ports/unix/guts/renameat.c
|
||||
index c8203b7..f13cd1e 100644
|
||||
--- a/ports/unix/guts/renameat.c
|
||||
+++ b/ports/unix/guts/renameat.c
|
||||
@@ -1,15 +1,111 @@
|
||||
/*
|
||||
- * Copyright (c) 2008-2010 Wind River Systems; see
|
||||
+ * Copyright (c) 2008-2012 Wind River Systems; see
|
||||
* guts/COPYRIGHT for information.
|
||||
*
|
||||
* static int
|
||||
* wrap_renameat(int olddirfd, const char *oldpath, int newdirfd, const char *newpath) {
|
||||
* int rc = -1;
|
||||
*/
|
||||
+ pseudo_msg_t *msg;
|
||||
+ struct stat oldbuf, newbuf;
|
||||
+ int oldrc, newrc;
|
||||
+ int save_errno;
|
||||
+ int old_db_entry = 0;
|
||||
|
||||
- pseudo_diag("help! unimplemented renameat [%s -> %s].\n", oldpath, newpath);
|
||||
+ pseudo_debug(2, "renameat: %d,%s->%d,%s\n",
|
||||
+ olddirfd, oldpath ? oldpath : "<nil>",
|
||||
+ newdirfd, newpath ? newpath : "<nil>");
|
||||
+
|
||||
+#ifdef PSEUDO_NO_REAL_AT_FUNCTIONS
|
||||
+ if (olddirfd != AT_FDCWD || newdirfd != AT_FDCWD) {
|
||||
+ errno = ENOSYS;
|
||||
+ return -1;
|
||||
+ }
|
||||
+#endif
|
||||
+
|
||||
+ if (!oldpath || !newpath) {
|
||||
+ errno = EFAULT;
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ save_errno = errno;
|
||||
+
|
||||
+#ifdef PSEUDO_NO_REAL_AT_FUNCTIONS
|
||||
+ newrc = real_lstat(newpath, &newbuf);
|
||||
+ oldrc = real_lstat(oldpath, &oldbuf);
|
||||
+#else
|
||||
+ oldrc = real___fxstatat(_STAT_VER, olddirfd, oldpath, &oldbuf, AT_SYMLINK_NOFOLLOW);
|
||||
+ newrc = real___fxstatat(_STAT_VER, newdirfd, newpath, &newbuf, AT_SYMLINK_NOFOLLOW);
|
||||
+#endif
|
||||
+
|
||||
+ errno = save_errno;
|
||||
+
|
||||
+ /* newpath must be removed. */
|
||||
+ /* as with unlink, we have to mark that the file may get deleted */
|
||||
+ msg = pseudo_client_op_plain(OP_MAY_UNLINK, 0, -1, newdirfd, newpath, newrc ? NULL : &newbuf);
|
||||
+ if (msg && msg->result == RESULT_SUCCEED)
|
||||
+ old_db_entry = 1;
|
||||
rc = real_renameat(olddirfd, oldpath, newdirfd, newpath);
|
||||
+ save_errno = errno;
|
||||
+ if (old_db_entry) {
|
||||
+ if (rc == -1) {
|
||||
+ /* since we failed, that wasn't really unlinked -- put
|
||||
+ * it back.
|
||||
+ */
|
||||
+ pseudo_client_op_plain(OP_CANCEL_UNLINK, 0, -1, newdirfd, newpath, &newbuf);
|
||||
+ } else {
|
||||
+ /* confirm that the file was removed */
|
||||
+ pseudo_client_op_plain(OP_DID_UNLINK, 0, -1, newdirfd, newpath, &newbuf);
|
||||
+ }
|
||||
+ }
|
||||
+ if (rc == -1) {
|
||||
+ /* and we're done. */
|
||||
+ errno = save_errno;
|
||||
+ return rc;
|
||||
+ }
|
||||
+ save_errno = errno;
|
||||
+ /* nothing to do for a "rename" of a link to itself */
|
||||
+ if (newrc != -1 && oldrc != -1 &&
|
||||
+ newbuf.st_dev == oldbuf.st_dev &&
|
||||
+ newbuf.st_ino == oldbuf.st_ino) {
|
||||
+ return rc;
|
||||
+ }
|
||||
+
|
||||
+ /* rename(3) is not mv(1). rename(file, dir) fails; you must provide
|
||||
+ * the corrected path yourself. You can rename over a directory only
|
||||
+ * if the source is a directory. Symlinks are simply removed.
|
||||
+ *
|
||||
+ * If we got here, the real rename call succeeded. That means newpath
|
||||
+ * has been unlinked and oldpath has been linked to it.
|
||||
+ *
|
||||
+ * There are a ton of special cases to error check. I don't check
|
||||
+ * for any of them, because in every such case, the underlying rename
|
||||
+ * failed, and there is nothing to do.
|
||||
+ * The only tricky part is that, because we used to ignore symlinks,
|
||||
+ * we may have to rename or remove directory trees even though in
|
||||
+ * theory rename can never destroy a directory tree.
|
||||
+ */
|
||||
+ if (!old_db_entry) {
|
||||
+ /* create an entry under the old name, which will then be
|
||||
+ * renamed; this way, children would get renamed too, if there
|
||||
+ * were any.
|
||||
+ */
|
||||
+ if (newrc == 0) {
|
||||
+ if (newbuf.st_dev != oldbuf.st_dev) {
|
||||
+ oldbuf.st_dev = newbuf.st_dev;
|
||||
+ oldbuf.st_ino = newbuf.st_ino;
|
||||
+ }
|
||||
+ }
|
||||
+ pseudo_debug(1, "creating new '%s' [%llu] to rename\n",
|
||||
+ oldpath, (unsigned long long) oldbuf.st_ino);
|
||||
+ pseudo_client_op_plain(OP_LINK, 0, -1, olddirfd, oldpath, &oldbuf);
|
||||
+ }
|
||||
+ /* special case: use 'fd' for olddirfd, because
|
||||
+ * we know it has no other meaning for RENAME
|
||||
+ */
|
||||
+ pseudo_client_op_plain(OP_RENAME, 0, olddirfd, newdirfd, newpath, &oldbuf, oldpath);
|
||||
|
||||
+ errno = save_errno;
|
||||
/* return rc;
|
||||
* }
|
||||
*/
|
||||
diff --git a/pseudo_client.c b/pseudo_client.c
|
||||
index 48607c2..4a30420 100644
|
||||
--- a/pseudo_client.c
|
||||
+++ b/pseudo_client.c
|
||||
@@ -988,6 +988,8 @@ base_path(int dirfd, const char *path, int leave_last) {
|
||||
if (dirfd != -1 && dirfd != AT_FDCWD) {
|
||||
if (dirfd >= 0) {
|
||||
basepath = fd_path(dirfd);
|
||||
+ }
|
||||
+ if (basepath) {
|
||||
baselen = strlen(basepath);
|
||||
} else {
|
||||
pseudo_diag("got *at() syscall for unknown directory, fd %d\n", dirfd);
|
||||
@@ -1128,7 +1130,10 @@ pseudo_client_op(pseudo_op_t op, int access, int fd, int dirfd, const char *path
|
||||
if (path) {
|
||||
pseudo_debug(2, " %s", path);
|
||||
}
|
||||
- if (fd != -1) {
|
||||
+ /* for OP_RENAME in renameat, "fd" is also used for the
|
||||
+ * second dirfd.
|
||||
+ */
|
||||
+ if (fd != -1 && op != OP_RENAME) {
|
||||
pseudo_debug(2, " [fd %d]", fd);
|
||||
}
|
||||
if (buf) {
|
||||
@@ -1,10 +1,12 @@
|
||||
require pseudo.inc
|
||||
|
||||
PR = "r4"
|
||||
PR = "r5"
|
||||
|
||||
SRC_URI = "http://www.yoctoproject.org/downloads/${BPN}/${BPN}-${PV}.tar.bz2 \
|
||||
file://oe-config.patch \
|
||||
file://static_sqlite.patch"
|
||||
file://static_sqlite.patch \
|
||||
file://opendir.patch \
|
||||
file://renameat.patch"
|
||||
|
||||
SRC_URI[md5sum] = "a2819084bab7e991f06626d02cf55048"
|
||||
SRC_URI[sha256sum] = "4749a22df687f44d24c26e97170d4781a1bd52d5ee092364a40877e4d96ff058"
|
||||
|
||||
Reference in New Issue
Block a user