Currently, ftpfs is broken with respect to files with spaces in their
filename. We assume all files will be sent as a single string, while
this is not the case. My fix is a kind of nasty hack, but I couldn't
think of a better way that didn't require a lot more restructuring
than I was willing to do. Anyway, example of the problem:
ls /n/ftp/mp3/mp3
:
/n/ftp/mp3/mp3/Borsato
:
The expected output from ls is:
'/n/ftp/mp3/mp3/Marco Borsato'
With this patch, any filenames with spaces in them are fixed for
correct output:
'/n/ftp/mp3/mp3/thievery corporation - sounds from the thievery hi-fi/04. transcendence.mp3'
for example.
I reorganized the case handling as well, but that's more of a style
thing. If you have other suggestions for changes that would make this
more suitable for incorporating as a patch, I'd love to hear them!
Notes:
Tue Oct 2 16:23:55 EDT 2007 geoff
it is indeed a nasty hack and a moderately large diff for
what one would hope to be a minor change. it also seems that
spaces are likely to cause problems elsewhere in ftp, client
and server. given that ftp is a complex, ugly, and old protocol,
i'm inclined to document the limitation and call it a day.
saved in case we decide to revisit this.
Reference: /n/sources/patch/saved/ftpfs-unix-spacefiles
Date: Tue Oct 2 22:12:59 CES 2007
Signed-off-by: devon.odell@gmail.com
Reviewed-by: geoff
--- /sys/src/cmd/ip/ftpfs/proto.c Tue Apr 17 22:03:45 2007
+++ /sys/src/cmd/ip/ftpfs/proto.c Tue Apr 17 22:03:44 2007
@@ -507,6 +507,7 @@
char *field[15];
char *dfield[4];
char *cp;
+ char *pc = strdup(p);
String *s;
int dn, n;
Dir d, *dp;
@@ -661,6 +662,28 @@
case Plan9:
default:
switch(n){
+ case 1:
+ s = s_copy(field[0]);
+ d.uid = "none";
+ d.gid = d.uid;
+ d.mode = 0777;
+ d.atime = 0;
+ break;
+ case 4: /* a Windows_NT version */
+ s = s_copy(field[3]);
+ d.uid = "NT";
+ d.gid = d.uid;
+ if(strcmp("
", field[2]) == 0){
+ d.length = 0;
+ d.mode = DMDIR|0777;
+ } else {
+ d.mode = 0666;
+ d.length = atoi(field[2]);
+ }
+ dn = getfields(field[0], dfield, 4, 1, "/-");
+ if(dn == 3)
+ d.atime = cracktime(dfield[0], dfield[1], dfield[2], field[1]);
+ break;
case 8: /* ls -l */
s = s_copy(field[7]);
d.uid = field[2];
@@ -683,41 +706,42 @@
else
d.atime = cracktime(field[5], field[6], field[7], 0);
break;
- case 10: /* plan 9 */
- s = s_copy(field[9]);
- d.uid = field[3];
- d.gid = field[4];
- d.mode = crackmode(field[0]);
- d.length = atoi(field[5]);
- if(strchr(field[8], ':'))
- d.atime = cracktime(field[6], field[7], 0, field[8]);
- else
- d.atime = cracktime(field[6], field[7], field[8], 0);
- break;
- case 4: /* a Windows_NT version */
- s = s_copy(field[3]);
- d.uid = "NT";
- d.gid = d.uid;
- if(strcmp("", field[2]) == 0){
- d.length = 0;
- d.mode = DMDIR|0777;
- } else {
- d.mode = 0666;
- d.length = atoi(field[2]);
+ case 10:
+ if (os == Plan9) {
+ s = s_copy(field[9]);
+ d.uid = field[3];
+ d.gid = field[4];
+ d.mode = crackmode(field[0]);
+ d.length = atoi(field[5]);
+ if(strchr(field[8], ':'))
+ d.atime = cracktime(field[6], field[7], 0, field[8]);
+ else
+ d.atime = cracktime(field[6], field[7], field[8], 0);
}
- dn = getfields(field[0], dfield, 4, 1, "/-");
- if(dn == 3)
- d.atime = cracktime(dfield[0], dfield[1], dfield[2], field[1]);
- break;
- case 1:
- s = s_copy(field[0]);
- d.uid = "none";
- d.gid = d.uid;
- d.mode = 0777;
- d.atime = 0;
- break;
+ /* Fallthrough; UNIX servers don't encapsulate files with spaces in their names */
default:
- return nil;
+ if (os == Unix && n > 9) {
+ char *t = strstr(pc, field[7]);
+
+ if (t == nil) {
+ write(2, "XXX!!!\n",7);
+ return nil;
+ }
+
+ t += strlen(field[7]) + 1;
+
+ d.uid = field[2];
+ d.gid = field[3];
+ d.mode = crackmode(field[0]);
+ d.length = atoi(field[4]);
+ if(strchr(field[7], ':'))
+ d.atime = cracktime(field[5], field[6], 0, field[7]);
+ else
+ d.atime = cracktime(field[5], field[6], field[7], 0);
+
+ s = s_copy(t);
+ } else
+ return nil;
}
}
d.muid = d.uid;