mirror of
https://github.com/neovim/neovim.git
synced 2024-12-20 03:05:11 -07:00
os/fileio: Add ability to use os/fileio.c for file descriptors
Code imported from #6299
This commit is contained in:
parent
5ab9e9f617
commit
72b3fd9664
@ -49,7 +49,6 @@ int file_open(FileDescriptor *const ret_fp, const char *const fname,
|
||||
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
|
||||
{
|
||||
int os_open_flags = 0;
|
||||
int fd;
|
||||
TriState wr = kNone;
|
||||
// -V:FLAG:501
|
||||
#define FLAG(flags, flag, fcntl_flags, wrval, cond) \
|
||||
@ -74,14 +73,35 @@ int file_open(FileDescriptor *const ret_fp, const char *const fname,
|
||||
FLAG(flags, kFileNoSymlink, O_NOFOLLOW, kNone, true);
|
||||
#endif
|
||||
#undef FLAG
|
||||
// wr is used for kFileReadOnly flag, but on
|
||||
// QB:neovim-qb-slave-ubuntu-12-04-64bit it still errors out with
|
||||
// `error: variable ‘wr’ set but not used [-Werror=unused-but-set-variable]`
|
||||
(void)wr;
|
||||
|
||||
fd = os_open(fname, os_open_flags, mode);
|
||||
const int fd = os_open(fname, os_open_flags, mode);
|
||||
|
||||
if (fd < 0) {
|
||||
return fd;
|
||||
}
|
||||
return file_open_fd(ret_fp, fd, (wr == kTrue));
|
||||
}
|
||||
|
||||
ret_fp->wr = (wr == kTrue);
|
||||
/// Wrap file descriptor with FileDescriptor structure
|
||||
///
|
||||
/// @warning File descriptor wrapped like this must not be accessed by other
|
||||
/// means.
|
||||
///
|
||||
/// @param[out] ret_fp Address where information needed for reading from or
|
||||
/// writing to a file is saved
|
||||
/// @param[in] fd File descriptor to wrap.
|
||||
/// @param[in] wr True if fd is opened for writing only, false if it is read
|
||||
/// only.
|
||||
///
|
||||
/// @return Error code (@see os_strerror()) or 0. Currently always returns 0.
|
||||
int file_open_fd(FileDescriptor *const ret_fp, const int fd, const bool wr)
|
||||
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
|
||||
{
|
||||
ret_fp->wr = wr;
|
||||
ret_fp->fd = fd;
|
||||
ret_fp->eof = false;
|
||||
ret_fp->rv = rbuffer_new(kRWBufferSize);
|
||||
@ -115,6 +135,26 @@ FileDescriptor *file_open_new(int *const error, const char *const fname,
|
||||
return fp;
|
||||
}
|
||||
|
||||
/// Like file_open_fd(), but allocate and return ret_fp
|
||||
///
|
||||
/// @param[out] error Error code, @see os_strerror(). Is set to zero on
|
||||
/// success.
|
||||
/// @param[in] fd File descriptor to wrap.
|
||||
/// @param[in] wr True if fd is opened for writing only, false if it is read
|
||||
/// only.
|
||||
///
|
||||
/// @return [allocated] Opened file or NULL in case of error.
|
||||
FileDescriptor *file_open_fd_new(int *const error, const int fd, const bool wr)
|
||||
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_MALLOC FUNC_ATTR_WARN_UNUSED_RESULT
|
||||
{
|
||||
FileDescriptor *const fp = xmalloc(sizeof(*fp));
|
||||
if ((*error = file_open_fd(fp, fd, wr)) != 0) {
|
||||
xfree(fp);
|
||||
return NULL;
|
||||
}
|
||||
return fp;
|
||||
}
|
||||
|
||||
/// Close file and free its buffer
|
||||
///
|
||||
/// @param[in,out] fp File to close.
|
||||
|
@ -6,8 +6,10 @@ local itp = helpers.gen_itp(it)
|
||||
local eq = helpers.eq
|
||||
local ffi = helpers.ffi
|
||||
local cimport = helpers.cimport
|
||||
local cppimport = helpers.cppimport
|
||||
|
||||
local m = cimport('./src/nvim/os/fileio.h')
|
||||
local m = cimport('./src/nvim/os/os.h', './src/nvim/os/fileio.h')
|
||||
cppimport('fcntl.h')
|
||||
|
||||
local fcontents = ''
|
||||
for i = 0, 255 do
|
||||
@ -58,6 +60,18 @@ local function file_open_new(fname, flags, mode)
|
||||
return ret1[0], ret2
|
||||
end
|
||||
|
||||
local function file_open_fd(fd, flags)
|
||||
local ret2 = ffi.new('FileDescriptor')
|
||||
local ret1 = m.file_open_fd(ret2, fd, flags)
|
||||
return ret1, ret2
|
||||
end
|
||||
|
||||
local function file_open_fd_new(fd, flags)
|
||||
local ret1 = ffi.new('int[?]', 1, {0})
|
||||
local ret2 = ffi.gc(m.file_open_fd_new(ret1, fd, flags), nil)
|
||||
return ret1[0], ret2
|
||||
end
|
||||
|
||||
local function file_write(fp, buf)
|
||||
return m.file_write(fp, buf, #buf)
|
||||
end
|
||||
@ -96,6 +110,46 @@ local function file_skip(fp, size)
|
||||
return m.file_skip(fp, size)
|
||||
end
|
||||
|
||||
describe('file_open_fd', function()
|
||||
itp('can use file descriptor returned by os_open for reading', function()
|
||||
local fd = m.os_open(file1, m.kO_RDONLY, 0)
|
||||
local err, fp = file_open_fd(fd, false)
|
||||
eq(0, err)
|
||||
eq({#fcontents, fcontents}, {file_read(fp, #fcontents)})
|
||||
eq(0, m.file_close(fp, false))
|
||||
end)
|
||||
itp('can use file descriptor returned by os_open for writing', function()
|
||||
eq(nil, lfs.attributes(filec))
|
||||
local fd = m.os_open(filec, m.kO_WRONLY + m.kO_CREAT, 384)
|
||||
local err, fp = file_open_fd(fd, true)
|
||||
eq(0, err)
|
||||
eq(4, file_write(fp, 'test'))
|
||||
eq(0, m.file_close(fp, false))
|
||||
eq(4, lfs.attributes(filec).size)
|
||||
eq('test', io.open(filec):read('*a'))
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('file_open_fd_new', function()
|
||||
itp('can use file descriptor returned by os_open for reading', function()
|
||||
local fd = m.os_open(file1, m.kO_RDONLY, 0)
|
||||
local err, fp = file_open_fd_new(fd, false)
|
||||
eq(0, err)
|
||||
eq({#fcontents, fcontents}, {file_read(fp, #fcontents)})
|
||||
eq(0, m.file_free(fp, false))
|
||||
end)
|
||||
itp('can use file descriptor returned by os_open for writing', function()
|
||||
eq(nil, lfs.attributes(filec))
|
||||
local fd = m.os_open(filec, m.kO_WRONLY + m.kO_CREAT, 384)
|
||||
local err, fp = file_open_fd_new(fd, true)
|
||||
eq(0, err)
|
||||
eq(4, file_write(fp, 'test'))
|
||||
eq(0, m.file_free(fp, false))
|
||||
eq(4, lfs.attributes(filec).size)
|
||||
eq('test', io.open(filec):read('*a'))
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('file_open', function()
|
||||
itp('can create a rwx------ file with kFileCreate', function()
|
||||
local err, fp = file_open(filec, m.kFileCreate, 448)
|
||||
|
Loading…
Reference in New Issue
Block a user