-
Notifications
You must be signed in to change notification settings - Fork 200
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This commit adds basic emulation of a current working directory to wasi-libc. The `getcwd` and `chdir` symbols are now implemented and available for use. The `getcwd` implementation is pretty simple in that it just copies out of a new global, `__wasilibc_cwd`, which defaults to `"/"`. The `chdir` implementation is much more involved and has more ramification, however. A new function, `make_absolute`, was added to the preopens object. Paths stored in the preopen table are now always stored as absolute paths instead of relative paths, and initial relative paths are interpreted as being relative to `/`. Looking up a path to preopen now always turns it into an absolute path, relative to the current working directory, and an appropriate path is then returned. The signature of `__wasilibc_find_relpath` has changed as well. It now returns two path components, one for the absolute part and one for the relative part. Additionally the relative part is always dynamically allocated since it may no longer be a substring of the original input path. This has been tested lightly against the Rust standard library so far, but I'm not a regular C developer so there's likely a few things to improve!
- Loading branch information
1 parent
215adc8
commit 874df5b
Showing
7 changed files
with
270 additions
and
92 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
#include <errno.h> | ||
#include <fcntl.h> | ||
#include <limits.h> | ||
#include <stdlib.h> | ||
#include <string.h> | ||
#include <sys/stat.h> | ||
#include <unistd.h> | ||
#include <wasi/libc-find-relpath.h> | ||
#include <wasi/libc.h> | ||
|
||
char *__wasilibc_cwd = "/"; | ||
static int __wasilibc_cwd_mallocd = 0; | ||
|
||
int chdir(const char *path) | ||
{ | ||
// Find a preopen'd directory as well as a relative path we're anchored | ||
// from which we're changing directories to. | ||
char *relative; | ||
const char *abs; | ||
int parent_fd = __wasilibc_find_relpath(path, &abs, &relative); | ||
if (parent_fd == -1) { | ||
errno = ENOENT; | ||
return -1; | ||
} | ||
|
||
// Make sure that this directory we're accessing is indeed a directory. | ||
struct stat dirinfo; | ||
int ret = fstatat(parent_fd, relative, &dirinfo, 0); | ||
if (ret == -1) { | ||
free(relative); | ||
return -1; | ||
} | ||
if (!S_ISDIR(dirinfo.st_mode)) { | ||
free(relative); | ||
errno = ENOTDIR; | ||
return -1; | ||
} | ||
|
||
// Copy over our new absolute path into `__wasilibc_cwd`. Only copy over | ||
// the relative portion of the path if it's not equal to `.` | ||
size_t len = strlen(abs); | ||
int copy_relative = strcmp(relative, ".") != 0; | ||
char *new_cwd = malloc(len + (copy_relative ? strlen(relative) : 0)); | ||
if (new_cwd == NULL) { | ||
errno = ENOMEM; | ||
return -1; | ||
} | ||
strcpy(new_cwd, abs); | ||
if (copy_relative) | ||
strcpy(new_cwd + strlen(abs), relative); | ||
free(relative); | ||
|
||
// And set our new malloc'd buffer into the global cwd, freeing the | ||
// previous one if necessary. | ||
char *prev_cwd = __wasilibc_cwd; | ||
__wasilibc_cwd = new_cwd; | ||
if (__wasilibc_cwd_mallocd) | ||
free(prev_cwd); | ||
__wasilibc_cwd_mallocd = 1; | ||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
#include <unistd.h> | ||
#include <errno.h> | ||
#include <string.h> | ||
|
||
extern char *__wasilibc_cwd; | ||
|
||
char *getcwd(char *buf, size_t size) | ||
{ | ||
if (!buf) { | ||
buf = strdup(__wasilibc_cwd); | ||
if (!buf) { | ||
errno = ENOMEM; | ||
return -1; | ||
} | ||
} else { | ||
size_t len = strlen(__wasilibc_cwd); | ||
if (size < strlen(__wasilibc_cwd) + 1) { | ||
errno = ERANGE; | ||
return 0; | ||
} | ||
strcpy(buf, __wasilibc_cwd); | ||
} | ||
return buf; | ||
} | ||
|
Oops, something went wrong.