2 * ROX-Filer, filer for the ROX desktop project
3 * Copyright (C) 2006, Thomas Leonard and others (see changelog for details).
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 2 of the License, or (at your option)
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
16 * Place, Suite 330, Boston, MA 02111-1307 USA
19 /* dir.c - directory scanning and caching */
23 * A Directory contains a list DirItems, each having a name and some details
24 * (size, image, owner, etc).
26 * There is a list of file names that need to be rechecked. While this
27 * list is non-empty, items are taken from the list in an idle callback
28 * and checked. Missing items are removed from the Directory, new items are
29 * added and existing items are updated if they've changed.
31 * When a whole directory is to be rescanned:
33 * - A list of all filenames in the directory is fetched, without any
34 * of the extra details.
35 * - This list is compared to the current DirItems, removing any that are now
37 * - Each window onto the directory is asked which items it will actually
38 * display, and the union of these sets is the new recheck list.
40 * This system is designed to get the number of items and their names quickly,
41 * so that the auto-sizer can make a good guess. It also prevents checking
42 * hidden files if they're not going to be displayed.
44 * To get the Directory object, use dir_cache, which will automatically
45 * trigger a rescan if needed.
47 * To get notified when the Directory changes, use the dir_attach() and
48 * dir_detach() functions.
63 #include "gui_support.h"
69 #include "usericons.h"
72 /* For debugging. Can't detach when this is non-zero. */
73 static int in_callback
= 0;
75 GHashTable
*dir_cache_new
= NULL
; /* URI -> Directory */
77 /* Static prototypes */
78 static void update(Directory
*dir
, gchar
*pathname
, gpointer data
);
79 static void set_idle_callback(Directory
*dir
);
80 static DirItem
*insert_item(Directory
*dir
, const guchar
*leafname
);
81 static void remove_missing(Directory
*dir
, GPtrArray
*keep
);
82 static void dir_recheck(Directory
*dir
,
83 const guchar
*path
, const guchar
*leafname
);
84 static GPtrArray
*hash_to_array(GHashTable
*hash
);
85 static void dir_force_update_item(Directory
*dir
, const gchar
*leaf
);
86 static Directory
*dir_new(const char *uri
);
87 static void dir_rescan(Directory
*dir
);
89 /****************************************************************
90 * EXTERNAL INTERFACE *
91 ****************************************************************/
95 dir_cache_new
= g_hash_table_new(g_str_hash
, g_str_equal
);
98 /* Get a new or existing Directory object.
99 * If create is false, only return an existing object.
100 * If true, create one if necessary.
101 * Call g_object_unref() when done.
102 * Will return null if directory doesn't exist : TODO
104 Directory
*dir_lookup(const char *uri
, gboolean may_create
)
108 dir
= g_hash_table_lookup(dir_cache_new
, uri
);
113 g_hash_table_insert(dir_cache_new
, dir
->pathname
, dir
);
114 g_object_ref(dir
); /* One ref for the cache */
117 g_object_ref(dir
); /* One ref for the caller */
122 static void dir_changed_cb(GFileMonitor
*monitor
, GFile
*file
, GFile
*other_file
,
123 GFileMonitorEvent event_type
, Directory
*dir
)
125 // TODO: don't do a full rescan!
129 /* Periodically calls callback to notify about changes to the contents
131 * Before this function returns, it calls the callback once to add all
132 * the items currently in the directory (unless the dir is empty).
133 * It then calls callback(DIR_QUEUE_INTERESTING) to find out which items the
134 * caller cares about.
135 * If we are not scanning, it also calls callback(DIR_END_SCAN).
137 void dir_attach(Directory
*dir
, DirCallback callback
, gpointer data
)
142 g_return_if_fail(dir
!= NULL
);
143 g_return_if_fail(callback
!= NULL
);
145 user
= g_new(DirUser
, 1);
146 user
->callback
= callback
;
151 g_return_if_fail(dir
->monitor
== NULL
);
152 dir
->monitor
= g_file_monitor_directory(dir
->gfile
, G_FILE_MONITOR_NONE
, NULL
, NULL
);
154 g_signal_connect(dir
->monitor
, "changed", (GCallback
) dir_changed_cb
, dir
);
156 g_warning("Failed to monitor directory '%s'", dir
->pathname
);
159 dir
->users
= g_list_prepend(dir
->users
, user
);
163 items
= hash_to_array(dir
->known_items
);
165 callback(dir
, DIR_ADD
, items
, data
);
166 g_ptr_array_free(items
, TRUE
);
168 if (dir
->needs_update
&& !dir
->scanning
)
171 callback(dir
, DIR_QUEUE_INTERESTING
, NULL
, data
);
173 /* May start scanning if noone was watching before */
174 set_idle_callback(dir
);
177 callback(dir
, DIR_END_SCAN
, NULL
, data
);
180 /* Undo the effect of dir_attach */
181 void dir_detach(Directory
*dir
, DirCallback callback
, gpointer data
)
186 g_return_if_fail(dir
!= NULL
);
187 g_return_if_fail(callback
!= NULL
);
188 g_return_if_fail(in_callback
== 0);
190 for (list
= dir
->users
; list
; list
= list
->next
)
192 user
= (DirUser
*) list
->data
;
193 if (user
->callback
== callback
&& user
->data
== data
)
196 dir
->users
= g_list_remove(dir
->users
, user
);
199 /* May stop scanning if noone's watching */
200 set_idle_callback(dir
);
202 if (!dir
->users
&& dir
->monitor
)
204 g_object_unref(dir
->monitor
);
212 g_warning("dir_detach: Callback/data pair not attached!\n");
215 void dir_update(Directory
*dir
, gchar
*pathname
)
217 update(dir
, pathname
, NULL
);
220 /* Rescan this directory */
221 void refresh_dirs(const char *path
)
224 //g_fscache_update(dir_cache, path);
227 /* When something has happened to a particular object, call this
228 * and all appropriate changes will be made.
230 void dir_check_this(const guchar
*path
)
236 dir_path
= g_path_get_dirname(path
);
237 real_path
= pathdup(dir_path
);
240 dir
= dir_lookup(real_path
, FALSE
);
243 dir_recheck(dir
, real_path
, g_basename(path
));
250 /* Used when we fork an action child, otherwise we can't delete or unmount
251 * any directory which we're watching!
253 void dir_drop_all_dnotifies(void)
255 /* TODO: still needed with GIO? */
258 /* Tell watchers that this item has changed, but don't rescan.
259 * (used when thumbnail has been created for an item)
261 void dir_force_update_path(const gchar
*path
)
266 g_return_if_fail(path
[0] == '/');
268 dir_path
= g_path_get_dirname(path
);
270 dir
= NULL
; //g_fscache_lookup_full(dir_cache, dir_path, FSCACHE_LOOKUP_PEEK, NULL); TODO
273 dir_force_update_item(dir
, g_basename(path
));
280 /* Ensure that 'leafname' is up-to-date. Returns the new/updated
281 * DirItem, or NULL if the file no longer exists.
283 DirItem
*dir_update_item(Directory
*dir
, const gchar
*leafname
)
287 time(&diritem_recent_time
);
288 item
= insert_item(dir
, leafname
);
294 /* Add item to the recheck_list if it's marked as needing it.
295 * Item must have ITEM_FLAG_NEED_RESCAN_QUEUE.
296 * Items on the list will get checked later in an idle callback.
298 void dir_queue_recheck(Directory
*dir
, DirItem
*item
)
300 g_return_if_fail(dir
!= NULL
);
301 g_return_if_fail(item
!= NULL
);
302 g_return_if_fail(item
->flags
& ITEM_FLAG_NEED_RESCAN_QUEUE
);
304 dir
->recheck_list
= g_list_prepend(dir
->recheck_list
,
305 g_strdup(item
->leafname
));
306 item
->flags
&= ~ITEM_FLAG_NEED_RESCAN_QUEUE
;
309 static void free_recheck_list(Directory
*dir
)
311 destroy_glist(&dir
->recheck_list
);
314 /* If scanning state has changed then notify all filer windows */
315 static void dir_set_scanning(Directory
*dir
, gboolean scanning
)
319 if (scanning
== dir
->scanning
)
324 dir
->scanning
= scanning
;
326 for (next
= dir
->users
; next
; next
= next
->next
)
328 DirUser
*user
= (DirUser
*) next
->data
;
331 scanning
? DIR_START_SCAN
: DIR_END_SCAN
,
336 /* Useful for profiling */
347 /* Notify everyone that the error status of the directory has changed */
348 static void dir_error_changed(Directory
*dir
)
354 for (next
= dir
->users
; next
; next
= next
->next
)
356 DirUser
*user
= (DirUser
*) next
->data
;
358 user
->callback(dir
, DIR_ERROR_CHANGED
, NULL
, user
->data
);
364 /* This is called in the background when there are items on the
365 * dir->recheck_list to process.
367 static gboolean
recheck_callback(gpointer data
)
369 Directory
*dir
= (Directory
*) data
;
373 g_return_val_if_fail(dir
!= NULL
, FALSE
);
374 g_return_val_if_fail(dir
->recheck_list
!= NULL
, FALSE
);
376 /* Remove the first name from the list */
377 next
= dir
->recheck_list
;
378 dir
->recheck_list
= g_list_remove_link(dir
->recheck_list
, next
);
379 leaf
= (guchar
*) next
->data
;
384 insert_item(dir
, leaf
);
388 if (dir
->recheck_list
)
389 return TRUE
; /* Call again */
391 /* The recheck_list list empty. Stop scanning, unless
392 * needs_update, in which case we start scanning again.
397 dir
->have_scanned
= TRUE
;
398 dir_set_scanning(dir
, FALSE
);
399 g_source_remove(dir
->idle_callback
);
400 dir
->idle_callback
= 0;
402 if (dir
->needs_update
)
408 /* Add all the new items to the items array.
409 * Notify everyone who is watching us.
411 void dir_merge_new(Directory
*dir
)
413 GPtrArray
*new = dir
->new_items
;
414 GPtrArray
*up
= dir
->up_items
;
415 GPtrArray
*gone
= dir
->gone_items
;
421 for (list
= dir
->users
; list
; list
= list
->next
)
423 DirUser
*user
= (DirUser
*) list
->data
;
426 user
->callback(dir
, DIR_ADD
, new, user
->data
);
428 user
->callback(dir
, DIR_UPDATE
, up
, user
->data
);
430 user
->callback(dir
, DIR_REMOVE
, gone
, user
->data
);
435 for (i
= 0; i
< new->len
; i
++)
437 DirItem
*item
= (DirItem
*) new->pdata
[i
];
439 g_hash_table_insert(dir
->known_items
, item
->leafname
, item
);
442 for (i
= 0; i
< gone
->len
; i
++)
444 DirItem
*item
= (DirItem
*) gone
->pdata
[i
];
449 g_ptr_array_set_size(gone
, 0);
450 g_ptr_array_set_size(new, 0);
451 g_ptr_array_set_size(up
, 0);
454 /****************************************************************
455 * INTERNAL FUNCTIONS *
456 ****************************************************************/
458 static void free_items_array(GPtrArray
*array
)
462 for (i
= 0; i
< array
->len
; i
++)
464 DirItem
*item
= (DirItem
*) array
->pdata
[i
];
469 g_ptr_array_free(array
, TRUE
);
472 /* Tell everyone watching that these items have gone */
473 static void notify_deleted(Directory
*dir
, GPtrArray
*deleted
)
482 for (next
= dir
->users
; next
; next
= next
->next
)
484 DirUser
*user
= (DirUser
*) next
->data
;
486 user
->callback(dir
, DIR_REMOVE
, deleted
, user
->data
);
492 static void mark_unused(gpointer key
, gpointer value
, gpointer data
)
494 DirItem
*item
= (DirItem
*) value
;
496 item
->may_delete
= TRUE
;
499 static void keep_deleted(gpointer key
, gpointer value
, gpointer data
)
501 DirItem
*item
= (DirItem
*) value
;
502 GPtrArray
*deleted
= (GPtrArray
*) data
;
504 if (item
->may_delete
)
505 g_ptr_array_add(deleted
, item
);
508 static gboolean
check_unused(gpointer key
, gpointer value
, gpointer data
)
510 DirItem
*item
= (DirItem
*) value
;
512 return item
->may_delete
;
515 /* Remove all the old items that have gone.
516 * Notify everyone who is watching us of the removed items.
518 static void remove_missing(Directory
*dir
, GPtrArray
*keep
)
523 deleted
= g_ptr_array_new();
525 /* Mark all current items as may_delete */
526 g_hash_table_foreach(dir
->known_items
, mark_unused
, NULL
);
528 /* Unmark all items also in 'keep' */
529 for (i
= 0; i
< keep
->len
; i
++)
531 guchar
*leaf
= (guchar
*) keep
->pdata
[i
];
534 item
= g_hash_table_lookup(dir
->known_items
, leaf
);
537 item
->may_delete
= FALSE
;
540 /* Add each item still marked to 'deleted' */
541 g_hash_table_foreach(dir
->known_items
, keep_deleted
, deleted
);
543 /* Remove all items still marked */
544 g_hash_table_foreach_remove(dir
->known_items
, check_unused
, NULL
);
546 notify_deleted(dir
, deleted
);
548 free_items_array(deleted
);
551 static gint
notify_timeout(gpointer data
)
553 Directory
*dir
= (Directory
*) data
;
555 g_return_val_if_fail(dir
->notify_active
== TRUE
, FALSE
);
559 dir
->notify_active
= FALSE
;
565 /* Call dir_merge_new() after a while. */
566 static void delayed_notify(Directory
*dir
)
568 if (dir
->notify_active
)
571 g_timeout_add(1500, notify_timeout
, dir
);
572 dir
->notify_active
= TRUE
;
575 /* Stat this item and add, update or remove it.
576 * Returns the new/updated item, if any.
577 * (leafname may be from the current DirItem item)
578 * Ensure diritem_recent_time is reasonably up-to-date before calling this.
580 static DirItem
*insert_item(Directory
*dir
, const guchar
*leafname
)
585 gboolean do_compare
= FALSE
; /* (old is filled in) */
587 if (leafname
[0] == '.' && (leafname
[1] == '\n' ||
588 (leafname
[1] == '.' && leafname
[2] == '\n')))
589 return NULL
; /* Ignore '.' and '..' */
591 full_path
= g_file_get_child(dir
->gfile
, leafname
);
592 item
= g_hash_table_lookup(dir
->known_items
, leafname
);
596 if (item
->base_type
!= TYPE_UNKNOWN
)
598 /* Preserve the old details so we can compare */
601 g_object_ref(old
._image
);
604 diritem_restat_gfile(full_path
, item
);
605 g_object_unref(full_path
);
609 /* Item isn't already here. This won't normally happen,
610 * because blank items are added when scanning, before
613 item
= diritem_new(leafname
);
614 diritem_restat_gfile(full_path
, item
);
615 g_object_unref(full_path
);
616 if (item
->base_type
== TYPE_ERROR
&&
617 item
->lstat_errno
== ENOENT
)
622 g_ptr_array_add(dir
->new_items
, item
);
626 /* No need to queue the item for scanning. If we got here because
627 * the item was queued, this flag will normally already be clear.
629 item
->flags
&= ~ITEM_FLAG_NEED_RESCAN_QUEUE
;
631 if (item
->base_type
== TYPE_ERROR
&& item
->lstat_errno
== ENOENT
)
633 /* Item has been deleted */
634 g_hash_table_remove(dir
->known_items
, item
->leafname
);
635 g_ptr_array_add(dir
->gone_items
, item
);
636 if (do_compare
&& old
._image
)
637 g_object_unref(old
._image
);
644 /* It's a bit inefficient that we force the image to be
645 * loaded here, if we had an old image.
647 if (item
->lstat_errno
== old
.lstat_errno
648 && item
->base_type
== old
.base_type
649 && item
->flags
== old
.flags
650 && item
->size
== old
.size
651 && item
->mode
== old
.mode
652 && item
->atime
== old
.atime
653 && item
->ctime
== old
.ctime
654 && item
->mtime
== old
.mtime
655 && item
->uid
== old
.uid
656 && item
->gid
== old
.gid
657 && item
->mime_type
== old
.mime_type
658 && (old
._image
== NULL
|| di_image(item
) == old
._image
))
661 g_object_unref(old
._image
);
665 g_object_unref(old
._image
);
668 g_ptr_array_add(dir
->up_items
, item
);
674 static void update(Directory
*dir
, gchar
*pathname
, gpointer data
)
677 g_free(dir
->pathname
);
678 dir
->pathname
= pathdup(pathname
);
681 dir
->needs_update
= TRUE
;
686 /* If there is work to do, set the idle callback.
687 * Otherwise, stop scanning and unset the idle callback.
689 static void set_idle_callback(Directory
*dir
)
691 if (dir
->recheck_list
&& dir
->users
)
693 /* Work to do, and someone's watching */
694 dir_set_scanning(dir
, TRUE
);
695 if (dir
->idle_callback
)
697 time(&diritem_recent_time
);
698 dir
->idle_callback
= g_idle_add(recheck_callback
, dir
);
699 /* Do the first call now (will remove the callback itself) */
700 recheck_callback(dir
);
704 dir_set_scanning(dir
, FALSE
);
705 if (dir
->idle_callback
)
707 g_source_remove(dir
->idle_callback
);
708 dir
->idle_callback
= 0;
713 /* See dir_force_update_path() */
714 static void dir_force_update_item(Directory
*dir
, const gchar
*leaf
)
720 items
= g_ptr_array_new();
722 item
= g_hash_table_lookup(dir
->known_items
, leaf
);
726 g_ptr_array_add(items
, item
);
730 for (list
= dir
->users
; list
; list
= list
->next
)
732 DirUser
*user
= (DirUser
*) list
->data
;
734 user
->callback(dir
, DIR_UPDATE
, items
, user
->data
);
740 g_ptr_array_free(items
, TRUE
);
743 static void dir_recheck(Directory
*dir
,
744 const guchar
*path
, const guchar
*leafname
)
746 guchar
*old
= dir
->pathname
;
748 dir
->pathname
= g_strdup(path
);
751 time(&diritem_recent_time
);
752 insert_item(dir
, leafname
);
755 static void to_array(gpointer key
, gpointer value
, gpointer data
)
757 GPtrArray
*array
= (GPtrArray
*) data
;
759 g_ptr_array_add(array
, value
);
762 /* Convert a hash table to an unsorted GPtrArray.
763 * g_ptr_array_free() the result.
765 static GPtrArray
*hash_to_array(GHashTable
*hash
)
769 array
= g_ptr_array_new();
771 g_hash_table_foreach(hash
, to_array
, array
);
776 static gpointer parent_class
;
778 /* Note: dir_cache is never purged, so this shouldn't get called */
779 static void dir_finialize(GObject
*object
)
782 Directory
*dir
= (Directory
*) object
;
784 g_return_if_fail(dir
->users
== NULL
);
786 g_print("[ dir finalize ]\n");
788 free_recheck_list(dir
);
789 set_idle_callback(dir
);
790 if (dir
->rescan_timeout
!= -1)
791 g_source_remove(dir
->rescan_timeout
);
793 dir_merge_new(dir
); /* Ensures new, up and gone are empty */
795 g_ptr_array_free(dir
->up_items
, TRUE
);
796 g_ptr_array_free(dir
->new_items
, TRUE
);
797 g_ptr_array_free(dir
->gone_items
, TRUE
);
799 items
= hash_to_array(dir
->known_items
);
800 free_items_array(items
);
801 g_hash_table_destroy(dir
->known_items
);
804 g_free(dir
->pathname
);
806 G_OBJECT_CLASS(parent_class
)->finalize(object
);
809 static void directory_class_init(gpointer gclass
, gpointer data
)
811 GObjectClass
*object
= (GObjectClass
*) gclass
;
813 parent_class
= g_type_class_peek_parent(gclass
);
815 object
->finalize
= dir_finialize
;
818 static void directory_init(GTypeInstance
*object
, gpointer gclass
)
820 Directory
*dir
= (Directory
*) object
;
822 dir
->known_items
= g_hash_table_new(g_str_hash
, g_str_equal
);
825 dir
->recheck_list
= NULL
;
826 dir
->idle_callback
= 0;
827 dir
->scanning
= FALSE
;
828 dir
->have_scanned
= FALSE
;
831 dir
->needs_update
= TRUE
;
832 dir
->notify_active
= FALSE
;
833 dir
->pathname
= NULL
;
835 dir
->rescan_timeout
= -1;
837 dir
->new_items
= g_ptr_array_new();
838 dir
->up_items
= g_ptr_array_new();
839 dir
->gone_items
= g_ptr_array_new();
842 static GType
dir_get_type(void)
844 static GType type
= 0;
848 static const GTypeInfo info
=
850 sizeof (DirectoryClass
),
851 NULL
, /* base_init */
852 NULL
, /* base_finalise */
853 directory_class_init
,
854 NULL
, /* class_finalise */
855 NULL
, /* class_data */
862 type
= g_type_register_static(G_TYPE_OBJECT
, "Directory",
869 static Directory
*dir_new(const char *uri
)
873 dir
= g_object_new(dir_get_type(), NULL
);
875 dir
->gfile
= g_file_new_for_uri(uri
);
876 dir
->pathname
= g_strdup(uri
);
881 static void dir_rescan_internal(Directory
*dir
, GError
**error
)
884 GFileEnumerator
*iter
;
889 info
= g_file_query_info(dir
->gfile
, "unix::*", G_FILE_QUERY_INFO_NONE
, NULL
, error
);
892 dir
->stat_info
.st_ino
= g_file_info_get_attribute_uint64(info
, G_FILE_ATTRIBUTE_UNIX_INODE
);
893 dir
->stat_info
.st_dev
= g_file_info_get_attribute_uint32(info
, G_FILE_ATTRIBUTE_UNIX_DEVICE
);
894 g_object_unref(info
);
896 iter
= g_file_enumerate_children(dir
->gfile
, USEFUL_GIO_ATTRS
, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS
, NULL
, error
);
900 dir_set_scanning(dir
, TRUE
);
904 names
= g_ptr_array_new();
906 /* Make a list of all the names in the directory */
907 while ((info
= g_file_enumerator_next_file(iter
, NULL
, error
)))
913 g_warning("Error scanning directory: %s", (*error
)->message
);
914 g_error_free(*error
);
919 name
= g_file_info_get_attribute_byte_string(info
, G_FILE_ATTRIBUTE_STANDARD_NAME
);
920 g_return_if_fail(name
!= NULL
);
922 if (name
[0] == '.' && (name
[1] == '\0' || (name
[1] == '.' && name
[2] == '\0')))
924 /* Skip '.' and '..' */
928 g_ptr_array_add(names
, g_strdup(name
));
931 g_object_unref(info
);
933 g_object_unref(iter
);
935 /* Compare the list with the current DirItems, removing
936 * any that are missing.
938 remove_missing(dir
, names
);
940 free_recheck_list(dir
);
942 /* For each name found, mark it as needing to be put on the rescan
943 * list at some point in the future.
944 * If the item is new, put a blank place-holder item in the directory.
946 for (i
= 0; i
< names
->len
; i
++)
949 guchar
*name
= names
->pdata
[i
];
951 old
= g_hash_table_lookup(dir
->known_items
, name
);
954 /* This flag is cleared when the item is added
955 * to the rescan list.
957 old
->flags
|= ITEM_FLAG_NEED_RESCAN_QUEUE
;
963 new = diritem_new(name
);
964 g_ptr_array_add(dir
->new_items
, new);
971 /* Ask everyone which items they need to display, and add them to
972 * the recheck list. Typically, this means we don't waste time
973 * scanning hidden items.
976 for (next
= dir
->users
; next
; next
= next
->next
)
978 DirUser
*user
= (DirUser
*) next
->data
;
980 DIR_QUEUE_INTERESTING
,
985 g_ptr_array_free(names
, TRUE
);
987 set_idle_callback(dir
);
991 /* Get the names of all files in the directory.
992 * Remove any DirItems that are no longer listed.
993 * Replace the recheck_list with the items found.
995 static void dir_rescan(Directory
*dir
)
997 GError
*error
= NULL
;
999 g_return_if_fail(dir
!= NULL
);
1001 dir
->needs_update
= FALSE
;
1004 mount_update(FALSE
);
1007 null_g_free(&dir
->error
);
1008 dir_error_changed(dir
);
1011 dir_rescan_internal(dir
, &error
);
1015 dir
->error
= g_strdup(error
->message
);
1016 dir_error_changed(dir
); /* Report on attach */
1017 g_error_free(error
);