diff --git a/include/ntfs-3g/unistr.h b/include/ntfs-3g/unistr.h index 8cadc3c4..b6d428e3 100644 --- a/include/ntfs-3g/unistr.h +++ b/include/ntfs-3g/unistr.h @@ -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); diff --git a/libntfs-3g/dir.c b/libntfs-3g/dir.c index 2539586c..8633c7d9 100644 --- a/libntfs-3g/dir.c +++ b/libntfs-3g/dir.c @@ -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; diff --git a/libntfs-3g/unistr.c b/libntfs-3g/unistr.c index 9a238014..e12d21e7 100644 --- a/libntfs-3g/unistr.c +++ b/libntfs-3g/unistr.c @@ -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= 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 diff --git a/src/lowntfs-3g.c b/src/lowntfs-3g.c index 23fb9910..a7852a99 100644 --- a/src/lowntfs-3g.c +++ b/src/lowntfs-3g.c @@ -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; } diff --git a/src/ntfs-3g.8.in b/src/ntfs-3g.8.in index f9b2df9b..57fffc96 100644 --- a/src/ntfs-3g.8.in +++ b/src/ntfs-3g.8.in @@ -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 diff --git a/src/ntfs-3g.c b/src/ntfs-3g.c index bcf2f24f..be2a819b 100644 --- a/src/ntfs-3g.c +++ b/src/ntfs-3g.c @@ -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; }