On Wed, Aug 06, 2008 at 01:11:30PM +0200, Bram Moolenaar wrote: > Matt Wozniski wrote: > > > Try this: > > > > In terminal 1: > > touch a > > ln -s a b > > vim b > > > > In terminal 2: > > vim b > > > > We get: > > > > E325: ATTENTION > > Found a swap file by the name "/tmp/vimtest/.a.swp" > > ... > > file name: /tmp/vimtest/b > > ... > > While opening file "b" > > > > So, we know that the file we're working on is "b", but that the > > swapfile exists at "a". > > > > Then, press 'r' to recover, and we get... > > > > "b" 0L, 0C > > E305: No swap file found for b > > > > because recover is only looking for b.swp and not noticing a.swp. > > Seems this should be easy to deal with, since we already know that > > /tmp/vimtest/.a.swp is the swap file for /tmp/vimtest/b, but I don't > > have time to dig in right now so I'll have to punt this to the list. > > Yeah, that is wrong. One more for the todo list...
This is happening because symlinks are resolved (if readlink(2) is available) when creating a swapfile to make sure that swapfiles are stored alongside the actual file being edited (in a default config). ml_recover calls recover_names to get the list of potential file names, so this needs to perform the same symlink resolution. Attached is a patch to fix this. -- James GPG Key: 1024D/61326D40 2003-09-02 James Vega <[EMAIL PROTECTED]>
diff --git a/src/memline.c b/src/memline.c
index f5a68b1..fb569f2 100644
--- a/src/memline.c
+++ b/src/memline.c
@@ -1364,6 +1364,88 @@ theend:
return;
}
+#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 || errno == ENOENT)
+ {
+ /* Found non-symlink or not existing file, 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
+
/*
* Find the names of swap files in current directory and the directory given
* with the 'directory' option.
@@ -1390,6 +1472,17 @@ recover_names(fname, list, nr)
int i;
char_u *dirp;
char_u *dir_name;
+#ifdef HAVE_READLINK
+ char_u fname_buf[MAXPATHL];
+ char_u *fname_res;
+
+ /* 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
if (list)
{
@@ -1442,7 +1535,13 @@ recover_names(fname, list, nr)
#endif
}
else
- num_names = recov_file_names(names, *fname, TRUE);
+ num_names = recov_file_names(names,
+#ifdef HAVE_READLINK
+ fname_res,
+#else
+ *fname,
+#endif
+ TRUE);
}
else /* check directory dir_name */
{
@@ -1479,12 +1578,24 @@ recover_names(fname, list, nr)
if (after_pathsep(dir_name, p) && p[-1] == p[-2])
{
/* Ends with '//', Use Full path for swap name */
- tail = make_percent_swname(dir_name, *fname);
+ tail = make_percent_swname(dir_name,
+#ifdef HAVE_READLINK
+ fname_res
+#else
+ *fname
+#endif
+ );
}
else
#endif
{
- tail = gettail(*fname);
+ tail = gettail(
+#ifdef HAVE_READLINK
+ fname_res
+#else
+ *fname
+#endif
+ );
tail = concat_fnames(dir_name, tail, TRUE);
}
if (tail == NULL)
@@ -1524,11 +1635,18 @@ recover_names(fname, list, nr)
struct stat st;
char_u *swapname;
+ swapname = modname(
+#ifdef HAVE_READLINK
+ fname_res,
+#else
+ *fname,
+#endif
#if defined(VMS) || defined(RISCOS)
- swapname = modname(*fname, (char_u *)"_swp", FALSE);
+ (char_u *)"_swp", FALSE
#else
- swapname = modname(*fname, (char_u *)".swp", TRUE);
+ (char_u *)".swp", TRUE
#endif
+ );
if (swapname != NULL)
{
if (mch_stat((char *)swapname, &st) != -1) /* It exists! */
@@ -3482,88 +3600,6 @@ 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 || errno == ENOENT)
- {
- /* Found non-symlink or not existing file, 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.
signature.asc
Description: Digital signature
