1// RUN: %clangxx %s -o %t && %run %t
2
3#include <assert.h>
4#include <grp.h>
5#include <memory>
6#include <pwd.h>
7#include <stdio.h>
8#include <stdlib.h>
9#include <string.h>
10
11std::unique_ptr<char []> any_group;
12const int N = 123456;
13
14void Check(const char *str) {
15 if (!str)
16 return;
17 assert(strlen(str) != N);
18}
19
20void Check(const passwd *result) {
21 Check(str: result->pw_name);
22 Check(str: result->pw_passwd);
23 assert(result->pw_uid != N);
24 assert(result->pw_gid != N);
25#if !defined(__ANDROID__)
26 Check(str: result->pw_gecos);
27#endif
28 Check(str: result->pw_dir);
29
30#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
31 assert(result->pw_change != N);
32 Check(result->pw_class);
33 assert(result->pw_expire != N);
34#endif
35
36#if defined(__FreeBSD__)
37 assert(result->pw_fields != N);
38#endif
39
40 // SunOS also has pw_age and pw_comment which are documented as unused.
41}
42
43void Check(const group *result) {
44 Check(str: result->gr_name);
45 Check(str: result->gr_passwd);
46 assert(result->gr_gid != N);
47 for (char **mem = result->gr_mem; *mem; ++mem)
48 Check(str: *mem);
49 if (!any_group) {
50 auto length = strlen(s: result->gr_name);
51 any_group.reset(p: new char[length + 1]);
52 memcpy(dest: any_group.get(), src: result->gr_name, n: length + 1);
53 }
54}
55
56template <class T, class Fn, class... Args>
57void test(Fn f, Args... args) {
58 T *result = f(args...);
59 Check(result);
60}
61
62template <class T, class Fn, class... Args>
63void test_r(Fn f, Args... args) {
64 T gr;
65 T *result;
66 char buff[10000];
67 assert(!f(args..., &gr, buff, sizeof(buff), &result));
68 Check(&gr);
69 Check(result);
70}
71
72int main(int argc, const char *argv[]) {
73 test<passwd>(f: &getpwuid, args: 0);
74 test<passwd>(f: &getpwnam, args: "root");
75 test<group>(f: &getgrgid, args: 0);
76 test<group>(f: &getgrnam, args: any_group.get());
77
78#if !defined(__ANDROID__)
79 setpwent();
80 test<passwd>(f: &getpwent);
81 setgrent();
82 test<group>(f: &getgrent);
83
84#if !defined(__APPLE__) && !(defined(__sun__) && defined(__svr4__))
85 setpwent();
86 test_r<passwd>(f: &getpwent_r);
87 setgrent();
88 test_r<group>(f: &getgrent_r);
89#endif
90
91 test_r<passwd>(f: &getpwuid_r, args: 0);
92 test_r<passwd>(f: &getpwnam_r, args: "root");
93
94 test_r<group>(f: &getgrgid_r, args: 0);
95 test_r<group>(f: &getgrnam_r, args: any_group.get());
96
97#if defined(__linux__)
98 auto pwd_file = [] {
99 return std::unique_ptr<FILE, decltype(&fclose)>(fopen(filename: "/etc/passwd", modes: "r"),
100 &fclose);
101 };
102 auto gr_file = [] {
103 return std::unique_ptr<FILE, decltype(&fclose)>(fopen(filename: "/etc/group", modes: "r"),
104 &fclose);
105 };
106 test<passwd>(f: &fgetpwent, args: pwd_file().get());
107 test<group>(f: &fgetgrent, args: gr_file().get());
108 test_r<passwd>(f: &fgetpwent_r, args: pwd_file().get());
109 test_r<group>(f: &fgetgrent_r, args: gr_file().get());
110#endif
111
112#endif // __ANDROID__
113
114 return 0;
115}
116

source code of compiler-rt/test/sanitizer_common/TestCases/Posix/getpw_getgr.cpp