summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Peach <jpeach@samba.org>2007-12-22 14:55:37 -0800
committerJames Peach <jpeach@samba.org>2007-12-22 14:55:37 -0800
commit596018455af0d80add90215689a80d336157429c (patch)
treee57331a0b8e0737da5fe4efb6b7d171a029402cf
parent4dc0c1b88be359cbf4e5273e1670ef0f87b9e36b (diff)
downloadsamba-596018455af0d80add90215689a80d336157429c.tar.gz
samba-596018455af0d80add90215689a80d336157429c.tar.bz2
samba-596018455af0d80add90215689a80d336157429c.zip
Use filesystem capabilities to support case-insensitive filesystems.
If we know the underlying filesystem is case-insensitive, then we know that it won't help to search for case variations of the requested name. Jeremy, please review (and revert if you disagree). (This used to be commit 9e8b8f8c16612d8a08b55802f4fd9afca5498a7c)
-rw-r--r--source3/smbd/dir.c38
-rw-r--r--source3/smbd/filename.c9
2 files changed, 30 insertions, 17 deletions
diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c
index 05679ee0ee..ccf91fe57d 100644
--- a/source3/smbd/dir.c
+++ b/source3/smbd/dir.c
@@ -646,10 +646,13 @@ const char *dptr_ReadDirName(TALLOC_CTX *ctx,
TALLOC_FREE(pathreal);
- /* In case sensitive mode we don't search - we know if it doesn't exist
- with a stat we will fail. */
+ /* Stat failed. We know this is authoratiative if we are
+ * providing case sensitive semantics or the underlying
+ * filesystem is case sensitive.
+ */
- if (dptr->conn->case_sensitive) {
+ if (dptr->conn->case_sensitive ||
+ !(dptr->conn->fs_capabilities & FILE_CASE_SENSITIVE_SEARCH)) {
/* We need to set the underlying dir_hnd offset to -1 also as
this function is usually called with the output from TellDir. */
dptr->dir_hnd->offset = *poffset = END_OF_DIRECTORY_OFFSET;
@@ -924,12 +927,7 @@ static bool user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_S
return True;
}
- /* If we can't stat it does not show it */
- if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0)) {
- DEBUG(10,("user_can_read_file: SMB_VFS_STAT failed for file %s with error %s\n",
- name, strerror(errno) ));
- return False;
- }
+ SMB_ASSERT(VALID_STAT(*pst));
/* Pseudo-open the file (note - no fd's created). */
@@ -987,10 +985,7 @@ static bool user_can_write_file(connection_struct *conn, char *name, SMB_STRUCT_
return True;
}
- /* If we can't stat it does not show it */
- if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0)) {
- return False;
- }
+ SMB_ASSERT(VALID_STAT(*pst));
/* Pseudo-open the file */
@@ -1039,9 +1034,7 @@ static bool file_is_special(connection_struct *conn, char *name, SMB_STRUCT_STAT
if (conn->admin_user)
return False;
- /* If we can't stat it does not show it */
- if (!VALID_STAT(*pst) && (SMB_VFS_STAT(conn, name, pst) != 0))
- return True;
+ SMB_ASSERT(VALID_STAT(*pst));
if (S_ISREG(pst->st_mode) || S_ISDIR(pst->st_mode) || S_ISLNK(pst->st_mode))
return False;
@@ -1050,7 +1043,9 @@ static bool file_is_special(connection_struct *conn, char *name, SMB_STRUCT_STAT
}
/*******************************************************************
- Should the file be seen by the client ?
+ Should the file be seen by the client ? NOTE: A successful return
+ is no guarantee of the file's existence ... you also have to check
+ whether pst is valid.
********************************************************************/
bool is_visible_file(connection_struct *conn, const char *dir_path, const char *name, SMB_STRUCT_STAT *pst, bool use_veto)
@@ -1086,6 +1081,15 @@ bool is_visible_file(connection_struct *conn, const char *dir_path, const char *
return True;
}
+ /* If the file name does not exist, there's no point checking
+ * the configuration options. We succeed, on the basis that the
+ * checks *might* have passed if the file was present.
+ */
+ if (SMB_VFS_STAT(conn, entry, pst) != 0) {
+ SAFE_FREE(entry);
+ return True;
+ }
+
/* Honour _hide unreadable_ option */
if (hide_unreadable && !user_can_read_file(conn, entry, pst)) {
DEBUG(10,("is_visible_file: file %s is unreadable.\n", entry ));
diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c
index dc733d4568..f0d036b82b 100644
--- a/source3/smbd/filename.c
+++ b/source3/smbd/filename.c
@@ -735,6 +735,15 @@ static bool scan_directory(connection_struct *conn, const char *path,
path = ".";
}
+ /* If we have a case-sensitive filesystem, it doesn't do us any
+ * good to search for a name. If a case variation of the name was
+ * there, then the original stat(2) would have found it.
+ */
+ if (!mangled && !(conn->fs_capabilities & FILE_CASE_SENSITIVE_SEARCH)) {
+ errno = ENOENT;
+ return False;
+ }
+
/*
* The incoming name can be mangled, and if we de-mangle it
* here it will not compare correctly against the filename (name2)