mirror of
https://github.com/neovim/neovim.git
synced 2026-03-20 15:39:43 +00:00
shada: First write temporary file and only then check any permissions
It is not logical that on UNIX permissions can prevent even writing temporary file, while on other OS it will first write temporary file and then fail during rename.
This commit is contained in:
@@ -2903,11 +2903,6 @@ int shada_write_file(const char *const file, bool nomerge)
|
||||
.error = NULL,
|
||||
};
|
||||
ShaDaReadDef sd_reader;
|
||||
#ifdef UNIX
|
||||
bool do_fchown = false;
|
||||
uv_uid_t old_uid = (uv_uid_t) -1;
|
||||
uv_gid_t old_gid = (uv_gid_t) -1;
|
||||
#endif
|
||||
|
||||
intptr_t fd;
|
||||
|
||||
@@ -2916,31 +2911,6 @@ int shada_write_file(const char *const file, bool nomerge)
|
||||
nomerge = true;
|
||||
goto shada_write_file_nomerge;
|
||||
}
|
||||
#ifdef UNIX
|
||||
// For Unix we check the owner of the file. It's not very nice to
|
||||
// overwrite a user’s viminfo file after a "su root", with a
|
||||
// viminfo file that the user can't read.
|
||||
FileInfo old_info;
|
||||
if (os_fileinfo((char *)fname, &old_info)) {
|
||||
if (getuid() == ROOT_UID) {
|
||||
if (old_info.stat.st_uid != ROOT_UID
|
||||
|| old_info.stat.st_gid != getgid()) {
|
||||
do_fchown = true;
|
||||
old_uid = (uv_uid_t) old_info.stat.st_uid;
|
||||
old_gid = (uv_gid_t) old_info.stat.st_gid;
|
||||
}
|
||||
} else if (!(old_info.stat.st_uid == getuid()
|
||||
? (old_info.stat.st_mode & 0200)
|
||||
: (old_info.stat.st_gid == getgid()
|
||||
? (old_info.stat.st_mode & 0020)
|
||||
: (old_info.stat.st_mode & 0002)))) {
|
||||
EMSG2(_("E137: ShaDa file is not writable: %s"), fname);
|
||||
sd_reader.close(&sd_reader);
|
||||
xfree(fname);
|
||||
return FAIL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
tempname = modname(fname, ".tmp.a", false);
|
||||
if (tempname == NULL) {
|
||||
nomerge = true;
|
||||
@@ -3024,27 +2994,47 @@ shada_write_file_nomerge: {}
|
||||
const ShaDaWriteResult sw_ret = shada_write(&sd_writer, (nomerge
|
||||
? NULL
|
||||
: &sd_reader));
|
||||
#ifdef UNIX
|
||||
if (!do_fchown) {
|
||||
#endif
|
||||
sd_writer.close(&sd_writer);
|
||||
#ifdef UNIX
|
||||
}
|
||||
#ifndef UNIX
|
||||
sd_writer.close(&sd_writer);
|
||||
#endif
|
||||
if (!nomerge) {
|
||||
sd_reader.close(&sd_reader);
|
||||
bool did_remove = false;
|
||||
if (sw_ret == kSDWriteSuccessfull) {
|
||||
#ifdef UNIX
|
||||
if (do_fchown) {
|
||||
const int fchown_ret = os_fchown((int) fd, old_uid, old_gid);
|
||||
sd_writer.close(&sd_writer);
|
||||
if (fchown_ret != 0) {
|
||||
EMSG3(_(RNERR "Failed setting uid and gid for file %s: %s"),
|
||||
tempname, os_strerror(fchown_ret));
|
||||
bool closed = false;
|
||||
// For Unix we check the owner of the file. It's not very nice to
|
||||
// overwrite a user’s viminfo file after a "su root", with a
|
||||
// viminfo file that the user can't read.
|
||||
FileInfo old_info;
|
||||
if (os_fileinfo((char *)fname, &old_info)) {
|
||||
if (getuid() == ROOT_UID) {
|
||||
if (old_info.stat.st_uid != ROOT_UID
|
||||
|| old_info.stat.st_gid != getgid()) {
|
||||
const uv_uid_t old_uid = (uv_uid_t) old_info.stat.st_uid;
|
||||
const uv_gid_t old_gid = (uv_gid_t) old_info.stat.st_gid;
|
||||
const int fchown_ret = os_fchown((int) fd, old_uid, old_gid);
|
||||
sd_writer.close(&sd_writer);
|
||||
if (fchown_ret != 0) {
|
||||
EMSG3(_(RNERR "Failed setting uid and gid for file %s: %s"),
|
||||
tempname, os_strerror(fchown_ret));
|
||||
goto shada_write_file_did_not_remove;
|
||||
}
|
||||
closed = true;
|
||||
}
|
||||
} else if (!(old_info.stat.st_uid == getuid()
|
||||
? (old_info.stat.st_mode & 0200)
|
||||
: (old_info.stat.st_gid == getgid()
|
||||
? (old_info.stat.st_mode & 0020)
|
||||
: (old_info.stat.st_mode & 0002)))) {
|
||||
EMSG2(_("E137: ShaDa file is not writable: %s"), fname);
|
||||
sd_writer.close(&sd_writer);
|
||||
goto shada_write_file_did_not_remove;
|
||||
}
|
||||
}
|
||||
if (!closed) {
|
||||
sd_writer.close(&sd_writer);
|
||||
}
|
||||
#endif
|
||||
if (vim_rename(tempname, fname) == -1) {
|
||||
EMSG3(_(RNERR "Can't rename ShaDa file from %s to %s!"),
|
||||
|
||||
Reference in New Issue
Block a user