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;