aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/fileio.c
diff options
context:
space:
mode:
authorJosh Rahm <joshuarahm@gmail.com>2023-01-25 18:23:01 +0000
committerJosh Rahm <joshuarahm@gmail.com>2023-01-25 18:23:01 +0000
commit142d9041391780ac15b89886a54015fdc5c73995 (patch)
tree0f6b5cac1a60810a03f52826c9e67c9e2780b033 /src/nvim/fileio.c
parentad86b5db74922285699ab2a1dbb2ff20e6268a33 (diff)
parent3c48d3c83fc21dbc0841f9210f04bdb073d73cd1 (diff)
downloadrneovim-142d9041391780ac15b89886a54015fdc5c73995.tar.gz
rneovim-142d9041391780ac15b89886a54015fdc5c73995.tar.bz2
rneovim-142d9041391780ac15b89886a54015fdc5c73995.zip
Merge remote-tracking branch 'upstream/master' into userreg
Diffstat (limited to 'src/nvim/fileio.c')
-rw-r--r--src/nvim/fileio.c618
1 files changed, 319 insertions, 299 deletions
diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c
index 30898981de..9da9d6199e 100644
--- a/src/nvim/fileio.c
+++ b/src/nvim/fileio.c
@@ -6,62 +6,72 @@
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
+#include <iconv.h>
#include <inttypes.h>
+#include <limits.h>
#include <stdbool.h>
+#include <stdio.h>
#include <string.h>
+#include <sys/stat.h>
+#include <uv.h>
-#include "nvim/api/private/helpers.h"
+#include "auto/config.h"
#include "nvim/ascii.h"
+#include "nvim/autocmd.h"
#include "nvim/buffer.h"
+#include "nvim/buffer_defs.h"
#include "nvim/buffer_updates.h"
#include "nvim/change.h"
-#include "nvim/charset.h"
#include "nvim/cursor.h"
#include "nvim/diff.h"
#include "nvim/drawscreen.h"
#include "nvim/edit.h"
#include "nvim/eval.h"
-#include "nvim/eval/typval.h"
-#include "nvim/eval/userfunc.h"
#include "nvim/ex_cmds.h"
-#include "nvim/ex_docmd.h"
#include "nvim/ex_eval.h"
#include "nvim/fileio.h"
#include "nvim/fold.h"
-#include "nvim/func_attr.h"
#include "nvim/garray.h"
#include "nvim/getchar.h"
-#include "nvim/hashtab.h"
+#include "nvim/gettext.h"
+#include "nvim/globals.h"
+#include "nvim/highlight_defs.h"
#include "nvim/iconv.h"
#include "nvim/input.h"
+#include "nvim/log.h"
+#include "nvim/macros.h"
#include "nvim/mbyte.h"
#include "nvim/memfile.h"
#include "nvim/memline.h"
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/move.h"
-#include "nvim/normal.h"
#include "nvim/option.h"
#include "nvim/optionstr.h"
+#include "nvim/os/fs_defs.h"
#include "nvim/os/input.h"
#include "nvim/os/os.h"
-#include "nvim/os/os_defs.h"
#include "nvim/os/time.h"
-#include "nvim/os_unix.h"
#include "nvim/path.h"
-#include "nvim/quickfix.h"
+#include "nvim/pos.h"
#include "nvim/regexp.h"
-#include "nvim/search.h"
+#include "nvim/screen.h"
#include "nvim/sha256.h"
#include "nvim/shada.h"
-#include "nvim/state.h"
#include "nvim/strings.h"
#include "nvim/types.h"
#include "nvim/ui.h"
-#include "nvim/ui_compositor.h"
#include "nvim/undo.h"
#include "nvim/vim.h"
-#include "nvim/window.h"
+
+#if defined(HAVE_FLOCK) && defined(HAVE_DIRFD)
+# include <dirent.h>
+# include <sys/file.h>
+#endif
+
+#ifdef OPEN_CHR_FILES
+# include "nvim/charset.h"
+#endif
#define BUFSIZE 8192 // size of normal write buffer
#define SMBUFSIZE 256 // size of emergency write buffer
@@ -72,15 +82,17 @@
#endif
#define HAS_BW_FLAGS
-#define FIO_LATIN1 0x01 // convert Latin1
-#define FIO_UTF8 0x02 // convert UTF-8
-#define FIO_UCS2 0x04 // convert UCS-2
-#define FIO_UCS4 0x08 // convert UCS-4
-#define FIO_UTF16 0x10 // convert UTF-16
-#define FIO_ENDIAN_L 0x80 // little endian
-#define FIO_NOCONVERT 0x2000 // skip encoding conversion
-#define FIO_UCSBOM 0x4000 // check for BOM at start of file
-#define FIO_ALL (-1) // allow all formats
+enum {
+ FIO_LATIN1 = 0x01, // convert Latin1
+ FIO_UTF8 = 0x02, // convert UTF-8
+ FIO_UCS2 = 0x04, // convert UCS-2
+ FIO_UCS4 = 0x08, // convert UCS-4
+ FIO_UTF16 = 0x10, // convert UTF-16
+ FIO_ENDIAN_L = 0x80, // little endian
+ FIO_NOCONVERT = 0x2000, // skip encoding conversion
+ FIO_UCSBOM = 0x4000, // check for BOM at start of file
+ FIO_ALL = -1, // allow all formats
+};
// When converting, a read() or write() may leave some bytes to be converted
// for the next call. The value is guessed...
@@ -93,7 +105,7 @@
// Structure to pass arguments from buf_write() to buf_write_bytes().
struct bw_info {
int bw_fd; // file descriptor
- char_u *bw_buf; // buffer with data to be written
+ char *bw_buf; // buffer with data to be written
int bw_len; // length of data
#ifdef HAS_BW_FLAGS
int bw_flags; // FIO_ flags
@@ -101,14 +113,12 @@ struct bw_info {
char_u bw_rest[CONV_RESTLEN]; // not converted bytes
int bw_restlen; // nr of bytes in bw_rest[]
int bw_first; // first write call
- char_u *bw_conv_buf; // buffer for writing converted chars
+ char *bw_conv_buf; // buffer for writing converted chars
size_t bw_conv_buflen; // size of bw_conv_buf
int bw_conv_error; // set for conversion error
linenr_T bw_conv_error_lnum; // first line with error or zero
linenr_T bw_start_lnum; // line number at start of buffer
-#ifdef HAVE_ICONV
iconv_t bw_iconv_fd; // descriptor for iconv() or -1
-#endif
};
#ifdef INCLUDE_GENERATED_DECLARATIONS
@@ -126,7 +136,7 @@ void filemess(buf_T *buf, char *name, char *s, int attr)
if (msg_silent != 0) {
return;
}
- add_quoted_fname((char *)IObuff, IOSIZE - 100, buf, (const char *)name);
+ add_quoted_fname(IObuff, IOSIZE - 100, buf, (const char *)name);
// Avoid an over-long translation to cause trouble.
xstrlcat(IObuff, s, IOSIZE);
// For the first message may have to start a new line.
@@ -143,7 +153,7 @@ void filemess(buf_T *buf, char *name, char *s, int attr)
msg_scroll = msg_scroll_save;
msg_scrolled_ign = true;
// may truncate the message to avoid a hit-return prompt
- msg_outtrans_attr(msg_may_trunc(false, (char *)IObuff), attr);
+ msg_outtrans_attr(msg_may_trunc(false, IObuff), attr);
msg_clr_eos();
ui_flush();
msg_scrolled_ign = false;
@@ -236,11 +246,9 @@ int readfile(char *fname, char *sfname, linenr_T from, linenr_T lines_to_skip,
char *fenc_next = NULL; // next item in 'fencs' or NULL
bool advance_fenc = false;
long real_size = 0;
-#ifdef HAVE_ICONV
iconv_t iconv_fd = (iconv_t)-1; // descriptor for iconv() or -1
bool did_iconv = false; // true when iconv() failed and trying
// 'charconvert' next
-#endif
bool converted = false; // true if conversion done
bool notconverted = false; // true if conversion wanted but it wasn't possible
char conv_rest[CONV_RESTLEN];
@@ -266,7 +274,7 @@ int readfile(char *fname, char *sfname, linenr_T from, linenr_T lines_to_skip,
&& fname != NULL
&& vim_strchr(p_cpo, CPO_FNAMER) != NULL
&& !(flags & READ_DUMMY)) {
- if (set_rw_fname((char_u *)fname, (char_u *)sfname) == FAIL) {
+ if (set_rw_fname(fname, sfname) == FAIL) {
return FAIL;
}
}
@@ -476,7 +484,7 @@ int readfile(char *fname, char *sfname, linenr_T from, linenr_T lines_to_skip,
}
}
if (!silent) {
- if (dir_of_file_exists((char_u *)fname)) {
+ if (dir_of_file_exists(fname)) {
filemess(curbuf, sfname, new_file_message(), 0);
} else {
filemess(curbuf, sfname, _("[New DIRECTORY]"), 0);
@@ -498,18 +506,17 @@ int readfile(char *fname, char *sfname, linenr_T from, linenr_T lines_to_skip,
return FAIL;
}
return OK; // a new file is not an error
- } else {
- filemess(curbuf, sfname, ((fd == UV_EFBIG) ? _("[File too big]") :
+ }
+ filemess(curbuf, sfname, ((fd == UV_EFBIG) ? _("[File too big]") :
#if defined(UNIX) && defined(EOVERFLOW)
- // libuv only returns -errno
- // in Unix and in Windows
- // open() does not set
- // EOVERFLOW
- (fd == -EOVERFLOW) ? _("[File too big]") :
+ // libuv only returns -errno
+ // in Unix and in Windows
+ // open() does not set
+ // EOVERFLOW
+ (fd == -EOVERFLOW) ? _("[File too big]") :
#endif
- _("[Permission Denied]")), 0);
- curbuf->b_p_ro = true; // must use "w!" now
- }
+ _("[Permission Denied]")), 0);
+ curbuf->b_p_ro = true; // must use "w!" now
return FAIL;
}
@@ -524,6 +531,8 @@ int readfile(char *fname, char *sfname, linenr_T from, linenr_T lines_to_skip,
// Don't change 'eol' if reading from buffer as it will already be
// correctly set when reading stdin.
if (!read_buffer) {
+ curbuf->b_p_eof = false;
+ curbuf->b_start_eof = false;
curbuf->b_p_eol = true;
curbuf->b_start_eol = true;
}
@@ -766,13 +775,11 @@ retry:
}
}
-#ifdef HAVE_ICONV
if (iconv_fd != (iconv_t)-1) {
// aborted conversion with iconv(), close the descriptor
iconv_close(iconv_fd);
iconv_fd = (iconv_t)-1;
}
-#endif
if (advance_fenc) {
// Try the next entry in 'fileencodings'.
@@ -822,32 +829,24 @@ retry:
// appears not to handle this correctly. This works just like
// conversion to UTF-8 except how the resulting character is put in
// the buffer.
- fio_flags = get_fio_flags((char_u *)fenc);
+ fio_flags = get_fio_flags(fenc);
}
-#ifdef HAVE_ICONV
// Try using iconv() if we can't convert internally.
if (fio_flags == 0
&& !did_iconv) {
- iconv_fd = (iconv_t)my_iconv_open((char_u *)"utf-8", (char_u *)fenc);
+ iconv_fd = (iconv_t)my_iconv_open("utf-8", fenc);
}
-#endif
// Use the 'charconvert' expression when conversion is required
// and we can't do it internally or with iconv().
if (fio_flags == 0 && !read_stdin && !read_buffer && *p_ccv != NUL
- && !read_fifo
-#ifdef HAVE_ICONV
- && iconv_fd == (iconv_t)-1
-#endif
- ) {
-#ifdef HAVE_ICONV
+ && !read_fifo && iconv_fd == (iconv_t)-1) {
did_iconv = false;
-#endif
// Skip conversion when it's already done (retry for wrong
// "fileformat").
if (tmpname == NULL) {
- tmpname = (char *)readfile_charconvert((char_u *)fname, (char_u *)fenc, &fd);
+ tmpname = readfile_charconvert(fname, fenc, &fd);
if (tmpname == NULL) {
// Conversion failed. Try another one.
advance_fenc = true;
@@ -861,11 +860,7 @@ retry:
}
}
} else {
- if (fio_flags == 0
-#ifdef HAVE_ICONV
- && iconv_fd == (iconv_t)-1
-#endif
- ) {
+ if (fio_flags == 0 && iconv_fd == (iconv_t)-1) {
// Conversion wanted but we can't.
// Try the next conversion in 'fileencodings'
advance_fenc = true;
@@ -948,12 +943,9 @@ retry:
// ucs-4 to utf-8: 4 bytes become up to 6 bytes, size must be
// multiple of 4
real_size = (int)size;
-#ifdef HAVE_ICONV
if (iconv_fd != (iconv_t)-1) {
size = size / ICONV_MULT;
- } else {
-#endif
- if (fio_flags & FIO_LATIN1) {
+ } else if (fio_flags & FIO_LATIN1) {
size = size / 2;
} else if (fio_flags & (FIO_UCS2 | FIO_UTF16)) {
size = (size * 2 / 3) & ~1;
@@ -962,9 +954,7 @@ retry:
} else if (fio_flags == FIO_UCSBOM) {
size = size / ICONV_MULT; // worst case
}
-#ifdef HAVE_ICONV
- }
-#endif
+
if (conv_restlen > 0) {
// Insert unconverted bytes from previous line.
memmove(ptr, conv_rest, (size_t)conv_restlen); // -V614
@@ -984,7 +974,7 @@ retry:
tlen = 0;
for (;;) {
p = (char_u *)ml_get(read_buf_lnum) + read_buf_col;
- n = (int)STRLEN(p);
+ n = (int)strlen((char *)p);
if ((int)tlen + n + 1 > size) {
// Filled up to "size", append partial line.
// Change NL to NUL to reverse the effect done
@@ -1036,11 +1026,7 @@ retry:
// not be converted. Truncated file?
// When we did a conversion report an error.
- if (fio_flags != 0
-#ifdef HAVE_ICONV
- || iconv_fd != (iconv_t)-1
-#endif
- ) {
+ if (fio_flags != 0 || iconv_fd != (iconv_t)-1) {
if (can_retry) {
goto rewind_retry;
}
@@ -1048,9 +1034,8 @@ retry:
conv_error = curbuf->b_ml.ml_line_count
- linecnt + 1;
}
- }
- // Remember the first linenr with an illegal byte
- else if (illegal_byte == 0) {
+ } else if (illegal_byte == 0) {
+ // Remember the first linenr with an illegal byte
illegal_byte = curbuf->b_ml.ml_line_count
- linecnt + 1;
}
@@ -1062,23 +1047,17 @@ retry:
// character if we were converting; if we weren't,
// leave the UTF8 checking code to do it, as it
// works slightly differently.
- if (bad_char_behavior != BAD_KEEP && (fio_flags != 0
-#ifdef HAVE_ICONV
- || iconv_fd != (iconv_t)-1
-#endif
- )) {
+ if (bad_char_behavior != BAD_KEEP && (fio_flags != 0 || iconv_fd != (iconv_t)-1)) {
while (conv_restlen > 0) {
*(--ptr) = (char)bad_char_behavior;
conv_restlen--;
}
}
fio_flags = 0; // don't convert this
-#ifdef HAVE_ICONV
if (iconv_fd != (iconv_t)-1) {
iconv_close(iconv_fd);
iconv_fd = (iconv_t)-1;
}
-#endif
}
}
}
@@ -1095,15 +1074,15 @@ retry:
|| (!curbuf->b_p_bomb
&& tmpname == NULL
&& (*fenc == 'u' || *fenc == NUL)))) {
- char_u *ccname;
+ char *ccname;
int blen = 0;
// no BOM detection in a short file or in binary mode
if (size < 2 || curbuf->b_p_bin) {
ccname = NULL;
} else {
- ccname = check_for_bom((char_u *)ptr, size, &blen,
- fio_flags == FIO_UCSBOM ? FIO_ALL : get_fio_flags((char_u *)fenc));
+ ccname = check_for_bom(ptr, size, &blen,
+ fio_flags == FIO_UCSBOM ? FIO_ALL : get_fio_flags(fenc));
}
if (ccname != NULL) {
// Remove BOM from the text
@@ -1125,7 +1104,7 @@ retry:
if (fenc_alloced) {
xfree(fenc);
}
- fenc = (char *)ccname;
+ fenc = ccname;
fenc_alloced = false;
}
// retry reading without getting new bytes or rewinding
@@ -1143,7 +1122,6 @@ retry:
break;
}
-#ifdef HAVE_ICONV
if (iconv_fd != (iconv_t)-1) {
// Attempt conversion of the read bytes to 'encoding' using iconv().
const char *fromp = ptr;
@@ -1163,7 +1141,7 @@ retry:
goto rewind_retry;
}
if (conv_error == 0) {
- conv_error = readfile_linenr(linecnt, (char_u *)ptr, (char_u *)top);
+ conv_error = readfile_linenr(linecnt, ptr, top);
}
// Deal with a bad byte and continue with the next.
@@ -1181,7 +1159,7 @@ retry:
if (from_size > 0) {
// Some remaining characters, keep them for the next
// round.
- memmove(conv_rest, (char_u *)fromp, from_size);
+ memmove(conv_rest, fromp, from_size);
conv_restlen = (int)from_size;
}
@@ -1190,7 +1168,6 @@ retry:
memmove(line_start, buffer, (size_t)linerest);
size = (top - ptr);
}
-#endif
if (fio_flags != 0) {
unsigned int u8c;
@@ -1275,7 +1252,7 @@ retry:
goto rewind_retry;
}
if (conv_error == 0) {
- conv_error = readfile_linenr(linecnt, (char_u *)ptr, p);
+ conv_error = readfile_linenr(linecnt, ptr, (char *)p);
}
if (bad_char_behavior == BAD_DROP) {
continue;
@@ -1303,7 +1280,7 @@ retry:
goto rewind_retry;
}
if (conv_error == 0) {
- conv_error = readfile_linenr(linecnt, (char_u *)ptr, p);
+ conv_error = readfile_linenr(linecnt, ptr, (char *)p);
}
if (bad_char_behavior == BAD_DROP) {
continue;
@@ -1344,7 +1321,7 @@ retry:
goto rewind_retry;
}
if (conv_error == 0) {
- conv_error = readfile_linenr(linecnt, (char_u *)ptr, p);
+ conv_error = readfile_linenr(linecnt, ptr, (char *)p);
}
if (bad_char_behavior == BAD_DROP) {
continue;
@@ -1382,7 +1359,7 @@ retry:
// an incomplete character at the end though, the next
// read() will get the next bytes, we'll check it
// then.
- l = utf_ptr2len_len(p, todo);
+ l = utf_ptr2len_len((char *)p, todo);
if (l > todo && !incomplete_tail) {
// Avoid retrying with a different encoding when
// a truncated file is more likely, or attempting
@@ -1408,15 +1385,15 @@ retry:
if (can_retry && !incomplete_tail) {
break;
}
-#ifdef HAVE_ICONV
+
// When we did a conversion report an error.
if (iconv_fd != (iconv_t)-1 && conv_error == 0) {
- conv_error = readfile_linenr(linecnt, (char_u *)ptr, p);
+ conv_error = readfile_linenr(linecnt, ptr, (char *)p);
}
-#endif
+
// Remember the first linenr with an illegal byte
if (conv_error == 0 && illegal_byte == 0) {
- illegal_byte = readfile_linenr(linecnt, (char_u *)ptr, p);
+ illegal_byte = readfile_linenr(linecnt, ptr, (char *)p);
}
// Drop, keep or replace the bad byte.
@@ -1436,17 +1413,13 @@ retry:
// Detected a UTF-8 error.
rewind_retry:
// Retry reading with another conversion.
-#ifdef HAVE_ICONV
if (*p_ccv != NUL && iconv_fd != (iconv_t)-1) {
// iconv() failed, try 'charconvert'
did_iconv = true;
} else {
-#endif
- // use next item from 'fileencodings'
- advance_fenc = true;
-#ifdef HAVE_ICONV
- }
-#endif
+ // use next item from 'fileencodings'
+ advance_fenc = true;
+ }
file_rewind = true;
goto retry;
}
@@ -1542,7 +1515,7 @@ rewind_retry:
break;
}
if (read_undo_file) {
- sha256_update(&sha_ctx, (char_u *)line_start, (size_t)len);
+ sha256_update(&sha_ctx, (uint8_t *)line_start, (size_t)len);
}
lnum++;
if (--read_count == 0) {
@@ -1598,7 +1571,7 @@ rewind_retry:
break;
}
if (read_undo_file) {
- sha256_update(&sha_ctx, (char_u *)line_start, (size_t)len);
+ sha256_update(&sha_ctx, (uint8_t *)line_start, (size_t)len);
}
lnum++;
if (--read_count == 0) {
@@ -1623,16 +1596,28 @@ failed:
error = false;
}
+ // In Dos format ignore a trailing CTRL-Z, unless 'binary' is set.
+ // In old days the file length was in sector count and the CTRL-Z the
+ // marker where the file really ended. Assuming we write it to a file
+ // system that keeps file length properly the CTRL-Z should be dropped.
+ // Set the 'endoffile' option so the user can decide what to write later.
+ // In Unix format the CTRL-Z is just another character.
+ if (linerest != 0
+ && !curbuf->b_p_bin
+ && fileformat == EOL_DOS
+ && ptr[-1] == Ctrl_Z) {
+ ptr--;
+ linerest--;
+ if (set_options) {
+ curbuf->b_p_eof = true;
+ }
+ }
+
// If we get EOF in the middle of a line, note the fact and
// complete the line ourselves.
- // In Dos format ignore a trailing CTRL-Z, unless 'binary' set.
if (!error
&& !got_int
- && linerest != 0
- && !(!curbuf->b_p_bin
- && fileformat == EOL_DOS
- && *line_start == Ctrl_Z
- && ptr == line_start + 1)) {
+ && linerest != 0) {
// remember for when writing
if (set_options) {
curbuf->b_p_eol = false;
@@ -1643,7 +1628,7 @@ failed:
error = true;
} else {
if (read_undo_file) {
- sha256_update(&sha_ctx, (char_u *)line_start, (size_t)len);
+ sha256_update(&sha_ctx, (uint8_t *)line_start, (size_t)len);
}
read_no_eol_lnum = ++lnum;
}
@@ -1659,11 +1644,9 @@ failed:
if (fenc_alloced) {
xfree(fenc);
}
-#ifdef HAVE_ICONV
if (iconv_fd != (iconv_t)-1) {
iconv_close(iconv_fd);
}
-#endif
if (!read_buffer && !read_stdin) {
close(fd); // errors are ignored
@@ -1734,7 +1717,7 @@ failed:
}
if (!filtering && !(flags & READ_DUMMY) && !silent) {
- add_quoted_fname((char *)IObuff, IOSIZE, curbuf, (const char *)sfname);
+ add_quoted_fname(IObuff, IOSIZE, curbuf, (const char *)sfname);
c = false;
#ifdef UNIX
@@ -1799,7 +1782,7 @@ failed:
msg_scrolled_ign = true;
if (!read_stdin && !read_buffer) {
- p = (char_u *)msg_trunc_attr((char *)IObuff, false, 0);
+ p = (char_u *)msg_trunc_attr(IObuff, false, 0);
}
if (read_stdin || read_buffer || restart_edit != 0
@@ -1863,7 +1846,7 @@ failed:
char_u hash[UNDO_HASH_SIZE];
sha256_finish(&sha_ctx, hash);
- u_read_undo(NULL, hash, (char_u *)fname);
+ u_read_undo(NULL, hash, fname);
}
if (!read_stdin && !read_fifo && (!read_buffer || sfname != NULL)) {
@@ -1919,7 +1902,7 @@ failed:
bool is_dev_fd_file(char *fname)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
{
- return STRNCMP(fname, "/dev/fd/", 8) == 0
+ return strncmp(fname, "/dev/fd/", 8) == 0
&& ascii_isdigit((uint8_t)fname[8])
&& *skipdigits(fname + 9) == NUL
&& (fname[9] != NUL
@@ -1934,9 +1917,9 @@ bool is_dev_fd_file(char *fname)
/// @param linecnt line count before reading more bytes
/// @param p start of more bytes read
/// @param endp end of more bytes read
-static linenr_T readfile_linenr(linenr_T linecnt, char_u *p, char_u *endp)
+static linenr_T readfile_linenr(linenr_T linecnt, char *p, const char *endp)
{
- char_u *s;
+ char *s;
linenr_T lnum;
lnum = curbuf->b_ml.ml_line_count - linecnt + 1;
@@ -1990,11 +1973,13 @@ void set_file_options(int set_options, exarg_T *eap)
/// Set forced 'fileencoding'.
void set_forced_fenc(exarg_T *eap)
{
- if (eap->force_enc != 0) {
- char *fenc = enc_canonize(eap->cmd + eap->force_enc);
- set_string_option_direct("fenc", -1, fenc, OPT_FREE|OPT_LOCAL, 0);
- xfree(fenc);
+ if (eap->force_enc == 0) {
+ return;
}
+
+ char *fenc = enc_canonize(eap->cmd + eap->force_enc);
+ set_string_option_direct("fenc", -1, fenc, OPT_FREE|OPT_LOCAL, 0);
+ xfree(fenc);
}
/// Find next fileencoding to use from 'fileencodings'.
@@ -2014,7 +1999,7 @@ static char *next_fenc(char **pp, bool *alloced)
*pp = NULL;
return "";
}
- p = vim_strchr((*pp), ',');
+ p = vim_strchr(*pp, ',');
if (p == NULL) {
r = enc_canonize(*pp);
*pp += strlen(*pp);
@@ -2039,22 +2024,22 @@ static char *next_fenc(char **pp, bool *alloced)
///
/// @return name of the resulting converted file (the caller should delete it after reading it).
/// Returns NULL if the conversion failed ("*fdp" is not set) .
-static char_u *readfile_charconvert(char_u *fname, char_u *fenc, int *fdp)
+static char *readfile_charconvert(char *fname, char *fenc, int *fdp)
{
- char_u *tmpname;
+ char *tmpname;
char *errmsg = NULL;
- tmpname = (char_u *)vim_tempname();
+ tmpname = vim_tempname();
if (tmpname == NULL) {
errmsg = _("Can't find temp file for conversion");
} else {
close(*fdp); // close the input file, ignore errors
*fdp = -1;
- if (eval_charconvert((char *)fenc, "utf-8",
- (char *)fname, (char *)tmpname) == FAIL) {
+ if (eval_charconvert(fenc, "utf-8",
+ fname, tmpname) == FAIL) {
errmsg = _("Conversion with 'charconvert' failed");
}
- if (errmsg == NULL && (*fdp = os_open((char *)tmpname, O_RDONLY, 0)) < 0) {
+ if (errmsg == NULL && (*fdp = os_open(tmpname, O_RDONLY, 0)) < 0) {
errmsg = _("can't read output of 'charconvert'");
}
}
@@ -2064,14 +2049,14 @@ static char_u *readfile_charconvert(char_u *fname, char_u *fenc, int *fdp)
// another type of conversion might still work.
msg(errmsg);
if (tmpname != NULL) {
- os_remove((char *)tmpname); // delete converted file
+ os_remove(tmpname); // delete converted file
XFREE_CLEAR(tmpname);
}
}
// If the input file is closed, open it (caller should check for error).
if (*fdp < 0) {
- *fdp = os_open((char *)fname, O_RDONLY, 0);
+ *fdp = os_open(fname, O_RDONLY, 0);
}
return tmpname;
@@ -2191,8 +2176,7 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
return FAIL;
}
- // Disallow writing from .exrc and .vimrc in current directory for
- // security reasons.
+ // Disallow writing in secure mode.
if (check_secure()) {
return FAIL;
}
@@ -2208,9 +2192,7 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
write_info.bw_conv_error = false;
write_info.bw_conv_error_lnum = 0;
write_info.bw_restlen = 0;
-#ifdef HAVE_ICONV
write_info.bw_iconv_fd = (iconv_t)-1;
-#endif
// After writing a file changedtick changes but we don't want to display
// the line.
@@ -2229,7 +2211,7 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
&& !filtering
&& (!append || vim_strchr(p_cpo, CPO_FNAMEAPP) != NULL)
&& vim_strchr(p_cpo, CPO_FNAMEW) != NULL) {
- if (set_rw_fname((char_u *)fname, (char_u *)sfname) == FAIL) {
+ if (set_rw_fname(fname, sfname) == FAIL) {
return FAIL;
}
buf = curbuf; // just in case autocmds made "buf" invalid
@@ -2448,7 +2430,7 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
if (!filtering) {
filemess(buf,
#ifndef UNIX
- (char_u *)sfname,
+ sfname,
#else
fname,
#endif
@@ -2492,7 +2474,7 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
}
#else // win32
// Check for a writable device name.
- c = fname == NULL ? NODE_OTHER : os_nodetype((char *)fname);
+ c = fname == NULL ? NODE_OTHER : os_nodetype(fname);
if (c == NODE_OTHER) {
SET_ERRMSG_NUM("E503", _("is not a file or writable device"));
goto fail;
@@ -2510,7 +2492,7 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
goto fail;
}
if (overwriting) {
- os_fileinfo((char *)fname, &file_info_old);
+ os_fileinfo(fname, &file_info_old);
}
}
#endif // !UNIX
@@ -2541,13 +2523,13 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
#ifdef HAVE_ACL
// For systems that support ACL: get the ACL from the original file.
if (!newfile) {
- acl = mch_get_acl((char_u *)fname);
+ acl = os_get_acl(fname);
}
#endif
// If 'backupskip' is not empty, don't make a backup for some files.
dobackup = (p_wb || p_bk || *p_pm != NUL);
- if (dobackup && *p_bsk != NUL && match_file_list(p_bsk, (char_u *)sfname, (char_u *)ffname)) {
+ if (dobackup && *p_bsk != NUL && match_file_list(p_bsk, sfname, ffname)) {
dobackup = false;
}
@@ -2590,21 +2572,21 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
// arbitrary numbers).
STRCPY(IObuff, fname);
for (i = 4913;; i += 123) {
- char *tail = path_tail((char *)IObuff);
+ char *tail = path_tail(IObuff);
size_t size = (size_t)(tail - IObuff);
snprintf(tail, IOSIZE - size, "%d", i);
- if (!os_fileinfo_link((char *)IObuff, &file_info)) {
+ if (!os_fileinfo_link(IObuff, &file_info)) {
break;
}
}
- fd = os_open((char *)IObuff,
+ fd = os_open(IObuff,
O_CREAT|O_WRONLY|O_EXCL|O_NOFOLLOW, (int)perm);
if (fd < 0) { // can't write in directory
backup_copy = true;
} else {
#ifdef UNIX
os_fchown(fd, (uv_uid_t)file_info_old.stat.st_uid, (uv_gid_t)file_info_old.stat.st_gid);
- if (!os_fileinfo((char *)IObuff, &file_info)
+ if (!os_fileinfo(IObuff, &file_info)
|| file_info.stat.st_uid != file_info_old.stat.st_uid
|| file_info.stat.st_gid != file_info_old.stat.st_gid
|| (long)file_info.stat.st_mode != perm) {
@@ -2614,7 +2596,7 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
// Close the file before removing it, on MS-Windows we
// can't delete an open file.
close(fd);
- os_remove((char *)IObuff);
+ os_remove(IObuff);
}
}
}
@@ -2668,16 +2650,16 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
dirp = p_bdir;
while (*dirp) {
// Isolate one directory name, using an entry in 'bdir'.
- size_t dir_len = copy_option_part(&dirp, (char *)IObuff, IOSIZE, ",");
- p = (char *)IObuff + dir_len;
- bool trailing_pathseps = after_pathsep((char *)IObuff, p) && p[-1] == p[-2];
+ size_t dir_len = copy_option_part(&dirp, IObuff, IOSIZE, ",");
+ p = IObuff + dir_len;
+ bool trailing_pathseps = after_pathsep(IObuff, p) && p[-1] == p[-2];
if (trailing_pathseps) {
IObuff[dir_len - 2] = NUL;
}
- if (*dirp == NUL && !os_isdir((char *)IObuff)) {
+ if (*dirp == NUL && !os_isdir(IObuff)) {
int ret;
char *failed_dir;
- if ((ret = os_mkdir_recurse((char *)IObuff, 0755, &failed_dir)) != 0) {
+ if ((ret = os_mkdir_recurse(IObuff, 0755, &failed_dir)) != 0) {
semsg(_("E303: Unable to create directory \"%s\" for backup file: %s"),
failed_dir, os_strerror(ret));
xfree(failed_dir);
@@ -2685,14 +2667,14 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
}
if (trailing_pathseps) {
// Ends with '//', Use Full path
- if ((p = make_percent_swname((char *)IObuff, fname))
+ if ((p = make_percent_swname(IObuff, fname))
!= NULL) {
backup = modname(p, backup_ext, no_prepend_dot);
xfree(p);
}
}
- rootname = get_file_in_dir(fname, (char *)IObuff);
+ rootname = get_file_in_dir(fname, IObuff);
if (rootname == NULL) {
some_error = true; // out of memory
goto nobackup;
@@ -2768,10 +2750,11 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
#endif
// copy the file
- if (os_copy(fname, backup, UV_FS_COPYFILE_FICLONE)
- != 0) {
- SET_ERRMSG(_("E506: Can't write to backup file "
- "(add ! to override)"));
+ if (os_copy(fname, backup, UV_FS_COPYFILE_FICLONE) != 0) {
+ SET_ERRMSG(_("E509: Cannot create backup file (add ! to override)"));
+ XFREE_CLEAR(backup);
+ backup = NULL;
+ continue;
}
#ifdef UNIX
@@ -2780,8 +2763,9 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
(double)file_info_old.stat.st_mtim.tv_sec);
#endif
#ifdef HAVE_ACL
- mch_set_acl((char_u *)backup, acl);
+ os_set_acl(backup, acl);
#endif
+ SET_ERRMSG(NULL);
break;
}
}
@@ -2817,16 +2801,16 @@ nobackup:
dirp = p_bdir;
while (*dirp) {
// Isolate one directory name and make the backup file name.
- size_t dir_len = copy_option_part(&dirp, (char *)IObuff, IOSIZE, ",");
- p = (char *)IObuff + dir_len;
- bool trailing_pathseps = after_pathsep((char *)IObuff, p) && p[-1] == p[-2];
+ size_t dir_len = copy_option_part(&dirp, IObuff, IOSIZE, ",");
+ p = IObuff + dir_len;
+ bool trailing_pathseps = after_pathsep(IObuff, p) && p[-1] == p[-2];
if (trailing_pathseps) {
IObuff[dir_len - 2] = NUL;
}
- if (*dirp == NUL && !os_isdir((char *)IObuff)) {
+ if (*dirp == NUL && !os_isdir(IObuff)) {
int ret;
char *failed_dir;
- if ((ret = os_mkdir_recurse((char *)IObuff, 0755, &failed_dir)) != 0) {
+ if ((ret = os_mkdir_recurse(IObuff, 0755, &failed_dir)) != 0) {
semsg(_("E303: Unable to create directory \"%s\" for backup file: %s"),
failed_dir, os_strerror(ret));
xfree(failed_dir);
@@ -2834,7 +2818,7 @@ nobackup:
}
if (trailing_pathseps) {
// path ends with '//', use full path
- if ((p = make_percent_swname((char *)IObuff, fname))
+ if ((p = make_percent_swname(IObuff, fname))
!= NULL) {
backup = modname(p, backup_ext, no_prepend_dot);
xfree(p);
@@ -2842,7 +2826,7 @@ nobackup:
}
if (backup == NULL) {
- rootname = get_file_in_dir(fname, (char *)IObuff);
+ rootname = get_file_in_dir(fname, IObuff);
if (rootname == NULL) {
backup = NULL;
} else {
@@ -2953,7 +2937,7 @@ nobackup:
// Latin1 to Unicode conversion. This is handled in buf_write_bytes().
// Prepare the flags for it and allocate bw_conv_buf when needed.
if (converted) {
- wb_flags = get_fio_flags((char_u *)fenc);
+ wb_flags = get_fio_flags(fenc);
if (wb_flags & (FIO_UCS2 | FIO_UCS4 | FIO_UTF16 | FIO_UTF8)) {
// Need to allocate a buffer to translate into.
if (wb_flags & (FIO_UCS2 | FIO_UTF16 | FIO_UTF8)) {
@@ -2969,10 +2953,9 @@ nobackup:
}
if (converted && wb_flags == 0) {
-#ifdef HAVE_ICONV
// Use iconv() conversion when conversion is needed and it's not done
// internally.
- write_info.bw_iconv_fd = (iconv_t)my_iconv_open((char_u *)fenc, (char_u *)"utf-8");
+ write_info.bw_iconv_fd = (iconv_t)my_iconv_open(fenc, "utf-8");
if (write_info.bw_iconv_fd != (iconv_t)-1) {
// We're going to use iconv(), allocate a buffer to convert in.
write_info.bw_conv_buflen = (size_t)bufsize * ICONV_MULT;
@@ -2982,28 +2965,21 @@ nobackup:
}
write_info.bw_first = true;
} else {
-#endif
-
- // When the file needs to be converted with 'charconvert' after
- // writing, write to a temp file instead and let the conversion
- // overwrite the original file.
- if (*p_ccv != NUL) {
- wfname = vim_tempname();
- if (wfname == NULL) { // Can't write without a tempfile!
- SET_ERRMSG(_("E214: Can't find temp file for writing"));
- goto restore_backup;
+ // When the file needs to be converted with 'charconvert' after
+ // writing, write to a temp file instead and let the conversion
+ // overwrite the original file.
+ if (*p_ccv != NUL) {
+ wfname = vim_tempname();
+ if (wfname == NULL) { // Can't write without a tempfile!
+ SET_ERRMSG(_("E214: Can't find temp file for writing"));
+ goto restore_backup;
+ }
}
}
}
-#ifdef HAVE_ICONV
-}
-#endif
-
if (converted && wb_flags == 0
-#ifdef HAVE_ICONV
&& write_info.bw_iconv_fd == (iconv_t)-1
-#endif
&& wfname == fname) {
if (!forceit) {
SET_ERRMSG(_("E213: Cannot convert (add ! to write without conversion)"));
@@ -3039,9 +3015,11 @@ nobackup:
// false.
while ((fd = os_open(wfname,
O_WRONLY |
- (append ?
- (forceit ? (O_APPEND | O_CREAT) : O_APPEND)
- : (O_CREAT | O_TRUNC)),
+ (append
+ ? (forceit
+ ? (O_APPEND | O_CREAT)
+ : O_APPEND)
+ : (O_CREAT | O_TRUNC)),
perm < 0 ? 0666 : (perm & 0777))) < 0) {
// A forced write will try to create a new file if the old one
// is still readonly. This may also happen when the directory
@@ -3122,7 +3100,7 @@ restore_backup:
}
SET_ERRMSG(NULL);
- write_info.bw_buf = (char_u *)buffer;
+ write_info.bw_buf = buffer;
nchars = 0;
// use "++bin", "++nobin" or 'binary'
@@ -3135,7 +3113,7 @@ restore_backup:
// Skip the BOM when appending and the file already existed, the BOM
// only makes sense at the start of the file.
if (buf->b_p_bomb && !write_bin && (!append || perm < 0)) {
- write_info.bw_len = make_bom((char_u *)buffer, (char_u *)fenc);
+ write_info.bw_len = make_bom((char_u *)buffer, fenc);
if (write_info.bw_len > 0) {
// don't convert
write_info.bw_flags = FIO_NOCONVERT | wb_flags;
@@ -3167,7 +3145,7 @@ restore_backup:
// Keep it fast!
ptr = ml_get_buf(buf, lnum, false) - 1;
if (write_undo_file) {
- sha256_update(&sha_ctx, (char_u *)ptr + 1, (uint32_t)(strlen(ptr + 1) + 1));
+ sha256_update(&sha_ctx, (uint8_t *)ptr + 1, (uint32_t)(strlen(ptr + 1) + 1));
}
while ((c = *++ptr) != NUL) {
if (c == NL) {
@@ -3241,6 +3219,11 @@ restore_backup:
nchars += len;
}
+ if (!buf->b_p_fixeol && buf->b_p_eof) {
+ // write trailing CTRL-Z
+ (void)write_eintr(write_info.bw_fd, "\x1a", 1);
+ }
+
// Stop when writing done or an error was encountered.
if (!checking_conversion || end == 0) {
break;
@@ -3308,7 +3291,7 @@ restore_backup:
// Probably need to set the ACL before changing the user (can't set the
// ACL on a file the user doesn't own).
if (!backup_copy) {
- mch_set_acl((char_u *)wfname, acl);
+ os_set_acl(wfname, acl);
}
#endif
@@ -3336,7 +3319,7 @@ restore_backup:
} else {
errmsg_allocated = true;
SET_ERRMSG(xmalloc(300));
- vim_snprintf(errmsg, 300,
+ vim_snprintf(errmsg, 300, // NOLINT(runtime/printf)
_("E513: write error, conversion failed in line %" PRIdLINENR
" (make 'fenc' empty to override)"),
write_info.bw_conv_error_lnum);
@@ -3385,13 +3368,13 @@ restore_backup:
fname = sfname; // use shortname now, for the messages
#endif
if (!filtering) {
- add_quoted_fname((char *)IObuff, IOSIZE, buf, (const char *)fname);
+ add_quoted_fname(IObuff, IOSIZE, buf, (const char *)fname);
c = false;
if (write_info.bw_conv_error) {
STRCAT(IObuff, _(" CONVERSION ERROR"));
c = true;
if (write_info.bw_conv_error_lnum != 0) {
- vim_snprintf_add((char *)IObuff, IOSIZE, _(" in line %" PRId64 ";"),
+ vim_snprintf_add(IObuff, IOSIZE, _(" in line %" PRId64 ";"),
(int64_t)write_info.bw_conv_error_lnum);
}
} else if (notconverted) {
@@ -3425,7 +3408,7 @@ restore_backup:
}
}
- set_keep_msg(msg_trunc_attr((char *)IObuff, false, 0), 0);
+ set_keep_msg(msg_trunc_attr(IObuff, false, 0), 0);
}
// When written everything correctly: reset 'modified'. Unless not
@@ -3517,22 +3500,20 @@ nofail:
}
xfree(fenc_tofree);
xfree(write_info.bw_conv_buf);
-#ifdef HAVE_ICONV
if (write_info.bw_iconv_fd != (iconv_t)-1) {
iconv_close(write_info.bw_iconv_fd);
write_info.bw_iconv_fd = (iconv_t)-1;
}
-#endif
#ifdef HAVE_ACL
- mch_free_acl(acl);
+ os_free_acl(acl);
#endif
if (errmsg != NULL) {
// - 100 to save some space for further error message
#ifndef UNIX
- add_quoted_fname((char *)IObuff, IOSIZE - 100, buf, (const char *)sfname);
+ add_quoted_fname(IObuff, IOSIZE - 100, buf, (const char *)sfname);
#else
- add_quoted_fname((char *)IObuff, IOSIZE - 100, buf, (const char *)fname);
+ add_quoted_fname(IObuff, IOSIZE - 100, buf, (const char *)fname);
#endif
if (errnum != NULL) {
if (errmsgarg != 0) {
@@ -3571,10 +3552,10 @@ nofail:
// When writing the whole file and 'undofile' is set, also write the undo
// file.
if (retval == OK && write_undo_file) {
- char hash[UNDO_HASH_SIZE];
+ uint8_t hash[UNDO_HASH_SIZE];
- sha256_finish(&sha_ctx, (char_u *)hash);
- u_write_undo(NULL, false, buf, (char_u *)hash);
+ sha256_finish(&sha_ctx, hash);
+ u_write_undo(NULL, false, buf, hash);
}
if (!should_abort(retval)) {
@@ -3618,7 +3599,7 @@ nofail:
/// Set the name of the current buffer. Use when the buffer doesn't have a
/// name and a ":r" or ":w" command with a file name is used.
-static int set_rw_fname(char_u *fname, char_u *sfname)
+static int set_rw_fname(char *fname, char *sfname)
{
buf_T *buf = curbuf;
@@ -3636,7 +3617,7 @@ static int set_rw_fname(char_u *fname, char_u *sfname)
return FAIL;
}
- if (setfname(curbuf, (char *)fname, (char *)sfname, false) == OK) {
+ if (setfname(curbuf, fname, sfname, false) == OK) {
curbuf->b_flags |= BF_NOTEDITED;
}
@@ -3709,22 +3690,22 @@ static bool msg_add_fileformat(int eol_type)
/// Append line and character count to IObuff.
void msg_add_lines(int insert_space, long lnum, off_T nchars)
{
- char_u *p;
+ char *p;
- p = (char_u *)IObuff + STRLEN(IObuff);
+ p = IObuff + strlen(IObuff);
if (insert_space) {
*p++ = ' ';
}
if (shortmess(SHM_LINES)) {
- vim_snprintf((char *)p, (size_t)(IOSIZE - (p - (char_u *)IObuff)), "%" PRId64 "L, %" PRId64 "B",
+ vim_snprintf(p, (size_t)(IOSIZE - (p - IObuff)), "%" PRId64 "L, %" PRId64 "B",
(int64_t)lnum, (int64_t)nchars);
} else {
- vim_snprintf((char *)p, (size_t)(IOSIZE - (p - (char_u *)IObuff)),
+ vim_snprintf(p, (size_t)(IOSIZE - (p - IObuff)),
NGETTEXT("%" PRId64 " line, ", "%" PRId64 " lines, ", lnum),
(int64_t)lnum);
- p += STRLEN(p);
- vim_snprintf((char *)p, (size_t)(IOSIZE - (p - (char_u *)IObuff)),
+ p += strlen(p);
+ vim_snprintf(p, (size_t)(IOSIZE - (p - IObuff)),
NGETTEXT("%" PRId64 " byte", "%" PRId64 " bytes", nchars),
(int64_t)nchars);
}
@@ -3767,7 +3748,7 @@ static bool time_differs(const FileInfo *file_info, long mtime, long mtime_ns) F
|| file_info->stat.st_mtim.tv_sec - mtime > 1
|| mtime - file_info->stat.st_mtim.tv_sec > 1;
#else
- || (long)file_info->stat.st_mtim.tv_sec != mtime;
+ || file_info->stat.st_mtim.tv_sec != mtime;
#endif
}
@@ -3778,7 +3759,7 @@ static bool time_differs(const FileInfo *file_info, long mtime, long mtime_ns) F
static int buf_write_bytes(struct bw_info *ip)
{
int wlen;
- char_u *buf = ip->bw_buf; // data to write
+ char *buf = ip->bw_buf; // data to write
int len = ip->bw_len; // length of data
#ifdef HAS_BW_FLAGS
int flags = ip->bw_flags; // extra flags
@@ -3786,7 +3767,7 @@ static int buf_write_bytes(struct bw_info *ip)
// Skip conversion when writing the BOM.
if (!(flags & FIO_NOCONVERT)) {
- char_u *p;
+ char *p;
unsigned c;
int n;
@@ -3794,7 +3775,7 @@ static int buf_write_bytes(struct bw_info *ip)
// Convert latin1 in the buffer to UTF-8 in the file.
p = ip->bw_conv_buf; // translate to buffer
for (wlen = 0; wlen < len; wlen++) {
- p += utf_char2bytes(buf[wlen], (char *)p);
+ p += utf_char2bytes((uint8_t)buf[wlen], p);
}
buf = ip->bw_conv_buf;
len = (int)(p - ip->bw_conv_buf);
@@ -3818,7 +3799,7 @@ static int buf_write_bytes(struct bw_info *ip)
l = len;
}
memmove(ip->bw_rest + ip->bw_restlen, buf, (size_t)l);
- n = utf_ptr2len_len(ip->bw_rest, ip->bw_restlen + l);
+ n = utf_ptr2len_len((char *)ip->bw_rest, ip->bw_restlen + l);
if (n > ip->bw_restlen + len) {
// We have an incomplete byte sequence at the end to
// be written. We can't convert it without the
@@ -3858,9 +3839,9 @@ static int buf_write_bytes(struct bw_info *ip)
break;
}
if (n > 1) {
- c = (unsigned)utf_ptr2char((char *)buf + wlen);
+ c = (unsigned)utf_ptr2char(buf + wlen);
} else {
- c = buf[wlen];
+ c = (uint8_t)buf[wlen];
}
}
@@ -3880,7 +3861,6 @@ static int buf_write_bytes(struct bw_info *ip)
}
}
-#ifdef HAVE_ICONV
if (ip->bw_iconv_fd != (iconv_t)-1) {
const char *from;
size_t fromlen;
@@ -3895,17 +3875,17 @@ static int buf_write_bytes(struct bw_info *ip)
// the bytes of the current call. Use the end of the
// conversion buffer for this.
fromlen = (size_t)len + (size_t)ip->bw_restlen;
- fp = (char *)ip->bw_conv_buf + ip->bw_conv_buflen - fromlen;
+ fp = ip->bw_conv_buf + ip->bw_conv_buflen - fromlen;
memmove(fp, ip->bw_rest, (size_t)ip->bw_restlen);
memmove(fp + ip->bw_restlen, buf, (size_t)len);
from = fp;
tolen = ip->bw_conv_buflen - fromlen;
} else {
- from = (const char *)buf;
+ from = buf;
fromlen = (size_t)len;
tolen = ip->bw_conv_buflen;
}
- to = (char *)ip->bw_conv_buf;
+ to = ip->bw_conv_buf;
if (ip->bw_first) {
size_t save_len = tolen;
@@ -3916,7 +3896,7 @@ static int buf_write_bytes(struct bw_info *ip)
// There is a bug in iconv() on Linux (which appears to be
// wide-spread) which sets "to" to NULL and messes up "tolen".
if (to == NULL) {
- to = (char *)ip->bw_conv_buf;
+ to = ip->bw_conv_buf;
tolen = save_len;
}
ip->bw_first = false;
@@ -3937,9 +3917,8 @@ static int buf_write_bytes(struct bw_info *ip)
ip->bw_restlen = (int)fromlen;
buf = ip->bw_conv_buf;
- len = (int)((char_u *)to - ip->bw_conv_buf);
+ len = (int)(to - ip->bw_conv_buf);
}
-#endif
}
if (ip->bw_fd < 0) {
@@ -3957,9 +3936,9 @@ static int buf_write_bytes(struct bw_info *ip)
/// @param flags FIO_ flags that specify which encoding to use
///
/// @return true for an error, false when it's OK.
-static bool ucs2bytes(unsigned c, char_u **pp, int flags) FUNC_ATTR_NONNULL_ALL
+static bool ucs2bytes(unsigned c, char **pp, int flags) FUNC_ATTR_NONNULL_ALL
{
- char_u *p = *pp;
+ char_u *p = (char_u *)(*pp);
bool error = false;
int cc;
@@ -4013,7 +3992,7 @@ static bool ucs2bytes(unsigned c, char_u **pp, int flags) FUNC_ATTR_NONNULL_ALL
}
}
- *pp = p;
+ *pp = (char *)p;
return error;
}
@@ -4036,8 +4015,8 @@ static bool need_conversion(const char *fenc)
} else {
// Ignore difference between "ansi" and "latin1", "ucs-4" and
// "ucs-4be", etc.
- enc_flags = get_fio_flags((char_u *)p_enc);
- fenc_flags = get_fio_flags((char_u *)fenc);
+ enc_flags = get_fio_flags(p_enc);
+ fenc_flags = get_fio_flags(fenc);
same_encoding = (enc_flags != 0 && fenc_flags == enc_flags);
}
if (same_encoding) {
@@ -4055,12 +4034,12 @@ static bool need_conversion(const char *fenc)
/// use 'encoding'.
///
/// @param name string to check for encoding
-static int get_fio_flags(const char_u *name)
+static int get_fio_flags(const char *name)
{
int prop;
if (*name == NUL) {
- name = (char_u *)p_enc;
+ name = p_enc;
}
prop = enc_canon_props(name);
if (prop & ENC_UNICODE) {
@@ -4096,8 +4075,9 @@ static int get_fio_flags(const char_u *name)
///
/// @return the name of the encoding and set "*lenp" to the length or,
/// NULL when no BOM found.
-static char_u *check_for_bom(char_u *p, long size, int *lenp, int flags)
+static char *check_for_bom(const char *p_in, long size, int *lenp, int flags)
{
+ const uint8_t *p = (const uint8_t *)p_in;
char *name = NULL;
int len = 2;
@@ -4133,16 +4113,16 @@ static char_u *check_for_bom(char_u *p, long size, int *lenp, int flags)
}
*lenp = len;
- return (char_u *)name;
+ return name;
}
/// Generate a BOM in "buf[4]" for encoding "name".
///
/// @return the length of the BOM (zero when no BOM).
-static int make_bom(char_u *buf, char_u *name)
+static int make_bom(char_u *buf, char *name)
{
int flags;
- char_u *p;
+ char *p;
flags = get_fio_flags(name);
@@ -4157,9 +4137,9 @@ static int make_bom(char_u *buf, char_u *name)
buf[2] = 0xbf;
return 3;
}
- p = buf;
+ p = (char *)buf;
(void)ucs2bytes(0xfeff, &p, flags);
- return (int)(p - buf);
+ return (int)((char_u *)p - buf);
}
/// Shorten filename of a buffer.
@@ -4171,7 +4151,7 @@ static int make_bom(char_u *buf, char_u *name)
///
/// For buffers that have buftype "nofile" or "scratch": never change the file
/// name.
-void shorten_buf_fname(buf_T *buf, char_u *dirname, int force)
+void shorten_buf_fname(buf_T *buf, char *dirname, int force)
{
char *p;
@@ -4180,11 +4160,11 @@ void shorten_buf_fname(buf_T *buf, char_u *dirname, int force)
&& !path_with_url(buf->b_fname)
&& (force
|| buf->b_sfname == NULL
- || path_is_absolute((char_u *)buf->b_sfname))) {
+ || path_is_absolute(buf->b_sfname))) {
if (buf->b_sfname != buf->b_ffname) {
XFREE_CLEAR(buf->b_sfname);
}
- p = path_shorten_fname(buf->b_ffname, (char *)dirname);
+ p = path_shorten_fname(buf->b_ffname, dirname);
if (p != NULL) {
buf->b_sfname = xstrdup(p);
buf->b_fname = buf->b_sfname;
@@ -4198,11 +4178,11 @@ void shorten_buf_fname(buf_T *buf, char_u *dirname, int force)
/// Shorten filenames for all buffers.
void shorten_fnames(int force)
{
- char_u dirname[MAXPATHL];
+ char dirname[MAXPATHL];
os_dirname(dirname, MAXPATHL);
FOR_ALL_BUFFERS(buf) {
- shorten_buf_fname(buf, dirname, force);
+ shorten_buf_fname(buf, (char *)dirname, force);
// Always make the swap file name a full path, a "nofile" buffer may
// also have a swap file.
@@ -4247,7 +4227,7 @@ char *modname(const char *fname, const char *ext, bool prepend_dot)
// (we need the full path in case :cd is used).
if (fname == NULL || *fname == NUL) {
retval = xmalloc(MAXPATHL + extlen + 3); // +3 for PATHSEP, "_" (Win), NUL
- if (os_dirname((char_u *)retval, MAXPATHL) == FAIL
+ if (os_dirname(retval, MAXPATHL) == FAIL
|| strlen(retval) == 0) {
xfree(retval);
return NULL;
@@ -4258,7 +4238,7 @@ char *modname(const char *fname, const char *ext, bool prepend_dot)
} else {
fnamelen = strlen(fname);
retval = xmalloc(fnamelen + extlen + 3);
- strcpy(retval, fname);
+ strcpy(retval, fname); // NOLINT(runtime/printf)
}
// Search backwards until we hit a '/', '\' or ':'.
@@ -4276,12 +4256,11 @@ char *modname(const char *fname, const char *ext, bool prepend_dot)
ptr[BASENAMELEN] = '\0';
}
- char *s;
- s = ptr + strlen(ptr);
+ char *s = ptr + strlen(ptr);
// Append the extension.
// ext can start with '.' and cannot exceed 3 more characters.
- strcpy(s, ext);
+ strcpy(s, ext); // NOLINT(runtime/printf)
char *e;
// Prepend the dot if needed.
@@ -4315,7 +4294,8 @@ char *modname(const char *fname, const char *ext, bool prepend_dot)
/// @param fp file to read from
///
/// @return true for EOF or error
-bool vim_fgets(char_u *buf, int size, FILE *fp) FUNC_ATTR_NONNULL_ALL
+bool vim_fgets(char *buf, int size, FILE *fp)
+ FUNC_ATTR_NONNULL_ALL
{
char *retval;
@@ -4324,7 +4304,7 @@ bool vim_fgets(char_u *buf, int size, FILE *fp) FUNC_ATTR_NONNULL_ALL
do {
errno = 0;
- retval = fgets((char *)buf, size, fp);
+ retval = fgets(buf, size, fp);
} while (retval == NULL && errno == EINTR && ferror(fp));
if (buf[size - 2] != NUL && buf[size - 2] != '\n') {
@@ -4518,7 +4498,7 @@ int vim_rename(const char *from, const char *to)
}
if (use_tmp_file) {
- char_u tempname[MAXPATHL + 1];
+ char tempname[MAXPATHL + 1];
// Find a name that doesn't exist and is in the same directory.
// Rename "from" to "tempname" and then rename "tempname" to "to".
@@ -4527,17 +4507,17 @@ int vim_rename(const char *from, const char *to)
}
STRCPY(tempname, from);
for (n = 123; n < 99999; n++) {
- char *tail = path_tail((char *)tempname);
- snprintf(tail, (size_t)((MAXPATHL + 1) - (tail - (char *)tempname - 1)), "%d", n);
+ char *tail = path_tail(tempname);
+ snprintf(tail, (size_t)((MAXPATHL + 1) - (tail - tempname - 1)), "%d", n);
- if (!os_path_exists((char *)tempname)) {
- if (os_rename((char_u *)from, tempname) == OK) {
- if (os_rename(tempname, (char_u *)to) == OK) {
+ if (!os_path_exists(tempname)) {
+ if (os_rename(from, tempname) == OK) {
+ if (os_rename(tempname, to) == OK) {
return 0;
}
// Strange, the second step failed. Try moving the
// file back and return failure.
- (void)os_rename(tempname, (char_u *)from);
+ (void)os_rename(tempname, from);
return -1;
}
// If it fails for one temp name it will most likely fail
@@ -4555,7 +4535,7 @@ int vim_rename(const char *from, const char *to)
os_remove((char *)to);
// First try a normal rename, return if it works.
- if (os_rename((char_u *)from, (char_u *)to) == OK) {
+ if (os_rename(from, to) == OK) {
return 0;
}
@@ -4563,12 +4543,12 @@ int vim_rename(const char *from, const char *to)
perm = os_getperm(from);
#ifdef HAVE_ACL
// For systems that support ACL: get the ACL from the original file.
- acl = mch_get_acl((char_u *)from);
+ acl = os_get_acl(from);
#endif
fd_in = os_open((char *)from, O_RDONLY, 0);
if (fd_in < 0) {
#ifdef HAVE_ACL
- mch_free_acl(acl);
+ os_free_acl(acl);
#endif
return -1;
}
@@ -4579,7 +4559,7 @@ int vim_rename(const char *from, const char *to)
if (fd_out < 0) {
close(fd_in);
#ifdef HAVE_ACL
- mch_free_acl(acl);
+ os_free_acl(acl);
#endif
return -1;
}
@@ -4591,7 +4571,7 @@ int vim_rename(const char *from, const char *to)
close(fd_out);
close(fd_in);
#ifdef HAVE_ACL
- mch_free_acl(acl);
+ os_free_acl(acl);
#endif
return -1;
}
@@ -4613,11 +4593,11 @@ int vim_rename(const char *from, const char *to)
to = from;
}
#ifndef UNIX // For Unix os_open() already set the permission.
- os_setperm((const char *)to, perm);
+ os_setperm(to, perm);
#endif
#ifdef HAVE_ACL
- mch_set_acl((char_u *)to, acl);
- mch_free_acl(acl);
+ os_set_acl(to, acl);
+ os_free_acl(acl);
#endif
if (errmsg != NULL) {
semsg(errmsg, to);
@@ -4924,7 +4904,7 @@ int buf_check_timestamp(buf_T *buf)
}
msg_clr_eos();
(void)msg_end();
- if (emsg_silent == 0) {
+ if (emsg_silent == 0 && !in_assert_fails) {
ui_flush();
// give the user some time to think about it
os_delay(1004L, true);
@@ -4975,7 +4955,7 @@ void buf_reload(buf_T *buf, int orig_mode, bool reload_options)
aco_save_T aco;
int flags = READ_NEW;
- // set curwin/curbuf for "buf" and save some things
+ // Set curwin/curbuf for "buf" and save some things.
aucmd_prepbuf(&aco, buf);
// Unless reload_options is set, we only want to read the text from the
@@ -5122,11 +5102,11 @@ void write_lnum_adjust(linenr_T offset)
#if defined(BACKSLASH_IN_FILENAME)
/// Convert all backslashes in fname to forward slashes in-place,
/// unless when it looks like a URL.
-void forward_slash(char_u *fname)
+void forward_slash(char *fname)
{
- char_u *p;
+ char *p;
- if (path_with_url((const char *)fname)) {
+ if (path_with_url(fname)) {
return;
}
for (p = fname; *p != NUL; p++) {
@@ -5139,6 +5119,9 @@ void forward_slash(char_u *fname)
/// Path to Nvim's own temp dir. Ends in a slash.
static char *vim_tempdir = NULL;
+#if defined(HAVE_FLOCK) && defined(HAVE_DIRFD)
+DIR *vim_tempdir_dp = NULL; ///< File descriptor of temp dir
+#endif
/// Creates a directory for private use by this instance of Nvim, trying each of
/// `TEMP_DIR_NAMES` until one succeeds.
@@ -5211,10 +5194,9 @@ static void vim_mktempdir(void)
if (vim_settempdir(path)) {
// Successfully created and set temporary directory so stop trying.
break;
- } else {
- // Couldn't set `vim_tempdir` to `path` so remove created directory.
- os_rmdir(path);
}
+ // Couldn't set `vim_tempdir` to `path` so remove created directory.
+ os_rmdir(path);
}
(void)umask(umask_save);
}
@@ -5281,7 +5263,7 @@ int delete_recursive(const char *name)
garray_T ga;
if (readdir_core(&ga, exp, NULL, NULL) == OK) {
for (int i = 0; i < ga.ga_len; i++) {
- vim_snprintf((char *)NameBuff, MAXPATHL, "%s/%s", exp, ((char_u **)ga.ga_data)[i]);
+ vim_snprintf(NameBuff, MAXPATHL, "%s/%s", exp, ((char **)ga.ga_data)[i]);
if (delete_recursive((const char *)NameBuff) != 0) {
// Remember the failure but continue deleting any further
// entries.
@@ -5304,15 +5286,50 @@ int delete_recursive(const char *name)
return result;
}
+#if defined(HAVE_FLOCK) && defined(HAVE_DIRFD)
+/// Open temporary directory and take file lock to prevent
+/// to be auto-cleaned.
+static void vim_opentempdir(void)
+{
+ if (vim_tempdir_dp != NULL) {
+ return;
+ }
+
+ DIR *dp = opendir(vim_tempdir);
+ if (dp == NULL) {
+ return;
+ }
+
+ vim_tempdir_dp = dp;
+ flock(dirfd(vim_tempdir_dp), LOCK_SH);
+}
+
+/// Close temporary directory - it automatically release file lock.
+static void vim_closetempdir(void)
+{
+ if (vim_tempdir_dp == NULL) {
+ return;
+ }
+
+ closedir(vim_tempdir_dp);
+ vim_tempdir_dp = NULL;
+}
+#endif
+
/// Delete the temp directory and all files it contains.
void vim_deltempdir(void)
{
- if (vim_tempdir != NULL) {
- // remove the trailing path separator
- path_tail(vim_tempdir)[-1] = NUL;
- delete_recursive(vim_tempdir);
- XFREE_CLEAR(vim_tempdir);
+ if (vim_tempdir == NULL) {
+ return;
}
+
+#if defined(HAVE_FLOCK) && defined(HAVE_DIRFD)
+ vim_closetempdir();
+#endif
+ // remove the trailing path separator
+ path_tail(vim_tempdir)[-1] = NUL;
+ delete_recursive(vim_tempdir);
+ XFREE_CLEAR(vim_tempdir);
}
/// Gets path to Nvim's own temp dir (ending with slash).
@@ -5337,12 +5354,16 @@ char *vim_gettempdir(void)
static bool vim_settempdir(char *tempdir)
{
char *buf = verbose_try_malloc(MAXPATHL + 2);
- if (!buf) {
+ if (buf == NULL) {
return false;
}
+
vim_FullName(tempdir, buf, MAXPATHL, false);
add_pathsep(buf);
vim_tempdir = xstrdup(buf);
+#if defined(HAVE_FLOCK) && defined(HAVE_DIRFD)
+ vim_opentempdir();
+#endif
xfree(buf);
return true;
}
@@ -5430,28 +5451,27 @@ bool match_file_pat(char *pattern, regprog_T **prog, char *fname, char *sfname,
/// @param ffname full file name
///
/// @return true if there was a match
-bool match_file_list(char_u *list, char_u *sfname, char_u *ffname)
+bool match_file_list(char *list, char *sfname, char *ffname)
FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ARG(1, 3)
{
- char_u buf[100];
- char_u *tail;
- char_u *regpat;
+ char buf[100];
+ char *tail;
+ char *regpat;
char allow_dirs;
bool match;
char *p;
- tail = (char_u *)path_tail((char *)sfname);
+ tail = path_tail(sfname);
// try all patterns in 'wildignore'
- p = (char *)list;
+ p = list;
while (*p) {
- copy_option_part(&p, (char *)buf, ARRAY_SIZE(buf), ",");
- regpat = (char_u *)file_pat_to_reg_pat((char *)buf, NULL, &allow_dirs, false);
+ copy_option_part(&p, buf, ARRAY_SIZE(buf), ",");
+ regpat = file_pat_to_reg_pat(buf, NULL, &allow_dirs, false);
if (regpat == NULL) {
break;
}
- match = match_file_pat((char *)regpat, NULL, (char *)ffname, (char *)sfname, (char *)tail,
- (int)allow_dirs);
+ match = match_file_pat(regpat, NULL, ffname, sfname, tail, (int)allow_dirs);
xfree(regpat);
if (match) {
return true;
@@ -5560,7 +5580,7 @@ char *file_pat_to_reg_pat(const char *pat, const char *pat_end, char *allow_dirs
// "\*" to "\\.*" e.g., "dir\*.c"
// "\?" to "\\." e.g., "dir\??.c"
// "\+" to "\+" e.g., "fileX\+.c"
- if ((vim_isfilec(p[1]) || p[1] == '*' || p[1] == '?')
+ if ((vim_isfilec((uint8_t)p[1]) || p[1] == '*' || p[1] == '?')
&& p[1] != '+') {
reg_pat[i++] = '[';
reg_pat[i++] = '\\';