diff options
author | Justin M. Keyes <justinkz@gmail.com> | 2014-07-14 09:06:36 -0400 |
---|---|---|
committer | Justin M. Keyes <justinkz@gmail.com> | 2014-07-14 09:06:36 -0400 |
commit | f693b4043d29ec21d990661450cdbd353da0e036 (patch) | |
tree | 4e06241295ab8e32358a06eff245431daae52d24 | |
parent | bf6b0e3c0aa34beca13eee898decdf0fcde8b502 (diff) | |
parent | 0ceebc2c913cc497735e001772cb6b395c36cecc (diff) | |
download | rneovim-f693b4043d29ec21d990661450cdbd353da0e036.tar.gz rneovim-f693b4043d29ec21d990661450cdbd353da0e036.tar.bz2 rneovim-f693b4043d29ec21d990661450cdbd353da0e036.zip |
Merge #846 'impl mch_open with libuv'
-rw-r--r-- | src/nvim/eval.c | 2 | ||||
-rw-r--r-- | src/nvim/ex_cmds.c | 6 | ||||
-rw-r--r-- | src/nvim/ex_cmds2.c | 4 | ||||
-rw-r--r-- | src/nvim/fileio.c | 40 | ||||
-rw-r--r-- | src/nvim/macros.h | 7 | ||||
-rw-r--r-- | src/nvim/memline.c | 6 | ||||
-rw-r--r-- | src/nvim/os/fs.c | 20 | ||||
-rw-r--r-- | src/nvim/undo.c | 4 | ||||
-rw-r--r-- | test/includes/pre/sys/errno.h | 4 | ||||
-rw-r--r-- | test/includes/pre/sys/fcntl.h | 7 | ||||
-rw-r--r-- | test/unit/os/fs.moon | 71 |
11 files changed, 125 insertions, 46 deletions
diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 5216c7fb28..0a15c0b376 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -8317,7 +8317,7 @@ static void f_filereadable(typval_T *argvars, typval_T *rettv) # define O_NONBLOCK 0 #endif p = get_tv_string(&argvars[0]); - if (*p && !os_isdir(p) && (fd = mch_open((char *)p, + if (*p && !os_isdir(p) && (fd = os_open((char *)p, O_RDONLY | O_NONBLOCK, 0)) >= 0) { n = TRUE; close(fd); diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c index d8cd7961fb..78325fd4a4 100644 --- a/src/nvim/ex_cmds.c +++ b/src/nvim/ex_cmds.c @@ -1575,19 +1575,19 @@ void write_viminfo(char_u *file, int forceit) if (tempname != NULL) { int fd; - /* Use mch_open() to be able to use O_NOFOLLOW and set file + /* Use os_open() to be able to use O_NOFOLLOW and set file * protection: * Unix: same as original file, but strip s-bit. Reset umask to * avoid it getting in the way. * Others: r&w for user only. */ # ifdef UNIX umask_save = umask(0); - fd = mch_open((char *)tempname, + fd = os_open((char *)tempname, O_CREAT|O_EXCL|O_WRONLY|O_NOFOLLOW, (int)((old_info.stat.st_mode & 0777) | 0600)); (void)umask(umask_save); # else - fd = mch_open((char *)tempname, + fd = os_open((char *)tempname, O_CREAT|O_EXCL|O_WRONLY|O_NOFOLLOW, 0600); # endif if (fd < 0) diff --git a/src/nvim/ex_cmds2.c b/src/nvim/ex_cmds2.c index 3158eafe65..85a9e9315a 100644 --- a/src/nvim/ex_cmds2.c +++ b/src/nvim/ex_cmds2.c @@ -2372,9 +2372,9 @@ int source_level(void *cookie) */ static FILE *fopen_noinh_readbin(char *filename) { - int fd_tmp = mch_open(filename, O_RDONLY, 0); + int fd_tmp = os_open(filename, O_RDONLY, 0); - if (fd_tmp == -1) + if (fd_tmp < 0) return NULL; # ifdef HAVE_FD_CLOEXEC diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c index f4d4005fa8..ea32e19b50 100644 --- a/src/nvim/fileio.c +++ b/src/nvim/fileio.c @@ -428,7 +428,7 @@ readfile ( #ifdef UNIX /* * On Unix it is possible to read a directory, so we have to - * check for it before the mch_open(). + * check for it before os_open(). */ perm = os_getperm(fname); if (perm >= 0 && !S_ISREG(perm) /* not a regular file ... */ @@ -507,13 +507,13 @@ readfile ( if (!read_buffer && !read_stdin) { if (!newfile || readonlymode) { file_readonly = TRUE; - } else if ((fd = mch_open((char *)fname, O_RDWR, 0)) < 0) { + } else if ((fd = os_open((char *)fname, O_RDWR, 0)) < 0) { // opening in readwrite mode failed => file is readonly file_readonly = TRUE; } if (file_readonly == TRUE) { // try to open readonly - fd = mch_open((char *)fname, O_RDONLY, 0); + fd = os_open((char *)fname, O_RDONLY, 0); } } @@ -696,9 +696,7 @@ readfile ( if (!read_stdin && (curbuf != old_curbuf || (using_b_ffname && (old_b_ffname != curbuf->b_ffname)) || (using_b_fname && (old_b_fname != curbuf->b_fname)) - || (fd = - mch_open((char *)fname, O_RDONLY, - 0)) < 0)) { + || (fd = os_open((char *)fname, O_RDONLY, 0)) < 0)) { --no_wait_return; msg_scroll = msg_save; if (fd < 0) @@ -2157,9 +2155,9 @@ readfile_charconvert ( if (eval_charconvert(fenc, enc_utf8 ? (char_u *)"utf-8" : p_enc, fname, tmpname) == FAIL) errmsg = (char_u *)_("Conversion with 'charconvert' failed"); - if (errmsg == NULL && (*fdp = mch_open((char *)tmpname, - O_RDONLY, 0)) < 0) + if (errmsg == NULL && (*fdp = os_open((char *)tmpname, O_RDONLY, 0)) < 0) { errmsg = (char_u *)_("can't read output of 'charconvert'"); + } } if (errmsg != NULL) { @@ -2174,8 +2172,9 @@ readfile_charconvert ( } /* If the input file is closed, open it (caller should check for error). */ - if (*fdp < 0) - *fdp = mch_open((char *)fname, O_RDONLY, 0); + if (*fdp < 0) { + *fdp = os_open((char *)fname, O_RDONLY, 0); + } return tmpname; } @@ -2737,7 +2736,7 @@ buf_write ( break; } } - fd = mch_open((char *)IObuff, + fd = os_open((char *)IObuff, O_CREAT|O_WRONLY|O_EXCL|O_NOFOLLOW, perm); if (fd < 0) /* can't write in directory */ backup_copy = TRUE; @@ -2791,8 +2790,7 @@ buf_write ( else backup_ext = p_bex; - if (backup_copy - && (fd = mch_open((char *)fname, O_RDONLY, 0)) >= 0) { + if (backup_copy && (fd = os_open((char *)fname, O_RDONLY, 0)) >= 0) { int bfd; char_u *copybuf, *wp; int some_error = FALSE; @@ -2890,7 +2888,7 @@ buf_write ( os_remove((char *)backup); /* Open with O_EXCL to avoid the file being created while * we were sleeping (symlink hacker attack?) */ - bfd = mch_open((char *)backup, + bfd = os_open((char *)backup, O_WRONLY|O_CREAT|O_EXCL|O_NOFOLLOW, perm & 0777); if (bfd < 0) { @@ -3194,7 +3192,7 @@ nobackup: * (this may happen when the user reached his quotum for number of files). * Appending will fail if the file does not exist and forceit is FALSE. */ - while ((fd = mch_open((char *)wfname, O_WRONLY | (append + while ((fd = os_open((char *)wfname, O_WRONLY | (append ? (forceit ? ( O_APPEND | O_CREAT) : @@ -3515,8 +3513,8 @@ restore_backup: MSG(_(e_interr)); out_flush(); } - if ((fd = mch_open((char *)backup, O_RDONLY, 0)) >= 0) { - if ((write_info.bw_fd = mch_open((char *)fname, + if ((fd = os_open((char *)backup, O_RDONLY, 0)) >= 0) { + if ((write_info.bw_fd = os_open((char *)fname, O_WRONLY | O_CREAT | O_TRUNC, perm & 0777)) >= 0) { /* copy the file. */ @@ -3646,7 +3644,7 @@ restore_backup: int empty_fd; if (org == NULL - || (empty_fd = mch_open(org, + || (empty_fd = os_open(org, O_CREAT | O_EXCL | O_NOFOLLOW, perm < 0 ? 0666 : (perm & 0777))) < 0) EMSG(_("E206: patchmode: can't touch empty original file")); @@ -4615,7 +4613,7 @@ int vim_rename(char_u *from, char_u *to) /* For systems that support ACL: get the ACL from the original file. */ acl = mch_get_acl(from); #endif - fd_in = mch_open((char *)from, O_RDONLY, 0); + fd_in = os_open((char *)from, O_RDONLY, 0); if (fd_in == -1) { #ifdef HAVE_ACL mch_free_acl(acl); @@ -4624,7 +4622,7 @@ int vim_rename(char_u *from, char_u *to) } /* Create the new file with same permissions as the original. */ - fd_out = mch_open((char *)to, + fd_out = os_open((char *)to, O_CREAT|O_EXCL|O_WRONLY|O_NOFOLLOW, (int)perm); if (fd_out == -1) { close(fd_in); @@ -4660,7 +4658,7 @@ int vim_rename(char_u *from, char_u *to) errmsg = _("E210: Error reading \"%s\""); to = from; } -#ifndef UNIX /* for Unix mch_open() already set the permission */ +#ifndef UNIX /* for Unix os_open() already set the permission */ os_setperm(to, perm); #endif #ifdef HAVE_ACL diff --git a/src/nvim/macros.h b/src/nvim/macros.h index fab4f548c8..bff19f17dd 100644 --- a/src/nvim/macros.h +++ b/src/nvim/macros.h @@ -108,13 +108,12 @@ #endif # define mch_fopen(n, p) fopen((n), (p)) -# define mch_open(n, m, p) open((n), (m), (p)) -/* mch_open_rw(): invoke mch_open() with third argument for user R/W. */ +/* mch_open_rw(): invoke os_open() with third argument for user R/W. */ #if defined(UNIX) /* open in rw------- mode */ -# define mch_open_rw(n, f) mch_open((n), (f), (mode_t)0600) +# define mch_open_rw(n, f) os_open((n), (f), (mode_t)0600) #else -# define mch_open_rw(n, f) mch_open((n), (f), 0) +# define mch_open_rw(n, f) os_open((n), (f), 0) #endif #ifdef STARTUPTIME diff --git a/src/nvim/memline.c b/src/nvim/memline.c index 2627d98292..2fb404a148 100644 --- a/src/nvim/memline.c +++ b/src/nvim/memline.c @@ -440,7 +440,7 @@ void ml_setname(buf_T *buf) } if (mfp->mf_fd == -1) { /* need to (re)open the swap file */ - mfp->mf_fd = mch_open((char *)mfp->mf_fname, O_RDWR, 0); + mfp->mf_fd = os_open((char *)mfp->mf_fname, O_RDWR, 0); if (mfp->mf_fd < 0) { /* could not (re)open the swap file, what can we do???? */ EMSG(_("E301: Oops, lost the swap file!!!")); @@ -1517,7 +1517,7 @@ static time_t swapfile_info(char_u *fname) /* * print the original file name */ - fd = mch_open((char *)fname, O_RDONLY, 0); + fd = os_open((char *)fname, O_RDONLY, 0); if (fd >= 0) { if (read_eintr(fd, &b0, sizeof(b0)) == sizeof(b0)) { if (STRNCMP(b0.b0_version, "VIM 3.0", 7) == 0) { @@ -3329,7 +3329,7 @@ findswapname ( * Try to read block 0 from the swap file to get the original * file name (and inode number). */ - fd = mch_open((char *)fname, O_RDONLY, 0); + fd = os_open((char *)fname, O_RDONLY, 0); if (fd >= 0) { if (read_eintr(fd, &b0, sizeof(b0)) == sizeof(b0)) { /* diff --git a/src/nvim/os/fs.c b/src/nvim/os/fs.c index c1cb418d5c..dce95eb3c9 100644 --- a/src/nvim/os/fs.c +++ b/src/nvim/os/fs.c @@ -150,6 +150,24 @@ static bool is_executable_in_path(const char_u *name) return false; } +/// Opens or creates a file and returns a non-negative integer representing +/// the lowest-numbered unused file descriptor, for use in subsequent system +/// calls (read, write, lseek, fcntl, etc.). If the operation fails, `-errno` +/// is returned, and no file is created or modified. +/// +/// @param flags Bitwise OR of flags defined in <fcntl.h> +/// @param mode Permissions for the newly-created file (IGNORED if 'flags' is +/// not `O_CREAT` or `O_TMPFILE`), subject to the current umask +/// @return file descriptor, or negative `errno` on failure +int os_open(const char* path, int flags, int mode) +{ + uv_fs_t open_req; + int r = uv_fs_open(uv_default_loop(), &open_req, path, flags, mode, NULL); + uv_fs_req_cleanup(&open_req); + // r is the same as open_req.result (except for OOM: then only r is set). + return r; +} + /// Get stat information for a file. /// /// @return OK on success, FAIL if a failure occurred. @@ -291,7 +309,7 @@ int os_remove(const char *path) /// Get the file information for a given path /// -/// @param file_descriptor File descriptor of the file. +/// @param path Path to the file. /// @param[out] file_info Pointer to a FileInfo to put the information in. /// @return `true` on success, `false` for failure. bool os_get_file_info(const char *path, FileInfo *file_info) diff --git a/src/nvim/undo.c b/src/nvim/undo.c index cb40878b43..b9f3309cef 100644 --- a/src/nvim/undo.c +++ b/src/nvim/undo.c @@ -1045,7 +1045,7 @@ void u_write_undo(char_u *name, int forceit, buf_T *buf, char_u *hash) if (os_file_exists(file_name)) { if (name == NULL || !forceit) { /* Check we can read it and it's an undo file. */ - fd = mch_open((char *)file_name, O_RDONLY, 0); + fd = os_open((char *)file_name, O_RDONLY, 0); if (fd < 0) { if (name != NULL || p_verbose > 0) { if (name == NULL) @@ -1089,7 +1089,7 @@ void u_write_undo(char_u *name, int forceit, buf_T *buf, char_u *hash) goto theend; } - fd = mch_open((char *)file_name, + fd = os_open((char *)file_name, O_CREAT|O_WRONLY|O_EXCL|O_NOFOLLOW, perm); if (fd < 0) { EMSG2(_(e_not_open), file_name); diff --git a/test/includes/pre/sys/errno.h b/test/includes/pre/sys/errno.h new file mode 100644 index 0000000000..0b8934d33e --- /dev/null +++ b/test/includes/pre/sys/errno.h @@ -0,0 +1,4 @@ +#include <sys/errno.h> + +static const int kENOENT = ENOENT; +static const int kEEXIST = EEXIST; diff --git a/test/includes/pre/sys/fcntl.h b/test/includes/pre/sys/fcntl.h new file mode 100644 index 0000000000..767c97a631 --- /dev/null +++ b/test/includes/pre/sys/fcntl.h @@ -0,0 +1,7 @@ +#include <sys/fcntl.h> + +static const mode_t kO_RDONLY = O_RDONLY; +static const mode_t kO_WRONLY = O_WRONLY; +static const mode_t kO_RDWR = O_RDWR; +static const mode_t kO_CREAT = O_CREAT; +static const mode_t kO_EXCL = O_EXCL; diff --git a/test/unit/os/fs.moon b/test/unit/os/fs.moon index 1d4d7448f5..a1445aeb0c 100644 --- a/test/unit/os/fs.moon +++ b/test/unit/os/fs.moon @@ -9,6 +9,14 @@ FAIL = 0 OK = 1 cppimport 'sys/stat.h' +cppimport 'sys/fcntl.h' +cppimport 'sys/errno.h' + +assert_file_exists = (filepath) -> + eq false, nil == (lfs.attributes filepath, 'r') + +assert_file_does_not_exist = (filepath) -> + eq true, nil == (lfs.attributes filepath, 'r') describe 'fs function', -> setup -> @@ -217,12 +225,6 @@ describe 'fs function', -> eq 2, os_file_is_writable 'unit-test-directory' describe 'file operations', -> - setup -> - (io.open 'unit-test-directory/test_remove.file', 'w').close! - - teardown -> - os.remove 'unit-test-directory/test_remove.file' - os_file_exists = (filename) -> fs.os_file_exists (to_cstr filename) @@ -232,6 +234,9 @@ describe 'fs function', -> os_remove = (path) -> fs.os_remove (to_cstr path) + os_open = (path, flags, mode) -> + fs.os_open (to_cstr path), flags, mode + describe 'os_file_exists', -> it 'returns false when given a non-existing file', -> eq false, (os_file_exists 'non-existing-file') @@ -267,13 +272,61 @@ describe 'fs function', -> file\close! describe 'os_remove', -> + before_each -> + (io.open 'unit-test-directory/test_remove.file', 'w').close! + after_each -> + os.remove 'unit-test-directory/test_remove.file' + it 'returns non-zero when given a non-existing file', -> neq 0, (os_remove 'non-existing-file') it 'removes the given file and returns 0', -> - eq true, (os_file_exists 'unit-test-directory/test_remove.file') - eq 0, (os_remove 'unit-test-directory/test_remove.file') - eq false, (os_file_exists 'unit-test-directory/test_remove.file') + f = 'unit-test-directory/test_remove.file' + assert_file_exists f + eq 0, (os_remove f) + assert_file_does_not_exist f + + describe 'os_open', -> + before_each -> + (io.open 'unit-test-directory/test_existing.file', 'w').close! + after_each -> + os.remove 'unit-test-directory/test_existing.file' + os.remove 'test_new_file' + + new_file = 'test_new_file' + existing_file = 'unit-test-directory/test_existing.file' + + it 'returns -ENOENT for O_RDWR on a non-existing file', -> + eq -ffi.C.kENOENT, (os_open 'non-existing-file', ffi.C.kO_RDWR, 0) + + it 'returns non-negative for O_CREAT on a non-existing file', -> + assert_file_does_not_exist new_file + assert.is_true 0 <= (os_open new_file, ffi.C.kO_CREAT, 0) + + it 'returns non-negative for O_CREAT on a existing file', -> + assert_file_exists existing_file + assert.is_true 0 <= (os_open existing_file, ffi.C.kO_CREAT, 0) + + it 'returns -EEXIST for O_CREAT|O_EXCL on a existing file', -> + assert_file_exists existing_file + eq -ffi.C.kEEXIST, (os_open existing_file, (bit.bor ffi.C.kO_CREAT, ffi.C.kO_EXCL), 0) + + it 'sets `rwx` permissions for O_CREAT 700', -> + assert_file_does_not_exist new_file + --create the file + os_open new_file, ffi.C.kO_CREAT, tonumber("700", 8) + --verify permissions + eq 'rwx------', lfs.attributes(new_file)['permissions'] + + it 'sets `rw` permissions for O_CREAT 600', -> + assert_file_does_not_exist new_file + --create the file + os_open new_file, ffi.C.kO_CREAT, tonumber("600", 8) + --verify permissions + eq 'rw-------', lfs.attributes(new_file)['permissions'] + + it 'returns a non-negative file descriptor for an existing file', -> + assert.is_true 0 <= (os_open existing_file, ffi.C.kO_RDWR, 0) describe 'folder operations', -> os_mkdir = (path, mode) -> |