Loading ...
Sorry, an error occurred while loading the content.

Patch 6.2.064

Expand Messages
  • Bram Moolenaar
    Patch 6.2.064 Problem: resolve() only handles one symbolic link, need to repeat it to resolve all of them. Then need to simplify the file name. Solution:
    Message 1 of 1 , Aug 10, 2003
    • 0 Attachment
      Patch 6.2.064
      Problem: resolve() only handles one symbolic link, need to repeat it to
      resolve all of them. Then need to simplify the file name.
      Solution: Make resolve() resolve all symbolic links and simplify the result.
      Add simplify() to just simplify a file name. Fix that test49
      doesn't work if /tmp is a symbolic link. (Servatius Brandt)
      Files: runtime/doc/eval.txt, src/eval.c, src/tag.c,
      src/testdir/test49.vim


      *** ../vim-6.2.063/runtime/doc/eval.txt Sun Jun 1 14:45:23 2003
      --- runtime/doc/eval.txt Thu Aug 7 19:31:16 2003
      ***************
      *** 1,4 ****
      ! *eval.txt* For Vim version 6.2. Last change: 2003 Jun 01


      VIM REFERENCE MANUAL by Bram Moolenaar
      --- 1,4 ----
      ! *eval.txt* For Vim version 6.2. Last change: 2003 Aug 07


      VIM REFERENCE MANUAL by Bram Moolenaar
      ***************
      *** 885,890 ****
      --- 887,893 ----
      setline( {lnum}, {line}) Number set line {lnum} to {line}
      setreg( {n}, {v}[, {opt}]) Number set register to value and type
      setwinvar( {nr}, {varname}, {val}) set {varname} in window {nr} to {val}
      + simplify( {filename}) String simplify filename as much as possible
      strftime( {format}[, {time}]) String time in specified format
      stridx( {haystack}, {needle}) Number first index of {needle} in {haystack}
      strlen( {expr}) Number length of the String {expr}
      ***************
      *** 2104,2116 ****
      successfully, and non-zero when the renaming failed.
      This function is not available in the |sandbox|.

      ! resolve({filename}) *resolve()*
      On MS-Windows, when {filename} is a shortcut (a .lnk file),
      ! returns the path the shortcut points to.
      ! On Unix, when {filename} is a symbolic link, returns the path
      ! the symlink points to. This only happens once, the returned
      ! path could be a symlink again.
      ! Otherwise {filename} is returned.

      search({pattern} [, {flags}]) *search()*
      Search for regexp pattern {pattern}. The search starts at the
      --- 2112,2129 ----
      successfully, and non-zero when the renaming failed.
      This function is not available in the |sandbox|.

      ! resolve({filename}) *resolve()* *E655*
      On MS-Windows, when {filename} is a shortcut (a .lnk file),
      ! returns the path the shortcut points to in a simplified form.
      ! On Unix, repeat resolving symbolic links in all path
      ! components of {filename} and return the simplified result.
      ! To cope with link cycles, resolving of symbolic links is
      ! stopped after 100 iterations.
      ! On other systems, return the simplified {filename}.
      ! The simplification step is done as by |simplify()|.
      ! resolve() keeps a leading path component specifying the
      ! current directory (provided the result is still a relative
      ! path name) and also keeps a trailing path separator.

      search({pattern} [, {flags}]) *search()*
      Search for regexp pattern {pattern}. The search starts at the
      ***************
      *** 2302,2307 ****
      --- 2315,2335 ----
      :call setwinvar(2, "myvar", "foobar")
      < This function is not available in the |sandbox|.

      + simplify({filename}) *simplify()*
      + Simplify the file name as much as possible without changing
      + the meaning. Shortcuts (on MS-Windows) or symbolic links (on
      + Unix) are not resolved. If the first path component in
      + {filename} designates the current directory, this will be
      + valid for the result as well. A trailing path separator is
      + not removed either.
      + Example: >
      + simplify("./dir/.././/file/") == "./file/"
      + < Note: The combination "dir/.." is only removed if "dir" is
      + a searchable directory or does not exist. On Unix, it is also
      + removed when "dir" is a symbolic link within the same
      + directory. In order to resolve all the involved symbolic
      + links before simplifying the path name, use |resolve()|.
      +
      strftime({format} [, {time}]) *strftime()*
      The result is a String, which is a formatted date and time, as
      specified by the {format} string. The given {time} is used,
      *** ../vim-6.2.063/src/eval.c Sun Aug 10 22:24:37 2003
      --- src/eval.c Thu Jul 31 19:47:34 2003
      ***************
      *** 318,323 ****
      --- 318,324 ----
      static void f_serverlist __ARGS((VAR argvars, VAR retvar));
      static void f_setline __ARGS((VAR argvars, VAR retvar));
      static void f_setreg __ARGS((VAR argvars, VAR retvar));
      + static void f_simplify __ARGS((VAR argvars, VAR retvar));
      static void find_some_match __ARGS((VAR argvars, VAR retvar, int start));
      static void f_strftime __ARGS((VAR argvars, VAR retvar));
      static void f_stridx __ARGS((VAR argvars, VAR retvar));
      ***************
      *** 2812,2817 ****
      --- 2813,2819 ----
      {"setline", 2, 2, f_setline},
      {"setreg", 2, 3, f_setreg},
      {"setwinvar", 3, 3, f_setwinvar},
      + {"simplify", 1, 1, f_simplify},
      #ifdef HAVE_STRFTIME
      {"strftime", 1, 2, f_strftime},
      #endif
      ***************
      *** 5808,5813 ****
      --- 5810,5816 ----
      VAR retvar;
      {
      char_u *p;
      + int limit = 100;

      p = get_var_string(&argvars[0]);
      #ifdef FEAT_SHORTCUT
      ***************
      *** 5826,5858 ****
      char_u buf[MAXPATHL + 1];
      char_u *cpy;
      int len;

      ! len = readlink((char *)p, (char *)buf, MAXPATHL);
      ! if (len > 0)
      {
      ! buf[len] = NUL;
      ! if (gettail(p) > p && !mch_isFullName(buf))
      {
      ! /* symlink is relative to directory of argument */
      ! cpy = alloc((unsigned)(STRLEN(p) + STRLEN(buf) + 1));
      ! if (cpy != NULL)
      {
      ! STRCPY(cpy, p);
      ! STRCPY(gettail(cpy), buf);
      ! retvar->var_val.var_string = cpy;
      ! p = NULL;
      }
      }
      else
      ! p = buf;
      }
      ! if (p != NULL)
      ! retvar->var_val.var_string = vim_strsave(p);
      }
      # else
      retvar->var_val.var_string = vim_strsave(p);
      # endif
      #endif
      retvar->var_type = VAR_STRING;
      }

      --- 5829,6020 ----
      char_u buf[MAXPATHL + 1];
      char_u *cpy;
      int len;
      + char_u *remain = NULL;
      + char_u *q;
      + int is_relative_to_current = FALSE;
      + int has_trailing_pathsep = FALSE;

      ! p = vim_strsave(p);
      !
      ! if (p[0] == '.' && (vim_ispathsep(p[1])
      ! || (p[1] == '.' && (vim_ispathsep(p[2])))))
      ! is_relative_to_current = TRUE;
      !
      ! len = STRLEN(p);
      ! if (len > 0 && vim_ispathsep(p[len-1]))
      ! has_trailing_pathsep = TRUE;
      !
      ! q = getnextcomp(p);
      ! if (*q != NUL)
      ! {
      ! /* Separate the first path component in "p", and keep the
      ! * remainder (beginning with the path separator). */
      ! remain = vim_strsave(q - 1);
      ! q[-1] = NUL;
      ! }
      !
      ! for(;;)
      {
      ! for (;;)
      {
      ! len = readlink((char *)p, (char *)buf, MAXPATHL);
      ! if (len <= 0)
      ! break;
      ! buf[len] = NUL;
      !
      ! if (limit-- == 0)
      ! {
      ! vim_free(p);
      ! vim_free(remain);
      ! EMSG(_("E655: Too much symbolic links (cycle?)"));
      ! retvar->var_val.var_string = NULL;
      ! goto fail;
      ! }
      !
      ! /* Ensure that the result will have a trailing path separator
      ! * if the argument has one. */
      ! if (remain == NULL && has_trailing_pathsep)
      ! add_pathsep(buf);
      !
      ! /* Separate the first path component in the link value and
      ! * concatenate the remainders. */
      ! q = getnextcomp(vim_ispathsep(*buf) ? buf + 1 : buf);
      ! if (*q != NUL)
      ! {
      ! if (remain == NULL)
      ! remain = vim_strsave(q - 1);
      ! else
      ! {
      ! cpy = vim_strnsave(q-1, STRLEN(q-1)+STRLEN(remain));
      ! if (cpy != NULL)
      ! {
      ! STRCAT(cpy, remain);
      ! vim_free(remain);
      ! remain = cpy;
      ! }
      ! }
      ! q[-1] = NUL;
      ! }
      !
      ! q = gettail(p);
      ! if (q > p && *q == NUL)
      ! {
      ! /* Ignore trailing path separator. */
      ! q[-1] = NUL;
      ! q = gettail(p);
      ! }
      ! if (q > p && !mch_isFullName(buf))
      ! {
      ! /* symlink is relative to directory of argument */
      ! cpy = alloc((unsigned)(STRLEN(p) + STRLEN(buf) + 1));
      ! if (cpy != NULL)
      ! {
      ! STRCPY(cpy, p);
      ! STRCPY(gettail(cpy), buf);
      ! vim_free(p);
      ! p = cpy;
      ! }
      ! }
      ! else
      {
      ! vim_free(p);
      ! p = vim_strsave(buf);
      }
      }
      +
      + if (remain == NULL)
      + break;
      +
      + /* Append the first path component of "remain" to "p". */
      + q = getnextcomp(remain + 1);
      + len = q - remain - (*q != NUL);
      + cpy = vim_strnsave(p, STRLEN(p) + len);
      + if (cpy != NULL)
      + {
      + STRNCAT(cpy, remain, len);
      + vim_free(p);
      + p = cpy;
      + }
      + /* Shorten "remain". */
      + if (*q != NUL)
      + STRCPY(remain, q - 1);
      else
      ! {
      ! vim_free(remain);
      ! remain = NULL;
      ! }
      }
      !
      ! /* If the result is a relative path name, make it explicitly relative to
      ! * the current directory if and only if the argument had this form. */
      ! if (!vim_ispathsep(*p))
      ! {
      ! if (is_relative_to_current
      ! && *p != NUL
      ! && !(p[0] == '.'
      ! && (p[1] == NUL
      ! || vim_ispathsep(p[1])
      ! || (p[1] == '.'
      ! && (p[2] == NUL
      ! || vim_ispathsep(p[2]))))))
      ! {
      ! /* Prepend "./". */
      ! cpy = vim_strnsave((char_u *)"./", 2 + STRLEN(p));
      ! if (cpy != NULL)
      ! {
      ! STRCAT(cpy, p);
      ! vim_free(p);
      ! p = cpy;
      ! }
      ! }
      ! else if (!is_relative_to_current)
      ! {
      ! /* Strip leading "./". */
      ! q = p;
      ! while (q[0] == '.' && vim_ispathsep(q[1]))
      ! q += 2;
      ! if (q > p)
      ! mch_memmove(p, p + 2, STRLEN(p + 2) + (size_t)1);
      ! }
      ! }
      !
      ! /* Ensure that the result will have no trailing path separator
      ! * if the argument had none. But keep "/" or "//". */
      ! if (!has_trailing_pathsep)
      ! {
      ! q = p + STRLEN(p);
      ! while ((q > p + 2 || (q == p + 2 && !vim_ispathsep(*p)))
      ! && vim_ispathsep(q[-1]))
      ! --q;
      ! *q = NUL;
      ! }
      !
      ! retvar->var_val.var_string = p;
      }
      # else
      retvar->var_val.var_string = vim_strsave(p);
      # endif
      #endif
      +
      + simplify_filename(retvar->var_val.var_string);
      +
      + fail:
      + retvar->var_type = VAR_STRING;
      + }
      +
      + /*
      + * "simplify()" function
      + */
      + static void
      + f_simplify(argvars, retvar)
      + VAR argvars;
      + VAR retvar;
      + {
      + char_u *p;
      +
      + p = get_var_string(&argvars[0]);
      + retvar->var_val.var_string = vim_strsave(p);
      + simplify_filename(retvar->var_val.var_string); /* simplify in place */
      retvar->var_type = VAR_STRING;
      }

      *** ../vim-6.2.063/src/tag.c Sun Aug 10 22:24:37 2003
      --- src/tag.c Thu Jul 31 18:27:34 2003
      ***************
      *** 2864,2875 ****
      #ifndef AMIGA /* Amiga doesn't have "..", it uses "/" */
      int components = 0;
      char_u *p, *tail, *start;
      ! #ifdef UNIX
      ! char_u *orig = vim_strsave(filename);
      !
      ! if (orig == NULL)
      ! return;
      ! #endif

      p = filename;
      #ifdef BACKSLASH_IN_FILENAME
      --- 2864,2871 ----
      #ifndef AMIGA /* Amiga doesn't have "..", it uses "/" */
      int components = 0;
      char_u *p, *tail, *start;
      ! int stripping_disabled = FALSE;
      ! int relative = TRUE;

      p = filename;
      #ifdef BACKSLASH_IN_FILENAME
      ***************
      *** 2877,2889 ****
      p += 2;
      #endif

      ! while (vim_ispathsep(*p))
      ! ++p;
      ! start = p; /* remember start after "c:/" or "/" or "//" */

      do
      {
      ! /* At this point "p" is pointing to the char following a "/". */
      #ifdef VMS
      /* VMS allows device:[path] - don't strip the [ in directory */
      if ((*p == '[' || *p == '<') && p > filename && p[-1] == ':')
      --- 2873,2891 ----
      p += 2;
      #endif

      ! if (vim_ispathsep(*p))
      ! {
      ! relative = FALSE;
      ! do
      ! ++p;
      ! while (vim_ispathsep(*p));
      ! }
      ! start = p; /* remember start after "c:/" or "/" or "///" */

      do
      {
      ! /* At this point "p" is pointing to the char following a single "/"
      ! * or "p" is at the "start" of the (absolute or relative) path name. */
      #ifdef VMS
      /* VMS allows device:[path] - don't strip the [ in directory */
      if ((*p == '[' || *p == '<') && p > filename && p[-1] == ':')
      ***************
      *** 2898,2952 ****
      /* ":: composition: vms host/passwd component */
      ++components;
      p = getnextcomp(p + 2);
      -
      }
      else
      #endif
      if (vim_ispathsep(*p))
      movetail(p, p + 1); /* remove duplicate "/" */
      ! else if (p[0] == '.' && vim_ispathsep(p[1]))
      ! movetail(p, p + 2); /* strip "./" */
      ! else if (p[0] == '.' && p[1] == '.' && vim_ispathsep(p[2]))
      {
      if (components > 0) /* strip one preceding component */
      {
      ! tail = p + 3; /* skip to after "../" or "..///" */
      ! while (vim_ispathsep(*tail))
      ! ++tail;
      ! --p;
      ! /* skip back to after previous '/' */
      ! while (p > start && !vim_ispathsep(p[-1]))
      ! --p;
      ! /* skip back to after first '/' in a row */
      ! while (p - 1 > start && vim_ispathsep(p[-2]))
      --p;
      ! movetail(p, tail); /* strip previous component */
      ! --components;
      }
      - else /* leading "../" */
      - p += 3; /* skip to char after "/" */
      }
      else
      {
      ++components; /* simple path component */
      p = getnextcomp(p);
      }
      ! } while (p != NULL && *p != NUL);
      !
      ! #ifdef UNIX
      ! /* Check that the new file name is really the same file. This will not be
      ! * the case when using symbolic links: "dir/link/../name" != "dir/name". */
      ! {
      ! struct stat orig_st, new_st;
      !
      ! if ( mch_stat((char *)orig, &orig_st) < 0
      ! || mch_stat((char *)filename, &new_st) < 0
      ! || orig_st.st_ino != new_st.st_ino
      ! || orig_st.st_dev != new_st.st_dev)
      ! STRCPY(filename, orig);
      ! vim_free(orig);
      ! }
      ! #endif
      #endif /* !AMIGA */
      }

      --- 2900,3064 ----
      /* ":: composition: vms host/passwd component */
      ++components;
      p = getnextcomp(p + 2);
      }
      else
      #endif
      if (vim_ispathsep(*p))
      movetail(p, p + 1); /* remove duplicate "/" */
      ! else if (p[0] == '.' && (vim_ispathsep(p[1]) || p[1] == NUL))
      ! {
      ! if (p == start && relative)
      ! p += 1 + (p[1] != NUL); /* keep single "." or leading "./" */
      ! else
      ! {
      ! /* Strip "./" or ".///". If we are at the end of the file name
      ! * and there is no trailing path separator, either strip "/." if
      ! * we are after "start", or strip "." if we are at the beginning
      ! * of an absolute path name . */
      ! tail = p + 1;
      ! if (p[1] != NUL)
      ! while (vim_ispathsep(*tail))
      ! ++tail;
      ! else if (p > start)
      ! --p; /* strip preceding path separator */
      ! movetail(p, tail);
      ! }
      ! }
      ! else if (p[0] == '.' && p[1] == '.' &&
      ! (vim_ispathsep(p[2]) || p[2] == NUL))
      {
      + /* Skip to after ".." or "../" or "..///". */
      + tail = p + 2;
      + while (vim_ispathsep(*tail))
      + ++tail;
      +
      if (components > 0) /* strip one preceding component */
      {
      ! int do_strip = FALSE;
      ! char_u saved_char;
      ! struct stat st, new_st;
      !
      ! /* Don't strip for an erroneous file name. */
      ! if (!stripping_disabled)
      ! {
      ! /* If the preceding component does not exist in the file
      ! * system, we strip it. On Unix, we don't accept a symbolic
      ! * link that refers to a non-existent file. */
      ! saved_char = p[-1];
      ! p[-1] = NUL;
      ! #ifdef UNIX
      ! if (mch_lstat((char *)filename, &st) < 0)
      ! #else
      ! if (mch_stat((char *)filename, &st) < 0)
      ! #endif
      ! do_strip = TRUE;
      ! p[-1] = saved_char;
      !
      --p;
      ! /* Skip back to after previous '/'. */
      ! while (p > start && !vim_ispathsep(p[-1]))
      ! --p;
      !
      ! if (!do_strip)
      ! {
      ! /* If the component exists in the file system, check
      ! * that stripping it won't change the meaning of the
      ! * file name. First get information about the
      ! * unstripped file name. This may fail if the component
      ! * to strip is not a searchable directory (but a regular
      ! * file, for instance), since the trailing "/.." cannot
      ! * be applied then. We don't strip it then since we
      ! * don't want to replace an erroneous file name by
      ! * a valid one, and we disable stripping of later
      ! * components. */
      ! saved_char = *tail;
      ! *tail = NUL;
      ! if (mch_stat((char *)filename, &st) >= 0)
      ! do_strip = TRUE;
      ! else
      ! stripping_disabled = TRUE;
      ! *tail = saved_char;
      ! #ifdef UNIX
      ! if (do_strip)
      ! {
      ! /* On Unix, the check for the unstripped file name
      ! * above works also for a symbolic link pointing to
      ! * a searchable directory. But then the parent of
      ! * the directory pointed to by the link must be the
      ! * same as the stripped file name. (The latter
      ! * exists in the file system since it is the
      ! * component's parent directory.) */
      ! if (p == start && relative)
      ! (void)mch_stat(".", &new_st);
      ! else
      ! {
      ! saved_char = *p;
      ! *p = NUL;
      ! (void)mch_stat((char *)filename, &new_st);
      ! *p = saved_char;
      ! }
      !
      ! if (new_st.st_ino != st.st_ino ||
      ! new_st.st_dev != st.st_dev)
      ! {
      ! do_strip = FALSE;
      ! /* We don't disable stripping of later
      ! * components since the unstripped path name is
      ! * still valid. */
      ! }
      ! }
      ! #endif
      ! }
      ! }
      !
      ! if (!do_strip)
      ! {
      ! /* Skip the ".." or "../" and reset the counter for the
      ! * components that might be stripped later on. */
      ! p = tail;
      ! components = 0;
      ! }
      ! else
      ! {
      ! /* Strip previous component. If the result would get empty
      ! * and there is no trailing path separator, leave a single
      ! * "." instead. If we are at the end of the file name and
      ! * there is no trailing path separator and a preceding
      ! * component is left after stripping, strip its trailing
      ! * path separator as well. */
      ! if (p == start && relative && tail[-1] == '.')
      ! {
      ! *p++ = '.';
      ! *p = NUL;
      ! }
      ! else
      ! {
      ! if (p > start && tail[-1] == '.')
      ! --p;
      ! movetail(p, tail); /* strip previous component */
      ! }
      !
      ! --components;
      ! }
      ! }
      ! else if (p == start && !relative) /* leading "/.." or "/../" */
      ! movetail(p, tail); /* strip ".." or "../" */
      ! else
      ! {
      ! if (p == start + 2 && p[-2] == '.') /* leading "./../" */
      ! {
      ! movetail(p - 2, p); /* strip leading "./" */
      ! tail -= 2;
      ! }
      ! p = tail; /* skip to char after ".." or "../" */
      }
      }
      else
      {
      ++components; /* simple path component */
      p = getnextcomp(p);
      }
      ! } while (*p != NUL);
      #endif /* !AMIGA */
      }

      *** ../vim-6.2.063/src/testdir/test49.vim Fri May 30 21:45:31 2003
      --- src/testdir/test49.vim Thu Jul 31 18:25:02 2003
      ***************
      *** 1,6 ****
      " Vim script language tests
      " Author: Servatius Brandt <Servatius.Brandt@...>
      ! " Last Change: 2003 May 30

      "-------------------------------------------------------------------------------
      " Test environment {{{1
      --- 1,6 ----
      " Vim script language tests
      " Author: Servatius Brandt <Servatius.Brandt@...>
      ! " Last Change: 2003 Jul 30

      "-------------------------------------------------------------------------------
      " Test environment {{{1
      ***************
      *** 5076,5082 ****
      Xpath 1048576 " X: 1048576
      let exception = v:exception
      let throwpoint = v:throwpoint
      ! call CHECK(7, "autsch", scriptT, '\<6\>')
      finally
      Xpath 2097152 " X: 2097152
      let exception = v:exception
      --- 5076,5085 ----
      Xpath 1048576 " X: 1048576
      let exception = v:exception
      let throwpoint = v:throwpoint
      ! " Symbolic links in tempname()s are not resolved, whereas resolving
      ! " is done for v:throwpoint. Resolve the temporary file name for
      ! " scriptT, so that it can be matched against v:throwpoint.
      ! call CHECK(7, "autsch", resolve(scriptT), '\<6\>')
      finally
      Xpath 2097152 " X: 2097152
      let exception = v:exception
      ***************
      *** 5091,5097 ****
      Xpath 8388608 " X: 8388608
      let exception = v:exception
      let throwpoint = v:throwpoint
      ! call CHECK(9, "brrrr", scriptT, '\<8\>')
      finally
      Xpath 16777216 " X: 16777216
      let exception = v:exception
      --- 5094,5101 ----
      Xpath 8388608 " X: 8388608
      let exception = v:exception
      let throwpoint = v:throwpoint
      ! " Resolve scriptT for matching it against v:throwpoint.
      ! call CHECK(9, "brrrr", resolve(scriptT), '\<8\>')
      finally
      Xpath 16777216 " X: 16777216
      let exception = v:exception
      *** ../vim-6.2.063/src/version.c Sun Aug 10 22:24:37 2003
      --- src/version.c Sun Aug 10 22:26:34 2003
      ***************
      *** 632,633 ****
      --- 632,635 ----
      { /* Add new patch number below this line */
      + /**/
      + 64,
      /**/

      --
      From "know your smileys":
      :-{} Too much lipstick

      /// Bram Moolenaar -- Bram@... -- http://www.Moolenaar.net \\\
      /// Creator of Vim - Vi IMproved -- http://www.Vim.org \\\
      \\\ Project leader for A-A-P -- http://www.A-A-P.org ///
      \\\ Help AIDS victims, buy here: http://ICCF-Holland.org/click1.html ///
    Your message has been successfully submitted and would be delivered to recipients shortly.