aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/nvim/fileio.c205
1 files changed, 122 insertions, 83 deletions
diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c
index 047abebde0..cad48aee52 100644
--- a/src/nvim/fileio.c
+++ b/src/nvim/fileio.c
@@ -125,6 +125,8 @@ typedef struct {
bool alloc;
} Error_T;
+static char *err_readonly = "is read-only (cannot override: \"W\" in 'cpoptions')";
+
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "fileio.c.generated.h"
#endif
@@ -2314,6 +2316,111 @@ static void emit_err(Error_T *e)
}
}
+#if defined(UNIX)
+
+static int get_fileinfo_os(char *fname, FileInfo *file_info_old, bool overwriting, long *perm,
+ bool *device, bool *newfile, Error_T *err)
+{
+ *perm = -1;
+ if (!os_fileinfo(fname, file_info_old)) {
+ *newfile = true;
+ } else {
+ *perm = (long)file_info_old->stat.st_mode;
+ if (!S_ISREG(file_info_old->stat.st_mode)) { // not a file
+ if (S_ISDIR(file_info_old->stat.st_mode)) {
+ *err = set_err_num("E502", _("is a directory"));
+ return FAIL;
+ }
+ if (os_nodetype(fname) != NODE_WRITABLE) {
+ *err = set_err_num("E503", _("is not a file or writable device"));
+ return FAIL;
+ }
+ // It's a device of some kind (or a fifo) which we can write to
+ // but for which we can't make a backup.
+ *device = true;
+ *newfile = true;
+ *perm = -1;
+ }
+ }
+ return OK;
+}
+
+#else
+
+static int get_fileinfo_os(char *fname, FileInfo *file_info_old, bool overwriting, long *perm,
+ bool *device, bool *newfile, Error_T *err)
+{
+ // Check for a writable device name.
+ char nodetype = fname == NULL ? NODE_OTHER : (char)os_nodetype(fname);
+ if (nodetype == NODE_OTHER) {
+ *err = set_err_num("E503", _("is not a file or writable device"));
+ return FAIL;
+ }
+ if (nodetype == NODE_WRITABLE) {
+ *device = true;
+ *newfile = true;
+ *perm = -1;
+ } else {
+ *perm = os_getperm((const char *)fname);
+ if (*perm < 0) {
+ *newfile = true;
+ } else if (os_isdir(fname)) {
+ *err = set_err_num("E502", _("is a directory"));
+ return FAIL;
+ }
+ if (overwriting) {
+ os_fileinfo(fname, file_info_old);
+ }
+ }
+ return OK;
+}
+
+#endif
+
+/// @param buf
+/// @param fname File name
+/// @param overwriting
+/// @param forceit
+/// @param[out] file_info_old
+/// @param[out] perm
+/// @param[out] device
+/// @param[out] newfile
+/// @param[out] readonly
+static int get_fileinfo(buf_T *buf, char *fname, bool overwriting, bool forceit,
+ FileInfo *file_info_old, long *perm, bool *device, bool *newfile,
+ bool *readonly, Error_T *err)
+{
+ if (get_fileinfo_os(fname, file_info_old, overwriting, perm, device, newfile, err) == FAIL) {
+ return FAIL;
+ }
+
+ *readonly = false; // overwritten file is read-only
+
+ if (!*device && !*newfile) {
+ // Check if the file is really writable (when renaming the file to
+ // make a backup we won't discover it later).
+ *readonly = !os_file_is_writable(fname);
+
+ if (!forceit && *readonly) {
+ if (vim_strchr(p_cpo, CPO_FWRITE) != NULL) {
+ *err = set_err_num("E504", _(err_readonly));
+ } else {
+ *err = set_err_num("E505", _("is read-only (add ! to override)"));
+ }
+ return FAIL;
+ }
+
+ // If 'forceit' is false, check if the timestamp hasn't changed since reading the file.
+ if (overwriting && !forceit) {
+ int retval = check_mtime(buf, file_info_old);
+ if (retval == FAIL) {
+ return FAIL;
+ }
+ }
+ }
+ return OK;
+}
+
/// buf_write() - write to file "fname" lines "start" through "end"
///
/// We do our own buffering here because fwrite() is so slow.
@@ -2338,8 +2445,6 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
int retval = OK;
int msg_save = msg_scroll;
int prev_got_int = got_int;
- static char *err_readonly =
- "is read-only (cannot override: \"W\" in 'cpoptions')";
// writing everything
int whole = (start == 1 && end == buf->b_ml.ml_line_count);
int write_undo_file = false;
@@ -2467,8 +2572,10 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
}
Error_T err = { 0 };
- int newfile = false; // true if file doesn't exist yet
- int device = false; // writing to a device
+ long perm; // file permissions
+ bool newfile = false; // true if file doesn't exist yet
+ bool device = false; // writing to a device
+ bool file_readonly = false; // overwritten file is read-only
char *backup = NULL;
char *fenc_tofree = NULL; // allocated "fenc"
@@ -2480,78 +2587,10 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
// backup or new file
#endif
- long perm; // file permissions
-#if defined(UNIX)
- perm = -1;
- if (!os_fileinfo(fname, &file_info_old)) {
- newfile = true;
- } else {
- perm = (long)file_info_old.stat.st_mode;
- if (!S_ISREG(file_info_old.stat.st_mode)) { // not a file
- if (S_ISDIR(file_info_old.stat.st_mode)) {
- err = set_err_num("E502", _("is a directory"));
- goto fail;
- }
- if (os_nodetype(fname) != NODE_WRITABLE) {
- err = set_err_num("E503", _("is not a file or writable device"));
- goto fail;
- }
- // It's a device of some kind (or a fifo) which we can write to
- // but for which we can't make a backup.
- device = true;
- newfile = true;
- perm = -1;
- }
- }
-#else // win32
- // Check for a writable device name.
- char nodetype = fname == NULL ? NODE_OTHER : os_nodetype(fname);
- if (nodetype == NODE_OTHER) {
- err = set_err_num("E503", _("is not a file or writable device"));
+ if (get_fileinfo(buf, fname, overwriting, forceit, &file_info_old, &perm, &device, &newfile,
+ &file_readonly, &err) == FAIL) {
goto fail;
}
- if (nodetype == NODE_WRITABLE) {
- device = true;
- newfile = true;
- perm = -1;
- } else {
- perm = os_getperm((const char *)fname);
- if (perm < 0) {
- newfile = true;
- } else if (os_isdir(fname)) {
- err = set_err_num("E502", _("is a directory"));
- goto fail;
- }
- if (overwriting) {
- os_fileinfo(fname, &file_info_old);
- }
- }
-#endif // !UNIX
-
- bool file_readonly = false; // overwritten file is read-only
-
- if (!device && !newfile) {
- // Check if the file is really writable (when renaming the file to
- // make a backup we won't discover it later).
- file_readonly = !os_file_is_writable(fname);
-
- if (!forceit && file_readonly) {
- if (vim_strchr(p_cpo, CPO_FWRITE) != NULL) {
- err = set_err_num("E504", _(err_readonly));
- } else {
- err = set_err_num("E505", _("is read-only (add ! to override)"));
- }
- goto fail;
- }
-
- // If 'forceit' is false, check if the timestamp hasn't changed since reading the file.
- if (overwriting && !forceit) {
- retval = check_mtime(buf, &file_info_old);
- if (retval == FAIL) {
- goto fail;
- }
- }
- }
#ifdef HAVE_ACL
// For systems that support ACL: get the ACL from the original file.
@@ -3407,37 +3446,37 @@ restore_backup:
#endif
if (!filtering) {
add_quoted_fname(IObuff, IOSIZE, buf, (const char *)fname);
- char c = false;
+ bool insert_space = false;
if (write_info.bw_conv_error) {
STRCAT(IObuff, _(" CONVERSION ERROR"));
- c = true;
+ insert_space = true;
if (write_info.bw_conv_error_lnum != 0) {
vim_snprintf_add(IObuff, IOSIZE, _(" in line %" PRId64 ";"),
(int64_t)write_info.bw_conv_error_lnum);
}
} else if (notconverted) {
STRCAT(IObuff, _("[NOT converted]"));
- c = true;
+ insert_space = true;
} else if (converted) {
STRCAT(IObuff, _("[converted]"));
- c = true;
+ insert_space = true;
}
if (device) {
STRCAT(IObuff, _("[Device]"));
- c = true;
+ insert_space = true;
} else if (newfile) {
STRCAT(IObuff, new_file_message());
- c = true;
+ insert_space = true;
}
if (no_eol) {
msg_add_eol();
- c = true;
+ insert_space = true;
}
// may add [unix/dos/mac]
if (msg_add_fileformat(fileformat)) {
- c = true;
+ insert_space = true;
}
- msg_add_lines(c, (long)lnum, nchars); // add line/char count
+ msg_add_lines(insert_space, (long)lnum, nchars); // add line/char count
if (!shortmess(SHM_WRITE)) {
if (append) {
STRCAT(IObuff, shortmess(SHM_WRI) ? _(" [a]") : _(" appended"));