BuildSystem: Move all userpace libraries under the userspace directory
As the number of libraries is increasing, root directory starts to expand. This adds better organization for libraries
This commit is contained in:
162
userspace/libraries/LibC/grp.cpp
Normal file
162
userspace/libraries/LibC/grp.cpp
Normal 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;
|
||||
}
|
||||
Reference in New Issue
Block a user