#include #include #include #include /* 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, .pread = 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; }