medit/moo/moofileview/moofilesystem.c

1207 lines
34 KiB
C
Raw Normal View History

2006-05-21 18:11:05 -05:00
/*
* moofilesystem.c
2005-08-25 09:29:01 +00:00
*
2010-12-21 20:15:45 -08:00
* Copyright (C) 2004-2010 by Yevgen Muntyan <emuntyan@users.sourceforge.net>
2005-08-25 09:29:01 +00:00
*
* This file is part of medit. medit is free software; you can
* redistribute it and/or modify it under the terms of the
* GNU Lesser General Public License as published by the
* Free Software Foundation; either version 2.1 of the License,
* or (at your option) any later version.
2005-08-25 09:29:01 +00:00
*
* You should have received a copy of the GNU Lesser General Public
* License along with medit. If not, see <http://www.gnu.org/licenses/>.
2005-08-25 09:29:01 +00:00
*/
2006-12-10 16:48:59 -06:00
#include <config.h>
2005-08-25 09:29:01 +00:00
#include "moofilesystem.h"
#include "moofolder-private.h"
#include "mooutils/mooutils-fs.h"
2008-01-18 21:45:53 -06:00
#include "mooutils/mooutils-mem.h"
#include "mooutils/mooutils.h"
#include "marshals.h"
2008-11-26 22:50:19 -06:00
#include <gio/gio.h>
2005-08-25 09:29:01 +00:00
#include <stdio.h>
#ifndef __WIN32__
#include <sys/wait.h>
#else
2008-02-10 12:55:20 -06:00
#include <windows.h>
2005-08-25 09:29:01 +00:00
#include <io.h>
2008-02-10 12:55:20 -06:00
#include <shellapi.h>
2005-08-25 09:29:01 +00:00
#endif
2009-11-14 22:16:05 -08:00
#if 0 && MOO_DEBUG
2006-12-10 16:48:59 -06:00
#define DEBUG_MESSAGE g_message
#else
2008-06-08 14:54:36 -05:00
static void G_GNUC_PRINTF(1,2) DEBUG_MESSAGE (G_GNUC_UNUSED const char *format, ...)
2006-12-10 16:48:59 -06:00
{
}
#endif
2006-04-16 12:14:12 -05:00
#define BROKEN_NAME "<" "????" ">"
#define FOLDERS_CACHE_SIZE 10
typedef struct {
GQueue *queue;
GHashTable *paths;
} FoldersCache;
2005-08-25 09:29:01 +00:00
struct _MooFileSystemPrivate {
GHashTable *folders;
MooFileWatch *fam;
FoldersCache cache;
guint debug_timeout;
2005-08-25 09:29:01 +00:00
};
static MooFileSystem *fs_instance = NULL;
static void moo_file_system_dispose (GObject *object);
static char *_moo_file_system_normalize_path (MooFileSystem *fs,
const char *path,
gboolean is_folder,
GError **error);
2005-08-25 09:29:01 +00:00
static MooFolder *get_folder (MooFileSystem *fs,
const char *path,
MooFileFlags wanted,
GError **error);
static gboolean create_folder (MooFileSystem *fs,
const char *path,
GError **error);
2006-03-10 22:41:41 -06:00
static MooFolder *get_parent_folder (MooFileSystem *fs,
MooFolder *folder,
MooFileFlags flags);
2006-04-16 12:14:12 -05:00
static gboolean delete_file (MooFileSystem *fs,
const char *path,
2008-09-07 10:56:37 -05:00
MooDeleteFileFlags flags,
2006-04-16 12:14:12 -05:00
GError **error);
2005-08-25 09:29:01 +00:00
static gboolean move_file_unix (MooFileSystem *fs,
const char *old_path,
const char *new_path,
GError **error);
2007-01-04 04:42:10 -06:00
#ifndef __WIN32__
static MooFolder *get_root_folder_unix (MooFileSystem *fs,
MooFileFlags wanted);
2005-08-25 09:29:01 +00:00
static char *normalize_path_unix (MooFileSystem *fs,
const char *path,
gboolean is_folder,
GError **error);
static char *make_path_unix (MooFileSystem *fs,
const char *base_path,
const char *display_name,
GError **error);
static gboolean parse_path_unix (MooFileSystem *fs,
const char *path_utf8,
char **dirname,
char **display_dirname,
char **display_basename,
GError **error);
2005-09-02 23:27:25 +00:00
static char *get_absolute_path_unix (MooFileSystem *fs,
const char *display_name,
const char *current_dir);
2005-08-25 09:29:01 +00:00
#else /* __WIN32__ */
static MooFolder *get_root_folder_win32 (MooFileSystem *fs,
MooFileFlags wanted);
2007-01-04 04:42:10 -06:00
#if 0
2005-08-25 09:29:01 +00:00
static gboolean move_file_win32 (MooFileSystem *fs,
const char *old_path,
const char *new_path,
GError **error);
2007-01-04 04:42:10 -06:00
#endif
2005-08-25 09:29:01 +00:00
static char *normalize_path_win32 (MooFileSystem *fs,
const char *path,
gboolean is_folder,
GError **error);
static char *make_path_win32 (MooFileSystem *fs,
const char *base_path,
const char *display_name,
GError **error);
static gboolean parse_path_win32 (MooFileSystem *fs,
const char *path_utf8,
char **dirname,
char **display_dirname,
char **display_basename,
GError **error);
2005-09-02 23:27:25 +00:00
static char *get_absolute_path_win32 (MooFileSystem *fs,
const char *display_name,
const char *current_dir);
2005-08-25 09:29:01 +00:00
#endif /* __WIN32__ */
/* MOO_TYPE_FILE_SYSTEM */
G_DEFINE_TYPE (MooFileSystem, _moo_file_system, G_TYPE_OBJECT)
2005-08-25 09:29:01 +00:00
static void
_moo_file_system_class_init (MooFileSystemClass *klass)
2005-08-25 09:29:01 +00:00
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->dispose = moo_file_system_dispose;
2005-08-25 09:29:01 +00:00
klass->get_folder = get_folder;
klass->create_folder = create_folder;
2006-03-10 22:41:41 -06:00
klass->get_parent_folder = get_parent_folder;
2006-04-16 12:14:12 -05:00
klass->delete_file = delete_file;
2005-08-25 09:29:01 +00:00
#ifdef __WIN32__
klass->get_root_folder = get_root_folder_win32;
2007-01-04 04:42:10 -06:00
klass->move_file = move_file_unix;
2005-08-25 09:29:01 +00:00
klass->normalize_path = normalize_path_win32;
klass->make_path = make_path_win32;
klass->parse_path = parse_path_win32;
2005-09-02 23:27:25 +00:00
klass->get_absolute_path = get_absolute_path_win32;
2005-08-25 09:29:01 +00:00
#else /* !__WIN32__ */
klass->get_root_folder = get_root_folder_unix;
klass->move_file = move_file_unix;
klass->normalize_path = normalize_path_unix;
klass->make_path = make_path_unix;
klass->parse_path = parse_path_unix;
2005-09-02 23:27:25 +00:00
klass->get_absolute_path = get_absolute_path_unix;
2005-08-25 09:29:01 +00:00
#endif /* !__WIN32__ */
}
static void
add_folder_cache (MooFileSystem *fs,
MooFolderImpl *impl)
{
FoldersCache *cache = &fs->priv->cache;
2006-12-10 16:48:59 -06:00
DEBUG_MESSAGE ("%s: adding folder %s to cache", G_STRFUNC, impl->path);
g_queue_push_head (cache->queue, impl);
g_hash_table_insert (cache->paths, impl->path, impl);
if (cache->queue->length > FOLDERS_CACHE_SIZE)
{
MooFolderImpl *old = g_queue_pop_tail (cache->queue);
g_hash_table_remove (cache->paths, old->path);
2006-12-10 16:48:59 -06:00
DEBUG_MESSAGE ("%s: removing folder %s from cache", G_STRFUNC, old->path);
_moo_folder_impl_free (old);
}
}
void
_moo_file_system_folder_finalized (MooFileSystem *fs,
MooFolder *folder)
{
MooFolderImpl *impl;
g_return_if_fail (MOO_IS_FILE_SYSTEM (fs));
g_return_if_fail (MOO_IS_FOLDER (folder));
impl = folder->impl;
folder->impl = NULL;
impl->proxy = NULL;
g_hash_table_remove (fs->priv->folders, impl->path);
if (!impl->deleted)
2006-12-10 16:48:59 -06:00
{
add_folder_cache (fs, impl);
2006-12-10 16:48:59 -06:00
}
else
2006-12-10 16:48:59 -06:00
{
DEBUG_MESSAGE ("%s: folder %s deleted, freeing", G_STRFUNC, impl->path);
_moo_folder_impl_free (impl);
2006-12-10 16:48:59 -06:00
}
}
static void
calc_mem_hash_cb (G_GNUC_UNUSED const char *name,
MooFolder *folder,
gsize *mem)
{
mem[0] += _moo_folder_mem_usage (folder);
mem[1] += g_hash_table_size (folder->impl->files);
}
static gboolean
debug_timeout (MooFileSystem *fs)
{
gsize mem[2] = {0, 0};
g_hash_table_foreach (fs->priv->folders, (GHFunc) calc_mem_hash_cb, mem);
2007-06-20 13:46:39 -05:00
g_print ("%" G_GSIZE_FORMAT " bytes in %" G_GSIZE_FORMAT " files\n", mem[0], mem[1]);
return TRUE;
}
static void
_moo_file_system_init (MooFileSystem *fs)
2005-08-25 09:29:01 +00:00
{
fs->priv = g_new0 (MooFileSystemPrivate, 1);
fs->priv->folders = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
fs->priv->cache.queue = g_queue_new ();
fs->priv->cache.paths = g_hash_table_new (g_str_hash, g_str_equal);
if (0)
fs->priv->debug_timeout = g_timeout_add (5000, (GSourceFunc) debug_timeout, fs);
2005-08-25 09:29:01 +00:00
}
static void
moo_file_system_dispose (GObject *object)
2005-08-25 09:29:01 +00:00
{
MooFileSystem *fs = MOO_FILE_SYSTEM (object);
if (fs->priv)
2005-08-25 09:29:01 +00:00
{
g_hash_table_destroy (fs->priv->folders);
g_hash_table_destroy (fs->priv->cache.paths);
g_queue_foreach (fs->priv->cache.queue, (GFunc) _moo_folder_impl_free, NULL);
g_queue_free (fs->priv->cache.queue);
2005-08-25 09:29:01 +00:00
if (fs->priv->fam)
{
moo_file_watch_close (fs->priv->fam, NULL);
moo_file_watch_unref (fs->priv->fam);
}
if (fs->priv->debug_timeout)
g_source_remove (fs->priv->debug_timeout);
g_free (fs->priv);
fs->priv = NULL;
}
2005-08-25 09:29:01 +00:00
G_OBJECT_CLASS (_moo_file_system_parent_class)->finalize (object);
2005-08-25 09:29:01 +00:00
}
MooFileSystem *
_moo_file_system_create (void)
2005-08-25 09:29:01 +00:00
{
if (!fs_instance)
{
2010-08-12 18:17:00 -07:00
fs_instance = MOO_FILE_SYSTEM (g_object_new (MOO_TYPE_FILE_SYSTEM, (const char*) NULL));
2005-08-25 09:29:01 +00:00
g_object_weak_ref (G_OBJECT (fs_instance),
(GWeakNotify) g_nullify_pointer, &fs_instance);
return fs_instance;
}
else
{
return g_object_ref (fs_instance);
}
}
MooFolder *
_moo_file_system_get_root_folder (MooFileSystem *fs,
MooFileFlags wanted)
2005-08-25 09:29:01 +00:00
{
g_return_val_if_fail (MOO_IS_FILE_SYSTEM (fs), NULL);
return MOO_FILE_SYSTEM_GET_CLASS(fs)->get_root_folder (fs, wanted);
}
MooFolder *
_moo_file_system_get_folder (MooFileSystem *fs,
const char *path,
MooFileFlags wanted,
GError **error)
2005-08-25 09:29:01 +00:00
{
g_return_val_if_fail (MOO_IS_FILE_SYSTEM (fs), NULL);
return MOO_FILE_SYSTEM_GET_CLASS(fs)->get_folder (fs, path, wanted, error);
}
MooFolder *
_moo_file_system_get_parent_folder (MooFileSystem *fs,
MooFolder *folder,
MooFileFlags wanted)
2005-08-25 09:29:01 +00:00
{
g_return_val_if_fail (MOO_IS_FILE_SYSTEM (fs), NULL);
g_return_val_if_fail (MOO_IS_FOLDER (folder), NULL);
return MOO_FILE_SYSTEM_GET_CLASS(fs)->get_parent_folder (fs, folder, wanted);
}
2006-04-16 12:14:12 -05:00
gboolean
_moo_file_system_create_folder (MooFileSystem *fs,
const char *path,
GError **error)
2005-08-25 09:29:01 +00:00
{
g_return_val_if_fail (MOO_IS_FILE_SYSTEM (fs), FALSE);
g_return_val_if_fail (path != NULL, FALSE);
return MOO_FILE_SYSTEM_GET_CLASS(fs)->create_folder (fs, path, error);
}
2006-04-16 12:14:12 -05:00
gboolean
2008-09-07 10:56:37 -05:00
_moo_file_system_delete_file (MooFileSystem *fs,
const char *path,
MooDeleteFileFlags flags,
GError **error)
2005-08-25 09:29:01 +00:00
{
g_return_val_if_fail (MOO_IS_FILE_SYSTEM (fs), FALSE);
g_return_val_if_fail (path != NULL, FALSE);
2008-09-07 10:56:37 -05:00
return MOO_FILE_SYSTEM_GET_CLASS(fs)->delete_file (fs, path, flags, error);
2005-08-25 09:29:01 +00:00
}
2006-04-16 12:14:12 -05:00
gboolean
_moo_file_system_move_file (MooFileSystem *fs,
const char *old_path,
const char *new_path,
GError **error)
2005-08-25 09:29:01 +00:00
{
g_return_val_if_fail (MOO_IS_FILE_SYSTEM (fs), FALSE);
g_return_val_if_fail (old_path && new_path, FALSE);
return MOO_FILE_SYSTEM_GET_CLASS(fs)->move_file (fs, old_path, new_path, error);
}
2006-04-16 12:14:12 -05:00
char *
_moo_file_system_make_path (MooFileSystem *fs,
const char *base_path,
const char *display_name,
GError **error)
2005-08-25 09:29:01 +00:00
{
g_return_val_if_fail (MOO_IS_FILE_SYSTEM (fs), NULL);
g_return_val_if_fail (base_path != NULL && display_name != NULL, NULL);
2005-08-25 09:29:01 +00:00
return MOO_FILE_SYSTEM_GET_CLASS(fs)->make_path (fs, base_path, display_name, error);
}
static char *
_moo_file_system_normalize_path (MooFileSystem *fs,
const char *path,
gboolean is_folder,
GError **error)
2005-08-25 09:29:01 +00:00
{
g_return_val_if_fail (MOO_IS_FILE_SYSTEM (fs), NULL);
g_return_val_if_fail (path != NULL, NULL);
2005-08-25 09:29:01 +00:00
return MOO_FILE_SYSTEM_GET_CLASS(fs)->normalize_path (fs, path, is_folder, error);
}
2006-04-16 12:14:12 -05:00
gboolean
_moo_file_system_parse_path (MooFileSystem *fs,
const char *path_utf8,
char **dirname,
char **display_dirname,
char **display_basename,
GError **error)
2005-08-25 09:29:01 +00:00
{
g_return_val_if_fail (MOO_IS_FILE_SYSTEM (fs), FALSE);
g_return_val_if_fail (path_utf8 != NULL, FALSE);
return MOO_FILE_SYSTEM_GET_CLASS(fs)->parse_path (fs, path_utf8, dirname,
display_dirname, display_basename,
error);
}
2006-04-16 12:14:12 -05:00
char *
_moo_file_system_get_absolute_path (MooFileSystem *fs,
const char *display_name,
const char *current_dir)
2005-09-02 23:27:25 +00:00
{
g_return_val_if_fail (MOO_IS_FILE_SYSTEM (fs), NULL);
g_return_val_if_fail (display_name != NULL, NULL);
return MOO_FILE_SYSTEM_GET_CLASS(fs)->get_absolute_path (fs, display_name, current_dir);
}
2006-04-16 12:14:12 -05:00
MooFileWatch *
_moo_file_system_get_file_watch (MooFileSystem *fs)
2005-08-25 09:29:01 +00:00
{
g_return_val_if_fail (MOO_IS_FILE_SYSTEM (fs), NULL);
if (!fs->priv->fam)
{
GError *error = NULL;
fs->priv->fam = moo_file_watch_new (&error);
if (!fs->priv->fam)
{
g_warning ("moo_fam_open failed: %s", moo_error_message (error));
2005-08-25 09:29:01 +00:00
g_error_free (error);
}
}
return fs->priv->fam;
}
/* TODO what's this? */
void
_moo_file_system_folder_deleted (MooFileSystem *fs,
MooFolderImpl *impl)
2005-08-25 09:29:01 +00:00
{
if (impl->proxy)
{
g_hash_table_remove (fs->priv->folders, impl->path);
2006-12-10 16:48:59 -06:00
DEBUG_MESSAGE ("%s: folder %s deleted, proxy alive", G_STRFUNC, impl->path);
}
else
{
2006-12-10 16:48:59 -06:00
DEBUG_MESSAGE ("%s: cached folder %s deleted, freeing", G_STRFUNC, impl->path);
g_hash_table_remove (fs->priv->cache.paths, impl->path);
g_queue_remove (fs->priv->cache.queue, impl);
_moo_folder_impl_free (impl);
}
2005-08-25 09:29:01 +00:00
}
static MooFolder *
2006-04-16 12:14:12 -05:00
get_folder (MooFileSystem *fs,
const char *path,
MooFileFlags wanted,
GError **error)
2005-08-25 09:29:01 +00:00
{
MooFolder *folder;
MooFolderImpl *impl;
2005-08-25 09:29:01 +00:00
char *norm_path = NULL;
g_return_val_if_fail (path != NULL, NULL);
#ifdef __WIN32__
if (!*path)
2005-08-25 09:29:01 +00:00
return get_root_folder_win32 (fs, wanted);
#endif /* __WIN32__ */
/* XXX check the caller */
2008-01-27 00:07:18 -06:00
if (!_moo_path_is_absolute (path))
{
g_set_error (error, MOO_FILE_ERROR,
MOO_FILE_ERROR_BAD_FILENAME,
"folder path '%s' is not absolute",
path);
return NULL;
}
2005-08-25 09:29:01 +00:00
norm_path = _moo_file_system_normalize_path (fs, path, TRUE, error);
2005-08-25 09:29:01 +00:00
if (!norm_path)
return NULL;
folder = g_hash_table_lookup (fs->priv->folders, norm_path);
if (folder)
{
_moo_folder_set_wanted (folder, wanted, TRUE);
2005-08-25 09:29:01 +00:00
g_object_ref (folder);
goto out;
}
impl = g_hash_table_lookup (fs->priv->cache.paths, norm_path);
if (impl)
{
g_hash_table_remove (fs->priv->cache.paths, impl->path);
g_queue_remove (fs->priv->cache.queue, impl);
folder = _moo_folder_new_with_impl (impl);
g_hash_table_insert (fs->priv->folders, norm_path, folder);
norm_path = NULL;
_moo_folder_set_wanted (folder, wanted, TRUE);
goto out;
}
2005-08-25 09:29:01 +00:00
if (!g_file_test (norm_path, G_FILE_TEST_EXISTS))
{
g_set_error (error, MOO_FILE_ERROR,
MOO_FILE_ERROR_NONEXISTENT,
"'%s' does not exist", norm_path);
folder = NULL;
goto out;
}
if (!g_file_test (norm_path, G_FILE_TEST_IS_DIR))
{
g_set_error (error, MOO_FILE_ERROR,
MOO_FILE_ERROR_NOT_FOLDER,
"'%s' is not a folder", norm_path);
folder = NULL;
goto out;
}
folder = _moo_folder_new (fs, norm_path, wanted, error);
2005-08-25 09:29:01 +00:00
if (folder)
{
g_hash_table_insert (fs->priv->folders, norm_path, folder);
2005-08-25 09:29:01 +00:00
norm_path = NULL;
}
out:
g_free (norm_path);
return folder;
}
/* TODO */
static gboolean
2006-04-16 12:14:12 -05:00
create_folder (G_GNUC_UNUSED MooFileSystem *fs,
const char *path,
GError **error)
2005-08-25 09:29:01 +00:00
{
2015-12-25 21:30:53 -08:00
mgw_errno_t err;
2005-08-25 09:29:01 +00:00
g_return_val_if_fail (path != NULL, FALSE);
/* XXX check the caller */
2008-01-27 00:07:18 -06:00
if (!_moo_path_is_absolute (path))
{
g_set_error (error, MOO_FILE_ERROR,
MOO_FILE_ERROR_BAD_FILENAME,
"folder path '%s' is not absolute",
path);
return FALSE;
}
2005-08-25 09:29:01 +00:00
/* TODO mkdir must (?) adjust permissions according to umask */
#ifndef __WIN32__
2015-12-25 21:30:53 -08:00
if (mgw_mkdir (path, S_IRWXU | S_IRWXG | S_IRWXO, &err))
2005-08-25 09:29:01 +00:00
#else
2015-12-25 21:30:53 -08:00
if (_moo_mkdir (path, &err))
2005-08-25 09:29:01 +00:00
#endif
{
g_set_error (error, MOO_FILE_ERROR,
2015-12-25 21:30:53 -08:00
_moo_file_error_from_errno (err),
"%s", mgw_strerror (err));
2005-08-25 09:29:01 +00:00
return FALSE;
}
return TRUE;
}
/***************************************************************************/
2006-03-10 22:41:41 -06:00
/* common methods
2005-08-25 09:29:01 +00:00
*/
/* folder may be deleted, but this function returns parent
folder anyway, if that exists */
2006-03-10 22:41:41 -06:00
static MooFolder *
get_parent_folder (MooFileSystem *fs,
MooFolder *folder,
MooFileFlags wanted)
2005-08-25 09:29:01 +00:00
{
char *parent_path;
MooFolder *parent;
g_return_val_if_fail (MOO_IS_FILE_SYSTEM (fs), NULL);
g_return_val_if_fail (MOO_IS_FOLDER (folder), NULL);
g_return_val_if_fail (_moo_folder_get_file_system (folder) == fs, NULL);
2005-08-25 09:29:01 +00:00
2006-03-11 01:09:12 -06:00
parent_path = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "..",
_moo_folder_get_path (folder));
2005-08-25 09:29:01 +00:00
parent = _moo_file_system_get_folder (fs, parent_path, wanted, NULL);
2005-08-25 09:29:01 +00:00
g_free (parent_path);
return parent;
}
2006-04-16 11:39:47 -05:00
static char *
normalize_path (const char *path)
{
GPtrArray *comps;
gboolean first_slash;
char **pieces, **p;
char *normpath;
g_return_val_if_fail (path != NULL, NULL);
first_slash = (path[0] == G_DIR_SEPARATOR);
pieces = g_strsplit (path, G_DIR_SEPARATOR_S, 0);
g_return_val_if_fail (pieces != NULL, NULL);
comps = g_ptr_array_new ();
for (p = pieces; *p != NULL; ++p)
{
char *s = *p;
gboolean push = TRUE;
gboolean pop = FALSE;
if (!strcmp (s, "") || !strcmp (s, "."))
{
push = FALSE;
}
else if (!strcmp (s, ".."))
{
if (!comps->len && first_slash)
{
push = FALSE;
}
else if (comps->len)
{
push = FALSE;
pop = TRUE;
}
}
if (pop)
{
g_free (comps->pdata[comps->len - 1]);
g_ptr_array_remove_index (comps, comps->len - 1);
}
if (push)
g_ptr_array_add (comps, g_strdup (s));
}
g_ptr_array_add (comps, NULL);
if (comps->len == 1)
{
if (first_slash)
normpath = g_strdup (G_DIR_SEPARATOR_S);
else
normpath = g_strdup (".");
}
else
{
2008-01-18 21:45:53 -06:00
normpath = g_strjoinv (G_DIR_SEPARATOR_S, (char**) comps->pdata);
2006-04-16 11:39:47 -05:00
if (first_slash)
{
2008-01-18 21:45:53 -06:00
gsize len = strlen (normpath);
normpath = g_renew (char, normpath, len + 2);
memmove (normpath + 1, normpath, len + 1);
2006-04-16 11:39:47 -05:00
normpath[0] = G_DIR_SEPARATOR;
}
}
g_strfreev (pieces);
g_strfreev ((char**) comps->pdata);
g_ptr_array_free (comps, FALSE);
return normpath;
}
2008-02-10 12:55:20 -06:00
#if defined(__WIN32__) && 0
#ifndef FOF_NORECURSION
#define FOF_NORECURSION 0x1000
#endif
static gboolean
delete_file_win32 (const char *path,
gboolean recursive,
GError **error)
{
gboolean success;
SHFILEOPSTRUCT op = {0};
gunichar2 *path_utf16;
long len;
if (!(path_utf16 = g_utf8_to_utf16 (path, -1, NULL, &len, error)))
return FALSE;
path_utf16 = g_renew (gunichar2, path_utf16, len + 2);
path_utf16[len + 1] = 0;
op.wFunc = FO_DELETE;
op.pFrom = path_utf16;
op.fFlags = FOF_ALLOWUNDO;
if (!recursive)
op.fFlags |= FOF_NORECURSION;
success = SHFileOperation (&op) == 0;
if (!success)
g_set_error (error, MOO_FILE_ERROR,
MOO_FILE_ERROR_FAILED,
"Could not delete '%s'",
path);
g_free (path_utf16);
return success;
}
#endif
static gboolean
2006-04-16 12:14:12 -05:00
delete_file (G_GNUC_UNUSED MooFileSystem *fs,
2008-09-07 10:56:37 -05:00
const char *path,
MooDeleteFileFlags flags,
GError **error)
2006-04-16 12:14:12 -05:00
{
gboolean isdir;
2015-12-25 21:30:53 -08:00
mgw_errno_t err;
2006-04-16 12:14:12 -05:00
g_return_val_if_fail (path != NULL, FALSE);
2008-01-27 00:07:18 -06:00
g_return_val_if_fail (_moo_path_is_absolute (path), FALSE);
2008-09-07 10:56:37 -05:00
g_return_val_if_fail (!error || !*error, FALSE);
if (flags & MOO_DELETE_TO_TRASH)
{
GFile *file = g_file_new_for_path (path);
gboolean retval = g_file_trash (file, NULL, error);
g_object_unref (file);
return retval;
}
2006-04-16 12:14:12 -05:00
2008-02-10 12:55:20 -06:00
#if defined(__WIN32__) && 0
2008-09-07 10:56:37 -05:00
return delete_file_win32 (path, (flags & MOO_DELETE_RECURSIVE) != 0, error);
2008-02-10 12:55:20 -06:00
#endif
2006-04-16 12:14:12 -05:00
if (g_file_test (path, G_FILE_TEST_IS_SYMLINK))
isdir = FALSE;
else
isdir = g_file_test (path, G_FILE_TEST_IS_DIR);
if (isdir)
2008-09-07 10:56:37 -05:00
return _moo_remove_dir (path, (flags & MOO_DELETE_RECURSIVE) != 0, error);
2006-04-16 12:14:12 -05:00
2015-12-25 21:30:53 -08:00
if (mgw_remove (path, &err) != 0)
2006-04-16 12:14:12 -05:00
{
char *path_utf8 = g_filename_display_name (path);
2006-04-16 12:14:12 -05:00
g_set_error (error, MOO_FILE_ERROR,
_moo_file_error_from_errno (err),
2006-04-16 12:14:12 -05:00
"Could not delete file '%s': %s",
path_utf8 ? path_utf8 : BROKEN_NAME,
2015-12-25 21:30:53 -08:00
mgw_strerror (err));
2006-04-16 12:14:12 -05:00
g_free (path_utf8);
return FALSE;
}
return TRUE;
}
2006-03-10 22:41:41 -06:00
/***************************************************************************/
/* UNIX methods
*/
static gboolean
move_file_unix (G_GNUC_UNUSED MooFileSystem *fs,
const char *old_path,
const char *new_path,
GError **error)
2005-08-25 09:29:01 +00:00
{
2015-12-25 21:30:53 -08:00
mgw_errno_t err;
2005-08-25 09:29:01 +00:00
g_return_val_if_fail (old_path && new_path, FALSE);
2008-01-27 00:07:18 -06:00
g_return_val_if_fail (_moo_path_is_absolute (old_path), FALSE);
g_return_val_if_fail (_moo_path_is_absolute (new_path), FALSE);
2005-08-25 09:29:01 +00:00
/* XXX */
2015-12-25 21:30:53 -08:00
if (_moo_rename (old_path, new_path, &err))
2005-08-25 09:29:01 +00:00
{
g_set_error (error, MOO_FILE_ERROR,
2015-12-25 21:30:53 -08:00
_moo_file_error_from_errno (err),
"%s", mgw_strerror (err));
2005-08-25 09:29:01 +00:00
return FALSE;
}
return TRUE;
}
2007-01-04 04:42:10 -06:00
#ifndef __WIN32__
static MooFolder *
get_root_folder_unix (MooFileSystem *fs,
MooFileFlags wanted)
{
return _moo_file_system_get_folder (fs, "/", wanted, NULL);
}
static char *
make_path_unix (G_GNUC_UNUSED MooFileSystem *fs,
const char *base_path,
const char *display_name,
GError **error)
2005-08-25 09:29:01 +00:00
{
GError *error_here = NULL;
char *path, *name;
2006-04-16 11:39:47 -05:00
g_return_val_if_fail (base_path != NULL, NULL);
g_return_val_if_fail (display_name != NULL, NULL);
2005-08-25 09:29:01 +00:00
/* XXX check the caller */
2008-01-27 00:07:18 -06:00
if (!_moo_path_is_absolute (base_path))
{
g_set_error (error, MOO_FILE_ERROR,
MOO_FILE_ERROR_BAD_FILENAME,
"path '%s' is not absolute",
base_path);
return NULL;
}
2005-08-25 09:29:01 +00:00
name = g_filename_from_utf8 (display_name, -1, NULL, NULL, &error_here);
if (error_here)
{
g_set_error (error, MOO_FILE_ERROR,
MOO_FILE_ERROR_BAD_FILENAME,
"Could not convert '%s' to filename encoding: %s",
display_name, error_here->message);
g_free (name);
g_error_free (error_here);
2006-04-16 11:39:47 -05:00
return NULL;
2005-08-25 09:29:01 +00:00
}
path = g_strdup_printf ("%s/%s", base_path, name);
g_free (name);
return path;
}
2008-01-18 21:45:53 -06:00
/* XXX make sure error is set TODO: error checking, etc. */
static char *
normalize_path_unix (G_GNUC_UNUSED MooFileSystem *fs,
const char *path,
gboolean is_folder,
G_GNUC_UNUSED GError **error)
2005-08-25 09:29:01 +00:00
{
guint len;
2008-01-18 21:45:53 -06:00
char *normpath;
2005-08-25 09:29:01 +00:00
g_return_val_if_fail (path != NULL, NULL);
2008-01-18 21:45:53 -06:00
normpath = normalize_path (path);
2005-08-25 09:29:01 +00:00
if (!is_folder)
2008-01-18 21:45:53 -06:00
return normpath;
2005-08-25 09:29:01 +00:00
2008-01-18 21:45:53 -06:00
len = strlen (normpath);
g_return_val_if_fail (len > 0, normpath);
2005-08-25 09:29:01 +00:00
2008-01-18 21:45:53 -06:00
if (normpath[len-1] != G_DIR_SEPARATOR)
2005-08-25 09:29:01 +00:00
{
2008-01-18 21:45:53 -06:00
normpath = g_renew (char, normpath, len + 2);
2005-08-25 09:29:01 +00:00
normpath[len] = G_DIR_SEPARATOR;
normpath[len+1] = 0;
}
#if 0
g_print ("path: '%s'\nnormpath: '%s'\n",
path, normpath);
#endif
return normpath;
}
/* XXX must set error */
static gboolean
parse_path_unix (MooFileSystem *fs,
const char *path_utf8,
char **dirname_p,
char **display_dirname_p,
char **display_basename_p,
GError **error)
2005-08-25 09:29:01 +00:00
{
const char *separator;
char *dirname = NULL, *norm_dirname = NULL;
char *display_dirname = NULL, *display_basename = NULL;
g_return_val_if_fail (path_utf8 && path_utf8[0], FALSE);
/* XXX check the caller */
2008-01-27 00:07:18 -06:00
if (!_moo_path_is_absolute (path_utf8))
{
g_set_error (error, MOO_FILE_ERROR,
MOO_FILE_ERROR_BAD_FILENAME,
"path '%s' is not absolute",
path_utf8);
return FALSE;
}
2005-08-25 09:29:01 +00:00
if (!strcmp (path_utf8, "/"))
{
display_dirname = g_strdup ("/");
display_basename = g_strdup ("");
norm_dirname = g_strdup ("/");
goto success;
}
separator = strrchr (path_utf8, '/');
g_return_val_if_fail (separator != NULL, FALSE);
display_dirname = g_strndup (path_utf8, separator - path_utf8 + 1);
display_basename = g_strdup (separator + 1);
dirname = g_filename_from_utf8 (display_dirname, -1, NULL, NULL, error);
if (!dirname)
goto error;
2005-08-25 09:29:01 +00:00
norm_dirname = _moo_file_system_normalize_path (fs, dirname, TRUE, error);
2005-08-25 09:29:01 +00:00
if (!norm_dirname)
goto error;
2005-08-25 09:29:01 +00:00
else
goto success;
/* no fallthrough */
g_assert_not_reached ();
error:
2005-08-25 09:29:01 +00:00
g_free (dirname);
g_free (norm_dirname);
g_free (display_dirname);
g_free (display_basename);
return FALSE;
success:
g_clear_error (error);
g_free (dirname);
*dirname_p = norm_dirname;
*display_dirname_p = display_dirname;
*display_basename_p = display_basename;
return TRUE;
}
2005-09-02 23:27:25 +00:00
/* XXX unicode */
static char *
get_absolute_path_unix (G_GNUC_UNUSED MooFileSystem *fs,
const char *short_name,
const char *current_dir)
2005-09-02 23:27:25 +00:00
{
g_return_val_if_fail (short_name && short_name[0], NULL);
if (short_name[0] == '~')
{
const char *home = g_get_home_dir ();
g_return_val_if_fail (home != NULL, NULL);
if (short_name[1])
return g_build_filename (home, short_name + 1, NULL);
else
return g_strdup (home);
}
2008-01-27 00:07:18 -06:00
if (_moo_path_is_absolute (short_name))
2005-09-02 23:27:25 +00:00
return g_strdup (short_name);
if (current_dir)
return g_build_filename (current_dir, short_name, NULL);
return NULL;
}
2005-08-25 09:29:01 +00:00
#endif /* !__WIN32__ */
/***************************************************************************/
/* Win32 methods
*/
#ifdef __WIN32__
2006-04-20 14:13:42 -05:00
static MooFolder *
get_root_folder_win32 (MooFileSystem *fs,
MooFileFlags wanted)
2005-08-25 09:29:01 +00:00
{
2009-11-22 19:14:01 -08:00
MOO_IMPLEMENT_ME
return _moo_file_system_get_folder (fs, "c:\\", wanted, NULL);
2005-08-25 09:29:01 +00:00
}
2007-01-04 04:42:10 -06:00
#if 0
2006-03-10 22:41:41 -06:00
static gboolean
2006-04-20 14:13:42 -05:00
move_file_win32 (G_GNUC_UNUSED MooFileSystem *fs,
G_GNUC_UNUSED const char *old_path,
G_GNUC_UNUSED const char *new_path,
2006-03-10 22:41:41 -06:00
GError **error)
{
2009-11-22 19:14:01 -08:00
MOO_IMPLEMENT_ME
2006-03-10 22:41:41 -06:00
g_set_error (error, MOO_FILE_ERROR,
MOO_FILE_ERROR_NOT_IMPLEMENTED,
"Renaming files is not implemented on win32");
return FALSE;
}
2007-01-04 04:42:10 -06:00
#endif
2006-03-10 22:41:41 -06:00
2006-04-16 11:39:47 -05:00
static void
splitdrive (const char *fullpath,
char **drive,
char **path)
{
if (fullpath[0] && fullpath[1] == ':')
{
*drive = g_strndup (fullpath, 2);
*path = g_strdup (fullpath + 2);
}
else
{
*drive = NULL;
*path = g_strdup (fullpath);
}
}
2006-03-10 22:41:41 -06:00
static char *
2006-04-20 14:13:42 -05:00
normalize_path_win32 (G_GNUC_UNUSED MooFileSystem *fs,
2006-04-16 11:39:47 -05:00
const char *fullpath,
gboolean isdir,
2006-04-20 14:13:42 -05:00
G_GNUC_UNUSED GError **error)
{
2006-04-16 11:39:47 -05:00
char *drive, *path, *normpath;
2006-04-20 14:13:42 -05:00
guint slashes;
2008-01-17 19:27:10 -06:00
gboolean drive_slashes = FALSE;
2006-04-16 11:39:47 -05:00
g_return_val_if_fail (fullpath != NULL, NULL);
2006-04-20 14:13:42 -05:00
splitdrive (fullpath, &drive, &path);
2006-04-16 11:39:47 -05:00
g_strdelimit (path, "/", '\\');
for (slashes = 0; path[slashes] == '\\'; ++slashes) ;
2006-04-20 14:13:42 -05:00
if (drive && path[0] != '\\')
2006-04-16 11:39:47 -05:00
{
char *tmp = path;
2006-04-20 14:13:42 -05:00
path = g_strdup_printf ("\\%s", path);
2006-04-16 11:39:47 -05:00
g_free (tmp);
}
2006-04-20 14:13:42 -05:00
if (!drive)
{
char *tmp = path;
drive = g_strndup (path, slashes);
path = g_strdup (tmp + slashes);
2006-04-16 11:39:47 -05:00
g_free (tmp);
2008-01-17 19:27:10 -06:00
drive_slashes = TRUE;
2006-04-16 11:39:47 -05:00
}
2006-04-20 14:13:42 -05:00
// else if (path[0] == '\\')
// {
// char *tmp;
//
// tmp = drive;
// drive = g_strdup_printf ("%s\\", drive);
// g_free (tmp);
//
// tmp = path;
// path = g_strdup (path + slashes);
// g_free (tmp);
// }
2006-04-16 11:39:47 -05:00
normpath = normalize_path (path);
if (!normpath[0] && !drive)
{
char *tmp = normpath;
normpath = g_strdup (".");
g_free (tmp);
}
else if (drive)
{
char *tmp = normpath;
2008-01-17 19:27:10 -06:00
if (normpath[0] == '\\' || drive_slashes)
normpath = g_strdup_printf ("%s%s", drive, normpath);
else
normpath = g_strdup_printf ("%s\\%s", drive, normpath);
2006-04-16 11:39:47 -05:00
g_free (tmp);
}
if (isdir)
{
2015-07-11 14:32:02 -07:00
gsize len = strlen (normpath);
2006-04-16 11:39:47 -05:00
if (!len || normpath[len -1] != '\\')
{
char *tmp = normpath;
normpath = g_strdup_printf ("%s\\", normpath);
g_free (tmp);
}
}
g_free (drive);
g_free (path);
return normpath;
}
2006-03-10 22:41:41 -06:00
static char *
make_path_win32 (G_GNUC_UNUSED MooFileSystem *fs,
const char *base_path,
const char *display_name,
G_GNUC_UNUSED GError **error)
{
2008-01-27 00:07:18 -06:00
g_return_val_if_fail (_moo_path_is_absolute (base_path), NULL);
2006-04-16 11:39:47 -05:00
g_return_val_if_fail (display_name != NULL, NULL);
2006-03-10 22:41:41 -06:00
return g_strdup_printf ("%s\\%s", base_path, display_name);
}
static gboolean
parse_path_win32 (MooFileSystem *fs,
const char *path_utf8,
char **dirname_p,
char **display_dirname_p,
char **display_basename_p,
GError **error)
{
2009-11-22 19:14:01 -08:00
MOO_IMPLEMENT_ME
const char *separator;
2006-04-16 11:39:47 -05:00
char *norm_dirname = NULL, *dirname = NULL, *basename = NULL;
gsize len;
g_return_val_if_fail (path_utf8 && path_utf8[0], FALSE);
2008-01-27 00:07:18 -06:00
g_return_val_if_fail (_moo_path_is_absolute (path_utf8), FALSE);
separator = strrchr (path_utf8, '\\');
g_return_val_if_fail (separator != NULL, FALSE);
len = strlen (path_utf8);
if (path_utf8[len - 1] == '\\')
{
dirname = g_strdup (path_utf8);
basename = g_strdup ("");
}
else
{
dirname = g_path_get_dirname (path_utf8);
basename = g_path_get_basename (path_utf8);
}
norm_dirname = _moo_file_system_normalize_path (fs, dirname, TRUE, error);
if (!norm_dirname)
goto error;
*dirname_p = norm_dirname;
2006-04-16 11:39:47 -05:00
*display_dirname_p = dirname;
*display_basename_p = basename;
g_message ("parsed '%s' into '%s' and '%s'", path_utf8, dirname, basename);
return TRUE;
error:
g_free (dirname);
g_free (basename);
g_free (norm_dirname);
g_message ("could not parse '%s'", path_utf8);
return FALSE;
}
static char *
2006-04-20 14:13:42 -05:00
get_absolute_path_win32 (G_GNUC_UNUSED MooFileSystem *fs,
const char *short_name,
const char *current_dir)
{
g_return_val_if_fail (short_name && short_name[0], NULL);
2008-01-27 00:07:18 -06:00
if (_moo_path_is_absolute (short_name))
return g_strdup (short_name);
if (current_dir)
return g_build_filename (current_dir, short_name, NULL);
return NULL;
}
2005-08-25 09:29:01 +00:00
#endif /* __WIN32__ */