summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gio/gfile.c24
-rw-r--r--gio/glocalfile.c23
-rw-r--r--gio/glocalfile.h2
-rw-r--r--gio/glocalfileoutputstream.c36
-rw-r--r--gio/glocalfileoutputstream.h2
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);