summaryrefslogtreecommitdiff
Diffstat
-rwxr-xr-xAndroid.mk138
-rwxr-xr-xAndroid.mk.bak89
-rwxr-xr-xCREDITS20
-rwxr-xr-xINSTALL200
-rwxr-xr-xMakefile715
-rwxr-xr-xMakefile.am106
-rwxr-xr-xMakefile.in955
-rwxr-xr-xNEWS4
-rwxr-xr-xREADME80
-rwxr-xr-xTODO.ntfsprogs126
-rwxr-xr-xaclocal.m47091
-rwxr-xr-xcompile21
-rwxr-xr-xconfig.guess292
-rw-r--r--[-rwxr-xr-x]config.h165
-rwxr-xr-xconfig.h.in110
-rwxr-xr-xconfig.log3290
-rwxr-xr-xconfig.status1220
-rwxr-xr-xconfig.sub104
-rwxr-xr-xconfigure26448
-rwxr-xr-xconfigure.ac291
-rwxr-xr-xdepcomp87
-rwxr-xr-xinclude/Makefile.in181
-rwxr-xr-xinclude/fuse-lite/Makefile.in112
-rwxr-xr-xinclude/fuse-lite/fuse.h61
-rwxr-xr-xinclude/fuse-lite/fuse_common.h49
-rwxr-xr-xinclude/fuse-lite/fuse_kernel.h6
-rwxr-xr-xinclude/fuse-lite/fuse_lowlevel.h20
-rwxr-xr-xinclude/ntfs-3g/Makefile.am4
-rwxr-xr-xinclude/ntfs-3g/Makefile.in163
-rwxr-xr-xinclude/ntfs-3g/acls.h3
-rwxr-xr-xinclude/ntfs-3g/attrib.h50
-rwxr-xr-xinclude/ntfs-3g/cache.h7
-rwxr-xr-xinclude/ntfs-3g/compat.h6
-rwxr-xr-xinclude/ntfs-3g/compress.h6
-rwxr-xr-xinclude/ntfs-3g/debug.h4
-rwxr-xr-xinclude/ntfs-3g/device.h18
-rwxr-xr-xinclude/ntfs-3g/device_io.h21
-rwxr-xr-xinclude/ntfs-3g/dir.h11
-rwxr-xr-xinclude/ntfs-3g/layout.h32
-rwxr-xr-xinclude/ntfs-3g/lcnalloc.h1
-rwxr-xr-xinclude/ntfs-3g/logging.h3
-rwxr-xr-xinclude/ntfs-3g/mst.h3
-rwxr-xr-xinclude/ntfs-3g/ntfstime.h12
-rwxr-xr-xinclude/ntfs-3g/param.h72
-rwxr-xr-xinclude/ntfs-3g/realpath.h24
-rwxr-xr-xinclude/ntfs-3g/runlist.h3
-rwxr-xr-xinclude/ntfs-3g/security.h20
-rwxr-xr-xinclude/ntfs-3g/types.h8
-rwxr-xr-xinclude/ntfs-3g/unistr.h13
-rwxr-xr-xinclude/ntfs-3g/volume.h78
-rwxr-xr-xinclude/ntfs-3g/xattrs.h75
-rwxr-xr-xinstall-sh5
-rwxr-xr-xlibfuse-lite/Makefile.am3
-rwxr-xr-xlibfuse-lite/Makefile.in188
-rwxr-xr-xlibfuse-lite/fuse.c418
-rwxr-xr-xlibfuse-lite/fuse_kern_chan.c2
-rwxr-xr-xlibfuse-lite/fuse_lowlevel.c53
-rwxr-xr-xlibfuse-lite/fuse_opt.c20
-rwxr-xr-xlibfuse-lite/fuse_session.c12
-rwxr-xr-xlibfuse-lite/fusermount.c97
-rwxr-xr-xlibfuse-lite/helper.c21
-rwxr-xr-xlibfuse-lite/mount.c486
-rwxr-xr-xlibfuse-lite/mount_util.c246
-rwxr-xr-xlibfuse-lite/mount_util.h11
-rwxr-xr-xlibntfs-3g/Makefile.am15
-rwxr-xr-xlibntfs-3g/Makefile.in420
-rwxr-xr-xlibntfs-3g/acls.c219
-rwxr-xr-xlibntfs-3g/attrib.c1205
-rwxr-xr-xlibntfs-3g/bootsect.c4
-rwxr-xr-xlibntfs-3g/cache.c7
-rwxr-xr-xlibntfs-3g/compress.c962
-rwxr-xr-xlibntfs-3g/device.c252
-rwxr-xr-xlibntfs-3g/dir.c374
-rwxr-xr-xlibntfs-3g/efs.c217
-rwxr-xr-xlibntfs-3g/index.c30
-rwxr-xr-xlibntfs-3g/inode.c46
-rwxr-xr-xlibntfs-3g/lcnalloc.c36
-rw-r--r--libntfs-3g/libntfs-3g.pc10
-rw-r--r--libntfs-3g/libntfs-3g.script.so2
-rwxr-xr-xlibntfs-3g/logfile.c23
-rwxr-xr-xlibntfs-3g/logging.c24
-rwxr-xr-xlibntfs-3g/mft.c12
-rwxr-xr-xlibntfs-3g/mst.c24
-rwxr-xr-xlibntfs-3g/object_id.c9
-rwxr-xr-xlibntfs-3g/realpath.c103
-rwxr-xr-xlibntfs-3g/reparse.c67
-rwxr-xr-xlibntfs-3g/runlist.c62
-rwxr-xr-xlibntfs-3g/security.c345
-rwxr-xr-xlibntfs-3g/unistr.c244
-rwxr-xr-xlibntfs-3g/unix_io.c19
-rwxr-xr-xlibntfs-3g/volume.c365
-rwxr-xr-xlibntfs-3g/win32_io.c708
-rwxr-xr-xlibntfs-3g/xattrs.c791
-rwxr-xr-xlibtool9301
-rwxr-xr-xltmain.sh8439
-rwxr-xr-xm4/libtool.m47377
-rwxr-xr-xm4/ltoptions.m4368
-rwxr-xr-xm4/ltsugar.m4123
-rwxr-xr-xm4/ltversion.m423
-rwxr-xr-xm4/lt~obsolete.m492
-rwxr-xr-xmissing49
-rwxr-xr-xntfsprogs/Makefile.am154
-rwxr-xr-xntfsprogs/Makefile.in1199
-rwxr-xr-xntfsprogs/attrdef.c168
-rwxr-xr-xntfsprogs/attrdef.h7
-rwxr-xr-xntfsprogs/boot.c268
-rwxr-xr-xntfsprogs/boot.h7
-rwxr-xr-xntfsprogs/cluster.c118
-rwxr-xr-xntfsprogs/cluster.h39
-rwxr-xr-xntfsprogs/list.h194
-rw-r--r--ntfsprogs/mkntfs.8290
-rwxr-xr-xntfsprogs/mkntfs.8.in290
-rwxr-xr-xntfsprogs/mkntfs.c5177
-rw-r--r--ntfsprogs/ntfscat.8136
-rwxr-xr-xntfsprogs/ntfscat.8.in136
-rwxr-xr-xntfsprogs/ntfscat.c440
-rwxr-xr-xntfsprogs/ntfscat.h46
-rwxr-xr-xntfsprogs/ntfsck.c883
-rw-r--r--ntfsprogs/ntfsclone.8391
-rwxr-xr-xntfsprogs/ntfsclone.8.in391
-rwxr-xr-xntfsprogs/ntfsclone.c2701
-rw-r--r--ntfsprogs/ntfscluster.8124
-rwxr-xr-xntfsprogs/ntfscluster.8.in124
-rwxr-xr-xntfsprogs/ntfscluster.c563
-rwxr-xr-xntfsprogs/ntfscluster.h63
-rw-r--r--ntfsprogs/ntfscmp.877
-rwxr-xr-xntfsprogs/ntfscmp.8.in77
-rwxr-xr-xntfsprogs/ntfscmp.c1012
-rw-r--r--ntfsprogs/ntfscp.8111
-rwxr-xr-xntfsprogs/ntfscp.8.in111
-rwxr-xr-xntfsprogs/ntfscp.c590
-rwxr-xr-xntfsprogs/ntfsdecrypt.c1436
-rwxr-xr-xntfsprogs/ntfsdump_logfile.c779
-rw-r--r--ntfsprogs/ntfsfix.881
-rwxr-xr-xntfsprogs/ntfsfix.8.in81
-rwxr-xr-xntfsprogs/ntfsfix.c1657
-rw-r--r--ntfsprogs/ntfsinfo.889
-rwxr-xr-xntfsprogs/ntfsinfo.8.in89
-rwxr-xr-xntfsprogs/ntfsinfo.c2384
-rw-r--r--ntfsprogs/ntfslabel.8118
-rwxr-xr-xntfsprogs/ntfslabel.8.in118
-rwxr-xr-xntfsprogs/ntfslabel.c458
-rw-r--r--ntfsprogs/ntfsls.8172
-rwxr-xr-xntfsprogs/ntfsls.8.in172
-rwxr-xr-xntfsprogs/ntfsls.c717
-rwxr-xr-xntfsprogs/ntfsmftalloc.c368
-rwxr-xr-xntfsprogs/ntfsmove.c923
-rwxr-xr-xntfsprogs/ntfsmove.h46
-rw-r--r--ntfsprogs/ntfsprogs.869
-rwxr-xr-xntfsprogs/ntfsprogs.8.in69
-rw-r--r--ntfsprogs/ntfsresize.8326
-rwxr-xr-xntfsprogs/ntfsresize.8.in326
-rwxr-xr-xntfsprogs/ntfsresize.c4497
-rwxr-xr-xntfsprogs/ntfstruncate.c809
-rw-r--r--ntfsprogs/ntfsundelete.8324
-rwxr-xr-xntfsprogs/ntfsundelete.8.in324
-rwxr-xr-xntfsprogs/ntfsundelete.c2490
-rwxr-xr-xntfsprogs/ntfsundelete.h112
-rwxr-xr-xntfsprogs/ntfswipe.c2131
-rwxr-xr-xntfsprogs/ntfswipe.h54
-rwxr-xr-xntfsprogs/sd.c607
-rwxr-xr-xntfsprogs/sd.h11
-rwxr-xr-xntfsprogs/utils.c1184
-rwxr-xr-xntfsprogs/utils.h137
-rwxr-xr-xprog.IAB1071
-rwxr-xr-xprog.IAD5
-rwxr-xr-xprog.IMB466
-rwxr-xr-xprog.IMD2
-rwxr-xr-xprog.PFI2
-rwxr-xr-xprog.PO1
-rwxr-xr-xprog.PR14
-rwxr-xr-xprog.PRI219
-rwxr-xr-xprog.PS979
-rwxr-xr-xprog.SearchResults3
-rwxr-xr-xprog.WK39
-rwxr-xr-xsrc/Makefile.am86
-rwxr-xr-xsrc/Makefile.in938
-rwxr-xr-xsrc/lowntfs-3g.c1538
-rw-r--r--src/ntfs-3g.8448
-rwxr-xr-xsrc/ntfs-3g.8.in217
-rwxr-xr-xsrc/ntfs-3g.c1357
-rw-r--r--src/ntfs-3g.probe.881
-rwxr-xr-xsrc/ntfs-3g.probe.8.in4
-rwxr-xr-xsrc/ntfs-3g.probe.c9
-rw-r--r--src/ntfs-3g.secaudit.8184
-rwxr-xr-xsrc/ntfs-3g.secaudit.8.in15
-rw-r--r--src/ntfs-3g.usermap.896
-rwxr-xr-xsrc/ntfs-3g_common.c745
-rwxr-xr-xsrc/ntfs-3g_common.h185
-rwxr-xr-xsrc/secaudit.c673
-rwxr-xr-xsrc/secaudit.h32
-rwxr-xr-xsrc/usermap.c3
-rw-r--r--[-rwxr-xr-x]stamp-h10
193 files changed, 80411 insertions, 44563 deletions
diff --git a/libntfs-3g/dir.c b/libntfs-3g/dir.c
index 9c82765..2539586 100755
--- a/libntfs-3g/dir.c
+++ b/libntfs-3g/dir.c
@@ -253,10 +253,11 @@ u64 ntfs_inode_lookup_by_name(ntfs_inode *dir_ni,
INDEX_ROOT *ir;
INDEX_ENTRY *ie;
INDEX_ALLOCATION *ia;
+ IGNORE_CASE_BOOL case_sensitivity;
u8 *index_end;
ntfs_attr *ia_na;
int eo, rc;
- u32 index_block_size, index_vcn_size;
+ u32 index_block_size;
u8 index_vcn_size_bits;
ntfs_log_trace("Entering\n");
@@ -277,6 +278,7 @@ u64 ntfs_inode_lookup_by_name(ntfs_inode *dir_ni,
"%lld", (unsigned long long)dir_ni->mft_no);
goto put_err_out;
}
+ case_sensitivity = (NVolCaseSensitive(vol) ? CASE_SENSITIVE : IGNORE_CASE);
/* Get to the index root value. */
ir = (INDEX_ROOT*)((u8*)ctx->attr +
le16_to_cpu(ctx->attr->value_offset));
@@ -324,7 +326,7 @@ u64 ntfs_inode_lookup_by_name(ntfs_inode *dir_ni,
rc = ntfs_names_full_collate(uname, uname_len,
(ntfschar*)&ie->key.file_name.file_name,
ie->key.file_name.file_name_length,
- CASE_SENSITIVE, vol->upcase, vol->upcase_len);
+ case_sensitivity, vol->upcase, vol->upcase_len);
/*
* If uname collates before the name of the current entry, there
* is definitely no such name in this index but we might need to
@@ -354,7 +356,7 @@ u64 ntfs_inode_lookup_by_name(ntfs_inode *dir_ni,
ntfs_attr_put_search_ctx(ctx);
if (mref)
return mref;
- ntfs_log_debug("Entry not found.\n");
+ ntfs_log_debug("Entry not found - between root entries.\n");
errno = ENOENT;
return -1;
} /* Child node present, descend into it. */
@@ -376,11 +378,9 @@ u64 ntfs_inode_lookup_by_name(ntfs_inode *dir_ni,
/* Determine the size of a vcn in the directory index. */
if (vol->cluster_size <= index_block_size) {
- index_vcn_size = vol->cluster_size;
index_vcn_size_bits = vol->cluster_size_bits;
} else {
- index_vcn_size = vol->sector_size;
- index_vcn_size_bits = vol->sector_size_bits;
+ index_vcn_size_bits = NTFS_BLOCK_SIZE_BITS;
}
/* Get the starting vcn of the index_block holding the child node. */
@@ -466,7 +466,7 @@ descend_into_child_node:
rc = ntfs_names_full_collate(uname, uname_len,
(ntfschar*)&ie->key.file_name.file_name,
ie->key.file_name.file_name_length,
- CASE_SENSITIVE, vol->upcase, vol->upcase_len);
+ case_sensitivity, vol->upcase, vol->upcase_len);
/*
* If uname collates before the name of the current entry, there
* is definitely no such name in this index but we might need to
@@ -545,51 +545,68 @@ u64 ntfs_inode_lookup_by_mbsname(ntfs_inode *dir_ni, const char *name)
int uname_len;
ntfschar *uname = (ntfschar*)NULL;
u64 inum;
+ char *cached_name;
+ const char *const_name;
+
+ if (!NVolCaseSensitive(dir_ni->vol)) {
+ cached_name = ntfs_uppercase_mbs(name,
+ dir_ni->vol->upcase, dir_ni->vol->upcase_len);
+ const_name = cached_name;
+ } else {
+ cached_name = (char*)NULL;
+ const_name = name;
+ }
+ if (const_name) {
#if CACHE_LOOKUP_SIZE
- struct CACHED_LOOKUP item;
- struct CACHED_LOOKUP *cached;
/*
* fetch inode from cache
*/
- if (dir_ni->vol->lookup_cache) {
- item.name = name;
- item.namesize = strlen(name) + 1;
- item.parent = dir_ni->mft_no;
- cached = (struct CACHED_LOOKUP*)ntfs_fetch_cache(
- dir_ni->vol->lookup_cache, GENERIC(&item),
- lookup_cache_compare);
- if (cached) {
- inum = cached->inum;
- if (inum == (u64)-1)
- errno = ENOENT;
- } else {
- /* Generate unicode name. */
- uname_len = ntfs_mbstoucs(name, &uname);
- if (uname_len >= 0) {
- inum = ntfs_inode_lookup_by_name(dir_ni,
- uname, uname_len);
- item.inum = inum;
+ if (dir_ni->vol->lookup_cache) {
+ struct CACHED_LOOKUP item;
+ struct CACHED_LOOKUP *cached;
+
+ item.name = const_name;
+ item.namesize = strlen(const_name) + 1;
+ item.parent = dir_ni->mft_no;
+ cached = (struct CACHED_LOOKUP*)ntfs_fetch_cache(
+ dir_ni->vol->lookup_cache,
+ GENERIC(&item), lookup_cache_compare);
+ if (cached) {
+ inum = cached->inum;
+ if (inum == (u64)-1)
+ errno = ENOENT;
+ } else {
+ /* Generate unicode name. */
+ uname_len = ntfs_mbstoucs(name, &uname);
+ if (uname_len >= 0) {
+ inum = ntfs_inode_lookup_by_name(dir_ni,
+ uname, uname_len);
+ item.inum = inum;
/* enter into cache, even if not found */
- ntfs_enter_cache(dir_ni->vol->lookup_cache,
+ ntfs_enter_cache(dir_ni->vol->lookup_cache,
GENERIC(&item),
lookup_cache_compare);
- free(uname);
- } else
+ free(uname);
+ } else
+ inum = (s64)-1;
+ }
+ } else
+#endif
+ {
+ /* Generate unicode name. */
+ uname_len = ntfs_mbstoucs(cached_name, &uname);
+ if (uname_len >= 0)
+ inum = ntfs_inode_lookup_by_name(dir_ni,
+ uname, uname_len);
+ else
inum = (s64)-1;
}
+ if (cached_name)
+ free(cached_name);
} else
-#endif
- {
- /* Generate unicode name. */
- uname_len = ntfs_mbstoucs(name, &uname);
- if (uname_len >= 0)
- inum = ntfs_inode_lookup_by_name(dir_ni,
- uname, uname_len);
- else
- inum = (s64)-1;
- }
+ inum = (s64)-1;
return (inum);
}
@@ -604,17 +621,29 @@ void ntfs_inode_update_mbsname(ntfs_inode *dir_ni, const char *name, u64 inum)
#if CACHE_LOOKUP_SIZE
struct CACHED_LOOKUP item;
struct CACHED_LOOKUP *cached;
+ char *cached_name;
if (dir_ni->vol->lookup_cache) {
- item.name = name;
- item.namesize = strlen(name) + 1;
- item.parent = dir_ni->mft_no;
- item.inum = inum;
- cached = (struct CACHED_LOOKUP*)ntfs_enter_cache(
+ if (!NVolCaseSensitive(dir_ni->vol)) {
+ cached_name = ntfs_uppercase_mbs(name,
+ dir_ni->vol->upcase, dir_ni->vol->upcase_len);
+ item.name = cached_name;
+ } else {
+ cached_name = (char*)NULL;
+ item.name = name;
+ }
+ if (item.name) {
+ item.namesize = strlen(item.name) + 1;
+ item.parent = dir_ni->mft_no;
+ item.inum = inum;
+ cached = (struct CACHED_LOOKUP*)ntfs_enter_cache(
dir_ni->vol->lookup_cache,
GENERIC(&item), lookup_cache_compare);
- if (cached)
- cached->inum = inum;
+ if (cached)
+ cached->inum = inum;
+ if (cached_name)
+ free(cached_name);
+ }
}
#endif
}
@@ -838,6 +867,87 @@ typedef enum {
INDEX_TYPE_ALLOCATION, /* index allocation */
} INDEX_TYPE;
+/*
+ * Decode Interix file types
+ *
+ * Non-Interix types are returned as plain files, because a
+ * Windows user may force patterns very similar to Interix,
+ * and most metadata files have such similar patters.
+ */
+
+static u32 ntfs_interix_types(ntfs_inode *ni)
+{
+ ntfs_attr *na;
+ u32 dt_type;
+ le64 magic;
+
+ dt_type = NTFS_DT_UNKNOWN;
+ na = ntfs_attr_open(ni, AT_DATA, NULL, 0);
+ if (na) {
+ /* Unrecognized patterns (eg HID + SYST) are plain files */
+ dt_type = NTFS_DT_REG;
+ if (na->data_size <= 1) {
+ if (!(ni->flags & FILE_ATTR_HIDDEN))
+ dt_type = (na->data_size ?
+ NTFS_DT_SOCK : NTFS_DT_FIFO);
+ } else {
+ if ((na->data_size >= (s64)sizeof(magic))
+ && (ntfs_attr_pread(na, 0, sizeof(magic), &magic)
+ == sizeof(magic))) {
+ if (magic == INTX_SYMBOLIC_LINK)
+ dt_type = NTFS_DT_LNK;
+ else if (magic == INTX_BLOCK_DEVICE)
+ dt_type = NTFS_DT_BLK;
+ else if (magic == INTX_CHARACTER_DEVICE)
+ dt_type = NTFS_DT_CHR;
+ }
+ }
+ ntfs_attr_close(na);
+ }
+ return (dt_type);
+}
+
+/*
+ * Decode file types
+ *
+ * Better only use for Interix types and junctions,
+ * unneeded complexity when used for plain files or directories
+ *
+ * Error cases are logged and returned as unknown.
+ */
+
+static u32 ntfs_dir_entry_type(ntfs_inode *dir_ni, MFT_REF mref,
+ FILE_ATTR_FLAGS attributes)
+{
+ ntfs_inode *ni;
+ u32 dt_type;
+
+ dt_type = NTFS_DT_UNKNOWN;
+ ni = ntfs_inode_open(dir_ni->vol, mref);
+ if (ni) {
+ if ((attributes & FILE_ATTR_REPARSE_POINT)
+ && ntfs_possible_symlink(ni))
+ dt_type = NTFS_DT_LNK;
+ else
+ if ((attributes & FILE_ATTR_SYSTEM)
+ && !(attributes & FILE_ATTR_I30_INDEX_PRESENT))
+ dt_type = ntfs_interix_types(ni);
+ else
+ dt_type = (attributes
+ & FILE_ATTR_I30_INDEX_PRESENT
+ ? NTFS_DT_DIR : NTFS_DT_REG);
+ if (ntfs_inode_close(ni)) {
+ /* anything special worth doing ? */
+ ntfs_log_error("Failed to close inode %lld\n",
+ (long long)MREF(mref));
+ }
+ }
+ if (dt_type == NTFS_DT_UNKNOWN)
+ ntfs_log_error("Could not decode the type of inode %lld\n",
+ (long long)MREF(mref));
+ return (dt_type);
+}
+
/**
* ntfs_filldir - ntfs specific filldir method
* @dir_ni: ntfs inode of current directory
@@ -858,6 +968,10 @@ static int ntfs_filldir(ntfs_inode *dir_ni, s64 *pos, u8 ivcn_bits,
{
FILE_NAME_ATTR *fn = &ie->key.file_name;
unsigned dt_type;
+ BOOL metadata;
+ ntfschar *loname;
+ int res;
+ MFT_REF mref;
ntfs_log_trace("Entering.\n");
@@ -868,18 +982,51 @@ static int ntfs_filldir(ntfs_inode *dir_ni, s64 *pos, u8 ivcn_bits,
dir_ni->vol->mft_record_size;
else /* if (index_type == INDEX_TYPE_ROOT) */
*pos = (u8*)ie - (u8*)iu.ir;
+ mref = le64_to_cpu(ie->indexed_file);
+ metadata = (MREF(mref) != FILE_root) && (MREF(mref) < FILE_first_user);
/* Skip root directory self reference entry. */
if (MREF_LE(ie->indexed_file) == FILE_root)
return 0;
- if (ie->key.file_name.file_attributes & FILE_ATTR_I30_INDEX_PRESENT)
+ if ((ie->key.file_name.file_attributes
+ & (FILE_ATTR_REPARSE_POINT | FILE_ATTR_SYSTEM))
+ && !metadata)
+ dt_type = ntfs_dir_entry_type(dir_ni, mref,
+ ie->key.file_name.file_attributes);
+ else if (ie->key.file_name.file_attributes
+ & FILE_ATTR_I30_INDEX_PRESENT)
dt_type = NTFS_DT_DIR;
- else if (fn->file_attributes & FILE_ATTR_SYSTEM)
- dt_type = NTFS_DT_UNKNOWN;
else
dt_type = NTFS_DT_REG;
- return filldir(dirent, fn->file_name, fn->file_name_length,
- fn->file_name_type, *pos,
- le64_to_cpu(ie->indexed_file), dt_type);
+
+ /* return metadata files and hidden files if requested */
+ if ((!metadata && (NVolShowHidFiles(dir_ni->vol)
+ || !(fn->file_attributes & FILE_ATTR_HIDDEN)))
+ || (NVolShowSysFiles(dir_ni->vol) && (NVolShowHidFiles(dir_ni->vol)
+ || metadata))) {
+ if (NVolCaseSensitive(dir_ni->vol)) {
+ res = filldir(dirent, fn->file_name,
+ fn->file_name_length,
+ fn->file_name_type, *pos,
+ mref, dt_type);
+ } else {
+ loname = (ntfschar*)ntfs_malloc(2*fn->file_name_length);
+ if (loname) {
+ memcpy(loname, fn->file_name,
+ 2*fn->file_name_length);
+ ntfs_name_locase(loname, fn->file_name_length,
+ dir_ni->vol->locase,
+ dir_ni->vol->upcase_len);
+ res = filldir(dirent, loname,
+ fn->file_name_length,
+ fn->file_name_type, *pos,
+ mref, dt_type);
+ free(loname);
+ } else
+ res = -1;
+ }
+ } else
+ res = 0;
+ return (res);
}
/**
@@ -975,7 +1122,7 @@ int ntfs_readdir(ntfs_inode *dir_ni, s64 *pos,
INDEX_ENTRY *ie;
INDEX_ALLOCATION *ia = NULL;
int rc, ir_pos, bmp_buf_size, bmp_buf_pos, eo;
- u32 index_block_size, index_vcn_size;
+ u32 index_block_size;
u8 index_block_size_bits, index_vcn_size_bits;
ntfs_log_trace("Entering.\n");
@@ -1067,11 +1214,9 @@ int ntfs_readdir(ntfs_inode *dir_ni, s64 *pos,
}
index_block_size_bits = ffs(index_block_size) - 1;
if (vol->cluster_size <= index_block_size) {
- index_vcn_size = vol->cluster_size;
index_vcn_size_bits = vol->cluster_size_bits;
} else {
- index_vcn_size = vol->sector_size;
- index_vcn_size_bits = vol->sector_size_bits;
+ index_vcn_size_bits = NTFS_BLOCK_SIZE_BITS;
}
/* Are we jumping straight into the index allocation attribute? */
@@ -1337,8 +1482,8 @@ err_out:
* on error with errno set to the error code.
*/
static ntfs_inode *__ntfs_create(ntfs_inode *dir_ni, le32 securid,
- ntfschar *name, u8 name_len, mode_t type, dev_t dev,
- ntfschar *target, int target_len)
+ const ntfschar *name, u8 name_len, mode_t type, dev_t dev,
+ const ntfschar *target, int target_len)
{
ntfs_inode *ni;
int rollback_data = 0, rollback_sd = 0;
@@ -1397,7 +1542,20 @@ static ntfs_inode *__ntfs_create(ntfs_inode *dir_ni, le32 securid,
ni->flags = FILE_ATTR_SYSTEM;
}
ni->flags |= FILE_ATTR_ARCHIVE;
+ if (NVolHideDotFiles(dir_ni->vol)
+ && (name_len > 1)
+ && (name[0] == const_cpu_to_le16('.'))
+ && (name[1] != const_cpu_to_le16('.')))
+ ni->flags |= FILE_ATTR_HIDDEN;
+ /*
+ * Set compression flag according to parent directory
+ * unless NTFS version < 3.0 or cluster size > 4K
+ * or compression has been disabled
+ */
if ((dir_ni->flags & FILE_ATTR_COMPRESSED)
+ && (dir_ni->vol->major_ver >= 3)
+ && NVolCompression(dir_ni->vol)
+ && (dir_ni->vol->cluster_size <= MAX_COMPRESSION_CLUSTER_SIZE)
&& (S_ISREG(type) || S_ISDIR(type)))
ni->flags |= FILE_ATTR_COMPRESSED;
/* Add STANDARD_INFORMATION to inode. */
@@ -1440,7 +1598,7 @@ static ntfs_inode *__ntfs_create(ntfs_inode *dir_ni, le32 securid,
else
ir->clusters_per_index_block =
ni->vol->indx_record_size >>
- ni->vol->sector_size_bits;
+ NTFS_BLOCK_SIZE_BITS;
ir->index.entries_offset = cpu_to_le32(sizeof(INDEX_HEADER));
ir->index.index_length = cpu_to_le32(index_len);
ir->index.allocated_size = cpu_to_le32(index_len);
@@ -1527,6 +1685,7 @@ static ntfs_inode *__ntfs_create(ntfs_inode *dir_ni, le32 securid,
else
fn->file_attributes |= ni->flags & FILE_ATTR_COMPRESSED;
fn->file_attributes |= FILE_ATTR_ARCHIVE;
+ fn->file_attributes |= ni->flags & FILE_ATTR_HIDDEN;
fn->creation_time = ni->creation_time;
fn->last_data_change_time = ni->last_data_change_time;
fn->last_mft_change_time = ni->last_mft_change_time;
@@ -1593,7 +1752,7 @@ err_out:
* Some wrappers around __ntfs_create() ...
*/
-ntfs_inode *ntfs_create(ntfs_inode *dir_ni, le32 securid, ntfschar *name,
+ntfs_inode *ntfs_create(ntfs_inode *dir_ni, le32 securid, const ntfschar *name,
u8 name_len, mode_t type)
{
if (type != S_IFREG && type != S_IFDIR && type != S_IFIFO &&
@@ -1605,7 +1764,7 @@ ntfs_inode *ntfs_create(ntfs_inode *dir_ni, le32 securid, ntfschar *name,
}
ntfs_inode *ntfs_create_device(ntfs_inode *dir_ni, le32 securid,
- ntfschar *name, u8 name_len, mode_t type, dev_t dev)
+ const ntfschar *name, u8 name_len, mode_t type, dev_t dev)
{
if (type != S_IFCHR && type != S_IFBLK) {
ntfs_log_error("Invalid arguments.\n");
@@ -1615,7 +1774,8 @@ ntfs_inode *ntfs_create_device(ntfs_inode *dir_ni, le32 securid,
}
ntfs_inode *ntfs_create_symlink(ntfs_inode *dir_ni, le32 securid,
- ntfschar *name, u8 name_len, ntfschar *target, int target_len)
+ const ntfschar *name, u8 name_len, const ntfschar *target,
+ int target_len)
{
if (!target || !target_len) {
ntfs_log_error("%s: Invalid argument (%p, %d)\n", __FUNCTION__,
@@ -1690,7 +1850,8 @@ no_hardlink:
* Return 0 on success or -1 on error with errno set to the error code.
*/
int ntfs_delete(ntfs_volume *vol, const char *pathname,
- ntfs_inode *ni, ntfs_inode *dir_ni, ntfschar *name, u8 name_len)
+ ntfs_inode *ni, ntfs_inode *dir_ni, const ntfschar *name,
+ u8 name_len)
{
ntfs_attr_search_ctx *actx = NULL;
FILE_NAME_ATTR *fn = NULL;
@@ -1734,7 +1895,7 @@ search:
while (!ntfs_attr_lookup(AT_FILE_NAME, AT_UNNAMED, 0, CASE_SENSITIVE,
0, NULL, 0, actx)) {
char *s;
- BOOL case_sensitive = IGNORE_CASE;
+ IGNORE_CASE_BOOL case_sensitive = IGNORE_CASE;
errno = 0;
fn = (FILE_NAME_ATTR*)((u8*)actx->attr +
@@ -1766,8 +1927,9 @@ search:
(long long unsigned)MREF_LE(fn->parent_directory));
continue;
}
-
- if (fn->file_name_type == FILE_NAME_POSIX || case_sensitive_match)
+ if (case_sensitive_match
+ || ((fn->file_name_type == FILE_NAME_POSIX)
+ && NVolCaseSensitive(ni->vol)))
case_sensitive = CASE_SENSITIVE;
if (ntfs_names_are_equal(fn->file_name, fn->file_name_length,
@@ -1803,8 +1965,18 @@ search:
if (ntfs_index_remove(dir_ni, ni, fn, le32_to_cpu(actx->attr->value_length)))
goto err_out;
- if (ntfs_attr_record_rm(actx))
- goto err_out;
+ /*
+ * Keep the last name in place, this is useful for undeletion
+ * (Windows also does so), however delete the name if it were
+ * in an extent, to avoid leaving an attribute list.
+ */
+ if ((ni->mrec->link_count == cpu_to_le16(1)) && !actx->base_ntfs_ino) {
+ /* make sure to not loop to another search */
+ looking_for_dos_name = FALSE;
+ } else {
+ if (ntfs_attr_record_rm(actx))
+ goto err_out;
+ }
ni->mrec->link_count = cpu_to_le16(le16_to_cpu(
ni->mrec->link_count) - 1);
@@ -1927,6 +2099,7 @@ search:
"Leaving inconsistent metadata.\n");
}
#endif
+ debug_double_inode(ni->mft_no,0);
if (ntfs_mft_record_free(ni->vol, ni)) {
err = errno;
ntfs_log_error("Failed to free base MFT record. "
@@ -1969,7 +2142,7 @@ err_out:
*
* Return 0 on success or -1 on error with errno set to the error code.
*/
-static int ntfs_link_i(ntfs_inode *ni, ntfs_inode *dir_ni, ntfschar *name,
+static int ntfs_link_i(ntfs_inode *ni, ntfs_inode *dir_ni, const ntfschar *name,
u8 name_len, FILE_NAME_TYPE_FLAGS nametype)
{
FILE_NAME_ATTR *fn = NULL;
@@ -1989,6 +2162,15 @@ static int ntfs_link_i(ntfs_inode *ni, ntfs_inode *dir_ni, ntfschar *name,
err = EOPNOTSUPP;
goto err_out;
}
+ if (NVolHideDotFiles(dir_ni->vol)) {
+ /* Set hidden flag according to the latest name */
+ if ((name_len > 1)
+ && (name[0] == const_cpu_to_le16('.'))
+ && (name[1] != const_cpu_to_le16('.')))
+ ni->flags |= FILE_ATTR_HIDDEN;
+ else
+ ni->flags &= ~FILE_ATTR_HIDDEN;
+ }
/* Create FILE_NAME attribute. */
fn_len = sizeof(FILE_NAME_ATTR) + name_len * sizeof(ntfschar);
@@ -2046,7 +2228,8 @@ err_out:
return -1;
}
-int ntfs_link(ntfs_inode *ni, ntfs_inode *dir_ni, ntfschar *name, u8 name_len)
+int ntfs_link(ntfs_inode *ni, ntfs_inode *dir_ni, const ntfschar *name,
+ u8 name_len)
{
return (ntfs_link_i(ni, dir_ni, name, name_len, FILE_NAME_POSIX));
}
@@ -2097,6 +2280,8 @@ ntfs_inode *ntfs_dir_parent_inode(ntfs_inode *ni)
/*
* Get a DOS name for a file in designated directory
*
+ * Not allowed if there are several non-dos names (EMLINK)
+ *
* Returns size if found
* 0 if not found
* -1 if there was an error (described by errno)
@@ -2105,6 +2290,7 @@ ntfs_inode *ntfs_dir_parent_inode(ntfs_inode *ni)
static int get_dos_name(ntfs_inode *ni, u64 dnum, ntfschar *dosname)
{
size_t outsize = 0;
+ int namecount = 0;
FILE_NAME_ATTR *fn;
ntfs_attr_search_ctx *ctx;
@@ -2119,6 +2305,8 @@ static int get_dos_name(ntfs_inode *ni, u64 dnum, ntfschar *dosname)
fn = (FILE_NAME_ATTR*)((u8*)ctx->attr +
le16_to_cpu(ctx->attr->value_offset));
+ if (fn->file_name_type != FILE_NAME_DOS)
+ namecount++;
if ((fn->file_name_type & FILE_NAME_DOS)
&& (MREF_LE(fn->parent_directory) == dnum)) {
/*
@@ -2133,6 +2321,10 @@ static int get_dos_name(ntfs_inode *ni, u64 dnum, ntfschar *dosname)
}
}
ntfs_attr_put_search_ctx(ctx);
+ if ((outsize > 0) && (namecount > 1)) {
+ outsize = -1;
+ errno = EMLINK; /* this error implies there is a dos name */
+ }
return (outsize);
}
@@ -2140,6 +2332,8 @@ static int get_dos_name(ntfs_inode *ni, u64 dnum, ntfschar *dosname)
/*
* Get a long name for a file in designated directory
*
+ * Not allowed if there are several non-dos names (EMLINK)
+ *
* Returns size if found
* 0 if not found
* -1 if there was an error (described by errno)
@@ -2148,6 +2342,7 @@ static int get_dos_name(ntfs_inode *ni, u64 dnum, ntfschar *dosname)
static int get_long_name(ntfs_inode *ni, u64 dnum, ntfschar *longname)
{
size_t outsize = 0;
+ int namecount = 0;
FILE_NAME_ATTR *fn;
ntfs_attr_search_ctx *ctx;
@@ -2163,6 +2358,8 @@ static int get_long_name(ntfs_inode *ni, u64 dnum, ntfschar *longname)
fn = (FILE_NAME_ATTR*)((u8*)ctx->attr +
le16_to_cpu(ctx->attr->value_offset));
+ if (fn->file_name_type != FILE_NAME_DOS)
+ namecount++;
if ((fn->file_name_type & FILE_NAME_WIN32)
&& (MREF_LE(fn->parent_directory) == dnum)) {
/*
@@ -2173,6 +2370,11 @@ static int get_long_name(ntfs_inode *ni, u64 dnum, ntfschar *longname)
memcpy(longname,fn->file_name,outsize*sizeof(ntfschar));
}
}
+ if (namecount > 1) {
+ ntfs_attr_put_search_ctx(ctx);
+ errno = EMLINK;
+ return -1;
+ }
/* if not found search for POSIX names */
if (!outsize) {
ntfs_attr_reinit_search_ctx(ctx);
@@ -2249,7 +2451,7 @@ int ntfs_get_ntfs_dos_name(ntfs_inode *ni, ntfs_inode *dir_ni,
*/
static int set_namespace(ntfs_inode *ni, ntfs_inode *dir_ni,
- ntfschar *name, int len,
+ const ntfschar *name, int len,
FILE_NAME_TYPE_FLAGS nametype)
{
ntfs_attr_search_ctx *actx;
@@ -2323,9 +2525,9 @@ static int set_namespace(ntfs_inode *ni, ntfs_inode *dir_ni,
*/
static int set_dos_name(ntfs_inode *ni, ntfs_inode *dir_ni,
- ntfschar *shortname, int shortlen,
- ntfschar *longname, int longlen,
- ntfschar *deletename, int deletelen, BOOL existed)
+ const ntfschar *shortname, int shortlen,
+ const ntfschar *longname, int longlen,
+ const ntfschar *deletename, int deletelen, BOOL existed)
{
unsigned int linkcount;
ntfs_volume *vol;
@@ -2429,24 +2631,24 @@ int ntfs_set_ntfs_dos_name(ntfs_inode *ni, ntfs_inode *dir_ni,
int res = 0;
int longlen = 0;
int shortlen = 0;
- char newname[MAX_DOS_NAME_LENGTH + 1];
+ char newname[3*MAX_DOS_NAME_LENGTH + 1];
ntfschar oldname[MAX_DOS_NAME_LENGTH];
int oldlen;
- ntfs_volume *vol;
- u64 fnum;
u64 dnum;
BOOL closed = FALSE;
ntfschar *shortname = NULL;
ntfschar longname[NTFS_MAX_NAME_LEN];
- vol = ni->vol;
- fnum = ni->mft_no;
- /* convert the string to the NTFS wide chars */
- if (size > MAX_DOS_NAME_LENGTH)
- size = MAX_DOS_NAME_LENGTH;
+ /* copy the string to insert a null char, and truncate */
+ if (size > 3*MAX_DOS_NAME_LENGTH)
+ size = 3*MAX_DOS_NAME_LENGTH;
strncpy(newname, value, size);
+ /* a long name may be truncated badly and be untranslatable */
newname[size] = 0;
+ /* convert the string to the NTFS wide chars, and truncate */
shortlen = ntfs_mbstoucs(newname, &shortname);
+ 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)) {
ntfs_inode_close_in_dir(ni,dir_ni);
@@ -2493,7 +2695,8 @@ int ntfs_set_ntfs_dos_name(ntfs_inode *ni, ntfs_inode *dir_ni,
res = -1;
} else {
res = -1;
- errno = ENOENT;
+ if (!longlen)
+ errno = ENOENT;
}
free(shortname);
if (!closed) {
@@ -2569,7 +2772,8 @@ int ntfs_remove_ntfs_dos_name(ntfs_inode *ni, ntfs_inode *dir_ni)
}
}
} else {
- errno = ENOENT;
+ if (!longlen)
+ errno = ENOENT;
res = -1;
}
if (!deleted) {