* 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 <http://www.gnu.org/licenses/>.
*
* Author: Alexander Larsson <alexl@redhat.com>
*/
#include "config.h"
+#include <glib.h>
+
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
#include <fcntl.h>
#include <errno.h>
-#ifdef HAVE_GRP_H
+#ifdef G_OS_UNIX
#include <grp.h>
-#endif
-#ifdef HAVE_PWD_H
#include <pwd.h>
#endif
#ifdef HAVE_SELINUX
#include <gfileinfo-priv.h>
#include <gvfs.h>
-#include "glibintl.h"
+#ifdef G_OS_UNIX
+#include <unistd.h>
+#include "glib-unix.h"
+#include "glib-private.h"
+#endif
+
+#include "thumbnail-verify.h"
#ifdef G_OS_WIN32
#include <windows.h>
#include "glocalfileinfo.h"
#include "gioerror.h"
#include "gthemedicon.h"
-#include "gcontenttype.h"
#include "gcontenttypeprivate.h"
+#include "glibintl.h"
struct ThumbMD5Context {
g_free (escaped_attr);
get_one_xattr_from_fd (fd, info, gio_attr, attr);
+ g_free (gio_attr);
}
len = strlen (attr) + 1;
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)
*comma = 0;
data->real_name = convert_pwd_string_to_utf8 (gecos);
}
+#endif
}
/* Default fallbacks */
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);
}
+/* @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;
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_by_id (info, G_FILE_ATTRIBUTE_ID_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_by_id (info, G_FILE_ATTRIBUTE_ID_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
}
#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,
/* 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);
g_object_unref (info);
g_set_error (error, G_IO_ERROR,
g_io_error_from_errno (errsv),
- _("Error stating file '%s': %s"),
+ _("Error when getting information for file '%s': %s"),
display_name, g_strerror (errsv));
g_free (display_name);
return NULL;
if (stat_ok)
set_info_from_stat (info, &statbuf, attribute_matcher);
-#ifndef G_OS_WIN32
- if (basename != NULL && basename[0] == '.')
+#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] == '~' &&
(stat_ok && S_ISREG (statbuf.st_mode)))
}
#endif
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);
- }
-
- 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_ID_STANDARD_ICON) ||
+ _g_file_attribute_matcher_matches_id (attribute_matcher,
+ G_FILE_ATTRIBUTE_ID_STANDARD_SYMBOLIC_ICON))
{
char *content_type = get_content_type (basename, path, stat_ok ? &statbuf : NULL, is_symlink, symlink_broken, flags, FALSE);
g_file_info_set_content_type (info, content_type);
if (_g_file_attribute_matcher_matches_id (attribute_matcher,
- G_FILE_ATTRIBUTE_ID_STANDARD_ICON))
+ 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 if (g_strcmp0 (path, g_get_user_special_dir (G_USER_DIRECTORY_DOCUMENTS)) == 0)
- icon = g_themed_icon_new_with_default_fallbacks ("folder-documents");
- else if (g_strcmp0 (path, g_get_user_special_dir (G_USER_DIRECTORY_DOWNLOAD)) == 0)
- icon = g_themed_icon_new_with_default_fallbacks ("folder-download");
- else if (g_strcmp0 (path, g_get_user_special_dir (G_USER_DIRECTORY_MUSIC)) == 0)
- icon = g_themed_icon_new_with_default_fallbacks ("folder-music");
- else if (g_strcmp0 (path, g_get_user_special_dir (G_USER_DIRECTORY_PICTURES)) == 0)
- icon = g_themed_icon_new_with_default_fallbacks ("folder-pictures");
- else if (g_strcmp0 (path, g_get_user_special_dir (G_USER_DIRECTORY_PUBLIC_SHARE)) == 0)
- icon = g_themed_icon_new_with_default_fallbacks ("folder-publicshare");
- else if (g_strcmp0 (path, g_get_user_special_dir (G_USER_DIRECTORY_TEMPLATES)) == 0)
- icon = g_themed_icon_new_with_default_fallbacks ("folder-templates");
- else if (g_strcmp0 (path, g_get_user_special_dir (G_USER_DIRECTORY_VIDEOS)) == 0)
- icon = g_themed_icon_new_with_default_fallbacks ("folder-videos");
- 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_id (attribute_matcher,
G_FILE_ATTRIBUTE_ID_THUMBNAIL_PATH))
- get_thumbnail_attributes (path, info);
+ {
+ 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);
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;
}
return TRUE;
}
-#ifdef HAVE_CHOWN
+#ifdef G_OS_UNIX
static gboolean
set_unix_uid_gid (char *filename,
const GFileAttributeValue *uid_value,
if (strcmp (attribute, G_FILE_ATTRIBUTE_UNIX_MODE) == 0)
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)
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;
}
#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)