vim-patch:8.2.0151: detecting a script was already sourced is unreliable

Problem:    Detecting a script was already sourced is unreliable.
Solution:   Do not use the inode number.
978d170bdc
This commit is contained in:
zeertzjq
2022-07-08 11:26:03 +08:00
parent eafa09de7d
commit 159a0b651f
2 changed files with 8 additions and 23 deletions

View File

@@ -2156,34 +2156,23 @@ scriptitem_T *get_current_script_id(char_u *fname, sctx_T *ret_sctx)
sctx_T script_sctx = { .sc_seq = ++last_current_SID_seq, sctx_T script_sctx = { .sc_seq = ++last_current_SID_seq,
.sc_lnum = 0, .sc_lnum = 0,
.sc_sid = 0 }; .sc_sid = 0 };
FileID file_id;
scriptitem_T *si = NULL; scriptitem_T *si = NULL;
bool file_id_ok = os_fileid((char *)fname, &file_id);
assert(script_items.ga_len >= 0); assert(script_items.ga_len >= 0);
for (script_sctx.sc_sid = script_items.ga_len; script_sctx.sc_sid > 0; script_sctx.sc_sid--) { for (script_sctx.sc_sid = script_items.ga_len; script_sctx.sc_sid > 0; script_sctx.sc_sid--) {
// We used to check inode here, but that doesn't work:
// - If a script is edited and written, it may get a different
// inode number, even though to the user it is the same script.
// - If a script is deleted and another script is written, with a
// different name, the inode may be re-used.
si = &SCRIPT_ITEM(script_sctx.sc_sid); si = &SCRIPT_ITEM(script_sctx.sc_sid);
if (si->sn_name != NULL) { if (si->sn_name != NULL && FNAMECMP(si->sn_name, fname) == 0) {
// Compare dev/ino when possible, it catches symbolic links. // Found it!
// Also compare file names, the inode may change when the file was break;
// edited or it may be re-used for another script (esp. in tests).
if (file_id_ok && si->file_id_valid && !os_fileid_equal(&(si->file_id), &file_id)) {
continue;
}
if (FNAMECMP(si->sn_name, fname) == 0) {
// Found it!
break;
}
} }
} }
if (script_sctx.sc_sid == 0) { if (script_sctx.sc_sid == 0) {
si = new_script_item((char *)vim_strsave(fname), &script_sctx.sc_sid); si = new_script_item((char *)vim_strsave(fname), &script_sctx.sc_sid);
if (file_id_ok) {
si->file_id_valid = true;
si->file_id = file_id;
} else {
si->file_id_valid = false;
}
} }
if (ret_sctx != NULL) { if (ret_sctx != NULL) {
*ret_sctx = script_sctx; *ret_sctx = script_sctx;

View File

@@ -15,12 +15,8 @@
#define CCGD_ALLBUF 8 // may write all buffers #define CCGD_ALLBUF 8 // may write all buffers
#define CCGD_EXCMD 16 // may suggest using ! #define CCGD_EXCMD 16 // may suggest using !
/// Also store the dev/ino, so that we don't have to stat() each
/// script when going through the list.
typedef struct scriptitem_S { typedef struct scriptitem_S {
char_u *sn_name; char_u *sn_name;
bool file_id_valid;
FileID file_id;
bool sn_prof_on; ///< true when script is/was profiled bool sn_prof_on; ///< true when script is/was profiled
bool sn_pr_force; ///< forceit: profile functions in this script bool sn_pr_force; ///< forceit: profile functions in this script
proftime_T sn_pr_child; ///< time set when going into first child proftime_T sn_pr_child; ///< time set when going into first child