diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/nvim/fileio.c | 6 | ||||
| -rw-r--r-- | src/nvim/os/fs.c | 67 | ||||
| -rw-r--r-- | src/nvim/os/fs_defs.h | 6 | ||||
| -rw-r--r-- | src/nvim/os_unix.c | 20 | ||||
| -rw-r--r-- | src/nvim/os_unix.h | 6 | 
5 files changed, 75 insertions, 30 deletions
diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c index c431f721dd..b9d9ea5457 100644 --- a/src/nvim/fileio.c +++ b/src/nvim/fileio.c @@ -2576,7 +2576,7 @@ buf_write (          errmsg = (char_u *)_("is a directory");          goto fail;        } -      if (mch_nodetype(fname) != NODE_WRITABLE) { +      if (os_nodetype((char *)fname) != NODE_WRITABLE) {          errnum = (char_u *)"E503: ";          errmsg = (char_u *)_("is not a file or writable device");          goto fail; @@ -2588,11 +2588,11 @@ buf_write (        perm = -1;      }    } -#else /* !UNIX */ +#else /* win32 */        /*         * Check for a writable device name.         */ -  c = mch_nodetype(fname); +  c = os_nodetype((char *)fname);    if (c == NODE_OTHER) {      errnum = (char_u *)"E503: ";      errmsg = (char_u *)_("is not a file or writable device"); diff --git a/src/nvim/os/fs.c b/src/nvim/os/fs.c index bc2d37764d..3d5281a636 100644 --- a/src/nvim/os/fs.c +++ b/src/nvim/os/fs.c @@ -94,9 +94,74 @@ bool os_isdir(const char_u *name)    return true;  } +/// Check what `name` is: +/// @return NODE_NORMAL: file or directory (or doesn't exist) +///         NODE_WRITABLE: writable device, socket, fifo, etc. +///         NODE_OTHER: non-writable things +int os_nodetype(const char *name) +{ +#ifdef WIN32 +  // 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) { +    return NODE_WRITABLE; +  } +#endif + +  uv_stat_t statbuf; +  if (os_stat(name, &statbuf) == 0) { +    return NODE_NORMAL; +  } + +#ifndef WIN32 +  // libuv does not handle BLK and DIR in uv_handle_type. +  //    Related: https://github.com/joyent/libuv/pull/1421 +  if (S_ISREG(statbuf.st_mode) || S_ISDIR(statbuf.st_mode)) { +    return NODE_NORMAL; +  } +  if (S_ISBLK(statbuf.st_mode)) {  // block device isn't writable +    return NODE_OTHER; +  } +#endif + +  // Vim os_win32.c:mch_nodetype does this (since patch 7.4.015): +  //    if (enc_codepage >= 0 && (int)GetACP() != enc_codepage) { +  //      wn = enc_to_utf16(name, NULL); +  //      hFile = CreatFile(wn, ...) +  // to get a HANDLE. But libuv just calls win32's _get_osfhandle() on the fd we +  // give it. uv_fs_open calls fs__capture_path which does a similar dance and +  // saves us the hassle. + +  int nodetype = NODE_WRITABLE; +  int fd = os_open(name, O_RDONLY, 0); +  switch(uv_guess_handle(fd)) { +    case UV_TTY:         // FILE_TYPE_CHAR +      nodetype = NODE_WRITABLE; +      break; +    case UV_FILE:        // FILE_TYPE_DISK +      nodetype = NODE_NORMAL; +      break; +    case UV_NAMED_PIPE:  // not handled explicitly in Vim os_win32.c +    case UV_UDP:         // unix only +    case UV_TCP:         // unix only +    case UV_UNKNOWN_HANDLE: +    default: +#ifdef WIN32 +      nodetype = NODE_OTHER; +#else +      nodetype = NODE_WRITABLE;  // Everything else is writable? +#endif +      break; +  } + +  close(fd); +  return nodetype; +} +  /// Checks if the given path represents an executable file.  /// -/// @param[in]  name     The name of the executable. +/// @param[in]  name     Name of the executable.  /// @param[out] abspath  Path of the executable, if found and not `NULL`.  ///  /// @return `true` if `name` is executable and diff --git a/src/nvim/os/fs_defs.h b/src/nvim/os/fs_defs.h index 52b2841514..0bd9c37750 100644 --- a/src/nvim/os/fs_defs.h +++ b/src/nvim/os/fs_defs.h @@ -26,4 +26,10 @@ typedef struct {  /// negative libuv error codes are returned by a number of os functions.  #define os_strerror uv_strerror +// Values returned by os_nodetype() +#define NODE_NORMAL     0  // file or directory, check with os_isdir() +#define NODE_WRITABLE   1  // something we can write to (character +                           // device, fifo, socket, ..) +#define NODE_OTHER      2  // non-writable thing (e.g., block device) +  #endif  // NVIM_OS_FS_DEFS_H diff --git a/src/nvim/os_unix.c b/src/nvim/os_unix.c index 2a859a0f7a..63a3dbc054 100644 --- a/src/nvim/os_unix.c +++ b/src/nvim/os_unix.c @@ -136,26 +136,6 @@ void mch_free_acl(vim_acl_T aclent)  }  #endif -/* - * Check what "name" is: - * NODE_NORMAL: file or directory (or doesn't exist) - * NODE_WRITABLE: writable device, socket, fifo, etc. - * NODE_OTHER: non-writable things - */ -int mch_nodetype(char_u *name) -{ -  struct stat st; - -  if (stat((char *)name, &st)) -    return NODE_NORMAL; -  if (S_ISREG(st.st_mode) || S_ISDIR(st.st_mode)) -    return NODE_NORMAL; -  if (S_ISBLK(st.st_mode))      /* block device isn't writable */ -    return NODE_OTHER; -  /* Everything else is writable? */ -  return NODE_WRITABLE; -} -  void mch_exit(int r)  {    exiting = true; diff --git a/src/nvim/os_unix.h b/src/nvim/os_unix.h index 5a3eb84ba4..d627b16ec0 100644 --- a/src/nvim/os_unix.h +++ b/src/nvim/os_unix.h @@ -4,12 +4,6 @@  #include "nvim/types.h"  // for vim_acl_T  #include "nvim/os/shell.h" -/* Values returned by mch_nodetype() */ -#define NODE_NORMAL     0       /* file or directory, check with os_isdir()*/ -#define NODE_WRITABLE   1       /* something we can write to (character -                                   device, fifo, socket, ..) */ -#define NODE_OTHER      2       /* non-writable thing (e.g., block device) */ -  #ifdef INCLUDE_GENERATED_DECLARATIONS  # include "os_unix.h.generated.h"  #endif  | 
