1990e194eSOGAWA Hirofumi /* 2990e194eSOGAWA Hirofumi * linux/fs/vfat/namei.c 3990e194eSOGAWA Hirofumi * 4990e194eSOGAWA Hirofumi * Written 1992,1993 by Werner Almesberger 5990e194eSOGAWA Hirofumi * 6990e194eSOGAWA Hirofumi * Windows95/Windows NT compatible extended MSDOS filesystem 7990e194eSOGAWA Hirofumi * by Gordon Chaffee Copyright (C) 1995. Send bug reports for the 8990e194eSOGAWA Hirofumi * VFAT filesystem to <chaffee@cs.berkeley.edu>. Specify 9990e194eSOGAWA Hirofumi * what file operation caused you trouble and if you can duplicate 10990e194eSOGAWA Hirofumi * the problem, send a script that demonstrates it. 11990e194eSOGAWA Hirofumi * 12990e194eSOGAWA Hirofumi * Short name translation 1999, 2001 by Wolfram Pienkoss <wp@bszh.de> 13990e194eSOGAWA Hirofumi * 14990e194eSOGAWA Hirofumi * Support Multibyte characters and cleanup by 15990e194eSOGAWA Hirofumi * OGAWA Hirofumi <hirofumi@mail.parknet.co.jp> 16990e194eSOGAWA Hirofumi */ 17990e194eSOGAWA Hirofumi 18990e194eSOGAWA Hirofumi #include <linux/module.h> 19990e194eSOGAWA Hirofumi #include <linux/ctype.h> 20990e194eSOGAWA Hirofumi #include <linux/slab.h> 21990e194eSOGAWA Hirofumi #include <linux/namei.h> 229e975daeSOGAWA Hirofumi #include "fat.h" 23990e194eSOGAWA Hirofumi 241b524672SOGAWA Hirofumi /* 251b524672SOGAWA Hirofumi * If new entry was created in the parent, it could create the 8.3 261b524672SOGAWA Hirofumi * alias (the shortname of logname). So, the parent may have the 271b524672SOGAWA Hirofumi * negative-dentry which matches the created 8.3 alias. 281b524672SOGAWA Hirofumi * 291b524672SOGAWA Hirofumi * If it happened, the negative dentry isn't actually negative 301b524672SOGAWA Hirofumi * anymore. So, drop it. 311b524672SOGAWA Hirofumi */ 321b524672SOGAWA Hirofumi static int vfat_revalidate_shortname(struct dentry *dentry) 33990e194eSOGAWA Hirofumi { 34990e194eSOGAWA Hirofumi int ret = 1; 35990e194eSOGAWA Hirofumi spin_lock(&dentry->d_lock); 362b0143b5SDavid Howells if (dentry->d_time != d_inode(dentry->d_parent)->i_version) 37990e194eSOGAWA Hirofumi ret = 0; 38990e194eSOGAWA Hirofumi spin_unlock(&dentry->d_lock); 39990e194eSOGAWA Hirofumi return ret; 40990e194eSOGAWA Hirofumi } 41990e194eSOGAWA Hirofumi 420b728e19SAl Viro static int vfat_revalidate(struct dentry *dentry, unsigned int flags) 431b524672SOGAWA Hirofumi { 440b728e19SAl Viro if (flags & LOOKUP_RCU) 4534286d66SNick Piggin return -ECHILD; 4634286d66SNick Piggin 471b524672SOGAWA Hirofumi /* This is not negative dentry. Always valid. */ 482b0143b5SDavid Howells if (d_really_is_positive(dentry)) 491b524672SOGAWA Hirofumi return 1; 501b524672SOGAWA Hirofumi return vfat_revalidate_shortname(dentry); 511b524672SOGAWA Hirofumi } 521b524672SOGAWA Hirofumi 530b728e19SAl Viro static int vfat_revalidate_ci(struct dentry *dentry, unsigned int flags) 541b524672SOGAWA Hirofumi { 550b728e19SAl Viro if (flags & LOOKUP_RCU) 5634286d66SNick Piggin return -ECHILD; 5734286d66SNick Piggin 581b524672SOGAWA Hirofumi /* 591b524672SOGAWA Hirofumi * This is not negative dentry. Always valid. 601b524672SOGAWA Hirofumi * 611b524672SOGAWA Hirofumi * Note, rename() to existing directory entry will have ->d_inode, 621b524672SOGAWA Hirofumi * and will use existing name which isn't specified name by user. 631b524672SOGAWA Hirofumi * 641b524672SOGAWA Hirofumi * We may be able to drop this positive dentry here. But dropping 651b524672SOGAWA Hirofumi * positive dentry isn't good idea. So it's unsupported like 661b524672SOGAWA Hirofumi * rename("filename", "FILENAME") for now. 671b524672SOGAWA Hirofumi */ 682b0143b5SDavid Howells if (d_really_is_positive(dentry)) 691b524672SOGAWA Hirofumi return 1; 701b524672SOGAWA Hirofumi 711b524672SOGAWA Hirofumi /* 721b524672SOGAWA Hirofumi * This may be nfsd (or something), anyway, we can't see the 731b524672SOGAWA Hirofumi * intent of this. So, since this can be for creation, drop it. 741b524672SOGAWA Hirofumi */ 750b728e19SAl Viro if (!flags) 761b524672SOGAWA Hirofumi return 0; 771b524672SOGAWA Hirofumi 781b524672SOGAWA Hirofumi /* 791b524672SOGAWA Hirofumi * Drop the negative dentry, in order to make sure to use the 801b524672SOGAWA Hirofumi * case sensitive name which is specified by user if this is 811b524672SOGAWA Hirofumi * for creation. 821b524672SOGAWA Hirofumi */ 830b728e19SAl Viro if (flags & (LOOKUP_CREATE | LOOKUP_RENAME_TARGET)) 841b524672SOGAWA Hirofumi return 0; 851b524672SOGAWA Hirofumi 861b524672SOGAWA Hirofumi return vfat_revalidate_shortname(dentry); 871b524672SOGAWA Hirofumi } 881b524672SOGAWA Hirofumi 89990e194eSOGAWA Hirofumi /* returns the length of a struct qstr, ignoring trailing dots */ 90621e155aSNick Piggin static unsigned int __vfat_striptail_len(unsigned int len, const char *name) 91990e194eSOGAWA Hirofumi { 92621e155aSNick Piggin while (len && name[len - 1] == '.') 93990e194eSOGAWA Hirofumi len--; 94990e194eSOGAWA Hirofumi return len; 95990e194eSOGAWA Hirofumi } 96990e194eSOGAWA Hirofumi 97621e155aSNick Piggin static unsigned int vfat_striptail_len(const struct qstr *qstr) 98621e155aSNick Piggin { 99621e155aSNick Piggin return __vfat_striptail_len(qstr->len, qstr->name); 100621e155aSNick Piggin } 101621e155aSNick Piggin 102990e194eSOGAWA Hirofumi /* 103990e194eSOGAWA Hirofumi * Compute the hash for the vfat name corresponding to the dentry. 104990e194eSOGAWA Hirofumi * Note: if the name is invalid, we leave the hash code unchanged so 105990e194eSOGAWA Hirofumi * that the existing dentry can be used. The vfat fs routines will 106990e194eSOGAWA Hirofumi * return ENOENT or EINVAL as appropriate. 107990e194eSOGAWA Hirofumi */ 108da53be12SLinus Torvalds static int vfat_hash(const struct dentry *dentry, struct qstr *qstr) 109990e194eSOGAWA Hirofumi { 1108387ff25SLinus Torvalds qstr->hash = full_name_hash(dentry, qstr->name, vfat_striptail_len(qstr)); 111990e194eSOGAWA Hirofumi return 0; 112990e194eSOGAWA Hirofumi } 113990e194eSOGAWA Hirofumi 114990e194eSOGAWA Hirofumi /* 115990e194eSOGAWA Hirofumi * Compute the hash for the vfat name corresponding to the dentry. 116990e194eSOGAWA Hirofumi * Note: if the name is invalid, we leave the hash code unchanged so 117990e194eSOGAWA Hirofumi * that the existing dentry can be used. The vfat fs routines will 118990e194eSOGAWA Hirofumi * return ENOENT or EINVAL as appropriate. 119990e194eSOGAWA Hirofumi */ 120da53be12SLinus Torvalds static int vfat_hashi(const struct dentry *dentry, struct qstr *qstr) 121990e194eSOGAWA Hirofumi { 122b1e6a015SNick Piggin struct nls_table *t = MSDOS_SB(dentry->d_sb)->nls_io; 123990e194eSOGAWA Hirofumi const unsigned char *name; 124990e194eSOGAWA Hirofumi unsigned int len; 125990e194eSOGAWA Hirofumi unsigned long hash; 126990e194eSOGAWA Hirofumi 127990e194eSOGAWA Hirofumi name = qstr->name; 128990e194eSOGAWA Hirofumi len = vfat_striptail_len(qstr); 129990e194eSOGAWA Hirofumi 1308387ff25SLinus Torvalds hash = init_name_hash(dentry); 131990e194eSOGAWA Hirofumi while (len--) 132990e194eSOGAWA Hirofumi hash = partial_name_hash(nls_tolower(t, *name++), hash); 133990e194eSOGAWA Hirofumi qstr->hash = end_name_hash(hash); 134990e194eSOGAWA Hirofumi 135990e194eSOGAWA Hirofumi return 0; 136990e194eSOGAWA Hirofumi } 137990e194eSOGAWA Hirofumi 138990e194eSOGAWA Hirofumi /* 139990e194eSOGAWA Hirofumi * Case insensitive compare of two vfat names. 140990e194eSOGAWA Hirofumi */ 141*6fa67e70SAl Viro static int vfat_cmpi(const struct dentry *dentry, 142621e155aSNick Piggin unsigned int len, const char *str, const struct qstr *name) 143990e194eSOGAWA Hirofumi { 144d3fe1985SAl Viro struct nls_table *t = MSDOS_SB(dentry->d_sb)->nls_io; 145990e194eSOGAWA Hirofumi unsigned int alen, blen; 146990e194eSOGAWA Hirofumi 147990e194eSOGAWA Hirofumi /* A filename cannot end in '.' or we treat it like it has none */ 148621e155aSNick Piggin alen = vfat_striptail_len(name); 149621e155aSNick Piggin blen = __vfat_striptail_len(len, str); 150990e194eSOGAWA Hirofumi if (alen == blen) { 151621e155aSNick Piggin if (nls_strnicmp(t, name->name, str, alen) == 0) 152990e194eSOGAWA Hirofumi return 0; 153990e194eSOGAWA Hirofumi } 154990e194eSOGAWA Hirofumi return 1; 155990e194eSOGAWA Hirofumi } 156990e194eSOGAWA Hirofumi 157990e194eSOGAWA Hirofumi /* 158990e194eSOGAWA Hirofumi * Case sensitive compare of two vfat names. 159990e194eSOGAWA Hirofumi */ 160*6fa67e70SAl Viro static int vfat_cmp(const struct dentry *dentry, 161621e155aSNick Piggin unsigned int len, const char *str, const struct qstr *name) 162990e194eSOGAWA Hirofumi { 163990e194eSOGAWA Hirofumi unsigned int alen, blen; 164990e194eSOGAWA Hirofumi 165990e194eSOGAWA Hirofumi /* A filename cannot end in '.' or we treat it like it has none */ 166621e155aSNick Piggin alen = vfat_striptail_len(name); 167621e155aSNick Piggin blen = __vfat_striptail_len(len, str); 168990e194eSOGAWA Hirofumi if (alen == blen) { 169621e155aSNick Piggin if (strncmp(name->name, str, alen) == 0) 170990e194eSOGAWA Hirofumi return 0; 171990e194eSOGAWA Hirofumi } 172990e194eSOGAWA Hirofumi return 1; 173990e194eSOGAWA Hirofumi } 174990e194eSOGAWA Hirofumi 175ce6cdc47SAl Viro static const struct dentry_operations vfat_ci_dentry_ops = { 1761b524672SOGAWA Hirofumi .d_revalidate = vfat_revalidate_ci, 177990e194eSOGAWA Hirofumi .d_hash = vfat_hashi, 178990e194eSOGAWA Hirofumi .d_compare = vfat_cmpi, 1791b524672SOGAWA Hirofumi }; 1801b524672SOGAWA Hirofumi 181ce6cdc47SAl Viro static const struct dentry_operations vfat_dentry_ops = { 182990e194eSOGAWA Hirofumi .d_revalidate = vfat_revalidate, 183990e194eSOGAWA Hirofumi .d_hash = vfat_hash, 184990e194eSOGAWA Hirofumi .d_compare = vfat_cmp, 185990e194eSOGAWA Hirofumi }; 186990e194eSOGAWA Hirofumi 187990e194eSOGAWA Hirofumi /* Characters that are undesirable in an MS-DOS file name */ 188990e194eSOGAWA Hirofumi 189990e194eSOGAWA Hirofumi static inline wchar_t vfat_bad_char(wchar_t w) 190990e194eSOGAWA Hirofumi { 191990e194eSOGAWA Hirofumi return (w < 0x0020) 192990e194eSOGAWA Hirofumi || (w == '*') || (w == '?') || (w == '<') || (w == '>') 193990e194eSOGAWA Hirofumi || (w == '|') || (w == '"') || (w == ':') || (w == '/') 194990e194eSOGAWA Hirofumi || (w == '\\'); 195990e194eSOGAWA Hirofumi } 196990e194eSOGAWA Hirofumi 197990e194eSOGAWA Hirofumi static inline wchar_t vfat_replace_char(wchar_t w) 198990e194eSOGAWA Hirofumi { 199990e194eSOGAWA Hirofumi return (w == '[') || (w == ']') || (w == ';') || (w == ',') 200990e194eSOGAWA Hirofumi || (w == '+') || (w == '='); 201990e194eSOGAWA Hirofumi } 202990e194eSOGAWA Hirofumi 203990e194eSOGAWA Hirofumi static wchar_t vfat_skip_char(wchar_t w) 204990e194eSOGAWA Hirofumi { 205990e194eSOGAWA Hirofumi return (w == '.') || (w == ' '); 206990e194eSOGAWA Hirofumi } 207990e194eSOGAWA Hirofumi 208990e194eSOGAWA Hirofumi static inline int vfat_is_used_badchars(const wchar_t *s, int len) 209990e194eSOGAWA Hirofumi { 210990e194eSOGAWA Hirofumi int i; 211990e194eSOGAWA Hirofumi 212990e194eSOGAWA Hirofumi for (i = 0; i < len; i++) 213990e194eSOGAWA Hirofumi if (vfat_bad_char(s[i])) 214990e194eSOGAWA Hirofumi return -EINVAL; 215990e194eSOGAWA Hirofumi 216990e194eSOGAWA Hirofumi if (s[i - 1] == ' ') /* last character cannot be space */ 217990e194eSOGAWA Hirofumi return -EINVAL; 218990e194eSOGAWA Hirofumi 219990e194eSOGAWA Hirofumi return 0; 220990e194eSOGAWA Hirofumi } 221990e194eSOGAWA Hirofumi 222990e194eSOGAWA Hirofumi static int vfat_find_form(struct inode *dir, unsigned char *name) 223990e194eSOGAWA Hirofumi { 224990e194eSOGAWA Hirofumi struct fat_slot_info sinfo; 225990e194eSOGAWA Hirofumi int err = fat_scan(dir, name, &sinfo); 226990e194eSOGAWA Hirofumi if (err) 227990e194eSOGAWA Hirofumi return -ENOENT; 228990e194eSOGAWA Hirofumi brelse(sinfo.bh); 229990e194eSOGAWA Hirofumi return 0; 230990e194eSOGAWA Hirofumi } 231990e194eSOGAWA Hirofumi 232990e194eSOGAWA Hirofumi /* 233990e194eSOGAWA Hirofumi * 1) Valid characters for the 8.3 format alias are any combination of 234990e194eSOGAWA Hirofumi * letters, uppercase alphabets, digits, any of the 235990e194eSOGAWA Hirofumi * following special characters: 236990e194eSOGAWA Hirofumi * $ % ' ` - @ { } ~ ! # ( ) & _ ^ 237990e194eSOGAWA Hirofumi * In this case Longfilename is not stored in disk. 238990e194eSOGAWA Hirofumi * 239990e194eSOGAWA Hirofumi * WinNT's Extension: 240990e194eSOGAWA Hirofumi * File name and extension name is contain uppercase/lowercase 241990e194eSOGAWA Hirofumi * only. And it is expressed by CASE_LOWER_BASE and CASE_LOWER_EXT. 242990e194eSOGAWA Hirofumi * 243990e194eSOGAWA Hirofumi * 2) File name is 8.3 format, but it contain the uppercase and 244990e194eSOGAWA Hirofumi * lowercase char, muliti bytes char, etc. In this case numtail is not 245990e194eSOGAWA Hirofumi * added, but Longfilename is stored. 246990e194eSOGAWA Hirofumi * 247990e194eSOGAWA Hirofumi * 3) When the one except for the above, or the following special 248990e194eSOGAWA Hirofumi * character are contained: 249990e194eSOGAWA Hirofumi * . [ ] ; , + = 250990e194eSOGAWA Hirofumi * numtail is added, and Longfilename must be stored in disk . 251990e194eSOGAWA Hirofumi */ 252990e194eSOGAWA Hirofumi struct shortname_info { 253990e194eSOGAWA Hirofumi unsigned char lower:1, 254990e194eSOGAWA Hirofumi upper:1, 255990e194eSOGAWA Hirofumi valid:1; 256990e194eSOGAWA Hirofumi }; 257990e194eSOGAWA Hirofumi #define INIT_SHORTNAME_INFO(x) do { \ 258990e194eSOGAWA Hirofumi (x)->lower = 1; \ 259990e194eSOGAWA Hirofumi (x)->upper = 1; \ 260990e194eSOGAWA Hirofumi (x)->valid = 1; \ 261990e194eSOGAWA Hirofumi } while (0) 262990e194eSOGAWA Hirofumi 263990e194eSOGAWA Hirofumi static inline int to_shortname_char(struct nls_table *nls, 264990e194eSOGAWA Hirofumi unsigned char *buf, int buf_size, 265990e194eSOGAWA Hirofumi wchar_t *src, struct shortname_info *info) 266990e194eSOGAWA Hirofumi { 267990e194eSOGAWA Hirofumi int len; 268990e194eSOGAWA Hirofumi 269990e194eSOGAWA Hirofumi if (vfat_skip_char(*src)) { 270990e194eSOGAWA Hirofumi info->valid = 0; 271990e194eSOGAWA Hirofumi return 0; 272990e194eSOGAWA Hirofumi } 273990e194eSOGAWA Hirofumi if (vfat_replace_char(*src)) { 274990e194eSOGAWA Hirofumi info->valid = 0; 275990e194eSOGAWA Hirofumi buf[0] = '_'; 276990e194eSOGAWA Hirofumi return 1; 277990e194eSOGAWA Hirofumi } 278990e194eSOGAWA Hirofumi 279990e194eSOGAWA Hirofumi len = nls->uni2char(*src, buf, buf_size); 280990e194eSOGAWA Hirofumi if (len <= 0) { 281990e194eSOGAWA Hirofumi info->valid = 0; 282990e194eSOGAWA Hirofumi buf[0] = '_'; 283990e194eSOGAWA Hirofumi len = 1; 284990e194eSOGAWA Hirofumi } else if (len == 1) { 285990e194eSOGAWA Hirofumi unsigned char prev = buf[0]; 286990e194eSOGAWA Hirofumi 287990e194eSOGAWA Hirofumi if (buf[0] >= 0x7F) { 288990e194eSOGAWA Hirofumi info->lower = 0; 289990e194eSOGAWA Hirofumi info->upper = 0; 290990e194eSOGAWA Hirofumi } 291990e194eSOGAWA Hirofumi 292990e194eSOGAWA Hirofumi buf[0] = nls_toupper(nls, buf[0]); 293990e194eSOGAWA Hirofumi if (isalpha(buf[0])) { 294990e194eSOGAWA Hirofumi if (buf[0] == prev) 295990e194eSOGAWA Hirofumi info->lower = 0; 296990e194eSOGAWA Hirofumi else 297990e194eSOGAWA Hirofumi info->upper = 0; 298990e194eSOGAWA Hirofumi } 299990e194eSOGAWA Hirofumi } else { 300990e194eSOGAWA Hirofumi info->lower = 0; 301990e194eSOGAWA Hirofumi info->upper = 0; 302990e194eSOGAWA Hirofumi } 303990e194eSOGAWA Hirofumi 304990e194eSOGAWA Hirofumi return len; 305990e194eSOGAWA Hirofumi } 306990e194eSOGAWA Hirofumi 307990e194eSOGAWA Hirofumi /* 308990e194eSOGAWA Hirofumi * Given a valid longname, create a unique shortname. Make sure the 309990e194eSOGAWA Hirofumi * shortname does not exist 310990e194eSOGAWA Hirofumi * Returns negative number on error, 0 for a normal 311990e194eSOGAWA Hirofumi * return, and 1 for valid shortname 312990e194eSOGAWA Hirofumi */ 313990e194eSOGAWA Hirofumi static int vfat_create_shortname(struct inode *dir, struct nls_table *nls, 314990e194eSOGAWA Hirofumi wchar_t *uname, int ulen, 315990e194eSOGAWA Hirofumi unsigned char *name_res, unsigned char *lcase) 316990e194eSOGAWA Hirofumi { 317990e194eSOGAWA Hirofumi struct fat_mount_options *opts = &MSDOS_SB(dir->i_sb)->options; 318990e194eSOGAWA Hirofumi wchar_t *ip, *ext_start, *end, *name_start; 31930d1872dSNikolaus Schulz unsigned char base[9], ext[4], buf[5], *p; 320990e194eSOGAWA Hirofumi unsigned char charbuf[NLS_MAX_CHARSET_SIZE]; 321990e194eSOGAWA Hirofumi int chl, chi; 322990e194eSOGAWA Hirofumi int sz = 0, extlen, baselen, i, numtail_baselen, numtail2_baselen; 323990e194eSOGAWA Hirofumi int is_shortname; 324990e194eSOGAWA Hirofumi struct shortname_info base_info, ext_info; 325990e194eSOGAWA Hirofumi 326990e194eSOGAWA Hirofumi is_shortname = 1; 327990e194eSOGAWA Hirofumi INIT_SHORTNAME_INFO(&base_info); 328990e194eSOGAWA Hirofumi INIT_SHORTNAME_INFO(&ext_info); 329990e194eSOGAWA Hirofumi 330990e194eSOGAWA Hirofumi /* Now, we need to create a shortname from the long name */ 331990e194eSOGAWA Hirofumi ext_start = end = &uname[ulen]; 332990e194eSOGAWA Hirofumi while (--ext_start >= uname) { 333990e194eSOGAWA Hirofumi if (*ext_start == 0x002E) { /* is `.' */ 334990e194eSOGAWA Hirofumi if (ext_start == end - 1) { 335990e194eSOGAWA Hirofumi sz = ulen; 336990e194eSOGAWA Hirofumi ext_start = NULL; 337990e194eSOGAWA Hirofumi } 338990e194eSOGAWA Hirofumi break; 339990e194eSOGAWA Hirofumi } 340990e194eSOGAWA Hirofumi } 341990e194eSOGAWA Hirofumi 342990e194eSOGAWA Hirofumi if (ext_start == uname - 1) { 343990e194eSOGAWA Hirofumi sz = ulen; 344990e194eSOGAWA Hirofumi ext_start = NULL; 345990e194eSOGAWA Hirofumi } else if (ext_start) { 346990e194eSOGAWA Hirofumi /* 347990e194eSOGAWA Hirofumi * Names which start with a dot could be just 348990e194eSOGAWA Hirofumi * an extension eg. "...test". In this case Win95 349990e194eSOGAWA Hirofumi * uses the extension as the name and sets no extension. 350990e194eSOGAWA Hirofumi */ 351990e194eSOGAWA Hirofumi name_start = &uname[0]; 352990e194eSOGAWA Hirofumi while (name_start < ext_start) { 353990e194eSOGAWA Hirofumi if (!vfat_skip_char(*name_start)) 354990e194eSOGAWA Hirofumi break; 355990e194eSOGAWA Hirofumi name_start++; 356990e194eSOGAWA Hirofumi } 357990e194eSOGAWA Hirofumi if (name_start != ext_start) { 358990e194eSOGAWA Hirofumi sz = ext_start - uname; 359990e194eSOGAWA Hirofumi ext_start++; 360990e194eSOGAWA Hirofumi } else { 361990e194eSOGAWA Hirofumi sz = ulen; 362990e194eSOGAWA Hirofumi ext_start = NULL; 363990e194eSOGAWA Hirofumi } 364990e194eSOGAWA Hirofumi } 365990e194eSOGAWA Hirofumi 366990e194eSOGAWA Hirofumi numtail_baselen = 6; 367990e194eSOGAWA Hirofumi numtail2_baselen = 2; 368990e194eSOGAWA Hirofumi for (baselen = i = 0, p = base, ip = uname; i < sz; i++, ip++) { 369990e194eSOGAWA Hirofumi chl = to_shortname_char(nls, charbuf, sizeof(charbuf), 370990e194eSOGAWA Hirofumi ip, &base_info); 371990e194eSOGAWA Hirofumi if (chl == 0) 372990e194eSOGAWA Hirofumi continue; 373990e194eSOGAWA Hirofumi 374990e194eSOGAWA Hirofumi if (baselen < 2 && (baselen + chl) > 2) 375990e194eSOGAWA Hirofumi numtail2_baselen = baselen; 376990e194eSOGAWA Hirofumi if (baselen < 6 && (baselen + chl) > 6) 377990e194eSOGAWA Hirofumi numtail_baselen = baselen; 378990e194eSOGAWA Hirofumi for (chi = 0; chi < chl; chi++) { 379990e194eSOGAWA Hirofumi *p++ = charbuf[chi]; 380990e194eSOGAWA Hirofumi baselen++; 381990e194eSOGAWA Hirofumi if (baselen >= 8) 382990e194eSOGAWA Hirofumi break; 383990e194eSOGAWA Hirofumi } 384990e194eSOGAWA Hirofumi if (baselen >= 8) { 385990e194eSOGAWA Hirofumi if ((chi < chl - 1) || (ip + 1) - uname < sz) 386990e194eSOGAWA Hirofumi is_shortname = 0; 387990e194eSOGAWA Hirofumi break; 388990e194eSOGAWA Hirofumi } 389990e194eSOGAWA Hirofumi } 390990e194eSOGAWA Hirofumi if (baselen == 0) { 391990e194eSOGAWA Hirofumi return -EINVAL; 392990e194eSOGAWA Hirofumi } 393990e194eSOGAWA Hirofumi 394990e194eSOGAWA Hirofumi extlen = 0; 395990e194eSOGAWA Hirofumi if (ext_start) { 396990e194eSOGAWA Hirofumi for (p = ext, ip = ext_start; extlen < 3 && ip < end; ip++) { 397990e194eSOGAWA Hirofumi chl = to_shortname_char(nls, charbuf, sizeof(charbuf), 398990e194eSOGAWA Hirofumi ip, &ext_info); 399990e194eSOGAWA Hirofumi if (chl == 0) 400990e194eSOGAWA Hirofumi continue; 401990e194eSOGAWA Hirofumi 402990e194eSOGAWA Hirofumi if ((extlen + chl) > 3) { 403990e194eSOGAWA Hirofumi is_shortname = 0; 404990e194eSOGAWA Hirofumi break; 405990e194eSOGAWA Hirofumi } 406990e194eSOGAWA Hirofumi for (chi = 0; chi < chl; chi++) { 407990e194eSOGAWA Hirofumi *p++ = charbuf[chi]; 408990e194eSOGAWA Hirofumi extlen++; 409990e194eSOGAWA Hirofumi } 410990e194eSOGAWA Hirofumi if (extlen >= 3) { 411990e194eSOGAWA Hirofumi if (ip + 1 != end) 412990e194eSOGAWA Hirofumi is_shortname = 0; 413990e194eSOGAWA Hirofumi break; 414990e194eSOGAWA Hirofumi } 415990e194eSOGAWA Hirofumi } 416990e194eSOGAWA Hirofumi } 417990e194eSOGAWA Hirofumi ext[extlen] = '\0'; 418990e194eSOGAWA Hirofumi base[baselen] = '\0'; 419990e194eSOGAWA Hirofumi 420990e194eSOGAWA Hirofumi /* Yes, it can happen. ".\xe5" would do it. */ 421990e194eSOGAWA Hirofumi if (base[0] == DELETED_FLAG) 422990e194eSOGAWA Hirofumi base[0] = 0x05; 423990e194eSOGAWA Hirofumi 424990e194eSOGAWA Hirofumi /* OK, at this point we know that base is not longer than 8 symbols, 425990e194eSOGAWA Hirofumi * ext is not longer than 3, base is nonempty, both don't contain 426990e194eSOGAWA Hirofumi * any bad symbols (lowercase transformed to uppercase). 427990e194eSOGAWA Hirofumi */ 428990e194eSOGAWA Hirofumi 429990e194eSOGAWA Hirofumi memset(name_res, ' ', MSDOS_NAME); 430990e194eSOGAWA Hirofumi memcpy(name_res, base, baselen); 431990e194eSOGAWA Hirofumi memcpy(name_res + 8, ext, extlen); 432990e194eSOGAWA Hirofumi *lcase = 0; 433990e194eSOGAWA Hirofumi if (is_shortname && base_info.valid && ext_info.valid) { 434990e194eSOGAWA Hirofumi if (vfat_find_form(dir, name_res) == 0) 435990e194eSOGAWA Hirofumi return -EEXIST; 436990e194eSOGAWA Hirofumi 437990e194eSOGAWA Hirofumi if (opts->shortname & VFAT_SFN_CREATE_WIN95) { 438990e194eSOGAWA Hirofumi return (base_info.upper && ext_info.upper); 439990e194eSOGAWA Hirofumi } else if (opts->shortname & VFAT_SFN_CREATE_WINNT) { 440990e194eSOGAWA Hirofumi if ((base_info.upper || base_info.lower) && 441990e194eSOGAWA Hirofumi (ext_info.upper || ext_info.lower)) { 442990e194eSOGAWA Hirofumi if (!base_info.upper && base_info.lower) 443990e194eSOGAWA Hirofumi *lcase |= CASE_LOWER_BASE; 444990e194eSOGAWA Hirofumi if (!ext_info.upper && ext_info.lower) 445990e194eSOGAWA Hirofumi *lcase |= CASE_LOWER_EXT; 446990e194eSOGAWA Hirofumi return 1; 447990e194eSOGAWA Hirofumi } 448990e194eSOGAWA Hirofumi return 0; 449990e194eSOGAWA Hirofumi } else { 450990e194eSOGAWA Hirofumi BUG(); 451990e194eSOGAWA Hirofumi } 452990e194eSOGAWA Hirofumi } 453990e194eSOGAWA Hirofumi 454990e194eSOGAWA Hirofumi if (opts->numtail == 0) 455990e194eSOGAWA Hirofumi if (vfat_find_form(dir, name_res) < 0) 456990e194eSOGAWA Hirofumi return 0; 457990e194eSOGAWA Hirofumi 458990e194eSOGAWA Hirofumi /* 459990e194eSOGAWA Hirofumi * Try to find a unique extension. This used to 460990e194eSOGAWA Hirofumi * iterate through all possibilities sequentially, 461990e194eSOGAWA Hirofumi * but that gave extremely bad performance. Windows 462990e194eSOGAWA Hirofumi * only tries a few cases before using random 463990e194eSOGAWA Hirofumi * values for part of the base. 464990e194eSOGAWA Hirofumi */ 465990e194eSOGAWA Hirofumi 466990e194eSOGAWA Hirofumi if (baselen > 6) { 467990e194eSOGAWA Hirofumi baselen = numtail_baselen; 468990e194eSOGAWA Hirofumi name_res[7] = ' '; 469990e194eSOGAWA Hirofumi } 470990e194eSOGAWA Hirofumi name_res[baselen] = '~'; 471990e194eSOGAWA Hirofumi for (i = 1; i < 10; i++) { 472990e194eSOGAWA Hirofumi name_res[baselen + 1] = i + '0'; 473990e194eSOGAWA Hirofumi if (vfat_find_form(dir, name_res) < 0) 474990e194eSOGAWA Hirofumi return 0; 475990e194eSOGAWA Hirofumi } 476990e194eSOGAWA Hirofumi 47730d1872dSNikolaus Schulz i = jiffies; 478990e194eSOGAWA Hirofumi sz = (jiffies >> 16) & 0x7; 479990e194eSOGAWA Hirofumi if (baselen > 2) { 480990e194eSOGAWA Hirofumi baselen = numtail2_baselen; 481990e194eSOGAWA Hirofumi name_res[7] = ' '; 482990e194eSOGAWA Hirofumi } 483990e194eSOGAWA Hirofumi name_res[baselen + 4] = '~'; 484990e194eSOGAWA Hirofumi name_res[baselen + 5] = '1' + sz; 485990e194eSOGAWA Hirofumi while (1) { 48630d1872dSNikolaus Schulz snprintf(buf, sizeof(buf), "%04X", i & 0xffff); 487990e194eSOGAWA Hirofumi memcpy(&name_res[baselen], buf, 4); 488990e194eSOGAWA Hirofumi if (vfat_find_form(dir, name_res) < 0) 489990e194eSOGAWA Hirofumi break; 490990e194eSOGAWA Hirofumi i -= 11; 491990e194eSOGAWA Hirofumi } 492990e194eSOGAWA Hirofumi return 0; 493990e194eSOGAWA Hirofumi } 494990e194eSOGAWA Hirofumi 495990e194eSOGAWA Hirofumi /* Translate a string, including coded sequences into Unicode */ 496990e194eSOGAWA Hirofumi static int 497990e194eSOGAWA Hirofumi xlate_to_uni(const unsigned char *name, int len, unsigned char *outname, 498990e194eSOGAWA Hirofumi int *longlen, int *outlen, int escape, int utf8, 499990e194eSOGAWA Hirofumi struct nls_table *nls) 500990e194eSOGAWA Hirofumi { 501990e194eSOGAWA Hirofumi const unsigned char *ip; 502990e194eSOGAWA Hirofumi unsigned char nc; 503990e194eSOGAWA Hirofumi unsigned char *op; 504990e194eSOGAWA Hirofumi unsigned int ec; 505990e194eSOGAWA Hirofumi int i, k, fill; 506990e194eSOGAWA Hirofumi int charlen; 507990e194eSOGAWA Hirofumi 508990e194eSOGAWA Hirofumi if (utf8) { 5090720a06aSAlan Stern *outlen = utf8s_to_utf16s(name, len, UTF16_HOST_ENDIAN, 5100720a06aSAlan Stern (wchar_t *) outname, FAT_LFN_LEN + 2); 51167638e40SOGAWA Hirofumi if (*outlen < 0) 51267638e40SOGAWA Hirofumi return *outlen; 513eeb5b4aeSKevin Dankwardt else if (*outlen > FAT_LFN_LEN) 514990e194eSOGAWA Hirofumi return -ENAMETOOLONG; 515990e194eSOGAWA Hirofumi 516990e194eSOGAWA Hirofumi op = &outname[*outlen * sizeof(wchar_t)]; 517990e194eSOGAWA Hirofumi } else { 518990e194eSOGAWA Hirofumi for (i = 0, ip = name, op = outname, *outlen = 0; 519d533df07SNamjae Jeon i < len && *outlen < FAT_LFN_LEN; 52041f0c02eSNamjae Jeon *outlen += 1) { 521990e194eSOGAWA Hirofumi if (escape && (*ip == ':')) { 522990e194eSOGAWA Hirofumi if (i > len - 5) 523990e194eSOGAWA Hirofumi return -EINVAL; 524990e194eSOGAWA Hirofumi ec = 0; 525990e194eSOGAWA Hirofumi for (k = 1; k < 5; k++) { 526990e194eSOGAWA Hirofumi nc = ip[k]; 527990e194eSOGAWA Hirofumi ec <<= 4; 528990e194eSOGAWA Hirofumi if (nc >= '0' && nc <= '9') { 529990e194eSOGAWA Hirofumi ec |= nc - '0'; 530990e194eSOGAWA Hirofumi continue; 531990e194eSOGAWA Hirofumi } 532990e194eSOGAWA Hirofumi if (nc >= 'a' && nc <= 'f') { 533990e194eSOGAWA Hirofumi ec |= nc - ('a' - 10); 534990e194eSOGAWA Hirofumi continue; 535990e194eSOGAWA Hirofumi } 536990e194eSOGAWA Hirofumi if (nc >= 'A' && nc <= 'F') { 537990e194eSOGAWA Hirofumi ec |= nc - ('A' - 10); 538990e194eSOGAWA Hirofumi continue; 539990e194eSOGAWA Hirofumi } 540990e194eSOGAWA Hirofumi return -EINVAL; 541990e194eSOGAWA Hirofumi } 542990e194eSOGAWA Hirofumi *op++ = ec & 0xFF; 543990e194eSOGAWA Hirofumi *op++ = ec >> 8; 544990e194eSOGAWA Hirofumi ip += 5; 545990e194eSOGAWA Hirofumi i += 5; 546990e194eSOGAWA Hirofumi } else { 54741f0c02eSNamjae Jeon charlen = nls->char2uni(ip, len - i, 54841f0c02eSNamjae Jeon (wchar_t *)op); 54941f0c02eSNamjae Jeon if (charlen < 0) 550990e194eSOGAWA Hirofumi return -EINVAL; 551990e194eSOGAWA Hirofumi ip += charlen; 552990e194eSOGAWA Hirofumi i += charlen; 553990e194eSOGAWA Hirofumi op += 2; 554990e194eSOGAWA Hirofumi } 555990e194eSOGAWA Hirofumi } 556990e194eSOGAWA Hirofumi if (i < len) 557990e194eSOGAWA Hirofumi return -ENAMETOOLONG; 558990e194eSOGAWA Hirofumi } 559990e194eSOGAWA Hirofumi 560990e194eSOGAWA Hirofumi *longlen = *outlen; 561990e194eSOGAWA Hirofumi if (*outlen % 13) { 562990e194eSOGAWA Hirofumi *op++ = 0; 563990e194eSOGAWA Hirofumi *op++ = 0; 564990e194eSOGAWA Hirofumi *outlen += 1; 565990e194eSOGAWA Hirofumi if (*outlen % 13) { 566990e194eSOGAWA Hirofumi fill = 13 - (*outlen % 13); 567990e194eSOGAWA Hirofumi for (i = 0; i < fill; i++) { 568990e194eSOGAWA Hirofumi *op++ = 0xff; 569990e194eSOGAWA Hirofumi *op++ = 0xff; 570990e194eSOGAWA Hirofumi } 571990e194eSOGAWA Hirofumi *outlen += fill; 572990e194eSOGAWA Hirofumi } 573990e194eSOGAWA Hirofumi } 574990e194eSOGAWA Hirofumi 575990e194eSOGAWA Hirofumi return 0; 576990e194eSOGAWA Hirofumi } 577990e194eSOGAWA Hirofumi 578990e194eSOGAWA Hirofumi static int vfat_build_slots(struct inode *dir, const unsigned char *name, 579990e194eSOGAWA Hirofumi int len, int is_dir, int cluster, 580990e194eSOGAWA Hirofumi struct timespec *ts, 581990e194eSOGAWA Hirofumi struct msdos_dir_slot *slots, int *nr_slots) 582990e194eSOGAWA Hirofumi { 583990e194eSOGAWA Hirofumi struct msdos_sb_info *sbi = MSDOS_SB(dir->i_sb); 584990e194eSOGAWA Hirofumi struct fat_mount_options *opts = &sbi->options; 585990e194eSOGAWA Hirofumi struct msdos_dir_slot *ps; 586990e194eSOGAWA Hirofumi struct msdos_dir_entry *de; 587990e194eSOGAWA Hirofumi unsigned char cksum, lcase; 588990e194eSOGAWA Hirofumi unsigned char msdos_name[MSDOS_NAME]; 589990e194eSOGAWA Hirofumi wchar_t *uname; 590990e194eSOGAWA Hirofumi __le16 time, date; 5917decd1cbSOGAWA Hirofumi u8 time_cs; 592990e194eSOGAWA Hirofumi int err, ulen, usize, i; 593990e194eSOGAWA Hirofumi loff_t offset; 594990e194eSOGAWA Hirofumi 595990e194eSOGAWA Hirofumi *nr_slots = 0; 596990e194eSOGAWA Hirofumi 597990e194eSOGAWA Hirofumi uname = __getname(); 598990e194eSOGAWA Hirofumi if (!uname) 599990e194eSOGAWA Hirofumi return -ENOMEM; 600990e194eSOGAWA Hirofumi 601990e194eSOGAWA Hirofumi err = xlate_to_uni(name, len, (unsigned char *)uname, &ulen, &usize, 602990e194eSOGAWA Hirofumi opts->unicode_xlate, opts->utf8, sbi->nls_io); 603990e194eSOGAWA Hirofumi if (err) 604990e194eSOGAWA Hirofumi goto out_free; 605990e194eSOGAWA Hirofumi 606990e194eSOGAWA Hirofumi err = vfat_is_used_badchars(uname, ulen); 607990e194eSOGAWA Hirofumi if (err) 608990e194eSOGAWA Hirofumi goto out_free; 609990e194eSOGAWA Hirofumi 610990e194eSOGAWA Hirofumi err = vfat_create_shortname(dir, sbi->nls_disk, uname, ulen, 611990e194eSOGAWA Hirofumi msdos_name, &lcase); 612990e194eSOGAWA Hirofumi if (err < 0) 613990e194eSOGAWA Hirofumi goto out_free; 614990e194eSOGAWA Hirofumi else if (err == 1) { 615990e194eSOGAWA Hirofumi de = (struct msdos_dir_entry *)slots; 616990e194eSOGAWA Hirofumi err = 0; 617990e194eSOGAWA Hirofumi goto shortname; 618990e194eSOGAWA Hirofumi } 619990e194eSOGAWA Hirofumi 620990e194eSOGAWA Hirofumi /* build the entry of long file name */ 621990e194eSOGAWA Hirofumi cksum = fat_checksum(msdos_name); 622990e194eSOGAWA Hirofumi 623990e194eSOGAWA Hirofumi *nr_slots = usize / 13; 624990e194eSOGAWA Hirofumi for (ps = slots, i = *nr_slots; i > 0; i--, ps++) { 625990e194eSOGAWA Hirofumi ps->id = i; 626990e194eSOGAWA Hirofumi ps->attr = ATTR_EXT; 627990e194eSOGAWA Hirofumi ps->reserved = 0; 628990e194eSOGAWA Hirofumi ps->alias_checksum = cksum; 629990e194eSOGAWA Hirofumi ps->start = 0; 630990e194eSOGAWA Hirofumi offset = (i - 1) * 13; 631990e194eSOGAWA Hirofumi fatwchar_to16(ps->name0_4, uname + offset, 5); 632990e194eSOGAWA Hirofumi fatwchar_to16(ps->name5_10, uname + offset + 5, 6); 633990e194eSOGAWA Hirofumi fatwchar_to16(ps->name11_12, uname + offset + 11, 2); 634990e194eSOGAWA Hirofumi } 635990e194eSOGAWA Hirofumi slots[0].id |= 0x40; 636990e194eSOGAWA Hirofumi de = (struct msdos_dir_entry *)ps; 637990e194eSOGAWA Hirofumi 638990e194eSOGAWA Hirofumi shortname: 639990e194eSOGAWA Hirofumi /* build the entry of 8.3 alias name */ 640990e194eSOGAWA Hirofumi (*nr_slots)++; 641990e194eSOGAWA Hirofumi memcpy(de->name, msdos_name, MSDOS_NAME); 642990e194eSOGAWA Hirofumi de->attr = is_dir ? ATTR_DIR : ATTR_ARCH; 643990e194eSOGAWA Hirofumi de->lcase = lcase; 6447decd1cbSOGAWA Hirofumi fat_time_unix2fat(sbi, ts, &time, &date, &time_cs); 645990e194eSOGAWA Hirofumi de->time = de->ctime = time; 646990e194eSOGAWA Hirofumi de->date = de->cdate = de->adate = date; 6477decd1cbSOGAWA Hirofumi de->ctime_cs = time_cs; 648a943ed71SSteven J. Magnani fat_set_start(de, cluster); 649990e194eSOGAWA Hirofumi de->size = 0; 650990e194eSOGAWA Hirofumi out_free: 651990e194eSOGAWA Hirofumi __putname(uname); 652990e194eSOGAWA Hirofumi return err; 653990e194eSOGAWA Hirofumi } 654990e194eSOGAWA Hirofumi 655990e194eSOGAWA Hirofumi static int vfat_add_entry(struct inode *dir, struct qstr *qname, int is_dir, 656990e194eSOGAWA Hirofumi int cluster, struct timespec *ts, 657990e194eSOGAWA Hirofumi struct fat_slot_info *sinfo) 658990e194eSOGAWA Hirofumi { 659990e194eSOGAWA Hirofumi struct msdos_dir_slot *slots; 660990e194eSOGAWA Hirofumi unsigned int len; 661990e194eSOGAWA Hirofumi int err, nr_slots; 662990e194eSOGAWA Hirofumi 663990e194eSOGAWA Hirofumi len = vfat_striptail_len(qname); 664990e194eSOGAWA Hirofumi if (len == 0) 665990e194eSOGAWA Hirofumi return -ENOENT; 666990e194eSOGAWA Hirofumi 667990e194eSOGAWA Hirofumi slots = kmalloc(sizeof(*slots) * MSDOS_SLOTS, GFP_NOFS); 668990e194eSOGAWA Hirofumi if (slots == NULL) 669990e194eSOGAWA Hirofumi return -ENOMEM; 670990e194eSOGAWA Hirofumi 671990e194eSOGAWA Hirofumi err = vfat_build_slots(dir, qname->name, len, is_dir, cluster, ts, 672990e194eSOGAWA Hirofumi slots, &nr_slots); 673990e194eSOGAWA Hirofumi if (err) 674990e194eSOGAWA Hirofumi goto cleanup; 675990e194eSOGAWA Hirofumi 676990e194eSOGAWA Hirofumi err = fat_add_entries(dir, slots, nr_slots, sinfo); 677990e194eSOGAWA Hirofumi if (err) 678990e194eSOGAWA Hirofumi goto cleanup; 679990e194eSOGAWA Hirofumi 680990e194eSOGAWA Hirofumi /* update timestamp */ 681990e194eSOGAWA Hirofumi dir->i_ctime = dir->i_mtime = dir->i_atime = *ts; 682990e194eSOGAWA Hirofumi if (IS_DIRSYNC(dir)) 683990e194eSOGAWA Hirofumi (void)fat_sync_inode(dir); 684990e194eSOGAWA Hirofumi else 685990e194eSOGAWA Hirofumi mark_inode_dirty(dir); 686990e194eSOGAWA Hirofumi cleanup: 687990e194eSOGAWA Hirofumi kfree(slots); 688990e194eSOGAWA Hirofumi return err; 689990e194eSOGAWA Hirofumi } 690990e194eSOGAWA Hirofumi 691990e194eSOGAWA Hirofumi static int vfat_find(struct inode *dir, struct qstr *qname, 692990e194eSOGAWA Hirofumi struct fat_slot_info *sinfo) 693990e194eSOGAWA Hirofumi { 694990e194eSOGAWA Hirofumi unsigned int len = vfat_striptail_len(qname); 695990e194eSOGAWA Hirofumi if (len == 0) 696990e194eSOGAWA Hirofumi return -ENOENT; 697990e194eSOGAWA Hirofumi return fat_search_long(dir, qname->name, len, sinfo); 698990e194eSOGAWA Hirofumi } 699990e194eSOGAWA Hirofumi 7008045e298SOGAWA Hirofumi /* 7018045e298SOGAWA Hirofumi * (nfsd's) anonymous disconnected dentry? 7028045e298SOGAWA Hirofumi * NOTE: !IS_ROOT() is not anonymous (I.e. d_splice_alias() did the job). 7038045e298SOGAWA Hirofumi */ 7048045e298SOGAWA Hirofumi static int vfat_d_anon_disconn(struct dentry *dentry) 7058045e298SOGAWA Hirofumi { 7068045e298SOGAWA Hirofumi return IS_ROOT(dentry) && (dentry->d_flags & DCACHE_DISCONNECTED); 7078045e298SOGAWA Hirofumi } 7088045e298SOGAWA Hirofumi 709990e194eSOGAWA Hirofumi static struct dentry *vfat_lookup(struct inode *dir, struct dentry *dentry, 71000cd8dd3SAl Viro unsigned int flags) 711990e194eSOGAWA Hirofumi { 712990e194eSOGAWA Hirofumi struct super_block *sb = dir->i_sb; 713990e194eSOGAWA Hirofumi struct fat_slot_info sinfo; 714068f5ae0SOGAWA Hirofumi struct inode *inode; 715990e194eSOGAWA Hirofumi struct dentry *alias; 7161b524672SOGAWA Hirofumi int err; 717990e194eSOGAWA Hirofumi 718e40b34c7SMarco Stornelli mutex_lock(&MSDOS_SB(sb)->s_lock); 719990e194eSOGAWA Hirofumi 720990e194eSOGAWA Hirofumi err = vfat_find(dir, &dentry->d_name, &sinfo); 721990e194eSOGAWA Hirofumi if (err) { 722068f5ae0SOGAWA Hirofumi if (err == -ENOENT) { 723068f5ae0SOGAWA Hirofumi inode = NULL; 724068f5ae0SOGAWA Hirofumi goto out; 725068f5ae0SOGAWA Hirofumi } 726990e194eSOGAWA Hirofumi goto error; 727990e194eSOGAWA Hirofumi } 7281b524672SOGAWA Hirofumi 729990e194eSOGAWA Hirofumi inode = fat_build_inode(sb, sinfo.de, sinfo.i_pos); 730990e194eSOGAWA Hirofumi brelse(sinfo.bh); 731990e194eSOGAWA Hirofumi if (IS_ERR(inode)) { 732068f5ae0SOGAWA Hirofumi err = PTR_ERR(inode); 733068f5ae0SOGAWA Hirofumi goto error; 734990e194eSOGAWA Hirofumi } 7351b524672SOGAWA Hirofumi 736990e194eSOGAWA Hirofumi alias = d_find_alias(inode); 7371ead0e79SAl Viro /* 7381ead0e79SAl Viro * Checking "alias->d_parent == dentry->d_parent" to make sure 7391ead0e79SAl Viro * FS is not corrupted (especially double linked dir). 7401ead0e79SAl Viro */ 7411ead0e79SAl Viro if (alias && alias->d_parent == dentry->d_parent && 7421ead0e79SAl Viro !vfat_d_anon_disconn(alias)) { 7431b524672SOGAWA Hirofumi /* 7448045e298SOGAWA Hirofumi * This inode has non anonymous-DCACHE_DISCONNECTED 7458045e298SOGAWA Hirofumi * dentry. This means, the user did ->lookup() by an 7468045e298SOGAWA Hirofumi * another name (longname vs 8.3 alias of it) in past. 7471b524672SOGAWA Hirofumi * 7481b524672SOGAWA Hirofumi * Switch to new one for reason of locality if possible. 7491b524672SOGAWA Hirofumi */ 7501c13a243SOGAWA Hirofumi BUG_ON(d_unhashed(alias)); 7511c13a243SOGAWA Hirofumi if (!S_ISDIR(inode->i_mode)) 7521c13a243SOGAWA Hirofumi d_move(alias, dentry); 753990e194eSOGAWA Hirofumi iput(inode); 754e40b34c7SMarco Stornelli mutex_unlock(&MSDOS_SB(sb)->s_lock); 755990e194eSOGAWA Hirofumi return alias; 7568045e298SOGAWA Hirofumi } else 7578045e298SOGAWA Hirofumi dput(alias); 7588045e298SOGAWA Hirofumi 759068f5ae0SOGAWA Hirofumi out: 760e40b34c7SMarco Stornelli mutex_unlock(&MSDOS_SB(sb)->s_lock); 7611ead0e79SAl Viro if (!inode) 7621ead0e79SAl Viro dentry->d_time = dir->i_version; 7631ead0e79SAl Viro return d_splice_alias(inode, dentry); 764068f5ae0SOGAWA Hirofumi error: 765e40b34c7SMarco Stornelli mutex_unlock(&MSDOS_SB(sb)->s_lock); 766068f5ae0SOGAWA Hirofumi return ERR_PTR(err); 767990e194eSOGAWA Hirofumi } 768990e194eSOGAWA Hirofumi 7694acdaf27SAl Viro static int vfat_create(struct inode *dir, struct dentry *dentry, umode_t mode, 770ebfc3b49SAl Viro bool excl) 771990e194eSOGAWA Hirofumi { 772990e194eSOGAWA Hirofumi struct super_block *sb = dir->i_sb; 773990e194eSOGAWA Hirofumi struct inode *inode; 774990e194eSOGAWA Hirofumi struct fat_slot_info sinfo; 775990e194eSOGAWA Hirofumi struct timespec ts; 776990e194eSOGAWA Hirofumi int err; 777990e194eSOGAWA Hirofumi 778e40b34c7SMarco Stornelli mutex_lock(&MSDOS_SB(sb)->s_lock); 779990e194eSOGAWA Hirofumi 780990e194eSOGAWA Hirofumi ts = CURRENT_TIME_SEC; 781990e194eSOGAWA Hirofumi err = vfat_add_entry(dir, &dentry->d_name, 0, 0, &ts, &sinfo); 782990e194eSOGAWA Hirofumi if (err) 783990e194eSOGAWA Hirofumi goto out; 784990e194eSOGAWA Hirofumi dir->i_version++; 785990e194eSOGAWA Hirofumi 786990e194eSOGAWA Hirofumi inode = fat_build_inode(sb, sinfo.de, sinfo.i_pos); 787990e194eSOGAWA Hirofumi brelse(sinfo.bh); 788990e194eSOGAWA Hirofumi if (IS_ERR(inode)) { 789990e194eSOGAWA Hirofumi err = PTR_ERR(inode); 790990e194eSOGAWA Hirofumi goto out; 791990e194eSOGAWA Hirofumi } 792990e194eSOGAWA Hirofumi inode->i_version++; 793990e194eSOGAWA Hirofumi inode->i_mtime = inode->i_atime = inode->i_ctime = ts; 794990e194eSOGAWA Hirofumi /* timestamp is already written, so mark_inode_dirty() is unneeded. */ 795990e194eSOGAWA Hirofumi 796990e194eSOGAWA Hirofumi d_instantiate(dentry, inode); 797990e194eSOGAWA Hirofumi out: 798e40b34c7SMarco Stornelli mutex_unlock(&MSDOS_SB(sb)->s_lock); 799990e194eSOGAWA Hirofumi return err; 800990e194eSOGAWA Hirofumi } 801990e194eSOGAWA Hirofumi 802990e194eSOGAWA Hirofumi static int vfat_rmdir(struct inode *dir, struct dentry *dentry) 803990e194eSOGAWA Hirofumi { 8042b0143b5SDavid Howells struct inode *inode = d_inode(dentry); 805990e194eSOGAWA Hirofumi struct super_block *sb = dir->i_sb; 806990e194eSOGAWA Hirofumi struct fat_slot_info sinfo; 807990e194eSOGAWA Hirofumi int err; 808990e194eSOGAWA Hirofumi 809e40b34c7SMarco Stornelli mutex_lock(&MSDOS_SB(sb)->s_lock); 810990e194eSOGAWA Hirofumi 811990e194eSOGAWA Hirofumi err = fat_dir_empty(inode); 812990e194eSOGAWA Hirofumi if (err) 813990e194eSOGAWA Hirofumi goto out; 814990e194eSOGAWA Hirofumi err = vfat_find(dir, &dentry->d_name, &sinfo); 815990e194eSOGAWA Hirofumi if (err) 816990e194eSOGAWA Hirofumi goto out; 817990e194eSOGAWA Hirofumi 818990e194eSOGAWA Hirofumi err = fat_remove_entries(dir, &sinfo); /* and releases bh */ 819990e194eSOGAWA Hirofumi if (err) 820990e194eSOGAWA Hirofumi goto out; 821990e194eSOGAWA Hirofumi drop_nlink(dir); 822990e194eSOGAWA Hirofumi 823990e194eSOGAWA Hirofumi clear_nlink(inode); 824990e194eSOGAWA Hirofumi inode->i_mtime = inode->i_atime = CURRENT_TIME_SEC; 825990e194eSOGAWA Hirofumi fat_detach(inode); 8261ead0e79SAl Viro dentry->d_time = dir->i_version; 827990e194eSOGAWA Hirofumi out: 828e40b34c7SMarco Stornelli mutex_unlock(&MSDOS_SB(sb)->s_lock); 829990e194eSOGAWA Hirofumi 830990e194eSOGAWA Hirofumi return err; 831990e194eSOGAWA Hirofumi } 832990e194eSOGAWA Hirofumi 833990e194eSOGAWA Hirofumi static int vfat_unlink(struct inode *dir, struct dentry *dentry) 834990e194eSOGAWA Hirofumi { 8352b0143b5SDavid Howells struct inode *inode = d_inode(dentry); 836990e194eSOGAWA Hirofumi struct super_block *sb = dir->i_sb; 837990e194eSOGAWA Hirofumi struct fat_slot_info sinfo; 838990e194eSOGAWA Hirofumi int err; 839990e194eSOGAWA Hirofumi 840e40b34c7SMarco Stornelli mutex_lock(&MSDOS_SB(sb)->s_lock); 841990e194eSOGAWA Hirofumi 842990e194eSOGAWA Hirofumi err = vfat_find(dir, &dentry->d_name, &sinfo); 843990e194eSOGAWA Hirofumi if (err) 844990e194eSOGAWA Hirofumi goto out; 845990e194eSOGAWA Hirofumi 846990e194eSOGAWA Hirofumi err = fat_remove_entries(dir, &sinfo); /* and releases bh */ 847990e194eSOGAWA Hirofumi if (err) 848990e194eSOGAWA Hirofumi goto out; 849990e194eSOGAWA Hirofumi clear_nlink(inode); 850990e194eSOGAWA Hirofumi inode->i_mtime = inode->i_atime = CURRENT_TIME_SEC; 851990e194eSOGAWA Hirofumi fat_detach(inode); 8521ead0e79SAl Viro dentry->d_time = dir->i_version; 853990e194eSOGAWA Hirofumi out: 854e40b34c7SMarco Stornelli mutex_unlock(&MSDOS_SB(sb)->s_lock); 855990e194eSOGAWA Hirofumi 856990e194eSOGAWA Hirofumi return err; 857990e194eSOGAWA Hirofumi } 858990e194eSOGAWA Hirofumi 85918bb1db3SAl Viro static int vfat_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) 860990e194eSOGAWA Hirofumi { 861990e194eSOGAWA Hirofumi struct super_block *sb = dir->i_sb; 862990e194eSOGAWA Hirofumi struct inode *inode; 863990e194eSOGAWA Hirofumi struct fat_slot_info sinfo; 864990e194eSOGAWA Hirofumi struct timespec ts; 865990e194eSOGAWA Hirofumi int err, cluster; 866990e194eSOGAWA Hirofumi 867e40b34c7SMarco Stornelli mutex_lock(&MSDOS_SB(sb)->s_lock); 868990e194eSOGAWA Hirofumi 869990e194eSOGAWA Hirofumi ts = CURRENT_TIME_SEC; 870990e194eSOGAWA Hirofumi cluster = fat_alloc_new_dir(dir, &ts); 871990e194eSOGAWA Hirofumi if (cluster < 0) { 872990e194eSOGAWA Hirofumi err = cluster; 873990e194eSOGAWA Hirofumi goto out; 874990e194eSOGAWA Hirofumi } 875990e194eSOGAWA Hirofumi err = vfat_add_entry(dir, &dentry->d_name, 1, cluster, &ts, &sinfo); 876990e194eSOGAWA Hirofumi if (err) 877990e194eSOGAWA Hirofumi goto out_free; 878990e194eSOGAWA Hirofumi dir->i_version++; 879990e194eSOGAWA Hirofumi inc_nlink(dir); 880990e194eSOGAWA Hirofumi 881990e194eSOGAWA Hirofumi inode = fat_build_inode(sb, sinfo.de, sinfo.i_pos); 882990e194eSOGAWA Hirofumi brelse(sinfo.bh); 883990e194eSOGAWA Hirofumi if (IS_ERR(inode)) { 884990e194eSOGAWA Hirofumi err = PTR_ERR(inode); 885990e194eSOGAWA Hirofumi /* the directory was completed, just return a error */ 886990e194eSOGAWA Hirofumi goto out; 887990e194eSOGAWA Hirofumi } 888990e194eSOGAWA Hirofumi inode->i_version++; 889bfe86848SMiklos Szeredi set_nlink(inode, 2); 890990e194eSOGAWA Hirofumi inode->i_mtime = inode->i_atime = inode->i_ctime = ts; 891990e194eSOGAWA Hirofumi /* timestamp is already written, so mark_inode_dirty() is unneeded. */ 892990e194eSOGAWA Hirofumi 893990e194eSOGAWA Hirofumi d_instantiate(dentry, inode); 894990e194eSOGAWA Hirofumi 895e40b34c7SMarco Stornelli mutex_unlock(&MSDOS_SB(sb)->s_lock); 896990e194eSOGAWA Hirofumi return 0; 897990e194eSOGAWA Hirofumi 898990e194eSOGAWA Hirofumi out_free: 899990e194eSOGAWA Hirofumi fat_free_clusters(dir, cluster); 900990e194eSOGAWA Hirofumi out: 901e40b34c7SMarco Stornelli mutex_unlock(&MSDOS_SB(sb)->s_lock); 902990e194eSOGAWA Hirofumi return err; 903990e194eSOGAWA Hirofumi } 904990e194eSOGAWA Hirofumi 905990e194eSOGAWA Hirofumi static int vfat_rename(struct inode *old_dir, struct dentry *old_dentry, 906990e194eSOGAWA Hirofumi struct inode *new_dir, struct dentry *new_dentry) 907990e194eSOGAWA Hirofumi { 908990e194eSOGAWA Hirofumi struct buffer_head *dotdot_bh; 909990e194eSOGAWA Hirofumi struct msdos_dir_entry *dotdot_de; 910990e194eSOGAWA Hirofumi struct inode *old_inode, *new_inode; 911990e194eSOGAWA Hirofumi struct fat_slot_info old_sinfo, sinfo; 912990e194eSOGAWA Hirofumi struct timespec ts; 9137669e8fbSSteven J. Magnani loff_t new_i_pos; 914990e194eSOGAWA Hirofumi int err, is_dir, update_dotdot, corrupt = 0; 915990e194eSOGAWA Hirofumi struct super_block *sb = old_dir->i_sb; 916990e194eSOGAWA Hirofumi 917990e194eSOGAWA Hirofumi old_sinfo.bh = sinfo.bh = dotdot_bh = NULL; 9182b0143b5SDavid Howells old_inode = d_inode(old_dentry); 9192b0143b5SDavid Howells new_inode = d_inode(new_dentry); 920e40b34c7SMarco Stornelli mutex_lock(&MSDOS_SB(sb)->s_lock); 921990e194eSOGAWA Hirofumi err = vfat_find(old_dir, &old_dentry->d_name, &old_sinfo); 922990e194eSOGAWA Hirofumi if (err) 923990e194eSOGAWA Hirofumi goto out; 924990e194eSOGAWA Hirofumi 925990e194eSOGAWA Hirofumi is_dir = S_ISDIR(old_inode->i_mode); 926990e194eSOGAWA Hirofumi update_dotdot = (is_dir && old_dir != new_dir); 927990e194eSOGAWA Hirofumi if (update_dotdot) { 9287669e8fbSSteven J. Magnani if (fat_get_dotdot_entry(old_inode, &dotdot_bh, &dotdot_de)) { 929990e194eSOGAWA Hirofumi err = -EIO; 930990e194eSOGAWA Hirofumi goto out; 931990e194eSOGAWA Hirofumi } 932990e194eSOGAWA Hirofumi } 933990e194eSOGAWA Hirofumi 934990e194eSOGAWA Hirofumi ts = CURRENT_TIME_SEC; 935990e194eSOGAWA Hirofumi if (new_inode) { 936990e194eSOGAWA Hirofumi if (is_dir) { 937990e194eSOGAWA Hirofumi err = fat_dir_empty(new_inode); 938990e194eSOGAWA Hirofumi if (err) 939990e194eSOGAWA Hirofumi goto out; 940990e194eSOGAWA Hirofumi } 941990e194eSOGAWA Hirofumi new_i_pos = MSDOS_I(new_inode)->i_pos; 942990e194eSOGAWA Hirofumi fat_detach(new_inode); 943990e194eSOGAWA Hirofumi } else { 944990e194eSOGAWA Hirofumi err = vfat_add_entry(new_dir, &new_dentry->d_name, is_dir, 0, 945990e194eSOGAWA Hirofumi &ts, &sinfo); 946990e194eSOGAWA Hirofumi if (err) 947990e194eSOGAWA Hirofumi goto out; 948990e194eSOGAWA Hirofumi new_i_pos = sinfo.i_pos; 949990e194eSOGAWA Hirofumi } 950990e194eSOGAWA Hirofumi new_dir->i_version++; 951990e194eSOGAWA Hirofumi 952990e194eSOGAWA Hirofumi fat_detach(old_inode); 953990e194eSOGAWA Hirofumi fat_attach(old_inode, new_i_pos); 954990e194eSOGAWA Hirofumi if (IS_DIRSYNC(new_dir)) { 955990e194eSOGAWA Hirofumi err = fat_sync_inode(old_inode); 956990e194eSOGAWA Hirofumi if (err) 957990e194eSOGAWA Hirofumi goto error_inode; 958990e194eSOGAWA Hirofumi } else 959990e194eSOGAWA Hirofumi mark_inode_dirty(old_inode); 960990e194eSOGAWA Hirofumi 961990e194eSOGAWA Hirofumi if (update_dotdot) { 962a943ed71SSteven J. Magnani fat_set_start(dotdot_de, MSDOS_I(new_dir)->i_logstart); 963b522412aSAl Viro mark_buffer_dirty_inode(dotdot_bh, old_inode); 964990e194eSOGAWA Hirofumi if (IS_DIRSYNC(new_dir)) { 965990e194eSOGAWA Hirofumi err = sync_dirty_buffer(dotdot_bh); 966990e194eSOGAWA Hirofumi if (err) 967990e194eSOGAWA Hirofumi goto error_dotdot; 968990e194eSOGAWA Hirofumi } 969990e194eSOGAWA Hirofumi drop_nlink(old_dir); 970990e194eSOGAWA Hirofumi if (!new_inode) 971990e194eSOGAWA Hirofumi inc_nlink(new_dir); 972990e194eSOGAWA Hirofumi } 973990e194eSOGAWA Hirofumi 974990e194eSOGAWA Hirofumi err = fat_remove_entries(old_dir, &old_sinfo); /* and releases bh */ 975990e194eSOGAWA Hirofumi old_sinfo.bh = NULL; 976990e194eSOGAWA Hirofumi if (err) 977990e194eSOGAWA Hirofumi goto error_dotdot; 978990e194eSOGAWA Hirofumi old_dir->i_version++; 979990e194eSOGAWA Hirofumi old_dir->i_ctime = old_dir->i_mtime = ts; 980990e194eSOGAWA Hirofumi if (IS_DIRSYNC(old_dir)) 981990e194eSOGAWA Hirofumi (void)fat_sync_inode(old_dir); 982990e194eSOGAWA Hirofumi else 983990e194eSOGAWA Hirofumi mark_inode_dirty(old_dir); 984990e194eSOGAWA Hirofumi 985990e194eSOGAWA Hirofumi if (new_inode) { 986990e194eSOGAWA Hirofumi drop_nlink(new_inode); 987990e194eSOGAWA Hirofumi if (is_dir) 988990e194eSOGAWA Hirofumi drop_nlink(new_inode); 989990e194eSOGAWA Hirofumi new_inode->i_ctime = ts; 990990e194eSOGAWA Hirofumi } 991990e194eSOGAWA Hirofumi out: 992990e194eSOGAWA Hirofumi brelse(sinfo.bh); 993990e194eSOGAWA Hirofumi brelse(dotdot_bh); 994990e194eSOGAWA Hirofumi brelse(old_sinfo.bh); 995e40b34c7SMarco Stornelli mutex_unlock(&MSDOS_SB(sb)->s_lock); 996990e194eSOGAWA Hirofumi 997990e194eSOGAWA Hirofumi return err; 998990e194eSOGAWA Hirofumi 999990e194eSOGAWA Hirofumi error_dotdot: 1000990e194eSOGAWA Hirofumi /* data cluster is shared, serious corruption */ 1001990e194eSOGAWA Hirofumi corrupt = 1; 1002990e194eSOGAWA Hirofumi 1003990e194eSOGAWA Hirofumi if (update_dotdot) { 1004a943ed71SSteven J. Magnani fat_set_start(dotdot_de, MSDOS_I(old_dir)->i_logstart); 1005b522412aSAl Viro mark_buffer_dirty_inode(dotdot_bh, old_inode); 1006990e194eSOGAWA Hirofumi corrupt |= sync_dirty_buffer(dotdot_bh); 1007990e194eSOGAWA Hirofumi } 1008990e194eSOGAWA Hirofumi error_inode: 1009990e194eSOGAWA Hirofumi fat_detach(old_inode); 1010990e194eSOGAWA Hirofumi fat_attach(old_inode, old_sinfo.i_pos); 1011990e194eSOGAWA Hirofumi if (new_inode) { 1012990e194eSOGAWA Hirofumi fat_attach(new_inode, new_i_pos); 1013990e194eSOGAWA Hirofumi if (corrupt) 1014990e194eSOGAWA Hirofumi corrupt |= fat_sync_inode(new_inode); 1015990e194eSOGAWA Hirofumi } else { 1016990e194eSOGAWA Hirofumi /* 1017990e194eSOGAWA Hirofumi * If new entry was not sharing the data cluster, it 1018990e194eSOGAWA Hirofumi * shouldn't be serious corruption. 1019990e194eSOGAWA Hirofumi */ 1020990e194eSOGAWA Hirofumi int err2 = fat_remove_entries(new_dir, &sinfo); 1021990e194eSOGAWA Hirofumi if (corrupt) 1022990e194eSOGAWA Hirofumi corrupt |= err2; 1023990e194eSOGAWA Hirofumi sinfo.bh = NULL; 1024990e194eSOGAWA Hirofumi } 1025990e194eSOGAWA Hirofumi if (corrupt < 0) { 102685c78591SDenis Karpov fat_fs_error(new_dir->i_sb, 1027990e194eSOGAWA Hirofumi "%s: Filesystem corrupted (i_pos %lld)", 1028990e194eSOGAWA Hirofumi __func__, sinfo.i_pos); 1029990e194eSOGAWA Hirofumi } 1030990e194eSOGAWA Hirofumi goto out; 1031990e194eSOGAWA Hirofumi } 1032990e194eSOGAWA Hirofumi 1033990e194eSOGAWA Hirofumi static const struct inode_operations vfat_dir_inode_operations = { 1034990e194eSOGAWA Hirofumi .create = vfat_create, 1035990e194eSOGAWA Hirofumi .lookup = vfat_lookup, 1036990e194eSOGAWA Hirofumi .unlink = vfat_unlink, 1037990e194eSOGAWA Hirofumi .mkdir = vfat_mkdir, 1038990e194eSOGAWA Hirofumi .rmdir = vfat_rmdir, 1039990e194eSOGAWA Hirofumi .rename = vfat_rename, 1040990e194eSOGAWA Hirofumi .setattr = fat_setattr, 1041990e194eSOGAWA Hirofumi .getattr = fat_getattr, 1042990e194eSOGAWA Hirofumi }; 1043990e194eSOGAWA Hirofumi 10443d23985dSAl Viro static void setup(struct super_block *sb) 1045990e194eSOGAWA Hirofumi { 1046384f5c96SOGAWA Hirofumi MSDOS_SB(sb)->dir_ops = &vfat_dir_inode_operations; 10473d23985dSAl Viro if (MSDOS_SB(sb)->options.name_check != 's') 10483d23985dSAl Viro sb->s_d_op = &vfat_ci_dentry_ops; 10493d23985dSAl Viro else 10503d23985dSAl Viro sb->s_d_op = &vfat_dentry_ops; 1051db719222SJan Blunck } 1052990e194eSOGAWA Hirofumi 10533d23985dSAl Viro static int vfat_fill_super(struct super_block *sb, void *data, int silent) 10543d23985dSAl Viro { 1055384f5c96SOGAWA Hirofumi return fat_fill_super(sb, data, silent, 1, setup); 1056990e194eSOGAWA Hirofumi } 1057990e194eSOGAWA Hirofumi 1058152a0836SAl Viro static struct dentry *vfat_mount(struct file_system_type *fs_type, 1059990e194eSOGAWA Hirofumi int flags, const char *dev_name, 1060152a0836SAl Viro void *data) 1061990e194eSOGAWA Hirofumi { 1062152a0836SAl Viro return mount_bdev(fs_type, flags, dev_name, data, vfat_fill_super); 1063990e194eSOGAWA Hirofumi } 1064990e194eSOGAWA Hirofumi 1065990e194eSOGAWA Hirofumi static struct file_system_type vfat_fs_type = { 1066990e194eSOGAWA Hirofumi .owner = THIS_MODULE, 1067990e194eSOGAWA Hirofumi .name = "vfat", 1068152a0836SAl Viro .mount = vfat_mount, 1069990e194eSOGAWA Hirofumi .kill_sb = kill_block_super, 1070990e194eSOGAWA Hirofumi .fs_flags = FS_REQUIRES_DEV, 1071990e194eSOGAWA Hirofumi }; 10727f78e035SEric W. Biederman MODULE_ALIAS_FS("vfat"); 1073990e194eSOGAWA Hirofumi 1074990e194eSOGAWA Hirofumi static int __init init_vfat_fs(void) 1075990e194eSOGAWA Hirofumi { 1076990e194eSOGAWA Hirofumi return register_filesystem(&vfat_fs_type); 1077990e194eSOGAWA Hirofumi } 1078990e194eSOGAWA Hirofumi 1079990e194eSOGAWA Hirofumi static void __exit exit_vfat_fs(void) 1080990e194eSOGAWA Hirofumi { 1081990e194eSOGAWA Hirofumi unregister_filesystem(&vfat_fs_type); 1082990e194eSOGAWA Hirofumi } 1083990e194eSOGAWA Hirofumi 1084990e194eSOGAWA Hirofumi MODULE_LICENSE("GPL"); 1085990e194eSOGAWA Hirofumi MODULE_DESCRIPTION("VFAT filesystem support"); 1086990e194eSOGAWA Hirofumi MODULE_AUTHOR("Gordon Chaffee"); 1087990e194eSOGAWA Hirofumi 1088990e194eSOGAWA Hirofumi module_init(init_vfat_fs) 1089990e194eSOGAWA Hirofumi module_exit(exit_vfat_fs) 1090