Serenity Operating System
1/*
2 * Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#include <LibTest/TestCase.h>
8
9#include <AK/Vector.h>
10#include <pwd.h>
11
12struct PasswdEntry {
13 DeprecatedString name;
14 uid_t uid {};
15};
16
17static Vector<PasswdEntry> get_all_passwd_entries()
18{
19 Vector<PasswdEntry> entries;
20 setpwent();
21 while (auto* pwd = getpwent()) {
22 entries.append(PasswdEntry {
23 .name = pwd->pw_name,
24 .uid = pwd->pw_uid,
25 });
26 }
27 return entries;
28}
29
30TEST_CASE(getpwuid_r)
31{
32 // Verify that all known passwd entries can be found with getpwuid_r()
33 for (auto const& entry : get_all_passwd_entries()) {
34 struct passwd pwd_buffer = {};
35 char buffer[4096] = {};
36 struct passwd* result = nullptr;
37 auto rc = getpwuid_r(entry.uid, &pwd_buffer, buffer, sizeof(buffer), &result);
38 EXPECT_EQ(rc, 0);
39 EXPECT_EQ(entry.uid, result->pw_uid);
40 EXPECT_EQ(entry.name, result->pw_name);
41 }
42
43 // Verify that a bogus UID can't be found with getpwuid_r()
44 {
45 struct passwd pwd_buffer = {};
46 char buffer[4096] = {};
47 struct passwd* result = nullptr;
48 auto rc = getpwuid_r(99991999, &pwd_buffer, buffer, sizeof(buffer), &result);
49 EXPECT_EQ(rc, ENOENT);
50 EXPECT_EQ(result, nullptr);
51 }
52
53 // Verify that two calls to getpwuid_r() don't clobber each other.
54 {
55 struct passwd pwd_buffer1 = {};
56 char buffer1[4096] = {};
57 struct passwd* result1 = nullptr;
58 auto rc1 = getpwuid_r(0, &pwd_buffer1, buffer1, sizeof(buffer1), &result1);
59 EXPECT_EQ(rc1, 0);
60 EXPECT_NE(result1, nullptr);
61 EXPECT_EQ(result1, &pwd_buffer1);
62
63 struct passwd pwd_buffer2 = {};
64 char buffer2[4096] = {};
65 struct passwd* result2 = nullptr;
66 auto rc2 = getpwuid_r(0, &pwd_buffer2, buffer2, sizeof(buffer2), &result2);
67 EXPECT_EQ(rc2, 0);
68 EXPECT_NE(result2, nullptr);
69 EXPECT_EQ(result2, &pwd_buffer2);
70
71 EXPECT_NE(result1, result2);
72 }
73}
74
75TEST_CASE(getpwnam_r)
76{
77 // Verify that all known passwd entries can be found with getpwnam_r()
78 for (auto const& entry : get_all_passwd_entries()) {
79 struct passwd pwd_buffer = {};
80 char buffer[4096] = {};
81 struct passwd* result = nullptr;
82 auto rc = getpwnam_r(entry.name.characters(), &pwd_buffer, buffer, sizeof(buffer), &result);
83 EXPECT_EQ(rc, 0);
84 EXPECT_EQ(entry.uid, result->pw_uid);
85 EXPECT_EQ(entry.name, result->pw_name);
86 }
87
88 // Verify that a bogus name can't be found with getpwnam_r()
89 {
90 struct passwd pwd_buffer = {};
91 char buffer[4096] = {};
92 struct passwd* result = nullptr;
93 auto rc = getpwnam_r("99991999", &pwd_buffer, buffer, sizeof(buffer), &result);
94 EXPECT_EQ(rc, ENOENT);
95 EXPECT_EQ(result, nullptr);
96 }
97
98 // Verify that two calls to getpwnam_r() don't clobber each other.
99 {
100 struct passwd pwd_buffer1 = {};
101 char buffer1[4096] = {};
102 struct passwd* result1 = nullptr;
103 auto rc1 = getpwnam_r("root", &pwd_buffer1, buffer1, sizeof(buffer1), &result1);
104 EXPECT_EQ(rc1, 0);
105 EXPECT_NE(result1, nullptr);
106 EXPECT_EQ(result1, &pwd_buffer1);
107
108 struct passwd pwd_buffer2 = {};
109 char buffer2[4096] = {};
110 struct passwd* result2 = nullptr;
111 auto rc2 = getpwnam_r("root", &pwd_buffer2, buffer2, sizeof(buffer2), &result2);
112 EXPECT_EQ(rc2, 0);
113 EXPECT_NE(result2, nullptr);
114 EXPECT_EQ(result2, &pwd_buffer2);
115
116 EXPECT_NE(result1, result2);
117 }
118}