Compare commits
3 Commits
1bd33e76e5
...
753de3d9f0
Author | SHA1 | Date |
---|---|---|
Bananymous | 753de3d9f0 | |
Bananymous | 668c4c8976 | |
Bananymous | d2bc399770 |
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -7,6 +7,7 @@ set(LIBC_SOURCES
|
|||
ctype.cpp
|
||||
dirent.cpp
|
||||
fcntl.cpp
|
||||
grp.cpp
|
||||
malloc.cpp
|
||||
printf_impl.cpp
|
||||
pwd.cpp
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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)
|
||||
{
|
||||
return BAN::String::formatted("{}", 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)
|
||||
|
|
Loading…
Reference in New Issue