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