diff --git a/daemon-Add-support-for-edit-mode.patch b/daemon-Add-support-for-edit-mode.patch new file mode 100644 index 0000000..7f43021 --- /dev/null +++ b/daemon-Add-support-for-edit-mode.patch @@ -0,0 +1,94 @@ +From 1d4acb8d95612384f603aa5c0c8d20060010fbc7 Mon Sep 17 00:00:00 2001 +From: Ondrej Holy +Date: Thu, 1 Aug 2024 12:35:43 +0200 +Subject: [PATCH] daemon: Add support for edit mode + +Currently, it is impossible to open the output stream without truncating +the file or appending it. This is a problem for many POSIX applications +relying on our FUSE daemon. Let's add an edit mode that could be used for +this purpose. + +Related: https://gitlab.gnome.org/GNOME/gvfs/-/issues/249 +--- + daemon/gvfsbackend.h | 8 ++++++++ + daemon/gvfsjobopenforwrite.c | 23 +++++++++++++++++++++++ + daemon/gvfsjobopenforwrite.h | 3 ++- + 3 files changed, 33 insertions(+), 1 deletion(-) + +diff --git a/daemon/gvfsbackend.h b/daemon/gvfsbackend.h +index 9c7476cf..0f97cff6 100644 +--- a/daemon/gvfsbackend.h ++++ b/daemon/gvfsbackend.h +@@ -211,6 +211,14 @@ struct _GVfsBackendClass + const char *etag, + gboolean make_backup, + GFileCreateFlags flags); ++ gboolean (*try_edit) (GVfsBackend *backend, ++ GVfsJobOpenForWrite *job, ++ const char *filename, ++ GFileCreateFlags flags); ++ void (*edit) (GVfsBackend *backend, ++ GVfsJobOpenForWrite *job, ++ const char *filename, ++ GFileCreateFlags flags); + void (*close_write) (GVfsBackend *backend, + GVfsJobCloseWrite *job, + GVfsBackendHandle handle); +diff --git a/daemon/gvfsjobopenforwrite.c b/daemon/gvfsjobopenforwrite.c +index 439b63c4..5b6e8033 100644 +--- a/daemon/gvfsjobopenforwrite.c ++++ b/daemon/gvfsjobopenforwrite.c +@@ -220,6 +220,20 @@ run (GVfsJob *job) + op_job->make_backup, + op_job->flags); + } ++ else if (op_job->mode == OPEN_FOR_WRITE_EDIT) ++ { ++ if (class->edit == NULL) ++ { ++ g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, ++ _("Operation not supported")); ++ return; ++ } ++ ++ class->edit (op_job->backend, ++ op_job, ++ op_job->filename, ++ op_job->flags); ++ } + else + g_assert_not_reached (); /* Handled in try */ + } +@@ -259,6 +273,15 @@ try (GVfsJob *job) + op_job->make_backup, + op_job->flags); + } ++ else if (op_job->mode == OPEN_FOR_WRITE_EDIT) ++ { ++ if (class->try_edit == NULL) ++ return FALSE; ++ return class->try_edit (op_job->backend, ++ op_job, ++ op_job->filename, ++ op_job->flags); ++ } + else + { + GError *error = NULL; +diff --git a/daemon/gvfsjobopenforwrite.h b/daemon/gvfsjobopenforwrite.h +index 141189f3..e070d0ea 100644 +--- a/daemon/gvfsjobopenforwrite.h ++++ b/daemon/gvfsjobopenforwrite.h +@@ -41,7 +41,8 @@ typedef struct _GVfsJobOpenForWriteClass GVfsJobOpenForWriteClass; + typedef enum { + OPEN_FOR_WRITE_CREATE = 0, + OPEN_FOR_WRITE_APPEND = 1, +- OPEN_FOR_WRITE_REPLACE = 2 ++ OPEN_FOR_WRITE_REPLACE = 2, ++ OPEN_FOR_WRITE_EDIT = 3 + } GVfsJobOpenForWriteMode; + + typedef enum { +-- +2.46.2 + diff --git a/fuse-Use-edit-mode-instead-of-returning-ENOTSUP.patch b/fuse-Use-edit-mode-instead-of-returning-ENOTSUP.patch new file mode 100644 index 0000000..9a9195a --- /dev/null +++ b/fuse-Use-edit-mode-instead-of-returning-ENOTSUP.patch @@ -0,0 +1,39 @@ +From fabacfef29e24628f7a1a303be4b54cb006431bb Mon Sep 17 00:00:00 2001 +From: Ondrej Holy +Date: Thu, 1 Aug 2024 12:40:15 +0200 +Subject: [PATCH] fuse: Use edit mode instead of returning ENOTSUP + +Currently, the FUSE daemon fails with the `ENOTSUP` error when opening +a file for writing without `O_APPEND` or `O_TRUNC`. This is a problem +for many POSIX applications. Let's try the newly added edit mode instead. + +Fixes: https://gitlab.gnome.org/GNOME/gvfs/-/issues/249 +--- + client/gvfsfusedaemon.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/client/gvfsfusedaemon.c b/client/gvfsfusedaemon.c +index ff5641ae..9ec4e3d8 100644 +--- a/client/gvfsfusedaemon.c ++++ b/client/gvfsfusedaemon.c +@@ -1003,6 +1003,8 @@ setup_input_stream (GFile *file, FileHandle *fh) + return result; + } + ++#define _g_file_edit(file, flags, cancellable, error) g_file_append_to(file, flags | (1 << 15), cancellable, error) ++ + static gint + setup_output_stream (GFile *file, FileHandle *fh, int flags) + { +@@ -1032,7 +1034,7 @@ setup_output_stream (GFile *file, FileHandle *fh, int flags) + else if (flags & O_APPEND) + fh->stream = g_file_append_to (file, 0, NULL, &error); + else +- result = -ENOTSUP; ++ fh->stream = _g_file_edit (file, 0, NULL, &error); + if (fh->stream) + fh->pos = g_seekable_tell (G_SEEKABLE (fh->stream)); + } +-- +2.46.2 + diff --git a/gdaemonfile-Use-edit-mode-when-private-edit-flag-is-.patch b/gdaemonfile-Use-edit-mode-when-private-edit-flag-is-.patch new file mode 100644 index 0000000..16f56e0 --- /dev/null +++ b/gdaemonfile-Use-edit-mode-when-private-edit-flag-is-.patch @@ -0,0 +1,52 @@ +From 5dd5f5b97bc753cdf32a04e3de4bddce651ceb9b Mon Sep 17 00:00:00 2001 +From: Ondrej Holy +Date: Thu, 1 Aug 2024 12:39:49 +0200 +Subject: [PATCH] gdaemonfile: Use edit mode when private edit flag is used + +The newly added edit mode is meant only for private use by our FUSE +daemon. Let's add a new private flag for the append operation to enable +the edit mode. +--- + client/gdaemonfile.c | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +diff --git a/client/gdaemonfile.c b/client/gdaemonfile.c +index 485698b2..d66d0934 100644 +--- a/client/gdaemonfile.c ++++ b/client/gdaemonfile.c +@@ -57,6 +57,8 @@ G_DEFINE_TYPE_WITH_CODE (GDaemonFile, g_daemon_file, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (G_TYPE_FILE, + g_daemon_file_file_iface_init)) + ++#define PRIVATE_EDIT_FLAG (1 << 15) ++ + static void + g_daemon_file_finalize (GObject *object) + { +@@ -1198,7 +1200,10 @@ g_daemon_file_append_to (GFile *file, + GCancellable *cancellable, + GError **error) + { +- return file_open_write (file, 1, "", FALSE, flags, cancellable, error); ++ if (flags & PRIVATE_EDIT_FLAG) ++ return file_open_write (file, 3, "", FALSE, flags, cancellable, error); ++ else ++ return file_open_write (file, 1, "", FALSE, flags, cancellable, error); + } + + static GFileOutputStream * +@@ -3130,7 +3135,10 @@ g_daemon_file_append_to_async (GFile *file, + g_task_set_source_tag (task, g_daemon_file_append_to_async); + g_task_set_priority (task, io_priority); + +- file_open_write_async (file, task, 1, "", FALSE, flags); ++ if (flags & PRIVATE_EDIT_FLAG) ++ file_open_write_async (file, task, 3, "", FALSE, flags); ++ else ++ file_open_write_async (file, task, 1, "", FALSE, flags); + } + + static GFileOutputStream * +-- +2.46.2 + diff --git a/gvfs.spec b/gvfs.spec index 48f29e3..bb8444c 100644 --- a/gvfs.spec +++ b/gvfs.spec @@ -22,7 +22,7 @@ Name: gvfs Version: 1.48.1 -Release: 5%{?dist} +Release: 6%{?dist} Summary: Backends for the gio framework in GLib License: GPLv3 and LGPLv2+ and BSD and MPLv2.0 @@ -36,6 +36,15 @@ Patch1: smb-Rework-anonymous-handling-to-avoid-EINVAL.patch # https://issues.redhat.com/browse/RHEL-52342 Patch2: trash-Add-support-for-x-gvfs-trash-mount-option.patch +# https://issues.redhat.com/browse/RHEL-71088 +Patch3: daemon-Add-support-for-edit-mode.patch +Patch4: gdaemonfile-Use-edit-mode-when-private-edit-flag-is-.patch +Patch5: fuse-Use-edit-mode-instead-of-returning-ENOTSUP.patch +Patch6: smb-Fail-when-initial_offset-can-t-be-determined.patch +Patch7: smb-Disable-seek-support-when-appening.patch +Patch8: smb-Fix-offset-after-truncate-when-appending.patch +Patch9: smb-Implement-support-for-edit-mode.patch + BuildRequires: meson BuildRequires: gcc BuildRequires: pkgconfig @@ -432,6 +441,9 @@ killall -USR1 gvfsd >&/dev/null || : %{_datadir}/installed-tests %changelog +* Thu Feb 13 2025 Ondrej Holy - 1.48.1-6 +- Add edit mode support for smb backend (RHEL-71088) + * Thu Sep 26 2024 Ondrej Holy - 1.48.1-5 - Add support for x-gvfs-trash mount option (RHEL-52353) diff --git a/smb-Disable-seek-support-when-appening.patch b/smb-Disable-seek-support-when-appening.patch new file mode 100644 index 0000000..02ab6bd --- /dev/null +++ b/smb-Disable-seek-support-when-appening.patch @@ -0,0 +1,36 @@ +From b17f15558194ab3025c8a5cb1a2767c54333f28e Mon Sep 17 00:00:00 2001 +From: Ondrej Holy +Date: Wed, 13 Nov 2024 11:22:27 +0100 +Subject: [PATCH] smb: Disable seek support when appening + +The seek is currently enabled when appending. However, the libsmbclient +doesn't support O_APPEND flag property [1]. The offset is not reset after +seeking. Let's disable seek support when appending to deal with it. The +seek operation doesn't make sense when appening anyway. + +[1] https://github.com/samba-team/samba/blob/e4e3f05/source3/libsmb/libsmb_file.c#L162-L183 +--- + daemon/gvfsbackendsmb.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/daemon/gvfsbackendsmb.c b/daemon/gvfsbackendsmb.c +index dafbb71c..c2075555 100644 +--- a/daemon/gvfsbackendsmb.c ++++ b/daemon/gvfsbackendsmb.c +@@ -871,7 +871,12 @@ do_append_to (GVfsBackend *backend, + handle->file = file; + + g_vfs_job_open_for_write_set_initial_offset (job, initial_offset); +- g_vfs_job_open_for_write_set_can_seek (job, TRUE); ++ ++ /* The O_APPEND flag is not properly supported by the libsmbclient library ++ * when seeking. See: ++ * https://github.com/samba-team/samba/blob/e4e3f05/source3/libsmb/libsmb_file.c#L162-L183 ++ */ ++ g_vfs_job_open_for_write_set_can_seek (job, FALSE); + g_vfs_job_open_for_write_set_can_truncate (job, TRUE); + g_vfs_job_open_for_write_set_handle (job, handle); + g_vfs_job_succeeded (G_VFS_JOB (job)); +-- +2.46.2 + diff --git a/smb-Fail-when-initial_offset-can-t-be-determined.patch b/smb-Fail-when-initial_offset-can-t-be-determined.patch new file mode 100644 index 0000000..40302e3 --- /dev/null +++ b/smb-Fail-when-initial_offset-can-t-be-determined.patch @@ -0,0 +1,54 @@ +From 885bcc18b65ebd6d3c5bac56994f9f631cb9d363 Mon Sep 17 00:00:00 2001 +From: Ondrej Holy +Date: Wed, 6 Nov 2024 14:58:18 +0100 +Subject: [PATCH] smb: Fail when initial_offset can't be determined + +Currently, when the initial_offset can't be determined, the seek and +truncate operations are disabled. Let's fail immediatelly instead to +simplify the code as a preparation for the follow-up changes. Just a +note tha this situation can't happen with the current libsmbclient +codebase. +--- + daemon/gvfsbackendsmb.c | 22 ++++++++++++---------- + 1 file changed, 12 insertions(+), 10 deletions(-) + +diff --git a/daemon/gvfsbackendsmb.c b/daemon/gvfsbackendsmb.c +index c1c2d5f0..dafbb71c 100644 +--- a/daemon/gvfsbackendsmb.c ++++ b/daemon/gvfsbackendsmb.c +@@ -857,20 +857,22 @@ do_append_to (GVfsBackend *backend, + g_vfs_job_failed_from_errno (G_VFS_JOB (job), fixup_open_errno (errno)); + else + { +- handle = g_new0 (SmbWriteHandle, 1); +- handle->file = file; +- + smbc_lseek = smbc_getFunctionLseek (op_backend->smb_context); + initial_offset = smbc_lseek (op_backend->smb_context, file, + 0, SEEK_CUR); + if (initial_offset == (off_t) -1) +- g_vfs_job_open_for_write_set_can_seek (job, FALSE); +- else +- { +- g_vfs_job_open_for_write_set_initial_offset (job, initial_offset); +- g_vfs_job_open_for_write_set_can_seek (job, TRUE); +- g_vfs_job_open_for_write_set_can_truncate (job, TRUE); +- } ++ { ++ g_vfs_job_failed_from_errno (G_VFS_JOB (job), ++ fixup_open_errno (errno)); ++ return; ++ } ++ ++ handle = g_new0 (SmbWriteHandle, 1); ++ handle->file = file; ++ ++ g_vfs_job_open_for_write_set_initial_offset (job, initial_offset); ++ g_vfs_job_open_for_write_set_can_seek (job, TRUE); ++ g_vfs_job_open_for_write_set_can_truncate (job, TRUE); + g_vfs_job_open_for_write_set_handle (job, handle); + g_vfs_job_succeeded (G_VFS_JOB (job)); + } +-- +2.46.2 + diff --git a/smb-Fix-offset-after-truncate-when-appending.patch b/smb-Fix-offset-after-truncate-when-appending.patch new file mode 100644 index 0000000..8055108 --- /dev/null +++ b/smb-Fix-offset-after-truncate-when-appending.patch @@ -0,0 +1,85 @@ +From b4ff6ddb32296f43439b4be79c7864f7ae7d14f1 Mon Sep 17 00:00:00 2001 +From: Ondrej Holy +Date: Wed, 13 Nov 2024 11:34:19 +0100 +Subject: [PATCH] smb: Fix offset after truncate when appending + +The truncate operation is currently enabled when appending. However, +the libsmbclient doesn't support O_APPEND flag property [1]. The +offset is not reset after the truncate operation. This may lead to +data corruptions. Let's explicitely seek to the desired offset when +truncating to prevent this. + +[1] https://github.com/samba-team/samba/blob/e4e3f05/source3/libsmb/libsmb_file.c#L162-L183 +--- + daemon/gvfsbackendsmb.c | 27 ++++++++++++++++++++++++--- + 1 file changed, 24 insertions(+), 3 deletions(-) + +diff --git a/daemon/gvfsbackendsmb.c b/daemon/gvfsbackendsmb.c +index c2075555..f287264b 100644 +--- a/daemon/gvfsbackendsmb.c ++++ b/daemon/gvfsbackendsmb.c +@@ -780,6 +780,7 @@ typedef struct { + char *uri; + char *tmp_uri; + char *backup_uri; ++ GVfsJobOpenForWriteMode mode; + } SmbWriteHandle; + + static void +@@ -824,6 +825,7 @@ do_create (GVfsBackend *backend, + { + handle = g_new0 (SmbWriteHandle, 1); + handle->file = file; ++ handle->mode = job->mode; + + g_vfs_job_open_for_write_set_can_seek (job, TRUE); + g_vfs_job_open_for_write_set_can_truncate (job, TRUE); +@@ -869,6 +871,7 @@ do_append_to (GVfsBackend *backend, + + handle = g_new0 (SmbWriteHandle, 1); + handle->file = file; ++ handle->mode = job->mode; + + g_vfs_job_open_for_write_set_initial_offset (job, initial_offset); + +@@ -1141,6 +1144,7 @@ do_replace (GVfsBackend *backend, + handle->uri = uri; + handle->tmp_uri = tmp_uri; + handle->backup_uri = backup_uri; ++ handle->mode = job->mode; + + g_vfs_job_open_for_write_set_can_seek (job, TRUE); + g_vfs_job_open_for_write_set_can_truncate (job, TRUE); +@@ -1229,9 +1233,26 @@ do_truncate (GVfsBackend *backend, + + smbc_ftruncate = smbc_getFunctionFtruncate (op_backend->smb_context); + if (smbc_ftruncate (op_backend->smb_context, handle->file, size) == -1) +- g_vfs_job_failed_from_errno (G_VFS_JOB (job), errno); +- else +- g_vfs_job_succeeded (G_VFS_JOB (job)); ++ { ++ g_vfs_job_failed_from_errno (G_VFS_JOB (job), errno); ++ return; ++ } ++ ++ if (handle->mode == OPEN_FOR_WRITE_APPEND) ++ { ++ smbc_lseek_fn smbc_lseek; ++ off_t res; ++ ++ smbc_lseek = smbc_getFunctionLseek (op_backend->smb_context); ++ res = smbc_lseek (op_backend->smb_context, handle->file, size, SEEK_SET); ++ if (res == (off_t)-1) ++ { ++ g_vfs_job_failed_from_errno (G_VFS_JOB (job), errno); ++ return; ++ } ++ } ++ ++ g_vfs_job_succeeded (G_VFS_JOB (job)); + } + + static void +-- +2.46.2 + diff --git a/smb-Implement-support-for-edit-mode.patch b/smb-Implement-support-for-edit-mode.patch new file mode 100644 index 0000000..3e6bdf6 --- /dev/null +++ b/smb-Implement-support-for-edit-mode.patch @@ -0,0 +1,177 @@ +From bcbf85cc1f9bd8c1cb673a5d7d3f9907d84e3caa Mon Sep 17 00:00:00 2001 +From: Ondrej Holy +Date: Wed, 13 Nov 2024 11:52:28 +0100 +Subject: [PATCH] smb: Implement support for edit mode + +Implement support for the newly added edit mode in the SMB backend. + +Related: https://gitlab.gnome.org/GNOME/gvfs/-/issues/249 +--- + daemon/gvfsbackendsmb.c | 109 +++++++++++++++++++--------------------- + 1 file changed, 53 insertions(+), 56 deletions(-) + +diff --git a/daemon/gvfsbackendsmb.c b/daemon/gvfsbackendsmb.c +index f287264b..4fbdfd23 100644 +--- a/daemon/gvfsbackendsmb.c ++++ b/daemon/gvfsbackendsmb.c +@@ -793,10 +793,11 @@ smb_write_handle_free (SmbWriteHandle *handle) + } + + static void +-do_create (GVfsBackend *backend, +- GVfsJobOpenForWrite *job, +- const char *filename, +- GFileCreateFlags flags) ++open_for_write (GVfsBackend *backend, ++ GVfsJobOpenForWrite *job, ++ const char *filename, ++ GFileCreateFlags flags, ++ int open_flags) + { + GVfsBackendSmb *op_backend = G_VFS_BACKEND_SMB (backend); + char *uri; +@@ -804,12 +805,12 @@ do_create (GVfsBackend *backend, + SmbWriteHandle *handle; + smbc_open_fn smbc_open; + int errsv; ++ off_t initial_offset = 0; + + uri = create_smb_uri (op_backend->server, op_backend->port, op_backend->share, filename); + smbc_open = smbc_getFunctionOpen (op_backend->smb_context); + errno = 0; +- file = smbc_open (op_backend->smb_context, uri, +- O_CREAT|O_RDWR|O_EXCL, 0666); ++ file = smbc_open (op_backend->smb_context, uri, open_flags, 0666); + g_free (uri); + + if (file == NULL) +@@ -817,48 +818,16 @@ do_create (GVfsBackend *backend, + errsv = fixup_open_errno (errno); + + /* We guarantee EEXIST on create on existing dir */ +- if (errsv == EISDIR) ++ if (job->mode == OPEN_FOR_WRITE_CREATE && errsv == EISDIR) + errsv = EEXIST; + g_vfs_job_failed_from_errno (G_VFS_JOB (job), errsv); ++ return; + } +- else +- { +- handle = g_new0 (SmbWriteHandle, 1); +- handle->file = file; +- handle->mode = job->mode; +- +- g_vfs_job_open_for_write_set_can_seek (job, TRUE); +- g_vfs_job_open_for_write_set_can_truncate (job, TRUE); +- g_vfs_job_open_for_write_set_handle (job, handle); +- g_vfs_job_succeeded (G_VFS_JOB (job)); +- } +-} + +-static void +-do_append_to (GVfsBackend *backend, +- GVfsJobOpenForWrite *job, +- const char *filename, +- GFileCreateFlags flags) +-{ +- GVfsBackendSmb *op_backend = G_VFS_BACKEND_SMB (backend); +- char *uri; +- SMBCFILE *file; +- SmbWriteHandle *handle; +- off_t initial_offset; +- smbc_open_fn smbc_open; +- smbc_lseek_fn smbc_lseek; +- +- uri = create_smb_uri (op_backend->server, op_backend->port, op_backend->share, filename); +- smbc_open = smbc_getFunctionOpen (op_backend->smb_context); +- errno = 0; +- file = smbc_open (op_backend->smb_context, uri, +- O_CREAT|O_RDWR|O_APPEND, 0666); +- g_free (uri); +- +- if (file == NULL) +- g_vfs_job_failed_from_errno (G_VFS_JOB (job), fixup_open_errno (errno)); +- else ++ if (job->mode == OPEN_FOR_WRITE_APPEND) + { ++ smbc_lseek_fn smbc_lseek; ++ + smbc_lseek = smbc_getFunctionLseek (op_backend->smb_context); + initial_offset = smbc_lseek (op_backend->smb_context, file, + 0, SEEK_CUR); +@@ -868,24 +837,51 @@ do_append_to (GVfsBackend *backend, + fixup_open_errno (errno)); + return; + } ++ } + +- handle = g_new0 (SmbWriteHandle, 1); +- handle->file = file; +- handle->mode = job->mode; ++ handle = g_new0 (SmbWriteHandle, 1); ++ handle->file = file; ++ handle->mode = job->mode; + +- g_vfs_job_open_for_write_set_initial_offset (job, initial_offset); ++ g_vfs_job_open_for_write_set_initial_offset (job, initial_offset); + +- /* The O_APPEND flag is not properly supported by the libsmbclient library +- * when seeking. See: +- * https://github.com/samba-team/samba/blob/e4e3f05/source3/libsmb/libsmb_file.c#L162-L183 +- */ +- g_vfs_job_open_for_write_set_can_seek (job, FALSE); +- g_vfs_job_open_for_write_set_can_truncate (job, TRUE); +- g_vfs_job_open_for_write_set_handle (job, handle); +- g_vfs_job_succeeded (G_VFS_JOB (job)); +- } ++ /* The O_APPEND flag is not properly supported by the libsmbclient library ++ * when seeking. See: ++ * https://github.com/samba-team/samba/blob/e4e3f05/source3/libsmb/libsmb_file.c#L162-L183 ++ */ ++ g_vfs_job_open_for_write_set_can_seek (job, ++ job->mode != OPEN_FOR_WRITE_APPEND); ++ g_vfs_job_open_for_write_set_can_truncate (job, TRUE); ++ g_vfs_job_open_for_write_set_handle (job, handle); ++ g_vfs_job_succeeded (G_VFS_JOB (job)); + } + ++static void ++do_create (GVfsBackend *backend, ++ GVfsJobOpenForWrite *job, ++ const char *filename, ++ GFileCreateFlags flags) ++{ ++ open_for_write (backend, job, filename, flags, O_CREAT|O_RDWR|O_EXCL); ++} ++ ++static void ++do_append_to (GVfsBackend *backend, ++ GVfsJobOpenForWrite *job, ++ const char *filename, ++ GFileCreateFlags flags) ++{ ++ open_for_write (backend, job, filename, flags, O_CREAT|O_RDWR|O_APPEND); ++} ++ ++static void ++do_edit (GVfsBackend *backend, ++ GVfsJobOpenForWrite *job, ++ const char *filename, ++ GFileCreateFlags flags) ++{ ++ open_for_write (backend, job, filename, flags, O_CREAT|O_RDWR); ++} + + static char * + get_dir_from_uri (const char *uri) +@@ -2153,6 +2149,7 @@ g_vfs_backend_smb_class_init (GVfsBackendSmbClass *klass) + backend_class->close_read = do_close_read; + backend_class->create = do_create; + backend_class->append_to = do_append_to; ++ backend_class->edit = do_edit; + backend_class->replace = do_replace; + backend_class->write = do_write; + backend_class->seek_on_write = do_seek_on_write; +-- +2.46.2 +