Bug 35353 - cfs strips eighth bit of file name on "output"
Summary: cfs strips eighth bit of file name on "output"
Status: Closed FIXED
Alias: None
Product: Ports & Packages
Classification: Unclassified
Component: Individual Port(s) (show other bugs)
Version: Latest
Hardware: Any Any
: Normal Affects Only Me
Assignee: Brian Feldman
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2002-02-26 21:00 UTC by Olof Samuelsson
Modified: 2004-04-18 04:11 UTC (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Olof Samuelsson 2002-02-26 21:00:02 UTC
cfs seems to strip the eighth bit of characters in file names when listing directories.  It is not stripped on input (see "How to repeat...").

How-To-Repeat: (setup cfs, cattach /crypt/crypt)
cd /crypt/crypt/apa
and ...
boulard:/crypt/crypt/apa$ ls 
boulard:/crypt/crypt/apa$ touch åtrå
boulard:/crypt/crypt/apa$ ls
etre
boulard:/crypt/crypt/apa$ ls -l
ls: etre: No such file or directory
boulard:/crypt/crypt/apa(1)$ rm etre
rm: etre: No such file or directory
boulard:/crypt/crypt/apa(1)$ cat åtrå
boulard:/crypt/crypt/apa$ rm åtrå
boulard:/crypt/crypt/apa$ ls
boulard:/crypt/crypt/apa$
Comment 1 Patrick Li freebsd_committer freebsd_triage 2002-02-26 21:53:29 UTC
Responsible Changed
From-To: freebsd-ports->green

Over to maintainer
Comment 2 Olof Samuelsson 2002-08-09 15:28:00 UTC
I've tested the following patch (from Debian) for a short while and it 
seems to solve the problem:
--- Orig-cfs_fh.c       Sun Apr 28 15:32:16 2002
+++ cfs_fh.c    Sun Apr 28 15:45:11 2002
@@ -225,7 +225,9 @@
 }
 
 /*
- * set high order bits
+ * Carefully frob the high order bits of s in a way that is both easily
+ * reversible (see unchksum) and backwards-compatible (at least for 7-bit
+ * characters).
  */
 chksum(s,l)
      char *s;
@@ -236,14 +238,43 @@
        u_char bits[8];
 
        acc=0;
-       for (i=0; s[i]!='\0'; i++)
-               acc += s[i]*((i%6)+1);
+       /* Everything we do here must be reproducible without knowledge of
+          bit 7 because unchksum won't have that information.  Therefore,
+          only accumulate the lower 7 bits of each char and stop at the
+          first occurrence of either 0x00 or 0x80.  Note that, for inputs
+          with bit 7 constantly zero, this is equivalent to looking at the
+          whole string. */
+       for (i=0; (s[i]&0x7f) != '\0'; i++)
+               acc += (s[i]&0x7f)*((i%6)+1);
+       for (; s[i]!='\0'; i++) /* advance i if we stopped at a 0x80 */
+               ;
        for (i++; i<l; i++)     /* fill up the end */
                s[i] = s[i%8];
        for (i=0; i<8; i++)
                bits[i] = (acc<<(i%8))&0x80;
        for (i=0; i<l; i++)
-               s[i] |= bits[i%8];
+               s[i] ^= bits[i%8];
+}
+
+unchksum(s,l)
+    char *s;
+    long l;
+{
+       u_long acc;
+       int i;
+       u_char bits[8];
+
+       acc=0;
+       for (i=0; (s[i]&0x7f) != '\0'; i++)
+               acc += (s[i]&0x7f)*((i%6)+1);
+       for (i=0; i<8; i++)
+               bits[i] = (acc<<(i%8))&0x80;
+       for (i=0; i<l; i++) {
+               s[i] ^= bits[i%8];
+               /* not sure whether this actually buys any performance */
+               if(s[i]=='\0')
+                       break;  /* found end of filename, can stop here */
+       }
 }
 
 
@@ -286,9 +317,7 @@
        if (l%CFSBLOCK)
                return NULL;
        dodecrypt(key,clearstring,l,10241,zerovect);
-       for (i=0; (clearstring[i]&0x7f) !='\0'; i++)
-               clearstring[i] &= 0x7f;
-       clearstring[i]='\0';
+       unchksum(clearstring,l);
        return clearstring;
 }
Comment 3 Brian Feldman freebsd_committer freebsd_triage 2004-04-18 04:11:02 UTC
State Changed
From-To: open->closed

Thank you for fixing this!  I am sorry for not applying your PR sooner.