Rejected reserved files names when option windows_names is set
Windows applies legacy restrictions to file names, so when the option windows_names is applied, reject the same reserved names, which are CON, PRN, AUX, NUL, COM1..COM9, and LPT1..LPT9edge.strict_endians
parent
e5ea399ee6
commit
543b17b7ef
|
@ -69,6 +69,8 @@ extern ntfschar *ntfs_str2ucs(const char *s, int *len);
|
|||
extern void ntfs_ucsfree(ntfschar *ucs);
|
||||
|
||||
extern BOOL ntfs_forbidden_chars(const ntfschar *name, int len);
|
||||
extern BOOL ntfs_forbidden_names(ntfs_volume *vol,
|
||||
const ntfschar *name, int len);
|
||||
extern BOOL ntfs_collapsible_chars(ntfs_volume *vol,
|
||||
const ntfschar *shortname, int shortlen,
|
||||
const ntfschar *longname, int longlen);
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* Copyright (c) 2004-2005 Richard Russon
|
||||
* Copyright (c) 2004-2008 Szabolcs Szakacsits
|
||||
* Copyright (c) 2005-2007 Yura Pakhuchiy
|
||||
* Copyright (c) 2008-2010 Jean-Pierre Andre
|
||||
* Copyright (c) 2008-2014 Jean-Pierre Andre
|
||||
*
|
||||
* This program/include file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as published
|
||||
|
@ -2650,7 +2650,8 @@ int ntfs_set_ntfs_dos_name(ntfs_inode *ni, ntfs_inode *dir_ni,
|
|||
if (shortlen > MAX_DOS_NAME_LENGTH)
|
||||
shortlen = MAX_DOS_NAME_LENGTH;
|
||||
/* make sure the short name has valid chars */
|
||||
if ((shortlen < 0) || ntfs_forbidden_chars(shortname,shortlen)) {
|
||||
if ((shortlen < 0)
|
||||
|| ntfs_forbidden_names(ni->vol,shortname,shortlen)) {
|
||||
ntfs_inode_close_in_dir(ni,dir_ni);
|
||||
ntfs_inode_close(dir_ni);
|
||||
res = -errno;
|
||||
|
@ -2661,7 +2662,7 @@ int ntfs_set_ntfs_dos_name(ntfs_inode *ni, ntfs_inode *dir_ni,
|
|||
if (longlen > 0) {
|
||||
oldlen = get_dos_name(ni, dnum, oldname);
|
||||
if ((oldlen >= 0)
|
||||
&& !ntfs_forbidden_chars(longname, longlen)) {
|
||||
&& !ntfs_forbidden_names(ni->vol, longname, longlen)) {
|
||||
if (oldlen > 0) {
|
||||
if (flags & XATTR_CREATE) {
|
||||
res = -1;
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* Copyright (c) 2000-2004 Anton Altaparmakov
|
||||
* Copyright (c) 2002-2009 Szabolcs Szakacsits
|
||||
* Copyright (c) 2008-2011 Jean-Pierre Andre
|
||||
* Copyright (c) 2008-2014 Jean-Pierre Andre
|
||||
* Copyright (c) 2008 Bernhard Kaindl
|
||||
*
|
||||
* This program/include file is free software; you can redistribute it and/or
|
||||
|
@ -1367,7 +1367,7 @@ BOOL ntfs_forbidden_chars(const ntfschar *name, int len)
|
|||
BOOL forbidden;
|
||||
int ch;
|
||||
int i;
|
||||
u32 mainset = (1L << ('\"' - 0x20))
|
||||
static const u32 mainset = (1L << ('\"' - 0x20))
|
||||
| (1L << ('*' - 0x20))
|
||||
| (1L << ('/' - 0x20))
|
||||
| (1L << (':' - 0x20))
|
||||
|
@ -1376,8 +1376,8 @@ BOOL ntfs_forbidden_chars(const ntfschar *name, int len)
|
|||
| (1L << ('?' - 0x20));
|
||||
|
||||
forbidden = (len == 0)
|
||||
|| (le16_to_cpu(name[len-1]) == ' ')
|
||||
|| (le16_to_cpu(name[len-1]) == '.');
|
||||
|| (name[len-1] == const_cpu_to_le16(' '))
|
||||
|| (name[len-1] == const_cpu_to_le16('.'));
|
||||
for (i=0; i<len; i++) {
|
||||
ch = le16_to_cpu(name[i]);
|
||||
if ((ch < 0x20)
|
||||
|
@ -1392,6 +1392,92 @@ BOOL ntfs_forbidden_chars(const ntfschar *name, int len)
|
|||
return (forbidden);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check whether a name contains no forbidden chars and
|
||||
* is not a reserved name for DOS or Win32 use
|
||||
*
|
||||
* The reserved names are CON, PRN, AUX, NUL, COM1..COM9, LPT1..LPT9
|
||||
* with no suffix or any suffix.
|
||||
*
|
||||
* If the name is forbidden, errno is set to EINVAL
|
||||
*/
|
||||
|
||||
BOOL ntfs_forbidden_names(ntfs_volume *vol, const ntfschar *name, int len)
|
||||
{
|
||||
BOOL forbidden;
|
||||
int h;
|
||||
static const ntfschar dot = const_cpu_to_le16('.');
|
||||
static const ntfschar con[] = { const_cpu_to_le16('c'),
|
||||
const_cpu_to_le16('o'), const_cpu_to_le16('n') };
|
||||
static const ntfschar prn[] = { const_cpu_to_le16('p'),
|
||||
const_cpu_to_le16('r'), const_cpu_to_le16('n') };
|
||||
static const ntfschar aux[] = { const_cpu_to_le16('a'),
|
||||
const_cpu_to_le16('u'), const_cpu_to_le16('x') };
|
||||
static const ntfschar nul[] = { const_cpu_to_le16('n'),
|
||||
const_cpu_to_le16('u'), const_cpu_to_le16('l') };
|
||||
static const ntfschar com[] = { const_cpu_to_le16('c'),
|
||||
const_cpu_to_le16('o'), const_cpu_to_le16('m') };
|
||||
static const ntfschar lpt[] = { const_cpu_to_le16('l'),
|
||||
const_cpu_to_le16('p'), const_cpu_to_le16('t') };
|
||||
|
||||
forbidden = ntfs_forbidden_chars(name, len);
|
||||
if (!forbidden && (len >= 3)) {
|
||||
/*
|
||||
* Rough hash check to tell whether the first couple of chars
|
||||
* may be one of CO PR AU NU LP or lowercase variants.
|
||||
*/
|
||||
h = ((le16_to_cpu(name[0]) & 31)*48)
|
||||
^ ((le16_to_cpu(name[1]) & 31)*165);
|
||||
if ((h % 23) == 17) {
|
||||
/* do a full check, depending on the third char */
|
||||
switch (le16_to_cpu(name[2]) & ~0x20) {
|
||||
case 'N' :
|
||||
if (((len == 3) || (name[3] == dot))
|
||||
&& (!ntfs_ucsncasecmp(name, con, 3,
|
||||
vol->upcase, vol->upcase_len)
|
||||
|| !ntfs_ucsncasecmp(name, prn, 3,
|
||||
vol->upcase, vol->upcase_len)))
|
||||
forbidden = TRUE;
|
||||
break;
|
||||
case 'X' :
|
||||
if (((len == 3) || (name[3] == dot))
|
||||
&& !ntfs_ucsncasecmp(name, aux, 3,
|
||||
vol->upcase, vol->upcase_len))
|
||||
forbidden = TRUE;
|
||||
break;
|
||||
case 'L' :
|
||||
if (((len == 3) || (name[3] == dot))
|
||||
&& !ntfs_ucsncasecmp(name, nul, 3,
|
||||
vol->upcase, vol->upcase_len))
|
||||
forbidden = TRUE;
|
||||
break;
|
||||
case 'M' :
|
||||
if ((len > 3)
|
||||
&& (le16_to_cpu(name[3]) >= '1')
|
||||
&& (le16_to_cpu(name[3]) <= '9')
|
||||
&& ((len == 4) || (name[4] == dot))
|
||||
&& !ntfs_ucsncasecmp(name, com, 3,
|
||||
vol->upcase, vol->upcase_len))
|
||||
forbidden = TRUE;
|
||||
break;
|
||||
case 'T' :
|
||||
if ((len > 3)
|
||||
&& (le16_to_cpu(name[3]) >= '1')
|
||||
&& (le16_to_cpu(name[3]) <= '9')
|
||||
&& ((len == 4) || (name[4] == dot))
|
||||
&& !ntfs_ucsncasecmp(name, lpt, 3,
|
||||
vol->upcase, vol->upcase_len))
|
||||
forbidden = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (forbidden)
|
||||
errno = EINVAL;
|
||||
return (forbidden);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check whether the same name can be used as a DOS and
|
||||
* a Win32 name
|
||||
|
|
|
@ -1851,7 +1851,7 @@ static int ntfs_fuse_create(fuse_req_t req, fuse_ino_t parent, const char *name,
|
|||
uname_len = ntfs_mbstoucs(name, &uname);
|
||||
if ((uname_len < 0)
|
||||
|| (ctx->windows_names
|
||||
&& ntfs_forbidden_chars(uname,uname_len))) {
|
||||
&& ntfs_forbidden_names(ctx->vol,uname,uname_len))) {
|
||||
res = -errno;
|
||||
goto exit;
|
||||
}
|
||||
|
@ -2067,7 +2067,7 @@ static int ntfs_fuse_newlink(fuse_req_t req __attribute__((unused)),
|
|||
uname_len = ntfs_mbstoucs(newname, &uname);
|
||||
if ((uname_len < 0)
|
||||
|| (ctx->windows_names
|
||||
&& ntfs_forbidden_chars(uname,uname_len))) {
|
||||
&& ntfs_forbidden_names(ctx->vol,uname,uname_len))) {
|
||||
res = -errno;
|
||||
goto exit;
|
||||
}
|
||||
|
|
|
@ -250,10 +250,24 @@ adjusted to the latest name.
|
|||
.TP
|
||||
.B windows_names
|
||||
This option prevents files, directories and extended attributes to be
|
||||
created with a name not allowed by windows, either because it contains
|
||||
some not allowed character (which are the nine characters " * / : < > ? \\ | and
|
||||
those whose code is less than 0x20) or because the last character is a space
|
||||
or a dot. Existing such files can still be read (and renamed).
|
||||
created with a name not allowed by windows, because
|
||||
.RS
|
||||
.RS
|
||||
.sp
|
||||
- it contains some not allowed character,
|
||||
.br
|
||||
- or the last character is a space or a dot,
|
||||
.br
|
||||
- or the name is reserved.
|
||||
.sp
|
||||
.RE
|
||||
The forbidden characters are the nine characters " * / : < > ? \\ | and
|
||||
those whose code is less than 0x20, and
|
||||
the reserved names are CON, PRN, AUX, NUL, COM1..COM9, LPT1..LPT9,
|
||||
with no suffix or followed by a dot.
|
||||
.sp
|
||||
Existing such files can still be read (and renamed).
|
||||
.RE
|
||||
.TP
|
||||
.B allow_other
|
||||
This option overrides the security measure restricting file access
|
||||
|
|
|
@ -1636,7 +1636,7 @@ static int ntfs_fuse_create(const char *org_path, mode_t typemode, dev_t dev,
|
|||
uname_len = ntfs_mbstoucs(name, &uname);
|
||||
if ((uname_len < 0)
|
||||
|| (ctx->windows_names
|
||||
&& ntfs_forbidden_chars(uname,uname_len))) {
|
||||
&& ntfs_forbidden_names(ctx->vol,uname,uname_len))) {
|
||||
res = -errno;
|
||||
goto exit;
|
||||
}
|
||||
|
@ -1840,7 +1840,8 @@ static int ntfs_fuse_mknod_common(const char *org_path, mode_t mode, dev_t dev,
|
|||
if (stream_name_len
|
||||
&& (!S_ISREG(mode)
|
||||
|| (ctx->windows_names
|
||||
&& ntfs_forbidden_chars(stream_name,stream_name_len)))) {
|
||||
&& ntfs_forbidden_names(ctx->vol,stream_name,
|
||||
stream_name_len)))) {
|
||||
res = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
|
@ -1909,7 +1910,7 @@ static int ntfs_fuse_link(const char *old_path, const char *new_path)
|
|||
uname_len = ntfs_mbstoucs(name, &uname);
|
||||
if ((uname_len < 0)
|
||||
|| (ctx->windows_names
|
||||
&& ntfs_forbidden_chars(uname,uname_len))) {
|
||||
&& ntfs_forbidden_names(ctx->vol,uname,uname_len))) {
|
||||
res = -errno;
|
||||
goto exit;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue