Commit 85110331 authored by Federico Mena Quintero's avatar Federico Mena Quintero Committed by Federico Mena Quintero
Browse files

Fix #162617.

2005-01-10  Federico Mena Quintero  <federico@ximian.com>

	Fix #162617.

	* gtk/gtkfilesystemunix.c (STAT_NEEDED_MASK): Take out
	GTK_FILE_INFO_IS_HIDDEN; we don't need to stat() to know this.
	(gtk_file_system_unix_get_folder): Make error reporting more
	accurate.  Don't bail out if we can't read the directory.
	(fill_in_stats): Don't return an error; just assume we don't have
	stat info for this folder's files.
	(fill_in_names): Don't create the hash table for the names if we
	can't open the directory.
	(gtk_file_folder_unix_list_children): Don't emit the
	"finished-loading" signal --- we don't do asynchronous loads, so
	we are always finished loading.
	(gtk_file_folder_unix_get_info): Use helper functions; handle the
	case where we can't stat '/'.
	(get_icon_type_from_path): Don't call fill_in_stats() here; only
	use the info we have.
	(fill_in_mime_type): Don't return an error.  Don't do anything if
	we don't have the stat info.
parent fe100e48
2005-01-10 Federico Mena Quintero <federico@ximian.com>
Fix #162617.
* gtk/gtkfilesystemunix.c (STAT_NEEDED_MASK): Take out
GTK_FILE_INFO_IS_HIDDEN; we don't need to stat() to know this.
(gtk_file_system_unix_get_folder): Make error reporting more
accurate. Don't bail out if we can't read the directory.
(fill_in_stats): Don't return an error; just assume we don't have
stat info for this folder's files.
(fill_in_names): Don't create the hash table for the names if we
can't open the directory.
(gtk_file_folder_unix_list_children): Don't emit the
"finished-loading" signal --- we don't do asynchronous loads, so
we are always finished loading.
(gtk_file_folder_unix_get_info): Use helper functions; handle the
case where we can't stat '/'.
(get_icon_type_from_path): Don't call fill_in_stats() here; only
use the info we have.
(fill_in_mime_type): Don't return an error. Don't do anything if
we don't have the stat info.
2005-01-10 Owen Taylor <otaylor@redhat.com>
* Makefile.am (EXTRA_DIST): Adding missing ChangeLog.pre*
......
2005-01-10 Federico Mena Quintero <federico@ximian.com>
Fix #162617.
* gtk/gtkfilesystemunix.c (STAT_NEEDED_MASK): Take out
GTK_FILE_INFO_IS_HIDDEN; we don't need to stat() to know this.
(gtk_file_system_unix_get_folder): Make error reporting more
accurate. Don't bail out if we can't read the directory.
(fill_in_stats): Don't return an error; just assume we don't have
stat info for this folder's files.
(fill_in_names): Don't create the hash table for the names if we
can't open the directory.
(gtk_file_folder_unix_list_children): Don't emit the
"finished-loading" signal --- we don't do asynchronous loads, so
we are always finished loading.
(gtk_file_folder_unix_get_info): Use helper functions; handle the
case where we can't stat '/'.
(get_icon_type_from_path): Don't call fill_in_stats() here; only
use the info we have.
(fill_in_mime_type): Don't return an error. Don't do anything if
we don't have the stat info.
2005-01-10 Owen Taylor <otaylor@redhat.com>
* Makefile.am (EXTRA_DIST): Adding missing ChangeLog.pre*
......
2005-01-10 Federico Mena Quintero <federico@ximian.com>
Fix #162617.
* gtk/gtkfilesystemunix.c (STAT_NEEDED_MASK): Take out
GTK_FILE_INFO_IS_HIDDEN; we don't need to stat() to know this.
(gtk_file_system_unix_get_folder): Make error reporting more
accurate. Don't bail out if we can't read the directory.
(fill_in_stats): Don't return an error; just assume we don't have
stat info for this folder's files.
(fill_in_names): Don't create the hash table for the names if we
can't open the directory.
(gtk_file_folder_unix_list_children): Don't emit the
"finished-loading" signal --- we don't do asynchronous loads, so
we are always finished loading.
(gtk_file_folder_unix_get_info): Use helper functions; handle the
case where we can't stat '/'.
(get_icon_type_from_path): Don't call fill_in_stats() here; only
use the info we have.
(fill_in_mime_type): Don't return an error. Don't do anything if
we don't have the stat info.
2005-01-10 Owen Taylor <otaylor@redhat.com>
* Makefile.am (EXTRA_DIST): Adding missing ChangeLog.pre*
......
......@@ -115,7 +115,6 @@ struct stat_info_entry {
};
static const GtkFileInfoType STAT_NEEDED_MASK = (GTK_FILE_INFO_IS_FOLDER |
GTK_FILE_INFO_IS_HIDDEN |
GTK_FILE_INFO_MODIFICATION_TIME |
GTK_FILE_INFO_SIZE);
......@@ -215,8 +214,8 @@ static GtkFilePath *filename_to_path (const gchar *filename);
static gboolean filename_is_root (const char *filename);
static gboolean fill_in_names (GtkFileFolderUnix *folder_unix, GError **error);
static gboolean fill_in_stats (GtkFileFolderUnix *folder_unix, GError **error);
static gboolean fill_in_mime_type (GtkFileFolderUnix *folder_unix, GError **error);
static void fill_in_stats (GtkFileFolderUnix *folder_unix);
static void fill_in_mime_type (GtkFileFolderUnix *folder_unix);
static char * get_parent_dir (const char *filename);
......@@ -406,29 +405,41 @@ gtk_file_system_unix_get_folder (GtkFileSystem *file_system,
}
else
{
if (!g_file_test (filename, G_FILE_TEST_EXISTS))
struct stat statbuf;
int result;
int code;
int my_errno;
result = stat (filename, &statbuf);
if (result == 0)
{
gchar *display_name = g_filename_display_name (filename);
g_set_error (error,
GTK_FILE_SYSTEM_ERROR,
GTK_FILE_SYSTEM_ERROR_NONEXISTENT,
_("Error getting information for '%s': %s"),
display_name,
g_strerror (ENOENT));
if (!S_ISDIR (statbuf.st_mode))
{
result = -1;
code = GTK_FILE_SYSTEM_ERROR_NOT_FOLDER;
my_errno = ENOTDIR;
}
}
else
{
my_errno = errno;
g_free (display_name);
g_free (filename_copy);
return NULL;
if (my_errno == ENOENT)
code = GTK_FILE_SYSTEM_ERROR_NONEXISTENT;
else
code = GTK_FILE_SYSTEM_ERROR_FAILED;
}
else if (!g_file_test (filename, G_FILE_TEST_IS_DIR))
if (result != 0)
{
gchar *display_name = g_filename_display_name (filename);
g_set_error (error,
GTK_FILE_SYSTEM_ERROR,
GTK_FILE_SYSTEM_ERROR_NOT_FOLDER,
code,
_("Error getting information for '%s': %s"),
display_name,
g_strerror (ENOTDIR));
g_strerror (my_errno));
g_free (display_name);
g_free (filename_copy);
......@@ -449,16 +460,11 @@ gtk_file_system_unix_get_folder (GtkFileSystem *file_system,
folder_unix);
}
if ((types & STAT_NEEDED_MASK) && !fill_in_stats (folder_unix, error))
{
g_object_unref (folder_unix);
return NULL;
}
if ((types & GTK_FILE_INFO_MIME_TYPE) && !fill_in_mime_type (folder_unix, error))
{
g_object_unref (folder_unix);
return NULL;
}
if ((types & STAT_NEEDED_MASK) != 0)
fill_in_stats (folder_unix);
if ((types & GTK_FILE_INFO_MIME_TYPE) != 0)
fill_in_mime_type (folder_unix);
return GTK_FILE_FOLDER (folder_unix);
}
......@@ -1138,13 +1144,12 @@ get_icon_type_from_path (GtkFileSystemUnix *system_unix,
*mime_type = NULL;
if (folder_unix)
if (folder_unix && folder_unix->have_stat)
{
char *basename;
struct stat_info_entry *entry;
if (!fill_in_stats (folder_unix, NULL))
return ICON_NONE;
g_assert (folder_unix->stat_info != NULL);
basename = g_path_get_basename (filename);
entry = g_hash_table_lookup (folder_unix->stat_info, basename);
......@@ -1159,20 +1164,18 @@ get_icon_type_from_path (GtkFileSystemUnix *system_unix,
icon_type = entry->icon_type;
if (icon_type == ICON_REGULAR)
{
(void)fill_in_mime_type (folder_unix, NULL);
fill_in_mime_type (folder_unix);
*mime_type = entry->mime_type;
}
return icon_type;
}
else
icon_type = ICON_NONE;
}
else
{
icon_type = get_icon_type (filename, NULL);
if (icon_type == ICON_REGULAR)
*mime_type = xdg_mime_get_mime_type_for_file (filename);
}
icon_type = get_icon_type (filename, NULL);
if (icon_type == ICON_REGULAR)
*mime_type = xdg_mime_get_mime_type_for_file (filename);
return icon_type;
}
......@@ -1677,78 +1680,89 @@ gtk_file_folder_unix_finalize (GObject *object)
folder_parent_class->finalize (object);
}
/* Creates a GtkFileInfo for "/" by stat()ing it */
static GtkFileInfo *
gtk_file_folder_unix_get_info (GtkFileFolder *folder,
const GtkFilePath *path,
GError **error)
file_info_for_root_with_error (const char *root_name,
GError **error)
{
GtkFileFolderUnix *folder_unix = GTK_FILE_FOLDER_UNIX (folder);
struct stat statbuf;
GtkFileInfo *info;
gchar *dirname, *basename;
const char *filename;
struct stat_info_entry *entry;
gboolean file_must_exist;
GtkFileInfoType types;
if (!path)
if (stat (root_name, &statbuf) != 0)
{
struct stat buf;
int saved_errno;
g_return_val_if_fail (filename_is_root (folder_unix->filename), NULL);
saved_errno = errno;
g_set_error (error,
GTK_FILE_SYSTEM_ERROR,
GTK_FILE_SYSTEM_ERROR_FAILED,
_("Error getting information for '/': %s"),
g_strerror (saved_errno));
if (stat (folder_unix->filename, &buf) != 0)
return NULL;
return NULL;
}
info = gtk_file_info_new ();
gtk_file_info_set_display_name (info, "/");
gtk_file_info_set_is_folder (info, TRUE);
gtk_file_info_set_is_hidden (info, FALSE);
gtk_file_info_set_mime_type (info, "x-directory/normal");
gtk_file_info_set_modification_time (info, buf.st_mtime);
gtk_file_info_set_size (info, buf.st_size);
info = gtk_file_info_new ();
gtk_file_info_set_display_name (info, "/");
gtk_file_info_set_is_folder (info, TRUE);
gtk_file_info_set_is_hidden (info, FALSE);
gtk_file_info_set_mime_type (info, "x-directory/normal");
gtk_file_info_set_modification_time (info, statbuf.st_mtime);
gtk_file_info_set_size (info, statbuf.st_size);
return info;
}
return info;
}
filename = gtk_file_path_get_string (path);
g_return_val_if_fail (filename != NULL, NULL);
g_return_val_if_fail (g_path_is_absolute (filename), NULL);
static gboolean
stat_with_error (const char *filename,
struct stat *statbuf,
GError **error)
{
if (stat (filename, statbuf) == -1 &&
(errno != ENOENT || lstat (filename, statbuf) == -1))
{
int saved_errno;
int code;
char *display_name;
dirname = get_parent_dir (filename);
g_return_val_if_fail (strcmp (dirname, folder_unix->filename) == 0, NULL);
g_free (dirname);
saved_errno = errno;
basename = g_path_get_basename (filename);
types = folder_unix->types;
file_must_exist = (types & ~GTK_FILE_INFO_DISPLAY_NAME) != 0;
entry = file_must_exist
? g_hash_table_lookup (folder_unix->stat_info, basename)
: NULL;
/* basename freed later. */
if (saved_errno == ENOENT)
code = GTK_FILE_SYSTEM_ERROR_NONEXISTENT;
else
code = GTK_FILE_SYSTEM_ERROR_FAILED;
if (!file_must_exist || entry)
{
info = gtk_file_info_new ();
}
else
{
gchar *display_name = g_filename_display_name (filename);
display_name = g_filename_display_name (filename);
g_set_error (error,
GTK_FILE_SYSTEM_ERROR,
GTK_FILE_SYSTEM_ERROR_NONEXISTENT,
_("Error getting information for '%s'"),
display_name);
code,
_("Error getting information for '%s': %s"),
display_name,
g_strerror (saved_errno));
g_free (display_name);
info = NULL;
types = 0;
return FALSE;
}
return TRUE;
}
/* Creates a new GtkFileInfo from the specified data */
static GtkFileInfo *
create_file_info (const char *filename,
const char *basename,
GtkFileInfoType types,
struct stat *statbuf,
const char *mime_type)
{
GtkFileInfo *info;
info = gtk_file_info_new ();
if (types & GTK_FILE_INFO_DISPLAY_NAME)
{
gchar *display_name = g_filename_display_basename (filename);
gtk_file_info_set_display_name (info, display_name);
g_free (display_name);
}
......@@ -1756,22 +1770,125 @@ gtk_file_folder_unix_get_info (GtkFileFolder *folder,
gtk_file_info_set_is_hidden (info, basename[0] == '.');
if (types & GTK_FILE_INFO_IS_FOLDER)
gtk_file_info_set_is_folder (info, S_ISDIR (entry->statbuf.st_mode));
gtk_file_info_set_is_folder (info, S_ISDIR (statbuf->st_mode));
if (types & GTK_FILE_INFO_MIME_TYPE)
gtk_file_info_set_mime_type (info, entry->mime_type);
gtk_file_info_set_mime_type (info, mime_type);
if (types & GTK_FILE_INFO_MODIFICATION_TIME)
gtk_file_info_set_modification_time (info, entry->statbuf.st_mtime);
gtk_file_info_set_modification_time (info, statbuf->st_mtime);
if (types & GTK_FILE_INFO_SIZE)
gtk_file_info_set_size (info, (gint64)entry->statbuf.st_size);
g_free (basename);
gtk_file_info_set_size (info, (gint64) statbuf->st_size);
return info;
}
static struct stat_info_entry *
create_stat_info_entry_and_emit_add (GtkFileFolderUnix *folder_unix,
const char *filename,
const char *basename,
struct stat *statbuf)
{
GSList *paths;
GtkFilePath *path;
struct stat_info_entry *entry;
entry = g_new0 (struct stat_info_entry, 1);
if ((folder_unix->types & STAT_NEEDED_MASK) != 0)
entry->statbuf = *statbuf;
if ((folder_unix->types & GTK_FILE_INFO_MIME_TYPE) != 0)
entry->mime_type = g_strdup (xdg_mime_get_mime_type_for_file (filename));
g_hash_table_insert (folder_unix->stat_info,
g_strdup (basename),
entry);
path = gtk_file_path_new_dup (filename);
paths = g_slist_append (NULL, path);
g_signal_emit_by_name (folder_unix, "files-added", paths);
gtk_file_path_free (path);
g_slist_free (paths);
return entry;
}
static GtkFileInfo *
gtk_file_folder_unix_get_info (GtkFileFolder *folder,
const GtkFilePath *path,
GError **error)
{
GtkFileFolderUnix *folder_unix = GTK_FILE_FOLDER_UNIX (folder);
GtkFileInfo *info;
gchar *dirname, *basename;
const char *filename;
GtkFileInfoType types;
struct stat statbuf;
const char *mime_type;
/* Get_info for "/" */
if (!path)
{
g_return_val_if_fail (filename_is_root (folder_unix->filename), NULL);
return file_info_for_root_with_error (folder_unix->filename, error);
}
/* Get_info for normal files */
filename = gtk_file_path_get_string (path);
g_return_val_if_fail (filename != NULL, NULL);
g_return_val_if_fail (g_path_is_absolute (filename), NULL);
dirname = get_parent_dir (filename);
g_return_val_if_fail (strcmp (dirname, folder_unix->filename) == 0, NULL);
g_free (dirname);
basename = g_path_get_basename (filename);
types = folder_unix->types;
if (folder_unix->have_stat)
{
struct stat_info_entry *entry;
g_assert (folder_unix->stat_info != NULL);
entry = g_hash_table_lookup (folder_unix->stat_info, basename);
if (!entry)
{
if (!stat_with_error (filename, &statbuf, error))
{
g_free (basename);
return NULL;
}
entry = create_stat_info_entry_and_emit_add (folder_unix, filename, basename, &statbuf);
}
info = create_file_info (filename, basename, types, &entry->statbuf, entry->mime_type);
g_free (basename);
return info;
}
else
{
if (!stat_with_error (filename, &statbuf, error))
{
g_free (basename);
return NULL;
}
if ((types & GTK_FILE_INFO_MIME_TYPE) != 0)
mime_type = xdg_mime_get_mime_type_for_file (filename);
else
mime_type = NULL;
info = create_file_info (filename, basename, types, &statbuf, mime_type);
g_free (basename);
return info;
}
}
static void
cb_list_children (gpointer key, gpointer value, gpointer user_data)
......@@ -1804,7 +1921,6 @@ gtk_file_folder_unix_list_children (GtkFileFolder *folder,
l->data = filename_to_path (fullname);
g_free (fullname);
}
g_signal_emit_by_name (folder_unix, "finished-loading");
return TRUE;
}
......@@ -1831,17 +1947,14 @@ fill_in_names (GtkFileFolderUnix *folder_unix, GError **error)
if (folder_unix->stat_info)
return TRUE;
#if 0
g_print ("Reading directory %s\n", folder_unix->filename);
#endif
folder_unix->stat_info = g_hash_table_new_full (g_str_hash, g_str_equal,
(GDestroyNotify)g_free,
(GDestroyNotify)free_stat_info_entry);
dir = g_dir_open (folder_unix->filename, 0, error);
if (!dir)
return FALSE;
folder_unix->stat_info = g_hash_table_new_full (g_str_hash, g_str_equal,
(GDestroyNotify) g_free,
(GDestroyNotify) free_stat_info_entry);
while (TRUE)
{
const gchar *basename = g_dir_read_name (dir);
......@@ -1879,24 +1992,20 @@ cb_fill_in_stats (gpointer key, gpointer value, gpointer user_data)
}
static gboolean
fill_in_stats (GtkFileFolderUnix *folder_unix, GError **error)
static void
fill_in_stats (GtkFileFolderUnix *folder_unix)
{
if (folder_unix->have_stat)
return TRUE;
return;
if (!fill_in_names (folder_unix, error))
return FALSE;
if (!fill_in_names (folder_unix, NULL))
return;
#if 0
g_print ("Stating directory %s\n", folder_unix->filename);
#endif
g_hash_table_foreach_remove (folder_unix->stat_info,
cb_fill_in_stats,
folder_unix);
folder_unix->have_stat = TRUE;
return TRUE;
}
......@@ -1917,21 +2026,22 @@ cb_fill_in_mime_type (gpointer key, gpointer value, gpointer user_data)
return FALSE;
}
static gboolean
fill_in_mime_type (GtkFileFolderUnix *folder_unix, GError **error)
static void
fill_in_mime_type (GtkFileFolderUnix *folder_unix)
{
if (folder_unix->have_mime_type)
return TRUE;
return;
if (!folder_unix->have_stat)
return;
g_assert (folder_unix->stat_info != NULL);
#if 0
g_print ("Getting mime types for directory %s\n", folder_unix->filename);
#endif
g_hash_table_foreach_remove (folder_unix->stat_info,
cb_fill_in_mime_type,
folder_unix);
folder_unix->have_mime_type = TRUE;
return TRUE;
}
static GtkFilePath *
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment