r2893: added very primitive name mangling support to pvfs
authorAndrew Tridgell <tridge@samba.org>
Sun, 10 Oct 2004 05:29:59 +0000 (05:29 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 17:59:45 +0000 (12:59 -0500)
(This used to be commit 749fa73544201f521d9cd3fa972b89cae99bc2c0)

source4/ntvfs/posix/pvfs_resolve.c
source4/ntvfs/posix/pvfs_shortname.c

index e846b7be77e3c9d6d885d964634d371b3d8236cd..5d6f270a424490cc3a29cfc8f59a8ff24013341e 100644 (file)
 /*
   compare two filename components. This is where the name mangling hook will go
 */
-static int component_compare(const char *c1, const char *c2)
+static int component_compare(struct pvfs_state *pvfs, const char *comp, const char *name)
 {
-       return StrCaseCmp(c1, c2);
+       char *shortname;
+       int ret;
+
+       if (StrCaseCmp(comp, name) == 0) return 0;
+
+       shortname = pvfs_short_name_component(pvfs, name);
+
+       ret = StrCaseCmp(comp, shortname);
+
+       talloc_free(shortname);
+       return ret;
 }
 
 /*
@@ -110,7 +120,7 @@ static NTSTATUS pvfs_case_search(struct pvfs_state *pvfs, struct pvfs_filename *
                }
 
                while ((de = readdir(dir))) {
-                       if (component_compare(components[i], de->d_name) == 0) {
+                       if (component_compare(pvfs, components[i], de->d_name) == 0) {
                                break;
                        }
                }
index 21c0ca6ea0d21a7e31631e9a4faeda4c080d9d86..ae911ad885819c5f55df7f226fda24029f7039df 100644 (file)
 #include "include/includes.h"
 #include "vfs_posix.h"
 
+#define FNV1_PRIME 0x01000193
+/*the following number is a fnv1 of the string: idra@samba.org 2002 */
+#define FNV1_INIT  0xa6b93095
+
+/* 
+   hash a string of the specified length. The string does not need to be
+   null terminated 
+
+   this hash needs to be fast with a low collision rate (what hash doesn't?)
+*/
+static uint32_t mangle_hash(const char *key)
+{
+       uint32_t value;
+       codepoint_t c;
+       size_t c_size;
+
+       for (value = FNV1_INIT; 
+            (c=next_codepoint(key, &c_size)); 
+            key += c_size) {
+               c = toupper_w(c);
+                value *= (uint32_t)FNV1_PRIME;
+                value ^= (uint32_t)c;
+        }
+
+       /* note that we force it to a 31 bit hash, to keep within the limits
+          of the 36^6 mangle space */
+       return value & ~0x80000000;  
+}
 
 /*
   return the short name for a component of a full name
 */
 char *pvfs_short_name_component(struct pvfs_state *pvfs, const char *name)
 {
-       return talloc_strndup(pvfs, name, 12);
+       const char *basechars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+       uint32_t hash;
+       char c1, c2;
+       const char *ext;
+
+       if (strlen(name) < 12) {
+               return talloc_strdup(pvfs, name);
+       }
+
+       hash = mangle_hash(name);
+       ext = strrchr(name, '.');
+
+       c1 = basechars[(hash/36)%36];
+       c2 = basechars[hash%36];
+
+       return talloc_asprintf(pvfs, "%.5s~%c%c%.4s", name, c1, c2, ext?ext:"");
+       
 }