mirror of
https://github.com/neovim/neovim.git
synced 2026-04-18 21:40:45 +00:00
Merge pull request #38751 from zeertzjq/vim-9.2.0291
vim-patch:9.2.{0291,0293}
This commit is contained in:
@@ -1503,9 +1503,10 @@ scripterror:
|
||||
|
||||
if (parmp->diff_mode && os_isdir(p) && GARGCOUNT > 0
|
||||
&& !os_isdir(alist_name(&GARGLIST[0]))) {
|
||||
char *r = concat_fnames(p, path_tail(alist_name(&GARGLIST[0])), true);
|
||||
const char *tail = path_tail(alist_name(&GARGLIST[0]));
|
||||
String ret = concat_fnames(cstr_as_string(p), cstr_as_string(tail), true);
|
||||
xfree(p);
|
||||
p = r;
|
||||
p = ret.data;
|
||||
}
|
||||
|
||||
#ifdef CASE_INSENSITIVE_FILENAME
|
||||
|
||||
@@ -1327,11 +1327,11 @@ int recover_names(char *fname, bool do_list, list_T *ret_list, int nr, char **fn
|
||||
}
|
||||
} else { // check directory dir_name
|
||||
if (fname == NULL) {
|
||||
names[0] = concat_fnames(dir_name.data, "*.sw?", true);
|
||||
names[0] = concat_fnames(dir_name, STATIC_CSTR_AS_STRING("*.sw?"), true).data;
|
||||
// For Unix names starting with a dot are special. MS-Windows
|
||||
// supports this too, on some file systems.
|
||||
names[1] = concat_fnames(dir_name.data, ".*.sw?", true);
|
||||
names[2] = concat_fnames(dir_name.data, ".sw?", true);
|
||||
names[1] = concat_fnames(dir_name, STATIC_CSTR_AS_STRING(".*.sw?"), true).data;
|
||||
names[2] = concat_fnames(dir_name, STATIC_CSTR_AS_STRING(".sw?"), true).data;
|
||||
num_names = 3;
|
||||
} else {
|
||||
p = dir_name.data + dir_name.size;
|
||||
@@ -1340,7 +1340,7 @@ int recover_names(char *fname, bool do_list, list_T *ret_list, int nr, char **fn
|
||||
tail = make_percent_swname(dir_name.data, p, fname_res);
|
||||
} else {
|
||||
tail = path_tail(fname_res);
|
||||
tail = concat_fnames(dir_name.data, tail, true);
|
||||
tail = concat_fnames(dir_name, cstr_as_string(tail), true).data;
|
||||
}
|
||||
num_names = recov_file_names(names, tail, false);
|
||||
xfree(tail);
|
||||
@@ -1433,8 +1433,8 @@ int recover_names(char *fname, bool do_list, list_T *ret_list, int nr, char **fn
|
||||
ui_flush();
|
||||
} else if (ret_list != NULL) {
|
||||
for (int i = 0; i < num_files; i++) {
|
||||
char *name = concat_fnames(dir_name.data, files[i], true);
|
||||
tv_list_append_allocated_string(ret_list, name);
|
||||
String name = concat_fnames(dir_name, cstr_as_string(files[i]), true);
|
||||
tv_list_append_allocated_string(ret_list, name.data);
|
||||
}
|
||||
} else {
|
||||
file_count += num_files;
|
||||
@@ -1459,24 +1459,27 @@ int recover_names(char *fname, bool do_list, list_T *ret_list, int nr, char **fn
|
||||
char *make_percent_swname(char *dir, char *dir_end, const char *name)
|
||||
FUNC_ATTR_NONNULL_ARG(1, 2)
|
||||
{
|
||||
char *d = NULL;
|
||||
char *f = fix_fname(name != NULL ? name : "");
|
||||
if (f == NULL) {
|
||||
String fixed_fname;
|
||||
fixed_fname.data = fix_fname(name != NULL ? name : "");
|
||||
if (fixed_fname.data == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *s = xstrdup(f);
|
||||
for (d = s; *d != NUL; MB_PTR_ADV(d)) {
|
||||
if (vim_ispathsep(*d)) {
|
||||
*d = '%';
|
||||
char *p;
|
||||
for (p = fixed_fname.data; *p != NUL; MB_PTR_ADV(p)) {
|
||||
if (vim_ispathsep(*p)) {
|
||||
*p = '%';
|
||||
}
|
||||
}
|
||||
fixed_fname.size = (size_t)(p - fixed_fname.data);
|
||||
|
||||
dir_end[-1] = NUL; // remove one trailing slash
|
||||
d = concat_fnames(dir, s, true);
|
||||
xfree(s);
|
||||
xfree(f);
|
||||
return d;
|
||||
// remove one trailing slash
|
||||
p = &dir_end[-1];
|
||||
*p = NUL;
|
||||
String d = concat_fnames(cbuf_as_string(dir, (size_t)(p - dir)), fixed_fname, true);
|
||||
xfree(fixed_fname.data);
|
||||
|
||||
return d.data;
|
||||
}
|
||||
|
||||
// PID of swapfile owner, or zero if not running.
|
||||
@@ -1684,7 +1687,8 @@ static int recov_file_names(char **names, char *path, bool prepend_dot)
|
||||
}
|
||||
|
||||
// Form the normal swapfile name pattern by appending ".sw?".
|
||||
names[num_names] = concat_fnames(path, ".sw?", false);
|
||||
names[num_names] = concat_fnames(cstr_as_string(path),
|
||||
STATIC_CSTR_AS_STRING(".sw?"), false).data;
|
||||
if (num_names >= 1) { // check if we have the same name twice
|
||||
char *p = names[num_names - 1];
|
||||
int i = (int)strlen(names[num_names - 1]) - (int)strlen(names[num_names]);
|
||||
@@ -3327,28 +3331,31 @@ char *makeswapname(char *fname, char *ffname, buf_T *buf, char *dir_name)
|
||||
/// @param dname don't use "dirname", it is a global for Alpha
|
||||
char *get_file_in_dir(char *fname, char *dname)
|
||||
{
|
||||
char *retval;
|
||||
|
||||
char *tail = path_tail(fname);
|
||||
String retval;
|
||||
String tail = cstr_as_string(path_tail(fname));
|
||||
|
||||
if (dname[0] == '.' && dname[1] == NUL) {
|
||||
retval = xstrdup(fname);
|
||||
} else if (dname[0] == '.' && vim_ispathsep(dname[1])) {
|
||||
if (tail == fname) { // no path before file name
|
||||
retval = concat_fnames(dname + 2, tail, true);
|
||||
} else {
|
||||
char save_char = *tail;
|
||||
*tail = NUL;
|
||||
char *t = concat_fnames(fname, dname + 2, true);
|
||||
*tail = save_char;
|
||||
retval = concat_fnames(t, tail, true);
|
||||
xfree(t);
|
||||
}
|
||||
retval = cbuf_to_string(fname, (size_t)(tail.data - fname) + tail.size);
|
||||
} else {
|
||||
retval = concat_fnames(dname, tail, true);
|
||||
size_t dname_len = strlen(dname);
|
||||
if (dname[0] == '.' && vim_ispathsep(dname[1])) {
|
||||
if (tail.data == fname) { // no path before file name
|
||||
retval = concat_fnames(cbuf_as_string(dname + 2, dname_len - 2), tail, true);
|
||||
} else {
|
||||
const char save_char = *tail.data;
|
||||
*tail.data = NUL;
|
||||
String tmp = concat_fnames(cbuf_as_string(fname, (size_t)(tail.data - fname)),
|
||||
cbuf_as_string(dname + 2, dname_len - 2), true);
|
||||
*tail.data = save_char;
|
||||
retval = concat_fnames(tmp, tail, true);
|
||||
xfree(tmp.data);
|
||||
}
|
||||
} else {
|
||||
retval = concat_fnames(cbuf_as_string(dname, dname_len), tail, true);
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
return retval.data;
|
||||
}
|
||||
|
||||
/// Build the ATTENTION message: info about an existing swapfile.
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <uv.h>
|
||||
|
||||
#include "auto/config.h"
|
||||
#include "nvim/api/private/helpers.h"
|
||||
#include "nvim/ascii_defs.h"
|
||||
#include "nvim/buffer_defs.h"
|
||||
#include "nvim/charset.h"
|
||||
@@ -826,11 +827,13 @@ static char *vim_runtime_dir(const char *vimdir)
|
||||
if (vimdir == NULL || *vimdir == NUL) {
|
||||
return NULL;
|
||||
}
|
||||
char *p = concat_fnames(vimdir, RUNTIME_DIRNAME, true);
|
||||
if (os_isdir(p)) {
|
||||
return p;
|
||||
size_t vimdir_len = strlen(vimdir);
|
||||
String p = concat_fnames(cbuf_as_string((char *)vimdir, vimdir_len),
|
||||
STATIC_CSTR_AS_STRING(RUNTIME_DIRNAME), true);
|
||||
if (os_isdir(p.data)) {
|
||||
return p.data;
|
||||
}
|
||||
xfree(p);
|
||||
xfree(p.data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -443,14 +443,16 @@ int path_fnamencmp(const char *const fname1, const char *const fname2, size_t le
|
||||
///
|
||||
/// @return fname1
|
||||
static inline char *do_concat_fnames(char *fname1, const size_t len1, const char *fname2,
|
||||
const size_t len2, const bool sep)
|
||||
const size_t len2, const bool sep, size_t *len)
|
||||
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET
|
||||
{
|
||||
if (sep && *fname1 && !after_pathsep(fname1, fname1 + len1)) {
|
||||
fname1[len1] = PATHSEP;
|
||||
memmove(fname1 + len1 + 1, fname2, len2 + 1);
|
||||
*len = len1 + 1 + len2;
|
||||
} else {
|
||||
memmove(fname1 + len1, fname2, len2 + 1);
|
||||
*len = len1 + len2;
|
||||
}
|
||||
|
||||
return fname1;
|
||||
@@ -465,14 +467,14 @@ static inline char *do_concat_fnames(char *fname1, const size_t len1, const char
|
||||
/// @param sep is a flag to indicate a path separator should be added
|
||||
/// if necessary
|
||||
/// @return [allocated] Concatenation of fname1 and fname2.
|
||||
char *concat_fnames(const char *fname1, const char *fname2, bool sep)
|
||||
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET
|
||||
String concat_fnames(String fname1, String fname2, bool sep)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
const size_t len1 = strlen(fname1);
|
||||
const size_t len2 = strlen(fname2);
|
||||
char *dest = xmalloc(len1 + len2 + 3);
|
||||
memmove(dest, fname1, len1 + 1);
|
||||
return do_concat_fnames(dest, len1, fname2, len2, sep);
|
||||
String ret;
|
||||
ret.data = xmalloc(fname1.size + (sep ? 1 : 0) + fname2.size + 1);
|
||||
memmove(ret.data, fname1.data, fname1.size + 1);
|
||||
do_concat_fnames(ret.data, fname1.size, fname2.data, fname2.size, sep, &ret.size);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// Concatenate file names fname1 and fname2
|
||||
@@ -491,8 +493,9 @@ char *concat_fnames_realloc(char *fname1, const char *fname2, bool sep)
|
||||
{
|
||||
const size_t len1 = strlen(fname1);
|
||||
const size_t len2 = strlen(fname2);
|
||||
size_t len;
|
||||
return do_concat_fnames(xrealloc(fname1, len1 + len2 + 3), len1,
|
||||
fname2, len2, sep);
|
||||
fname2, len2, sep, &len);
|
||||
}
|
||||
|
||||
/// Adds a path separator to a filename, unless it already ends in one.
|
||||
@@ -502,13 +505,17 @@ char *concat_fnames_realloc(char *fname1, const char *fname2, bool sep)
|
||||
bool add_pathsep(char *p)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
const size_t len = strlen(p);
|
||||
if (*p != NUL && !after_pathsep(p, p + len)) {
|
||||
if (*p == NUL) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const size_t plen = strlen(p);
|
||||
if (!after_pathsep(p, p + plen)) {
|
||||
const size_t pathsep_len = sizeof(PATHSEPSTR);
|
||||
if (len > MAXPATHL - pathsep_len) {
|
||||
if (plen > MAXPATHL - pathsep_len) {
|
||||
return false;
|
||||
}
|
||||
memcpy(p + len, PATHSEPSTR, pathsep_len);
|
||||
memcpy(p + plen, PATHSEPSTR, pathsep_len);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <stddef.h> // IWYU pragma: keep
|
||||
|
||||
#include "nvim/api/private/defs.h" // IWYU pragma: keep
|
||||
#include "nvim/garray_defs.h" // IWYU pragma: keep
|
||||
#include "nvim/types_defs.h" // IWYU pragma: keep
|
||||
|
||||
|
||||
@@ -2307,8 +2307,8 @@ void copy_loclist_stack(win_T *from, win_T *to)
|
||||
/// Also sets the b_has_qf_entry flag.
|
||||
static int qf_get_fnum(qf_list_T *qfl, char *directory, char *fname)
|
||||
{
|
||||
char *ptr = NULL;
|
||||
char *bufname;
|
||||
String ptr = STRING_INIT;
|
||||
String bufname;
|
||||
buf_T *buf;
|
||||
if (fname == NULL || *fname == NUL) { // no file name
|
||||
return 0;
|
||||
@@ -2320,43 +2320,43 @@ static int qf_get_fnum(qf_list_T *qfl, char *directory, char *fname)
|
||||
}
|
||||
slash_adjust(fname);
|
||||
#endif
|
||||
String fname_str = cstr_as_string(fname);
|
||||
if (directory != NULL && !vim_isAbsName(fname)) {
|
||||
ptr = concat_fnames(directory, fname, true);
|
||||
ptr = concat_fnames(cstr_as_string(directory), fname_str, true);
|
||||
// Here we check if the file really exists.
|
||||
// This should normally be true, but if make works without
|
||||
// "leaving directory"-messages we might have missed a
|
||||
// directory change.
|
||||
if (!os_path_exists(ptr)) {
|
||||
xfree(ptr);
|
||||
if (!os_path_exists(ptr.data)) {
|
||||
xfree(ptr.data);
|
||||
directory = qf_guess_filepath(qfl, fname);
|
||||
if (directory) {
|
||||
ptr = concat_fnames(directory, fname, true);
|
||||
ptr = concat_fnames(cstr_as_string(directory), fname_str, true);
|
||||
} else {
|
||||
ptr = xstrdup(fname);
|
||||
ptr = copy_string(fname_str, NULL);
|
||||
}
|
||||
}
|
||||
// Use concatenated directory name and file name.
|
||||
bufname = ptr;
|
||||
} else {
|
||||
bufname = fname;
|
||||
bufname = fname_str;
|
||||
}
|
||||
|
||||
if (qf_last_bufname != NULL
|
||||
&& strcmp(bufname, qf_last_bufname) == 0
|
||||
if (qf_last_bufname != NULL && strcmp(bufname.data, qf_last_bufname) == 0
|
||||
&& bufref_valid(&qf_last_bufref)) {
|
||||
buf = qf_last_bufref.br_buf;
|
||||
xfree(ptr);
|
||||
xfree(ptr.data);
|
||||
} else {
|
||||
xfree(qf_last_bufname);
|
||||
buf = buflist_new(bufname, NULL, 0, BLN_NOOPT);
|
||||
qf_last_bufname = (bufname == ptr) ? bufname : xstrdup(bufname);
|
||||
buf = buflist_new(bufname.data, NULL, 0, BLN_NOOPT);
|
||||
qf_last_bufname = (bufname.data == ptr.data)
|
||||
? bufname.data : xmemdupz(bufname.data, bufname.size);
|
||||
set_bufref(&qf_last_bufref, buf);
|
||||
}
|
||||
if (buf == NULL) {
|
||||
return 0;
|
||||
}
|
||||
buf->b_has_qf_entry =
|
||||
IS_QF_LIST(qfl) ? BUF_HAS_QF_ENTRY : BUF_HAS_LL_ENTRY;
|
||||
buf->b_has_qf_entry = IS_QF_LIST(qfl) ? BUF_HAS_QF_ENTRY : BUF_HAS_LL_ENTRY;
|
||||
return buf->b_fnum;
|
||||
}
|
||||
|
||||
@@ -2382,16 +2382,18 @@ static char *qf_push_dir(char *dirbuf, struct dir_stack_T **stackptr, bool is_fi
|
||||
// Okay we don't have an absolute path.
|
||||
// dirbuf must be a subdir of one of the directories on the stack.
|
||||
// Let's search...
|
||||
size_t dirbuf_len = strlen(dirbuf);
|
||||
ds_new = (*stackptr)->next;
|
||||
(*stackptr)->dirname = NULL;
|
||||
while (ds_new) {
|
||||
char *dirname = concat_fnames(ds_new->dirname, dirbuf, true);
|
||||
if (os_isdir(dirname)) {
|
||||
String dirname = concat_fnames(cstr_as_string(ds_new->dirname),
|
||||
cbuf_as_string(dirbuf, dirbuf_len), true);
|
||||
if (os_isdir(dirname.data)) {
|
||||
xfree((*stackptr)->dirname);
|
||||
(*stackptr)->dirname = dirname;
|
||||
(*stackptr)->dirname = dirname.data;
|
||||
break;
|
||||
}
|
||||
xfree(dirname);
|
||||
xfree(dirname.data);
|
||||
ds_new = ds_new->next;
|
||||
}
|
||||
|
||||
@@ -2406,7 +2408,7 @@ static char *qf_push_dir(char *dirbuf, struct dir_stack_T **stackptr, bool is_fi
|
||||
// Nothing found -> it must be on top level
|
||||
if (ds_new == NULL) {
|
||||
xfree((*stackptr)->dirname);
|
||||
(*stackptr)->dirname = xstrdup(dirbuf);
|
||||
(*stackptr)->dirname = xmemdupz(dirbuf, dirbuf_len);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2479,19 +2481,20 @@ static char *qf_guess_filepath(qf_list_T *qfl, char *filename)
|
||||
}
|
||||
|
||||
struct dir_stack_T *ds_ptr = qfl->qf_dir_stack->next;
|
||||
char *fullname = NULL;
|
||||
String fullname = STRING_INIT;
|
||||
String filename_str = cstr_as_string(filename);
|
||||
while (ds_ptr) {
|
||||
xfree(fullname);
|
||||
fullname = concat_fnames(ds_ptr->dirname, filename, true);
|
||||
xfree(fullname.data);
|
||||
fullname = concat_fnames(cstr_as_string(ds_ptr->dirname), filename_str, true);
|
||||
|
||||
if (os_path_exists(fullname)) {
|
||||
if (os_path_exists(fullname.data)) {
|
||||
break;
|
||||
}
|
||||
|
||||
ds_ptr = ds_ptr->next;
|
||||
}
|
||||
|
||||
xfree(fullname);
|
||||
xfree(fullname.data);
|
||||
|
||||
// clean up all dirs we already left
|
||||
while (qfl->qf_dir_stack->next != ds_ptr) {
|
||||
|
||||
@@ -1029,7 +1029,7 @@ static int gen_expand_wildcards_and_cb(int num_pat, char **pats, int flags, bool
|
||||
/// @param is_pack whether the added dir is a "pack/*/start/*/" style package
|
||||
static int add_pack_dir_to_rtp(char *fname, bool is_pack)
|
||||
{
|
||||
char *afterdir = NULL;
|
||||
String afterdir = STRING_INIT;
|
||||
int retval = FAIL;
|
||||
|
||||
char *p1 = get_past_head(fname);
|
||||
@@ -1063,17 +1063,24 @@ static int add_pack_dir_to_rtp(char *fname, bool is_pack)
|
||||
// Find "ffname" in "p_rtp", ignoring '/' vs '\' differences
|
||||
// Also stop at the first "after" directory
|
||||
size_t fname_len = strlen(ffname);
|
||||
char buf[MAXPATHL];
|
||||
char buf_data[MAXPATHL];
|
||||
String buf;
|
||||
buf.data = buf_data;
|
||||
|
||||
const char *insp = NULL;
|
||||
const char *after_insp = NULL;
|
||||
size_t p_rtp_len = 0;
|
||||
const char *entry = p_rtp;
|
||||
while (*entry != NUL) {
|
||||
const char *cur_entry = entry;
|
||||
copy_option_part((char **)&entry, buf, MAXPATHL, ",");
|
||||
buf.size = copy_option_part((char **)&entry, buf.data, MAXPATHL, ",");
|
||||
|
||||
char *p = strstr(buf, "after");
|
||||
// keep track of p_rtp length as we go to make the strlen() below have less work to do
|
||||
p_rtp_len += (*(cur_entry + buf.size) == ',') ? buf.size + 1 : buf.size;
|
||||
|
||||
char *p = strstr(buf.data, "after");
|
||||
bool is_after = p != NULL
|
||||
&& p > buf
|
||||
&& p > buf.data
|
||||
&& vim_ispathsep(p[-1])
|
||||
&& (vim_ispathsep(p[5]) || p[5] == NUL || p[5] == ',');
|
||||
|
||||
@@ -1088,8 +1095,8 @@ static int add_pack_dir_to_rtp(char *fname, bool is_pack)
|
||||
}
|
||||
|
||||
if (insp == NULL) {
|
||||
add_pathsep(buf);
|
||||
char *const rtp_ffname = fix_fname(buf);
|
||||
add_pathsep(buf.data);
|
||||
char *const rtp_ffname = fix_fname(buf.data);
|
||||
if (rtp_ffname == NULL) {
|
||||
goto theend;
|
||||
}
|
||||
@@ -1101,24 +1108,25 @@ static int add_pack_dir_to_rtp(char *fname, bool is_pack)
|
||||
}
|
||||
}
|
||||
|
||||
// finish measuring the length of p_rtp
|
||||
p_rtp_len += strlen(p_rtp + p_rtp_len);
|
||||
if (insp == NULL) {
|
||||
// Both "fname" and "after" not found, append at the end.
|
||||
insp = p_rtp + strlen(p_rtp);
|
||||
insp = p_rtp + p_rtp_len;
|
||||
}
|
||||
|
||||
// check if rtp/pack/name/start/name/after exists
|
||||
afterdir = concat_fnames(fname, "after", true);
|
||||
size_t afterlen = 0;
|
||||
if (is_pack ? pack_has_entries(afterdir) : os_isdir(afterdir)) {
|
||||
afterlen = strlen(afterdir) + 1; // add one for comma
|
||||
fname_len = strlen(fname);
|
||||
afterdir = concat_fnames(cbuf_as_string(fname, fname_len), STATIC_CSTR_AS_STRING("after"), true);
|
||||
if (is_pack ? !pack_has_entries(afterdir.data) : !os_isdir(afterdir.data)) {
|
||||
afterdir.size = 0;
|
||||
}
|
||||
|
||||
const size_t oldlen = strlen(p_rtp);
|
||||
const size_t addlen = strlen(fname) + 1; // add one for comma
|
||||
const size_t new_rtp_capacity = oldlen + addlen + afterlen + 1;
|
||||
// add one for NUL ------------------------------------------^
|
||||
char *const new_rtp = try_malloc(new_rtp_capacity);
|
||||
if (new_rtp == NULL) {
|
||||
const size_t new_rtp_capacity = p_rtp_len + fname_len + afterdir.size + 3;
|
||||
// add two for commas and one more for NUL -----------------------------^
|
||||
String new_rtp;
|
||||
new_rtp.data = try_malloc(new_rtp_capacity);
|
||||
if (new_rtp.data == NULL) {
|
||||
goto theend;
|
||||
}
|
||||
|
||||
@@ -1126,49 +1134,54 @@ static int add_pack_dir_to_rtp(char *fname, bool is_pack)
|
||||
// Create new_rtp, first: {keep},{fname}
|
||||
size_t keep = (size_t)(insp - p_rtp);
|
||||
size_t first_pos = keep;
|
||||
memmove(new_rtp, p_rtp, keep);
|
||||
size_t new_rtp_len = keep;
|
||||
memmove(new_rtp.data, p_rtp, keep);
|
||||
new_rtp.size = keep;
|
||||
if (*insp == NUL) {
|
||||
new_rtp[new_rtp_len++] = ','; // add comma before
|
||||
new_rtp.data[new_rtp.size++] = ','; // add comma before
|
||||
first_pos++;
|
||||
}
|
||||
memmove(new_rtp + new_rtp_len, fname, addlen - 1);
|
||||
new_rtp_len += addlen - 1;
|
||||
memmove(new_rtp.data + new_rtp.size, fname, fname_len);
|
||||
new_rtp.size += fname_len;
|
||||
if (*insp != NUL) {
|
||||
new_rtp[new_rtp_len++] = ','; // add comma after
|
||||
new_rtp.data[new_rtp.size++] = ','; // add comma after
|
||||
}
|
||||
|
||||
size_t after_pos = 0;
|
||||
|
||||
if (afterlen > 0 && after_insp != NULL) {
|
||||
if (afterdir.size > 0 && after_insp != NULL) {
|
||||
size_t keep_after = (size_t)(after_insp - p_rtp);
|
||||
size_t append_len = keep_after - keep;
|
||||
|
||||
// Add to new_rtp: {keep},{fname}{keep_after},{afterdir}
|
||||
memmove(new_rtp + new_rtp_len, p_rtp + keep, keep_after - keep);
|
||||
new_rtp_len += keep_after - keep;
|
||||
memmove(new_rtp + new_rtp_len, afterdir, afterlen - 1);
|
||||
new_rtp_len += afterlen - 1;
|
||||
new_rtp[new_rtp_len++] = ',';
|
||||
memmove(new_rtp.data + new_rtp.size, p_rtp + keep, append_len);
|
||||
new_rtp.size += append_len;
|
||||
memmove(new_rtp.data + new_rtp.size, afterdir.data, afterdir.size);
|
||||
new_rtp.size += afterdir.size;
|
||||
new_rtp.data[new_rtp.size++] = ',';
|
||||
keep = keep_after;
|
||||
after_pos = keep_after;
|
||||
}
|
||||
|
||||
if (p_rtp[keep] != NUL) {
|
||||
size_t append_len = p_rtp_len - keep;
|
||||
// Append rest: {keep},{fname}{keep_after},{afterdir}{rest}
|
||||
memmove(new_rtp + new_rtp_len, p_rtp + keep, oldlen - keep + 1);
|
||||
memmove(new_rtp.data + new_rtp.size, p_rtp + keep, append_len + 1); // add one for NUL
|
||||
new_rtp.size += append_len;
|
||||
} else {
|
||||
new_rtp[new_rtp_len] = NUL;
|
||||
new_rtp.data[new_rtp.size] = NUL;
|
||||
}
|
||||
|
||||
if (afterlen > 0 && after_insp == NULL) {
|
||||
if (afterdir.size > 0 && after_insp == NULL) {
|
||||
// Append afterdir when "after" was not found:
|
||||
// {keep},{fname}{rest},{afterdir}
|
||||
after_pos = xstrlcat(new_rtp, ",", new_rtp_capacity);
|
||||
xstrlcat(new_rtp, afterdir, new_rtp_capacity);
|
||||
new_rtp.data[new_rtp.size++] = ',';
|
||||
after_pos = new_rtp.size;
|
||||
memmove(new_rtp.data + new_rtp.size, afterdir.data, afterdir.size + 1); // add one for NUL
|
||||
new_rtp.size += afterdir.size;
|
||||
}
|
||||
|
||||
bool was_valid = runtime_search_path_valid;
|
||||
set_option_value_give_err(kOptRuntimepath, CSTR_AS_OPTVAL(new_rtp), 0);
|
||||
set_option_value_give_err(kOptRuntimepath, STRING_OPTVAL(new_rtp), 0);
|
||||
|
||||
assert(!runtime_search_path_valid);
|
||||
// If this is the result of "packadd opt_pack", rebuilding runtime_search_pat
|
||||
@@ -1181,16 +1194,17 @@ static int add_pack_dir_to_rtp(char *fname, bool is_pack)
|
||||
kv_pushp(runtime_search_path);
|
||||
ssize_t i = (ssize_t)(kv_size(runtime_search_path)) - 1;
|
||||
|
||||
if (afterlen > 0) {
|
||||
if (afterdir.size > 0) {
|
||||
kv_pushp(runtime_search_path);
|
||||
i += 1;
|
||||
for (; i >= 1; i--) {
|
||||
if (i > 1 && kv_A(runtime_search_path, i - 2).pos_in_rtp >= after_pos) {
|
||||
kv_A(runtime_search_path, i) = kv_A(runtime_search_path, i - 2);
|
||||
kv_A(runtime_search_path, i).pos_in_rtp += addlen + afterlen;
|
||||
kv_A(runtime_search_path, i).pos_in_rtp += fname_len + afterdir.size + 2;
|
||||
} else {
|
||||
kv_A(runtime_search_path, i) = (SearchPathItem){ xstrdup(afterdir), true, true, kNone,
|
||||
after_pos + addlen };
|
||||
kv_A(runtime_search_path, i) = (SearchPathItem){
|
||||
xmemdupz(afterdir.data, afterdir.size), true, true, kNone, after_pos + fname_len + 1,
|
||||
};
|
||||
i--;
|
||||
break;
|
||||
}
|
||||
@@ -1200,20 +1214,21 @@ static int add_pack_dir_to_rtp(char *fname, bool is_pack)
|
||||
for (; i >= 0; i--) {
|
||||
if (i > 0 && kv_A(runtime_search_path, i - 1).pos_in_rtp >= first_pos) {
|
||||
kv_A(runtime_search_path, i) = kv_A(runtime_search_path, i - 1);
|
||||
kv_A(runtime_search_path, i).pos_in_rtp += addlen;
|
||||
kv_A(runtime_search_path, i).pos_in_rtp += fname_len + 1;
|
||||
} else {
|
||||
kv_A(runtime_search_path, i) = (SearchPathItem){ xstrdup(fname), false, true, kNone,
|
||||
first_pos };
|
||||
kv_A(runtime_search_path, i) = (SearchPathItem){
|
||||
xmemdupz(fname, fname_len), false, true, kNone, first_pos
|
||||
};
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
xfree(new_rtp);
|
||||
xfree(new_rtp.data);
|
||||
retval = OK;
|
||||
|
||||
theend:
|
||||
xfree(ffname);
|
||||
xfree(afterdir);
|
||||
xfree(afterdir.data);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
@@ -688,9 +688,10 @@ char *u_get_undo_file_name(const char *const buf_ffname, const bool reading)
|
||||
#endif
|
||||
|
||||
char dir_name[MAXPATHL + 1];
|
||||
char *munged_name = NULL;
|
||||
String munged_name = STRING_INIT;
|
||||
char *undo_file_name = NULL;
|
||||
|
||||
const size_t ffname_len = strlen(ffname);
|
||||
// Loop over 'undodir'. When reading find the first file that exists.
|
||||
// When not reading use the first directory that exists or ".".
|
||||
char *dirp = p_udir;
|
||||
@@ -699,11 +700,10 @@ char *u_get_undo_file_name(const char *const buf_ffname, const bool reading)
|
||||
if (dir_len == 1 && dir_name[0] == '.') {
|
||||
// Use same directory as the ffname,
|
||||
// "dir/name" -> "dir/.name.un~"
|
||||
const size_t ffname_len = strlen(ffname);
|
||||
undo_file_name = xmalloc(ffname_len + 6);
|
||||
memmove(undo_file_name, ffname, ffname_len + 1);
|
||||
char *const tail = path_tail(undo_file_name);
|
||||
const size_t tail_len = strlen(tail);
|
||||
const size_t tail_len = ffname_len - (size_t)(tail - undo_file_name);
|
||||
memmove(tail + 1, tail, tail_len + 1);
|
||||
*tail = '.';
|
||||
memmove(tail + tail_len + 1, ".un~", sizeof(".un~"));
|
||||
@@ -714,6 +714,7 @@ char *u_get_undo_file_name(const char *const buf_ffname, const bool reading)
|
||||
char *p = &dir_name[dir_len - 1];
|
||||
while (vim_ispathsep(*p)) {
|
||||
*p-- = NUL;
|
||||
dir_len--;
|
||||
}
|
||||
|
||||
bool has_directory = os_isdir(dir_name);
|
||||
@@ -730,15 +731,16 @@ char *u_get_undo_file_name(const char *const buf_ffname, const bool reading)
|
||||
}
|
||||
}
|
||||
if (has_directory) {
|
||||
if (munged_name == NULL) {
|
||||
munged_name = xstrdup(ffname);
|
||||
for (char *c = munged_name; *c != NUL; MB_PTR_ADV(c)) {
|
||||
if (munged_name.data == NULL) {
|
||||
munged_name = cbuf_to_string(ffname, ffname_len);
|
||||
for (char *c = munged_name.data; *c != NUL; MB_PTR_ADV(c)) {
|
||||
if (vim_ispathsep(*c)) {
|
||||
*c = '%';
|
||||
}
|
||||
}
|
||||
}
|
||||
undo_file_name = concat_fnames(dir_name, munged_name, true);
|
||||
undo_file_name = concat_fnames(cbuf_as_string(dir_name, dir_len),
|
||||
munged_name, true).data;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -750,7 +752,7 @@ char *u_get_undo_file_name(const char *const buf_ffname, const bool reading)
|
||||
XFREE_CLEAR(undo_file_name);
|
||||
}
|
||||
|
||||
xfree(munged_name);
|
||||
xfree(munged_name.data);
|
||||
return undo_file_name;
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,13 @@ func Test_packadd()
|
||||
" plugdir should be inserted before plugdir/after
|
||||
call assert_match('^nosuchdir,' . s:plugdir . ',', &rtp)
|
||||
|
||||
" This used to cause heep-buffer-overflow
|
||||
" All existing entries in 'rtp' have the same length here
|
||||
let &rtp = 'Xfoodir,Xbardir,Xbazdir'
|
||||
packadd mytest
|
||||
" plugdir should be inserted after the existing directories
|
||||
call assert_match('^Xfoodir,Xbardir,Xbazdir,' .. s:plugdir .. ',', &rtp)
|
||||
|
||||
set rtp&
|
||||
let rtp = &rtp
|
||||
filetype on
|
||||
|
||||
Reference in New Issue
Block a user