-
Notifications
You must be signed in to change notification settings - Fork 73
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
🚸 Add missing filesystem functions #184
Conversation
You have some build errors: https://gist.github.com/nathan-moore/7763e0a66be450e184284b8a07982150 Also, what about ser_driver and dev_driver? They also make a fs_driver struct and need to be added to. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably also should run this through Clang format when you're done with it.
src/system/dev/vfs.c
Outdated
int file_size(const char* file) { | ||
// Returns true if is under size constraint | ||
size_t i = 0; | ||
for (i = 0; i < MAX_FILELEN; i++) { | ||
if (file[i] == '\0') { | ||
break; | ||
} | ||
} | ||
if (i == MAX_FILELEN) { | ||
return i != MAX_FILELEN; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this can be removed, see below
src/system/dev/vfs.c
Outdated
int _open(const char* file, int flags, int mode) { | ||
struct _reent* r = _REENT; | ||
// Check if the filename is too long or not NULL terminated | ||
if (!file_size(file)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just realized we can definitely use strnlen
here...
if (!file_size(file)) { | |
if (strnlen(file, MAX_FILELEN) == MAX_FILELEN) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure why we didn't before, unless @edjubuh had some concerns about it? (it's part of the C standard as of C11)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, a slightly larger review this time. I should have thought about this more earlier, but basically it doesn't make sense given the current implementation to have anything that takes a path argument (as opposed to a file descriptor argument) to the fs_driver
struct.
there's two ways I see that we could go about this:
- do what we did with
open
, and explicitly delegate to a function like*_open_r
- change the
fs_driver
's semantics so that each function taking a path name is called having stripped off the driver-descriptive part of the path
I would have said that the first option is the easiest, however given the number of functions being added here I don't actually think that's the case. Plus, the second option would make #178 easier to work on in the future.
So let me elaborate on the second point. Let's consider mkdir
as an example.
int mkdir(const char* pathname, mode_t mode) {
struct _reent* r = _REENT;
// check length of pathname
size_t len = 0;
if ((len = strnlen(pathname, MAX_FILELEN)) == MAX_FILELEN) {
r->_errno = ENAMETOOLONG;
return -1;
}
if (len <= 3) {
// this means that it's too short to be meaningful (needs to at least have "/a/")
r->_errno = ENOENT;
return -1;
} else if (*pathname != '/') {
// our paths need to start with '/' by convention. this check is delayed so that we
// can ensure dereferencing the pathname is safe
r->_errno = ENOENT;
return -1;
}
// now we've established there's some meaningful path
// by convention, a path should be of the form `/drv/path...` where `drv` is the driver id
// so we want to find the first substring that starts and ends with '/' to extract this id
char* path = strchr(pathname + 1, '/'); // skip the first character as we already know it
size_t drvlen = len - strlen(path);
char* drv = malloc(drvlen * sizeof(*drv)); // allocate some space for the driver id
strncpy(drv, pathname, drvlen);
// at this point we have everything we need, so look up the driver for the driver id
struct fs_driver* driver;
if (!(driver = driver_lookup(drv)) {
free(drv); // make sure to free up memory
r->_errno = EFAULT; // this errno value is up for debate
return -1;
}
free(drv);
return driver->mkdir_r(r, pathname + drvlen, mode);
}
A lot of that path extraction stuff could definitely be refactored into its own function. driver_lookup
and associated storage would also need to be defined and implemented. Since we currently only support the three drivers (usd
, ser
, and dev
), this would be as simple as checking the driver id and returning a pointer to the right driver (this can be easily extended later).
|
||
int _chdir(const char* path) { | ||
struct _reent* r = _REENT; | ||
return file_table[file].driver->chdir(r, file_table[file].arg, path); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same as mkdir
src/system/dev/vfs.c
Outdated
|
||
int _chmod(const char* path, mode_t mode) { | ||
struct _reent* r = _REENT; | ||
return file_table[file].driver->chdir(r, file_table[file].arg, path, mode); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same as mkdir
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This calls chdir, not chmod.
|
||
int _pathconf(const char* path, int name) { | ||
struct _reent* r = _REENT; | ||
return file_table[file].driver->pathconf(r, file_table[file].arg, path, name); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same as mkdir
include/system/dev/vfs.h
Outdated
int (*mkdir_r)(struct _reent*, void* const, mode_t mode); | ||
int (*link_r)(struct _reent*, void* const, char*, char*); | ||
int (*unlink_r)(struct _reent*, void* const, char*); | ||
int (*chdir_r)(struct _reent*, void* const, const char*); | ||
int (*chmod_r)(struct _reent*, void* const, const char*); | ||
long (*pathconf_r)(struct _reent*, void* const, const char*, int); | ||
char* (*getcwd_r)(struct _reent*, void* const, const char*, size_t); | ||
int (*stat_r)(struct _reent*, void* const, const char*, struct*); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
whatever implementation we end up with, these signatures are wrong. they should match the functions as they're defined
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I'll line up the signatures and everything during the last clean up commit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you might as well do it sooner rather than later. it will make it easier for us to compile it for you
src/system/dev/vfs.c
Outdated
|
||
int _unlink(char* name) { | ||
struct _reent* r = _REENT; | ||
return file_table[file].driver->mkdir(r, file_table[file].arg, path); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Plus this calls mkdir, not unlink.
src/system/dev/vfs.c
Outdated
|
||
int _chmod(const char* path, mode_t mode) { | ||
struct _reent* r = _REENT; | ||
return file_table[file].driver->chdir(r, file_table[file].arg, path, mode); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This calls chdir, not chmod.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Newlib supports namespace clean functions for some of these. The ones it does I think you should be doing. There's a list hotel put on the original issue with the function names you should be matching, and it includes which ones have underscores and which ones don't.
return file_table[file].driver->mkdir(r, file_table[file].arg, path); | ||
} | ||
|
||
int unlink(char* name) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
int unlink(char* name) { | |
int _unlink(char* name) { |
return file_table[file].driver->unlink(r, file_table[file].arg, path); | ||
} | ||
|
||
int link(char* old, char* new) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
int link(char* old, char* new) { | |
int _link(char* old, char* new) { |
return file_table[file].driver->link(r, file_table[file].arg, new, old); | ||
} | ||
|
||
int stat(const char* restrict path, struct stat* st) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
int stat(const char* restrict path, struct stat* st) { | |
int _stat(const char* restrict path, struct stat* st) { |
as this isn't immediately causing issues, let's close it and we can revisit it later as needed. plus i think the idea is that we'll rework a lot of this along the lines i mentioned (#184 (review)) come PROS 4 |
Summary:
Provides Stubs for
chdir
mkdir -- Partial Implementation
chmod
pathconf
getcwd
unlink
link -- Partial Implementation
stat
fixes #176
(maybe) closes #175