aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/os/fs.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/os/fs.c')
-rw-r--r--src/nvim/os/fs.c83
1 files changed, 70 insertions, 13 deletions
diff --git a/src/nvim/os/fs.c b/src/nvim/os/fs.c
index 52c10d0ca7..5eeb275701 100644
--- a/src/nvim/os/fs.c
+++ b/src/nvim/os/fs.c
@@ -19,6 +19,15 @@
// Many fs functions from libuv return that value on success.
static const int kLibuvSuccess = 0;
+static uv_loop_t fs_loop;
+
+
+// Initialize the fs module
+void fs_init(void)
+{
+ uv_loop_init(&fs_loop);
+}
+
/// Change to the given directory.
///
@@ -184,7 +193,7 @@ int os_open(const char* path, int flags, int mode)
FUNC_ATTR_NONNULL_ALL
{
uv_fs_t open_req;
- int r = uv_fs_open(uv_default_loop(), &open_req, path, flags, mode, NULL);
+ int r = uv_fs_open(&fs_loop, &open_req, path, flags, mode, NULL);
uv_fs_req_cleanup(&open_req);
// r is the same as open_req.result (except for OOM: then only r is set).
return r;
@@ -197,7 +206,7 @@ static bool os_stat(const char *name, uv_stat_t *statbuf)
FUNC_ATTR_NONNULL_ALL
{
uv_fs_t request;
- int result = uv_fs_stat(uv_default_loop(), &request, name, NULL);
+ int result = uv_fs_stat(&fs_loop, &request, name, NULL);
*statbuf = request.statbuf;
uv_fs_req_cleanup(&request);
return (result == kLibuvSuccess);
@@ -224,7 +233,7 @@ int os_setperm(const char_u *name, int perm)
FUNC_ATTR_NONNULL_ALL
{
uv_fs_t request;
- int result = uv_fs_chmod(uv_default_loop(), &request,
+ int result = uv_fs_chmod(&fs_loop, &request,
(const char*)name, perm, NULL);
uv_fs_req_cleanup(&request);
@@ -245,7 +254,7 @@ int os_fchown(int file_descriptor, uv_uid_t owner, uv_gid_t group)
FUNC_ATTR_NONNULL_ALL
{
uv_fs_t request;
- int result = uv_fs_fchown(uv_default_loop(), &request, file_descriptor,
+ int result = uv_fs_fchown(&fs_loop, &request, file_descriptor,
owner, group, NULL);
uv_fs_req_cleanup(&request);
return result;
@@ -294,7 +303,7 @@ int os_rename(const char_u *path, const char_u *new_path)
FUNC_ATTR_NONNULL_ALL
{
uv_fs_t request;
- int result = uv_fs_rename(uv_default_loop(), &request,
+ int result = uv_fs_rename(&fs_loop, &request,
(const char *)path, (const char *)new_path, NULL);
uv_fs_req_cleanup(&request);
@@ -307,16 +316,64 @@ int os_rename(const char_u *path, const char_u *new_path)
/// Make a directory.
///
-/// @return `0` for success, non-zero for failure.
+/// @return `0` for success, -errno for failure.
int os_mkdir(const char *path, int32_t mode)
FUNC_ATTR_NONNULL_ALL
{
uv_fs_t request;
- int result = uv_fs_mkdir(uv_default_loop(), &request, path, mode, NULL);
+ int result = uv_fs_mkdir(&fs_loop, &request, path, mode, NULL);
uv_fs_req_cleanup(&request);
return result;
}
+/// Make a directory, with higher levels when needed
+///
+/// @param[in] dir Directory to create.
+/// @param[in] mode Permissions for the newly-created directory.
+/// @param[out] failed_dir If it failed to create directory, then this
+/// argument is set to an allocated string containing
+/// the name of the directory which os_mkdir_recurse
+/// failed to create. I.e. it will contain dir or any
+/// of the higher level directories.
+///
+/// @return `0` for success, -errno for failure.
+int os_mkdir_recurse(const char *const dir, int32_t mode,
+ char **const failed_dir)
+ FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
+{
+ // Get end of directory name in "dir".
+ // We're done when it's "/" or "c:/".
+ const size_t dirlen = strlen(dir);
+ char *const curdir = xmemdupz(dir, dirlen);
+ char *const past_head = (char *) get_past_head((char_u *) curdir);
+ char *e = curdir + dirlen;
+ const char *const real_end = e;
+ const char past_head_save = *past_head;
+ while (!os_isdir((char_u *) curdir)) {
+ e = (char *) path_tail_with_sep((char_u *) curdir);
+ if (e <= past_head) {
+ *past_head = NUL;
+ break;
+ }
+ *e = NUL;
+ }
+ while (e != real_end) {
+ if (e > past_head) {
+ *e = '/';
+ } else {
+ *past_head = past_head_save;
+ }
+ e += strlen(e);
+ int ret;
+ if ((ret = os_mkdir(curdir, mode)) != 0) {
+ *failed_dir = curdir;
+ return ret;
+ }
+ }
+ xfree(curdir);
+ return 0;
+}
+
/// Create a unique temporary directory.
///
/// @param[in] template Template of the path to the directory with XXXXXX
@@ -328,7 +385,7 @@ int os_mkdtemp(const char *template, char *path)
FUNC_ATTR_NONNULL_ALL
{
uv_fs_t request;
- int result = uv_fs_mkdtemp(uv_default_loop(), &request, template, NULL);
+ int result = uv_fs_mkdtemp(&fs_loop, &request, template, NULL);
if (result == kLibuvSuccess) {
STRNCPY(path, request.path, TEMP_FILE_PATH_MAXLEN);
}
@@ -343,7 +400,7 @@ int os_rmdir(const char *path)
FUNC_ATTR_NONNULL_ALL
{
uv_fs_t request;
- int result = uv_fs_rmdir(uv_default_loop(), &request, path, NULL);
+ int result = uv_fs_rmdir(&fs_loop, &request, path, NULL);
uv_fs_req_cleanup(&request);
return result;
}
@@ -356,7 +413,7 @@ int os_rmdir(const char *path)
bool os_scandir(Directory *dir, const char *path)
FUNC_ATTR_NONNULL_ALL
{
- int r = uv_fs_scandir(uv_default_loop(), &dir->request, path, 0, NULL);
+ int r = uv_fs_scandir(&fs_loop, &dir->request, path, 0, NULL);
if (r <= 0) {
os_closedir(dir);
}
@@ -388,7 +445,7 @@ int os_remove(const char *path)
FUNC_ATTR_NONNULL_ALL
{
uv_fs_t request;
- int result = uv_fs_unlink(uv_default_loop(), &request, path, NULL);
+ int result = uv_fs_unlink(&fs_loop, &request, path, NULL);
uv_fs_req_cleanup(&request);
return result;
}
@@ -413,7 +470,7 @@ bool os_fileinfo_link(const char *path, FileInfo *file_info)
FUNC_ATTR_NONNULL_ALL
{
uv_fs_t request;
- int result = uv_fs_lstat(uv_default_loop(), &request, path, NULL);
+ int result = uv_fs_lstat(&fs_loop, &request, path, NULL);
file_info->stat = request.statbuf;
uv_fs_req_cleanup(&request);
return (result == kLibuvSuccess);
@@ -428,7 +485,7 @@ bool os_fileinfo_fd(int file_descriptor, FileInfo *file_info)
FUNC_ATTR_NONNULL_ALL
{
uv_fs_t request;
- int result = uv_fs_fstat(uv_default_loop(), &request, file_descriptor, NULL);
+ int result = uv_fs_fstat(&fs_loop, &request, file_descriptor, NULL);
file_info->stat = request.statbuf;
uv_fs_req_cleanup(&request);
return (result == kLibuvSuccess);