diff options
-rw-r--r-- | gio/gfile.c | 24 | ||||
-rw-r--r-- | gio/glocalfile.c | 23 | ||||
-rw-r--r-- | gio/glocalfile.h | 2 | ||||
-rw-r--r-- | gio/glocalfileoutputstream.c | 36 | ||||
-rw-r--r-- | gio/glocalfileoutputstream.h | 2 |
5 files changed, 63 insertions, 24 deletions
diff --git a/gio/gfile.c b/gio/gfile.c index 57d3bc31c..b64a97d35 100644 --- a/gio/gfile.c +++ b/gio/gfile.c @@ -60,6 +60,7 @@ #include "gfileoutputstream.h" #include "glocalfileoutputstream.h" #include "glocalfileiostream.h" +#include "glocalfile.h" #include "gcancellable.h" #include "gasyncresult.h" #include "gioerror.h" @@ -3099,7 +3100,28 @@ file_copy_fallback (GFile *source, do_set_attributes = TRUE; } - if (flags & G_FILE_COPY_OVERWRITE) + /* In the local file path, we pass down the source info which + * includes things like unix::mode, to ensure that the target file + * is not created with different permissions from the source file. + * + * If a future API like g_file_replace_with_info() is added, switch + * this code to use that. + */ + if (G_IS_LOCAL_FILE (destination)) + { + if (flags & G_FILE_COPY_OVERWRITE) + out = (GOutputStream*)_g_local_file_output_stream_replace (_g_local_file_get_filename (G_LOCAL_FILE (destination)), + FALSE, NULL, + flags & G_FILE_COPY_BACKUP, + G_FILE_CREATE_REPLACE_DESTINATION, + info, + cancellable, error); + else + out = (GOutputStream*)_g_local_file_output_stream_create (_g_local_file_get_filename (G_LOCAL_FILE (destination)), + FALSE, 0, info, + cancellable, error); + } + else if (flags & G_FILE_COPY_OVERWRITE) { out = (GOutputStream *)g_file_replace (destination, NULL, diff --git a/gio/glocalfile.c b/gio/glocalfile.c index 9007faab5..a4196dcc0 100644 --- a/gio/glocalfile.c +++ b/gio/glocalfile.c @@ -187,6 +187,11 @@ g_local_file_init (GLocalFile *local) { } +const char * +_g_local_file_get_filename (GLocalFile *file) +{ + return file->filename; +} static char * canonicalize_filename (const char *filename) @@ -1396,8 +1401,8 @@ g_local_file_create (GFile *file, GError **error) { return _g_local_file_output_stream_create (G_LOCAL_FILE (file)->filename, - FALSE, - flags, cancellable, error); + FALSE, flags, NULL, + cancellable, error); } static GFileOutputStream * @@ -1409,9 +1414,9 @@ g_local_file_replace (GFile *file, GError **error) { return _g_local_file_output_stream_replace (G_LOCAL_FILE (file)->filename, - FALSE, - etag, make_backup, flags, - cancellable, error); + FALSE, + etag, make_backup, flags, NULL, + cancellable, error); } static GFileIOStream * @@ -1443,7 +1448,7 @@ g_local_file_create_readwrite (GFile *file, GFileIOStream *res; output = _g_local_file_output_stream_create (G_LOCAL_FILE (file)->filename, - TRUE, flags, + TRUE, flags, NULL, cancellable, error); if (output == NULL) return NULL; @@ -1465,9 +1470,9 @@ g_local_file_replace_readwrite (GFile *file, GFileIOStream *res; output = _g_local_file_output_stream_replace (G_LOCAL_FILE (file)->filename, - TRUE, - etag, make_backup, flags, - cancellable, error); + TRUE, + etag, make_backup, flags, NULL, + cancellable, error); if (output == NULL) return NULL; diff --git a/gio/glocalfile.h b/gio/glocalfile.h index abb36fa8e..4d0208462 100644 --- a/gio/glocalfile.h +++ b/gio/glocalfile.h @@ -46,6 +46,8 @@ GType _g_local_file_get_type (void) G_GNUC_CONST; GFile * _g_local_file_new (const char *filename); +const char * _g_local_file_get_filename (GLocalFile *file); + G_END_DECLS #endif /* __G_LOCAL_FILE_H__ */ diff --git a/gio/glocalfileoutputstream.c b/gio/glocalfileoutputstream.c index b408ae9fb..ccee49d79 100644 --- a/gio/glocalfileoutputstream.c +++ b/gio/glocalfileoutputstream.c @@ -37,6 +37,7 @@ #include "gioerror.h" #include "gcancellable.h" #include "glocalfileoutputstream.h" +#include "gfileinfo.h" #include "glocalfileinfo.h" #ifdef G_OS_UNIX @@ -608,10 +609,23 @@ _g_local_file_output_stream_open (const char *filename, return output_stream_open (filename, open_flags, 0666, cancellable, error); } +static gint +mode_from_flags_or_info (GFileCreateFlags flags, + GFileInfo *reference_info) +{ + if (flags & G_FILE_CREATE_PRIVATE) + return 0600; + else if (reference_info && g_file_info_has_attribute (reference_info, "unix::mode")) + return g_file_info_get_attribute_uint32 (reference_info, "unix::mode") & (~S_IFMT); + else + return 0666; +} + GFileOutputStream * _g_local_file_output_stream_create (const char *filename, gboolean readable, GFileCreateFlags flags, + GFileInfo *reference_info, GCancellable *cancellable, GError **error) { @@ -621,10 +635,7 @@ _g_local_file_output_stream_create (const char *filename, if (g_cancellable_set_error_if_cancelled (cancellable, error)) return NULL; - if (flags & G_FILE_CREATE_PRIVATE) - mode = 0600; - else - mode = 0666; + mode = mode_from_flags_or_info (flags, reference_info); open_flags = O_CREAT | O_EXCL | O_BINARY; if (readable) @@ -735,6 +746,7 @@ handle_overwrite_open (const char *filename, gboolean create_backup, char **temp_filename, GFileCreateFlags flags, + GFileInfo *reference_info, GCancellable *cancellable, GError **error) { @@ -746,10 +758,7 @@ handle_overwrite_open (const char *filename, int res; int mode; - if (flags & G_FILE_CREATE_PRIVATE) - mode = 0600; - else - mode = 0666; + mode = mode_from_flags_or_info (flags, reference_info); /* We only need read access to the original file if we are creating a backup. * We also add O_CREATE to avoid a race if the file was just removed */ @@ -1070,6 +1079,7 @@ _g_local_file_output_stream_replace (const char *filename, const char *etag, gboolean create_backup, GFileCreateFlags flags, + GFileInfo *reference_info, GCancellable *cancellable, GError **error) { @@ -1085,10 +1095,7 @@ _g_local_file_output_stream_replace (const char *filename, temp_file = NULL; - if (flags & G_FILE_CREATE_PRIVATE) - mode = 0600; - else - mode = 0666; + mode = mode_from_flags_or_info (flags, reference_info); sync_on_close = FALSE; /* If the file doesn't exist, create it */ @@ -1103,8 +1110,9 @@ _g_local_file_output_stream_replace (const char *filename, { /* The file already exists */ fd = handle_overwrite_open (filename, readable, etag, - create_backup, &temp_file, - flags, cancellable, error); + create_backup, &temp_file, + flags, reference_info, + cancellable, error); if (fd == -1) return NULL; diff --git a/gio/glocalfileoutputstream.h b/gio/glocalfileoutputstream.h index 844eacb8f..b8f062a8e 100644 --- a/gio/glocalfileoutputstream.h +++ b/gio/glocalfileoutputstream.h @@ -67,6 +67,7 @@ GFileOutputStream * _g_local_file_output_stream_open (const char *file GFileOutputStream * _g_local_file_output_stream_create (const char *filename, gboolean readable, GFileCreateFlags flags, + GFileInfo *reference_info, GCancellable *cancellable, GError **error); GFileOutputStream * _g_local_file_output_stream_append (const char *filename, @@ -78,6 +79,7 @@ GFileOutputStream * _g_local_file_output_stream_replace (const char *file const char *etag, gboolean create_backup, GFileCreateFlags flags, + GFileInfo *reference_info, GCancellable *cancellable, GError **error); |