aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJustin M. Keyes <justinkz@gmail.com>2014-07-14 09:06:36 -0400
committerJustin M. Keyes <justinkz@gmail.com>2014-07-14 09:06:36 -0400
commitf693b4043d29ec21d990661450cdbd353da0e036 (patch)
tree4e06241295ab8e32358a06eff245431daae52d24
parentbf6b0e3c0aa34beca13eee898decdf0fcde8b502 (diff)
parent0ceebc2c913cc497735e001772cb6b395c36cecc (diff)
downloadrneovim-f693b4043d29ec21d990661450cdbd353da0e036.tar.gz
rneovim-f693b4043d29ec21d990661450cdbd353da0e036.tar.bz2
rneovim-f693b4043d29ec21d990661450cdbd353da0e036.zip
Merge #846 'impl mch_open with libuv'
-rw-r--r--src/nvim/eval.c2
-rw-r--r--src/nvim/ex_cmds.c6
-rw-r--r--src/nvim/ex_cmds2.c4
-rw-r--r--src/nvim/fileio.c40
-rw-r--r--src/nvim/macros.h7
-rw-r--r--src/nvim/memline.c6
-rw-r--r--src/nvim/os/fs.c20
-rw-r--r--src/nvim/undo.c4
-rw-r--r--test/includes/pre/sys/errno.h4
-rw-r--r--test/includes/pre/sys/fcntl.h7
-rw-r--r--test/unit/os/fs.moon71
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) ->