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

[PATCH] New option for breaking hard links when saving files

Expand Messages
  • Guillermo Ontañón
    Hi, The patch below adds a new option to Vim called breakhlinks , with this option activated, Vim will check if the file to be saved is a hard link, if so, it
    Message 1 of 2 , Nov 30, 2002
    • 0 Attachment
      Hi,

      The patch below adds a new option to Vim called 'breakhlinks', with this
      option activated, Vim will check if the file to be saved is a hard link,
      if so, it will break the link.

      This patch is our (if done this with Ricardo, in the CC) very first
      attempt to hacking Vim, so we'd appreciate if people here would review
      it and comment on it, we may have missed some details, or we may be
      completely wrong.

      This option is useful in some situations, as an example, one of the
      recommended ways [1] of making diffs to the linux kernel is to create a
      hard-linked copy of the kernel tree and let the editor break the link
      when modifying a file, leaving all other files as links but the modified
      ones as real copies. In the case of the linux kernel, doing things this
      way saves a lot of disk space.

      We've added the option as a compile time feature, it probably shouldn't
      since it's a very small feature, but we figured the maintainers would
      know better.

      The patch is against version 6.1.263

      [1] http://www.kernel.org/pub/linux/docs/lkml/#s1-10


      --
      Guillermo Ontañón
      gontanon@... || http://weezer.dragon-lance.net
      GRupo de Usuarios de Linux de La Almunia - http://grulla.hispalinux.es
      PGP key: 1024D/3AE9EA90
      Fingerprint: EF61 44E1 6725 A343 B165 2CEC 83C2 938B 3AE9 EA90



      diff -ur ../vim61.263/runtime/doc/eval.txt ./runtime/doc/eval.txt
      --- ../vim61.263/runtime/doc/eval.txt Thu Nov 28 19:52:48 2002
      +++ ./runtime/doc/eval.txt Thu Nov 28 21:26:36 2002
      @@ -2430,6 +2430,7 @@
      autocmd Compiled with autocommands support.
      balloon_eval Compiled with |balloon-eval| support.
      beos BeOS version of Vim.
      +breakhlinks Compiled with |breakhlinks| support.
      browse Compiled with |:browse| support, and browse() will
      work.
      builtin_terms Compiled with some builtin terminals.
      diff -ur ../vim61.263/runtime/doc/options.txt ./runtime/doc/options.txt
      --- ../vim61.263/runtime/doc/options.txt Thu Nov 28 19:54:51 2002
      +++ ./runtime/doc/options.txt Thu Nov 28 20:33:48 2002
      @@ -921,6 +921,17 @@
      This option lets you choose which characters might cause a line
      break if 'linebreak' is on.

      + *'breakhlinks'* *'bhl'*
      +'breakhlinks' 'bhl' boolean (default off)
      + global
      + {not in Vi}
      + {not available when compiled without the
      + |+breakhlinks| feature}
      + When this option is on, writing a file which is a hard link will cause
      + the hard link to be broken. This is useful for programmers that work
      + on big source trees, allowing them to just hard link the whole tree
      + and let the editor break the link when they change a file.
      +
      *'browsedir'* *'bsdir'*
      'browsedir' 'bsdir' string (default for "last")
      global
      diff -ur ../vim61.263/runtime/doc/quickref.txt ./runtime/doc/quickref.txt
      --- ../vim61.263/runtime/doc/quickref.txt Fri Mar 22 21:18:38 2002
      +++ ./runtime/doc/quickref.txt Thu Nov 28 20:33:48 2002
      @@ -605,6 +605,7 @@
      |'bioskey'| |'biosk'| MS-DOS: use bios calls for input characters
      |'bomb'| prepend a Byte Order Mark to the file
      |'breakat'| |'brk'| characters that may cause a line break
      +|'breakhlinks'| |'bhl'| break hard links when saving a file
      |'browsedir'| |'bsdir'| which directory to start browsing in
      |'bufhidden'| |'bh'| what to do when buffer is no longer in window
      |'buflisted'| |'bl'| whether the buffer shows up in the buffer list
      diff -ur ../vim61.263/runtime/doc/various.txt ./runtime/doc/various.txt
      --- ../vim61.263/runtime/doc/various.txt Fri Mar 22 21:18:42 2002
      +++ ./runtime/doc/various.txt Thu Nov 28 20:33:48 2002
      @@ -224,6 +224,7 @@
      *+ARP* Amiga only: ARP support included
      N *+autocmd* |:autocmd|, automatic commands
      m *+balloon_eval* |balloon-eval| support
      +N *+breakhlinks* |'breakhlinks'| support
      N *+browse* |:browse| command
      N *+builtin_terms* some terminals builtin |builtin-terms|
      B *++builtin_terms* maximal terminals builtin |builtin-terms|
      diff -ur ../vim61.263/runtime/optwin.vim ./runtime/optwin.vim
      --- ../vim61.263/runtime/optwin.vim Thu Nov 28 19:53:14 2002
      +++ ./runtime/optwin.vim Thu Nov 28 21:25:34 2002
      @@ -848,6 +848,10 @@
      call append("$", "\t(local to buffer)")
      call <SID>BinOptionL("sn")
      endif
      +if has("breakhlinks")
      + call append("$", "breakhlinks\tBreak hard links when saving a file")
      + call <SID>BinOptionG("bhl")
      +endif


      call <SID>Header("the swap file")
      diff -ur ../vim61.263/src/eval.c ./src/eval.c
      --- ../vim61.263/src/eval.c Thu Nov 28 19:55:21 2002
      +++ ./src/eval.c Thu Nov 28 20:37:21 2002
      @@ -4205,6 +4205,9 @@
      "all_builtin_terms",
      # endif
      #endif
      +#ifdef FEAT_BREAKHLINKS
      + "breakhlinks",
      +#endif
      #ifdef FEAT_BYTEOFF
      "byte_offset",
      #endif
      diff -ur ../vim61.263/src/feature.h ./src/feature.h
      --- ../vim61.263/src/feature.h Thu Nov 28 19:53:15 2002
      +++ ./src/feature.h Thu Nov 28 20:40:16 2002
      @@ -1116,3 +1116,13 @@
      # define FEAT_FOOTER

      #endif
      +
      +/*
      + * breakhlinks Include an option to break hard links when saving
      + * hard-linked files
      + */
      +#ifdef FEAT_NORMAL
      +#ifdef UNIX
      +#define FEAT_BREAKHLINKS
      +#endif
      +#endif
      diff -ur ../vim61.263/src/fileio.c ./src/fileio.c
      --- ../vim61.263/src/fileio.c Thu Nov 28 19:55:07 2002
      +++ ./src/fileio.c Fri Nov 29 02:07:26 2002
      @@ -1875,6 +1875,14 @@
      msg_add_eol();
      c = TRUE;
      }
      +#ifdef UNIX
      + /* show a message if file is a hard link and 'breakhlinks' is on */
      + if (p_bhl && newfile && !read_stdin
      + && !read_buffer && st.st_nlink>1) {
      + STRCAT(IObuff, _("[hardlink]"));
      + c = TRUE;
      + }
      +#endif
      if (ff_error == EOL_DOS)
      {
      STRCAT(IObuff, _("[CR missing]"));
      @@ -2354,6 +2362,9 @@
      vim_acl_T acl = NULL; /* ACL copied from original file to
      backup or new file */
      #endif
      +#ifdef UNIX
      + char *backup_link = NULL;
      +#endif

      if (fname == NULL || *fname == NUL) /* safety check */
      return FAIL;
      @@ -3303,6 +3314,35 @@
      }
      #endif

      +#ifdef UNIX
      + /* break hard link: delete original file, and create a backup hardlink in
      + * case writing fails */
      + if (!append && p_bhl && st_old.st_nlink > 1) {
      + struct stat tmpstat;
      + int j = 0, i = strlen(fname) + 6;
      +
      + backup_link = (char *) malloc(sizeof(char) * i);
      + strcpy(backup_link, fname);
      + backup_link = strcat(backup_link, ".tmp ");
      + /* this is not perfect, but should find a non-existing name */
      + do {
      + backup_link[i-2] = 'a' + j++;
      + } while (!stat (backup_link, &tmpstat) && ('a' + j) <= 'z');
      + if (('a' + j) <= 'z' && !link(fname, backup_link)) {
      + if (unlink ((char *)fname)) {
      + unlink (backup_link);
      + free (backup_link);
      + backup_link = NULL;
      + errmsg = (char_u *)_("Can't unlink file, hard link not broken");
      + }
      + } else {
      + errmsg = (char_u *)_("Can't create backup link, hard link not broken");
      + free (backup_link);
      + backup_link = NULL;
      + }
      + }
      +#endif
      +
      /*
      * Open the file "wfname" for writing.
      * We may try to open the file twice: If we can't write to the
      @@ -3325,9 +3365,14 @@
      {
      #ifdef UNIX
      struct stat st;
      -
      - /* Don't delete the file when it's a hard or symbolic link. */
      - if ((!newfile && st_old.st_nlink > 1)
      + nlink_t hard_link;
      +
      + if (p_bhl && backup_link)
      + hard_link = 1;
      + else
      + hard_link = st_old.st_nlink;
      + /* Don't delete the file when it's a hard or symbolic link. */
      + if ((!newfile && hard_link > 1)
      || (mch_lstat((char *)fname, &st) == 0
      && (st.st_dev != st_old.st_dev
      || st.st_ino != st_old.st_ino)))
      @@ -3364,6 +3409,15 @@
      * away. If we moved or removed the original file try to put the
      * backup in its place.
      */
      +#ifdef UNIX
      + if (backup_link) {
      + unlink (fname);
      + link (backup_link, fname);
      + unlink (backup_link);
      + free (backup_link);
      + backup_link = NULL;
      + }
      +#endif
      if (backup != NULL && wfname == fname)
      {
      if (backup_copy)
      @@ -3674,6 +3728,15 @@
      * file. Otherwise rename the backup file.
      * If this is OK, don't give the extra warning message.
      */
      +#ifdef UNIX
      + if (backup_link) {
      + unlink (fname);
      + link (backup_link, fname);
      + unlink (backup_link);
      + free (backup_link);
      + backup_link = NULL;
      + }
      +#endif
      if (backup != NULL)
      {
      if (backup_copy)
      @@ -3882,6 +3945,13 @@
      fail:
      --no_wait_return; /* may wait for return now */
      nofail:
      +#ifdef UNIX
      + if (backup_link) {
      + unlink (backup_link);
      + free (backup_link);
      + backup_link = NULL;
      + }
      +#endif

      vim_free(backup);
      if (buffer != smallbuf)
      diff -ur ../vim61.263/src/option.c ./src/option.c
      --- ../vim61.263/src/option.c Thu Nov 28 19:55:12 2002
      +++ ./src/option.c Thu Nov 28 21:00:51 2002
      @@ -424,6 +424,15 @@
      {(char_u *)0L, (char_u *)0L}
      #endif
      },
      + {"breakhlinks", "bhl", P_BOOL|P_VI_DEF,
      +#ifdef FEAT_BREAKHLINKS
      + (char_u *)&p_bhl, PV_NONE,
      + {(char_u *)0L, (char_u *)0L}
      +#else
      + (char_u *)NULL, PV_NONE,
      + {(char_u *)0L, (char_u *)0L}
      +#endif
      + },
      {"browsedir", "bsdir",P_STRING|P_VI_DEF,
      #ifdef FEAT_BROWSE
      (char_u *)&p_bsdir, PV_NONE,
      diff -ur ../vim61.263/src/option.h ./src/option.h
      --- ../vim61.263/src/option.h Thu Nov 28 19:55:02 2002
      +++ ./src/option.h Thu Nov 28 21:02:13 2002
      @@ -309,6 +309,9 @@
      #ifdef FEAT_LINEBREAK
      EXTERN char_u *p_breakat; /* 'breakat' */
      #endif
      +#ifdef FEAT_BREAKHLINKS
      +EXTERN char_u *p_bhl; /* 'breakhlinks' */
      +#endif
      EXTERN char_u *p_cmp; /* 'casemap' */
      EXTERN unsigned cmp_flags;
      #ifdef IN_OPTION_C
      diff -ur ../vim61.263/src/version.c ./src/version.c
      --- ../vim61.263/src/version.c Thu Nov 28 19:55:25 2002
      +++ ./src/version.c Thu Nov 28 20:33:48 2002
      @@ -70,6 +70,11 @@
      #else
      "-balloon_eval",
      #endif
      +#ifdef FEAT_BREAKHLINKS
      + "+breakhlinks",
      +#else
      + "-breakhlinks",
      +#endif
      #ifdef FEAT_BROWSE
      "+browse",
      #else
    • Piet Delport
      ... [...] ... [...] This is probably a stupid question, but what does this option achieve that :set bkc=no doesn t already? -- Piet Delport Today s subliminal
      Message 2 of 2 , Dec 1, 2002
      • 0 Attachment
        On Sat, 30 Nov 2002 at 20:11:22 +0100, Guillermo Ontañón wrote:
        >
        > The patch below adds a new option to Vim called 'breakhlinks', with this
        > option activated, Vim will check if the file to be saved is a hard link,
        > if so, it will break the link.
        >
        [...]
        >
        > This option is useful in some situations, as an example, one of the
        > recommended ways [1] of making diffs to the linux kernel is to create a
        > hard-linked copy of the kernel tree and let the editor break the link
        > when modifying a file, leaving all other files as links but the modified
        > ones as real copies. In the case of the linux kernel, doing things this
        > way saves a lot of disk space.
        >
        [...]

        This is probably a stupid question, but what does this option achieve
        that :set bkc=no doesn't already?

        --
        Piet Delport
        Today's subliminal thought is:
      Your message has been successfully submitted and would be delivered to recipients shortly.