This is an automated email from the ASF dual-hosted git repository.

markt pushed a commit to branch 11.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git


The following commit(s) were added to refs/heads/11.0.x by this push:
     new c3fffb051e Improve detection of case sensitive vs case insensitive 
file systems
c3fffb051e is described below

commit c3fffb051eb5b54aa8c1302d47151834f3f61370
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Tue Feb 18 09:46:45 2025 +0000

    Improve detection of case sensitive vs case insensitive file systems
---
 .../catalina/webresources/DirResourceSet.java      | 42 +++++++++++++----
 webapps/docs/changelog.xml                         | 53 ++--------------------
 2 files changed, 38 insertions(+), 57 deletions(-)

diff --git a/java/org/apache/catalina/webresources/DirResourceSet.java 
b/java/org/apache/catalina/webresources/DirResourceSet.java
index 4f39e87378..dbbc126c41 100644
--- a/java/org/apache/catalina/webresources/DirResourceSet.java
+++ b/java/org/apache/catalina/webresources/DirResourceSet.java
@@ -369,22 +369,48 @@ public class DirResourceSet extends 
AbstractFileResourceSet implements WebResour
 
     /*
      * Determines if this ResourceSet is based on a case sensitive file system 
or not.
+     *
+     * File systems are usually case sensitive or not. Windows, via the 
command 'fsutil.exe file setCaseSensitiveInfo
+     * <path> enable', may be case sensitive in some directories and case 
insensitive in others.
+     *
+     * If this method incorrectly determines that the DirResourceSet is case 
sensitive, the file locking mechanism that
+     * ensures write operations are performed atomically will not operate 
correctly. If this method incorrectly
+     * determines that the DirResourceSet is case insensitive, there is a 
small performance penalty for writes.
+     *
+     * Given the above, this method only reports the file system as case 
sensitive if no indication of case
+     * insensitivity is detected. This does mean that Windows based 
DirResourceSet instances will be reported as case
+     * insensitive even all of the directories in the DirResourceSet have been 
configured as case sensitive.
      */
     private boolean isCaseSensitive() {
         try {
             String canonicalPath = getFileBase().getCanonicalPath();
+            /*
+             * If any lower case characters are found in the canonical file 
name formed by converting the test file name
+             * to upper case, the underlying file system must be, at least in 
part, case insensitive.
+             */
             File upper = new File(canonicalPath.toUpperCase(Locale.ENGLISH));
-            if (!canonicalPath.equals(upper.getCanonicalPath())) {
-                return true;
-            }
-            File lower = new File(canonicalPath.toLowerCase(Locale.ENGLISH));
-            if (!canonicalPath.equals(lower.getCanonicalPath())) {
-                return true;
+            String upperCanonicalPath = upper.getCanonicalPath();
+            char[] upperCharacters = upperCanonicalPath.toCharArray();
+            for (char c : upperCharacters) {
+                if (Character.isLowerCase(c)) {
+                    return false;
+                }
             }
+
             /*
-             * Both upper and lower case versions of the current fileBase have 
the same canonical path so the file
-             * system must be case insensitive.
+             * If any upper case characters are found in the canonical file 
name formed by converting the test file name
+             * to lower case, the underlying file system must be, at least in 
part, case insensitive.
              */
+            File lower = new File(canonicalPath.toLowerCase(Locale.ENGLISH));
+            String lowerCanonicalPath = lower.getCanonicalPath();
+            char[] lowerCharacters = lowerCanonicalPath.toCharArray();
+            for (char c : lowerCharacters) {
+                if (Character.isUpperCase(c)) {
+                    return false;
+                }
+            }
+
+            return true;
         } catch (IOException ioe) {
             log.warn(sm.getString("dirResourceSet.isCaseSensitive.fail", 
getFileBase().getAbsolutePath()), ioe);
         }
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index c4a39bb95c..82e666d497 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -116,6 +116,10 @@
         possible that cached 'not found' results could effectively hide lookup
         results using the correct resource name. (markt)
       </fix>
+      <fix>
+        Improve the mechanism for detecting whether a web application has been
+        deployed to a case sensitive or a case insensitive file system. (markt)
+      </fix>
     </changelog>
   </subsection>
   <subsection name="Other">
@@ -699,55 +703,6 @@
         controlled via the new <code>notFoundClassResourceCacheSize</code> on
         the StandardContext. (markt)
       </fix>
-      <fix>
-        Stop after <code>INITIALIZED</code> state should be a noop since it is
-        possible for subcomponents to be in <code>FAILED</code> after init.
-        (remm)
-      </fix>
-      <fix>
-        Fix incorrect web resource cache size calculations when there are
-        concurrent <code>PUT</code> and <code>DELETE</code> requests for the
-        same resource. (markt)
-      </fix>
-      <add>
-        Add debug logging for the web resource cache so the current size can be
-        tracked as resources are added and removed. (markt)
-      </add>
-      <update>
-        Replace legacy WebDAV <code>opaquelocktoken:</code> scheme for lock
-        tokens with <code>urn:uuid:</code> as recommended by RFC 4918, and
-        remove <code>secret</code> init parameter. (remm)
-      </update>
-      <fix>
-        Concurrent reads and writes (e.g. <code>GET</code> and <code>PUT</code>
-        / <code>DELETE</code>) for the same path caused corruption of the
-        <code>FileResource</code> where some of the fields were set as if the
-        file exists and some were set as if it does not. This resulted in
-        inconsistent metadata. (markt)
-      </fix>
-      <fix>
-        <bug>69415</bug>: Ensure that the <code>ExpiresFilter</code> only sets
-        cache headers on <code>GET</code> and <code>HEAD</code> requests. Also
-        skip requests where the application has set <code>Cache-Control:
-        no-store</code>. (markt)
-      </fix>
-      <fix>
-        <bug>69419</bug>: Improve the performance of
-        <code>ServletRequest.getAttribute()</code> when there are multiple
-        levels of nested includes. Based on a patch provided by John
-        Engebretson. (markt)
-      </fix>
-      <fix>
-        <bug>69426</bug>: Restore providing a value (rather than null) for
-        <code>Class.getProtectionDomain().getCodeSource().getLocation()</code>
-        as a number of libraries and JRE features depend on this being non-null
-        even when a SecurityManager is not is use. (markt)
-      </fix>
-      <add>
-        All applications to send an early hints informational response by
-        calling <code>HttpServletResponse.sendError()</code> with a status code
-        of 103. (schultz)
-      </add>
     </changelog>
   </subsection>
   <subsection name="Coyote">


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to