Apple Event: May 7th at 7 am PT

Looks like no one’s replied in a while. To start the conversation again, simply ask a new question.

How to hard link a symlink?

I'm looking for a way to create a hard link to a symbolic link in OS X 10.8 aka Mountain Lion.


Here's a brief illustration (inode numbers shortened for easier digestion):


$ echo "Hello" > file $ ln file hardlink $ ln -s file symlink $ ln -s nofile dangling-symlink $ ln symlink redirected-hardlink $ ln dangling-symlink symlink-hardlink ln: dangling-symlink: No such file or directory $ ls -liog total 40 458 lrwxr-xr-x 1 6 8 Jan 00:54 dangling-symlink -> nofile 433 -rw-r--r-- 3 6 8 Jan 00:53 file 433 -rw-r--r-- 3 6 8 Jan 00:53 hardlink 433 -rw-r--r-- 3 6 8 Jan 00:53 redirected-hardlink 456 lrwxr-xr-x 1 4 8 Jan 00:53 symlink -> file


So the inode ids for "file" and "hardlink" are the same, as one would expect.

The inode id for "redirected-hardlink" is the same as those two, meaning the hard link has dereferenced "symlink", rather than linking to it directly.

Since "dangling-symlink" can't be dereferenced, my attempt to create a hard link for it fails.


Just as well, as that's not what I want anyway—what I do want is a hard link to the actual symlink, i.e. for "redirected-hardlink" to point to inode 456, not 433. And for that last command to not fail, but instead produce a hard link with node id 458


I know this is possible in Linux and FreeBSD (the former by default, the latter via `ln -P`), but so far have failed to find a way to achieve the same in OS X.


Any suggestions?

I need something that works without installing additional software—code that can be made to run on a standard installation plus Xcode is fine.


Many thanks in advance for any pointers!


Message was edited by: Ronald Jore Fixed typos.

OS X Mountain Lion (10.8.5)

Posted on Jan 7, 2014 6:11 AM

Reply
Question marked as Best reply

Posted on Jan 7, 2014 7:34 PM

link() in the system call that implements hardlinks


man 2 link

<https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/ man2/link.2.html>

link() will resolve and follow symbolic links contained within both path1 and path2. If the last com-ponent component ponent of path1 is a symbolic link, link() will point the hard link, path2, to the underlying object pointed to by path1, not to the symbolic link itself.

As far as I can see, Mac OS X does not have a way to link to a symlink, only to the object pointed to by symlink.


Linux has linkat() which does not follow symlinks by default

<http://man7.org/linux/man-pages/man2/linkat.2.html>

Mac OS X does not have a linkat() function.


NOTE: linkat() is NOT POSIX compliant.

3 replies
Question marked as Best reply

Jan 7, 2014 7:34 PM in response to Ronald Jore

link() in the system call that implements hardlinks


man 2 link

<https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/ man2/link.2.html>

link() will resolve and follow symbolic links contained within both path1 and path2. If the last com-ponent component ponent of path1 is a symbolic link, link() will point the hard link, path2, to the underlying object pointed to by path1, not to the symbolic link itself.

As far as I can see, Mac OS X does not have a way to link to a symlink, only to the object pointed to by symlink.


Linux has linkat() which does not follow symlinks by default

<http://man7.org/linux/man-pages/man2/linkat.2.html>

Mac OS X does not have a linkat() function.


NOTE: linkat() is NOT POSIX compliant.

Jan 8, 2014 3:55 AM in response to BobHarris

Thank you for your quick response, BobHarris, much appreciated.

BobHarris wrote:


link() in the system call that implements hardlinks


man 2 link

<https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/ man2/link.2.html>

link() will resolve and follow symbolic links contained within both path1 and path2. If the last com-ponent component ponent of path1 is a symbolic link, link() will point the hard link, path2, to the underlying object pointed to by path1, not to the symbolic link itself.


Yes, that's what the manpage states.

Considering the fact that it also says


As mandated by POSIX.1, path1 may not be a directory.


and link() still creates directory hard links just fine, I was hoping that there might similarly be some non-documented implementation details with regards to symlinks.


As far as I can see, Mac OS X does not have a way to link to a symlink, only to the object pointed to by symlink.


That may well be the case.


Linux has linkat() which does not follow symlinks by default

<http://man7.org/linux/man-pages/man2/linkat.2.html>

Mac OS X does not have a linkat() function.


Ok. My thinking was that since OpenBSD has it, and Darwin is based on OpenBSD (if I'm not mistaken; but in any case FreeBSD and NetBSD also have it), there'd be a chance that it is present in Darwin as well, albeit possibly not exposed to the user.


NOTE: linkat() is NOT POSIX compliant.


Are you sure about that?


I don't have access to the standard itself, but the OpenBSD manpage linked above has this:


The link() and linkat() functions are expected to conform to IEEE Std

1003.1-2008 (``POSIX.1'').


Further, if I can believe this blogpost, then linkat() was added to the POSIX specification about five years ago, i.e. well before Mountain Lion was released.


Anyway, it seems that the available evidence points to 10.8.5 not supporting linkat (would that make it non-compliant?), so I'll take it that what I want is really not supported. 😟


Should anyone coming across this post have any further information, I'd appreciate hearing about it, now or later.

Jan 8, 2014 5:07 AM in response to Ronald Jore

I did some more googling based on what has transpired so far, and guess I can wrap this up...


For the record: linkat() is indeed defined in POSIX (and does allow directory hard links):

http://pubs.opengroup.org/onlinepubs/9699919799/functions/linkat.html


I got there via the gnulib documentation, which also states

Gnulib module: linkat

Portability problems fixed by Gnulib:

This function is missing on some platforms: glibc 2.3.6, Mac OS X 10.5, [...]


That looked to me as if gnulib provided a replacement for that missing function, so I wanted to know how it does that. Easy to check by looking at the source, where we find:

#if !HAVE_LINKAT


/* Create a link. If FILE1 is a symlink, either create a hardlink to

that symlink, or fake it by creating an identical symlink. */


So, faking it, it is. Interesting comment in that context:

/* A symlink cannot be modified in-place. Therefore, creating

an identical symlink behaves like a hard link to a symlink,

except for incorrect st_ino and st_nlink. [...]

So it seems the GNU project didn't find any magic incantations, either, to make this work.

Oh well. Not what I wanted, but I'll call it closure. Thanks again!

How to hard link a symlink?

Welcome to Apple Support Community
A forum where Apple customers help each other with their products. Get started with your Apple ID.