Re: msdos fs cd ...

Gordon Chaffee (chaffee@CS.Berkeley.EDU)
Mon, 29 Dec 1997 02:05:40 -0800 (PST)


ther writes:
> hmm - i wonder if this should happend ;)
>
> ghanima:/dos_d# ls
> justroot.txt
> ghanima:/dos_d# cd ...
> ghanima:/dos_d/...# ls
> justroot.txt
> ghanima:/dos_d/...# cd ..
> ghanima:/dos_d# ls
> justroot.txt
>
> cd ... acts like a cd .. but its displayed like an existing directory..
> after a few 100 "cd ..." bash sigsegv's.

I think you meant vfat, not msdos. I tried it under msdos, and it does
the correct thing. Under vfat, it showed the behavior you found. Here
is a patch that fixes it. I'm putting in some more work on this patch
because there are some bad interactions of the dcache and vfat short
aliases. Basically, if you do a lookup on a long name, remove a file
via the short alias, the long name doesn't get removed from the dcache.
For now, here is the patch.

- Gordon

diff -u linux{-2.1.75-clean,}/fs/vfat/namei.c
--- linux-2.1.75-clean/fs/vfat/namei.c Sun Dec 21 21:46:51 1997
+++ linux/fs/vfat/namei.c Mon Dec 29 01:58:27 1997
@@ -173,6 +173,9 @@

len = qstr->len;
name = qstr->name;
+ while (len && name[len-1] == '.')
+ len--;
+
hash = init_name_hash();
while (len--) {
c = tolower(*name++);
@@ -193,14 +196,12 @@
/* A filename cannot end in '.' or we treat it like it has none */
alen = a->len;
blen = b->len;
- if (alen != blen) {
- if (a->name[alen-1] == '.')
- alen--;
- if (b->name[blen-1] == '.')
- blen--;
- if (alen != blen)
- return 1;
- }
+ while (alen && a->name[alen-1] == '.')
+ alen--;
+ while (blen && b->name[blen-1] == '.')
+ blen--;
+ if (alen != blen)
+ return 1;

return strnicmp(a->name, b->name, alen);
}
@@ -940,11 +941,8 @@
vf->name, vf->len, name, name_len);
#endif

- /* Filenames cannot end in '.' or we treat like it has none */
if (vf->len != name_len) {
- if ((vf->len != name_len + 1) || (vf->name[name_len] != '.')) {
- return 0;
- }
+ return 0;
}

s1 = name; s2 = vf->name;
@@ -1584,7 +1582,7 @@
/* Is this the same file, different case? */
if (new_inode != old_inode) {
PRINTK(("vfat_rename 9\n"));
- res = vfat_unlinkx(new_dir,new_dentry,1);
+ res = vfat_unlink(new_dir,new_dentry);
PRINTK(("vfat_rename 10\n"));
if (res < 0) goto rename_done;
}