From 69d61453df6019caef4e7960fa78c6a3c51f3d2a Mon Sep 17 00:00:00 2001 From: tprouty Date: Sat, 2 May 2009 00:28:38 +0000 Subject: s3: Fix trans2 path to use case-insensitive stat optimization Often times before creating a file, a client will first query to see if it already exists. Since some systems have a case-insensitive stat that is called from unix_convert, we can definitively return STATUS_NO_SUCH_FILE to the client without scanning the whole directory. This code path is taken from trans2querypathinfo, but trans2findfirst still does a full directory scan even though the get_real_filename (the case-insensitive stat vfs call) can prevent this. This patch adds the get_real_filename call to the trans2find* path, and also changes the vfs_default behavior for SMB_VFS_GET_REAL_FILENAME. Previously, in the absence of a get_real_filename implementation, we would fallback to the full directory scan. The default behavior now returns -1 and sets errno to EOPNOTSUPP. This allows SMB_VFS_GET_REALFILENAME to be called from trans2* and unix_convert. --- source3/smbd/dir.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'source3/smbd/dir.c') diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index b4a8f942c2..e7902871d3 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -576,6 +576,9 @@ const char *dptr_ReadDirName(TALLOC_CTX *ctx, { char *name = NULL; char *pathreal = NULL; + char *found_name = NULL; + int ret; + SET_STAT_INVALID(*pst); if (dptr->has_wild || dptr->did_stat) { @@ -640,6 +643,20 @@ const char *dptr_ReadDirName(TALLOC_CTX *ctx, goto clean; } + /* + * Try case-insensitive stat if the fs has the ability. This avoids + * scanning the whole directory. + */ + ret = SMB_VFS_GET_REAL_FILENAME(dptr->conn, dptr->path, dptr->wcard, + ctx, &found_name); + if (ret == 0) { + name = found_name; + goto clean; + } else if (errno == ENOENT) { + /* The case-insensitive lookup was authoritative. */ + goto clean; + } + TALLOC_FREE(pathreal); return dptr_normal_ReadDirName(dptr, poffset, pst); -- cgit