95 lines
1.6 KiB
C
95 lines
1.6 KiB
C
#include <gint/fs.h>
|
|
#include <gint/defs/attributes.h>
|
|
#include <unistd.h>
|
|
#include <errno.h>
|
|
|
|
/* File descriptor table */
|
|
static fs_descriptor_t fdtable[FS_FD_MAX] = { 0 };
|
|
|
|
fs_descriptor_t const *fs_get_descriptor(int fd)
|
|
{
|
|
if((unsigned)fd >= FS_FD_MAX)
|
|
return NULL;
|
|
if(fdtable[fd].type == NULL)
|
|
return NULL;
|
|
|
|
return &fdtable[fd];
|
|
}
|
|
|
|
int fs_create_descriptor(fs_descriptor_t const *data)
|
|
{
|
|
if(data->type == NULL)
|
|
return -1;
|
|
|
|
/* Leave 0/1/2 for stdin, stdout and stderr */
|
|
for(int i = 3; i < FS_FD_MAX; i++) {
|
|
if(fdtable[i].type == NULL) {
|
|
fdtable[i] = *data;
|
|
return i;
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
void fs_free_descriptor(int fd)
|
|
{
|
|
if((unsigned)fd >= FS_FD_MAX)
|
|
return;
|
|
|
|
fdtable[fd].type = NULL;
|
|
fdtable[fd].data = NULL;
|
|
}
|
|
|
|
int open_generic(fs_descriptor_type_t *type, void *data, int fd)
|
|
{
|
|
if(!type) {
|
|
errno = EINVAL;
|
|
return -1;
|
|
}
|
|
fs_descriptor_t d = {
|
|
.type = type,
|
|
.data = data
|
|
};
|
|
|
|
/* Re-use file descriptor mode */
|
|
if(fd >= 0) {
|
|
if(fd >= FS_FD_MAX) {
|
|
errno = EBADF;
|
|
return -1;
|
|
}
|
|
if(fdtable[fd].type) {
|
|
errno = ENFILE;
|
|
return -1;
|
|
}
|
|
|
|
fdtable[fd] = d;
|
|
return fd;
|
|
}
|
|
/* Normal allocation mode */
|
|
else {
|
|
return fs_create_descriptor(&d);
|
|
}
|
|
}
|
|
|
|
/* Standard streams */
|
|
|
|
static fs_descriptor_type_t devnull = {
|
|
.read = NULL,
|
|
.write = NULL,
|
|
.lseek = NULL,
|
|
.close = NULL,
|
|
};
|
|
|
|
GCONSTRUCTOR static void init_standard_streams(void)
|
|
{
|
|
fdtable[STDIN_FILENO].type = &devnull;
|
|
fdtable[STDIN_FILENO].data = NULL;
|
|
|
|
fdtable[STDOUT_FILENO].type = &devnull;
|
|
fdtable[STDOUT_FILENO].data = NULL;
|
|
|
|
fdtable[STDERR_FILENO].type = &devnull;
|
|
fdtable[STDERR_FILENO].data = NULL;
|
|
}
|