Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Path: blob/master/libraries/AP_Filesystem/posix_compat.cpp
Views: 1798
/*1This program is free software: you can redistribute it and/or modify2it under the terms of the GNU General Public License as published by3the Free Software Foundation, either version 3 of the License, or4(at your option) any later version.56This program is distributed in the hope that it will be useful,7but WITHOUT ANY WARRANTY; without even the implied warranty of8MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the9GNU General Public License for more details.1011You should have received a copy of the GNU General Public License12along with this program. If not, see <http://www.gnu.org/licenses/>.13*/14/*15compatibility with posix APIs using AP_Filesystem1617This implements the FILE* API from posix sufficiently well for Lua18scripting to function. It has no buffering so is inefficient for19single character operations. We deliberately use this implementation20in HAL_SITL and HAL_Linux where it is not needed in order to have a21uniform implementation across all platforms22*/2324#include "AP_Filesystem.h"2526#if AP_FILESYSTEM_FATFS_ENABLED || AP_FILESYSTEM_POSIX_ENABLED || AP_FILESYSTEM_ESP32_ENABLED || AP_FILESYSTEM_ROMFS_ENABLED2728#include "posix_compat.h"29#include <stdarg.h>30#include <AP_Math/AP_Math.h>3132#define CHECK_STREAM(stream, ret) while (stream == NULL || stream->fd < 0) { errno = EBADF; return ret; }3334#define modecmp(str, pat) (strcmp(str, pat) == 0 ? 1: 0)3536/*37map a fopen() file mode to a open() mode38*/39static int posix_fopen_modes_to_open(const char *mode)40{41int flag = 0;4243if (modecmp(mode,"r") || modecmp(mode,"rb")) {44flag = O_RDONLY;45return flag;46}47if (modecmp(mode,"r+") || modecmp(mode, "r+b" ) || modecmp(mode, "rb+" )) {48flag = O_RDWR | O_TRUNC;49return flag;50}51if (modecmp(mode,"w") || modecmp(mode,"wb")) {52flag = O_WRONLY | O_CREAT | O_TRUNC;53return flag;54}55if (modecmp(mode,"w+") || modecmp(mode, "w+b" ) || modecmp(mode, "wb+" )) {56flag = O_RDWR | O_CREAT | O_TRUNC;57return flag;58}59if (modecmp(mode,"a") || modecmp(mode,"ab")) {60flag = O_WRONLY | O_CREAT | O_APPEND;61return flag;62}63if (modecmp(mode,"a+") || modecmp(mode, "a+b" ) || modecmp(mode, "ab+" )) {64flag = O_RDWR | O_CREAT | O_APPEND;65return flag;66}67return -1;68}6970APFS_FILE *apfs_fopen(const char *pathname, const char *mode)71{72APFS_FILE *f = NEW_NOTHROW APFS_FILE;73if (!f) {74return nullptr;75}76f->fd = AP::FS().open(pathname, posix_fopen_modes_to_open(mode));77if (f->fd == -1) {78delete f;79return nullptr;80}81f->unget = -1;82return f;83}8485int apfs_fprintf(APFS_FILE *stream, const char *fmt, ...)86{87CHECK_STREAM(stream, -1);88va_list va;89char* buf = NULL;90int16_t len;91va_start(va, fmt);92len = vasprintf(&buf, fmt, va);93va_end(va);94if (len > 0) {95len = AP::FS().write(stream->fd, buf, len);96free(buf);97}9899return len;100}101102int apfs_fflush(APFS_FILE *stream)103{104CHECK_STREAM(stream, EOF);105if (AP::FS().fsync(stream->fd) == 0) {106return 0;107}108return EOF;109}110111size_t apfs_fread(void *ptr, size_t size, size_t nmemb, APFS_FILE *stream)112{113CHECK_STREAM(stream, 0);114ssize_t ret = AP::FS().read(stream->fd, ptr, size*nmemb);115if (ret <= 0) {116stream->eof = true;117return 0;118}119return ret / size;120}121122size_t apfs_fwrite(const void *ptr, size_t size, size_t nmemb, APFS_FILE *stream)123{124CHECK_STREAM(stream, 0);125ssize_t ret = AP::FS().write(stream->fd, ptr, size*nmemb);126if (ret <= 0) {127stream->error = true;128return 0;129}130return ret / size;131}132133int apfs_fputs(const char *s, APFS_FILE *stream)134{135CHECK_STREAM(stream, EOF);136ssize_t ret = AP::FS().write(stream->fd, s, strlen(s));137if (ret < 0) {138stream->error = true;139return EOF;140}141return ret;142}143144#undef fgets145char *apfs_fgets(char *s, int size, APFS_FILE *stream)146{147CHECK_STREAM(stream, NULL);148auto &fs = AP::FS();149if (!fs.fgets(s, size, stream->fd)) {150return NULL;151}152return s;153}154155void apfs_clearerr(APFS_FILE *stream)156{157stream->error = false;158}159160int apfs_fseek(APFS_FILE *stream, long offset, int whence)161{162CHECK_STREAM(stream, EOF);163stream->eof = false;164AP::FS().lseek(stream->fd, offset, whence);165return 0;166}167168int apfs_ferror(APFS_FILE *stream)169{170CHECK_STREAM(stream, EOF);171return stream->error;172}173174int apfs_fclose(APFS_FILE *stream)175{176CHECK_STREAM(stream, EOF);177int ret = AP::FS().close(stream->fd);178stream->fd = -1;179if (stream->tmpfile_name) {180AP::FS().unlink(stream->tmpfile_name);181free(stream->tmpfile_name);182stream->tmpfile_name = NULL;183}184delete stream;185return ret;186}187188APFS_FILE *apfs_tmpfile(void)189{190char *fname = NULL;191if (asprintf(&fname, "tmp.%03u", unsigned(get_random16()) % 1000) <= 0) {192return NULL;193}194APFS_FILE *ret = apfs_fopen(fname, "w");195if (!ret) {196free(fname);197return NULL;198}199ret->tmpfile_name = fname;200return ret;201}202203int apfs_getc(APFS_FILE *stream)204{205CHECK_STREAM(stream, EOF);206uint8_t c;207if (stream->unget != -1) {208c = stream->unget;209stream->unget = -1;210return c;211}212ssize_t ret = AP::FS().read(stream->fd, &c, 1);213if (ret <= 0) {214stream->eof = true;215return EOF;216}217return c;218}219220int apfs_ungetc(int c, APFS_FILE *stream)221{222CHECK_STREAM(stream, EOF);223stream->unget = c;224stream->eof = false;225return c;226}227228int apfs_feof(APFS_FILE *stream)229{230return stream->eof;231}232233APFS_FILE *apfs_freopen(const char *pathname, const char *mode, APFS_FILE *stream)234{235CHECK_STREAM(stream, NULL);236int ret = AP::FS().close(stream->fd);237if (ret < 0) {238return NULL;239}240if (stream->tmpfile_name) {241AP::FS().unlink(stream->tmpfile_name);242free(stream->tmpfile_name);243stream->tmpfile_name = NULL;244}245stream->fd = AP::FS().open(pathname, posix_fopen_modes_to_open(mode));246stream->error = false;247stream->eof = false;248stream->unget = -1;249return stream;250}251252long apfs_ftell(APFS_FILE *stream)253{254CHECK_STREAM(stream, EOF);255return AP::FS().lseek(stream->fd, 0, SEEK_CUR);256}257258int apfs_remove(const char *pathname)259{260return AP::FS().unlink(pathname);261}262263#endif // AP_FILESYSTEM_POSIX_ENABLED264265266