CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
Ardupilot

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.

GitHub Repository: Ardupilot/ardupilot
Path: blob/master/libraries/AP_Filesystem/AP_Filesystem_posix.cpp
Views: 1798
1
/*
2
This program is free software: you can redistribute it and/or modify
3
it under the terms of the GNU General Public License as published by
4
the Free Software Foundation, either version 3 of the License, or
5
(at your option) any later version.
6
7
This program is distributed in the hope that it will be useful,
8
but WITHOUT ANY WARRANTY; without even the implied warranty of
9
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
GNU General Public License for more details.
11
12
You should have received a copy of the GNU General Public License
13
along with this program. If not, see <http://www.gnu.org/licenses/>.
14
*/
15
/*
16
ArduPilot filesystem interface for posix systems
17
*/
18
19
#include "AP_Filesystem_config.h"
20
21
#if AP_FILESYSTEM_POSIX_ENABLED
22
23
#include "AP_Filesystem.h"
24
#include <AP_HAL/AP_HAL.h>
25
#include <AP_Vehicle/AP_Vehicle_Type.h>
26
27
#if defined(__APPLE__) || defined(__OpenBSD__)
28
#include <sys/mount.h>
29
#elif CONFIG_HAL_BOARD != HAL_BOARD_QURT
30
#include <sys/vfs.h>
31
#endif
32
33
#if AP_FILESYSTEM_POSIX_HAVE_UTIME
34
#include <utime.h>
35
#endif
36
37
extern const AP_HAL::HAL& hal;
38
39
/*
40
map a filename so operations are relative to the current directory if needed
41
*/
42
static const char *map_filename(const char *fname)
43
{
44
#if AP_FILESYSTEM_POSIX_MAP_FILENAME_ALLOC
45
// this system needs to add a prefix to the filename, which means
46
// memory allocation. This is needed for QURT which lacks chdir()
47
char *fname2 = nullptr;
48
asprintf(&fname2, "%s/%s", AP_FILESYSTEM_POSIX_MAP_FILENAME_BASEDIR, fname);
49
return fname2;
50
#else
51
52
#if CONFIG_HAL_BOARD == HAL_BOARD_SITL && !APM_BUILD_TYPE(APM_BUILD_Replay)
53
// on SITL only allow paths under subdirectory. Users can still
54
// escape with .. if they want to
55
if (strcmp(fname, "/") == 0) {
56
return ".";
57
}
58
if (*fname == '/') {
59
fname++;
60
}
61
#endif
62
// on Linux allow original name
63
return fname;
64
#endif // AP_FILESYSTEM_POSIX_MAP_FILENAME_ALLOC
65
}
66
67
static void map_filename_free(const char *fname)
68
{
69
#if AP_FILESYSTEM_POSIX_MAP_FILENAME_ALLOC
70
::free(const_cast<char*>(fname));
71
#endif
72
}
73
74
int AP_Filesystem_Posix::open(const char *fname, int flags, bool allow_absolute_paths)
75
{
76
FS_CHECK_ALLOWED(-1);
77
if (! allow_absolute_paths) {
78
fname = map_filename(fname);
79
}
80
struct stat st;
81
if (::stat(fname, &st) == 0 &&
82
((st.st_mode & S_IFMT) != S_IFREG && (st.st_mode & S_IFMT) != S_IFLNK)) {
83
// only allow links and files
84
if (!allow_absolute_paths) {
85
map_filename_free(fname);
86
}
87
return -1;
88
}
89
90
// we automatically add O_CLOEXEC as we always want it for ArduPilot FS usage
91
auto ret = ::open(fname, flags | O_CLOEXEC, 0644);
92
if (!allow_absolute_paths) {
93
map_filename_free(fname);
94
}
95
return ret;
96
}
97
98
int AP_Filesystem_Posix::close(int fd)
99
{
100
FS_CHECK_ALLOWED(-1);
101
return ::close(fd);
102
}
103
104
int32_t AP_Filesystem_Posix::read(int fd, void *buf, uint32_t count)
105
{
106
FS_CHECK_ALLOWED(-1);
107
return ::read(fd, buf, count);
108
}
109
110
int32_t AP_Filesystem_Posix::write(int fd, const void *buf, uint32_t count)
111
{
112
FS_CHECK_ALLOWED(-1);
113
return ::write(fd, buf, count);
114
}
115
116
int AP_Filesystem_Posix::fsync(int fd)
117
{
118
#if AP_FILESYSTEM_POSIX_HAVE_FSYNC
119
FS_CHECK_ALLOWED(-1);
120
return ::fsync(fd);
121
#else
122
// we have to pass success here as otherwise it is assumed to be
123
// failed IO and the caller may close the fd and give up
124
return 0;
125
#endif
126
}
127
128
int32_t AP_Filesystem_Posix::lseek(int fd, int32_t offset, int seek_from)
129
{
130
FS_CHECK_ALLOWED(-1);
131
return ::lseek(fd, offset, seek_from);
132
}
133
134
int AP_Filesystem_Posix::stat(const char *pathname, struct stat *stbuf)
135
{
136
FS_CHECK_ALLOWED(-1);
137
pathname = map_filename(pathname);
138
auto ret = ::stat(pathname, stbuf);
139
map_filename_free(pathname);
140
return ret;
141
}
142
143
int AP_Filesystem_Posix::unlink(const char *pathname)
144
{
145
FS_CHECK_ALLOWED(-1);
146
pathname = map_filename(pathname);
147
// we match the FATFS interface and use unlink
148
// for both files and directories
149
int ret = ::rmdir(const_cast<char*>(pathname));
150
if (ret == -1) {
151
ret = ::unlink(pathname);
152
}
153
map_filename_free(pathname);
154
return ret;
155
}
156
157
int AP_Filesystem_Posix::mkdir(const char *pathname)
158
{
159
FS_CHECK_ALLOWED(-1);
160
pathname = map_filename(pathname);
161
auto ret = ::mkdir(const_cast<char*>(pathname), 0775);
162
map_filename_free(pathname);
163
return ret;
164
}
165
166
void *AP_Filesystem_Posix::opendir(const char *pathname)
167
{
168
FS_CHECK_ALLOWED(nullptr);
169
pathname = map_filename(pathname);
170
auto *ret = (void*)::opendir(pathname);
171
map_filename_free(pathname);
172
return ret;
173
}
174
175
struct dirent *AP_Filesystem_Posix::readdir(void *dirp)
176
{
177
FS_CHECK_ALLOWED(nullptr);
178
return ::readdir((DIR *)dirp);
179
}
180
181
int AP_Filesystem_Posix::closedir(void *dirp)
182
{
183
FS_CHECK_ALLOWED(-1);
184
return ::closedir((DIR *)dirp);
185
}
186
187
int AP_Filesystem_Posix::rename(const char *oldpath, const char *newpath)
188
{
189
FS_CHECK_ALLOWED(-1);
190
oldpath = map_filename(oldpath);
191
newpath = map_filename(newpath);
192
auto ret = ::rename(oldpath, newpath);
193
map_filename_free(oldpath);
194
map_filename_free(newpath);
195
return ret;
196
}
197
198
// return free disk space in bytes
199
int64_t AP_Filesystem_Posix::disk_free(const char *path)
200
{
201
#if AP_FILESYSTEM_POSIX_HAVE_STATFS
202
FS_CHECK_ALLOWED(-1);
203
path = map_filename(path);
204
struct statfs stats;
205
if (::statfs(path, &stats) < 0) {
206
map_filename_free(path);
207
return -1;
208
}
209
map_filename_free(path);
210
return (((int64_t)stats.f_bavail) * stats.f_bsize);
211
#else
212
return -1;
213
#endif
214
}
215
216
// return total disk space in bytes
217
int64_t AP_Filesystem_Posix::disk_space(const char *path)
218
{
219
#if AP_FILESYSTEM_POSIX_HAVE_STATFS
220
FS_CHECK_ALLOWED(-1);
221
path = map_filename(path);
222
struct statfs stats;
223
if (::statfs(path, &stats) < 0) {
224
map_filename_free(path);
225
return -1;
226
}
227
map_filename_free(path);
228
return (((int64_t)stats.f_blocks) * stats.f_bsize);
229
#else
230
return -1;
231
#endif
232
}
233
234
235
/*
236
set mtime on a file
237
*/
238
bool AP_Filesystem_Posix::set_mtime(const char *filename, const uint32_t mtime_sec)
239
{
240
#if AP_FILESYSTEM_POSIX_HAVE_UTIME
241
FS_CHECK_ALLOWED(false);
242
filename = map_filename(filename);
243
struct utimbuf times {};
244
times.actime = mtime_sec;
245
times.modtime = mtime_sec;
246
247
auto ret = utime(filename, &times) == 0;
248
map_filename_free(filename);
249
return ret;
250
#else
251
return false;
252
#endif
253
}
254
255
#endif // AP_FILESYSTEM_POSIX_ENABLED
256
257