vfs_fruit: return fake pipe fd in fruit_open_meta_netatalk()
authorRalph Boehme <slow@samba.org>
Tue, 23 May 2017 15:44:16 +0000 (17:44 +0200)
committerVolker Lendecke <vl@samba.org>
Wed, 9 Aug 2017 16:41:06 +0000 (18:41 +0200)
Do not open the basefile, that conflict with "kernel oplocks = yes". We
just return a fake file fd based on dup'ing a pipe fd and ensure all VFS
functions that go through vfs_fruit and work on the metadata stream can
deal with it.

Bug: https://bugzilla.samba.org/show_bug.cgi?id=12791

Signed-off-by: Ralph Boehme <slow@samba.org>
Reviewed-by: Richard Sharpe <realrichardsharpe@gmail.com>
Reviewed-by: Volker Lendecke <vl@samba.org>
source3/modules/vfs_fruit.c

index 1f2d48906f0aeed97c577ba2a0a23f840532b6b0..205244d5ab15d3e490e0b88e596d93682ee5f6cd 100644 (file)
@@ -2739,56 +2739,24 @@ static int fruit_open_meta_netatalk(vfs_handle_struct *handle,
                                    int flags,
                                    mode_t mode)
 {
-       int rc = 0;
-       struct smb_filename *smb_fname_base = NULL;
-       int baseflags;
-       int hostfd = -1;
+       int rc;
+       int fakefd = -1;
        struct adouble *ad = NULL;
+       int fds[2];
 
        DBG_DEBUG("Path [%s]\n", smb_fname_str_dbg(smb_fname));
 
-       /* Create an smb_filename with stream_name == NULL. */
-       smb_fname_base = synthetic_smb_fname(talloc_tos(),
-                                       smb_fname->base_name,
-                                       NULL,
-                                       NULL,
-                                       smb_fname->flags);
-
-       if (smb_fname_base == NULL) {
-               errno = ENOMEM;
-               rc = -1;
-               goto exit;
-       }
-
        /*
-        * We use baseflags to turn off nasty side-effects when opening the
-        * underlying file.
+        * 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.
         */
-       baseflags = flags;
-       baseflags &= ~O_TRUNC;
-       baseflags &= ~O_EXCL;
-       baseflags &= ~O_CREAT;
-
-       hostfd = SMB_VFS_NEXT_OPEN(handle, smb_fname_base, fsp,
-                                  baseflags, mode);
-
-       /*
-        * It is legit to open a stream on a directory, but the base
-        * fd has to be read-only.
-        */
-       if ((hostfd == -1) && (errno == EISDIR)) {
-               baseflags &= ~O_ACCMODE;
-               baseflags |= O_RDONLY;
-               hostfd = SMB_VFS_NEXT_OPEN(handle, smb_fname_base, fsp,
-                                          baseflags, mode);
-       }
-
-       TALLOC_FREE(smb_fname_base);
-
-       if (hostfd == -1) {
-               rc = -1;
+       rc = pipe(fds);
+       if (rc != 0) {
                goto exit;
        }
+       fakefd = fds[0];
+       close(fds[1]);
 
        if (flags & (O_CREAT | O_TRUNC)) {
                /*
@@ -2801,10 +2769,7 @@ static int fruit_open_meta_netatalk(vfs_handle_struct *handle,
                        goto exit;
                }
 
-               fsp->fh->fd = hostfd;
-
-               rc = ad_fset(ad, fsp);
-               fsp->fh->fd = -1;
+               rc = ad_set(ad, fsp->fsp_name);
                if (rc != 0) {
                        rc = -1;
                        goto exit;
@@ -2814,22 +2779,16 @@ static int fruit_open_meta_netatalk(vfs_handle_struct *handle,
        }
 
 exit:
-       DEBUG(10, ("fruit_open meta rc=%d, fd=%d\n", rc, hostfd));
+       DEBUG(10, ("fruit_open meta rc=%d, fd=%d\n", rc, fakefd));
        if (rc != 0) {
                int saved_errno = errno;
-               if (hostfd >= 0) {
-                       /*
-                        * BUGBUGBUG -- we would need to call
-                        * fd_close_posix here, but we don't have a
-                        * full fsp yet
-                        */
-                       fsp->fh->fd = hostfd;
-                       SMB_VFS_NEXT_CLOSE(handle, fsp);
+               if (fakefd >= 0) {
+                       close(fakefd);
                }
-               hostfd = -1;
+               fakefd = -1;
                errno = saved_errno;
        }
-       return hostfd;
+       return fakefd;
 }
 
 static int fruit_open_meta(vfs_handle_struct *handle,