#include <string.h>
#include <errno.h>
#include <fcntl.h>
+#ifdef HAVE_UNISTD_H
#include <unistd.h>
+#endif
#if HAVE_SYS_STATFS_H
#include <sys/statfs.h>
#include "glocalfileoutputstream.h"
#include "glocaldirectorymonitor.h"
#include "glocalfilemonitor.h"
-#include "gvolumeprivate.h"
+#include "gmountprivate.h"
#include <glib/gstdio.h>
#include "glibintl.h"
+#ifdef G_OS_WIN32
+#include <windows.h>
+#include <io.h>
+#include <direct.h>
+
+#ifndef S_ISDIR
+#define S_ISDIR(m) (((m) & _S_IFMT) == _S_IFDIR)
+#endif
+#ifndef S_ISLNK
+#define S_ISLNK(m) (0)
+#endif
+#endif
+
#include "gioalias.h"
-static void g_local_file_file_iface_init (GFileIface *iface);
+static void g_local_file_file_iface_init (GFileIface *iface);
static GFileAttributeInfoList *local_writable_attributes = NULL;
static GFileAttributeInfoList *local_writable_namespaces = NULL;
G_IMPLEMENT_INTERFACE (G_TYPE_FILE,
g_local_file_file_iface_init))
-static char * find_mountpoint_for (const char *file, dev_t dev);
+static char *find_mountpoint_for (const char *file, dev_t dev);
static void
g_local_file_finalize (GObject *object)
g_file_attribute_info_list_add (list,
G_FILE_ATTRIBUTE_UNIX_MODE,
G_FILE_ATTRIBUTE_TYPE_UINT32,
- G_FILE_ATTRIBUTE_FLAGS_COPY_WHEN_MOVED);
+ G_FILE_ATTRIBUTE_INFO_COPY_WHEN_MOVED);
#ifdef HAVE_CHOWN
g_file_attribute_info_list_add (list,
G_FILE_ATTRIBUTE_UNIX_UID,
G_FILE_ATTRIBUTE_TYPE_UINT32,
- G_FILE_ATTRIBUTE_FLAGS_COPY_WHEN_MOVED);
+ G_FILE_ATTRIBUTE_INFO_COPY_WHEN_MOVED);
g_file_attribute_info_list_add (list,
G_FILE_ATTRIBUTE_UNIX_GID,
G_FILE_ATTRIBUTE_TYPE_UINT32,
- G_FILE_ATTRIBUTE_FLAGS_COPY_WHEN_MOVED);
+ G_FILE_ATTRIBUTE_INFO_COPY_WHEN_MOVED);
#endif
#ifdef HAVE_SYMLINK
g_file_attribute_info_list_add (list,
- G_FILE_ATTRIBUTE_STD_SYMLINK_TARGET,
+ G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET,
G_FILE_ATTRIBUTE_TYPE_BYTE_STRING,
0);
#endif
g_file_attribute_info_list_add (list,
G_FILE_ATTRIBUTE_TIME_MODIFIED,
G_FILE_ATTRIBUTE_TYPE_UINT64,
- G_FILE_ATTRIBUTE_FLAGS_COPY_WHEN_MOVED);
+ G_FILE_ATTRIBUTE_INFO_COPY_WHEN_MOVED);
g_file_attribute_info_list_add (list,
G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC,
G_FILE_ATTRIBUTE_TYPE_UINT32,
- G_FILE_ATTRIBUTE_FLAGS_COPY_WHEN_MOVED);
+ G_FILE_ATTRIBUTE_INFO_COPY_WHEN_MOVED);
g_file_attribute_info_list_add (list,
G_FILE_ATTRIBUTE_TIME_ACCESS,
G_FILE_ATTRIBUTE_TYPE_UINT64,
- G_FILE_ATTRIBUTE_FLAGS_COPY_WHEN_MOVED);
+ G_FILE_ATTRIBUTE_INFO_COPY_WHEN_MOVED);
g_file_attribute_info_list_add (list,
G_FILE_ATTRIBUTE_TIME_ACCESS_USEC,
G_FILE_ATTRIBUTE_TYPE_UINT32,
- G_FILE_ATTRIBUTE_FLAGS_COPY_WHEN_MOVED);
+ G_FILE_ATTRIBUTE_INFO_COPY_WHEN_MOVED);
#endif
local_writable_attributes = list;
g_file_attribute_info_list_add (list,
"xattr",
G_FILE_ATTRIBUTE_TYPE_STRING,
- G_FILE_ATTRIBUTE_FLAGS_COPY_WITH_FILE |
- G_FILE_ATTRIBUTE_FLAGS_COPY_WHEN_MOVED);
+ G_FILE_ATTRIBUTE_INFO_COPY_WITH_FILE |
+ G_FILE_ATTRIBUTE_INFO_COPY_WHEN_MOVED);
g_file_attribute_info_list_add (list,
- "xattr_sys",
+ "xattr-sys",
G_FILE_ATTRIBUTE_TYPE_STRING,
- G_FILE_ATTRIBUTE_FLAGS_COPY_WHEN_MOVED);
+ G_FILE_ATTRIBUTE_INFO_COPY_WHEN_MOVED);
#endif
local_writable_namespaces = list;
while ((c = *string++) != 0)
{
- if (g_ascii_iscntrl(c))
+ if (g_ascii_iscntrl (c))
return FALSE;
}
prefix_len = strlen (prefix);
if (strncmp (path, prefix, prefix_len) != 0)
return NULL;
+
+ /* Handle the case where prefix is the root, so that
+ * the IS_DIR_SEPRARATOR check below works */
+ if (prefix_len > 0 &&
+ G_IS_DIR_SEPARATOR (prefix[prefix_len-1]))
+ prefix_len--;
+
return path + prefix_len;
}
}
#endif
+#ifndef G_OS_WIN32
+
G_LOCK_DEFINE_STATIC(mount_info_hash);
static GHashTable *mount_info_hash = NULL;
-guint64 mount_info_hash_cache_time = 0;
+static guint64 mount_info_hash_cache_time = 0;
typedef enum {
MOUNT_INFO_READONLY = 1<<0
device_equal (gconstpointer v1,
gconstpointer v2)
{
- return *(dev_t *)v1 == * (dev_t *)v2;
+ return *(dev_t *)v1 == *(dev_t *)v2;
}
static guint
guint mount_info;
char *mountpoint;
dev_t *dev;
- GUnixMount *mount;
+ GUnixMountEntry *mount;
guint64 cache_time;
- if (lstat (path, &buf) != 0)
+ if (g_lstat (path, &buf) != 0)
return;
G_LOCK (mount_info_hash);
if (mountpoint == NULL)
mountpoint = "/";
- mount = g_get_unix_mount_at (mountpoint, &cache_time);
+ mount = g_unix_mount_at (mountpoint, &cache_time);
if (mount)
{
if (g_unix_mount_is_readonly (mount))
}
if (mount_info & MOUNT_INFO_READONLY)
- g_file_info_set_attribute_boolean (fs_info, G_FILE_ATTRIBUTE_FS_READONLY, TRUE);
+ g_file_info_set_attribute_boolean (fs_info, G_FILE_ATTRIBUTE_FILESYSTEM_READONLY, TRUE);
}
+#endif
+
static GFileInfo *
g_local_file_query_filesystem_info (GFile *file,
const char *attributes,
GFileInfo *info;
int statfs_result;
gboolean no_size;
+#ifndef G_OS_WIN32
guint64 block_size;
#ifdef USE_STATFS
struct statfs statfs_buffer;
#elif defined(USE_STATVFS)
struct statvfs statfs_buffer;
#endif
+#endif
GFileAttributeMatcher *attribute_matcher;
no_size = FALSE;
attribute_matcher = g_file_attribute_matcher_new (attributes);
if (g_file_attribute_matcher_matches (attribute_matcher,
- G_FILE_ATTRIBUTE_FS_FREE))
- g_file_info_set_attribute_uint64 (info, G_FILE_ATTRIBUTE_FS_FREE, block_size * statfs_buffer.f_bavail);
+ G_FILE_ATTRIBUTE_FILESYSTEM_FREE))
+ {
+#ifdef G_OS_WIN32
+ gchar *localdir = g_path_get_dirname (local->filename);
+ wchar_t *wdirname = g_utf8_to_utf16 (localdir, -1, NULL, NULL, NULL);
+ ULARGE_INTEGER li;
+
+ g_free (localdir);
+ if (GetDiskFreeSpaceExW (wdirname, &li, NULL, NULL))
+ g_file_info_set_attribute_uint64 (info, G_FILE_ATTRIBUTE_FILESYSTEM_FREE, (guint64)li.QuadPart);
+ g_free (wdirname);
+#else
+ g_file_info_set_attribute_uint64 (info, G_FILE_ATTRIBUTE_FILESYSTEM_FREE, block_size * statfs_buffer.f_bavail);
+#endif
+ }
if (g_file_attribute_matcher_matches (attribute_matcher,
- G_FILE_ATTRIBUTE_FS_SIZE))
- g_file_info_set_attribute_uint64 (info, G_FILE_ATTRIBUTE_FS_SIZE, block_size * statfs_buffer.f_blocks);
-
+ G_FILE_ATTRIBUTE_FILESYSTEM_SIZE))
+ {
+#ifdef G_OS_WIN32
+ gchar *localdir = g_path_get_dirname (local->filename);
+ wchar_t *wdirname = g_utf8_to_utf16 (localdir, -1, NULL, NULL, NULL);
+ ULARGE_INTEGER li;
+
+ g_free (localdir);
+ if (GetDiskFreeSpaceExW (wdirname, NULL, &li, NULL))
+ g_file_info_set_attribute_uint64 (info, G_FILE_ATTRIBUTE_FILESYSTEM_SIZE, (guint64)li.QuadPart);
+ g_free (wdirname);
+#else
+ g_file_info_set_attribute_uint64 (info, G_FILE_ATTRIBUTE_FILESYSTEM_SIZE, block_size * statfs_buffer.f_blocks);
+#endif
+ }
#ifdef USE_STATFS
fstype = get_fs_type (statfs_buffer.f_type);
if (fstype &&
g_file_attribute_matcher_matches (attribute_matcher,
- G_FILE_ATTRIBUTE_FS_TYPE))
- g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_FS_TYPE, fstype);
+ G_FILE_ATTRIBUTE_FILESYSTEM_TYPE))
+ g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_FILESYSTEM_TYPE, fstype);
#endif
if (g_file_attribute_matcher_matches (attribute_matcher,
- G_FILE_ATTRIBUTE_FS_READONLY))
+ G_FILE_ATTRIBUTE_FILESYSTEM_READONLY))
{
+#ifdef G_OS_WIN32
+ /* need to implement with *unix_mount* */
+#else
get_mount_info (info, local->filename, attribute_matcher);
+#endif
}
g_file_attribute_matcher_unref (attribute_matcher);
return info;
}
-static GVolume *
-g_local_file_find_enclosing_volume (GFile *file,
- GCancellable *cancellable,
- GError **error)
+static GMount *
+g_local_file_find_enclosing_mount (GFile *file,
+ GCancellable *cancellable,
+ GError **error)
{
GLocalFile *local = G_LOCAL_FILE (file);
struct stat buf;
char *mountpoint;
- GVolume *volume;
+ GMount *mount;
- if (lstat (local->filename, &buf) != 0)
+ if (g_lstat (local->filename, &buf) != 0)
{
g_set_error (error, G_IO_ERROR,
G_IO_ERROR_NOT_FOUND,
- _("Containing volume does not exist"));
+ _("Containing mount does not exist"));
return NULL;
}
{
g_set_error (error, G_IO_ERROR,
G_IO_ERROR_NOT_FOUND,
- _("Containing volume does not exist"));
+ _("Containing mount does not exist"));
return NULL;
}
- volume = _g_volume_get_for_mount_path (mountpoint);
+ mount = _g_mount_get_for_mount_path (mountpoint, cancellable);
g_free (mountpoint);
- if (volume)
- return volume;
+ if (mount)
+ return mount;
g_set_error (error, G_IO_ERROR,
G_IO_ERROR_NOT_FOUND,
- _("Containing volume does not exist"));
+ _("Containing mount does not exist"));
return NULL;
}
return NULL;
}
- new_file = g_file_get_child_for_display_name (parent, display_name, error);
+ new_file = g_file_get_child_for_display_name (parent, display_name, error);
g_object_unref (parent);
if (new_file == NULL)
}
static gboolean
-g_local_file_set_attribute (GFile *file,
- const char *attribute,
- const GFileAttributeValue *value,
- GFileQueryInfoFlags flags,
- GCancellable *cancellable,
- GError **error)
+g_local_file_set_attribute (GFile *file,
+ const char *attribute,
+ GFileAttributeType type,
+ gpointer value_p,
+ GFileQueryInfoFlags flags,
+ GCancellable *cancellable,
+ GError **error)
{
GLocalFile *local = G_LOCAL_FILE (file);
return _g_local_file_info_set_attribute (local->filename,
attribute,
- value,
+ type,
+ value_p,
flags,
cancellable,
error);
{
GLocalFile *local = G_LOCAL_FILE (file);
int res, chained_res;
- GFileIface* default_iface;
+ GFileIface *default_iface;
res = _g_local_file_info_set_attributes (local->filename,
info, flags,
{
char *resolved, *canonical, *parent, *link2;
char symlink_value[4096];
+#ifdef G_OS_WIN32
+#else
ssize_t res;
+#endif
+#ifdef G_OS_WIN32
+#else
res = readlink (link, symlink_value, sizeof (symlink_value) - 1);
+
if (res == -1)
return g_strdup (link);
symlink_value[res] = 0;
+#endif
if (g_path_is_absolute (symlink_value))
return canonicalize_filename (symlink_value);
}
}
+#ifndef G_OS_WIN32
+
static char *
find_topdir_for (const char *file)
{
return find_mountpoint_for (dir, dir_dev);
}
+#endif
+
static char *
get_unique_filename (const char *basename,
int id)
dot = strchr (basename, '.');
if (dot)
- return g_strdup_printf ("%.*s.%d%s", dot - basename, basename, id, dot);
+ return g_strdup_printf ("%.*s.%d%s", (int)(dot - basename), basename, id, dot);
else
return g_strdup_printf ("%s.%d", basename, id);
}
GError **error)
{
GLocalFile *local = G_LOCAL_FILE (file);
- struct stat file_stat, home_stat, trash_stat, global_stat;
+ struct stat file_stat, home_stat;
const char *homedir;
- char *dirname;
- char *trashdir, *globaldir, *topdir, *infodir, *filesdir;
+ char *trashdir, *topdir, *infodir, *filesdir;
char *basename, *trashname, *trashfile, *infoname, *infofile;
char *original_name, *original_name_escaped;
- uid_t uid;
- char uid_str[32];
int i;
char *data;
gboolean is_homedir_trash;
- time_t t;
- struct tm now;
char delete_time[32];
int fd;
+#ifndef G_OS_WIN32
+ struct stat trash_stat, global_stat;
+ char *dirname, *globaldir;
+#endif
if (g_lstat (local->filename, &file_stat) != 0)
{
}
else
{
+#ifdef G_OS_WIN32
+ g_warning ("Recycle bin not implemented");
+#else
+ uid_t uid;
+ char uid_str[32];
+
uid = geteuid ();
g_snprintf (uid_str, sizeof (uid_str), "%lu", (unsigned long)uid);
trashdir = NULL;
}
}
+#endif
if (trashdir == NULL)
{
g_free (original_name);
g_free (topdir);
- t = time (NULL);
- localtime_r (&t, &now);
- delete_time[0] = 0;
- strftime(delete_time, sizeof (delete_time), "%Y-%m-%dT%H:%M:%S", &now);
+#ifdef G_OS_WIN32
+ {
+ GTimeVal now;
+ g_get_current_time (&now);
+ strncpy (delete_time, g_time_val_to_iso8601 (&now), sizeof (delete_time));
+ }
+#else
+ {
+ time_t t;
+ struct tm now;
+ t = time (NULL);
+ localtime_r (&t, &now);
+ delete_time[0] = 0;
+ strftime(delete_time, sizeof (delete_time), "%Y-%m-%dT%H:%M:%S", &now);
+ }
+#endif
data = g_strdup_printf ("[Trash Info]\nPath=%s\nDeletionDate=%s\n",
original_name_escaped, delete_time);
gpointer progress_callback_data,
GError **error)
{
- GLocalFile *local_source = G_LOCAL_FILE (source);
+ GLocalFile *local_source;
GLocalFile *local_destination = G_LOCAL_FILE (destination);
struct stat statbuf;
gboolean destination_exist, source_is_dir;
char *backup_name;
int res;
-
+ off_t source_size;
+
+ if (!G_IS_LOCAL_FILE (source) ||
+ !G_IS_LOCAL_FILE (destination))
+ {
+ /* Fall back to default move */
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, "Move not supported");
+ return FALSE;
+ }
+
+ local_source = G_LOCAL_FILE (source);
+
res = g_lstat (local_source->filename, &statbuf);
if (res == -1)
{
}
else
source_is_dir = S_ISDIR (statbuf.st_mode);
+
+ source_size = statbuf.st_size;
destination_exist = FALSE;
res = g_lstat (local_destination->filename, &statbuf);
_("Error moving file: %s"),
g_strerror (errsv));
return FALSE;
-
}
+
+ /* Make sure we send full copied size */
+ if (progress_callback)
+ progress_callback (source_size, source_size, progress_callback_data);
+
return TRUE;
}
-static GDirectoryMonitor*
+static GFileMonitor*
g_local_file_monitor_dir (GFile *file,
GFileMonitorFlags flags,
- GCancellable *cancellable)
+ GCancellable *cancellable,
+ GError **error)
{
GLocalFile* local_file = G_LOCAL_FILE(file);
- return _g_local_directory_monitor_new (local_file->filename, flags);
+ return _g_local_directory_monitor_new (local_file->filename, flags, error);
}
static GFileMonitor*
g_local_file_monitor_file (GFile *file,
GFileMonitorFlags flags,
- GCancellable *cancellable)
+ GCancellable *cancellable,
+ GError **error)
{
GLocalFile* local_file = G_LOCAL_FILE(file);
- return _g_local_file_monitor_new (local_file->filename, flags);
+ return _g_local_file_monitor_new (local_file->filename, flags, error);
}
static void
iface->enumerate_children = g_local_file_enumerate_children;
iface->query_info = g_local_file_query_info;
iface->query_filesystem_info = g_local_file_query_filesystem_info;
- iface->find_enclosing_volume = g_local_file_find_enclosing_volume;
+ iface->find_enclosing_mount = g_local_file_find_enclosing_mount;
iface->query_settable_attributes = g_local_file_query_settable_attributes;
iface->query_writable_namespaces = g_local_file_query_writable_namespaces;
iface->set_attribute = g_local_file_set_attribute;
iface->set_attributes_from_info = g_local_file_set_attributes_from_info;
- iface->read = g_local_file_read;
+ iface->read_fn = g_local_file_read;
iface->append_to = g_local_file_append_to;
iface->create = g_local_file_create;
iface->replace = g_local_file_replace;