Skip to content

Commit 1ba220b

Browse files
authored
Merge pull request #1102 from ingve/posixstubs
posix: pwd-related functions
2 parents bae5b87 + a6c4ec9 commit 1ba220b

6 files changed

Lines changed: 206 additions & 0 deletions

File tree

src/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ set(OS_OBJECTS
5353
posix/sys/socket.cpp posix/sys/select.cpp posix/sys/utsname.cpp posix/sys/mman.cpp posix/arpa/inet.cpp
5454
posix/ucontext.cpp posix/ucontext_asm.asm
5555
posix/sys/stat.cpp posix/ftw.cpp posix/file_fd.cpp posix/dlfcn.cpp
56+
posix/pwd.cpp
5657
)
5758

5859
add_library(os STATIC ${OS_OBJECTS} apic_boot.o)

src/posix/pwd.cpp

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
// This file is a part of the IncludeOS unikernel - www.includeos.org
2+
//
3+
// Copyright 2015-2017 Oslo and Akershus University College of Applied Sciences
4+
// and Alfred Bratterud
5+
//
6+
// Licensed under the Apache License, Version 2.0 (the "License");
7+
// you may not use this file except in compliance with the License.
8+
// You may obtain a copy of the License at
9+
//
10+
// http://www.apache.org/licenses/LICENSE-2.0
11+
//
12+
// Unless required by applicable law or agreed to in writing, software
13+
// distributed under the License is distributed on an "AS IS" BASIS,
14+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
// See the License for the specific language governing permissions and
16+
// limitations under the License.
17+
18+
#include <string>
19+
#include <vector>
20+
#include <fstream>
21+
#include <pwd.h>
22+
#include <info>
23+
#include <gsl/gsl_assert>
24+
25+
const char* pwd_path = "/etc/passwd";
26+
27+
/* Applications are not allowed to modify the structure to which the return
28+
values point, nor any storage areas pointed to by pointers within the
29+
structure. Returned pointers might be invalidated or the structure/
30+
storage areas might be overwritten by subsequent calls. */
31+
static struct passwd ret;
32+
33+
class Pwd {
34+
public:
35+
static Pwd& instance() {
36+
static Pwd pwd;
37+
return pwd;
38+
}
39+
40+
void rewind() {pos_ = 0;}
41+
42+
void close() {open_ = false;}
43+
44+
struct passwd* find(const char* name) {
45+
Expects(name != nullptr);
46+
if (!open_) {
47+
read();
48+
}
49+
const auto it = std::find_if(begin(entries_), end(entries_), [name](const auto& entry){
50+
return (strcmp(name, entry.c_str()) == 0);
51+
});
52+
if (it == end(entries_)) {
53+
return nullptr;
54+
}
55+
extract(*it);
56+
return &ret;
57+
}
58+
59+
struct passwd* next() noexcept {
60+
if (!open_) {
61+
read();
62+
}
63+
if (pos_ >= entries_.size()) {
64+
return nullptr;
65+
}
66+
try {
67+
const auto& ent = entries_[pos_];
68+
int field_seps = std::count(std::begin(ent), std::end(ent), '\0');
69+
if (field_seps != 6) {
70+
INFO("pwd", "not a valid passwd file entry");
71+
return nullptr;
72+
}
73+
extract(ent);
74+
++pos_;
75+
return &ret;
76+
}
77+
catch (...) {
78+
INFO("pwd", "error parsing pwd entry");
79+
return nullptr;
80+
}
81+
}
82+
83+
void extract(const std::string& ent) {
84+
ret.pw_name = const_cast<char*>(ent.c_str());
85+
size_t pw_pos = ent.find('\0') + 1;
86+
size_t uid_pos = ent.find('\0', pw_pos) + 1;
87+
size_t gid_pos = ent.find('\0', uid_pos) + 1;
88+
size_t info_pos = ent.find('\0', gid_pos) + 1;
89+
size_t dir_pos = ent.find('\0', info_pos) + 1;
90+
size_t shell_pos = ent.find('\0', dir_pos) + 1;
91+
ret.pw_uid = std::stol(ret.pw_name + uid_pos);
92+
ret.pw_gid = std::stol(ret.pw_name + gid_pos);
93+
ret.pw_dir = ret.pw_name + dir_pos;
94+
ret.pw_shell = ret.pw_name + shell_pos;
95+
}
96+
97+
void print() {
98+
printf(" instance @%p\n", this);
99+
printf(" open: %d\n", open_);
100+
printf(" pos: %d\n", pos_);
101+
printf(" entries: %d\n", entries_.size());
102+
}
103+
104+
private:
105+
Pwd() : open_ {false}, pos_ {0} {}
106+
107+
void read() {
108+
std::ifstream is(pwd_path);
109+
std::string line;
110+
while (std::getline(is, line)) {
111+
std::replace(std::begin(line), std::end(line), ':', '\0');
112+
entries_.push_back(line);
113+
}
114+
rewind();
115+
open_ = true;
116+
}
117+
bool open_;
118+
size_t pos_;
119+
std::vector<std::string> entries_;
120+
};
121+
122+
void endpwent(void) {
123+
Pwd& pwd = Pwd::instance();
124+
pwd.close();
125+
}
126+
127+
void setpwent(void) {
128+
Pwd& pwd = Pwd::instance();
129+
pwd.rewind();
130+
}
131+
132+
struct passwd *getpwent(void) {
133+
Pwd& pwd = Pwd::instance();
134+
return pwd.next();
135+
}
136+
137+
struct passwd *getpwnam(const char *name) {
138+
if (name == nullptr) {
139+
return nullptr;
140+
}
141+
Pwd& pwd = Pwd::instance();
142+
return pwd.find(name);
143+
}

test/posix/integration/conf/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ set(SOURCES
2424
service.cpp
2525
test_sysconf.c
2626
test_pathconf.c
27+
test_pwd.c
2728
)
2829

2930
# DRIVERS / PLUGINS:
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,5 @@
1+
nobody:*:-2:-2:Unprivileged User:/var/empty:/usr/bin/false
12
root:*:0:0:System Administrator:/var/root:/bin/sh
3+
daemon:*:1:1:System Services:/var/root:/usr/bin/false
4+
_ftp:*:98:-2:FTP Daemon:/var/empty:/usr/bin/false
5+
_launchservicesd:*:239:239:_launchservicesd:/var/empty:/usr/bin/false

test/posix/integration/conf/service.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
extern "C" void test_sysconf();
2929
extern "C" void test_pathconf();
30+
extern "C" void test_pwd();
3031

3132
fs::Disk_ptr& memdisk() {
3233
static auto disk = fs::new_shared_memdisk();
@@ -74,5 +75,8 @@ int main(int argc, char *argv[]) {
7475
value = getenv("INCLUDEOS_CORE_DUMP");
7576
printf("INCLUDEOS_CORE_DUMP: %s\n", value);
7677

78+
// test pwd-related functions
79+
test_pwd();
80+
7781
INFO("Conf", "SUCCESS");
7882
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// This file is a part of the IncludeOS unikernel - www.includeos.org
2+
//
3+
// Copyright 2015-2017 Oslo and Akershus University College of Applied Sciences
4+
// and Alfred Bratterud
5+
//
6+
// Licensed under the Apache License, Version 2.0 (the "License");
7+
// you may not use this file except in compliance with the License.
8+
// You may obtain a copy of the License at
9+
//
10+
// http://www.apache.org/licenses/LICENSE-2.0
11+
//
12+
// Unless required by applicable law or agreed to in writing, software
13+
// distributed under the License is distributed on an "AS IS" BASIS,
14+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
// See the License for the specific language governing permissions and
16+
// limitations under the License.
17+
18+
#include <pwd.h>
19+
#include <stdio.h>
20+
21+
void print_pwd_entry(struct passwd* pwd_ent);
22+
23+
void test_pwd() {
24+
struct passwd* pwd_ent;
25+
26+
while((pwd_ent = getpwent()) != NULL) {
27+
print_pwd_entry(pwd_ent);
28+
}
29+
30+
printf("Back to start!\n");
31+
setpwent();
32+
pwd_ent = getpwent();
33+
print_pwd_entry(pwd_ent);
34+
endpwent();
35+
36+
pwd_ent = getpwnam("root");
37+
if (pwd_ent != NULL) {
38+
print_pwd_entry(pwd_ent);
39+
}
40+
41+
pwd_ent = getpwnam("alfred");
42+
if (pwd_ent != NULL) {
43+
print_pwd_entry(pwd_ent);
44+
}
45+
}
46+
47+
void print_pwd_entry(struct passwd* pwd_ent) {
48+
printf("Name: %s\n", pwd_ent->pw_name);
49+
printf("Uid: %d\n", pwd_ent->pw_uid);
50+
printf("Gid: %d\n", pwd_ent->pw_gid);
51+
printf("Path: %s\n", pwd_ent->pw_dir);
52+
printf("Shell: %s\n\n", pwd_ent->pw_shell);
53+
}

0 commit comments

Comments
 (0)