diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/eval.c | 3 | ||||
| -rw-r--r-- | src/memline.c | 112 | ||||
| -rw-r--r-- | src/misc1.c | 23 | ||||
| -rw-r--r-- | src/proto/misc1.pro | 183 |
4 files changed, 226 insertions, 95 deletions
diff --git a/src/eval.c b/src/eval.c index a3bf58d35..fe3c5a7ad 100644 --- a/src/eval.c +++ b/src/eval.c @@ -12836,10 +12836,9 @@ f_resolve(argvars, rettv) remain = vim_strsave(q - 1); else { - cpy = vim_strnsave(q-1, STRLEN(q-1) + STRLEN(remain)); + cpy = concat_str(q - 1, remain); if (cpy != NULL) { - STRCAT(cpy, remain); vim_free(remain); remain = cpy; } diff --git a/src/memline.c b/src/memline.c index a6ab42c4e..a8e4025be 100644 --- a/src/memline.c +++ b/src/memline.c @@ -3382,6 +3382,87 @@ ml_lineadd(buf, count) } } +#ifdef HAVE_READLINK +static int resolve_symlink __ARGS((char_u *fname, char_u *buf)); + +/* + * Resolve a symlink in the last component of a file name. + * Note that f_resolve() does it for every part of the path, we don't do that + * here. + * If it worked returns OK and the resolved link in "buf[MAXPATHL]". + * Otherwise returns FAIL. + */ + static int +resolve_symlink(fname, buf) + char_u *fname; + char_u *buf; +{ + char_u tmp[MAXPATHL]; + int ret; + int depth = 0; + + if (fname == NULL) + return FAIL; + + /* Put the result so far in tmp[], starting with the original name. */ + vim_strncpy(tmp, fname, MAXPATHL - 1); + + for (;;) + { + /* Limit symlink depth to 100, catch recursive loops. */ + if (++depth == 100) + { + EMSG2(_("E773: Symlink loop for \"%s\""), fname); + return FAIL; + } + + ret = readlink((char *)tmp, (char *)buf, MAXPATHL - 1); + if (ret <= 0) + { + if (errno == EINVAL) /* found non-symlink, stop here */ + { + /* When at the first level use the unmodifed name, skip the + * call to vim_FullName(). */ + if (depth == 1) + return FAIL; + + /* Use the resolved name in tmp[]. */ + break; + } + + /* There must be some error reading links, use original name. */ + return FAIL; + } + buf[ret] = NUL; + + /* + * Check whether the symlink is relative or absolute. + * If it's relative, build a new path based on the directory + * portion of the filename (if any) and the path the symlink + * points to. + */ + if (mch_isFullName(buf)) + STRCPY(tmp, buf); + else + { + char_u *tail; + + tail = gettail(tmp); + if (STRLEN(tail) + STRLEN(buf) >= MAXPATHL) + return FAIL; + STRCPY(tail, buf); + } + } + + /* + * Try to resolve the full name of the file so that the swapfile name will + * be consistent even when opening a relative symlink from different + * working directories. + */ + return vim_FullName(tmp, buf, MAXPATHL, TRUE); +} +#endif + /* * Make swap file name out of the file name and a directory name. * Returns pointer to allocated memory or NULL. @@ -3395,6 +3476,10 @@ makeswapname(fname, ffname, buf, dir_name) char_u *dir_name; { char_u *r, *s; +#ifdef HAVE_READLINK + char_u fname_buf[MAXPATHL]; + char_u *fname_res; +#endif #if defined(UNIX) || defined(WIN3264) /* Need _very_ long file names */ s = dir_name + STRLEN(dir_name); @@ -3410,6 +3495,15 @@ makeswapname(fname, ffname, buf, dir_name) } #endif +#ifdef HAVE_READLINK + /* Expand symlink in the file name, so that we put the swap file with the + * actual file instead of with the symlink. */ + if (resolve_symlink(fname, fname_buf) == OK) + fname_res = fname_buf; + else + fname_res = fname; +#endif + r = buf_modname( #ifdef SHORT_FNAME TRUE, @@ -3420,7 +3514,11 @@ makeswapname(fname, ffname, buf, dir_name) /* Avoid problems if fname has special chars, eg <Wimp$Scrap> */ ffname, #else +# ifdef HAVE_READLINK + fname_res, +# else fname, +# endif #endif (char_u *) #if defined(VMS) || defined(RISCOS) @@ -3848,7 +3946,17 @@ findswapname(buf, dirp, old_fname) if (fnamecmp(gettail(buf->b_ffname), gettail(b0.b0_fname)) != 0 || !same_directory(fname, buf->b_ffname)) - differ = TRUE; + { +#ifdef CHECK_INODE + /* Symlinks may point to the same file even + * when the name differs, need to check the + * inode too. */ + expand_env(b0.b0_fname, NameBuff, MAXPATHL); + if (fnamecmp_ino(buf->b_ffname, NameBuff, + char_to_long(b0.b0_ino))) +#endif + differ = TRUE; + } } else { @@ -3859,7 +3967,7 @@ findswapname(buf, dirp, old_fname) expand_env(b0.b0_fname, NameBuff, MAXPATHL); #ifdef CHECK_INODE if (fnamecmp_ino(buf->b_ffname, NameBuff, - char_to_long(b0.b0_ino))) + char_to_long(b0.b0_ino))) differ = TRUE; #else if (fnamecmp(NameBuff, buf->b_ffname) != 0) diff --git a/src/misc1.c b/src/misc1.c index bef297cf2..cd8acceaa 100644 --- a/src/misc1.c +++ b/src/misc1.c @@ -4443,6 +4443,29 @@ vim_ispathlistsep(c) } #endif +/* + * Return TRUE if the directory of "fname" exists, FALSE otherwise. + * Also returns TRUE if there is no directory name. + * "fname" must be writable!. + */ + int +dir_of_file_exists(fname) + char_u *fname; +{ + char_u *p; + int c; + int retval; + + p = gettail_sep(fname); + if (p == fname) + return TRUE; + c = *p; + *p = NUL; + retval = mch_isdir(fname); + *p = c; + return retval; +} + #if (defined(CASE_INSENSITIVE_FILENAME) && defined(BACKSLASH_IN_FILENAME)) \ || defined(PROTO) /* diff --git a/src/proto/misc1.pro b/src/proto/misc1.pro index 584207289..20c7b513f 100644 --- a/src/proto/misc1.pro +++ b/src/proto/misc1.pro @@ -1,93 +1,94 @@ /* misc1.c */ -int get_indent __ARGS((void)); -int get_indent_lnum __ARGS((linenr_T lnum)); -int get_indent_buf __ARGS((buf_T *buf, linenr_T lnum)); -int get_indent_str __ARGS((char_u *ptr, int ts)); -int set_indent __ARGS((int size, int flags)); -int get_number_indent __ARGS((linenr_T lnum)); -int open_line __ARGS((int dir, int flags, int old_indent)); -int get_leader_len __ARGS((char_u *line, char_u **flags, int backward)); -int plines __ARGS((linenr_T lnum)); -int plines_win __ARGS((win_T *wp, linenr_T lnum, int winheight)); -int plines_nofill __ARGS((linenr_T lnum)); -int plines_win_nofill __ARGS((win_T *wp, linenr_T lnum, int winheight)); -int plines_win_nofold __ARGS((win_T *wp, linenr_T lnum)); -int plines_win_col __ARGS((win_T *wp, linenr_T lnum, long column)); -int plines_m_win __ARGS((win_T *wp, linenr_T first, linenr_T last)); -void ins_bytes __ARGS((char_u *p)); -void ins_bytes_len __ARGS((char_u *p, int len)); -void ins_char __ARGS((int c)); -void ins_char_bytes __ARGS((char_u *buf, int charlen)); -void ins_str __ARGS((char_u *s)); -int del_char __ARGS((int fixpos)); -int del_chars __ARGS((long count, int fixpos)); -int del_bytes __ARGS((long count, int fixpos)); -int truncate_line __ARGS((int fixpos)); -void del_lines __ARGS((long nlines, int undo)); -int gchar_pos __ARGS((pos_T *pos)); -int gchar_cursor __ARGS((void)); -void pchar_cursor __ARGS((int c)); -int inindent __ARGS((int extra)); -char_u *skip_to_option_part __ARGS((char_u *p)); -void changed __ARGS((void)); -void changed_bytes __ARGS((linenr_T lnum, colnr_T col)); -void appended_lines __ARGS((linenr_T lnum, long count)); -void appended_lines_mark __ARGS((linenr_T lnum, long count)); -void deleted_lines __ARGS((linenr_T lnum, long count)); -void deleted_lines_mark __ARGS((linenr_T lnum, long count)); -void changed_lines __ARGS((linenr_T lnum, colnr_T col, linenr_T lnume, long xtra)); -void unchanged __ARGS((buf_T *buf, int ff)); -void check_status __ARGS((buf_T *buf)); -void change_warning __ARGS((int col)); -int ask_yesno __ARGS((char_u *str, int direct)); -int get_keystroke __ARGS((void)); -int get_number __ARGS((int colon, int *mouse_used)); -int prompt_for_number __ARGS((int *mouse_used)); -void msgmore __ARGS((long n)); -void beep_flush __ARGS((void)); -void vim_beep __ARGS((void)); -void init_homedir __ARGS((void)); -void free_homedir __ARGS((void)); -void expand_env __ARGS((char_u *src, char_u *dst, int dstlen)); -void expand_env_esc __ARGS((char_u *srcp, char_u *dst, int dstlen, int esc, char_u *startstr)); -char_u *vim_getenv __ARGS((char_u *name, int *mustfree)); -char_u *expand_env_save __ARGS((char_u *src)); -void vim_setenv __ARGS((char_u *name, char_u *val)); -char_u *get_env_name __ARGS((expand_T *xp, int idx)); -void home_replace __ARGS((buf_T *buf, char_u *src, char_u *dst, int dstlen, int one)); -char_u *home_replace_save __ARGS((buf_T *buf, char_u *src)); -int fullpathcmp __ARGS((char_u *s1, char_u *s2, int checkname)); -char_u *gettail __ARGS((char_u *fname)); -char_u *gettail_sep __ARGS((char_u *fname)); -char_u *getnextcomp __ARGS((char_u *fname)); -char_u *get_past_head __ARGS((char_u *path)); -int vim_ispathsep __ARGS((int c)); -int vim_ispathlistsep __ARGS((int c)); -int vim_fnamecmp __ARGS((char_u *x, char_u *y)); -int vim_fnamencmp __ARGS((char_u *x, char_u *y, size_t len)); -char_u *concat_fnames __ARGS((char_u *fname1, char_u *fname2, int sep)); -char_u *concat_str __ARGS((char_u *str1, char_u *str2)); -void add_pathsep __ARGS((char_u *p)); -char_u *FullName_save __ARGS((char_u *fname, int force)); -pos_T *find_start_comment __ARGS((int ind_maxcomment)); -void do_c_expr_indent __ARGS((void)); -int cin_islabel __ARGS((int ind_maxcomment)); -int cin_iscase __ARGS((char_u *s)); -int cin_isscopedecl __ARGS((char_u *s)); -int get_c_indent __ARGS((void)); -int get_expr_indent __ARGS((void)); -int get_lisp_indent __ARGS((void)); -void prepare_to_exit __ARGS((void)); -void preserve_exit __ARGS((void)); -int vim_fexists __ARGS((char_u *fname)); -void line_breakcheck __ARGS((void)); -void fast_breakcheck __ARGS((void)); -int expand_wildcards __ARGS((int num_pat, char_u **pat, int *num_file, char_u ***file, int flags)); -int match_suffix __ARGS((char_u *fname)); -int unix_expandpath __ARGS((garray_T *gap, char_u *path, int wildoff, int flags, int didstar)); -int gen_expand_wildcards __ARGS((int num_pat, char_u **pat, int *num_file, char_u ***file, int flags)); -void addfile __ARGS((garray_T *gap, char_u *f, int flags)); -char_u *get_cmd_output __ARGS((char_u *cmd, char_u *infile, int flags)); -void FreeWild __ARGS((int count, char_u **files)); -int goto_im __ARGS((void)); +extern int get_indent __ARGS((void)); +extern int get_indent_lnum __ARGS((linenr_T lnum)); +extern int get_indent_buf __ARGS((buf_T *buf, linenr_T lnum)); +extern int get_indent_str __ARGS((char_u *ptr, int ts)); +extern int set_indent __ARGS((int size, int flags)); +extern int get_number_indent __ARGS((linenr_T lnum)); +extern int open_line __ARGS((int dir, int flags, int old_indent)); +extern int get_leader_len __ARGS((char_u *line, char_u **flags, int backward)); +extern int plines __ARGS((linenr_T lnum)); +extern int plines_win __ARGS((win_T *wp, linenr_T lnum, int winheight)); +extern int plines_nofill __ARGS((linenr_T lnum)); +extern int plines_win_nofill __ARGS((win_T *wp, linenr_T lnum, int winheight)); +extern int plines_win_nofold __ARGS((win_T *wp, linenr_T lnum)); +extern int plines_win_col __ARGS((win_T *wp, linenr_T lnum, long column)); +extern int plines_m_win __ARGS((win_T *wp, linenr_T first, linenr_T last)); +extern void ins_bytes __ARGS((char_u *p)); +extern void ins_bytes_len __ARGS((char_u *p, int len)); +extern void ins_char __ARGS((int c)); +extern void ins_char_bytes __ARGS((char_u *buf, int charlen)); +extern void ins_str __ARGS((char_u *s)); +extern int del_char __ARGS((int fixpos)); +extern int del_chars __ARGS((long count, int fixpos)); +extern int del_bytes __ARGS((long count, int fixpos)); +extern int truncate_line __ARGS((int fixpos)); +extern void del_lines __ARGS((long nlines, int undo)); +extern int gchar_pos __ARGS((pos_T *pos)); +extern int gchar_cursor __ARGS((void)); +extern void pchar_cursor __ARGS((int c)); +extern int inindent __ARGS((int extra)); +extern char_u *skip_to_option_part __ARGS((char_u *p)); +extern void changed __ARGS((void)); +extern void changed_bytes __ARGS((linenr_T lnum, colnr_T col)); +extern void appended_lines __ARGS((linenr_T lnum, long count)); +extern void appended_lines_mark __ARGS((linenr_T lnum, long count)); +extern void deleted_lines __ARGS((linenr_T lnum, long count)); +extern void deleted_lines_mark __ARGS((linenr_T lnum, long count)); +extern void changed_lines __ARGS((linenr_T lnum, colnr_T col, linenr_T lnume, long xtra)); +extern void unchanged __ARGS((buf_T *buf, int ff)); +extern void check_status __ARGS((buf_T *buf)); +extern void change_warning __ARGS((int col)); +extern int ask_yesno __ARGS((char_u *str, int direct)); +extern int get_keystroke __ARGS((void)); +extern int get_number __ARGS((int colon, int *mouse_used)); +extern int prompt_for_number __ARGS((int *mouse_used)); +extern void msgmore __ARGS((long n)); +extern void beep_flush __ARGS((void)); +extern void vim_beep __ARGS((void)); +extern void init_homedir __ARGS((void)); +extern void free_homedir __ARGS((void)); +extern void expand_env __ARGS((char_u *src, char_u *dst, int dstlen)); +extern void expand_env_esc __ARGS((char_u *srcp, char_u *dst, int dstlen, int esc, char_u *startstr)); +extern char_u *vim_getenv __ARGS((char_u *name, int *mustfree)); +extern char_u *expand_env_save __ARGS((char_u *src)); +extern void vim_setenv __ARGS((char_u *name, char_u *val)); +extern char_u *get_env_name __ARGS((expand_T *xp, int idx)); +extern void home_replace __ARGS((buf_T *buf, char_u *src, char_u *dst, int dstlen, int one)); +extern char_u *home_replace_save __ARGS((buf_T *buf, char_u *src)); +extern int fullpathcmp __ARGS((char_u *s1, char_u *s2, int checkname)); +extern char_u *gettail __ARGS((char_u *fname)); +extern char_u *gettail_sep __ARGS((char_u *fname)); +extern char_u *getnextcomp __ARGS((char_u *fname)); +extern char_u *get_past_head __ARGS((char_u *path)); +extern int vim_ispathsep __ARGS((int c)); +extern int vim_ispathlistsep __ARGS((int c)); +extern int dir_of_file_exists __ARGS((char_u *fname)); +extern int vim_fnamecmp __ARGS((char_u *x, char_u *y)); +extern int vim_fnamencmp __ARGS((char_u *x, char_u *y, size_t len)); +extern char_u *concat_fnames __ARGS((char_u *fname1, char_u *fname2, int sep)); +extern char_u *concat_str __ARGS((char_u *str1, char_u *str2)); +extern void add_pathsep __ARGS((char_u *p)); +extern char_u *FullName_save __ARGS((char_u *fname, int force)); +extern pos_T *find_start_comment __ARGS((int ind_maxcomment)); +extern void do_c_expr_indent __ARGS((void)); +extern int cin_islabel __ARGS((int ind_maxcomment)); +extern int cin_iscase __ARGS((char_u *s)); +extern int cin_isscopedecl __ARGS((char_u *s)); +extern int get_c_indent __ARGS((void)); +extern int get_expr_indent __ARGS((void)); +extern int get_lisp_indent __ARGS((void)); +extern void prepare_to_exit __ARGS((void)); +extern void preserve_exit __ARGS((void)); +extern int vim_fexists __ARGS((char_u *fname)); +extern void line_breakcheck __ARGS((void)); +extern void fast_breakcheck __ARGS((void)); +extern int expand_wildcards __ARGS((int num_pat, char_u **pat, int *num_file, char_u ***file, int flags)); +extern int match_suffix __ARGS((char_u *fname)); +extern int unix_expandpath __ARGS((garray_T *gap, char_u *path, int wildoff, int flags, int didstar)); +extern int gen_expand_wildcards __ARGS((int num_pat, char_u **pat, int *num_file, char_u ***file, int flags)); +extern void addfile __ARGS((garray_T *gap, char_u *f, int flags)); +extern char_u *get_cmd_output __ARGS((char_u *cmd, char_u *infile, int flags)); +extern void FreeWild __ARGS((int count, char_u **files)); +extern int goto_im __ARGS((void)); /* vim: set ft=c : */ |
