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/jiffies.h> 20990e194eSOGAWA Hirofumi #include <linux/ctype.h> 21990e194eSOGAWA Hirofumi #include <linux/slab.h> 22990e194eSOGAWA Hirofumi #include <linux/buffer_head.h> 23990e194eSOGAWA Hirofumi #include <linux/namei.h> 249e975daeSOGAWA Hirofumi #include "fat.h" 25990e194eSOGAWA Hirofumi 261b524672SOGAWA Hirofumi /* 271b524672SOGAWA Hirofumi * If new entry was created in the parent, it could create the 8.3 281b524672SOGAWA Hirofumi * alias (the shortname of logname). So, the parent may have the 291b524672SOGAWA Hirofumi * negative-dentry which matches the created 8.3 alias. 301b524672SOGAWA Hirofumi * 311b524672SOGAWA Hirofumi * If it happened, the negative dentry isn't actually negative 321b524672SOGAWA Hirofumi * anymore. So, drop it. 331b524672SOGAWA Hirofumi */ 341b524672SOGAWA Hirofumi static int vfat_revalidate_shortname(struct dentry *dentry) 35990e194eSOGAWA Hirofumi { 36990e194eSOGAWA Hirofumi int ret = 1; 37990e194eSOGAWA Hirofumi spin_lock(&dentry->d_lock); 38990e194eSOGAWA Hirofumi if (dentry->d_time != dentry->d_parent->d_inode->i_version) 39990e194eSOGAWA Hirofumi ret = 0; 40990e194eSOGAWA Hirofumi spin_unlock(&dentry->d_lock); 41990e194eSOGAWA Hirofumi return ret; 42990e194eSOGAWA Hirofumi } 43990e194eSOGAWA Hirofumi 440b728e19SAl Viro static int vfat_revalidate(struct dentry *dentry, unsigned int flags) 451b524672SOGAWA Hirofumi { 460b728e19SAl Viro if (flags & LOOKUP_RCU) 4734286d66SNick Piggin return -ECHILD; 4834286d66SNick Piggin 491b524672SOGAWA Hirofumi /* This is not negative dentry. Always valid. */ 501b524672SOGAWA Hirofumi if (dentry->d_inode) 511b524672SOGAWA Hirofumi return 1; 521b524672SOGAWA Hirofumi return vfat_revalidate_shortname(dentry); 531b524672SOGAWA Hirofumi } 541b524672SOGAWA Hirofumi 550b728e19SAl Viro static int vfat_revalidate_ci(struct dentry *dentry, unsigned int flags) 561b524672SOGAWA Hirofumi { 570b728e19SAl Viro if (flags & LOOKUP_RCU) 5834286d66SNick Piggin return -ECHILD; 5934286d66SNick Piggin 601b524672SOGAWA Hirofumi /* 611b524672SOGAWA Hirofumi * This is not negative dentry. Always valid. 621b524672SOGAWA Hirofumi * 631b524672SOGAWA Hirofumi * Note, rename() to existing directory entry will have ->d_inode, 641b524672SOGAWA Hirofumi * and will use existing name which isn't specified name by user. 651b524672SOGAWA Hirofumi * 661b524672SOGAWA Hirofumi * We may be able to drop this positive dentry here. But dropping 671b524672SOGAWA Hirofumi * positive dentry isn't good idea. So it's unsupported like 681b524672SOGAWA Hirofumi * rename("filename", "FILENAME") for now. 691b524672SOGAWA Hirofumi */ 701b524672SOGAWA Hirofumi if (dentry->d_inode) 711b524672SOGAWA Hirofumi return 1; 721b524672SOGAWA Hirofumi 731b524672SOGAWA Hirofumi /* 741b524672SOGAWA Hirofumi * This may be nfsd (or something), anyway, we can't see the 751b524672SOGAWA Hirofumi * intent of this. So, since this can be for creation, drop it. 761b524672SOGAWA Hirofumi */ 770b728e19SAl Viro if (!flags) 781b524672SOGAWA Hirofumi return 0; 791b524672SOGAWA Hirofumi 801b524672SOGAWA Hirofumi /* 811b524672SOGAWA Hirofumi * Drop the negative dentry, in order to make sure to use the 821b524672SOGAWA Hirofumi * case sensitive name which is specified by user if this is 831b524672SOGAWA Hirofumi * for creation. 841b524672SOGAWA Hirofumi */ 850b728e19SAl Viro if (flags & (LOOKUP_CREATE | LOOKUP_RENAME_TARGET)) 861b524672SOGAWA Hirofumi return 0; 871b524672SOGAWA Hirofumi 881b524672SOGAWA Hirofumi return vfat_revalidate_shortname(dentry); 891b524672SOGAWA Hirofumi } 901b524672SOGAWA Hirofumi 91990e194eSOGAWA Hirofumi /* returns the length of a struct qstr, ignoring trailing dots */ 92621e155aSNick Piggin static unsigned int __vfat_striptail_len(unsigned int len, const char *name) 93990e194eSOGAWA Hirofumi { 94621e155aSNick Piggin while (len && name[len - 1] == '.') 95990e194eSOGAWA Hirofumi len--; 96990e194eSOGAWA Hirofumi return len; 97990e194eSOGAWA Hirofumi } 98990e194eSOGAWA Hirofumi 99621e155aSNick Piggin static unsigned int vfat_striptail_len(const struct qstr *qstr) 100621e155aSNick Piggin { 101621e155aSNick Piggin return __vfat_striptail_len(qstr->len, qstr->name); 102621e155aSNick Piggin } 103621e155aSNick Piggin 104990e194eSOGAWA Hirofumi /* 105990e194eSOGAWA Hirofumi * Compute the hash for the vfat name corresponding to the dentry. 106990e194eSOGAWA Hirofumi * Note: if the name is invalid, we leave the hash code unchanged so 107990e194eSOGAWA Hirofumi * that the existing dentry can be used. The vfat fs routines will 108990e194eSOGAWA Hirofumi * return ENOENT or EINVAL as appropriate. 109990e194eSOGAWA Hirofumi */ 110b1e6a015SNick Piggin static int vfat_hash(const struct dentry *dentry, const struct inode *inode, 111b1e6a015SNick Piggin struct qstr *qstr) 112990e194eSOGAWA Hirofumi { 113990e194eSOGAWA Hirofumi qstr->hash = full_name_hash(qstr->name, vfat_striptail_len(qstr)); 114990e194eSOGAWA Hirofumi return 0; 115990e194eSOGAWA Hirofumi } 116990e194eSOGAWA Hirofumi 117990e194eSOGAWA Hirofumi /* 118990e194eSOGAWA Hirofumi * Compute the hash for the vfat name corresponding to the dentry. 119990e194eSOGAWA Hirofumi * Note: if the name is invalid, we leave the hash code unchanged so 120990e194eSOGAWA Hirofumi * that the existing dentry can be used. The vfat fs routines will 121990e194eSOGAWA Hirofumi * return ENOENT or EINVAL as appropriate. 122990e194eSOGAWA Hirofumi */ 123b1e6a015SNick Piggin static int vfat_hashi(const struct dentry *dentry, const struct inode *inode, 124b1e6a015SNick Piggin struct qstr *qstr) 125990e194eSOGAWA Hirofumi { 126b1e6a015SNick Piggin struct nls_table *t = MSDOS_SB(dentry->d_sb)->nls_io; 127990e194eSOGAWA Hirofumi const unsigned char *name; 128990e194eSOGAWA Hirofumi unsigned int len; 129990e194eSOGAWA Hirofumi unsigned long hash; 130990e194eSOGAWA Hirofumi 131990e194eSOGAWA Hirofumi name = qstr->name; 132990e194eSOGAWA Hirofumi len = vfat_striptail_len(qstr); 133990e194eSOGAWA Hirofumi 134990e194eSOGAWA Hirofumi hash = init_name_hash(); 135990e194eSOGAWA Hirofumi while (len--) 136990e194eSOGAWA Hirofumi hash = partial_name_hash(nls_tolower(t, *name++), hash); 137990e194eSOGAWA Hirofumi qstr->hash = end_name_hash(hash); 138990e194eSOGAWA Hirofumi 139990e194eSOGAWA Hirofumi return 0; 140990e194eSOGAWA Hirofumi } 141990e194eSOGAWA Hirofumi 142990e194eSOGAWA Hirofumi /* 143990e194eSOGAWA Hirofumi * Case insensitive compare of two vfat names. 144990e194eSOGAWA Hirofumi */ 145621e155aSNick Piggin static int vfat_cmpi(const struct dentry *parent, const struct inode *pinode, 146621e155aSNick Piggin const struct dentry *dentry, const struct inode *inode, 147621e155aSNick Piggin unsigned int len, const char *str, const struct qstr *name) 148990e194eSOGAWA Hirofumi { 149621e155aSNick Piggin struct nls_table *t = MSDOS_SB(parent->d_sb)->nls_io; 150990e194eSOGAWA Hirofumi unsigned int alen, blen; 151990e194eSOGAWA Hirofumi 152990e194eSOGAWA Hirofumi /* A filename cannot end in '.' or we treat it like it has none */ 153621e155aSNick Piggin alen = vfat_striptail_len(name); 154621e155aSNick Piggin blen = __vfat_striptail_len(len, str); 155990e194eSOGAWA Hirofumi if (alen == blen) { 156621e155aSNick Piggin if (nls_strnicmp(t, name->name, str, alen) == 0) 157990e194eSOGAWA Hirofumi return 0; 158990e194eSOGAWA Hirofumi } 159990e194eSOGAWA Hirofumi return 1; 160990e194eSOGAWA Hirofumi } 161990e194eSOGAWA Hirofumi 162990e194eSOGAWA Hirofumi /* 163990e194eSOGAWA Hirofumi * Case sensitive compare of two vfat names. 164990e194eSOGAWA Hirofumi */ 165621e155aSNick Piggin static int vfat_cmp(const struct dentry *parent, const struct inode *pinode, 166621e155aSNick Piggin const struct dentry *dentry, const struct inode *inode, 167621e155aSNick Piggin unsigned int len, const char *str, const struct qstr *name) 168990e194eSOGAWA Hirofumi { 169990e194eSOGAWA Hirofumi unsigned int alen, blen; 170990e194eSOGAWA Hirofumi 171990e194eSOGAWA Hirofumi /* A filename cannot end in '.' or we treat it like it has none */ 172621e155aSNick Piggin alen = vfat_striptail_len(name); 173621e155aSNick Piggin blen = __vfat_striptail_len(len, str); 174990e194eSOGAWA Hirofumi if (alen == blen) { 175621e155aSNick Piggin if (strncmp(name->name, str, alen) == 0) 176990e194eSOGAWA Hirofumi return 0; 177990e194eSOGAWA Hirofumi } 178990e194eSOGAWA Hirofumi return 1; 179990e194eSOGAWA Hirofumi } 180990e194eSOGAWA Hirofumi 181ce6cdc47SAl Viro static const struct dentry_operations vfat_ci_dentry_ops = { 1821b524672SOGAWA Hirofumi .d_revalidate = vfat_revalidate_ci, 183990e194eSOGAWA Hirofumi .d_hash = vfat_hashi, 184990e194eSOGAWA Hirofumi .d_compare = vfat_cmpi, 1851b524672SOGAWA Hirofumi }; 1861b524672SOGAWA Hirofumi 187ce6cdc47SAl Viro static const struct dentry_operations vfat_dentry_ops = { 188990e194eSOGAWA Hirofumi .d_revalidate = vfat_revalidate, 189990e194eSOGAWA Hirofumi .d_hash = vfat_hash, 190990e194eSOGAWA Hirofumi .d_compare = vfat_cmp, 191990e194eSOGAWA Hirofumi }; 192990e194eSOGAWA Hirofumi 193990e194eSOGAWA Hirofumi /* Characters that are undesirable in an MS-DOS file name */ 194990e194eSOGAWA Hirofumi 195990e194eSOGAWA Hirofumi static inline wchar_t vfat_bad_char(wchar_t w) 196990e194eSOGAWA Hirofumi { 197990e194eSOGAWA Hirofumi return (w < 0x0020) 198990e194eSOGAWA Hirofumi || (w == '*') || (w == '?') || (w == '<') || (w == '>') 199990e194eSOGAWA Hirofumi || (w == '|') || (w == '"') || (w == ':') || (w == '/') 200990e194eSOGAWA Hirofumi || (w == '\\'); 201990e194eSOGAWA Hirofumi } 202990e194eSOGAWA Hirofumi 203990e194eSOGAWA Hirofumi static inline wchar_t vfat_replace_char(wchar_t w) 204990e194eSOGAWA Hirofumi { 205990e194eSOGAWA Hirofumi return (w == '[') || (w == ']') || (w == ';') || (w == ',') 206990e194eSOGAWA Hirofumi || (w == '+') || (w == '='); 207990e194eSOGAWA Hirofumi } 208990e194eSOGAWA Hirofumi 209990e194eSOGAWA Hirofumi static wchar_t vfat_skip_char(wchar_t w) 210990e194eSOGAWA Hirofumi { 211990e194eSOGAWA Hirofumi return (w == '.') || (w == ' '); 212990e194eSOGAWA Hirofumi } 213990e194eSOGAWA Hirofumi 214990e194eSOGAWA Hirofumi static inline int vfat_is_used_badchars(const wchar_t *s, int len) 215990e194eSOGAWA Hirofumi { 216990e194eSOGAWA Hirofumi int i; 217990e194eSOGAWA Hirofumi 218990e194eSOGAWA Hirofumi for (i = 0; i < len; i++) 219990e194eSOGAWA Hirofumi if (vfat_bad_char(s[i])) 220990e194eSOGAWA Hirofumi return -EINVAL; 221990e194eSOGAWA Hirofumi 222990e194eSOGAWA Hirofumi if (s[i - 1] == ' ') /* last character cannot be space */ 223990e194eSOGAWA Hirofumi return -EINVAL; 224990e194eSOGAWA Hirofumi 225990e194eSOGAWA Hirofumi return 0; 226990e194eSOGAWA Hirofumi } 227990e194eSOGAWA Hirofumi 228990e194eSOGAWA Hirofumi static int vfat_find_form(struct inode *dir, unsigned char *name) 229990e194eSOGAWA Hirofumi { 230990e194eSOGAWA Hirofumi struct fat_slot_info sinfo; 231990e194eSOGAWA Hirofumi int err = fat_scan(dir, name, &sinfo); 232990e194eSOGAWA Hirofumi if (err) 233990e194eSOGAWA Hirofumi return -ENOENT; 234990e194eSOGAWA Hirofumi brelse(sinfo.bh); 235990e194eSOGAWA Hirofumi return 0; 236990e194eSOGAWA Hirofumi } 237990e194eSOGAWA Hirofumi 238990e194eSOGAWA Hirofumi /* 239990e194eSOGAWA Hirofumi * 1) Valid characters for the 8.3 format alias are any combination of 240990e194eSOGAWA Hirofumi * letters, uppercase alphabets, digits, any of the 241990e194eSOGAWA Hirofumi * following special characters: 242990e194eSOGAWA Hirofumi * $ % ' ` - @ { } ~ ! # ( ) & _ ^ 243990e194eSOGAWA Hirofumi * In this case Longfilename is not stored in disk. 244990e194eSOGAWA Hirofumi * 245990e194eSOGAWA Hirofumi * WinNT's Extension: 246990e194eSOGAWA Hirofumi * File name and extension name is contain uppercase/lowercase 247990e194eSOGAWA Hirofumi * only. And it is expressed by CASE_LOWER_BASE and CASE_LOWER_EXT. 248990e194eSOGAWA Hirofumi * 249990e194eSOGAWA Hirofumi * 2) File name is 8.3 format, but it contain the uppercase and 250990e194eSOGAWA Hirofumi * lowercase char, muliti bytes char, etc. In this case numtail is not 251990e194eSOGAWA Hirofumi * added, but Longfilename is stored. 252990e194eSOGAWA Hirofumi * 253990e194eSOGAWA Hirofumi * 3) When the one except for the above, or the following special 254990e194eSOGAWA Hirofumi * character are contained: 255990e194eSOGAWA Hirofumi * . [ ] ; , + = 256990e194eSOGAWA Hirofumi * numtail is added, and Longfilename must be stored in disk . 257990e194eSOGAWA Hirofumi */ 258990e194eSOGAWA Hirofumi struct shortname_info { 259990e194eSOGAWA Hirofumi unsigned char lower:1, 260990e194eSOGAWA Hirofumi upper:1, 261990e194eSOGAWA Hirofumi valid:1; 262990e194eSOGAWA Hirofumi }; 263990e194eSOGAWA Hirofumi #define INIT_SHORTNAME_INFO(x) do { \ 264990e194eSOGAWA Hirofumi (x)->lower = 1; \ 265990e194eSOGAWA Hirofumi (x)->upper = 1; \ 266990e194eSOGAWA Hirofumi (x)->valid = 1; \ 267990e194eSOGAWA Hirofumi } while (0) 268990e194eSOGAWA Hirofumi 269990e194eSOGAWA Hirofumi static inline int to_shortname_char(struct nls_table *nls, 270990e194eSOGAWA Hirofumi unsigned char *buf, int buf_size, 271990e194eSOGAWA Hirofumi wchar_t *src, struct shortname_info *info) 272990e194eSOGAWA Hirofumi { 273990e194eSOGAWA Hirofumi int len; 274990e194eSOGAWA Hirofumi 275990e194eSOGAWA Hirofumi if (vfat_skip_char(*src)) { 276990e194eSOGAWA Hirofumi info->valid = 0; 277990e194eSOGAWA Hirofumi return 0; 278990e194eSOGAWA Hirofumi } 279990e194eSOGAWA Hirofumi if (vfat_replace_char(*src)) { 280990e194eSOGAWA Hirofumi info->valid = 0; 281990e194eSOGAWA Hirofumi buf[0] = '_'; 282990e194eSOGAWA Hirofumi return 1; 283990e194eSOGAWA Hirofumi } 284990e194eSOGAWA Hirofumi 285990e194eSOGAWA Hirofumi len = nls->uni2char(*src, buf, buf_size); 286990e194eSOGAWA Hirofumi if (len <= 0) { 287990e194eSOGAWA Hirofumi info->valid = 0; 288990e194eSOGAWA Hirofumi buf[0] = '_'; 289990e194eSOGAWA Hirofumi len = 1; 290990e194eSOGAWA Hirofumi } else if (len == 1) { 291990e194eSOGAWA Hirofumi unsigned char prev = buf[0]; 292990e194eSOGAWA Hirofumi 293990e194eSOGAWA Hirofumi if (buf[0] >= 0x7F) { 294990e194eSOGAWA Hirofumi info->lower = 0; 295990e194eSOGAWA Hirofumi info->upper = 0; 296990e194eSOGAWA Hirofumi } 297990e194eSOGAWA Hirofumi 298990e194eSOGAWA Hirofumi buf[0] = nls_toupper(nls, buf[0]); 299990e194eSOGAWA Hirofumi if (isalpha(buf[0])) { 300990e194eSOGAWA Hirofumi if (buf[0] == prev) 301990e194eSOGAWA Hirofumi info->lower = 0; 302990e194eSOGAWA Hirofumi else 303990e194eSOGAWA Hirofumi info->upper = 0; 304990e194eSOGAWA Hirofumi } 305990e194eSOGAWA Hirofumi } else { 306990e194eSOGAWA Hirofumi info->lower = 0; 307990e194eSOGAWA Hirofumi info->upper = 0; 308990e194eSOGAWA Hirofumi } 309990e194eSOGAWA Hirofumi 310990e194eSOGAWA Hirofumi return len; 311990e194eSOGAWA Hirofumi } 312990e194eSOGAWA Hirofumi 313990e194eSOGAWA Hirofumi /* 314990e194eSOGAWA Hirofumi * Given a valid longname, create a unique shortname. Make sure the 315990e194eSOGAWA Hirofumi * shortname does not exist 316990e194eSOGAWA Hirofumi * Returns negative number on error, 0 for a normal 317990e194eSOGAWA Hirofumi * return, and 1 for valid shortname 318990e194eSOGAWA Hirofumi */ 319990e194eSOGAWA Hirofumi static int vfat_create_shortname(struct inode *dir, struct nls_table *nls, 320990e194eSOGAWA Hirofumi wchar_t *uname, int ulen, 321990e194eSOGAWA Hirofumi unsigned char *name_res, unsigned char *lcase) 322990e194eSOGAWA Hirofumi { 323990e194eSOGAWA Hirofumi struct fat_mount_options *opts = &MSDOS_SB(dir->i_sb)->options; 324990e194eSOGAWA Hirofumi wchar_t *ip, *ext_start, *end, *name_start; 32530d1872dSNikolaus Schulz unsigned char base[9], ext[4], buf[5], *p; 326990e194eSOGAWA Hirofumi unsigned char charbuf[NLS_MAX_CHARSET_SIZE]; 327990e194eSOGAWA Hirofumi int chl, chi; 328990e194eSOGAWA Hirofumi int sz = 0, extlen, baselen, i, numtail_baselen, numtail2_baselen; 329990e194eSOGAWA Hirofumi int is_shortname; 330990e194eSOGAWA Hirofumi struct shortname_info base_info, ext_info; 331990e194eSOGAWA Hirofumi 332990e194eSOGAWA Hirofumi is_shortname = 1; 333990e194eSOGAWA Hirofumi INIT_SHORTNAME_INFO(&base_info); 334990e194eSOGAWA Hirofumi INIT_SHORTNAME_INFO(&ext_info); 335990e194eSOGAWA Hirofumi 336990e194eSOGAWA Hirofumi /* Now, we need to create a shortname from the long name */ 337990e194eSOGAWA Hirofumi ext_start = end = &uname[ulen]; 338990e194eSOGAWA Hirofumi while (--ext_start >= uname) { 339990e194eSOGAWA Hirofumi if (*ext_start == 0x002E) { /* is `.' */ 340990e194eSOGAWA Hirofumi if (ext_start == end - 1) { 341990e194eSOGAWA Hirofumi sz = ulen; 342990e194eSOGAWA Hirofumi ext_start = NULL; 343990e194eSOGAWA Hirofumi } 344990e194eSOGAWA Hirofumi break; 345990e194eSOGAWA Hirofumi } 346990e194eSOGAWA Hirofumi } 347990e194eSOGAWA Hirofumi 348990e194eSOGAWA Hirofumi if (ext_start == uname - 1) { 349990e194eSOGAWA Hirofumi sz = ulen; 350990e194eSOGAWA Hirofumi ext_start = NULL; 351990e194eSOGAWA Hirofumi } else if (ext_start) { 352990e194eSOGAWA Hirofumi /* 353990e194eSOGAWA Hirofumi * Names which start with a dot could be just 354990e194eSOGAWA Hirofumi * an extension eg. "...test". In this case Win95 355990e194eSOGAWA Hirofumi * uses the extension as the name and sets no extension. 356990e194eSOGAWA Hirofumi */ 357990e194eSOGAWA Hirofumi name_start = &uname[0]; 358990e194eSOGAWA Hirofumi while (name_start < ext_start) { 359990e194eSOGAWA Hirofumi if (!vfat_skip_char(*name_start)) 360990e194eSOGAWA Hirofumi break; 361990e194eSOGAWA Hirofumi name_start++; 362990e194eSOGAWA Hirofumi } 363990e194eSOGAWA Hirofumi if (name_start != ext_start) { 364990e194eSOGAWA Hirofumi sz = ext_start - uname; 365990e194eSOGAWA Hirofumi ext_start++; 366990e194eSOGAWA Hirofumi } else { 367990e194eSOGAWA Hirofumi sz = ulen; 368990e194eSOGAWA Hirofumi ext_start = NULL; 369990e194eSOGAWA Hirofumi } 370990e194eSOGAWA Hirofumi } 371990e194eSOGAWA Hirofumi 372990e194eSOGAWA Hirofumi numtail_baselen = 6; 373990e194eSOGAWA Hirofumi numtail2_baselen = 2; 374990e194eSOGAWA Hirofumi for (baselen = i = 0, p = base, ip = uname; i < sz; i++, ip++) { 375990e194eSOGAWA Hirofumi chl = to_shortname_char(nls, charbuf, sizeof(charbuf), 376990e194eSOGAWA Hirofumi ip, &base_info); 377990e194eSOGAWA Hirofumi if (chl == 0) 378990e194eSOGAWA Hirofumi continue; 379990e194eSOGAWA Hirofumi 380990e194eSOGAWA Hirofumi if (baselen < 2 && (baselen + chl) > 2) 381990e194eSOGAWA Hirofumi numtail2_baselen = baselen; 382990e194eSOGAWA Hirofumi if (baselen < 6 && (baselen + chl) > 6) 383990e194eSOGAWA Hirofumi numtail_baselen = baselen; 384990e194eSOGAWA Hirofumi for (chi = 0; chi < chl; chi++) { 385990e194eSOGAWA Hirofumi *p++ = charbuf[chi]; 386990e194eSOGAWA Hirofumi baselen++; 387990e194eSOGAWA Hirofumi if (baselen >= 8) 388990e194eSOGAWA Hirofumi break; 389990e194eSOGAWA Hirofumi } 390990e194eSOGAWA Hirofumi if (baselen >= 8) { 391990e194eSOGAWA Hirofumi if ((chi < chl - 1) || (ip + 1) - uname < sz) 392990e194eSOGAWA Hirofumi is_shortname = 0; 393990e194eSOGAWA Hirofumi break; 394990e194eSOGAWA Hirofumi } 395990e194eSOGAWA Hirofumi } 396990e194eSOGAWA Hirofumi if (baselen == 0) { 397990e194eSOGAWA Hirofumi return -EINVAL; 398990e194eSOGAWA Hirofumi } 399990e194eSOGAWA Hirofumi 400990e194eSOGAWA Hirofumi extlen = 0; 401990e194eSOGAWA Hirofumi if (ext_start) { 402990e194eSOGAWA Hirofumi for (p = ext, ip = ext_start; extlen < 3 && ip < end; ip++) { 403990e194eSOGAWA Hirofumi chl = to_shortname_char(nls, charbuf, sizeof(charbuf), 404990e194eSOGAWA Hirofumi ip, &ext_info); 405990e194eSOGAWA Hirofumi if (chl == 0) 406990e194eSOGAWA Hirofumi continue; 407990e194eSOGAWA Hirofumi 408990e194eSOGAWA Hirofumi if ((extlen + chl) > 3) { 409990e194eSOGAWA Hirofumi is_shortname = 0; 410990e194eSOGAWA Hirofumi break; 411990e194eSOGAWA Hirofumi } 412990e194eSOGAWA Hirofumi for (chi = 0; chi < chl; chi++) { 413990e194eSOGAWA Hirofumi *p++ = charbuf[chi]; 414990e194eSOGAWA Hirofumi extlen++; 415990e194eSOGAWA Hirofumi } 416990e194eSOGAWA Hirofumi if (extlen >= 3) { 417990e194eSOGAWA Hirofumi if (ip + 1 != end) 418990e194eSOGAWA Hirofumi is_shortname = 0; 419990e194eSOGAWA Hirofumi break; 420990e194eSOGAWA Hirofumi } 421990e194eSOGAWA Hirofumi } 422990e194eSOGAWA Hirofumi } 423990e194eSOGAWA Hirofumi ext[extlen] = '\0'; 424990e194eSOGAWA Hirofumi base[baselen] = '\0'; 425990e194eSOGAWA Hirofumi 426990e194eSOGAWA Hirofumi /* Yes, it can happen. ".\xe5" would do it. */ 427990e194eSOGAWA Hirofumi if (base[0] == DELETED_FLAG) 428990e194eSOGAWA Hirofumi base[0] = 0x05; 429990e194eSOGAWA Hirofumi 430990e194eSOGAWA Hirofumi /* OK, at this point we know that base is not longer than 8 symbols, 431990e194eSOGAWA Hirofumi * ext is not longer than 3, base is nonempty, both don't contain 432990e194eSOGAWA Hirofumi * any bad symbols (lowercase transformed to uppercase). 433990e194eSOGAWA Hirofumi */ 434990e194eSOGAWA Hirofumi 435990e194eSOGAWA Hirofumi memset(name_res, ' ', MSDOS_NAME); 436990e194eSOGAWA Hirofumi memcpy(name_res, base, baselen); 437990e194eSOGAWA Hirofumi memcpy(name_res + 8, ext, extlen); 438990e194eSOGAWA Hirofumi *lcase = 0; 439990e194eSOGAWA Hirofumi if (is_shortname && base_info.valid && ext_info.valid) { 440990e194eSOGAWA Hirofumi if (vfat_find_form(dir, name_res) == 0) 441990e194eSOGAWA Hirofumi return -EEXIST; 442990e194eSOGAWA Hirofumi 443990e194eSOGAWA Hirofumi if (opts->shortname & VFAT_SFN_CREATE_WIN95) { 444990e194eSOGAWA Hirofumi return (base_info.upper && ext_info.upper); 445990e194eSOGAWA Hirofumi } else if (opts->shortname & VFAT_SFN_CREATE_WINNT) { 446990e194eSOGAWA Hirofumi if ((base_info.upper || base_info.lower) && 447990e194eSOGAWA Hirofumi (ext_info.upper || ext_info.lower)) { 448990e194eSOGAWA Hirofumi if (!base_info.upper && base_info.lower) 449990e194eSOGAWA Hirofumi *lcase |= CASE_LOWER_BASE; 450990e194eSOGAWA Hirofumi if (!ext_info.upper && ext_info.lower) 451990e194eSOGAWA Hirofumi *lcase |= CASE_LOWER_EXT; 452990e194eSOGAWA Hirofumi return 1; 453990e194eSOGAWA Hirofumi } 454990e194eSOGAWA Hirofumi return 0; 455990e194eSOGAWA Hirofumi } else { 456990e194eSOGAWA Hirofumi BUG(); 457990e194eSOGAWA Hirofumi } 458990e194eSOGAWA Hirofumi } 459990e194eSOGAWA Hirofumi 460990e194eSOGAWA Hirofumi if (opts->numtail == 0) 461990e194eSOGAWA Hirofumi if (vfat_find_form(dir, name_res) < 0) 462990e194eSOGAWA Hirofumi return 0; 463990e194eSOGAWA Hirofumi 464990e194eSOGAWA Hirofumi /* 465990e194eSOGAWA Hirofumi * Try to find a unique extension. This used to 466990e194eSOGAWA Hirofumi * iterate through all possibilities sequentially, 467990e194eSOGAWA Hirofumi * but that gave extremely bad performance. Windows 468990e194eSOGAWA Hirofumi * only tries a few cases before using random 469990e194eSOGAWA Hirofumi * values for part of the base. 470990e194eSOGAWA Hirofumi */ 471990e194eSOGAWA Hirofumi 472990e194eSOGAWA Hirofumi if (baselen > 6) { 473990e194eSOGAWA Hirofumi baselen = numtail_baselen; 474990e194eSOGAWA Hirofumi name_res[7] = ' '; 475990e194eSOGAWA Hirofumi } 476990e194eSOGAWA Hirofumi name_res[baselen] = '~'; 477990e194eSOGAWA Hirofumi for (i = 1; i < 10; i++) { 478990e194eSOGAWA Hirofumi name_res[baselen + 1] = i + '0'; 479990e194eSOGAWA Hirofumi if (vfat_find_form(dir, name_res) < 0) 480990e194eSOGAWA Hirofumi return 0; 481990e194eSOGAWA Hirofumi } 482990e194eSOGAWA Hirofumi 48330d1872dSNikolaus Schulz i = jiffies; 484990e194eSOGAWA Hirofumi sz = (jiffies >> 16) & 0x7; 485990e194eSOGAWA Hirofumi if (baselen > 2) { 486990e194eSOGAWA Hirofumi baselen = numtail2_baselen; 487990e194eSOGAWA Hirofumi name_res[7] = ' '; 488990e194eSOGAWA Hirofumi } 489990e194eSOGAWA Hirofumi name_res[baselen + 4] = '~'; 490990e194eSOGAWA Hirofumi name_res[baselen + 5] = '1' + sz; 491990e194eSOGAWA Hirofumi while (1) { 49230d1872dSNikolaus Schulz snprintf(buf, sizeof(buf), "%04X", i & 0xffff); 493990e194eSOGAWA Hirofumi memcpy(&name_res[baselen], buf, 4); 494990e194eSOGAWA Hirofumi if (vfat_find_form(dir, name_res) < 0) 495990e194eSOGAWA Hirofumi break; 496990e194eSOGAWA Hirofumi i -= 11; 497990e194eSOGAWA Hirofumi } 498990e194eSOGAWA Hirofumi return 0; 499990e194eSOGAWA Hirofumi } 500990e194eSOGAWA Hirofumi 501990e194eSOGAWA Hirofumi /* Translate a string, including coded sequences into Unicode */ 502990e194eSOGAWA Hirofumi static int 503990e194eSOGAWA Hirofumi xlate_to_uni(const unsigned char *name, int len, unsigned char *outname, 504990e194eSOGAWA Hirofumi int *longlen, int *outlen, int escape, int utf8, 505990e194eSOGAWA Hirofumi struct nls_table *nls) 506990e194eSOGAWA Hirofumi { 507990e194eSOGAWA Hirofumi const unsigned char *ip; 508990e194eSOGAWA Hirofumi unsigned char nc; 509990e194eSOGAWA Hirofumi unsigned char *op; 510990e194eSOGAWA Hirofumi unsigned int ec; 511990e194eSOGAWA Hirofumi int i, k, fill; 512990e194eSOGAWA Hirofumi int charlen; 513990e194eSOGAWA Hirofumi 514990e194eSOGAWA Hirofumi if (utf8) { 5150720a06aSAlan Stern *outlen = utf8s_to_utf16s(name, len, UTF16_HOST_ENDIAN, 5160720a06aSAlan Stern (wchar_t *) outname, FAT_LFN_LEN + 2); 51767638e40SOGAWA Hirofumi if (*outlen < 0) 51867638e40SOGAWA Hirofumi return *outlen; 519eeb5b4aeSKevin Dankwardt else if (*outlen > FAT_LFN_LEN) 520990e194eSOGAWA Hirofumi return -ENAMETOOLONG; 521990e194eSOGAWA Hirofumi 522990e194eSOGAWA Hirofumi op = &outname[*outlen * sizeof(wchar_t)]; 523990e194eSOGAWA Hirofumi } else { 524990e194eSOGAWA Hirofumi for (i = 0, ip = name, op = outname, *outlen = 0; 525d533df07SNamjae Jeon i < len && *outlen < FAT_LFN_LEN; 52641f0c02eSNamjae Jeon *outlen += 1) { 527990e194eSOGAWA Hirofumi if (escape && (*ip == ':')) { 528990e194eSOGAWA Hirofumi if (i > len - 5) 529990e194eSOGAWA Hirofumi return -EINVAL; 530990e194eSOGAWA Hirofumi ec = 0; 531990e194eSOGAWA Hirofumi for (k = 1; k < 5; k++) { 532990e194eSOGAWA Hirofumi nc = ip[k]; 533990e194eSOGAWA Hirofumi ec <<= 4; 534990e194eSOGAWA Hirofumi if (nc >= '0' && nc <= '9') { 535990e194eSOGAWA Hirofumi ec |= nc - '0'; 536990e194eSOGAWA Hirofumi continue; 537990e194eSOGAWA Hirofumi } 538990e194eSOGAWA Hirofumi if (nc >= 'a' && nc <= 'f') { 539990e194eSOGAWA Hirofumi ec |= nc - ('a' - 10); 540990e194eSOGAWA Hirofumi continue; 541990e194eSOGAWA Hirofumi } 542990e194eSOGAWA Hirofumi if (nc >= 'A' && nc <= 'F') { 543990e194eSOGAWA Hirofumi ec |= nc - ('A' - 10); 544990e194eSOGAWA Hirofumi continue; 545990e194eSOGAWA Hirofumi } 546990e194eSOGAWA Hirofumi return -EINVAL; 547990e194eSOGAWA Hirofumi } 548990e194eSOGAWA Hirofumi *op++ = ec & 0xFF; 549990e194eSOGAWA Hirofumi *op++ = ec >> 8; 550990e194eSOGAWA Hirofumi ip += 5; 551990e194eSOGAWA Hirofumi i += 5; 552990e194eSOGAWA Hirofumi } else { 55341f0c02eSNamjae Jeon charlen = nls->char2uni(ip, len - i, 55441f0c02eSNamjae Jeon (wchar_t *)op); 55541f0c02eSNamjae Jeon if (charlen < 0) 556990e194eSOGAWA Hirofumi return -EINVAL; 557990e194eSOGAWA Hirofumi ip += charlen; 558990e194eSOGAWA Hirofumi i += charlen; 559990e194eSOGAWA Hirofumi op += 2; 560990e194eSOGAWA Hirofumi } 561990e194eSOGAWA Hirofumi } 562990e194eSOGAWA Hirofumi if (i < len) 563990e194eSOGAWA Hirofumi return -ENAMETOOLONG; 564990e194eSOGAWA Hirofumi } 565990e194eSOGAWA Hirofumi 566990e194eSOGAWA Hirofumi *longlen = *outlen; 567990e194eSOGAWA Hirofumi if (*outlen % 13) { 568990e194eSOGAWA Hirofumi *op++ = 0; 569990e194eSOGAWA Hirofumi *op++ = 0; 570990e194eSOGAWA Hirofumi *outlen += 1; 571990e194eSOGAWA Hirofumi if (*outlen % 13) { 572990e194eSOGAWA Hirofumi fill = 13 - (*outlen % 13); 573990e194eSOGAWA Hirofumi for (i = 0; i < fill; i++) { 574990e194eSOGAWA Hirofumi *op++ = 0xff; 575990e194eSOGAWA Hirofumi *op++ = 0xff; 576990e194eSOGAWA Hirofumi } 577990e194eSOGAWA Hirofumi *outlen += fill; 578990e194eSOGAWA Hirofumi } 579990e194eSOGAWA Hirofumi } 580990e194eSOGAWA Hirofumi 581990e194eSOGAWA Hirofumi return 0; 582990e194eSOGAWA Hirofumi } 583990e194eSOGAWA Hirofumi 584990e194eSOGAWA Hirofumi static int vfat_build_slots(struct inode *dir, const unsigned char *name, 585990e194eSOGAWA Hirofumi int len, int is_dir, int cluster, 586990e194eSOGAWA Hirofumi struct timespec *ts, 587990e194eSOGAWA Hirofumi struct msdos_dir_slot *slots, int *nr_slots) 588990e194eSOGAWA Hirofumi { 589990e194eSOGAWA Hirofumi struct msdos_sb_info *sbi = MSDOS_SB(dir->i_sb); 590990e194eSOGAWA Hirofumi struct fat_mount_options *opts = &sbi->options; 591990e194eSOGAWA Hirofumi struct msdos_dir_slot *ps; 592990e194eSOGAWA Hirofumi struct msdos_dir_entry *de; 593990e194eSOGAWA Hirofumi unsigned char cksum, lcase; 594990e194eSOGAWA Hirofumi unsigned char msdos_name[MSDOS_NAME]; 595990e194eSOGAWA Hirofumi wchar_t *uname; 596990e194eSOGAWA Hirofumi __le16 time, date; 5977decd1cbSOGAWA Hirofumi u8 time_cs; 598990e194eSOGAWA Hirofumi int err, ulen, usize, i; 599990e194eSOGAWA Hirofumi loff_t offset; 600990e194eSOGAWA Hirofumi 601990e194eSOGAWA Hirofumi *nr_slots = 0; 602990e194eSOGAWA Hirofumi 603990e194eSOGAWA Hirofumi uname = __getname(); 604990e194eSOGAWA Hirofumi if (!uname) 605990e194eSOGAWA Hirofumi return -ENOMEM; 606990e194eSOGAWA Hirofumi 607990e194eSOGAWA Hirofumi err = xlate_to_uni(name, len, (unsigned char *)uname, &ulen, &usize, 608990e194eSOGAWA Hirofumi opts->unicode_xlate, opts->utf8, sbi->nls_io); 609990e194eSOGAWA Hirofumi if (err) 610990e194eSOGAWA Hirofumi goto out_free; 611990e194eSOGAWA Hirofumi 612990e194eSOGAWA Hirofumi err = vfat_is_used_badchars(uname, ulen); 613990e194eSOGAWA Hirofumi if (err) 614990e194eSOGAWA Hirofumi goto out_free; 615990e194eSOGAWA Hirofumi 616990e194eSOGAWA Hirofumi err = vfat_create_shortname(dir, sbi->nls_disk, uname, ulen, 617990e194eSOGAWA Hirofumi msdos_name, &lcase); 618990e194eSOGAWA Hirofumi if (err < 0) 619990e194eSOGAWA Hirofumi goto out_free; 620990e194eSOGAWA Hirofumi else if (err == 1) { 621990e194eSOGAWA Hirofumi de = (struct msdos_dir_entry *)slots; 622990e194eSOGAWA Hirofumi err = 0; 623990e194eSOGAWA Hirofumi goto shortname; 624990e194eSOGAWA Hirofumi } 625990e194eSOGAWA Hirofumi 626990e194eSOGAWA Hirofumi /* build the entry of long file name */ 627990e194eSOGAWA Hirofumi cksum = fat_checksum(msdos_name); 628990e194eSOGAWA Hirofumi 629990e194eSOGAWA Hirofumi *nr_slots = usize / 13; 630990e194eSOGAWA Hirofumi for (ps = slots, i = *nr_slots; i > 0; i--, ps++) { 631990e194eSOGAWA Hirofumi ps->id = i; 632990e194eSOGAWA Hirofumi ps->attr = ATTR_EXT; 633990e194eSOGAWA Hirofumi ps->reserved = 0; 634990e194eSOGAWA Hirofumi ps->alias_checksum = cksum; 635990e194eSOGAWA Hirofumi ps->start = 0; 636990e194eSOGAWA Hirofumi offset = (i - 1) * 13; 637990e194eSOGAWA Hirofumi fatwchar_to16(ps->name0_4, uname + offset, 5); 638990e194eSOGAWA Hirofumi fatwchar_to16(ps->name5_10, uname + offset + 5, 6); 639990e194eSOGAWA Hirofumi fatwchar_to16(ps->name11_12, uname + offset + 11, 2); 640990e194eSOGAWA Hirofumi } 641990e194eSOGAWA Hirofumi slots[0].id |= 0x40; 642990e194eSOGAWA Hirofumi de = (struct msdos_dir_entry *)ps; 643990e194eSOGAWA Hirofumi 644990e194eSOGAWA Hirofumi shortname: 645990e194eSOGAWA Hirofumi /* build the entry of 8.3 alias name */ 646990e194eSOGAWA Hirofumi (*nr_slots)++; 647990e194eSOGAWA Hirofumi memcpy(de->name, msdos_name, MSDOS_NAME); 648990e194eSOGAWA Hirofumi de->attr = is_dir ? ATTR_DIR : ATTR_ARCH; 649990e194eSOGAWA Hirofumi de->lcase = lcase; 6507decd1cbSOGAWA Hirofumi fat_time_unix2fat(sbi, ts, &time, &date, &time_cs); 651990e194eSOGAWA Hirofumi de->time = de->ctime = time; 652990e194eSOGAWA Hirofumi de->date = de->cdate = de->adate = date; 6537decd1cbSOGAWA Hirofumi de->ctime_cs = time_cs; 654a943ed71SSteven J. Magnani fat_set_start(de, cluster); 655990e194eSOGAWA Hirofumi de->size = 0; 656990e194eSOGAWA Hirofumi out_free: 657990e194eSOGAWA Hirofumi __putname(uname); 658990e194eSOGAWA Hirofumi return err; 659990e194eSOGAWA Hirofumi } 660990e194eSOGAWA Hirofumi 661990e194eSOGAWA Hirofumi static int vfat_add_entry(struct inode *dir, struct qstr *qname, int is_dir, 662990e194eSOGAWA Hirofumi int cluster, struct timespec *ts, 663990e194eSOGAWA Hirofumi struct fat_slot_info *sinfo) 664990e194eSOGAWA Hirofumi { 665990e194eSOGAWA Hirofumi struct msdos_dir_slot *slots; 666990e194eSOGAWA Hirofumi unsigned int len; 667990e194eSOGAWA Hirofumi int err, nr_slots; 668990e194eSOGAWA Hirofumi 669990e194eSOGAWA Hirofumi len = vfat_striptail_len(qname); 670990e194eSOGAWA Hirofumi if (len == 0) 671990e194eSOGAWA Hirofumi return -ENOENT; 672990e194eSOGAWA Hirofumi 673990e194eSOGAWA Hirofumi slots = kmalloc(sizeof(*slots) * MSDOS_SLOTS, GFP_NOFS); 674990e194eSOGAWA Hirofumi if (slots == NULL) 675990e194eSOGAWA Hirofumi return -ENOMEM; 676990e194eSOGAWA Hirofumi 677990e194eSOGAWA Hirofumi err = vfat_build_slots(dir, qname->name, len, is_dir, cluster, ts, 678990e194eSOGAWA Hirofumi slots, &nr_slots); 679990e194eSOGAWA Hirofumi if (err) 680990e194eSOGAWA Hirofumi goto cleanup; 681990e194eSOGAWA Hirofumi 682990e194eSOGAWA Hirofumi err = fat_add_entries(dir, slots, nr_slots, sinfo); 683990e194eSOGAWA Hirofumi if (err) 684990e194eSOGAWA Hirofumi goto cleanup; 685990e194eSOGAWA Hirofumi 686990e194eSOGAWA Hirofumi /* update timestamp */ 687990e194eSOGAWA Hirofumi dir->i_ctime = dir->i_mtime = dir->i_atime = *ts; 688990e194eSOGAWA Hirofumi if (IS_DIRSYNC(dir)) 689990e194eSOGAWA Hirofumi (void)fat_sync_inode(dir); 690990e194eSOGAWA Hirofumi else 691990e194eSOGAWA Hirofumi mark_inode_dirty(dir); 692990e194eSOGAWA Hirofumi cleanup: 693990e194eSOGAWA Hirofumi kfree(slots); 694990e194eSOGAWA Hirofumi return err; 695990e194eSOGAWA Hirofumi } 696990e194eSOGAWA Hirofumi 697990e194eSOGAWA Hirofumi static int vfat_find(struct inode *dir, struct qstr *qname, 698990e194eSOGAWA Hirofumi struct fat_slot_info *sinfo) 699990e194eSOGAWA Hirofumi { 700990e194eSOGAWA Hirofumi unsigned int len = vfat_striptail_len(qname); 701990e194eSOGAWA Hirofumi if (len == 0) 702990e194eSOGAWA Hirofumi return -ENOENT; 703990e194eSOGAWA Hirofumi return fat_search_long(dir, qname->name, len, sinfo); 704990e194eSOGAWA Hirofumi } 705990e194eSOGAWA Hirofumi 7068045e298SOGAWA Hirofumi /* 7078045e298SOGAWA Hirofumi * (nfsd's) anonymous disconnected dentry? 7088045e298SOGAWA Hirofumi * NOTE: !IS_ROOT() is not anonymous (I.e. d_splice_alias() did the job). 7098045e298SOGAWA Hirofumi */ 7108045e298SOGAWA Hirofumi static int vfat_d_anon_disconn(struct dentry *dentry) 7118045e298SOGAWA Hirofumi { 7128045e298SOGAWA Hirofumi return IS_ROOT(dentry) && (dentry->d_flags & DCACHE_DISCONNECTED); 7138045e298SOGAWA Hirofumi } 7148045e298SOGAWA Hirofumi 715990e194eSOGAWA Hirofumi static struct dentry *vfat_lookup(struct inode *dir, struct dentry *dentry, 71600cd8dd3SAl Viro unsigned int flags) 717990e194eSOGAWA Hirofumi { 718990e194eSOGAWA Hirofumi struct super_block *sb = dir->i_sb; 719990e194eSOGAWA Hirofumi struct fat_slot_info sinfo; 720068f5ae0SOGAWA Hirofumi struct inode *inode; 721990e194eSOGAWA Hirofumi struct dentry *alias; 7221b524672SOGAWA Hirofumi int err; 723990e194eSOGAWA Hirofumi 724e40b34c7SMarco Stornelli mutex_lock(&MSDOS_SB(sb)->s_lock); 725990e194eSOGAWA Hirofumi 726990e194eSOGAWA Hirofumi err = vfat_find(dir, &dentry->d_name, &sinfo); 727990e194eSOGAWA Hirofumi if (err) { 728068f5ae0SOGAWA Hirofumi if (err == -ENOENT) { 729068f5ae0SOGAWA Hirofumi inode = NULL; 730068f5ae0SOGAWA Hirofumi goto out; 731068f5ae0SOGAWA Hirofumi } 732990e194eSOGAWA Hirofumi goto error; 733990e194eSOGAWA Hirofumi } 7341b524672SOGAWA Hirofumi 735990e194eSOGAWA Hirofumi inode = fat_build_inode(sb, sinfo.de, sinfo.i_pos); 736990e194eSOGAWA Hirofumi brelse(sinfo.bh); 737990e194eSOGAWA Hirofumi if (IS_ERR(inode)) { 738068f5ae0SOGAWA Hirofumi err = PTR_ERR(inode); 739068f5ae0SOGAWA Hirofumi goto error; 740990e194eSOGAWA Hirofumi } 7411b524672SOGAWA Hirofumi 742990e194eSOGAWA Hirofumi alias = d_find_alias(inode); 7438045e298SOGAWA Hirofumi if (alias && !vfat_d_anon_disconn(alias)) { 7441b524672SOGAWA Hirofumi /* 7458045e298SOGAWA Hirofumi * This inode has non anonymous-DCACHE_DISCONNECTED 7468045e298SOGAWA Hirofumi * dentry. This means, the user did ->lookup() by an 7478045e298SOGAWA Hirofumi * another name (longname vs 8.3 alias of it) in past. 7481b524672SOGAWA Hirofumi * 7491b524672SOGAWA Hirofumi * Switch to new one for reason of locality if possible. 7501b524672SOGAWA Hirofumi */ 7511c13a243SOGAWA Hirofumi BUG_ON(d_unhashed(alias)); 7521c13a243SOGAWA Hirofumi if (!S_ISDIR(inode->i_mode)) 7531c13a243SOGAWA Hirofumi d_move(alias, dentry); 754990e194eSOGAWA Hirofumi iput(inode); 755e40b34c7SMarco Stornelli mutex_unlock(&MSDOS_SB(sb)->s_lock); 756990e194eSOGAWA Hirofumi return alias; 7578045e298SOGAWA Hirofumi } else 7588045e298SOGAWA Hirofumi dput(alias); 7598045e298SOGAWA Hirofumi 760068f5ae0SOGAWA Hirofumi out: 761e40b34c7SMarco Stornelli mutex_unlock(&MSDOS_SB(sb)->s_lock); 762990e194eSOGAWA Hirofumi dentry->d_time = dentry->d_parent->d_inode->i_version; 763990e194eSOGAWA Hirofumi dentry = d_splice_alias(inode, dentry); 7643d23985dSAl Viro if (dentry) 765990e194eSOGAWA Hirofumi dentry->d_time = dentry->d_parent->d_inode->i_version; 766990e194eSOGAWA Hirofumi return dentry; 767068f5ae0SOGAWA Hirofumi 768068f5ae0SOGAWA Hirofumi error: 769e40b34c7SMarco Stornelli mutex_unlock(&MSDOS_SB(sb)->s_lock); 770068f5ae0SOGAWA Hirofumi return ERR_PTR(err); 771990e194eSOGAWA Hirofumi } 772990e194eSOGAWA Hirofumi 7734acdaf27SAl Viro static int vfat_create(struct inode *dir, struct dentry *dentry, umode_t mode, 774ebfc3b49SAl Viro bool excl) 775990e194eSOGAWA Hirofumi { 776990e194eSOGAWA Hirofumi struct super_block *sb = dir->i_sb; 777990e194eSOGAWA Hirofumi struct inode *inode; 778990e194eSOGAWA Hirofumi struct fat_slot_info sinfo; 779990e194eSOGAWA Hirofumi struct timespec ts; 780990e194eSOGAWA Hirofumi int err; 781990e194eSOGAWA Hirofumi 782e40b34c7SMarco Stornelli mutex_lock(&MSDOS_SB(sb)->s_lock); 783990e194eSOGAWA Hirofumi 784990e194eSOGAWA Hirofumi ts = CURRENT_TIME_SEC; 785990e194eSOGAWA Hirofumi err = vfat_add_entry(dir, &dentry->d_name, 0, 0, &ts, &sinfo); 786990e194eSOGAWA Hirofumi if (err) 787990e194eSOGAWA Hirofumi goto out; 788990e194eSOGAWA Hirofumi dir->i_version++; 789990e194eSOGAWA Hirofumi 790990e194eSOGAWA Hirofumi inode = fat_build_inode(sb, sinfo.de, sinfo.i_pos); 791990e194eSOGAWA Hirofumi brelse(sinfo.bh); 792990e194eSOGAWA Hirofumi if (IS_ERR(inode)) { 793990e194eSOGAWA Hirofumi err = PTR_ERR(inode); 794990e194eSOGAWA Hirofumi goto out; 795990e194eSOGAWA Hirofumi } 796990e194eSOGAWA Hirofumi inode->i_version++; 797990e194eSOGAWA Hirofumi inode->i_mtime = inode->i_atime = inode->i_ctime = ts; 798990e194eSOGAWA Hirofumi /* timestamp is already written, so mark_inode_dirty() is unneeded. */ 799990e194eSOGAWA Hirofumi 800990e194eSOGAWA Hirofumi dentry->d_time = dentry->d_parent->d_inode->i_version; 801990e194eSOGAWA Hirofumi d_instantiate(dentry, inode); 802990e194eSOGAWA Hirofumi out: 803e40b34c7SMarco Stornelli mutex_unlock(&MSDOS_SB(sb)->s_lock); 804990e194eSOGAWA Hirofumi return err; 805990e194eSOGAWA Hirofumi } 806990e194eSOGAWA Hirofumi 807990e194eSOGAWA Hirofumi static int vfat_rmdir(struct inode *dir, struct dentry *dentry) 808990e194eSOGAWA Hirofumi { 809990e194eSOGAWA Hirofumi struct inode *inode = dentry->d_inode; 810990e194eSOGAWA Hirofumi struct super_block *sb = dir->i_sb; 811990e194eSOGAWA Hirofumi struct fat_slot_info sinfo; 812990e194eSOGAWA Hirofumi int err; 813990e194eSOGAWA Hirofumi 814e40b34c7SMarco Stornelli mutex_lock(&MSDOS_SB(sb)->s_lock); 815990e194eSOGAWA Hirofumi 816990e194eSOGAWA Hirofumi err = fat_dir_empty(inode); 817990e194eSOGAWA Hirofumi if (err) 818990e194eSOGAWA Hirofumi goto out; 819990e194eSOGAWA Hirofumi err = vfat_find(dir, &dentry->d_name, &sinfo); 820990e194eSOGAWA Hirofumi if (err) 821990e194eSOGAWA Hirofumi goto out; 822990e194eSOGAWA Hirofumi 823990e194eSOGAWA Hirofumi err = fat_remove_entries(dir, &sinfo); /* and releases bh */ 824990e194eSOGAWA Hirofumi if (err) 825990e194eSOGAWA Hirofumi goto out; 826990e194eSOGAWA Hirofumi drop_nlink(dir); 827990e194eSOGAWA Hirofumi 828990e194eSOGAWA Hirofumi clear_nlink(inode); 829990e194eSOGAWA Hirofumi inode->i_mtime = inode->i_atime = CURRENT_TIME_SEC; 830990e194eSOGAWA Hirofumi fat_detach(inode); 831990e194eSOGAWA Hirofumi out: 832e40b34c7SMarco Stornelli mutex_unlock(&MSDOS_SB(sb)->s_lock); 833990e194eSOGAWA Hirofumi 834990e194eSOGAWA Hirofumi return err; 835990e194eSOGAWA Hirofumi } 836990e194eSOGAWA Hirofumi 837990e194eSOGAWA Hirofumi static int vfat_unlink(struct inode *dir, struct dentry *dentry) 838990e194eSOGAWA Hirofumi { 839990e194eSOGAWA Hirofumi struct inode *inode = dentry->d_inode; 840990e194eSOGAWA Hirofumi struct super_block *sb = dir->i_sb; 841990e194eSOGAWA Hirofumi struct fat_slot_info sinfo; 842990e194eSOGAWA Hirofumi int err; 843990e194eSOGAWA Hirofumi 844e40b34c7SMarco Stornelli mutex_lock(&MSDOS_SB(sb)->s_lock); 845990e194eSOGAWA Hirofumi 846990e194eSOGAWA Hirofumi err = vfat_find(dir, &dentry->d_name, &sinfo); 847990e194eSOGAWA Hirofumi if (err) 848990e194eSOGAWA Hirofumi goto out; 849990e194eSOGAWA Hirofumi 850990e194eSOGAWA Hirofumi err = fat_remove_entries(dir, &sinfo); /* and releases bh */ 851990e194eSOGAWA Hirofumi if (err) 852990e194eSOGAWA Hirofumi goto out; 853990e194eSOGAWA Hirofumi clear_nlink(inode); 854990e194eSOGAWA Hirofumi inode->i_mtime = inode->i_atime = CURRENT_TIME_SEC; 855990e194eSOGAWA Hirofumi fat_detach(inode); 856990e194eSOGAWA Hirofumi out: 857e40b34c7SMarco Stornelli mutex_unlock(&MSDOS_SB(sb)->s_lock); 858990e194eSOGAWA Hirofumi 859990e194eSOGAWA Hirofumi return err; 860990e194eSOGAWA Hirofumi } 861990e194eSOGAWA Hirofumi 86218bb1db3SAl Viro static int vfat_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) 863990e194eSOGAWA Hirofumi { 864990e194eSOGAWA Hirofumi struct super_block *sb = dir->i_sb; 865990e194eSOGAWA Hirofumi struct inode *inode; 866990e194eSOGAWA Hirofumi struct fat_slot_info sinfo; 867990e194eSOGAWA Hirofumi struct timespec ts; 868990e194eSOGAWA Hirofumi int err, cluster; 869990e194eSOGAWA Hirofumi 870e40b34c7SMarco Stornelli mutex_lock(&MSDOS_SB(sb)->s_lock); 871990e194eSOGAWA Hirofumi 872990e194eSOGAWA Hirofumi ts = CURRENT_TIME_SEC; 873990e194eSOGAWA Hirofumi cluster = fat_alloc_new_dir(dir, &ts); 874990e194eSOGAWA Hirofumi if (cluster < 0) { 875990e194eSOGAWA Hirofumi err = cluster; 876990e194eSOGAWA Hirofumi goto out; 877990e194eSOGAWA Hirofumi } 878990e194eSOGAWA Hirofumi err = vfat_add_entry(dir, &dentry->d_name, 1, cluster, &ts, &sinfo); 879990e194eSOGAWA Hirofumi if (err) 880990e194eSOGAWA Hirofumi goto out_free; 881990e194eSOGAWA Hirofumi dir->i_version++; 882990e194eSOGAWA Hirofumi inc_nlink(dir); 883990e194eSOGAWA Hirofumi 884990e194eSOGAWA Hirofumi inode = fat_build_inode(sb, sinfo.de, sinfo.i_pos); 885990e194eSOGAWA Hirofumi brelse(sinfo.bh); 886990e194eSOGAWA Hirofumi if (IS_ERR(inode)) { 887990e194eSOGAWA Hirofumi err = PTR_ERR(inode); 888990e194eSOGAWA Hirofumi /* the directory was completed, just return a error */ 889990e194eSOGAWA Hirofumi goto out; 890990e194eSOGAWA Hirofumi } 891990e194eSOGAWA Hirofumi inode->i_version++; 892bfe86848SMiklos Szeredi set_nlink(inode, 2); 893990e194eSOGAWA Hirofumi inode->i_mtime = inode->i_atime = inode->i_ctime = ts; 894990e194eSOGAWA Hirofumi /* timestamp is already written, so mark_inode_dirty() is unneeded. */ 895990e194eSOGAWA Hirofumi 896990e194eSOGAWA Hirofumi dentry->d_time = dentry->d_parent->d_inode->i_version; 897990e194eSOGAWA Hirofumi d_instantiate(dentry, inode); 898990e194eSOGAWA Hirofumi 899e40b34c7SMarco Stornelli mutex_unlock(&MSDOS_SB(sb)->s_lock); 900990e194eSOGAWA Hirofumi return 0; 901990e194eSOGAWA Hirofumi 902990e194eSOGAWA Hirofumi out_free: 903990e194eSOGAWA Hirofumi fat_free_clusters(dir, cluster); 904990e194eSOGAWA Hirofumi out: 905e40b34c7SMarco Stornelli mutex_unlock(&MSDOS_SB(sb)->s_lock); 906990e194eSOGAWA Hirofumi return err; 907990e194eSOGAWA Hirofumi } 908990e194eSOGAWA Hirofumi 909990e194eSOGAWA Hirofumi static int vfat_rename(struct inode *old_dir, struct dentry *old_dentry, 910990e194eSOGAWA Hirofumi struct inode *new_dir, struct dentry *new_dentry) 911990e194eSOGAWA Hirofumi { 912990e194eSOGAWA Hirofumi struct buffer_head *dotdot_bh; 913990e194eSOGAWA Hirofumi struct msdos_dir_entry *dotdot_de; 914990e194eSOGAWA Hirofumi struct inode *old_inode, *new_inode; 915990e194eSOGAWA Hirofumi struct fat_slot_info old_sinfo, sinfo; 916990e194eSOGAWA Hirofumi struct timespec ts; 9177669e8fbSSteven J. Magnani loff_t new_i_pos; 918990e194eSOGAWA Hirofumi int err, is_dir, update_dotdot, corrupt = 0; 919990e194eSOGAWA Hirofumi struct super_block *sb = old_dir->i_sb; 920990e194eSOGAWA Hirofumi 921990e194eSOGAWA Hirofumi old_sinfo.bh = sinfo.bh = dotdot_bh = NULL; 922990e194eSOGAWA Hirofumi old_inode = old_dentry->d_inode; 923990e194eSOGAWA Hirofumi new_inode = new_dentry->d_inode; 924e40b34c7SMarco Stornelli mutex_lock(&MSDOS_SB(sb)->s_lock); 925990e194eSOGAWA Hirofumi err = vfat_find(old_dir, &old_dentry->d_name, &old_sinfo); 926990e194eSOGAWA Hirofumi if (err) 927990e194eSOGAWA Hirofumi goto out; 928990e194eSOGAWA Hirofumi 929990e194eSOGAWA Hirofumi is_dir = S_ISDIR(old_inode->i_mode); 930990e194eSOGAWA Hirofumi update_dotdot = (is_dir && old_dir != new_dir); 931990e194eSOGAWA Hirofumi if (update_dotdot) { 9327669e8fbSSteven J. Magnani if (fat_get_dotdot_entry(old_inode, &dotdot_bh, &dotdot_de)) { 933990e194eSOGAWA Hirofumi err = -EIO; 934990e194eSOGAWA Hirofumi goto out; 935990e194eSOGAWA Hirofumi } 936990e194eSOGAWA Hirofumi } 937990e194eSOGAWA Hirofumi 938990e194eSOGAWA Hirofumi ts = CURRENT_TIME_SEC; 939990e194eSOGAWA Hirofumi if (new_inode) { 940990e194eSOGAWA Hirofumi if (is_dir) { 941990e194eSOGAWA Hirofumi err = fat_dir_empty(new_inode); 942990e194eSOGAWA Hirofumi if (err) 943990e194eSOGAWA Hirofumi goto out; 944990e194eSOGAWA Hirofumi } 945990e194eSOGAWA Hirofumi new_i_pos = MSDOS_I(new_inode)->i_pos; 946990e194eSOGAWA Hirofumi fat_detach(new_inode); 947990e194eSOGAWA Hirofumi } else { 948990e194eSOGAWA Hirofumi err = vfat_add_entry(new_dir, &new_dentry->d_name, is_dir, 0, 949990e194eSOGAWA Hirofumi &ts, &sinfo); 950990e194eSOGAWA Hirofumi if (err) 951990e194eSOGAWA Hirofumi goto out; 952990e194eSOGAWA Hirofumi new_i_pos = sinfo.i_pos; 953990e194eSOGAWA Hirofumi } 954990e194eSOGAWA Hirofumi new_dir->i_version++; 955990e194eSOGAWA Hirofumi 956990e194eSOGAWA Hirofumi fat_detach(old_inode); 957990e194eSOGAWA Hirofumi fat_attach(old_inode, new_i_pos); 958990e194eSOGAWA Hirofumi if (IS_DIRSYNC(new_dir)) { 959990e194eSOGAWA Hirofumi err = fat_sync_inode(old_inode); 960990e194eSOGAWA Hirofumi if (err) 961990e194eSOGAWA Hirofumi goto error_inode; 962990e194eSOGAWA Hirofumi } else 963990e194eSOGAWA Hirofumi mark_inode_dirty(old_inode); 964990e194eSOGAWA Hirofumi 965990e194eSOGAWA Hirofumi if (update_dotdot) { 966a943ed71SSteven J. Magnani fat_set_start(dotdot_de, MSDOS_I(new_dir)->i_logstart); 967b522412aSAl Viro mark_buffer_dirty_inode(dotdot_bh, old_inode); 968990e194eSOGAWA Hirofumi if (IS_DIRSYNC(new_dir)) { 969990e194eSOGAWA Hirofumi err = sync_dirty_buffer(dotdot_bh); 970990e194eSOGAWA Hirofumi if (err) 971990e194eSOGAWA Hirofumi goto error_dotdot; 972990e194eSOGAWA Hirofumi } 973990e194eSOGAWA Hirofumi drop_nlink(old_dir); 974990e194eSOGAWA Hirofumi if (!new_inode) 975990e194eSOGAWA Hirofumi inc_nlink(new_dir); 976990e194eSOGAWA Hirofumi } 977990e194eSOGAWA Hirofumi 978990e194eSOGAWA Hirofumi err = fat_remove_entries(old_dir, &old_sinfo); /* and releases bh */ 979990e194eSOGAWA Hirofumi old_sinfo.bh = NULL; 980990e194eSOGAWA Hirofumi if (err) 981990e194eSOGAWA Hirofumi goto error_dotdot; 982990e194eSOGAWA Hirofumi old_dir->i_version++; 983990e194eSOGAWA Hirofumi old_dir->i_ctime = old_dir->i_mtime = ts; 984990e194eSOGAWA Hirofumi if (IS_DIRSYNC(old_dir)) 985990e194eSOGAWA Hirofumi (void)fat_sync_inode(old_dir); 986990e194eSOGAWA Hirofumi else 987990e194eSOGAWA Hirofumi mark_inode_dirty(old_dir); 988990e194eSOGAWA Hirofumi 989990e194eSOGAWA Hirofumi if (new_inode) { 990990e194eSOGAWA Hirofumi drop_nlink(new_inode); 991990e194eSOGAWA Hirofumi if (is_dir) 992990e194eSOGAWA Hirofumi drop_nlink(new_inode); 993990e194eSOGAWA Hirofumi new_inode->i_ctime = ts; 994990e194eSOGAWA Hirofumi } 995990e194eSOGAWA Hirofumi out: 996990e194eSOGAWA Hirofumi brelse(sinfo.bh); 997990e194eSOGAWA Hirofumi brelse(dotdot_bh); 998990e194eSOGAWA Hirofumi brelse(old_sinfo.bh); 999e40b34c7SMarco Stornelli mutex_unlock(&MSDOS_SB(sb)->s_lock); 1000990e194eSOGAWA Hirofumi 1001990e194eSOGAWA Hirofumi return err; 1002990e194eSOGAWA Hirofumi 1003990e194eSOGAWA Hirofumi error_dotdot: 1004990e194eSOGAWA Hirofumi /* data cluster is shared, serious corruption */ 1005990e194eSOGAWA Hirofumi corrupt = 1; 1006990e194eSOGAWA Hirofumi 1007990e194eSOGAWA Hirofumi if (update_dotdot) { 1008a943ed71SSteven J. Magnani fat_set_start(dotdot_de, MSDOS_I(old_dir)->i_logstart); 1009b522412aSAl Viro mark_buffer_dirty_inode(dotdot_bh, old_inode); 1010990e194eSOGAWA Hirofumi corrupt |= sync_dirty_buffer(dotdot_bh); 1011990e194eSOGAWA Hirofumi } 1012990e194eSOGAWA Hirofumi error_inode: 1013990e194eSOGAWA Hirofumi fat_detach(old_inode); 1014990e194eSOGAWA Hirofumi fat_attach(old_inode, old_sinfo.i_pos); 1015990e194eSOGAWA Hirofumi if (new_inode) { 1016990e194eSOGAWA Hirofumi fat_attach(new_inode, new_i_pos); 1017990e194eSOGAWA Hirofumi if (corrupt) 1018990e194eSOGAWA Hirofumi corrupt |= fat_sync_inode(new_inode); 1019990e194eSOGAWA Hirofumi } else { 1020990e194eSOGAWA Hirofumi /* 1021990e194eSOGAWA Hirofumi * If new entry was not sharing the data cluster, it 1022990e194eSOGAWA Hirofumi * shouldn't be serious corruption. 1023990e194eSOGAWA Hirofumi */ 1024990e194eSOGAWA Hirofumi int err2 = fat_remove_entries(new_dir, &sinfo); 1025990e194eSOGAWA Hirofumi if (corrupt) 1026990e194eSOGAWA Hirofumi corrupt |= err2; 1027990e194eSOGAWA Hirofumi sinfo.bh = NULL; 1028990e194eSOGAWA Hirofumi } 1029990e194eSOGAWA Hirofumi if (corrupt < 0) { 103085c78591SDenis Karpov fat_fs_error(new_dir->i_sb, 1031990e194eSOGAWA Hirofumi "%s: Filesystem corrupted (i_pos %lld)", 1032990e194eSOGAWA Hirofumi __func__, sinfo.i_pos); 1033990e194eSOGAWA Hirofumi } 1034990e194eSOGAWA Hirofumi goto out; 1035990e194eSOGAWA Hirofumi } 1036990e194eSOGAWA Hirofumi 1037990e194eSOGAWA Hirofumi static const struct inode_operations vfat_dir_inode_operations = { 1038990e194eSOGAWA Hirofumi .create = vfat_create, 1039990e194eSOGAWA Hirofumi .lookup = vfat_lookup, 1040990e194eSOGAWA Hirofumi .unlink = vfat_unlink, 1041990e194eSOGAWA Hirofumi .mkdir = vfat_mkdir, 1042990e194eSOGAWA Hirofumi .rmdir = vfat_rmdir, 1043990e194eSOGAWA Hirofumi .rename = vfat_rename, 1044990e194eSOGAWA Hirofumi .setattr = fat_setattr, 1045990e194eSOGAWA Hirofumi .getattr = fat_getattr, 1046990e194eSOGAWA Hirofumi }; 1047990e194eSOGAWA Hirofumi 10483d23985dSAl Viro static void setup(struct super_block *sb) 1049990e194eSOGAWA Hirofumi { 1050384f5c96SOGAWA Hirofumi MSDOS_SB(sb)->dir_ops = &vfat_dir_inode_operations; 10513d23985dSAl Viro if (MSDOS_SB(sb)->options.name_check != 's') 10523d23985dSAl Viro sb->s_d_op = &vfat_ci_dentry_ops; 10533d23985dSAl Viro else 10543d23985dSAl Viro sb->s_d_op = &vfat_dentry_ops; 1055db719222SJan Blunck } 1056990e194eSOGAWA Hirofumi 10573d23985dSAl Viro static int vfat_fill_super(struct super_block *sb, void *data, int silent) 10583d23985dSAl Viro { 1059384f5c96SOGAWA Hirofumi return fat_fill_super(sb, data, silent, 1, setup); 1060990e194eSOGAWA Hirofumi } 1061990e194eSOGAWA Hirofumi 1062152a0836SAl Viro static struct dentry *vfat_mount(struct file_system_type *fs_type, 1063990e194eSOGAWA Hirofumi int flags, const char *dev_name, 1064152a0836SAl Viro void *data) 1065990e194eSOGAWA Hirofumi { 1066152a0836SAl Viro return mount_bdev(fs_type, flags, dev_name, data, vfat_fill_super); 1067990e194eSOGAWA Hirofumi } 1068990e194eSOGAWA Hirofumi 1069990e194eSOGAWA Hirofumi static struct file_system_type vfat_fs_type = { 1070990e194eSOGAWA Hirofumi .owner = THIS_MODULE, 1071990e194eSOGAWA Hirofumi .name = "vfat", 1072152a0836SAl Viro .mount = vfat_mount, 1073990e194eSOGAWA Hirofumi .kill_sb = kill_block_super, 1074990e194eSOGAWA Hirofumi .fs_flags = FS_REQUIRES_DEV, 1075990e194eSOGAWA Hirofumi }; 1076*7f78e035SEric W. Biederman MODULE_ALIAS_FS("vfat"); 1077990e194eSOGAWA Hirofumi 1078990e194eSOGAWA Hirofumi static int __init init_vfat_fs(void) 1079990e194eSOGAWA Hirofumi { 1080990e194eSOGAWA Hirofumi return register_filesystem(&vfat_fs_type); 1081990e194eSOGAWA Hirofumi } 1082990e194eSOGAWA Hirofumi 1083990e194eSOGAWA Hirofumi static void __exit exit_vfat_fs(void) 1084990e194eSOGAWA Hirofumi { 1085990e194eSOGAWA Hirofumi unregister_filesystem(&vfat_fs_type); 1086990e194eSOGAWA Hirofumi } 1087990e194eSOGAWA Hirofumi 1088990e194eSOGAWA Hirofumi MODULE_LICENSE("GPL"); 1089990e194eSOGAWA Hirofumi MODULE_DESCRIPTION("VFAT filesystem support"); 1090990e194eSOGAWA Hirofumi MODULE_AUTHOR("Gordon Chaffee"); 1091990e194eSOGAWA Hirofumi 1092990e194eSOGAWA Hirofumi module_init(init_vfat_fs) 1093990e194eSOGAWA Hirofumi module_exit(exit_vfat_fs) 1094