New upstream version 1.9.0+git20190515+996bead
Andrej Shadura
4 years ago
456 | 456 | |
457 | 457 | END OF TERMS AND CONDITIONS |
458 | 458 | |
459 | How to Apply These Terms to Your New Libraries | |
460 | ||
461 | If you develop a new library, and you want it to be of the greatest | |
462 | possible use to the public, we recommend making it free software that | |
463 | everyone can redistribute and change. You can do so by permitting | |
464 | redistribution under these terms (or, alternatively, under the terms of the | |
465 | ordinary General Public License). | |
466 | ||
467 | To apply these terms, attach the following notices to the library. It is | |
468 | safest to attach them to the start of each source file to most effectively | |
469 | convey the exclusion of warranty; and each file should have at least the | |
470 | "copyright" line and a pointer to where the full notice is found. | |
471 | ||
472 | <one line to give the library's name and a brief idea of what it does.> | |
473 | Copyright (C) <year> <name of author> | |
474 | ||
475 | This library is free software; you can redistribute it and/or | |
476 | modify it under the terms of the GNU Lesser General Public | |
477 | License as published by the Free Software Foundation; either | |
478 | version 2.1 of the License, or (at your option) any later version. | |
479 | ||
480 | This library is distributed in the hope that it will be useful, | |
481 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
482 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
483 | Lesser General Public License for more details. | |
484 | ||
485 | You should have received a copy of the GNU Lesser General Public | |
486 | License along with this library; if not, write to the Free Software | |
487 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
488 | ||
489 | Also add information on how to contact you by electronic and paper mail. | |
490 | ||
491 | You should also get your employer (if you work as a programmer) or your | |
492 | school, if any, to sign a "copyright disclaimer" for the library, if | |
493 | necessary. Here is a sample; alter the names: | |
494 | ||
495 | Yoyodyne, Inc., hereby disclaims all copyright interest in the | |
496 | library `Frob' (a library for tweaking knobs) written by James Random Hacker. | |
497 | ||
498 | <signature of Ty Coon>, 1 April 1990 | |
499 | Ty Coon, President of Vice | |
500 | ||
501 | That's all there is to it! | |
502 | ||
503 | ||
459 | Note: | |
460 | Individual files contain the following tag instead of the full license text. | |
461 | ||
462 | SPDX-License-Identifier: LGPL-2.1-only | |
463 | ||
464 | This enables machine processing of license information based on the SPDX | |
465 | License Identifiers that are here available: http://spdx.org/licenses/ |
0 | 2019-05-15: | |
1 | * (RP) Add SDPX license headers to source files. | |
2 | ||
3 | 2019-04-10: | |
4 | * (seebs) Experimental workaround for special non-blocking open | |
5 | case. | |
6 | * (seebs) fix warnings in renameat2. | |
7 | ||
8 | 2019-04-09: | |
9 | * (seebs) Partial fix for db corruption issue. | |
10 | * (seebs) Make a glibc renameat2 wrapper that just fails because | |
11 | implementing renameat2 semantics is Surprisingly Hard. | |
12 | ||
13 | 2018-12-15: | |
14 | * (seebs) Import IPC patch from Rasmus Villemoes. | |
15 | * (seebs) Import (another) IPC patch from Rasmus Villemoes. | |
16 | ||
17 | 2018-11-29: | |
18 | * (seebs) add missing <stdint.h> to pseudo_db.c. Thanks to | |
19 | Bernhard Hartleb <bernhard.hartleb@gmail.com> for pointing | |
20 | this out. | |
21 | ||
22 | 2018-09-20: | |
23 | * (seebs) coerce inodes to signed int64_t range when shoving | |
24 | them into sqlite. | |
25 | * (seebs) add another /*fallthrough*/ comment to make gcc7 happy. | |
26 | * (seebs) also make sure inodes are handled as 64-bit, not | |
27 | 32-bit, which probably matters more. Thanks to <Jack.Fewx@dell.com> | |
28 | for catching this. | |
29 | ||
30 | 2018-04-13: | |
31 | * (seebs) Reduce spamminess of path mismatches. | |
32 | Don't log path mismatches with multiple links unless you've | |
33 | requested path+verbose debugging. Also allow pseudo_debug | |
34 | to take a 0 to indicate "always debug", because we want that | |
35 | message unconditionally, and I don't want near-identical | |
36 | calls to diag() and debug(). | |
37 | * (seebs) Fix a lurking stray slash that could happen while | |
38 | resolving absolute symlinks. | |
39 | * (seebs) fix mishandled flags for symlink following. | |
40 | ||
41 | 2018-04-02: | |
42 | * (seebs) Change default copyright notice in guts to | |
43 | say "Peter Seebach" rather than "Wind River" as I haven't | |
44 | worked there in over a year. | |
45 | ||
46 | 2018-03-31: | |
47 | * (seebs) keep pseudo_fix_path from changing errno, because | |
48 | *some* people think they should check errno to find out | |
49 | whether an error occurred, even if no call has returned | |
50 | a status indicating an error, and this is completely wrong | |
51 | but we can't fix them all. | |
52 | * (seebs) check for wrapper initialization in syscall wrapper, | |
53 | because what if it was the *first* call someone made. (Thanks | |
54 | to Joshua Watt <jpewhacker@gmail.com> for diagnosing this | |
55 | before I got a chance.) | |
56 | ||
57 | 2018-03-30: | |
58 | * (seebs) fix path stuff more thoroughly. | |
59 | * (seebs) Merge suggested README change from Richard Tollerton | |
60 | <rich.tollerton@ni.com> pointing to oe-core list. | |
61 | * (seebs) Merge suggested setuid/etc bit change from | |
62 | Richard Tollerton, and associated test case. | |
63 | ||
64 | 2018-03-29: | |
65 | * (seebs) wrap syscall, and if SYS_renameat2 exists, try to | |
66 | reject it with ENOSYS, because coreutils started using a | |
67 | new syscall. An actual renameat2 wrapper will be a major | |
68 | effort ("changing the pseudo_ipc data structure") and is | |
69 | pointless when glibc hasn't got a wrapper so we have no | |
70 | viable test cases. | |
71 | ||
72 | 2018-03-06: | |
73 | * (seebs) Update path handling a bit to correctly fail if a path | |
74 | tries to have a slash after a plain file name, even in cases | |
75 | like "foo/.", which were previously ignored (or in the case of | |
76 | "..", resolved as though it had been a directory). | |
77 | ||
78 | 2018-03-01: | |
79 | * (seebs) If you get a CREAT for an existing file, and it matches | |
80 | both path and inode, don't delete the entry because the inode | |
81 | matched and then not create it because the path used to match | |
82 | before you delete it. | |
83 | ||
84 | 2018-02-26: | |
85 | * (seebs) implement mkstemps, mkostemp, and mkostemps. Actually, | |
86 | move implementation all to mkostemps, then implement the others | |
87 | in terms of it. | |
88 | ||
89 | 2018-02-19: | |
90 | * (seebs) fix using index of request rather than request's value | |
91 | ||
92 | 2018-02-16: | |
93 | * (seebs) allow closing client #0. | |
94 | ||
95 | 2018-02-15: | |
96 | * (seebs) O_TMPFILE is actually some other flag AND O_DIRECTORYy, | |
97 | so a test for (flags & O_TMPFILE) does not actually test that | |
98 | O_TMPFILE is set. | |
99 | ||
100 | 2018-01-20: | |
101 | * (seebs) merge patch from <joshua.g.lock@linux.intel.com> to fix | |
102 | open/openat flags. | |
103 | ||
104 | 2018-01-16: | |
105 | * (seebs) rework the LINKAT case significantly but now | |
106 | it's actually probably right. | |
107 | * (<zboszor@pr.hu>) handle extremely long group names | |
108 | in getgrnam and similar functions. | |
109 | * (seebs) drop the diagnostic for a missing "real" function | |
110 | as it turns out to be counterproductive at best. | |
111 | * (seebs) merge epoll support from <alexander.kanavin@linux.intel.com> | |
112 | * (seebs) add wrapper for statvfs (based on patch from | |
113 | <dan.dedrick@gmail.com>) | |
114 | * (seebs) Call this 1.9.0. | |
115 | * (seebs) Experimental-ish: Require a response even for FASTOP | |
116 | just to confirm delivery of message/server availability. | |
117 | ||
118 | 2017-12-22: | |
119 | * (seebs) handle the pathological case of LINKAT with | |
120 | AT_SYMLINK_FOLLOW on /proc/self/fd/N. | |
121 | ||
122 | 2017-12-18: | |
123 | * (seebs) Add a list of clients as a handler for SIGUSR2. (Useful | |
124 | for debugging, maybe.) | |
125 | ||
126 | 2017-04-13: | |
127 | * (seebs) don't unset LD_PRELOAD or the like, because if you | |
128 | do that, bash can segfault because it "knows" how many | |
129 | fields are in environ. | |
130 | ||
131 | 2017-02-24: | |
132 | * (seebs) import posix_acl_default fix from Anton Gerasimov | |
133 | <anton@advancedtelematic.com> | |
134 | 2017-02-03: | |
135 | * (gportay) contributed fix to Makefile (fix binaries rebuild). | |
136 | ||
137 | 2017-02-01: | |
138 | * (seebs) handle xattr deletion slightly more carefully. | |
139 | * (seebs) tag this as 1.8.2 | |
140 | ||
141 | 2016-12-12: | |
142 | * (seebs) contributed fix to makewrappers (fix space/tab issues) | |
143 | * (seebs) contributed fixes for Python 3 print support | |
144 | * (seebs) contributed fixes for Python 3 support | |
145 | * All of these from: Gaël PORTAY <gael.portay@savoirfairelinux.com> | |
146 | * (seebs) import fix from Rabin Vincent for test case | |
147 | * (seebs) import fix from Rabin Vincent for pthread mutexes | |
148 | * (seebs) import fix from George McCollister for capset. | |
149 | * (seebs) import fix from Igor Gnatenko for man page sections. | |
150 | ||
151 | 2016-11-23: | |
152 | * (seebs) actually wait on server shutdown for pseudo -S [cmd] | |
153 | ||
154 | 2016-11-04: | |
155 | * (seebs) clarify usage message on missing --prefix | |
156 | ||
157 | 2016-10-31: | |
158 | * (seebs) drop silly if | |
159 | ||
160 | 2016-10-29: | |
161 | * (seebs) handle x32 | |
162 | ||
0 | 163 | 2016-10-13: |
1 | 164 | * (seebs) handle commas in CFLAGS |
2 | 165 |
2 | 2 | # |
3 | 3 | # Copyright (c) 2008-2015 Wind River Systems, Inc. |
4 | 4 | # |
5 | # This program is free software; you can redistribute it and/or modify | |
6 | # it under the terms of the Lesser GNU General Public License version 2.1 as | |
7 | # published by the Free Software Foundation. | |
8 | # | |
9 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | |
12 | # See the Lesser GNU General Public License for more details. | |
13 | # | |
14 | # You should have received a copy of the Lesser GNU General Public License | |
15 | # version 2.1 along with this program; if not, write to the Free Software | |
16 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
5 | # SPDX-License-Identifier: LGPL-2.1-only | |
17 | 6 | # |
18 | 7 | |
19 | 8 | # configuration flags |
24 | 13 | SQLITE_LIB=@SQLITE_LIB@ |
25 | 14 | SQLITE_MEMORY=@SQLITE_MEMORY@ |
26 | 15 | FORCE_ASYNC=@FORCE_ASYNC@ |
16 | EPOLL=@EPOLL@ | |
27 | 17 | XATTR=@XATTR@ |
28 | 18 | XATTRDB=@XATTRDB@ |
29 | 19 | PROFILING=@PROFILING@ |
43 | 33 | ARCH_FLAGS=@ARCH_FLAGS@ |
44 | 34 | MARK64=@MARK64@ |
45 | 35 | RPATH=@RPATH@ |
46 | VERSION=1.8.1 | |
36 | VERSION=1.9.0 | |
47 | 37 | |
48 | 38 | LIB=@LIB@ |
49 | 39 | BIN=bin |
53 | 43 | |
54 | 44 | CFLAGS_BASE=-pipe -std=gnu99 -Wall -W -Wextra |
55 | 45 | CFLAGS_CODE=-fPIC -D_LARGEFILE64_SOURCE -D_ATFILE_SOURCE $(ARCH_FLAGS) |
56 | CFLAGS_DEFS=-DPSEUDO_PREFIX='"$(PREFIX)"' -DPSEUDO_SUFFIX='"$(SUFFIX)"' -DPSEUDO_BINDIR='"$(BIN)"' -DPSEUDO_LIBDIR='"$(LIB)"' -DPSEUDO_LOCALSTATEDIR='"$(LOCALSTATE)"' -DPSEUDO_VERSION='"$(VERSION)"' $(SQLITE_MEMORY) $(FORCE_ASYNC) -DPSEUDO_PASSWD_FALLBACK='$(PASSWD_FALLBACK)' $(OPTDEFS) | |
46 | CFLAGS_DEFS=-DPSEUDO_PREFIX='"$(PREFIX)"' -DPSEUDO_SUFFIX='"$(SUFFIX)"' -DPSEUDO_BINDIR='"$(BIN)"' -DPSEUDO_LIBDIR='"$(LIB)"' -DPSEUDO_LOCALSTATEDIR='"$(LOCALSTATE)"' -DPSEUDO_VERSION='"$(VERSION)"' $(SQLITE_MEMORY) $(FORCE_ASYNC) -DPSEUDO_PASSWD_FALLBACK='$(PASSWD_FALLBACK)' $(OPTDEFS) $(EPOLL) | |
57 | 47 | CFLAGS_DEBUG=-O2 -g |
58 | 48 | @DEFAULT_SQLITE@CFLAGS_SQL=-L$(SQLITE)/$(SQLITE_LIB) -I$(SQLITE)/include $(RPATH) |
59 | 49 | CFLAGS_PSEUDO=$(CFLAGS_BASE) $(CFLAGS_CODE) $(CFLAGS_DEFS) \ |
83 | 73 | |
84 | 74 | all: $(LIBPSEUDO) $(PSEUDO) $(PSEUDODB) $(PSEUDOLOG) $(PSEUDO_PROFILE) |
85 | 75 | |
86 | test: all $(BIN) $(LIB) $(LOCALSTATE) | |
76 | test: all | $(BIN) $(LIB) $(LOCALSTATE) | |
87 | 77 | @./run_tests.sh -v |
88 | 78 | |
89 | 79 | install-lib: $(LIBPSEUDO) |
105 | 95 | |
106 | 96 | pseudo: $(PSEUDO) |
107 | 97 | |
108 | $(PSEUDO): $(BIN) pseudo.o $(SHOBJS) $(DBOBJS) pseudo_client.o pseudo_server.o pseudo_ipc.o | |
98 | $(PSEUDO): pseudo.o $(SHOBJS) $(DBOBJS) pseudo_client.o pseudo_server.o pseudo_ipc.o | $(BIN) | |
109 | 99 | $(CC) $(CFLAGS) $(CFLAGS_PSEUDO) -o $(PSEUDO) \ |
110 | 100 | pseudo.o pseudo_server.o pseudo_client.o pseudo_ipc.o \ |
111 | 101 | $(DBOBJS) $(SHOBJS) $(LDFLAGS) $(DB_LDFLAGS) $(CLIENT_LDFLAGS) |
112 | 102 | |
113 | 103 | pseudolog: $(PSEUDOLOG) |
114 | 104 | |
115 | $(PSEUDOLOG): $(BIN) pseudolog.o $(SHOBJS) $(DBOBJS) pseudo_client.o pseudo_ipc.o | |
105 | $(PSEUDOLOG): pseudolog.o $(SHOBJS) $(DBOBJS) pseudo_client.o pseudo_ipc.o | $(BIN) | |
116 | 106 | $(CC) $(CFLAGS) $(CFLAGS_PSEUDO) -o $(PSEUDOLOG) pseudolog.o pseudo_client.o pseudo_ipc.o \ |
117 | 107 | $(DBOBJS) $(SHOBJS) $(LDFLAGS) $(DB_LDFLAGS) $(CLIENT_LDFLAGS) |
118 | 108 | |
119 | 109 | pseudodb: $(PSEUDODB) |
120 | 110 | |
121 | $(PSEUDODB): $(BIN) pseudodb.o $(SHOBJS) $(DBOBJS) pseudo_ipc.o | |
111 | $(PSEUDODB): pseudodb.o $(SHOBJS) $(DBOBJS) pseudo_ipc.o | $(BIN) | |
122 | 112 | $(CC) $(CFLAGS) $(CFLAGS_PSEUDO) -o $(PSEUDODB) pseudodb.o \ |
123 | 113 | $(DBOBJS) $(SHOBJS) pseudo_ipc.o $(LDFLAGS) $(DB_LDFLAGS) $(CLIENT_LDFLAGS) |
124 | 114 | |
125 | 115 | libpseudo: $(LIBPSEUDO) |
126 | 116 | |
127 | $(LIBPSEUDO): $(LIB) $(WRAPOBJS) pseudo_client.o pseudo_ipc.o $(SHOBJS) | |
117 | $(LIBPSEUDO): $(WRAPOBJS) pseudo_client.o pseudo_ipc.o $(SHOBJS) | $(LIB) | |
128 | 118 | $(CC) $(CFLAGS) $(CFLAGS_PSEUDO) -shared -o $(LIBPSEUDO) \ |
129 | 119 | pseudo_client.o pseudo_ipc.o \ |
130 | 120 | $(WRAPOBJS) $(SHOBJS) $(LDFLAGS) $(CLIENT_LDFLAGS) |
167 | 157 | offsets64: |
168 | 158 | $(CC) -m64 -o offsets64 offsets.c |
169 | 159 | |
170 | $(PSEUDO_PROFILE): $(BIN) pseudo_profile | |
160 | $(PSEUDO_PROFILE): pseudo_profile | $(BIN) | |
171 | 161 | cp pseudo_profile $(BIN) |
172 | 162 | |
173 | 163 | pseudo_profile: Makefile pseudo_profile.c tables wrappers |
84 | 84 | deal of fun, and I'm pretty happy that we're finally ready to make it |
85 | 85 | available for other people to look at. |
86 | 86 | |
87 | ||
88 | CONTACT: | |
89 | ||
90 | Discussions and patches should be directed at the openembedded-core mailing | |
91 | list at openembedded-core at lists.openembedded.org. More information at | |
92 | https://www.openembedded.org/wiki/Mailing_lists. Bugs should be filed with | |
93 | the Yocto project at https://bugzilla.yoctoproject.org/. |
3 | 3 | # |
4 | 4 | # Copyright (c) 2008-2014 Wind River Systems, Inc. |
5 | 5 | # |
6 | # This program is free software; you can redistribute it and/or modify | |
7 | # it under the terms of the Lesser GNU General Public License version 2.1 as | |
8 | # published by the Free Software Foundation. | |
9 | # | |
10 | # This program is distributed in the hope that it will be useful, | |
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | |
13 | # See the Lesser GNU General Public License for more details. | |
14 | # | |
15 | # You should have received a copy of the Lesser GNU General Public License | |
16 | # version 2.1 along with this program; if not, write to the Free Software | |
17 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
6 | # SPDX-License-Identifier: LGPL-2.1-only | |
18 | 7 | # |
19 | 8 | # not a real configure script... |
20 | 9 | opt_prefix= |
24 | 13 | opt_bits= |
25 | 14 | opt_sqlite=/usr |
26 | 15 | opt_rpath= |
16 | opt_epoll= | |
27 | 17 | opt_memory= |
28 | 18 | opt_async= |
29 | 19 | opt_xattr= |
36 | 26 | |
37 | 27 | usage() |
38 | 28 | { |
29 | [ -n "$*" ] && echo >&2 "$*" | |
39 | 30 | echo >&2 "usage:" |
40 | 31 | echo >&2 " configure --prefix=..." |
41 | 32 | echo >&2 " [--libdir=...]" |
42 | 33 | echo >&2 " [--suffix=...]" |
43 | 34 | echo >&2 " [--enable-memory-db]" |
35 | echo >&2 " [--enable-epoll]" | |
44 | 36 | echo >&2 " [--enable-xattr]" |
45 | 37 | echo >&2 " [--enable-xattrdb]" |
46 | 38 | echo >&2 " [--enable-profiling]" |
114 | 106 | --enable-profiling=yes | --enable-profiling) |
115 | 107 | opt_profiling=true |
116 | 108 | ;; |
109 | --enable-epoll=no) | |
110 | opt_epoll=false | |
111 | ;; | |
112 | --enable-epoll=yes | --enable-epoll) | |
113 | opt_epoll=true | |
114 | ;; | |
117 | 115 | --enable-xattr=no) |
118 | 116 | opt_xattr=false |
119 | 117 | ;; |
214 | 212 | fi |
215 | 213 | |
216 | 214 | if [ -z "$opt_prefix" ]; then |
217 | usage | |
215 | usage "Error: You must specify a prefix path for installation (--prefix=)." | |
218 | 216 | fi |
219 | 217 | |
220 | 218 | if [ -z "$opt_libdir" ]; then |
251 | 249 | |
252 | 250 | if [ -z "$opt_async" ]; then |
253 | 251 | opt_async=false |
252 | fi | |
253 | ||
254 | if [ -z "$opt_epoll" ]; then | |
255 | opt_epoll=false | |
254 | 256 | fi |
255 | 257 | |
256 | 258 | if $opt_async; then |
281 | 283 | fi |
282 | 284 | fi |
283 | 285 | |
286 | if $opt_epoll; then | |
287 | EPOLL="-DPSEUDO_EPOLL" | |
288 | else | |
289 | EPOLL="" | |
290 | fi | |
291 | ||
284 | 292 | if $opt_xattr || $opt_xattrdb; then |
285 | 293 | if ! $xattr_runs; then |
286 | 294 | echo >&2 "WARNING: getfattr doesn't work, but xattr-related features requestd." |
320 | 328 | |
321 | 329 | sed -e ' |
322 | 330 | s,@PREFIX@,'"$opt_prefix"',g |
331 | s,@EPOLL@,'"$EPOLL"',g | |
323 | 332 | s,@XATTR@,'"$opt_xattr"',g |
324 | 333 | s,@XATTRDB@,'"$opt_xattrdb"',g |
325 | 334 | s,@PROFILING@,'"$opt_profiling"',g |
17 | 17 | pseudo_loaded, "server couldn't get out of pseudo environment" |
18 | 18 | pseudo_prefix, "couldn't get valid pseudo prefix" |
19 | 19 | pseudo_invocation, "invalid server command arguments" |
20 | epoll_create, "epoll_create() failed" | |
21 | epoll_ctl, "epoll_ctl() failed" | |
22 |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2014 Wind River Systems, Inc. |
2 | 2 | * |
3 | * This program is free software; you can redistribute it and/or modify | |
4 | * it under the terms of the Lesser GNU General Public License version 2.1 as | |
5 | * published by the Free Software Foundation. | |
6 | * | |
7 | * This program is distributed in the hope that it will be useful, | |
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | |
10 | * See the Lesser GNU General Public License for more details. | |
11 | * | |
12 | * You should have received a copy of the Lesser GNU General Public License | |
13 | * version 2.1 along with this program; if not, write to the Free Software | |
14 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
3 | * SPDX-License-Identifier: LGPL-2.1-only | |
15 | 4 | * |
16 | 5 | */ |
1 | 1 | # |
2 | 2 | # Copyright (c) 2008-2010, 2013 Wind River Systems, Inc. |
3 | 3 | # |
4 | # This program is free software; you can redistribute it and/or modify | |
5 | # it under the terms of the Lesser GNU General Public License version 2.1 as | |
6 | # published by the Free Software Foundation. | |
7 | # | |
8 | # This program is distributed in the hope that it will be useful, | |
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | |
11 | # See the Lesser GNU General Public License for more details. | |
12 | # | |
13 | # You should have received a copy of the Lesser GNU General Public License | |
14 | # version 2.1 along with this program; if not, write to the Free Software | |
15 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
4 | # SPDX-License-Identifier: LGPL-2.1-only | |
16 | 5 | # |
17 | 6 | """convert tables.in files to enums, tables, and support code. |
18 | 7 | |
50 | 39 | import glob |
51 | 40 | import sys |
52 | 41 | import string |
42 | import os | |
53 | 43 | from templatefile import TemplateFile |
54 | 44 | |
55 | 45 | class DataType: |
57 | 47 | |
58 | 48 | def __init__(self, path): |
59 | 49 | """read the first line of path, then make tuples of the rest""" |
60 | source = file(path) | |
61 | definition = source.readline().rstrip() | |
62 | self.name, qualifiers = string.split(definition, ': ', 2) | |
63 | if '; ' in qualifiers: | |
64 | self.prefix, columns = string.split(qualifiers, '; ') | |
65 | else: | |
66 | self.prefix = qualifiers | |
67 | columns = [] | |
68 | self.flags = False | |
69 | if len(columns): | |
70 | self.columns = [] | |
71 | columns = string.split(columns, ', ') | |
72 | for col in columns: | |
73 | indexed = False | |
74 | if col.startswith("FLAGS"): | |
75 | print "Flags: set for %s" % self.name | |
76 | self.flags = True | |
50 | with open(path,'r') as source: | |
51 | definition = source.readline().rstrip() | |
52 | self.name, qualifiers = definition.split(': ', 2) | |
53 | if '; ' in qualifiers: | |
54 | self.prefix, columns = qualifiers.split('; ') | |
55 | else: | |
56 | self.prefix = qualifiers | |
57 | columns = [] | |
58 | self.flags = False | |
59 | if len(columns): | |
60 | self.columns = [] | |
61 | columns = columns.split(', ') | |
62 | for col in columns: | |
63 | indexed = False | |
64 | if col.startswith("FLAGS"): | |
65 | print("Flags: set for %s" % self.name) | |
66 | self.flags = True | |
67 | continue | |
68 | if col.startswith("INDEXED "): | |
69 | col = col[8:] | |
70 | indexed = True | |
71 | if "=" in col: | |
72 | name, default = col.split(' = ') | |
73 | else: | |
74 | name, default = col, "" | |
75 | if " " in name: | |
76 | words = name.split(' ') | |
77 | name = words[-1] | |
78 | del words[-1] | |
79 | type = ' '.join(words) | |
80 | else: | |
81 | type = "char *" | |
82 | self.columns.append({"indexed":indexed, "type":type, "name":name, "value":default}) | |
83 | else: | |
84 | self.columns = [] | |
85 | self.data = [] | |
86 | self.comments = [] | |
87 | index = 1 | |
88 | for line in source.readlines(): | |
89 | item = {} | |
90 | if line.startswith('#'): | |
91 | self.comments.append(line.rstrip().replace('#', '')) | |
77 | 92 | continue |
78 | if col.startswith("INDEXED "): | |
79 | col = col[8:] | |
80 | indexed = True | |
81 | if "=" in col: | |
82 | name, default = string.split(col, ' = ') | |
83 | else: | |
84 | name, default = col, "" | |
85 | if " " in name: | |
86 | words = string.split(name, ' ') | |
87 | name = words[-1] | |
88 | del words[-1] | |
89 | type = ' '.join(words) | |
90 | else: | |
91 | type = "char *" | |
92 | self.columns.append({"indexed":indexed, "type":type, "name":name, "value":default}) | |
93 | else: | |
94 | self.columns = [] | |
95 | self.data = [] | |
96 | self.comments = [] | |
97 | index = 1 | |
98 | for line in source.readlines(): | |
99 | item = {} | |
100 | if line.startswith('#'): | |
101 | self.comments.append(line.rstrip().replace('#', '')) | |
102 | continue | |
103 | # first entry on the line is the "real" name/id, following hunks | |
104 | # are additional columns | |
105 | cols = string.split(line.rstrip(), ', ') | |
106 | item["name"] = cols.pop(0) | |
107 | item["upper"] = item["name"].replace('-', '_').upper() | |
108 | column_list = [] | |
109 | for col in self.columns: | |
110 | if len(cols) > 0: | |
111 | value = cols.pop(0) | |
112 | if col["indexed"]: | |
113 | if not "max" in col: | |
114 | col["max"] = value | |
115 | if value > col["max"]: | |
116 | col["max"] = value | |
117 | if not "min" in col: | |
118 | col["min"] = value | |
119 | if value < col["min"]: | |
120 | col["min"] = value | |
121 | column_list.append({"name":col["name"], "value":value}) | |
122 | else: | |
123 | column_list.append({"name":col["name"], "value":col["value"]}) | |
124 | item["cols"] = column_list | |
125 | item["index"] = index | |
126 | index = index + 1 | |
127 | self.data.append(item) | |
93 | # first entry on the line is the "real" name/id, following hunks | |
94 | # are additional columns | |
95 | cols = line.rstrip().split(', ') | |
96 | item["name"] = cols.pop(0) | |
97 | item["upper"] = item["name"].replace('-', '_').upper() | |
98 | column_list = [] | |
99 | for col in self.columns: | |
100 | if len(cols) > 0: | |
101 | value = cols.pop(0) | |
102 | if col["indexed"]: | |
103 | if not "max" in col: | |
104 | col["max"] = value | |
105 | if value > col["max"]: | |
106 | col["max"] = value | |
107 | if not "min" in col: | |
108 | col["min"] = value | |
109 | if value < col["min"]: | |
110 | col["min"] = value | |
111 | column_list.append({"name":col["name"], "value":value}) | |
112 | else: | |
113 | column_list.append({"name":col["name"], "value":col["value"]}) | |
114 | item["cols"] = column_list | |
115 | item["index"] = index | |
116 | index = index + 1 | |
117 | self.data.append(item) | |
128 | 118 | |
129 | 119 | def __getitem__(self, key): |
130 | 120 | """Make this object look like a dict for Templates to use""" |
247 | 237 | template_file.emit('header') |
248 | 238 | templates.append(template_file) |
249 | 239 | except IOError: |
250 | print "Invalid or malformed template %s. Aborting." % path | |
240 | print("Invalid or malformed template %s. Aborting." % path) | |
251 | 241 | exit(1) |
252 | 242 | |
253 | 243 | for filename in sys.argv[1:]: |
255 | 245 | sys.stdout.write("%s: " % filename) |
256 | 246 | datatype = DataType(filename) |
257 | 247 | datatypes.append(datatype) |
258 | print datatype.__repr__() | |
259 | print "" | |
260 | ||
261 | print "Writing datatypes...", | |
248 | print(datatype.__repr__()) | |
249 | print("") | |
250 | ||
251 | print("Writing datatypes...") | |
262 | 252 | for datatype in datatypes: |
263 | 253 | # populate various tables and files with each datatype |
264 | 254 | for template_file in templates: |
265 | 255 | template_file.emit('body', datatype) |
266 | print "done. Cleaning up." | |
256 | print("done. Cleaning up.") | |
267 | 257 | |
268 | 258 | for template_file in templates: |
269 | 259 | # clean up files |
1 | 1 | # |
2 | 2 | # Copyright (c) 2008-2011,2013 Wind River Systems, Inc. |
3 | 3 | # |
4 | # This program is free software; you can redistribute it and/or modify | |
5 | # it under the terms of the Lesser GNU General Public License version 2.1 as | |
6 | # published by the Free Software Foundation. | |
7 | # | |
8 | # This program is distributed in the hope that it will be useful, | |
9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | |
11 | # See the Lesser GNU General Public License for more details. | |
12 | # | |
13 | # You should have received a copy of the Lesser GNU General Public License | |
14 | # version 2.1 along with this program; if not, write to the Free Software | |
15 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
4 | # SPDX-License-Identifier: LGPL-2.1-only | |
16 | 5 | # |
17 | 6 | """convert wrapfuncs.in to wrapper function stubs and tables""" |
18 | 7 | |
274 | 263 | self.specific_dirfds[arg.name[:-5]] = True |
275 | 264 | self.dirfd = 'dirfd' |
276 | 265 | elif arg.name == 'flags': |
277 | self.flags = 'flags' | |
266 | self.flags = '(flags & AT_SYMLINK_NOFOLLOW)' | |
278 | 267 | elif arg.name.endswith('path'): |
279 | 268 | self.paths_to_munge.append(arg.name) |
280 | 269 | |
323 | 312 | |
324 | 313 | def maybe_async_skip(self): |
325 | 314 | if self.async_skip: |
326 | return """/* This function is not called if pseudo is configured --enable-force-async */ | |
315 | return """/* This function is not called if pseudo is configured --enable-force-async */ | |
327 | 316 | #ifdef PSEUDO_FORCE_ASYNC |
328 | 317 | if (!pseudo_allow_fsync) { |
329 | 318 | PROFILE_DONE; |
332 | 321 | #endif |
333 | 322 | """ % self.async_skip |
334 | 323 | else: |
335 | return "" | |
324 | return "" | |
336 | 325 | |
337 | 326 | def comment(self): |
338 | 327 | """declare self (in a comment)""" |
392 | 381 | |
393 | 382 | def rc_format(self): |
394 | 383 | """the format string to use for the return value""" |
395 | return typedata.get(self.type, { 'format': '[%s]', 'value': '"' + self.type + '"' })['format'] | |
384 | return typedata.get(self.type, { 'format': '[%s]', 'value': '"' + self.type + '"' })['format'] | |
396 | 385 | |
397 | 386 | def rc_value(self): |
398 | 387 | """the value to pass for the format string for the return value""" |
399 | return typedata.get(self.type, { 'format': '[%s]', 'value': '"' + self.type + '"' })['value'] | |
388 | return typedata.get(self.type, { 'format': '[%s]', 'value': '"' + self.type + '"' })['value'] | |
400 | 389 | |
401 | 390 | def rc_decl(self): |
402 | 391 | """declare rc (if needed)""" |
452 | 441 | """ |
453 | 442 | |
454 | 443 | def __init__(self, port, sources): |
444 | if type(port) is not str: | |
445 | port = str(port, encoding="ascii") | |
455 | 446 | self.name = port |
456 | 447 | self.subports = [] |
457 | 448 | self.preports = [] |
458 | print port | |
449 | print(port) | |
459 | 450 | |
460 | 451 | if os.path.exists(self.portfile("pseudo_wrappers.c")): |
461 | 452 | self.wrappers = self.portfile("pseudo_wrappers.c") |
482 | 473 | if retcode: |
483 | 474 | raise Exception("preports script failed for port %s" % self.name) |
484 | 475 | |
485 | for preport in string.split(portlist): | |
476 | for preport in portlist.split(): | |
486 | 477 | next = Port(preport, sources) |
487 | 478 | self.preports.append(next) |
488 | 479 | |
493 | 484 | if retcode: |
494 | 485 | raise Exception("subports script failed for port %s" % self.name) |
495 | 486 | |
496 | for subport in string.split(portlist): | |
487 | for subport in portlist.split(): | |
497 | 488 | next = Port(subport, sources) |
498 | 489 | self.subports.append(next) |
499 | 490 | |
503 | 494 | prefuncs = pre.functions() |
504 | 495 | for name in prefuncs.keys(): |
505 | 496 | if name in mergedfuncs: |
506 | print "Warning: %s from %s overriding %s" % (name, pre.name, mergedfuncs[name].port) | |
497 | print("Warning: %s from %s overriding %s" % (name, pre.name, mergedfuncs[name].port)) | |
507 | 498 | mergedfuncs[name] = prefuncs[name] |
508 | 499 | for name in self.funcs.keys(): |
509 | 500 | if name in mergedfuncs: |
510 | print "Warning: %s from %s overriding %s" % (name, self.name, mergedfuncs[name].port) | |
501 | print("Warning: %s from %s overriding %s" % (name, self.name, mergedfuncs[name].port)) | |
511 | 502 | mergedfuncs[name] = self.funcs[name] |
512 | 503 | for sub in self.subports: |
513 | 504 | subfuncs = sub.functions() |
514 | 505 | for name in subfuncs.keys(): |
515 | 506 | if name in mergedfuncs: |
516 | print "Warning: %s from %s overriding %s" % (name, sub.name, mergedfuncs[name].port) | |
507 | print("Warning: %s from %s overriding %s" % (name, sub.name, mergedfuncs[name].port)) | |
517 | 508 | mergedfuncs[name] = subfuncs[name] |
518 | 509 | return mergedfuncs |
519 | 510 | |
520 | 511 | def define(self): |
521 | return '#define PSEUDO_PORT_%s 1' % string.upper(self.name).replace('/', '_') | |
512 | return '#define PSEUDO_PORT_%s 1' % self.name.upper().replace('/', '_') | |
522 | 513 | |
523 | 514 | def portdeps(self): |
524 | deps = [] | |
525 | if self.wrappers: | |
526 | deps.append(self.wrappers) | |
527 | if self.portdef_file: | |
528 | deps.append(self.portdef_file) | |
515 | deps = [] | |
516 | if self.wrappers: | |
517 | deps.append(self.wrappers) | |
518 | if self.portdef_file: | |
519 | deps.append(self.portdef_file) | |
529 | 520 | if deps: |
530 | 521 | return 'pseudo_wrappers.o: %s' % ' '.join(deps) |
531 | 522 | else: |
575 | 566 | func.directory = directory |
576 | 567 | funcs[func.name] = func |
577 | 568 | sys.stdout.write(".") |
578 | except Exception, e: | |
579 | print "Parsing failed:", e | |
569 | except Exception(e): | |
570 | print("Parsing failed:", e) | |
580 | 571 | exit(1) |
581 | 572 | funclist.close() |
582 | print "" | |
573 | print("") | |
583 | 574 | return funcs |
584 | 575 | |
585 | 576 | def main(argv): |
589 | 580 | |
590 | 581 | for arg in argv: |
591 | 582 | name, value = arg.split('=') |
592 | os.environ["port_" + name] = value | |
583 | os.environ["port_" + name] = value | |
593 | 584 | |
594 | 585 | # error checking helpfully provided by the exception handler |
595 | 586 | copyright_file = open('guts/COPYRIGHT') |
598 | 589 | |
599 | 590 | for path in glob.glob('templates/*'): |
600 | 591 | try: |
601 | print "Considering template: " + path | |
592 | print("Considering template: " + path) | |
602 | 593 | source = TemplateFile(path) |
603 | if source.name.endswith('.c') or source.name.endswith('.h'): | |
594 | if source.name.endswith('.c') or source.name.endswith('.h'): | |
604 | 595 | source.emit('copyright') |
605 | 596 | source.emit('header') |
606 | 597 | sources.append(source) |
607 | 598 | except IOError: |
608 | print "Invalid or malformed template %s. Aborting." % path | |
599 | print("Invalid or malformed template %s. Aborting." % path) | |
609 | 600 | exit(1) |
610 | 601 | |
611 | 602 | try: |
612 | 603 | port = Port('common', sources) |
613 | 604 | |
614 | 605 | except KeyError: |
615 | print "Unknown uname -s result: '%s'." % uname_s | |
616 | print "Known system types are:" | |
617 | print "%-20s %-10s %s" % ("uname -s", "port name", "description") | |
606 | print("Unknown uname -s result: '%s'." % uname_s) | |
607 | print("Known system types are:") | |
608 | print("%-20s %-10s %s" % ("uname -s", "port name", "description")) | |
618 | 609 | for key in host_ports: |
619 | print "%-20s %-10s %s" % (key, host_ports[key], | |
620 | host_descrs[host_ports[key]]) | |
610 | print("%-20s %-10s %s" % (key, host_ports[key], | |
611 | host_descrs[host_ports[key]])) | |
621 | 612 | |
622 | 613 | # the per-function stuff |
623 | print "Writing functions...", | |
614 | print("Writing functions...") | |
624 | 615 | all_funcs = port.functions() |
625 | 616 | for name in sorted(all_funcs.keys()): |
626 | 617 | # populate various tables and files with each function |
627 | 618 | for source in sources: |
628 | 619 | source.emit('body', all_funcs[name]) |
629 | print "done. Cleaning up." | |
620 | print("done. Cleaning up.") | |
630 | 621 | |
631 | 622 | for source in sources: |
632 | 623 | # clean up files |
2 | 2 | * |
3 | 3 | * Copyright (c) 2008-2010 Wind River Systems, Inc. |
4 | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify | |
6 | * it under the terms of the Lesser GNU General Public License version 2.1 as | |
7 | * published by the Free Software Foundation. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | |
12 | * See the Lesser GNU General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the Lesser GNU General Public License | |
15 | * version 2.1 along with this program; if not, write to the Free Software | |
16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
5 | * SPDX-License-Identifier: LGPL-2.1-only | |
17 | 6 | * |
18 | 7 | */ |
19 | 8 | #ifndef _LARGEFILE64_SOURCE |
0 | 0 | #!/bin/sh |
1 | # | |
2 | # SPDX-License-Identifier: LGPL-2.1-only | |
3 | # | |
4 | ||
1 | 5 | # do a quick performance test of pseudo |
2 | 6 | opt_f=false |
3 | 7 | flag_f= |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2011 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * int execl(const char *file, const char *arg, va_list ap) |
5 | 7 | * int rc = -1; |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2011 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * int execle(const char *file, const char *arg, va_list ap) |
5 | 7 | * int rc = -1; |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2011 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * int execlp(const char *file, const char *arg, va_list ap) |
5 | 7 | * int rc = -1; |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_execv(const char *file, char *const *argv) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_execve(const char *file, char *const *argv, char *const *envp) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_execvp(const char *file, char *const *argv) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_fork(void) { |
0 | /* | |
1 | * SPDX-License-Identifier: LGPL-2.1-only | |
2 | * | |
3 | */ | |
4 | ||
0 | 5 | /* these aren't used, but the wrapper table isn't happy unless they |
1 | 6 | * exist |
2 | 7 | */ |
0 | 0 | #!/bin/sh |
1 | # | |
2 | # SPDX-License-Identifier: LGPL-2.1-only | |
3 | # | |
4 | ||
1 | 5 | case $(uname -s) in |
2 | 6 | Linux) echo "linux";; |
3 | 7 | Darwin) echo "darwin";; |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010 Wind River Systems, Inc. |
2 | 2 | * |
3 | * This program is free software; you can redistribute it and/or modify | |
4 | * it under the terms of the Lesser GNU General Public License version 2.1 as | |
5 | * published by the Free Software Foundation. | |
6 | * | |
7 | * This program is distributed in the hope that it will be useful, | |
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | |
10 | * See the Lesser GNU General Public License for more details. | |
11 | * | |
12 | * You should have received a copy of the Lesser GNU General Public License | |
13 | * version 2.1 along with this program; if not, write to the Free Software | |
14 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
3 | * SPDX-License-Identifier: LGPL-2.1-only | |
15 | 4 | * |
16 | 5 | */ |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2011, 2012 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * int fcntl(int fd, int cmd, ... { struct flock *lock }) |
5 | 7 | * int rc = -1; |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2011 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * int fgetgrent_r(FILE *fp, struct group*gbuf, char *buf, size_t buflen, struct group **gbufp) |
5 | 7 | * int rc = -1; |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2011 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * int fgetpwent_r(FILE *fp, struct passwd *pbuf, char *buf, size_t buflen, struct passwd **pbufp) |
5 | 7 | * int rc = -1; |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2014 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * ssize_t fgetxattr(int filedes, const char *name, void *value, size_t size, u_int32_t position, int options) |
5 | 7 | * ssize_t rc = -1; |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2014 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * ssize_t flistxattr(int filedes, char *list, size_t size, int options) |
5 | 7 | * ssize_t rc = -1; |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2014 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * int fremovexattr(int filedes, const char *name, int options) |
5 | 7 | * int rc = -1; |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2014 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * int fsetxattr(int filedes, const char *name, const void *value, size_t size, u_int32_t position, int options) |
5 | 7 | * int rc = -1; |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2011 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * int fstat(int fd, struct stat *buf) |
5 | 7 | * int rc = -1; |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2011 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * int getgrent_r(struct group *gbuf, char *buf, size_t buflen, struct group **gbufp) |
5 | 7 | * int rc = -1; |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_getgrouplist(const char *name, int basegid, int *groups, int *ngroups) { |
8 | 10 | |
9 | 11 | int found = 0; |
10 | 12 | int found_group = 0; |
11 | char buf[PSEUDO_PWD_MAX]; | |
12 | struct group grp, *gbuf = &grp; | |
13 | size_t buflen = PSEUDO_PWD_MAX; | |
14 | char *buf = NULL; | |
15 | struct group grp; | |
13 | 16 | |
14 | setgrent(); | |
15 | while ((rc = wrap_getgrent_r(gbuf, buf, PSEUDO_PWD_MAX, &gbuf)) == 0) { | |
16 | int i = 0; | |
17 | for (i = 0; gbuf->gr_mem[i]; ++i) { | |
18 | if (!strcmp(gbuf->gr_mem[i], name)) { | |
19 | if (found < *ngroups) | |
20 | groups[found] = gbuf->gr_gid; | |
21 | ++found; | |
22 | if ((int) gbuf->gr_gid == basegid) | |
23 | found_group = 1; | |
17 | rc = ERANGE; | |
18 | ||
19 | do { | |
20 | struct group *gbuf = &grp; | |
21 | char *new_buf = buf; | |
22 | ||
23 | if (rc == ERANGE) | |
24 | new_buf = realloc(buf, buflen); | |
25 | ||
26 | if (!new_buf) { | |
27 | rc = ENOMEM; | |
28 | break; | |
29 | } | |
30 | ||
31 | buf = new_buf; | |
32 | ||
33 | found = 0; | |
34 | found_group = 0; | |
35 | setgrent(); | |
36 | while ((rc = wrap_getgrent_r(gbuf, buf, buflen, &gbuf)) == 0) { | |
37 | int i = 0; | |
38 | for (i = 0; gbuf->gr_mem[i]; ++i) { | |
39 | if (!strcmp(gbuf->gr_mem[i], name)) { | |
40 | if (found < *ngroups) | |
41 | groups[found] = gbuf->gr_gid; | |
42 | ++found; | |
43 | if ((int) gbuf->gr_gid == basegid) | |
44 | found_group = 1; | |
45 | } | |
24 | 46 | } |
25 | 47 | } |
26 | } | |
27 | endgrent(); | |
48 | endgrent(); | |
49 | ||
50 | if (rc == ERANGE) | |
51 | buflen = buflen << 1; | |
52 | } while (rc == ERANGE); | |
53 | free(buf); | |
28 | 54 | if (!found_group) { |
29 | 55 | if (found < *ngroups) |
30 | 56 | groups[found] = basegid; |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_getgroups(int size, gid_t *list) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2011 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * int getpwent_r(struct passwd *pwbuf, char *buf, size_t buflen, struct passwd **pwbufp) |
5 | 7 | * int rc = -1; |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2014 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * ssize_t getxattr(const char *path, const char *name, void *value, size_t size, u_int32_t position, int options) |
5 | 7 | * ssize_t rc = -1; |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2014 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * ssize_t listxattr(const char *path, char *list, size_t size, int options) |
5 | 7 | * ssize_t rc = -1; |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2011 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * int lstat(const char *path, struct stat *buf) |
5 | 7 | * int rc = -1; |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2011-2013 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * int open(const char *path, int flags, ... { int mode }) |
5 | 7 | * int rc = -1; |
11 | 13 | |
12 | 14 | /* mask out mode bits appropriately */ |
13 | 15 | mode = mode & ~pseudo_umask; |
14 | #ifdef PSEUDO_FORCE_ASYNCH | |
16 | #ifdef PSEUDO_FORCE_ASYNC | |
15 | 17 | flags &= ~O_SYNC; |
16 | 18 | #endif |
17 | 19 |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2014 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * int removexattr(const char *path, const char *name, int options) |
5 | 7 | * int rc = -1; |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_scandir(const char *path, struct dirent ***namelist, int (*filter)(struct dirent *), int (*compar)(const void *, const void *)) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2014 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * int setxattr(const char *path, const char *name, const void *value, size_t size, u_int32_t position, int options) |
5 | 7 | * int rc = -1; |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2011 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * int stat(const char *path, struct stat *buf) |
5 | 7 | * int rc = -1; |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2013 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * int sync_file_range(int fd, off_t offset, off_t nbytes, unsigned int flags) |
5 | 7 | * int rc = -1; |
0 | /* | |
1 | * SPDX-License-Identifier: LGPL-2.1-only | |
2 | * | |
3 | */ | |
0 | 4 | #define PRELINK_LIBRARIES "DYLD_INSERT_LIBRARIES" |
1 | 5 | #define PRELINK_PATH "DYLD_LIBRARY_PATH" |
2 | 6 | #define PSEUDO_STATBUF_64 0 |
2 | 2 | * |
3 | 3 | * Copyright (c) 2008-2011 Wind River Systems, Inc. |
4 | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify | |
6 | * it under the terms of the Lesser GNU General Public License version 2.1 as | |
7 | * published by the Free Software Foundation. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | |
12 | * See the Lesser GNU General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the Lesser GNU General Public License | |
15 | * version 2.1 along with this program; if not, write to the Free Software | |
16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
5 | * SPDX-License-Identifier: LGPL-2.1-only | |
17 | 6 | * |
18 | 7 | */ |
19 | 8 | /* we need XATTR_NOFOLLOW in scope */ |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010 Wind River Systems, Inc. |
2 | 2 | * |
3 | * This program is free software; you can redistribute it and/or modify | |
4 | * it under the terms of the Lesser GNU General Public License version 2.1 as | |
5 | * published by the Free Software Foundation. | |
6 | * | |
7 | * This program is distributed in the hope that it will be useful, | |
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | |
10 | * See the Lesser GNU General Public License for more details. | |
11 | * | |
12 | * You should have received a copy of the Lesser GNU General Public License | |
13 | * version 2.1 along with this program; if not, write to the Free Software | |
14 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
3 | * SPDX-License-Identifier: LGPL-2.1-only | |
15 | 4 | * |
16 | 5 | */ |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * int |
5 | 7 | * wrap___fxstat(int ver, int fd, struct stat *buf) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * int |
5 | 7 | * wrap___fxstat64(int ver, int fd, struct stat64 *buf) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap___fxstatat(int ver, int dirfd, const char *path, struct stat *buf, int flags) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap___fxstatat64(int ver, int dirfd, const char *path, struct stat64 *buf, int flags) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap___lxstat(int ver, const char *path, struct stat *buf) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap___lxstat64(int ver, const char *path, struct stat64 *buf) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010,2012 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap___openat64_2(int dirfd, const char *path, int flags) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap___openat_2(int dirfd, const char *path, int flags) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap___xmknod(int ver, const char *path, mode_t mode, dev_t *dev) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap___xmknodat(int ver, int dirfd, const char *path, mode_t mode, dev_t *dev) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap___xstat(int ver, const char *path, struct stat *buf) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap___xstat64(int ver, const char *path, struct stat64 *buf) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static char * |
5 | 7 | * wrap_canonicalize_file_name(const char *filename) { |
0 | /* | |
1 | * Copyright (c) 2016 Wind River Systems; see | |
2 | * guts/COPYRIGHT for information. | |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
5 | * | |
6 | * int capset(cap_user_header_t hdrp, const cap_user_data_t datap) | |
7 | * int rc = -1; | |
8 | */ | |
9 | ||
10 | rc = real_capset(hdrp, datap); | |
11 | ||
12 | /* return rc; | |
13 | * } | |
14 | */ |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_creat64(const char *path, ...mode_t mode) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_eaccess(const char *path, int mode) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_euidaccess(const char *path, int mode) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_fcntl(int fd, int cmd, ...struct flock *lock) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static FILE * |
5 | 7 | * wrap_fopen64(const char *path, const char *mode) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static FILE * |
5 | 7 | * wrap_freopen64(const char *path, const char *mode, FILE *stream) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2011 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * int fstat(int fd, struct stat *buf) |
5 | 7 | * int rc = -1; |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2012 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * int fstat64(int fd, struct stat *buf) |
5 | 7 | * int rc = -1; |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_ftw64(const char *path, int (*fn)(const char *, const struct stat64 *, int), int nopenfd) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static char * |
5 | 7 | * wrap_get_current_dir_name(void) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2010-2011 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_getgrent_r(struct group *gbuf, char *buf, size_t buflen, struct group **gbufp) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_getgrouplist(const char *user, gid_t group, gid_t *groups, int *ngroups) { |
8 | 10 | |
9 | 11 | int found = 0; |
10 | 12 | int found_group = 0; |
11 | char buf[PSEUDO_PWD_MAX]; | |
12 | struct group grp, *gbuf = &grp; | |
13 | size_t buflen = PSEUDO_PWD_MAX; | |
14 | char *buf = NULL; | |
15 | struct group grp; | |
13 | 16 | |
14 | setgrent(); | |
15 | while ((rc = wrap_getgrent_r(gbuf, buf, PSEUDO_PWD_MAX, &gbuf)) == 0) { | |
16 | int i = 0; | |
17 | for (i = 0; gbuf->gr_mem[i]; ++i) { | |
18 | if (!strcmp(gbuf->gr_mem[i], user)) { | |
19 | if (found < *ngroups) | |
20 | groups[found] = gbuf->gr_gid; | |
21 | ++found; | |
22 | if (gbuf->gr_gid == group) | |
23 | found_group = 1; | |
17 | rc = ERANGE; | |
18 | ||
19 | do { | |
20 | struct group *gbuf = &grp; | |
21 | char *new_buf = buf; | |
22 | ||
23 | if (rc == ERANGE) | |
24 | new_buf = realloc(buf, buflen); | |
25 | ||
26 | if (!new_buf) { | |
27 | rc = ENOMEM; | |
28 | break; | |
29 | } | |
30 | ||
31 | buf = new_buf; | |
32 | ||
33 | found = 0; | |
34 | found_group = 0; | |
35 | setgrent(); | |
36 | while ((rc = wrap_getgrent_r(gbuf, buf, buflen, &gbuf)) == 0) { | |
37 | int i = 0; | |
38 | for (i = 0; gbuf->gr_mem[i]; ++i) { | |
39 | if (!strcmp(gbuf->gr_mem[i], user)) { | |
40 | if (found < *ngroups) | |
41 | groups[found] = gbuf->gr_gid; | |
42 | ++found; | |
43 | if (gbuf->gr_gid == group) | |
44 | found_group = 1; | |
45 | } | |
24 | 46 | } |
25 | 47 | } |
26 | } | |
27 | endgrent(); | |
48 | endgrent(); | |
49 | ||
50 | if (rc == ERANGE) | |
51 | buflen = buflen << 1; | |
52 | } while (rc == ERANGE); | |
53 | free(buf); | |
28 | 54 | if (!found_group) { |
29 | 55 | if (found < *ngroups) |
30 | 56 | groups[found] = group; |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_getgroups(int size, gid_t *list) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_getpw(uid_t uid, char *buf) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2010-2011 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_getpwent_r(struct passwd *pwbuf, char *buf, size_t buflen, struct passwd **pwbufp) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_getresuid(uid_t *ruid, uid_t *euid, uid_t *suid) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_glob64(const char *pattern, int flags, int (*errfunc)(const char *, int), glob64_t *pglob) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_lchown(const char *path, uid_t owner, gid_t group) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_lckpwdf(void) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2011 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * int lstat(const char *path, struct stat *buf) |
5 | 7 | * int rc = -1; |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2012 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * int lstat64(const char *path, struct stat *buf) |
5 | 7 | * int rc = -1; |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2016 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * int mknod(const char *path, mode_t mode, dev_t dev) |
5 | 7 | * int rc = -1; |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2016 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * int mknodat(int dirfd, const char *path, mode_t mode, dev_t dev) |
5 | 7 | * int rc = -1; |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_mkstemp64(char *template) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_nftw64(const char *path, int (*fn)(const char *, const struct stat64 *, int, struct FTW *), int nopenfd, int flag) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_open(const char *path, int flags, ...mode_t mode) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010,2012 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_open64(const char *path, int flags, ...mode_t mode) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010, 2013 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_openat(int dirfd, const char *path, int flags, ...mode_t mode) { |
6 | 8 | * int rc = -1; |
7 | 9 | */ |
8 | 10 | struct stat64 buf; |
11 | int overly_magic_nonblocking = 0; | |
9 | 12 | int existed = 1; |
10 | 13 | int save_errno; |
14 | sigset_t local_saved_sigmask; | |
11 | 15 | |
12 | 16 | /* mask out mode bits appropriately */ |
13 | 17 | mode = mode & ~pseudo_umask; |
19 | 23 | } |
20 | 24 | #endif |
21 | 25 | |
22 | #ifdef PSEUDO_FORCE_ASYNCH | |
26 | #ifdef PSEUDO_FORCE_ASYNC | |
23 | 27 | /* Yes, I'm aware that every Linux system I've seen has |
24 | 28 | * DSYNC and RSYNC being the same value as SYNC. |
25 | 29 | */ |
37 | 41 | ); |
38 | 42 | #endif |
39 | 43 | |
44 | #ifdef O_TMPFILE | |
45 | /* don't handle O_CREAT the same way if O_TMPFILE exists | |
46 | * and is set. | |
47 | */ | |
48 | if ((flags & O_TMPFILE) == O_TMPFILE) { | |
49 | existed = 0; | |
50 | } else | |
51 | #endif | |
40 | 52 | /* if a creation has been requested, check whether file exists */ |
53 | /* note "else" in #ifdef O_TMPFILE above */ | |
41 | 54 | if (flags & O_CREAT) { |
42 | 55 | save_errno = errno; |
43 | 56 | #ifdef PSEUDO_NO_REAL_AT_FUNCTIONS |
51 | 64 | errno = save_errno; |
52 | 65 | } |
53 | 66 | |
67 | /* if a pipe is opened without O_NONBLOCK, for only reading or | |
68 | * only writing, it can block forever. We need to do extra magic | |
69 | * in that case... | |
70 | */ | |
71 | if (!(flags & O_NONBLOCK) && ((flags & (O_WRONLY | O_RDONLY | O_RDWR)) != O_RDWR)) { | |
72 | save_errno = errno; | |
73 | #ifdef PSEUDO_NO_REAL_AT_FUNCTIONS | |
74 | rc = real___xstat64(_STAT_VER, path, &buf); | |
75 | #else | |
76 | rc = real___fxstatat64(_STAT_VER, dirfd, path, &buf, 0); | |
77 | #endif | |
78 | if (rc != -1 && S_ISFIFO(buf.st_mode)) { | |
79 | overly_magic_nonblocking = 1; | |
80 | } | |
81 | } | |
82 | ||
83 | /* this is a horrible special case and i do not know whether it will work */ | |
84 | if (overly_magic_nonblocking) { | |
85 | pseudo_droplock(); | |
86 | sigprocmask(SIG_SETMASK, &pseudo_saved_sigmask, &local_saved_sigmask); | |
87 | } | |
54 | 88 | /* because we are not actually root, secretly mask in 0600 to the |
55 | 89 | * underlying mode. The ", 0" is because the only time mode matters |
56 | 90 | * is if a file is going to be created, in which case it's |
61 | 95 | #else |
62 | 96 | rc = real_openat(dirfd, path, flags, PSEUDO_FS_MODE(mode, 0)); |
63 | 97 | #endif |
64 | save_errno = errno; | |
98 | if (overly_magic_nonblocking) { | |
99 | save_errno = errno; | |
100 | sigprocmask(SIG_SETMASK, &local_saved_sigmask, NULL); | |
101 | /* well this is a problem. we can't NOT proceed; we may have | |
102 | * already opened the file! we can't even return up the call | |
103 | * stack to stuff that's going to try to drop the lock. | |
104 | */ | |
105 | if (pseudo_getlock()) { | |
106 | pseudo_diag("PANIC: after opening a readonly/writeonly FIFO (path '%s', fd %d, errno %d, saved errno %d), could not regain lock. unrecoverable. sorry. bye.\n", | |
107 | path, rc, errno, save_errno); | |
108 | abort(); | |
109 | } | |
110 | errno = save_errno; | |
111 | } | |
65 | 112 | |
66 | 113 | if (rc != -1) { |
114 | save_errno = errno; | |
67 | 115 | int stat_rc; |
116 | #ifdef O_TMPFILE | |
117 | /* in O_TMPFILE case, nothing gets put in the | |
118 | * database, because there's no directory entries for | |
119 | * the file yet. | |
120 | */ | |
121 | if ((flags & O_TMPFILE) == O_TMPFILE) { | |
122 | real_fchmod(rc, PSEUDO_FS_MODE(mode, 0)); | |
123 | errno = save_errno; | |
124 | return rc; | |
125 | } | |
126 | #endif | |
68 | 127 | #ifdef PSEUDO_NO_REAL_AT_FUNCTIONS |
69 | 128 | stat_rc = real___xstat64(_STAT_VER, path, &buf); |
70 | 129 | #else |
75 | 134 | buf.st_mode = PSEUDO_DB_MODE(buf.st_mode, mode); |
76 | 135 | if (!existed) { |
77 | 136 | real_fchmod(rc, PSEUDO_FS_MODE(mode, 0)); |
137 | // file has no path, but has been created | |
78 | 138 | pseudo_client_op(OP_CREAT, 0, -1, dirfd, path, &buf); |
79 | 139 | } |
80 | pseudo_client_op(OP_OPEN, PSEUDO_ACCESS(flags), rc, dirfd, path, &buf); | |
140 | pseudo_client_op(OP_OPEN, PSEUDO_ACCESS(flags), rc, dirfd, path, &buf); | |
81 | 141 | } else { |
82 | 142 | pseudo_debug(PDBGF_FILE, "openat (fd %d, path %d/%s, flags %d) succeeded, but stat failed (%s).\n", |
83 | 143 | rc, dirfd, path, flags, strerror(errno)); |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010,2012 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_openat64(int dirfd, const char *path, int flags, ...mode_t mode) { |
0 | /* | |
1 | * Copyright (c) 2019 Peter Seebach/Seebs <seebs@seebs.net>; see | |
2 | * guts/COPYRIGHT for information. | |
3 | * | |
4 | * [Note: copyright added by code generator, may be | |
5 | * incorrect. Remove this if you fix it.] | |
6 | * | |
7 | * SPDX-License-Identifier: LGPL-2.1-only | |
8 | * | |
9 | * int renameat2(int olddirfd, const char *oldpath, int newdirfd, const char *newpath, unsigned int flags) | |
10 | * int rc = -1; | |
11 | */ | |
12 | ||
13 | (void) olddirfd; | |
14 | (void) oldpath; | |
15 | (void) newdirfd; | |
16 | (void) newpath; | |
17 | (void) flags; | |
18 | /* for now, let's try just failing out hard, and hope things retry with a | |
19 | * different syscall. | |
20 | */ | |
21 | errno = ENOSYS; | |
22 | rc = -1; | |
23 | ||
24 | /* return rc; | |
25 | * } | |
26 | */ |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_scandir(const char *path, struct dirent ***namelist, int (*filter)(const struct dirent *), int (*compar)(const void *, const void *)) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_scandir64(const char *path, struct dirent64 ***namelist, int (*filter)(const struct dirent64 *), int (*compar)(const void *, const void *)) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_setfsgid(gid_t fsgid) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_setfsuid(uid_t fsuid) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_setgroups(size_t size, const gid_t *list) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_setresgid(gid_t rgid, gid_t egid, gid_t sgid) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_setresuid(uid_t ruid, uid_t euid, uid_t suid) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2011 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * int stat(const char *path, struct stat *buf) |
5 | 7 | * int rc = -1; |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2012 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * int stat64(const char *path, struct stat *buf) |
5 | 7 | * int rc = -1; |
0 | /* | |
1 | * Copyright (c) 2018 Wind River Systems; see | |
2 | * guts/COPYRIGHT for information. | |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
5 | * | |
6 | * long syscall(long nr) | |
7 | * long rc = -1; | |
8 | */ | |
9 | ||
10 | /* we should never get here, syscall is hand-wrapped */ | |
11 | rc = -1; | |
12 | errno = ENOTSUPP; | |
13 | ||
14 | /* return rc; | |
15 | * } | |
16 | */ |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_truncate64(const char *path, off64_t length) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_ulckpwdf(void) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2011 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * clone(...) { |
0 | /* | |
1 | * SPDX-License-Identifier: LGPL-2.1-only | |
2 | * | |
3 | */ | |
4 | ||
0 | 5 | static int |
1 | 6 | wrap_clone(int (*fn)(void *), void *child_stack, int flags, void *arg, va_list |
2 | 7 | ap) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * ssize_t fgetxattr(int filedes, const char *name, void *value, size_t size) |
5 | 7 | * ssize_t rc = -1; |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * ssize_t flistxattr(int filedes, char *list, size_t size) |
5 | 7 | * ssize_t rc = -1; |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * int fremovexattr(int filedes, const char *name) |
5 | 7 | * int rc = -1; |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * int fsetxattr(int filedes, const char *name, const void *value, size_t size, int flags) |
5 | 7 | * int rc = -1; |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * ssize_t getxattr(const char *pathname, const char *name, void *value, size_t size) |
5 | 7 | * ssize_t rc = -1; |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * ssize_t lgetxattr(const char *pathname, const char *name, void *value, size_t size) |
5 | 7 | * ssize_t rc = -1; |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * ssize_t listxattr(const char *pathname, char *list, size_t size) |
5 | 7 | * ssize_t rc = -1; |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * ssize_t llistxattr(const char *pathname, char *list, size_t size) |
5 | 7 | * ssize_t rc = -1; |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * int lremovexattr(const char *pathname, const char *name) |
5 | 7 | * int rc = -1; |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * int lsetxattr(const char *pathname, const char *name, const void *value, size_t size, int flags) |
5 | 7 | * int rc = -1; |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * int removexattr(const char *pathname, const char *name) |
5 | 7 | * int rc = -1; |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * int setxattr(const char *pathname, const char *name, const void *value, size_t size, int flags) |
5 | 7 | * int rc = -1; |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2011 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * clone(...) { |
0 | /* | |
1 | * SPDX-License-Identifier: LGPL-2.1-only | |
2 | * | |
3 | */ | |
0 | 4 | static int |
1 | 5 | wrap_clone(int (*fn)(void *), void *child_stack, int flags, void *arg) { |
2 | 6 | /* unused */ |
0 | /* | |
1 | * SPDX-License-Identifier: LGPL-2.1-only | |
2 | * | |
3 | */ | |
0 | 4 | #define PRELINK_LIBRARIES "LD_PRELOAD" |
1 | 5 | #define PRELINK_PATH "LD_LIBRARY_PATH" |
2 | 6 | #define PSEUDO_STATBUF_64 1 |
19 | 23 | */ |
20 | 24 | #define GLIBC_COMPAT_SYMBOL(sym, ver) __asm(".symver " #sym "," #sym "@GLIBC_" #ver) |
21 | 25 | |
22 | #ifdef __amd64__ | |
26 | #if defined(__amd64__) && !defined(__ILP32__) | |
23 | 27 | GLIBC_COMPAT_SYMBOL(memcpy,2.2.5); |
24 | 28 | #elif defined(__i386__) |
25 | 29 | GLIBC_COMPAT_SYMBOL(memcpy,2.0); |
26 | 30 | #endif |
31 | ||
32 | #include <linux/capability.h> | |
33 | #include <sys/syscall.h> |
0 | /* | |
1 | * SPDX-License-Identifier: LGPL-2.1-only | |
2 | * | |
3 | */ | |
0 | 4 | /* the unix port wants to know that real_stat() and |
1 | 5 | * friends exist. So they do. And because the Linux |
2 | 6 | * port really uses stat64 for those... |
41 | 45 | pseudo_mknodat(int dirfd, const char *path, mode_t mode, dev_t dev) { |
42 | 46 | return real___xmknodat(_MKNOD_VER, dirfd, path, mode, &dev); |
43 | 47 | } |
48 | ||
49 | int pseudo_capset(cap_user_header_t hdrp, const cap_user_data_t datap) { | |
50 | (void)hdrp; | |
51 | (void)datap; | |
52 | ||
53 | return 0; | |
54 | } | |
55 | ||
56 | long | |
57 | syscall(long number, ...) { | |
58 | long rc = -1; | |
59 | ||
60 | if (!pseudo_check_wrappers() || !real_syscall) { | |
61 | /* rc was initialized to the "failure" value */ | |
62 | pseudo_enosys("syscall"); | |
63 | return rc; | |
64 | } | |
65 | ||
66 | #ifdef SYS_renameat2 | |
67 | /* concerns exist about trying to parse arguments because syscall(2) | |
68 | * specifies strange ABI behaviors. If we can get better clarity on | |
69 | * that, it could make sense to redirect to wrap_renameat2(). | |
70 | */ | |
71 | if (number == SYS_renameat2) { | |
72 | errno = ENOSYS; | |
73 | return -1; | |
74 | } | |
75 | #else | |
76 | (void) number; | |
77 | #endif | |
78 | ||
79 | /* gcc magic to attempt to just pass these args to syscall. we have to | |
80 | * guess about the number of args; the docs discuss calling conventions | |
81 | * up to 7, so let's try that? | |
82 | */ | |
83 | void *res = __builtin_apply((void (*)()) real_syscall, __builtin_apply_args(), sizeof(long) * 7); | |
84 | __builtin_return(res); | |
85 | } | |
86 | ||
87 | /* unused. | |
88 | */ | |
89 | static long wrap_syscall(long nr, va_list ap) { | |
90 | (void) nr; | |
91 | (void) ap; | |
92 | return -1; | |
93 | } |
0 | /* | |
1 | * Copyright (c) 2018 Wind River Systems; see | |
2 | * guts/COPYRIGHT for information. | |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
5 | * | |
6 | * int statvfs(const char *path, struct statvfs *buf) | |
7 | * int rc = -1; | |
8 | */ | |
9 | ||
10 | rc = real_statvfs(path, buf); | |
11 | ||
12 | /* return rc; | |
13 | * } | |
14 | */ |
0 | int statvfs(const char *path, struct statvfs *buf); |
40 | 40 | echo "linux/noxattr" |
41 | 41 | fi |
42 | 42 | rm -f dummy.c dummy.o |
43 | ||
44 | cat > dummy.c <<EOF | |
45 | #include <sys/statvfs.h> | |
46 | int i; | |
47 | EOF | |
48 | if ! ${CC} -c -o dummy.o dummy.c >/dev/null 2>&1; then | |
49 | echo >&2 "Warning: Can't compile trivial program using <sys/statvfs.h>". | |
50 | echo >&2 " xattr support will require that header." | |
51 | else | |
52 | echo "linux/statvfs" | |
53 | fi | |
54 | rm -f dummy.c dummy.o | |
55 |
4 | 4 | int __fxstat(int ver, int fd, struct stat *buf); |
5 | 5 | int lchown(const char *path, uid_t owner, gid_t group); /* flags=AT_SYMLINK_NOFOLLOW */ |
6 | 6 | int __fxstatat(int ver, int dirfd, const char *path, struct stat *buf, int flags); |
7 | int openat(int dirfd, const char *path, int flags, ...{mode_t mode}); | |
8 | int __openat_2(int dirfd, const char *path, int flags); | |
7 | int openat(int dirfd, const char *path, int flags, ...{mode_t mode}); /* flags=0 */ | |
8 | int __openat_2(int dirfd, const char *path, int flags); /* flags=0 */ | |
9 | 9 | int mknod(const char *path, mode_t mode, dev_t dev); /* real_func=pseudo_mknod */ |
10 | 10 | int mknodat(int dirfd, const char *path, mode_t mode, dev_t dev); /* real_func=pseudo_mknodat */ |
11 | 11 | int __xmknod(int ver, const char *path, mode_t mode, dev_t *dev); /* flags=AT_SYMLINK_NOFOLLOW */ |
52 | 52 | int getpw(uid_t uid, char *buf); |
53 | 53 | int getpwent_r(struct passwd *pwbuf, char *buf, size_t buflen, struct passwd **pwbufp); |
54 | 54 | int getgrent_r(struct group *gbuf, char *buf, size_t buflen, struct group **gbufp); |
55 | int capset(cap_user_header_t hdrp, const cap_user_data_t datap); /* real_func=pseudo_capset */ | |
56 | long syscall(long nr, ...); /* hand_wrapped=1 */ | |
57 | int renameat2(int olddirfd, const char *oldpath, int newdirfd, const char *newpath, unsigned int flags); /* flags=AT_SYMLINK_NOFOLLOW */ |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2014 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * ssize_t fgetxattr(int filedes, const char *name, void *value, size_t size) |
5 | 7 | * ssize_t rc = -1; |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2014 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * ssize_t flistxattr(int filedes, char *list, size_t size) |
5 | 7 | * ssize_t rc = -1; |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2014 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * int fremovexattr(int filedes, const char *name) |
5 | 7 | * int rc = -1; |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2014 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * int fsetxattr(int filedes, const char *name, const void *value, size_t size, int xflags) |
5 | 7 | * int rc = -1; |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2014 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * ssize_t getxattr(const char *path, const char *name, void *value, size_t size) |
5 | 7 | * ssize_t rc = -1; |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2014 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * ssize_t lgetxattr(const char *path, const char *name, void *value, size_t size) |
5 | 7 | * ssize_t rc = -1; |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2014 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * ssize_t listxattr(const char *path, char *list, size_t size) |
5 | 7 | * ssize_t rc = -1; |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2014 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * ssize_t llistxattr(const char *path, char *list, size_t size) |
5 | 7 | * ssize_t rc = -1; |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2014 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * int lremovexattr(const char *path, const char *name) |
5 | 7 | * int rc = -1; |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2014 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * int lsetxattr(const char *path, const char *name, const void *value, size_t size, int xflags) |
5 | 7 | * int rc = -1; |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2014 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * int removexattr(const char *path, const char *name) |
5 | 7 | * int rc = -1; |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2014 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * int setxattr(const char *path, const char *name, const void *value, size_t size, int xflags) |
5 | 7 | * int rc = -1; |
0 | /* | |
1 | * SPDX-License-Identifier: LGPL-2.1-only | |
2 | * | |
3 | */ | |
0 | 4 | #include <attr/xattr.h> |
1 | 5 | #include <stdint.h> |
0 | /* | |
1 | * SPDX-License-Identifier: LGPL-2.1-only | |
2 | * | |
3 | */ | |
0 | 4 | /* shared functionality for the xattr code */ |
1 | 5 | /* Each of these functions is expecting to get an optional name, and |
2 | 6 | * a populated statbuf to use for sending messages to the server. |
61 | 65 | posix_permissions(const acl_header *header, int entries, int *extra, int *mode) { |
62 | 66 | int acl_seen = 0; |
63 | 67 | if (le32(header->version) != 2) { |
64 | pseudo_diag("Fatal: ACL support no available for header version %d.\n", | |
68 | pseudo_diag("Fatal: ACL support not available for header version %d.\n", | |
65 | 69 | le32(header->version)); |
66 | return 1; | |
70 | return -1; | |
67 | 71 | } |
68 | 72 | *mode = 0; |
69 | 73 | *extra = 0; |
96 | 100 | return 0; |
97 | 101 | } |
98 | 102 | |
103 | static int get_special_bits(const char *path, int fd) { | |
104 | int rc; | |
105 | struct stat64 buf; | |
106 | if (path) { | |
107 | rc = lstat64(path, &buf); | |
108 | } else { | |
109 | rc = fstat64(fd, &buf); | |
110 | } | |
111 | if (rc == -1) { | |
112 | return rc; | |
113 | } | |
114 | ||
115 | return buf.st_mode & (S_ISUID | S_ISGID | S_ISVTX); | |
116 | } | |
117 | ||
99 | 118 | #define RC_AND_BUF \ |
100 | 119 | int rc; \ |
101 | 120 | PSEUDO_STATBUF buf; \ |
139 | 158 | pseudo_debug(PDBGF_XATTR, "setxattr(%s [fd %d], %s => '%.*s')\n", |
140 | 159 | path ? path : "<no path>", fd, name, (int) size, (char *) value); |
141 | 160 | |
161 | /* Filter out erroneous sizes for POSIX ACL | |
162 | * see posix_acl_xattr_count in include/linux/posix_acl_xattr.h of Linux source code */ | |
163 | /* I don't think there's any posix_acl_* values that aren't in this format */ | |
164 | if (!strncmp(name, "system.posix_acl_", 17)) { | |
165 | // ACL is corrupt, issue an error | |
166 | if(size < sizeof(acl_header) || (size - sizeof(acl_header)) % sizeof(acl_entry) != 0) { | |
167 | pseudo_debug(PDBGF_XATTR, "invalid data size for %s: %d\n", | |
168 | name, (int) size); | |
169 | errno = EINVAL; | |
170 | return -1; | |
171 | } | |
172 | ||
173 | // ACL is empty, do nothing | |
174 | if((size - sizeof(acl_header)) / sizeof(acl_entry) == 0) { | |
175 | /* on some systems, "cp -a" will attempt to clone the | |
176 | * posix_acl_default entry for a directory (which would specify | |
177 | * default ACLs for new files in that directory), but if the | |
178 | * original was empty, we get a header but no entries. With | |
179 | * real xattr, that ends up being silently discarded, apparently, | |
180 | * so we discard it too. | |
181 | */ | |
182 | pseudo_debug(PDBGF_XATTR, "0-length ACL entry %s.\n", name); | |
183 | return 0; | |
184 | } | |
185 | } | |
142 | 186 | /* this may be a plain chmod */ |
143 | 187 | if (!strcmp(name, "system.posix_acl_access")) { |
144 | 188 | int extra; |
145 | 189 | int mode; |
146 | 190 | int entries = (size - sizeof(acl_header)) / sizeof(acl_entry); |
147 | if (!posix_permissions(value, entries, &extra, &mode)) { | |
191 | int res = posix_permissions(value, entries, &extra, &mode); | |
192 | if (res == 0) { | |
193 | /* POSIX ACLs don't actually include | |
194 | * setuid/setgid/sticky bit. We need to add those back | |
195 | * in ourselves. */ | |
196 | mode |= get_special_bits(path, fd); | |
148 | 197 | pseudo_debug(PDBGF_XATTR, "posix_acl_access translated to mode %04o. Remaining attribute(s): %d.\n", |
149 | 198 | mode, extra); |
150 | 199 | buf.st_mode = mode; |
163 | 212 | if (!extra) { |
164 | 213 | return 0; |
165 | 214 | } |
166 | } | |
167 | } | |
215 | } else if (res == -1) { | |
216 | errno = EOPNOTSUPP; | |
217 | return -1; | |
218 | } | |
219 | } | |
220 | ||
168 | 221 | if (!strcmp(name, "user.pseudo_data")) { |
169 | 222 | pseudo_debug(PDBGF_XATTR | PDBGF_XATTRDB, "user.pseudo_data xattribute does not get to go in database.\n"); |
170 | 223 | return -1; |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010 Wind River Systems, Inc. |
2 | 2 | * |
3 | * This program is free software; you can redistribute it and/or modify | |
4 | * it under the terms of the Lesser GNU General Public License version 2.1 as | |
5 | * published by the Free Software Foundation. | |
6 | * | |
7 | * This program is distributed in the hope that it will be useful, | |
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | |
10 | * See the Lesser GNU General Public License for more details. | |
11 | * | |
12 | * You should have received a copy of the Lesser GNU General Public License | |
13 | * version 2.1 along with this program; if not, write to the Free Software | |
14 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
3 | * SPDX-License-Identifier: LGPL-2.1-only | |
15 | 4 | * |
16 | 5 | */ |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static void |
5 | 7 | * wrap_endgrent(void) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static void |
5 | 7 | * wrap_endpwent(void) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static gid_t |
5 | 7 | * wrap_getegid(void) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static uid_t |
5 | 7 | * wrap_geteuid(void) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static gid_t |
5 | 7 | * wrap_getgid(void) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static struct group * |
5 | 7 | * wrap_getgrent(void) { |
6 | 8 | * struct group * rc = NULL; |
7 | 9 | */ |
8 | 10 | static struct group grp; |
9 | static char grbuf[PSEUDO_PWD_MAX]; | |
10 | int r_rc; | |
11 | static size_t grbuflen = PSEUDO_PWD_MAX; | |
12 | static char *grbuf = NULL; | |
13 | int r_rc = ERANGE; | |
11 | 14 | |
12 | r_rc = wrap_getgrent_r(&grp, grbuf, PSEUDO_PWD_MAX, &rc); | |
15 | do { | |
16 | char *new_grbuf = grbuf; | |
17 | ||
18 | if (r_rc == ERANGE) | |
19 | new_grbuf = realloc(grbuf, grbuflen); | |
20 | ||
21 | if (!new_grbuf) { | |
22 | r_rc = ENOMEM; | |
23 | break; | |
24 | } | |
25 | ||
26 | grbuf = new_grbuf; | |
27 | ||
28 | r_rc = wrap_getgrent_r(&grp, grbuf, grbuflen, &rc); | |
29 | ||
30 | if (r_rc == ERANGE) | |
31 | grbuflen = grbuflen << 1; | |
32 | ||
33 | } while (r_rc == ERANGE); | |
34 | ||
13 | 35 | /* different error return conventions */ |
14 | 36 | if (r_rc != 0) { |
15 | 37 | errno = r_rc; |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static struct group * |
5 | 7 | * wrap_getgrgid(gid_t gid) { |
6 | 8 | * struct group * rc = NULL; |
7 | 9 | */ |
8 | 10 | static struct group grp; |
9 | static char grbuf[PSEUDO_PWD_MAX]; | |
10 | int r_rc; | |
11 | static size_t grbuflen = PSEUDO_PWD_MAX; | |
12 | static char *grbuf = NULL; | |
13 | int r_rc = ERANGE; | |
11 | 14 | |
12 | r_rc = wrap_getgrgid_r(gid, &grp, grbuf, PSEUDO_PWD_MAX, &rc); | |
15 | do { | |
16 | char *new_grbuf = grbuf; | |
17 | ||
18 | if (r_rc == ERANGE) | |
19 | new_grbuf = realloc(grbuf, grbuflen); | |
20 | ||
21 | if (!new_grbuf) { | |
22 | r_rc = ENOMEM; | |
23 | break; | |
24 | } | |
25 | ||
26 | grbuf = new_grbuf; | |
27 | ||
28 | r_rc = wrap_getgrgid_r(gid, &grp, grbuf, grbuflen, &rc); | |
29 | ||
30 | if (r_rc == ERANGE) | |
31 | grbuflen = grbuflen << 1; | |
32 | ||
33 | } while (r_rc == ERANGE); | |
34 | ||
13 | 35 | /* different error return conventions */ |
14 | 36 | if (r_rc != 0) { |
15 | 37 | errno = r_rc; |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_getgrgid_r(gid_t gid, struct group *gbuf, char *buf, size_t buflen, struct group **gbufp) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static struct group * |
5 | 7 | * wrap_getgrnam(const char *name) { |
7 | 9 | */ |
8 | 10 | |
9 | 11 | static struct group grp; |
10 | static char grbuf[PSEUDO_PWD_MAX]; | |
11 | int r_rc; | |
12 | static size_t grbufsz = PSEUDO_PWD_MAX; | |
13 | static char *grbuf = NULL; | |
14 | int r_rc = ERANGE; | |
12 | 15 | |
13 | r_rc = wrap_getgrnam_r(name, &grp, grbuf, PSEUDO_PWD_MAX, &rc); | |
16 | do { | |
17 | char *new_grbuf = grbuf; | |
18 | ||
19 | if (r_rc != 0) | |
20 | new_grbuf = realloc(grbuf, grbufsz); | |
21 | ||
22 | if (!new_grbuf) { | |
23 | r_rc = ENOMEM; | |
24 | break; | |
25 | } | |
26 | ||
27 | grbuf = new_grbuf; | |
28 | ||
29 | r_rc = wrap_getgrnam_r(name, &grp, grbuf, grbufsz, &rc); | |
30 | ||
31 | if (r_rc == ERANGE) | |
32 | grbufsz = grbufsz << 1; | |
33 | } while (r_rc == ERANGE); | |
34 | ||
14 | 35 | /* different error return conventions */ |
15 | 36 | if (r_rc != 0) { |
16 | 37 | errno = r_rc; |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_getgrnam_r(const char *name, struct group *gbuf, char *buf, size_t buflen, struct group **gbufp) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static struct passwd * |
5 | 7 | * wrap_getpwent(void) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static struct passwd * |
5 | 7 | * wrap_getpwnam(const char *name) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_getpwnam_r(const char *name, struct passwd *pwbuf, char *buf, size_t buflen, struct passwd **pwbufp) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static struct passwd * |
5 | 7 | * wrap_getpwuid(uid_t uid) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_getpwuid_r(uid_t uid, struct passwd *pwbuf, char *buf, size_t buflen, struct passwd **pwbufp) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static uid_t |
5 | 7 | * wrap_getuid(void) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_setegid(gid_t egid) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_seteuid(uid_t euid) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_setgid(gid_t gid) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static void |
5 | 7 | * wrap_setgrent(void) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static void |
5 | 7 | * wrap_setpwent(void) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_setregid(gid_t rgid, gid_t egid) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_setreuid(uid_t ruid, uid_t euid) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_setuid(uid_t uid) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010 Wind River Systems, Inc. |
2 | 2 | * |
3 | * This program is free software; you can redistribute it and/or modify | |
4 | * it under the terms of the Lesser GNU General Public License version 2.1 as | |
5 | * published by the Free Software Foundation. | |
6 | * | |
7 | * This program is distributed in the hope that it will be useful, | |
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | |
10 | * See the Lesser GNU General Public License for more details. | |
11 | * | |
12 | * You should have received a copy of the Lesser GNU General Public License | |
13 | * version 2.1 along with this program; if not, write to the Free Software | |
14 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
3 | * SPDX-License-Identifier: LGPL-2.1-only | |
15 | 4 | * |
16 | 5 | */ |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2010, 2012 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_access(const char *path, int mode) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_acct(const char *path) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2016 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) |
5 | 7 | * int rc = -1; |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_chdir(const char *path) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_chmod(const char *path, mode_t mode) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_chown(const char *path, uid_t owner, gid_t group) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_chroot(const char *path) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_close(int fd) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2012 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_closedir(DIR *dirp) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_creat(const char *path, mode_t mode) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_dup(int fd) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_dup2(int oldfd, int newfd) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_fchdir(int dirfd) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010, 2012, 2013 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_fchmod(int fd, mode_t mode) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010, 2012, 2013 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_fchmodat(int dirfd, const char *path, mode_t mode, int flags) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010, 2012, 2013 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_fchown(int fd, uid_t owner, gid_t group) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010, 2012, 2013 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_fchownat(int dirfd, const char *path, uid_t owner, gid_t group, int flags) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_fclose(FILE *fp) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2013 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * int fdatasync(int fd) |
5 | 7 | * int rc = -1; |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010, 2012 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static FILE * |
5 | 7 | * wrap_fopen(const char *path, const char *mode) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static FILE * |
5 | 7 | * wrap_freopen(const char *path, const char *mode, FILE *stream) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2013 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * int fsync(int fd) |
5 | 7 | * int rc = -1; |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static FTS * |
5 | 7 | * wrap_fts_open(char * const *path_argv, int options, int (*compar)(const FTSENT **, const FTSENT **)) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_ftw(const char *path, int (*fn)(const char *, const struct stat *, int), int nopenfd) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static char * |
5 | 7 | * wrap_getcwd(char *buf, size_t size) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static char * |
5 | 7 | * wrap_getwd(char *buf) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_glob(const char *pattern, int flags, int (*errfunc)(const char *, int), glob_t *pglob) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008,2011 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * int lchown(const char *path, uid_t owner, gid_t group) |
5 | 7 | * int rc = -1; |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010, 2012, 2013 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_link(const char *oldname, const char *newname) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2012, 2013 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * int linkat(int olddirfd, const char *oldname, int newdirfd, const char *newname, int flags) |
5 | 7 | * int rc = -1; |
6 | 8 | */ |
7 | 9 | |
8 | int rc2, rflags, save_errno; | |
10 | int rc2 = 0, rflags, save_errno, tmpfile_fd = -1; | |
9 | 11 | pseudo_msg_t *msg; |
10 | char *oldpath = NULL, *newpath = NULL; | |
12 | const char *oldpath = NULL, *newpath = NULL; | |
11 | 13 | PSEUDO_STATBUF buf; |
12 | 14 | |
13 | /* This is gratuitously complicated. On Linux 2.6.18 and later, | |
14 | * flags may contain AT_SYMLINK_FOLLOW, which implies following | |
15 | * symlinks; otherwise, linkat() will *not* follow symlinks. FreeBSD | |
16 | * appears to use the same semantics. | |
17 | * | |
18 | * So on Darwin, always pass AT_SYMLINK_FOLLOW, because the | |
19 | * alternative doesn't work. And never pass AT_SYMLINK_NOFOLLOW | |
20 | * because that's not a valid flag to linkat(). | |
21 | * | |
22 | * So we need a flag for path resolution which is AT_SYMLINK_NOFOLLOW | |
23 | * unless AT_SYMLINK_FOLLOW was specified, in which case it's 0. | |
24 | */ | |
25 | ||
26 | rflags = (flags & AT_SYMLINK_FOLLOW) ? 0 : AT_SYMLINK_NOFOLLOW; | |
15 | /* This is gratuitously complicated. On Linux 2.6.18 and later, | |
16 | * flags may contain AT_SYMLINK_FOLLOW, which implies following | |
17 | * symlinks; otherwise, linkat() will *not* follow symlinks. FreeBSD | |
18 | * appears to use the same semantics. | |
19 | * | |
20 | * So on Darwin, always pass AT_SYMLINK_FOLLOW, because the | |
21 | * alternative doesn't work. And never pass AT_SYMLINK_NOFOLLOW | |
22 | * because that's not a valid flag to linkat(). | |
23 | * | |
24 | * So we need a flag for path resolution which is AT_SYMLINK_NOFOLLOW | |
25 | * unless AT_SYMLINK_FOLLOW was specified, in which case it's 0. | |
26 | */ | |
27 | ||
28 | rflags = (flags & AT_SYMLINK_FOLLOW) ? 0 : AT_SYMLINK_NOFOLLOW; | |
27 | 29 | |
28 | 30 | #ifdef PSEUDO_NO_REAL_AT_FUNCTIONS |
29 | 31 | if (olddirfd != AT_FDCWD || newdirfd != AT_FDCWD) { |
31 | 33 | return -1; |
32 | 34 | } |
33 | 35 | #endif |
34 | oldpath = pseudo_root_path(__func__, __LINE__, olddirfd, oldname, rflags); | |
35 | newpath = pseudo_root_path(__func__, __LINE__, newdirfd, newname, AT_SYMLINK_NOFOLLOW); | |
36 | rc = real_link(oldpath, newpath); | |
37 | save_errno = errno; | |
38 | if (rc == -1) { | |
39 | errno = save_errno; | |
40 | return rc; | |
41 | } | |
36 | oldpath = oldname; | |
37 | if (pseudo_chroot_len && strncmp(oldpath, pseudo_chroot, pseudo_chroot_len) && | |
38 | oldpath[pseudo_chroot_len] == '/') { | |
39 | oldpath += pseudo_chroot_len; | |
40 | } | |
42 | 41 | |
43 | /* if we got this far, the link succeeded, and oldpath and newpath | |
44 | * are the newly-allocated canonical paths. If OS, filesystem, or | |
45 | * the flags value prevent hard linking to symlinks, the resolved | |
46 | * path should be the target's path anyway, so lstat is safe here. | |
47 | */ | |
48 | /* find the target: */ | |
49 | rc2 = base_lstat(oldpath, &buf); | |
50 | if (rc2 == -1) { | |
51 | pseudo_diag("Fatal: Tried to stat '%s' after linking it, but failed: %s.\n", | |
52 | oldpath, strerror(errno)); | |
53 | errno = ENOENT; | |
54 | return rc; | |
55 | } | |
56 | msg = pseudo_client_op(OP_STAT, 0, -1, -1, oldpath, &buf); | |
57 | if (msg && msg->result == RESULT_SUCCEED) { | |
58 | pseudo_stat_msg(&buf, msg); | |
59 | } | |
60 | /* Long story short: I am pretty sure we still want OP_LINK even | |
61 | * if the thing linked is a symlink. | |
62 | */ | |
63 | pseudo_client_op(OP_LINK, 0, -1, -1, newpath, &buf); | |
42 | newpath = pseudo_root_path(__func__, __LINE__, newdirfd, newname, AT_SYMLINK_NOFOLLOW); | |
64 | 43 | |
65 | errno = save_errno; | |
44 | /* weird special case: if you link /proc/self/fd/N, you're supposed | |
45 | * to get a link to fd N. Used in conjunction with opening a directory | |
46 | * with O_TMPFILE in flags, which actually opens an already-deleted | |
47 | * file atomically, so there's no way to access the file *at all* | |
48 | * unless it's linked. | |
49 | */ | |
50 | #ifdef O_TMPFILE | |
51 | if (!strncmp(oldpath, "/proc/self/fd/", 14) && (flags & AT_SYMLINK_FOLLOW)) { | |
52 | #ifdef PSEUDO_NO_REAL_AT_FUNCTIONS | |
53 | /* only linkat() lets you do this horrible thing */ | |
54 | errno = ENOSYS; | |
55 | return -1; | |
56 | #endif | |
57 | tmpfile_fd = atoi(oldpath + 14); | |
58 | // call actual link | |
59 | rc = real_linkat(AT_FDCWD, oldpath, AT_FDCWD, newpath, AT_SYMLINK_FOLLOW); | |
60 | } else | |
61 | #endif | |
62 | { | |
63 | oldpath = pseudo_root_path(__func__, __LINE__, olddirfd, oldname, rflags); | |
64 | rc = real_link(oldpath, newpath); | |
65 | } | |
66 | ||
67 | save_errno = errno; | |
68 | if (rc == -1) { | |
69 | return rc; | |
70 | } | |
71 | ||
72 | /* if we got this far, the link succeeded, and oldpath and newpath | |
73 | * are the newly-allocated canonical paths. If OS, filesystem, or | |
74 | * the flags value prevent hard linking to symlinks, the resolved | |
75 | * path should be the target's path anyway, so lstat is safe here. | |
76 | */ | |
77 | /* find the target: */ | |
78 | if (tmpfile_fd != -1) { | |
79 | rc2 = base_fstat(tmpfile_fd, &buf); | |
80 | } else { | |
81 | rc2 = base_lstat(oldpath, &buf); | |
82 | } | |
83 | if (rc2 == -1) { | |
84 | pseudo_diag("Fatal: Tried to stat '%s' after linking it, but failed: %s.\n", | |
85 | oldpath, strerror(errno)); | |
86 | errno = ENOENT; | |
87 | return rc2; | |
88 | } | |
89 | if (tmpfile_fd != -1) { | |
90 | /* if tmpfile_fd is set, it's *possible* but not *certain* that | |
91 | * we're looking at a file descriptor from an O_TMPFILE open, | |
92 | * which would not be in the database. | |
93 | * | |
94 | * If it's not, we want to treat this like a CREAT operation, | |
95 | * instead of a "link". | |
96 | */ | |
97 | msg = pseudo_client_op(OP_FSTAT, 0, tmpfile_fd, -1, 0, &buf); | |
98 | if (!msg || msg->result != RESULT_SUCCEED) { | |
99 | /* create it, mark it as open so we have a path recorded | |
100 | * in the client, and return rc immediately instead | |
101 | * of continuing on to call OP_LINK. | |
102 | */ | |
103 | pseudo_client_op(OP_CREAT, 0, tmpfile_fd, -1, newpath, &buf); | |
104 | pseudo_client_op(OP_OPEN, 0, tmpfile_fd, -1, newpath, &buf); | |
105 | errno = save_errno; | |
106 | return rc; | |
107 | } | |
108 | } else { | |
109 | msg = pseudo_client_op(OP_STAT, 0, -1, -1, oldpath, &buf); | |
110 | } | |
111 | if (msg && msg->result == RESULT_SUCCEED) { | |
112 | pseudo_stat_msg(&buf, msg); | |
113 | } | |
114 | /* Long story short: I am pretty sure we still want OP_LINK even | |
115 | * if the thing linked is a symlink. | |
116 | */ | |
117 | pseudo_client_op(OP_LINK, 0, -1, -1, newpath, &buf); | |
118 | ||
119 | errno = save_errno; | |
66 | 120 | |
67 | 121 | /* return rc; |
68 | 122 | * } |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_lutimes(const char *path, const struct timeval *tv) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_mkdir(const char *path, mode_t mode) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010, 2012 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_mkdirat(int dirfd, const char *path, mode_t mode) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2010, 2012 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static char * |
5 | 7 | * wrap_mkdtemp(char *template) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_mkfifo(const char *path, mode_t mode) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2015 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_mkfifoat(int dirfd, const char *path, mode_t mode) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2011,2014 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * int mknod(const char *path, mode_t mode, dev_t dev) |
5 | 7 | * int rc = -1; |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2011 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * int mknodat(int dirfd, const char *path, mode_t mode, dev_t dev) |
5 | 7 | * int rc = -1; |
0 | /* | |
1 | * Copyright (c) 2018 Wind River Systems; see | |
2 | * guts/COPYRIGHT for information. | |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
5 | * | |
6 | * int mkostemp(char *template, int oflags) | |
7 | * int rc = -1; | |
8 | */ | |
9 | ||
10 | /* mkostemp = mkostemps() with suffixlen of 0 */ | |
11 | rc = wrap_mkostemps(template, 0, oflags); | |
12 | ||
13 | /* return rc; | |
14 | * } | |
15 | */ |
0 | /* | |
1 | * Copyright (c) 2008-2010, 2012 Wind River Systems; see | |
2 | * guts/COPYRIGHT for information. | |
3 | * | |
4 | * Copyright (c) 2018 Peter Seebach; see | |
5 | * guts/COPYRIGHT for information. | |
6 | * | |
7 | * SPDX-License-Identifier: LGPL-2.1-only | |
8 | * | |
9 | * int mkostemps(char *template, int suffixlen, int oflags) | |
10 | * int rc = -1; | |
11 | */ | |
12 | ||
13 | PSEUDO_STATBUF buf; | |
14 | int save_errno; | |
15 | size_t len; | |
16 | char *tmp_template; | |
17 | ||
18 | if (!template) { | |
19 | errno = EFAULT; | |
20 | return 0; | |
21 | } | |
22 | ||
23 | len = strlen(template); | |
24 | tmp_template = PSEUDO_ROOT_PATH(AT_FDCWD, template, AT_SYMLINK_NOFOLLOW); | |
25 | ||
26 | if (!tmp_template) { | |
27 | errno = ENOENT; | |
28 | return -1; | |
29 | } | |
30 | ||
31 | rc = real_mkostemps(tmp_template, suffixlen, oflags); | |
32 | ||
33 | if (rc != -1) { | |
34 | save_errno = errno; | |
35 | ||
36 | if (base_fstat(rc, &buf) != -1) { | |
37 | real_fchmod(rc, PSEUDO_FS_MODE(0600, 0)); | |
38 | pseudo_client_op(OP_CREAT, 0, -1, -1, tmp_template, &buf); | |
39 | pseudo_client_op(OP_OPEN, PSA_READ | PSA_WRITE, rc, -1, tmp_template, &buf); | |
40 | } else { | |
41 | pseudo_debug(PDBGF_CONSISTENCY, "mkstemp (fd %d) succeeded, but fstat failed (%s).\n", | |
42 | rc, strerror(errno)); | |
43 | pseudo_client_op(OP_OPEN, PSA_READ | PSA_WRITE, rc, -1, tmp_template, 0); | |
44 | } | |
45 | errno = save_errno; | |
46 | } | |
47 | /* WARNING: At least one system allows the number of Xs to be something | |
48 | * other than 6. I do not attempt to handle this. | |
49 | */ | |
50 | /* mkstemp only changes the XXXXXX at the end, or suffixlen characters before | |
51 | * the end if mkostemp/mkostemps. | |
52 | */ | |
53 | memcpy(template + len - 6 - suffixlen, tmp_template + strlen(tmp_template) - 6 - suffixlen, 6); | |
54 | /* return rc; | |
55 | * } | |
56 | */ |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010, 2012 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_mkstemp(char *template) { |
6 | 8 | * int rc = -1; |
7 | 9 | */ |
8 | PSEUDO_STATBUF buf; | |
9 | int save_errno; | |
10 | size_t len; | |
11 | char *tmp_template; | |
10 | /* mkstemp() is just like mkostemps() with no flags and no suffix */ | |
11 | rc = wrap_mkostemps(template, 0, 0); | |
12 | 12 | |
13 | if (!template) { | |
14 | errno = EFAULT; | |
15 | return 0; | |
16 | } | |
17 | ||
18 | len = strlen(template); | |
19 | tmp_template = PSEUDO_ROOT_PATH(AT_FDCWD, template, AT_SYMLINK_NOFOLLOW); | |
20 | ||
21 | if (!tmp_template) { | |
22 | errno = ENOENT; | |
23 | return -1; | |
24 | } | |
25 | ||
26 | rc = real_mkstemp(tmp_template); | |
27 | ||
28 | if (rc != -1) { | |
29 | save_errno = errno; | |
30 | ||
31 | if (base_fstat(rc, &buf) != -1) { | |
32 | real_fchmod(rc, PSEUDO_FS_MODE(0600, 0)); | |
33 | pseudo_client_op(OP_CREAT, 0, -1, -1, tmp_template, &buf); | |
34 | pseudo_client_op(OP_OPEN, PSA_READ | PSA_WRITE, rc, -1, tmp_template, &buf); | |
35 | } else { | |
36 | pseudo_debug(PDBGF_CONSISTENCY, "mkstemp (fd %d) succeeded, but fstat failed (%s).\n", | |
37 | rc, strerror(errno)); | |
38 | pseudo_client_op(OP_OPEN, PSA_READ | PSA_WRITE, rc, -1, tmp_template, 0); | |
39 | } | |
40 | errno = save_errno; | |
41 | } | |
42 | /* mkstemp only changes the XXXXXX at the end. */ | |
43 | memcpy(template + len - 6, tmp_template + strlen(tmp_template) - 6, 6); | |
44 | 13 | /* return rc; |
45 | 14 | * } |
46 | 15 | */ |
0 | /* | |
1 | * Copyright (c) 2018 Wind River Systems; see | |
2 | * guts/COPYRIGHT for information. | |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
5 | * | |
6 | * int mkstemps(char *template, int suffixlen) | |
7 | * int rc = -1; | |
8 | */ | |
9 | ||
10 | /* mkstemps() is mkostemps() with no flags */ | |
11 | rc = wrap_mkostemps(template, suffixlen, 0); | |
12 | ||
13 | /* return rc; | |
14 | * } | |
15 | */ |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static char * |
5 | 7 | * wrap_mktemp(char *template) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2013 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * int msync(void *addr, size_t length, int flags) |
5 | 7 | * int rc = -1; |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_nftw(const char *path, int (*fn)(const char *, const struct stat *, int, struct FTW *), int nopenfd, int flag) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2010, 2012 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static DIR * |
5 | 7 | * wrap_opendir(const char *path) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static long |
5 | 7 | * wrap_pathconf(const char *path, int name) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2012 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * FILE *popen(const char *command, const char *mode) |
5 | 7 | * FILE *rc = NULL; |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static ssize_t |
5 | 7 | * wrap_readlink(const char *path, char *buf, size_t bufsiz) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static ssize_t |
5 | 7 | * wrap_readlinkat(int dirfd, const char *path, char *buf, size_t bufsiz) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static char * |
5 | 7 | * wrap_realpath(const char *name, char *resolved_name) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010, 2012 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_remove(const char *path) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010, 2012 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_rename(const char *oldpath, const char *newpath) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2012 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_renameat(int olddirfd, const char *oldpath, int newdirfd, const char *newpath) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010, 2012 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_rmdir(const char *path) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_symlink(const char *oldname, const char *newpath) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010, 2012 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_symlinkat(const char *oldname, int dirfd, const char *newpath) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2013 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * void sync(void) |
5 | 7 | * |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2013 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * int sync_file_range(int fd, off64_t offset, off64_t nbytes, unsigned int flags) |
5 | 7 | * int rc = -1; |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2011, 2012 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * int system(const char *command) |
5 | 7 | * int rc = -1; |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static char * |
5 | 7 | * wrap_tempnam(const char *template, const char *pfx) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static char * |
5 | 7 | * wrap_tmpnam(char *s) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_truncate(const char *path, off_t length) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2014 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * mode_t umask(mode_t mask) |
5 | 7 | * mode_t rc = 0; |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_unlink(const char *path) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2008-2010, 2012 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_unlinkat(int dirfd, const char *path, int rflags) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_utime(const char *path, const struct utimbuf *buf) { |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2010 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * static int |
5 | 7 | * wrap_utimes(const char *path, const struct timeval *times) { |
0 | /* | |
1 | * SPDX-License-Identifier: LGPL-2.1-only | |
2 | * | |
3 | */ | |
0 | 4 | FILE * |
1 | 5 | popen(const char *command, const char *mode) { |
2 | 6 | sigset_t saved; |
0 | 0 | /* |
1 | 1 | * Copyright (c) 2013 Wind River Systems; see |
2 | 2 | * guts/COPYRIGHT for information. |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
3 | 5 | * |
4 | 6 | * int syncfs(int fd) |
5 | 7 | * int rc = -1; |
45 | 45 | int mknod(const char *path, mode_t mode, dev_t dev); /* flags=AT_SYMLINK_NOFOLLOW */ |
46 | 46 | int mknodat(int dirfd, const char *path, mode_t mode, dev_t dev); /* flags=AT_SYMLINK_NOFOLLOW */ |
47 | 47 | int mkstemp(char *template); /* flags=AT_SYMLINK_NOFOLLOW */ |
48 | int mkostemp(char *template, int oflags); /* flags=AT_SYMLINK_NOFOLLOW */ | |
49 | int mkstemps(char *template, int suffixlen); /* flags=AT_SYMLINK_NOFOLLOW */ | |
50 | int mkostemps(char *template, int suffixlen, int oflags); /* flags=AT_SYMLINK_NOFOLLOW */ | |
48 | 51 | int rename(const char *oldpath, const char *newpath); /* flags=AT_SYMLINK_NOFOLLOW */ |
49 | 52 | int renameat(int olddirfd, const char *oldpath, int newdirfd, const char *newpath); /* flags=AT_SYMLINK_NOFOLLOW */ |
50 | 53 | int rmdir(const char *path); /* flags=AT_SYMLINK_NOFOLLOW */ |
15 | 15 | .\" version 2.1 along with this program; if not, write to the Free Software |
16 | 16 | .\" Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
17 | 17 | .TH pseudo 1 "pseudo - pretending to be root" |
18 | .SH NAME | |
19 | pseudo \- run a command in a virtual root environment | |
18 | 20 | .SH SYNOPSIS |
19 | 21 | .B pseudo |
20 | 22 | .RB [ \-dflv ] |
2 | 2 | * |
3 | 3 | * Copyright (c) 2008-2013 Wind River Systems, Inc. |
4 | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify | |
6 | * it under the terms of the Lesser GNU General Public License version 2.1 as | |
7 | * published by the Free Software Foundation. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | |
12 | * See the Lesser GNU General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the Lesser GNU General Public License | |
15 | * version 2.1 along with this program; if not, write to the Free Software | |
16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
5 | * SPDX-License-Identifier: LGPL-2.1-only | |
17 | 6 | * |
18 | 7 | */ |
19 | 8 | #include <stdlib.h> |
333 | 322 | |
334 | 323 | /* If you didn't specify a command, opt_S shuts down here. */ |
335 | 324 | if (opt_S && argc <= optind) { |
336 | return pseudo_client_shutdown(); | |
325 | return pseudo_client_shutdown(0); | |
337 | 326 | } |
338 | 327 | |
339 | 328 | if (opt_d && opt_f) { |
408 | 397 | * the server. |
409 | 398 | */ |
410 | 399 | if (opt_S) { |
411 | pseudo_client_shutdown(); | |
400 | pseudo_client_shutdown(1); | |
412 | 401 | } |
413 | 402 | if (WIFEXITED(rc)) { |
414 | 403 | return WEXITSTATUS(rc); |
443 | 432 | char *path_by_ino = 0; |
444 | 433 | char *oldpath = 0; |
445 | 434 | size_t oldpathlen = 0; |
446 | int found_path = 0, found_ino = 0; | |
435 | int found_path = 0, found_ino = 0, found_exact = 0; | |
447 | 436 | int prefer_ino = 0; |
448 | 437 | int xattr_flags = 0; |
449 | 438 | int trailing_slash = 0; |
542 | 531 | *msg = msg_header; |
543 | 532 | found_path = 1; |
544 | 533 | found_ino = 1; |
534 | found_exact = 1; | |
545 | 535 | /* note: we have to avoid freeing this later */ |
546 | 536 | path_by_ino = msg->path; |
547 | 537 | if (msg->op == OP_LINK) { |
628 | 618 | pseudo_diag("dir mismatch: '%s' [%llu] db mode 0%o, header mode 0%o (unlinking db)\n", |
629 | 619 | msg->path, (unsigned long long) by_path.ino, |
630 | 620 | (int) by_path.mode, (int) msg_header.mode); |
631 | /* unlink everything with this inode */ | |
632 | pdb_unlink_file_dev(&by_path); | |
621 | /* unlink this path -- the inode may be in use elsewhere */ | |
622 | pdb_unlink_file(msg); | |
633 | 623 | found_path = 0; |
634 | 624 | } else if (S_ISLNK(by_path.mode) != S_ISLNK(msg_header.mode)) { |
635 | 625 | pseudo_diag("symlink mismatch: '%s' [%llu] db mode 0%o, header mode 0%o (unlinking db)\n", |
636 | 626 | msg->path, (unsigned long long) by_path.ino, |
637 | 627 | (int) by_path.mode, (int) msg_header.mode); |
638 | /* unlink everything with this inode */ | |
639 | pdb_unlink_file_dev(&by_path); | |
628 | /* unlink this path -- the inode may be in use elsewhere */ | |
629 | pdb_unlink_file(msg); | |
640 | 630 | found_path = 0; |
641 | 631 | } |
642 | 632 | if (trailing_slash && !S_ISDIR(by_path.mode)) { |
704 | 694 | msg->path); |
705 | 695 | pdb_did_unlink_file(path_by_ino, &by_ino, by_ino.deleting); |
706 | 696 | } else { |
707 | pseudo_diag("path mismatch [%d link%s]: ino %llu db '%s' req '%s'.\n", | |
697 | int flags = 0; | |
698 | if (msg->nlink > 1) { | |
699 | flags = PDBGF_FILE | PDBGF_VERBOSE; | |
700 | } | |
701 | pseudo_debug(flags, "path mismatch [%d link%s]: ino %llu db '%s' req '%s'.\n", | |
708 | 702 | msg->nlink, |
709 | 703 | msg->nlink == 1 ? "" : "s", |
710 | 704 | (unsigned long long) msg_header.ino, |
767 | 761 | break; |
768 | 762 | case OP_CREAT: |
769 | 763 | /* implies a new file -- not a link, which would be OP_LINK */ |
770 | if (found_ino) { | |
764 | if (found_ino && !found_exact) { | |
771 | 765 | /* CREAT should never be sent if the file existed. |
772 | 766 | * So, any existing entry is an error. Nuke it. |
767 | * ... But only if it wasn't a match on both inode *and* | |
768 | * path, because if it were, that would be harmless. | |
773 | 769 | */ |
774 | 770 | pseudo_diag("creat for '%s' replaces existing %llu ['%s'].\n", |
775 | 771 | msg->pathlen ? msg->path : "no path", |
1011 | 1007 | if (msg->op == OP_REPLACE_XATTR) { |
1012 | 1008 | xattr_flags = XATTR_REPLACE; |
1013 | 1009 | } |
1010 | /* fallthrough */ | |
1014 | 1011 | case OP_SET_XATTR: |
1015 | 1012 | if (pdb_set_xattr(msg, oldpath, oldpathlen, xattr_flags)) { |
1016 | 1013 | msg->result = RESULT_FAIL; |
2 | 2 | * |
3 | 3 | * Copyright (c) 2008-2010, 2013 Wind River Systems, Inc. |
4 | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify | |
6 | * it under the terms of the Lesser GNU General Public License version 2.1 as | |
7 | * published by the Free Software Foundation. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | |
12 | * See the Lesser GNU General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the Lesser GNU General Public License | |
15 | * version 2.1 along with this program; if not, write to the Free Software | |
16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
5 | * SPDX-License-Identifier: LGPL-2.1-only | |
17 | 6 | * |
18 | 7 | */ |
19 | 8 | #include <stdlib.h> |
52 | 41 | if ((x) & PDBGF_VERBOSE) { \ |
53 | 42 | if ((pseudo_util_debug_flags & PDBGF_VERBOSE) && (pseudo_util_debug_flags & ((x) & ~PDBGF_VERBOSE))) { pseudo_diag(__VA_ARGS__); } \ |
54 | 43 | } else { \ |
55 | if (pseudo_util_debug_flags & (x)) { pseudo_diag(__VA_ARGS__); } \ | |
44 | if ((pseudo_util_debug_flags & (x)) || ((x) == 0)) { pseudo_diag(__VA_ARGS__); } \ | |
56 | 45 | } \ |
57 | 46 | } while (0) |
58 | 47 | #define pseudo_debug_call(x, fn, ...) do { \ |
2 | 2 | * |
3 | 3 | * Copyright (c) 2008-2013 Wind River Systems, Inc. |
4 | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify | |
6 | * it under the terms of the Lesser GNU General Public License version 2.1 as | |
7 | * published by the Free Software Foundation. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | |
12 | * See the Lesser GNU General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the Lesser GNU General Public License | |
15 | * version 2.1 along with this program; if not, write to the Free Software | |
16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
5 | * SPDX-License-Identifier: LGPL-2.1-only | |
17 | 6 | * |
18 | 7 | */ |
19 | 8 | #define _GNU_SOURCE |
1330 | 1319 | * indicating a successful send. |
1331 | 1320 | */ |
1332 | 1321 | pseudo_debug(PDBGF_CLIENT | PDBGF_VERBOSE, "sent!\n"); |
1333 | if (msg->type != PSEUDO_MSG_FASTOP) { | |
1334 | response = pseudo_msg_receive(connect_fd); | |
1335 | if (!response) { | |
1336 | pseudo_debug(PDBGF_CLIENT, "expected response did not occur; retrying\n"); | |
1322 | response = pseudo_msg_receive(connect_fd); | |
1323 | if (!response) { | |
1324 | pseudo_debug(PDBGF_CLIENT, "expected response did not occur; retrying\n"); | |
1325 | } else { | |
1326 | if (response->type != PSEUDO_MSG_ACK) { | |
1327 | pseudo_debug(PDBGF_CLIENT, "got non-ack response %d\n", response->type); | |
1328 | return 0; | |
1337 | 1329 | } else { |
1338 | if (response->type != PSEUDO_MSG_ACK) { | |
1339 | pseudo_debug(PDBGF_CLIENT, "got non-ack response %d\n", response->type); | |
1340 | return 0; | |
1341 | } else { | |
1342 | pseudo_debug(PDBGF_CLIENT | PDBGF_VERBOSE, "got response type %d\n", response->type); | |
1343 | return response; | |
1344 | } | |
1345 | } | |
1346 | } else { | |
1347 | return 0; | |
1330 | pseudo_debug(PDBGF_CLIENT | PDBGF_VERBOSE, "got response type %d\n", response->type); | |
1331 | return response; | |
1332 | } | |
1348 | 1333 | } |
1349 | 1334 | } |
1350 | 1335 | pseudo_diag("pseudo: server connection persistently failed, aborting.\n"); |
1356 | 1341 | } |
1357 | 1342 | |
1358 | 1343 | int |
1359 | pseudo_client_shutdown(void) { | |
1344 | pseudo_client_shutdown(int wait_on_socket) { | |
1360 | 1345 | pseudo_msg_t msg; |
1361 | 1346 | pseudo_msg_t *ack; |
1362 | 1347 | char *pseudo_path; |
1427 | 1412 | pseudo_diag("server did not respond to shutdown query.\n"); |
1428 | 1413 | return 1; |
1429 | 1414 | } |
1430 | if (ack->type == PSEUDO_MSG_ACK) { | |
1431 | return 0; | |
1432 | } | |
1433 | pseudo_diag("Server refused shutdown. Remaining client fds: %d\n", ack->fd); | |
1434 | pseudo_diag("Client pids: %s\n", ack->path); | |
1435 | pseudo_diag("Server will shut down after all clients exit.\n"); | |
1415 | if (ack->type != PSEUDO_MSG_ACK) { | |
1416 | pseudo_diag("Server refused shutdown. Remaining client fds: %d\n", ack->fd); | |
1417 | pseudo_diag("Client pids: %s\n", ack->path); | |
1418 | pseudo_diag("Server will shut down after all clients exit.\n"); | |
1419 | } | |
1420 | if (wait_on_socket) { | |
1421 | /* try to receive a message the server won't send; | |
1422 | * this should abort/error-out when the server actually | |
1423 | * shuts down. */ | |
1424 | ack = pseudo_msg_receive(connect_fd); | |
1425 | } | |
1436 | 1426 | return 0; |
1437 | 1427 | } |
1438 | 1428 | |
1483 | 1473 | } |
1484 | 1474 | |
1485 | 1475 | newpath = pseudo_fix_path(basepath, path, minlen, baselen, NULL, leave_last); |
1486 | pseudo_debug(PDBGF_PATH, "base_path: %s</>%s\n", | |
1476 | pseudo_debug(PDBGF_PATH, "base_path[%s]: %s</>%s => %s\n", | |
1477 | leave_last ? "nofollow" : "follow", | |
1487 | 1478 | basepath ? basepath : "<nil>", |
1488 | path ? path : "<nil>"); | |
1479 | path ? path : "<nil>", | |
1480 | newpath ? newpath : "<nil>"); | |
1489 | 1481 | return newpath; |
1490 | 1482 | } |
1491 | 1483 | |
1675 | 1667 | * empty path for that. |
1676 | 1668 | */ |
1677 | 1669 | if (path_extra_1) { |
1678 | size_t full_len = path_extra_1len + 1 + pathlen; | |
1670 | size_t full_len = path_extra_1len + 1 + pathlen - strip_slash; | |
1679 | 1671 | size_t partial_len = pathlen - 1 - strip_slash; |
1680 | 1672 | if (path_extra_2) { |
1681 | 1673 | full_len += path_extra_2len + 1; |
2 | 2 | * |
3 | 3 | * Copyright (c) 2008-2010 Wind River Systems, Inc. |
4 | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify | |
6 | * it under the terms of the Lesser GNU General Public License version 2.1 as | |
7 | * published by the Free Software Foundation. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | |
12 | * See the Lesser GNU General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the Lesser GNU General Public License | |
15 | * version 2.1 along with this program; if not, write to the Free Software | |
16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
5 | * SPDX-License-Identifier: LGPL-2.1-only | |
17 | 6 | * |
18 | 7 | */ |
19 | 8 | extern pseudo_msg_t *pseudo_client_op(pseudo_op_t op, int access, int fd, int dirfd, const char *path, const PSEUDO_STATBUF *buf, ...); |
33 | 22 | extern void pseudo_client_touchuid(void); |
34 | 23 | extern void pseudo_client_touchgid(void); |
35 | 24 | extern char *pseudo_client_fdpath(int fd); |
36 | extern int pseudo_client_shutdown(void); | |
25 | extern int pseudo_client_shutdown(int); | |
37 | 26 | extern int pseudo_fd(int fd, int how); |
38 | 27 | #define MOVE_FD 0 |
39 | 28 | #define COPY_FD 1 |
2 | 2 | * |
3 | 3 | * Copyright (c) 2008-2010,2013 Wind River Systems, Inc. |
4 | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify | |
6 | * it under the terms of the Lesser GNU General Public License version 2.1 as | |
7 | * published by the Free Software Foundation. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | |
12 | * See the Lesser GNU General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the Lesser GNU General Public License | |
15 | * version 2.1 along with this program; if not, write to the Free Software | |
16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
5 | * SPDX-License-Identifier: LGPL-2.1-only | |
17 | 6 | * |
18 | 7 | */ |
19 | 8 | #include <stdio.h> |
20 | 9 | #include <stdlib.h> |
21 | 10 | #include <string.h> |
11 | #include <stdint.h> | |
22 | 12 | #include <sys/stat.h> |
23 | 13 | #include <sys/xattr.h> |
24 | 14 | #include <time.h> |
369 | 359 | } |
370 | 360 | } |
371 | 361 | |
362 | /* sqlite3 supports only signed integers, thus, the highest positive | |
363 | * value is 2^63-1. some filesystems with 64-bit ino_t will produce | |
364 | * ino_t values in the 2^63..2^64-1 range. we convert those into | |
365 | * the value you'd get treating the 2^63 bit as a sign bit, so sqlite | |
366 | * doesn't convert them into floats, because the float type can't | |
367 | * represent values accurately in this range, which can result in | |
368 | * erroneous matches, etcetera. | |
369 | * | |
370 | * note, when reading the values back out, the conversion does the | |
371 | * right thing. e.g., if the inode number had been 2^63 exactly, | |
372 | * it will convert to -(2^63). that, converted to unsigned, will | |
373 | * convert back to 2^63 exactly, etcetera. | |
374 | * | |
375 | * so far as i know, ino_t is always unsigned. we don't care about | |
376 | * the 32-bit inode case; sqlite can represent those just fine. | |
377 | */ | |
378 | static int64_t | |
379 | signed_ino(ino_t ino) { | |
380 | if (ino > (uint64_t) INT64_MAX) { | |
381 | return (int64_t) (ino + INT64_MIN) + INT64_MIN; | |
382 | } | |
383 | return (int64_t) ino; | |
384 | } | |
385 | ||
372 | 386 | #ifdef USE_MEMORY_DB |
373 | 387 | |
374 | 388 | static void |
781 | 795 | e->gid = trait->data.ivalue; |
782 | 796 | break; |
783 | 797 | case PSQF_INODE: |
784 | e->ino = trait->data.ivalue; | |
798 | e->ino = (ino_t) trait->data.ivalue; | |
785 | 799 | break; |
786 | 800 | case PSQF_MODE: |
787 | 801 | e->mode = trait->data.ivalue; |
874 | 888 | sqlite3_bind_int(insert, field++, e->client); |
875 | 889 | sqlite3_bind_int(insert, field++, e->dev); |
876 | 890 | sqlite3_bind_int(insert, field++, e->gid); |
877 | sqlite3_bind_int64(insert, field++, e->ino); | |
891 | sqlite3_bind_int64(insert, field++, signed_ino(e->ino)); | |
878 | 892 | sqlite3_bind_int(insert, field++, e->mode); |
879 | 893 | if (e->path) { |
880 | 894 | sqlite3_bind_text(insert, field++, e->path, -1, SQLITE_STATIC); |
968 | 982 | sqlite3_bind_int(insert, field++, msg->client); |
969 | 983 | sqlite3_bind_int(insert, field++, msg->dev); |
970 | 984 | sqlite3_bind_int(insert, field++, msg->gid); |
971 | sqlite3_bind_int64(insert, field++, msg->ino); | |
985 | sqlite3_bind_int64(insert, field++, signed_ino(msg->ino)); | |
972 | 986 | sqlite3_bind_int(insert, field++, msg->mode); |
973 | 987 | if (msg->pathlen) { |
974 | 988 | sqlite3_bind_text(insert, field++, msg->path, -1, SQLITE_STATIC); |
1375 | 1389 | l->gid = sqlite3_column_int64(h->stmt, column++); |
1376 | 1390 | break; |
1377 | 1391 | case PSQF_INODE: |
1378 | l->ino = sqlite3_column_int64(h->stmt, column++); | |
1392 | l->ino = (ino_t) sqlite3_column_int64(h->stmt, column++); | |
1379 | 1393 | break; |
1380 | 1394 | case PSQF_MODE: |
1381 | 1395 | l->mode = sqlite3_column_int64(h->stmt, column++); |
1494 | 1508 | static void |
1495 | 1509 | pdb_clear_xattrs(pseudo_msg_t *msg) { |
1496 | 1510 | static sqlite3_stmt *delete; |
1497 | char *delete_sql = "DELETE FROM xattrs WHERE dev = ? AND ino = ?;"; | |
1511 | char *delete_sql = "DELETE FROM xattrs WHERE dev = ? AND ino = ? AND (SELECT COUNT(*) FROM files WHERE dev = ? AND ino = ?) = 0;"; | |
1498 | 1512 | int rc; |
1499 | 1513 | |
1500 | 1514 | if (!msg) |
1506 | 1520 | if (!delete) { |
1507 | 1521 | rc = sqlite3_prepare_v2(file_db, delete_sql, strlen(delete_sql), &delete, NULL); |
1508 | 1522 | if (rc) { |
1509 | dberr(file_db, "couldn't prepare DELETE statement for unused xattrs"); | |
1523 | dberr(file_db, "couldn't prepare DELETE statement for specific inode xattrs"); | |
1510 | 1524 | return; |
1511 | 1525 | } |
1512 | 1526 | } |
1513 | 1527 | sqlite3_bind_int(delete, 1, msg->dev); |
1514 | sqlite3_bind_int(delete, 2, msg->ino); | |
1528 | sqlite3_bind_int64(delete, 2, signed_ino(msg->ino)); | |
1529 | sqlite3_bind_int(delete, 3, msg->dev); | |
1530 | sqlite3_bind_int64(delete, 4, signed_ino(msg->ino)); | |
1515 | 1531 | rc = sqlite3_step(delete); |
1516 | 1532 | if (rc != SQLITE_DONE) { |
1517 | 1533 | dberr(file_db, "delete of unused xattrs may have failed"); |
1546 | 1562 | } |
1547 | 1563 | } |
1548 | 1564 | sqlite3_bind_int(copy, 1, msg->dev); |
1549 | sqlite3_bind_int(copy, 2, msg->ino); | |
1565 | sqlite3_bind_int64(copy, 2, signed_ino(msg->ino)); | |
1550 | 1566 | sqlite3_bind_int(copy, 3, oldmsg->dev); |
1551 | sqlite3_bind_int(copy, 4, oldmsg->ino); | |
1567 | sqlite3_bind_int64(copy, 4, signed_ino(oldmsg->ino)); | |
1552 | 1568 | rc = sqlite3_step(copy); |
1553 | 1569 | if (rc != SQLITE_DONE) { |
1554 | 1570 | dberr(file_db, "copy of xattrs may have failed"); |
1578 | 1594 | } |
1579 | 1595 | int existing; |
1580 | 1596 | sqlite3_bind_int(scan, 1, msg->dev); |
1581 | sqlite3_bind_int(scan, 2, msg->ino); | |
1597 | sqlite3_bind_int64(scan, 2, signed_ino(msg->ino)); | |
1582 | 1598 | rc = sqlite3_step(scan); |
1583 | 1599 | if (rc == SQLITE_ROW) { |
1584 | 1600 | existing = (int) sqlite3_column_int64(scan, 0); |
1632 | 1648 | sqlite3_bind_text(insert, 1, "NAMELESS FILE", -1, SQLITE_STATIC); |
1633 | 1649 | } |
1634 | 1650 | sqlite3_bind_int(insert, 2, msg->dev); |
1635 | sqlite3_bind_int64(insert, 3, msg->ino); | |
1651 | sqlite3_bind_int64(insert, 3, signed_ino(msg->ino)); | |
1636 | 1652 | sqlite3_bind_int(insert, 4, msg->uid); |
1637 | 1653 | sqlite3_bind_int(insert, 5, msg->gid); |
1638 | 1654 | sqlite3_bind_int(insert, 6, msg->mode); |
1673 | 1689 | return 1; |
1674 | 1690 | } |
1675 | 1691 | sqlite3_bind_int(sql_delete, 1, msg->dev); |
1676 | sqlite3_bind_int64(sql_delete, 2, msg->ino); | |
1692 | sqlite3_bind_int64(sql_delete, 2, signed_ino(msg->ino)); | |
1677 | 1693 | file_db_dirty = 1; |
1678 | 1694 | rc = sqlite3_step(sql_delete); |
1679 | 1695 | if (rc != SQLITE_DONE) { |
2165 | 2181 | pdb_copy_xattrs(oldmsg, msg); |
2166 | 2182 | } |
2167 | 2183 | sqlite3_bind_int(update, 1, msg->dev); |
2168 | sqlite3_bind_int64(update, 2, msg->ino); | |
2184 | sqlite3_bind_int64(update, 2, signed_ino(msg->ino)); | |
2169 | 2185 | rc = sqlite3_bind_text(update, 3, msg->path, -1, SQLITE_STATIC); |
2170 | 2186 | if (rc) { |
2171 | 2187 | /* msg->path can never be null, and if msg didn't |
2222 | 2238 | sqlite3_bind_int(update, 3, msg->mode); |
2223 | 2239 | sqlite3_bind_int(update, 4, msg->rdev); |
2224 | 2240 | sqlite3_bind_int(update, 5, msg->dev); |
2225 | sqlite3_bind_int64(update, 6, msg->ino); | |
2241 | sqlite3_bind_int64(update, 6, signed_ino(msg->ino)); | |
2226 | 2242 | |
2227 | 2243 | file_db_dirty = 1; |
2228 | 2244 | rc = sqlite3_step(update); |
2263 | 2279 | dberr(file_db, "error binding %s to select", msg->pathlen ? msg->path : "<nil>"); |
2264 | 2280 | } |
2265 | 2281 | sqlite3_bind_int(select, 2, msg->dev); |
2266 | sqlite3_bind_int64(select, 3, msg->ino); | |
2282 | sqlite3_bind_int64(select, 3, signed_ino(msg->ino)); | |
2267 | 2283 | rc = sqlite3_step(select); |
2268 | 2284 | switch (rc) { |
2269 | 2285 | case SQLITE_ROW: |
2322 | 2338 | switch (rc) { |
2323 | 2339 | case SQLITE_ROW: |
2324 | 2340 | msg->dev = sqlite3_column_int64(select, 2); |
2325 | msg->ino = sqlite3_column_int64(select, 3); | |
2341 | msg->ino = (ino_t) sqlite3_column_int64(select, 3); | |
2326 | 2342 | msg->uid = sqlite3_column_int64(select, 4); |
2327 | 2343 | msg->gid = sqlite3_column_int64(select, 5); |
2328 | 2344 | msg->mode = sqlite3_column_int64(select, 6); |
2367 | 2383 | return 0; |
2368 | 2384 | } |
2369 | 2385 | sqlite3_bind_int(select, 1, msg->dev); |
2370 | sqlite3_bind_int64(select, 2, msg->ino); | |
2386 | sqlite3_bind_int64(select, 2, signed_ino(msg->ino)); | |
2371 | 2387 | rc = sqlite3_step(select); |
2372 | 2388 | switch (rc) { |
2373 | 2389 | case SQLITE_ROW: |
2416 | 2432 | return 1; |
2417 | 2433 | } |
2418 | 2434 | sqlite3_bind_int(select, 1, msg->dev); |
2419 | sqlite3_bind_int64(select, 2, msg->ino); | |
2435 | sqlite3_bind_int64(select, 2, signed_ino(msg->ino)); | |
2420 | 2436 | rc = sqlite3_step(select); |
2421 | 2437 | switch (rc) { |
2422 | 2438 | case SQLITE_ROW: |
2468 | 2484 | } |
2469 | 2485 | pseudo_debug(PDBGF_XATTR, "requested xattr named '%s' for ino %lld\n", *value, (long long) msg->ino); |
2470 | 2486 | sqlite3_bind_int(select, 1, msg->dev); |
2471 | sqlite3_bind_int(select, 2, msg->ino); | |
2487 | sqlite3_bind_int64(select, 2, signed_ino(msg->ino)); | |
2472 | 2488 | rc = sqlite3_bind_text(select, 3, *value, -1, SQLITE_STATIC); |
2473 | 2489 | if (rc) { |
2474 | 2490 | dberr(file_db, "couldn't bind xattr name to SELECT."); |
2530 | 2546 | } |
2531 | 2547 | } |
2532 | 2548 | sqlite3_bind_int(select, 1, msg->dev); |
2533 | sqlite3_bind_int(select, 2, msg->ino); | |
2549 | sqlite3_bind_int64(select, 2, signed_ino(msg->ino)); | |
2534 | 2550 | do { |
2535 | 2551 | rc = sqlite3_step(select); |
2536 | 2552 | if (rc == SQLITE_ROW) { |
2584 | 2600 | } |
2585 | 2601 | } |
2586 | 2602 | sqlite3_bind_int(delete, 1, msg->dev); |
2587 | sqlite3_bind_int(delete, 2, msg->ino); | |
2603 | sqlite3_bind_int64(delete, 2, signed_ino(msg->ino)); | |
2588 | 2604 | rc = sqlite3_bind_text(delete, 3, value, len, SQLITE_STATIC); |
2589 | 2605 | if (rc) { |
2590 | 2606 | dberr(file_db, "couldn't bind xattr name to DELETE."); |
2625 | 2641 | } |
2626 | 2642 | } |
2627 | 2643 | sqlite3_bind_int(select, 1, msg->dev); |
2628 | sqlite3_bind_int(select, 2, msg->ino); | |
2644 | sqlite3_bind_int64(select, 2, signed_ino(msg->ino)); | |
2629 | 2645 | rc = sqlite3_bind_text(select, 3, value, -1, SQLITE_STATIC); |
2630 | 2646 | if (rc) { |
2631 | 2647 | dberr(file_db, "couldn't bind xattr name to SELECT."); |
2694 | 2710 | } |
2695 | 2711 | } |
2696 | 2712 | sqlite3_bind_int64(insert, 1, msg->dev); |
2697 | sqlite3_bind_int64(insert, 2, msg->ino); | |
2713 | sqlite3_bind_int64(insert, 2, signed_ino(msg->ino)); | |
2698 | 2714 | rc = sqlite3_bind_text(insert, 3, vname, -1, SQLITE_STATIC); |
2699 | 2715 | if (rc) { |
2700 | 2716 | dberr(file_db, "couldn't bind xattr name to INSERT statement"); |
2740 | 2756 | if (!msg) { |
2741 | 2757 | return 1; |
2742 | 2758 | } |
2743 | sqlite3_bind_int64(select, 1, msg->ino); | |
2759 | sqlite3_bind_int64(select, 1, signed_ino(msg->ino)); | |
2744 | 2760 | rc = sqlite3_step(select); |
2745 | 2761 | switch (rc) { |
2746 | 2762 | case SQLITE_ROW: |
2815 | 2831 | } |
2816 | 2832 | pseudo_debug(PDBGF_DB, "pdb_file: '%s'\n", s ? (const char *) s : "<nil>"); |
2817 | 2833 | m->dev = sqlite3_column_int64(l->stmt, column++); |
2818 | m->ino = sqlite3_column_int64(l->stmt, column++); | |
2834 | m->ino = (ino_t) sqlite3_column_int64(l->stmt, column++); | |
2819 | 2835 | m->uid = sqlite3_column_int64(l->stmt, column++); |
2820 | 2836 | m->gid = sqlite3_column_int64(l->stmt, column++); |
2821 | 2837 | m->mode = sqlite3_column_int64(l->stmt, column++); |
2 | 2 | * |
3 | 3 | * Copyright (c) 2008-2010 Wind River Systems, Inc. |
4 | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify | |
6 | * it under the terms of the Lesser GNU General Public License version 2.1 as | |
7 | * published by the Free Software Foundation. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | |
12 | * See the Lesser GNU General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the Lesser GNU General Public License | |
15 | * version 2.1 along with this program; if not, write to the Free Software | |
16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
5 | * SPDX-License-Identifier: LGPL-2.1-only | |
17 | 6 | * |
18 | 7 | */ |
19 | 8 | typedef struct { |
2 | 2 | * |
3 | 3 | * Copyright (c) 2008-2010 Wind River Systems, Inc. |
4 | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify | |
6 | * it under the terms of the Lesser GNU General Public License version 2.1 as | |
7 | * published by the Free Software Foundation. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | |
12 | * See the Lesser GNU General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the Lesser GNU General Public License | |
15 | * version 2.1 along with this program; if not, write to the Free Software | |
16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
5 | * SPDX-License-Identifier: LGPL-2.1-only | |
17 | 6 | * |
18 | 7 | */ |
19 | 8 | #include <stddef.h> |
25 | 14 | #include <ctype.h> |
26 | 15 | #include <errno.h> |
27 | 16 | #include <sys/stat.h> |
17 | #include <sys/socket.h> | |
28 | 18 | |
29 | 19 | #include "pseudo.h" |
30 | 20 | #include "pseudo_ipc.h" |
31 | 21 | |
32 | /* Short reads or writes can cause a sigpipe, killing the program, so we | |
33 | * trap it and report that something happened. | |
34 | */ | |
22 | /* Short reads or writes can cause a sigpipe, killing the program, so | |
23 | * we trap it and report that something happened. We can avoid the | |
24 | * overhead of setting/restoring the SIGPIPE handler if MSG_NOSIGNAL | |
25 | * is available. | |
26 | */ | |
27 | #ifndef MSG_NOSIGNAL | |
35 | 28 | static sig_atomic_t pipe_error = 0; |
36 | 29 | static void (*old_handler)(int) = SIG_DFL; |
37 | 30 | |
50 | 43 | allow_sigpipe(void) { |
51 | 44 | signal(SIGPIPE, old_handler); |
52 | 45 | } |
46 | #else | |
47 | #define pipe_error 0 | |
48 | #endif | |
53 | 49 | |
54 | 50 | #if 0 |
55 | 51 | /* useful only when debugging crazy stuff */ |
65 | 61 | } |
66 | 62 | #endif |
67 | 63 | |
64 | #ifdef MSG_NOSIGNAL | |
65 | static int | |
66 | do_send(int fd, struct iovec *iov, int iovlen) | |
67 | { | |
68 | struct msghdr hdr; | |
69 | ||
70 | memset(&hdr, 0, sizeof(hdr)); | |
71 | hdr.msg_iov = iov; | |
72 | hdr.msg_iovlen = iovlen; | |
73 | ||
74 | return sendmsg(fd, &hdr, MSG_NOSIGNAL); | |
75 | } | |
76 | #else | |
77 | static int | |
78 | do_send(int fd, struct iovec *iov, int iovlen) | |
79 | { | |
80 | int r, s = 0, i; | |
81 | ||
82 | ignore_sigpipe(); | |
83 | for (i = 0; i < iovlen; ++i) { | |
84 | r = write(fd, iov[i].iov_base, iov[i].iov_len); | |
85 | s += r; | |
86 | if (r != (int)iov[i].iov_len) | |
87 | break; | |
88 | } | |
89 | allow_sigpipe(); | |
90 | return s; | |
91 | } | |
92 | #endif | |
93 | ||
68 | 94 | /* |
69 | 95 | * send message on fd |
70 | 96 | * return: |
74 | 100 | */ |
75 | 101 | int |
76 | 102 | pseudo_msg_send(int fd, pseudo_msg_t *msg, size_t len, const char *path) { |
77 | int r; | |
103 | struct iovec iov[2]; | |
104 | int r, iovc; | |
78 | 105 | |
79 | 106 | if (!msg) |
80 | 107 | return 1; |
88 | 115 | if (len == (size_t) -1) |
89 | 116 | len = strlen(path) + 1; |
90 | 117 | msg->pathlen = len; |
91 | ignore_sigpipe(); | |
92 | r = write(fd, msg, PSEUDO_HEADER_SIZE); | |
93 | if (r == PSEUDO_HEADER_SIZE) { | |
94 | r += write(fd, path, len); | |
95 | } | |
96 | allow_sigpipe(); | |
97 | pseudo_debug(PDBGF_IPC | PDBGF_VERBOSE, "wrote %d bytes\n", r); | |
98 | if (pipe_error || (r == -1 && errno == EBADF)) | |
99 | return -1; | |
100 | return ((size_t) r != PSEUDO_HEADER_SIZE + len); | |
118 | iov[0].iov_base = msg; | |
119 | iov[0].iov_len = PSEUDO_HEADER_SIZE; | |
120 | iov[1].iov_base = (void*)path; | |
121 | iov[1].iov_len = len; | |
122 | iovc = 2; | |
101 | 123 | } else { |
102 | 124 | pseudo_debug(PDBGF_IPC, "msg type %d (%s), result %d (%s), path %.*s, mode 0%o\n", |
103 | 125 | msg->type, pseudo_op_name(msg->op), |
104 | 126 | msg->result, pseudo_res_name(msg->result), |
105 | 127 | msg->pathlen, msg->path, (int) msg->mode); |
106 | 128 | // display_msg_header(msg); |
107 | ignore_sigpipe(); | |
108 | r = write(fd, msg, PSEUDO_HEADER_SIZE + msg->pathlen); | |
109 | allow_sigpipe(); | |
110 | pseudo_debug(PDBGF_IPC | PDBGF_VERBOSE, "wrote %d bytes\n", r); | |
111 | if (pipe_error || (r == -1 && errno == EBADF)) | |
112 | return -1; | |
113 | return ((size_t) r != PSEUDO_HEADER_SIZE + msg->pathlen); | |
114 | } | |
129 | iov[0].iov_base = msg; | |
130 | iov[0].iov_len = PSEUDO_HEADER_SIZE + msg->pathlen; | |
131 | iovc = 1; | |
132 | } | |
133 | r = do_send(fd, iov, iovc); | |
134 | pseudo_debug(PDBGF_IPC | PDBGF_VERBOSE, "wrote %d bytes\n", r); | |
135 | if (pipe_error || (r == -1 && (errno == EBADF || errno == EPIPE))) | |
136 | return -1; | |
137 | return ((size_t) r != PSEUDO_HEADER_SIZE + msg->pathlen); | |
115 | 138 | } |
116 | 139 | |
117 | 140 | /* attempts to receive a message from fd |
2 | 2 | * |
3 | 3 | * Copyright (c) 2008-2010 Wind River Systems, Inc. |
4 | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify | |
6 | * it under the terms of the Lesser GNU General Public License version 2.1 as | |
7 | * published by the Free Software Foundation. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | |
12 | * See the Lesser GNU General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the Lesser GNU General Public License | |
15 | * version 2.1 along with this program; if not, write to the Free Software | |
16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
5 | * SPDX-License-Identifier: LGPL-2.1-only | |
17 | 6 | * |
18 | 7 | */ |
19 | 8 |
0 | /* | |
1 | * SPDX-License-Identifier: LGPL-2.1-only | |
2 | * | |
3 | */ | |
0 | 4 | #define _GNU_SOURCE |
1 | 5 | |
2 | 6 | #include <errno.h> |
2 | 2 | * |
3 | 3 | * Copyright (c) 2008-2010, 2013 Wind River Systems, Inc. |
4 | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify | |
6 | * it under the terms of the Lesser GNU General Public License version 2.1 as | |
7 | * published by the Free Software Foundation. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | |
12 | * See the Lesser GNU General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the Lesser GNU General Public License | |
15 | * version 2.1 along with this program; if not, write to the Free Software | |
16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
5 | * SPDX-License-Identifier: LGPL-2.1-only | |
17 | 6 | * |
18 | 7 | */ |
19 | 8 | #include <stdio.h> |
24 | 13 | |
25 | 14 | #include <unistd.h> |
26 | 15 | #include <fcntl.h> |
16 | #include <sys/ioctl.h> | |
27 | 17 | #include <sys/select.h> |
28 | 18 | #include <sys/time.h> |
29 | 19 | #include <sys/types.h> |
31 | 21 | #include <sys/un.h> |
32 | 22 | #include <sys/stat.h> |
33 | 23 | #include <sys/wait.h> |
24 | #ifdef PSEUDO_EPOLL | |
25 | #include <sys/epoll.h> | |
26 | #endif | |
34 | 27 | #include <signal.h> |
35 | 28 | |
36 | 29 | #include "pseudo.h" |
58 | 51 | |
59 | 52 | #define LOOP_DELAY 2 |
60 | 53 | #define DEFAULT_PSEUDO_SERVER_TIMEOUT 30 |
54 | #define EPOLL_MAX_EVENTS 10 | |
61 | 55 | int pseudo_server_timeout = DEFAULT_PSEUDO_SERVER_TIMEOUT; |
62 | 56 | static int die_peacefully = 0; |
63 | 57 | static int die_forcefully = 0; |
58 | static sig_atomic_t do_list_clients = 0; | |
64 | 59 | |
65 | 60 | /* when the client is linked with pseudo_wrappers, these are defined there. |
66 | 61 | * when it is linked with pseudo_server, though, we have to provide different |
76 | 71 | die_forcefully = 1; |
77 | 72 | } |
78 | 73 | |
74 | static void | |
75 | set_do_list_clients(int sig) { | |
76 | do_list_clients = sig; | |
77 | } | |
78 | ||
79 | 79 | static int messages = 0, responses = 0; |
80 | 80 | static struct timeval message_time = { .tv_sec = 0 }; |
81 | 81 | |
82 | #ifdef PSEUDO_EPOLL | |
83 | static void pseudo_server_loop_epoll(void); | |
84 | #else | |
82 | 85 | static void pseudo_server_loop(void); |
86 | #endif | |
83 | 87 | |
84 | 88 | /* helper function to make a directory, just like mkdir -p. |
85 | 89 | * Can't use system() because the child shell would end up trying |
368 | 372 | kill(ppid, SIGUSR1); |
369 | 373 | } |
370 | 374 | } |
375 | #ifdef PSEUDO_EPOLL | |
376 | pseudo_server_loop_epoll(); | |
377 | #else | |
371 | 378 | pseudo_server_loop(); |
379 | #endif | |
372 | 380 | return 0; |
373 | 381 | } |
374 | 382 | |
375 | 383 | /* mess with internal tables as needed */ |
376 | static void | |
384 | static unsigned int | |
377 | 385 | open_client(int fd) { |
378 | 386 | pseudo_client_t *new_clients; |
379 | 387 | int i; |
389 | 397 | ++active_clients; |
390 | 398 | if (i > highest_client) |
391 | 399 | highest_client = i; |
392 | return; | |
400 | return i; | |
393 | 401 | } |
394 | 402 | } |
395 | 403 | |
413 | 421 | |
414 | 422 | max_clients += 16; |
415 | 423 | ++active_clients; |
424 | return max_clients - 16; | |
416 | 425 | } else { |
417 | 426 | pseudo_diag("error allocating new client, fd %d\n", fd); |
418 | 427 | close(fd); |
428 | return 0; | |
419 | 429 | } |
420 | 430 | } |
421 | 431 | |
451 | 461 | serve_client(int i) { |
452 | 462 | pseudo_msg_t *in; |
453 | 463 | int rc; |
454 | ||
464 | struct timeval tv1, tv2; | |
465 | gettimeofday(&tv1, NULL); | |
466 | ||
467 | ++messages; | |
455 | 468 | pseudo_debug(PDBGF_SERVER, "message from client %d [%d:%s - %s] fd %d\n", |
456 | 469 | i, (int) clients[i].pid, |
457 | 470 | clients[i].program ? clients[i].program : "???", |
461 | 474 | if (in) { |
462 | 475 | char *response_path = 0; |
463 | 476 | size_t response_pathlen; |
464 | int send_response = 1; | |
477 | int send_response = 1; | |
465 | 478 | pseudo_debug(PDBGF_SERVER | PDBGF_VERBOSE, "got a message (%d): %s\n", in->type, (in->pathlen ? in->path : "<no path>")); |
466 | 479 | /* handle incoming ping */ |
467 | 480 | if (in->type == PSEUDO_MSG_PING && !clients[i].pid) { |
488 | 501 | } |
489 | 502 | pseudo_debug(PDBGF_SERVER, "\n"); |
490 | 503 | } |
504 | if (in->type == PSEUDO_MSG_SHUTDOWN && !clients[i].pid) { | |
505 | pseudo_debug(PDBGF_SERVER, "shutdown request from client %d [pid %d]\n", | |
506 | i, in->client); | |
507 | in->client = clients[i].pid; | |
508 | } | |
491 | 509 | /* sanity-check client ID */ |
492 | 510 | if (in->client != clients[i].pid) { |
493 | 511 | pseudo_debug(PDBGF_SERVER, "uh-oh, expected pid %d for client %d, got %d\n", |
497 | 515 | * pseudo_server_response. |
498 | 516 | */ |
499 | 517 | if (in->type != PSEUDO_MSG_SHUTDOWN) { |
500 | if (in->type == PSEUDO_MSG_FASTOP) | |
501 | send_response = 0; | |
502 | 518 | /* most messages don't need these, but xattr may */ |
503 | 519 | response_path = 0; |
504 | 520 | response_pathlen = -1; |
514 | 530 | in->pathlen = response_pathlen; |
515 | 531 | } else { |
516 | 532 | in->pathlen = 0; |
533 | } | |
534 | if (in->type == PSEUDO_MSG_FASTOP) { | |
535 | /* respond instantly */ | |
536 | send_response = 0; | |
537 | int t_type = in->type; | |
538 | int t_pathlen = in->pathlen; | |
539 | in->type = PSEUDO_MSG_ACK; | |
540 | in->pathlen = 0; | |
541 | if ((rc = pseudo_msg_send(clients[i].fd, in, in->pathlen, response_path)) != 0) { | |
542 | pseudo_debug(PDBGF_SERVER, "failed to send response to client %d [%d]: %d (%s)\n", | |
543 | i, (int) clients[i].pid, rc, strerror(errno)); | |
544 | } | |
545 | in->type = t_type; | |
546 | in->pathlen = t_pathlen; | |
517 | 547 | } |
518 | 548 | } else { |
519 | 549 | /* the server's listen fd is "a client", and |
545 | 575 | die_peacefully = 1; |
546 | 576 | } |
547 | 577 | } |
548 | if (send_response) { | |
549 | if ((rc = pseudo_msg_send(clients[i].fd, in, in->pathlen, response_path)) != 0) { | |
550 | pseudo_debug(PDBGF_SERVER, "failed to send response to client %d [%d]: %d (%s)\n", | |
551 | i, (int) clients[i].pid, rc, strerror(errno)); | |
552 | } | |
553 | } else { | |
554 | rc = 1; | |
555 | } | |
578 | if (send_response) { | |
579 | if ((rc = pseudo_msg_send(clients[i].fd, in, in->pathlen, response_path)) != 0) { | |
580 | pseudo_debug(PDBGF_SERVER, "failed to send response to client %d [%d]: %d (%s)\n", | |
581 | i, (int) clients[i].pid, rc, strerror(errno)); | |
582 | } | |
583 | } else { | |
584 | rc = 1; | |
585 | } | |
556 | 586 | free(response_path); |
557 | return rc; | |
558 | 587 | } else { |
559 | 588 | /* this should not be happening, but the exceptions aren't |
560 | 589 | * being detected in select() for some reason. |
561 | 590 | */ |
562 | 591 | pseudo_debug(PDBGF_SERVER, "client %d: no message\n", (int) clients[i].pid); |
563 | 592 | close_client(i); |
564 | return 0; | |
565 | } | |
566 | } | |
567 | ||
568 | /* get clients, handle messages, shut down. | |
569 | * This doesn't actually do any work, it just calls a ton of things which | |
570 | * do work. | |
571 | */ | |
572 | static void | |
573 | pseudo_server_loop(void) { | |
593 | rc = 0; | |
594 | } | |
595 | ||
596 | gettimeofday(&tv2, NULL); | |
597 | if (rc == 0) | |
598 | ++responses; | |
599 | message_time.tv_sec += (tv2.tv_sec - tv1.tv_sec); | |
600 | message_time.tv_usec += (tv2.tv_usec - tv1.tv_usec); | |
601 | if (message_time.tv_usec < 0) { | |
602 | message_time.tv_usec += 1000000; | |
603 | --message_time.tv_sec; | |
604 | } else while (message_time.tv_usec > 1000000) { | |
605 | message_time.tv_usec -= 1000000; | |
606 | ++message_time.tv_sec; | |
607 | } | |
608 | return rc; | |
609 | } | |
610 | ||
611 | #ifdef PSEUDO_EPOLL | |
612 | static void pseudo_server_loop_epoll(void) | |
613 | { | |
574 | 614 | struct sockaddr_un client; |
575 | 615 | socklen_t len; |
576 | fd_set reads, writes, events; | |
577 | int max_fd, current_clients; | |
578 | struct timeval timeout; | |
579 | 616 | int i; |
580 | 617 | int rc; |
581 | 618 | int fd; |
619 | int timeout; | |
620 | struct epoll_event ev, events[EPOLL_MAX_EVENTS]; | |
582 | 621 | int loop_timeout = pseudo_server_timeout; |
622 | struct sigaction eat_usr2 = { | |
623 | .sa_handler = set_do_list_clients | |
624 | }; | |
583 | 625 | |
584 | 626 | clients = malloc(16 * sizeof(*clients)); |
627 | ||
628 | sigaction(SIGUSR2, &eat_usr2, NULL); | |
585 | 629 | |
586 | 630 | clients[0].fd = listen_fd; |
587 | 631 | clients[0].pid = getpid(); |
602 | 646 | pseudo_diag("got into loop with no valid listen fd.\n"); |
603 | 647 | exit(PSEUDO_EXIT_LISTEN_FD); |
604 | 648 | } |
649 | ||
650 | timeout = LOOP_DELAY * 1000; | |
651 | ||
652 | int epollfd = epoll_create1(0); | |
653 | if (epollfd == -1) { | |
654 | pseudo_diag("epoll_create1() failed.\n"); | |
655 | exit(PSEUDO_EXIT_EPOLL_CREATE); | |
656 | } | |
657 | ev.events = EPOLLIN; | |
658 | ev.data.u64 = 0; | |
659 | if (epoll_ctl(epollfd, EPOLL_CTL_ADD, clients[0].fd, &ev) == -1) { | |
660 | pseudo_diag("epoll_ctl() failed with listening socket.\n"); | |
661 | exit(PSEUDO_EXIT_EPOLL_CTL); | |
662 | } | |
663 | ||
605 | 664 | pdb_log_msg(SEVERITY_INFO, NULL, NULL, NULL, "server started (pid %d)", getpid()); |
606 | 665 | |
607 | FD_ZERO(&reads); | |
608 | FD_ZERO(&writes); | |
609 | FD_ZERO(&events); | |
610 | FD_SET(clients[0].fd, &reads); | |
611 | FD_SET(clients[0].fd, &events); | |
612 | max_fd = clients[0].fd; | |
613 | timeout = (struct timeval) { .tv_sec = LOOP_DELAY, .tv_usec = 0 }; | |
614 | ||
615 | /* EINTR tends to come from profiling, so it is not a good reason to | |
616 | * exit; other signals are caught and set the flag causing a graceful | |
617 | * exit. */ | |
618 | while ((rc = select(max_fd + 1, &reads, &writes, &events, &timeout)) >= 0 || (errno == EINTR)) { | |
666 | for (;;) { | |
667 | rc = epoll_wait(epollfd, events, EPOLL_MAX_EVENTS, timeout); | |
619 | 668 | if (rc == 0 || (rc == -1 && errno == EINTR)) { |
620 | 669 | /* If there's no clients, start timing out. If there |
621 | 670 | * are active clients, never time out. |
622 | 671 | */ |
623 | 672 | if (active_clients == 1) { |
624 | 673 | loop_timeout -= LOOP_DELAY; |
625 | /* maybe flush database to disk */ | |
626 | pdb_maybe_backup(); | |
674 | /* maybe flush database to disk */ | |
675 | pdb_maybe_backup(); | |
627 | 676 | if (loop_timeout <= 0) { |
628 | 677 | pseudo_debug(PDBGF_SERVER, "no more clients, got bored.\n"); |
629 | 678 | die_peacefully = 1; |
633 | 682 | messages, |
634 | 683 | (double) message_time.tv_sec + |
635 | 684 | (double) message_time.tv_usec / 1000000.0, |
636 | responses); | |
685 | responses); | |
637 | 686 | } |
638 | 687 | } |
639 | 688 | } else if (rc > 0) { |
640 | 689 | loop_timeout = pseudo_server_timeout; |
641 | for (i = 1; i <= highest_client; ++i) { | |
642 | if (clients[i].fd == -1) | |
643 | continue; | |
644 | if (FD_ISSET(clients[i].fd, &events)) { | |
645 | /* this should happen but doesn't... */ | |
646 | close_client(i); | |
647 | } else if (FD_ISSET(clients[i].fd, &reads)) { | |
648 | struct timeval tv1, tv2; | |
649 | int rc; | |
650 | gettimeofday(&tv1, NULL); | |
651 | rc = serve_client(i); | |
652 | gettimeofday(&tv2, NULL); | |
653 | ++messages; | |
654 | if (rc == 0) | |
655 | ++responses; | |
656 | message_time.tv_sec += (tv2.tv_sec - tv1.tv_sec); | |
657 | message_time.tv_usec += (tv2.tv_usec - tv1.tv_usec); | |
658 | if (message_time.tv_usec < 0) { | |
659 | message_time.tv_usec += 1000000; | |
660 | --message_time.tv_sec; | |
661 | } else while (message_time.tv_usec > 1000000) { | |
662 | message_time.tv_usec -= 1000000; | |
663 | ++message_time.tv_sec; | |
690 | for (i = 0; i < rc; ++i) { | |
691 | int client_id = events[i].data.u64; | |
692 | if (clients[client_id].fd == listen_fd) { | |
693 | if (!die_forcefully) { | |
694 | len = sizeof(client); | |
695 | if ((fd = accept(listen_fd, (struct sockaddr *) &client, &len)) != -1) { | |
696 | /* Don't allow clients to end up on fd 2, because glibc's | |
697 | * malloc debug uses that fd unconditionally. | |
698 | */ | |
699 | if (fd == 2) { | |
700 | int newfd = fcntl(fd, F_DUPFD, 3); | |
701 | close(fd); | |
702 | fd = newfd; | |
703 | } | |
704 | pseudo_debug(PDBGF_SERVER, "new client fd %d\n", fd); | |
705 | /* A new client implicitly cancels any | |
706 | * previous shutdown request, or a | |
707 | * shutdown for lack of clients. | |
708 | */ | |
709 | pseudo_server_timeout = DEFAULT_PSEUDO_SERVER_TIMEOUT; | |
710 | die_peacefully = 0; | |
711 | ||
712 | ev.events = EPOLLIN; | |
713 | ev.data.u64 = open_client(fd); | |
714 | if (ev.data.u64 != 0 && epoll_ctl(epollfd, EPOLL_CTL_ADD, clients[ev.data.u64].fd, &ev) == -1) { | |
715 | pseudo_diag("epoll_ctl() failed with accepted socket.\n"); | |
716 | exit(PSEUDO_EXIT_EPOLL_CTL); | |
717 | } | |
718 | } else if (errno == EMFILE) { | |
719 | // select() loop would drop a client here, we do nothing (for now) | |
720 | pseudo_debug(PDBGF_SERVER, "Hit max open files.\n"); | |
721 | } | |
722 | } | |
723 | } else { | |
724 | int n = 0; | |
725 | ioctl(clients[client_id].fd, FIONREAD, &n); | |
726 | if (n == 0) { | |
727 | close_client(client_id); | |
728 | } else { | |
729 | serve_client(client_id); | |
664 | 730 | } |
665 | 731 | } |
666 | 732 | if (die_forcefully) |
667 | 733 | break; |
668 | 734 | } |
669 | if (!die_forcefully && | |
670 | (FD_ISSET(clients[0].fd, &events) || | |
671 | FD_ISSET(clients[0].fd, &reads))) { | |
672 | len = sizeof(client); | |
673 | if ((fd = accept(listen_fd, (struct sockaddr *) &client, &len)) != -1) { | |
674 | /* Don't allow clients to end up on fd 2, because glibc's | |
675 | * malloc debug uses that fd unconditionally. | |
676 | */ | |
677 | if (fd == 2) { | |
678 | int newfd = fcntl(fd, F_DUPFD, 3); | |
679 | close(fd); | |
680 | fd = newfd; | |
681 | } | |
682 | pseudo_debug(PDBGF_SERVER, "new client fd %d\n", fd); | |
683 | open_client(fd); | |
684 | /* A new client implicitly cancels any | |
685 | * previous shutdown request, or a | |
686 | * shutdown for lack of clients. | |
687 | */ | |
688 | pseudo_server_timeout = DEFAULT_PSEUDO_SERVER_TIMEOUT; | |
689 | die_peacefully = 0; | |
690 | } | |
691 | } | |
692 | 735 | pseudo_debug(PDBGF_SERVER, "server loop complete [%d clients left]\n", active_clients); |
736 | } else { | |
737 | pseudo_diag("epoll_wait failed: %s\n", strerror(errno)); | |
738 | break; | |
739 | } | |
740 | if (do_list_clients) { | |
741 | do_list_clients = 0; | |
742 | pseudo_diag("listing clients [1 through %d]:\n", highest_client); | |
743 | for (i = 1; i <= highest_client; ++i) { | |
744 | if (clients[i].fd == -1) { | |
745 | pseudo_diag("client %4d: inactive.\n", i); | |
746 | continue; | |
747 | } | |
748 | pseudo_diag("client %4d: fd %4d, pid %5d, program %s\n", | |
749 | i, clients[i].fd, clients[i].pid, | |
750 | clients[i].program ? clients[i].program : "<unspecified>"); | |
751 | } | |
752 | pseudo_diag("done.\n"); | |
693 | 753 | } |
694 | 754 | if (die_peacefully || die_forcefully) { |
695 | 755 | pseudo_debug(PDBGF_SERVER, "quitting.\n"); |
708 | 768 | /* usleep(300000); */ |
709 | 769 | exit(0); |
710 | 770 | } |
771 | } | |
772 | ||
773 | } | |
774 | #else | |
775 | ||
776 | /* get clients, handle messages, shut down. | |
777 | * This doesn't actually do any work, it just calls a ton of things which | |
778 | * do work. | |
779 | */ | |
780 | static void | |
781 | pseudo_server_loop(void) { | |
782 | struct sockaddr_un client; | |
783 | socklen_t len; | |
784 | fd_set reads, writes, events; | |
785 | int max_fd, current_clients; | |
786 | struct timeval timeout; | |
787 | int i; | |
788 | int rc; | |
789 | int fd; | |
790 | int loop_timeout = pseudo_server_timeout; | |
791 | struct sigaction eat_usr2 = { | |
792 | .sa_handler = set_do_list_clients | |
793 | }; | |
794 | ||
795 | clients = malloc(16 * sizeof(*clients)); | |
796 | ||
797 | sigaction(SIGUSR2, &eat_usr2, NULL); | |
798 | ||
799 | clients[0].fd = listen_fd; | |
800 | clients[0].pid = getpid(); | |
801 | ||
802 | for (i = 1; i < 16; ++i) { | |
803 | clients[i].fd = -1; | |
804 | clients[i].pid = 0; | |
805 | clients[i].tag = NULL; | |
806 | clients[i].program = NULL; | |
807 | } | |
808 | ||
809 | active_clients = 1; | |
810 | max_clients = 16; | |
811 | highest_client = 0; | |
812 | ||
813 | pseudo_debug(PDBGF_SERVER, "server loop started.\n"); | |
814 | if (listen_fd < 0) { | |
815 | pseudo_diag("got into loop with no valid listen fd.\n"); | |
816 | exit(PSEUDO_EXIT_LISTEN_FD); | |
817 | } | |
818 | pdb_log_msg(SEVERITY_INFO, NULL, NULL, NULL, "server started (pid %d)", getpid()); | |
819 | ||
820 | FD_ZERO(&reads); | |
821 | FD_ZERO(&events); | |
822 | FD_ZERO(&writes); | |
823 | FD_SET(clients[0].fd, &reads); | |
824 | FD_SET(clients[0].fd, &events); | |
825 | max_fd = clients[0].fd; | |
826 | timeout = (struct timeval) { .tv_sec = LOOP_DELAY, .tv_usec = 0 }; | |
827 | ||
828 | /* EINTR tends to come from profiling, so it is not a good reason to | |
829 | * exit; other signals are caught and set the flag causing a graceful | |
830 | * exit. */ | |
831 | sigset_t maskusr2; | |
832 | sigemptyset(&maskusr2); | |
833 | sigaddset(&maskusr2, SIGUSR2); | |
834 | sigprocmask(SIG_BLOCK, &maskusr2, NULL); | |
835 | while ((rc = select(max_fd + 1, &reads, &writes, &events, &timeout)) >= 0 || (errno == EINTR)) { | |
836 | sigprocmask(SIG_UNBLOCK, &maskusr2, NULL); | |
837 | if (rc == 0 || (rc == -1 && errno == EINTR)) { | |
838 | /* If there's no clients, start timing out. If there | |
839 | * are active clients, never time out. | |
840 | */ | |
841 | if (active_clients == 1) { | |
842 | loop_timeout -= LOOP_DELAY; | |
843 | /* maybe flush database to disk */ | |
844 | pdb_maybe_backup(); | |
845 | if (loop_timeout <= 0) { | |
846 | pseudo_debug(PDBGF_SERVER, "no more clients, got bored.\n"); | |
847 | die_peacefully = 1; | |
848 | } else { | |
849 | /* display this if not exiting */ | |
850 | pseudo_debug(PDBGF_SERVER | PDBGF_BENCHMARK, "%d messages handled in %.4f seconds, %d responses\n", | |
851 | messages, | |
852 | (double) message_time.tv_sec + | |
853 | (double) message_time.tv_usec / 1000000.0, | |
854 | responses); | |
855 | } | |
856 | } | |
857 | } else if (rc > 0) { | |
858 | loop_timeout = pseudo_server_timeout; | |
859 | for (i = 1; i <= highest_client; ++i) { | |
860 | if (clients[i].fd == -1) { | |
861 | continue; | |
862 | } else if (FD_ISSET(clients[i].fd, &reads)) { | |
863 | int n = 0; | |
864 | ioctl(clients[i].fd, FIONREAD, &n); | |
865 | if (n == 0) { | |
866 | close_client(i); | |
867 | } else { | |
868 | serve_client(i); | |
869 | } | |
870 | } | |
871 | if (die_forcefully) | |
872 | break; | |
873 | } | |
874 | if (!die_forcefully && | |
875 | (FD_ISSET(clients[0].fd, &events) || | |
876 | FD_ISSET(clients[0].fd, &reads))) { | |
877 | len = sizeof(client); | |
878 | if ((fd = accept(listen_fd, (struct sockaddr *) &client, &len)) != -1) { | |
879 | /* Don't allow clients to end up on fd 2, because glibc's | |
880 | * malloc debug uses that fd unconditionally. | |
881 | */ | |
882 | if (fd == 2) { | |
883 | int newfd = fcntl(fd, F_DUPFD, 3); | |
884 | close(fd); | |
885 | fd = newfd; | |
886 | } | |
887 | pseudo_debug(PDBGF_SERVER, "new client fd %d\n", fd); | |
888 | open_client(fd); | |
889 | /* A new client implicitly cancels any | |
890 | * previous shutdown request, or a | |
891 | * shutdown for lack of clients. | |
892 | */ | |
893 | pseudo_server_timeout = DEFAULT_PSEUDO_SERVER_TIMEOUT; | |
894 | die_peacefully = 0; | |
895 | } | |
896 | } | |
897 | pseudo_debug(PDBGF_SERVER, "server loop complete [%d clients left]\n", active_clients); | |
898 | } | |
899 | if (do_list_clients) { | |
900 | do_list_clients = 0; | |
901 | pseudo_diag("listing clients [1 through %d]:\n", highest_client); | |
902 | for (i = 1; i <= highest_client; ++i) { | |
903 | if (clients[i].fd == -1) { | |
904 | pseudo_diag("client %4d: inactive.\n", i); | |
905 | continue; | |
906 | } | |
907 | pseudo_diag("client %4d: fd %4d, pid %5d, state %s, program %s\n", | |
908 | i, clients[i].fd, clients[i].pid, | |
909 | FD_ISSET(clients[i].fd, &reads) ? "R" : "-", | |
910 | clients[i].program ? clients[i].program : "<unspecified>"); | |
911 | } | |
912 | pseudo_diag("done.\n"); | |
913 | } | |
914 | if (die_peacefully || die_forcefully) { | |
915 | pseudo_debug(PDBGF_SERVER, "quitting.\n"); | |
916 | pseudo_debug(PDBGF_SERVER | PDBGF_BENCHMARK, "server %d exiting: handled %d messages in %.4f seconds\n", | |
917 | getpid(), messages, | |
918 | (double) message_time.tv_sec + | |
919 | (double) message_time.tv_usec / 1000000.0); | |
920 | pdb_log_msg(SEVERITY_INFO, NULL, NULL, NULL, "server %d exiting: handled %d messages in %.4f seconds", | |
921 | getpid(), messages, | |
922 | (double) message_time.tv_sec + | |
923 | (double) message_time.tv_usec / 1000000.0); | |
924 | /* and at this point, we'll start refusing connections */ | |
925 | close(clients[0].fd); | |
926 | /* This is a good place to insert a delay for | |
927 | * debugging race conditions during startup. */ | |
928 | /* usleep(300000); */ | |
929 | exit(0); | |
930 | } | |
711 | 931 | FD_ZERO(&reads); |
712 | 932 | FD_ZERO(&writes); |
713 | 933 | FD_ZERO(&events); |
723 | 943 | if (clients[i].fd != -1) { |
724 | 944 | ++current_clients; |
725 | 945 | FD_SET(clients[i].fd, &reads); |
726 | FD_SET(clients[i].fd, &events); | |
727 | 946 | if (clients[i].fd > max_fd) |
728 | 947 | max_fd = clients[i].fd; |
729 | 948 | } |
734 | 953 | } |
735 | 954 | /* reinitialize timeout because Linux select alters it */ |
736 | 955 | timeout = (struct timeval) { .tv_sec = LOOP_DELAY, .tv_usec = 0 }; |
956 | sigprocmask(SIG_BLOCK, &maskusr2, NULL); | |
737 | 957 | } |
738 | 958 | pseudo_diag("select failed: %s\n", strerror(errno)); |
739 | 959 | } |
960 | #endif /* this is the else of #ifdef PSEUDO_EPOLL */ |
2 | 2 | * |
3 | 3 | * Copyright (c) 2008-2009 Wind River Systems, Inc. |
4 | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify | |
6 | * it under the terms of the Lesser GNU General Public License version 2.1 as | |
7 | * published by the Free Software Foundation. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | |
12 | * See the Lesser GNU General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the Lesser GNU General Public License | |
15 | * version 2.1 along with this program; if not, write to the Free Software | |
16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
5 | * SPDX-License-Identifier: LGPL-2.1-only | |
17 | 6 | * |
18 | 7 | */ |
19 | 8 | extern int pseudo_server_start(int); |
2 | 2 | * |
3 | 3 | * Copyright (c) 2008-2013 Wind River Systems, Inc. |
4 | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify | |
6 | * it under the terms of the Lesser GNU General Public License version 2.1 as | |
7 | * published by the Free Software Foundation. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | |
12 | * See the Lesser GNU General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the Lesser GNU General Public License | |
15 | * version 2.1 along with this program; if not, write to the Free Software | |
16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
5 | * SPDX-License-Identifier: LGPL-2.1-only | |
17 | 6 | * |
18 | 7 | */ |
19 | 8 | /* we need access to RTLD_NEXT for a horrible workaround */ |
264 | 253 | static int debugged_newline = 1; |
265 | 254 | static char pid_text[32]; |
266 | 255 | static size_t pid_len; |
267 | static int pseudo_append_element(char *newpath, char *root, size_t allocated, char **pcurrent, const char *element, size_t elen, int leave_this); | |
268 | static int pseudo_append_elements(char *newpath, char *root, size_t allocated, char **current, const char *elements, size_t elen, int leave_last); | |
256 | static int pseudo_append_element(char *newpath, char *root, size_t allocated, char **pcurrent, const char *element, size_t elen, PSEUDO_STATBUF *buf, int leave_this); | |
257 | static int pseudo_append_elements(char *newpath, char *root, size_t allocated, char **current, const char *elements, size_t elen, int leave_last, PSEUDO_STATBUF *sbuf); | |
269 | 258 | extern char **environ; |
270 | 259 | static ssize_t pseudo_max_pathlen = -1; |
271 | 260 | static ssize_t pseudo_sys_max_pathlen = -1; |
617 | 606 | * the symlink, appending each element in turn the same way. |
618 | 607 | */ |
619 | 608 | static int |
620 | pseudo_append_element(char *newpath, char *root, size_t allocated, char **pcurrent, const char *element, size_t elen, int leave_this) { | |
609 | pseudo_append_element(char *newpath, char *root, size_t allocated, char **pcurrent, const char *element, size_t elen, PSEUDO_STATBUF *buf, int leave_this) { | |
621 | 610 | static int link_recursion = 0; |
622 | 611 | size_t curlen; |
612 | int is_dir = S_ISDIR(buf->st_mode); | |
623 | 613 | char *current; |
624 | PSEUDO_STATBUF buf; | |
625 | 614 | if (!newpath || |
626 | 615 | !pcurrent || !*pcurrent || |
627 | 616 | !root || !element) { |
629 | 618 | return -1; |
630 | 619 | } |
631 | 620 | current = *pcurrent; |
632 | /* sanity-check: ignore // or /./ */ | |
633 | if (elen == 0 || (elen == 1 && *element == '.')) { | |
634 | return 1; | |
635 | } | |
636 | /* backtrack for .. */ | |
637 | if (elen == 2 && element[0] == '.' && element[1] == '.') { | |
638 | /* if newpath's whole contents are '/', do nothing */ | |
639 | if (current <= root + 1) | |
621 | pseudo_debug(PDBGF_PATH | PDBGF_VERBOSE, "pae: '%s', + '%.*s', is_dir %d\n", | |
622 | newpath, (int) elen, element, is_dir); | |
623 | /* the special cases here to skip empty paths, or ./.., should apply | |
624 | * only to directories; plain files, nodes, etcetera should just get | |
625 | * bogus paths. | |
626 | */ | |
627 | if (is_dir) { | |
628 | /* sanity-check: ignore // or /./ */ | |
629 | if (elen == 0 || (elen == 1 && *element == '.')) { | |
630 | return 0; | |
631 | } | |
632 | /* backtrack for .. */ | |
633 | if (elen == 2 && element[0] == '.' && element[1] == '.') { | |
634 | /* if newpath is empty, do nothing. */ | |
635 | if (current <= root) | |
636 | return 0; | |
637 | /* now find the previous slash */ | |
638 | while (current > root && *current != '/') { | |
639 | --current; | |
640 | } | |
641 | /* either we're at root, or we're at a slash. | |
642 | * either way, nul that out, leaving us with a | |
643 | * possibly-empty path which is not slash-terminated. | |
644 | */ | |
645 | *current = '\0'; | |
646 | *pcurrent = current; | |
640 | 647 | return 1; |
641 | /* backtrack to the character before the / */ | |
642 | current -= 2; | |
643 | /* now find the previous slash */ | |
644 | while (current > root && *current != '/') { | |
645 | --current; | |
646 | } | |
647 | /* and point to the nul just past it */ | |
648 | *(++current) = '\0'; | |
649 | *pcurrent = current; | |
650 | return 1; | |
648 | } | |
651 | 649 | } |
652 | 650 | curlen = current - newpath; |
653 | 651 | /* current length, plus / <element> / \0 */ |
656 | 654 | pseudo_diag("pseudo_append_element: path too long (wanted %lu bytes).\n", (unsigned long) curlen + elen + 3); |
657 | 655 | return -1; |
658 | 656 | } |
657 | /* append a slash */ | |
658 | *current++ = '/'; | |
659 | 659 | memcpy(current, element, elen); |
660 | 660 | current += elen; |
661 | /* nul-terminate, and we now point to the nul after the slash */ | |
661 | /* nul-terminate, and we now point to the nul after the element just added. */ | |
662 | 662 | *current = '\0'; |
663 | /* now, the moment of truth... is that a symlink? */ | |
664 | /* if lstat fails, that's fine -- nonexistent files aren't symlinks */ | |
665 | if (!leave_this) { | |
666 | int is_link; | |
667 | is_link = (pseudo_real_lstat) && (pseudo_real_lstat(newpath, &buf) != -1) && S_ISLNK(buf.st_mode); | |
663 | /* if we are not on the last element of a path and supposed to leave | |
664 | * it alone (for SYMLINK_NOFOLLOW type cases), and we are not trying to | |
665 | * go further under a regular file, we want to know whether this is a symlink. | |
666 | * either way, we want to update buf to show the correct state of the file. | |
667 | */ | |
668 | if (!pseudo_real_lstat || (pseudo_real_lstat(newpath, buf) == -1)) { | |
669 | // if we can't stat it, zero mode so we don't think it's | |
670 | // known to be a link or a regular file. | |
671 | buf->st_mode = 0; | |
672 | } | |
673 | /* it is intentional that this uses the "stale" is_dir for the file we | |
674 | * were appending to. we don't want to actually try to do this when | |
675 | * we're appending names to a regular file. | |
676 | */ | |
677 | if (!leave_this && is_dir) { | |
678 | int is_link = S_ISLNK(buf->st_mode); | |
668 | 679 | if (link_recursion >= PSEUDO_MAX_LINK_RECURSION && is_link) { |
669 | 680 | pseudo_diag("link recursion too deep, not expanding path '%s'.\n", newpath); |
670 | 681 | is_link = 0; |
683 | 694 | linkbuf[linklen] = '\0'; |
684 | 695 | /* absolute symlink means start over! */ |
685 | 696 | if (*linkbuf == '/') { |
686 | current = newpath + 1; | |
697 | current = newpath; | |
687 | 698 | } else { |
688 | 699 | /* point back at the end of the previous path... */ |
689 | current -= elen; | |
700 | current -= (elen + 1); | |
690 | 701 | } |
691 | 702 | /* null terminate at the new pointer */ |
692 | 703 | *current = '\0'; |
704 | *pcurrent = current; | |
705 | /* we know that we're now pointing either at a directory we | |
706 | * already decided was safe to go into, or root. either way, | |
707 | * the parent item mode should reflect it being a directory. | |
708 | * we don't need to call stat for that. | |
709 | */ | |
710 | buf->st_mode = S_IFDIR; | |
693 | 711 | /* append all the elements in series */ |
694 | *pcurrent = current; | |
695 | 712 | ++link_recursion; |
696 | retval = pseudo_append_elements(newpath, root, allocated, pcurrent, linkbuf, linklen, 0); | |
713 | retval = pseudo_append_elements(newpath, root, allocated, pcurrent, linkbuf, linklen, 0, buf); | |
697 | 714 | --link_recursion; |
698 | 715 | return retval; |
699 | 716 | } |
700 | 717 | } |
701 | /* okay, not a symlink, go ahead and append a slash */ | |
702 | *(current++) = '/'; | |
703 | *current = '\0'; | |
718 | /* we used to always append a slash here. now we don't; append_elements | |
719 | * handles slashes, so just update the pointer. | |
720 | */ | |
704 | 721 | *pcurrent = current; |
705 | 722 | return 1; |
706 | 723 | } |
707 | 724 | |
708 | 725 | static int |
709 | pseudo_append_elements(char *newpath, char *root, size_t allocated, char **current, const char *element, size_t elen, int leave_last) { | |
726 | pseudo_append_elements(char *newpath, char *root, size_t allocated, char **current, const char *path, size_t elen, int leave_last, PSEUDO_STATBUF *sbuf) { | |
710 | 727 | int retval = 1; |
711 | const char * start = element; | |
728 | /* a shareable buffer so we can cache stat results while walking the path */ | |
729 | PSEUDO_STATBUF buf; | |
730 | buf.st_mode = 0; | |
731 | const char * start = path; | |
712 | 732 | if (!newpath || !root || |
713 | 733 | !current || !*current || |
714 | !element) { | |
734 | !path) { | |
715 | 735 | pseudo_diag("pseudo_append_elements: invalid arguments."); |
716 | 736 | return -1; |
717 | 737 | } |
718 | while (element < (start + elen) && *element) { | |
738 | if (!sbuf) { | |
739 | /* we will use this buffer to hold "the current state of newpath". | |
740 | * append_element will update that whenever it appends an element, | |
741 | * and any calls back here from there will pass in the same buffer. | |
742 | * if we didn't get one, we start using this local one, which will | |
743 | * then get shared by anything we call. | |
744 | */ | |
745 | sbuf = &buf; | |
746 | if (*current > root) { | |
747 | if (!pseudo_real_lstat || (pseudo_real_lstat(newpath, sbuf) == -1)) { | |
748 | sbuf->st_mode = 0; | |
749 | } | |
750 | } else { | |
751 | /* Don't call lstat on an empty path, or at all when we | |
752 | * know that "root" is always directory-like. | |
753 | */ | |
754 | sbuf->st_mode = S_IFDIR; | |
755 | } | |
756 | } | |
757 | pseudo_debug(PDBGF_PATH | PDBGF_VERBOSE, "paes: newpath %s, element list <%.*s>\n", | |
758 | newpath, (int) elen, path); | |
759 | while (path < (start + elen) && *path) { | |
719 | 760 | size_t this_elen; |
720 | 761 | int leave_this = 0; |
721 | char *next = strchr(element, '/'); | |
762 | char *next = strchr(path, '/'); | |
722 | 763 | if (!next) { |
723 | next = strchr(element, '\0'); | |
764 | next = strchr(path, '\0'); | |
724 | 765 | leave_this = leave_last; |
725 | 766 | } |
726 | this_elen = next - element; | |
727 | switch (this_elen) { | |
728 | case 0: /* path => '/' */ | |
767 | this_elen = next - path; | |
768 | /* for a directory, we skip the append for empty path or "."; | |
769 | * regular files get it appended so they can fail properly | |
770 | * later for being invalid paths. | |
771 | */ | |
772 | pseudo_debug(PDBGF_PATH | PDBGF_VERBOSE, "element to add: '%.*s'\n", | |
773 | (int) this_elen, path); | |
774 | if (pseudo_append_element(newpath, root, allocated, current, path, this_elen, sbuf, leave_this) == -1) { | |
775 | retval = -1; | |
729 | 776 | break; |
730 | case 1: /* path => '?/' */ | |
731 | if (*element != '.') { | |
732 | if (pseudo_append_element(newpath, root, allocated, current, element, this_elen, leave_this) == -1) { | |
733 | retval = -1; | |
734 | } | |
735 | } | |
736 | break; | |
737 | default: | |
738 | if (pseudo_append_element(newpath, root, allocated, current, element, this_elen, leave_this) == -1) { | |
739 | retval = -1; | |
740 | } | |
741 | break; | |
742 | } | |
777 | } | |
778 | pseudo_debug(PDBGF_FILE | PDBGF_VERBOSE, "paes: append_element gave us '%s', current '%s'\n", | |
779 | newpath, *current); | |
743 | 780 | /* and now move past the separator */ |
744 | element += this_elen + 1; | |
781 | path += this_elen + 1; | |
745 | 782 | } |
746 | 783 | return retval; |
747 | 784 | } |
777 | 814 | newpath = pathbufs[pathbuf]; |
778 | 815 | pathbuf = (pathbuf + 1) % PATHBUFS; |
779 | 816 | pathlen = strlen(path); |
780 | /* a trailing slash has special meaning */ | |
781 | if (pathlen > 0 && path[pathlen - 1] == '/') { | |
817 | /* a trailing slash has special meaning, but processing | |
818 | * trailing slashes is expensive. | |
819 | */ | |
820 | while (pathlen > 0 && path[pathlen - 1] == '/') { | |
782 | 821 | trailing_slash = 1; |
822 | --pathlen; | |
783 | 823 | } |
784 | 824 | /* allow a bit of slush. overallocating a bit won't |
785 | 825 | * hurt. rounding to 256's in the hopes that it makes life |
799 | 839 | * part of the string; you can't back up over it. |
800 | 840 | */ |
801 | 841 | effective_root = newpath + rootlen; |
802 | *current++ = '/'; | |
803 | 842 | *current = '\0'; |
804 | 843 | /* at any given point: |
805 | * current points to just after the last / of newpath | |
844 | * path is not slash-terminated | |
845 | * current points to the null byte immediately after the path | |
806 | 846 | * path points to the next element of path |
807 | 847 | * newpathlen is the total allocated length of newpath |
808 | 848 | * (current - newpath) is the used length of newpath |
809 | 849 | */ |
810 | if (pseudo_append_elements(newpath, effective_root, newpathlen, ¤t, path, pathlen, leave_last) != -1) { | |
811 | --current; | |
812 | if (*current == '/' && current > effective_root && !trailing_slash) { | |
813 | *current = '\0'; | |
850 | int save_errno = errno; | |
851 | if (pseudo_append_elements(newpath, effective_root, newpathlen, ¤t, path, pathlen, leave_last, 0) != -1) { | |
852 | /* if we are expecting a trailing slash, or the path ended up being completely | |
853 | * empty (meaning it's pointing at either effective_root or the beginning of | |
854 | * the path), we need a slash here. | |
855 | */ | |
856 | if ((current == effective_root) || trailing_slash) { | |
857 | if ((current - newpath) < (int) newpathlen) { | |
858 | *current++ = '/'; | |
859 | *current = '\0'; | |
860 | } | |
814 | 861 | } |
815 | 862 | pseudo_debug(PDBGF_PATH, "%s + %s => <%s>\n", |
816 | 863 | base ? base : "<nil>", |
819 | 866 | if (lenp) { |
820 | 867 | *lenp = current - newpath; |
821 | 868 | } |
869 | errno = save_errno; | |
822 | 870 | return newpath; |
823 | 871 | } else { |
872 | errno = save_errno; | |
824 | 873 | return 0; |
825 | 874 | } |
826 | 875 | } |
843 | 892 | if (ld_preload && strlen(ld_preload)) { |
844 | 893 | SETENV(PRELINK_LIBRARIES, ld_preload, 1); |
845 | 894 | } else { |
846 | UNSETENV(PRELINK_LIBRARIES); | |
895 | SETENV(PRELINK_LIBRARIES, "", 1); | |
847 | 896 | } |
848 | 897 | } |
849 | 898 | } |
1565 | 1614 | pseudo_util_debug_fd = fd; |
1566 | 1615 | } |
1567 | 1616 | free(pseudo_path); |
1568 | if (fd == -1) | |
1569 | return -1; | |
1570 | else | |
1571 | return fd; | |
1617 | return fd; | |
1572 | 1618 | } |
1573 | 1619 | |
1574 | 1620 | int |
2 | 2 | * |
3 | 3 | * Copyright (c) 2008-2012 Wind River Systems, Inc. |
4 | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify | |
6 | * it under the terms of the Lesser GNU General Public License version 2.1 as | |
7 | * published by the Free Software Foundation. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | |
12 | * See the Lesser GNU General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the Lesser GNU General Public License | |
15 | * version 2.1 along with this program; if not, write to the Free Software | |
16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
5 | * SPDX-License-Identifier: LGPL-2.1-only | |
17 | 6 | * |
18 | 7 | */ |
19 | 8 | #include <assert.h> |
36 | 25 | #include <sys/wait.h> |
37 | 26 | #include <dlfcn.h> |
38 | 27 | |
28 | /* include this to get PSEUDO_PORT_* definitions */ | |
29 | #include "pseudo.h" | |
30 | ||
39 | 31 | /* used for various specific function arguments */ |
40 | 32 | #include <dirent.h> |
41 | 33 | #include <fts.h> |
44 | 36 | #include <grp.h> |
45 | 37 | #include <pwd.h> |
46 | 38 | #include <utime.h> |
47 | ||
48 | #include "pseudo.h" | |
39 | #ifdef PSEUDO_PORT_LINUX_STATVFS | |
40 | #include <sys/statvfs.h> | |
41 | #endif | |
42 | ||
49 | 43 | #include "pseudo_wrapfuncs.h" |
50 | 44 | #include "pseudo_ipc.h" |
51 | 45 | #include "pseudo_client.h" |
46 | ||
52 | 47 | |
53 | 48 | /* Types and declarations we need in advance. */ |
54 | 49 | #include "pseudo_wrapper_table.c" |
97 | 92 | extern int (*pseudo_real_fsetxattr)(int, const char *, const void *, size_t, int); |
98 | 93 | #endif |
99 | 94 | |
95 | static void libpseudo_atfork_child(void) | |
96 | { | |
97 | pthread_mutex_init(&pseudo_mutex, NULL); | |
98 | pseudo_mutex_recursion = 0; | |
99 | pseudo_mutex_holder = 0; | |
100 | } | |
101 | ||
100 | 102 | static void |
101 | 103 | _libpseudo_init(void) { |
104 | if (!_libpseudo_initted) | |
105 | pthread_atfork(NULL, NULL, libpseudo_atfork_child); | |
106 | ||
102 | 107 | pseudo_getlock(); |
103 | 108 | pseudo_antimagic(); |
104 | 109 | _libpseudo_initted = 1; |
120 | 125 | pseudo_init_one_wrapper(pseudo_function *func) { |
121 | 126 | int (*f)(void) = (int (*)(void)) NULL; |
122 | 127 | |
123 | char *e; | |
124 | 128 | if (*func->real != NULL) { |
125 | 129 | /* already initialized */ |
126 | 130 | return; |
136 | 140 | f = dlsym(RTLD_NEXT, func->name); |
137 | 141 | if (f) { |
138 | 142 | *func->real = f; |
139 | } else { | |
140 | #ifdef PSEUDO_NO_REAL_AT_FUNCTIONS | |
141 | char *s = func->name; | |
142 | s += strlen(s) - 2; | |
143 | /* *at() don't have to exist */ | |
144 | if (!strcmp(s, "at")) { | |
145 | return; | |
146 | } | |
147 | #endif | |
148 | e = dlerror(); | |
149 | if (e != NULL) { | |
150 | pseudo_diag("No real function for %s: %s\n", func->name, e); | |
151 | } else { | |
152 | pseudo_diag("No real function for %s, but dlerror NULL.\n", func->name); | |
153 | } | |
154 | } | |
143 | } | |
144 | /* it turns out that in some cases, we get apparently-harmless | |
145 | * errors if a function is missing, and that printing output | |
146 | * for these seems unhelpful. so we no longer do that. | |
147 | */ | |
155 | 148 | } |
156 | 149 | |
157 | 150 | void |
2 | 2 | * |
3 | 3 | * Copyright (c) 2008-2010 Wind River Systems, Inc. |
4 | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify | |
6 | * it under the terms of the Lesser GNU General Public License version 2.1 as | |
7 | * published by the Free Software Foundation. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | |
12 | * See the Lesser GNU General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the Lesser GNU General Public License | |
15 | * version 2.1 along with this program; if not, write to the Free Software | |
16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
5 | * SPDX-License-Identifier: LGPL-2.1-only | |
17 | 6 | * |
18 | 7 | */ |
19 | 8 | #include <stdio.h> |
15 | 15 | .\" version 2.1 along with this program; if not, write to the Free Software |
16 | 16 | .\" Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
17 | 17 | .TH pseudolog 1 "pseudo - pretending to be root" |
18 | .SH NAME | |
19 | pseudolog \- pseudo log parser | |
18 | 20 | .SH SYNOPSIS |
19 | 21 | .B pseudolog \-l |
20 | 22 | .RB [ \-Pv ] |
2 | 2 | * |
3 | 3 | * Copyright (c) 2008-2010 Wind River Systems, Inc. |
4 | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify | |
6 | * it under the terms of the Lesser GNU General Public License version 2.1 as | |
7 | * published by the Free Software Foundation. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | |
12 | * See the Lesser GNU General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the Lesser GNU General Public License | |
15 | * version 2.1 along with this program; if not, write to the Free Software | |
16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
5 | * SPDX-License-Identifier: LGPL-2.1-only | |
17 | 6 | * |
18 | 7 | */ |
19 | 8 | /* We need _XOPEN_SOURCE for strptime(), but if we define that, |
0 | # | |
1 | # SPDX-License-Identifier: LGPL-2.1-only | |
2 | # | |
3 | ||
0 | 4 | from string import Template |
1 | 5 | import os |
2 | 6 | |
78 | 82 | return |
79 | 83 | path = Template(self.path).safe_substitute(item) |
80 | 84 | if os.path.exists(path): |
81 | # print "We don't overwrite existing files." | |
85 | # print("We don't overwrite existing files.") | |
82 | 86 | return |
83 | 87 | self.file = open(path, 'w') |
84 | 88 | if not self.file: |
85 | print "Couldn't open '%s' (expanded from %s), " \ | |
89 | print("Couldn't open '%s' (expanded from %s), " \ | |
86 | 90 | "not emitting '%s'." % \ |
87 | (path, self.path, template) | |
91 | (path, self.path, template)) | |
88 | 92 | return |
89 | 93 | |
90 | 94 | def emit(self, template, item=None): |
102 | 106 | self.file.write(templ.safe_substitute(item)) |
103 | 107 | self.file.write("\n") |
104 | 108 | else: |
105 | print "Warning: Unknown template '%s'." % template | |
109 | print("Warning: Unknown template '%s'." % template) | |
106 | 110 | |
107 | 111 | if self.file_per_item: |
108 | 112 | if self.file: |
1 | 1 | @header |
2 | 2 | @body |
3 | 3 | /* |
4 | * Copyright (c) ${date} Wind River Systems; see | |
4 | * Copyright (c) ${date} Peter Seebach/Seebs <seebs@seebs.net>; see | |
5 | 5 | * guts/COPYRIGHT for information. |
6 | * | |
7 | * [Note: copyright added by code generator, may be | |
8 | * incorrect. Remove this if you fix it.] | |
9 | * | |
10 | * SPDX-License-Identifier: LGPL-2.1-only | |
6 | 11 | * |
7 | 12 | * ${comment} |
8 | 13 | * ${rc_decl} |
0 | 0 | #!/bin/bash |
1 | # | |
2 | # SPDX-License-Identifier: LGPL-2.1-only | |
3 | # | |
1 | 4 | |
2 | 5 | # Return vals: 2 - invalid arg list |
3 | 6 | # 1 - chroot failed |
0 | #!/bin/bash | |
1 | # | |
2 | # SPDX-License-Identifier: LGPL-2.1-only | |
3 | # | |
4 | set -e | |
5 | ||
6 | # Verify that special bits (setuid/setgid/sticky) are preserved. | |
7 | # | |
8 | # Return vals: | |
9 | # | |
10 | # 2 - Incorrect permissions | |
11 | # All other nonzero - Unexpected command error | |
12 | # 0 - Pass | |
13 | ||
14 | trap "rm -rf d1 d2" EXIT | |
15 | ||
16 | mkdir d1 | |
17 | chmod 7777 d1 | |
18 | cp -Rp d1 d2 | |
19 | perms=`ls -od d1 d2 | cut -c 1-10 | uniq` | |
20 | if [ "$perms" != drwsrwsrwt ]; then | |
21 | exit 2 | |
22 | fi | |
23 | ||
24 | ||
25 | exit 0 |
0 | 0 | #!/bin/bash |
1 | # | |
2 | # SPDX-License-Identifier: LGPL-2.1-only | |
3 | # | |
1 | 4 | mkdir d1 |
2 | 5 | touch d1/f1 |
3 | 6 | mv d1 d2 |
0 | 0 | #!/bin/bash |
1 | # | |
2 | # SPDX-License-Identifier: LGPL-2.1-only | |
3 | # | |
1 | 4 | |
2 | 5 | env -i A=A B=B C=C env | grep -q "PSEUDO_" |
3 | 6 |
0 | 0 | #!/bin/bash |
1 | # | |
2 | # SPDX-License-Identifier: LGPL-2.1-only | |
3 | # | |
1 | 4 | cat > execl_test.c << EOF |
2 | 5 | #include <unistd.h> |
3 | 6 | int main() { |
0 | 0 | #!/bin/bash |
1 | # | |
2 | # SPDX-License-Identifier: LGPL-2.1-only | |
3 | # | |
1 | 4 | |
2 | 5 | # Verify normal operation... |
3 | 6 | uid=`env -i id -u` |
0 | 0 | #!/bin/bash |
1 | # | |
2 | # SPDX-License-Identifier: LGPL-2.1-only | |
3 | # | |
1 | 4 | |
2 | 5 | # Verify normal operation... |
3 | 6 | uid=`id -u` |
0 | 0 | #!/bin/bash |
1 | # | |
2 | # SPDX-License-Identifier: LGPL-2.1-only | |
3 | # | |
1 | 4 | |
2 | 5 | # Verify normal operation... |
3 | 6 | uid=`env -i id -u` |
0 | 0 | #!/bin/bash |
1 | # | |
2 | # SPDX-License-Identifier: LGPL-2.1-only | |
3 | # | |
1 | 4 | |
2 | 5 | # Verify normal operation... |
3 | 6 | uid=`id -u` |
0 | 0 | #!/bin/bash |
1 | # | |
2 | # SPDX-License-Identifier: LGPL-2.1-only | |
3 | # | |
1 | 4 | |
2 | 5 | # Test if we re-invoke pseudo that chroot still works |
3 | 6 |
0 | #!/bin/bash | |
1 | # | |
2 | # SPDX-License-Identifier: LGPL-2.1-only | |
3 | # | |
4 | ||
5 | # Check that tclsh doesn't hang. Note that the timeout is not needed to | |
6 | # reproduce the hang in tclsh, it's only there to ensure that this test script | |
7 | # doesn't hang in case of a failing test. | |
8 | timeout 2s bash -c "echo 'open {|true} r+' | tclsh" |