smbd: add fd_openat()
authorRalph Boehme <slow@samba.org>
Thu, 14 May 2020 19:20:22 +0000 (21:20 +0200)
committerJeremy Allison <jra@samba.org>
Thu, 21 May 2020 20:38:35 +0000 (20:38 +0000)
Until we actually start passing real dirfsps to fd_openat(), fd_openat()
internally calls fd_open().

Signed-off-by: Ralph Boehme <slow@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
source3/smbd/open.c
source3/smbd/proto.h

index cbcebe71e73d8f81d045f046e4cc1dff24576ca2..a1d5f4b0c91b9c8d091d35835c3744c10f906f23 100644 (file)
@@ -836,6 +836,70 @@ NTSTATUS fd_open(files_struct *fsp,
        return status;
 }
 
+NTSTATUS fd_openat(files_struct *fsp,
+                  int flags,
+                  mode_t mode)
+{
+       NTSTATUS status = NT_STATUS_OK;
+       int saved_errno = 0;
+
+       if (fsp->dirfsp == fsp->conn->cwd_fsp) {
+               return fd_open(fsp, flags, mode);
+       }
+
+       /*
+        * Never follow symlinks at this point, filename_convert() should have
+        * resolved any symlink.
+        */
+
+       flags |= O_NOFOLLOW;
+
+       /*
+        * Only follow symlinks within a share
+        * definition.
+        */
+       fsp->fh->fd = SMB_VFS_OPENAT(fsp->conn,
+                                    fsp->dirfsp,
+                                    fsp->fsp_name,
+                                    fsp,
+                                    flags,
+                                    mode);
+       if (fsp->fh->fd == -1) {
+               saved_errno = errno;
+       }
+       if (saved_errno != 0) {
+               errno = saved_errno;
+       }
+
+       if (fsp->fh->fd == -1) {
+               int posix_errno = link_errno_convert(errno);
+
+               status = map_nt_error_from_unix(posix_errno);
+
+               if (errno == EMFILE) {
+                       static time_t last_warned = 0L;
+
+                       if (time((time_t *) NULL) > last_warned) {
+                               DEBUG(0,("Too many open files, unable "
+                                       "to open more!  smbd's max "
+                                       "open files = %d\n",
+                                       lp_max_open_files()));
+                               last_warned = time((time_t *) NULL);
+                       }
+               }
+
+               DBG_DEBUG("name %s, flags = 0%o mode = 0%o, fd = %d. %s\n",
+                         fsp_str_dbg(fsp), flags, (int)mode,
+                         fsp->fh->fd, strerror(errno));
+               return status;
+       }
+
+       DBG_DEBUG("name %s, flags = 0%o mode = 0%o, fd = %d\n",
+                 fsp_str_dbg(fsp), flags, (int)mode, fsp->fh->fd);
+
+       return status;
+}
+
 /****************************************************************************
  Close the file associated with a fsp.
 ****************************************************************************/
index 3a0b25f021b8abbdab4d39ff60b8eadc01ac46ab..eeb6fcbf3d6aa436d2e71a16d1b5df9e486ea966 100644 (file)
@@ -724,6 +724,9 @@ NTSTATUS check_parent_access(struct connection_struct *conn,
                                uint32_t access_mask);
 NTSTATUS fd_open(files_struct *fsp,
                 int flags, mode_t mode);
+NTSTATUS fd_openat(files_struct *fsp,
+                  int flags,
+                  mode_t mode);
 NTSTATUS fd_close(files_struct *fsp);
 void change_file_owner_to_parent(connection_struct *conn,
                                 struct smb_filename *inherit_from_dir,