mirror of
https://github.com/neovim/neovim.git
synced 2025-09-19 01:38:16 +00:00
fileio: Refactor errmsg handling
Adds os_strerror() result to a number of places. Also since I could not track where err\* variables are NULL and where they are not, using macros to make sure that all three variables are set at once. Removes #ifdef UNIX around the use of os_fsync, makes it use os_close in place of close in some places.
This commit is contained in:
@@ -2740,6 +2740,9 @@ A jump table for the options with a short description can be found at |Q_op|.
|
|||||||
mode, so it may be undesirable in some situations. Be warned that
|
mode, so it may be undesirable in some situations. Be warned that
|
||||||
turning this off increases the chances of data loss after a crash.
|
turning this off increases the chances of data loss after a crash.
|
||||||
|
|
||||||
|
Currently applies only to writing the buffer with e.g. |:w| and
|
||||||
|
|writefile()|.
|
||||||
|
|
||||||
*'gdefault'* *'gd'* *'nogdefault'* *'nogd'*
|
*'gdefault'* *'gd'* *'nogdefault'* *'nogd'*
|
||||||
'gdefault' 'gd' boolean (default off)
|
'gdefault' 'gd' boolean (default off)
|
||||||
global
|
global
|
||||||
|
@@ -2258,9 +2258,16 @@ buf_write (
|
|||||||
int len;
|
int len;
|
||||||
linenr_T lnum;
|
linenr_T lnum;
|
||||||
long nchars;
|
long nchars;
|
||||||
char_u *errmsg = NULL;
|
#define SET_ERRMSG_NUM(num, msg) \
|
||||||
int errmsg_allocated = FALSE;
|
errnum = num ": ", errmsg = msg, errmsgarg = 0
|
||||||
char_u *errnum = NULL;
|
#define SET_ERRMSG_ARG(msg, error) \
|
||||||
|
errnum = NULL, errmsg = msg, errmsgarg = error
|
||||||
|
#define SET_ERRMSG(msg) \
|
||||||
|
errnum = NULL, errmsg = msg, errmsgarg = 0
|
||||||
|
const char *errnum = NULL;
|
||||||
|
char *errmsg = NULL;
|
||||||
|
int errmsgarg = 0;
|
||||||
|
bool errmsg_allocated = false;
|
||||||
char_u *buffer;
|
char_u *buffer;
|
||||||
char_u smallbuf[SMBUFSIZE];
|
char_u smallbuf[SMBUFSIZE];
|
||||||
char_u *backup_ext;
|
char_u *backup_ext;
|
||||||
@@ -2282,7 +2289,6 @@ buf_write (
|
|||||||
/* writing everything */
|
/* writing everything */
|
||||||
int whole = (start == 1 && end == buf->b_ml.ml_line_count);
|
int whole = (start == 1 && end == buf->b_ml.ml_line_count);
|
||||||
linenr_T old_line_count = buf->b_ml.ml_line_count;
|
linenr_T old_line_count = buf->b_ml.ml_line_count;
|
||||||
int attr;
|
|
||||||
int fileformat;
|
int fileformat;
|
||||||
int write_bin;
|
int write_bin;
|
||||||
struct bw_info write_info; /* info for buf_write_bytes() */
|
struct bw_info write_info; /* info for buf_write_bytes() */
|
||||||
@@ -2577,13 +2583,11 @@ buf_write (
|
|||||||
perm = file_info_old.stat.st_mode;
|
perm = file_info_old.stat.st_mode;
|
||||||
if (!S_ISREG(file_info_old.stat.st_mode)) { /* not a file */
|
if (!S_ISREG(file_info_old.stat.st_mode)) { /* not a file */
|
||||||
if (S_ISDIR(file_info_old.stat.st_mode)) {
|
if (S_ISDIR(file_info_old.stat.st_mode)) {
|
||||||
errnum = (char_u *)"E502: ";
|
SET_ERRMSG_NUM("E502", _("is a directory"));
|
||||||
errmsg = (char_u *)_("is a directory");
|
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
if (os_nodetype((char *)fname) != NODE_WRITABLE) {
|
if (os_nodetype((char *)fname) != NODE_WRITABLE) {
|
||||||
errnum = (char_u *)"E503: ";
|
SET_ERRMSG_NUM("E503", _("is not a file or writable device"));
|
||||||
errmsg = (char_u *)_("is not a file or writable device");
|
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
/* It's a device of some kind (or a fifo) which we can write to
|
/* It's a device of some kind (or a fifo) which we can write to
|
||||||
@@ -2599,8 +2603,7 @@ buf_write (
|
|||||||
*/
|
*/
|
||||||
c = os_nodetype((char *)fname);
|
c = os_nodetype((char *)fname);
|
||||||
if (c == NODE_OTHER) {
|
if (c == NODE_OTHER) {
|
||||||
errnum = (char_u *)"E503: ";
|
SET_ERRMSG_NUM("E503", _("is not a file or writable device"));
|
||||||
errmsg = (char_u *)_("is not a file or writable device");
|
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
if (c == NODE_WRITABLE) {
|
if (c == NODE_WRITABLE) {
|
||||||
@@ -2612,8 +2615,7 @@ buf_write (
|
|||||||
if (perm < 0) {
|
if (perm < 0) {
|
||||||
newfile = true;
|
newfile = true;
|
||||||
} else if (os_isdir(fname)) {
|
} else if (os_isdir(fname)) {
|
||||||
errnum = (char_u *)"E502: ";
|
SET_ERRMSG_NUM("E502", _("is a directory"));
|
||||||
errmsg = (char_u *)_("is a directory");
|
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
if (overwriting) {
|
if (overwriting) {
|
||||||
@@ -2632,11 +2634,9 @@ buf_write (
|
|||||||
|
|
||||||
if (!forceit && file_readonly) {
|
if (!forceit && file_readonly) {
|
||||||
if (vim_strchr(p_cpo, CPO_FWRITE) != NULL) {
|
if (vim_strchr(p_cpo, CPO_FWRITE) != NULL) {
|
||||||
errnum = (char_u *)"E504: ";
|
SET_ERRMSG_NUM("E504", _(err_readonly));
|
||||||
errmsg = (char_u *)_(err_readonly);
|
|
||||||
} else {
|
} else {
|
||||||
errnum = (char_u *)"E505: ";
|
SET_ERRMSG_NUM("E505", _("is read-only (add ! to override)"));
|
||||||
errmsg = (char_u *)_("is read-only (add ! to override)");
|
|
||||||
}
|
}
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
@@ -2904,23 +2904,27 @@ buf_write (
|
|||||||
while ((write_info.bw_len = read_eintr(fd, copybuf,
|
while ((write_info.bw_len = read_eintr(fd, copybuf,
|
||||||
BUFSIZE)) > 0) {
|
BUFSIZE)) > 0) {
|
||||||
if (buf_write_bytes(&write_info) == FAIL) {
|
if (buf_write_bytes(&write_info) == FAIL) {
|
||||||
errmsg = (char_u *)_(
|
SET_ERRMSG(_(
|
||||||
"E506: Can't write to backup file (add ! to override)");
|
"E506: Can't write to backup file (add ! to override)"));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
os_breakcheck();
|
os_breakcheck();
|
||||||
if (got_int) {
|
if (got_int) {
|
||||||
errmsg = (char_u *)_(e_interr);
|
SET_ERRMSG(_(e_interr));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (close(bfd) < 0 && errmsg == NULL)
|
int error;
|
||||||
errmsg = (char_u *)_(
|
if ((error = os_close(bfd)) != 0 && errmsg == NULL) {
|
||||||
"E507: Close error for backup file (add ! to override)");
|
SET_ERRMSG_ARG(_(
|
||||||
if (write_info.bw_len < 0)
|
"E507: Close error for backup file (add ! to override): %s"),
|
||||||
errmsg = (char_u *)_(
|
error);
|
||||||
"E508: Can't read file for backup (add ! to override)");
|
}
|
||||||
|
if (write_info.bw_len < 0) {
|
||||||
|
SET_ERRMSG(_(
|
||||||
|
"E508: Can't read file for backup (add ! to override)"));
|
||||||
|
}
|
||||||
#ifdef UNIX
|
#ifdef UNIX
|
||||||
set_file_time(backup,
|
set_file_time(backup,
|
||||||
file_info_old.stat.st_atim.tv_sec,
|
file_info_old.stat.st_atim.tv_sec,
|
||||||
@@ -2937,18 +2941,19 @@ buf_write (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
nobackup:
|
nobackup:
|
||||||
close(fd); /* ignore errors for closing read file */
|
os_close(fd); /* ignore errors for closing read file */
|
||||||
xfree(copybuf);
|
xfree(copybuf);
|
||||||
|
|
||||||
if (backup == NULL && errmsg == NULL)
|
if (backup == NULL && errmsg == NULL) {
|
||||||
errmsg = (char_u *)_(
|
SET_ERRMSG(_(
|
||||||
"E509: Cannot create backup file (add ! to override)");
|
"E509: Cannot create backup file (add ! to override)"));
|
||||||
/* ignore errors when forceit is TRUE */
|
}
|
||||||
|
// Ignore errors when forceit is TRUE.
|
||||||
if ((some_error || errmsg != NULL) && !forceit) {
|
if ((some_error || errmsg != NULL) && !forceit) {
|
||||||
retval = FAIL;
|
retval = FAIL;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
errmsg = NULL;
|
SET_ERRMSG(NULL);
|
||||||
} else {
|
} else {
|
||||||
char_u *dirp;
|
char_u *dirp;
|
||||||
char_u *p;
|
char_u *p;
|
||||||
@@ -2963,8 +2968,7 @@ nobackup:
|
|||||||
* anyway, thus we need an extra check here.
|
* anyway, thus we need an extra check here.
|
||||||
*/
|
*/
|
||||||
if (file_readonly && vim_strchr(p_cpo, CPO_FWRITE) != NULL) {
|
if (file_readonly && vim_strchr(p_cpo, CPO_FWRITE) != NULL) {
|
||||||
errnum = (char_u *)"E504: ";
|
SET_ERRMSG_NUM("E504", _(err_readonly));
|
||||||
errmsg = (char_u *)_(err_readonly);
|
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3028,7 +3032,7 @@ nobackup:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (backup == NULL && !forceit) {
|
if (backup == NULL && !forceit) {
|
||||||
errmsg = (char_u *)_("E510: Can't make backup file (add ! to override)");
|
SET_ERRMSG(_("E510: Can't make backup file (add ! to override)"));
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3069,7 +3073,7 @@ nobackup:
|
|||||||
&& !(exiting && backup != NULL)) {
|
&& !(exiting && backup != NULL)) {
|
||||||
ml_preserve(buf, FALSE);
|
ml_preserve(buf, FALSE);
|
||||||
if (got_int) {
|
if (got_int) {
|
||||||
errmsg = (char_u *)_(e_interr);
|
SET_ERRMSG(_(e_interr));
|
||||||
goto restore_backup;
|
goto restore_backup;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3140,8 +3144,8 @@ nobackup:
|
|||||||
*/
|
*/
|
||||||
if (*p_ccv != NUL) {
|
if (*p_ccv != NUL) {
|
||||||
wfname = vim_tempname();
|
wfname = vim_tempname();
|
||||||
if (wfname == NULL) { /* Can't write without a tempfile! */
|
if (wfname == NULL) { // Can't write without a tempfile!
|
||||||
errmsg = (char_u *)_("E214: Can't find temp file for writing");
|
SET_ERRMSG(_("E214: Can't find temp file for writing"));
|
||||||
goto restore_backup;
|
goto restore_backup;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3153,8 +3157,8 @@ nobackup:
|
|||||||
&& wfname == fname
|
&& wfname == fname
|
||||||
) {
|
) {
|
||||||
if (!forceit) {
|
if (!forceit) {
|
||||||
errmsg = (char_u *)_(
|
SET_ERRMSG(_(
|
||||||
"E213: Cannot convert (add ! to write without conversion)");
|
"E213: Cannot convert (add ! to write without conversion)"));
|
||||||
goto restore_backup;
|
goto restore_backup;
|
||||||
}
|
}
|
||||||
notconverted = TRUE;
|
notconverted = TRUE;
|
||||||
@@ -3189,11 +3193,10 @@ nobackup:
|
|||||||
if ((!newfile && os_fileinfo_hardlinks(&file_info) > 1)
|
if ((!newfile && os_fileinfo_hardlinks(&file_info) > 1)
|
||||||
|| (os_fileinfo_link((char *)fname, &file_info)
|
|| (os_fileinfo_link((char *)fname, &file_info)
|
||||||
&& !os_fileinfo_id_equal(&file_info, &file_info_old))) {
|
&& !os_fileinfo_id_equal(&file_info, &file_info_old))) {
|
||||||
errmsg = (char_u *)_("E166: Can't open linked file for writing");
|
SET_ERRMSG(_("E166: Can't open linked file for writing"));
|
||||||
} else
|
} else {
|
||||||
#endif
|
#endif
|
||||||
{
|
SET_ERRMSG(_("E212: Can't open file for writing"));
|
||||||
errmsg = (char_u *)_("E212: Can't open file for writing");
|
|
||||||
if (forceit && vim_strchr(p_cpo, CPO_FWRITE) == NULL
|
if (forceit && vim_strchr(p_cpo, CPO_FWRITE) == NULL
|
||||||
&& perm >= 0) {
|
&& perm >= 0) {
|
||||||
#ifdef UNIX
|
#ifdef UNIX
|
||||||
@@ -3211,7 +3214,9 @@ nobackup:
|
|||||||
os_remove((char *)wfname);
|
os_remove((char *)wfname);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
#ifdef UNIX
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
restore_backup:
|
restore_backup:
|
||||||
@@ -3253,7 +3258,7 @@ restore_backup:
|
|||||||
xfree(wfname);
|
xfree(wfname);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
errmsg = NULL;
|
SET_ERRMSG(NULL);
|
||||||
|
|
||||||
|
|
||||||
write_info.bw_fd = fd;
|
write_info.bw_fd = fd;
|
||||||
@@ -3373,7 +3378,6 @@ restore_backup:
|
|||||||
nchars += len;
|
nchars += len;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(UNIX)
|
|
||||||
// On many journalling file systems there is a bug that causes both the
|
// On many journalling file systems there is a bug that causes both the
|
||||||
// original and the backup file to be lost when halting the system right
|
// original and the backup file to be lost when halting the system right
|
||||||
// after writing the file. That's because only the meta-data is
|
// after writing the file. That's because only the meta-data is
|
||||||
@@ -3382,11 +3386,11 @@ restore_backup:
|
|||||||
// For a device do try the fsync() but don't complain if it does not work
|
// For a device do try the fsync() but don't complain if it does not work
|
||||||
// (could be a pipe).
|
// (could be a pipe).
|
||||||
// If the 'fsync' option is FALSE, don't fsync(). Useful for laptops.
|
// If the 'fsync' option is FALSE, don't fsync(). Useful for laptops.
|
||||||
if (p_fs && os_fsync(fd) != 0 && !device) {
|
int error;
|
||||||
errmsg = (char_u *)_("E667: Fsync failed");
|
if (p_fs && (error = os_fsync(fd)) != 0 && !device) {
|
||||||
|
SET_ERRMSG_ARG(_("E667: Fsync failed: %s"), error);
|
||||||
end = 0;
|
end = 0;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef HAVE_SELINUX
|
#ifdef HAVE_SELINUX
|
||||||
/* Probably need to set the security context. */
|
/* Probably need to set the security context. */
|
||||||
@@ -3416,8 +3420,8 @@ restore_backup:
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (close(fd) != 0) {
|
if ((error = os_close(fd)) != 0) {
|
||||||
errmsg = (char_u *)_("E512: Close failed");
|
SET_ERRMSG_ARG(_("E512: Close failed: %s"), error);
|
||||||
end = 0;
|
end = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3454,21 +3458,25 @@ restore_backup:
|
|||||||
if (end == 0) {
|
if (end == 0) {
|
||||||
if (errmsg == NULL) {
|
if (errmsg == NULL) {
|
||||||
if (write_info.bw_conv_error) {
|
if (write_info.bw_conv_error) {
|
||||||
if (write_info.bw_conv_error_lnum == 0)
|
if (write_info.bw_conv_error_lnum == 0) {
|
||||||
errmsg = (char_u *)_(
|
SET_ERRMSG(_(
|
||||||
"E513: write error, conversion failed (make 'fenc' empty to override)");
|
"E513: write error, conversion failed "
|
||||||
else {
|
"(make 'fenc' empty to override)"));
|
||||||
errmsg_allocated = TRUE;
|
}
|
||||||
errmsg = xmalloc(300);
|
else {
|
||||||
vim_snprintf((char *)errmsg, 300,
|
errmsg_allocated = true;
|
||||||
_("E513: write error, conversion failed in line %" PRId64
|
SET_ERRMSG(xmalloc(300));
|
||||||
" (make 'fenc' empty to override)"),
|
vim_snprintf(
|
||||||
(int64_t)write_info.bw_conv_error_lnum);
|
errmsg, 300,
|
||||||
|
_("E513: write error, conversion failed in line %" PRIdLINENR
|
||||||
|
" (make 'fenc' empty to override)"),
|
||||||
|
write_info.bw_conv_error_lnum);
|
||||||
|
}
|
||||||
|
} else if (got_int) {
|
||||||
|
SET_ERRMSG(_(e_interr));
|
||||||
|
} else {
|
||||||
|
SET_ERRMSG(_("E514: write error (file system full?)"));
|
||||||
}
|
}
|
||||||
} else if (got_int)
|
|
||||||
errmsg = (char_u *)_(e_interr);
|
|
||||||
else
|
|
||||||
errmsg = (char_u *)_("E514: write error (file system full?)");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -3673,31 +3681,37 @@ nofail:
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (errmsg != NULL) {
|
if (errmsg != NULL) {
|
||||||
int numlen = errnum != NULL ? (int)STRLEN(errnum) : 0;
|
const size_t numlen = (errnum != NULL ? strlen(errnum) : 0);
|
||||||
|
|
||||||
attr = hl_attr(HLF_E); /* set highlight for error messages */
|
// Put file name in IObuff with quotes.
|
||||||
msg_add_fname(buf,
|
|
||||||
#ifndef UNIX
|
#ifndef UNIX
|
||||||
sfname
|
msg_add_fname(buf, sfname);
|
||||||
#else
|
#else
|
||||||
fname
|
msg_add_fname(buf, fname);
|
||||||
#endif
|
#endif
|
||||||
); /* put file name in IObuff with quotes */
|
const size_t errmsglen = strlen(errmsg);
|
||||||
if (STRLEN(IObuff) + STRLEN(errmsg) + numlen >= IOSIZE)
|
if (STRLEN(IObuff) + errmsglen + numlen >= IOSIZE) {
|
||||||
IObuff[IOSIZE - STRLEN(errmsg) - numlen - 1] = NUL;
|
IObuff[IOSIZE - errmsglen - numlen - 1] = NUL;
|
||||||
/* If the error message has the form "is ...", put the error number in
|
}
|
||||||
* front of the file name. */
|
// If the error message has the form "is ...", put the error number in
|
||||||
|
// front of the file name.
|
||||||
if (errnum != NULL) {
|
if (errnum != NULL) {
|
||||||
STRMOVE(IObuff + numlen, IObuff);
|
STRMOVE(IObuff + numlen, IObuff);
|
||||||
memmove(IObuff, errnum, (size_t)numlen);
|
memmove(IObuff, errnum, numlen);
|
||||||
}
|
}
|
||||||
STRCAT(IObuff, errmsg);
|
xstrlcat((char *)IObuff, errmsg, IOSIZE);
|
||||||
emsg(IObuff);
|
if (errmsgarg != 0) {
|
||||||
if (errmsg_allocated)
|
emsgf((const char *)IObuff, os_strerror(errmsgarg));
|
||||||
|
} else {
|
||||||
|
emsgf((const char *)IObuff);
|
||||||
|
}
|
||||||
|
if (errmsg_allocated) {
|
||||||
xfree(errmsg);
|
xfree(errmsg);
|
||||||
|
}
|
||||||
|
|
||||||
retval = FAIL;
|
retval = FAIL;
|
||||||
if (end == 0) {
|
if (end == 0) {
|
||||||
|
const int attr = hl_attr(HLF_E); // Set highlight for error messages.
|
||||||
MSG_PUTS_ATTR(_("\nWARNING: Original file may be lost or damaged\n"),
|
MSG_PUTS_ATTR(_("\nWARNING: Original file may be lost or damaged\n"),
|
||||||
attr | MSG_HIST);
|
attr | MSG_HIST);
|
||||||
MSG_PUTS_ATTR(_(
|
MSG_PUTS_ATTR(_(
|
||||||
@@ -3759,6 +3773,9 @@ nofail:
|
|||||||
got_int |= prev_got_int;
|
got_int |= prev_got_int;
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
|
#undef SET_ERRMSG
|
||||||
|
#undef SET_ERRMSG_ARG
|
||||||
|
#undef SET_ERRMSG_NUM
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Reference in New Issue
Block a user