Merge "Remove unused include"
diff --git a/docs/status.md b/docs/status.md
index 5d2603a..3d104e4 100644
--- a/docs/status.md
+++ b/docs/status.md
@@ -59,6 +59,9 @@
* `close_range` and `copy_file_range` (Linux-specific GNU extensions).
* `memset_explicit` in <string.h> (C23 addition).
* `__freadahead` in <stdio_ext.h> (in musl but not glibc).
+ * `posix_spawn_file_actions_addchdir_np` and
+ `posix_spawn_file_actions_addfchdir_np` in <spawn.h> (in musl/glibc
+ and macOS, but not iOS).
New libc behavior in U (API level 34):
* Support for `%b` and `%B` in the printf/wprintf family, `%b` in the
diff --git a/libc/NOTICE b/libc/NOTICE
index 9d55592..4d3a108 100644
--- a/libc/NOTICE
+++ b/libc/NOTICE
@@ -894,6 +894,34 @@
-------------------------------------------------------------------
+Copyright (C) 2023 The Android Open Source Project
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
+
+-------------------------------------------------------------------
+
Copyright (c) 1980, 1983, 1988, 1993
The Regents of the University of California. All rights reserved.
diff --git a/libc/bionic/spawn.cpp b/libc/bionic/spawn.cpp
index 5cf95d8..5d76f77 100644
--- a/libc/bionic/spawn.cpp
+++ b/libc/bionic/spawn.cpp
@@ -68,7 +68,9 @@
enum Action {
kOpen,
kClose,
- kDup2
+ kDup2,
+ kChdir,
+ kFchdir,
};
struct __posix_spawn_file_action {
@@ -93,6 +95,10 @@
} else if (what == kClose) {
// Failure to close is ignored.
close(fd);
+ } else if (what == kChdir) {
+ if (chdir(path) == -1) _exit(127);
+ } else if (what == kFchdir) {
+ if (fchdir(fd) == -1) _exit(127);
} else {
// It's a dup2.
if (fd == new_fd) {
@@ -340,7 +346,7 @@
if (action == nullptr) return errno;
action->next = nullptr;
- if (what == kOpen) {
+ if (what == kOpen || what == kChdir) {
action->path = strdup(path);
if (action->path == nullptr) {
free(action);
@@ -380,3 +386,12 @@
if (fd < 0 || new_fd < 0) return EBADF;
return posix_spawn_add_file_action(actions, kDup2, fd, new_fd, nullptr, 0, 0);
}
+
+int posix_spawn_file_actions_addchdir_np(posix_spawn_file_actions_t* actions, const char* path) {
+ return posix_spawn_add_file_action(actions, kChdir, -1, -1, path, 0, 0);
+}
+
+int posix_spawn_file_actions_addfchdir_np(posix_spawn_file_actions_t* actions, int fd) {
+ if (fd < 0) return EBADF;
+ return posix_spawn_add_file_action(actions, kFchdir, fd, -1, nullptr, 0, 0);
+}
diff --git a/libc/include/spawn.h b/libc/include/spawn.h
index 8bb34d0..6c34b98 100644
--- a/libc/include/spawn.h
+++ b/libc/include/spawn.h
@@ -87,6 +87,9 @@
int posix_spawn_file_actions_addclose(posix_spawn_file_actions_t _Nonnull * _Nonnull __actions, int __fd) __INTRODUCED_IN(28);
int posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t _Nonnull * _Nonnull __actions, int __fd, int __new_fd) __INTRODUCED_IN(28);
+int posix_spawn_file_actions_addchdir_np(posix_spawn_file_actions_t _Nonnull * _Nonnull __actions, const char* _Nonnull __path) __INTRODUCED_IN(34);
+int posix_spawn_file_actions_addfchdir_np(posix_spawn_file_actions_t _Nonnull * _Nonnull __actions, int __fd) __INTRODUCED_IN(34);
+
__END_DECLS
#endif
diff --git a/libc/include/utmp.h b/libc/include/utmp.h
index 7aa5718..d249f8a 100644
--- a/libc/include/utmp.h
+++ b/libc/include/utmp.h
@@ -30,7 +30,7 @@
/**
* @file utmp.h
- * @brief POSIX login records.
+ * @brief No-op implementation of non-POSIX login records. See <utmpx.h> for the POSIX equivalents.
*/
#include <sys/cdefs.h>
@@ -69,12 +69,12 @@
};
struct exit_status {
- short int e_termination;
- short int e_exit;
+ short e_termination;
+ short e_exit;
};
struct utmp {
- short int ut_type;
+ short ut_type;
pid_t ut_pid;
char ut_line[UT_LINESIZE];
char ut_id[4];
@@ -83,7 +83,7 @@
struct exit_status ut_exit;
- long int ut_session;
+ long ut_session;
struct timeval ut_tv;
int32_t ut_addr_v6[4];
@@ -97,21 +97,25 @@
__BEGIN_DECLS
/**
- * Does nothing.
+ * Returns -1 and sets errno to ENOTSUP.
*/
int utmpname(const char* _Nonnull __path);
+
/**
* Does nothing.
*/
void setutent(void);
+
/**
- * Does nothing.
+ * Does nothing and returns null.
*/
struct utmp* _Nullable getutent(void);
+
/**
- * Does nothing.
+ * Does nothing and returns null.
*/
struct utmp* _Nullable pututline(const struct utmp* _Nonnull __entry);
+
/**
* Does nothing.
*/
diff --git a/libc/include/utmpx.h b/libc/include/utmpx.h
new file mode 100644
index 0000000..5ed8e1a
--- /dev/null
+++ b/libc/include/utmpx.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#pragma once
+
+/**
+ * @file utmpx.h
+ * @brief No-op implementation of POSIX login records.
+ */
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <time.h>
+
+#define EMPTY 0
+#define RUN_LVL 1
+#define BOOT_TIME 2
+#define NEW_TIME 3
+#define OLD_TIME 4
+#define INIT_PROCESS 5
+#define LOGIN_PROCESS 6
+#define USER_PROCESS 7
+#define DEAD_PROCESS 8
+#define ACCOUNTING 9
+
+struct utmpx {
+ short ut_type;
+ pid_t ut_pid;
+ char ut_line[32];
+ char ut_id[4];
+ char ut_user[32];
+ char ut_host[256];
+
+ struct {
+ short e_termination;
+ short e_exit;
+ } ut_exit;
+
+ long ut_session;
+ struct timeval ut_tv;
+
+ int32_t ut_addr_v6[4];
+ char unused[20];
+};
+
+__BEGIN_DECLS
+
+/**
+ * Does nothing.
+ */
+void setutxent(void) __RENAME(setutent);
+
+/**
+ * Does nothing and returns null.
+ */
+struct utmpx* _Nullable getutxent(void) __RENAME(getutent);
+
+/**
+ * Does nothing and returns null.
+ */
+struct utmpx* _Nullable getutxid(const struct utmpx* _Nonnull __entry) __RENAME(getutent);
+
+/**
+ * Does nothing and returns null.
+ */
+struct utmpx* _Nullable getutxline(const struct utmpx* _Nonnull __entry) __RENAME(getutent);
+
+/**
+ * Does nothing and returns null.
+ */
+struct utmpx* _Nullable pututxline(const struct utmpx* _Nonnull __entry) __RENAME(pututline);
+
+/**
+ * Does nothing.
+ */
+void endutxent(void) __RENAME(endutent);
+
+__END_DECLS
diff --git a/libc/libc.map.txt b/libc/libc.map.txt
index 4a4e607..c75b13a 100644
--- a/libc/libc.map.txt
+++ b/libc/libc.map.txt
@@ -1580,6 +1580,8 @@
close_range;
copy_file_range;
memset_explicit;
+ posix_spawn_file_actions_addchdir_np;
+ posix_spawn_file_actions_addfchdir_np;
} LIBC_T;
LIBC_PRIVATE {
diff --git a/tests/Android.bp b/tests/Android.bp
index 6d2a8d4..1949079 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -514,6 +514,7 @@
"unistd_test.cpp",
"utils.cpp",
"utmp_test.cpp",
+ "utmpx_test.cpp",
"wchar_test.cpp",
"wctype_test.cpp",
],
diff --git a/tests/NOTICE b/tests/NOTICE
index 167f90b..cc99d20 100644
--- a/tests/NOTICE
+++ b/tests/NOTICE
@@ -426,3 +426,31 @@
-------------------------------------------------------------------
+Copyright (C) 2023 The Android Open Source Project
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
+
+-------------------------------------------------------------------
+
diff --git a/tests/headers/posix/utmpx_h.c b/tests/headers/posix/utmpx_h.c
new file mode 100644
index 0000000..44dfac9
--- /dev/null
+++ b/tests/headers/posix/utmpx_h.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <utmpx.h>
+
+#include "header_checks.h"
+
+static void utmpx_h() {
+ TYPE(struct utmpx);
+ STRUCT_MEMBER_ARRAY(struct utmpx, char/*[]*/, ut_user);
+ STRUCT_MEMBER_ARRAY(struct utmpx, char/*[]*/, ut_id);
+ STRUCT_MEMBER_ARRAY(struct utmpx, char/*[]*/, ut_line);
+ STRUCT_MEMBER(struct utmpx, pid_t, ut_pid);
+ STRUCT_MEMBER(struct utmpx, short, ut_type);
+#if !defined(__GLIBC__)
+ // POSIX says struct timeval, but glibc has an anonymous struct.
+ STRUCT_MEMBER(struct utmpx, struct timeval, ut_tv);
+#endif
+
+ TYPE(pid_t);
+ TYPE(struct timeval);
+
+ MACRO(EMPTY);
+ MACRO(BOOT_TIME);
+ MACRO(OLD_TIME);
+ MACRO(NEW_TIME);
+ MACRO(USER_PROCESS);
+ MACRO(INIT_PROCESS);
+ MACRO(LOGIN_PROCESS);
+ MACRO(DEAD_PROCESS);
+
+ FUNCTION(endutxent, void (*f)(void));
+ FUNCTION(getutxent, struct utmpx* (*f)(void));
+ FUNCTION(getutxid, struct utmpx* (*f)(const struct utmpx*));
+ FUNCTION(getutxline, struct utmpx* (*f)(const struct utmpx*));
+ FUNCTION(pututxline, struct utmpx* (*f)(const struct utmpx*));
+ FUNCTION(setutxent, void (*f)(void));
+}
diff --git a/tests/spawn_test.cpp b/tests/spawn_test.cpp
index a9563b8..ab3e877 100644
--- a/tests/spawn_test.cpp
+++ b/tests/spawn_test.cpp
@@ -232,18 +232,28 @@
}
TEST(spawn, posix_spawn_file_actions) {
+#if !defined(__GLIBC__)
int fds[2];
ASSERT_NE(-1, pipe(fds));
posix_spawn_file_actions_t fa;
ASSERT_EQ(0, posix_spawn_file_actions_init(&fa));
+ // Test addclose and adddup2 by redirecting output to the pipe created above.
ASSERT_EQ(0, posix_spawn_file_actions_addclose(&fa, fds[0]));
ASSERT_EQ(0, posix_spawn_file_actions_adddup2(&fa, fds[1], 1));
ASSERT_EQ(0, posix_spawn_file_actions_addclose(&fa, fds[1]));
// Check that close(2) failures are ignored by closing the same fd again.
ASSERT_EQ(0, posix_spawn_file_actions_addclose(&fa, fds[1]));
+ // Open a file directly, to test addopen.
ASSERT_EQ(0, posix_spawn_file_actions_addopen(&fa, 56, "/proc/version", O_RDONLY, 0));
+ // Test addfchdir by opening the same file a second way...
+ ASSERT_EQ(0, posix_spawn_file_actions_addopen(&fa, 57, "/proc", O_PATH, 0));
+ ASSERT_EQ(0, posix_spawn_file_actions_addfchdir_np(&fa, 57));
+ ASSERT_EQ(0, posix_spawn_file_actions_addopen(&fa, 58, "version", O_RDONLY, 0));
+ // Test addchdir by opening the same file a third way...
+ ASSERT_EQ(0, posix_spawn_file_actions_addchdir_np(&fa, "/"));
+ ASSERT_EQ(0, posix_spawn_file_actions_addopen(&fa, 59, "proc/version", O_RDONLY, 0));
ExecTestHelper eth;
eth.SetArgs({"ls", "-l", "/proc/self/fd", nullptr});
@@ -259,12 +269,21 @@
AssertChildExited(pid, 0);
// We'll know the dup2 worked if we see any ls(1) output in our pipe.
- // The open we can check manually...
+ // The opens we can check manually (and they implicitly check the chdirs)...
bool open_to_fd_56_worked = false;
+ bool open_to_fd_58_worked = false;
+ bool open_to_fd_59_worked = false;
for (const auto& line : android::base::Split(content, "\n")) {
if (line.find(" 56 -> /proc/version") != std::string::npos) open_to_fd_56_worked = true;
+ if (line.find(" 58 -> /proc/version") != std::string::npos) open_to_fd_58_worked = true;
+ if (line.find(" 59 -> /proc/version") != std::string::npos) open_to_fd_59_worked = true;
}
- ASSERT_TRUE(open_to_fd_56_worked);
+ ASSERT_TRUE(open_to_fd_56_worked) << content;
+ ASSERT_TRUE(open_to_fd_58_worked) << content;
+ ASSERT_TRUE(open_to_fd_59_worked) << content;
+#else
+ GTEST_SKIP() << "our old glibc doesn't have the chdirs; newer versions and musl do.";
+#endif
}
static void CatFileToString(posix_spawnattr_t* sa, const char* path, std::string* content) {
diff --git a/tests/utmp_test.cpp b/tests/utmp_test.cpp
index b024818..459f9c3 100644
--- a/tests/utmp_test.cpp
+++ b/tests/utmp_test.cpp
@@ -25,6 +25,7 @@
}
TEST(utmp, smoke) {
+ // The rest of <utmp.h> is just no-op implementations, so testing is trivial.
ASSERT_EQ(-1, utmpname("hello"));
setutent();
ASSERT_EQ(NULL, getutent());
diff --git a/tests/utmpx_test.cpp b/tests/utmpx_test.cpp
new file mode 100644
index 0000000..55427a6
--- /dev/null
+++ b/tests/utmpx_test.cpp
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <gtest/gtest.h>
+
+#include <utmpx.h>
+
+TEST(utmpx, smoke) {
+ // Our utmpx "implementation" just calls the utmp no-op functions.
+ setutxent();
+ utmpx empty = {.ut_type = EMPTY};
+ ASSERT_EQ(NULL, getutxent());
+ ASSERT_EQ(NULL, getutxid(&empty));
+ ASSERT_EQ(NULL, getutxline(&empty));
+ endutxent();
+ ASSERT_EQ(NULL, pututxline(&empty));
+}