From 6583f7c13e08659231a1e285a9be9d4104ee3328 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 11 Mar 2020 17:48:09 +1100 Subject: [PATCH] AP_Filesystem: added VFS system for multiple backends --- libraries/AP_Filesystem/AP_Filesystem.cpp | 184 ++++++++++++++++ libraries/AP_Filesystem/AP_Filesystem.h | 29 ++- .../AP_Filesystem/AP_Filesystem_FATFS.cpp | 34 +-- libraries/AP_Filesystem/AP_Filesystem_FATFS.h | 30 +++ .../AP_Filesystem/AP_Filesystem_ROMFS.cpp | 207 ++++++++++++++++++ libraries/AP_Filesystem/AP_Filesystem_ROMFS.h | 66 ++++++ .../AP_Filesystem/AP_Filesystem_backend.h | 53 +++++ .../AP_Filesystem/AP_Filesystem_posix.cpp | 36 +-- libraries/AP_Filesystem/AP_Filesystem_posix.h | 29 +++ 9 files changed, 631 insertions(+), 37 deletions(-) create mode 100644 libraries/AP_Filesystem/AP_Filesystem_ROMFS.cpp create mode 100644 libraries/AP_Filesystem/AP_Filesystem_ROMFS.h create mode 100644 libraries/AP_Filesystem/AP_Filesystem_backend.h diff --git a/libraries/AP_Filesystem/AP_Filesystem.cpp b/libraries/AP_Filesystem/AP_Filesystem.cpp index fb7b816f3f..371a028a76 100644 --- a/libraries/AP_Filesystem/AP_Filesystem.cpp +++ b/libraries/AP_Filesystem/AP_Filesystem.cpp @@ -19,6 +19,190 @@ static AP_Filesystem fs; +#if CONFIG_HAL_BOARD == HAL_BOARD_CHIBIOS +#include "AP_Filesystem_FATFS.h" +static AP_Filesystem_FATFS fs_local; +#endif +#if CONFIG_HAL_BOARD == HAL_BOARD_LINUX || CONFIG_HAL_BOARD == HAL_BOARD_SITL +#include "AP_Filesystem_posix.h" +static AP_Filesystem_Posix fs_local; +#endif + +#ifdef HAL_HAVE_AP_ROMFS_EMBEDDED_H +#include "AP_Filesystem_ROMFS.h" +static AP_Filesystem_ROMFS fs_romfs; +#endif + +/* + mapping from filesystem prefix to backend + */ +const AP_Filesystem::Backend AP_Filesystem::backends[] = { + { nullptr, fs_local }, +#ifdef HAL_HAVE_AP_ROMFS_EMBEDDED_H + { ":ROMFS/", fs_romfs }, +#endif +}; + +#define MAX_FD_PER_BACKEND 256U +#define NUM_BACKENDS ARRAY_SIZE(backends) +#define LOCAL_BACKEND backends[0]; +#define BACKEND_IDX(backend) (&(backend) - &backends[0]) + +/* + find backend by path + */ +const AP_Filesystem::Backend &AP_Filesystem::backend_by_path(const char *&path) const +{ + for (uint8_t i=1; i= NUM_BACKENDS*MAX_FD_PER_BACKEND) { + return LOCAL_BACKEND; + } + const uint8_t idx = uint32_t(fd) / MAX_FD_PER_BACKEND; + fd -= idx * MAX_FD_PER_BACKEND; + return backends[idx]; +} + +int AP_Filesystem::open(const char *fname, int flags) +{ + const Backend &backend = backend_by_path(fname); + int fd = backend.fs.open(fname, flags); + if (fd < 0) { + return -1; + } + if (uint32_t(fd) >= MAX_FD_PER_BACKEND) { + backend.fs.close(fd); + errno = ERANGE; + return -1; + } + // offset fd so we can recognise the backend + const uint8_t idx = (&backend - &backends[0]); + fd += idx * MAX_FD_PER_BACKEND; + return fd; +} + +int AP_Filesystem::close(int fd) +{ + const Backend &backend = backend_by_fd(fd); + return backend.fs.close(fd); +} + +ssize_t AP_Filesystem::read(int fd, void *buf, size_t count) +{ + const Backend &backend = backend_by_fd(fd); + return backend.fs.read(fd, buf, count); +} + +ssize_t AP_Filesystem::write(int fd, const void *buf, size_t count) +{ + const Backend &backend = backend_by_fd(fd); + return backend.fs.write(fd, buf, count); +} + +int AP_Filesystem::fsync(int fd) +{ + const Backend &backend = backend_by_fd(fd); + return backend.fs.fsync(fd); +} + +off_t AP_Filesystem::lseek(int fd, off_t offset, int seek_from) +{ + const Backend &backend = backend_by_fd(fd); + return backend.fs.lseek(fd, offset, seek_from); +} + +int AP_Filesystem::stat(const char *pathname, struct stat *stbuf) +{ + const Backend &backend = backend_by_path(pathname); + return backend.fs.stat(pathname, stbuf); +} + +int AP_Filesystem::unlink(const char *pathname) +{ + const Backend &backend = backend_by_path(pathname); + return backend.fs.unlink(pathname); +} + +int AP_Filesystem::mkdir(const char *pathname) +{ + const Backend &backend = backend_by_path(pathname); + return backend.fs.mkdir(pathname); +} + +AP_Filesystem::DirHandle *AP_Filesystem::opendir(const char *pathname) +{ + const Backend &backend = backend_by_path(pathname); + DirHandle *h = new DirHandle; + if (!h) { + return nullptr; + } + h->dir = backend.fs.opendir(pathname); + if (h->dir == nullptr) { + delete h; + return nullptr; + } + h->fs_index = BACKEND_IDX(backend); + return h; +} + +struct dirent *AP_Filesystem::readdir(DirHandle *dirp) +{ + if (!dirp) { + return nullptr; + } + const Backend &backend = backends[dirp->fs_index]; + return backend.fs.readdir(dirp->dir); +} + +int AP_Filesystem::closedir(DirHandle *dirp) +{ + if (!dirp) { + return -1; + } + const Backend &backend = backends[dirp->fs_index]; + int ret = backend.fs.closedir(dirp->dir); + delete dirp; + return ret; +} + +// return free disk space in bytes +int64_t AP_Filesystem::disk_free(const char *path) +{ + const Backend &backend = backend_by_path(path); + return backend.fs.disk_free(path); +} + +// return total disk space in bytes +int64_t AP_Filesystem::disk_space(const char *path) +{ + const Backend &backend = backend_by_path(path); + return backend.fs.disk_space(path); +} + + +/* + set mtime on a file + */ +bool AP_Filesystem::set_mtime(const char *filename, const time_t mtime_sec) +{ + const Backend &backend = backend_by_path(filename); + return backend.fs.set_mtime(filename, mtime_sec); +} + namespace AP { AP_Filesystem &FS() diff --git a/libraries/AP_Filesystem/AP_Filesystem.h b/libraries/AP_Filesystem/AP_Filesystem.h index fb63fed4ee..b37260ca54 100644 --- a/libraries/AP_Filesystem/AP_Filesystem.h +++ b/libraries/AP_Filesystem/AP_Filesystem.h @@ -33,6 +33,11 @@ #endif class AP_Filesystem { +private: + struct DirHandle { + uint8_t fs_index; + void *dir; + }; public: AP_Filesystem() {} @@ -47,9 +52,10 @@ public: int stat(const char *pathname, struct stat *stbuf); int unlink(const char *pathname); int mkdir(const char *pathname); - DIR *opendir(const char *pathname); - struct dirent *readdir(DIR *dirp); - int closedir(DIR *dirp); + + DirHandle *opendir(const char *pathname); + struct dirent *readdir(DirHandle *dirp); + int closedir(DirHandle *dirp); // return free disk space in bytes, -1 on error int64_t disk_free(const char *path); @@ -59,6 +65,23 @@ public: // set modification time on a file bool set_mtime(const char *filename, const time_t mtime_sec); + +private: + struct Backend { + const char *prefix; + AP_Filesystem_Backend &fs; + }; + static const struct Backend backends[]; + + /* + find backend by path + */ + const Backend &backend_by_path(const char *&path) const; + + /* + find backend by open fd + */ + const Backend &backend_by_fd(int &fd) const; }; namespace AP { diff --git a/libraries/AP_Filesystem/AP_Filesystem_FATFS.cpp b/libraries/AP_Filesystem/AP_Filesystem_FATFS.cpp index 1dfec099ed..4c080ffd1b 100644 --- a/libraries/AP_Filesystem/AP_Filesystem_FATFS.cpp +++ b/libraries/AP_Filesystem/AP_Filesystem_FATFS.cpp @@ -276,7 +276,7 @@ static bool remount_file_system(void) return true; } -int AP_Filesystem::open(const char *pathname, int flags) +int AP_Filesystem_FATFS::open(const char *pathname, int flags) { int fileno; int fatfs_modes; @@ -352,7 +352,7 @@ int AP_Filesystem::open(const char *pathname, int flags) return fileno; } -int AP_Filesystem::close(int fileno) +int AP_Filesystem_FATFS::close(int fileno) { FAT_FILE *stream; FIL *fh; @@ -382,7 +382,7 @@ int AP_Filesystem::close(int fileno) return 0; } -ssize_t AP_Filesystem::read(int fd, void *buf, size_t count) +ssize_t AP_Filesystem_FATFS::read(int fd, void *buf, size_t count) { UINT bytes = count; int res; @@ -431,7 +431,7 @@ ssize_t AP_Filesystem::read(int fd, void *buf, size_t count) return (ssize_t)total; } -ssize_t AP_Filesystem::write(int fd, const void *buf, size_t count) +ssize_t AP_Filesystem_FATFS::write(int fd, const void *buf, size_t count) { UINT bytes = count; FRESULT res; @@ -479,7 +479,7 @@ ssize_t AP_Filesystem::write(int fd, const void *buf, size_t count) return (ssize_t)total; } -int AP_Filesystem::fsync(int fileno) +int AP_Filesystem_FATFS::fsync(int fileno) { FAT_FILE *stream; FIL *fh; @@ -508,7 +508,7 @@ int AP_Filesystem::fsync(int fileno) return 0; } -off_t AP_Filesystem::lseek(int fileno, off_t position, int whence) +off_t AP_Filesystem_FATFS::lseek(int fileno, off_t position, int whence) { FRESULT res; FIL *fh; @@ -599,7 +599,7 @@ static time_t fat_time_to_unix(uint16_t date, uint16_t time) return unix; } -int AP_Filesystem::stat(const char *name, struct stat *buf) +int AP_Filesystem_FATFS::stat(const char *name, struct stat *buf) { FILINFO info; int res; @@ -667,7 +667,7 @@ int AP_Filesystem::stat(const char *name, struct stat *buf) return 0; } -int AP_Filesystem::unlink(const char *pathname) +int AP_Filesystem_FATFS::unlink(const char *pathname) { WITH_SEMAPHORE(sem); @@ -680,7 +680,7 @@ int AP_Filesystem::unlink(const char *pathname) return 0; } -int AP_Filesystem::mkdir(const char *pathname) +int AP_Filesystem_FATFS::mkdir(const char *pathname) { WITH_SEMAPHORE(sem); @@ -703,7 +703,7 @@ struct DIR_Wrapper { struct dirent de; }; -DIR *AP_Filesystem::opendir(const char *pathdir) +void *AP_Filesystem_FATFS::opendir(const char *pathdir) { WITH_SEMAPHORE(sem); @@ -730,9 +730,10 @@ DIR *AP_Filesystem::opendir(const char *pathdir) return &ret->d; } -struct dirent *AP_Filesystem::readdir(DIR *dirp) +struct dirent *AP_Filesystem_FATFS::readdir(void *dirp_void) { WITH_SEMAPHORE(sem); + DIR *dirp = (DIR *)dirp_void; struct DIR_Wrapper *d = (struct DIR_Wrapper *)dirp; if (!d) { @@ -744,7 +745,7 @@ struct dirent *AP_Filesystem::readdir(DIR *dirp) int res; d->de.d_name[0] = 0; - res = f_readdir ( dirp, &fno ); + res = f_readdir(dirp, &fno); if (res != FR_OK || fno.fname[0] == 0) { errno = fatfs_to_errno((FRESULT)res); return nullptr; @@ -760,8 +761,9 @@ struct dirent *AP_Filesystem::readdir(DIR *dirp) return &d->de; } -int AP_Filesystem::closedir(DIR *dirp) +int AP_Filesystem_FATFS::closedir(void *dirp_void) { + DIR *dirp = (DIR *)dirp_void; WITH_SEMAPHORE(sem); struct DIR_Wrapper *d = (struct DIR_Wrapper *)dirp; @@ -780,7 +782,7 @@ int AP_Filesystem::closedir(DIR *dirp) } // return free disk space in bytes -int64_t AP_Filesystem::disk_free(const char *path) +int64_t AP_Filesystem_FATFS::disk_free(const char *path) { WITH_SEMAPHORE(sem); @@ -801,7 +803,7 @@ int64_t AP_Filesystem::disk_free(const char *path) } // return total disk space in bytes -int64_t AP_Filesystem::disk_space(const char *path) +int64_t AP_Filesystem_FATFS::disk_space(const char *path) { WITH_SEMAPHORE(sem); @@ -841,7 +843,7 @@ static void unix_time_to_fat(time_t epoch, uint16_t &date, uint16_t &time) /* set mtime on a file */ -bool AP_Filesystem::set_mtime(const char *filename, const time_t mtime_sec) +bool AP_Filesystem_FATFS::set_mtime(const char *filename, const time_t mtime_sec) { FILINFO fno; uint16_t fdate, ftime; diff --git a/libraries/AP_Filesystem/AP_Filesystem_FATFS.h b/libraries/AP_Filesystem/AP_Filesystem_FATFS.h index d047dbf768..5844dfc380 100644 --- a/libraries/AP_Filesystem/AP_Filesystem_FATFS.h +++ b/libraries/AP_Filesystem/AP_Filesystem_FATFS.h @@ -2,12 +2,15 @@ FATFS backend for AP_Filesystem */ +#pragma once + #include #include #include #include #include #include +#include "AP_Filesystem_backend.h" // Seek offset macros #define SEEK_SET 0 @@ -27,3 +30,30 @@ struct dirent { char d_name[MAX_NAME_LEN]; /* filename */ uint8_t d_type; }; + +class AP_Filesystem_FATFS : public AP_Filesystem_Backend +{ +public: + // functions that closely match the equivalent posix calls + int open(const char *fname, int flags) override; + int close(int fd) override; + ssize_t read(int fd, void *buf, size_t count) override; + ssize_t write(int fd, const void *buf, size_t count) override; + int fsync(int fd) override; + off_t lseek(int fd, off_t offset, int whence) override; + int stat(const char *pathname, struct stat *stbuf) override; + int unlink(const char *pathname) override; + int mkdir(const char *pathname) override; + void *opendir(const char *pathname) override; + struct dirent *readdir(void *dirp) override; + int closedir(void *dirp) override; + + // return free disk space in bytes, -1 on error + int64_t disk_free(const char *path) override; + + // return total disk space in bytes, -1 on error + int64_t disk_space(const char *path) override; + + // set modification time on a file + bool set_mtime(const char *filename, const time_t mtime_sec) override; +}; diff --git a/libraries/AP_Filesystem/AP_Filesystem_ROMFS.cpp b/libraries/AP_Filesystem/AP_Filesystem_ROMFS.cpp new file mode 100644 index 0000000000..caf79f84b7 --- /dev/null +++ b/libraries/AP_Filesystem/AP_Filesystem_ROMFS.cpp @@ -0,0 +1,207 @@ +/* + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License + along with this program. If not, see . + */ +/* + ArduPilot filesystem interface for ROMFS + */ +#include "AP_Filesystem.h" +#include "AP_Filesystem_ROMFS.h" +#include +#include +#include + +#if defined(HAL_HAVE_AP_ROMFS_EMBEDDED_H) && HAVE_FILESYSTEM_SUPPORT + +int AP_Filesystem_ROMFS::open(const char *fname, int flags) +{ + uint8_t idx; + for (idx=0; idx= max_open_file || file[fd].data == nullptr) { + errno = EBADF; + return -1; + } + AP_ROMFS::free(file[fd].data); + file[fd].data = nullptr; + return 0; +} + +ssize_t AP_Filesystem_ROMFS::read(int fd, void *buf, size_t count) +{ + if (fd < 0 || fd >= max_open_file || file[fd].data == nullptr) { + errno = EBADF; + return -1; + } + count = MIN(file[fd].size - file[fd].ofs, count); + if (count == 0) { + return 0; + } + memcpy(buf, &file[fd].data[file[fd].ofs], count); + file[fd].ofs += count; + return count; +} + +ssize_t AP_Filesystem_ROMFS::write(int fd, const void *buf, size_t count) +{ + errno = EROFS; + return -1; +} + +int AP_Filesystem_ROMFS::fsync(int fd) +{ + return 0; +} + +off_t AP_Filesystem_ROMFS::lseek(int fd, off_t offset, int seek_from) +{ + if (fd < 0 || fd >= max_open_file || file[fd].data == nullptr) { + errno = EBADF; + return -1; + } + switch (seek_from) { + case SEEK_SET: + file[fd].ofs = MIN(file[fd].size, offset); + break; + case SEEK_CUR: + file[fd].ofs = MIN(file[fd].size, offset+file[fd].ofs); + break; + case SEEK_END: + file[fd].ofs = file[fd].size; + break; + } + return file[fd].ofs; +} + +int AP_Filesystem_ROMFS::stat(const char *name, struct stat *stbuf) +{ + uint32_t size; + const uint8_t *data = AP_ROMFS::find_decompress(name, size); + if (data == nullptr) { + errno = ENOENT; + return -1; + } + AP_ROMFS::free(data); + memset(stbuf, 0, sizeof(*stbuf)); + stbuf->st_size = size; + return 0; +} + +int AP_Filesystem_ROMFS::unlink(const char *pathname) +{ + errno = EROFS; + return -1; +} + +int AP_Filesystem_ROMFS::mkdir(const char *pathname) +{ + errno = EROFS; + return -1; +} + +void *AP_Filesystem_ROMFS::opendir(const char *pathname) +{ + uint8_t idx; + for (idx=0; idx= max_open_dir) { + errno = EBADF; + return nullptr; + } + const char *name = AP_ROMFS::dir_list(dir[idx].path, dir[idx].ofs); + if (!name) { + return nullptr; + } + const uint32_t plen = strlen(dir[idx].path); + if (strncmp(name, dir[idx].path, plen) != 0 || name[plen] != '/') { + return nullptr; + } + name += plen + 1; + dir[idx].de.d_type = DT_REG; + strncpy(dir[idx].de.d_name, name, sizeof(dir[idx].de.d_name)); + return &dir[idx].de; +} + +int AP_Filesystem_ROMFS::closedir(void *dirp) +{ + uint32_t idx = ((rdir *)dirp) - &dir[0]; + if (idx >= max_open_dir) { + errno = EBADF; + return -1; + } + free(dir[idx].path); + dir[idx].path = nullptr; + return 0; +} + +// return free disk space in bytes +int64_t AP_Filesystem_ROMFS::disk_free(const char *path) +{ + return 0; +} + +// return total disk space in bytes +int64_t AP_Filesystem_ROMFS::disk_space(const char *path) +{ + return 0; +} + +/* + set mtime on a file + */ +bool AP_Filesystem_ROMFS::set_mtime(const char *filename, const time_t mtime_sec) +{ + return false; +} + +#endif // HAL_HAVE_AP_ROMFS_EMBEDDED_H diff --git a/libraries/AP_Filesystem/AP_Filesystem_ROMFS.h b/libraries/AP_Filesystem/AP_Filesystem_ROMFS.h new file mode 100644 index 0000000000..9e202f38a2 --- /dev/null +++ b/libraries/AP_Filesystem/AP_Filesystem_ROMFS.h @@ -0,0 +1,66 @@ +/* + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License + along with this program. If not, see . + */ + +#pragma once + +#include "AP_Filesystem_backend.h" + +#if HAVE_FILESYSTEM_SUPPORT + +class AP_Filesystem_ROMFS : public AP_Filesystem_Backend +{ +public: + // functions that closely match the equivalent posix calls + int open(const char *fname, int flags) override; + int close(int fd) override; + ssize_t read(int fd, void *buf, size_t count) override; + ssize_t write(int fd, const void *buf, size_t count) override; + int fsync(int fd) override; + off_t lseek(int fd, off_t offset, int whence) override; + int stat(const char *pathname, struct stat *stbuf) override; + int unlink(const char *pathname) override; + int mkdir(const char *pathname) override; + void *opendir(const char *pathname) override; + struct dirent *readdir(void *dirp) override; + int closedir(void *dirp) override; + + // return free disk space in bytes, -1 on error + int64_t disk_free(const char *path) override; + + // return total disk space in bytes, -1 on error + int64_t disk_space(const char *path) override; + + // set modification time on a file + bool set_mtime(const char *filename, const time_t mtime_sec) override; + +private: + // only allow up to 4 files at a time + static constexpr uint8_t max_open_file = 4; + static constexpr uint8_t max_open_dir = 4; + struct rfile { + const uint8_t *data; + uint32_t size; + uint32_t ofs; + } file[max_open_file]; + + // allow up to 4 directory opens + struct rdir { + char *path; + uint16_t ofs; + struct dirent de; + } dir[max_open_dir]; +}; + +#endif // HAVE_FILESYSTEM_SUPPORT diff --git a/libraries/AP_Filesystem/AP_Filesystem_backend.h b/libraries/AP_Filesystem/AP_Filesystem_backend.h new file mode 100644 index 0000000000..0134c525bb --- /dev/null +++ b/libraries/AP_Filesystem/AP_Filesystem_backend.h @@ -0,0 +1,53 @@ +/* + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License + along with this program. If not, see . + */ +/* + ArduPilot filesystem backend interface. + */ +#pragma once + +#include +#include + +#include "AP_Filesystem_Available.h" + +#if HAVE_FILESYSTEM_SUPPORT +class AP_Filesystem_Backend { + +public: + // functions that closely match the equivalent posix calls + virtual int open(const char *fname, int flags) = 0; + virtual int close(int fd) = 0; + virtual ssize_t read(int fd, void *buf, size_t count) = 0; + virtual ssize_t write(int fd, const void *buf, size_t count) = 0; + virtual int fsync(int fd) = 0; + virtual off_t lseek(int fd, off_t offset, int whence) = 0; + virtual int stat(const char *pathname, struct stat *stbuf) = 0; + virtual int unlink(const char *pathname) = 0; + virtual int mkdir(const char *pathname) = 0; + virtual void *opendir(const char *pathname) = 0; + virtual struct dirent *readdir(void *dirp) = 0; + virtual int closedir(void *dirp) = 0; + + // return free disk space in bytes, -1 on error + virtual int64_t disk_free(const char *path) = 0; + + // return total disk space in bytes, -1 on error + virtual int64_t disk_space(const char *path) = 0; + + // set modification time on a file + virtual bool set_mtime(const char *filename, const time_t mtime_sec) = 0; +}; + +#endif // HAVE_FILESYSTEM_SUPPORT diff --git a/libraries/AP_Filesystem/AP_Filesystem_posix.cpp b/libraries/AP_Filesystem/AP_Filesystem_posix.cpp index 042bcf2db3..ad1c69f216 100644 --- a/libraries/AP_Filesystem/AP_Filesystem_posix.cpp +++ b/libraries/AP_Filesystem/AP_Filesystem_posix.cpp @@ -48,45 +48,45 @@ static const char *map_filename(const char *fname) return fname; } -int AP_Filesystem::open(const char *fname, int flags) +int AP_Filesystem_Posix::open(const char *fname, int flags) { fname = map_filename(fname); // we automatically add O_CLOEXEC as we always want it for ArduPilot FS usage return ::open(fname, flags | O_CLOEXEC, 0644); } -int AP_Filesystem::close(int fd) +int AP_Filesystem_Posix::close(int fd) { return ::close(fd); } -ssize_t AP_Filesystem::read(int fd, void *buf, size_t count) +ssize_t AP_Filesystem_Posix::read(int fd, void *buf, size_t count) { return ::read(fd, buf, count); } -ssize_t AP_Filesystem::write(int fd, const void *buf, size_t count) +ssize_t AP_Filesystem_Posix::write(int fd, const void *buf, size_t count) { return ::write(fd, buf, count); } -int AP_Filesystem::fsync(int fd) +int AP_Filesystem_Posix::fsync(int fd) { return ::fsync(fd); } -off_t AP_Filesystem::lseek(int fd, off_t offset, int seek_from) +off_t AP_Filesystem_Posix::lseek(int fd, off_t offset, int seek_from) { return ::lseek(fd, offset, seek_from); } -int AP_Filesystem::stat(const char *pathname, struct stat *stbuf) +int AP_Filesystem_Posix::stat(const char *pathname, struct stat *stbuf) { pathname = map_filename(pathname); return ::stat(pathname, stbuf); } -int AP_Filesystem::unlink(const char *pathname) +int AP_Filesystem_Posix::unlink(const char *pathname) { pathname = map_filename(pathname); // we match the FATFS interface and use unlink @@ -98,30 +98,30 @@ int AP_Filesystem::unlink(const char *pathname) return ret; } -int AP_Filesystem::mkdir(const char *pathname) +int AP_Filesystem_Posix::mkdir(const char *pathname) { pathname = map_filename(pathname); return ::mkdir(pathname, 0775); } -DIR *AP_Filesystem::opendir(const char *pathname) +void *AP_Filesystem_Posix::opendir(const char *pathname) { pathname = map_filename(pathname); - return ::opendir(pathname); + return (void*)::opendir(pathname); } -struct dirent *AP_Filesystem::readdir(DIR *dirp) +struct dirent *AP_Filesystem_Posix::readdir(void *dirp) { - return ::readdir(dirp); + return ::readdir((DIR *)dirp); } -int AP_Filesystem::closedir(DIR *dirp) +int AP_Filesystem_Posix::closedir(void *dirp) { - return ::closedir(dirp); + return ::closedir((DIR *)dirp); } // return free disk space in bytes -int64_t AP_Filesystem::disk_free(const char *path) +int64_t AP_Filesystem_Posix::disk_free(const char *path) { path = map_filename(path); struct statfs stats; @@ -132,7 +132,7 @@ int64_t AP_Filesystem::disk_free(const char *path) } // return total disk space in bytes -int64_t AP_Filesystem::disk_space(const char *path) +int64_t AP_Filesystem_Posix::disk_space(const char *path) { path = map_filename(path); struct statfs stats; @@ -146,7 +146,7 @@ int64_t AP_Filesystem::disk_space(const char *path) /* set mtime on a file */ -bool AP_Filesystem::set_mtime(const char *filename, const time_t mtime_sec) +bool AP_Filesystem_Posix::set_mtime(const char *filename, const time_t mtime_sec) { filename = map_filename(filename); struct utimbuf times {}; diff --git a/libraries/AP_Filesystem/AP_Filesystem_posix.h b/libraries/AP_Filesystem/AP_Filesystem_posix.h index 1f5f8bd2a8..75c0c4a711 100644 --- a/libraries/AP_Filesystem/AP_Filesystem_posix.h +++ b/libraries/AP_Filesystem/AP_Filesystem_posix.h @@ -23,3 +23,32 @@ #include #include #include +#include "AP_Filesystem_backend.h" + +class AP_Filesystem_Posix : public AP_Filesystem_Backend +{ +public: + // functions that closely match the equivalent posix calls + int open(const char *fname, int flags) override; + int close(int fd) override; + ssize_t read(int fd, void *buf, size_t count) override; + ssize_t write(int fd, const void *buf, size_t count) override; + int fsync(int fd) override; + off_t lseek(int fd, off_t offset, int whence) override; + int stat(const char *pathname, struct stat *stbuf) override; + int unlink(const char *pathname) override; + int mkdir(const char *pathname) override; + void *opendir(const char *pathname) override; + struct dirent *readdir(void *dirp) override; + int closedir(void *dirp) override; + + // return free disk space in bytes, -1 on error + int64_t disk_free(const char *path) override; + + // return total disk space in bytes, -1 on error + int64_t disk_space(const char *path) override; + + // set modification time on a file + bool set_mtime(const char *filename, const time_t mtime_sec) override; +}; +