Open Model Railroad Network (OpenMRN)
Loading...
Searching...
No Matches
FileSystem.cxx
Go to the documentation of this file.
1
34#include "Devtab.hxx"
35
36#include <fcntl.h>
37#include <unistd.h>
38
40
44 : FileIO(nullptr)
45{
46 mutex.lock();
47 next = first;
48 first = this;
49 prev = NULL;
50 if (next)
51 {
52 next->prev = this;
53 }
54 mutex.unlock();
55}
56
60{
61 mutex.lock();
62 if (first == this)
63 {
64 first = next;
65 }
66 else
67 {
68 prev->next = next;
69 }
70 if (next)
71 {
72 next->prev = prev;
73 }
74 mutex.unlock();
75}
76
82{
83 for (FileSystem *fs = first; fs != NULL; fs = fs->next)
84 {
85 if (fs->name == nullptr)
86 {
87 /* mount path has no name, probably not mounted yet */
88 continue;
89 }
90 size_t fs_name_len = strlen(fs->name);
91 if (fs_name_len > strlen(path))
92 {
93 /* path less than mount path */
94 continue;
95 }
96 if (strncmp(fs->name, path, fs_name_len))
97 {
98 /* no basename match */
99 continue;
100 }
101 if (path[fs_name_len] != '/' && strcmp(fs->name, path))
102 {
103 /* not a directory break or exact name match*/
104 continue;
105 }
106 return fs;
107 }
108
109 return nullptr;
110}
111
119int FileSystem::open(struct _reent *reent, const char *path, int flags, int mode)
120{
121 mutex.lock();
122 int fd = fd_alloc();
123 mutex.unlock();
124 if (fd < 0)
125 {
126 errno = EMFILE;
127 return -1;
128 }
129 files[fd].flags = flags;
130
131 FileSystem *fs = fs_lookup(path);
132
133 if (!fs)
134 {
135 // No device found.
136 fd_free(fd);
137 errno = ENODEV;
138 return -1;
139 }
140
141 files[fd].dev = fs;
142 files[fd].device = false;
143 const char *subpath = path + strlen(fs->name) + 1;
144 int result = files[fd].dev->open(&files[fd], subpath, flags, mode);
145 if (result < 0)
146 {
147 fd_free(fd);
148 errno = -result;
149 return -1;
150 }
151 return fd;
152}
153
159int FileSystem::close(struct _reent *reent, int fd)
160{
161 File* f = file_lookup(fd);
162 if (!f)
163 {
164 /* errno should already be set appropriately */
165 return -1;
166 }
167 if (fd >=0 && fd <= 2)
168 {
169 // stdin, stdout, and stderr never get closed
170 return 0;
171 }
172 int result = f->dev->close(f);
173 if (result < 0)
174 {
175 errno = -result;
176 return -1;
177 }
178 fd_free(fd);
179 return 0;
180}
181
187int FileSystem::unlink(struct _reent *reent, const char *path)
188{
189 FileSystem *fs = fs_lookup(path);
190 if (!fs)
191 {
192 errno = ENOENT;
193 return -1;
194 }
195
196 const char *subpath = path + strlen(fs->name) + 1;
197 int result = fs->unlink(subpath);
198 if (result < 0)
199 {
200 errno = -result;
201 return -1;
202 }
203 return 0;
204}
205
212int FileSystem::stat(struct _reent *reent, const char *path, struct stat *stat)
213{
214 FileSystem *fs = fs_lookup(path);
215 if (!fs)
216 {
217 errno = ENOENT;
218 return -1;
219 }
220
221 const char *subpath = path + strlen(fs->name) + 1;
222 int result = fs->stat(subpath, stat);
223 if (result < 0)
224 {
225 errno = -result;
226 return -1;
227 }
228 return 0;
229}
230
236int FileSystem::fstat(File* file, struct stat *stat)
237{
238 memset(stat, 0, sizeof(*stat));
239 return 0;
240}
241
247{
248 File *file = file_lookup(fd);
249 HASSERT(!file->device);
250
251 if (!file)
252 {
253 errno = EBADF;
254 return -1;
255 }
256
257 int result = static_cast<FileSystem*>(file->dev)->fsync(file);
258 if (result < 0)
259 {
260 errno = -result;
261 return -1;
262 }
263 return result;
264}
265
266/*
267 * FileSystem::closedir()
268 */
270{
271 File *file = (File*)dirp;
272 FileSystem *fs = static_cast<FileSystem*>(file->dev);
273
274 if (!file->dir)
275 {
276 errno = EBADF;
277 return -1;
278 }
279 int result = fs->closedir(file);
280 if (result < 0)
281 {
282 errno = -result;
283 return -1;
284 }
285 return result;
286}
287
288/*
289 * FileSystem::opendir()
290 */
291DIR *FileSystem::opendir(const char *name)
292{
293 mutex.lock();
294 int fd = fd_alloc();
295 mutex.unlock();
296 if (fd < 0)
297 {
298 errno = EMFILE;
299 return NULL;
300 }
301 files[fd].flags = 0;
302 files[fd].dir = true;
303
305 if (fs)
306 {
307 files[fd].dev = fs;
308 files[fd].device = false;
309 const char *subpath = name + strlen(fs->name) + 1;
310 DIR *result = (DIR*)fs->opendir(&files[fd], subpath);
311 if (result)
312 {
313 return result;
314 }
315 }
316 // No device found.
317 fd_free(fd);
318 errno = ENOENT;
319 return NULL;
320}
321
322/*
323 * FileSystem::readdir()
324 */
326{
327 File *file = (File*)dirp;
328 FileSystem *fs = static_cast<FileSystem*>(file->dev);
329
330 HASSERT(file->dir);
331
332 return fs->readdir(file);
333}
334
335
336#ifdef __cplusplus
337extern "C" {
338#endif
339
340/*
341 * closedir()
342 */
343int closedir(DIR *dirp)
344{
345 return FileSystem::closedir(dirp);
346}
347
348/*
349 * opendir()
350 */
351DIR *opendir(const char *name)
352{
353 return FileSystem::opendir(name);
354}
355
356/*
357 * readdir()
358 */
359struct dirent *readdir(DIR *dirp)
360{
361 return FileSystem::readdir(dirp);
362}
363
364#ifdef __cplusplus
365}
366#endif
367
DIR * opendir(const char *name)
Open a directory.
struct dirent * readdir(DIR *dirp)
Read the next entry in a directory.
int closedir(DIR *dirp)
Close a directory.
Base class for both Device and FileSystem objects.
Definition Devtab.hxx:73
static void fd_free(int fd)
Free up a file descriptor.
Definition Fileio.cxx:71
static File * file_lookup(int fd)
Looks up a reference to a File corresponding to a given file descriptor.
Definition Fileio.cxx:82
virtual int close(File *file)=0
Close a file or device.
static File files[]
File descriptor pool.
Definition Devtab.hxx:261
const char * name
device name
Definition Devtab.hxx:266
virtual int open(File *file, const char *path, int flags, int mode)=0
Open a file or device.
static int fd_alloc(void)
Allocate a free file descriptor.
Definition Fileio.cxx:47
static OSMutex mutex
mutual exclusion for fileio
Definition Devtab.hxx:264
Base class for all File systems.
Definition Devtab.hxx:280
static int open(struct _reent *reent, const char *path, int flags, int mode)
Open a file or device.
FileSystem * next
next device in linked list
Definition Devtab.hxx:420
virtual int fstat(File *file, struct stat *stat) override
Get the status information of a file or device.
static DIR * opendir(const char *name)
Open a directory.
static struct dirent * readdir(DIR *dirp)
Read the next entry in a directory.
FileSystem * prev
previous device in linked list
Definition Devtab.hxx:423
static int fsync(int fd)
Synchronize (flush) a file to disk.
virtual ~FileSystem()
Destructor.
FileSystem()
Constructor.
static int close(struct _reent *reent, int fd)
Close a file or device.
static FileSystem * fs_lookup(const char *path)
Locate the file system for a given path.
static int closedir(DIR *dirp)
Close a directory.
static FileSystem * first
first device in linked list
Definition Devtab.hxx:417
static int stat(struct _reent *reent, const char *path, struct stat *stat)
Get the status information of a file or device.
static int unlink(struct _reent *reent, const char *path)
Remove a file.
void lock()
Lock a mutex.
Definition OS.hxx:446
void unlock()
Unlock a mutex.
Definition OS.hxx:453
uintptr_t DIR
DIR typedef.
Definition dirent.h:45
#define HASSERT(x)
Checks that the value of expression x is true, else terminates the current process.
Definition macros.h:138
File information.
Definition Devtab.hxx:52
int flags
open flags
Definition Devtab.hxx:63
uint8_t dir
true if this is a directory, else false
Definition Devtab.hxx:67
uint8_t device
true if this is a device, false if file system
Definition Devtab.hxx:66
FileIO * dev
file operations
Definition Devtab.hxx:53
Directory entry structure.
Definition dirent.h:49