2 * linux/fs/vfat/namei.c
4 * Written 1992,1993 by Werner Almesberger
6 * Windows95/Windows NT compatible extended MSDOS filesystem
7 * by Gordon Chaffee Copyright (C) 1995. Send bug reports for the
8 * VFAT filesystem to <chaffee@cs.berkeley.edu>. Specify
9 * what file operation caused you trouble and if you can duplicate
10 * the problem, send a script that demonstrates it.
12 * Short name translation 1999, 2001 by Wolfram Pienkoss <wp@bszh.de>
14 * Support Multibyte character and cleanup by
15 * OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
18 #include <linux/module.h>
20 #include <linux/sched.h>
21 #include <linux/msdos_fs.h>
22 #include <linux/nls.h>
23 #include <linux/kernel.h>
24 #include <linux/errno.h>
25 #include <linux/string.h>
26 #include <linux/ctype.h>
27 #include <linux/stat.h>
29 #include <linux/slab.h>
32 #if (DEBUG_LEVEL >= 1)
33 # define PRINTK1(x) printk x
37 #if (DEBUG_LEVEL >= 2)
38 # define PRINTK2(x) printk x
42 #if (DEBUG_LEVEL >= 3)
43 # define PRINTK3(x) printk x
48 static int vfat_hashi(struct dentry *parent, struct qstr *qstr);
49 static int vfat_hash(struct dentry *parent, struct qstr *qstr);
50 static int vfat_cmpi(struct dentry *dentry, struct qstr *a, struct qstr *b);
51 static int vfat_cmp(struct dentry *dentry, struct qstr *a, struct qstr *b);
52 static int vfat_revalidate(struct dentry *dentry, int);
54 static struct dentry_operations vfat_dentry_ops[4] = {
60 d_revalidate: vfat_revalidate,
69 d_revalidate: vfat_revalidate,
75 static int vfat_revalidate(struct dentry *dentry, int flags)
77 PRINTK1(("vfat_revalidate: %s\n", dentry->d_name.name));
78 spin_lock(&dcache_lock);
79 if (dentry->d_time == dentry->d_parent->d_inode->i_version) {
80 spin_unlock(&dcache_lock);
83 spin_unlock(&dcache_lock);
87 static int simple_getbool(char *s, int *setval)
90 if (!strcmp(s,"1") || !strcmp(s,"yes") || !strcmp(s,"true")) {
92 } else if (!strcmp(s,"0") || !strcmp(s,"no") || !strcmp(s,"false")) {
103 static int parse_options(char *options, struct fat_mount_options *opts)
105 char *this_char,*value,save,*savep;
108 opts->unicode_xlate = opts->posixfs = 0;
111 opts->shortname = VFAT_SFN_DISPLAY_LOWER | VFAT_SFN_CREATE_WIN95;
112 /* for backward compatible */
115 opts->shortname = VFAT_SFN_DISPLAY_WIN95
116 | VFAT_SFN_CREATE_WIN95;
119 if (!options) return 1;
123 for (this_char = strtok(options,","); this_char; this_char = strtok(NULL,",")) {
124 if ((value = strchr(this_char,'=')) != NULL) {
129 if (!strcmp(this_char,"utf8")) {
130 ret = simple_getbool(value, &val);
131 if (ret) opts->utf8 = val;
132 } else if (!strcmp(this_char,"uni_xlate")) {
133 ret = simple_getbool(value, &val);
134 if (ret) opts->unicode_xlate = val;
135 } else if (!strcmp(this_char,"posix")) {
136 ret = simple_getbool(value, &val);
137 if (ret) opts->posixfs = val;
138 } else if (!strcmp(this_char,"nonumtail")) {
139 ret = simple_getbool(value, &val);
141 opts->numtail = !val;
143 } else if (!strcmp(this_char, "shortname")) {
144 if (!strcmp(value, "lower"))
145 opts->shortname = VFAT_SFN_DISPLAY_LOWER
146 | VFAT_SFN_CREATE_WIN95;
147 else if (!strcmp(value, "win95"))
148 opts->shortname = VFAT_SFN_DISPLAY_WIN95
149 | VFAT_SFN_CREATE_WIN95;
150 else if (!strcmp(value, "winnt"))
151 opts->shortname = VFAT_SFN_DISPLAY_WINNT
152 | VFAT_SFN_CREATE_WINNT;
153 else if (!strcmp(value, "mixed"))
154 opts->shortname = VFAT_SFN_DISPLAY_WINNT
155 | VFAT_SFN_CREATE_WIN95;
159 if (this_char != options)
160 *(this_char-1) = ',';
168 if (opts->unicode_xlate) {
174 static inline unsigned char
175 vfat_tolower(struct nls_table *t, unsigned char c)
177 unsigned char nc = t->charset2lower[c];
182 static inline unsigned char
183 vfat_toupper(struct nls_table *t, unsigned char c)
185 unsigned char nc = t->charset2upper[c];
191 vfat_strnicmp(struct nls_table *t, const unsigned char *s1,
192 const unsigned char *s2, int len)
195 if (vfat_tolower(t, *s1++) != vfat_tolower(t, *s2++))
202 * Compute the hash for the vfat name corresponding to the dentry.
203 * Note: if the name is invalid, we leave the hash code unchanged so
204 * that the existing dentry can be used. The vfat fs routines will
205 * return ENOENT or EINVAL as appropriate.
207 static int vfat_hash(struct dentry *dentry, struct qstr *qstr)
214 while (len && name[len-1] == '.')
217 qstr->hash = full_name_hash(name, len);
223 * Compute the hash for the vfat name corresponding to the dentry.
224 * Note: if the name is invalid, we leave the hash code unchanged so
225 * that the existing dentry can be used. The vfat fs routines will
226 * return ENOENT or EINVAL as appropriate.
228 static int vfat_hashi(struct dentry *dentry, struct qstr *qstr)
230 struct nls_table *t = MSDOS_SB(dentry->d_inode->i_sb)->nls_io;
237 while (len && name[len-1] == '.')
240 hash = init_name_hash();
242 hash = partial_name_hash(vfat_tolower(t, *name++), hash);
243 qstr->hash = end_name_hash(hash);
249 * Case insensitive compare of two vfat names.
251 static int vfat_cmpi(struct dentry *dentry, struct qstr *a, struct qstr *b)
253 struct nls_table *t = MSDOS_SB(dentry->d_inode->i_sb)->nls_io;
256 /* A filename cannot end in '.' or we treat it like it has none */
259 while (alen && a->name[alen-1] == '.')
261 while (blen && b->name[blen-1] == '.')
264 if (vfat_strnicmp(t, a->name, b->name, alen) == 0)
271 * Case sensitive compare of two vfat names.
273 static int vfat_cmp(struct dentry *dentry, struct qstr *a, struct qstr *b)
277 /* A filename cannot end in '.' or we treat it like it has none */
280 while (alen && a->name[alen-1] == '.')
282 while (blen && b->name[blen-1] == '.')
285 if (strncmp(a->name, b->name, alen) == 0)
293 static void dump_fat(struct super_block *sb,int start)
298 start = fat_access(sb,start,-1);
303 if (start == -1) break;
308 static void dump_de(struct msdos_dir_entry *de)
311 unsigned char *p = (unsigned char *) de;
314 for (i = 0; i < 32; i++, p++) {
322 /* MS-DOS "device special files" */
324 static const char *reserved3_names[] = {
325 "con ", "prn ", "nul ", "aux ", NULL
328 static const char *reserved4_names[] = {
329 "com1 ", "com2 ", "com3 ", "com4 ", "com5 ",
330 "com6 ", "com7 ", "com8 ", "com9 ",
331 "lpt1 ", "lpt2 ", "lpt3 ", "lpt4 ", "lpt5 ",
332 "lpt6 ", "lpt7 ", "lpt8 ", "lpt9 ",
336 /* Characters that are undesirable in an MS-DOS file name */
338 static wchar_t bad_chars[] = {
339 /* `*' `?' `<' `>' `|' `"' `:' `/' */
340 0x002A, 0x003F, 0x003C, 0x003E, 0x007C, 0x0022, 0x003A, 0x002F,
344 #define IS_BADCHAR(uni) (vfat_unistrchr(bad_chars, (uni)) != NULL)
346 static wchar_t replace_chars[] = {
347 /* `[' `]' `;' `,' `+' `=' */
348 0x005B, 0x005D, 0x003B, 0x002C, 0x002B, 0x003D, 0,
350 #define IS_REPLACECHAR(uni) (vfat_unistrchr(replace_chars, (uni)) != NULL)
352 static wchar_t skip_chars[] = {
356 #define IS_SKIPCHAR(uni) \
357 ((wchar_t)(uni) == skip_chars[0] || (wchar_t)(uni) == skip_chars[1])
359 static inline wchar_t *vfat_unistrchr(const wchar_t *s, const wchar_t c)
364 return (wchar_t *) s;
367 static inline int vfat_is_used_badchars(const wchar_t *s, int len)
371 for (i = 0; i < len; i++)
372 if (s[i] < 0x0020 || IS_BADCHAR(s[i]))
377 /* Checks the validity of a long MS-DOS filename */
378 /* Returns negative number on error, 0 for a normal
379 * return, and 1 for . or .. */
381 static int vfat_valid_longname(const char *name, int len, int xlate)
383 const char **reserved, *walk;
386 if (len && name[len-1] == ' ') return -EINVAL;
387 if (len >= 256) return -EINVAL;
388 if (len < 3) return 0;
390 for (walk = name; *walk != 0 && *walk != '.'; walk++);
391 baselen = walk - name;
394 for (reserved = reserved3_names; *reserved; reserved++) {
395 if (!strnicmp(name,*reserved,baselen))
398 } else if (baselen == 4) {
399 for (reserved = reserved4_names; *reserved; reserved++) {
400 if (!strnicmp(name,*reserved,baselen))
407 static int vfat_find_form(struct inode *dir,char *name)
409 struct msdos_dir_entry *de;
410 struct buffer_head *bh = NULL;
414 res = fat_scan(dir, name, &bh, &de, &i_pos);
415 fat_brelse(dir->i_sb, bh);
422 * 1) Valid characters for the 8.3 format alias are any combination of
423 * letters, uppercase alphabets, digits, any of the
424 * following special characters:
425 * $ % ' ` - @ { } ~ ! # ( ) & _ ^
426 * In this case Longfilename is not stored in disk.
429 * File name and extension name is contain uppercase/lowercase
430 * only. And it is expressed by CASE_LOWER_BASE and CASE_LOWER_EXT.
432 * 2) File name is 8.3 format, but it contain the uppercase and
433 * lowercase char, muliti bytes char, etc. In this case numtail is not
434 * added, but Longfilename is stored.
436 * 3) When the one except for the above, or the following special
437 * character are contained:
439 * numtail is added, and Longfilename must be stored in disk .
441 struct shortname_info {
442 unsigned char lower:1,
446 #define INIT_SHORTNAME_INFO(x) do { \
452 static inline unsigned char
453 shortname_info_to_lcase(struct shortname_info *base,
454 struct shortname_info *ext)
456 unsigned char lcase = 0;
458 if (base->valid && ext->valid) {
459 if (!base->upper && base->lower && (ext->lower || ext->upper))
460 lcase |= CASE_LOWER_BASE;
461 if (!ext->upper && ext->lower && (base->lower || base->upper))
462 lcase |= CASE_LOWER_EXT;
468 static inline int to_shortname_char(struct nls_table *nls,
469 char *buf, int buf_size, wchar_t *src,
470 struct shortname_info *info)
474 if (IS_SKIPCHAR(*src)) {
478 if (IS_REPLACECHAR(*src)) {
484 len = nls->uni2char(*src, buf, buf_size);
489 } else if (len == 1) {
490 unsigned char prev = buf[0];
492 if (buf[0] >= 0x7F) {
497 buf[0] = vfat_toupper(nls, buf[0]);
498 if (isalpha(buf[0])) {
513 * Given a valid longname, create a unique shortname. Make sure the
514 * shortname does not exist
515 * Returns negative number on error, 0 for a normal
516 * return, and 1 for valid shortname
518 static int vfat_create_shortname(struct inode *dir, struct nls_table *nls,
519 wchar_t *uname, int ulen,
520 char *name_res, unsigned char *lcase)
522 wchar_t *ip, *ext_start, *end, *name_start;
523 unsigned char base[9], ext[4], buf[8], *p;
524 unsigned char charbuf[NLS_MAX_CHARSET_SIZE];
526 int sz = 0, extlen, baselen, i, numtail_baselen, numtail2_baselen;
528 struct shortname_info base_info, ext_info;
529 unsigned short opt_shortname = MSDOS_SB(dir->i_sb)->options.shortname;
532 INIT_SHORTNAME_INFO(&base_info);
533 INIT_SHORTNAME_INFO(&ext_info);
535 /* Now, we need to create a shortname from the long name */
536 ext_start = end = &uname[ulen];
537 while (--ext_start >= uname) {
538 if (*ext_start == 0x002E) { /* is `.' */
539 if (ext_start == end - 1) {
547 if (ext_start == uname - 1) {
550 } else if (ext_start) {
552 * Names which start with a dot could be just
553 * an extension eg. "...test". In this case Win95
554 * uses the extension as the name and sets no extension.
556 name_start = &uname[0];
557 while (name_start < ext_start) {
558 if (!IS_SKIPCHAR(*name_start))
562 if (name_start != ext_start) {
563 sz = ext_start - uname;
572 numtail2_baselen = 2;
573 for (baselen = i = 0, p = base, ip = uname; i < sz; i++, ip++) {
574 chl = to_shortname_char(nls, charbuf, sizeof(charbuf),
579 if (baselen < 2 && (baselen + chl) > 2)
580 numtail2_baselen = baselen;
581 if (baselen < 6 && (baselen + chl) > 6)
582 numtail_baselen = baselen;
583 for (chi = 0; chi < chl; chi++){
590 if ((chi < chl - 1) || (ip + 1) - uname < sz)
601 for (p = ext, ip = ext_start; extlen < 3 && ip < end; ip++) {
602 chl = to_shortname_char(nls, charbuf, sizeof(charbuf),
607 if ((extlen + chl) > 3) {
611 for (chi = 0; chi < chl; chi++) {
623 base[baselen] = '\0';
625 /* Yes, it can happen. ".\xe5" would do it. */
626 if (base[0] == DELETED_FLAG)
629 /* OK, at this point we know that base is not longer than 8 symbols,
630 * ext is not longer than 3, base is nonempty, both don't contain
631 * any bad symbols (lowercase transformed to uppercase).
634 memset(name_res, ' ', MSDOS_NAME);
635 memcpy(name_res, base, baselen);
636 memcpy(name_res + 8, ext, extlen);
638 if (is_shortname && base_info.valid && ext_info.valid) {
639 if (vfat_find_form(dir, name_res) == 0)
642 if (opt_shortname & VFAT_SFN_CREATE_WIN95) {
643 return (base_info.upper && ext_info.upper);
644 } else if (opt_shortname & VFAT_SFN_CREATE_WINNT) {
645 if ((base_info.upper || base_info.lower)
646 && (ext_info.upper || ext_info.lower)) {
647 *lcase = shortname_info_to_lcase(&base_info,
657 if (MSDOS_SB(dir->i_sb)->options.numtail == 0)
658 if (vfat_find_form(dir, name_res) < 0)
662 * Try to find a unique extension. This used to
663 * iterate through all possibilities sequentially,
664 * but that gave extremely bad performance. Windows
665 * only tries a few cases before using random
666 * values for part of the base.
670 baselen = numtail_baselen;
673 name_res[baselen] = '~';
674 for (i = 1; i < 10; i++) {
675 name_res[baselen+1] = i + '0';
676 if (vfat_find_form(dir, name_res) < 0)
680 i = jiffies & 0xffff;
681 sz = (jiffies >> 16) & 0x7;
683 baselen = numtail2_baselen;
686 name_res[baselen+4] = '~';
687 name_res[baselen+5] = '1' + sz;
689 sprintf(buf, "%04X", i);
690 memcpy(&name_res[baselen], buf, 4);
691 if (vfat_find_form(dir, name_res) < 0)
698 /* Translate a string, including coded sequences into Unicode */
700 xlate_to_uni(const char *name, int len, char *outname, int *longlen, int *outlen,
701 int escape, int utf8, struct nls_table *nls)
703 const unsigned char *ip;
711 *outlen = utf8_mbstowcs((__u16 *) outname, name, PAGE_SIZE);
712 if (name[len-1] == '.')
714 op = &outname[*outlen * sizeof(__u16)];
716 if (name[len-1] == '.')
719 for (i = 0, ip = name, op = outname, *outlen = 0;
720 i < len && *outlen <= 260; *outlen += 1)
722 if (escape && (*ip == ':')) {
726 for (k = 1; k < 5; k++) {
729 if (nc >= '0' && nc <= '9') {
733 if (nc >= 'a' && nc <= 'f') {
734 ec |= nc - ('a' - 10);
737 if (nc >= 'A' && nc <= 'F') {
738 ec |= nc - ('A' - 10);
748 if ((charlen = nls->char2uni(ip, len-i, (wchar_t *)op)) < 0)
756 for (i = 0, ip = name, op = outname, *outlen = 0;
757 i < len && *outlen <= 260; i++, *outlen += 1)
765 return -ENAMETOOLONG;
773 fill = 13 - (*outlen % 13);
774 for (i = 0; i < fill; i++) {
786 vfat_fill_slots(struct inode *dir, struct msdos_dir_slot *ds, const char *name,
787 int len, int *slots, int is_dir, int uni_xlate)
789 struct nls_table *nls_io, *nls_disk;
791 struct msdos_dir_slot *ps;
792 struct msdos_dir_entry *de;
794 unsigned char cksum, lcase;
795 char *uniname, msdos_name[MSDOS_NAME];
796 int res, utf8, slot, ulen, unilen, i;
800 utf8 = MSDOS_SB(dir->i_sb)->options.utf8;
801 nls_io = MSDOS_SB(dir->i_sb)->nls_io;
802 nls_disk = MSDOS_SB(dir->i_sb)->nls_disk;
804 if (name[len-1] == '.')
806 if(!(page = __get_free_page(GFP_KERNEL)))
809 uniname = (char *) page;
810 res = xlate_to_uni(name, len, uniname, &ulen, &unilen, uni_xlate,
815 uname = (wchar_t *) page;
816 res = vfat_is_used_badchars(uname, ulen);
820 res = vfat_create_shortname(dir, nls_disk, uname, ulen,
825 de = (struct msdos_dir_entry *)ds;
830 /* build the entry of long file name */
831 *slots = unilen / 13;
832 for (cksum = i = 0; i < 11; i++) {
833 cksum = (((cksum&1)<<7)|((cksum&0xfe)>>1)) + msdos_name[i];
835 PRINTK3(("vfat_fill_slots 3: slots=%d\n",*slots));
837 for (ps = ds, slot = *slots; slot > 0; slot--, ps++) {
841 ps->alias_checksum = cksum;
843 offset = (slot - 1) * 13;
844 fatwchar_to16(ps->name0_4, uname + offset, 5);
845 fatwchar_to16(ps->name5_10, uname + offset + 5, 6);
846 fatwchar_to16(ps->name11_12, uname + offset + 11, 2);
849 de = (struct msdos_dir_entry *) ps;
852 PRINTK3(("vfat_fill_slots 9\n"));
853 /* build the entry of 8.3 alias name */
855 strncpy(de->name, msdos_name, MSDOS_NAME);
856 de->attr = is_dir ? ATTR_DIR : ATTR_ARCH;
858 de->adate = de->cdate = de->date = 0;
859 de->ctime_ms = de->ctime = de->time = 0;
869 /* We can't get "." or ".." here - VFS takes care of those cases */
871 static int vfat_build_slots(struct inode *dir, const char *name, int len,
872 struct msdos_dir_slot *ds, int *slots, int is_dir)
876 xlate = MSDOS_SB(dir->i_sb)->options.unicode_xlate;
877 res = vfat_valid_longname(name, len, xlate);
881 return vfat_fill_slots(dir, ds, name, len, slots, is_dir, xlate);
884 static int vfat_add_entry(struct inode *dir,struct qstr* qname,
885 int is_dir, struct vfat_slot_info *sinfo_out,
886 struct buffer_head **bh, struct msdos_dir_entry **de)
888 struct super_block *sb = dir->i_sb;
889 struct msdos_dir_slot *dir_slots;
893 struct msdos_dir_entry *dummy_de;
894 struct buffer_head *dummy_bh;
898 dir_slots = (struct msdos_dir_slot *)
899 kmalloc(sizeof(struct msdos_dir_slot) * MSDOS_SLOTS, GFP_KERNEL);
900 if (dir_slots == NULL)
904 while (len && qname->name[len-1] == '.')
906 res = fat_search_long(dir, qname->name, len,
907 (MSDOS_SB(sb)->options.name_check != 's')
908 || !MSDOS_SB(sb)->options.posixfs,
910 if (res > 0) /* found */
915 res = vfat_build_slots(dir, qname->name, len,
916 dir_slots, &slots, is_dir);
920 /* build the empty directory entry of number of slots */
921 offset = fat_add_entries(dir, slots, &dummy_bh, &dummy_de, &dummy_i_pos);
926 fat_brelse(sb, dummy_bh);
928 /* Now create the new entry */
930 for (slot = 0; slot < slots; slot++) {
931 if (fat_get_entry(dir, &offset, bh, de, &sinfo_out->i_pos) < 0) {
935 memcpy(*de, dir_slots + slot, sizeof(struct msdos_dir_slot));
936 fat_mark_buffer_dirty(sb, *bh);
940 /* update timestamp */
941 dir->i_ctime = dir->i_mtime = dir->i_atime = CURRENT_TIME;
942 mark_inode_dirty(dir);
944 fat_date_unix2dos(dir->i_mtime, &(*de)->time, &(*de)->date);
945 (*de)->ctime = (*de)->time;
946 (*de)->adate = (*de)->cdate = (*de)->date;
948 fat_mark_buffer_dirty(sb, *bh);
950 /* slots can't be less than 1 */
951 sinfo_out->long_slots = slots - 1;
952 sinfo_out->longname_offset =
953 offset - sizeof(struct msdos_dir_slot) * slots;
960 static int vfat_find(struct inode *dir,struct qstr* qname,
961 struct vfat_slot_info *sinfo, struct buffer_head **last_bh,
962 struct msdos_dir_entry **last_de)
964 struct super_block *sb = dir->i_sb;
969 while (len && qname->name[len-1] == '.')
971 res = fat_search_long(dir, qname->name, len,
972 (MSDOS_SB(sb)->options.name_check != 's'),
973 &offset,&sinfo->longname_offset);
975 sinfo->long_slots = res-1;
976 if (fat_get_entry(dir,&offset,last_bh,last_de,&sinfo->i_pos)>=0)
980 return res ? res : -ENOENT;
983 struct dentry *vfat_lookup(struct inode *dir,struct dentry *dentry)
986 struct vfat_slot_info sinfo;
988 struct dentry *alias;
989 struct buffer_head *bh = NULL;
990 struct msdos_dir_entry *de;
993 PRINTK2(("vfat_lookup: name=%s, len=%d\n",
994 dentry->d_name.name, dentry->d_name.len));
996 table = (MSDOS_SB(dir->i_sb)->options.name_check == 's') ? 2 : 0;
997 dentry->d_op = &vfat_dentry_ops[table];
1000 res = vfat_find(dir,&dentry->d_name,&sinfo,&bh,&de);
1005 inode = fat_build_inode(dir->i_sb, de, sinfo.i_pos, &res);
1006 fat_brelse(dir->i_sb, bh);
1008 return ERR_PTR(res);
1009 alias = d_find_alias(inode);
1011 if (d_invalidate(alias)==0)
1020 dentry->d_op = &vfat_dentry_ops[table];
1021 dentry->d_time = dentry->d_parent->d_inode->i_version;
1022 d_add(dentry,inode);
1026 int vfat_create(struct inode *dir,struct dentry* dentry,int mode)
1028 struct super_block *sb = dir->i_sb;
1029 struct inode *inode = NULL;
1030 struct buffer_head *bh = NULL;
1031 struct msdos_dir_entry *de;
1032 struct vfat_slot_info sinfo;
1035 res = vfat_add_entry(dir, &dentry->d_name, 0, &sinfo, &bh, &de);
1038 inode = fat_build_inode(sb, de, sinfo.i_pos, &res);
1042 inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
1043 mark_inode_dirty(inode);
1044 inode->i_version = ++event;
1045 dir->i_version = event;
1046 dentry->d_time = dentry->d_parent->d_inode->i_version;
1047 d_instantiate(dentry,inode);
1051 static void vfat_remove_entry(struct inode *dir,struct vfat_slot_info *sinfo,
1052 struct buffer_head *bh, struct msdos_dir_entry *de)
1054 struct super_block *sb = dir->i_sb;
1055 loff_t offset, i_pos;
1058 /* remove the shortname */
1059 dir->i_mtime = CURRENT_TIME;
1060 dir->i_atime = CURRENT_TIME;
1061 dir->i_version = ++event;
1062 mark_inode_dirty(dir);
1063 de->name[0] = DELETED_FLAG;
1064 fat_mark_buffer_dirty(sb, bh);
1065 /* remove the longname */
1066 offset = sinfo->longname_offset; de = NULL;
1067 for (i = sinfo->long_slots; i > 0; --i) {
1068 if (fat_get_entry(dir, &offset, &bh, &de, &i_pos) < 0)
1070 de->name[0] = DELETED_FLAG;
1072 fat_mark_buffer_dirty(sb, bh);
1074 if (bh) fat_brelse(sb, bh);
1077 int vfat_rmdir(struct inode *dir,struct dentry* dentry)
1080 struct vfat_slot_info sinfo;
1081 struct buffer_head *bh = NULL;
1082 struct msdos_dir_entry *de;
1084 res = fat_dir_empty(dentry->d_inode);
1088 res = vfat_find(dir,&dentry->d_name,&sinfo, &bh, &de);
1091 dentry->d_inode->i_nlink = 0;
1092 dentry->d_inode->i_mtime = CURRENT_TIME;
1093 dentry->d_inode->i_atime = CURRENT_TIME;
1094 fat_detach(dentry->d_inode);
1095 mark_inode_dirty(dentry->d_inode);
1097 vfat_remove_entry(dir,&sinfo,bh,de);
1102 int vfat_unlink(struct inode *dir, struct dentry* dentry)
1105 struct vfat_slot_info sinfo;
1106 struct buffer_head *bh = NULL;
1107 struct msdos_dir_entry *de;
1109 PRINTK1(("vfat_unlink: %s\n", dentry->d_name.name));
1110 res = vfat_find(dir,&dentry->d_name,&sinfo,&bh,&de);
1113 dentry->d_inode->i_nlink = 0;
1114 dentry->d_inode->i_mtime = CURRENT_TIME;
1115 dentry->d_inode->i_atime = CURRENT_TIME;
1116 fat_detach(dentry->d_inode);
1117 mark_inode_dirty(dentry->d_inode);
1119 vfat_remove_entry(dir,&sinfo,bh,de);
1125 int vfat_mkdir(struct inode *dir,struct dentry* dentry,int mode)
1127 struct super_block *sb = dir->i_sb;
1128 struct inode *inode = NULL;
1129 struct vfat_slot_info sinfo;
1130 struct buffer_head *bh = NULL;
1131 struct msdos_dir_entry *de;
1134 res = vfat_add_entry(dir, &dentry->d_name, 1, &sinfo, &bh, &de);
1137 inode = fat_build_inode(sb, de, sinfo.i_pos, &res);
1140 inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
1141 mark_inode_dirty(inode);
1142 inode->i_version = ++event;
1143 dir->i_version = event;
1145 inode->i_nlink = 2; /* no need to mark them dirty */
1146 res = fat_new_dir(inode, dir, 1);
1149 dentry->d_time = dentry->d_parent->d_inode->i_version;
1150 d_instantiate(dentry,inode);
1157 inode->i_mtime = CURRENT_TIME;
1158 inode->i_atime = CURRENT_TIME;
1160 mark_inode_dirty(inode);
1162 vfat_remove_entry(dir,&sinfo,bh,de);
1168 int vfat_rename(struct inode *old_dir,struct dentry *old_dentry,
1169 struct inode *new_dir,struct dentry *new_dentry)
1171 struct super_block *sb = old_dir->i_sb;
1172 struct buffer_head *old_bh,*new_bh,*dotdot_bh;
1173 struct msdos_dir_entry *old_de,*new_de,*dotdot_de;
1174 loff_t dotdot_i_pos;
1175 struct inode *old_inode, *new_inode;
1177 struct vfat_slot_info old_sinfo,sinfo;
1179 old_bh = new_bh = dotdot_bh = NULL;
1180 old_inode = old_dentry->d_inode;
1181 new_inode = new_dentry->d_inode;
1182 res = vfat_find(old_dir,&old_dentry->d_name,&old_sinfo,&old_bh,&old_de);
1183 PRINTK3(("vfat_rename 2\n"));
1184 if (res < 0) goto rename_done;
1186 is_dir = S_ISDIR(old_inode->i_mode);
1188 if (is_dir && (res = fat_scan(old_inode,MSDOS_DOTDOT,&dotdot_bh,
1189 &dotdot_de,&dotdot_i_pos)) < 0)
1192 if (new_dentry->d_inode) {
1193 res = vfat_find(new_dir,&new_dentry->d_name,&sinfo,&new_bh,
1195 if (res < 0 || MSDOS_I(new_inode)->i_pos != sinfo.i_pos) {
1196 /* WTF??? Cry and fail. */
1197 printk(KERN_WARNING "vfat_rename: fs corrupted\n");
1202 res = fat_dir_empty(new_inode);
1206 fat_detach(new_inode);
1208 res = vfat_add_entry(new_dir,&new_dentry->d_name,is_dir,&sinfo,
1210 if (res < 0) goto rename_done;
1213 new_dir->i_version = ++event;
1215 /* releases old_bh */
1216 vfat_remove_entry(old_dir,&old_sinfo,old_bh,old_de);
1218 fat_detach(old_inode);
1219 fat_attach(old_inode, sinfo.i_pos);
1220 mark_inode_dirty(old_inode);
1222 old_dir->i_version = ++event;
1223 old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
1224 mark_inode_dirty(old_dir);
1226 new_inode->i_nlink--;
1227 new_inode->i_ctime=CURRENT_TIME;
1231 int start = MSDOS_I(new_dir)->i_logstart;
1232 dotdot_de->start = CT_LE_W(start);
1233 dotdot_de->starthi = CT_LE_W(start>>16);
1234 fat_mark_buffer_dirty(sb, dotdot_bh);
1237 new_inode->i_nlink--;
1240 mark_inode_dirty(new_dir);
1245 fat_brelse(sb, dotdot_bh);
1246 fat_brelse(sb, old_bh);
1247 fat_brelse(sb, new_bh);
1253 /* Public inode operations for the VFAT fs */
1254 struct inode_operations vfat_dir_inode_operations = {
1255 create: vfat_create,
1256 lookup: vfat_lookup,
1257 unlink: vfat_unlink,
1260 rename: vfat_rename,
1261 setattr: fat_notify_change,
1264 struct super_block *vfat_read_super(struct super_block *sb,void *data,
1267 struct super_block *res;
1269 MSDOS_SB(sb)->options.isvfat = 1;
1271 res = fat_read_super(sb, data, silent, &vfat_dir_inode_operations);
1275 if (parse_options((char *) data, &(MSDOS_SB(sb)->options))) {
1276 MSDOS_SB(sb)->options.dotsOK = 0;
1277 if (MSDOS_SB(sb)->options.posixfs) {
1278 MSDOS_SB(sb)->options.name_check = 's';
1280 if (MSDOS_SB(sb)->options.name_check != 's') {
1281 sb->s_root->d_op = &vfat_dentry_ops[0];
1283 sb->s_root->d_op = &vfat_dentry_ops[2];