diff options
| -rw-r--r-- | meta/recipes-devtools/pseudo/pseudo/opendir.patch | 94 | ||||
| -rw-r--r-- | meta/recipes-devtools/pseudo/pseudo/renameat.patch | 229 | ||||
| -rw-r--r-- | meta/recipes-devtools/pseudo/pseudo_1.2.bb | 6 |
3 files changed, 327 insertions, 2 deletions
diff --git a/meta/recipes-devtools/pseudo/pseudo/opendir.patch b/meta/recipes-devtools/pseudo/pseudo/opendir.patch new file mode 100644 index 0000000000..bc6cec8e7e --- /dev/null +++ b/meta/recipes-devtools/pseudo/pseudo/opendir.patch | |||
| @@ -0,0 +1,94 @@ | |||
| 1 | commit 162f2692c399b93311652201a940fdaf9c9e6924 | ||
| 2 | Author: Peter Seebach <peter.seebach@windriver.com> | ||
| 3 | Date: Thu Feb 2 11:45:42 2012 -0600 | ||
| 4 | |||
| 5 | Make opendir/closedir stash and forget directory names. | ||
| 6 | |||
| 7 | The dirfd(DIR *) interface allows you to get the fd for a DIR *, | ||
| 8 | meaning you can use it with openat(), meaning you can need its | ||
| 9 | path. This causes a segfault. Also gonna fix the base_path | ||
| 10 | code not to segfault in that case, but first fix the underlying | ||
| 11 | problem. | ||
| 12 | |||
| 13 | Upstream-Status: Backport | ||
| 14 | |||
| 15 | diff --git a/ChangeLog.txt b/ChangeLog.txt | ||
| 16 | index 4de488c..9625b38 100644 | ||
| 17 | --- a/ChangeLog.txt | ||
| 18 | +++ b/ChangeLog.txt | ||
| 19 | @@ -1,3 +1,7 @@ | ||
| 20 | +2012-02-02: | ||
| 21 | + * (seebs) stash dir name for DIR * from opendir using dirfd. | ||
| 22 | + * (seebs) add closedir. | ||
| 23 | + | ||
| 24 | 2011-11-02: | ||
| 25 | * (seebs) Call this 1.2 because the UNLOAD change is moderately | ||
| 26 | significant, and so's the clone change. | ||
| 27 | diff --git a/ports/unix/guts/closedir.c b/ports/unix/guts/closedir.c | ||
| 28 | new file mode 100644 | ||
| 29 | index 0000000..1085361 | ||
| 30 | --- /dev/null | ||
| 31 | +++ b/ports/unix/guts/closedir.c | ||
| 32 | @@ -0,0 +1,20 @@ | ||
| 33 | +/* | ||
| 34 | + * Copyright (c) 2012 Wind River Systems; see | ||
| 35 | + * guts/COPYRIGHT for information. | ||
| 36 | + * | ||
| 37 | + * static int | ||
| 38 | + * wrap_closedir(DIR *dirp) { | ||
| 39 | + * int rc = -1; | ||
| 40 | + */ | ||
| 41 | + if (!dirp) { | ||
| 42 | + errno = EFAULT; | ||
| 43 | + return -1; | ||
| 44 | + } | ||
| 45 | + | ||
| 46 | + int fd = dirfd(dirp); | ||
| 47 | + pseudo_client_op(OP_CLOSE, 0, fd, -1, 0, 0); | ||
| 48 | + rc = real_closedir(dirp); | ||
| 49 | + | ||
| 50 | +/* return rc; | ||
| 51 | + * } | ||
| 52 | + */ | ||
| 53 | diff --git a/ports/unix/guts/opendir.c b/ports/unix/guts/opendir.c | ||
| 54 | index 8eaa71f..e69717e 100644 | ||
| 55 | --- a/ports/unix/guts/opendir.c | ||
| 56 | +++ b/ports/unix/guts/opendir.c | ||
| 57 | @@ -6,8 +6,25 @@ | ||
| 58 | * wrap_opendir(const char *path) { | ||
| 59 | * DIR * rc = NULL; | ||
| 60 | */ | ||
| 61 | + struct stat buf; | ||
| 62 | + int save_errno; | ||
| 63 | |||
| 64 | rc = real_opendir(path); | ||
| 65 | + if (rc) { | ||
| 66 | + int fd; | ||
| 67 | + save_errno = errno; | ||
| 68 | + fd = dirfd(rc); | ||
| 69 | + if (real_fstat(fd, &buf) == -1) { | ||
| 70 | + pseudo_debug(1, "diropen (fd %d) succeeded, but fstat failed (%s).\n", | ||
| 71 | + fd, strerror(errno)); | ||
| 72 | + pseudo_client_op_plain(OP_OPEN, PSA_READ, fd, -1, path, 0); | ||
| 73 | + } else { | ||
| 74 | + pseudo_client_op_plain(OP_OPEN, PSA_READ, fd, -1, path, &buf); | ||
| 75 | + } | ||
| 76 | + | ||
| 77 | + | ||
| 78 | + errno = save_errno; | ||
| 79 | + } | ||
| 80 | |||
| 81 | /* return rc; | ||
| 82 | * } | ||
| 83 | diff --git a/ports/unix/wrapfuncs.in b/ports/unix/wrapfuncs.in | ||
| 84 | index e06e404..32250c4 100644 | ||
| 85 | --- a/ports/unix/wrapfuncs.in | ||
| 86 | +++ b/ports/unix/wrapfuncs.in | ||
| 87 | @@ -21,6 +21,7 @@ long pathconf(const char *path, int name); | ||
| 88 | char *realpath(const char *name, char *resolved_name); /* version="GLIBC_2.3" */ | ||
| 89 | int remove(const char *path); /* flags=AT_SYMLINK_NOFOLLOW */ | ||
| 90 | DIR *opendir(const char *path); | ||
| 91 | +int closedir(DIR *dirp); | ||
| 92 | char *tempnam(const char *template, const char *pfx); | ||
| 93 | char *tmpnam(char *s); | ||
| 94 | int truncate(const char *path, off_t length); | ||
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 @@ | |||
| 1 | commit 795f2b44b7f692151556782f142a4a6e7d45d892 | ||
| 2 | Author: Peter Seebach <peter.seebach@windriver.com> | ||
| 3 | Date: Thu Feb 2 15:49:21 2012 -0600 | ||
| 4 | |||
| 5 | Implement renameat() | ||
| 6 | |||
| 7 | After three long years, someone tried to use this. This was impossibly | ||
| 8 | hard back when pseudo was written, because there was only one dirfd | ||
| 9 | provided for. Thing is, now, the canonicalization happens in wrapfuncs, | ||
| 10 | so a small tweak to makewrappers to recognize that oldpath should use | ||
| 11 | olddirfd if it exists is enough to get us fully canonicalized paths | ||
| 12 | when needed. | ||
| 13 | |||
| 14 | Also fix the crash if base_path gets called with an fd for which we have | ||
| 15 | no path. | ||
| 16 | |||
| 17 | Upstream-Status: Backport | ||
| 18 | |||
| 19 | diff --git a/ChangeLog.txt b/ChangeLog.txt | ||
| 20 | index 9625b38..25bd463 100644 | ||
| 21 | --- a/ChangeLog.txt | ||
| 22 | +++ b/ChangeLog.txt | ||
| 23 | @@ -1,6 +1,9 @@ | ||
| 24 | 2012-02-02: | ||
| 25 | * (seebs) stash dir name for DIR * from opendir using dirfd. | ||
| 26 | * (seebs) add closedir. | ||
| 27 | + * (seebs) add initial pass at renameat() | ||
| 28 | + * (seebs) in base_path, don't try to strlen the result if | ||
| 29 | + fd_path() returns NULL. | ||
| 30 | |||
| 31 | 2011-11-02: | ||
| 32 | * (seebs) Call this 1.2 because the UNLOAD change is moderately | ||
| 33 | diff --git a/makewrappers b/makewrappers | ||
| 34 | index 20bbf2b..bf344d6 100755 | ||
| 35 | --- a/makewrappers | ||
| 36 | +++ b/makewrappers | ||
| 37 | @@ -211,12 +211,13 @@ class Function: | ||
| 38 | self.flags = '0' | ||
| 39 | self.port = port | ||
| 40 | self.directory = '' | ||
| 41 | - self.version = 'NULL' | ||
| 42 | + self.version = 'NULL' | ||
| 43 | # On Darwin, some functions are SECRETLY converted to foo$INODE64 | ||
| 44 | # when called. So we have to look those up for real_* | ||
| 45 | self.inode64 = None | ||
| 46 | self.real_func = None | ||
| 47 | self.paths_to_munge = [] | ||
| 48 | + self.dirfds = {} | ||
| 49 | self.hand_wrapped = None | ||
| 50 | # used for the copyright date when creating stub functions | ||
| 51 | self.date = datetime.date.today().year | ||
| 52 | @@ -239,6 +240,7 @@ class Function: | ||
| 53 | # * If the arg has a name ending in 'path', we will canonicalize it. | ||
| 54 | # * If the arg is named 'dirfd' or 'flags', it becomes the default | ||
| 55 | # values for the dirfd and flags arguments when canonicalizing. | ||
| 56 | + # * If the name ends in dirfd, we do the same fancy stuff. | ||
| 57 | # * Note that the "comments" field (/* ... */ after the decl) can | ||
| 58 | # override the dirfd/flags values. | ||
| 59 | self.args = ArgumentList(bits.group(2)) | ||
| 60 | @@ -246,7 +248,9 @@ class Function: | ||
| 61 | # ignore varargs, they never get these special treatments | ||
| 62 | if arg.vararg: | ||
| 63 | pass | ||
| 64 | - elif arg.name == 'dirfd': | ||
| 65 | + elif arg.name[-5:] == 'dirfd': | ||
| 66 | + if len(arg.name) > 5: | ||
| 67 | + self.dirfds[arg.name[:-5]] = True | ||
| 68 | self.dirfd = 'dirfd' | ||
| 69 | elif arg.name == 'flags': | ||
| 70 | self.flags = 'flags' | ||
| 71 | @@ -325,9 +329,13 @@ class Function: | ||
| 72 | """create/allocate canonical paths""" | ||
| 73 | alloc_paths = [] | ||
| 74 | for path in self.paths_to_munge: | ||
| 75 | + prefix = path[:-4] | ||
| 76 | + if not prefix in self.dirfds: | ||
| 77 | + prefix = '' | ||
| 78 | + print "for path %s: prefix <%s>" % ( path, prefix ) | ||
| 79 | alloc_paths.append( | ||
| 80 | - "%s = pseudo_root_path(__func__, __LINE__, %s, %s, %s);" % | ||
| 81 | - (path, self.dirfd, path, self.flags)) | ||
| 82 | + "%s = pseudo_root_path(__func__, __LINE__, %s%s, %s, %s);" % | ||
| 83 | + (path, prefix, self.dirfd, path, self.flags)) | ||
| 84 | return "\n\t\t\t".join(alloc_paths) | ||
| 85 | |||
| 86 | def free_paths(self): | ||
| 87 | diff --git a/ports/unix/guts/renameat.c b/ports/unix/guts/renameat.c | ||
| 88 | index c8203b7..f13cd1e 100644 | ||
| 89 | --- a/ports/unix/guts/renameat.c | ||
| 90 | +++ b/ports/unix/guts/renameat.c | ||
| 91 | @@ -1,15 +1,111 @@ | ||
| 92 | /* | ||
| 93 | - * Copyright (c) 2008-2010 Wind River Systems; see | ||
| 94 | + * Copyright (c) 2008-2012 Wind River Systems; see | ||
| 95 | * guts/COPYRIGHT for information. | ||
| 96 | * | ||
| 97 | * static int | ||
| 98 | * wrap_renameat(int olddirfd, const char *oldpath, int newdirfd, const char *newpath) { | ||
| 99 | * int rc = -1; | ||
| 100 | */ | ||
| 101 | + pseudo_msg_t *msg; | ||
| 102 | + struct stat oldbuf, newbuf; | ||
| 103 | + int oldrc, newrc; | ||
| 104 | + int save_errno; | ||
| 105 | + int old_db_entry = 0; | ||
| 106 | |||
| 107 | - pseudo_diag("help! unimplemented renameat [%s -> %s].\n", oldpath, newpath); | ||
| 108 | + pseudo_debug(2, "renameat: %d,%s->%d,%s\n", | ||
| 109 | + olddirfd, oldpath ? oldpath : "<nil>", | ||
| 110 | + newdirfd, newpath ? newpath : "<nil>"); | ||
| 111 | + | ||
| 112 | +#ifdef PSEUDO_NO_REAL_AT_FUNCTIONS | ||
| 113 | + if (olddirfd != AT_FDCWD || newdirfd != AT_FDCWD) { | ||
| 114 | + errno = ENOSYS; | ||
| 115 | + return -1; | ||
| 116 | + } | ||
| 117 | +#endif | ||
| 118 | + | ||
| 119 | + if (!oldpath || !newpath) { | ||
| 120 | + errno = EFAULT; | ||
| 121 | + return -1; | ||
| 122 | + } | ||
| 123 | + | ||
| 124 | + save_errno = errno; | ||
| 125 | + | ||
| 126 | +#ifdef PSEUDO_NO_REAL_AT_FUNCTIONS | ||
| 127 | + newrc = real_lstat(newpath, &newbuf); | ||
| 128 | + oldrc = real_lstat(oldpath, &oldbuf); | ||
| 129 | +#else | ||
| 130 | + oldrc = real___fxstatat(_STAT_VER, olddirfd, oldpath, &oldbuf, AT_SYMLINK_NOFOLLOW); | ||
| 131 | + newrc = real___fxstatat(_STAT_VER, newdirfd, newpath, &newbuf, AT_SYMLINK_NOFOLLOW); | ||
| 132 | +#endif | ||
| 133 | + | ||
| 134 | + errno = save_errno; | ||
| 135 | + | ||
| 136 | + /* newpath must be removed. */ | ||
| 137 | + /* as with unlink, we have to mark that the file may get deleted */ | ||
| 138 | + msg = pseudo_client_op_plain(OP_MAY_UNLINK, 0, -1, newdirfd, newpath, newrc ? NULL : &newbuf); | ||
| 139 | + if (msg && msg->result == RESULT_SUCCEED) | ||
| 140 | + old_db_entry = 1; | ||
| 141 | rc = real_renameat(olddirfd, oldpath, newdirfd, newpath); | ||
| 142 | + save_errno = errno; | ||
| 143 | + if (old_db_entry) { | ||
| 144 | + if (rc == -1) { | ||
| 145 | + /* since we failed, that wasn't really unlinked -- put | ||
| 146 | + * it back. | ||
| 147 | + */ | ||
| 148 | + pseudo_client_op_plain(OP_CANCEL_UNLINK, 0, -1, newdirfd, newpath, &newbuf); | ||
| 149 | + } else { | ||
| 150 | + /* confirm that the file was removed */ | ||
| 151 | + pseudo_client_op_plain(OP_DID_UNLINK, 0, -1, newdirfd, newpath, &newbuf); | ||
| 152 | + } | ||
| 153 | + } | ||
| 154 | + if (rc == -1) { | ||
| 155 | + /* and we're done. */ | ||
| 156 | + errno = save_errno; | ||
| 157 | + return rc; | ||
| 158 | + } | ||
| 159 | + save_errno = errno; | ||
| 160 | + /* nothing to do for a "rename" of a link to itself */ | ||
| 161 | + if (newrc != -1 && oldrc != -1 && | ||
| 162 | + newbuf.st_dev == oldbuf.st_dev && | ||
| 163 | + newbuf.st_ino == oldbuf.st_ino) { | ||
| 164 | + return rc; | ||
| 165 | + } | ||
| 166 | + | ||
| 167 | + /* rename(3) is not mv(1). rename(file, dir) fails; you must provide | ||
| 168 | + * the corrected path yourself. You can rename over a directory only | ||
| 169 | + * if the source is a directory. Symlinks are simply removed. | ||
| 170 | + * | ||
| 171 | + * If we got here, the real rename call succeeded. That means newpath | ||
| 172 | + * has been unlinked and oldpath has been linked to it. | ||
| 173 | + * | ||
| 174 | + * There are a ton of special cases to error check. I don't check | ||
| 175 | + * for any of them, because in every such case, the underlying rename | ||
| 176 | + * failed, and there is nothing to do. | ||
| 177 | + * The only tricky part is that, because we used to ignore symlinks, | ||
| 178 | + * we may have to rename or remove directory trees even though in | ||
| 179 | + * theory rename can never destroy a directory tree. | ||
| 180 | + */ | ||
| 181 | + if (!old_db_entry) { | ||
| 182 | + /* create an entry under the old name, which will then be | ||
| 183 | + * renamed; this way, children would get renamed too, if there | ||
| 184 | + * were any. | ||
| 185 | + */ | ||
| 186 | + if (newrc == 0) { | ||
| 187 | + if (newbuf.st_dev != oldbuf.st_dev) { | ||
| 188 | + oldbuf.st_dev = newbuf.st_dev; | ||
| 189 | + oldbuf.st_ino = newbuf.st_ino; | ||
| 190 | + } | ||
| 191 | + } | ||
| 192 | + pseudo_debug(1, "creating new '%s' [%llu] to rename\n", | ||
| 193 | + oldpath, (unsigned long long) oldbuf.st_ino); | ||
| 194 | + pseudo_client_op_plain(OP_LINK, 0, -1, olddirfd, oldpath, &oldbuf); | ||
| 195 | + } | ||
| 196 | + /* special case: use 'fd' for olddirfd, because | ||
| 197 | + * we know it has no other meaning for RENAME | ||
| 198 | + */ | ||
| 199 | + pseudo_client_op_plain(OP_RENAME, 0, olddirfd, newdirfd, newpath, &oldbuf, oldpath); | ||
| 200 | |||
| 201 | + errno = save_errno; | ||
| 202 | /* return rc; | ||
| 203 | * } | ||
| 204 | */ | ||
| 205 | diff --git a/pseudo_client.c b/pseudo_client.c | ||
| 206 | index 48607c2..4a30420 100644 | ||
| 207 | --- a/pseudo_client.c | ||
| 208 | +++ b/pseudo_client.c | ||
| 209 | @@ -988,6 +988,8 @@ base_path(int dirfd, const char *path, int leave_last) { | ||
| 210 | if (dirfd != -1 && dirfd != AT_FDCWD) { | ||
| 211 | if (dirfd >= 0) { | ||
| 212 | basepath = fd_path(dirfd); | ||
| 213 | + } | ||
| 214 | + if (basepath) { | ||
| 215 | baselen = strlen(basepath); | ||
| 216 | } else { | ||
| 217 | pseudo_diag("got *at() syscall for unknown directory, fd %d\n", dirfd); | ||
| 218 | @@ -1128,7 +1130,10 @@ pseudo_client_op(pseudo_op_t op, int access, int fd, int dirfd, const char *path | ||
| 219 | if (path) { | ||
| 220 | pseudo_debug(2, " %s", path); | ||
| 221 | } | ||
| 222 | - if (fd != -1) { | ||
| 223 | + /* for OP_RENAME in renameat, "fd" is also used for the | ||
| 224 | + * second dirfd. | ||
| 225 | + */ | ||
| 226 | + if (fd != -1 && op != OP_RENAME) { | ||
| 227 | pseudo_debug(2, " [fd %d]", fd); | ||
| 228 | } | ||
| 229 | if (buf) { | ||
diff --git a/meta/recipes-devtools/pseudo/pseudo_1.2.bb b/meta/recipes-devtools/pseudo/pseudo_1.2.bb index f2ebc228d9..04bcbce1ea 100644 --- a/meta/recipes-devtools/pseudo/pseudo_1.2.bb +++ b/meta/recipes-devtools/pseudo/pseudo_1.2.bb | |||
| @@ -1,10 +1,12 @@ | |||
| 1 | require pseudo.inc | 1 | require pseudo.inc |
| 2 | 2 | ||
| 3 | PR = "r4" | 3 | PR = "r5" |
| 4 | 4 | ||
| 5 | SRC_URI = "http://www.yoctoproject.org/downloads/${BPN}/${BPN}-${PV}.tar.bz2 \ | 5 | SRC_URI = "http://www.yoctoproject.org/downloads/${BPN}/${BPN}-${PV}.tar.bz2 \ |
| 6 | file://oe-config.patch \ | 6 | file://oe-config.patch \ |
| 7 | file://static_sqlite.patch" | 7 | file://static_sqlite.patch \ |
| 8 | file://opendir.patch \ | ||
| 9 | file://renameat.patch" | ||
| 8 | 10 | ||
| 9 | SRC_URI[md5sum] = "a2819084bab7e991f06626d02cf55048" | 11 | SRC_URI[md5sum] = "a2819084bab7e991f06626d02cf55048" |
| 10 | SRC_URI[sha256sum] = "4749a22df687f44d24c26e97170d4781a1bd52d5ee092364a40877e4d96ff058" | 12 | SRC_URI[sha256sum] = "4749a22df687f44d24c26e97170d4781a1bd52d5ee092364a40877e4d96ff058" |
