1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
3 /* nautilus-file-utilities.c - implementation of file manipulation routines.
5 Copyright (C) 1999, 2000, 2001 Eazel, Inc.
7 The Gnome Library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public License as
9 published by the Free Software Foundation; either version 2 of the
10 License, or (at your option) any later version.
12 The Gnome Library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Library General Public License for more details.
17 You should have received a copy of the GNU Library General Public
18 License along with the Gnome Library; see the file COPYING.LIB. If not,
19 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA.
22 Authors: John Sullivan <sullivan@eazel.com>
26 #include "nautilus-file-utilities.h"
28 #include "nautilus-global-preferences.h"
29 #include "nautilus-lib-self-check-functions.h"
30 #include "nautilus-metadata.h"
31 #include "nautilus-metafile.h"
32 #include "nautilus-file.h"
33 #include "nautilus-search-directory.h"
34 #include "nautilus-signaller.h"
35 #include <eel/eel-glib-extensions.h>
36 #include <eel/eel-string.h>
37 #include <eel/eel-debug.h>
38 #include <libgnome/gnome-util.h>
39 #include <glib/gi18n.h>
40 #include <gio/gfilemonitor.h>
44 #define NAUTILUS_USER_DIRECTORY_NAME ".nautilus"
45 #define DEFAULT_NAUTILUS_DIRECTORY_MODE (0755)
47 #define DESKTOP_DIRECTORY_NAME "Desktop"
48 #define LEGACY_DESKTOP_DIRECTORY_NAME ".gnome-desktop"
49 #define DEFAULT_DESKTOP_DIRECTORY_MODE (0755)
51 static void update_xdg_dir_cache (void);
52 static void schedule_user_dirs_changed (void);
53 static void desktop_dir_changed (void);
57 nautilus_compute_title_for_location (GFile
*location
)
62 /* TODO-gio: This doesn't really work all that great if the
63 info about the file isn't known atm... */
67 file
= nautilus_file_get (location
);
68 title
= nautilus_file_get_display_name (file
);
69 nautilus_file_unref (file
);
73 title
= g_strdup ("");
81 * nautilus_get_user_directory:
83 * Get the path for the directory containing nautilus settings.
85 * Return value: the directory path.
88 nautilus_get_user_directory (void)
90 char *user_directory
= NULL
;
92 user_directory
= g_build_filename (g_get_home_dir (),
93 NAUTILUS_USER_DIRECTORY_NAME
,
96 if (!g_file_test (user_directory
, G_FILE_TEST_EXISTS
)) {
97 mkdir (user_directory
, DEFAULT_NAUTILUS_DIRECTORY_MODE
);
98 /* FIXME bugzilla.gnome.org 41286:
99 * How should we handle the case where this mkdir fails?
100 * Note that nautilus_application_startup will refuse to launch if this
101 * directory doesn't get created, so that case is OK. But the directory
102 * could be deleted after Nautilus was launched, and perhaps
103 * there is some bad side-effect of not handling that case.
107 return user_directory
;
118 parse_xdg_dirs (const char *config_file
)
121 char *config_file_free
= NULL
;
127 char *type_start
, *type_end
;
128 char *value
, *unescaped
;
131 array
= g_array_new (TRUE
, TRUE
, sizeof (XdgDirEntry
));
133 if (config_file
== NULL
)
135 config_file_free
= g_build_filename (g_get_user_config_dir (),
136 "user-dirs.dirs", NULL
);
137 config_file
= (const char *)config_file_free
;
140 if (g_file_get_contents (config_file
, &data
, NULL
, NULL
))
142 lines
= g_strsplit (data
, "\n", 0);
144 for (i
= 0; lines
[i
] != NULL
; i
++)
147 while (g_ascii_isspace (*p
))
153 value
= strchr (p
, '=');
158 g_strchug (g_strchomp (p
));
159 if (!g_str_has_prefix (p
, "XDG_"))
161 if (!g_str_has_suffix (p
, "_DIR"))
164 type_end
= p
+ strlen (p
) - 4;
166 while (g_ascii_isspace (*value
))
174 if (g_str_has_prefix (value
, "$HOME"))
178 while (*value
== '/')
181 else if (*value
!= '/')
184 d
= unescaped
= g_malloc (strlen (value
) + 1);
185 while (*value
&& *value
!= '"')
187 if ((*value
== '\\') && (*(value
+ 1) != 0))
194 dir
.type
= g_strdup (type_start
);
197 dir
.path
= g_build_filename (g_get_home_dir (), unescaped
, NULL
);
201 dir
.path
= unescaped
;
203 g_array_append_val (array
, dir
);
209 g_free (config_file_free
);
211 return (XdgDirEntry
*)g_array_free (array
, FALSE
);
214 static XdgDirEntry
*cached_xdg_dirs
= NULL
;
215 static GFileMonitor
*cached_xdg_dirs_monitor
= NULL
;
218 xdg_dir_changed (NautilusFile
*file
,
221 GFile
*location
, *dir_location
;
224 location
= nautilus_file_get_location (file
);
225 dir_location
= g_file_new_for_path (dir
->path
);
226 if (!g_file_equal (location
, dir_location
)) {
227 path
= g_file_get_path (location
);
237 argv
[i
++] = "xdg-user-dirs-update";
239 argv
[i
++] = dir
->type
;
240 argv
[i
++] = dir
->path
;
243 /* We do this sync, to avoid possible race-conditions
244 if multiple dirs change at the same time. Its
245 blocking the main thread, but these updates should
246 be very rare and very fast. */
249 G_SPAWN_SEARCH_PATH
|
250 G_SPAWN_STDOUT_TO_DEV_NULL
|
251 G_SPAWN_STDERR_TO_DEV_NULL
,
253 NULL
, NULL
, NULL
, NULL
);
254 schedule_user_dirs_changed ();
255 desktop_dir_changed ();
258 g_object_unref (location
);
259 g_object_unref (dir_location
);
263 xdg_dir_cache_changed_cb (GFileMonitor
*monitor
,
266 GFileMonitorEvent event_type
)
268 if (event_type
== G_FILE_MONITOR_EVENT_CHANGED
||
269 event_type
== G_FILE_MONITOR_EVENT_CREATED
) {
270 update_xdg_dir_cache ();
274 static int user_dirs_changed_tag
= 0;
277 emit_user_dirs_changed_idle (gpointer data
)
279 g_signal_emit_by_name (nautilus_signaller_get_current (),
280 "user_dirs_changed");
281 user_dirs_changed_tag
= 0;
286 schedule_user_dirs_changed (void)
288 if (user_dirs_changed_tag
== 0) {
289 user_dirs_changed_tag
= g_idle_add (emit_user_dirs_changed_idle
, NULL
);
294 unschedule_user_dirs_changed (void)
296 if (user_dirs_changed_tag
!= 0) {
297 g_source_remove (user_dirs_changed_tag
);
298 user_dirs_changed_tag
= 0;
303 free_xdg_dir_cache (void)
307 if (cached_xdg_dirs
!= NULL
) {
308 for (i
= 0; cached_xdg_dirs
[i
].type
!= NULL
; i
++) {
309 if (cached_xdg_dirs
[i
].file
!= NULL
) {
310 nautilus_file_monitor_remove (cached_xdg_dirs
[i
].file
,
311 &cached_xdg_dirs
[i
]);
312 g_signal_handlers_disconnect_by_func (cached_xdg_dirs
[i
].file
,
313 G_CALLBACK (xdg_dir_changed
),
314 &cached_xdg_dirs
[i
]);
315 nautilus_file_unref (cached_xdg_dirs
[i
].file
);
317 g_free (cached_xdg_dirs
[i
].type
);
318 g_free (cached_xdg_dirs
[i
].path
);
320 g_free (cached_xdg_dirs
);
325 destroy_xdg_dir_cache (void)
327 free_xdg_dir_cache ();
328 unschedule_user_dirs_changed ();
329 desktop_dir_changed ();
331 if (cached_xdg_dirs_monitor
!= NULL
) {
332 g_object_unref (cached_xdg_dirs_monitor
);
333 cached_xdg_dirs_monitor
= NULL
;
338 update_xdg_dir_cache (void)
341 char *config_file
, *uri
;
344 free_xdg_dir_cache ();
345 schedule_user_dirs_changed ();
346 desktop_dir_changed ();
348 cached_xdg_dirs
= parse_xdg_dirs (NULL
);
350 for (i
= 0 ; cached_xdg_dirs
[i
].type
!= NULL
; i
++) {
351 cached_xdg_dirs
[i
].file
= NULL
;
352 if (strcmp (cached_xdg_dirs
[i
].path
, g_get_home_dir ()) != 0) {
353 uri
= g_filename_to_uri (cached_xdg_dirs
[i
].path
, NULL
, NULL
);
354 cached_xdg_dirs
[i
].file
= nautilus_file_get_by_uri (uri
);
355 nautilus_file_monitor_add (cached_xdg_dirs
[i
].file
,
357 NAUTILUS_FILE_ATTRIBUTE_INFO
);
358 g_signal_connect (cached_xdg_dirs
[i
].file
,
359 "changed", G_CALLBACK (xdg_dir_changed
), &cached_xdg_dirs
[i
]);
364 if (cached_xdg_dirs_monitor
== NULL
) {
365 config_file
= g_build_filename (g_get_user_config_dir (),
366 "user-dirs.dirs", NULL
);
367 file
= g_file_new_for_path (config_file
);
368 cached_xdg_dirs_monitor
= g_file_monitor_file (file
, 0, NULL
);
369 g_signal_connect (cached_xdg_dirs_monitor
, "changed",
370 G_CALLBACK (xdg_dir_cache_changed_cb
), NULL
);
371 g_object_unref (file
);
372 g_free (config_file
);
374 eel_debug_call_at_shutdown (destroy_xdg_dir_cache
);
379 nautilus_get_xdg_dir (const char *type
)
383 if (cached_xdg_dirs
== NULL
) {
384 update_xdg_dir_cache ();
387 for (i
= 0 ; cached_xdg_dirs
!= NULL
&& cached_xdg_dirs
[i
].type
!= NULL
; i
++) {
388 if (strcmp (cached_xdg_dirs
[i
].type
, type
) == 0) {
389 return g_strdup (cached_xdg_dirs
[i
].path
);
392 if (strcmp ("DESKTOP", type
) == 0) {
393 return g_build_filename (g_get_home_dir (), DESKTOP_DIRECTORY_NAME
, NULL
);
395 if (strcmp ("TEMPLATES", type
) == 0) {
396 return g_build_filename (g_get_home_dir (), "Templates", NULL
);
399 return g_strdup (g_get_home_dir ());
403 get_desktop_path (void)
405 if (eel_preferences_get_boolean (NAUTILUS_PREFERENCES_DESKTOP_IS_HOME_DIR
)) {
406 return g_strdup (g_get_home_dir());
408 return nautilus_get_xdg_dir ("DESKTOP");
413 * nautilus_get_desktop_directory:
415 * Get the path for the directory containing files on the desktop.
417 * Return value: the directory path.
420 nautilus_get_desktop_directory (void)
422 char *desktop_directory
;
424 desktop_directory
= get_desktop_path ();
426 /* Don't try to create a home directory */
427 if (!eel_preferences_get_boolean (NAUTILUS_PREFERENCES_DESKTOP_IS_HOME_DIR
)) {
428 if (!g_file_test (desktop_directory
, G_FILE_TEST_EXISTS
)) {
429 mkdir (desktop_directory
, DEFAULT_DESKTOP_DIRECTORY_MODE
);
430 /* FIXME bugzilla.gnome.org 41286:
431 * How should we handle the case where this mkdir fails?
432 * Note that nautilus_application_startup will refuse to launch if this
433 * directory doesn't get created, so that case is OK. But the directory
434 * could be deleted after Nautilus was launched, and perhaps
435 * there is some bad side-effect of not handling that case.
440 return desktop_directory
;
444 nautilus_get_desktop_location (void)
446 char *desktop_directory
;
449 desktop_directory
= get_desktop_path ();
451 res
= g_file_new_for_path (desktop_directory
);
452 g_free (desktop_directory
);
458 * nautilus_get_desktop_directory_uri:
460 * Get the uri for the directory containing files on the desktop.
462 * Return value: the directory path.
465 nautilus_get_desktop_directory_uri (void)
470 desktop_path
= nautilus_get_desktop_directory ();
471 desktop_uri
= g_filename_to_uri (desktop_path
, NULL
, NULL
);
472 g_free (desktop_path
);
478 nautilus_get_desktop_directory_uri_no_create (void)
483 desktop_path
= get_desktop_path ();
484 desktop_uri
= g_filename_to_uri (desktop_path
, NULL
, NULL
);
485 g_free (desktop_path
);
491 nautilus_get_home_directory_uri (void)
493 return g_filename_to_uri (g_get_home_dir (), NULL
, NULL
);
498 nautilus_should_use_templates_directory (void)
503 dir
= nautilus_get_xdg_dir ("TEMPLATES");
504 res
= strcmp (dir
, g_get_home_dir ()) != 0;
510 nautilus_get_templates_directory (void)
512 return nautilus_get_xdg_dir ("TEMPLATES");
516 nautilus_create_templates_directory (void)
520 dir
= nautilus_get_templates_directory ();
521 if (!g_file_test (dir
, G_FILE_TEST_EXISTS
)) {
522 mkdir (dir
, DEFAULT_NAUTILUS_DIRECTORY_MODE
);
528 nautilus_get_templates_directory_uri (void)
530 char *directory
, *uri
;
532 directory
= nautilus_get_templates_directory ();
533 uri
= g_filename_to_uri (directory
, NULL
, NULL
);
539 nautilus_get_searches_directory (void)
544 user_dir
= nautilus_get_user_directory ();
545 searches_dir
= g_build_filename (user_dir
, "searches", NULL
);
548 if (!g_file_test (searches_dir
, G_FILE_TEST_EXISTS
))
549 mkdir (searches_dir
, DEFAULT_NAUTILUS_DIRECTORY_MODE
);
554 /* These need to be reset to NULL when desktop_is_home_dir changes */
555 static GFile
*desktop_dir
= NULL
;
556 static GFile
*desktop_dir_dir
= NULL
;
557 static char *desktop_dir_filename
= NULL
;
558 static gboolean desktop_dir_changed_callback_installed
= FALSE
;
562 desktop_dir_changed (void)
565 g_object_unref (desktop_dir
);
567 if (desktop_dir_dir
) {
568 g_object_unref (desktop_dir_dir
);
570 g_free (desktop_dir_filename
);
572 desktop_dir_dir
= NULL
;
573 desktop_dir_filename
= NULL
;
577 desktop_dir_changed_callback (gpointer callback_data
)
579 desktop_dir_changed ();
583 update_desktop_dir (void)
588 path
= get_desktop_path ();
589 desktop_dir
= g_file_new_for_path (path
);
591 dirname
= g_path_get_dirname (path
);
592 desktop_dir_dir
= g_file_new_for_path (dirname
);
594 desktop_dir_filename
= g_path_get_basename (path
);
599 nautilus_is_home_directory_file (GFile
*dir
,
600 const char *filename
)
603 static GFile
*home_dir_dir
= NULL
;
604 static char *home_dir_filename
= NULL
;
606 if (home_dir_dir
== NULL
) {
607 dirname
= g_path_get_dirname (g_get_home_dir ());
608 home_dir_dir
= g_file_new_for_path (dirname
);
610 home_dir_filename
= g_path_get_basename (g_get_home_dir ());
613 return (g_file_equal (dir
, home_dir_dir
) &&
614 strcmp (filename
, home_dir_filename
) == 0);
618 nautilus_is_home_directory (GFile
*dir
)
620 static GFile
*home_dir
= NULL
;
622 if (home_dir
== NULL
) {
623 home_dir
= g_file_new_for_path (g_get_home_dir ());
626 return g_file_equal (dir
, home_dir
);
630 nautilus_is_root_directory (GFile
*dir
)
632 static GFile
*root_dir
= NULL
;
634 if (root_dir
== NULL
) {
635 root_dir
= g_file_new_for_path ("/");
638 return g_file_equal (dir
, root_dir
);
643 nautilus_is_desktop_directory_file (GFile
*dir
,
647 if (!desktop_dir_changed_callback_installed
) {
648 eel_preferences_add_callback (NAUTILUS_PREFERENCES_DESKTOP_IS_HOME_DIR
,
649 desktop_dir_changed_callback
,
651 desktop_dir_changed_callback_installed
= TRUE
;
654 if (desktop_dir
== NULL
) {
655 update_desktop_dir ();
658 return (g_file_equal (dir
, desktop_dir_dir
) &&
659 strcmp (file
, desktop_dir_filename
) == 0);
663 nautilus_is_desktop_directory (GFile
*dir
)
666 if (!desktop_dir_changed_callback_installed
) {
667 eel_preferences_add_callback (NAUTILUS_PREFERENCES_DESKTOP_IS_HOME_DIR
,
668 desktop_dir_changed_callback
,
670 desktop_dir_changed_callback_installed
= TRUE
;
673 if (desktop_dir
== NULL
) {
674 update_desktop_dir ();
677 return g_file_equal (dir
, desktop_dir
);
682 * nautilus_get_gmc_desktop_directory:
684 * Get the path for the directory containing the legacy gmc desktop.
686 * Return value: the directory path.
689 nautilus_get_gmc_desktop_directory (void)
691 return g_build_filename (g_get_home_dir (), LEGACY_DESKTOP_DIRECTORY_NAME
, NULL
);
695 * nautilus_get_pixmap_directory
697 * Get the path for the directory containing Nautilus pixmaps.
699 * Return value: the directory path.
702 nautilus_get_pixmap_directory (void)
704 return g_strdup (DATADIR
"/pixmaps/nautilus");
707 /* FIXME bugzilla.gnome.org 42423:
708 * Callers just use this and dereference so we core dump if
709 * pixmaps are missing. That is lame.
712 nautilus_pixmap_file (const char *partial_path
)
716 path
= g_build_filename (DATADIR
"/pixmaps/nautilus", partial_path
, NULL
);
717 if (g_file_test (path
, G_FILE_TEST_EXISTS
)) {
721 tmp
= nautilus_get_pixmap_directory ();
722 g_debug ("Failed to locate \"%s\" in Nautilus pixmap path \"%s\". Incomplete installation?", partial_path
, tmp
);
730 nautilus_get_data_file_path (const char *partial_path
)
733 char *user_directory
;
735 /* first try the user's home directory */
736 user_directory
= nautilus_get_user_directory ();
737 path
= g_build_filename (user_directory
, partial_path
, NULL
);
738 g_free (user_directory
);
739 if (g_file_test (path
, G_FILE_TEST_EXISTS
)) {
744 /* next try the shared directory */
745 path
= g_build_filename (NAUTILUS_DATADIR
, partial_path
, NULL
);
746 if (g_file_test (path
, G_FILE_TEST_EXISTS
)) {
755 nautilus_ensure_unique_file_name (const char *directory_uri
,
756 const char *base_name
,
757 const char *extension
)
765 dir
= g_file_new_for_uri (directory_uri
);
767 info
= g_file_query_info (dir
, G_FILE_ATTRIBUTE_STD_TYPE
, 0, NULL
, NULL
);
769 g_object_unref (dir
);
772 g_object_unref (info
);
774 filename
= g_strdup_printf ("%s%s",
777 child
= g_file_get_child (dir
, filename
);
781 while ((info
= g_file_query_info (child
, G_FILE_ATTRIBUTE_STD_TYPE
, 0, NULL
, NULL
)) != NULL
) {
782 g_object_unref (info
);
783 g_object_unref (child
);
785 filename
= g_strdup_printf ("%s-%d%s",
789 child
= g_file_get_child (dir
, filename
);
795 res
= g_file_get_uri (child
);
796 g_object_unref (child
);
797 g_object_unref (dir
);
803 nautilus_unique_temporary_file_name (void)
805 const char *prefix
= "/tmp/nautilus-temp-file";
809 file_name
= g_strdup_printf ("%sXXXXXX", prefix
);
811 fd
= mkstemp (file_name
);
823 nautilus_find_existing_uri_in_hierarchy (GFile
*location
)
828 g_assert (location
!= NULL
);
830 location
= g_object_ref (location
);
831 while (location
!= NULL
) {
832 info
= g_file_query_info (location
,
835 g_object_unref (info
);
840 location
= g_file_get_parent (location
);
841 g_object_unref (tmp
);
847 #if !defined (NAUTILUS_OMIT_SELF_CHECK)
850 nautilus_self_check_file_utilities (void)
854 #endif /* !NAUTILUS_OMIT_SELF_CHECK */