You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
gnome-vfs2/desktop-method.c

979 lines
21 KiB

auto-import changelog data from gnome-vfs2-2.2.2-4.src.rpm Mon Feb 24 2003 Elliot Lee <sopwith@redhat.com> - debuginfo rebuild Mon Feb 24 2003 Alexander Larsson <alexl@redhat.com> 2.2.2-3 - Added patch to fix smb crash (#84982) Mon Feb 24 2003 Alexander Larsson <alexl@redhat.com> 2.2.2-2 - Add patch to fix notify race (#84668) Wed Feb 12 2003 Alexander Larsson <alexl@redhat.com> 2.2.2-1 - 2.2.2, fixes bad memleak (#83791) Tue Feb 11 2003 Havoc Pennington <hp@redhat.com> 2.2.1-3 - kill menu editing again, it was very very broken Mon Feb 10 2003 Bill Nottingham <notting@redhat.com> 2.2.1-2 - fix file list (#68226) - prereq GConf2 Mon Feb 10 2003 Alexander Larsson <alexl@redhat.com> 2.2.1-1 - Update to 2.2.1. fixes gnome-theme-manager hang Thu Feb 06 2003 Havoc Pennington <hp@redhat.com> 2.2.0-7 - move to menu editing modules.conf by default, we'll see if it works Tue Jan 28 2003 Matt Wilson <msw@redhat.com> 2.2.0-6 - use LIBTOOL=/usr/bin/libtool Mon Jan 27 2003 Havoc Pennington <hp@redhat.com> - it would help to *install* the stupid menu edit conf file - update the vfolder-hacks patch with some fixes Fri Jan 24 2003 Havoc Pennington <hp@redhat.com> - hack up editable vfolder backend to maybe work (still not the default config file) Wed Jan 22 2003 Havoc Pennington <hp@redhat.com> - include a non-default config file to use new vfolder method - build the new vfolder method Wed Jan 22 2003 Tim Powers <timp@redhat.com> - rebuilt Tue Jan 21 2003 Alexander Larsson <alexl@redhat.com> - Update to 2.2.0 Mon Jan 13 2003 Havoc Pennington <hp@redhat.com> - variation on the subfolders hack to try to fix it Sat Jan 11 2003 Havoc Pennington <hp@redhat.com> - fix bug where empty folders with empty subfolders would still be visible. Sat Jan 11 2003 Havoc Pennington <hp@redhat.com> - finish adapting desktop-method.c to underscore-prefixing action Sat Jan 11 2003 Havoc Pennington <hp@redhat.com> - adapt desktop-method.c to underscore-prefixing action Sat Jan 11 2003 Havoc Pennington <hp@redhat.com> - hardcode <DontShowIfEmpty>, it's stupid to ever override this. Sat Jan 11 2003 Havoc Pennington <hp@redhat.com> - make network:/// use libdesktop.so, and modify libdesktop.so to support it Sat Jan 11 2003 Havoc Pennington <hp@redhat.com> - Revert to George's vfolder backend from gnome-vfs-2.0.2 or so - put back libdesktop.so - don't build the new vfolder backend Wed Jan 08 2003 Alexander Larsson <alexl@redhat.com> 2.1.6-2 - Removed __libdir fix that was fixed upstream Wed Jan 08 2003 Alexander Larsson <alexl@redhat.com> 2.1.6-1 - Update to 2.1.6 Tue Jan 07 2003 Nalin Dahyabhai <nalin@redhat.com> 2.1.5-3 - rebuild Mon Dec 16 2002 Tim Powers <timp@redhat.com> 2.1.5-2 - rebuild Mon Dec 16 2002 Alexander Larsson <alexl@redhat.com> 2.1.5-1 - Update to 2.1.5 Thu Dec 12 2002 Nalin Dahyabhai <nalin@redhat.com> - use OpenSSL's pkg-config information, if available
20 years ago
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: 8; c-basic-offset: 8 -*- */
/* desktop-method.c
Copyright (C) 2001 Red Hat, Inc.
The Gnome Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The Gnome Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the Gnome Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
/* URI scheme for remapping directories under magic URIs, used
* for the magic desktop file directories such as start-here.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <glib.h>
#include <sys/types.h>
#include <dirent.h>
#include <errno.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <libgnomevfs/gnome-vfs-mime.h>
#include <libgnomevfs/gnome-vfs-module.h>
#include <libgnomevfs/gnome-vfs-method.h>
#include <libgnomevfs/gnome-vfs-utils.h>
#include <libgnomevfs/gnome-vfs-ops.h>
#include <libgnomevfs/gnome-vfs-module-shared.h>
#include <libgnomevfs/gnome-vfs-monitor-private.h>
/* FIXME Maybe when chaining to file:, we should call the gnome-vfs wrapper
* functions, instead of the file: methods directly.
*/
#define N_ELEMENTS(arr) (sizeof (arr) / sizeof ((arr)[0]))
static GnomeVFSURI* desktop_uri_to_file_uri (GnomeVFSURI *desktop_uri);
static GnomeVFSResult open_merged_directory (GnomeVFSMethod *method,
GnomeVFSMethodHandle **method_handle,
GnomeVFSURI *uri,
GnomeVFSFileInfoOptions options,
GnomeVFSContext *context);
static char* create_file_uri_in_dir (const char *dir,
const char *filename);
static GnomeVFSMethod *parent_method = NULL;
static GnomeVFSResult
do_open (GnomeVFSMethod *method,
GnomeVFSMethodHandle **method_handle,
GnomeVFSURI *uri,
GnomeVFSOpenMode mode,
GnomeVFSContext *context)
{
GnomeVFSURI *file_uri;
GnomeVFSResult result;
file_uri = desktop_uri_to_file_uri (uri);
result = (* parent_method->open) (parent_method,
method_handle,
file_uri,
mode,
context);
gnome_vfs_uri_unref (file_uri);
return result;
}
static GnomeVFSResult
do_create (GnomeVFSMethod *method,
GnomeVFSMethodHandle **method_handle,
GnomeVFSURI *uri,
GnomeVFSOpenMode mode,
gboolean exclusive,
guint perm,
GnomeVFSContext *context)
{
GnomeVFSURI *file_uri;
GnomeVFSResult result;
file_uri = desktop_uri_to_file_uri (uri);
result = (* parent_method->create) (parent_method,
method_handle,
file_uri,
mode,
exclusive,
perm,
context);
gnome_vfs_uri_unref (file_uri);
return result;
}
static GnomeVFSResult
do_close (GnomeVFSMethod *method,
GnomeVFSMethodHandle *method_handle,
GnomeVFSContext *context)
{
GnomeVFSResult result;
result = (* parent_method->close) (parent_method,
method_handle,
context);
return result;
}
static GnomeVFSResult
do_read (GnomeVFSMethod *method,
GnomeVFSMethodHandle *method_handle,
gpointer buffer,
GnomeVFSFileSize num_bytes,
GnomeVFSFileSize *bytes_read,
GnomeVFSContext *context)
{
GnomeVFSResult result;
result = (* parent_method->read) (parent_method,
method_handle,
buffer, num_bytes,
bytes_read,
context);
return result;
}
static GnomeVFSResult
do_write (GnomeVFSMethod *method,
GnomeVFSMethodHandle *method_handle,
gconstpointer buffer,
GnomeVFSFileSize num_bytes,
GnomeVFSFileSize *bytes_written,
GnomeVFSContext *context)
{
GnomeVFSResult result;
result = (* parent_method->write) (parent_method,
method_handle,
buffer, num_bytes,
bytes_written,
context);
return result;
}
static GnomeVFSResult
do_seek (GnomeVFSMethod *method,
GnomeVFSMethodHandle *method_handle,
GnomeVFSSeekPosition whence,
GnomeVFSFileOffset offset,
GnomeVFSContext *context)
{
GnomeVFSResult result;
result = (* parent_method->seek) (parent_method,
method_handle,
whence, offset,
context);
return result;
}
static GnomeVFSResult
do_tell (GnomeVFSMethod *method,
GnomeVFSMethodHandle *method_handle,
GnomeVFSFileOffset *offset_return)
{
GnomeVFSResult result;
result = (* parent_method->tell) (parent_method,
method_handle,
offset_return);
return result;
}
static GnomeVFSResult
do_truncate_handle (GnomeVFSMethod *method,
GnomeVFSMethodHandle *method_handle,
GnomeVFSFileSize where,
GnomeVFSContext *context)
{
GnomeVFSResult result;
result = (* parent_method->truncate_handle) (parent_method,
method_handle,
where,
context);
return result;
}
static GnomeVFSResult
do_truncate (GnomeVFSMethod *method,
GnomeVFSURI *uri,
GnomeVFSFileSize where,
GnomeVFSContext *context)
{
GnomeVFSURI *file_uri;
GnomeVFSResult result;
file_uri = desktop_uri_to_file_uri (uri);
result = (* parent_method->truncate) (parent_method,
file_uri,
where,
context);
gnome_vfs_uri_unref (file_uri);
return result;
}
typedef struct _DirHandle DirHandle;
struct _DirHandle
{
GSList *next;
GSList *handles;
};
static GnomeVFSResult
do_open_directory (GnomeVFSMethod *method,
GnomeVFSMethodHandle **method_handle,
GnomeVFSURI *uri,
GnomeVFSFileInfoOptions options,
GnomeVFSContext *context)
{
return open_merged_directory (method, method_handle,
uri, options, context);
}
static GnomeVFSResult
do_close_directory (GnomeVFSMethod *method,
GnomeVFSMethodHandle *method_handle,
GnomeVFSContext *context)
{
GnomeVFSResult result;
GSList *tmp;
DirHandle *dh;
dh = (DirHandle*) method_handle;
result = GNOME_VFS_OK;
tmp = dh->handles;
while (tmp != NULL) {
GnomeVFSResult this_result;
this_result = (* parent_method->close_directory) (parent_method,
tmp->data,
context);
if (this_result != GNOME_VFS_OK)
result = this_result;
tmp = tmp->next;
}
g_slist_free (dh->handles);
g_free (dh);
return result;
}
static GnomeVFSResult
do_read_directory (GnomeVFSMethod *method,
GnomeVFSMethodHandle *method_handle,
GnomeVFSFileInfo *file_info,
GnomeVFSContext *context)
{
GnomeVFSResult result;
GnomeVFSMethodHandle *parent_handle;
DirHandle *dh;
dh = (DirHandle*) method_handle;
if (dh->next == NULL) {
return GNOME_VFS_ERROR_EOF;
}
next:
parent_handle = dh->next->data;
result = (* parent_method->read_directory) (parent_method,
parent_handle,
file_info,
context);
if (result != GNOME_VFS_OK) {
dh->next = dh->next->next;
if (dh->next)
goto next;
else
return result;
} else {
return GNOME_VFS_OK;
}
}
static void
set_directory_mime_type (GnomeVFSFileInfo *file_info)
{
g_free (file_info->mime_type);
file_info->mime_type = g_strdup ("x-directory/vfolder-desktop");
file_info->valid_fields |= GNOME_VFS_FILE_INFO_FIELDS_MIME_TYPE;
}
static GnomeVFSResult
do_get_file_info (GnomeVFSMethod *method,
GnomeVFSURI *uri,
GnomeVFSFileInfo *file_info,
GnomeVFSFileInfoOptions options,
GnomeVFSContext *context)
{
GnomeVFSURI *file_uri;
GnomeVFSResult result;
file_uri = desktop_uri_to_file_uri (uri);
result = (* parent_method->get_file_info) (parent_method,
file_uri,
file_info,
options,
context);
if (file_info->type == GNOME_VFS_FILE_TYPE_DIRECTORY)
set_directory_mime_type (file_info);
gnome_vfs_uri_unref (file_uri);
return result;
}
static GnomeVFSResult
do_get_file_info_from_handle (GnomeVFSMethod *method,
GnomeVFSMethodHandle *method_handle,
GnomeVFSFileInfo *file_info,
GnomeVFSFileInfoOptions options,
GnomeVFSContext *context)
{
GnomeVFSResult result;
result = (* parent_method->get_file_info_from_handle) (parent_method,
method_handle,
file_info,
options,
context);
if (file_info->type == GNOME_VFS_FILE_TYPE_DIRECTORY)
set_directory_mime_type (file_info);
return result;
}
static gboolean
do_is_local (GnomeVFSMethod *method,
const GnomeVFSURI *uri)
{
return TRUE;
}
static GnomeVFSResult
do_make_directory (GnomeVFSMethod *method,
GnomeVFSURI *uri,
guint perm,
GnomeVFSContext *context)
{
GnomeVFSURI *file_uri;
GnomeVFSResult result;
file_uri = desktop_uri_to_file_uri (uri);
result = (* parent_method->make_directory) (parent_method,
file_uri,
perm,
context);
gnome_vfs_uri_unref (file_uri);
return result;
}
static GnomeVFSResult
do_remove_directory (GnomeVFSMethod *method,
GnomeVFSURI *uri,
GnomeVFSContext *context)
{
GnomeVFSURI *file_uri;
GnomeVFSResult result;
file_uri = desktop_uri_to_file_uri (uri);
result = (* parent_method->remove_directory) (parent_method,
file_uri,
context);
gnome_vfs_uri_unref (file_uri);
return result;
}
static GnomeVFSResult
do_find_directory (GnomeVFSMethod *method,
GnomeVFSURI *near_uri,
GnomeVFSFindDirectoryKind kind,
GnomeVFSURI **result_uri,
gboolean create_if_needed,
gboolean find_if_needed,
guint permissions,
GnomeVFSContext *context)
{
GnomeVFSURI *file_uri;
GnomeVFSURI *file_result_uri;
GnomeVFSResult result;
file_result_uri = NULL;
file_uri = desktop_uri_to_file_uri (near_uri);
result = (* parent_method->find_directory) (parent_method,
file_uri,
kind,
&file_result_uri,
create_if_needed,
find_if_needed,
permissions,
context);
gnome_vfs_uri_unref (file_uri);
if (result_uri)
*result_uri = file_result_uri;
if (file_result_uri == NULL)
result = GNOME_VFS_ERROR_NOT_FOUND;
return result;
}
static GnomeVFSResult
do_move (GnomeVFSMethod *method,
GnomeVFSURI *old_uri,
GnomeVFSURI *new_uri,
gboolean force_replace,
GnomeVFSContext *context)
{
GnomeVFSURI *old_file_uri;
GnomeVFSURI *new_file_uri;
GnomeVFSResult result;
old_file_uri = desktop_uri_to_file_uri (old_uri);
new_file_uri = desktop_uri_to_file_uri (new_uri);
result = (* parent_method->move) (parent_method,
old_file_uri,
new_file_uri,
force_replace,
context);
gnome_vfs_uri_unref (old_file_uri);
gnome_vfs_uri_unref (new_file_uri);
return result;
}
static GnomeVFSResult
do_unlink (GnomeVFSMethod *method,
GnomeVFSURI *uri,
GnomeVFSContext *context)
{
GnomeVFSURI *file_uri;
GnomeVFSResult result;
file_uri = desktop_uri_to_file_uri (uri);
result = (* parent_method->unlink) (parent_method,
file_uri,
context);
gnome_vfs_uri_unref (file_uri);
return result;
}
static GnomeVFSResult
do_create_symbolic_link (GnomeVFSMethod *method,
GnomeVFSURI *uri,
const char *target_reference,
GnomeVFSContext *context)
{
GnomeVFSURI *file_uri;
GnomeVFSResult result;
file_uri = desktop_uri_to_file_uri (uri);
result = (* parent_method->create_symbolic_link) (parent_method,
file_uri,
target_reference,
context);
gnome_vfs_uri_unref (file_uri);
return result;
}
static GnomeVFSResult
do_check_same_fs (GnomeVFSMethod *method,
GnomeVFSURI *source_uri,
GnomeVFSURI *target_uri,
gboolean *same_fs_return,
GnomeVFSContext *context)
{
GnomeVFSURI *source_file_uri;
GnomeVFSURI *target_file_uri;
GnomeVFSResult result;
source_file_uri = desktop_uri_to_file_uri (source_uri);
target_file_uri = desktop_uri_to_file_uri (target_uri);
result = (* parent_method->check_same_fs) (parent_method,
source_file_uri,
target_file_uri,
same_fs_return,
context);
gnome_vfs_uri_unref (source_file_uri);
gnome_vfs_uri_unref (target_file_uri);
return result;
}
static GnomeVFSResult
do_set_file_info (GnomeVFSMethod *method,
GnomeVFSURI *uri,
const GnomeVFSFileInfo *info,
GnomeVFSSetFileInfoMask mask,
GnomeVFSContext *context)
{
GnomeVFSURI *file_uri;
GnomeVFSResult result;
file_uri = desktop_uri_to_file_uri (uri);
result = (* parent_method->set_file_info) (parent_method,
file_uri,
info,
mask,
context);
gnome_vfs_uri_unref (file_uri);
return result;
}
typedef struct {
GnomeVFSMonitorHandle *handle;
GnomeVFSURI *desktop_uri;
} DesktopMonitorHandle;
static void
monitor_notify_cb (GnomeVFSMonitorHandle *handle,
const gchar *monitor_uri,
const gchar *info_uri,
GnomeVFSMonitorEventType event_type,
gpointer user_data)
{
DesktopMonitorHandle *monitor_handle;
GnomeVFSURI *desktop_info_uri;
const gchar *uri_diff;
gint monitor_uri_len;
monitor_handle = (DesktopMonitorHandle *) user_data;
desktop_info_uri = NULL;
monitor_uri_len = strlen (monitor_uri);
if (info_uri != NULL &&
strncmp (info_uri, monitor_uri, monitor_uri_len) == 0) {
uri_diff = &info_uri [monitor_uri_len];
if (*uri_diff != '\0') {
desktop_info_uri =
gnome_vfs_uri_append_string (
monitor_handle->desktop_uri,
uri_diff);
} else {
desktop_info_uri = monitor_handle->desktop_uri;
gnome_vfs_uri_ref (desktop_info_uri);
}
}
gnome_vfs_monitor_callback ((GnomeVFSMethodHandle *) monitor_handle,
desktop_info_uri,
event_type);
gnome_vfs_uri_unref (desktop_info_uri);
}
static GnomeVFSResult
do_monitor_add (GnomeVFSMethod *method,
GnomeVFSMethodHandle **method_handle_return,
GnomeVFSURI *uri,
GnomeVFSMonitorType monitor_type)
{
DesktopMonitorHandle *monitor_handle;
GnomeVFSURI *file_uri;
GnomeVFSResult result;
monitor_handle = g_new0 (DesktopMonitorHandle, 1);
monitor_handle->desktop_uri = uri;
gnome_vfs_uri_ref (uri);
file_uri = desktop_uri_to_file_uri (uri);
result = gnome_vfs_monitor_do_add (parent_method,
&monitor_handle->handle,
file_uri,
monitor_type,
monitor_notify_cb,
monitor_handle);
gnome_vfs_uri_unref (file_uri);
if (result != GNOME_VFS_OK) {
gnome_vfs_uri_unref (monitor_handle->desktop_uri);
g_free (monitor_handle);
}
*method_handle_return = (GnomeVFSMethodHandle *) monitor_handle;
return result;
}
static GnomeVFSResult
do_monitor_cancel (GnomeVFSMethod *method,
GnomeVFSMethodHandle *method_handle)
{
DesktopMonitorHandle *monitor_handle;
GnomeVFSResult result;
monitor_handle = (DesktopMonitorHandle *) method_handle;
result = gnome_vfs_monitor_do_cancel (monitor_handle->handle);
gnome_vfs_uri_unref (monitor_handle->desktop_uri);
g_free (monitor_handle);
return result;
}
/* gnome-vfs bureaucracy */
static GnomeVFSMethod method = {
sizeof (GnomeVFSMethod),
do_open,
do_create,
do_close,
do_read,
do_write,
do_seek,
do_tell,
do_truncate_handle,
do_open_directory,
do_close_directory,
do_read_directory,
do_get_file_info,
do_get_file_info_from_handle,
do_is_local,
do_make_directory,
do_remove_directory,
do_move,
do_unlink,
do_check_same_fs,
do_set_file_info,
do_truncate,
do_find_directory,
do_create_symbolic_link,
do_monitor_add,
do_monitor_cancel
};
typedef enum
{
SCHEME_FAVORITES,
SCHEME_PREFERENCES,
SCHEME_START_HERE,
SCHEME_SYSTEM_SETTINGS,
SCHEME_SERVER_SETTINGS,
SCHEME_PROGRAMS
} SchemeID;
#define MAX_DIRECTORIES 3
#define DIRECTORIES_INITIALIZER { NULL, NULL, NULL }
typedef struct _SchemeDescription SchemeDescription;
struct _SchemeDescription
{
SchemeID id;
const char *scheme;
char *directories[MAX_DIRECTORIES];
};
static SchemeDescription schemes[] =
{
{ SCHEME_FAVORITES, "favorites",
DIRECTORIES_INITIALIZER },
{ SCHEME_PREFERENCES, "preferences",
DIRECTORIES_INITIALIZER },
{ SCHEME_START_HERE, "start-here",
DIRECTORIES_INITIALIZER },
{ SCHEME_SYSTEM_SETTINGS, "system-settings",
DIRECTORIES_INITIALIZER },
{ SCHEME_SERVER_SETTINGS, "server-settings",
DIRECTORIES_INITIALIZER },
{ SCHEME_PROGRAMS, "programs",
DIRECTORIES_INITIALIZER }
};
GnomeVFSMethod *
vfs_module_init (const char *method_name,
const char *args)
{
int i;
parent_method = gnome_vfs_method_get ("file");
if (parent_method == NULL) {
g_error ("Could not find 'file' method for gnome-vfs");
return NULL;
}
i = 0;
while (i < N_ELEMENTS (schemes)) {
switch (schemes[i].id) {
case SCHEME_FAVORITES:
schemes[i].directories[0] =
g_strconcat (g_get_home_dir (),
"/.gnome/apps",
NULL);
break;
case SCHEME_PREFERENCES:
/* FIXME I think the GNOME 2 control center will move
* this, but we don't know where to yet
*/
schemes[i].directories[0] =
g_strconcat (DATADIR, "/control-center/capplets", NULL);
break;
case SCHEME_START_HERE:
schemes[i].directories[0] = g_strconcat (SYSCONFDIR,
"/X11/starthere",
NULL);
break;
case SCHEME_SYSTEM_SETTINGS:
schemes[i].directories[0] =
g_strconcat (SYSCONFDIR, "/X11/sysconfig", NULL);
break;
case SCHEME_SERVER_SETTINGS:
schemes[i].directories[0] =
g_strconcat (SYSCONFDIR, "/X11/serverconfig", NULL);
break;
case SCHEME_PROGRAMS:
schemes[i].directories[0] = g_strconcat (SYSCONFDIR,
"/X11/applnk",
NULL);
schemes[i].directories[1] =
g_strconcat (DATADIR, "gnome/apps", NULL);
break;
default:
g_assert_not_reached ();
break;
}
++i;
}
return &method;
}
void
vfs_module_shutdown (GnomeVFSMethod *method)
{
int i;
i = 0;
while (i < N_ELEMENTS (schemes)) {
int j;
j = 0;
while (j < MAX_DIRECTORIES) {
g_free (schemes[i].directories[j]);
schemes[i].directories[j] = NULL;
++j;
}
++i;
}
}
static const SchemeDescription*
get_desc_for_uri (GnomeVFSURI *desktop_uri)
{
const SchemeDescription *desc;
int i;
const char *scheme;
scheme = gnome_vfs_uri_get_scheme (desktop_uri);
desc = NULL;
i = 0;
while (i < N_ELEMENTS (schemes)) {
if (strcmp (schemes[i].scheme, scheme) == 0) {
desc = &schemes[i];
break;
}
++i;
}
return desc;
}
static GnomeVFSURI*
desktop_uri_to_file_uri (GnomeVFSURI *desktop_uri)
{
const SchemeDescription *desc;
GnomeVFSURI *new_uri;
const char *path;
int i;
desc = get_desc_for_uri (desktop_uri);
if (desc == NULL) {
gnome_vfs_uri_ref (desktop_uri);
return desktop_uri;
}
/* Prepend the base for the desktop URI.
* If the SchemeDescription contains > 1 directory, we use the directory
* after the first if the given file actually exists there.
*/
new_uri = NULL;
path = gnome_vfs_uri_get_path (desktop_uri);
i = 0;
while (desc->directories[i])
++i;
do {
char *s;
--i;
s = create_file_uri_in_dir (desc->directories[i], path);
new_uri = gnome_vfs_uri_new (s);
g_free (s);
if (i == 0 ||
gnome_vfs_uri_exists (new_uri)) {
return new_uri;
} else {
gnome_vfs_uri_unref (new_uri);
new_uri = NULL;
}
} while (i > 0);
g_assert_not_reached ();
return NULL;
}
static GnomeVFSResult
open_merged_directory (GnomeVFSMethod *method,
GnomeVFSMethodHandle **method_handle,
GnomeVFSURI *desktop_uri,
GnomeVFSFileInfoOptions options,
GnomeVFSContext *context)
{
GnomeVFSResult result;
DirHandle *dh;
const SchemeDescription *desc;
int i;
gboolean found;
const char *path;
desc = get_desc_for_uri (desktop_uri);
if (desc == NULL) {
return GNOME_VFS_ERROR_NOT_FOUND;
}
dh = g_new0 (DirHandle, 1);
/* Prepend the base for the desktop URI.
* If the SchemeDescription contains > 1 directory, we use the directory
* after the first if the given file actually exists there.
*/
found = FALSE;
path = gnome_vfs_uri_get_path (desktop_uri);
i = 0;
while (desc->directories[i]) {
char *s;
GnomeVFSURI *file_uri;
GnomeVFSMethodHandle *parent_handle = NULL;
s = create_file_uri_in_dir (desc->directories[i], path);
file_uri = gnome_vfs_uri_new (s);
g_free (s);
result = (* parent_method->open_directory) (parent_method,
&parent_handle,
file_uri,
options,
context);
if (result == GNOME_VFS_OK) {
found = TRUE;
dh->handles = g_slist_prepend (dh->handles, parent_handle);
}
gnome_vfs_uri_unref (file_uri);
++i;
}
dh->next = dh->handles;
*method_handle = (GnomeVFSMethodHandle*) dh;
return found ? GNOME_VFS_OK : GNOME_VFS_ERROR_NOT_FOUND;
}
static char*
create_file_uri_in_dir (const char *dir,
const char *filename)
{
char *dir_uri;
char *retval;
dir_uri = gnome_vfs_get_uri_from_local_path (dir);
retval = g_strconcat (dir_uri, "/", filename, NULL);
g_free (dir_uri);
return retval;
}