diff options
author | Khem Raj <raj.khem@gmail.com> | 2012-02-03 00:03:33 -0800 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2012-02-08 00:50:28 +0000 |
commit | 41936cd5bcfddfbf3374174c1e3cdea951d2d10f (patch) | |
tree | b0cdd347a41a848821c16812c98c3823280ff454 /meta/recipes-devtools/pseudo | |
parent | bdc50cbfbba0148a09f78e49b658f195295f3f80 (diff) | |
download | poky-41936cd5bcfddfbf3374174c1e3cdea951d2d10f.tar.gz |
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>
Diffstat (limited to 'meta/recipes-devtools/pseudo')
-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" |