initrd+libc: Add /etc/group and grp.h
This commit is contained in:
parent
9184bbfef6
commit
d7fee26aa2
@ -1,3 +1,4 @@
|
|||||||
|
#include <grp.h>
|
||||||
#include <luna/String.h>
|
#include <luna/String.h>
|
||||||
#include <os/ArgumentParser.h>
|
#include <os/ArgumentParser.h>
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
@ -31,8 +32,14 @@ Result<int> luna_main(int argc, char** argv)
|
|||||||
if (rc.has_value()) { gid = (u32)rc.value(); }
|
if (rc.has_value()) { gid = (u32)rc.value(); }
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fprintf(stderr, "FIXME: read entry from group file to determine GID for group %s\n", group.chars());
|
struct group* grp = getgrnam(group.chars());
|
||||||
return 1;
|
if (!grp)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s: unknown group %s!\n", argv[0], group.chars());
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
gid = grp->gr_gid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
3
initrd/etc/group
Normal file
3
initrd/etc/group
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
root:!:0:
|
||||||
|
users:!:1:
|
||||||
|
selene:!:1000:
|
40
libc/include/grp.h
Normal file
40
libc/include/grp.h
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
/* grp.h: Group file parsing. */
|
||||||
|
|
||||||
|
#ifndef _GRP_H
|
||||||
|
#define _GRP_H
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
struct group
|
||||||
|
{
|
||||||
|
char* gr_name;
|
||||||
|
char* gr_passwd;
|
||||||
|
gid_t gr_gid;
|
||||||
|
char** gr_mem;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Read the next entry from the group file. */
|
||||||
|
struct group* getgrent(void);
|
||||||
|
|
||||||
|
/* Find the entry with a matching group name in the group file. */
|
||||||
|
struct group* getgrnam(const char* name);
|
||||||
|
|
||||||
|
/* Find the entry with a matching group ID in the group file. */
|
||||||
|
struct group* getgrgid(gid_t gid);
|
||||||
|
|
||||||
|
/* Rewind the group file. */
|
||||||
|
void setgrent(void);
|
||||||
|
|
||||||
|
/* End group file parsing. */
|
||||||
|
void endgrent(void);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
128
libc/src/grp.cpp
Normal file
128
libc/src/grp.cpp
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
#include <errno.h>
|
||||||
|
#include <grp.h>
|
||||||
|
#include <luna/Vector.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
static struct group grp;
|
||||||
|
static FILE* f { nullptr };
|
||||||
|
static char buf[4096];
|
||||||
|
|
||||||
|
static Vector<char*> g_members;
|
||||||
|
|
||||||
|
extern char* _strtok_once(char* str, const char* delim);
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
static Result<struct group*> try_getgrent()
|
||||||
|
{
|
||||||
|
if (!f)
|
||||||
|
{
|
||||||
|
f = fopen("/etc/group", "r");
|
||||||
|
if (!f) return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
char* rc = fgets(buf, sizeof(buf), f);
|
||||||
|
if (!rc) return nullptr;
|
||||||
|
|
||||||
|
char* name = _strtok_once(rc, ":\n");
|
||||||
|
if (!name) continue;
|
||||||
|
|
||||||
|
char* passwd = _strtok_once(nullptr, ":\n");
|
||||||
|
if (!passwd) continue;
|
||||||
|
|
||||||
|
char* gid = _strtok_once(nullptr, ":\n");
|
||||||
|
if (!gid) continue;
|
||||||
|
|
||||||
|
char* members = _strtok_once(nullptr, ":\n");
|
||||||
|
if (!members) continue;
|
||||||
|
|
||||||
|
g_members.clear();
|
||||||
|
|
||||||
|
char* member = strtok(members, ",");
|
||||||
|
TRY(g_members.try_append(member));
|
||||||
|
|
||||||
|
if (member)
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
member = strtok(nullptr, ",");
|
||||||
|
TRY(g_members.try_append(member));
|
||||||
|
if (!member) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
grp.gr_name = name;
|
||||||
|
grp.gr_passwd = passwd;
|
||||||
|
grp.gr_gid = (gid_t)strtoul(gid, NULL, 10);
|
||||||
|
grp.gr_mem = g_members.data();
|
||||||
|
|
||||||
|
return &grp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct group* getgrent()
|
||||||
|
{
|
||||||
|
auto rc = try_getgrent();
|
||||||
|
if (rc.has_error())
|
||||||
|
{
|
||||||
|
errno = rc.error();
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return rc.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
struct group* getgrnam(const char* name)
|
||||||
|
{
|
||||||
|
setgrent();
|
||||||
|
|
||||||
|
struct group* entry;
|
||||||
|
|
||||||
|
while ((entry = getgrent()))
|
||||||
|
{
|
||||||
|
if (!strcmp(entry->gr_name, name))
|
||||||
|
{
|
||||||
|
endgrent();
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
endgrent();
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct group* getgrgid(gid_t gid)
|
||||||
|
{
|
||||||
|
setgrent();
|
||||||
|
|
||||||
|
struct group* entry;
|
||||||
|
|
||||||
|
while ((entry = getgrent()))
|
||||||
|
{
|
||||||
|
if (entry->gr_gid == gid)
|
||||||
|
{
|
||||||
|
endgrent();
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
endgrent();
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setgrent()
|
||||||
|
{
|
||||||
|
if (f) rewind(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void endgrent()
|
||||||
|
{
|
||||||
|
if (f)
|
||||||
|
{
|
||||||
|
fclose(f);
|
||||||
|
f = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -11,7 +11,7 @@ static char buf[4096];
|
|||||||
// Example:
|
// Example:
|
||||||
// strtok("hello:world::!:", ":") -> "hello", "world", "!"
|
// strtok("hello:world::!:", ":") -> "hello", "world", "!"
|
||||||
// _strtok_once("hello:world::!:", ":") -> "hello", "world", "", "!"
|
// _strtok_once("hello:world::!:", ":") -> "hello", "world", "", "!"
|
||||||
static char* _strtok_once(char* str, const char* delim)
|
char* _strtok_once(char* str, const char* delim)
|
||||||
{
|
{
|
||||||
static char* s = nullptr;
|
static char* s = nullptr;
|
||||||
if (str) s = str;
|
if (str) s = str;
|
||||||
|
Loading…
Reference in New Issue
Block a user