diff options
-rw-r--r-- | gio/gfile.c | 160 | ||||
-rw-r--r-- | gio/gfile.h | 211 | ||||
-rw-r--r-- | gio/glocalfile.c | 274 | ||||
-rw-r--r-- | gio/gvfserror.h | 2 |
4 files changed, 570 insertions, 77 deletions
diff --git a/gio/gfile.c b/gio/gfile.c index 462271ba..b407e3be 100644 --- a/gio/gfile.c +++ b/gio/gfile.c @@ -178,6 +178,18 @@ g_file_get_child (GFile *file, } GFile * +g_file_get_child_for_display_name (GFile *file, + const char *display_name, + GError **error) +{ + GFileIface *iface; + + iface = G_FILE_GET_IFACE (file); + + return (* iface->get_child_for_display_name) (file, display_name, error); +} + +GFile * g_file_resolve_relative (GFile *file, const char *relative_path) { @@ -548,6 +560,28 @@ g_file_make_directory (GFile *file, } gboolean +g_file_make_symbolic_link (GFile *file, + const char *symlink_value, + GCancellable *cancellable, + GError **error) +{ + GFileIface *iface; + + if (g_cancellable_is_cancelled (cancellable)) + { + g_set_error (error, + G_VFS_ERROR, + G_VFS_ERROR_CANCELLED, + _("Operation was cancelled")); + return FALSE; + } + + iface = G_FILE_GET_IFACE (file); + + return (* iface->make_symbolic_link) (file, symlink_value, cancellable, error); +} + +gboolean g_file_delete (GFile *file, GCancellable *cancellable, GError **error) @@ -568,6 +602,132 @@ g_file_delete (GFile *file, return (* iface->delete_file) (file, cancellable, error); } + +GFile * +g_file_set_display_name (GFile *file, + const char *display_name, + GCancellable *cancellable, + GError **error) +{ + GFileIface *iface; + + if (g_cancellable_is_cancelled (cancellable)) + { + g_set_error (error, + G_VFS_ERROR, + G_VFS_ERROR_CANCELLED, + _("Operation was cancelled")); + return FALSE; + } + + iface = G_FILE_GET_IFACE (file); + + return (* iface->set_display_name) (file, display_name, cancellable, error); +} + +gboolean +g_file_set_attribute (GFile *file, + const char *attribute, + GFileAttributeType type, + gconstpointer value, + GFileGetInfoFlags flags, + GCancellable *cancellable, + GError **error) +{ + GFileIface *iface; + + if (g_cancellable_is_cancelled (cancellable)) + { + g_set_error (error, + G_VFS_ERROR, + G_VFS_ERROR_CANCELLED, + _("Operation was cancelled")); + return FALSE; + } + + iface = G_FILE_GET_IFACE (file); + + return (* iface->set_attribute) (file, attribute, type, value, flags, cancellable, error); +} + +gboolean +g_file_set_attribute_string (GFile *file, + const char *attribute, + const char *value, + GFileGetInfoFlags flags, + GCancellable *cancellable, + GError **error) +{ + return g_file_set_attribute (file, attribute, + G_FILE_ATTRIBUTE_TYPE_STRING, + value, flags, cancellable, error); +} + +gboolean +g_file_set_attribute_byte_string (GFile *file, + const char *attribute, + const char *value, + GFileGetInfoFlags flags, + GCancellable *cancellable, + GError **error) +{ + return g_file_set_attribute (file, attribute, + G_FILE_ATTRIBUTE_TYPE_BYTE_STRING, + value, flags, cancellable, error); +} + +gboolean +g_file_set_attribute_uint32 (GFile *file, + const char *attribute, + guint32 value, + GFileGetInfoFlags flags, + GCancellable *cancellable, + GError **error) +{ + return g_file_set_attribute (file, attribute, + G_FILE_ATTRIBUTE_TYPE_UINT32, + &value, flags, cancellable, error); +} + +gboolean +g_file_set_attribute_int32 (GFile *file, + const char *attribute, + const char *value, + GFileGetInfoFlags flags, + GCancellable *cancellable, + GError **error) +{ + return g_file_set_attribute (file, attribute, + G_FILE_ATTRIBUTE_TYPE_INT32, + &value, flags, cancellable, error); +} + +gboolean +g_file_set_attribute_uint64 (GFile *file, + const char *attribute, + guint64 value, + GFileGetInfoFlags flags, + GCancellable *cancellable, + GError **error) +{ + return g_file_set_attribute (file, attribute, + G_FILE_ATTRIBUTE_TYPE_UINT64, + &value, flags, cancellable, error); +} + +gboolean +g_file_set_attribute_int64 (GFile *file, + const char *attribute, + gint64 value, + GFileGetInfoFlags flags, + GCancellable *cancellable, + GError **error) +{ + return g_file_set_attribute (file, attribute, + G_FILE_ATTRIBUTE_TYPE_INT64, + &value, flags, cancellable, error); +} + void g_file_mount (GFile *file, GMountOperation *mount_operation) diff --git a/gio/gfile.h b/gio/gfile.h index 78637bc6..47ad0a47 100644 --- a/gio/gfile.h +++ b/gio/gfile.h @@ -3,6 +3,7 @@ #include <glib-object.h> #include <gio/gvfstypes.h> +#include <gio/gfileinfo.h> #include <gio/gfileenumerator.h> #include <gio/gfileinputstream.h> #include <gio/gfileoutputstream.h> @@ -54,6 +55,9 @@ struct _GFileIface GFile * (*get_parent) (GFile *file); GFile * (*resolve_relative) (GFile *file, const char *relative_path); + GFile * (*get_child_for_display_name) (GFile *file, + const char *display_name, + GError **error); GFileEnumerator * (*enumerate_children) (GFile *file, const char *attributes, GFileGetInfoFlags flags, @@ -65,6 +69,17 @@ struct _GFileIface GCancellable *cancellable, GError **error); /* (*get_info_async) (GFile *file.. */ + GFile * (*set_display_name) (GFile *file, + const char *display_name, + GCancellable *cancellable, + GError **error); + gboolean (*set_attribute) (GFile *file, + const char *attribute, + GFileAttributeType type, + gconstpointer data, + GFileGetInfoFlags flags, + GCancellable *cancellable, + GError **error); GFileInputStream * (*read) (GFile *file, GCancellable *cancellable, GError **error); @@ -85,6 +100,10 @@ struct _GFileIface gboolean (*make_directory) (GFile *file, GCancellable *cancellable, GError **error); + gboolean (*make_symbolic_link) (GFile *file, + const char *symlink_value, + GCancellable *cancellable, + GError **error); gboolean (*copy) (GFile *source, GFile *destination, GFileCopyFlags flags, @@ -113,77 +132,129 @@ struct _GFileIface GType g_file_get_type (void) G_GNUC_CONST; -GFile *g_file_get_for_path (const char *path); -GFile *g_file_get_for_uri (const char *uri); -GFile *g_file_parse_name (const char *parse_name); -GFile *g_file_get_for_commandline_arg (const char *arg); - -GFile * g_file_dup (GFile *file); -guint g_file_hash (gconstpointer file); -gboolean g_file_equal (GFile *file1, - GFile *file2); -gboolean g_file_is_native (GFile *file); -char * g_file_get_basename (GFile *file); -char * g_file_get_path (GFile *file); -char * g_file_get_uri (GFile *file); -char * g_file_get_parse_name (GFile *file); -GFile * g_file_get_parent (GFile *file); -GFile * g_file_get_child (GFile *file, - const char *name); -GFile * g_file_resolve_relative (GFile *file, - const char *relative_path); -GFileEnumerator * g_file_enumerate_children (GFile *file, - const char *attributes, - GFileGetInfoFlags flags, - GCancellable *cancellable, - GError **error); -GFileInfo * g_file_get_info (GFile *file, - const char *attributes, - GFileGetInfoFlags flags, - GCancellable *cancellable, - GError **error); -GFileInputStream * g_file_read (GFile *file, - GCancellable *cancellable, - GError **error); -GFileOutputStream *g_file_append_to (GFile *file, - GCancellable *cancellable, - GError **error); -GFileOutputStream *g_file_create (GFile *file, - GCancellable *cancellable, - GError **error); -GFileOutputStream *g_file_replace (GFile *file, - time_t mtime, - gboolean make_backup, - GCancellable *cancellable, - GError **error); -void g_file_read_async (GFile *file, - int io_priority, - GFileReadCallback callback, - gpointer callback_data, - GCancellable *cancellable); - - -gboolean g_file_make_directory (GFile *file, - GCancellable *cancellable, - GError **error); -gboolean g_file_delete (GFile *file, - GCancellable *cancellable, - GError **error); -gboolean g_file_copy (GFile *source, - GFile *destination, - GFileCopyFlags flags, - GCancellable *cancellable, - GFileProgressCallback progress_callback, - gpointer progress_callback_data, - GError **error); -gboolean g_file_move (GFile *source, - GFile *destination, - GFileCopyFlags flags, - GCancellable *cancellable, - GFileProgressCallback progress_callback, - gpointer progress_callback_data, - GError **error); +GFile * g_file_get_for_path (const char *path); +GFile * g_file_get_for_uri (const char *uri); +GFile * g_file_parse_name (const char *parse_name); +GFile * g_file_get_for_commandline_arg (const char *arg); +GFile * g_file_dup (GFile *file); +guint g_file_hash (gconstpointer file); +gboolean g_file_equal (GFile *file1, + GFile *file2); +char * g_file_get_basename (GFile *file); +char * g_file_get_path (GFile *file); +char * g_file_get_uri (GFile *file); +char * g_file_get_parse_name (GFile *file); +GFile * g_file_get_parent (GFile *file); +GFile * g_file_get_child (GFile *file, + const char *name); +GFile * g_file_get_child_for_display_name (GFile *file, + const char *display_name, + GError **error); +GFile * g_file_resolve_relative (GFile *file, + const char *relative_path); +gboolean g_file_is_native (GFile *file); + +GFileInputStream * g_file_read (GFile *file, + GCancellable *cancellable, + GError **error); +GFileOutputStream *g_file_append_to (GFile *file, + GCancellable *cancellable, + GError **error); +GFileOutputStream *g_file_create (GFile *file, + GCancellable *cancellable, + GError **error); +GFileOutputStream *g_file_replace (GFile *file, + time_t mtime, + gboolean make_backup, + GCancellable *cancellable, + GError **error); +void g_file_read_async (GFile *file, + int io_priority, + GFileReadCallback callback, + gpointer callback_data, + GCancellable *cancellable); +GFileInfo * g_file_get_info (GFile *file, + const char *attributes, + GFileGetInfoFlags flags, + GCancellable *cancellable, + GError **error); +GFileEnumerator * g_file_enumerate_children (GFile *file, + const char *attributes, + GFileGetInfoFlags flags, + GCancellable *cancellable, + GError **error); +GFile *g_file_set_display_name (GFile *file, + const char *display_name, + GCancellable *cancellable, + GError **error); +gboolean g_file_delete (GFile *file, + GCancellable *cancellable, + GError **error); +gboolean g_file_copy (GFile *source, + GFile *destination, + GFileCopyFlags flags, + GCancellable *cancellable, + GFileProgressCallback progress_callback, + gpointer progress_callback_data, + GError **error); +gboolean g_file_move (GFile *source, + GFile *destination, + GFileCopyFlags flags, + GCancellable *cancellable, + GFileProgressCallback progress_callback, + gpointer progress_callback_data, + GError **error); +gboolean g_file_make_directory (GFile *file, + GCancellable *cancellable, + GError **error); +gboolean g_file_make_symbolic_link (GFile *file, + const char *symlink_value, + GCancellable *cancellable, + GError **error); +gboolean g_file_set_attribute (GFile *file, + const char *attribute, + GFileAttributeType type, + gconstpointer value, + GFileGetInfoFlags flags, + GCancellable *cancellable, + GError **error); +gboolean g_file_set_attribute_string (GFile *file, + const char *attribute, + const char *value, + GFileGetInfoFlags flags, + GCancellable *cancellable, + GError **error); +gboolean g_file_set_attribute_byte_string (GFile *file, + const char *attribute, + const char *value, + GFileGetInfoFlags flags, + GCancellable *cancellable, + GError **error); +gboolean g_file_set_attribute_uint32 (GFile *file, + const char *attribute, + guint32 value, + GFileGetInfoFlags flags, + GCancellable *cancellable, + GError **error); +gboolean g_file_set_attribute_int32 (GFile *file, + const char *attribute, + const char *value, + GFileGetInfoFlags flags, + GCancellable *cancellable, + GError **error); +gboolean g_file_set_attribute_uint64 (GFile *file, + const char *attribute, + guint64 value, + GFileGetInfoFlags flags, + GCancellable *cancellable, + GError **error); +gboolean g_file_set_attribute_int64 (GFile *file, + const char *attribute, + gint64 value, + GFileGetInfoFlags flags, + GCancellable *cancellable, + GError **error); void g_file_mount (GFile *file, GMountOperation *mount_operation); diff --git a/gio/glocalfile.c b/gio/glocalfile.c index d8d15a70..bc73ae85 100644 --- a/gio/glocalfile.c +++ b/gio/glocalfile.c @@ -319,7 +319,7 @@ g_local_file_resolve_relative (GFile *file, } static GFileEnumerator * -g_local_file_enumerate_children (GFile *file, +g_local_file_enumerate_children (GFile *file, const char *attributes, GFileGetInfoFlags flags, GCancellable *cancellable, @@ -331,6 +331,73 @@ g_local_file_enumerate_children (GFile *file, cancellable, error); } +static GFile * +g_local_file_get_child_for_display_name (GFile *file, + const char *display_name, + GError **error) +{ + GFile *parent, *new_file; + char *basename; + + basename = g_filename_from_utf8 (display_name, -1, NULL, NULL, NULL); + if (basename == NULL) + { + g_set_error (error, G_VFS_ERROR, + G_VFS_ERROR_INVALID_FILENAME, + _("Invalid filename %s"), display_name); + return NULL; + } + + parent = g_file_get_parent (file); + new_file = g_file_get_child (file, basename); + g_object_unref (parent); + g_free (basename); + + return new_file; +} + + +static GFile * +g_local_file_set_display_name (GFile *file, + const char *display_name, + GCancellable *cancellable, + GError **error) +{ + GLocalFile *local, *new_local; + GFile *new_file; + struct stat statbuf; + + new_file = g_file_get_child_for_display_name (file, display_name, error); + if (new_file == NULL) + return NULL; + + local = G_LOCAL_FILE (file); + new_local = G_LOCAL_FILE (new_file); + + g_stat (new_local->filename, &statbuf); + + if (!(g_stat (new_local->filename, &statbuf) == -1 && + errno == ENOENT)) + { + g_set_error (error, G_FILE_ERROR, + G_FILE_ERROR_EXIST, + _("Can't rename file, filename already exist")); + return NULL; + } + + if (rename (local->filename, new_local->filename) == -1) + { + g_set_error (error, G_FILE_ERROR, + g_file_error_from_errno (errno), + _("Error renaming file: %s"), + g_strerror (errno)); + g_object_unref (new_file); + return NULL; + } + + return new_file; +} + static GFileInfo * g_local_file_get_info (GFile *file, const char *attributes, @@ -358,6 +425,174 @@ g_local_file_get_info (GFile *file, return info; } +static gboolean +get_uint32 (GFileAttributeType type, + gconstpointer value, + guint32 *val_out, + GError **error) +{ + if (type != G_FILE_ATTRIBUTE_TYPE_UINT32) + { + g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_INVAL, + _("Invalid attribute type (uint32 expected)")); + return FALSE; + } + + *val_out = *(guint32 *)value; + + return TRUE; +} + +static gboolean +get_byte_string (GFileAttributeType type, + gconstpointer value, + const char **val_out, + GError **error) +{ + if (type != G_FILE_ATTRIBUTE_TYPE_BYTE_STRING) + { + g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_INVAL, + _("Invalid attribute type (byte string expected)")); + return FALSE; + } + + *val_out = (const char *)value; + + return TRUE; +} + + +static gboolean +g_local_file_set_attribute (GFile *file, + const char *attribute, + GFileAttributeType type, + gconstpointer value, + GFileGetInfoFlags flags, + GCancellable *cancellable, + GError **error) +{ + GLocalFile *local = G_LOCAL_FILE (file); + int res; + + if (strcmp (attribute, G_FILE_ATTRIBUTE_UNIX_MODE) == 0) + { + guint32 val; + + if (!get_uint32 (type, value, &val, error)) + return FALSE; + + if (g_chmod (local->filename, val) == -1) + { + g_set_error (error, G_FILE_ERROR, + g_file_error_from_errno (errno), + _("Error setting permissions: %s"), + g_strerror (errno)); + return FALSE; + } + return TRUE; + } + else if (strcmp (attribute, G_FILE_ATTRIBUTE_UNIX_UID) == 0) + { + guint32 val; + + if (!get_uint32 (type, value, &val, error)) + return FALSE; + + if (flags & G_FILE_GET_INFO_NOFOLLOW_SYMLINKS) + res = lchown (local->filename, val, -1); + else + res = chown (local->filename, val, -1); + + if (res == -1) + { + g_set_error (error, G_FILE_ERROR, + g_file_error_from_errno (errno), + _("Error setting owner: %s"), + g_strerror (errno)); + return FALSE; + } + return TRUE; + } + else if (strcmp (attribute, G_FILE_ATTRIBUTE_UNIX_GID) == 0) + { + guint32 val; + + if (!get_uint32 (type, value, &val, error)) + return FALSE; + + if (flags & G_FILE_GET_INFO_NOFOLLOW_SYMLINKS) + res = lchown (local->filename, -1, val); + else + res = chown (local->filename, -1, val); + + if (res == -1) + { + g_set_error (error, G_FILE_ERROR, + g_file_error_from_errno (errno), + _("Error setting owner: %s"), + g_strerror (errno)); + return FALSE; + } + return TRUE; + } + else if (strcmp (attribute, G_FILE_ATTRIBUTE_STD_SYMLINK_TARGET) == 0) + { + const char *val; + struct stat statbuf; + + if (!get_byte_string (type, value, &val, error)) + return FALSE; + + + if (val == NULL) + { + g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_INVAL, + _("symlink must be non-NULL")); + return FALSE; + } + + if (g_lstat (local->filename, &statbuf)) + { + g_set_error (error, G_FILE_ERROR, + g_file_error_from_errno (errno), + _("Error setting symlink: %s"), + g_strerror (errno)); + return FALSE; + } + + if (!S_ISLNK (statbuf.st_mode)) + { + g_set_error (error, G_VFS_ERROR, + G_VFS_ERROR_NOT_SYMBOLIC_LINK, + _("Error setting symlink: file is not a symlink")); + return FALSE; + } + + if (g_unlink (local->filename)) + { + g_set_error (error, G_FILE_ERROR, + g_file_error_from_errno (errno), + _("Error setting symlink: %s"), + g_strerror (errno)); + return FALSE; + } + + if (symlink (local->filename, val) != 0) + { + g_set_error (error, G_FILE_ERROR, + g_file_error_from_errno (errno), + _("Error setting symlink: %s"), + g_strerror (errno)); + return FALSE; + } + + return TRUE; + } + + g_set_error (error, G_VFS_ERROR, G_VFS_ERROR_NOT_SUPPORTED, "Copy not supported"); + return FALSE; +} + static GFileInputStream * g_local_file_read (GFile *file, GCancellable *cancellable, @@ -371,8 +606,8 @@ g_local_file_read (GFile *file, { g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno), - _("Error opening file %s: %s"), - local->filename, g_strerror (errno)); + _("Error opening file: %s"), + g_strerror (errno)); return NULL; } @@ -421,8 +656,8 @@ g_local_file_delete (GFile *file, { g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno), - _("Error removing file %s: %s"), - local->filename, g_strerror (errno)); + _("Error removing file: %s"), + g_strerror (errno)); return FALSE; } @@ -440,14 +675,35 @@ g_local_file_make_directory (GFile *file, { g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno), - _("Error removing file %s: %s"), - local->filename, g_strerror (errno)); + _("Error removing file: %s"), + g_strerror (errno)); + return FALSE; + } + + return TRUE; +} + +static gboolean +g_local_file_make_symbolic_link (GFile *file, + const char *symlink_value, + GCancellable *cancellable, + GError **error) +{ + GLocalFile *local = G_LOCAL_FILE (file); + + if (symlink (local->filename, symlink_value) == -1) + { + g_set_error (error, G_FILE_ERROR, + g_file_error_from_errno (errno), + _("Error making symbolic link: %s"), + g_strerror (errno)); return FALSE; } return TRUE; } + static gboolean g_local_file_copy (GFile *source, GFile *destination, @@ -565,14 +821,18 @@ g_local_file_file_iface_init (GFileIface *iface) iface->get_parse_name = g_local_file_get_parse_name; iface->get_parent = g_local_file_get_parent; iface->resolve_relative = g_local_file_resolve_relative; + iface->get_child_for_display_name = g_local_file_get_child_for_display_name; + iface->set_display_name = g_local_file_set_display_name; iface->enumerate_children = g_local_file_enumerate_children; iface->get_info = g_local_file_get_info; + iface->set_attribute = g_local_file_set_attribute; iface->read = g_local_file_read; iface->append_to = g_local_file_append_to; iface->create = g_local_file_create; iface->replace = g_local_file_replace; iface->delete_file = g_local_file_delete; iface->make_directory = g_local_file_make_directory; + iface->make_symbolic_link = g_local_file_make_symbolic_link; iface->copy = g_local_file_copy; iface->move = g_local_file_move; iface->mount = g_local_file_mount; diff --git a/gio/gvfserror.h b/gio/gvfserror.h index 97415b8e..edfaeacc 100644 --- a/gio/gvfserror.h +++ b/gio/gvfserror.h @@ -21,8 +21,10 @@ typedef enum G_VFS_ERROR_NOT_SUPPORTED, G_VFS_ERROR_READ_ONLY, G_VFS_ERROR_NOT_REGULAR_FILE, + G_VFS_ERROR_NOT_SYMBOLIC_LINK, G_VFS_ERROR_CANT_CREATE_BACKUP, G_VFS_ERROR_WRONG_MTIME, + G_VFS_ERROR_INVALID_FILENAME, } GVfsError; #endif /* __G_VFS_ERROR_H__ */ |