From: Ralph Boehme Date: Wed, 22 Aug 2018 13:25:26 +0000 (+0200) Subject: vfs_fruit: let fruit_open_meta() with O_CREAT return a fake-fd X-Git-Tag: samba-4.8.8~41 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0eebb6e0a47a53709b7a8ec67bd97dae7b1fd53e;p=thirdparty%2Fsamba.git vfs_fruit: let fruit_open_meta() with O_CREAT return a fake-fd This is the final step in implementing the needed macOS semantics on the FinderInfo stream: as long as the client hasn't written a non-zero FinderInfo blob to the stream, there mustn't be a visible filesystem entry for other openers. Bug: https://bugzilla.samba.org/show_bug.cgi?id=13646 Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison Autobuild-User(master): Jeremy Allison Autobuild-Date(master): Thu Nov 1 01:14:23 CET 2018 on sn-devel-144 (cherry picked from commit 1b2de44ea8114cf2025e8b8c843131e2f2dbed27) --- diff --git a/selftest/knownfail.d/samba3.vfs.fruit b/selftest/knownfail.d/samba3.vfs.fruit index 2d3c21caf91..6307e2b3404 100644 --- a/selftest/knownfail.d/samba3.vfs.fruit +++ b/selftest/knownfail.d/samba3.vfs.fruit @@ -1,5 +1,2 @@ ^samba3.vfs.fruit streams_depot.OS X AppleDouble file conversion\(nt4_dc\) ^samba3.vfs.fruit streams_depot.OS X AppleDouble file conversion without embedded xattr\(nt4_dc\) -^samba3.vfs.fruit metadata_netatalk.empty_stream\(nt4_dc\) -^samba3.vfs.fruit metadata_stream.empty_stream\(nt4_dc\) -^samba3.vfs.fruit streams_depot.empty_stream\(nt4_dc\) diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c index a4594c33567..d75ce01b118 100644 --- a/source3/modules/vfs_fruit.c +++ b/source3/modules/vfs_fruit.c @@ -3403,66 +3403,68 @@ static int fruit_connect(vfs_handle_struct *handle, return rc; } +static int fruit_fake_fd(void) +{ + int pipe_fds[2]; + int fd; + int ret; + + /* + * Return a valid fd, but ensure any attempt to use it returns + * an error (EPIPE). Once we get a write on the handle, we open + * the real fd. + */ + ret = pipe(pipe_fds); + if (ret != 0) { + return -1; + } + fd = pipe_fds[0]; + close(pipe_fds[1]); + + return fd; +} + static int fruit_open_meta_stream(vfs_handle_struct *handle, struct smb_filename *smb_fname, files_struct *fsp, int flags, mode_t mode) { - AfpInfo *ai = NULL; - char afpinfo_buf[AFP_INFO_SIZE]; - ssize_t len, written; - int hostfd = -1; - int rc = -1; + struct fruit_config_data *config = NULL; + struct fio *fio = NULL; + int open_flags = flags & ~O_CREAT; + int fd; - hostfd = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, flags, mode); - if (hostfd == -1) { - return -1; - } + DBG_DEBUG("Path [%s]\n", smb_fname_str_dbg(smb_fname)); - if (!(flags & (O_CREAT | O_TRUNC))) { - return hostfd; - } + SMB_VFS_HANDLE_GET_DATA(handle, config, + struct fruit_config_data, return -1); - ai = afpinfo_new(talloc_tos()); - if (ai == NULL) { - rc = -1; - goto fail; - } + fio = VFS_ADD_FSP_EXTENSION(handle, fsp, struct fio, NULL); + fio->type = ADOUBLE_META; + fio->config = config; - len = afpinfo_pack(ai, afpinfo_buf); - if (len != AFP_INFO_SIZE) { - rc = -1; - goto fail; + fd = SMB_VFS_NEXT_OPEN(handle, smb_fname, fsp, open_flags, mode); + if (fd != -1) { + return fd; } - /* Set fd, needed in SMB_VFS_NEXT_PWRITE() */ - fsp->fh->fd = hostfd; - - written = SMB_VFS_NEXT_PWRITE(handle, fsp, afpinfo_buf, - AFP_INFO_SIZE, 0); - fsp->fh->fd = -1; - if (written != AFP_INFO_SIZE) { - DBG_ERR("bad write [%zd/%d]\n", written, AFP_INFO_SIZE); - rc = -1; - goto fail; + if (!(flags & O_CREAT)) { + VFS_REMOVE_FSP_EXTENSION(handle, fsp); + return -1; } - rc = 0; + fd = fruit_fake_fd(); + if (fd == -1) { + VFS_REMOVE_FSP_EXTENSION(handle, fsp); + return -1; + } -fail: - DBG_DEBUG("rc=%d, fd=%d\n", rc, hostfd); + fio->fake_fd = true; + fio->flags = flags; + fio->mode = mode; - if (rc != 0) { - int saved_errno = errno; - if (hostfd >= 0) { - fsp->fh->fd = hostfd; - SMB_VFS_NEXT_CLOSE(handle, fsp); - } - hostfd = -1; - errno = saved_errno; - } - return hostfd; + return fd; } static int fruit_open_meta_netatalk(vfs_handle_struct *handle, @@ -3471,56 +3473,42 @@ static int fruit_open_meta_netatalk(vfs_handle_struct *handle, int flags, mode_t mode) { - int rc; - int fakefd = -1; + struct fruit_config_data *config = NULL; + struct fio *fio = NULL; struct adouble *ad = NULL; - int fds[2]; + bool meta_exists = false; + int fd; DBG_DEBUG("Path [%s]\n", smb_fname_str_dbg(smb_fname)); - /* - * Return a valid fd, but ensure any attempt to use it returns an error - * (EPIPE). All operations on the smb_fname or the fsp will use path - * based syscalls. - */ - rc = pipe(fds); - if (rc != 0) { - goto exit; + ad = ad_get(talloc_tos(), handle, smb_fname, ADOUBLE_META); + if (ad != NULL) { + meta_exists = true; } - fakefd = fds[0]; - close(fds[1]); - - if (flags & (O_CREAT | O_TRUNC)) { - /* - * The attribute does not exist or needs to be truncated, - * create an AppleDouble EA - */ - ad = ad_init(fsp, handle, ADOUBLE_META); - if (ad == NULL) { - rc = -1; - goto exit; - } - rc = ad_set(ad, fsp->fsp_name); - if (rc != 0) { - rc = -1; - goto exit; - } + TALLOC_FREE(ad); - TALLOC_FREE(ad); + if (!meta_exists && !(flags & O_CREAT)) { + errno = ENOENT; + return -1; } -exit: - DEBUG(10, ("fruit_open meta rc=%d, fd=%d\n", rc, fakefd)); - if (rc != 0) { - int saved_errno = errno; - if (fakefd >= 0) { - close(fakefd); - } - fakefd = -1; - errno = saved_errno; + fd = fruit_fake_fd(); + if (fd == -1) { + return -1; } - return fakefd; + + SMB_VFS_HANDLE_GET_DATA(handle, config, + struct fruit_config_data, return -1); + + fio = VFS_ADD_FSP_EXTENSION(handle, fsp, struct fio, NULL); + fio->type = ADOUBLE_META; + fio->config = config; + fio->fake_fd = true; + fio->flags = flags; + fio->mode = mode; + + return fd; } static int fruit_open_meta(vfs_handle_struct *handle, @@ -3529,7 +3517,6 @@ static int fruit_open_meta(vfs_handle_struct *handle, { int fd; struct fruit_config_data *config = NULL; - struct fio *fio = NULL; DBG_DEBUG("path [%s]\n", smb_fname_str_dbg(smb_fname)); @@ -3554,14 +3541,6 @@ static int fruit_open_meta(vfs_handle_struct *handle, DBG_DEBUG("path [%s] fd [%d]\n", smb_fname_str_dbg(smb_fname), fd); - if (fd == -1) { - return -1; - } - - fio = VFS_ADD_FSP_EXTENSION(handle, fsp, struct fio, NULL); - fio->type = ADOUBLE_META; - fio->config = config; - return fd; }