diff options
author | Josh Rahm <joshuarahm@gmail.com> | 2023-01-25 18:31:31 +0000 |
---|---|---|
committer | Josh Rahm <joshuarahm@gmail.com> | 2023-01-25 18:31:31 +0000 |
commit | 9243becbedbb6a1592208051f8fa2b090dcc5e7d (patch) | |
tree | 607c2a862ec3f4399b8766383f6f8e04c4aa43b4 /src/nvim/os/fs.c | |
parent | 9e40b6e9e1bc67f2d856adb837ee64dd0e25b717 (diff) | |
parent | 3c48d3c83fc21dbc0841f9210f04bdb073d73cd1 (diff) | |
download | rneovim-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.c | 149 |
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; |