aboutsummaryrefslogtreecommitdiffstats
path: root/meta/recipes-devtools/pseudo/pseudo/renameat.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-devtools/pseudo/pseudo/renameat.patch')
-rw-r--r--meta/recipes-devtools/pseudo/pseudo/renameat.patch229
1 files changed, 229 insertions, 0 deletions
diff --git a/meta/recipes-devtools/pseudo/pseudo/renameat.patch b/meta/recipes-devtools/pseudo/pseudo/renameat.patch
new file mode 100644
index 0000000000..a2b2cbc78c
--- /dev/null
+++ b/meta/recipes-devtools/pseudo/pseudo/renameat.patch
@@ -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) {