[PATCH] [SAMBA3] Improve handling of lookups in unsearchable
directories.
James Peach
jpeach at apple.com
Tue Feb 5 17:44:19 GMT 2008
This change allows us to hold open a directory iterator that is not
backed by a real open directory handle as long as we are not intending
to iterate or search for a wildcard. This means that clients using
FindFirst to lookup filenames do not require search privileges
unless we end up needing to do a case-matching search.
---
source/smbd/dir.c | 62 ++++++++++++++++++++++++++++++++++++++++++++
++------
1 files changed, 54 insertions(+), 8 deletions(-)
diff --git a/source/smbd/dir.c b/source/smbd/dir.c
index ca6f8bf..885e9f5 100644
--- a/source/smbd/dir.c
+++ b/source/smbd/dir.c
@@ -170,10 +170,8 @@ static void dptr_idleoldest(void)
*/
for(; dptr; dptr = dptr->prev) {
- if (dptr->dir_hnd) {
- dptr_idle(dptr);
- return;
- }
+ dptr_idle(dptr);
+ return;
}
}
@@ -328,8 +326,9 @@ void dptr_idlecnum(connection_struct *conn)
{
struct dptr_struct *dptr;
for(dptr = dirptrs; dptr; dptr = dptr->next) {
- if (dptr->conn == conn && dptr->dir_hnd)
+ if (dptr->conn == conn) {
dptr_idle(dptr);
+ }
}
}
@@ -342,8 +341,9 @@ void dptr_closepath(char *path,uint16 spid)
struct dptr_struct *dptr, *next;
for(dptr = dirptrs; dptr; dptr = next) {
next = dptr->next;
- if (spid == dptr->spid && strequal(dptr->path,path))
+ if (spid == dptr->spid && strequal(dptr->path,path)) {
dptr_close_internal(dptr);
+ }
}
}
@@ -659,6 +659,22 @@ const char *dptr_ReadDirName(TALLOC_CTX *ctx,
return NULL;
}
}
+
+ /* We can get here if we were searching for a filename (not a
wildcard)
+ * but we weren't able to open the containing directory. We have no
+ * hope of iterating, so we can only return NULL here.
+ */
+ if (dptr->dir_hnd->dir == NULL) {
+ /* XXX What we should be doing here is saving the errno from
+ * when we originally failed to open the directory. We need to
+ * return an NT_STATUS at this point so we can faithfully tell
+ * the client that we couldn't search for the file (distinct
+ * from the file not being found).
+ */
+ dptr->dir_hnd->offset = *poffset = END_OF_DIRECTORY_OFFSET;
+ return NULL;
+ }
+
return dptr_normal_ReadDirName(dptr, poffset, pst);
}
@@ -1148,8 +1164,27 @@ struct smb_Dir *OpenDir(TALLOC_CTX *mem_ctx,
connection_struct *conn,
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) ));
+ /* Unless we will be doing a wildcard search, iterating over
+ * the whole directory, or the path isn't a directory,
+ * we can try to muddle on without a directory handle.
+ *
+ * Note that we might still have to do a case-matching search
+ * if the filesystem is case sensitive and the client hasn't
+ * asked for the correct case. This will fail.
+ */
+ if (errno == ENOENT || errno == ENOTDIR ||
+ mask == NULL || ms_has_wild(mask)) {
+ DEBUG(5, ("OpenDir: can't open directory '%s': %s\n",
+ dirp->dir_path, strerror(errno) ));
+ goto fail;
+ }
+
+ /* We now have a directory handle that is not backed by an open
+ * directory. The only valid operation is to close or to read
+ * the (non-wildcard) name.
+ */
+ DEBUG(5, ("OpenDir: can't open directory '%s': %s, "
+ "continuing\n", dirp->dir_path, strerror(errno) ));
goto fail;
}
@@ -1170,6 +1205,8 @@ const char *ReadDirName(struct smb_Dir *dirp,
long *poffset)
const char *n;
connection_struct *conn = dirp->conn;
+ SMB_ASSERT(dirp->dir != NULL);
+
/* Cheat to allow . and .. to be the first entries returned. */
if (((*poffset == START_OF_DIRECTORY_OFFSET) || (*poffset ==
DOT_DOT_DIRECTORY_OFFSET)) && (dirp->file_number < 2)) {
if (dirp->file_number == 0) {
@@ -1210,7 +1247,10 @@ const char *ReadDirName(struct smb_Dir *dirp,
long *poffset)
void RewindDir(struct smb_Dir *dirp, long *poffset)
{
+ SMB_ASSERT(dirp->dir != NULL);
+
SMB_VFS_REWINDDIR(dirp->conn, dirp->dir);
+
dirp->file_number = 0;
dirp->offset = START_OF_DIRECTORY_OFFSET;
*poffset = START_OF_DIRECTORY_OFFSET;
@@ -1222,6 +1262,7 @@ void RewindDir(struct smb_Dir *dirp, long
*poffset)
void SeekDir(struct smb_Dir *dirp, long offset)
{
+ SMB_ASSERT(dirp->dir != NULL);
if (offset != dirp->offset) {
if (offset == START_OF_DIRECTORY_OFFSET) {
RewindDir(dirp, &offset);
@@ -1298,6 +1339,11 @@ bool SearchDir(struct smb_Dir *dirp, const char
*name, long *poffset)
const char *entry;
connection_struct *conn = dirp->conn;
+ /* Search is only valid for wildcards and we must have an open
+ * directory for those.
+ */
+ SMB_ASSERT(dirp->dir != NULL);
+
/* Search back in the name cache. */
if (dirp->name_cache_size && dirp->name_cache) {
for (i = dirp->name_cache_index; i >= 0; i--) {
--
1.5.3.4
More information about the samba-technical
mailing list