1 /* GTK - The GIMP Toolkit
2 * gtkfilesystemunix.c: Default implementation of GtkFileSystem for UNIX-like systems
3 * Copyright (C) 2003, Red Hat, Inc.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
21 #include "gtkfilesystem.h"
22 #include "gtkfilesystemunix.h"
27 #include <sys/types.h>
30 typedef struct _GtkFileSystemUnixClass GtkFileSystemUnixClass;
32 #define GTK_FILE_SYSTEM_UNIX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_FILE_SYSTEM_UNIX, GtkFileSystemUnixClass))
33 #define GTK_IS_FILE_SYSTEM_UNIX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_FILE_SYSTEM_UNIX))
34 #define GTK_FILE_SYSTEM_UNIX_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_FILE_SYSTEM_UNIX, GtkFileSystemUnixClass))
36 struct _GtkFileSystemUnixClass
38 GObjectClass parent_class;
41 struct _GtkFileSystemUnix
43 GObject parent_instance;
46 #define GTK_TYPE_FILE_FOLDER_UNIX (gtk_file_folder_unix_get_type ())
47 #define GTK_FILE_FOLDER_UNIX(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_FILE_FOLDER_UNIX, GtkFileFolderUnix))
48 #define GTK_IS_FILE_FOLDER_UNIX(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_FILE_FOLDER_UNIX))
49 #define GTK_FILE_FOLDER_UNIX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_FILE_FOLDER_UNIX, GtkFileFolderUnixClass))
50 #define GTK_IS_FILE_FOLDER_UNIX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_FILE_FOLDER_UNIX))
51 #define GTK_FILE_FOLDER_UNIX_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_FILE_FOLDER_UNIX, GtkFileFolderUnixClass))
53 typedef struct _GtkFileFolderUnix GtkFileFolderUnix;
54 typedef struct _GtkFileFolderUnixClass GtkFileFolderUnixClass;
56 struct _GtkFileFolderUnixClass
58 GObjectClass parent_class;
61 struct _GtkFileFolderUnix
63 GObject parent_instance;
65 GtkFileInfoType types;
69 static void gtk_file_system_unix_class_init (GtkFileSystemUnixClass *class);
70 static void gtk_file_system_unix_iface_init (GtkFileSystemIface *iface);
71 static void gtk_file_system_unix_init (GtkFileSystemUnix *impl);
72 static void gtk_file_system_unix_finalize (GObject *object);
74 static GSList * gtk_file_system_unix_list_roots (GtkFileSystem *file_system);
75 static GtkFileInfo * gtk_file_system_unix_get_root_info (GtkFileSystem *file_system,
77 GtkFileInfoType types,
79 static GtkFileFolder *gtk_file_system_unix_get_folder (GtkFileSystem *file_system,
81 GtkFileInfoType types,
83 static gboolean gtk_file_system_unix_create_folder (GtkFileSystem *file_system,
86 static gboolean gtk_file_system_unix_get_parent (GtkFileSystem *file_system,
90 static gchar * gtk_file_system_unix_make_uri (GtkFileSystem *file_system,
91 const gchar *base_uri,
92 const gchar *display_name,
95 static GType gtk_file_folder_unix_get_type (void);
96 static void gtk_file_folder_unix_class_init (GtkFileFolderUnixClass *class);
97 static void gtk_file_folder_unix_iface_init (GtkFileFolderIface *iface);
98 static void gtk_file_folder_unix_init (GtkFileFolderUnix *impl);
99 static void gtk_file_folder_unix_finalize (GObject *object);
101 static GtkFileInfo *gtk_file_folder_unix_get_info (GtkFileFolder *folder,
104 static gboolean gtk_file_folder_unix_list_children (GtkFileFolder *folder,
108 static gchar * filename_from_uri (const gchar *filename,
110 static gchar * filename_to_uri (const gchar *filename);
111 static gboolean filename_is_root (const char *filename);
112 static GtkFileInfo *filename_get_info (const gchar *filename,
113 GtkFileInfoType types,
120 _gtk_file_system_unix_get_type (void)
122 static GType file_system_unix_type = 0;
124 if (!file_system_unix_type)
126 static const GTypeInfo file_system_unix_info =
128 sizeof (GtkFileSystemUnixClass),
129 NULL, /* base_init */
130 NULL, /* base_finalize */
131 (GClassInitFunc) gtk_file_system_unix_class_init,
132 NULL, /* class_finalize */
133 NULL, /* class_data */
134 sizeof (GtkFileSystemUnix),
136 (GInstanceInitFunc) gtk_file_system_unix_init,
139 static const GInterfaceInfo file_system_info =
141 (GInterfaceInitFunc) gtk_file_system_unix_iface_init, /* interface_init */
142 NULL, /* interface_finalize */
143 NULL /* interface_data */
146 file_system_unix_type = g_type_register_static (G_TYPE_OBJECT,
148 &file_system_unix_info, 0);
149 g_type_add_interface_static (file_system_unix_type,
150 GTK_TYPE_FILE_SYSTEM,
154 return file_system_unix_type;
158 * _gtk_file_system_unix_new:
160 * Creates a new #GtkFileSystemUnix object. #GtkFileSystemUnix
161 * implements the #GtkFileSystem interface with direct access to
162 * the filesystem using Unix/Linux API calls
164 * Return value: the new #GtkFileSystemUnix object
167 _gtk_file_system_unix_new (void)
169 return g_object_new (GTK_TYPE_FILE_SYSTEM_UNIX, NULL);
173 gtk_file_system_unix_class_init (GtkFileSystemUnixClass *class)
175 GObjectClass *gobject_class = G_OBJECT_CLASS (class);
177 gobject_class->finalize = gtk_file_system_unix_finalize;
181 gtk_file_system_unix_iface_init (GtkFileSystemIface *iface)
183 iface->list_roots = gtk_file_system_unix_list_roots;
184 iface->get_folder = gtk_file_system_unix_get_folder;
185 iface->get_root_info = gtk_file_system_unix_get_root_info;
186 iface->create_folder = gtk_file_system_unix_create_folder;
187 iface->get_parent = gtk_file_system_unix_get_parent;
188 iface->make_uri = gtk_file_system_unix_make_uri;
192 gtk_file_system_unix_init (GtkFileSystemUnix *system_unix)
197 gtk_file_system_unix_finalize (GObject *object)
202 gtk_file_system_unix_list_roots (GtkFileSystem *file_system)
204 return g_slist_append (NULL, g_strdup ("file:///"));
208 gtk_file_system_unix_get_root_info (GtkFileSystem *file_system,
210 GtkFileInfoType types,
213 g_return_val_if_fail (strcmp (uri, "file:///") == 0, NULL);
215 return filename_get_info ("/", types, error);
218 static GtkFileFolder *
219 gtk_file_system_unix_get_folder (GtkFileSystem *file_system,
221 GtkFileInfoType types,
224 GtkFileFolderUnix *folder_unix;
227 filename = filename_from_uri (uri, error);
231 folder_unix = g_object_new (GTK_TYPE_FILE_FOLDER_UNIX, NULL);
232 folder_unix->filename = filename;
233 folder_unix->types = types;
235 return GTK_FILE_FOLDER (folder_unix);
239 gtk_file_system_unix_create_folder (GtkFileSystem *file_system,
246 filename = filename_from_uri (uri, error);
250 result = mkdir (filename, 0777) != 0;
254 gchar *filename_utf8 = g_filename_to_utf8 (filename, -1, NULL, NULL, NULL);
256 GTK_FILE_SYSTEM_ERROR,
257 GTK_FILE_SYSTEM_ERROR_NONEXISTANT,
258 "error creating directory '%s': %s",
259 filename_utf8 ? filename_utf8 : "???",
261 g_free (filename_utf8);
270 gtk_file_system_unix_get_parent (GtkFileSystem *file_system,
275 gchar *filename = filename_from_uri (uri, error);
280 if (filename_is_root (filename))
286 gchar *parent_filename = g_path_get_dirname (filename);
287 *parent = filename_to_uri (parent_filename);
288 g_free (parent_filename);
297 gtk_file_system_unix_make_uri (GtkFileSystem *file_system,
298 const gchar *base_uri,
299 const gchar *display_name,
302 gchar *base_filename;
304 gchar *full_filename;
305 GError *tmp_error = NULL;
308 base_filename = filename_from_uri (base_uri, error);
312 filename = g_filename_from_utf8 (display_name, -1, NULL, NULL, &tmp_error);
316 GTK_FILE_SYSTEM_ERROR,
317 GTK_FILE_SYSTEM_ERROR_BAD_FILENAME,
321 g_error_free (tmp_error);
322 g_free (base_filename);
327 full_filename = g_build_filename (base_filename, filename, NULL);
328 result = filename_to_uri (full_filename);
329 g_free (base_filename);
331 g_free (full_filename);
340 gtk_file_folder_unix_get_type (void)
342 static GType file_folder_unix_type = 0;
344 if (!file_folder_unix_type)
346 static const GTypeInfo file_folder_unix_info =
348 sizeof (GtkFileFolderUnixClass),
349 NULL, /* base_init */
350 NULL, /* base_finalize */
351 (GClassInitFunc) gtk_file_folder_unix_class_init,
352 NULL, /* class_finalize */
353 NULL, /* class_data */
354 sizeof (GtkFileFolderUnix),
356 (GInstanceInitFunc) gtk_file_folder_unix_init,
359 static const GInterfaceInfo file_folder_info =
361 (GInterfaceInitFunc) gtk_file_folder_unix_iface_init, /* interface_init */
362 NULL, /* interface_finalize */
363 NULL /* interface_data */
366 file_folder_unix_type = g_type_register_static (G_TYPE_OBJECT,
368 &file_folder_unix_info, 0);
369 g_type_add_interface_static (file_folder_unix_type,
370 GTK_TYPE_FILE_FOLDER,
374 return file_folder_unix_type;
378 gtk_file_folder_unix_class_init (GtkFileFolderUnixClass *class)
380 GObjectClass *gobject_class = G_OBJECT_CLASS (class);
382 gobject_class->finalize = gtk_file_folder_unix_finalize;
386 gtk_file_folder_unix_iface_init (GtkFileFolderIface *iface)
388 iface->get_info = gtk_file_folder_unix_get_info;
389 iface->list_children = gtk_file_folder_unix_list_children;
393 gtk_file_folder_unix_init (GtkFileFolderUnix *impl)
398 gtk_file_folder_unix_finalize (GObject *object)
400 GtkFileFolderUnix *folder_unix = GTK_FILE_FOLDER_UNIX (object);
402 g_free (folder_unix->filename);
406 gtk_file_folder_unix_get_info (GtkFileFolder *folder,
410 GtkFileFolderUnix *folder_unix = GTK_FILE_FOLDER_UNIX (folder);
415 filename = filename_from_uri (uri, error);
419 dirname = g_path_get_dirname (filename);
420 g_return_val_if_fail (strcmp (dirname, folder_unix->filename) == 0, NULL);
423 info = filename_get_info (filename, folder_unix->types, error);
431 gtk_file_folder_unix_list_children (GtkFileFolder *folder,
435 GtkFileFolderUnix *folder_unix = GTK_FILE_FOLDER_UNIX (folder);
436 GError *tmp_error = NULL;
441 dir = g_dir_open (folder_unix->filename, 0, &tmp_error);
445 GTK_FILE_SYSTEM_ERROR,
446 GTK_FILE_SYSTEM_ERROR_NONEXISTANT,
450 g_error_free (tmp_error);
457 const gchar *filename = g_dir_read_name (dir);
463 fullname = g_build_filename (folder_unix->filename, filename, NULL);
464 *children = g_slist_prepend (*children, filename_to_uri (fullname));
470 *children = g_slist_reverse (*children);
476 filename_get_info (const gchar *filename,
477 GtkFileInfoType types,
483 /* If stat fails, try to fall back to lstat to catch broken links
485 if (stat (filename, &statbuf) != 0 &&
486 lstat (filename, &statbuf) != 0)
488 gchar *filename_utf8 = g_filename_to_utf8 (filename, -1, NULL, NULL, NULL);
490 GTK_FILE_SYSTEM_ERROR,
491 GTK_FILE_SYSTEM_ERROR_NONEXISTANT,
492 "error getting information for '%s': %s",
493 filename_utf8 ? filename_utf8 : "???",
495 g_free (filename_utf8);
500 info = gtk_file_info_new ();
502 if (filename_is_root (filename))
504 if (types & GTK_FILE_INFO_DISPLAY_NAME)
505 gtk_file_info_set_display_name (info, "/");
507 if (types & GTK_FILE_INFO_IS_HIDDEN)
508 gtk_file_info_set_is_hidden (info, FALSE);
512 gchar *basename = g_path_get_basename (filename);
514 if (types & GTK_FILE_INFO_DISPLAY_NAME)
516 gchar *display_name = g_filename_to_utf8 (basename, -1, NULL, NULL, NULL);
518 display_name = g_strescape (basename, NULL);
520 gtk_file_info_set_display_name (info, display_name);
522 g_free (display_name);
525 if (types & GTK_FILE_INFO_IS_HIDDEN)
527 gtk_file_info_set_is_hidden (info, basename[0] == '.');
533 if (types & GTK_FILE_INFO_IS_FOLDER)
535 gtk_file_info_set_is_folder (info, S_ISDIR (statbuf.st_mode));
538 if (types & GTK_FILE_INFO_MIME_TYPE)
540 gtk_file_info_set_mime_type (info, "application/octet-stream");
543 if (types & GTK_FILE_INFO_MODIFICATION_TIME)
545 gtk_file_info_set_modification_time (info, statbuf.st_mtime);
548 if (types & GTK_FILE_INFO_SIZE)
550 gtk_file_info_set_size (info, (gint64)512 * (gint16)statbuf.st_blocks);
553 if (types & GTK_FILE_INFO_ICON)
555 /* NOT YET IMPLEMENTED */
562 filename_from_uri (const char *uri,
565 GError *tmp_error = NULL;
568 result = g_filename_from_uri (uri, NULL, &tmp_error);
572 GTK_FILE_SYSTEM_ERROR,
573 GTK_FILE_SYSTEM_ERROR_INVALID_URI,
577 g_error_free (tmp_error);
584 filename_to_uri (const char *filename)
588 result = g_filename_to_uri (filename, NULL, NULL);
590 g_warning ("GtkFileSystemUnix: Handling of non-UTF-8-representable-filenames needs to be fixed");
596 filename_is_root (const char *filename)
598 const gchar *after_root;
600 after_root = g_path_skip_root (filename);
602 return (*after_root == '\0');