Move mch_can_exe, executable_file to os/fs.c.

* Rename executable_file to is_executable.
This commit is contained in:
Thomas Wienecke
2014-03-06 14:21:02 +01:00
committed by Thiago de Arruda
parent 1468c12fd1
commit d5b223afe2
5 changed files with 102 additions and 91 deletions

View File

@@ -15,6 +15,7 @@
#include "os.h" #include "os.h"
#include "../message.h" #include "../message.h"
#include "../misc1.h"
#include "../misc2.h" #include "../misc2.h"
int mch_chdir(char *path) { int mch_chdir(char *path) {
@@ -191,3 +192,86 @@ int mch_isdir(char_u *name)
return TRUE; return TRUE;
} }
int is_executable(char_u *name);
/*
* Return 1 if "name" is an executable file, 0 if not or it doesn't exist.
*/
int is_executable(char_u *name)
{
uv_fs_t request;
if (0 != uv_fs_stat(uv_default_loop(), &request, (const char*) name, NULL)) {
return FALSE;
}
if (S_ISREG(request.statbuf.st_mode) &&
(S_IEXEC & request.statbuf.st_mode)) {
return TRUE;
}
return FALSE;
}
/*
* Return 1 if "name" can be found in $PATH and executed, 0 if not.
* Return -1 if unknown.
*/
int mch_can_exe(char_u *name)
{
char_u *buf;
char_u *path, *e;
int retval;
/* If it's an absolute or relative path don't need to use $PATH. */
if (mch_is_absolute_path(name) ||
(name[0] == '.' && (name[1] == '/' ||
(name[1] == '.' && name[2] == '/')))) {
return is_executable(name);
}
path = (char_u *)getenv("PATH");
/* PATH environment variable does not exist or is empty. */
if (path == NULL || *path == NUL) {
return -1;
}
int buf_len = STRLEN(name) + STRLEN(path) + 2;
buf = alloc((unsigned)(buf_len));
if (buf == NULL) {
return -1;
}
/*
* Walk through all entries in $PATH to check if "name" exists there and
* is an executable file.
*/
for (;; ) {
e = (char_u *)strchr((char *)path, ':');
if (e == NULL) {
e = path + STRLEN(path);
}
if (e - path <= 1) { /* empty entry means current dir */
STRCPY(buf, "./");
} else {
vim_strncpy(buf, path, e - path);
add_pathsep(buf);
}
append_path((char *) buf, (char *) name, buf_len);
retval = is_executable(buf);
if (retval == OK) {
break;
}
if (*e != ':') {
break;
}
path = e + 1;
}
vim_free(buf);
return retval;
}

View File

@@ -9,6 +9,7 @@ int mch_dirname(char_u *buf, int len);
int mch_get_absolute_path(char_u *fname, char_u *buf, int len, int force); int mch_get_absolute_path(char_u *fname, char_u *buf, int len, int force);
int mch_is_absolute_path(char_u *fname); int mch_is_absolute_path(char_u *fname);
int mch_isdir(char_u *name); int mch_isdir(char_u *name);
int mch_can_exe(char_u *name);
const char *mch_getenv(const char *name); const char *mch_getenv(const char *name);
int mch_setenv(const char *name, const char *value, int overwrite); int mch_setenv(const char *name, const char *value, int overwrite);
char *mch_getenvname_at_index(size_t index); char *mch_getenvname_at_index(size_t index);

View File

@@ -1319,71 +1319,6 @@ void mch_hide(char_u *name)
/* can't hide a file */ /* can't hide a file */
} }
int executable_file(char_u *name);
/*
* Return 1 if "name" is an executable file, 0 if not or it doesn't exist.
*/
int executable_file(char_u *name)
{
struct stat st;
if (stat((char *)name, &st))
return 0;
return S_ISREG(st.st_mode) && mch_access((char *)name, X_OK) == 0;
}
/*
* Return 1 if "name" can be found in $PATH and executed, 0 if not.
* Return -1 if unknown.
*/
int mch_can_exe(char_u *name)
{
char_u *buf;
char_u *p, *e;
int retval;
/* If it's an absolute or relative path don't need to use $PATH. */
if (mch_is_absolute_path(name) || (name[0] == '.' && (name[1] == '/'
|| (name[1] == '.' &&
name[2] == '/'))))
return executable_file(name);
p = (char_u *)mch_getenv("PATH");
if (p == NULL || *p == NUL)
return -1;
buf = alloc((unsigned)(STRLEN(name) + STRLEN(p) + 2));
if (buf == NULL)
return -1;
/*
* Walk through all entries in $PATH to check if "name" exists there and
* is an executable file.
*/
for (;; ) {
e = (char_u *)strchr((char *)p, ':');
if (e == NULL)
e = p + STRLEN(p);
if (e - p <= 1) /* empty entry means current dir */
STRCPY(buf, "./");
else {
vim_strncpy(buf, p, e - p);
add_pathsep(buf);
}
STRCAT(buf, name);
retval = executable_file(buf);
if (retval == 1)
break;
if (*e != ':')
break;
p = e + 1;
}
vim_free(buf);
return retval;
}
/* /*
* Check what "name" is: * Check what "name" is:
* NODE_NORMAL: file or directory (or doesn't exist) * NODE_NORMAL: file or directory (or doesn't exist)

View File

@@ -37,7 +37,6 @@ vim_acl_T mch_get_acl(char_u *fname);
void mch_set_acl(char_u *fname, vim_acl_T aclent); void mch_set_acl(char_u *fname, vim_acl_T aclent);
void mch_free_acl(vim_acl_T aclent); void mch_free_acl(vim_acl_T aclent);
void mch_hide(char_u *name); void mch_hide(char_u *name);
int mch_can_exe(char_u *name);
int mch_nodetype(char_u *name); int mch_nodetype(char_u *name);
void mch_early_init(void); void mch_early_init(void);
void mch_free_mem(void); void mch_free_mem(void);

View File

@@ -7,7 +7,7 @@ enum BOOLEAN {
TRUE = 1, FALSE = 0 TRUE = 1, FALSE = 0
}; };
int mch_isdir(char_u * name); int mch_isdir(char_u * name);
int executable_file(char_u *name); int is_executable(char_u *name);
int mch_can_exe(char_u *name); int mch_can_exe(char_u *name);
]] ]]
@@ -22,15 +22,13 @@ describe 'os_unix function', ->
-- that executable for several asserts. -- that executable for several asserts.
export absolute_executable = arg[0] export absolute_executable = arg[0]
-- Split absolute_executable into a directory and the actual file name and -- Split absolute_executable into a directory and the actual file name for
-- append the directory to $PATH. -- later usage.
export directory, executable = if (string.find absolute_executable, '/') export directory, executable_name = if (string.find absolute_executable, '/')
string.match(absolute_executable, '^(.*)/(.*)$') string.match(absolute_executable, '^(.*)/(.*)$')
else else
string.match(absolute_executable, '^(.*)\\(.*)$') string.match(absolute_executable, '^(.*)\\(.*)$')
package.path = package.path .. ';' .. directory
teardown -> teardown ->
lfs.rmdir 'unit-test-directory' lfs.rmdir 'unit-test-directory'
@@ -57,25 +55,25 @@ describe 'os_unix function', ->
it 'returns true if an arbitrary directory is given', -> it 'returns true if an arbitrary directory is given', ->
eq TRUE, (mch_isdir 'unit-test-directory') eq TRUE, (mch_isdir 'unit-test-directory')
describe 'executable_file', -> describe 'is_executable', ->
executable_file = (name) -> is_executable = (name) ->
name = cstr (string.len name), name name = cstr (string.len name), name
os.executable_file name os.is_executable name
it 'returns false when given a directory', -> it 'returns false when given a directory', ->
eq FALSE, (executable_file 'unit-test-directory') eq FALSE, (is_executable 'unit-test-directory')
it 'returns false when the given file does not exists', -> it 'returns false when the given file does not exists', ->
eq FALSE, (executable_file 'does-not-exist.file') eq FALSE, (is_executable 'does-not-exist.file')
it 'returns true when given an executable regular file', -> it 'returns true when given an executable regular file', ->
eq TRUE, (executable_file absolute_executable) eq TRUE, (is_executable absolute_executable)
it 'returns false when given a regular file without executable bit set', -> it 'returns false when given a regular file without executable bit set', ->
-- This is a critical test since Windows does not have any executable -- This is a critical test since Windows does not have any executable
-- bit. Thus executable_file returns TRUE on every regular file on -- bit. Thus is_executable returns TRUE on every regular file on
-- Windows and this test will fail. -- Windows and this test will fail.
eq FALSE, (executable_file 'unit-test-directory/test.file') eq FALSE, (is_executable 'unit-test-directory/test.file')
describe 'mch_can_exe', -> describe 'mch_can_exe', ->
mch_can_exe = (name) -> mch_can_exe = (name) ->
@@ -83,23 +81,17 @@ describe 'os_unix function', ->
os.mch_can_exe name os.mch_can_exe name
it 'returns false when given a directory', -> it 'returns false when given a directory', ->
eq FALSE, (mch_can_exe 'unit-test-directory') eq FALSE, (mch_can_exe './unit-test-directory')
it 'returns false when the given file does not exists', -> it 'returns false when the given file does not exists', ->
eq FALSE, (mch_can_exe 'does-not-exist.file') eq FALSE, (mch_can_exe 'does-not-exist.file')
it 'returns true when given an executable in the current directory', ->
old_dir = lfs.currentdir!
lfs.chdir directory
eq TRUE, (mch_can_exe executable)
lfs.chdir old_dir
it 'returns true when given an executable inside $PATH', -> it 'returns true when given an executable inside $PATH', ->
eq TRUE, (mch_can_exe executable) eq TRUE, (mch_can_exe executable_name)
it 'returns true when given an executable relative to the current dir', -> it 'returns true when given an executable relative to the current dir', ->
old_dir = lfs.currentdir! old_dir = lfs.currentdir!
lfs.chdir directory lfs.chdir directory
relative_executable = './' .. executable relative_executable = './' .. executable_name
eq TRUE, (mch_can_exe relative_executable) eq TRUE, (mch_can_exe relative_executable)
lfs.chdir old_dir lfs.chdir old_dir