09c434b8a0047 fs/fat/namei_vfat.c (Thomas Gleixner 2019-05-19 13:08:20 +0100 1) // SPDX-License-Identifier: GPL-2.0-only
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 2) /*
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 3) * linux/fs/vfat/namei.c
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 4) *
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 5) * Written 1992,1993 by Werner Almesberger
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 6) *
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 7) * Windows95/Windows NT compatible extended MSDOS filesystem
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 8) * by Gordon Chaffee Copyright (C) 1995. Send bug reports for the
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 9) * VFAT filesystem to <chaffee@cs.berkeley.edu>. Specify
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 10) * what file operation caused you trouble and if you can duplicate
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 11) * the problem, send a script that demonstrates it.
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 12) *
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 13) * Short name translation 1999, 2001 by Wolfram Pienkoss <wp@bszh.de>
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 14) *
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 15) * Support Multibyte characters and cleanup by
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 16) * OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 17) */
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 18)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 19) #include <linux/module.h>
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 20) #include <linux/ctype.h>
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 21) #include <linux/slab.h>
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 22) #include <linux/namei.h>
5680db4b66142 fs/fat/namei_vfat.c (OGAWA Hirofumi 2017-09-08 16:16:50 -0700 23) #include <linux/kernel.h>
2489dbabea80e fs/fat/namei_vfat.c (Jeff Layton 2017-12-11 06:35:09 -0500 24) #include <linux/iversion.h>
9e975dae2970d fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:46 -0800 25) #include "fat.h"
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 26)
814184fd40255 fs/fat/namei_vfat.c (Miklos Szeredi 2016-09-16 12:44:21 +0200 27) static inline unsigned long vfat_d_version(struct dentry *dentry)
814184fd40255 fs/fat/namei_vfat.c (Miklos Szeredi 2016-09-16 12:44:21 +0200 28) {
814184fd40255 fs/fat/namei_vfat.c (Miklos Szeredi 2016-09-16 12:44:21 +0200 29) return (unsigned long) dentry->d_fsdata;
814184fd40255 fs/fat/namei_vfat.c (Miklos Szeredi 2016-09-16 12:44:21 +0200 30) }
814184fd40255 fs/fat/namei_vfat.c (Miklos Szeredi 2016-09-16 12:44:21 +0200 31)
814184fd40255 fs/fat/namei_vfat.c (Miklos Szeredi 2016-09-16 12:44:21 +0200 32) static inline void vfat_d_version_set(struct dentry *dentry,
814184fd40255 fs/fat/namei_vfat.c (Miklos Szeredi 2016-09-16 12:44:21 +0200 33) unsigned long version)
814184fd40255 fs/fat/namei_vfat.c (Miklos Szeredi 2016-09-16 12:44:21 +0200 34) {
814184fd40255 fs/fat/namei_vfat.c (Miklos Szeredi 2016-09-16 12:44:21 +0200 35) dentry->d_fsdata = (void *) version;
814184fd40255 fs/fat/namei_vfat.c (Miklos Szeredi 2016-09-16 12:44:21 +0200 36) }
814184fd40255 fs/fat/namei_vfat.c (Miklos Szeredi 2016-09-16 12:44:21 +0200 37)
1b52467243c71 fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:51 -0800 38) /*
1b52467243c71 fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:51 -0800 39) * If new entry was created in the parent, it could create the 8.3
1b52467243c71 fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:51 -0800 40) * alias (the shortname of logname). So, the parent may have the
1b52467243c71 fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:51 -0800 41) * negative-dentry which matches the created 8.3 alias.
1b52467243c71 fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:51 -0800 42) *
1b52467243c71 fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:51 -0800 43) * If it happened, the negative dentry isn't actually negative
1b52467243c71 fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:51 -0800 44) * anymore. So, drop it.
1b52467243c71 fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:51 -0800 45) */
1b52467243c71 fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:51 -0800 46) static int vfat_revalidate_shortname(struct dentry *dentry)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 47) {
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 48) int ret = 1;
1b52467243c71 fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:51 -0800 49) spin_lock(&dentry->d_lock);
c472c07bfed9c fs/fat/namei_vfat.c (Goffredo Baroncelli 2018-02-01 08:15:25 -0500 50) if (!inode_eq_iversion(d_inode(dentry->d_parent), vfat_d_version(dentry)))
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 51) ret = 0;
1b52467243c71 fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:51 -0800 52) spin_unlock(&dentry->d_lock);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 53) return ret;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 54) }
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 55)
0b728e1911cbe fs/fat/namei_vfat.c (Al Viro 2012-06-10 16:03:43 -0400 56) static int vfat_revalidate(struct dentry *dentry, unsigned int flags)
1b52467243c71 fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:51 -0800 57) {
0b728e1911cbe fs/fat/namei_vfat.c (Al Viro 2012-06-10 16:03:43 -0400 58) if (flags & LOOKUP_RCU)
34286d6662308 fs/fat/namei_vfat.c (Nicholas Piggin 2011-01-07 17:49:57 +1100 59) return -ECHILD;
34286d6662308 fs/fat/namei_vfat.c (Nicholas Piggin 2011-01-07 17:49:57 +1100 60)
1b52467243c71 fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:51 -0800 61) /* This is not negative dentry. Always valid. */
2b0143b5c986b fs/fat/namei_vfat.c (David Howells 2015-03-17 22:25:59 +0000 62) if (d_really_is_positive(dentry))
1b52467243c71 fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:51 -0800 63) return 1;
1b52467243c71 fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:51 -0800 64) return vfat_revalidate_shortname(dentry);
1b52467243c71 fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:51 -0800 65) }
1b52467243c71 fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:51 -0800 66)
0b728e1911cbe fs/fat/namei_vfat.c (Al Viro 2012-06-10 16:03:43 -0400 67) static int vfat_revalidate_ci(struct dentry *dentry, unsigned int flags)
1b52467243c71 fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:51 -0800 68) {
0b728e1911cbe fs/fat/namei_vfat.c (Al Viro 2012-06-10 16:03:43 -0400 69) if (flags & LOOKUP_RCU)
34286d6662308 fs/fat/namei_vfat.c (Nicholas Piggin 2011-01-07 17:49:57 +1100 70) return -ECHILD;
34286d6662308 fs/fat/namei_vfat.c (Nicholas Piggin 2011-01-07 17:49:57 +1100 71)
1b52467243c71 fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:51 -0800 72) /*
1b52467243c71 fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:51 -0800 73) * This is not negative dentry. Always valid.
1b52467243c71 fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:51 -0800 74) *
1b52467243c71 fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:51 -0800 75) * Note, rename() to existing directory entry will have ->d_inode,
1b52467243c71 fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:51 -0800 76) * and will use existing name which isn't specified name by user.
1b52467243c71 fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:51 -0800 77) *
1b52467243c71 fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:51 -0800 78) * We may be able to drop this positive dentry here. But dropping
1b52467243c71 fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:51 -0800 79) * positive dentry isn't good idea. So it's unsupported like
1b52467243c71 fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:51 -0800 80) * rename("filename", "FILENAME") for now.
1b52467243c71 fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:51 -0800 81) */
2b0143b5c986b fs/fat/namei_vfat.c (David Howells 2015-03-17 22:25:59 +0000 82) if (d_really_is_positive(dentry))
1b52467243c71 fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:51 -0800 83) return 1;
1b52467243c71 fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:51 -0800 84)
1b52467243c71 fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:51 -0800 85) /*
1b52467243c71 fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:51 -0800 86) * This may be nfsd (or something), anyway, we can't see the
1b52467243c71 fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:51 -0800 87) * intent of this. So, since this can be for creation, drop it.
1b52467243c71 fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:51 -0800 88) */
0b728e1911cbe fs/fat/namei_vfat.c (Al Viro 2012-06-10 16:03:43 -0400 89) if (!flags)
1b52467243c71 fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:51 -0800 90) return 0;
1b52467243c71 fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:51 -0800 91)
1b52467243c71 fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:51 -0800 92) /*
1b52467243c71 fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:51 -0800 93) * Drop the negative dentry, in order to make sure to use the
1b52467243c71 fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:51 -0800 94) * case sensitive name which is specified by user if this is
1b52467243c71 fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:51 -0800 95) * for creation.
1b52467243c71 fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:51 -0800 96) */
0b728e1911cbe fs/fat/namei_vfat.c (Al Viro 2012-06-10 16:03:43 -0400 97) if (flags & (LOOKUP_CREATE | LOOKUP_RENAME_TARGET))
407938e79edca fs/fat/namei_vfat.c (Al Viro 2011-06-25 21:37:18 -0400 98) return 0;
1b52467243c71 fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:51 -0800 99)
1b52467243c71 fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:51 -0800 100) return vfat_revalidate_shortname(dentry);
1b52467243c71 fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:51 -0800 101) }
1b52467243c71 fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:51 -0800 102)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 103) /* returns the length of a struct qstr, ignoring trailing dots */
621e155a35919 fs/fat/namei_vfat.c (Nicholas Piggin 2011-01-07 17:49:27 +1100 104) static unsigned int __vfat_striptail_len(unsigned int len, const char *name)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 105) {
621e155a35919 fs/fat/namei_vfat.c (Nicholas Piggin 2011-01-07 17:49:27 +1100 106) while (len && name[len - 1] == '.')
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 107) len--;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 108) return len;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 109) }
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 110)
621e155a35919 fs/fat/namei_vfat.c (Nicholas Piggin 2011-01-07 17:49:27 +1100 111) static unsigned int vfat_striptail_len(const struct qstr *qstr)
621e155a35919 fs/fat/namei_vfat.c (Nicholas Piggin 2011-01-07 17:49:27 +1100 112) {
621e155a35919 fs/fat/namei_vfat.c (Nicholas Piggin 2011-01-07 17:49:27 +1100 113) return __vfat_striptail_len(qstr->len, qstr->name);
621e155a35919 fs/fat/namei_vfat.c (Nicholas Piggin 2011-01-07 17:49:27 +1100 114) }
621e155a35919 fs/fat/namei_vfat.c (Nicholas Piggin 2011-01-07 17:49:27 +1100 115)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 116) /*
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 117) * Compute the hash for the vfat name corresponding to the dentry.
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 118) * Note: if the name is invalid, we leave the hash code unchanged so
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 119) * that the existing dentry can be used. The vfat fs routines will
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 120) * return ENOENT or EINVAL as appropriate.
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 121) */
da53be12bbb4f fs/fat/namei_vfat.c (Linus Torvalds 2013-05-21 15:22:44 -0700 122) static int vfat_hash(const struct dentry *dentry, struct qstr *qstr)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 123) {
8387ff2577eb9 fs/fat/namei_vfat.c (Linus Torvalds 2016-06-10 07:51:30 -0700 124) qstr->hash = full_name_hash(dentry, qstr->name, vfat_striptail_len(qstr));
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 125) return 0;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 126) }
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 127)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 128) /*
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 129) * Compute the hash for the vfat name corresponding to the dentry.
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 130) * Note: if the name is invalid, we leave the hash code unchanged so
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 131) * that the existing dentry can be used. The vfat fs routines will
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 132) * return ENOENT or EINVAL as appropriate.
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 133) */
da53be12bbb4f fs/fat/namei_vfat.c (Linus Torvalds 2013-05-21 15:22:44 -0700 134) static int vfat_hashi(const struct dentry *dentry, struct qstr *qstr)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 135) {
b1e6a015a580a fs/fat/namei_vfat.c (Nicholas Piggin 2011-01-07 17:49:28 +1100 136) struct nls_table *t = MSDOS_SB(dentry->d_sb)->nls_io;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 137) const unsigned char *name;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 138) unsigned int len;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 139) unsigned long hash;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 140)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 141) name = qstr->name;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 142) len = vfat_striptail_len(qstr);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 143)
8387ff2577eb9 fs/fat/namei_vfat.c (Linus Torvalds 2016-06-10 07:51:30 -0700 144) hash = init_name_hash(dentry);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 145) while (len--)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 146) hash = partial_name_hash(nls_tolower(t, *name++), hash);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 147) qstr->hash = end_name_hash(hash);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 148)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 149) return 0;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 150) }
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 151)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 152) /*
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 153) * Case insensitive compare of two vfat names.
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 154) */
6fa67e7075593 fs/fat/namei_vfat.c (Al Viro 2016-07-31 16:37:25 -0400 155) static int vfat_cmpi(const struct dentry *dentry,
621e155a35919 fs/fat/namei_vfat.c (Nicholas Piggin 2011-01-07 17:49:27 +1100 156) unsigned int len, const char *str, const struct qstr *name)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 157) {
d3fe19852e96a fs/fat/namei_vfat.c (Al Viro 2016-07-29 18:23:59 -0400 158) struct nls_table *t = MSDOS_SB(dentry->d_sb)->nls_io;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 159) unsigned int alen, blen;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 160)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 161) /* A filename cannot end in '.' or we treat it like it has none */
621e155a35919 fs/fat/namei_vfat.c (Nicholas Piggin 2011-01-07 17:49:27 +1100 162) alen = vfat_striptail_len(name);
621e155a35919 fs/fat/namei_vfat.c (Nicholas Piggin 2011-01-07 17:49:27 +1100 163) blen = __vfat_striptail_len(len, str);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 164) if (alen == blen) {
621e155a35919 fs/fat/namei_vfat.c (Nicholas Piggin 2011-01-07 17:49:27 +1100 165) if (nls_strnicmp(t, name->name, str, alen) == 0)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 166) return 0;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 167) }
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 168) return 1;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 169) }
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 170)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 171) /*
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 172) * Case sensitive compare of two vfat names.
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 173) */
6fa67e7075593 fs/fat/namei_vfat.c (Al Viro 2016-07-31 16:37:25 -0400 174) static int vfat_cmp(const struct dentry *dentry,
621e155a35919 fs/fat/namei_vfat.c (Nicholas Piggin 2011-01-07 17:49:27 +1100 175) unsigned int len, const char *str, const struct qstr *name)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 176) {
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 177) unsigned int alen, blen;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 178)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 179) /* A filename cannot end in '.' or we treat it like it has none */
621e155a35919 fs/fat/namei_vfat.c (Nicholas Piggin 2011-01-07 17:49:27 +1100 180) alen = vfat_striptail_len(name);
621e155a35919 fs/fat/namei_vfat.c (Nicholas Piggin 2011-01-07 17:49:27 +1100 181) blen = __vfat_striptail_len(len, str);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 182) if (alen == blen) {
621e155a35919 fs/fat/namei_vfat.c (Nicholas Piggin 2011-01-07 17:49:27 +1100 183) if (strncmp(name->name, str, alen) == 0)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 184) return 0;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 185) }
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 186) return 1;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 187) }
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 188)
ce6cdc474aa5b fs/fat/namei_vfat.c (Al Viro 2009-02-20 05:59:46 +0000 189) static const struct dentry_operations vfat_ci_dentry_ops = {
1b52467243c71 fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:51 -0800 190) .d_revalidate = vfat_revalidate_ci,
1b52467243c71 fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:51 -0800 191) .d_hash = vfat_hashi,
1b52467243c71 fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:51 -0800 192) .d_compare = vfat_cmpi,
1b52467243c71 fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:51 -0800 193) };
1b52467243c71 fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:51 -0800 194)
ce6cdc474aa5b fs/fat/namei_vfat.c (Al Viro 2009-02-20 05:59:46 +0000 195) static const struct dentry_operations vfat_dentry_ops = {
1b52467243c71 fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:51 -0800 196) .d_revalidate = vfat_revalidate,
1b52467243c71 fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:51 -0800 197) .d_hash = vfat_hash,
1b52467243c71 fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:51 -0800 198) .d_compare = vfat_cmp,
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 199) };
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 200)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 201) /* Characters that are undesirable in an MS-DOS file name */
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 202)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 203) static inline wchar_t vfat_bad_char(wchar_t w)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 204) {
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 205) return (w < 0x0020)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 206) || (w == '*') || (w == '?') || (w == '<') || (w == '>')
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 207) || (w == '|') || (w == '"') || (w == ':') || (w == '/')
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 208) || (w == '\\');
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 209) }
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 210)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 211) static inline wchar_t vfat_replace_char(wchar_t w)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 212) {
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 213) return (w == '[') || (w == ']') || (w == ';') || (w == ',')
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 214) || (w == '+') || (w == '=');
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 215) }
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 216)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 217) static wchar_t vfat_skip_char(wchar_t w)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 218) {
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 219) return (w == '.') || (w == ' ');
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 220) }
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 221)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 222) static inline int vfat_is_used_badchars(const wchar_t *s, int len)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 223) {
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 224) int i;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 225)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 226) for (i = 0; i < len; i++)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 227) if (vfat_bad_char(s[i]))
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 228) return -EINVAL;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 229)
f22032ba8de29 fs/vfat/namei.c (Keith Mok 2008-04-28 02:16:29 -0700 230) if (s[i - 1] == ' ') /* last character cannot be space */
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 231) return -EINVAL;
f22032ba8de29 fs/vfat/namei.c (Keith Mok 2008-04-28 02:16:29 -0700 232)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 233) return 0;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 234) }
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 235)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 236) static int vfat_find_form(struct inode *dir, unsigned char *name)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 237) {
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 238) struct fat_slot_info sinfo;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 239) int err = fat_scan(dir, name, &sinfo);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 240) if (err)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 241) return -ENOENT;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 242) brelse(sinfo.bh);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 243) return 0;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 244) }
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 245)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 246) /*
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 247) * 1) Valid characters for the 8.3 format alias are any combination of
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 248) * letters, uppercase alphabets, digits, any of the
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 249) * following special characters:
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 250) * $ % ' ` - @ { } ~ ! # ( ) & _ ^
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 251) * In this case Longfilename is not stored in disk.
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 252) *
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 253) * WinNT's Extension:
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 254) * File name and extension name is contain uppercase/lowercase
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 255) * only. And it is expressed by CASE_LOWER_BASE and CASE_LOWER_EXT.
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 256) *
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 257) * 2) File name is 8.3 format, but it contain the uppercase and
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 258) * lowercase char, muliti bytes char, etc. In this case numtail is not
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 259) * added, but Longfilename is stored.
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 260) *
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 261) * 3) When the one except for the above, or the following special
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 262) * character are contained:
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 263) * . [ ] ; , + =
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 264) * numtail is added, and Longfilename must be stored in disk .
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 265) */
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 266) struct shortname_info {
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 267) unsigned char lower:1,
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 268) upper:1,
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 269) valid:1;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 270) };
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 271) #define INIT_SHORTNAME_INFO(x) do { \
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 272) (x)->lower = 1; \
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 273) (x)->upper = 1; \
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 274) (x)->valid = 1; \
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 275) } while (0)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 276)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 277) static inline int to_shortname_char(struct nls_table *nls,
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 278) unsigned char *buf, int buf_size,
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 279) wchar_t *src, struct shortname_info *info)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 280) {
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 281) int len;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 282)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 283) if (vfat_skip_char(*src)) {
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 284) info->valid = 0;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 285) return 0;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 286) }
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 287) if (vfat_replace_char(*src)) {
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 288) info->valid = 0;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 289) buf[0] = '_';
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 290) return 1;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 291) }
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 292)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 293) len = nls->uni2char(*src, buf, buf_size);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 294) if (len <= 0) {
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 295) info->valid = 0;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 296) buf[0] = '_';
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 297) len = 1;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 298) } else if (len == 1) {
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 299) unsigned char prev = buf[0];
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 300)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 301) if (buf[0] >= 0x7F) {
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 302) info->lower = 0;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 303) info->upper = 0;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 304) }
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 305)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 306) buf[0] = nls_toupper(nls, buf[0]);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 307) if (isalpha(buf[0])) {
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 308) if (buf[0] == prev)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 309) info->lower = 0;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 310) else
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 311) info->upper = 0;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 312) }
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 313) } else {
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 314) info->lower = 0;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 315) info->upper = 0;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 316) }
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 317)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 318) return len;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 319) }
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 320)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 321) /*
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 322) * Given a valid longname, create a unique shortname. Make sure the
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 323) * shortname does not exist
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 324) * Returns negative number on error, 0 for a normal
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 325) * return, and 1 for valid shortname
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 326) */
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 327) static int vfat_create_shortname(struct inode *dir, struct nls_table *nls,
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 328) wchar_t *uname, int ulen,
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 329) unsigned char *name_res, unsigned char *lcase)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 330) {
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 331) struct fat_mount_options *opts = &MSDOS_SB(dir->i_sb)->options;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 332) wchar_t *ip, *ext_start, *end, *name_start;
30d1872d9eb36 fs/fat/namei_vfat.c (Nikolaus Schulz 2010-04-01 02:21:10 +0900 333) unsigned char base[9], ext[4], buf[5], *p;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 334) unsigned char charbuf[NLS_MAX_CHARSET_SIZE];
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 335) int chl, chi;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 336) int sz = 0, extlen, baselen, i, numtail_baselen, numtail2_baselen;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 337) int is_shortname;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 338) struct shortname_info base_info, ext_info;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 339)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 340) is_shortname = 1;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 341) INIT_SHORTNAME_INFO(&base_info);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 342) INIT_SHORTNAME_INFO(&ext_info);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 343)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 344) /* Now, we need to create a shortname from the long name */
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 345) ext_start = end = &uname[ulen];
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 346) while (--ext_start >= uname) {
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 347) if (*ext_start == 0x002E) { /* is `.' */
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 348) if (ext_start == end - 1) {
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 349) sz = ulen;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 350) ext_start = NULL;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 351) }
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 352) break;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 353) }
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 354) }
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 355)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 356) if (ext_start == uname - 1) {
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 357) sz = ulen;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 358) ext_start = NULL;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 359) } else if (ext_start) {
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 360) /*
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 361) * Names which start with a dot could be just
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 362) * an extension eg. "...test". In this case Win95
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 363) * uses the extension as the name and sets no extension.
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 364) */
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 365) name_start = &uname[0];
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 366) while (name_start < ext_start) {
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 367) if (!vfat_skip_char(*name_start))
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 368) break;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 369) name_start++;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 370) }
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 371) if (name_start != ext_start) {
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 372) sz = ext_start - uname;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 373) ext_start++;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 374) } else {
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 375) sz = ulen;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 376) ext_start = NULL;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 377) }
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 378) }
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 379)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 380) numtail_baselen = 6;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 381) numtail2_baselen = 2;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 382) for (baselen = i = 0, p = base, ip = uname; i < sz; i++, ip++) {
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 383) chl = to_shortname_char(nls, charbuf, sizeof(charbuf),
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 384) ip, &base_info);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 385) if (chl == 0)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 386) continue;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 387)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 388) if (baselen < 2 && (baselen + chl) > 2)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 389) numtail2_baselen = baselen;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 390) if (baselen < 6 && (baselen + chl) > 6)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 391) numtail_baselen = baselen;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 392) for (chi = 0; chi < chl; chi++) {
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 393) *p++ = charbuf[chi];
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 394) baselen++;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 395) if (baselen >= 8)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 396) break;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 397) }
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 398) if (baselen >= 8) {
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 399) if ((chi < chl - 1) || (ip + 1) - uname < sz)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 400) is_shortname = 0;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 401) break;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 402) }
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 403) }
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 404) if (baselen == 0) {
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 405) return -EINVAL;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 406) }
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 407)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 408) extlen = 0;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 409) if (ext_start) {
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 410) for (p = ext, ip = ext_start; extlen < 3 && ip < end; ip++) {
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 411) chl = to_shortname_char(nls, charbuf, sizeof(charbuf),
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 412) ip, &ext_info);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 413) if (chl == 0)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 414) continue;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 415)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 416) if ((extlen + chl) > 3) {
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 417) is_shortname = 0;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 418) break;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 419) }
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 420) for (chi = 0; chi < chl; chi++) {
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 421) *p++ = charbuf[chi];
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 422) extlen++;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 423) }
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 424) if (extlen >= 3) {
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 425) if (ip + 1 != end)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 426) is_shortname = 0;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 427) break;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 428) }
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 429) }
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 430) }
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 431) ext[extlen] = '\0';
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 432) base[baselen] = '\0';
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 433)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 434) /* Yes, it can happen. ".\xe5" would do it. */
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 435) if (base[0] == DELETED_FLAG)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 436) base[0] = 0x05;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 437)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 438) /* OK, at this point we know that base is not longer than 8 symbols,
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 439) * ext is not longer than 3, base is nonempty, both don't contain
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 440) * any bad symbols (lowercase transformed to uppercase).
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 441) */
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 442)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 443) memset(name_res, ' ', MSDOS_NAME);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 444) memcpy(name_res, base, baselen);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 445) memcpy(name_res + 8, ext, extlen);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 446) *lcase = 0;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 447) if (is_shortname && base_info.valid && ext_info.valid) {
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 448) if (vfat_find_form(dir, name_res) == 0)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 449) return -EEXIST;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 450)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 451) if (opts->shortname & VFAT_SFN_CREATE_WIN95) {
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 452) return (base_info.upper && ext_info.upper);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 453) } else if (opts->shortname & VFAT_SFN_CREATE_WINNT) {
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 454) if ((base_info.upper || base_info.lower) &&
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 455) (ext_info.upper || ext_info.lower)) {
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 456) if (!base_info.upper && base_info.lower)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 457) *lcase |= CASE_LOWER_BASE;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 458) if (!ext_info.upper && ext_info.lower)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 459) *lcase |= CASE_LOWER_EXT;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 460) return 1;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 461) }
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 462) return 0;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 463) } else {
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 464) BUG();
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 465) }
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 466) }
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 467)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 468) if (opts->numtail == 0)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 469) if (vfat_find_form(dir, name_res) < 0)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 470) return 0;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 471)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 472) /*
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 473) * Try to find a unique extension. This used to
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 474) * iterate through all possibilities sequentially,
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 475) * but that gave extremely bad performance. Windows
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 476) * only tries a few cases before using random
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 477) * values for part of the base.
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 478) */
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 479)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 480) if (baselen > 6) {
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 481) baselen = numtail_baselen;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 482) name_res[7] = ' ';
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 483) }
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 484) name_res[baselen] = '~';
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 485) for (i = 1; i < 10; i++) {
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 486) name_res[baselen + 1] = i + '0';
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 487) if (vfat_find_form(dir, name_res) < 0)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 488) return 0;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 489) }
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 490)
30d1872d9eb36 fs/fat/namei_vfat.c (Nikolaus Schulz 2010-04-01 02:21:10 +0900 491) i = jiffies;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 492) sz = (jiffies >> 16) & 0x7;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 493) if (baselen > 2) {
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 494) baselen = numtail2_baselen;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 495) name_res[7] = ' ';
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 496) }
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 497) name_res[baselen + 4] = '~';
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 498) name_res[baselen + 5] = '1' + sz;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 499) while (1) {
30d1872d9eb36 fs/fat/namei_vfat.c (Nikolaus Schulz 2010-04-01 02:21:10 +0900 500) snprintf(buf, sizeof(buf), "%04X", i & 0xffff);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 501) memcpy(&name_res[baselen], buf, 4);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 502) if (vfat_find_form(dir, name_res) < 0)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 503) break;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 504) i -= 11;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 505) }
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 506) return 0;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 507) }
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 508)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 509) /* Translate a string, including coded sequences into Unicode */
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 510) static int
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 511) xlate_to_uni(const unsigned char *name, int len, unsigned char *outname,
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 512) int *longlen, int *outlen, int escape, int utf8,
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 513) struct nls_table *nls)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 514) {
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 515) const unsigned char *ip;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 516) unsigned char *op;
5680db4b66142 fs/fat/namei_vfat.c (OGAWA Hirofumi 2017-09-08 16:16:50 -0700 517) int i, fill;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 518) int charlen;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 519)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 520) if (utf8) {
0720a06a7518c fs/fat/namei_vfat.c (Alan Stern 2011-11-17 16:42:19 -0500 521) *outlen = utf8s_to_utf16s(name, len, UTF16_HOST_ENDIAN,
0720a06a7518c fs/fat/namei_vfat.c (Alan Stern 2011-11-17 16:42:19 -0500 522) (wchar_t *) outname, FAT_LFN_LEN + 2);
67638e4043083 fs/fat/namei_vfat.c (OGAWA Hirofumi 2009-08-01 21:30:31 +0900 523) if (*outlen < 0)
67638e4043083 fs/fat/namei_vfat.c (OGAWA Hirofumi 2009-08-01 21:30:31 +0900 524) return *outlen;
eeb5b4ae81f4a fs/fat/namei_vfat.c (Kevin Dankwardt 2010-02-10 23:43:40 +0900 525) else if (*outlen > FAT_LFN_LEN)
f22032ba8de29 fs/vfat/namei.c (Keith Mok 2008-04-28 02:16:29 -0700 526) return -ENAMETOOLONG;
f22032ba8de29 fs/vfat/namei.c (Keith Mok 2008-04-28 02:16:29 -0700 527)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 528) op = &outname[*outlen * sizeof(wchar_t)];
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 529) } else {
41f0c02eacec9 fs/fat/namei_vfat.c (Namjae Jeon 2012-03-23 15:02:38 -0700 530) for (i = 0, ip = name, op = outname, *outlen = 0;
d533df07c20c7 fs/fat/namei_vfat.c (Namjae Jeon 2012-03-23 15:02:39 -0700 531) i < len && *outlen < FAT_LFN_LEN;
41f0c02eacec9 fs/fat/namei_vfat.c (Namjae Jeon 2012-03-23 15:02:38 -0700 532) *outlen += 1) {
41f0c02eacec9 fs/fat/namei_vfat.c (Namjae Jeon 2012-03-23 15:02:38 -0700 533) if (escape && (*ip == ':')) {
5680db4b66142 fs/fat/namei_vfat.c (OGAWA Hirofumi 2017-09-08 16:16:50 -0700 534) u8 uc[2];
5680db4b66142 fs/fat/namei_vfat.c (OGAWA Hirofumi 2017-09-08 16:16:50 -0700 535)
41f0c02eacec9 fs/fat/namei_vfat.c (Namjae Jeon 2012-03-23 15:02:38 -0700 536) if (i > len - 5)
41f0c02eacec9 fs/fat/namei_vfat.c (Namjae Jeon 2012-03-23 15:02:38 -0700 537) return -EINVAL;
5680db4b66142 fs/fat/namei_vfat.c (OGAWA Hirofumi 2017-09-08 16:16:50 -0700 538)
5680db4b66142 fs/fat/namei_vfat.c (OGAWA Hirofumi 2017-09-08 16:16:50 -0700 539) if (hex2bin(uc, ip + 1, 2) < 0)
41f0c02eacec9 fs/fat/namei_vfat.c (Namjae Jeon 2012-03-23 15:02:38 -0700 540) return -EINVAL;
5680db4b66142 fs/fat/namei_vfat.c (OGAWA Hirofumi 2017-09-08 16:16:50 -0700 541)
5680db4b66142 fs/fat/namei_vfat.c (OGAWA Hirofumi 2017-09-08 16:16:50 -0700 542) *(wchar_t *)op = uc[0] << 8 | uc[1];
5680db4b66142 fs/fat/namei_vfat.c (OGAWA Hirofumi 2017-09-08 16:16:50 -0700 543)
5680db4b66142 fs/fat/namei_vfat.c (OGAWA Hirofumi 2017-09-08 16:16:50 -0700 544) op += 2;
41f0c02eacec9 fs/fat/namei_vfat.c (Namjae Jeon 2012-03-23 15:02:38 -0700 545) ip += 5;
41f0c02eacec9 fs/fat/namei_vfat.c (Namjae Jeon 2012-03-23 15:02:38 -0700 546) i += 5;
41f0c02eacec9 fs/fat/namei_vfat.c (Namjae Jeon 2012-03-23 15:02:38 -0700 547) } else {
41f0c02eacec9 fs/fat/namei_vfat.c (Namjae Jeon 2012-03-23 15:02:38 -0700 548) charlen = nls->char2uni(ip, len - i,
5680db4b66142 fs/fat/namei_vfat.c (OGAWA Hirofumi 2017-09-08 16:16:50 -0700 549) (wchar_t *)op);
41f0c02eacec9 fs/fat/namei_vfat.c (Namjae Jeon 2012-03-23 15:02:38 -0700 550) if (charlen < 0)
41f0c02eacec9 fs/fat/namei_vfat.c (Namjae Jeon 2012-03-23 15:02:38 -0700 551) return -EINVAL;
41f0c02eacec9 fs/fat/namei_vfat.c (Namjae Jeon 2012-03-23 15:02:38 -0700 552) ip += charlen;
41f0c02eacec9 fs/fat/namei_vfat.c (Namjae Jeon 2012-03-23 15:02:38 -0700 553) i += charlen;
41f0c02eacec9 fs/fat/namei_vfat.c (Namjae Jeon 2012-03-23 15:02:38 -0700 554) op += 2;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 555) }
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 556) }
41f0c02eacec9 fs/fat/namei_vfat.c (Namjae Jeon 2012-03-23 15:02:38 -0700 557) if (i < len)
41f0c02eacec9 fs/fat/namei_vfat.c (Namjae Jeon 2012-03-23 15:02:38 -0700 558) return -ENAMETOOLONG;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 559) }
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 560)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 561) *longlen = *outlen;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 562) if (*outlen % 13) {
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 563) *op++ = 0;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 564) *op++ = 0;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 565) *outlen += 1;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 566) if (*outlen % 13) {
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 567) fill = 13 - (*outlen % 13);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 568) for (i = 0; i < fill; i++) {
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 569) *op++ = 0xff;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 570) *op++ = 0xff;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 571) }
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 572) *outlen += fill;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 573) }
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 574) }
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 575)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 576) return 0;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 577) }
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 578)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 579) static int vfat_build_slots(struct inode *dir, const unsigned char *name,
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 580) int len, int is_dir, int cluster,
f423420c23899 fs/fat/namei_vfat.c (Arnd Bergmann 2018-08-21 21:59:48 -0700 581) struct timespec64 *ts,
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 582) struct msdos_dir_slot *slots, int *nr_slots)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 583) {
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 584) struct msdos_sb_info *sbi = MSDOS_SB(dir->i_sb);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 585) struct fat_mount_options *opts = &sbi->options;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 586) struct msdos_dir_slot *ps;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 587) struct msdos_dir_entry *de;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 588) unsigned char cksum, lcase;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 589) unsigned char msdos_name[MSDOS_NAME];
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 590) wchar_t *uname;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 591) __le16 time, date;
7decd1cb0305b fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:47 -0800 592) u8 time_cs;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 593) int err, ulen, usize, i;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 594) loff_t offset;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 595)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 596) *nr_slots = 0;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 597)
c7a6c4edc74ee fs/vfat/namei.c (OGAWA Hirofumi 2008-04-28 02:16:29 -0700 598) uname = __getname();
c7a6c4edc74ee fs/vfat/namei.c (OGAWA Hirofumi 2008-04-28 02:16:29 -0700 599) if (!uname)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 600) return -ENOMEM;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 601)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 602) err = xlate_to_uni(name, len, (unsigned char *)uname, &ulen, &usize,
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 603) opts->unicode_xlate, opts->utf8, sbi->nls_io);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 604) if (err)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 605) goto out_free;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 606)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 607) err = vfat_is_used_badchars(uname, ulen);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 608) if (err)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 609) goto out_free;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 610)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 611) err = vfat_create_shortname(dir, sbi->nls_disk, uname, ulen,
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 612) msdos_name, &lcase);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 613) if (err < 0)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 614) goto out_free;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 615) else if (err == 1) {
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 616) de = (struct msdos_dir_entry *)slots;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 617) err = 0;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 618) goto shortname;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 619) }
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 620)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 621) /* build the entry of long file name */
451cbaa1c3280 fs/vfat/namei.c (OGAWA Hirofumi 2005-10-30 15:03:49 -0800 622) cksum = fat_checksum(msdos_name);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 623)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 624) *nr_slots = usize / 13;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 625) for (ps = slots, i = *nr_slots; i > 0; i--, ps++) {
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 626) ps->id = i;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 627) ps->attr = ATTR_EXT;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 628) ps->reserved = 0;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 629) ps->alias_checksum = cksum;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 630) ps->start = 0;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 631) offset = (i - 1) * 13;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 632) fatwchar_to16(ps->name0_4, uname + offset, 5);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 633) fatwchar_to16(ps->name5_10, uname + offset + 5, 6);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 634) fatwchar_to16(ps->name11_12, uname + offset + 11, 2);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 635) }
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 636) slots[0].id |= 0x40;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 637) de = (struct msdos_dir_entry *)ps;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 638)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 639) shortname:
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 640) /* build the entry of 8.3 alias name */
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 641) (*nr_slots)++;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 642) memcpy(de->name, msdos_name, MSDOS_NAME);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 643) de->attr = is_dir ? ATTR_DIR : ATTR_ARCH;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 644) de->lcase = lcase;
7decd1cb0305b fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:47 -0800 645) fat_time_unix2fat(sbi, ts, &time, &date, &time_cs);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 646) de->time = de->ctime = time;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 647) de->date = de->cdate = de->adate = date;
7decd1cb0305b fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:47 -0800 648) de->ctime_cs = time_cs;
a943ed71c9171 fs/fat/namei_vfat.c (Steven J. Magnani 2012-07-30 14:42:13 -0700 649) fat_set_start(de, cluster);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 650) de->size = 0;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 651) out_free:
c7a6c4edc74ee fs/vfat/namei.c (OGAWA Hirofumi 2008-04-28 02:16:29 -0700 652) __putname(uname);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 653) return err;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 654) }
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 655)
b59091c04ae02 fs/fat/namei_vfat.c (Al Viro 2016-07-20 22:43:14 -0400 656) static int vfat_add_entry(struct inode *dir, const struct qstr *qname,
f423420c23899 fs/fat/namei_vfat.c (Arnd Bergmann 2018-08-21 21:59:48 -0700 657) int is_dir, int cluster, struct timespec64 *ts,
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 658) struct fat_slot_info *sinfo)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 659) {
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 660) struct msdos_dir_slot *slots;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 661) unsigned int len;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 662) int err, nr_slots;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 663)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 664) len = vfat_striptail_len(qname);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 665) if (len == 0)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 666) return -ENOENT;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 667)
6da2ec56059c3 fs/fat/namei_vfat.c (Kees Cook 2018-06-12 13:55:00 -0700 668) slots = kmalloc_array(MSDOS_SLOTS, sizeof(*slots), GFP_NOFS);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 669) if (slots == NULL)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 670) return -ENOMEM;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 671)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 672) err = vfat_build_slots(dir, qname->name, len, is_dir, cluster, ts,
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 673) slots, &nr_slots);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 674) if (err)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 675) goto cleanup;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 676)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 677) err = fat_add_entries(dir, slots, nr_slots, sinfo);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 678) if (err)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 679) goto cleanup;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 680)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 681) /* update timestamp */
cd83f6b194e95 fs/fat/namei_vfat.c (Frank Sorenson 2018-10-30 15:06:57 -0700 682) fat_truncate_time(dir, ts, S_CTIME|S_MTIME);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 683) if (IS_DIRSYNC(dir))
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 684) (void)fat_sync_inode(dir);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 685) else
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 686) mark_inode_dirty(dir);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 687) cleanup:
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 688) kfree(slots);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 689) return err;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 690) }
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 691)
b59091c04ae02 fs/fat/namei_vfat.c (Al Viro 2016-07-20 22:43:14 -0400 692) static int vfat_find(struct inode *dir, const struct qstr *qname,
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 693) struct fat_slot_info *sinfo)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 694) {
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 695) unsigned int len = vfat_striptail_len(qname);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 696) if (len == 0)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 697) return -ENOENT;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 698) return fat_search_long(dir, qname->name, len, sinfo);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 699) }
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 700)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 701) static struct dentry *vfat_lookup(struct inode *dir, struct dentry *dentry,
00cd8dd3bf95f fs/fat/namei_vfat.c (Al Viro 2012-06-10 17:13:09 -0400 702) unsigned int flags)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 703) {
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 704) struct super_block *sb = dir->i_sb;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 705) struct fat_slot_info sinfo;
068f5ae05c51d fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:51 -0800 706) struct inode *inode;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 707) struct dentry *alias;
1b52467243c71 fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:51 -0800 708) int err;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 709)
e40b34c792153 fs/fat/namei_vfat.c (Marco Stornelli 2012-10-06 12:40:03 +0200 710) mutex_lock(&MSDOS_SB(sb)->s_lock);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 711)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 712) err = vfat_find(dir, &dentry->d_name, &sinfo);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 713) if (err) {
068f5ae05c51d fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:51 -0800 714) if (err == -ENOENT) {
068f5ae05c51d fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:51 -0800 715) inode = NULL;
068f5ae05c51d fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:51 -0800 716) goto out;
068f5ae05c51d fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:51 -0800 717) }
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 718) goto error;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 719) }
1b52467243c71 fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:51 -0800 720)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 721) inode = fat_build_inode(sb, sinfo.de, sinfo.i_pos);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 722) brelse(sinfo.bh);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 723) if (IS_ERR(inode)) {
068f5ae05c51d fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:51 -0800 724) err = PTR_ERR(inode);
068f5ae05c51d fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:51 -0800 725) goto error;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 726) }
1b52467243c71 fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:51 -0800 727)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 728) alias = d_find_alias(inode);
1ead0e79bfedd fs/fat/namei_vfat.c (Al Viro 2014-12-02 15:59:37 -0800 729) /*
1ead0e79bfedd fs/fat/namei_vfat.c (Al Viro 2014-12-02 15:59:37 -0800 730) * Checking "alias->d_parent == dentry->d_parent" to make sure
1ead0e79bfedd fs/fat/namei_vfat.c (Al Viro 2014-12-02 15:59:37 -0800 731) * FS is not corrupted (especially double linked dir).
1ead0e79bfedd fs/fat/namei_vfat.c (Al Viro 2014-12-02 15:59:37 -0800 732) */
f6ddc16175f63 fs/fat/namei_vfat.c (Al Viro 2018-04-25 10:32:51 -0400 733) if (alias && alias->d_parent == dentry->d_parent) {
1b52467243c71 fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:51 -0800 734) /*
8045e2985012b fs/fat/namei_vfat.c (OGAWA Hirofumi 2010-01-12 03:32:24 +0900 735) * This inode has non anonymous-DCACHE_DISCONNECTED
8045e2985012b fs/fat/namei_vfat.c (OGAWA Hirofumi 2010-01-12 03:32:24 +0900 736) * dentry. This means, the user did ->lookup() by an
8045e2985012b fs/fat/namei_vfat.c (OGAWA Hirofumi 2010-01-12 03:32:24 +0900 737) * another name (longname vs 8.3 alias of it) in past.
1b52467243c71 fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:51 -0800 738) *
1b52467243c71 fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:51 -0800 739) * Switch to new one for reason of locality if possible.
1b52467243c71 fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:51 -0800 740) */
1c13a243a461d fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:52 -0800 741) if (!S_ISDIR(inode->i_mode))
1c13a243a461d fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:52 -0800 742) d_move(alias, dentry);
1c13a243a461d fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:52 -0800 743) iput(inode);
e40b34c792153 fs/fat/namei_vfat.c (Marco Stornelli 2012-10-06 12:40:03 +0200 744) mutex_unlock(&MSDOS_SB(sb)->s_lock);
1c13a243a461d fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:52 -0800 745) return alias;
8045e2985012b fs/fat/namei_vfat.c (OGAWA Hirofumi 2010-01-12 03:32:24 +0900 746) } else
8045e2985012b fs/fat/namei_vfat.c (OGAWA Hirofumi 2010-01-12 03:32:24 +0900 747) dput(alias);
8045e2985012b fs/fat/namei_vfat.c (OGAWA Hirofumi 2010-01-12 03:32:24 +0900 748)
068f5ae05c51d fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:51 -0800 749) out:
e40b34c792153 fs/fat/namei_vfat.c (Marco Stornelli 2012-10-06 12:40:03 +0200 750) mutex_unlock(&MSDOS_SB(sb)->s_lock);
1ead0e79bfedd fs/fat/namei_vfat.c (Al Viro 2014-12-02 15:59:37 -0800 751) if (!inode)
2489dbabea80e fs/fat/namei_vfat.c (Jeff Layton 2017-12-11 06:35:09 -0500 752) vfat_d_version_set(dentry, inode_query_iversion(dir));
1ead0e79bfedd fs/fat/namei_vfat.c (Al Viro 2014-12-02 15:59:37 -0800 753) return d_splice_alias(inode, dentry);
068f5ae05c51d fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:51 -0800 754) error:
e40b34c792153 fs/fat/namei_vfat.c (Marco Stornelli 2012-10-06 12:40:03 +0200 755) mutex_unlock(&MSDOS_SB(sb)->s_lock);
068f5ae05c51d fs/fat/namei_vfat.c (OGAWA Hirofumi 2008-11-06 12:53:51 -0800 756) return ERR_PTR(err);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 757) }
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 758)
549c7297717c3 fs/fat/namei_vfat.c (Christian Brauner 2021-01-21 14:19:43 +0100 759) static int vfat_create(struct user_namespace *mnt_userns, struct inode *dir,
549c7297717c3 fs/fat/namei_vfat.c (Christian Brauner 2021-01-21 14:19:43 +0100 760) struct dentry *dentry, umode_t mode, bool excl)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 761) {
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 762) struct super_block *sb = dir->i_sb;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 763) struct inode *inode;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 764) struct fat_slot_info sinfo;
95582b0083883 fs/fat/namei_vfat.c (Deepa Dinamani 2018-05-08 19:36:02 -0700 765) struct timespec64 ts;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 766) int err;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 767)
e40b34c792153 fs/fat/namei_vfat.c (Marco Stornelli 2012-10-06 12:40:03 +0200 768) mutex_lock(&MSDOS_SB(sb)->s_lock);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 769)
02027d42c3f74 fs/fat/namei_vfat.c (Deepa Dinamani 2016-09-14 07:48:05 -0700 770) ts = current_time(dir);
f423420c23899 fs/fat/namei_vfat.c (Arnd Bergmann 2018-08-21 21:59:48 -0700 771) err = vfat_add_entry(dir, &dentry->d_name, 0, 0, &ts, &sinfo);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 772) if (err)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 773) goto out;
2489dbabea80e fs/fat/namei_vfat.c (Jeff Layton 2017-12-11 06:35:09 -0500 774) inode_inc_iversion(dir);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 775)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 776) inode = fat_build_inode(sb, sinfo.de, sinfo.i_pos);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 777) brelse(sinfo.bh);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 778) if (IS_ERR(inode)) {
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 779) err = PTR_ERR(inode);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 780) goto out;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 781) }
2489dbabea80e fs/fat/namei_vfat.c (Jeff Layton 2017-12-11 06:35:09 -0500 782) inode_inc_iversion(inode);
cd83f6b194e95 fs/fat/namei_vfat.c (Frank Sorenson 2018-10-30 15:06:57 -0700 783) fat_truncate_time(inode, &ts, S_ATIME|S_CTIME|S_MTIME);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 784) /* timestamp is already written, so mark_inode_dirty() is unneeded. */
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 785)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 786) d_instantiate(dentry, inode);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 787) out:
e40b34c792153 fs/fat/namei_vfat.c (Marco Stornelli 2012-10-06 12:40:03 +0200 788) mutex_unlock(&MSDOS_SB(sb)->s_lock);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 789) return err;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 790) }
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 791)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 792) static int vfat_rmdir(struct inode *dir, struct dentry *dentry)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 793) {
2b0143b5c986b fs/fat/namei_vfat.c (David Howells 2015-03-17 22:25:59 +0000 794) struct inode *inode = d_inode(dentry);
8f5934278d1d8 fs/vfat/namei.c (Linus Torvalds 2008-05-19 19:53:01 -0700 795) struct super_block *sb = dir->i_sb;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 796) struct fat_slot_info sinfo;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 797) int err;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 798)
e40b34c792153 fs/fat/namei_vfat.c (Marco Stornelli 2012-10-06 12:40:03 +0200 799) mutex_lock(&MSDOS_SB(sb)->s_lock);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 800)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 801) err = fat_dir_empty(inode);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 802) if (err)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 803) goto out;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 804) err = vfat_find(dir, &dentry->d_name, &sinfo);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 805) if (err)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 806) goto out;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 807)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 808) err = fat_remove_entries(dir, &sinfo); /* and releases bh */
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 809) if (err)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 810) goto out;
9a53c3a783c2f fs/vfat/namei.c (Dave Hansen 2006-09-30 23:29:03 -0700 811) drop_nlink(dir);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 812)
ce71ec3684036 fs/vfat/namei.c (Dave Hansen 2006-09-30 23:29:06 -0700 813) clear_nlink(inode);
cd83f6b194e95 fs/fat/namei_vfat.c (Frank Sorenson 2018-10-30 15:06:57 -0700 814) fat_truncate_time(inode, NULL, S_ATIME|S_MTIME);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 815) fat_detach(inode);
2489dbabea80e fs/fat/namei_vfat.c (Jeff Layton 2017-12-11 06:35:09 -0500 816) vfat_d_version_set(dentry, inode_query_iversion(dir));
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 817) out:
e40b34c792153 fs/fat/namei_vfat.c (Marco Stornelli 2012-10-06 12:40:03 +0200 818) mutex_unlock(&MSDOS_SB(sb)->s_lock);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 819)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 820) return err;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 821) }
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 822)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 823) static int vfat_unlink(struct inode *dir, struct dentry *dentry)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 824) {
2b0143b5c986b fs/fat/namei_vfat.c (David Howells 2015-03-17 22:25:59 +0000 825) struct inode *inode = d_inode(dentry);
8f5934278d1d8 fs/vfat/namei.c (Linus Torvalds 2008-05-19 19:53:01 -0700 826) struct super_block *sb = dir->i_sb;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 827) struct fat_slot_info sinfo;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 828) int err;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 829)
e40b34c792153 fs/fat/namei_vfat.c (Marco Stornelli 2012-10-06 12:40:03 +0200 830) mutex_lock(&MSDOS_SB(sb)->s_lock);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 831)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 832) err = vfat_find(dir, &dentry->d_name, &sinfo);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 833) if (err)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 834) goto out;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 835)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 836) err = fat_remove_entries(dir, &sinfo); /* and releases bh */
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 837) if (err)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 838) goto out;
ce71ec3684036 fs/vfat/namei.c (Dave Hansen 2006-09-30 23:29:06 -0700 839) clear_nlink(inode);
cd83f6b194e95 fs/fat/namei_vfat.c (Frank Sorenson 2018-10-30 15:06:57 -0700 840) fat_truncate_time(inode, NULL, S_ATIME|S_MTIME);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 841) fat_detach(inode);
2489dbabea80e fs/fat/namei_vfat.c (Jeff Layton 2017-12-11 06:35:09 -0500 842) vfat_d_version_set(dentry, inode_query_iversion(dir));
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 843) out:
e40b34c792153 fs/fat/namei_vfat.c (Marco Stornelli 2012-10-06 12:40:03 +0200 844) mutex_unlock(&MSDOS_SB(sb)->s_lock);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 845)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 846) return err;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 847) }
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 848)
549c7297717c3 fs/fat/namei_vfat.c (Christian Brauner 2021-01-21 14:19:43 +0100 849) static int vfat_mkdir(struct user_namespace *mnt_userns, struct inode *dir,
549c7297717c3 fs/fat/namei_vfat.c (Christian Brauner 2021-01-21 14:19:43 +0100 850) struct dentry *dentry, umode_t mode)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 851) {
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 852) struct super_block *sb = dir->i_sb;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 853) struct inode *inode;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 854) struct fat_slot_info sinfo;
95582b0083883 fs/fat/namei_vfat.c (Deepa Dinamani 2018-05-08 19:36:02 -0700 855) struct timespec64 ts;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 856) int err, cluster;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 857)
e40b34c792153 fs/fat/namei_vfat.c (Marco Stornelli 2012-10-06 12:40:03 +0200 858) mutex_lock(&MSDOS_SB(sb)->s_lock);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 859)
02027d42c3f74 fs/fat/namei_vfat.c (Deepa Dinamani 2016-09-14 07:48:05 -0700 860) ts = current_time(dir);
f423420c23899 fs/fat/namei_vfat.c (Arnd Bergmann 2018-08-21 21:59:48 -0700 861) cluster = fat_alloc_new_dir(dir, &ts);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 862) if (cluster < 0) {
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 863) err = cluster;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 864) goto out;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 865) }
f423420c23899 fs/fat/namei_vfat.c (Arnd Bergmann 2018-08-21 21:59:48 -0700 866) err = vfat_add_entry(dir, &dentry->d_name, 1, cluster, &ts, &sinfo);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 867) if (err)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 868) goto out_free;
2489dbabea80e fs/fat/namei_vfat.c (Jeff Layton 2017-12-11 06:35:09 -0500 869) inode_inc_iversion(dir);
d8c76e6f45c11 fs/vfat/namei.c (Dave Hansen 2006-09-30 23:29:04 -0700 870) inc_nlink(dir);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 871)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 872) inode = fat_build_inode(sb, sinfo.de, sinfo.i_pos);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 873) brelse(sinfo.bh);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 874) if (IS_ERR(inode)) {
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 875) err = PTR_ERR(inode);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 876) /* the directory was completed, just return a error */
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 877) goto out;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 878) }
2489dbabea80e fs/fat/namei_vfat.c (Jeff Layton 2017-12-11 06:35:09 -0500 879) inode_inc_iversion(inode);
bfe8684869601 fs/fat/namei_vfat.c (Miklos Szeredi 2011-10-28 14:13:29 +0200 880) set_nlink(inode, 2);
cd83f6b194e95 fs/fat/namei_vfat.c (Frank Sorenson 2018-10-30 15:06:57 -0700 881) fat_truncate_time(inode, &ts, S_ATIME|S_CTIME|S_MTIME);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 882) /* timestamp is already written, so mark_inode_dirty() is unneeded. */
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 883)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 884) d_instantiate(dentry, inode);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 885)
e40b34c792153 fs/fat/namei_vfat.c (Marco Stornelli 2012-10-06 12:40:03 +0200 886) mutex_unlock(&MSDOS_SB(sb)->s_lock);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 887) return 0;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 888)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 889) out_free:
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 890) fat_free_clusters(dir, cluster);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 891) out:
e40b34c792153 fs/fat/namei_vfat.c (Marco Stornelli 2012-10-06 12:40:03 +0200 892) mutex_unlock(&MSDOS_SB(sb)->s_lock);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 893) return err;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 894) }
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 895)
549c7297717c3 fs/fat/namei_vfat.c (Christian Brauner 2021-01-21 14:19:43 +0100 896) static int vfat_rename(struct user_namespace *mnt_userns, struct inode *old_dir,
549c7297717c3 fs/fat/namei_vfat.c (Christian Brauner 2021-01-21 14:19:43 +0100 897) struct dentry *old_dentry, struct inode *new_dir,
549c7297717c3 fs/fat/namei_vfat.c (Christian Brauner 2021-01-21 14:19:43 +0100 898) struct dentry *new_dentry, unsigned int flags)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 899) {
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 900) struct buffer_head *dotdot_bh;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 901) struct msdos_dir_entry *dotdot_de;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 902) struct inode *old_inode, *new_inode;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 903) struct fat_slot_info old_sinfo, sinfo;
95582b0083883 fs/fat/namei_vfat.c (Deepa Dinamani 2018-05-08 19:36:02 -0700 904) struct timespec64 ts;
7669e8fb09da4 fs/fat/namei_vfat.c (Steven J. Magnani 2012-10-04 17:14:45 -0700 905) loff_t new_i_pos;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 906) int err, is_dir, update_dotdot, corrupt = 0;
8f5934278d1d8 fs/vfat/namei.c (Linus Torvalds 2008-05-19 19:53:01 -0700 907) struct super_block *sb = old_dir->i_sb;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 908)
f03b8ad8d3863 fs/fat/namei_vfat.c (Miklos Szeredi 2016-09-27 11:03:57 +0200 909) if (flags & ~RENAME_NOREPLACE)
f03b8ad8d3863 fs/fat/namei_vfat.c (Miklos Szeredi 2016-09-27 11:03:57 +0200 910) return -EINVAL;
f03b8ad8d3863 fs/fat/namei_vfat.c (Miklos Szeredi 2016-09-27 11:03:57 +0200 911)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 912) old_sinfo.bh = sinfo.bh = dotdot_bh = NULL;
2b0143b5c986b fs/fat/namei_vfat.c (David Howells 2015-03-17 22:25:59 +0000 913) old_inode = d_inode(old_dentry);
2b0143b5c986b fs/fat/namei_vfat.c (David Howells 2015-03-17 22:25:59 +0000 914) new_inode = d_inode(new_dentry);
e40b34c792153 fs/fat/namei_vfat.c (Marco Stornelli 2012-10-06 12:40:03 +0200 915) mutex_lock(&MSDOS_SB(sb)->s_lock);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 916) err = vfat_find(old_dir, &old_dentry->d_name, &old_sinfo);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 917) if (err)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 918) goto out;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 919)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 920) is_dir = S_ISDIR(old_inode->i_mode);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 921) update_dotdot = (is_dir && old_dir != new_dir);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 922) if (update_dotdot) {
7669e8fb09da4 fs/fat/namei_vfat.c (Steven J. Magnani 2012-10-04 17:14:45 -0700 923) if (fat_get_dotdot_entry(old_inode, &dotdot_bh, &dotdot_de)) {
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 924) err = -EIO;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 925) goto out;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 926) }
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 927) }
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 928)
02027d42c3f74 fs/fat/namei_vfat.c (Deepa Dinamani 2016-09-14 07:48:05 -0700 929) ts = current_time(old_dir);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 930) if (new_inode) {
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 931) if (is_dir) {
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 932) err = fat_dir_empty(new_inode);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 933) if (err)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 934) goto out;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 935) }
9131dd4256f95 fs/vfat/namei.c (OGAWA Hirofumi 2005-10-30 15:03:50 -0800 936) new_i_pos = MSDOS_I(new_inode)->i_pos;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 937) fat_detach(new_inode);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 938) } else {
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 939) err = vfat_add_entry(new_dir, &new_dentry->d_name, is_dir, 0,
f423420c23899 fs/fat/namei_vfat.c (Arnd Bergmann 2018-08-21 21:59:48 -0700 940) &ts, &sinfo);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 941) if (err)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 942) goto out;
9131dd4256f95 fs/vfat/namei.c (OGAWA Hirofumi 2005-10-30 15:03:50 -0800 943) new_i_pos = sinfo.i_pos;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 944) }
2489dbabea80e fs/fat/namei_vfat.c (Jeff Layton 2017-12-11 06:35:09 -0500 945) inode_inc_iversion(new_dir);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 946)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 947) fat_detach(old_inode);
9131dd4256f95 fs/vfat/namei.c (OGAWA Hirofumi 2005-10-30 15:03:50 -0800 948) fat_attach(old_inode, new_i_pos);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 949) if (IS_DIRSYNC(new_dir)) {
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 950) err = fat_sync_inode(old_inode);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 951) if (err)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 952) goto error_inode;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 953) } else
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 954) mark_inode_dirty(old_inode);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 955)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 956) if (update_dotdot) {
a943ed71c9171 fs/fat/namei_vfat.c (Steven J. Magnani 2012-07-30 14:42:13 -0700 957) fat_set_start(dotdot_de, MSDOS_I(new_dir)->i_logstart);
b522412aeabad fs/fat/namei_vfat.c (Al Viro 2009-06-07 13:44:36 -0400 958) mark_buffer_dirty_inode(dotdot_bh, old_inode);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 959) if (IS_DIRSYNC(new_dir)) {
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 960) err = sync_dirty_buffer(dotdot_bh);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 961) if (err)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 962) goto error_dotdot;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 963) }
9a53c3a783c2f fs/vfat/namei.c (Dave Hansen 2006-09-30 23:29:03 -0700 964) drop_nlink(old_dir);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 965) if (!new_inode)
d8c76e6f45c11 fs/vfat/namei.c (Dave Hansen 2006-09-30 23:29:04 -0700 966) inc_nlink(new_dir);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 967) }
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 968)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 969) err = fat_remove_entries(old_dir, &old_sinfo); /* and releases bh */
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 970) old_sinfo.bh = NULL;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 971) if (err)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 972) goto error_dotdot;
2489dbabea80e fs/fat/namei_vfat.c (Jeff Layton 2017-12-11 06:35:09 -0500 973) inode_inc_iversion(old_dir);
cd83f6b194e95 fs/fat/namei_vfat.c (Frank Sorenson 2018-10-30 15:06:57 -0700 974) fat_truncate_time(old_dir, &ts, S_CTIME|S_MTIME);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 975) if (IS_DIRSYNC(old_dir))
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 976) (void)fat_sync_inode(old_dir);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 977) else
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 978) mark_inode_dirty(old_dir);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 979)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 980) if (new_inode) {
9a53c3a783c2f fs/vfat/namei.c (Dave Hansen 2006-09-30 23:29:03 -0700 981) drop_nlink(new_inode);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 982) if (is_dir)
9a53c3a783c2f fs/vfat/namei.c (Dave Hansen 2006-09-30 23:29:03 -0700 983) drop_nlink(new_inode);
cd83f6b194e95 fs/fat/namei_vfat.c (Frank Sorenson 2018-10-30 15:06:57 -0700 984) fat_truncate_time(new_inode, &ts, S_CTIME);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 985) }
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 986) out:
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 987) brelse(sinfo.bh);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 988) brelse(dotdot_bh);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 989) brelse(old_sinfo.bh);
e40b34c792153 fs/fat/namei_vfat.c (Marco Stornelli 2012-10-06 12:40:03 +0200 990) mutex_unlock(&MSDOS_SB(sb)->s_lock);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 991)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 992) return err;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 993)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 994) error_dotdot:
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 995) /* data cluster is shared, serious corruption */
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 996) corrupt = 1;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 997)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 998) if (update_dotdot) {
a943ed71c9171 fs/fat/namei_vfat.c (Steven J. Magnani 2012-07-30 14:42:13 -0700 999) fat_set_start(dotdot_de, MSDOS_I(old_dir)->i_logstart);
b522412aeabad fs/fat/namei_vfat.c (Al Viro 2009-06-07 13:44:36 -0400 1000) mark_buffer_dirty_inode(dotdot_bh, old_inode);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 1001) corrupt |= sync_dirty_buffer(dotdot_bh);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 1002) }
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 1003) error_inode:
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 1004) fat_detach(old_inode);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 1005) fat_attach(old_inode, old_sinfo.i_pos);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 1006) if (new_inode) {
9131dd4256f95 fs/vfat/namei.c (OGAWA Hirofumi 2005-10-30 15:03:50 -0800 1007) fat_attach(new_inode, new_i_pos);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 1008) if (corrupt)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 1009) corrupt |= fat_sync_inode(new_inode);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 1010) } else {
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 1011) /*
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 1012) * If new entry was not sharing the data cluster, it
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 1013) * shouldn't be serious corruption.
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 1014) */
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 1015) int err2 = fat_remove_entries(new_dir, &sinfo);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 1016) if (corrupt)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 1017) corrupt |= err2;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 1018) sinfo.bh = NULL;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 1019) }
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 1020) if (corrupt < 0) {
85c7859190c41 fs/fat/namei_vfat.c (Denis Karpov 2009-06-04 02:34:22 +0900 1021) fat_fs_error(new_dir->i_sb,
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 1022) "%s: Filesystem corrupted (i_pos %lld)",
8e24eea728068 fs/vfat/namei.c (Harvey Harrison 2008-04-30 00:55:09 -0700 1023) __func__, sinfo.i_pos);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 1024) }
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 1025) goto out;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 1026) }
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 1027)
c5ef1c42c51b1 fs/vfat/namei.c (Arjan van de Ven 2007-02-12 00:55:40 -0800 1028) static const struct inode_operations vfat_dir_inode_operations = {
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 1029) .create = vfat_create,
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 1030) .lookup = vfat_lookup,
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 1031) .unlink = vfat_unlink,
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 1032) .mkdir = vfat_mkdir,
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 1033) .rmdir = vfat_rmdir,
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 1034) .rename = vfat_rename,
1278fdd34b122 fs/vfat/namei.c (OGAWA Hirofumi 2008-04-28 02:16:25 -0700 1035) .setattr = fat_setattr,
da63fc7ce63b4 fs/vfat/namei.c (OGAWA Hirofumi 2006-11-16 01:19:28 -0800 1036) .getattr = fat_getattr,
6bb885ecd7467 fs/fat/namei_vfat.c (Frank Sorenson 2018-10-30 15:06:53 -0700 1037) .update_time = fat_update_time,
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 1038) };
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 1039)
3d23985d6cfa7 fs/fat/namei_vfat.c (Al Viro 2010-12-18 10:44:00 -0500 1040) static void setup(struct super_block *sb)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 1041) {
384f5c96ea05a fs/fat/namei_vfat.c (OGAWA Hirofumi 2011-04-12 21:08:37 +0900 1042) MSDOS_SB(sb)->dir_ops = &vfat_dir_inode_operations;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 1043) if (MSDOS_SB(sb)->options.name_check != 's')
3d23985d6cfa7 fs/fat/namei_vfat.c (Al Viro 2010-12-18 10:44:00 -0500 1044) sb->s_d_op = &vfat_ci_dentry_ops;
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 1045) else
3d23985d6cfa7 fs/fat/namei_vfat.c (Al Viro 2010-12-18 10:44:00 -0500 1046) sb->s_d_op = &vfat_dentry_ops;
3d23985d6cfa7 fs/fat/namei_vfat.c (Al Viro 2010-12-18 10:44:00 -0500 1047) }
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 1048)
3d23985d6cfa7 fs/fat/namei_vfat.c (Al Viro 2010-12-18 10:44:00 -0500 1049) static int vfat_fill_super(struct super_block *sb, void *data, int silent)
3d23985d6cfa7 fs/fat/namei_vfat.c (Al Viro 2010-12-18 10:44:00 -0500 1050) {
384f5c96ea05a fs/fat/namei_vfat.c (OGAWA Hirofumi 2011-04-12 21:08:37 +0900 1051) return fat_fill_super(sb, data, silent, 1, setup);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 1052) }
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 1053)
152a083666710 fs/fat/namei_vfat.c (Al Viro 2010-07-25 00:46:55 +0400 1054) static struct dentry *vfat_mount(struct file_system_type *fs_type,
454e2398be9b9 fs/vfat/namei.c (David Howells 2006-06-23 02:02:57 -0700 1055) int flags, const char *dev_name,
152a083666710 fs/fat/namei_vfat.c (Al Viro 2010-07-25 00:46:55 +0400 1056) void *data)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 1057) {
152a083666710 fs/fat/namei_vfat.c (Al Viro 2010-07-25 00:46:55 +0400 1058) return mount_bdev(fs_type, flags, dev_name, data, vfat_fill_super);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 1059) }
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 1060)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 1061) static struct file_system_type vfat_fs_type = {
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 1062) .owner = THIS_MODULE,
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 1063) .name = "vfat",
152a083666710 fs/fat/namei_vfat.c (Al Viro 2010-07-25 00:46:55 +0400 1064) .mount = vfat_mount,
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 1065) .kill_sb = kill_block_super,
4b78993681083 fs/fat/namei_vfat.c (Christian Brauner 2021-01-21 14:19:56 +0100 1066) .fs_flags = FS_REQUIRES_DEV | FS_ALLOW_IDMAP,
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 1067) };
7f78e03513940 fs/fat/namei_vfat.c (Eric W. Biederman 2013-03-02 19:39:14 -0800 1068) MODULE_ALIAS_FS("vfat");
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 1069)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 1070) static int __init init_vfat_fs(void)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 1071) {
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 1072) return register_filesystem(&vfat_fs_type);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 1073) }
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 1074)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 1075) static void __exit exit_vfat_fs(void)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 1076) {
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 1077) unregister_filesystem(&vfat_fs_type);
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 1078) }
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 1079)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 1080) MODULE_LICENSE("GPL");
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 1081) MODULE_DESCRIPTION("VFAT filesystem support");
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 1082) MODULE_AUTHOR("Gordon Chaffee");
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 1083)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 1084) module_init(init_vfat_fs)
^1da177e4c3f4 fs/vfat/namei.c (Linus Torvalds 2005-04-16 15:20:36 -0700 1085) module_exit(exit_vfat_fs)