X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gio%2Fglocalfileinfo.c;h=7c46837cee5689294bbc76cadb109b3b1e965b06;hb=f14a66e3df9e5e3f0f170b68e976011c80ffc041;hp=7ecc9fccd81a07f93b757747d49ff8c7f4151f28;hpb=f5483302757a9c03c43e25c86cea4a7bd5aaaf3f;p=platform%2Fupstream%2Fglib.git diff --git a/gio/glocalfileinfo.c b/gio/glocalfileinfo.c index 7ecc9fc..7c46837 100644 --- a/gio/glocalfileinfo.c +++ b/gio/glocalfileinfo.c @@ -15,31 +15,25 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General - * Public License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307, USA. + * Public License along with this library; if not, see . * * Author: Alexander Larsson */ #include "config.h" +#include + #ifdef HAVE_SYS_TIME_H #include #endif #include #include #include -#ifdef HAVE_UNISTD_H -#include -#endif -#define _GNU_SOURCE #include #include -#ifdef HAVE_GRP_H +#ifdef G_OS_UNIX #include -#endif -#ifdef HAVE_PWD_H #include #endif #ifdef HAVE_SELINUX @@ -60,8 +54,16 @@ #include #include +#include +#include -#include "glibintl.h" +#ifdef G_OS_UNIX +#include +#include "glib-unix.h" +#include "glib-private.h" +#endif + +#include "thumbnail-verify.h" #ifdef G_OS_WIN32 #include @@ -89,10 +91,9 @@ #include "glocalfileinfo.h" #include "gioerror.h" #include "gthemedicon.h" -#include "gcontenttype.h" #include "gcontenttypeprivate.h" +#include "glibintl.h" -#include "gioalias.h" struct ThumbMD5Context { guint32 buf[4]; @@ -118,18 +119,18 @@ static GHashTable *gid_cache = NULL; char * _g_local_file_info_create_etag (GLocalFileStat *statbuf) { - GTimeVal tv; - - tv.tv_sec = statbuf->st_mtime; + glong sec, usec; + + sec = statbuf->st_mtime; #if defined (HAVE_STRUCT_STAT_ST_MTIMENSEC) - tv.tv_usec = statbuf->st_mtimensec / 1000; + usec = statbuf->st_mtimensec / 1000; #elif defined (HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC) - tv.tv_usec = statbuf->st_mtim.tv_nsec / 1000; + usec = statbuf->st_mtim.tv_nsec / 1000; #else - tv.tv_usec = 0; + usec = 0; #endif - return g_strdup_printf ("%lu:%lu", tv.tv_sec, tv.tv_usec); + return g_strdup_printf ("%lu:%lu", sec, usec); } static char * @@ -195,7 +196,7 @@ get_selinux_context (const char *path, { char *context; - if (!g_file_attribute_matcher_matches (attribute_matcher, G_FILE_ATTRIBUTE_SELINUX_CONTEXT)) + if (!_g_file_attribute_matcher_matches_id (attribute_matcher, G_FILE_ATTRIBUTE_ID_SELINUX_CONTEXT)) return; if (is_selinux_enabled ()) @@ -213,7 +214,7 @@ get_selinux_context (const char *path, if (context) { - g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_SELINUX_CONTEXT, context); + _g_file_info_set_attribute_string_by_id (info, G_FILE_ATTRIBUTE_ID_SELINUX_CONTEXT, context); freecon (context); } } @@ -321,7 +322,7 @@ hex_escape_string (const char *str, *p++ = hex_digits[c & 0xf]; } } - *p++ = 0; + *p = 0; *free_return = TRUE; return escaped_str; @@ -527,7 +528,7 @@ get_xattrs (const char *path, attr2 = strchr (attr, ':'); if (attr2) { - attr2++; /* Skip ':' */ + attr2 += 2; /* Skip '::' */ unescaped_attribute = hex_unescape_string (attr2, NULL, &free_unescaped_attribute); if (user) a = g_strconcat ("user.", unescaped_attribute, NULL); @@ -661,6 +662,7 @@ get_xattrs_from_fd (int fd, g_free (escaped_attr); get_one_xattr_from_fd (fd, info, gio_attr, attr); + g_free (gio_attr); } len = strlen (attr) + 1; @@ -786,21 +788,20 @@ _g_local_file_info_get_parent_info (const char *dir, GFileAttributeMatcher *attribute_matcher, GLocalParentFileInfo *parent_info) { - /* Use plain struct stat for now as long as we only look at the - * S_ISVTX bit which doesn't exist on Win32 anyway. - */ - struct stat statbuf; + GStatBuf statbuf; int res; - + + parent_info->extra_data = NULL; + parent_info->free_extra_data = NULL; parent_info->writable = FALSE; parent_info->is_sticky = FALSE; parent_info->has_trash_dir = FALSE; parent_info->device = 0; - if (g_file_attribute_matcher_matches (attribute_matcher, G_FILE_ATTRIBUTE_ACCESS_CAN_RENAME) || - g_file_attribute_matcher_matches (attribute_matcher, G_FILE_ATTRIBUTE_ACCESS_CAN_DELETE) || - g_file_attribute_matcher_matches (attribute_matcher, G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH) || - g_file_attribute_matcher_matches (attribute_matcher, G_FILE_ATTRIBUTE_UNIX_IS_MOUNTPOINT)) + if (_g_file_attribute_matcher_matches_id (attribute_matcher, G_FILE_ATTRIBUTE_ID_ACCESS_CAN_RENAME) || + _g_file_attribute_matcher_matches_id (attribute_matcher, G_FILE_ATTRIBUTE_ID_ACCESS_CAN_DELETE) || + _g_file_attribute_matcher_matches_id (attribute_matcher, G_FILE_ATTRIBUTE_ID_ACCESS_CAN_TRASH) || + _g_file_attribute_matcher_matches_id (attribute_matcher, G_FILE_ATTRIBUTE_ID_UNIX_IS_MOUNTPOINT)) { /* FIXME: Windows: The underlying _waccess() call in the C * library is mostly pointless as it only looks at the READONLY @@ -827,12 +828,20 @@ _g_local_file_info_get_parent_info (const char *dir, parent_info->device = statbuf.st_dev; /* No need to find trash dir if it's not writable anyway */ if (parent_info->writable && - g_file_attribute_matcher_matches (attribute_matcher, G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH)) + _g_file_attribute_matcher_matches_id (attribute_matcher, G_FILE_ATTRIBUTE_ID_ACCESS_CAN_TRASH)) parent_info->has_trash_dir = _g_local_file_has_trash_dir (dir, statbuf.st_dev); } } } +void +_g_local_file_info_free_parent_info (GLocalParentFileInfo *parent_info) +{ + if (parent_info->extra_data && + parent_info->free_extra_data) + parent_info->free_extra_data (parent_info->extra_data); +} + static void get_access_rights (GFileAttributeMatcher *attribute_matcher, GFileInfo *info, @@ -841,20 +850,20 @@ get_access_rights (GFileAttributeMatcher *attribute_matcher, GLocalParentFileInfo *parent_info) { /* FIXME: Windows: The underlyin _waccess() is mostly pointless */ - if (g_file_attribute_matcher_matches (attribute_matcher, - G_FILE_ATTRIBUTE_ACCESS_CAN_READ)) - g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_READ, - g_access (path, R_OK) == 0); + if (_g_file_attribute_matcher_matches_id (attribute_matcher, + G_FILE_ATTRIBUTE_ID_ACCESS_CAN_READ)) + _g_file_info_set_attribute_boolean_by_id (info, G_FILE_ATTRIBUTE_ID_ACCESS_CAN_READ, + g_access (path, R_OK) == 0); - if (g_file_attribute_matcher_matches (attribute_matcher, - G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE)) - g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE, - g_access (path, W_OK) == 0); + if (_g_file_attribute_matcher_matches_id (attribute_matcher, + G_FILE_ATTRIBUTE_ID_ACCESS_CAN_WRITE)) + _g_file_info_set_attribute_boolean_by_id (info, G_FILE_ATTRIBUTE_ID_ACCESS_CAN_WRITE, + g_access (path, W_OK) == 0); - if (g_file_attribute_matcher_matches (attribute_matcher, - G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE)) - g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE, - g_access (path, X_OK) == 0); + if (_g_file_attribute_matcher_matches_id (attribute_matcher, + G_FILE_ATTRIBUTE_ID_ACCESS_CAN_EXECUTE)) + _g_file_info_set_attribute_boolean_by_id (info, G_FILE_ATTRIBUTE_ID_ACCESS_CAN_EXECUTE, + g_access (path, X_OK) == 0); if (parent_info) @@ -879,17 +888,17 @@ get_access_rights (GFileAttributeMatcher *attribute_matcher, writable = TRUE; } - if (g_file_attribute_matcher_matches (attribute_matcher, G_FILE_ATTRIBUTE_ACCESS_CAN_RENAME)) - g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_RENAME, - writable); + if (_g_file_attribute_matcher_matches_id (attribute_matcher, G_FILE_ATTRIBUTE_ID_ACCESS_CAN_RENAME)) + _g_file_info_set_attribute_boolean_by_id (info, G_FILE_ATTRIBUTE_ID_ACCESS_CAN_RENAME, + writable); - if (g_file_attribute_matcher_matches (attribute_matcher, G_FILE_ATTRIBUTE_ACCESS_CAN_DELETE)) - g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_DELETE, - writable); + if (_g_file_attribute_matcher_matches_id (attribute_matcher, G_FILE_ATTRIBUTE_ID_ACCESS_CAN_DELETE)) + _g_file_info_set_attribute_boolean_by_id (info, G_FILE_ATTRIBUTE_ID_ACCESS_CAN_DELETE, + writable); - if (g_file_attribute_matcher_matches (attribute_matcher, G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH)) - g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_TRASH, - writable && parent_info->has_trash_dir); + if (_g_file_attribute_matcher_matches_id (attribute_matcher, G_FILE_ATTRIBUTE_ID_ACCESS_CAN_TRASH)) + _g_file_info_set_attribute_boolean_by_id (info, G_FILE_ATTRIBUTE_ID_ACCESS_CAN_TRASH, + writable && parent_info->has_trash_dir); } } @@ -924,68 +933,68 @@ set_info_from_stat (GFileInfo *info, g_file_info_set_file_type (info, file_type); g_file_info_set_size (info, statbuf->st_size); - g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_DEVICE, statbuf->st_dev); + _g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_DEVICE, statbuf->st_dev); #ifndef G_OS_WIN32 /* Pointless setting these on Windows even if they exist in the struct */ - g_file_info_set_attribute_uint64 (info, G_FILE_ATTRIBUTE_UNIX_INODE, statbuf->st_ino); - g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_NLINK, statbuf->st_nlink); - g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_UID, statbuf->st_uid); - g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_GID, statbuf->st_gid); - g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_RDEV, statbuf->st_rdev); + _g_file_info_set_attribute_uint64_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_INODE, statbuf->st_ino); + _g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_NLINK, statbuf->st_nlink); + _g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_UID, statbuf->st_uid); + _g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_GID, statbuf->st_gid); + _g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_RDEV, statbuf->st_rdev); #endif /* FIXME: st_mode is mostly pointless on Windows, too. Set the attribute or not? */ - g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_MODE, statbuf->st_mode); + _g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_MODE, statbuf->st_mode); #if defined (HAVE_STRUCT_STAT_ST_BLKSIZE) - g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_BLOCK_SIZE, statbuf->st_blksize); + _g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_BLOCK_SIZE, statbuf->st_blksize); #endif #if defined (HAVE_STRUCT_STAT_ST_BLOCKS) - g_file_info_set_attribute_uint64 (info, G_FILE_ATTRIBUTE_UNIX_BLOCKS, statbuf->st_blocks); - g_file_info_set_attribute_uint64 (info, G_FILE_ATTRIBUTE_STANDARD_ALLOCATED_SIZE, - statbuf->st_blocks * G_GUINT64_CONSTANT (512)); + _g_file_info_set_attribute_uint64_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_BLOCKS, statbuf->st_blocks); + _g_file_info_set_attribute_uint64_by_id (info, G_FILE_ATTRIBUTE_ID_STANDARD_ALLOCATED_SIZE, + statbuf->st_blocks * G_GUINT64_CONSTANT (512)); #endif - g_file_info_set_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_MODIFIED, statbuf->st_mtime); + _g_file_info_set_attribute_uint64_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_MODIFIED, statbuf->st_mtime); #if defined (HAVE_STRUCT_STAT_ST_MTIMENSEC) - g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC, statbuf->st_mtimensec / 1000); + _g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_MODIFIED_USEC, statbuf->st_mtimensec / 1000); #elif defined (HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC) - g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC, statbuf->st_mtim.tv_nsec / 1000); + _g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_MODIFIED_USEC, statbuf->st_mtim.tv_nsec / 1000); #endif - g_file_info_set_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_ACCESS, statbuf->st_atime); + _g_file_info_set_attribute_uint64_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_ACCESS, statbuf->st_atime); #if defined (HAVE_STRUCT_STAT_ST_ATIMENSEC) - g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_TIME_ACCESS_USEC, statbuf->st_atimensec / 1000); + _g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_ACCESS_USEC, statbuf->st_atimensec / 1000); #elif defined (HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC) - g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_TIME_ACCESS_USEC, statbuf->st_atim.tv_nsec / 1000); + _g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_ACCESS_USEC, statbuf->st_atim.tv_nsec / 1000); #endif - g_file_info_set_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_CHANGED, statbuf->st_ctime); + _g_file_info_set_attribute_uint64_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_CHANGED, statbuf->st_ctime); #if defined (HAVE_STRUCT_STAT_ST_CTIMENSEC) - g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_TIME_CHANGED_USEC, statbuf->st_ctimensec / 1000); + _g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_CHANGED_USEC, statbuf->st_ctimensec / 1000); #elif defined (HAVE_STRUCT_STAT_ST_CTIM_TV_NSEC) - g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_TIME_CHANGED_USEC, statbuf->st_ctim.tv_nsec / 1000); + _g_file_info_set_attribute_uint32_by_id (info, G_FILE_ATTRIBUTE_ID_TIME_CHANGED_USEC, statbuf->st_ctim.tv_nsec / 1000); #endif - if (g_file_attribute_matcher_matches (attribute_matcher, - G_FILE_ATTRIBUTE_ETAG_VALUE)) + if (_g_file_attribute_matcher_matches_id (attribute_matcher, + G_FILE_ATTRIBUTE_ID_ETAG_VALUE)) { char *etag = _g_local_file_info_create_etag (statbuf); - g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_ETAG_VALUE, etag); + _g_file_info_set_attribute_string_by_id (info, G_FILE_ATTRIBUTE_ID_ETAG_VALUE, etag); g_free (etag); } - if (g_file_attribute_matcher_matches (attribute_matcher, - G_FILE_ATTRIBUTE_ID_FILE)) + if (_g_file_attribute_matcher_matches_id (attribute_matcher, + G_FILE_ATTRIBUTE_ID_ID_FILE)) { char *id = _g_local_file_info_create_file_id (statbuf); - g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_ID_FILE, id); + _g_file_info_set_attribute_string_by_id (info, G_FILE_ATTRIBUTE_ID_ID_FILE, id); g_free (id); } - if (g_file_attribute_matcher_matches (attribute_matcher, - G_FILE_ATTRIBUTE_ID_FILESYSTEM)) + if (_g_file_attribute_matcher_matches_id (attribute_matcher, + G_FILE_ATTRIBUTE_ID_ID_FILESYSTEM)) { char *id = _g_local_file_info_create_fs_id (statbuf); - g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_ID_FILESYSTEM, id); + _g_file_info_set_attribute_string_by_id (info, G_FILE_ATTRIBUTE_ID_ID_FILESYSTEM, id); g_free (id); } } @@ -1088,6 +1097,7 @@ lookup_uid_data (uid_t uid) if (pwbufp->pw_name != NULL && pwbufp->pw_name[0] != 0) data->user_name = convert_pwd_string_to_utf8 (pwbufp->pw_name); +#ifndef __BIONIC__ gecos = pwbufp->pw_gecos; if (gecos) @@ -1097,6 +1107,7 @@ lookup_uid_data (uid_t uid) *comma = 0; data->real_name = convert_pwd_string_to_utf8 (gecos); } +#endif } /* Default fallbacks */ @@ -1207,19 +1218,19 @@ get_content_type (const char *basename, { if (is_symlink && (symlink_broken || (flags & G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS))) - return g_strdup ("inode/symlink"); - else if (S_ISDIR(statbuf->st_mode)) + return g_strdup ("inode/symlink"); + else if (statbuf != NULL && S_ISDIR(statbuf->st_mode)) return g_strdup ("inode/directory"); #ifndef G_OS_WIN32 - else if (S_ISCHR(statbuf->st_mode)) + else if (statbuf != NULL && S_ISCHR(statbuf->st_mode)) return g_strdup ("inode/chardevice"); - else if (S_ISBLK(statbuf->st_mode)) + else if (statbuf != NULL && S_ISBLK(statbuf->st_mode)) return g_strdup ("inode/blockdevice"); - else if (S_ISFIFO(statbuf->st_mode)) + else if (statbuf != NULL && S_ISFIFO(statbuf->st_mode)) return g_strdup ("inode/fifo"); #endif #ifdef S_ISSOCK - else if (S_ISSOCK(statbuf->st_mode)) + else if (statbuf != NULL && S_ISSOCK(statbuf->st_mode)) return g_strdup ("inode/socket"); #endif else @@ -1241,17 +1252,17 @@ get_content_type (const char *basename, sniff_length = 4096; #ifdef O_NOATIME - fd = open (path, O_RDONLY | O_NOATIME); + fd = g_open (path, O_RDONLY | O_NOATIME, 0); if (fd < 0 && errno == EPERM) #endif - fd = open (path, O_RDONLY); + fd = g_open (path, O_RDONLY, 0); if (fd != -1) { ssize_t res; res = read (fd, sniff_buffer, sniff_length); - close (fd); + (void) g_close (fd, NULL); if (res >= 0) { g_free (content_type); @@ -1266,9 +1277,11 @@ get_content_type (const char *basename, } +/* @stat_buf is the pre-calculated result of stat(path), or %NULL if that failed. */ static void -get_thumbnail_attributes (const char *path, - GFileInfo *info) +get_thumbnail_attributes (const char *path, + GFileInfo *info, + const GLocalFileStat *stat_buf) { GChecksum *checksum; char *uri; @@ -1279,32 +1292,53 @@ get_thumbnail_attributes (const char *path, checksum = g_checksum_new (G_CHECKSUM_MD5); g_checksum_update (checksum, (const guchar *) uri, strlen (uri)); - - g_free (uri); basename = g_strconcat (g_checksum_get_string (checksum), ".png", NULL); g_checksum_free (checksum); - filename = g_build_filename (g_get_home_dir (), - ".thumbnails", "normal", basename, + filename = g_build_filename (g_get_user_cache_dir (), + "thumbnails", "large", basename, NULL); if (g_file_test (filename, G_FILE_TEST_IS_REGULAR)) - g_file_info_set_attribute_byte_string (info, G_FILE_ATTRIBUTE_THUMBNAIL_PATH, filename); + { + _g_file_info_set_attribute_byte_string_by_id (info, G_FILE_ATTRIBUTE_ID_THUMBNAIL_PATH, filename); + _g_file_info_set_attribute_boolean_by_id (info, G_FILE_ATTRIBUTE_ID_THUMBNAIL_IS_VALID, + thumbnail_verify (filename, uri, stat_buf)); + } else { g_free (filename); - filename = g_build_filename (g_get_home_dir (), - ".thumbnails", "fail", - "gnome-thumbnail-factory", - basename, + filename = g_build_filename (g_get_user_cache_dir (), + "thumbnails", "normal", basename, NULL); if (g_file_test (filename, G_FILE_TEST_IS_REGULAR)) - g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_THUMBNAILING_FAILED, TRUE); + { + _g_file_info_set_attribute_byte_string_by_id (info, G_FILE_ATTRIBUTE_ID_THUMBNAIL_PATH, filename); + _g_file_info_set_attribute_boolean_by_id (info, G_FILE_ATTRIBUTE_ID_THUMBNAIL_IS_VALID, + thumbnail_verify (filename, uri, stat_buf)); + } + else + { + g_free (filename); + filename = g_build_filename (g_get_user_cache_dir (), + "thumbnails", "fail", + "gnome-thumbnail-factory", + basename, + NULL); + + if (g_file_test (filename, G_FILE_TEST_IS_REGULAR)) + { + _g_file_info_set_attribute_boolean_by_id (info, G_FILE_ATTRIBUTE_ID_THUMBNAILING_FAILED, TRUE); + _g_file_info_set_attribute_boolean_by_id (info, G_FILE_ATTRIBUTE_ID_THUMBNAIL_IS_VALID, + thumbnail_verify (filename, uri, stat_buf)); + } + } } g_free (basename); g_free (filename); + g_free (uri); } #ifdef G_OS_WIN32 @@ -1399,6 +1433,242 @@ win32_get_file_user_info (const gchar *filename, } #endif /* G_OS_WIN32 */ +#ifndef G_OS_WIN32 +/* support for '.hidden' files */ +G_LOCK_DEFINE_STATIC (hidden_cache); +static GHashTable *hidden_cache; + +static gboolean +remove_from_hidden_cache (gpointer user_data) +{ + G_LOCK (hidden_cache); + g_hash_table_remove (hidden_cache, user_data); + G_UNLOCK (hidden_cache); + + return FALSE; +} + +static GHashTable * +read_hidden_file (const gchar *dirname) +{ + gchar *contents = NULL; + gchar *filename; + + filename = g_build_path ("/", dirname, ".hidden", NULL); + (void) g_file_get_contents (filename, &contents, NULL, NULL); + g_free (filename); + + if (contents != NULL) + { + GHashTable *table; + gchar **lines; + gint i; + + table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); + + lines = g_strsplit (contents, "\n", 0); + g_free (contents); + + for (i = 0; lines[i]; i++) + /* hash table takes the individual strings... */ + g_hash_table_add (table, lines[i]); + + /* ... so we only free the container. */ + g_free (lines); + + return table; + } + else + return NULL; +} + +static void +maybe_unref_hash_table (gpointer data) +{ + if (data != NULL) + g_hash_table_unref (data); +} + +static gboolean +file_is_hidden (const gchar *path, + const gchar *basename) +{ + gboolean result; + gchar *dirname; + gpointer table; + + dirname = g_path_get_dirname (path); + + G_LOCK (hidden_cache); + + if G_UNLIKELY (hidden_cache == NULL) + hidden_cache = g_hash_table_new_full (g_str_hash, g_str_equal, + g_free, maybe_unref_hash_table); + + if (!g_hash_table_lookup_extended (hidden_cache, dirname, + NULL, &table)) + { + gchar *mydirname; + GSource *remove_from_cache_source; + + g_hash_table_insert (hidden_cache, + mydirname = g_strdup (dirname), + table = read_hidden_file (dirname)); + + remove_from_cache_source = g_timeout_source_new_seconds (5); + g_source_set_priority (remove_from_cache_source, G_PRIORITY_DEFAULT); + g_source_set_callback (remove_from_cache_source, + remove_from_hidden_cache, + mydirname, + NULL); + g_source_attach (remove_from_cache_source, + GLIB_PRIVATE_CALL (g_get_worker_context) ()); + g_source_unref (remove_from_cache_source); + } + + result = table != NULL && g_hash_table_contains (table, basename); + + G_UNLOCK (hidden_cache); + + g_free (dirname); + + return result; +} +#endif /* !G_OS_WIN32 */ + +void +_g_local_file_info_get_nostat (GFileInfo *info, + const char *basename, + const char *path, + GFileAttributeMatcher *attribute_matcher) +{ + g_file_info_set_name (info, basename); + + if (_g_file_attribute_matcher_matches_id (attribute_matcher, + G_FILE_ATTRIBUTE_ID_STANDARD_DISPLAY_NAME)) + { + char *display_name = g_filename_display_basename (path); + + /* look for U+FFFD REPLACEMENT CHARACTER */ + if (strstr (display_name, "\357\277\275") != NULL) + { + char *p = display_name; + display_name = g_strconcat (display_name, _(" (invalid encoding)"), NULL); + g_free (p); + } + g_file_info_set_display_name (info, display_name); + g_free (display_name); + } + + if (_g_file_attribute_matcher_matches_id (attribute_matcher, + G_FILE_ATTRIBUTE_ID_STANDARD_EDIT_NAME)) + { + char *edit_name = g_filename_display_basename (path); + g_file_info_set_edit_name (info, edit_name); + g_free (edit_name); + } + + + if (_g_file_attribute_matcher_matches_id (attribute_matcher, + G_FILE_ATTRIBUTE_ID_STANDARD_COPY_NAME)) + { + char *copy_name = g_filename_to_utf8 (basename, -1, NULL, NULL, NULL); + if (copy_name) + _g_file_info_set_attribute_string_by_id (info, G_FILE_ATTRIBUTE_ID_STANDARD_COPY_NAME, copy_name); + g_free (copy_name); + } +} + +static const char * +get_icon_name (const char *path, + const char *content_type, + gboolean use_symbolic, + gboolean *with_fallbacks_out) +{ + const char *name = NULL; + gboolean with_fallbacks = TRUE; + + if (strcmp (path, g_get_home_dir ()) == 0) + { + name = use_symbolic ? "user-home-symbolic" : "user-home"; + with_fallbacks = FALSE; + } + else if (strcmp (path, g_get_user_special_dir (G_USER_DIRECTORY_DESKTOP)) == 0) + { + name = use_symbolic ? "user-desktop-symbolic" : "user-desktop"; + with_fallbacks = FALSE; + } + else if (g_strcmp0 (path, g_get_user_special_dir (G_USER_DIRECTORY_DOCUMENTS)) == 0) + { + name = use_symbolic ? "folder-documents-symbolic" : "folder-documents"; + } + else if (g_strcmp0 (path, g_get_user_special_dir (G_USER_DIRECTORY_DOWNLOAD)) == 0) + { + name = use_symbolic ? "folder-download-symbolic" : "folder-download"; + } + else if (g_strcmp0 (path, g_get_user_special_dir (G_USER_DIRECTORY_MUSIC)) == 0) + { + name = use_symbolic ? "folder-music-symbolic" : "folder-music"; + } + else if (g_strcmp0 (path, g_get_user_special_dir (G_USER_DIRECTORY_PICTURES)) == 0) + { + name = use_symbolic ? "folder-pictures-symbolic" : "folder-pictures"; + } + else if (g_strcmp0 (path, g_get_user_special_dir (G_USER_DIRECTORY_PUBLIC_SHARE)) == 0) + { + name = use_symbolic ? "folder-publicshare-symbolic" : "folder-publicshare"; + } + else if (g_strcmp0 (path, g_get_user_special_dir (G_USER_DIRECTORY_TEMPLATES)) == 0) + { + name = use_symbolic ? "folder-templates-symbolic" : "folder-templates"; + } + else if (g_strcmp0 (path, g_get_user_special_dir (G_USER_DIRECTORY_VIDEOS)) == 0) + { + name = use_symbolic ? "folder-videos-symbolic" : "folder-videos"; + } + else if (g_strcmp0 (content_type, "inode/directory") == 0) + { + name = use_symbolic ? "folder-symbolic" : "folder"; + } + else + { + name = NULL; + } + + if (with_fallbacks_out != NULL) + *with_fallbacks_out = with_fallbacks; + + return name; +} + +static GIcon * +get_icon (const char *path, + const char *content_type, + gboolean use_symbolic) +{ + GIcon *icon = NULL; + const char *icon_name; + gboolean with_fallbacks; + + icon_name = get_icon_name (path, content_type, use_symbolic, &with_fallbacks); + if (icon_name != NULL) + { + if (with_fallbacks) + icon = g_themed_icon_new_with_default_fallbacks (icon_name); + else + icon = g_themed_icon_new (icon_name); + } + else + { + if (use_symbolic) + icon = g_content_type_get_symbolic_icon (content_type); + else + icon = g_content_type_get_icon (content_type); + } + + return icon; +} + GFileInfo * _g_local_file_info_get (const char *basename, const char *path, @@ -1413,21 +1683,28 @@ _g_local_file_info_get (const char *basename, struct stat statbuf2; #endif int res; + gboolean stat_ok; gboolean is_symlink, symlink_broken; #ifdef G_OS_WIN32 DWORD dos_attributes; #endif + char *symlink_target; + GVfs *vfs; + GVfsClass *class; + guint64 device; info = g_file_info_new (); /* Make sure we don't set any unwanted attributes */ g_file_info_set_attribute_mask (info, attribute_matcher); - g_file_info_set_name (info, basename); + _g_local_file_info_get_nostat (info, basename, path, attribute_matcher); - /* Avoid stat in trivial case */ if (attribute_matcher == NULL) - return info; + { + g_file_info_unset_attribute_mask (info); + return info; + } #ifndef G_OS_WIN32 res = g_lstat (path, &statbuf); @@ -1459,18 +1736,31 @@ _g_local_file_info_get (const char *basename, if (res == -1) { int errsv = errno; - char *display_name = g_filename_display_name (path); - g_object_unref (info); - g_set_error (error, G_IO_ERROR, - g_io_error_from_errno (errsv), - _("Error stating file '%s': %s"), - display_name, g_strerror (errsv)); - g_free (display_name); - return NULL; + + /* Don't bail out if we get Permission denied (SELinux?) */ + if (errsv != EACCES) + { + char *display_name = g_filename_display_name (path); + g_object_unref (info); + g_set_error (error, G_IO_ERROR, + g_io_error_from_errno (errsv), + _("Error when getting information for file '%s': %s"), + display_name, g_strerror (errsv)); + g_free (display_name); + return NULL; + } } - + + /* Even if stat() fails, try to get as much as other attributes possible */ + stat_ok = res != -1; + + if (stat_ok) + device = statbuf.st_dev; + else + device = 0; + #ifdef S_ISLNK - is_symlink = S_ISLNK (statbuf.st_mode); + is_symlink = stat_ok && S_ISLNK (statbuf.st_mode); #else is_symlink = FALSE; #endif @@ -1485,185 +1775,168 @@ _g_local_file_info_get (const char *basename, { res = stat (path, &statbuf2); - /* Report broken links as symlinks */ + /* Report broken links as symlinks */ if (res != -1) - statbuf = statbuf2; + { + statbuf = statbuf2; + stat_ok = TRUE; + } else symlink_broken = TRUE; } } #endif - set_info_from_stat (info, &statbuf, attribute_matcher); - -#ifndef G_OS_WIN32 - if (basename != NULL && basename[0] == '.') + if (stat_ok) + set_info_from_stat (info, &statbuf, attribute_matcher); + +#ifdef G_OS_UNIX + if (stat_ok && _g_local_file_is_lost_found_dir (path, statbuf.st_dev)) g_file_info_set_is_hidden (info, TRUE); +#endif + +#ifndef G_OS_WIN32 + if (_g_file_attribute_matcher_matches_id (attribute_matcher, + G_FILE_ATTRIBUTE_ID_STANDARD_IS_HIDDEN)) + { + if (basename != NULL && + (basename[0] == '.' || + file_is_hidden (path, basename))) + g_file_info_set_is_hidden (info, TRUE); + } - if (basename != NULL && basename[strlen (basename) -1] == '~') - g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_STANDARD_IS_BACKUP, TRUE); + if (basename != NULL && basename[strlen (basename) -1] == '~' && + (stat_ok && S_ISREG (statbuf.st_mode))) + _g_file_info_set_attribute_boolean_by_id (info, G_FILE_ATTRIBUTE_ID_STANDARD_IS_BACKUP, TRUE); #else if (dos_attributes & FILE_ATTRIBUTE_HIDDEN) g_file_info_set_is_hidden (info, TRUE); if (dos_attributes & FILE_ATTRIBUTE_ARCHIVE) - g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_DOS_IS_ARCHIVE, TRUE); + _g_file_info_set_attribute_boolean_by_id (info, G_FILE_ATTRIBUTE_ID_DOS_IS_ARCHIVE, TRUE); if (dos_attributes & FILE_ATTRIBUTE_SYSTEM) - g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_DOS_IS_SYSTEM, TRUE); + _g_file_info_set_attribute_boolean_by_id (info, G_FILE_ATTRIBUTE_ID_DOS_IS_SYSTEM, TRUE); #endif + symlink_target = NULL; #ifdef S_ISLNK - if (is_symlink && - g_file_attribute_matcher_matches (attribute_matcher, - G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET)) + if (is_symlink) { - char *link = read_link (path); - g_file_info_set_symlink_target (info, link); - g_free (link); + symlink_target = read_link (path); + if (symlink_target && + _g_file_attribute_matcher_matches_id (attribute_matcher, + G_FILE_ATTRIBUTE_ID_STANDARD_SYMLINK_TARGET)) + g_file_info_set_symlink_target (info, symlink_target); } #endif - - if (g_file_attribute_matcher_matches (attribute_matcher, - G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME)) + if (_g_file_attribute_matcher_matches_id (attribute_matcher, + G_FILE_ATTRIBUTE_ID_STANDARD_CONTENT_TYPE) || + _g_file_attribute_matcher_matches_id (attribute_matcher, + G_FILE_ATTRIBUTE_ID_STANDARD_ICON) || + _g_file_attribute_matcher_matches_id (attribute_matcher, + G_FILE_ATTRIBUTE_ID_STANDARD_SYMBOLIC_ICON)) { - char *display_name = g_filename_display_basename (path); - - /* look for U+FFFD REPLACEMENT CHARACTER */ - if (strstr (display_name, "\357\277\275") != NULL) - { - char *p = display_name; - display_name = g_strconcat (display_name, _(" (invalid encoding)"), NULL); - g_free (p); - } - g_file_info_set_display_name (info, display_name); - g_free (display_name); - } - - if (g_file_attribute_matcher_matches (attribute_matcher, - G_FILE_ATTRIBUTE_STANDARD_EDIT_NAME)) - { - char *edit_name = g_filename_display_basename (path); - g_file_info_set_edit_name (info, edit_name); - g_free (edit_name); - } - - - if (g_file_attribute_matcher_matches (attribute_matcher, - G_FILE_ATTRIBUTE_STANDARD_COPY_NAME)) - { - char *copy_name = g_filename_to_utf8 (basename, -1, NULL, NULL, NULL); - if (copy_name) - g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_COPY_NAME, copy_name); - g_free (copy_name); - } - - if (g_file_attribute_matcher_matches (attribute_matcher, - G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE) || - g_file_attribute_matcher_matches (attribute_matcher, - G_FILE_ATTRIBUTE_STANDARD_ICON)) - { - char *content_type = get_content_type (basename, path, &statbuf, is_symlink, symlink_broken, flags, FALSE); + char *content_type = get_content_type (basename, path, stat_ok ? &statbuf : NULL, is_symlink, symlink_broken, flags, FALSE); if (content_type) { g_file_info_set_content_type (info, content_type); - if (g_file_attribute_matcher_matches (attribute_matcher, - G_FILE_ATTRIBUTE_STANDARD_ICON)) + if (_g_file_attribute_matcher_matches_id (attribute_matcher, + G_FILE_ATTRIBUTE_ID_STANDARD_ICON) + || _g_file_attribute_matcher_matches_id (attribute_matcher, + G_FILE_ATTRIBUTE_ID_STANDARD_SYMBOLIC_ICON)) { GIcon *icon; - if (strcmp (path, g_get_home_dir ()) == 0) - icon = g_themed_icon_new ("user-home"); - else if (strcmp (path, g_get_user_special_dir (G_USER_DIRECTORY_DESKTOP)) == 0) - icon = g_themed_icon_new ("user-desktop"); - else + /* non symbolic icon */ + icon = get_icon (path, content_type, FALSE); + if (icon != NULL) { - icon = g_content_type_get_icon (content_type); - if (G_IS_THEMED_ICON (icon)) - { - const char *type_icon = NULL; - - if (S_ISDIR (statbuf.st_mode)) - type_icon = "folder"; - if (type_icon) - g_themed_icon_append_name (G_THEMED_ICON (icon), type_icon); - } + g_file_info_set_icon (info, icon); + g_object_unref (icon); } + /* symbolic icon */ + icon = get_icon (path, content_type, TRUE); if (icon != NULL) { - g_file_info_set_icon (info, icon); + g_file_info_set_symbolic_icon (info, icon); g_object_unref (icon); } + } g_free (content_type); } } - if (g_file_attribute_matcher_matches (attribute_matcher, - G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE)) + if (_g_file_attribute_matcher_matches_id (attribute_matcher, + G_FILE_ATTRIBUTE_ID_STANDARD_FAST_CONTENT_TYPE)) { - char *content_type = get_content_type (basename, path, &statbuf, is_symlink, symlink_broken, flags, TRUE); + char *content_type = get_content_type (basename, path, stat_ok ? &statbuf : NULL, is_symlink, symlink_broken, flags, TRUE); if (content_type) { - g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE, content_type); + _g_file_info_set_attribute_string_by_id (info, G_FILE_ATTRIBUTE_ID_STANDARD_FAST_CONTENT_TYPE, content_type); g_free (content_type); } } - if (g_file_attribute_matcher_matches (attribute_matcher, - G_FILE_ATTRIBUTE_OWNER_USER)) + if (_g_file_attribute_matcher_matches_id (attribute_matcher, + G_FILE_ATTRIBUTE_ID_OWNER_USER)) { char *name = NULL; #ifdef G_OS_WIN32 win32_get_file_user_info (path, NULL, &name, NULL); #else - name = get_username_from_uid (statbuf.st_uid); + if (stat_ok) + name = get_username_from_uid (statbuf.st_uid); #endif if (name) - g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_OWNER_USER, name); + _g_file_info_set_attribute_string_by_id (info, G_FILE_ATTRIBUTE_ID_OWNER_USER, name); g_free (name); } - if (g_file_attribute_matcher_matches (attribute_matcher, - G_FILE_ATTRIBUTE_OWNER_USER_REAL)) + if (_g_file_attribute_matcher_matches_id (attribute_matcher, + G_FILE_ATTRIBUTE_ID_OWNER_USER_REAL)) { char *name = NULL; #ifdef G_OS_WIN32 win32_get_file_user_info (path, NULL, NULL, &name); #else - name = get_realname_from_uid (statbuf.st_uid); + if (stat_ok) + name = get_realname_from_uid (statbuf.st_uid); #endif if (name) - g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_OWNER_USER_REAL, name); + _g_file_info_set_attribute_string_by_id (info, G_FILE_ATTRIBUTE_ID_OWNER_USER_REAL, name); g_free (name); } - if (g_file_attribute_matcher_matches (attribute_matcher, - G_FILE_ATTRIBUTE_OWNER_GROUP)) + if (_g_file_attribute_matcher_matches_id (attribute_matcher, + G_FILE_ATTRIBUTE_ID_OWNER_GROUP)) { char *name = NULL; #ifdef G_OS_WIN32 win32_get_file_user_info (path, &name, NULL, NULL); #else - name = get_groupname_from_gid (statbuf.st_gid); + if (stat_ok) + name = get_groupname_from_gid (statbuf.st_gid); #endif if (name) - g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_OWNER_GROUP, name); + _g_file_info_set_attribute_string_by_id (info, G_FILE_ATTRIBUTE_ID_OWNER_GROUP, name); g_free (name); } - if (parent_info && parent_info->device != 0 && - g_file_attribute_matcher_matches (attribute_matcher, G_FILE_ATTRIBUTE_UNIX_IS_MOUNTPOINT) && + if (stat_ok && parent_info && parent_info->device != 0 && + _g_file_attribute_matcher_matches_id (attribute_matcher, G_FILE_ATTRIBUTE_ID_UNIX_IS_MOUNTPOINT) && statbuf.st_dev != parent_info->device) - g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_UNIX_IS_MOUNTPOINT, TRUE); + _g_file_info_set_attribute_boolean_by_id (info, G_FILE_ATTRIBUTE_ID_UNIX_IS_MOUNTPOINT, TRUE); - get_access_rights (attribute_matcher, info, path, &statbuf, parent_info); + if (stat_ok) + get_access_rights (attribute_matcher, info, path, &statbuf, parent_info); #ifdef HAVE_SELINUX get_selinux_context (path, info, attribute_matcher, (flags & G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS) == 0); @@ -1671,19 +1944,40 @@ _g_local_file_info_get (const char *basename, get_xattrs (path, TRUE, info, attribute_matcher, (flags & G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS) == 0); get_xattrs (path, FALSE, info, attribute_matcher, (flags & G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS) == 0); - if (g_file_attribute_matcher_matches (attribute_matcher, - G_FILE_ATTRIBUTE_THUMBNAIL_PATH)) - get_thumbnail_attributes (path, info); - + if (_g_file_attribute_matcher_matches_id (attribute_matcher, + G_FILE_ATTRIBUTE_ID_THUMBNAIL_PATH)) + { + if (stat_ok) + get_thumbnail_attributes (path, info, &statbuf); + else + get_thumbnail_attributes (path, info, NULL); + } + + vfs = g_vfs_get_default (); + class = G_VFS_GET_CLASS (vfs); + if (class->local_file_add_info) + { + class->local_file_add_info (vfs, + path, + device, + attribute_matcher, + info, + NULL, + &parent_info->extra_data, + &parent_info->free_extra_data); + } + g_file_info_unset_attribute_mask (info); + g_free (symlink_target); + return info; } GFileInfo * -_g_local_file_info_get_from_fd (int fd, - char *attributes, - GError **error) +_g_local_file_info_get_from_fd (int fd, + const char *attributes, + GError **error) { GLocalFileStat stat_buf; GFileAttributeMatcher *matcher; @@ -1701,7 +1995,7 @@ _g_local_file_info_get_from_fd (int fd, g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errsv), - _("Error stating file descriptor: %s"), + _("Error when getting information for file descriptor: %s"), g_strerror (errsv)); return NULL; } @@ -1716,13 +2010,13 @@ _g_local_file_info_get_from_fd (int fd, set_info_from_stat (info, &stat_buf, matcher); #ifdef HAVE_SELINUX - if (g_file_attribute_matcher_matches (matcher, G_FILE_ATTRIBUTE_SELINUX_CONTEXT) && + if (_g_file_attribute_matcher_matches_id (matcher, G_FILE_ATTRIBUTE_ID_SELINUX_CONTEXT) && is_selinux_enabled ()) { char *context; if (fgetfilecon_raw (fd, &context) >= 0) { - g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_SELINUX_CONTEXT, context); + _g_file_info_set_attribute_string_by_id (info, G_FILE_ATTRIBUTE_ID_SELINUX_CONTEXT, context); freecon (context); } } @@ -1814,15 +2108,40 @@ get_string (const GFileAttributeValue *value, static gboolean set_unix_mode (char *filename, + GFileQueryInfoFlags flags, const GFileAttributeValue *value, GError **error) { - guint32 val; + guint32 val = 0; + 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; @@ -1835,7 +2154,7 @@ set_unix_mode (char *filename, return TRUE; } -#ifdef HAVE_CHOWN +#ifdef G_OS_UNIX static gboolean set_unix_uid_gid (char *filename, const GFileAttributeValue *uid_value, @@ -1844,7 +2163,7 @@ set_unix_uid_gid (char *filename, GError **error) { int res; - guint32 val; + guint32 val = 0; uid_t uid; gid_t gid; @@ -1980,8 +2299,8 @@ set_mtime_atime (char *filename, GError **error) { int res; - guint64 val; - guint32 val_usec; + guint64 val = 0; + guint32 val_usec = 0; struct stat statbuf; gboolean got_stat = FALSE; struct timeval times[2] = { {0, 0}, {0, 0} }; @@ -2047,7 +2366,7 @@ set_mtime_atime (char *filename, g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errsv), - _("Error setting owner: %s"), + _("Error setting modification or access time: %s"), g_strerror (errsv)); return FALSE; } @@ -2111,13 +2430,15 @@ _g_local_file_info_set_attribute (char *filename, GError **error) { GFileAttributeValue value = { 0 }; + GVfsClass *class; + GVfs *vfs; _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 +#ifdef G_OS_UNIX else if (strcmp (attribute, G_FILE_ATTRIBUTE_UNIX_UID) == 0) return set_unix_uid_gid (filename, &value, NULL, flags, error); else if (strcmp (attribute, G_FILE_ATTRIBUTE_UNIX_GID) == 0) @@ -2151,7 +2472,36 @@ _g_local_file_info_set_attribute (char *filename, else if (strcmp (attribute, G_FILE_ATTRIBUTE_SELINUX_CONTEXT) == 0) return set_selinux_context (filename, &value, error); #endif - + + vfs = g_vfs_get_default (); + class = G_VFS_GET_CLASS (vfs); + if (class->local_file_set_attributes) + { + GFileInfo *info; + + info = g_file_info_new (); + g_file_info_set_attribute (info, + attribute, + type, + value_p); + if (!class->local_file_set_attributes (vfs, filename, + info, + flags, cancellable, + error)) + { + g_object_unref (info); + return FALSE; + } + + if (g_file_info_get_attribute_status (info, attribute) == G_FILE_ATTRIBUTE_STATUS_SET) + { + g_object_unref (info); + return TRUE; + } + + g_object_unref (info); + } + g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, _("Setting attribute %s not supported"), attribute); return FALSE; @@ -2165,16 +2515,16 @@ _g_local_file_info_set_attributes (char *filename, GError **error) { GFileAttributeValue *value; -#ifdef HAVE_CHOWN +#ifdef G_OS_UNIX GFileAttributeValue *uid, *gid; -#endif #ifdef HAVE_UTIMES GFileAttributeValue *mtime, *mtime_usec, *atime, *atime_usec; #endif -#if defined (HAVE_CHOWN) && defined (HAVE_UTIMES) GFileAttributeStatus status; #endif gboolean res; + GVfsClass *class; + GVfs *vfs; /* Handles setting multiple specified data in a single set, and takes care of ordering restrictions when setting attributes */ @@ -2199,7 +2549,7 @@ _g_local_file_info_set_attributes (char *filename, } #endif -#ifdef HAVE_CHOWN +#ifdef G_OS_UNIX /* Group uid and gid setting into one call * Change ownership before permissions, since ownership changes can change permissions (e.g. setuid) @@ -2228,7 +2578,7 @@ _g_local_file_info_set_attributes (char *filename, 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; @@ -2295,5 +2645,20 @@ _g_local_file_info_set_attributes (char *filename, } #endif + vfs = g_vfs_get_default (); + class = G_VFS_GET_CLASS (vfs); + if (class->local_file_set_attributes) + { + if (!class->local_file_set_attributes (vfs, filename, + info, + flags, cancellable, + error)) + { + res = FALSE; + /* Don't set error multiple times */ + error = NULL; + } + } + return res; }