Compare commits

...

3 Commits

5 changed files with 174 additions and 7 deletions

View File

@ -61,7 +61,7 @@ namespace BAN
return result;
}
ErrorOr<Vector<StringView>> StringView::split(char delim, bool allow_empties)
ErrorOr<Vector<StringView>> StringView::split(char delim, bool allow_empties) const
{
size_type count = 0;
{
@ -92,12 +92,12 @@ namespace BAN
start = i + 1;
}
}
if (start != m_size)
if (start < m_size || (start == m_size && allow_empties))
TRY(result.push_back(this->substring(start)));
return result;
}
ErrorOr<Vector<StringView>> StringView::split(bool(*comp)(char), bool allow_empties)
ErrorOr<Vector<StringView>> StringView::split(bool(*comp)(char), bool allow_empties) const
{
size_type count = 0;
{
@ -128,7 +128,7 @@ namespace BAN
start = i + 1;
}
}
if (start != m_size)
if (start < m_size || (start == m_size && allow_empties))
TRY(result.push_back(this->substring(start)));
return result;
}

View File

@ -30,8 +30,8 @@ namespace BAN
StringView substring(size_type, size_type = -1) const;
ErrorOr<Vector<StringView>> split(char, bool = false);
ErrorOr<Vector<StringView>> split(bool(*comp)(char), bool = false);
ErrorOr<Vector<StringView>> split(char, bool = false) const;
ErrorOr<Vector<StringView>> split(bool(*comp)(char), bool = false) const;
char back() const;
char front() const;

View File

@ -7,6 +7,7 @@ set(LIBC_SOURCES
ctype.cpp
dirent.cpp
fcntl.cpp
grp.cpp
malloc.cpp
printf_impl.cpp
pwd.cpp

162
libc/grp.cpp Normal file
View File

@ -0,0 +1,162 @@
#include <BAN/StringView.h>
#include <BAN/Vector.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <grp.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/types.h>
static struct stat s_group_st;
static char* s_group_mmap = nullptr;
static int s_group_fd = -1;
static struct group s_group;
id_t parse_id(BAN::StringView string)
{
id_t id = 0;
for (char c : string)
{
if (!isdigit(c))
return -1;
id = (id * 10) + (c - '0');
}
return id;
}
static bool open_group_file()
{
if (s_group_fd == -1)
s_group_fd = open("/etc/group", O_RDONLY);
if (s_group_fd == -1)
return false;
if (fstat(s_group_fd, &s_group_st) == -1)
return false;
if (s_group_mmap == nullptr || s_group_mmap == MAP_FAILED)
s_group_mmap = (char*)mmap(nullptr, s_group_st.st_size, PROT_READ, MAP_PRIVATE, s_group_fd, 0);
if (s_group_mmap == MAP_FAILED)
return false;
s_group.gr_name = nullptr;
s_group.gr_mem = nullptr;
return true;
}
struct group* fill_group(const BAN::Vector<BAN::StringView>& parts)
{
if (parts.size() != 4)
return nullptr;
if (s_group.gr_name)
{
free(s_group.gr_name);
s_group.gr_name = nullptr;
}
if (s_group.gr_mem)
{
for (size_t i = 0; s_group.gr_mem && s_group.gr_mem[i]; i++)
free(s_group.gr_mem[i]);
free(s_group.gr_mem);
s_group.gr_mem = nullptr;
}
auto groups_or_error = parts[3].split(',');
if (groups_or_error.is_error())
return nullptr;
auto groups = groups_or_error.release_value();
s_group.gr_gid = parse_id(parts[2]);
if (s_group.gr_gid == -1)
return nullptr;
s_group.gr_name = (char*)malloc(parts[0].size() + 1);
if (s_group.gr_name == nullptr)
return nullptr;
memcpy(s_group.gr_name, parts[0].data(), parts[0].size());
s_group.gr_name[parts[0].size()] = '\0';
s_group.gr_mem = (char**)malloc((groups.size() + 1) * sizeof(char*));
if (s_group.gr_mem == nullptr)
return nullptr;
for (size_t i = 0; i < groups.size(); i++)
{
s_group.gr_mem[i] = (char*)malloc(groups[i].size() + 1);
if (s_group.gr_mem[i] == nullptr)
{
for (size_t j = 0; j < i; j++)
free(s_group.gr_mem[j]);
free(s_group.gr_mem);
s_group.gr_mem = nullptr;
return nullptr;
}
memcpy(s_group.gr_mem[i], groups[i].data(), groups[i].size());
s_group.gr_mem[i][groups[i].size()] = '\0';
}
s_group.gr_mem[groups.size()] = nullptr;
return &s_group;
}
struct group* getgrnam(const char* name)
{
if (s_group_mmap == nullptr || s_group_mmap == MAP_FAILED)
if (!open_group_file())
return nullptr;
off_t start = 0;
off_t end = 0;
while (start < s_group_st.st_size)
{
while (end < s_group_st.st_size && s_group_mmap[end] != '\n')
end++;
BAN::StringView line(s_group_mmap + start, end - start);
start = ++end;
auto parts_or_error = line.split(':', true);
if (parts_or_error.is_error())
return nullptr;
auto parts = parts_or_error.release_value();
if (parts.size() == 4 && parts[0] == name)
return fill_group(parts);
}
return nullptr;
}
struct group* getgrgid(gid_t gid)
{
if (s_group_mmap == nullptr || s_group_mmap == MAP_FAILED)
if (!open_group_file())
return nullptr;
off_t start = 0;
off_t end = 0;
while (start < s_group_st.st_size)
{
while (end < s_group_st.st_size && s_group_mmap[end] != '\n')
end++;
BAN::StringView line(s_group_mmap + start, end - start);
start = ++end;
auto parts_or_error = line.split(':', true);
if (parts_or_error.is_error())
return nullptr;
auto parts = parts_or_error.release_value();
if (parts.size() == 4 && parse_id(parts[2]) == gid)
return fill_group(parts);
}
return nullptr;
}

View File

@ -5,6 +5,7 @@
#include <dirent.h>
#include <fcntl.h>
#include <grp.h>
#include <pwd.h>
#include <stdio.h>
#include <sys/stat.h>
@ -84,7 +85,10 @@ BAN::String build_owner_name_string(uid_t uid)
BAN::String build_owner_group_string(gid_t gid)
{
struct group* grp = getgrgid(gid);
if (grp == nullptr)
return BAN::String::formatted("{}", gid);
return BAN::String(BAN::StringView(grp->gr_name));
}
BAN::String build_size_string(off_t size)