summaryrefslogtreecommitdiffstats
path: root/fs/vfat/namei.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/vfat/namei.c')
-rw-r--r--fs/vfat/namei.c37
1 files changed, 16 insertions, 21 deletions
diff --git a/fs/vfat/namei.c b/fs/vfat/namei.c
index cd450bea9f1a..5b66162d0747 100644
--- a/fs/vfat/namei.c
+++ b/fs/vfat/namei.c
@@ -176,15 +176,10 @@ static inline int vfat_is_used_badchars(const wchar_t *s, int len)
for (i = 0; i < len; i++)
if (vfat_bad_char(s[i]))
return -EINVAL;
- return 0;
-}
-static int vfat_valid_longname(const unsigned char *name, unsigned int len)
-{
- if (name[len - 1] == ' ')
+ if (s[i - 1] == ' ') /* last character cannot be space */
return -EINVAL;
- if (len >= 256)
- return -ENAMETOOLONG;
+
return 0;
}
@@ -477,7 +472,7 @@ xlate_to_uni(const unsigned char *name, int len, unsigned char *outname,
if (utf8) {
int name_len = strlen(name);
- *outlen = utf8_mbstowcs((wchar_t *)outname, name, PAGE_SIZE);
+ *outlen = utf8_mbstowcs((wchar_t *)outname, name, PATH_MAX);
/*
* We stripped '.'s before and set len appropriately,
@@ -485,11 +480,14 @@ xlate_to_uni(const unsigned char *name, int len, unsigned char *outname,
*/
*outlen -= (name_len - len);
+ if (*outlen > 255)
+ return -ENAMETOOLONG;
+
op = &outname[*outlen * sizeof(wchar_t)];
} else {
if (nls) {
for (i = 0, ip = name, op = outname, *outlen = 0;
- i < len && *outlen <= 260;
+ i < len && *outlen <= 255;
*outlen += 1)
{
if (escape && (*ip == ':')) {
@@ -525,18 +523,20 @@ xlate_to_uni(const unsigned char *name, int len, unsigned char *outname,
op += 2;
}
}
+ if (i < len)
+ return -ENAMETOOLONG;
} else {
for (i = 0, ip = name, op = outname, *outlen = 0;
- i < len && *outlen <= 260;
+ i < len && *outlen <= 255;
i++, *outlen += 1)
{
*op++ = *ip++;
*op++ = 0;
}
+ if (i < len)
+ return -ENAMETOOLONG;
}
}
- if (*outlen > 260)
- return -ENAMETOOLONG;
*longlen = *outlen;
if (*outlen % 13) {
@@ -565,7 +565,6 @@ static int vfat_build_slots(struct inode *dir, const unsigned char *name,
struct fat_mount_options *opts = &sbi->options;
struct msdos_dir_slot *ps;
struct msdos_dir_entry *de;
- unsigned long page;
unsigned char cksum, lcase;
unsigned char msdos_name[MSDOS_NAME];
wchar_t *uname;
@@ -574,15 +573,11 @@ static int vfat_build_slots(struct inode *dir, const unsigned char *name,
loff_t offset;
*nr_slots = 0;
- err = vfat_valid_longname(name, len);
- if (err)
- return err;
- page = __get_free_page(GFP_KERNEL);
- if (!page)
+ uname = __getname();
+ if (!uname)
return -ENOMEM;
- uname = (wchar_t *)page;
err = xlate_to_uni(name, len, (unsigned char *)uname, &ulen, &usize,
opts->unicode_xlate, opts->utf8, sbi->nls_io);
if (err)
@@ -634,7 +629,7 @@ shortname:
de->starthi = cpu_to_le16(cluster >> 16);
de->size = 0;
out_free:
- free_page(page);
+ __putname(uname);
return err;
}
@@ -1003,7 +998,7 @@ static const struct inode_operations vfat_dir_inode_operations = {
.mkdir = vfat_mkdir,
.rmdir = vfat_rmdir,
.rename = vfat_rename,
- .setattr = fat_notify_change,
+ .setattr = fat_setattr,
.getattr = fat_getattr,
};