aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/os/fs.c
diff options
context:
space:
mode:
authorJosh Rahm <joshuarahm@gmail.com>2023-01-25 18:31:31 +0000
committerJosh Rahm <joshuarahm@gmail.com>2023-01-25 18:31:31 +0000
commit9243becbedbb6a1592208051f8fa2b090dcc5e7d (patch)
tree607c2a862ec3f4399b8766383f6f8e04c4aa43b4 /src/nvim/os/fs.c
parent9e40b6e9e1bc67f2d856adb837ee64dd0e25b717 (diff)
parent3c48d3c83fc21dbc0841f9210f04bdb073d73cd1 (diff)
downloadrneovim-usermarks.tar.gz
rneovim-usermarks.tar.bz2
rneovim-usermarks.zip
Merge remote-tracking branch 'upstream/master' into usermarksusermarks
Diffstat (limited to 'src/nvim/os/fs.c')
-rw-r--r--src/nvim/os/fs.c149
1 files changed, 110 insertions, 39 deletions
diff --git a/src/nvim/os/fs.c b/src/nvim/os/fs.c
index 0d62a5f5f9..302faa8140 100644
--- a/src/nvim/os/fs.c
+++ b/src/nvim/os/fs.c
@@ -5,11 +5,23 @@
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
-#include <limits.h>
#include <stdbool.h>
#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
#include "auto/config.h"
+#include "nvim/gettext.h"
+#include "nvim/globals.h"
+#include "nvim/log.h"
+#include "nvim/macros.h"
+#include "nvim/option_defs.h"
+#include "nvim/os/fs_defs.h"
+#include "nvim/types.h"
+#include "nvim/vim.h"
#ifdef HAVE_SYS_UIO_H
# include <sys/uio.h>
@@ -18,16 +30,14 @@
#include <uv.h>
#include "nvim/ascii.h"
-#include "nvim/assert.h"
#include "nvim/memory.h"
#include "nvim/message.h"
-#include "nvim/option.h"
#include "nvim/os/os.h"
-#include "nvim/os/os_defs.h"
#include "nvim/path.h"
-#include "nvim/strings.h"
-#ifdef WIN32
+struct iovec;
+
+#ifdef MSWIN
# include "nvim/mbyte.h" // for utf8_to_utf16, utf16_to_utf8
#endif
@@ -95,12 +105,12 @@ int os_chdir(const char *path)
/// @param buf Buffer to store the directory name.
/// @param len Length of `buf`.
/// @return `OK` for success, `FAIL` for failure.
-int os_dirname(char_u *buf, size_t len)
+int os_dirname(char *buf, size_t len)
FUNC_ATTR_NONNULL_ALL
{
int error_number;
- if ((error_number = uv_cwd((char *)buf, &len)) != kLibuvSuccess) {
- STRLCPY(buf, uv_strerror(error_number), len);
+ if ((error_number = uv_cwd(buf, &len)) != kLibuvSuccess) {
+ xstrlcpy(buf, uv_strerror(error_number), len);
return FAIL;
}
return OK;
@@ -121,18 +131,17 @@ bool os_isrealdir(const char *name)
fs_loop_unlock();
if (S_ISLNK(request.statbuf.st_mode)) {
return false;
- } else {
- return S_ISDIR(request.statbuf.st_mode);
}
+ return S_ISDIR(request.statbuf.st_mode);
}
/// Check if the given path exists and is a directory.
///
/// @return `true` if `name` is a directory.
-bool os_isdir(const char_u *name)
+bool os_isdir(const char *name)
FUNC_ATTR_NONNULL_ALL
{
- int32_t mode = os_getperm((const char *)name);
+ int32_t mode = os_getperm(name);
if (mode < 0) {
return false;
}
@@ -151,7 +160,7 @@ bool os_isdir(const char_u *name)
int os_nodetype(const char *name)
FUNC_ATTR_NONNULL_ALL
{
-#ifndef WIN32 // Unix
+#ifndef MSWIN // Unix
uv_stat_t statbuf;
if (0 != os_stat(name, &statbuf)) {
return NODE_NORMAL; // File doesn't exist.
@@ -171,7 +180,7 @@ int os_nodetype(const char *name)
// Edge case from Vim os_win32.c:
// We can't open a file with a name "\\.\con" or "\\.\prn", trying to read
// from it later will cause Vim to hang. Thus return NODE_WRITABLE here.
- if (STRNCMP(name, "\\\\.\\", 4) == 0) {
+ if (strncmp(name, "\\\\.\\", 4) == 0) {
return NODE_WRITABLE;
}
@@ -241,7 +250,7 @@ bool os_can_exe(const char *name, char **abspath, bool use_path)
FUNC_ATTR_NONNULL_ARG(1)
{
if (!use_path || gettail_dir(name) != name) {
-#ifdef WIN32
+#ifdef MSWIN
if (is_executable_ext(name, abspath)) {
#else
// Must have path separator, cannot execute files in the current directory.
@@ -249,9 +258,8 @@ bool os_can_exe(const char *name, char **abspath, bool use_path)
&& is_executable(name, abspath)) {
#endif
return true;
- } else {
- return false;
}
+ return false;
}
return is_executable_in_path(name, abspath);
@@ -270,7 +278,7 @@ static bool is_executable(const char *name, char **abspath)
return false;
}
-#ifdef WIN32
+#ifdef MSWIN
// Windows does not have exec bit; just check if the file exists and is not
// a directory.
const bool ok = S_ISREG(mode);
@@ -287,14 +295,16 @@ static bool is_executable(const char *name, char **abspath)
return ok;
}
-#ifdef WIN32
+#ifdef MSWIN
/// Checks if file `name` is executable under any of these conditions:
/// - extension is in $PATHEXT and `name` is executable
/// - result of any $PATHEXT extension appended to `name` is executable
static bool is_executable_ext(const char *name, char **abspath)
FUNC_ATTR_NONNULL_ARG(1)
{
- const bool is_unix_shell = strstr((char *)path_tail(p_sh), "sh") != NULL;
+ const bool is_unix_shell = strstr(path_tail(p_sh), "powershell") == NULL
+ && strstr(path_tail(p_sh), "pwsh") == NULL
+ && strstr(path_tail(p_sh), "sh") != NULL;
char *nameext = strrchr(name, '.');
size_t nameext_len = nameext ? strlen(nameext) : 0;
xstrlcpy(os_buf, name, sizeof(os_buf));
@@ -320,11 +330,11 @@ static bool is_executable_ext(const char *name, char **abspath)
const char *ext_end = ext;
size_t ext_len =
- copy_option_part(&ext_end, (char_u *)buf_end,
+ copy_option_part((char **)&ext_end, buf_end,
sizeof(os_buf) - (size_t)(buf_end - os_buf), ENV_SEPSTR);
if (ext_len != 0) {
bool in_pathext = nameext_len == ext_len
- && 0 == mb_strnicmp((char_u *)nameext, (char_u *)ext, ext_len);
+ && 0 == mb_strnicmp(nameext, ext, ext_len);
if (((in_pathext || is_unix_shell) && is_executable(name, abspath))
|| is_executable(os_buf, abspath)) {
@@ -351,7 +361,7 @@ static bool is_executable_in_path(const char *name, char **abspath)
return false;
}
-#ifdef WIN32
+#ifdef MSWIN
// Prepend ".;" to $PATH.
size_t pathlen = strlen(path_env);
char *path = memcpy(xmallocz(pathlen + 2), "." ENV_SEPSTR, 2);
@@ -371,10 +381,10 @@ static bool is_executable_in_path(const char *name, char **abspath)
char *e = xstrchrnul(p, ENV_SEPCHAR);
// Combine the $PATH segment with `name`.
- STRLCPY(buf, p, e - p + 1);
+ xstrlcpy(buf, p, (size_t)(e - p) + 1);
append_path(buf, name, buf_len);
-#ifdef WIN32
+#ifdef MSWIN
if (is_executable_ext(buf, abspath)) {
#else
if (is_executable(buf, abspath)) {
@@ -446,7 +456,7 @@ FILE *os_fopen(const char *path, const char *flags)
default:
abort();
}
-#ifdef WIN32
+#ifdef MSWIN
if (flags[1] == 'b') {
iflags |= O_BINARY;
}
@@ -756,9 +766,8 @@ int32_t os_getperm(const char *name)
int stat_result = os_stat(name, &statbuf);
if (stat_result == kLibuvSuccess) {
return (int32_t)statbuf.st_mode;
- } else {
- return stat_result;
}
+ return stat_result;
}
/// Set the permission of a file.
@@ -772,6 +781,38 @@ int os_setperm(const char *const name, int perm)
return (r == kLibuvSuccess ? OK : FAIL);
}
+#if defined(HAVE_ACL)
+# ifdef HAVE_SYS_ACL_H
+# include <sys/acl.h>
+# endif
+# ifdef HAVE_SYS_ACCESS_H
+# include <sys/access.h>
+# endif
+
+// Return a pointer to the ACL of file "fname" in allocated memory.
+// Return NULL if the ACL is not available for whatever reason.
+vim_acl_T os_get_acl(const char *fname)
+{
+ vim_acl_T ret = NULL;
+ return ret;
+}
+
+// Set the ACL of file "fname" to "acl" (unless it's NULL).
+void os_set_acl(const char *fname, vim_acl_T aclent)
+{
+ if (aclent == NULL) {
+ return;
+ }
+}
+
+void os_free_acl(vim_acl_T aclent)
+{
+ if (aclent == NULL) {
+ return;
+ }
+}
+#endif
+
#ifdef UNIX
/// Checks if the current user owns a file.
///
@@ -821,10 +862,10 @@ int os_fchown(int fd, uv_uid_t owner, uv_gid_t group)
/// Check if a path exists.
///
/// @return `true` if `path` exists
-bool os_path_exists(const char_u *path)
+bool os_path_exists(const char *path)
{
uv_stat_t statbuf;
- return os_stat((char *)path, &statbuf) == kLibuvSuccess;
+ return os_stat(path, &statbuf) == kLibuvSuccess;
}
/// Sets file access and modification times.
@@ -865,7 +906,7 @@ int os_file_is_writable(const char *name)
int r;
RUN_UV_FS_FUNC(r, uv_fs_access, name, W_OK, NULL);
if (r == 0) {
- return os_isdir((char_u *)name) ? 2 : 1;
+ return os_isdir(name) ? 2 : 1;
}
return 0;
}
@@ -873,12 +914,11 @@ int os_file_is_writable(const char *name)
/// Rename a file or directory.
///
/// @return `OK` for success, `FAIL` for failure.
-int os_rename(const char_u *path, const char_u *new_path)
+int os_rename(const char *path, const char *new_path)
FUNC_ATTR_NONNULL_ALL
{
int r;
- RUN_UV_FS_FUNC(r, uv_fs_rename, (const char *)path, (const char *)new_path,
- NULL);
+ RUN_UV_FS_FUNC(r, uv_fs_rename, path, new_path, NULL);
return (r == kLibuvSuccess ? OK : FAIL);
}
@@ -911,11 +951,11 @@ int os_mkdir_recurse(const char *const dir, int32_t mode, char **const failed_di
// 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 *const past_head = get_past_head(curdir);
char *e = curdir + dirlen;
const char *const real_end = e;
const char past_head_save = *past_head;
- while (!os_isdir((char_u *)curdir)) {
+ while (!os_isdir(curdir)) {
e = path_tail_with_sep(curdir);
if (e <= past_head) {
*past_head = NUL;
@@ -946,6 +986,37 @@ int os_mkdir_recurse(const char *const dir, int32_t mode, char **const failed_di
return 0;
}
+/// Create the parent directory of a file if it does not exist
+///
+/// @param[in] fname Full path of the file name whose parent directories
+/// we want to create
+/// @param[in] mode Permissions for the newly-created directory.
+///
+/// @return `0` for success, libuv error code for failure.
+int os_file_mkdir(char *fname, int32_t mode)
+ FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
+{
+ if (!dir_of_file_exists(fname)) {
+ char *tail = path_tail_with_sep(fname);
+ char *last_char = tail + strlen(tail) - 1;
+ if (vim_ispathsep(*last_char)) {
+ emsg(_(e_noname));
+ return -1;
+ }
+ char c = *tail;
+ *tail = NUL;
+ int r;
+ char *failed_dir;
+ if (((r = os_mkdir_recurse(fname, mode, &failed_dir)) < 0)) {
+ semsg(_(e_mkdir), failed_dir, os_strerror(r));
+ xfree(failed_dir);
+ }
+ *tail = c;
+ return r;
+ }
+ return 0;
+}
+
/// Create a unique temporary directory.
///
/// @param[in] template Template of the path to the directory with XXXXXX
@@ -1208,7 +1279,7 @@ char *os_realpath(const char *name, char *buf)
return result == kLibuvSuccess ? buf : NULL;
}
-#ifdef WIN32
+#ifdef MSWIN
# include <shlobj.h>
/// When "fname" is the name of a shortcut (*.lnk) resolve the file it points
@@ -1310,7 +1381,7 @@ bool os_is_reparse_point_include(const char *path)
}
p = utf16_path;
- if (isalpha(p[0]) && p[1] == L':' && IS_PATH_SEP(p[2])) {
+ if (isalpha((uint8_t)p[0]) && p[1] == L':' && IS_PATH_SEP(p[2])) {
p += 3;
} else if (IS_PATH_SEP(p[0]) && IS_PATH_SEP(p[1])) {
p += 2;