mirror of
https://git.code.sf.net/p/ntfs-3g/ntfs-3g.git
synced 2024-11-23 10:04:00 +08:00
Allowed names with trailing dot or space on conditions
Windows places filenames with a trailing dot or space in the Win32 namespace and allows setting DOS names on such files. This is true even though on Windows such filenames can only be created and accessed using WinNT-style paths and will confuse most Windows software. Regardless, because libntfs-3g did not allow setting DOS names on such files, in some cases it was impossible to correctly restore, using libntfs-3g, a directory structure that was created under Windows. Update ntfs_set_ntfs_dos_name() to permit operating on a file that has a long name with a trailing dot or space. But continue to forbid creating such names on a filesystem FUSE-mounted with the windows_name option. Additionally, continue to forbid a trailing a dot or space in DOS names; this matches the Windows behavior. (contributed by Eric Biggers)
This commit is contained in:
parent
1178a7a801
commit
17b56ccfa2
@ -1068,12 +1068,17 @@ typedef enum {
|
||||
FILE_NAME_WIN32 = 0x01,
|
||||
/* The standard WinNT/2k NTFS long filenames. Case insensitive.
|
||||
All Unicode chars except: '\0', '"', '*', '/', ':', '<',
|
||||
'>', '?', '\' and '|'. Further, names cannot end with a '.'
|
||||
or a space. */
|
||||
'>', '?', '\' and '|'. Trailing dots and spaces are allowed,
|
||||
even though on Windows a filename with such a suffix can only
|
||||
be created and accessed using a WinNT-style path, i.e.
|
||||
\\?\-prefixed. (If a regular path is used, Windows will
|
||||
strip the trailing dots and spaces, which makes such
|
||||
filenames incompatible with most Windows software.) */
|
||||
FILE_NAME_DOS = 0x02,
|
||||
/* The standard DOS filenames (8.3 format). Uppercase only.
|
||||
All 8-bit characters greater space, except: '"', '*', '+',
|
||||
',', '/', ':', ';', '<', '=', '>', '?' and '\'. */
|
||||
',', '/', ':', ';', '<', '=', '>', '?' and '\'. Trailing
|
||||
dots and spaces are forbidden. */
|
||||
FILE_NAME_WIN32_AND_DOS = 0x03,
|
||||
/* 3 means that both the Win32 and the DOS filenames are
|
||||
identical and hence have been saved in this single filename
|
||||
|
@ -68,9 +68,9 @@ 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_chars(const ntfschar *name, int len, BOOL strict);
|
||||
extern BOOL ntfs_forbidden_names(ntfs_volume *vol,
|
||||
const ntfschar *name, int len);
|
||||
const ntfschar *name, int len, BOOL strict);
|
||||
extern BOOL ntfs_collapsible_chars(ntfs_volume *vol,
|
||||
const ntfschar *shortname, int shortlen,
|
||||
const ntfschar *longname, int longlen);
|
||||
|
@ -2654,9 +2654,12 @@ int ntfs_set_ntfs_dos_name(ntfs_inode *ni, ntfs_inode *dir_ni,
|
||||
shortlen = ntfs_mbstoucs(newname, &shortname);
|
||||
if (shortlen > MAX_DOS_NAME_LENGTH)
|
||||
shortlen = MAX_DOS_NAME_LENGTH;
|
||||
/* make sure the short name has valid chars */
|
||||
|
||||
/* Make sure the short name has valid chars.
|
||||
* Note: the short name cannot end with dot or space, but the
|
||||
* corresponding long name can. */
|
||||
if ((shortlen < 0)
|
||||
|| ntfs_forbidden_names(ni->vol,shortname,shortlen)) {
|
||||
|| ntfs_forbidden_names(ni->vol,shortname,shortlen,TRUE)) {
|
||||
ntfs_inode_close_in_dir(ni,dir_ni);
|
||||
ntfs_inode_close(dir_ni);
|
||||
res = -errno;
|
||||
@ -2667,7 +2670,8 @@ 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_names(ni->vol, longname, longlen)) {
|
||||
&& !ntfs_forbidden_names(ni->vol, longname, longlen,
|
||||
FALSE)) {
|
||||
if (oldlen > 0) {
|
||||
if (flags & XATTR_CREATE) {
|
||||
res = -1;
|
||||
|
@ -1477,10 +1477,14 @@ void ntfs_ucsfree(ntfschar *ucs)
|
||||
* Check whether a name contains no chars forbidden
|
||||
* for DOS or Win32 use
|
||||
*
|
||||
* If @strict is TRUE, then trailing dots and spaces are forbidden.
|
||||
* These names are technically allowed in the Win32 namespace, but
|
||||
* they can be problematic. See comment for FILE_NAME_WIN32.
|
||||
*
|
||||
* If there is a bad char, errno is set to EINVAL
|
||||
*/
|
||||
|
||||
BOOL ntfs_forbidden_chars(const ntfschar *name, int len)
|
||||
BOOL ntfs_forbidden_chars(const ntfschar *name, int len, BOOL strict)
|
||||
{
|
||||
BOOL forbidden;
|
||||
int ch;
|
||||
@ -1493,9 +1497,9 @@ BOOL ntfs_forbidden_chars(const ntfschar *name, int len)
|
||||
| (1L << ('>' - 0x20))
|
||||
| (1L << ('?' - 0x20));
|
||||
|
||||
forbidden = (len == 0)
|
||||
|| (name[len-1] == const_cpu_to_le16(' '))
|
||||
|| (name[len-1] == const_cpu_to_le16('.'));
|
||||
forbidden = (len == 0) ||
|
||||
(strict && (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)
|
||||
@ -1517,10 +1521,15 @@ BOOL ntfs_forbidden_chars(const ntfschar *name, int len)
|
||||
* The reserved names are CON, PRN, AUX, NUL, COM1..COM9, LPT1..LPT9
|
||||
* with no suffix or any suffix.
|
||||
*
|
||||
* If @strict is TRUE, then trailing dots and spaces are forbidden.
|
||||
* These names are technically allowed in the Win32 namespace, but
|
||||
* they can be problematic. See comment for FILE_NAME_WIN32.
|
||||
*
|
||||
* If the name is forbidden, errno is set to EINVAL
|
||||
*/
|
||||
|
||||
BOOL ntfs_forbidden_names(ntfs_volume *vol, const ntfschar *name, int len)
|
||||
BOOL ntfs_forbidden_names(ntfs_volume *vol, const ntfschar *name, int len,
|
||||
BOOL strict)
|
||||
{
|
||||
BOOL forbidden;
|
||||
int h;
|
||||
@ -1538,7 +1547,7 @@ BOOL ntfs_forbidden_names(ntfs_volume *vol, const ntfschar *name, int len)
|
||||
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);
|
||||
forbidden = ntfs_forbidden_chars(name, len, strict);
|
||||
if (!forbidden && (len >= 3)) {
|
||||
/*
|
||||
* Rough hash check to tell whether the first couple of chars
|
||||
|
@ -2169,7 +2169,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_names(ctx->vol,uname,uname_len))) {
|
||||
&& ntfs_forbidden_names(ctx->vol,uname,uname_len,TRUE))) {
|
||||
res = -errno;
|
||||
goto exit;
|
||||
}
|
||||
@ -2390,7 +2390,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_names(ctx->vol,uname,uname_len))) {
|
||||
&& ntfs_forbidden_names(ctx->vol,uname,uname_len,TRUE))) {
|
||||
res = -errno;
|
||||
goto exit;
|
||||
}
|
||||
@ -3571,7 +3571,7 @@ static void ntfs_fuse_setxattr(fuse_req_t req, fuse_ino_t ino, const char *name,
|
||||
lename_len = fix_xattr_prefix(name, namespace, &lename);
|
||||
if ((lename_len == -1)
|
||||
|| (ctx->windows_names
|
||||
&& ntfs_forbidden_chars(lename,lename_len))) {
|
||||
&& ntfs_forbidden_chars(lename,lename_len,TRUE))) {
|
||||
res = -errno;
|
||||
goto exit;
|
||||
}
|
||||
|
@ -1954,7 +1954,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_names(ctx->vol,uname,uname_len))) {
|
||||
&& ntfs_forbidden_names(ctx->vol,uname,uname_len,TRUE))) {
|
||||
res = -errno;
|
||||
goto exit;
|
||||
}
|
||||
@ -2162,7 +2162,7 @@ static int ntfs_fuse_mknod_common(const char *org_path, mode_t mode, dev_t dev,
|
||||
&& (!S_ISREG(mode)
|
||||
|| (ctx->windows_names
|
||||
&& ntfs_forbidden_names(ctx->vol,stream_name,
|
||||
stream_name_len)))) {
|
||||
stream_name_len, TRUE)))) {
|
||||
res = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
@ -2231,7 +2231,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_names(ctx->vol,uname,uname_len))) {
|
||||
&& ntfs_forbidden_names(ctx->vol,uname,uname_len,TRUE))) {
|
||||
res = -errno;
|
||||
goto exit;
|
||||
}
|
||||
@ -3379,7 +3379,7 @@ static int ntfs_fuse_setxattr(const char *path, const char *name,
|
||||
lename_len = fix_xattr_prefix(name, namespace, &lename);
|
||||
if ((lename_len == -1)
|
||||
|| (ctx->windows_names
|
||||
&& ntfs_forbidden_chars(lename,lename_len))) {
|
||||
&& ntfs_forbidden_chars(lename,lename_len,TRUE))) {
|
||||
res = -errno;
|
||||
goto exit;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user