3

I have 2 existing files : abcd and xyz.

$ cat abcd
abcd 
$ cat xyz
xyz

Now, when I try to softlink these files, I get this message :

ln: cannot create xyz: File exists

I do not want to use

ln -sf abcd xyz

command as it will overwrite the content of xyz with that of abcd.

What I want is: both abcd and xyz should display their original content once they are unlinked.

Or in other words, I just want to temporarily link both of these files.

Please suggest if there is any other solution to this other than soft/hard link like using mount, etc.

Edit : I am using Solaris OS which has no manual entry for commands like mount --bind,mount -B, bindfs, fusermount,etc

Also, I tried to use : mount -o bind abcd xyz and it gave following msg : cannot open /etc/vfstab. I checked and found out that /etc/vfstab was having only Root access.

  • mv xyz xyz.orig – n.caillou Jun 10 '17 at 16:34
17

This is not what ln is meant to do. ln creates a hardlink of an existing file, i.e., two (or more) directory entries that point to the same file in the disk. Linked files work in a way that editing one will affect all.

The functionality you want is not something native to Unix (link files so that they appear as one and so that they can be unlinked later). Linux, though, has (some years ago) implemented something called bind mounting, allowing a file or a directory to be mounted on top of another (files on top of files and directories on top of directories).

Proposed solution: If you want a file to appear "to be" another temporarily, then use bind mount (mount -B file1 file2). This will mount file1 on top of file2. After unmounting this later, both files will show again as they originally exist.

# echo A >A

# echo B >B

# mount -B A B

# cat A
A

# cat B
A

# umount B

# cat A
A

# cat B
B

If you expected that the "linked" files show as a concatenation of both, you will have to create a third file and remove it later.

  • I didn't know this one. Why does it demand sudo priviliges? – Tomasz Jun 10 '17 at 15:53
  • 3
    If this allowed regular users to "fake" other users files contents this could create major security issues. (I'm inclined to agree that if the user owns all involved files and directories this should be allowed. Unfortunately it isn't). – Marcelo Jun 10 '17 at 16:01
  • 3
    Allowing regular users to do this could create a denial-of-service vulnerability through a flood of bind mounts. I don't know how well a typical Linux kernel handles millions of mount points. If somebody has a VM snapshot handy I'd be curious to find out. :-) – David Foerster Jun 10 '17 at 17:00
  • @DavidFoster - Yes, this makes sense. Thank you for the input. Anyway, the feature worth it, so there could be a limit/mount-quota/something-similar. (a little off-topic just wondering philosophically...) – Marcelo Jun 10 '17 at 17:02
  • Bind mounting with mount --bind has existed in Linux for over a decade. This probably won't help the asker since the question was tagged Solaris. Also, it requires root. A similar solution is to use bindfs, which works on most unices and doesn't require root (provided that FUSE is allowed). – Gilles Jun 10 '17 at 23:30
6

This command:

ln -sf abcd xyz

does not overwrite the content of xyz with that of abcd, as you think. A symbolic link is not a file, so it doesn't contain any content.

If you want to temporarily link xyz to abcd while not loosing it's content, you need to store the content somehow.

  • You can copy the contents to a temporary file. I guess no illustration for this is needed.
  • You can also use the memory, that is store the contents in a variable.
  • You can use a hard link.

Now I'll demonstrate the last one. You have abcd and xyz, as explained in your question.

  1. Hard-link xyz with zyx, so that the contents is kept in zyx letting you manipulate xyz.

    $ ln xyz zyx
    

    At this point xyz and zyx are two hard links of the inode containing the data xyz, as described in your question. You can check this with:

    $ cat zyx
    xyz
    
  2. Now that zyx is in place, you can force the relinking of xyz to abcd.

    $ ln -sf abcd xyz
    

    zyx still keeps the characters xyz. You can check this with:

    $ cat zyx
    xyz
    

    While xyz is now soft-linked to abcd. To check run this:

    $ cat xyz
    abcd
    
  3. Once you want to restore the starting state, relink xyz to the original contents. That is, relink it to the original inode.

    $ ln -f zyx xyz
    

    To check if it works:

    $ cat xyz
    xyz
    

    And now you can unlink the additional hard-link zyx with:

    $ rm zyx
    

    Or keep it for future operations. Either way xyz still contains what it did at the beginning.

    $ rm zyx
    $ cat xyz
    xyz
    
  • @VivekSingh Good. Accept the answer if it's satisfactory. And upvote it if you like me. – Tomasz Jun 10 '17 at 15:42
  • @VivekSingh - this is not necessary to store the contents temporarily as proposed above. The expected behavior can be obtained using bind mount (if you are using Linux). Please check my answer. – Marcelo Jun 10 '17 at 15:44
  • @Marcelo, I am using Putty console in a Windows 7 configuration system. Unfortunately, I am getting this error, when I am using "mount --bind abcd xyz" or "mount -B abcd xyz" : mount -B abcd xyz mount: illegal option -- B. Can you please elaborate or provide exact command for the same. – Raid_Master Jun 10 '17 at 16:03
  • @VivekSingh - Some questions: Is the target system a Linux? ; Are you entering the command as root? (please post the output of uname -a and whoami) – Marcelo Jun 10 '17 at 16:08
  • 1
    @VivekSingh - I guess that since you don't own root privileges you'll have to work with scripts using cp, ln, etc, to backup the original contents, linking the files and then restoring them back. mount is a command supposed to be run as root. You could talk to your system administrator so that he could allow you to use a very specific mount line and parameters with sudo, but I guess this may be more difficult to convince than practical (Still, I'm not even sure Solaris supports bind mounting, so it may worth nothing in the end). – Marcelo Jun 10 '17 at 16:36
2

both abcd and xyz should display their original content once they are unlinked

Then what you want is not a link. If two files are linked, then they have the same content. More precisely, two directory entries are linked if they point to the same file. Unlinking a file doesn't leave two files: unlinking a directory entry means removing this directory entry (the system call to remove a file is even called unlink).

There's no general feature to shadow a file with another file. You can use the bindfs filesystem to shadow a directory with another directory. To shadow the directory xyz with the directory abcd, run

bindfs -n -o nonempty xyz abcd

After this, the former contents of abcd are hidden, and accessing abcd in any way accesses xyz. Bindfs is a FUSE filesystem that creates a bind mount. To undo the shadowing and see the original content of abcd, unmount the filesystem:

fusermount -u abcd

Note that mounting a filesystem doesn't change what's stored on the disk. The shadowing is limited to your machine, and only lasts at most until the next reboot. If you want the shadowing to last, you need to add this mounting to the list of things to mount at boot time (/etc/fstab). But if you want the shadowing to last, then mounting is probably not the right approach: instead just move the file and create a symbolic link

mv abcd abcd.orig
ln -s xyz abcd

and to go back, remove the symlink and move back the original file

rm abcd
mv abcd.orig abcd
  • @Giles I have edited my question, can you please have a look again – Raid_Master Jun 11 '17 at 8:10
  • @VivekSingh Re-read my answer. I didn't say to use mount --bind, in fact I told you it wouldn't work on Solaris. Use bindfs instead. It isn't part of the default installation, install it either from the site (click the link in my answer) or as a package if it's available as a package. – Gilles Jun 11 '17 at 21:34
  • @Giles Thanks, in my case I have to overshadow one file with another which I guess is not possible, so I believe I have to use link approach only – Raid_Master Jun 12 '17 at 11:30
  • @VivekSingh I suspect that making and removing a link is not the best approach, but it's difficult to say because you're asking about your proposed solution rather than asking about your problem. I suggest asking a new question where you describe your problem and ask how to solve it, without insisting on a particular method. – Gilles Jun 12 '17 at 11:58
  • @Giles Could you please help me with another question of mine : unix.stackexchange.com/questions/372009/… – Raid_Master Jun 25 '17 at 10:47
2

On Linux, as an alternative to bind mount, you can also use overlay mount to link one file with another temporarily. The advantage of an overlay is that you can change overlay without needing root privilege, unlike bind mount which will require root privilege to shadow and unshadow files.

Demonstration:

Create a test partition with some test files (note that you need root to create a mountpoint that isn't listed in /etc/fstab, but you won't need root for any of the other steps):

$ mkdir one two work mpnt
$ sudo mount -t overlay none -olowerdir=one,upperdir=two,workdir=work mpnt
$ echo "hello world" > one/abcd
$ echo "another" > one/xyz

We created the test files in folder one above, these files are also visible in the mount point mpnt.

$ ls -lh mpnt
total 8.0K
-rw-r--r-- 1 lieryan lieryan 12 Jun 11 03:33 abcd
-rw-r--r-- 1 lieryan lieryan  8 Jun 11 03:33 xyz

Let's modify the files in mpnt:

$ ln -sf abcd mpnt/xyz 

We modified mpnt/xyz above to be a symlink, but overlayfs redirects all writes to mpnt to the upperdir, so the symlink we created are actually written to two, we can see the symlink in folder two as well as mpnt:

$ ls -lh two
total 0
lrwxrwxrwx 1 lieryan lieryan 4 Jun 11 03:34 xyz -> abcd
$ ls -lh mpnt
total 4.0K
-rw-r--r-- 1 lieryan lieryan 12 Jun 11 03:33 abcd
lrwxrwxrwx 1 lieryan lieryan  4 Jun 11 03:34 xyz -> abcd

The symlink works as expected when used from mpnt:

$ cat mpnt/xyz
hello world

If we delete something from mpnt, overlayfs will also redirect the write to upperdir:

$ rm mpnt/xyz

In this case though, overlayfs actually creates a special character device file (notice the c attribute), called a whiteout file. When overlayfs sees this type of file in the upperdir, overlayfs pretends that the file don't exist in mpnt:

$ ls -lh mpnt 
total 4.0K
-rw-r--r-- 1 lieryan lieryan 12 Jun 11 03:33 abcd
$ ls -lh two
total 4.0K
c--------- 1 lieryan lieryan 12 Jun 11 03:33 xyz

We can remove the special character file from the upperdir to restore xyz from lowerdir:

$ rm two/xyz  # delete the "whiteout" file
rm: remove write-protected character special file 'two/xyz'? y

Now xyz is visible again in mpnt, and has the same file content as one/xyz.

$ ls -lh mpnt 
total 8.0K
-rw-r--r-- 1 lieryan lieryan 12 Jun 11 03:33 abcd
-rw-r--r-- 1 lieryan lieryan  8 Jun 11 03:33 xyz
$ cat mpnt/xyz
another
  • Why am I getting this: overlayfs: filesystem on 'two' not supported as upperdir? – Tomasz Jun 10 '17 at 18:23
  • @tomas: From man mount: The upper filesystem will normally be writable and if it is it must support the creation of trusted.* extended attributes, and must provide a valid d_type in readdir responses, so NFS is not suitable. What filesystem are you using as the upperdir? – Lie Ryan Jun 10 '17 at 18:38
  • This is new to me. My only disk is all ext4. If this is a good answer... – Tomasz Jun 10 '17 at 18:44
  • @tomas: what directory are you using for your test? If you are doing it on /tmp, that is mounted as tmpfs on some systems. tmpfs doesn't support extended attributes either, so it can't be used as upperdir. Check your mount table by running mount command. – Lie Ryan Jun 10 '17 at 18:52
  • type ecryptfs (rw,nosuid,nodev,relatime,ecryptfs_fnek_sig=1c2cadf7870dc437,ecryptfs_sig=89832faac44a6443,ecryptfs_cipher=aes,ecryptfs_key_bytes=16,ecryptfs_unlink_sigs) – Tomasz Jun 10 '17 at 19:14
1

As far as i understand you, you want to link two files but you don't want to loose the data in both files. You tagged your post with Solaris so i assume you use this operating system. So refering to functionalities of other operating systems doesn't seem to be useful. This answer assumes that you are using one or more zfs datasets for the data.

You could simply make a zfs snapshot of your filesystem where you want to place the link instead of the file, make the ln -sf abcd xyz, do whatever you want with it and then roll back

root@solaris:/rpool# zfs create rpool/filesystem1
root@solaris:/rpool# mkfile 1k /rpool/filesystem1/file1
root@solaris:/rpool# mkfile 1k /rpool/filesystem1/file2
root@solaris:/rpool# ls -l /rpool/filesystem1
total 2
-rw-------   1 root     root        1024 Jun  8 20:33 file1 .  
-rw-------   1 root     root        1024 Jun  8 20:33 file2
root@solaris:/rpool# zfs snapshot rpool/filesystem1@withtwofiles
root@solaris:/rpool# rm /rpool/filesystem1/file2
root@solaris:/rpool# ln -s /rpool/filesystem1/file1 /rpool/filesystem1/file1
root@solaris:/rpool# ls -l /rpool/filesystem1
total 4
-rw-------   1 root     root        1024 Jun  8 20:33 file1
lrwxrwxrwx   1 root     root          24 Jun  8 20:33 file2 -> /rpool/filesystem1/file1
root@solaris:/rpool# zfs rollback rpool/filesystem1@withtwofiles
root@solaris:/rpool# ls -l /rpool/filesystem1
total 6
-rw-------   1 root     root        1024 Jun  8 20:33 file1
-rw-------   1 root     root        1024 Jun  8 20:33 file2
root@solaris:/rpool# 

Instead of unlinking you just rollback the filesystem with the link

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.