diff options
| author | John Schmidt <john.schmidt.h@gmail.com> | 2014-04-08 17:50:10 +0200 |
|---|---|---|
| committer | Thiago de Arruda <tpadilha84@gmail.com> | 2014-04-08 21:56:05 -0300 |
| commit | ac620411383259400cff2f12ffe576f066ed4ca7 (patch) | |
| tree | a32272ff4afae8f7ef39f5ed94260c85a1eb92e7 /src/os | |
| parent | 6fb58d1c5c859402871e1d546f7fea1a91dd2995 (diff) | |
| download | rneovim-ac620411383259400cff2f12ffe576f066ed4ca7.tar.gz rneovim-ac620411383259400cff2f12ffe576f066ed4ca7.tar.bz2 rneovim-ac620411383259400cff2f12ffe576f066ed4ca7.zip | |
Move exe functions back to os/fs.c
Diffstat (limited to 'src/os')
| -rw-r--r-- | src/os/fs.c | 80 | ||||
| -rw-r--r-- | src/os/os.h | 10 |
2 files changed, 89 insertions, 1 deletions
diff --git a/src/os/fs.c b/src/os/fs.c index 2834b1e836..a68e66ef00 100644 --- a/src/os/fs.c +++ b/src/os/fs.c @@ -7,6 +7,9 @@ #include "misc2.h" #include "path.h" +static bool is_executable(const char_u *name); +static bool is_executable_in_path(const char_u *name); + // Many fs functions from libuv return that value on success. static const int kLibuvSuccess = 0; @@ -45,6 +48,82 @@ bool os_isdir(const char_u *name) return true; } +bool os_can_exe(const char_u *name) +{ + // If it's an absolute or relative path don't need to use $PATH. + if (path_is_absolute_path(name) || + (name[0] == '.' && (name[1] == '/' || + (name[1] == '.' && name[2] == '/')))) { + return is_executable(name); + } + + return is_executable_in_path(name); +} + +// Return true if "name" is an executable file, false if not or it doesn't +// exist. +static bool is_executable(const char_u *name) +{ + int32_t mode = os_getperm(name); + + if (mode < 0) { + return false; + } + + if (S_ISREG(mode) && (S_IEXEC & mode)) { + return true; + } + + return false; +} + +/// Check if a file is inside the $PATH and is executable. +/// +/// @return `true` if `name` is an executable inside $PATH. +static bool is_executable_in_path(const char_u *name) +{ + const char *path = getenv("PATH"); + // PATH environment variable does not exist or is empty. + if (path == NULL || *path == NUL) { + return false; + } + + int buf_len = STRLEN(name) + STRLEN(path) + 2; + char_u *buf = alloc((unsigned)(buf_len)); + + // Walk through all entries in $PATH to check if "name" exists there and + // is an executable file. + for (;; ) { + const char *e = strchr(path, ':'); + if (e == NULL) { + e = path + STRLEN(path); + } + + // Glue together the given directory from $PATH with name and save into + // buf. + vim_strncpy(buf, (char_u *) path, e - path); + append_path((char *) buf, (const char *) name, buf_len); + + if (is_executable(buf)) { + // Found our executable. Free buf and return. + vim_free(buf); + return true; + } + + if (*e != ':') { + // End of $PATH without finding any executable called name. + vim_free(buf); + return false; + } + + path = e + 1; + } + + // We should never get to this point. + assert(false); + return false; +} + int os_stat(const char_u *name, uv_stat_t *statbuf) { uv_fs_t request; @@ -123,4 +202,3 @@ int os_rename(const char_u *path, const char_u *new_path) return FAIL; } - diff --git a/src/os/os.h b/src/os/os.h index 96164a59f5..ff21a95f3a 100644 --- a/src/os/os.h +++ b/src/os/os.h @@ -21,6 +21,16 @@ int os_dirname(char_u *buf, size_t len); /// @return `true` if `fname` is a directory. bool os_isdir(const char_u *name); +/// Check if the given path represents an executable file. +/// +/// @return `true` if `name` is executable and +/// - can be found in $PATH, +/// - is relative to current dir or +/// - is absolute. +/// +/// @return `false` otherwise. +bool os_can_exe(const char_u *name); + /// Get the file permissions for a given file. /// /// @return `-1` when `name` doesn't exist. |