Symbolic link handling

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • makholm
    Journeyman
    • Jul 2008
    • 11

    Symbolic link handling

    [Build 462]

    As has already been pointed out elsewhere, the handling of symlinks in the directory compare is a bit inconsistent. Here's how I think it should work...

    As symbolic links are frequently used to e.g. select a default version among multiple available version of a file (see your local /usr/lib for example), being able to compare the actual symlink instead of the file it points to will be a really important feature for many people.

    The defacto standard for most Unix tools is to have an option for either dereferencing symlinks or not. (See for example the du or cp manpages.) My proposal is that BC should follow this practice. I think should have a "dereference symbolic links" option with the following behaviour:

    When "dereference symbolic links" is disabled:
    Directory compare uses lstat() to get the meta data of the symlink and file compare uses readlink() to show where the symlink is pointing.

    Editing the symlink is basically equivalent of editing a one-line text file, except the contents are written back to the link with the symlink() call instead of open()/write().

    When "dereference symbolic links" is enabled:
    Directory compare uses stat() to get the meta data of the target file and file compare uses open()/read() to show the content of the target file.

    Editing a dereferenced symilnk really edits the target file of the symlink and saving the file will actually save the target file and retain the symlink. I.e. editing and saving will not turn the symlink into a real file.

    This behaviour will align well with how existing Unix tools deal with symlinks and thus with the principle of least surprise.

    Ideally the "dereference symbolic links" option should be easily accessible on the toolbar.
  • makholm
    Journeyman
    • Jul 2008
    • 11

    #2
    Posted more comments here:
    http://www.scootersoftware.com/vbull...ad.php?p=13711

    Comment

    • Zoë
      Team Scooter
      • Oct 2007
      • 2666

      #3
      Thank you for your very well thought out replies, that's exactly the kind of response I was hoping for. There are some technical hurdles that will make it difficult to switch the stat/lstat behavior without restarting BC, and even more to make it a session-level thing instead of a program wide setting, but hopefully we'll be able to overcome them.
      Zoë P Scooter Software

      Comment

      • makholm
        Journeyman
        • Jul 2008
        • 11

        #4
        Originally posted by Craig
        Thank you for your very well thought out replies, that's exactly the kind of response I was hoping for.
        My pleasure... In my opinion, BC is well on its way to becoming a must-have application for development on Linux. I just want to see it get there ASAP... :-)

        Originally posted by Craig
        There are some technical hurdles that will make it difficult to switch the stat/lstat behavior without restarting BC, and even more to make it a session-level thing instead of a program wide setting, but hopefully we'll be able to overcome them.
        This puzzles me a bit... Out of curiosity - are these hurdles related to Delphi/Kylix or something else?

        Comment

        • Zoë
          Team Scooter
          • Oct 2007
          • 2666

          #5
          Originally posted by makholm
          This puzzles me a bit... Out of curiosity - are these hurdles related to Delphi/Kylix or something else?
          Internal application architecture. The file system structures are loaded into memory and shared between all of the open views; we don't just "stat" every file as we're displaying it.
          Zoë P Scooter Software

          Comment

          • makholm
            Journeyman
            • Jul 2008
            • 11

            #6
            So you'd have to either do both lstat() and stat() for all symlinks and keep both results or reload meta data when we switching modes...

            Hmm...

            Maybe the most sensible thing to do would be to always lstat() everything, then if the entry turns out to be symlink, stat() as well and keep both struct stat's...

            This complicates things a bit, of course but nobody said it should be easy, right? :-)

            Of course, the really right thing to do might be to store the meta data for any entry in a hash-like structure keyed by file name + parent node (much like the file system does it except you can't reliably use inode numbers for this). Then you would know if e.g. two symilnks point to the same target or even if the file in one side is a symlink pointing to the same name in the other side... Always this would save you from having to stat() and allocate memory more than once for link targets...

            If you have an object encapsulating a directory entry, you could presumably then teach it which struct stat to return:

            Code:
            if (deref_links_option && entry->is_symilnk)
                while (entry->is_symlink)
                    entry = entry->link_target
            meta_data = entry->struct_stat
            (This of course, blatantly disregards the fact that symilnks pointing to e.g. non-existant files are still perfectly valid symlinks but let's not go there now...)

            The problem with only keeping one chunk of meta data (i.e. using stat() on everything and pretending links are just plain files) is that you're presenting a half truth to the user and that can be extremely confusing... Expecially in weird borderline cases such as links pointing to non-existing files (think a symilnk that points to a dir on a USB stick that may or may not be mounted right now => lstat()/readlink() succeeds, stat()/open() fails). In these cases, knowing whether the entry (i.e. the thing that the user double-clicked) was really a symlink, can help a lot in producing meaningful error messages... E.g. think "I double-clicked this file, which is clearly there, but I get no such file or directory" vs. "symbolic link points to non-existant file"...

            Ok, I'm getting carried away, I'll shut up now... :-)

            In any case though, invalidating your meta data cache and doing a refresh when changing the "dereference symlinks" option would, in my opinion, be perfectly acceptable...

            Comment

            • palfvin
              New User
              • Jan 2009
              • 1

              #7
              Alternative to BC

              When I sent a message to Scooter Support regarding this fix/feature, they said it wasn't in the release under development and couldn't make any promises regarding future availability.

              This is a showstopper for us in the sense that it prevents us from automatically comparing directories. On the other hand, I don't know of any alternatives that do support symbolic links properly (I'm interested in comparing the links themselves, not chasing them down). Support said they didn't know of any either.

              So my question is to anyone on this thread: Do you know of any alternatives to BC that handle symlinks properly?

              Comment

              • Pete
                Fanatic
                • Nov 2007
                • 190

                #8
                Infinite Loop

                While backing up my home directory, Wine has a couple of links that cause BC to go into an infinite loop during a folder compare:

                /home/pete/.wine/dosdevices/z: --> /
                /home/pete/.wine/drive_c/users/pete/My Documents --> /home/pete

                Overall I'm very happy with the behavior of BC in Linux. In general it seems like quite an accomplishment.

                However I'd also like to see an option to never follow symbolic links to files and folders. I know where the actual targets are if I want to back them up. I personally don't need a session-specific setting and doubt that I'd ever want to follow symbolic links. I want to back up the links so they're there when I restore my data after a clean install. With the current situation I lose the link information plus end up with the targets which by the way can be huge directories.

                My workaround is to exclude the misbehaving items from the compare but I hope there'll be a better solution.

                Comment

                • Aaron
                  Team Scooter
                  • Oct 2007
                  • 16002

                  #9
                  Thanks for the suggestion, Pete. This is something we are currently working on, so feedback in this area is appreciated.
                  Aaron P Scooter Software

                  Comment

                  • Dave_L
                    Veteran
                    • Dec 2007
                    • 351

                    #10
                    [BC 3.2.0.12469, MEPIS 7.0]

                    Thanks for adding the option to follow/not-follow symbolic links in 3.2. It seems to work as desired.

                    (I've only tested it with local files, not with FTP.)

                    Comment

                    • Pete
                      Fanatic
                      • Nov 2007
                      • 190

                      #11
                      Yes, really appreciate the new ability to not follow symlinks using the beta. Works fine in Ubuntu 10.4 with regards to Wine's symlinks.

                      Comment

                      Working...