summaryrefslogtreecommitdiff
path: root/source3/smbd/dir.c
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2011-02-09 15:05:58 -0800
committerJeremy Allison <jra@samba.org>2011-02-09 15:13:40 -0800
commit1607ebfe8632fa13c5ffb466b8c9f416d7ab20aa (patch)
tree8abea25027bd719eb7eb8e1fdb89371e7f72d49a /source3/smbd/dir.c
parent61c1f312d2665197d34245537a8f5b641bda1243 (diff)
downloadsamba-1607ebfe8632fa13c5ffb466b8c9f416d7ab20aa.tar.gz
Allow SMB2_FIND to actually use the open fd handle if we support fdopendir. Fallback to pathname opendir if not.
Diffstat (limited to 'source3/smbd/dir.c')
-rw-r--r--source3/smbd/dir.c54
1 files changed, 43 insertions, 11 deletions
diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c
index f81206e0ecf..edc1ffe65f3 100644
--- a/source3/smbd/dir.c
+++ b/source3/smbd/dir.c
@@ -190,7 +190,7 @@ static struct dptr_struct *dptr_get(struct smbd_server_connection *sconn,
dptr_idleoldest(sconn);
DEBUG(4,("dptr_get: Reopening dptr key %d\n",key));
if (!(dptr->dir_hnd = OpenDir(
- NULL, dptr->conn, dptr->path,
+ NULL, dptr->conn, NULL, dptr->path,
dptr->wcard, dptr->attr))) {
DEBUG(4,("dptr_get: Failed to open %s (%s)\n",dptr->path,
strerror(errno)));
@@ -413,7 +413,8 @@ static void dptr_close_oldest(struct smbd_server_connection *sconn,
wcard must not be zero.
****************************************************************************/
-NTSTATUS dptr_create(connection_struct *conn, const char *path, bool old_handle, bool expect_close,uint16 spid,
+NTSTATUS dptr_create(connection_struct *conn, files_struct *fsp,
+ const char *path, bool old_handle, bool expect_close,uint16 spid,
const char *wcard, bool wcard_has_wild, uint32 attr, struct dptr_struct **dptr_ret)
{
struct smbd_server_connection *sconn = conn->sconn;
@@ -421,6 +422,10 @@ NTSTATUS dptr_create(connection_struct *conn, const char *path, bool old_handle,
struct smb_Dir *dir_hnd;
NTSTATUS status;
+ if (fsp && fsp->is_directory && fsp->fh->fd != -1) {
+ path = fsp->fsp_name->base_name;
+ }
+
DEBUG(5,("dptr_create dir=%s\n", path));
if (sconn == NULL) {
@@ -432,12 +437,14 @@ NTSTATUS dptr_create(connection_struct *conn, const char *path, bool old_handle,
return NT_STATUS_INVALID_PARAMETER;
}
- status = check_name(conn,path);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
+ if (!fsp) {
+ status = check_name(conn,path);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
}
- dir_hnd = OpenDir(NULL, conn, path, wcard, attr);
+ dir_hnd = OpenDir(NULL, conn, fsp, path, wcard, attr);
if (!dir_hnd) {
return map_nt_error_from_unix(errno);
}
@@ -1305,7 +1312,10 @@ static int smb_Dir_destructor(struct smb_Dir *dirp)
********************************************************************/
struct smb_Dir *OpenDir(TALLOC_CTX *mem_ctx, connection_struct *conn,
- const char *name, const char *mask, uint32 attr)
+ files_struct *fsp,
+ const char *name,
+ const char *mask,
+ uint32 attr)
{
struct smb_Dir *dirp = TALLOC_ZERO_P(mem_ctx, struct smb_Dir);
struct smbd_server_connection *sconn = conn->sconn;
@@ -1317,7 +1327,11 @@ struct smb_Dir *OpenDir(TALLOC_CTX *mem_ctx, connection_struct *conn,
dirp->conn = conn;
dirp->name_cache_size = lp_directory_name_cache_size(SNUM(conn));
- dirp->dir_path = talloc_strdup(dirp, name);
+ if (fsp) {
+ dirp->dir_path = talloc_strdup(dirp, fsp->fsp_name->base_name);
+ } else {
+ dirp->dir_path = talloc_strdup(dirp, name);
+ }
if (!dirp->dir_path) {
errno = ENOMEM;
goto fail;
@@ -1328,7 +1342,25 @@ struct smb_Dir *OpenDir(TALLOC_CTX *mem_ctx, connection_struct *conn,
}
talloc_set_destructor(dirp, smb_Dir_destructor);
- dirp->dir = SMB_VFS_OPENDIR(conn, dirp->dir_path, mask, attr);
+ if (fsp && fsp->is_directory && fsp->fh->fd != -1) {
+ dirp->dir = SMB_VFS_FDOPENDIR(fsp, mask, attr);
+ if (dirp->dir == NULL) {
+ DEBUG(10,("OpenDir: SMB_VFS_FDOPENDIR on %s returned "
+ "NULL (%s)\n",
+ dirp->dir_path,
+ strerror(errno)));
+ if (errno != ENOSYS) {
+ return NULL;
+ }
+ }
+ }
+
+ if (dirp->dir == NULL) {
+ /* FDOPENDIR didn't work - or fsp == NULL. Use
+ OPENDIR instead. */
+ dirp->dir = SMB_VFS_OPENDIR(conn, dirp->dir_path, mask, attr);
+ }
+
if (!dirp->dir) {
DEBUG(5,("OpenDir: Can't open %s. %s\n", dirp->dir_path,
strerror(errno) ));
@@ -1536,8 +1568,8 @@ NTSTATUS can_delete_directory(struct connection_struct *conn,
const char *dname = NULL;
char *talloced = NULL;
SMB_STRUCT_STAT st;
- struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn, dirname,
- NULL, 0);
+ struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn, NULL,
+ dirname, NULL, 0);
if (!dir_hnd) {
return map_nt_error_from_unix(errno);