Description: when copying symlinks, we cannot also copy file permissions, since those would get written to the symlink target, not the symlink itself. Ubuntu: https://launchpad.net/bugs/418135 Upstream: http://bugzilla.gnome.org/show_bug.cgi?id=593406 Patch: from git://git.gnome.org/glib e695c0932f5d02f3b222f0b7a3de1f8c00ba7b81 bb7852e34b1845e516290e1b45a960a345ee8a43 48e0af0157f52ac12b904bd92540432a18b139c7 3826963e65d8c4c68bcd3e4066505f63ef734b95 diff -Naurp glib-2.18.1/configure glib-2.18.1.oden/configure --- glib-2.18.1/configure 2008-09-17 18:54:36.000000000 -0400 +++ glib-2.18.1.oden/configure 2009-09-24 05:05:55.000000000 -0400 @@ -34533,7 +34533,7 @@ done -for ac_func in chown lchown fchmod fchown link statvfs statfs utimes getgrgid getpwuid +for ac_func in chown lchmod lchown fchmod fchown link statvfs statfs utimes getgrgid getpwuid do as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` { $as_echo "$as_me:$LINENO: checking for $ac_func" >&5 diff -Naurp glib-2.18.1/configure.in glib-2.18.1.oden/configure.in --- glib-2.18.1/configure.in 2008-09-17 18:34:01.000000000 -0400 +++ glib-2.18.1.oden/configure.in 2009-09-24 05:05:55.000000000 -0400 @@ -938,7 +938,7 @@ AC_MSG_RESULT(unsigned $glib_size_type) # Check for some functions AC_CHECK_FUNCS(lstat strerror strsignal memmove vsnprintf stpcpy strcasecmp strncasecmp poll getcwd vasprintf setenv unsetenv getc_unlocked readlink symlink fdwalk) -AC_CHECK_FUNCS(chown lchown fchmod fchown link statvfs statfs utimes getgrgid getpwuid) +AC_CHECK_FUNCS(chown lchmod lchown fchmod fchown link statvfs statfs utimes getgrgid getpwuid) AC_CHECK_FUNCS(getmntent_r setmntent endmntent hasmntopt getmntinfo) # Check for high-resolution sleep functions AC_CHECK_FUNCS(nanosleep nsleep) diff -Naurp glib-2.18.1/gio/glocalfileinfo.c glib-2.18.1.oden/gio/glocalfileinfo.c --- glib-2.18.1/gio/glocalfileinfo.c 2008-09-17 18:33:49.000000000 -0400 +++ glib-2.18.1.oden/gio/glocalfileinfo.c 2009-09-24 05:05:55.000000000 -0400 @@ -1805,15 +1805,40 @@ get_string (const GFileAttributeValue * static gboolean set_unix_mode (char *filename, + GFileQueryInfoFlags flags, const GFileAttributeValue *value, GError **error) { guint32 val; + int res = 0; if (!get_uint32 (value, &val, error)) return FALSE; - - if (g_chmod (filename, val) == -1) + +#ifdef HAVE_SYMLINK + if (flags & G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS) { +#ifdef HAVE_LCHMOD + res = lchmod (filename, val); +#else + struct stat statbuf; + /* Calling chmod on a symlink changes permissions on the symlink. + * We don't want to do this, so we need to check for a symlink */ + res = g_lstat (filename, &statbuf); + if (res == 0 && S_ISLNK (statbuf.st_mode)) + { + g_set_error_literal (error, G_IO_ERROR, + G_IO_ERROR_NOT_SUPPORTED, + _("Cannot set permissions on symlinks")); + return FALSE; + } + else if (res == 0) + res = g_chmod (filename, val); +#endif + } else +#endif + res = g_chmod (filename, val); + + if (res == -1) { int errsv = errno; @@ -2106,7 +2131,7 @@ _g_local_file_info_set_attribute (char _g_file_attribute_value_set_from_pointer (&value, type, value_p, FALSE); if (strcmp (attribute, G_FILE_ATTRIBUTE_UNIX_MODE) == 0) - return set_unix_mode (filename, &value, error); + return set_unix_mode (filename, flags, &value, error); #ifdef HAVE_CHOWN else if (strcmp (attribute, G_FILE_ATTRIBUTE_UNIX_UID) == 0) @@ -2219,7 +2244,7 @@ _g_local_file_info_set_attributes (char value = _g_file_info_get_attribute_value (info, G_FILE_ATTRIBUTE_UNIX_MODE); if (value) { - if (!set_unix_mode (filename, value, error)) + if (!set_unix_mode (filename, flags, value, error)) { value->status = G_FILE_ATTRIBUTE_STATUS_ERROR_SETTING; res = FALSE;