mirror of
https://git.code.sf.net/p/ntfs-3g/ntfs-3g.git
synced 2024-11-23 10:04:00 +08:00
Adapted to ntfs-3g.1.5222-RC
This commit is contained in:
parent
4898e594b8
commit
d3f3a19866
12
configure.ac
12
configure.ac
@ -23,8 +23,8 @@
|
||||
|
||||
# Autoconf
|
||||
AC_PREREQ(2.59)
|
||||
AC_INIT([ntfs-3g],[1.2812],[ntfs-3g-devel@lists.sf.net])
|
||||
LIBNTFS_3G_VERSION="36"
|
||||
AC_INIT([ntfs-3g],[1.5222-RC],[ntfs-3g-devel@lists.sf.net])
|
||||
LIBNTFS_3G_VERSION="47"
|
||||
AC_CONFIG_SRCDIR([src/ntfs-3g.c])
|
||||
|
||||
# Environment
|
||||
@ -107,10 +107,10 @@ AC_ARG_ENABLE(
|
||||
)
|
||||
|
||||
AC_ARG_ENABLE(
|
||||
[posix-acl],
|
||||
[AS_HELP_STRING([--disable-posix-acl],[disable POSIX ACL support])],
|
||||
[posix-acls],
|
||||
[AS_HELP_STRING([--enable-posix-acls],[enable POSIX ACL support])],
|
||||
,
|
||||
[enable_posix_acl="yes"]
|
||||
[enable_posix_acls="no"]
|
||||
)
|
||||
|
||||
AC_ARG_ENABLE(
|
||||
@ -316,7 +316,7 @@ test "${enable_device_default_io_ops}" = "no" && AC_DEFINE(
|
||||
)
|
||||
|
||||
test "${enable_mtab}" = "no" && AC_DEFINE([IGNORE_MTAB], [1], [Don't update /etc/mtab])
|
||||
test "${enable_posix_acl}" = "yes" && AC_DEFINE([POSIXACLS], [1], [POSIX ACL support])
|
||||
test "${enable_posix_acls}" != "no" && AC_DEFINE([POSIXACLS], [1], [POSIX ACL support])
|
||||
|
||||
test "${enable_really_static}" = "yes" && enable_library="no"
|
||||
test "${enable_library}" = "no" && enable_ldconfig="no"
|
||||
|
@ -241,6 +241,8 @@ struct _ntfs_volume {
|
||||
|
||||
};
|
||||
|
||||
extern const char *ntfs_home;
|
||||
|
||||
extern ntfs_volume *ntfs_volume_alloc(void);
|
||||
|
||||
extern ntfs_volume *ntfs_volume_startup(struct ntfs_device *dev,
|
||||
@ -259,6 +261,9 @@ extern int ntfs_logfile_reset(ntfs_volume *vol);
|
||||
extern int ntfs_volume_write_flags(ntfs_volume *vol, const u16 flags);
|
||||
|
||||
extern int ntfs_volume_error(int err);
|
||||
extern void ntfs_mount_error(const char *vol, const char *mntpoint, int err);
|
||||
|
||||
extern int ntfs_set_locale(void);
|
||||
|
||||
#endif /* defined _NTFS_VOLUME_H */
|
||||
|
||||
|
@ -171,7 +171,7 @@ u64 ntfs_inode_lookup_by_name(ntfs_inode *dir_ni, const ntfschar *uname,
|
||||
if (ntfs_attr_lookup(AT_INDEX_ROOT, NTFS_INDEX_I30, 4, CASE_SENSITIVE, 0, NULL,
|
||||
0, ctx)) {
|
||||
ntfs_log_perror("Index root attribute missing in directory inode "
|
||||
"0x%llx", (unsigned long long)dir_ni->mft_no);
|
||||
"%lld", (unsigned long long)dir_ni->mft_no);
|
||||
goto put_err_out;
|
||||
}
|
||||
/* Get to the index root value. */
|
||||
@ -180,7 +180,7 @@ u64 ntfs_inode_lookup_by_name(ntfs_inode *dir_ni, const ntfschar *uname,
|
||||
index_block_size = le32_to_cpu(ir->index_block_size);
|
||||
if (index_block_size < NTFS_BLOCK_SIZE ||
|
||||
index_block_size & (index_block_size - 1)) {
|
||||
ntfs_log_debug("Index block size %u is invalid.\n",
|
||||
ntfs_log_error("Index block size %u is invalid.\n",
|
||||
(unsigned)index_block_size);
|
||||
goto put_err_out;
|
||||
}
|
||||
@ -197,8 +197,11 @@ u64 ntfs_inode_lookup_by_name(ntfs_inode *dir_ni, const ntfschar *uname,
|
||||
if ((u8*)ie < (u8*)ctx->mrec || (u8*)ie +
|
||||
sizeof(INDEX_ENTRY_HEADER) > index_end ||
|
||||
(u8*)ie + le16_to_cpu(ie->key_length) >
|
||||
index_end)
|
||||
index_end) {
|
||||
ntfs_log_error("Index entry out of bounds in inode %lld"
|
||||
"\n", (unsigned long long)dir_ni->mft_no);
|
||||
goto put_err_out;
|
||||
}
|
||||
/*
|
||||
* The last entry cannot contain a name. It can however contain
|
||||
* a pointer to a child node in the B+tree so we just break out.
|
||||
@ -206,8 +209,11 @@ u64 ntfs_inode_lookup_by_name(ntfs_inode *dir_ni, const ntfschar *uname,
|
||||
if (ie->ie_flags & INDEX_ENTRY_END)
|
||||
break;
|
||||
|
||||
if (!le16_to_cpu(ie->length))
|
||||
if (!le16_to_cpu(ie->length)) {
|
||||
ntfs_log_error("Zero length index entry in inode %lld"
|
||||
"\n", (unsigned long long)dir_ni->mft_no);
|
||||
goto put_err_out;
|
||||
}
|
||||
/*
|
||||
* Not a perfect match, need to do full blown collation so we
|
||||
* know which way in the B+tree we have to go.
|
||||
@ -266,8 +272,7 @@ u64 ntfs_inode_lookup_by_name(ntfs_inode *dir_ni, const ntfschar *uname,
|
||||
/* Open the index allocation attribute. */
|
||||
ia_na = ntfs_attr_open(dir_ni, AT_INDEX_ALLOCATION, NTFS_INDEX_I30, 4);
|
||||
if (!ia_na) {
|
||||
ntfs_log_perror("Failed to open index allocation attribute. Directory "
|
||||
"inode 0x%llx is corrupt or driver bug",
|
||||
ntfs_log_perror("Failed to open index allocation (inode %lld)",
|
||||
(unsigned long long)dir_ni->mft_no);
|
||||
goto put_err_out;
|
||||
}
|
||||
@ -305,7 +310,7 @@ descend_into_child_node:
|
||||
}
|
||||
|
||||
if (sle64_to_cpu(ia->index_block_vcn) != vcn) {
|
||||
ntfs_log_debug("Actual VCN (0x%llx) of index buffer is different "
|
||||
ntfs_log_error("Actual VCN (0x%llx) of index buffer is different "
|
||||
"from expected VCN (0x%llx).\n",
|
||||
(long long)sle64_to_cpu(ia->index_block_vcn),
|
||||
(long long)vcn);
|
||||
@ -313,7 +318,7 @@ descend_into_child_node:
|
||||
goto close_err_out;
|
||||
}
|
||||
if (le32_to_cpu(ia->index.allocated_size) + 0x18 != index_block_size) {
|
||||
ntfs_log_debug("Index buffer (VCN 0x%llx) of directory inode 0x%llx "
|
||||
ntfs_log_error("Index buffer (VCN 0x%llx) of directory inode 0x%llx "
|
||||
"has a size (%u) differing from the directory "
|
||||
"specified size (%u).\n", (long long)vcn,
|
||||
(unsigned long long)dir_ni->mft_no,
|
||||
@ -324,7 +329,7 @@ descend_into_child_node:
|
||||
}
|
||||
index_end = (u8*)&ia->index + le32_to_cpu(ia->index.index_length);
|
||||
if (index_end > (u8*)ia + index_block_size) {
|
||||
ntfs_log_debug("Size of index buffer (VCN 0x%llx) of directory inode "
|
||||
ntfs_log_error("Size of index buffer (VCN 0x%llx) of directory inode "
|
||||
"0x%llx exceeds maximum size.\n",
|
||||
(long long)vcn, (unsigned long long)dir_ni->mft_no);
|
||||
errno = EIO;
|
||||
@ -345,9 +350,9 @@ descend_into_child_node:
|
||||
sizeof(INDEX_ENTRY_HEADER) > index_end ||
|
||||
(u8*)ie + le16_to_cpu(ie->key_length) >
|
||||
index_end) {
|
||||
ntfs_log_debug("Index entry out of bounds in directory "
|
||||
"inode 0x%llx.\n",
|
||||
(unsigned long long)dir_ni->mft_no);
|
||||
ntfs_log_error("Index entry out of bounds in directory "
|
||||
"inode %lld.\n",
|
||||
(unsigned long long)dir_ni->mft_no);
|
||||
errno = EIO;
|
||||
goto close_err_out;
|
||||
}
|
||||
@ -360,6 +365,8 @@ descend_into_child_node:
|
||||
|
||||
if (!le16_to_cpu(ie->length)) {
|
||||
errno = EIO;
|
||||
ntfs_log_error("Zero length index entry in inode %lld"
|
||||
"\n", (unsigned long long)dir_ni->mft_no);
|
||||
goto close_err_out;
|
||||
}
|
||||
/*
|
||||
@ -406,8 +413,8 @@ descend_into_child_node:
|
||||
*/
|
||||
if (ie->ie_flags & INDEX_ENTRY_NODE) {
|
||||
if ((ia->index.ih_flags & NODE_MASK) == LEAF_NODE) {
|
||||
ntfs_log_debug("Index entry with child node found in a leaf "
|
||||
"node in directory inode 0x%llx.\n",
|
||||
ntfs_log_error("Index entry with child node found in a leaf "
|
||||
"node in directory inode %lld.\n",
|
||||
(unsigned long long)dir_ni->mft_no);
|
||||
errno = EIO;
|
||||
goto close_err_out;
|
||||
@ -416,8 +423,8 @@ descend_into_child_node:
|
||||
vcn = sle64_to_cpup((u8*)ie + le16_to_cpu(ie->length) - 8);
|
||||
if (vcn >= 0)
|
||||
goto descend_into_child_node;
|
||||
ntfs_log_debug("Negative child node vcn in directory inode "
|
||||
"0x%llx.\n", (unsigned long long)dir_ni->mft_no);
|
||||
ntfs_log_error("Negative child node vcn in directory inode "
|
||||
"0x%llx.\n", (unsigned long long)dir_ni->mft_no);
|
||||
errno = EIO;
|
||||
goto close_err_out;
|
||||
}
|
||||
@ -486,7 +493,7 @@ ntfs_inode *ntfs_pathname_to_inode(ntfs_volume *vol, ntfs_inode *parent,
|
||||
|
||||
ascii = strdup(pathname);
|
||||
if (!ascii) {
|
||||
ntfs_log_debug("Out of memory.\n");
|
||||
ntfs_log_error("Out of memory.\n");
|
||||
err = ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
@ -550,7 +557,8 @@ ntfs_inode *ntfs_pathname_to_inode(ntfs_volume *vol, ntfs_inode *parent,
|
||||
|
||||
len = ntfs_mbstoucs(p, &unicode);
|
||||
if (len < 0) {
|
||||
ntfs_log_debug("Couldn't convert name to Unicode: %s.\n", p);
|
||||
ntfs_log_perror("Couldn't convert filename to Unicode: "
|
||||
"'%s'.\n", p);
|
||||
err = errno;
|
||||
goto close;
|
||||
} else if (len > NTFS_MAX_NAME_LEN) {
|
||||
@ -735,21 +743,21 @@ static MFT_REF ntfs_mft_get_parent_ref(ntfs_inode *ni)
|
||||
if (!ctx)
|
||||
return ERR_MREF(-1);
|
||||
if (ntfs_attr_lookup(AT_FILE_NAME, AT_UNNAMED, 0, 0, 0, NULL, 0, ctx)) {
|
||||
ntfs_log_debug("No file name found in inode 0x%llx. Corrupt "
|
||||
"inode.\n", (unsigned long long)ni->mft_no);
|
||||
ntfs_log_error("No file name found in inode %lld\n",
|
||||
(unsigned long long)ni->mft_no);
|
||||
goto err_out;
|
||||
}
|
||||
if (ctx->attr->non_resident) {
|
||||
ntfs_log_debug("File name attribute must be resident. Corrupt inode "
|
||||
"0x%llx.\n", (unsigned long long)ni->mft_no);
|
||||
ntfs_log_error("File name attribute must be resident (inode "
|
||||
"%lld)\n", (unsigned long long)ni->mft_no);
|
||||
goto io_err_out;
|
||||
}
|
||||
fn = (FILE_NAME_ATTR*)((u8*)ctx->attr +
|
||||
le16_to_cpu(ctx->attr->value_offset));
|
||||
if ((u8*)fn + le32_to_cpu(ctx->attr->value_length) >
|
||||
(u8*)ctx->attr + le32_to_cpu(ctx->attr->length)) {
|
||||
ntfs_log_debug("Corrupt file name attribute in inode 0x%llx.\n",
|
||||
(unsigned long long)ni->mft_no);
|
||||
ntfs_log_error("Corrupt file name attribute in inode %lld.\n",
|
||||
(unsigned long long)ni->mft_no);
|
||||
goto io_err_out;
|
||||
}
|
||||
mref = le64_to_cpu(fn->parent_directory);
|
||||
@ -809,7 +817,7 @@ int ntfs_readdir(ntfs_inode *dir_ni, s64 *pos,
|
||||
|
||||
vol = dir_ni->vol;
|
||||
|
||||
ntfs_log_trace("Entering for inode 0x%llx, *pos 0x%llx.\n",
|
||||
ntfs_log_trace("Entering for inode %lld, *pos 0x%llx.\n",
|
||||
(unsigned long long)dir_ni->mft_no, (long long)*pos);
|
||||
|
||||
/* Open the index allocation attribute. */
|
||||
@ -817,7 +825,7 @@ int ntfs_readdir(ntfs_inode *dir_ni, s64 *pos,
|
||||
if (!ia_na) {
|
||||
if (errno != ENOENT) {
|
||||
ntfs_log_perror("Failed to open index allocation attribute. "
|
||||
"Directory inode 0x%llx is corrupt or bug",
|
||||
"Directory inode %lld is corrupt or bug",
|
||||
(unsigned long long)dir_ni->mft_no);
|
||||
return -1;
|
||||
}
|
||||
@ -867,7 +875,7 @@ int ntfs_readdir(ntfs_inode *dir_ni, s64 *pos,
|
||||
if (ntfs_attr_lookup(AT_INDEX_ROOT, NTFS_INDEX_I30, 4, CASE_SENSITIVE, 0, NULL,
|
||||
0, ctx)) {
|
||||
ntfs_log_perror("Index root attribute missing in directory inode "
|
||||
"0x%llx", (unsigned long long)dir_ni->mft_no);
|
||||
"%lld", (unsigned long long)dir_ni->mft_no);
|
||||
goto dir_err_out;
|
||||
}
|
||||
/* Get to the index root value. */
|
||||
@ -1034,7 +1042,7 @@ find_next_index_buffer:
|
||||
goto dir_err_out;
|
||||
}
|
||||
if (le32_to_cpu(ia->index.allocated_size) + 0x18 != index_block_size) {
|
||||
ntfs_log_error("Index buffer (VCN 0x%llx) of directory inode 0x%llx "
|
||||
ntfs_log_error("Index buffer (VCN 0x%llx) of directory inode %lld "
|
||||
"has a size (%u) differing from the directory "
|
||||
"specified size (%u).\n", (long long)ia_start >>
|
||||
index_vcn_size_bits,
|
||||
@ -1046,7 +1054,7 @@ find_next_index_buffer:
|
||||
index_end = (u8*)&ia->index + le32_to_cpu(ia->index.index_length);
|
||||
if (index_end > (u8*)ia + index_block_size) {
|
||||
ntfs_log_error("Size of index buffer (VCN 0x%llx) of directory inode "
|
||||
"0x%llx exceeds maximum size.\n",
|
||||
"%lld exceeds maximum size.\n",
|
||||
(long long)ia_start >> index_vcn_size_bits,
|
||||
(unsigned long long)dir_ni->mft_no);
|
||||
goto dir_err_out;
|
||||
@ -1068,7 +1076,7 @@ find_next_index_buffer:
|
||||
(u8*)ie + le16_to_cpu(ie->key_length) >
|
||||
index_end) {
|
||||
ntfs_log_error("Index entry out of bounds in directory inode "
|
||||
"0x%llx.\n", (unsigned long long)dir_ni->mft_no);
|
||||
"%lld.\n", (unsigned long long)dir_ni->mft_no);
|
||||
goto dir_err_out;
|
||||
}
|
||||
/* The last entry cannot contain a name. */
|
||||
|
@ -387,293 +387,323 @@ int ntfs_file_values_compare(const FILE_NAME_ATTR *file_name_attr1,
|
||||
err_val, ic, upcase, upcase_len);
|
||||
}
|
||||
|
||||
/*
|
||||
#
|
||||
# NTFS uses Unicode (UTF-16LE [NTFS-3G uses UCS-2LE, which is enough
|
||||
# for now]) for path names, but the Unicode code points need to be
|
||||
# converted before a path can be accessed under NTFS. For 7 bit ASCII/ANSI,
|
||||
# glibc does this even without a locale in a hard-coded fashion as that
|
||||
# appears to be is easy because the low 7-bit ASCII range appears to be
|
||||
# available # in all charsets but it does not convert anything if
|
||||
# there was some error with the locale setup or none set up like
|
||||
# when mount is called during early boot where he (by policy) do
|
||||
# not use locales (and may be not available if /usr is not yet mounted),
|
||||
# so this patch fixes the resulting issues for systems which use
|
||||
# UTF-8 and for others, specifying the locale in fstab brings them
|
||||
# the encoding which they want.
|
||||
#
|
||||
# If no locale is defined or there was a problem with setting one
|
||||
# up and whenever nl_langinfo(CODESET) returns a sting starting with
|
||||
# "ANSI", use an internal UCS-2LE <-> UTF-8 codeset converter to fix
|
||||
# the bug where NTFS-3G does not show any path names which include
|
||||
# international characters!!! (and also fails on creating them) as result.
|
||||
#
|
||||
# Author: Bernhard Kaindl <bk@suse.de>
|
||||
#
|
||||
*/
|
||||
|
||||
|
||||
/* Return the amount of 16-bit elements in UTF-16LE needed (without
|
||||
* the terminating null to store given UTF-8 string and -1 if it does
|
||||
* not fit into PATH_MAX
|
||||
*
|
||||
* JPA : made compliant with RFC3629 / RFC2781
|
||||
*/
|
||||
static int utf16_to_utf8_size(const ntfschar *ins, const int ins_len, int outs_len)
|
||||
{
|
||||
int i;
|
||||
int count = 0;
|
||||
BOOL surrog;
|
||||
|
||||
surrog = FALSE;
|
||||
for (i = 0; i < ins_len && ins[i]; i++) {
|
||||
unsigned short c = le16_to_cpu(ins[i]);
|
||||
if (surrog) {
|
||||
if ((c >= 0xdc00) && (c < 0xe000)) {
|
||||
surrog = FALSE;
|
||||
count += 4;
|
||||
} else goto fail;
|
||||
} else
|
||||
if (c < 0x80)
|
||||
count++;
|
||||
else if (c < 0x800)
|
||||
count += 2;
|
||||
else if (c < 0xd800)
|
||||
count += 3;
|
||||
else if (c < 0xdc00)
|
||||
surrog = TRUE;
|
||||
#if NOREVBOM
|
||||
else if ((c >= 0xe000) && (c < 0xfffe))
|
||||
#else
|
||||
else if (c >= 0xe000)
|
||||
#endif
|
||||
count += 3;
|
||||
else goto fail;
|
||||
if (count > outs_len)
|
||||
goto fail;
|
||||
}
|
||||
if (surrog) goto fail;
|
||||
return count;
|
||||
fail:
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* ntfs_utf16_to_utf8 - convert a little endian UTF16LE string to an UTF-8 string
|
||||
* @ins: input utf16 string buffer
|
||||
* @ins_len: length of input string in utf16 characters
|
||||
* @outs: on return contains the (allocated) output multibyte string
|
||||
* @outs_len: length of output buffer in bytes
|
||||
*
|
||||
* JPA : made compliant with RFC3629 / RFC2781
|
||||
*/
|
||||
static int ntfs_utf16_to_utf8(const ntfschar *ins, const int ins_len,
|
||||
char **outs, int outs_len)
|
||||
{
|
||||
char *t;
|
||||
int i, size;
|
||||
ntfschar halfpair;
|
||||
|
||||
halfpair = 0;
|
||||
if (!*outs)
|
||||
outs_len = PATH_MAX;
|
||||
|
||||
size = utf16_to_utf8_size(ins, ins_len, outs_len);
|
||||
|
||||
if (size < 0) {
|
||||
errno = ENAMETOOLONG;
|
||||
goto fail;
|
||||
}
|
||||
if (!*outs)
|
||||
*outs = ntfs_malloc((outs_len = size + 1));
|
||||
|
||||
t = *outs;
|
||||
|
||||
for (i = 0; i < ins_len && ins[i]; i++) {
|
||||
unsigned short c = le16_to_cpu(ins[i]);
|
||||
/* size not double-checked */
|
||||
if (halfpair) {
|
||||
if ((c >= 0xdc00) && (c < 0xe000)) {
|
||||
*t++ = 0xf0 + (((halfpair + 64) >> 8) & 7);
|
||||
*t++ = 0x80 + (((halfpair + 64) >> 2) & 63);
|
||||
*t++ = 0x80 + ((c >> 6) & 15) + ((halfpair & 3) << 4);
|
||||
*t++ = 0x80 + (c & 63);
|
||||
halfpair = 0;
|
||||
} else goto fail;
|
||||
} else if (c < 0x80) {
|
||||
*t++ = c;
|
||||
} else {
|
||||
if (c < 0x800) {
|
||||
*t++ = (0xc0 | ((c >> 6) & 0x3f));
|
||||
*t++ = 0x80 | (c & 0x3f);
|
||||
} else if (c < 0xd800) {
|
||||
*t++ = 0xe0 | (c >> 12);
|
||||
*t++ = 0x80 | ((c >> 6) & 0x3f);
|
||||
*t++ = 0x80 | (c & 0x3f);
|
||||
} else if (c < 0xdc00)
|
||||
halfpair = c;
|
||||
else if (c >= 0xe000) {
|
||||
*t++ = 0xe0 | (c >> 12);
|
||||
*t++ = 0x80 | ((c >> 6) & 0x3f);
|
||||
*t++ = 0x80 | (c & 0x3f);
|
||||
} else goto fail;
|
||||
}
|
||||
}
|
||||
*t = '\0';
|
||||
return t - *outs;
|
||||
fail:
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/* Return the amount of 16-bit elements in UTF-16LE needed (without
|
||||
* the terminating null to store given UTF-8 string and -1 if it does
|
||||
* not fit into PATH_MAX
|
||||
*
|
||||
* Note : this does not check whether the input sequence is a valid utf8
|
||||
* string, and should be used only in context where such check is made
|
||||
*
|
||||
* JPA : made compliant with RFC3629 / RFC2781
|
||||
*
|
||||
*/
|
||||
static int utf8_to_utf16_size(const char *s)
|
||||
{
|
||||
unsigned int byte;
|
||||
size_t count = 0;
|
||||
|
||||
while ((byte = *((const unsigned char *)s++))) {
|
||||
if (++count >= PATH_MAX || byte >= 0xF5)
|
||||
goto fail;
|
||||
if (!*s) break;
|
||||
if (byte >= 0xC0) s++;
|
||||
if (!*s) break;
|
||||
if (byte >= 0xE0) s++;
|
||||
if (!*s) break;
|
||||
if (byte >= 0xF0) {
|
||||
s++;
|
||||
if (++count >= PATH_MAX)
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
fail:
|
||||
return -1;
|
||||
}
|
||||
/* This converts one UTF-8 sequence to cpu-endian Unicode value
|
||||
* within range U+0 .. U+10ffff and excluding U+D800 .. U+DFFF
|
||||
* Returns the number of used utf8 bytes or -1 if sequence is invalid
|
||||
*
|
||||
* JPA : made compliant with RFC3629 / RFC2781
|
||||
*/
|
||||
static int utf8_to_unicode(u32 *wc, const char *s)
|
||||
{
|
||||
unsigned int byte = *((const unsigned char *)s);
|
||||
|
||||
/* single byte */
|
||||
if (byte == 0) {
|
||||
*wc = (u32) 0;
|
||||
return 0;
|
||||
} else if (byte < 0x80) {
|
||||
*wc = (u32) byte;
|
||||
return 1;
|
||||
/* double byte */
|
||||
} else if (byte < 0xc2) {
|
||||
goto fail;
|
||||
} else if (byte < 0xE0) {
|
||||
if (strlen(s) < 2)
|
||||
goto fail;
|
||||
if ((s[1] & 0xC0) == 0x80) {
|
||||
*wc = ((u32)(byte & 0x1F) << 6)
|
||||
| ((u32)(s[1] & 0x3F));
|
||||
return 2;
|
||||
} else
|
||||
goto fail;
|
||||
/* three-byte */
|
||||
} else if (byte < 0xF0) {
|
||||
if (strlen(s) < 3)
|
||||
goto fail;
|
||||
if (((s[1] & 0xC0) == 0x80) && ((s[2] & 0xC0) == 0x80)) {
|
||||
*wc = ((u32)(byte & 0x0F) << 12)
|
||||
| ((u32)(s[1] & 0x3F) << 6)
|
||||
| ((u32)(s[2] & 0x3F));
|
||||
/* Check valid ranges */
|
||||
#if NOREVBOM
|
||||
if (((*wc >= 0x800) && (*wc <= 0xD7FF))
|
||||
|| ((*wc >= 0xe000) && (*wc <= 0xFFFD)))
|
||||
return 3;
|
||||
#else
|
||||
if (((*wc >= 0x800) && (*wc <= 0xD7FF))
|
||||
|| ((*wc >= 0xe000) && (*wc <= 0xFFFF)))
|
||||
return 3;
|
||||
#endif
|
||||
}
|
||||
goto fail;
|
||||
/* four-byte */
|
||||
} else if (byte < 0xF5) {
|
||||
if (strlen(s) < 4)
|
||||
goto fail;
|
||||
if (((s[1] & 0xC0) == 0x80) && ((s[2] & 0xC0) == 0x80)
|
||||
&& ((s[3] & 0xC0) == 0x80)) {
|
||||
*wc = ((u32)(byte & 0x07) << 18)
|
||||
| ((u32)(s[1] & 0x3F) << 12)
|
||||
| ((u32)(s[2] & 0x3F) << 6)
|
||||
| ((u32)(s[3] & 0x3F));
|
||||
/* Check valid ranges */
|
||||
if ((*wc <= 0x10ffff) && (*wc >= 0x10000))
|
||||
return 4;
|
||||
}
|
||||
goto fail;
|
||||
}
|
||||
fail:
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* ntfs_utf8_to_utf16 - convert a UTF-8 string to a UTF-16LE string
|
||||
* @ins: input multibyte string buffer
|
||||
* @outs: on return contains the (allocated) output utf16 string
|
||||
* @outs_len: length of output buffer in utf16 characters
|
||||
*
|
||||
* JPA : made compliant with RFC3629 / RFC2781
|
||||
*/
|
||||
static int ntfs_utf8_to_utf16(const char *ins, ntfschar **outs)
|
||||
{
|
||||
const char *t = ins;
|
||||
u32 wc;
|
||||
ntfschar *outpos;
|
||||
int shorts = utf8_to_utf16_size(ins);
|
||||
|
||||
if (shorts < 0) {
|
||||
errno = EILSEQ;
|
||||
goto fail;
|
||||
}
|
||||
if (!*outs)
|
||||
*outs = ntfs_malloc((shorts+1) * sizeof(ntfschar));
|
||||
|
||||
outpos = *outs;
|
||||
|
||||
while(1) {
|
||||
int m = utf8_to_unicode(&wc, t);
|
||||
if (m < 0) {
|
||||
errno = EILSEQ;
|
||||
goto fail;
|
||||
}
|
||||
if (wc < 0x10000)
|
||||
*outpos++ = cpu_to_le16(wc);
|
||||
else {
|
||||
wc -= 0x10000;
|
||||
*outpos++ = cpu_to_le16((wc >> 10) + 0xd800);
|
||||
*outpos++ = cpu_to_le16((wc & 0x3ff) + 0xdc00);
|
||||
}
|
||||
if (m == 0)
|
||||
break;
|
||||
t += m;
|
||||
}
|
||||
return --outpos - *outs;
|
||||
fail:
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
NTFS uses Unicode (UTF-16LE [NTFS-3G uses UCS-2LE, which is enough
|
||||
for now]) for path names, but the Unicode code points need to be
|
||||
converted before a path can be accessed under NTFS. For 7 bit ASCII/ANSI,
|
||||
glibc does this even without a locale in a hard-coded fashion as that
|
||||
appears to be is easy because the low 7-bit ASCII range appears to be
|
||||
available in all charsets but it does not convert anything if
|
||||
there was some error with the locale setup or none set up like
|
||||
when mount is called during early boot where he (by policy) do
|
||||
not use locales (and may be not available if /usr is not yet mounted),
|
||||
so this patch fixes the resulting issues for systems which use
|
||||
UTF-8 and for others, specifying the locale in fstab brings them
|
||||
the encoding which they want.
|
||||
|
||||
If no locale is defined or there was a problem with setting one
|
||||
up and whenever nl_langinfo(CODESET) returns a sting starting with
|
||||
"ANSI", use an internal UCS-2LE <-> UTF-8 codeset converter to fix
|
||||
the bug where NTFS-3G does not show any path names which include
|
||||
international characters!!! (and also fails on creating them) as result.
|
||||
|
||||
Author: Bernhard Kaindl <bk@suse.de>
|
||||
Jean-Pierre Andre made it compliant with RFC3629/RFC2781.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Return the amount of 8-bit elements in UTF-8 needed (without the terminating
|
||||
* null) to store a given UTF-16LE string.
|
||||
*
|
||||
* Return -1 with errno set if string has invalid byte sequence or too long.
|
||||
*/
|
||||
static int utf16_to_utf8_size(const ntfschar *ins, const int ins_len, int outs_len)
|
||||
{
|
||||
int i, ret = -1;
|
||||
int count = 0;
|
||||
BOOL surrog;
|
||||
|
||||
surrog = FALSE;
|
||||
for (i = 0; i < ins_len && ins[i]; i++) {
|
||||
unsigned short c = le16_to_cpu(ins[i]);
|
||||
if (surrog) {
|
||||
if ((c >= 0xdc00) && (c < 0xe000)) {
|
||||
surrog = FALSE;
|
||||
count += 4;
|
||||
} else
|
||||
goto fail;
|
||||
} else
|
||||
if (c < 0x80)
|
||||
count++;
|
||||
else if (c < 0x800)
|
||||
count += 2;
|
||||
else if (c < 0xd800)
|
||||
count += 3;
|
||||
else if (c < 0xdc00)
|
||||
surrog = TRUE;
|
||||
#if NOREVBOM
|
||||
else if ((c >= 0xe000) && (c < 0xfffe))
|
||||
#else
|
||||
else if (c >= 0xe000)
|
||||
#endif
|
||||
count += 3;
|
||||
else
|
||||
goto fail;
|
||||
if (count > outs_len) {
|
||||
errno = ENAMETOOLONG;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
if (surrog)
|
||||
goto fail;
|
||||
|
||||
ret = count;
|
||||
out:
|
||||
return ret;
|
||||
fail:
|
||||
errno = EILSEQ;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* ntfs_utf16_to_utf8 - convert a little endian UTF16LE string to an UTF-8 string
|
||||
* @ins: input utf16 string buffer
|
||||
* @ins_len: length of input string in utf16 characters
|
||||
* @outs: on return contains the (allocated) output multibyte string
|
||||
* @outs_len: length of output buffer in bytes
|
||||
*
|
||||
* Return -1 with errno set if string has invalid byte sequence or too long.
|
||||
*/
|
||||
static int ntfs_utf16_to_utf8(const ntfschar *ins, const int ins_len,
|
||||
char **outs, int outs_len)
|
||||
{
|
||||
char *t;
|
||||
int i, size, ret = -1;
|
||||
ntfschar halfpair;
|
||||
|
||||
halfpair = 0;
|
||||
if (!*outs)
|
||||
outs_len = PATH_MAX;
|
||||
|
||||
size = utf16_to_utf8_size(ins, ins_len, outs_len);
|
||||
|
||||
if (size < 0)
|
||||
goto out;
|
||||
|
||||
if (!*outs) {
|
||||
outs_len = size + 1;
|
||||
*outs = ntfs_malloc(outs_len);
|
||||
if (!*outs)
|
||||
goto out;
|
||||
}
|
||||
|
||||
t = *outs;
|
||||
|
||||
for (i = 0; i < ins_len && ins[i]; i++) {
|
||||
unsigned short c = le16_to_cpu(ins[i]);
|
||||
/* size not double-checked */
|
||||
if (halfpair) {
|
||||
if ((c >= 0xdc00) && (c < 0xe000)) {
|
||||
*t++ = 0xf0 + (((halfpair + 64) >> 8) & 7);
|
||||
*t++ = 0x80 + (((halfpair + 64) >> 2) & 63);
|
||||
*t++ = 0x80 + ((c >> 6) & 15) + ((halfpair & 3) << 4);
|
||||
*t++ = 0x80 + (c & 63);
|
||||
halfpair = 0;
|
||||
} else
|
||||
goto fail;
|
||||
} else if (c < 0x80) {
|
||||
*t++ = c;
|
||||
} else {
|
||||
if (c < 0x800) {
|
||||
*t++ = (0xc0 | ((c >> 6) & 0x3f));
|
||||
*t++ = 0x80 | (c & 0x3f);
|
||||
} else if (c < 0xd800) {
|
||||
*t++ = 0xe0 | (c >> 12);
|
||||
*t++ = 0x80 | ((c >> 6) & 0x3f);
|
||||
*t++ = 0x80 | (c & 0x3f);
|
||||
} else if (c < 0xdc00)
|
||||
halfpair = c;
|
||||
else if (c >= 0xe000) {
|
||||
*t++ = 0xe0 | (c >> 12);
|
||||
*t++ = 0x80 | ((c >> 6) & 0x3f);
|
||||
*t++ = 0x80 | (c & 0x3f);
|
||||
} else
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
*t = '\0';
|
||||
ret = t - *outs;
|
||||
out:
|
||||
return ret;
|
||||
fail:
|
||||
errno = EILSEQ;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the amount of 16-bit elements in UTF-16LE needed
|
||||
* (without the terminating null) to store given UTF-8 string.
|
||||
*
|
||||
* Return -1 with errno set if it's longer than PATH_MAX or string is invalid.
|
||||
*
|
||||
* Note: This does not check whether the input sequence is a valid utf8 string,
|
||||
* and should be used only in context where such check is made!
|
||||
*/
|
||||
static int utf8_to_utf16_size(const char *s)
|
||||
{
|
||||
int ret = -1;
|
||||
unsigned int byte;
|
||||
size_t count = 0;
|
||||
|
||||
while ((byte = *((const unsigned char *)s++))) {
|
||||
if (++count >= PATH_MAX)
|
||||
goto fail;
|
||||
if (byte >= 0xF5) {
|
||||
errno = EILSEQ;
|
||||
goto out;
|
||||
}
|
||||
if (!*s)
|
||||
break;
|
||||
if (byte >= 0xC0)
|
||||
s++;
|
||||
if (!*s)
|
||||
break;
|
||||
if (byte >= 0xE0)
|
||||
s++;
|
||||
if (!*s)
|
||||
break;
|
||||
if (byte >= 0xF0) {
|
||||
s++;
|
||||
if (++count >= PATH_MAX)
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
ret = count;
|
||||
out:
|
||||
return ret;
|
||||
fail:
|
||||
errno = ENAMETOOLONG;
|
||||
goto out;
|
||||
}
|
||||
/*
|
||||
* This converts one UTF-8 sequence to cpu-endian Unicode value
|
||||
* within range U+0 .. U+10ffff and excluding U+D800 .. U+DFFF
|
||||
*
|
||||
* Return the number of used utf8 bytes or -1 with errno set
|
||||
* if sequence is invalid.
|
||||
*/
|
||||
static int utf8_to_unicode(u32 *wc, const char *s)
|
||||
{
|
||||
unsigned int byte = *((const unsigned char *)s);
|
||||
|
||||
/* single byte */
|
||||
if (byte == 0) {
|
||||
*wc = (u32) 0;
|
||||
return 0;
|
||||
} else if (byte < 0x80) {
|
||||
*wc = (u32) byte;
|
||||
return 1;
|
||||
/* double byte */
|
||||
} else if (byte < 0xc2) {
|
||||
goto fail;
|
||||
} else if (byte < 0xE0) {
|
||||
if (strlen(s) < 2)
|
||||
goto fail;
|
||||
if ((s[1] & 0xC0) == 0x80) {
|
||||
*wc = ((u32)(byte & 0x1F) << 6)
|
||||
| ((u32)(s[1] & 0x3F));
|
||||
return 2;
|
||||
} else
|
||||
goto fail;
|
||||
/* three-byte */
|
||||
} else if (byte < 0xF0) {
|
||||
if (strlen(s) < 3)
|
||||
goto fail;
|
||||
if (((s[1] & 0xC0) == 0x80) && ((s[2] & 0xC0) == 0x80)) {
|
||||
*wc = ((u32)(byte & 0x0F) << 12)
|
||||
| ((u32)(s[1] & 0x3F) << 6)
|
||||
| ((u32)(s[2] & 0x3F));
|
||||
/* Check valid ranges */
|
||||
#if NOREVBOM
|
||||
if (((*wc >= 0x800) && (*wc <= 0xD7FF))
|
||||
|| ((*wc >= 0xe000) && (*wc <= 0xFFFD)))
|
||||
return 3;
|
||||
#else
|
||||
if (((*wc >= 0x800) && (*wc <= 0xD7FF))
|
||||
|| ((*wc >= 0xe000) && (*wc <= 0xFFFF)))
|
||||
return 3;
|
||||
#endif
|
||||
}
|
||||
goto fail;
|
||||
/* four-byte */
|
||||
} else if (byte < 0xF5) {
|
||||
if (strlen(s) < 4)
|
||||
goto fail;
|
||||
if (((s[1] & 0xC0) == 0x80) && ((s[2] & 0xC0) == 0x80)
|
||||
&& ((s[3] & 0xC0) == 0x80)) {
|
||||
*wc = ((u32)(byte & 0x07) << 18)
|
||||
| ((u32)(s[1] & 0x3F) << 12)
|
||||
| ((u32)(s[2] & 0x3F) << 6)
|
||||
| ((u32)(s[3] & 0x3F));
|
||||
/* Check valid ranges */
|
||||
if ((*wc <= 0x10ffff) && (*wc >= 0x10000))
|
||||
return 4;
|
||||
}
|
||||
goto fail;
|
||||
}
|
||||
fail:
|
||||
errno = EILSEQ;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* ntfs_utf8_to_utf16 - convert a UTF-8 string to a UTF-16LE string
|
||||
* @ins: input multibyte string buffer
|
||||
* @outs: on return contains the (allocated) output utf16 string
|
||||
* @outs_len: length of output buffer in utf16 characters
|
||||
*
|
||||
* Return -1 with errno set.
|
||||
*/
|
||||
static int ntfs_utf8_to_utf16(const char *ins, ntfschar **outs)
|
||||
{
|
||||
const char *t = ins;
|
||||
u32 wc;
|
||||
ntfschar *outpos;
|
||||
int shorts, ret = -1;
|
||||
|
||||
shorts = utf8_to_utf16_size(ins);
|
||||
if (shorts < 0)
|
||||
goto fail;
|
||||
|
||||
if (!*outs) {
|
||||
*outs = ntfs_malloc((shorts + 1) * sizeof(ntfschar));
|
||||
if (!*outs)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
outpos = *outs;
|
||||
|
||||
while(1) {
|
||||
int m = utf8_to_unicode(&wc, t);
|
||||
if (m < 0)
|
||||
goto fail;
|
||||
if (wc < 0x10000)
|
||||
*outpos++ = cpu_to_le16(wc);
|
||||
else {
|
||||
wc -= 0x10000;
|
||||
*outpos++ = cpu_to_le16((wc >> 10) + 0xd800);
|
||||
*outpos++ = cpu_to_le16((wc & 0x3ff) + 0xdc00);
|
||||
}
|
||||
if (m == 0)
|
||||
break;
|
||||
t += m;
|
||||
}
|
||||
|
||||
ret = --outpos - *outs;
|
||||
fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* ntfs_ucstombs - convert a little endian Unicode string to a multibyte string
|
||||
* @ins: input Unicode string buffer
|
||||
@ -1041,9 +1071,8 @@ void ntfs_ucsfree(ntfschar *ucs)
|
||||
}
|
||||
|
||||
/*
|
||||
* Define the character encoding to be used
|
||||
*
|
||||
* Using UTF-8 unless specified otherwise
|
||||
* Define the character encoding to be used.
|
||||
* Use UTF-8 unless specified otherwise.
|
||||
*/
|
||||
|
||||
int ntfs_set_char_encoding(const char *locale)
|
||||
@ -1059,6 +1088,6 @@ int ntfs_set_char_encoding(const char *locale)
|
||||
ntfs_log_error("Invalid locale, encoding to UTF-8\n");
|
||||
use_utf8 = 1;
|
||||
}
|
||||
return (0); /* always successful */
|
||||
return 0; /* always successful */
|
||||
}
|
||||
|
||||
|
@ -49,6 +49,9 @@
|
||||
#ifdef HAVE_LIMITS_H
|
||||
#include <limits.h>
|
||||
#endif
|
||||
#ifdef HAVE_LOCALE_H
|
||||
#include <locale.h>
|
||||
#endif
|
||||
|
||||
#include "volume.h"
|
||||
#include "attrib.h"
|
||||
@ -67,6 +70,66 @@
|
||||
#define PATH_MAX 4096
|
||||
#endif
|
||||
|
||||
const char *ntfs_home =
|
||||
"Ntfs-3g news, support and information: http://ntfs-3g.org\n";
|
||||
|
||||
static const char *invalid_ntfs_msg =
|
||||
"The device '%s' doesn't seem to have a valid NTFS.\n"
|
||||
"Maybe the wrong device is used? Or the whole disk instead of a\n"
|
||||
"partition (e.g. /dev/sda, not /dev/sda1)? Or the other way around?\n";
|
||||
|
||||
static const char *corrupt_volume_msg =
|
||||
"NTFS is either inconsistent, or there is a hardware fault, or it's a\n"
|
||||
"SoftRAID/FakeRAID hardware. In the first case run chkdsk /f on Windows\n"
|
||||
"then reboot into Windows twice. The usage of the /f parameter is very\n"
|
||||
"important! If the device is a SoftRAID/FakeRAID then first activate\n"
|
||||
"it and mount a different device under the /dev/mapper/ directory, (e.g.\n"
|
||||
"/dev/mapper/nvidia_eahaabcc1). Please see the 'dmraid' documentation\n"
|
||||
"for more details.\n";
|
||||
|
||||
static const char *hibernated_volume_msg =
|
||||
"The NTFS partition is hibernated. Please resume and shutdown Windows\n"
|
||||
"properly, or mount the volume read-only with the 'ro' mount option, or\n"
|
||||
"mount the volume read-write with the 'remove_hiberfile' mount option.\n"
|
||||
"For example type on the command line:\n"
|
||||
"\n"
|
||||
" mount -t ntfs-3g -o remove_hiberfile %s %s\n"
|
||||
"\n";
|
||||
|
||||
static const char *unclean_journal_msg =
|
||||
"Mount is denied because NTFS is marked to be in use. Choose one action:\n"
|
||||
"\n"
|
||||
"Choice 1: If you have Windows then disconnect the external devices by\n"
|
||||
" clicking on the 'Safely Remove Hardware' icon in the Windows\n"
|
||||
" taskbar then shutdown Windows cleanly.\n"
|
||||
"\n"
|
||||
"Choice 2: If you don't have Windows then you can use the 'force' option for\n"
|
||||
" your own responsibility. For example type on the command line:\n";
|
||||
|
||||
static const char *opened_volume_msg =
|
||||
"Mount is denied because the NTFS volume is already exclusively opened.\n"
|
||||
"The volume may be already mounted, or another software may use it which\n"
|
||||
"could be identified for example by the help of the 'fuser' command.\n";
|
||||
|
||||
static const char *fakeraid_msg =
|
||||
"Either the device is missing or it's powered down, or you have\n"
|
||||
"SoftRAID hardware and must use an activated, different device under\n"
|
||||
"/dev/mapper/, (e.g. /dev/mapper/nvidia_eahaabcc1) to mount NTFS.\n"
|
||||
"Please see the 'dmraid' documentation for help.\n";
|
||||
|
||||
static const char *access_denied_msg =
|
||||
"Please check '%s' and the ntfs-3g binary permissions,\n"
|
||||
"and the mounting user ID. More explanation is provided at\n"
|
||||
"http://ntfs-3g.org/support.html#unprivileged\n";
|
||||
|
||||
static const char *forced_mount_msg =
|
||||
"\n"
|
||||
" mount -t ntfs-3g -o force %s %s\n"
|
||||
"\n"
|
||||
" Or add the option to the relevant row in the /etc/fstab file:\n"
|
||||
"\n"
|
||||
" %s %s ntfs-3g force 0 0\n";
|
||||
|
||||
/**
|
||||
* ntfs_volume_alloc - Create an NTFS volume object and initialise it
|
||||
*
|
||||
@ -1475,3 +1538,47 @@ int ntfs_volume_error(int err)
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void ntfs_mount_error(const char *volume, const char *mntpoint, int err)
|
||||
{
|
||||
switch (err) {
|
||||
case NTFS_VOLUME_NOT_NTFS:
|
||||
ntfs_log_error(invalid_ntfs_msg, volume);
|
||||
break;
|
||||
case NTFS_VOLUME_CORRUPT:
|
||||
ntfs_log_error("%s", corrupt_volume_msg);
|
||||
break;
|
||||
case NTFS_VOLUME_HIBERNATED:
|
||||
ntfs_log_error(hibernated_volume_msg, volume, mntpoint);
|
||||
break;
|
||||
case NTFS_VOLUME_UNCLEAN_UNMOUNT:
|
||||
ntfs_log_error("%s", unclean_journal_msg);
|
||||
ntfs_log_error(forced_mount_msg, volume, mntpoint,
|
||||
volume, mntpoint);
|
||||
break;
|
||||
case NTFS_VOLUME_LOCKED:
|
||||
ntfs_log_error("%s", opened_volume_msg);
|
||||
break;
|
||||
case NTFS_VOLUME_RAID:
|
||||
ntfs_log_error("%s", fakeraid_msg);
|
||||
break;
|
||||
case NTFS_VOLUME_NO_PRIVILEGE:
|
||||
ntfs_log_error(access_denied_msg, volume);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int ntfs_set_locale(void)
|
||||
{
|
||||
const char *locale;
|
||||
|
||||
locale = setlocale(LC_ALL, "");
|
||||
if (!locale) {
|
||||
locale = setlocale(LC_ALL, NULL);
|
||||
ntfs_log_error("Couldn't set local environment, using default "
|
||||
"'%s'.\n", locale);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -90,7 +90,6 @@
|
||||
#include "unistr.h"
|
||||
#include "layout.h"
|
||||
#include "index.h"
|
||||
#include "utils.h"
|
||||
#include "ntfstime.h"
|
||||
#include "security.h"
|
||||
#include "reparse.h"
|
||||
@ -161,11 +160,6 @@ static char def_opts[] = "silent,allow_other,nonempty,";
|
||||
static ntfs_fuse_context_t *ctx;
|
||||
static u32 ntfs_sequence;
|
||||
|
||||
static const char *locale_msg =
|
||||
"WARNING: Couldn't set locale to '%s' thus some file names may not\n"
|
||||
" be correct or visible. Please see the potential solution at\n"
|
||||
" http://ntfs-3g.org/support.html#locale\n";
|
||||
|
||||
static const char *usage_msg =
|
||||
"\n"
|
||||
"%s %s %s %d - Third Generation NTFS Driver\n"
|
||||
@ -176,8 +170,8 @@ static const char *usage_msg =
|
||||
"\n"
|
||||
"Usage: %s [-o option[,...]] <device|image_file> <mount_point>\n"
|
||||
"\n"
|
||||
"Options: ro (read-only mount), force, remove_hiberfile, locale=,\n"
|
||||
" uid=, gid=, umask=, fmask=, dmask=, streams_interface=.\n"
|
||||
"Options: ro (read-only mount), force, remove_hiberfile, uid=,\n"
|
||||
" gid=, umask=, fmask=, dmask=, streams_interface=.\n"
|
||||
" Please see the details in the manual.\n"
|
||||
"\n"
|
||||
"Examples: ntfs-3g -o force /dev/sda1 /mnt/windows\n"
|
||||
@ -297,7 +291,10 @@ static int ntfs_fuse_statfs(const char *path __attribute__((unused)),
|
||||
if (!vol)
|
||||
return -ENODEV;
|
||||
|
||||
/* File system block size, used for optimal transfer block size. */
|
||||
/*
|
||||
* File system block size. Used to calculate used/free space by df.
|
||||
* Incorrectly documented as "optimal transfer block size".
|
||||
*/
|
||||
sfs->f_bsize = vol->cluster_size;
|
||||
|
||||
/* Fundamental file system block size, used as the unit. */
|
||||
@ -667,7 +664,7 @@ static int ntfs_fuse_filler(ntfs_fuse_fill_context_t *fill_ctx,
|
||||
if (ntfs_ucstombs(name, name_len, &filename, 0) < 0) {
|
||||
ntfs_log_perror("Skipping unrepresentable filename (inode %llu)",
|
||||
(unsigned long long)MREF(mref));
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ntfs_fuse_is_named_data_stream(filename)) {
|
||||
@ -2541,10 +2538,10 @@ static char *parse_mount_options(const char *orig_opts)
|
||||
goto err_exit;
|
||||
ctx->hiberfile = TRUE;
|
||||
} else if (!strcmp(opt, "locale")) {
|
||||
/* option "locale" kept undocumented */
|
||||
if (missing_option_value(val, "locale"))
|
||||
goto err_exit;
|
||||
if (ntfs_set_char_encoding(val))
|
||||
ntfs_log_error(locale_msg, val);
|
||||
ntfs_set_char_encoding(val);
|
||||
} else if (!strcmp(opt, "streams_interface")) {
|
||||
if (missing_option_value(val, "streams_interface"))
|
||||
goto err_exit;
|
||||
@ -2985,7 +2982,7 @@ int main(int argc, char *argv[])
|
||||
if (drop_privs())
|
||||
return NTFS_VOLUME_NO_PRIVILEGE;
|
||||
|
||||
utils_set_locale();
|
||||
ntfs_set_locale();
|
||||
ntfs_log_set_handler(ntfs_log_handler_stderr);
|
||||
|
||||
if (parse_options(argc, argv)) {
|
||||
@ -3123,7 +3120,7 @@ int main(int argc, char *argv[])
|
||||
fuse_unmount(opts.mnt_point, ctx->fc);
|
||||
fuse_destroy(fh);
|
||||
err_out:
|
||||
utils_mount_error(opts.device, opts.mnt_point, err);
|
||||
ntfs_mount_error(opts.device, opts.mnt_point, err);
|
||||
err2:
|
||||
ntfs_close();
|
||||
free(ctx);
|
||||
|
Loading…
Reference in New Issue
Block a user