116 lines · cpp
1// RUN: %clangxx %s -o %t && %run %t2 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(result->pw_name);22 Check(result->pw_passwd);23 assert(result->pw_uid != N);24 assert(result->pw_gid != N);25#if !defined(__ANDROID__)26 Check(result->pw_gecos);27#endif28 Check(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#endif35 36#if defined(__FreeBSD__)37 assert(result->pw_fields != N);38#endif39 40 // SunOS also has pw_age and pw_comment which are documented as unused.41}42 43void Check(const group *result) {44 Check(result->gr_name);45 Check(result->gr_passwd);46 assert(result->gr_gid != N);47 for (char **mem = result->gr_mem; *mem; ++mem)48 Check(*mem);49 if (!any_group) {50 auto length = strlen(result->gr_name);51 any_group.reset(new char[length + 1]);52 memcpy(any_group.get(), result->gr_name, 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>(&getpwuid, 0);74 test<passwd>(&getpwnam, "root");75 test<group>(&getgrgid, 0);76 test<group>(&getgrnam, any_group.get());77 78#if !defined(__ANDROID__)79 setpwent();80 test<passwd>(&getpwent);81 setgrent();82 test<group>(&getgrent);83 84#if !defined(__APPLE__) && !(defined(__sun__) && defined(__svr4__))85 setpwent();86 test_r<passwd>(&getpwent_r);87 setgrent();88 test_r<group>(&getgrent_r);89#endif90 91 test_r<passwd>(&getpwuid_r, 0);92 test_r<passwd>(&getpwnam_r, "root");93 94 test_r<group>(&getgrgid_r, 0);95 test_r<group>(&getgrnam_r, any_group.get());96 97#if defined(__linux__)98 auto pwd_file = [] {99 return std::unique_ptr<FILE, decltype(&fclose)>(fopen("/etc/passwd", "r"),100 &fclose);101 };102 auto gr_file = [] {103 return std::unique_ptr<FILE, decltype(&fclose)>(fopen("/etc/group", "r"),104 &fclose);105 };106 test<passwd>(&fgetpwent, pwd_file().get());107 test<group>(&fgetgrent, gr_file().get());108 test_r<passwd>(&fgetpwent_r, pwd_file().get());109 test_r<group>(&fgetgrent_r, gr_file().get());110#endif111 112#endif // __ANDROID__113 114 return 0;115}116