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/AP_Filesystem_posix.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/*15ArduPilot filesystem interface for posix systems16*/1718#include "AP_Filesystem_config.h"1920#if AP_FILESYSTEM_POSIX_ENABLED2122#include "AP_Filesystem.h"23#include <AP_HAL/AP_HAL.h>24#include <AP_Vehicle/AP_Vehicle_Type.h>2526#if defined(__APPLE__) || defined(__OpenBSD__)27#include <sys/mount.h>28#elif CONFIG_HAL_BOARD != HAL_BOARD_QURT29#include <sys/vfs.h>30#endif3132#if AP_FILESYSTEM_POSIX_HAVE_UTIME33#include <utime.h>34#endif3536extern const AP_HAL::HAL& hal;3738/*39map a filename so operations are relative to the current directory if needed40*/41static const char *map_filename(const char *fname)42{43#if AP_FILESYSTEM_POSIX_MAP_FILENAME_ALLOC44// this system needs to add a prefix to the filename, which means45// memory allocation. This is needed for QURT which lacks chdir()46char *fname2 = nullptr;47asprintf(&fname2, "%s/%s", AP_FILESYSTEM_POSIX_MAP_FILENAME_BASEDIR, fname);48return fname2;49#else5051#if CONFIG_HAL_BOARD == HAL_BOARD_SITL && !APM_BUILD_TYPE(APM_BUILD_Replay)52// on SITL only allow paths under subdirectory. Users can still53// escape with .. if they want to54if (strcmp(fname, "/") == 0) {55return ".";56}57if (*fname == '/') {58fname++;59}60#endif61// on Linux allow original name62return fname;63#endif // AP_FILESYSTEM_POSIX_MAP_FILENAME_ALLOC64}6566static void map_filename_free(const char *fname)67{68#if AP_FILESYSTEM_POSIX_MAP_FILENAME_ALLOC69::free(const_cast<char*>(fname));70#endif71}7273int AP_Filesystem_Posix::open(const char *fname, int flags, bool allow_absolute_paths)74{75FS_CHECK_ALLOWED(-1);76if (! allow_absolute_paths) {77fname = map_filename(fname);78}79struct stat st;80if (::stat(fname, &st) == 0 &&81((st.st_mode & S_IFMT) != S_IFREG && (st.st_mode & S_IFMT) != S_IFLNK)) {82// only allow links and files83if (!allow_absolute_paths) {84map_filename_free(fname);85}86return -1;87}8889// we automatically add O_CLOEXEC as we always want it for ArduPilot FS usage90auto ret = ::open(fname, flags | O_CLOEXEC, 0644);91if (!allow_absolute_paths) {92map_filename_free(fname);93}94return ret;95}9697int AP_Filesystem_Posix::close(int fd)98{99FS_CHECK_ALLOWED(-1);100return ::close(fd);101}102103int32_t AP_Filesystem_Posix::read(int fd, void *buf, uint32_t count)104{105FS_CHECK_ALLOWED(-1);106return ::read(fd, buf, count);107}108109int32_t AP_Filesystem_Posix::write(int fd, const void *buf, uint32_t count)110{111FS_CHECK_ALLOWED(-1);112return ::write(fd, buf, count);113}114115int AP_Filesystem_Posix::fsync(int fd)116{117#if AP_FILESYSTEM_POSIX_HAVE_FSYNC118FS_CHECK_ALLOWED(-1);119return ::fsync(fd);120#else121// we have to pass success here as otherwise it is assumed to be122// failed IO and the caller may close the fd and give up123return 0;124#endif125}126127int32_t AP_Filesystem_Posix::lseek(int fd, int32_t offset, int seek_from)128{129FS_CHECK_ALLOWED(-1);130return ::lseek(fd, offset, seek_from);131}132133int AP_Filesystem_Posix::stat(const char *pathname, struct stat *stbuf)134{135FS_CHECK_ALLOWED(-1);136pathname = map_filename(pathname);137auto ret = ::stat(pathname, stbuf);138map_filename_free(pathname);139return ret;140}141142int AP_Filesystem_Posix::unlink(const char *pathname)143{144FS_CHECK_ALLOWED(-1);145pathname = map_filename(pathname);146// we match the FATFS interface and use unlink147// for both files and directories148int ret = ::rmdir(const_cast<char*>(pathname));149if (ret == -1) {150ret = ::unlink(pathname);151}152map_filename_free(pathname);153return ret;154}155156int AP_Filesystem_Posix::mkdir(const char *pathname)157{158FS_CHECK_ALLOWED(-1);159pathname = map_filename(pathname);160auto ret = ::mkdir(const_cast<char*>(pathname), 0775);161map_filename_free(pathname);162return ret;163}164165void *AP_Filesystem_Posix::opendir(const char *pathname)166{167FS_CHECK_ALLOWED(nullptr);168pathname = map_filename(pathname);169auto *ret = (void*)::opendir(pathname);170map_filename_free(pathname);171return ret;172}173174struct dirent *AP_Filesystem_Posix::readdir(void *dirp)175{176FS_CHECK_ALLOWED(nullptr);177return ::readdir((DIR *)dirp);178}179180int AP_Filesystem_Posix::closedir(void *dirp)181{182FS_CHECK_ALLOWED(-1);183return ::closedir((DIR *)dirp);184}185186int AP_Filesystem_Posix::rename(const char *oldpath, const char *newpath)187{188FS_CHECK_ALLOWED(-1);189oldpath = map_filename(oldpath);190newpath = map_filename(newpath);191auto ret = ::rename(oldpath, newpath);192map_filename_free(oldpath);193map_filename_free(newpath);194return ret;195}196197// return free disk space in bytes198int64_t AP_Filesystem_Posix::disk_free(const char *path)199{200#if AP_FILESYSTEM_POSIX_HAVE_STATFS201FS_CHECK_ALLOWED(-1);202path = map_filename(path);203struct statfs stats;204if (::statfs(path, &stats) < 0) {205map_filename_free(path);206return -1;207}208map_filename_free(path);209return (((int64_t)stats.f_bavail) * stats.f_bsize);210#else211return -1;212#endif213}214215// return total disk space in bytes216int64_t AP_Filesystem_Posix::disk_space(const char *path)217{218#if AP_FILESYSTEM_POSIX_HAVE_STATFS219FS_CHECK_ALLOWED(-1);220path = map_filename(path);221struct statfs stats;222if (::statfs(path, &stats) < 0) {223map_filename_free(path);224return -1;225}226map_filename_free(path);227return (((int64_t)stats.f_blocks) * stats.f_bsize);228#else229return -1;230#endif231}232233234/*235set mtime on a file236*/237bool AP_Filesystem_Posix::set_mtime(const char *filename, const uint32_t mtime_sec)238{239#if AP_FILESYSTEM_POSIX_HAVE_UTIME240FS_CHECK_ALLOWED(false);241filename = map_filename(filename);242struct utimbuf times {};243times.actime = mtime_sec;244times.modtime = mtime_sec;245246auto ret = utime(filename, ×) == 0;247map_filename_free(filename);248return ret;249#else250return false;251#endif252}253254#endif // AP_FILESYSTEM_POSIX_ENABLED255256257