/* * This file is part of Jehanne. * * Copyright (C) 2017 Giacomo Tesio * * This is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, version 3 of the License. * * Jehanne is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with Jehanne. If not, see . */ #include #include #include #include "internal.h" static PosixStatReader __libposix_stat_reader; static PosixOpenTranslator __libposix_open_translation; typedef enum SeekTypes { SeekSet = 0, SeekCurrent = 1, SeekEnd = 2 } SeekTypes; static int *__libposix_seek_types; void __libposix_files_check_conf(void) { if(__libposix_stat_reader == nil) sysfatal("libposix: no stat reader"); if(__libposix_open_translation == nil) sysfatal("libposix: no open translator"); if(__libposix_seek_types == nil) sysfatal("libposix: no seek translations"); } int libposix_translate_open(PosixOpenTranslator translation) { if(__libposix_initialized()) return 0; if(translation == nil) return 0; __libposix_open_translation = translation; return 1; } int libposix_set_stat_reader(PosixStatReader reader) { if(__libposix_initialized()) return 0; if(reader == nil) return 0; __libposix_stat_reader = reader; return 1; } int libposix_translate_seek_whence(int seek_set, int seek_cur, int seek_end) { if(__libposix_initialized()) return 0; if(seek_set == seek_cur) return 0; if(seek_set == seek_end) return 0; if(seek_cur == seek_end) return 0; __libposix_seek_types = malloc(sizeof(int)*3); if(__libposix_seek_types == nil) return 0; __libposix_seek_types[SeekSet] = seek_set; __libposix_seek_types[SeekCurrent] = seek_cur; __libposix_seek_types[SeekEnd] = seek_end; return 1; } static SeekTypes find_seek_type(int whence) { if(__libposix_seek_types[SeekSet] == whence) return SeekSet; if(__libposix_seek_types[SeekCurrent] == whence) return SeekCurrent; if(__libposix_seek_types[SeekEnd] == whence) return SeekEnd; return -1; } int POSIX_pipe(int *errnop, int fildes[2]) { int res; res = jehanne_pipe(fildes); if(res == -1) *errnop = __libposix_get_errno(PosixEMFILE); return res; } int POSIX_open(int *errnop, const char *name, int flags, int mode) { long omode = 0, cperm = 0; PosixError e; int f; if(name == nil){ *errnop = __libposix_get_errno(PosixENOENT); return -1; } e = __libposix_open_translation(flags, mode, &omode, &cperm); if(e != 0){ *errnop = __libposix_get_errno(e); return -1; } if(cperm == 0){ f = sys_open(name, omode); } else { f = ocreate(name, (unsigned int)omode, (unsigned int)cperm); } if(f >= 0) return f; *errnop = __libposix_translate_errstr((uintptr_t)POSIX_open); return -1; } long POSIX_read(int *errnop, int fd, char *buf, size_t len) { long r; if(fd < 0){ *errnop = __libposix_get_errno(PosixEBADF); return -1; } OnIgnoredSignalInterrupt: r = sys_pread(fd, buf, len, -1); if(r < 0){ if(__libposix_restart_syscall()) goto OnIgnoredSignalInterrupt; *errnop = __libposix_translate_errstr((uintptr_t)POSIX_read); return -1; } return r; } long POSIX_write(int *errnop, int fd, const void *buf, size_t len) { long w; if(fd < 0){ *errnop = __libposix_get_errno(PosixEBADF); return -1; } OnIgnoredSignalInterrupt: w = sys_pwrite(fd, buf, len, -1); if(w < 0){ if(__libposix_restart_syscall()) goto OnIgnoredSignalInterrupt; *errnop = __libposix_translate_errstr((uintptr_t)POSIX_write); return -1; } return w; } off_t POSIX_lseek(int *errnop, int fd, off_t pos, int whence) { SeekTypes stype; long r; stype = find_seek_type(whence); if(stype == -1){ *errnop = __libposix_get_errno(PosixEINVAL); return -1; } if(fd < 0){ *errnop = __libposix_get_errno(PosixEBADF); return -1; } r = sys_seek(fd, pos, stype); if(r >= 0) return r; *errnop = __libposix_translate_errstr((uintptr_t)POSIX_lseek); return -1; } long POSIX_pread(int *errnop, int fd, char *buf, size_t len, long offset) { long r; if(fd < 0){ *errnop = __libposix_get_errno(PosixEBADF); return -1; } OnIgnoredSignalInterrupt: r = sys_pread(fd, buf, len, offset); if(r < 0){ if(__libposix_restart_syscall()) goto OnIgnoredSignalInterrupt; *errnop = __libposix_translate_errstr((uintptr_t)POSIX_read); return -1; } return r; } long POSIX_pwrite(int *errnop, int fd, const char *buf, size_t len, long offset) { long w; if(fd < 0){ *errnop = __libposix_get_errno(PosixEBADF); return -1; } OnIgnoredSignalInterrupt: w = sys_pwrite(fd, buf, len, offset); if(w < 0){ if(__libposix_restart_syscall()) goto OnIgnoredSignalInterrupt; *errnop = __libposix_translate_errstr((uintptr_t)POSIX_write); return -1; } return w; } int POSIX_close(int *errno, int file) { long ret; ret = sys_close(file); switch(ret){ case 0: return 0; case ~0: *errno = __libposix_translate_errstr((uintptr_t)POSIX_close); break; default: *errno = ret; break; } return -1; } int POSIX_link(int *errnop, const char *old, const char *new) { int err; /* let choose the most appropriate error */ if(old == nil || new == nil || old[0] == 0 || new[0] == 0) err = __libposix_get_errno(PosixENOENT); else if(access(new, AEXIST) == 0) err = __libposix_get_errno(PosixEEXIST); else if(access(old, AEXIST) == 0) err = __libposix_get_errno(PosixENOENT); else { /* Jehanne does not support links. * A custom overlay filesystem might support them in * the future but so far it does not exists yet. * * We return EXDEV so that a posix compliant caller * can fallback to a simple copy. */ err = __libposix_get_errno(PosixEXDEV); } *errnop = err; return -1; } int POSIX_unlink(int *errnop, const char *name) { long ret; if(name == nil || name[0] == 0){ *errnop = __libposix_get_errno(PosixENOENT); return -1; } ret = sys_remove(name); switch(ret){ case 0: return 0; case ~0: *errnop = __libposix_translate_errstr((uintptr_t)POSIX_unlink); break; default: *errnop = ret; break; } return -1; } int POSIX_fstat(int *errnop, int file, void *pstat) { Dir *d; PosixError e; if(pstat == nil){ *errnop = __libposix_get_errno(PosixEOVERFLOW); return -1; } if(file < 0){ *errnop = __libposix_get_errno(PosixEBADF); return -1; } OnIgnoredSignalInterrupt: d = dirfstat(file); if(d == nil) { if(__libposix_restart_syscall()) goto OnIgnoredSignalInterrupt; *errnop = __libposix_translate_errstr((uintptr_t)POSIX_fstat); return -1; } e = __libposix_stat_reader(pstat, d); free(d); if(e == 0) return 0; *errnop = __libposix_get_errno(e); return -1; } int POSIX_stat(int *errnop, const char *file, void *pstat) { Dir *d; PosixError e; if(pstat == nil){ *errnop = __libposix_get_errno(PosixEOVERFLOW); return -1; } if(file == nil){ *errnop = __libposix_get_errno(PosixEBADF); return -1; } d = dirstat(file); if(d == nil) { *errnop = __libposix_translate_errstr((uintptr_t)POSIX_stat); return -1; } e = __libposix_stat_reader(pstat, d); free(d); if(e == 0) return 0; *errnop = __libposix_get_errno(e); return -1; } int libposix_getdents(int *errnop, int fd, struct dirent *buf, int buf_bytes) { return 0; }