How to change the Symlink permission?

Some systems support changing the permission of a symbolic link, others do not.

  • chmod -- change file modes or Access Control Lists (OSX and FreeBSD, using -h)

    -h If the file is a symbolic link, change the mode of the link itself rather than the file that the link points to.

  • chmod - change file mode bits (Linux)

    chmod never changes the permissions of symbolic links; the chmod system call cannot change their permissions. This is not a problem since the permissions of symbolic links are never used. However, for each symbolic link listed on the command line, chmod changes the permissions of the pointed-to file. In contrast, chmod ignores symbolic links encountered during recursive directory traversals.

Since the feature differs, POSIX does not mention the possibility.

From comments, someone suggests that a recent change to GNU coreutils provides the -h option. At the moment, that does not appear in the source-code for chmod:

  while ((c = getopt_long (argc, argv,
                           ("Rcfvr::w::x::X::s::t::u::g::o::a::,::+::=::"
                            "0::1::2::3::4::5::6::7::"),
                           long_options, NULL))

and long_options has this:

static struct option const long_options[] =
{
  {"changes", no_argument, NULL, 'c'},
  {"recursive", no_argument, NULL, 'R'},
  {"no-preserve-root", no_argument, NULL, NO_PRESERVE_ROOT},
  {"preserve-root", no_argument, NULL, PRESERVE_ROOT},
  {"quiet", no_argument, NULL, 'f'},
  {"reference", required_argument, NULL, REFERENCE_FILE_OPTION},
  {"silent", no_argument, NULL, 'f'},
  {"verbose", no_argument, NULL, 'v'},
  {GETOPT_HELP_OPTION_DECL},
  {GETOPT_VERSION_OPTION_DECL},
  {NULL, 0, NULL, 0}
};

Permissions are set with chmod. Ownership is set with chown. GNU coreutils (like BSD) supports the ability to change a symbolic link's ownership. This is a different feature, since the ownership of a symbolic link is related to whether one can modify the contents of the link (and point it to a different target). Again, this started as a BSD feature (OSX, FreeBSD, etc), which is also supported with Linux (and Solaris, etc). POSIX says of this feature:

-h
For each file operand that names a file of type symbolic link, chown shall attempt to set the user ID of the symbolic link. If a group ID was specified, for each file operand that names a file of type symbolic link, chown shall attempt to set the group ID of the symbolic link.

So much for the command-line tools (and shell scripts). However, you could write your own utility, using a feature of POSIX which is not mentioned in the discussion of the chmod utility:

int chmod(const char *path, mode_t mode);
int fchmodat(int fd, const char *path, mode_t mode, int flag);

The latter function adds a flag parameter, which is described thus:

Values for flag are constructed by a bitwise-inclusive OR of flags from the following list, defined in <fcntl.h>:

AT_SYMLINK_NOFOLLOW
If path names a symbolic link, then the mode of the symbolic link is changed.

That is, the purpose of fchmodat is to provide the feature you asked about. But the command-line chmod utility is documented (so far) only in terms of chmod (without this feature).

fchmodat, by the way, appears to have started as a poorly-documented feature of Solaris which was adopted by the Red Hat and GNU developers ten years ago, and suggested by them for standardization:

  • one more openat-style function required: fchmodat
  • Austin Group Minutes of the 17 May 2007 Teleconference
  • [Fwd: The Austin Group announces Revision Draft 2 now available]

According to The Linux Programming Interface, since 2.6.16, Linux supports AT_SYMLINK_NOFOLLOW in these calls: faccessat, fchownat, fstatat, utimensat, and linkat was implemented in 2.6.18 (both rather "old": 2006, according to OSNews).

Whether the feature is useful to you, or not, depends on the systems that you are using.


The permission for symlinks is not evaluated.

In former times, there was no way to change the permission bits for symlinks.

Since a while, POSIX introduced fchmodat() and all platforms that support this call, are able to change the permission bits for symlinks.

Do not expect this to have effects on the symlink though.