diff options
Diffstat (limited to 'lib/mlibc/options/posix/generic/grp-stubs.cpp')
-rw-r--r-- | lib/mlibc/options/posix/generic/grp-stubs.cpp | 316 |
1 files changed, 0 insertions, 316 deletions
diff --git a/lib/mlibc/options/posix/generic/grp-stubs.cpp b/lib/mlibc/options/posix/generic/grp-stubs.cpp deleted file mode 100644 index f8b2813..0000000 --- a/lib/mlibc/options/posix/generic/grp-stubs.cpp +++ /dev/null @@ -1,316 +0,0 @@ - -#include <grp.h> -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <bits/ensure.h> - -#include <mlibc/debug.hpp> -#include <mlibc/posix-sysdeps.hpp> - -namespace { - FILE *global_file; - - bool open_global_file() { - if(!global_file) { - global_file = fopen("/etc/group", "r"); - if(!global_file) { - errno = EIO; - return false; - } - } - - return true; - } - - void close_global_file() { - if(global_file) { - fclose(global_file); - global_file = nullptr; - } - } - - template<typename F> - void walk_segments(frg::string_view line, char delimiter, F fn) { - size_t s = 0; - while(true) { - size_t d = line.find_first(delimiter, s); - if(d == size_t(-1)) - break; - auto chunk = line.sub_string(s, d - s); - fn(chunk); - s = d + 1; - } - if(line[s]) { - auto chunk = line.sub_string(s, line.size() - s); - - if (chunk.size() > 0) { - // Remove trailing newline - if (chunk[chunk.size() - 1] == '\n') - chunk = chunk.sub_string(0, chunk.size() - 1); - - fn(chunk); - } - } - } - - bool extract_entry(frg::string_view line, group *entry) { - frg::string_view segments[5]; - - // Parse the line into 3 or 4 segments (depending if the group has members or not) - int n = 0; - walk_segments(line, ':', [&] (frg::string_view s) { - __ensure(n < 4); - segments[n++] = s; - }); - - if(n < 3) // n can be 3 when there are no members in the group - return false; - - // TODO: Handle strndup() and malloc() failure. - auto name = strndup(segments[0].data(), segments[0].size()); - __ensure(name); - - auto passwd = strndup(segments[1].data(), segments[1].size()); - - auto gid = segments[2].to_number<int>(); - if(!gid) - return false; - - size_t n_members = 0; - walk_segments(segments[3], ',', [&] (frg::string_view) { - n_members++; - }); - - auto members = reinterpret_cast<char **>(malloc(sizeof(char *) * (n_members + 1))); - __ensure(members); - size_t k = 0; - walk_segments(segments[3], ',', [&] (frg::string_view m) { - members[k] = strndup(m.data(), m.size()); - __ensure(members[k]); - k++; - }); - members[k] = nullptr; - - entry->gr_name = name; - entry->gr_passwd = passwd; - entry->gr_gid = *gid; - entry->gr_mem = members; - return true; - } - - void clear_entry(group *entry) { - free(entry->gr_name); - if(entry->gr_mem) { - for(size_t i = 0; entry->gr_mem[i]; i++) - free(entry->gr_mem[i]); - free(entry->gr_mem); - } - entry->gr_name = nullptr; - entry->gr_mem = nullptr; - } - - template<typename C> - int walk_file(struct group *entry, C cond) { - auto file = fopen("/etc/group", "r"); - if(!file) { - return EIO; - } - - char line[512]; - while(fgets(line, 512, file)) { - if(!extract_entry(line, entry)) - continue; - if(cond(entry)) { - fclose(file); - return 0; - } - } - - int err = ESRCH; - if(ferror(file)) { - err = EIO; - } - - fclose(file); - return err; - } - - int copy_to_buffer(struct group *grp, char *buffer, size_t size) { - // Adjust to correct alignment so that we can put gr_mem first in buffer - uintptr_t mask = sizeof(char *) - 1; - size_t offset = (reinterpret_cast<uintptr_t>(buffer) % sizeof(char *) + mask) & ~mask; - if (size < offset) - return ERANGE; - - buffer += offset; - size -= offset; - - // Calculate the amount of space we need - size_t nmemb, required_size = 0; - for (nmemb = 0; grp->gr_mem[nmemb] != nullptr; nmemb++) { - // One for the string's null terminator and one for the pointer in gr_mem - required_size += strlen(grp->gr_mem[nmemb]) + 1 + sizeof(char *); - } - - // One for null terminator of gr_name, plus sizeof(char *) for nullptr terminator of gr_mem - required_size += strlen(grp->gr_name) + 1 + sizeof(char *); - if (size < required_size) - return ERANGE; - - // Put the gr_mem array first in the buffer as we are guaranteed - // that the pointer is aligned correctly - char *string_data = buffer + (nmemb + 1) * sizeof(char *); - - for (size_t i = 0; i < nmemb; i++) { - reinterpret_cast<char **>(buffer)[i] = string_data; - string_data = stpcpy(string_data, grp->gr_mem[i]) + 1; - free(grp->gr_mem[i]); - } - - reinterpret_cast<char **>(buffer)[nmemb] = nullptr; - free(grp->gr_mem); - grp->gr_mem = reinterpret_cast<char **>(buffer); - - char *gr_name = stpcpy(string_data, grp->gr_name) + 1; - free(grp->gr_name); - grp->gr_name = string_data; - - __ensure(gr_name <= buffer + size); - return 0; - } -} - -void endgrent(void) { - close_global_file(); -} - -struct group *getgrent(void) { - static group entry; - char line[512]; - - if(!open_global_file()) { - return nullptr; - } - - if(fgets(line, 512, global_file)) { - clear_entry(&entry); - if(!extract_entry(line, &entry)) { - errno = EINVAL; - return nullptr; - } - return &entry; - } - - if(ferror(global_file)) { - errno = EIO; - } - - return nullptr; -} - -struct group *getgrgid(gid_t gid) { - static group entry; - - int err = walk_file(&entry, [&] (group *entry) { - return entry->gr_gid == gid; - }); - - if (err) { - errno = err; - return nullptr; - } - - return &entry; -} - -int getgrgid_r(gid_t gid, struct group *grp, char *buffer, size_t size, struct group **result) { - *result = nullptr; - int err = walk_file(grp, [&] (group *entry) { - return entry->gr_gid == gid; - }); - - if (err) { - return err; - } - - err = copy_to_buffer(grp, buffer, size); - if (err) { - return err; - } - - *result = grp; - return 0; -} - -struct group *getgrnam(const char *name) { - static group entry; - - int err = walk_file(&entry, [&] (group *entry) { - return !strcmp(entry->gr_name, name); - }); - - if (err) { - errno = err; - return nullptr; - } - - return &entry; -} - -int getgrnam_r(const char *name, struct group *grp, char *buffer, size_t size, struct group **result) { - *result = nullptr; - - int err = walk_file(grp, [&] (group *entry) { - return !strcmp(entry->gr_name, name); - }); - - if (err) { - return err; - } - - err = copy_to_buffer(grp, buffer, size); - if (err) { - return err; - } - - *result = grp; - return 0; -} - -void setgrent(void) { - if(!open_global_file()) { - return; - } - rewind(global_file); -} - -int setgroups(size_t size, const gid_t *list) { - MLIBC_CHECK_OR_ENOSYS(mlibc::sys_setgroups, -1); - if(int e = mlibc::sys_setgroups(size, list); e) { - errno = e; - return -1; - } - return 0; -} - -int initgroups(const char *, gid_t) { - mlibc::infoLogger() << "mlibc: initgroups is a stub" << frg::endlog; - return 0; -} - -int putgrent(const struct group *, FILE *) { - __ensure(!"Not implemented"); - __builtin_unreachable(); -} - -struct group *fgetgrent(FILE *) { - __ensure(!"Not implemented"); - __builtin_unreachable(); -} - -int getgrouplist(const char *, gid_t, gid_t *, int *) { - mlibc::infoLogger() << "mlibc: getgrouplist is a stub" << frg::endlog; - return 0; -} |