mirror of
https://github.com/Maschell/libntfs-wiiu.git
synced 2024-12-18 08:01:50 +01:00
Probably broke the wii/cube support, but wii u should work now!
This commit is contained in:
parent
844e936067
commit
bb10015e70
@ -27,18 +27,18 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__gamecube__) || defined (__wii__)
|
/*#if defined(__gamecube__) || defined (__wii__)
|
||||||
#include <gctypes.h>
|
#include <gctypes.h>
|
||||||
#include <ogc/disc_io.h>
|
#include <ogc/disc_io.h>
|
||||||
#include <gccore.h>
|
#include <gccore.h>
|
||||||
#elif defined (__wiiu__)
|
#elif defined (__wiiu__)*/
|
||||||
#include <iosuhax_disc_interface.h>
|
#include <iosuhax_disc_interface.h>
|
||||||
typedef uint8_t u8;
|
typedef uint8_t u8;
|
||||||
typedef uint16_t u16;
|
typedef uint16_t u16;
|
||||||
typedef int32_t s32;
|
typedef int32_t s32;
|
||||||
typedef uint32_t u32;
|
typedef uint32_t u32;
|
||||||
typedef int mutex_t;
|
typedef int mutex_t;
|
||||||
#endif
|
/*#endif*/
|
||||||
|
|
||||||
/* NTFS errno values */
|
/* NTFS errno values */
|
||||||
#define ENOPART 3000 /* No partition was found */
|
#define ENOPART 3000 /* No partition was found */
|
||||||
|
@ -8,7 +8,7 @@ $(error "Please set DEVKITPPC in your environment. export DEVKITPPC=<path to>dev
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(PLATFORM),wiiu)
|
ifeq ($(PLATFORM),wiiu)
|
||||||
include $(DEVKITPPC)/wii_rules
|
include $(DEVKITPPC)/wiiu_rules
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(PLATFORM),wii)
|
ifeq ($(PLATFORM),wii)
|
||||||
@ -32,7 +32,7 @@ LIBDIR := ../lib
|
|||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
# options for code generation
|
# options for code generation
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
CFLAGS = -Os -Wall -ffast-math -pipe $(MACHDEP) $(INCLUDE) -DHAVE_CONFIG_H
|
CFLAGS = -Wall -ffast-math -pipe $(MACHDEP) $(INCLUDE) -DHAVE_CONFIG_H
|
||||||
CXXFLAGS = $(CFLAGS)
|
CXXFLAGS = $(CFLAGS)
|
||||||
ASFLAGS := -g
|
ASFLAGS := -g
|
||||||
export NTFSBIN := $(LIBDIR)/$(PLATFORM)/libntfs.a
|
export NTFSBIN := $(LIBDIR)/$(PLATFORM)/libntfs.a
|
||||||
@ -87,11 +87,9 @@ export OFILES := $(addsuffix .o,$(BINFILES)) \
|
|||||||
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
|
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
|
||||||
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
||||||
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
||||||
-I$(CURDIR)/$(BUILD) \
|
-I$(CURDIR)/$(BUILD) -I$(PORTLIBS)/include
|
||||||
-I$(LIBOGC_INC)
|
|
||||||
|
|
||||||
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) \
|
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) $(PORTLIBS)/lib
|
||||||
-L$(LIBOGC_LIB)
|
|
||||||
|
|
||||||
.PHONY: $(BUILD) clean
|
.PHONY: $(BUILD) clean
|
||||||
|
|
||||||
|
@ -73,7 +73,7 @@ BOOL ntfs_boot_sector_is_ntfs(NTFS_BOOT_SECTOR *b)
|
|||||||
ntfs_log_debug("Checking bytes per sector.\n");
|
ntfs_log_debug("Checking bytes per sector.\n");
|
||||||
if (le16_to_cpu(b->bpb.bytes_per_sector) < 256 ||
|
if (le16_to_cpu(b->bpb.bytes_per_sector) < 256 ||
|
||||||
le16_to_cpu(b->bpb.bytes_per_sector) > 4096) {
|
le16_to_cpu(b->bpb.bytes_per_sector) > 4096) {
|
||||||
ntfs_log_error("Unexpected bytes per sector value (%d).\n",
|
ntfs_log_error("Unexpected bytes per sector value (%d).\n",
|
||||||
le16_to_cpu(b->bpb.bytes_per_sector));
|
le16_to_cpu(b->bpb.bytes_per_sector));
|
||||||
goto not_ntfs;
|
goto not_ntfs;
|
||||||
}
|
}
|
||||||
@ -89,10 +89,10 @@ BOOL ntfs_boot_sector_is_ntfs(NTFS_BOOT_SECTOR *b)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ntfs_log_debug("Checking cluster size.\n");
|
ntfs_log_debug("Checking cluster size.\n");
|
||||||
i = (u32)le16_to_cpu(b->bpb.bytes_per_sector) *
|
i = (u32)le16_to_cpu(b->bpb.bytes_per_sector) *
|
||||||
b->bpb.sectors_per_cluster;
|
b->bpb.sectors_per_cluster;
|
||||||
if (i > 65536) {
|
if (i > 65536) {
|
||||||
ntfs_log_error("Unexpected cluster size (%d).\n", i);
|
ntfs_log_error("Unexpected cluster size (%d).\n", (int)i);
|
||||||
goto not_ntfs;
|
goto not_ntfs;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,7 +109,7 @@ BOOL ntfs_boot_sector_is_ntfs(NTFS_BOOT_SECTOR *b)
|
|||||||
le16_to_cpu(b->bpb.root_entries),
|
le16_to_cpu(b->bpb.root_entries),
|
||||||
le16_to_cpu(b->bpb.sectors),
|
le16_to_cpu(b->bpb.sectors),
|
||||||
le16_to_cpu(b->bpb.sectors_per_fat),
|
le16_to_cpu(b->bpb.sectors_per_fat),
|
||||||
le32_to_cpu(b->bpb.large_sectors),
|
(int)le32_to_cpu(b->bpb.large_sectors),
|
||||||
b->bpb.fats);
|
b->bpb.fats);
|
||||||
goto not_ntfs;
|
goto not_ntfs;
|
||||||
}
|
}
|
||||||
@ -193,14 +193,14 @@ int ntfs_boot_sector_parse(ntfs_volume *vol, const NTFS_BOOT_SECTOR *bs)
|
|||||||
"\n", sectors_per_cluster);
|
"\n", sectors_per_cluster);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
sectors = sle64_to_cpu(bs->number_of_sectors);
|
sectors = sle64_to_cpu(bs->number_of_sectors);
|
||||||
ntfs_log_debug("NumberOfSectors = %lld\n", (long long)sectors);
|
ntfs_log_debug("NumberOfSectors = %lld\n", (long long)sectors);
|
||||||
if (!sectors) {
|
if (!sectors) {
|
||||||
ntfs_log_error("Volume size is set to zero.\n");
|
ntfs_log_error("Volume size is set to zero.\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (vol->dev->d_ops->seek(vol->dev,
|
if (vol->dev->d_ops->seek(vol->dev,
|
||||||
(sectors - 1) << vol->sector_size_bits,
|
(sectors - 1) << vol->sector_size_bits,
|
||||||
SEEK_SET) == -1) {
|
SEEK_SET) == -1) {
|
||||||
ntfs_log_perror("Failed to read last sector (%lld)",
|
ntfs_log_perror("Failed to read last sector (%lld)",
|
||||||
@ -208,7 +208,7 @@ int ntfs_boot_sector_parse(ntfs_volume *vol, const NTFS_BOOT_SECTOR *bs)
|
|||||||
ntfs_log_error("%s", last_sector_error);
|
ntfs_log_error("%s", last_sector_error);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
vol->nr_clusters = sectors >> (ffs(sectors_per_cluster) - 1);
|
vol->nr_clusters = sectors >> (ffs(sectors_per_cluster) - 1);
|
||||||
|
|
||||||
vol->mft_lcn = sle64_to_cpu(bs->mft_lcn);
|
vol->mft_lcn = sle64_to_cpu(bs->mft_lcn);
|
||||||
@ -223,11 +223,11 @@ int ntfs_boot_sector_parse(ntfs_volume *vol, const NTFS_BOOT_SECTOR *bs)
|
|||||||
(long long)vol->nr_clusters);
|
(long long)vol->nr_clusters);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
vol->cluster_size = sectors_per_cluster * vol->sector_size;
|
vol->cluster_size = sectors_per_cluster * vol->sector_size;
|
||||||
if (vol->cluster_size & (vol->cluster_size - 1)) {
|
if (vol->cluster_size & (vol->cluster_size - 1)) {
|
||||||
ntfs_log_error("cluster_size (%d) is not a power of 2.\n",
|
ntfs_log_error("cluster_size (%d) is not a power of 2.\n",
|
||||||
vol->cluster_size);
|
(int)vol->cluster_size);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
vol->cluster_size_bits = ffs(vol->cluster_size) - 1;
|
vol->cluster_size_bits = ffs(vol->cluster_size) - 1;
|
||||||
@ -252,7 +252,7 @@ int ntfs_boot_sector_parse(ntfs_volume *vol, const NTFS_BOOT_SECTOR *bs)
|
|||||||
vol->mft_record_size = c << vol->cluster_size_bits;
|
vol->mft_record_size = c << vol->cluster_size_bits;
|
||||||
if (vol->mft_record_size & (vol->mft_record_size - 1)) {
|
if (vol->mft_record_size & (vol->mft_record_size - 1)) {
|
||||||
ntfs_log_error("mft_record_size (%d) is not a power of 2.\n",
|
ntfs_log_error("mft_record_size (%d) is not a power of 2.\n",
|
||||||
vol->mft_record_size);
|
(int)vol->mft_record_size);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
vol->mft_record_size_bits = ffs(vol->mft_record_size) - 1;
|
vol->mft_record_size_bits = ffs(vol->mft_record_size) - 1;
|
||||||
|
@ -35,7 +35,11 @@
|
|||||||
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <ogc/lwp_watchdog.h>
|
#if defined (__wiiu__)
|
||||||
|
|
||||||
|
#elif defined(__gamecube__) || defined (__wii__)
|
||||||
|
#include <ogc/lwp_watchdog.h>
|
||||||
|
#endif
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
|
||||||
|
@ -49,6 +49,7 @@
|
|||||||
typedef uint16_t u16;
|
typedef uint16_t u16;
|
||||||
typedef int32_t s32;
|
typedef int32_t s32;
|
||||||
typedef uint32_t u32;
|
typedef uint32_t u32;
|
||||||
|
typedef uint64_t u64;
|
||||||
typedef int mutex_t;
|
typedef int mutex_t;
|
||||||
#elif defined(__gamecube__) || defined (__wii__)
|
#elif defined(__gamecube__) || defined (__wii__)
|
||||||
#include <gctypes.h>
|
#include <gctypes.h>
|
||||||
|
@ -69,11 +69,11 @@ extern char *strsep(char **stringp, const char *delim);
|
|||||||
#define O_BINARY 0 /* unix is binary by default */
|
#define O_BINARY 0 /* unix is binary by default */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef GEKKO
|
#if defined(GEKKO) || defined (__wiiu__)
|
||||||
|
|
||||||
#include "mem_allocate.h"
|
#include "mem_allocate.h"
|
||||||
|
|
||||||
#define XATTR_CREATE 1
|
#define XATTR_CREATE 1
|
||||||
#define XATTR_REPLACE 2
|
#define XATTR_REPLACE 2
|
||||||
|
|
||||||
#define MINORBITS 20
|
#define MINORBITS 20
|
||||||
@ -81,7 +81,7 @@ extern char *strsep(char **stringp, const char *delim);
|
|||||||
|
|
||||||
#define major(dev) ((unsigned int) ((dev) >> MINORBITS))
|
#define major(dev) ((unsigned int) ((dev) >> MINORBITS))
|
||||||
#define minor(dev) ((unsigned int) ((dev) & MINORMASK))
|
#define minor(dev) ((unsigned int) ((dev) & MINORMASK))
|
||||||
#define mkdev(ma,mi) (((ma) << MINORBITS) | (mi))
|
#define mkdev(ma,mi) (((ma) << MINORBITS) | (mi))
|
||||||
#define random rand
|
#define random rand
|
||||||
|
|
||||||
#endif /* defined GEKKO */
|
#endif /* defined GEKKO */
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
#ifndef __CYGWIN32__
|
#ifndef __CYGWIN32__
|
||||||
|
|
||||||
/* Not on Cygwin; use standard Unix style low level device operations. */
|
/* Not on Cygwin; use standard Unix style low level device operations. */
|
||||||
#include "unix_io.c"
|
//#include "unix_io.c"
|
||||||
|
|
||||||
#else /* __CYGWIN32__ */
|
#else /* __CYGWIN32__ */
|
||||||
|
|
||||||
|
99
source/dir.c
99
source/dir.c
@ -66,6 +66,11 @@
|
|||||||
#include <sys/xattr.h>
|
#include <sys/xattr.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(__wiiu__)
|
||||||
|
#define major(dev) ((int)(((unsigned int) (dev) >> 8) & 0xff))
|
||||||
|
#define minor(dev) ((int)((dev) & 0xff))
|
||||||
|
#endif // defined
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The little endian Unicode strings "$I30", "$SII", "$SDH", "$O"
|
* The little endian Unicode strings "$I30", "$SII", "$SDH", "$O"
|
||||||
* and "$Q" as global constants.
|
* and "$Q" as global constants.
|
||||||
@ -313,7 +318,7 @@ u64 ntfs_inode_lookup_by_name(ntfs_inode *dir_ni,
|
|||||||
*/
|
*/
|
||||||
if (ie->ie_flags & INDEX_ENTRY_END)
|
if (ie->ie_flags & INDEX_ENTRY_END)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (!le16_to_cpu(ie->length)) {
|
if (!le16_to_cpu(ie->length)) {
|
||||||
ntfs_log_error("Zero length index entry in inode %lld"
|
ntfs_log_error("Zero length index entry in inode %lld"
|
||||||
"\n", (unsigned long long)dir_ni->mft_no);
|
"\n", (unsigned long long)dir_ni->mft_no);
|
||||||
@ -441,7 +446,7 @@ descend_into_child_node:
|
|||||||
(u8*)ie + le16_to_cpu(ie->key_length) >
|
(u8*)ie + le16_to_cpu(ie->key_length) >
|
||||||
index_end) {
|
index_end) {
|
||||||
ntfs_log_error("Index entry out of bounds in directory "
|
ntfs_log_error("Index entry out of bounds in directory "
|
||||||
"inode %lld.\n",
|
"inode %lld.\n",
|
||||||
(unsigned long long)dir_ni->mft_no);
|
(unsigned long long)dir_ni->mft_no);
|
||||||
errno = EIO;
|
errno = EIO;
|
||||||
goto close_err_out;
|
goto close_err_out;
|
||||||
@ -452,7 +457,7 @@ descend_into_child_node:
|
|||||||
*/
|
*/
|
||||||
if (ie->ie_flags & INDEX_ENTRY_END)
|
if (ie->ie_flags & INDEX_ENTRY_END)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (!le16_to_cpu(ie->length)) {
|
if (!le16_to_cpu(ie->length)) {
|
||||||
errno = EIO;
|
errno = EIO;
|
||||||
ntfs_log_error("Zero length index entry in inode %lld"
|
ntfs_log_error("Zero length index entry in inode %lld"
|
||||||
@ -681,9 +686,9 @@ ntfs_inode *ntfs_pathname_to_inode(ntfs_volume *vol, ntfs_inode *parent,
|
|||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ntfs_log_trace("path: '%s'\n", pathname);
|
ntfs_log_trace("path: '%s'\n", pathname);
|
||||||
|
|
||||||
ascii = strdup(pathname);
|
ascii = strdup(pathname);
|
||||||
if (!ascii) {
|
if (!ascii) {
|
||||||
ntfs_log_error("Out of memory.\n");
|
ntfs_log_error("Out of memory.\n");
|
||||||
@ -818,7 +823,7 @@ ntfs_inode *ntfs_pathname_to_inode(ntfs_volume *vol, ntfs_inode *parent,
|
|||||||
err = EIO;
|
err = EIO;
|
||||||
goto close;
|
goto close;
|
||||||
}
|
}
|
||||||
|
|
||||||
free(unicode);
|
free(unicode);
|
||||||
unicode = NULL;
|
unicode = NULL;
|
||||||
|
|
||||||
@ -974,7 +979,7 @@ static int ntfs_filldir(ntfs_inode *dir_ni, s64 *pos, u8 ivcn_bits,
|
|||||||
MFT_REF mref;
|
MFT_REF mref;
|
||||||
|
|
||||||
ntfs_log_trace("Entering.\n");
|
ntfs_log_trace("Entering.\n");
|
||||||
|
|
||||||
/* Advance the position even if going to skip the entry. */
|
/* Advance the position even if going to skip the entry. */
|
||||||
if (index_type == INDEX_TYPE_ALLOCATION)
|
if (index_type == INDEX_TYPE_ALLOCATION)
|
||||||
*pos = (u8*)ie - (u8*)iu.ia + (sle64_to_cpu(
|
*pos = (u8*)ie - (u8*)iu.ia + (sle64_to_cpu(
|
||||||
@ -1055,7 +1060,7 @@ static MFT_REF ntfs_mft_get_parent_ref(ntfs_inode *ni)
|
|||||||
int eo;
|
int eo;
|
||||||
|
|
||||||
ntfs_log_trace("Entering.\n");
|
ntfs_log_trace("Entering.\n");
|
||||||
|
|
||||||
if (!ni) {
|
if (!ni) {
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return ERR_MREF(-1);
|
return ERR_MREF(-1);
|
||||||
@ -1065,7 +1070,7 @@ static MFT_REF ntfs_mft_get_parent_ref(ntfs_inode *ni)
|
|||||||
if (!ctx)
|
if (!ctx)
|
||||||
return ERR_MREF(-1);
|
return ERR_MREF(-1);
|
||||||
if (ntfs_attr_lookup(AT_FILE_NAME, AT_UNNAMED, 0, 0, 0, NULL, 0, ctx)) {
|
if (ntfs_attr_lookup(AT_FILE_NAME, AT_UNNAMED, 0, 0, 0, NULL, 0, ctx)) {
|
||||||
ntfs_log_error("No file name found in inode %lld\n",
|
ntfs_log_error("No file name found in inode %lld\n",
|
||||||
(unsigned long long)ni->mft_no);
|
(unsigned long long)ni->mft_no);
|
||||||
goto err_out;
|
goto err_out;
|
||||||
}
|
}
|
||||||
@ -1126,7 +1131,7 @@ int ntfs_readdir(ntfs_inode *dir_ni, s64 *pos,
|
|||||||
u8 index_block_size_bits, index_vcn_size_bits;
|
u8 index_block_size_bits, index_vcn_size_bits;
|
||||||
|
|
||||||
ntfs_log_trace("Entering.\n");
|
ntfs_log_trace("Entering.\n");
|
||||||
|
|
||||||
if (!dir_ni || !pos || !filldir) {
|
if (!dir_ni || !pos || !filldir) {
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return -1;
|
return -1;
|
||||||
@ -1246,10 +1251,10 @@ int ntfs_readdir(ntfs_inode *dir_ni, s64 *pos,
|
|||||||
/* The last entry cannot contain a name. */
|
/* The last entry cannot contain a name. */
|
||||||
if (ie->ie_flags & INDEX_ENTRY_END)
|
if (ie->ie_flags & INDEX_ENTRY_END)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (!le16_to_cpu(ie->length))
|
if (!le16_to_cpu(ie->length))
|
||||||
goto dir_err_out;
|
goto dir_err_out;
|
||||||
|
|
||||||
/* Skip index root entry if continuing previous readdir. */
|
/* Skip index root entry if continuing previous readdir. */
|
||||||
if (ir_pos > (u8*)ie - (u8*)ir)
|
if (ir_pos > (u8*)ie - (u8*)ir)
|
||||||
continue;
|
continue;
|
||||||
@ -1402,10 +1407,10 @@ find_next_index_buffer:
|
|||||||
/* The last entry cannot contain a name. */
|
/* The last entry cannot contain a name. */
|
||||||
if (ie->ie_flags & INDEX_ENTRY_END)
|
if (ie->ie_flags & INDEX_ENTRY_END)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (!le16_to_cpu(ie->length))
|
if (!le16_to_cpu(ie->length))
|
||||||
goto dir_err_out;
|
goto dir_err_out;
|
||||||
|
|
||||||
/* Skip index entry if continuing previous readdir. */
|
/* Skip index entry if continuing previous readdir. */
|
||||||
if (ia_pos - ia_start > (u8*)ie - (u8*)ia)
|
if (ia_pos - ia_start > (u8*)ie - (u8*)ia)
|
||||||
continue;
|
continue;
|
||||||
@ -1492,19 +1497,19 @@ static ntfs_inode *__ntfs_create(ntfs_inode *dir_ni, le32 securid,
|
|||||||
int err, fn_len, si_len;
|
int err, fn_len, si_len;
|
||||||
|
|
||||||
ntfs_log_trace("Entering.\n");
|
ntfs_log_trace("Entering.\n");
|
||||||
|
|
||||||
/* Sanity checks. */
|
/* Sanity checks. */
|
||||||
if (!dir_ni || !name || !name_len) {
|
if (!dir_ni || !name || !name_len) {
|
||||||
ntfs_log_error("Invalid arguments.\n");
|
ntfs_log_error("Invalid arguments.\n");
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dir_ni->flags & FILE_ATTR_REPARSE_POINT) {
|
if (dir_ni->flags & FILE_ATTR_REPARSE_POINT) {
|
||||||
errno = EOPNOTSUPP;
|
errno = EOPNOTSUPP;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ni = ntfs_mft_record_alloc(dir_ni->vol, NULL);
|
ni = ntfs_mft_record_alloc(dir_ni->vol, NULL);
|
||||||
if (!ni)
|
if (!ni)
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -1596,7 +1601,7 @@ static ntfs_inode *__ntfs_create(ntfs_inode *dir_ni, le32 securid,
|
|||||||
ni->vol->indx_record_size >>
|
ni->vol->indx_record_size >>
|
||||||
ni->vol->cluster_size_bits;
|
ni->vol->cluster_size_bits;
|
||||||
else
|
else
|
||||||
ir->clusters_per_index_block =
|
ir->clusters_per_index_block =
|
||||||
ni->vol->indx_record_size >>
|
ni->vol->indx_record_size >>
|
||||||
NTFS_BLOCK_SIZE_BITS;
|
NTFS_BLOCK_SIZE_BITS;
|
||||||
ir->index.entries_offset = cpu_to_le32(sizeof(INDEX_HEADER));
|
ir->index.entries_offset = cpu_to_le32(sizeof(INDEX_HEADER));
|
||||||
@ -1725,7 +1730,7 @@ err_out:
|
|||||||
|
|
||||||
if (rollback_sd)
|
if (rollback_sd)
|
||||||
ntfs_attr_remove(ni, AT_SECURITY_DESCRIPTOR, AT_UNNAMED, 0);
|
ntfs_attr_remove(ni, AT_SECURITY_DESCRIPTOR, AT_UNNAMED, 0);
|
||||||
|
|
||||||
if (rollback_data)
|
if (rollback_data)
|
||||||
ntfs_attr_remove(ni, AT_DATA, AT_UNNAMED, 0);
|
ntfs_attr_remove(ni, AT_DATA, AT_UNNAMED, 0);
|
||||||
/*
|
/*
|
||||||
@ -1790,7 +1795,7 @@ int ntfs_check_empty_dir(ntfs_inode *ni)
|
|||||||
{
|
{
|
||||||
ntfs_attr *na;
|
ntfs_attr *na;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if (!(ni->mrec->flags & MFT_RECORD_IS_DIRECTORY))
|
if (!(ni->mrec->flags & MFT_RECORD_IS_DIRECTORY))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -1800,7 +1805,7 @@ int ntfs_check_empty_dir(ntfs_inode *ni)
|
|||||||
ntfs_log_perror("Failed to open directory");
|
ntfs_log_perror("Failed to open directory");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Non-empty directory? */
|
/* Non-empty directory? */
|
||||||
if ((na->data_size != sizeof(INDEX_ROOT) + sizeof(INDEX_ENTRY_HEADER))){
|
if ((na->data_size != sizeof(INDEX_ROOT) + sizeof(INDEX_ENTRY_HEADER))){
|
||||||
/* Both ENOTEMPTY and EEXIST are ok. We use the more common. */
|
/* Both ENOTEMPTY and EEXIST are ok. We use the more common. */
|
||||||
@ -1808,7 +1813,7 @@ int ntfs_check_empty_dir(ntfs_inode *ni)
|
|||||||
ntfs_log_debug("Directory is not empty\n");
|
ntfs_log_debug("Directory is not empty\n");
|
||||||
ret = -1;
|
ret = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ntfs_attr_close(na);
|
ntfs_attr_close(na);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -1817,23 +1822,23 @@ static int ntfs_check_unlinkable_dir(ntfs_inode *ni, FILE_NAME_ATTR *fn)
|
|||||||
{
|
{
|
||||||
int link_count = le16_to_cpu(ni->mrec->link_count);
|
int link_count = le16_to_cpu(ni->mrec->link_count);
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = ntfs_check_empty_dir(ni);
|
ret = ntfs_check_empty_dir(ni);
|
||||||
if (!ret || errno != ENOTEMPTY)
|
if (!ret || errno != ENOTEMPTY)
|
||||||
return ret;
|
return ret;
|
||||||
/*
|
/*
|
||||||
* Directory is non-empty, so we can unlink only if there is more than
|
* Directory is non-empty, so we can unlink only if there is more than
|
||||||
* one "real" hard link, i.e. links aren't different DOS and WIN32 names
|
* one "real" hard link, i.e. links aren't different DOS and WIN32 names
|
||||||
*/
|
*/
|
||||||
if ((link_count == 1) ||
|
if ((link_count == 1) ||
|
||||||
(link_count == 2 && fn->file_name_type == FILE_NAME_DOS)) {
|
(link_count == 2 && fn->file_name_type == FILE_NAME_DOS)) {
|
||||||
errno = ENOTEMPTY;
|
errno = ENOTEMPTY;
|
||||||
ntfs_log_debug("Non-empty directory without hard links\n");
|
ntfs_log_debug("Non-empty directory without hard links\n");
|
||||||
goto no_hardlink;
|
goto no_hardlink;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
no_hardlink:
|
no_hardlink:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1872,7 +1877,7 @@ int ntfs_delete(ntfs_volume *vol, const char *pathname,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
ntfs_log_trace("Entering.\n");
|
ntfs_log_trace("Entering.\n");
|
||||||
|
|
||||||
if (!ni || !dir_ni || !name || !name_len) {
|
if (!ni || !dir_ni || !name || !name_len) {
|
||||||
ntfs_log_error("Invalid arguments.\n");
|
ntfs_log_error("Invalid arguments.\n");
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
@ -1918,12 +1923,12 @@ search:
|
|||||||
else
|
else
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Ignore hard links from other directories */
|
/* Ignore hard links from other directories */
|
||||||
if (dir_ni->mft_no != MREF_LE(fn->parent_directory)) {
|
if (dir_ni->mft_no != MREF_LE(fn->parent_directory)) {
|
||||||
ntfs_log_debug("MFT record numbers don't match "
|
ntfs_log_debug("MFT record numbers don't match "
|
||||||
"(%llu != %llu)\n",
|
"(%llu != %llu)\n",
|
||||||
(long long unsigned)dir_ni->mft_no,
|
(long long unsigned)dir_ni->mft_no,
|
||||||
(long long unsigned)MREF_LE(fn->parent_directory));
|
(long long unsigned)MREF_LE(fn->parent_directory));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -1931,11 +1936,11 @@ search:
|
|||||||
|| ((fn->file_name_type == FILE_NAME_POSIX)
|
|| ((fn->file_name_type == FILE_NAME_POSIX)
|
||||||
&& NVolCaseSensitive(ni->vol)))
|
&& NVolCaseSensitive(ni->vol)))
|
||||||
case_sensitive = CASE_SENSITIVE;
|
case_sensitive = CASE_SENSITIVE;
|
||||||
|
|
||||||
if (ntfs_names_are_equal(fn->file_name, fn->file_name_length,
|
if (ntfs_names_are_equal(fn->file_name, fn->file_name_length,
|
||||||
name, name_len, case_sensitive,
|
name, name_len, case_sensitive,
|
||||||
ni->vol->upcase, ni->vol->upcase_len)){
|
ni->vol->upcase, ni->vol->upcase_len)){
|
||||||
|
|
||||||
if (fn->file_name_type == FILE_NAME_WIN32) {
|
if (fn->file_name_type == FILE_NAME_WIN32) {
|
||||||
looking_for_dos_name = TRUE;
|
looking_for_dos_name = TRUE;
|
||||||
ntfs_attr_reinit_search_ctx(actx);
|
ntfs_attr_reinit_search_ctx(actx);
|
||||||
@ -1958,13 +1963,13 @@ search:
|
|||||||
}
|
}
|
||||||
goto err_out;
|
goto err_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ntfs_check_unlinkable_dir(ni, fn) < 0)
|
if (ntfs_check_unlinkable_dir(ni, fn) < 0)
|
||||||
goto err_out;
|
goto err_out;
|
||||||
|
|
||||||
if (ntfs_index_remove(dir_ni, ni, fn, le32_to_cpu(actx->attr->value_length)))
|
if (ntfs_index_remove(dir_ni, ni, fn, le32_to_cpu(actx->attr->value_length)))
|
||||||
goto err_out;
|
goto err_out;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Keep the last name in place, this is useful for undeletion
|
* Keep the last name in place, this is useful for undeletion
|
||||||
* (Windows also does so), however delete the name if it were
|
* (Windows also does so), however delete the name if it were
|
||||||
@ -1977,10 +1982,10 @@ search:
|
|||||||
if (ntfs_attr_record_rm(actx))
|
if (ntfs_attr_record_rm(actx))
|
||||||
goto err_out;
|
goto err_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
ni->mrec->link_count = cpu_to_le16(le16_to_cpu(
|
ni->mrec->link_count = cpu_to_le16(le16_to_cpu(
|
||||||
ni->mrec->link_count) - 1);
|
ni->mrec->link_count) - 1);
|
||||||
|
|
||||||
ntfs_inode_mark_dirty(ni);
|
ntfs_inode_mark_dirty(ni);
|
||||||
if (looking_for_dos_name) {
|
if (looking_for_dos_name) {
|
||||||
looking_for_dos_name = FALSE;
|
looking_for_dos_name = FALSE;
|
||||||
@ -2106,7 +2111,7 @@ search:
|
|||||||
"Leaving inconsistent metadata.\n");
|
"Leaving inconsistent metadata.\n");
|
||||||
}
|
}
|
||||||
ni = NULL;
|
ni = NULL;
|
||||||
ok:
|
ok:
|
||||||
ntfs_inode_update_times(dir_ni, NTFS_UPDATE_MCTIME);
|
ntfs_inode_update_times(dir_ni, NTFS_UPDATE_MCTIME);
|
||||||
out:
|
out:
|
||||||
if (actx)
|
if (actx)
|
||||||
@ -2149,14 +2154,14 @@ static int ntfs_link_i(ntfs_inode *ni, ntfs_inode *dir_ni, const ntfschar *name,
|
|||||||
int fn_len, err;
|
int fn_len, err;
|
||||||
|
|
||||||
ntfs_log_trace("Entering.\n");
|
ntfs_log_trace("Entering.\n");
|
||||||
|
|
||||||
if (!ni || !dir_ni || !name || !name_len ||
|
if (!ni || !dir_ni || !name || !name_len ||
|
||||||
ni->mft_no == dir_ni->mft_no) {
|
ni->mft_no == dir_ni->mft_no) {
|
||||||
err = EINVAL;
|
err = EINVAL;
|
||||||
ntfs_log_perror("ntfs_link wrong arguments");
|
ntfs_log_perror("ntfs_link wrong arguments");
|
||||||
goto err_out;
|
goto err_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ni->flags & FILE_ATTR_REPARSE_POINT)
|
if ((ni->flags & FILE_ATTR_REPARSE_POINT)
|
||||||
&& !ntfs_possible_symlink(ni)) {
|
&& !ntfs_possible_symlink(ni)) {
|
||||||
err = EOPNOTSUPP;
|
err = EOPNOTSUPP;
|
||||||
@ -2171,7 +2176,7 @@ static int ntfs_link_i(ntfs_inode *ni, ntfs_inode *dir_ni, const ntfschar *name,
|
|||||||
else
|
else
|
||||||
ni->flags &= ~FILE_ATTR_HIDDEN;
|
ni->flags &= ~FILE_ATTR_HIDDEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create FILE_NAME attribute. */
|
/* Create FILE_NAME attribute. */
|
||||||
fn_len = sizeof(FILE_NAME_ATTR) + name_len * sizeof(ntfschar);
|
fn_len = sizeof(FILE_NAME_ATTR) + name_len * sizeof(ntfschar);
|
||||||
fn = ntfs_calloc(fn_len);
|
fn = ntfs_calloc(fn_len);
|
||||||
@ -2559,7 +2564,7 @@ static int set_dos_name(ntfs_inode *ni, ntfs_inode *dir_ni,
|
|||||||
if (set_namespace(ni, dir_ni, longname, longlen,
|
if (set_namespace(ni, dir_ni, longname, longlen,
|
||||||
FILE_NAME_WIN32_AND_DOS) >= 0) {
|
FILE_NAME_WIN32_AND_DOS) >= 0) {
|
||||||
if (!ntfs_delete(vol,
|
if (!ntfs_delete(vol,
|
||||||
(const char*)NULL, ni, dir_ni,
|
(const char*)NULL, ni, dir_ni,
|
||||||
deletename, deletelen))
|
deletename, deletelen))
|
||||||
res = 0;
|
res = 0;
|
||||||
deleted = TRUE;
|
deleted = TRUE;
|
||||||
@ -2580,7 +2585,7 @@ static int set_dos_name(ntfs_inode *ni, ntfs_inode *dir_ni,
|
|||||||
res = -1;
|
res = -1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!ntfs_link_i(ni, dir_ni, shortname, shortlen,
|
if (!ntfs_link_i(ni, dir_ni, shortname, shortlen,
|
||||||
FILE_NAME_DOS)
|
FILE_NAME_DOS)
|
||||||
/* make sure a new link was recorded */
|
/* make sure a new link was recorded */
|
||||||
&& (le16_to_cpu(ni->mrec->link_count) > linkcount)) {
|
&& (le16_to_cpu(ni->mrec->link_count) > linkcount)) {
|
||||||
@ -2756,7 +2761,7 @@ int ntfs_remove_ntfs_dos_name(ntfs_inode *ni, ntfs_inode *dir_ni)
|
|||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
* DOS name has been found, but cannot
|
* DOS name has been found, but cannot
|
||||||
* migrate to Posix : something bad
|
* migrate to Posix : something bad
|
||||||
* has happened
|
* has happened
|
||||||
*/
|
*/
|
||||||
errno = EIO;
|
errno = EIO;
|
||||||
|
@ -54,6 +54,8 @@
|
|||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
typedef double f64;
|
||||||
|
|
||||||
#include "ntfs.h"
|
#include "ntfs.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "logging.h"
|
#include "logging.h"
|
||||||
@ -62,6 +64,7 @@
|
|||||||
#include "cache.h"
|
#include "cache.h"
|
||||||
#include "device.h"
|
#include "device.h"
|
||||||
#include "bootsect.h"
|
#include "bootsect.h"
|
||||||
|
#include "mem_allocate.h"
|
||||||
|
|
||||||
#define DEV_FD(dev) ((gekko_fd *)dev->d_private)
|
#define DEV_FD(dev) ((gekko_fd *)dev->d_private)
|
||||||
|
|
||||||
@ -119,7 +122,7 @@ static int ntfs_device_gekko_io_open(struct ntfs_device *dev, int flags)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!interface->readSectors(fd->startSector, 1, boot)) {
|
if (!interface->readSectors(fd->startSector, 1, boot)) {
|
||||||
ntfs_log_perror("read failure @ sector %d\n", fd->startSector);
|
ntfs_log_perror("read failure @ sector %d\n", (int)fd->startSector);
|
||||||
errno = EIO;
|
errno = EIO;
|
||||||
ntfs_free(boot);
|
ntfs_free(boot);
|
||||||
return -1;
|
return -1;
|
||||||
@ -318,7 +321,7 @@ static s64 ntfs_device_gekko_io_readbytes(struct ntfs_device *dev, s64 offset, s
|
|||||||
// Read from the device
|
// Read from the device
|
||||||
ntfs_log_trace("direct read from sector %d (%d sector(s) long)\n", sec_start, sec_count);
|
ntfs_log_trace("direct read from sector %d (%d sector(s) long)\n", sec_start, sec_count);
|
||||||
if (!ntfs_device_gekko_io_readsectors(dev, sec_start, sec_count, buf)) {
|
if (!ntfs_device_gekko_io_readsectors(dev, sec_start, sec_count, buf)) {
|
||||||
ntfs_log_perror("direct read failure @ sector %d (%d sector(s) long)\n", sec_start, sec_count);
|
ntfs_log_perror("direct read failure @ sector %d (%d sector(s) long)\n", (int)sec_start, (int)sec_count);
|
||||||
errno = EIO;
|
errno = EIO;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -336,10 +339,10 @@ static s64 ntfs_device_gekko_io_readbytes(struct ntfs_device *dev, s64 offset, s
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Read from the device
|
// Read from the device
|
||||||
ntfs_log_trace("buffered read from sector %d (%d sector(s) long)\n", sec_start, sec_count);
|
ntfs_log_trace("buffered read from sector %d (%d sector(s) long)\n", (int)sec_start, (int)sec_count);
|
||||||
ntfs_log_trace("count: %d sec_count:%d fd->sectorSize: %d )\n", (u32)count, (u32)sec_count,(u32)fd->sectorSize);
|
ntfs_log_trace("count: %d sec_count:%d fd->sectorSize: %d )\n", (u32)count, (u32)sec_count,(u32)fd->sectorSize);
|
||||||
if (!ntfs_device_gekko_io_readsectors(dev, sec_start, sec_count, buffer)) {
|
if (!ntfs_device_gekko_io_readsectors(dev, sec_start, sec_count, buffer)) {
|
||||||
ntfs_log_perror("buffered read failure @ sector %d (%d sector(s) long)\n", sec_start, sec_count);
|
ntfs_log_perror("buffered read failure @ sector %d (%d sector(s) long)\n", (int)sec_start, (int)sec_count);
|
||||||
ntfs_free(buffer);
|
ntfs_free(buffer);
|
||||||
errno = EIO;
|
errno = EIO;
|
||||||
return -1;
|
return -1;
|
||||||
@ -406,9 +409,9 @@ static s64 ntfs_device_gekko_io_writebytes(struct ntfs_device *dev, s64 offset,
|
|||||||
if((buffer_offset == 0) && (count % fd->sectorSize == 0))
|
if((buffer_offset == 0) && (count % fd->sectorSize == 0))
|
||||||
{
|
{
|
||||||
// Write to the device
|
// Write to the device
|
||||||
ntfs_log_trace("direct write to sector %d (%d sector(s) long)\n", sec_start, sec_count);
|
ntfs_log_trace("direct write to sector %d (%d sector(s) long)\n", (int)sec_start, (int)sec_count);
|
||||||
if (!ntfs_device_gekko_io_writesectors(dev, sec_start, sec_count, buf)) {
|
if (!ntfs_device_gekko_io_writesectors(dev, sec_start, sec_count, buf)) {
|
||||||
ntfs_log_perror("direct write failure @ sector %d (%d sector(s) long)\n", sec_start, sec_count);
|
ntfs_log_perror("direct write failure @ sector %d (%d sector(s) long)\n", (int)sec_start, (int)sec_count);
|
||||||
errno = EIO;
|
errno = EIO;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -428,7 +431,7 @@ static s64 ntfs_device_gekko_io_writebytes(struct ntfs_device *dev, s64 offset,
|
|||||||
if(buffer_offset != 0)
|
if(buffer_offset != 0)
|
||||||
{
|
{
|
||||||
if (!ntfs_device_gekko_io_readsectors(dev, sec_start, 1, buffer)) {
|
if (!ntfs_device_gekko_io_readsectors(dev, sec_start, 1, buffer)) {
|
||||||
ntfs_log_perror("read failure @ sector %d\n", sec_start);
|
ntfs_log_perror("read failure @ sector %d\n", (int)sec_start);
|
||||||
ntfs_free(buffer);
|
ntfs_free(buffer);
|
||||||
errno = EIO;
|
errno = EIO;
|
||||||
return -1;
|
return -1;
|
||||||
@ -437,7 +440,7 @@ static s64 ntfs_device_gekko_io_writebytes(struct ntfs_device *dev, s64 offset,
|
|||||||
if((buffer_offset+count) % fd->sectorSize != 0)
|
if((buffer_offset+count) % fd->sectorSize != 0)
|
||||||
{
|
{
|
||||||
if (!ntfs_device_gekko_io_readsectors(dev, sec_start + sec_count - 1, 1, buffer + ((sec_count-1) * fd->sectorSize))) {
|
if (!ntfs_device_gekko_io_readsectors(dev, sec_start + sec_count - 1, 1, buffer + ((sec_count-1) * fd->sectorSize))) {
|
||||||
ntfs_log_perror("read failure @ sector %d\n", sec_start + sec_count - 1);
|
ntfs_log_perror("read failure @ sector %d\n", (int)sec_start + (int)sec_count - 1);
|
||||||
ntfs_free(buffer);
|
ntfs_free(buffer);
|
||||||
errno = EIO;
|
errno = EIO;
|
||||||
return -1;
|
return -1;
|
||||||
@ -450,7 +453,7 @@ static s64 ntfs_device_gekko_io_writebytes(struct ntfs_device *dev, s64 offset,
|
|||||||
// Write to the device
|
// Write to the device
|
||||||
ntfs_log_trace("buffered write to sector %d (%d sector(s) long)\n", sec_start, sec_count);
|
ntfs_log_trace("buffered write to sector %d (%d sector(s) long)\n", sec_start, sec_count);
|
||||||
if (!ntfs_device_gekko_io_writesectors(dev, sec_start, sec_count, buffer)) {
|
if (!ntfs_device_gekko_io_writesectors(dev, sec_start, sec_count, buffer)) {
|
||||||
ntfs_log_perror("buffered write failure @ sector %d\n", sec_start);
|
ntfs_log_perror("buffered write failure @ sector %d\n", (int)sec_start);
|
||||||
ntfs_free(buffer);
|
ntfs_free(buffer);
|
||||||
errno = EIO;
|
errno = EIO;
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -59,6 +59,7 @@ typedef struct _gekko_fd {
|
|||||||
u32 cachePageSize; /* The number of sectors per cache page */
|
u32 cachePageSize; /* The number of sectors per cache page */
|
||||||
} gekko_fd;
|
} gekko_fd;
|
||||||
|
|
||||||
|
|
||||||
/* Forward declarations */
|
/* Forward declarations */
|
||||||
struct ntfs_device_operations;
|
struct ntfs_device_operations;
|
||||||
|
|
||||||
|
516
source/index.c
516
source/index.c
File diff suppressed because it is too large
Load Diff
@ -124,7 +124,7 @@ ntfs_inode *ntfs_inode_allocate(ntfs_volume *vol)
|
|||||||
static void __ntfs_inode_release(ntfs_inode *ni)
|
static void __ntfs_inode_release(ntfs_inode *ni)
|
||||||
{
|
{
|
||||||
if (NInoDirty(ni))
|
if (NInoDirty(ni))
|
||||||
ntfs_log_error("Releasing dirty inode %lld!\n",
|
ntfs_log_error("Releasing dirty inode %lld!\n",
|
||||||
(long long)ni->mft_no);
|
(long long)ni->mft_no);
|
||||||
if (NInoAttrList(ni) && ni->attr_list)
|
if (NInoAttrList(ni) && ni->attr_list)
|
||||||
free(ni->attr_list);
|
free(ni->attr_list);
|
||||||
@ -243,7 +243,7 @@ static ntfs_inode *ntfs_inode_real_open(ntfs_volume *vol, const MFT_REF mref)
|
|||||||
if (l != ni->attr_list_size) {
|
if (l != ni->attr_list_size) {
|
||||||
errno = EIO;
|
errno = EIO;
|
||||||
ntfs_log_perror("Unexpected attrlist size (%lld <> %u), inode "
|
ntfs_log_perror("Unexpected attrlist size (%lld <> %u), inode "
|
||||||
"%lld", (long long)l, ni->attr_list_size,
|
"%lld", (long long)l, (unsigned int) ni->attr_list_size,
|
||||||
(long long)MREF(mref));
|
(long long)MREF(mref));
|
||||||
goto put_err_out;
|
goto put_err_out;
|
||||||
}
|
}
|
||||||
@ -273,7 +273,7 @@ get_size:
|
|||||||
set_nino_flag(ni,KnownSize);
|
set_nino_flag(ni,KnownSize);
|
||||||
}
|
}
|
||||||
ntfs_attr_put_search_ctx(ctx);
|
ntfs_attr_put_search_ctx(ctx);
|
||||||
out:
|
out:
|
||||||
ntfs_log_leave("\n");
|
ntfs_log_leave("\n");
|
||||||
return ni;
|
return ni;
|
||||||
|
|
||||||
@ -313,7 +313,7 @@ err_out:
|
|||||||
int ntfs_inode_real_close(ntfs_inode *ni)
|
int ntfs_inode_real_close(ntfs_inode *ni)
|
||||||
{
|
{
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
|
|
||||||
if (!ni)
|
if (!ni)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -378,8 +378,8 @@ int ntfs_inode_real_close(ntfs_inode *ni)
|
|||||||
i = -1;
|
i = -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We could successfully sync, so only log this error
|
* We could successfully sync, so only log this error
|
||||||
* and try to sync other inode extents too.
|
* and try to sync other inode extents too.
|
||||||
*/
|
*/
|
||||||
@ -387,7 +387,7 @@ int ntfs_inode_real_close(ntfs_inode *ni)
|
|||||||
ntfs_log_error("Extent inode %lld was not found\n",
|
ntfs_log_error("Extent inode %lld was not found\n",
|
||||||
(long long)ni->mft_no);
|
(long long)ni->mft_no);
|
||||||
}
|
}
|
||||||
|
|
||||||
__ntfs_inode_release(ni);
|
__ntfs_inode_release(ni);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
err:
|
err:
|
||||||
@ -585,11 +585,11 @@ ntfs_inode *ntfs_extent_inode_open(ntfs_inode *base_ni, const MFT_REF mref)
|
|||||||
ntfs_log_perror("%s", __FUNCTION__);
|
ntfs_log_perror("%s", __FUNCTION__);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ntfs_log_enter("Opening extent inode %lld (base mft record %lld).\n",
|
ntfs_log_enter("Opening extent inode %lld (base mft record %lld).\n",
|
||||||
(unsigned long long)mft_no,
|
(unsigned long long)mft_no,
|
||||||
(unsigned long long)base_ni->mft_no);
|
(unsigned long long)base_ni->mft_no);
|
||||||
|
|
||||||
if (!base_ni->mft_no) {
|
if (!base_ni->mft_no) {
|
||||||
/*
|
/*
|
||||||
* When getting extents of MFT, we must be sure
|
* When getting extents of MFT, we must be sure
|
||||||
@ -833,7 +833,7 @@ static int ntfs_inode_sync_file_name(ntfs_inode *ni, ntfs_inode *dir_ni)
|
|||||||
if (dir_ni)
|
if (dir_ni)
|
||||||
index_ni = dir_ni;
|
index_ni = dir_ni;
|
||||||
else
|
else
|
||||||
index_ni = ntfs_inode_open(ni->vol,
|
index_ni = ntfs_inode_open(ni->vol,
|
||||||
le64_to_cpu(fn->parent_directory));
|
le64_to_cpu(fn->parent_directory));
|
||||||
if (!index_ni) {
|
if (!index_ni) {
|
||||||
if (!err)
|
if (!err)
|
||||||
@ -996,8 +996,8 @@ static int ntfs_inode_sync_in_dir(ntfs_inode *ni, ntfs_inode *dir_ni)
|
|||||||
}
|
}
|
||||||
NInoAttrListSetDirty(ni);
|
NInoAttrListSetDirty(ni);
|
||||||
goto sync_inode;
|
goto sync_inode;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (na->data_size == ni->attr_list_size) {
|
if (na->data_size == ni->attr_list_size) {
|
||||||
if (ntfs_attr_pwrite(na, 0, ni->attr_list_size,
|
if (ntfs_attr_pwrite(na, 0, ni->attr_list_size,
|
||||||
ni->attr_list) != ni->attr_list_size) {
|
ni->attr_list) != ni->attr_list_size) {
|
||||||
@ -1019,7 +1019,7 @@ static int ntfs_inode_sync_in_dir(ntfs_inode *ni, ntfs_inode *dir_ni)
|
|||||||
}
|
}
|
||||||
ntfs_attr_close(na);
|
ntfs_attr_close(na);
|
||||||
}
|
}
|
||||||
|
|
||||||
sync_inode:
|
sync_inode:
|
||||||
/* Write this inode out to the $MFT (and $MFTMirr if applicable). */
|
/* Write this inode out to the $MFT (and $MFTMirr if applicable). */
|
||||||
if (NInoTestAndClearDirty(ni)) {
|
if (NInoTestAndClearDirty(ni)) {
|
||||||
@ -1045,8 +1045,8 @@ sync_inode:
|
|||||||
eni = ni->extent_nis[i];
|
eni = ni->extent_nis[i];
|
||||||
if (!NInoTestAndClearDirty(eni))
|
if (!NInoTestAndClearDirty(eni))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (ntfs_mft_record_write(eni->vol, eni->mft_no,
|
if (ntfs_mft_record_write(eni->vol, eni->mft_no,
|
||||||
eni->mrec)) {
|
eni->mrec)) {
|
||||||
if (!err || errno == EIO) {
|
if (!err || errno == EIO) {
|
||||||
err = errno;
|
err = errno;
|
||||||
@ -1066,7 +1066,7 @@ sync_inode:
|
|||||||
errno = err;
|
errno = err;
|
||||||
ret = -1;
|
ret = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ntfs_log_leave("\n");
|
ntfs_log_leave("\n");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -1135,19 +1135,19 @@ int ntfs_inode_add_attrlist(ntfs_inode *ni)
|
|||||||
}
|
}
|
||||||
/* Walk through all attributes. */
|
/* Walk through all attributes. */
|
||||||
while (!ntfs_attr_lookup(AT_UNUSED, NULL, 0, 0, 0, NULL, 0, ctx)) {
|
while (!ntfs_attr_lookup(AT_UNUSED, NULL, 0, 0, 0, NULL, 0, ctx)) {
|
||||||
|
|
||||||
int ale_size;
|
int ale_size;
|
||||||
|
|
||||||
if (ctx->attr->type == AT_ATTRIBUTE_LIST) {
|
if (ctx->attr->type == AT_ATTRIBUTE_LIST) {
|
||||||
err = EIO;
|
err = EIO;
|
||||||
ntfs_log_perror("Attribute list already present");
|
ntfs_log_perror("Attribute list already present");
|
||||||
goto put_err_out;
|
goto put_err_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
ale_size = (sizeof(ATTR_LIST_ENTRY) + sizeof(ntfschar) *
|
ale_size = (sizeof(ATTR_LIST_ENTRY) + sizeof(ntfschar) *
|
||||||
ctx->attr->name_length + 7) & ~7;
|
ctx->attr->name_length + 7) & ~7;
|
||||||
al_len += ale_size;
|
al_len += ale_size;
|
||||||
|
|
||||||
aln = realloc(al, al_len);
|
aln = realloc(al, al_len);
|
||||||
if (!aln) {
|
if (!aln) {
|
||||||
err = errno;
|
err = errno;
|
||||||
@ -1156,9 +1156,9 @@ int ntfs_inode_add_attrlist(ntfs_inode *ni)
|
|||||||
}
|
}
|
||||||
ale = (ATTR_LIST_ENTRY *)(aln + ((u8 *)ale - al));
|
ale = (ATTR_LIST_ENTRY *)(aln + ((u8 *)ale - al));
|
||||||
al = aln;
|
al = aln;
|
||||||
|
|
||||||
memset(ale, 0, ale_size);
|
memset(ale, 0, ale_size);
|
||||||
|
|
||||||
/* Add attribute to attribute list. */
|
/* Add attribute to attribute list. */
|
||||||
ale->type = ctx->attr->type;
|
ale->type = ctx->attr->type;
|
||||||
ale->length = cpu_to_le16((sizeof(ATTR_LIST_ENTRY) +
|
ale->length = cpu_to_le16((sizeof(ATTR_LIST_ENTRY) +
|
||||||
@ -1225,7 +1225,7 @@ int ntfs_inode_add_attrlist(ntfs_inode *ni)
|
|||||||
ntfs_attr_close(na);
|
ntfs_attr_close(na);
|
||||||
goto remove_attrlist_record;;
|
goto remove_attrlist_record;;
|
||||||
}
|
}
|
||||||
|
|
||||||
ntfs_attr_put_search_ctx(ctx);
|
ntfs_attr_put_search_ctx(ctx);
|
||||||
ntfs_attr_close(na);
|
ntfs_attr_close(na);
|
||||||
return 0;
|
return 0;
|
||||||
@ -1326,12 +1326,12 @@ int ntfs_inode_free_space(ntfs_inode *ni, int size)
|
|||||||
* find next, because we don't need such.
|
* find next, because we don't need such.
|
||||||
*/
|
*/
|
||||||
while (ctx->ntfs_ino->mft_no != ni->mft_no) {
|
while (ctx->ntfs_ino->mft_no != ni->mft_no) {
|
||||||
retry:
|
retry:
|
||||||
if (ntfs_attr_position(AT_UNUSED, ctx))
|
if (ntfs_attr_position(AT_UNUSED, ctx))
|
||||||
goto put_err_out;
|
goto put_err_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ntfs_inode_base(ctx->ntfs_ino)->mft_no == FILE_MFT &&
|
if (ntfs_inode_base(ctx->ntfs_ino)->mft_no == FILE_MFT &&
|
||||||
ctx->attr->type == AT_DATA)
|
ctx->attr->type == AT_DATA)
|
||||||
goto retry;
|
goto retry;
|
||||||
|
|
||||||
@ -1352,10 +1352,10 @@ retry:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* Reposition to first attribute after $STANDARD_INFORMATION
|
* Reposition to first attribute after $STANDARD_INFORMATION
|
||||||
* and $ATTRIBUTE_LIST instead of simply skipping this attribute
|
* and $ATTRIBUTE_LIST instead of simply skipping this attribute
|
||||||
* because in the case when we have got only in-memory attribute
|
* because in the case when we have got only in-memory attribute
|
||||||
* list then ntfs_attr_lookup will fail when it tries to find
|
* list then ntfs_attr_lookup will fail when it tries to find
|
||||||
* $ATTRIBUTE_LIST.
|
* $ATTRIBUTE_LIST.
|
||||||
*/
|
*/
|
||||||
ntfs_attr_reinit_search_ctx(ctx);
|
ntfs_attr_reinit_search_ctx(ctx);
|
||||||
@ -1397,7 +1397,7 @@ void ntfs_inode_update_times(ntfs_inode *ni, ntfs_time_update_flags mask)
|
|||||||
ni->last_data_change_time = now;
|
ni->last_data_change_time = now;
|
||||||
if (mask & NTFS_UPDATE_CTIME)
|
if (mask & NTFS_UPDATE_CTIME)
|
||||||
ni->last_mft_change_time = now;
|
ni->last_mft_change_time = now;
|
||||||
|
|
||||||
NInoFileNameSetDirty(ni);
|
NInoFileNameSetDirty(ni);
|
||||||
NInoSetDirty(ni);
|
NInoSetDirty(ni);
|
||||||
}
|
}
|
||||||
@ -1410,7 +1410,7 @@ void ntfs_inode_update_times(ntfs_inode *ni, ntfs_time_update_flags mask)
|
|||||||
* Check if the mft record given by @mft_no and @attr contains the bad sector
|
* Check if the mft record given by @mft_no and @attr contains the bad sector
|
||||||
* list. Please note that mft record numbers describing $Badclus extent inodes
|
* list. Please note that mft record numbers describing $Badclus extent inodes
|
||||||
* will not match the current $Badclus:$Bad check.
|
* will not match the current $Badclus:$Bad check.
|
||||||
*
|
*
|
||||||
* On success return 1 if the file is $Badclus:$Bad, otherwise return 0.
|
* On success return 1 if the file is $Badclus:$Bad, otherwise return 0.
|
||||||
* On error return -1 with errno set to the error code.
|
* On error return -1 with errno set to the error code.
|
||||||
*/
|
*/
|
||||||
@ -1424,7 +1424,7 @@ int ntfs_inode_badclus_bad(u64 mft_no, ATTR_RECORD *attr)
|
|||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mft_no != FILE_BadClus)
|
if (mft_no != FILE_BadClus)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -1498,7 +1498,7 @@ int ntfs_inode_get_times(ntfs_inode *ni, char *value, size_t size)
|
|||||||
ret = -ERANGE;
|
ret = -ERANGE;
|
||||||
}
|
}
|
||||||
ntfs_attr_put_search_ctx(ctx);
|
ntfs_attr_put_search_ctx(ctx);
|
||||||
}
|
}
|
||||||
return (ret ? ret : -errno);
|
return (ret ? ret : -errno);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
28
source/lock.c
Normal file
28
source/lock.c
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
|
||||||
|
#ifndef USE_LWP_LOCK
|
||||||
|
|
||||||
|
#ifndef mutex_t
|
||||||
|
typedef int mutex_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void __attribute__ ((weak)) _NTFS_lock_init(mutex_t *mutex, int unkwn)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void __attribute__ ((weak)) _NTFS_lock_deinit(mutex_t *mutex)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void __attribute__ ((weak)) _NTFS_lock(mutex_t *mutex)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void __attribute__ ((weak)) _NTFS_unlock(mutex_t *mutex)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // USE_LWP_LOCK
|
71
source/lock.h
Normal file
71
source/lock.h
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
lock.h
|
||||||
|
|
||||||
|
Copyright (c) 2008 Sven Peter <svpe@gmx.net>
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
other materials provided with the distribution.
|
||||||
|
3. The name of the author may not be used to endorse or promote products derived
|
||||||
|
from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
|
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||||
|
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
|
||||||
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||||
|
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _LOCK_H
|
||||||
|
#define _LOCK_H
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef USE_LWP_LOCK
|
||||||
|
|
||||||
|
static inline void _NTFS_lock_init(mutex_t *mutex, int unkwn)
|
||||||
|
{
|
||||||
|
LWP_MutexInit(mutex, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void _NTFS_lock_deinit(mutex_t *mutex)
|
||||||
|
{
|
||||||
|
LWP_MutexDestroy(*mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void _NTFS_lock(mutex_t *mutex)
|
||||||
|
{
|
||||||
|
LWP_MutexLock(*mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void _NTFS_unlock(mutex_t *mutex)
|
||||||
|
{
|
||||||
|
LWP_MutexUnlock(*mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
// We still need a blank lock type
|
||||||
|
#ifndef mutex_t
|
||||||
|
typedef int mutex_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void _NTFS_lock_init(mutex_t *mutex,int unkwn);
|
||||||
|
void _NTFS_lock_deinit(mutex_t *mutex);
|
||||||
|
void _NTFS_lock(mutex_t *mutex);
|
||||||
|
void _NTFS_unlock(mutex_t *mutex);
|
||||||
|
|
||||||
|
#endif // USE_LWP_LOCK
|
||||||
|
|
||||||
|
|
||||||
|
#endif // _LOCK_H
|
||||||
|
|
146
source/mft.c
146
source/mft.c
@ -85,7 +85,7 @@ int ntfs_mft_records_read(const ntfs_volume *vol, const MFT_REF mref,
|
|||||||
VCN m;
|
VCN m;
|
||||||
|
|
||||||
ntfs_log_trace("inode %llu\n", (unsigned long long)MREF(mref));
|
ntfs_log_trace("inode %llu\n", (unsigned long long)MREF(mref));
|
||||||
|
|
||||||
if (!vol || !vol->mft_na || !b || count < 0) {
|
if (!vol || !vol->mft_na || !b || count < 0) {
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
ntfs_log_perror("%s: b=%p count=%lld mft=%llu", __FUNCTION__,
|
ntfs_log_perror("%s: b=%p count=%lld mft=%llu", __FUNCTION__,
|
||||||
@ -209,12 +209,12 @@ int ntfs_mft_records_write(const ntfs_volume *vol, const MFT_REF mref,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ntfs_mft_record_check(const ntfs_volume *vol, const MFT_REF mref,
|
int ntfs_mft_record_check(const ntfs_volume *vol, const MFT_REF mref,
|
||||||
MFT_RECORD *m)
|
MFT_RECORD *m)
|
||||||
{
|
{
|
||||||
ATTR_RECORD *a;
|
ATTR_RECORD *a;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
|
|
||||||
if (!ntfs_is_file_record(m->magic)) {
|
if (!ntfs_is_file_record(m->magic)) {
|
||||||
if (!NVolNoFixupWarn(vol))
|
if (!NVolNoFixupWarn(vol))
|
||||||
ntfs_log_error("Record %llu has no FILE magic (0x%x)\n",
|
ntfs_log_error("Record %llu has no FILE magic (0x%x)\n",
|
||||||
@ -222,22 +222,22 @@ int ntfs_mft_record_check(const ntfs_volume *vol, const MFT_REF mref,
|
|||||||
(int)le32_to_cpu(*(le32*)m));
|
(int)le32_to_cpu(*(le32*)m));
|
||||||
goto err_out;
|
goto err_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (le32_to_cpu(m->bytes_allocated) != vol->mft_record_size) {
|
if (le32_to_cpu(m->bytes_allocated) != vol->mft_record_size) {
|
||||||
ntfs_log_error("Record %llu has corrupt allocation size "
|
ntfs_log_error("Record %llu has corrupt allocation size "
|
||||||
"(%u <> %u)\n", (unsigned long long)MREF(mref),
|
"(%u <> %u)\n", (unsigned long long)MREF(mref),
|
||||||
vol->mft_record_size,
|
(unsigned int) vol->mft_record_size,
|
||||||
le32_to_cpu(m->bytes_allocated));
|
(unsigned int) le32_to_cpu(m->bytes_allocated));
|
||||||
goto err_out;
|
goto err_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
a = (ATTR_RECORD *)((char *)m + le16_to_cpu(m->attrs_offset));
|
a = (ATTR_RECORD *)((char *)m + le16_to_cpu(m->attrs_offset));
|
||||||
if (p2n(a) < p2n(m) || (char *)a > (char *)m + vol->mft_record_size) {
|
if (p2n(a) < p2n(m) || (char *)a > (char *)m + vol->mft_record_size) {
|
||||||
ntfs_log_error("Record %llu is corrupt\n",
|
ntfs_log_error("Record %llu is corrupt\n",
|
||||||
(unsigned long long)MREF(mref));
|
(unsigned long long)MREF(mref));
|
||||||
goto err_out;
|
goto err_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
err_out:
|
err_out:
|
||||||
if (ret)
|
if (ret)
|
||||||
@ -286,7 +286,7 @@ int ntfs_file_record_read(const ntfs_volume *vol, const MFT_REF mref,
|
|||||||
ntfs_log_perror("%s: mrec=%p", __FUNCTION__, mrec);
|
ntfs_log_perror("%s: mrec=%p", __FUNCTION__, mrec);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
m = *mrec;
|
m = *mrec;
|
||||||
if (!m) {
|
if (!m) {
|
||||||
m = ntfs_malloc(vol->mft_record_size);
|
m = ntfs_malloc(vol->mft_record_size);
|
||||||
@ -298,7 +298,7 @@ int ntfs_file_record_read(const ntfs_volume *vol, const MFT_REF mref,
|
|||||||
|
|
||||||
if (ntfs_mft_record_check(vol, mref, m))
|
if (ntfs_mft_record_check(vol, mref, m))
|
||||||
goto err_out;
|
goto err_out;
|
||||||
|
|
||||||
if (MSEQNO(mref) && MSEQNO(mref) != le16_to_cpu(m->sequence_number)) {
|
if (MSEQNO(mref) && MSEQNO(mref) != le16_to_cpu(m->sequence_number)) {
|
||||||
ntfs_log_error("Record %llu has wrong SeqNo (%d <> %d)\n",
|
ntfs_log_error("Record %llu has wrong SeqNo (%d <> %d)\n",
|
||||||
(unsigned long long)MREF(mref), MSEQNO(mref),
|
(unsigned long long)MREF(mref), MSEQNO(mref),
|
||||||
@ -412,21 +412,21 @@ int ntfs_mft_record_format(const ntfs_volume *vol, const MFT_REF mref)
|
|||||||
int ret = -1;
|
int ret = -1;
|
||||||
|
|
||||||
ntfs_log_enter("Entering\n");
|
ntfs_log_enter("Entering\n");
|
||||||
|
|
||||||
m = ntfs_calloc(vol->mft_record_size);
|
m = ntfs_calloc(vol->mft_record_size);
|
||||||
if (!m)
|
if (!m)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (ntfs_mft_record_layout(vol, mref, m))
|
if (ntfs_mft_record_layout(vol, mref, m))
|
||||||
goto free_m;
|
goto free_m;
|
||||||
|
|
||||||
if (ntfs_mft_record_write(vol, mref, m))
|
if (ntfs_mft_record_write(vol, mref, m))
|
||||||
goto free_m;
|
goto free_m;
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
free_m:
|
free_m:
|
||||||
free(m);
|
free(m);
|
||||||
out:
|
out:
|
||||||
ntfs_log_leave("\n");
|
ntfs_log_leave("\n");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -486,7 +486,7 @@ static int ntfs_mft_bitmap_find_free_rec(ntfs_volume *vol, ntfs_inode *base_ni)
|
|||||||
int ret = -1;
|
int ret = -1;
|
||||||
|
|
||||||
ntfs_log_enter("Entering\n");
|
ntfs_log_enter("Entering\n");
|
||||||
|
|
||||||
mftbmp_na = vol->mftbmp_na;
|
mftbmp_na = vol->mftbmp_na;
|
||||||
/*
|
/*
|
||||||
* Set the end of the pass making sure we do not overflow the mft
|
* Set the end of the pass making sure we do not overflow the mft
|
||||||
@ -521,7 +521,7 @@ static int ntfs_mft_bitmap_find_free_rec(ntfs_volume *vol, ntfs_inode *base_ni)
|
|||||||
buf = ntfs_malloc(PAGE_SIZE);
|
buf = ntfs_malloc(PAGE_SIZE);
|
||||||
if (!buf)
|
if (!buf)
|
||||||
goto leave;
|
goto leave;
|
||||||
|
|
||||||
ntfs_log_debug("Starting bitmap search: pass %u, pass_start 0x%llx, "
|
ntfs_log_debug("Starting bitmap search: pass %u, pass_start 0x%llx, "
|
||||||
"pass_end 0x%llx, data_pos 0x%llx.\n", pass,
|
"pass_end 0x%llx, data_pos 0x%llx.\n", pass,
|
||||||
(long long)pass_start, (long long)pass_end,
|
(long long)pass_start, (long long)pass_end,
|
||||||
@ -556,18 +556,18 @@ static int ntfs_mft_bitmap_find_free_rec(ntfs_volume *vol, ntfs_inode *base_ni)
|
|||||||
byte ? *byte : -1, b);
|
byte ? *byte : -1, b);
|
||||||
for (; bit < size && data_pos + bit < pass_end;
|
for (; bit < size && data_pos + bit < pass_end;
|
||||||
bit &= ~7ull, bit += 8) {
|
bit &= ~7ull, bit += 8) {
|
||||||
/*
|
/*
|
||||||
* If we're extending $MFT and running out of the first
|
* If we're extending $MFT and running out of the first
|
||||||
* mft record (base record) then give up searching since
|
* mft record (base record) then give up searching since
|
||||||
* no guarantee that the found record will be accessible.
|
* no guarantee that the found record will be accessible.
|
||||||
*/
|
*/
|
||||||
if (ntfs_is_mft(base_ni) && bit > 400)
|
if (ntfs_is_mft(base_ni) && bit > 400)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
byte = buf + (bit >> 3);
|
byte = buf + (bit >> 3);
|
||||||
if (*byte == 0xff)
|
if (*byte == 0xff)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Note: ffz() result must be zero based. */
|
/* Note: ffz() result must be zero based. */
|
||||||
b = ntfs_ffz((unsigned long)*byte);
|
b = ntfs_ffz((unsigned long)*byte);
|
||||||
if (b < 8 && b >= (bit & 7)) {
|
if (b < 8 && b >= (bit & 7)) {
|
||||||
@ -606,7 +606,7 @@ static int ntfs_mft_bitmap_find_free_rec(ntfs_volume *vol, ntfs_inode *base_ni)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* No free mft records in currently initialized mft bitmap. */
|
/* No free mft records in currently initialized mft bitmap. */
|
||||||
out:
|
out:
|
||||||
free(buf);
|
free(buf);
|
||||||
errno = ENOSPC;
|
errno = ENOSPC;
|
||||||
leave:
|
leave:
|
||||||
@ -633,9 +633,9 @@ static int ntfs_mft_attr_extend(ntfs_attr *na)
|
|||||||
ntfs_log_perror("%s: MP update failed", __FUNCTION__);
|
ntfs_log_perror("%s: MP update failed", __FUNCTION__);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = STATUS_OK;
|
ret = STATUS_OK;
|
||||||
out:
|
out:
|
||||||
ntfs_log_leave("\n");
|
ntfs_log_leave("\n");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -673,7 +673,7 @@ static int ntfs_mft_bitmap_extend_allocation_i(ntfs_volume *vol)
|
|||||||
return STATUS_ERROR;
|
return STATUS_ERROR;
|
||||||
}
|
}
|
||||||
lcn = rl->lcn + rl->length;
|
lcn = rl->lcn + rl->length;
|
||||||
|
|
||||||
rl2 = ntfs_cluster_alloc(vol, rl[1].vcn, 1, lcn, DATA_ZONE);
|
rl2 = ntfs_cluster_alloc(vol, rl[1].vcn, 1, lcn, DATA_ZONE);
|
||||||
if (!rl2) {
|
if (!rl2) {
|
||||||
ntfs_log_error("Failed to allocate a cluster for "
|
ntfs_log_error("Failed to allocate a cluster for "
|
||||||
@ -809,7 +809,7 @@ undo_alloc:
|
|||||||
lcn = rl->lcn;
|
lcn = rl->lcn;
|
||||||
rl->lcn = rl[1].lcn;
|
rl->lcn = rl[1].lcn;
|
||||||
rl->length = 0;
|
rl->length = 0;
|
||||||
|
|
||||||
/* FIXME: use an ntfs_cluster_free_* function */
|
/* FIXME: use an ntfs_cluster_free_* function */
|
||||||
if (ntfs_bitmap_clear_bit(vol->lcnbmp_na, lcn))
|
if (ntfs_bitmap_clear_bit(vol->lcnbmp_na, lcn))
|
||||||
ntfs_log_error("Failed to free cluster.%s\n", es);
|
ntfs_log_error("Failed to free cluster.%s\n", es);
|
||||||
@ -851,7 +851,7 @@ undo_alloc:
|
|||||||
static int ntfs_mft_bitmap_extend_allocation(ntfs_volume *vol)
|
static int ntfs_mft_bitmap_extend_allocation(ntfs_volume *vol)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ntfs_log_enter("Entering\n");
|
ntfs_log_enter("Entering\n");
|
||||||
ret = ntfs_mft_bitmap_extend_allocation_i(vol);
|
ret = ntfs_mft_bitmap_extend_allocation_i(vol);
|
||||||
ntfs_log_leave("\n");
|
ntfs_log_leave("\n");
|
||||||
@ -879,7 +879,7 @@ static int ntfs_mft_bitmap_extend_initialized(ntfs_volume *vol)
|
|||||||
int ret = -1;
|
int ret = -1;
|
||||||
|
|
||||||
ntfs_log_enter("Entering\n");
|
ntfs_log_enter("Entering\n");
|
||||||
|
|
||||||
mftbmp_na = vol->mftbmp_na;
|
mftbmp_na = vol->mftbmp_na;
|
||||||
ctx = ntfs_attr_get_search_ctx(mftbmp_na->ni, NULL);
|
ctx = ntfs_attr_get_search_ctx(mftbmp_na->ni, NULL);
|
||||||
if (!ctx)
|
if (!ctx)
|
||||||
@ -909,7 +909,7 @@ static int ntfs_mft_bitmap_extend_initialized(ntfs_volume *vol)
|
|||||||
ll = ntfs_attr_pwrite(mftbmp_na, old_initialized_size, 8, &ll);
|
ll = ntfs_attr_pwrite(mftbmp_na, old_initialized_size, 8, &ll);
|
||||||
if (ll == 8) {
|
if (ll == 8) {
|
||||||
ntfs_log_debug("Wrote eight initialized bytes to mft bitmap.\n");
|
ntfs_log_debug("Wrote eight initialized bytes to mft bitmap.\n");
|
||||||
vol->free_mft_records += (8 * 8);
|
vol->free_mft_records += (8 * 8);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@ -981,7 +981,7 @@ static int ntfs_mft_data_extend_allocation(ntfs_volume *vol)
|
|||||||
BOOL update_mp = FALSE;
|
BOOL update_mp = FALSE;
|
||||||
|
|
||||||
ntfs_log_enter("Extending mft data allocation.\n");
|
ntfs_log_enter("Extending mft data allocation.\n");
|
||||||
|
|
||||||
mft_na = vol->mft_na;
|
mft_na = vol->mft_na;
|
||||||
/*
|
/*
|
||||||
* Determine the preferred allocation location, i.e. the last lcn of
|
* Determine the preferred allocation location, i.e. the last lcn of
|
||||||
@ -990,7 +990,7 @@ static int ntfs_mft_data_extend_allocation(ntfs_volume *vol)
|
|||||||
*/
|
*/
|
||||||
rl = ntfs_attr_find_vcn(mft_na,
|
rl = ntfs_attr_find_vcn(mft_na,
|
||||||
(mft_na->allocated_size - 1) >> vol->cluster_size_bits);
|
(mft_na->allocated_size - 1) >> vol->cluster_size_bits);
|
||||||
|
|
||||||
if (!rl || !rl->length || rl->lcn < 0) {
|
if (!rl || !rl->length || rl->lcn < 0) {
|
||||||
ntfs_log_error("Failed to determine last allocated "
|
ntfs_log_error("Failed to determine last allocated "
|
||||||
"cluster of mft data attribute.\n");
|
"cluster of mft data attribute.\n");
|
||||||
@ -998,7 +998,7 @@ static int ntfs_mft_data_extend_allocation(ntfs_volume *vol)
|
|||||||
errno = EIO;
|
errno = EIO;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
lcn = rl->lcn + rl->length;
|
lcn = rl->lcn + rl->length;
|
||||||
ntfs_log_debug("Last lcn of mft data attribute is 0x%llx.\n", (long long)lcn);
|
ntfs_log_debug("Last lcn of mft data attribute is 0x%llx.\n", (long long)lcn);
|
||||||
/* Minimum allocation is one mft record worth of clusters. */
|
/* Minimum allocation is one mft record worth of clusters. */
|
||||||
@ -1009,7 +1009,7 @@ static int ntfs_mft_data_extend_allocation(ntfs_volume *vol)
|
|||||||
nr = vol->mft_record_size << 4 >> vol->cluster_size_bits;
|
nr = vol->mft_record_size << 4 >> vol->cluster_size_bits;
|
||||||
if (!nr)
|
if (!nr)
|
||||||
nr = min_nr;
|
nr = min_nr;
|
||||||
|
|
||||||
old_last_vcn = rl[1].vcn;
|
old_last_vcn = rl[1].vcn;
|
||||||
do {
|
do {
|
||||||
rl2 = ntfs_cluster_alloc(vol, old_last_vcn, nr, lcn, MFT_ZONE);
|
rl2 = ntfs_cluster_alloc(vol, old_last_vcn, nr, lcn, MFT_ZONE);
|
||||||
@ -1029,9 +1029,9 @@ static int ntfs_mft_data_extend_allocation(ntfs_volume *vol)
|
|||||||
ntfs_log_debug("Retrying mft data allocation with minimal cluster "
|
ntfs_log_debug("Retrying mft data allocation with minimal cluster "
|
||||||
"count %lli.\n", (long long)nr);
|
"count %lli.\n", (long long)nr);
|
||||||
} while (1);
|
} while (1);
|
||||||
|
|
||||||
ntfs_log_debug("Allocated %lld clusters.\n", (long long)nr);
|
ntfs_log_debug("Allocated %lld clusters.\n", (long long)nr);
|
||||||
|
|
||||||
rl = ntfs_runlists_merge(mft_na->rl, rl2);
|
rl = ntfs_runlists_merge(mft_na->rl, rl2);
|
||||||
if (!rl) {
|
if (!rl) {
|
||||||
err = errno;
|
err = errno;
|
||||||
@ -1045,7 +1045,7 @@ static int ntfs_mft_data_extend_allocation(ntfs_volume *vol)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
mft_na->rl = rl;
|
mft_na->rl = rl;
|
||||||
|
|
||||||
/* Find the last run in the new runlist. */
|
/* Find the last run in the new runlist. */
|
||||||
for (; rl[1].length; rl++)
|
for (; rl[1].length; rl++)
|
||||||
;
|
;
|
||||||
@ -1195,13 +1195,13 @@ static int ntfs_mft_record_init(ntfs_volume *vol, s64 size)
|
|||||||
ntfs_attr *mft_na;
|
ntfs_attr *mft_na;
|
||||||
s64 old_data_initialized, old_data_size;
|
s64 old_data_initialized, old_data_size;
|
||||||
ntfs_attr_search_ctx *ctx;
|
ntfs_attr_search_ctx *ctx;
|
||||||
|
|
||||||
ntfs_log_enter("Entering\n");
|
ntfs_log_enter("Entering\n");
|
||||||
|
|
||||||
/* NOTE: Caller must sanity check vol, vol->mft_na and vol->mftbmp_na */
|
/* NOTE: Caller must sanity check vol, vol->mft_na and vol->mftbmp_na */
|
||||||
|
|
||||||
mft_na = vol->mft_na;
|
mft_na = vol->mft_na;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The mft record is outside the initialized data. Extend the mft data
|
* The mft record is outside the initialized data. Extend the mft data
|
||||||
* attribute until it covers the allocated record. The loop is only
|
* attribute until it covers the allocated record. The loop is only
|
||||||
@ -1224,10 +1224,10 @@ static int ntfs_mft_record_init(ntfs_volume *vol, s64 size)
|
|||||||
(long long)mft_na->data_size,
|
(long long)mft_na->data_size,
|
||||||
(long long)mft_na->initialized_size);
|
(long long)mft_na->initialized_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
old_data_initialized = mft_na->initialized_size;
|
old_data_initialized = mft_na->initialized_size;
|
||||||
old_data_size = mft_na->data_size;
|
old_data_size = mft_na->data_size;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Extend mft data initialized size (and data size of course) to reach
|
* Extend mft data initialized size (and data size of course) to reach
|
||||||
* the allocated mft record, formatting the mft records along the way.
|
* the allocated mft record, formatting the mft records along the way.
|
||||||
@ -1246,7 +1246,7 @@ static int ntfs_mft_record_init(ntfs_volume *vol, s64 size)
|
|||||||
goto undo_data_init;
|
goto undo_data_init;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update the mft data attribute record to reflect the new sizes. */
|
/* Update the mft data attribute record to reflect the new sizes. */
|
||||||
ctx = ntfs_attr_get_search_ctx(mft_na->ni, NULL);
|
ctx = ntfs_attr_get_search_ctx(mft_na->ni, NULL);
|
||||||
if (!ctx)
|
if (!ctx)
|
||||||
@ -1262,7 +1262,7 @@ static int ntfs_mft_record_init(ntfs_volume *vol, s64 size)
|
|||||||
ctx->attr->initialized_size = cpu_to_sle64(mft_na->initialized_size);
|
ctx->attr->initialized_size = cpu_to_sle64(mft_na->initialized_size);
|
||||||
ctx->attr->data_size = cpu_to_sle64(mft_na->data_size);
|
ctx->attr->data_size = cpu_to_sle64(mft_na->data_size);
|
||||||
ctx->attr->allocated_size = cpu_to_sle64(mft_na->allocated_size);
|
ctx->attr->allocated_size = cpu_to_sle64(mft_na->allocated_size);
|
||||||
|
|
||||||
/* Ensure the changes make it to disk. */
|
/* Ensure the changes make it to disk. */
|
||||||
ntfs_inode_mark_dirty(ctx->ntfs_ino);
|
ntfs_inode_mark_dirty(ctx->ntfs_ino);
|
||||||
ntfs_attr_put_search_ctx(ctx);
|
ntfs_attr_put_search_ctx(ctx);
|
||||||
@ -1272,21 +1272,21 @@ static int ntfs_mft_record_init(ntfs_volume *vol, s64 size)
|
|||||||
(long long)mft_na->allocated_size,
|
(long long)mft_na->allocated_size,
|
||||||
(long long)mft_na->data_size,
|
(long long)mft_na->data_size,
|
||||||
(long long)mft_na->initialized_size);
|
(long long)mft_na->initialized_size);
|
||||||
|
|
||||||
/* Sanity checks. */
|
/* Sanity checks. */
|
||||||
if (mft_na->data_size > mft_na->allocated_size ||
|
if (mft_na->data_size > mft_na->allocated_size ||
|
||||||
mft_na->initialized_size > mft_na->data_size)
|
mft_na->initialized_size > mft_na->data_size)
|
||||||
NTFS_BUG("mft_na sanity checks failed");
|
NTFS_BUG("mft_na sanity checks failed");
|
||||||
|
|
||||||
/* Sync MFT to minimize data loss if there won't be clean unmount. */
|
/* Sync MFT to minimize data loss if there won't be clean unmount. */
|
||||||
if (ntfs_inode_sync(mft_na->ni))
|
if (ntfs_inode_sync(mft_na->ni))
|
||||||
goto undo_data_init;
|
goto undo_data_init;
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
out:
|
out:
|
||||||
ntfs_log_leave("\n");
|
ntfs_log_leave("\n");
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
undo_data_init:
|
undo_data_init:
|
||||||
mft_na->initialized_size = old_data_initialized;
|
mft_na->initialized_size = old_data_initialized;
|
||||||
mft_na->data_size = old_data_size;
|
mft_na->data_size = old_data_size;
|
||||||
@ -1299,11 +1299,11 @@ static int ntfs_mft_rec_init(ntfs_volume *vol, s64 size)
|
|||||||
ntfs_attr *mft_na;
|
ntfs_attr *mft_na;
|
||||||
s64 old_data_initialized, old_data_size;
|
s64 old_data_initialized, old_data_size;
|
||||||
ntfs_attr_search_ctx *ctx;
|
ntfs_attr_search_ctx *ctx;
|
||||||
|
|
||||||
ntfs_log_enter("Entering\n");
|
ntfs_log_enter("Entering\n");
|
||||||
|
|
||||||
mft_na = vol->mft_na;
|
mft_na = vol->mft_na;
|
||||||
|
|
||||||
if (size > mft_na->allocated_size || size > mft_na->initialized_size) {
|
if (size > mft_na->allocated_size || size > mft_na->initialized_size) {
|
||||||
errno = EIO;
|
errno = EIO;
|
||||||
ntfs_log_perror("%s: unexpected $MFT sizes, see below", __FUNCTION__);
|
ntfs_log_perror("%s: unexpected $MFT sizes, see below", __FUNCTION__);
|
||||||
@ -1315,10 +1315,10 @@ static int ntfs_mft_rec_init(ntfs_volume *vol, s64 size)
|
|||||||
(long long)mft_na->initialized_size);
|
(long long)mft_na->initialized_size);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
old_data_initialized = mft_na->initialized_size;
|
old_data_initialized = mft_na->initialized_size;
|
||||||
old_data_size = mft_na->data_size;
|
old_data_size = mft_na->data_size;
|
||||||
|
|
||||||
/* Update the mft data attribute record to reflect the new sizes. */
|
/* Update the mft data attribute record to reflect the new sizes. */
|
||||||
ctx = ntfs_attr_get_search_ctx(mft_na->ni, NULL);
|
ctx = ntfs_attr_get_search_ctx(mft_na->ni, NULL);
|
||||||
if (!ctx)
|
if (!ctx)
|
||||||
@ -1335,19 +1335,19 @@ static int ntfs_mft_rec_init(ntfs_volume *vol, s64 size)
|
|||||||
ctx->attr->data_size = cpu_to_sle64(mft_na->data_size);
|
ctx->attr->data_size = cpu_to_sle64(mft_na->data_size);
|
||||||
|
|
||||||
/* CHECKME: ctx->attr->allocation_size is already ok? */
|
/* CHECKME: ctx->attr->allocation_size is already ok? */
|
||||||
|
|
||||||
/* Ensure the changes make it to disk. */
|
/* Ensure the changes make it to disk. */
|
||||||
ntfs_inode_mark_dirty(ctx->ntfs_ino);
|
ntfs_inode_mark_dirty(ctx->ntfs_ino);
|
||||||
ntfs_attr_put_search_ctx(ctx);
|
ntfs_attr_put_search_ctx(ctx);
|
||||||
|
|
||||||
/* Sanity checks. */
|
/* Sanity checks. */
|
||||||
if (mft_na->data_size > mft_na->allocated_size ||
|
if (mft_na->data_size > mft_na->allocated_size ||
|
||||||
mft_na->initialized_size > mft_na->data_size)
|
mft_na->initialized_size > mft_na->data_size)
|
||||||
NTFS_BUG("mft_na sanity checks failed");
|
NTFS_BUG("mft_na sanity checks failed");
|
||||||
out:
|
out:
|
||||||
ntfs_log_leave("\n");
|
ntfs_log_leave("\n");
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
undo_data_init:
|
undo_data_init:
|
||||||
mft_na->initialized_size = old_data_initialized;
|
mft_na->initialized_size = old_data_initialized;
|
||||||
mft_na->data_size = old_data_size;
|
mft_na->data_size = old_data_size;
|
||||||
@ -1377,7 +1377,7 @@ static ntfs_inode *ntfs_mft_rec_alloc(ntfs_volume *vol)
|
|||||||
|
|
||||||
if (errno != ENOSPC)
|
if (errno != ENOSPC)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
errno = ENOSPC;
|
errno = ENOSPC;
|
||||||
/* strerror() is intentionally used below, we want to log this error. */
|
/* strerror() is intentionally used below, we want to log this error. */
|
||||||
ntfs_log_error("No free mft record for $MFT: %s\n", strerror(errno));
|
ntfs_log_error("No free mft record for $MFT: %s\n", strerror(errno));
|
||||||
@ -1388,7 +1388,7 @@ found_free_rec:
|
|||||||
ntfs_log_error("Failed to allocate bit in mft bitmap #2\n");
|
ntfs_log_error("Failed to allocate bit in mft bitmap #2\n");
|
||||||
goto err_out;
|
goto err_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
ll = (bit + 1) << vol->mft_record_size_bits;
|
ll = (bit + 1) << vol->mft_record_size_bits;
|
||||||
if (ll > mft_na->initialized_size)
|
if (ll > mft_na->initialized_size)
|
||||||
if (ntfs_mft_rec_init(vol, ll) < 0)
|
if (ntfs_mft_rec_init(vol, ll) < 0)
|
||||||
@ -1402,7 +1402,7 @@ found_free_rec:
|
|||||||
m = ntfs_malloc(vol->mft_record_size);
|
m = ntfs_malloc(vol->mft_record_size);
|
||||||
if (!m)
|
if (!m)
|
||||||
goto undo_mftbmp_alloc;
|
goto undo_mftbmp_alloc;
|
||||||
|
|
||||||
if (ntfs_mft_record_read(vol, bit, m)) {
|
if (ntfs_mft_record_read(vol, bit, m)) {
|
||||||
free(m);
|
free(m);
|
||||||
goto undo_mftbmp_alloc;
|
goto undo_mftbmp_alloc;
|
||||||
@ -1470,7 +1470,7 @@ found_free_rec:
|
|||||||
base_ni->extent_nis = extent_nis;
|
base_ni->extent_nis = extent_nis;
|
||||||
}
|
}
|
||||||
base_ni->extent_nis[base_ni->nr_extents++] = ni;
|
base_ni->extent_nis[base_ni->nr_extents++] = ni;
|
||||||
|
|
||||||
/* Make sure the allocated inode is written out to disk later. */
|
/* Make sure the allocated inode is written out to disk later. */
|
||||||
ntfs_inode_mark_dirty(ni);
|
ntfs_inode_mark_dirty(ni);
|
||||||
/* Initialize time, allocated and data size in ntfs_inode struct. */
|
/* Initialize time, allocated and data size in ntfs_inode struct. */
|
||||||
@ -1486,7 +1486,7 @@ found_free_rec:
|
|||||||
ntfs_log_error("allocated %sinode %lld\n",
|
ntfs_log_error("allocated %sinode %lld\n",
|
||||||
base_ni ? "extent " : "", (long long)bit);
|
base_ni ? "extent " : "", (long long)bit);
|
||||||
out:
|
out:
|
||||||
ntfs_log_leave("\n");
|
ntfs_log_leave("\n");
|
||||||
return ni;
|
return ni;
|
||||||
|
|
||||||
undo_mftbmp_alloc:
|
undo_mftbmp_alloc:
|
||||||
@ -1498,7 +1498,7 @@ err_out:
|
|||||||
if (!errno)
|
if (!errno)
|
||||||
errno = EIO;
|
errno = EIO;
|
||||||
ni = NULL;
|
ni = NULL;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1595,7 +1595,7 @@ ntfs_inode *ntfs_mft_record_alloc(ntfs_volume *vol, ntfs_inode *base_ni)
|
|||||||
|
|
||||||
if (base_ni)
|
if (base_ni)
|
||||||
ntfs_log_enter("Entering (allocating an extent mft record for "
|
ntfs_log_enter("Entering (allocating an extent mft record for "
|
||||||
"base mft record %lld).\n",
|
"base mft record %lld).\n",
|
||||||
(long long)base_ni->mft_no);
|
(long long)base_ni->mft_no);
|
||||||
else
|
else
|
||||||
ntfs_log_enter("Entering (allocating a base mft record)\n");
|
ntfs_log_enter("Entering (allocating a base mft record)\n");
|
||||||
@ -1603,7 +1603,7 @@ ntfs_inode *ntfs_mft_record_alloc(ntfs_volume *vol, ntfs_inode *base_ni)
|
|||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ntfs_is_mft(base_ni)) {
|
if (ntfs_is_mft(base_ni)) {
|
||||||
ni = ntfs_mft_rec_alloc(vol);
|
ni = ntfs_mft_rec_alloc(vol);
|
||||||
goto out;
|
goto out;
|
||||||
@ -1611,7 +1611,7 @@ ntfs_inode *ntfs_mft_record_alloc(ntfs_volume *vol, ntfs_inode *base_ni)
|
|||||||
|
|
||||||
mft_na = vol->mft_na;
|
mft_na = vol->mft_na;
|
||||||
mftbmp_na = vol->mftbmp_na;
|
mftbmp_na = vol->mftbmp_na;
|
||||||
retry:
|
retry:
|
||||||
bit = ntfs_mft_bitmap_find_free_rec(vol, base_ni);
|
bit = ntfs_mft_bitmap_find_free_rec(vol, base_ni);
|
||||||
if (bit >= 0) {
|
if (bit >= 0) {
|
||||||
ntfs_log_debug("found free record (#1) at %lld\n",
|
ntfs_log_debug("found free record (#1) at %lld\n",
|
||||||
@ -1688,7 +1688,7 @@ found_free_rec:
|
|||||||
ntfs_log_error("Failed to allocate bit in mft bitmap.\n");
|
ntfs_log_error("Failed to allocate bit in mft bitmap.\n");
|
||||||
goto err_out;
|
goto err_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The mft bitmap is now uptodate. Deal with mft data attribute now. */
|
/* The mft bitmap is now uptodate. Deal with mft data attribute now. */
|
||||||
ll = (bit + 1) << vol->mft_record_size_bits;
|
ll = (bit + 1) << vol->mft_record_size_bits;
|
||||||
if (ll > mft_na->initialized_size)
|
if (ll > mft_na->initialized_size)
|
||||||
@ -1704,7 +1704,7 @@ found_free_rec:
|
|||||||
m = ntfs_malloc(vol->mft_record_size);
|
m = ntfs_malloc(vol->mft_record_size);
|
||||||
if (!m)
|
if (!m)
|
||||||
goto undo_mftbmp_alloc;
|
goto undo_mftbmp_alloc;
|
||||||
|
|
||||||
if (ntfs_mft_record_read(vol, bit, m)) {
|
if (ntfs_mft_record_read(vol, bit, m)) {
|
||||||
free(m);
|
free(m);
|
||||||
goto undo_mftbmp_alloc;
|
goto undo_mftbmp_alloc;
|
||||||
@ -1787,9 +1787,9 @@ found_free_rec:
|
|||||||
/* Return the opened, allocated inode of the allocated mft record. */
|
/* Return the opened, allocated inode of the allocated mft record. */
|
||||||
ntfs_log_debug("allocated %sinode 0x%llx.\n",
|
ntfs_log_debug("allocated %sinode 0x%llx.\n",
|
||||||
base_ni ? "extent " : "", (long long)bit);
|
base_ni ? "extent " : "", (long long)bit);
|
||||||
vol->free_mft_records--;
|
vol->free_mft_records--;
|
||||||
out:
|
out:
|
||||||
ntfs_log_leave("\n");
|
ntfs_log_leave("\n");
|
||||||
return ni;
|
return ni;
|
||||||
|
|
||||||
undo_mftbmp_alloc:
|
undo_mftbmp_alloc:
|
||||||
@ -1801,7 +1801,7 @@ err_out:
|
|||||||
if (!errno)
|
if (!errno)
|
||||||
errno = EIO;
|
errno = EIO;
|
||||||
ni = NULL;
|
ni = NULL;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1865,7 +1865,7 @@ int ntfs_mft_record_free(ntfs_volume *vol, ntfs_inode *ni)
|
|||||||
#else
|
#else
|
||||||
if (!ntfs_inode_close(ni)) {
|
if (!ntfs_inode_close(ni)) {
|
||||||
#endif
|
#endif
|
||||||
vol->free_mft_records++;
|
vol->free_mft_records++;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
err = errno;
|
err = errno;
|
||||||
|
@ -101,7 +101,7 @@ int ntfs_mst_post_read_fixup_warn(NTFS_RECORD *b, const u32 size,
|
|||||||
errno = EIO;
|
errno = EIO;
|
||||||
ntfs_log_perror("Incomplete multi-sector transfer: "
|
ntfs_log_perror("Incomplete multi-sector transfer: "
|
||||||
"magic: 0x%08x size: %d usa_ofs: %d usa_count:"
|
"magic: 0x%08x size: %d usa_ofs: %d usa_count:"
|
||||||
" %d data: %d usn: %d", *(le32 *)b, size,
|
" %d data: %d usn: %d", (unsigned int)*(le32 *)b, (int)size,
|
||||||
usa_ofs, usa_count, *data_pos, usn);
|
usa_ofs, usa_count, *data_pos, usn);
|
||||||
b->magic = magic_BAAD;
|
b->magic = magic_BAAD;
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -37,9 +37,12 @@
|
|||||||
#include "ntfsinternal.h"
|
#include "ntfsinternal.h"
|
||||||
#include "ntfsfile.h"
|
#include "ntfsfile.h"
|
||||||
#include "ntfsdir.h"
|
#include "ntfsdir.h"
|
||||||
|
|
||||||
#include "gekko_io.h"
|
#include "gekko_io.h"
|
||||||
|
|
||||||
#include "cache.h"
|
#include "cache.h"
|
||||||
|
|
||||||
|
|
||||||
// NTFS device driver devoptab
|
// NTFS device driver devoptab
|
||||||
static const devoptab_t devops_ntfs = {
|
static const devoptab_t devops_ntfs = {
|
||||||
NULL, /* Device name */
|
NULL, /* Device name */
|
||||||
@ -197,7 +200,7 @@ int ntfsFindPartitions (const DISC_INTERFACE *interface, sec_t **partitions)
|
|||||||
if (sector.boot.oem_id == NTFS_OEM_ID) {
|
if (sector.boot.oem_id == NTFS_OEM_ID) {
|
||||||
ntfs_log_debug("Logical Partition @ %d: Valid NTFS boot sector found\n", part_lba);
|
ntfs_log_debug("Logical Partition @ %d: Valid NTFS boot sector found\n", part_lba);
|
||||||
if(sector.ebr.partition.type != PARTITION_TYPE_NTFS) {
|
if(sector.ebr.partition.type != PARTITION_TYPE_NTFS) {
|
||||||
ntfs_log_warning("Logical Partition @ %d: Is NTFS but type is 0x%x; 0x%x was expected\n", part_lba, sector.ebr.partition.type, PARTITION_TYPE_NTFS);
|
ntfs_log_warning("Logical Partition @ %d: Is NTFS but type is 0x%x; 0x%x was expected\n", (int) part_lba, sector.ebr.partition.type, PARTITION_TYPE_NTFS);
|
||||||
}
|
}
|
||||||
if (partition_count < NTFS_MAX_PARTITIONS) {
|
if (partition_count < NTFS_MAX_PARTITIONS) {
|
||||||
partition_starts[partition_count] = part_lba;
|
partition_starts[partition_count] = part_lba;
|
||||||
|
@ -220,7 +220,7 @@ int ntfs_open_r (struct _reent *r, void *fileStruct, const char *path, int flags
|
|||||||
return (int)fileStruct;
|
return (int)fileStruct;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ntfs_close_r (struct _reent *r, int fd)
|
int ntfs_close_r (struct _reent *r, void * fd)
|
||||||
{
|
{
|
||||||
ntfs_log_trace("fd %p\n", (void *) fd);
|
ntfs_log_trace("fd %p\n", (void *) fd);
|
||||||
|
|
||||||
@ -253,7 +253,7 @@ int ntfs_close_r (struct _reent *r, int fd)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t ntfs_write_r (struct _reent *r, int fd, const char *ptr, size_t len)
|
ssize_t ntfs_write_r (struct _reent *r, void * fd, const char *ptr, size_t len)
|
||||||
{
|
{
|
||||||
ntfs_log_trace("fd %p, ptr %p, len %u\n", (void *) fd, ptr, len);
|
ntfs_log_trace("fd %p, ptr %p, len %u\n", (void *) fd, ptr, len);
|
||||||
|
|
||||||
@ -319,7 +319,7 @@ ssize_t ntfs_write_r (struct _reent *r, int fd, const char *ptr, size_t len)
|
|||||||
return written;
|
return written;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t ntfs_read_r (struct _reent *r, int fd, char *ptr, size_t len)
|
ssize_t ntfs_read_r (struct _reent *r, void * fd, char *ptr, size_t len)
|
||||||
{
|
{
|
||||||
ntfs_log_trace("fd %p, ptr %p, len %u\n", (void *) fd, ptr, len);
|
ntfs_log_trace("fd %p, ptr %p, len %u\n", (void *) fd, ptr, len);
|
||||||
|
|
||||||
@ -378,7 +378,7 @@ ssize_t ntfs_read_r (struct _reent *r, int fd, char *ptr, size_t len)
|
|||||||
return read;
|
return read;
|
||||||
}
|
}
|
||||||
|
|
||||||
off_t ntfs_seek_r (struct _reent *r, int fd, off_t pos, int dir)
|
off_t ntfs_seek_r (struct _reent *r, void * fd, off_t pos, int dir)
|
||||||
{
|
{
|
||||||
ntfs_log_trace("fd %p, pos %llu, dir %i\n", (void *) fd, pos, dir);
|
ntfs_log_trace("fd %p, pos %llu, dir %i\n", (void *) fd, pos, dir);
|
||||||
|
|
||||||
@ -406,7 +406,7 @@ off_t ntfs_seek_r (struct _reent *r, int fd, off_t pos, int dir)
|
|||||||
|
|
||||||
return position;
|
return position;
|
||||||
}
|
}
|
||||||
int ntfs_fstat_r (struct _reent *r, int fd, struct stat *st)
|
int ntfs_fstat_r (struct _reent *r, void * fd, struct stat *st)
|
||||||
{
|
{
|
||||||
ntfs_log_trace("fd %p\n", (void *) fd);
|
ntfs_log_trace("fd %p\n", (void *) fd);
|
||||||
|
|
||||||
@ -431,7 +431,7 @@ int ntfs_fstat_r (struct _reent *r, int fd, struct stat *st)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ntfs_ftruncate_r (struct _reent *r, int fd, off_t len)
|
int ntfs_ftruncate_r (struct _reent *r, void * fd, off_t len)
|
||||||
{
|
{
|
||||||
ntfs_log_trace("fd %p, len %llu\n", (void *) fd, (u64) len);
|
ntfs_log_trace("fd %p, len %llu\n", (void *) fd, (u64) len);
|
||||||
|
|
||||||
@ -498,7 +498,7 @@ int ntfs_ftruncate_r (struct _reent *r, int fd, off_t len)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ntfs_fsync_r (struct _reent *r, int fd)
|
int ntfs_fsync_r (struct _reent *r, void * fd)
|
||||||
{
|
{
|
||||||
ntfs_log_trace("fd %p\n", (void *) fd);
|
ntfs_log_trace("fd %p\n", (void *) fd);
|
||||||
|
|
||||||
|
@ -53,13 +53,13 @@ void ntfsCloseFile (ntfs_file_state *file);
|
|||||||
|
|
||||||
/* Gekko devoptab file routines for NTFS-based devices */
|
/* Gekko devoptab file routines for NTFS-based devices */
|
||||||
extern int ntfs_open_r (struct _reent *r, void *fileStruct, const char *path, int flags, int mode);
|
extern int ntfs_open_r (struct _reent *r, void *fileStruct, const char *path, int flags, int mode);
|
||||||
extern int ntfs_close_r (struct _reent *r, int fd);
|
extern int ntfs_close_r (struct _reent *r, void *fd);
|
||||||
extern ssize_t ntfs_write_r (struct _reent *r, int fd, const char *ptr, size_t len);
|
extern ssize_t ntfs_write_r (struct _reent *r, void * fd, const char *ptr, size_t len);
|
||||||
extern ssize_t ntfs_read_r (struct _reent *r, int fd, char *ptr, size_t len);
|
extern ssize_t ntfs_read_r (struct _reent *r, void * fd, char *ptr, size_t len);
|
||||||
extern off_t ntfs_seek_r (struct _reent *r, int fd, off_t pos, int dir);
|
extern off_t ntfs_seek_r (struct _reent *r, void * fd, off_t pos, int dir);
|
||||||
extern int ntfs_fstat_r (struct _reent *r, int fd, struct stat *st);
|
extern int ntfs_fstat_r (struct _reent *r, void * fd, struct stat *st);
|
||||||
extern int ntfs_ftruncate_r (struct _reent *r, int fd, off_t len);
|
extern int ntfs_ftruncate_r (struct _reent *r, void * fd, off_t len);
|
||||||
extern int ntfs_fsync_r (struct _reent *r, int fd);
|
extern int ntfs_fsync_r (struct _reent *r, void * fd);
|
||||||
|
|
||||||
#endif /* _NTFSFILE_H */
|
#endif /* _NTFSFILE_H */
|
||||||
|
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
#include "ntfsinternal.h"
|
#include "ntfsinternal.h"
|
||||||
#include "ntfsdir.h"
|
#include "ntfsdir.h"
|
||||||
#include "ntfsfile.h"
|
#include "ntfsfile.h"
|
||||||
|
#include "lock.h"
|
||||||
|
|
||||||
#if defined(__wii__)
|
#if defined(__wii__)
|
||||||
#include <sdcard/wiisd_io.h>
|
#include <sdcard/wiisd_io.h>
|
||||||
@ -52,11 +53,11 @@ const INTERFACE_ID ntfs_disc_interfaces[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#elif defined (__wiiu__)
|
#elif defined (__wiiu__)
|
||||||
#include <iosuhax_disc_interface.h>
|
#include <iosuhax_disc_interface.h>
|
||||||
|
|
||||||
const INTERFACE_ID ntfs_disc_interfaces[] = {
|
const INTERFACE_ID ntfs_disc_interfaces[] = {
|
||||||
{"sd", get_io_wiiu_sd},
|
{"sd", &IOSUHAX_sdio_disc_interface},
|
||||||
{"usb", get_io_wiiu_usb},
|
{"usb", &IOSUHAX_usb_disc_interface},
|
||||||
{NULL, NULL}
|
{NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -199,7 +200,7 @@ int ntfsInitVolume (ntfs_vd *vd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Initialise the volume lock
|
// Initialise the volume lock
|
||||||
LWP_MutexInit(&vd->lock, false);
|
_NTFS_lock_init(&vd->lock, false);
|
||||||
|
|
||||||
// Reset the volumes name cache
|
// Reset the volumes name cache
|
||||||
vd->name[0] = '\0';
|
vd->name[0] = '\0';
|
||||||
@ -262,7 +263,7 @@ void ntfsDeinitVolume (ntfs_vd *vd)
|
|||||||
ntfsUnlock(vd);
|
ntfsUnlock(vd);
|
||||||
|
|
||||||
// Deinitialise the volume lock
|
// Deinitialise the volume lock
|
||||||
LWP_MutexDestroy(vd->lock);
|
_NTFS_lock_deinit((mutex_t *)vd->lock);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,7 @@
|
|||||||
#include "reparse.h"
|
#include "reparse.h"
|
||||||
#include "security.h"
|
#include "security.h"
|
||||||
#include "efs.h"
|
#include "efs.h"
|
||||||
|
#include "lock.h"
|
||||||
#include "unistr.h"
|
#include "unistr.h"
|
||||||
|
|
||||||
#if defined (__wiiu__)
|
#if defined (__wiiu__)
|
||||||
@ -151,13 +152,13 @@ typedef struct _ntfs_vd {
|
|||||||
/* Lock volume */
|
/* Lock volume */
|
||||||
static inline void ntfsLock (ntfs_vd *vd)
|
static inline void ntfsLock (ntfs_vd *vd)
|
||||||
{
|
{
|
||||||
LWP_MutexLock(vd->lock);
|
_NTFS_lock((mutex_t *)vd->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Unlock volume */
|
/* Unlock volume */
|
||||||
static inline void ntfsUnlock (ntfs_vd *vd)
|
static inline void ntfsUnlock (ntfs_vd *vd)
|
||||||
{
|
{
|
||||||
LWP_MutexUnlock(vd->lock);
|
_NTFS_unlock((mutex_t *)vd->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Gekko device related routines */
|
/* Gekko device related routines */
|
||||||
|
@ -40,7 +40,7 @@
|
|||||||
/*
|
/*
|
||||||
* assume "struct timespec" is not defined if st_mtime is not defined
|
* assume "struct timespec" is not defined if st_mtime is not defined
|
||||||
*/
|
*/
|
||||||
#if !defined(st_mtime) & !defined(__timespec_defined)
|
#if !defined(st_mtime) & !defined(__timespec_defined) & !defined(__wiiu__)
|
||||||
struct timespec {
|
struct timespec {
|
||||||
time_t tv_sec;
|
time_t tv_sec;
|
||||||
long tv_nsec;
|
long tv_nsec;
|
||||||
|
@ -75,7 +75,7 @@
|
|||||||
#include "realpath.h"
|
#include "realpath.h"
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
|
|
||||||
const char *ntfs_home =
|
const char *ntfs_home =
|
||||||
"News, support and information: http://tuxera.com\n";
|
"News, support and information: http://tuxera.com\n";
|
||||||
|
|
||||||
static const char *invalid_ntfs_msg =
|
static const char *invalid_ntfs_msg =
|
||||||
@ -108,7 +108,7 @@ static const char *opened_volume_msg =
|
|||||||
|
|
||||||
static const char *fakeraid_msg =
|
static const char *fakeraid_msg =
|
||||||
"Either the device is missing or it's powered down, or you have\n"
|
"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"
|
"SoftRAID hardware and must use an activated, different device under\n"
|
||||||
"/dev/mapper/, (e.g. /dev/mapper/nvidia_eahaabcc1) to mount NTFS.\n"
|
"/dev/mapper/, (e.g. /dev/mapper/nvidia_eahaabcc1) to mount NTFS.\n"
|
||||||
"Please see the 'dmraid' documentation for help.\n";
|
"Please see the 'dmraid' documentation for help.\n";
|
||||||
|
|
||||||
@ -144,8 +144,8 @@ static int ntfs_inode_free(ntfs_inode **ni)
|
|||||||
if (ni && *ni) {
|
if (ni && *ni) {
|
||||||
ret = ntfs_inode_close(*ni);
|
ret = ntfs_inode_close(*ni);
|
||||||
*ni = NULL;
|
*ni = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -169,7 +169,7 @@ static int __ntfs_volume_release(ntfs_volume *v)
|
|||||||
|
|
||||||
if (ntfs_inode_free(&v->vol_ni))
|
if (ntfs_inode_free(&v->vol_ni))
|
||||||
ntfs_error_set(&err);
|
ntfs_error_set(&err);
|
||||||
/*
|
/*
|
||||||
* FIXME: Inodes must be synced before closing
|
* FIXME: Inodes must be synced before closing
|
||||||
* attributes, otherwise unmount could fail.
|
* attributes, otherwise unmount could fail.
|
||||||
*/
|
*/
|
||||||
@ -178,20 +178,20 @@ static int __ntfs_volume_release(ntfs_volume *v)
|
|||||||
ntfs_attr_free(&v->lcnbmp_na);
|
ntfs_attr_free(&v->lcnbmp_na);
|
||||||
if (ntfs_inode_free(&v->lcnbmp_ni))
|
if (ntfs_inode_free(&v->lcnbmp_ni))
|
||||||
ntfs_error_set(&err);
|
ntfs_error_set(&err);
|
||||||
|
|
||||||
if (v->mft_ni && NInoDirty(v->mft_ni))
|
if (v->mft_ni && NInoDirty(v->mft_ni))
|
||||||
ntfs_inode_sync(v->mft_ni);
|
ntfs_inode_sync(v->mft_ni);
|
||||||
ntfs_attr_free(&v->mftbmp_na);
|
ntfs_attr_free(&v->mftbmp_na);
|
||||||
ntfs_attr_free(&v->mft_na);
|
ntfs_attr_free(&v->mft_na);
|
||||||
if (ntfs_inode_free(&v->mft_ni))
|
if (ntfs_inode_free(&v->mft_ni))
|
||||||
ntfs_error_set(&err);
|
ntfs_error_set(&err);
|
||||||
|
|
||||||
if (v->mftmirr_ni && NInoDirty(v->mftmirr_ni))
|
if (v->mftmirr_ni && NInoDirty(v->mftmirr_ni))
|
||||||
ntfs_inode_sync(v->mftmirr_ni);
|
ntfs_inode_sync(v->mftmirr_ni);
|
||||||
ntfs_attr_free(&v->mftmirr_na);
|
ntfs_attr_free(&v->mftmirr_na);
|
||||||
if (ntfs_inode_free(&v->mftmirr_ni))
|
if (ntfs_inode_free(&v->mftmirr_ni))
|
||||||
ntfs_error_set(&err);
|
ntfs_error_set(&err);
|
||||||
|
|
||||||
if (v->dev) {
|
if (v->dev) {
|
||||||
struct ntfs_device *dev = v->dev;
|
struct ntfs_device *dev = v->dev;
|
||||||
|
|
||||||
@ -260,10 +260,10 @@ static int ntfs_mft_load(ntfs_volume *vol)
|
|||||||
ntfs_log_perror("Error reading $MFT");
|
ntfs_log_perror("Error reading $MFT");
|
||||||
goto error_exit;
|
goto error_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ntfs_mft_record_check(vol, 0, mb))
|
if (ntfs_mft_record_check(vol, 0, mb))
|
||||||
goto error_exit;
|
goto error_exit;
|
||||||
|
|
||||||
ctx = ntfs_attr_get_search_ctx(vol->mft_ni, NULL);
|
ctx = ntfs_attr_get_search_ctx(vol->mft_ni, NULL);
|
||||||
if (!ctx)
|
if (!ctx)
|
||||||
goto error_exit;
|
goto error_exit;
|
||||||
@ -288,7 +288,7 @@ static int ntfs_mft_load(ntfs_volume *vol)
|
|||||||
vol->mft_ni->attr_list = ntfs_malloc(l);
|
vol->mft_ni->attr_list = ntfs_malloc(l);
|
||||||
if (!vol->mft_ni->attr_list)
|
if (!vol->mft_ni->attr_list)
|
||||||
goto error_exit;
|
goto error_exit;
|
||||||
|
|
||||||
l = ntfs_get_attribute_value(vol, ctx->attr, vol->mft_ni->attr_list);
|
l = ntfs_get_attribute_value(vol, ctx->attr, vol->mft_ni->attr_list);
|
||||||
if (!l) {
|
if (!l) {
|
||||||
ntfs_log_error("Failed to get value of $MFT/$ATTR_LIST.\n");
|
ntfs_log_error("Failed to get value of $MFT/$ATTR_LIST.\n");
|
||||||
@ -297,16 +297,16 @@ static int ntfs_mft_load(ntfs_volume *vol)
|
|||||||
if (l != vol->mft_ni->attr_list_size) {
|
if (l != vol->mft_ni->attr_list_size) {
|
||||||
ntfs_log_error("Partial read of $MFT/$ATTR_LIST (%lld != "
|
ntfs_log_error("Partial read of $MFT/$ATTR_LIST (%lld != "
|
||||||
"%u).\n", (long long)l,
|
"%u).\n", (long long)l,
|
||||||
vol->mft_ni->attr_list_size);
|
(unsigned int) vol->mft_ni->attr_list_size);
|
||||||
goto io_error_exit;
|
goto io_error_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
mft_has_no_attr_list:
|
mft_has_no_attr_list:
|
||||||
|
|
||||||
ntfs_attr_setup_flag(vol->mft_ni);
|
ntfs_attr_setup_flag(vol->mft_ni);
|
||||||
|
|
||||||
/* We now have a fully setup ntfs inode for $MFT in vol->mft_ni. */
|
/* We now have a fully setup ntfs inode for $MFT in vol->mft_ni. */
|
||||||
|
|
||||||
/* Get an ntfs attribute for $MFT/$DATA and set it up, too. */
|
/* Get an ntfs attribute for $MFT/$DATA and set it up, too. */
|
||||||
vol->mft_na = ntfs_attr_open(vol->mft_ni, AT_DATA, AT_UNNAMED, 0);
|
vol->mft_na = ntfs_attr_open(vol->mft_ni, AT_DATA, AT_UNNAMED, 0);
|
||||||
if (!vol->mft_na) {
|
if (!vol->mft_na) {
|
||||||
@ -428,18 +428,18 @@ static int ntfs_mftmirr_load(ntfs_volume *vol)
|
|||||||
ntfs_log_perror("Failed to open inode $MFTMirr");
|
ntfs_log_perror("Failed to open inode $MFTMirr");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
vol->mftmirr_na = ntfs_attr_open(vol->mftmirr_ni, AT_DATA, AT_UNNAMED, 0);
|
vol->mftmirr_na = ntfs_attr_open(vol->mftmirr_ni, AT_DATA, AT_UNNAMED, 0);
|
||||||
if (!vol->mftmirr_na) {
|
if (!vol->mftmirr_na) {
|
||||||
ntfs_log_perror("Failed to open $MFTMirr/$DATA");
|
ntfs_log_perror("Failed to open $MFTMirr/$DATA");
|
||||||
goto error_exit;
|
goto error_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ntfs_attr_map_runlist(vol->mftmirr_na, 0) < 0) {
|
if (ntfs_attr_map_runlist(vol->mftmirr_na, 0) < 0) {
|
||||||
ntfs_log_perror("Failed to map runlist of $MFTMirr/$DATA");
|
ntfs_log_perror("Failed to map runlist of $MFTMirr/$DATA");
|
||||||
goto error_exit;
|
goto error_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error_exit:
|
error_exit:
|
||||||
@ -484,12 +484,12 @@ ntfs_volume *ntfs_volume_startup(struct ntfs_device *dev,
|
|||||||
bs = ntfs_malloc(sizeof(NTFS_BOOT_SECTOR));
|
bs = ntfs_malloc(sizeof(NTFS_BOOT_SECTOR));
|
||||||
if (!bs)
|
if (!bs)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* Allocate the volume structure. */
|
/* Allocate the volume structure. */
|
||||||
vol = ntfs_volume_alloc();
|
vol = ntfs_volume_alloc();
|
||||||
if (!vol)
|
if (!vol)
|
||||||
goto error_exit;
|
goto error_exit;
|
||||||
|
|
||||||
/* Create the default upcase table. */
|
/* Create the default upcase table. */
|
||||||
vol->upcase_len = ntfs_upcase_build_default(&vol->upcase);
|
vol->upcase_len = ntfs_upcase_build_default(&vol->upcase);
|
||||||
if (!vol->upcase_len || !vol->upcase)
|
if (!vol->upcase_len || !vol->upcase)
|
||||||
@ -498,7 +498,7 @@ ntfs_volume *ntfs_volume_startup(struct ntfs_device *dev,
|
|||||||
/* Default with no locase table and case sensitive file names */
|
/* Default with no locase table and case sensitive file names */
|
||||||
vol->locase = (ntfschar*)NULL;
|
vol->locase = (ntfschar*)NULL;
|
||||||
NVolSetCaseSensitive(vol);
|
NVolSetCaseSensitive(vol);
|
||||||
|
|
||||||
/* by default, all files are shown and not marked hidden */
|
/* by default, all files are shown and not marked hidden */
|
||||||
NVolSetShowSysFiles(vol);
|
NVolSetShowSysFiles(vol);
|
||||||
NVolSetShowHidFiles(vol);
|
NVolSetShowHidFiles(vol);
|
||||||
@ -511,7 +511,7 @@ ntfs_volume *ntfs_volume_startup(struct ntfs_device *dev,
|
|||||||
#endif
|
#endif
|
||||||
if (flags & NTFS_MNT_RDONLY)
|
if (flags & NTFS_MNT_RDONLY)
|
||||||
NVolSetReadOnly(vol);
|
NVolSetReadOnly(vol);
|
||||||
|
|
||||||
/* ...->open needs bracketing to compile with glibc 2.7 */
|
/* ...->open needs bracketing to compile with glibc 2.7 */
|
||||||
if ((dev->d_ops->open)(dev, NVolReadOnly(vol) ? O_RDONLY: O_RDWR)) {
|
if ((dev->d_ops->open)(dev, NVolReadOnly(vol) ? O_RDONLY: O_RDWR)) {
|
||||||
if (!NVolReadOnly(vol) && (errno == EROFS)) {
|
if (!NVolReadOnly(vol) && (errno == EROFS)) {
|
||||||
@ -531,7 +531,7 @@ ntfs_volume *ntfs_volume_startup(struct ntfs_device *dev,
|
|||||||
}
|
}
|
||||||
/* Attach the device to the volume. */
|
/* Attach the device to the volume. */
|
||||||
vol->dev = dev;
|
vol->dev = dev;
|
||||||
|
|
||||||
/* Now read the bootsector. */
|
/* Now read the bootsector. */
|
||||||
br = ntfs_pread(dev, 0, sizeof(NTFS_BOOT_SECTOR), bs);
|
br = ntfs_pread(dev, 0, sizeof(NTFS_BOOT_SECTOR), bs);
|
||||||
if (br != sizeof(NTFS_BOOT_SECTOR)) {
|
if (br != sizeof(NTFS_BOOT_SECTOR)) {
|
||||||
@ -549,7 +549,7 @@ ntfs_volume *ntfs_volume_startup(struct ntfs_device *dev,
|
|||||||
}
|
}
|
||||||
if (ntfs_boot_sector_parse(vol, bs) < 0)
|
if (ntfs_boot_sector_parse(vol, bs) < 0)
|
||||||
goto error_exit;
|
goto error_exit;
|
||||||
|
|
||||||
free(bs);
|
free(bs);
|
||||||
bs = NULL;
|
bs = NULL;
|
||||||
/* Now set the device block size to the sector size. */
|
/* Now set the device block size to the sector size. */
|
||||||
@ -558,7 +558,7 @@ ntfs_volume *ntfs_volume_startup(struct ntfs_device *dev,
|
|||||||
"sector size. This may affect performance "
|
"sector size. This may affect performance "
|
||||||
"but should be harmless otherwise. Error: "
|
"but should be harmless otherwise. Error: "
|
||||||
"%s\n", strerror(errno));
|
"%s\n", strerror(errno));
|
||||||
|
|
||||||
/* We now initialize the cluster allocator. */
|
/* We now initialize the cluster allocator. */
|
||||||
vol->full_zones = 0;
|
vol->full_zones = 0;
|
||||||
mft_zone_size = vol->nr_clusters >> 3; /* 12.5% */
|
mft_zone_size = vol->nr_clusters >> 3; /* 12.5% */
|
||||||
@ -652,14 +652,14 @@ static int ntfs_volume_check_logfile(ntfs_volume *vol)
|
|||||||
errno = EIO;
|
errno = EIO;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0);
|
na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0);
|
||||||
if (!na) {
|
if (!na) {
|
||||||
ntfs_log_perror("Failed to open $FILE_LogFile/$DATA");
|
ntfs_log_perror("Failed to open $FILE_LogFile/$DATA");
|
||||||
err = EIO;
|
err = EIO;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ntfs_check_logfile(na, &rp) || !ntfs_is_logfile_clean(na, rp))
|
if (!ntfs_check_logfile(na, &rp) || !ntfs_is_logfile_clean(na, rp))
|
||||||
err = EOPNOTSUPP;
|
err = EOPNOTSUPP;
|
||||||
/*
|
/*
|
||||||
@ -682,7 +682,7 @@ static int ntfs_volume_check_logfile(ntfs_volume *vol)
|
|||||||
}
|
}
|
||||||
free(rp);
|
free(rp);
|
||||||
ntfs_attr_close(na);
|
ntfs_attr_close(na);
|
||||||
out:
|
out:
|
||||||
if (ntfs_inode_close(ni))
|
if (ntfs_inode_close(ni))
|
||||||
ntfs_error_set(&err);
|
ntfs_error_set(&err);
|
||||||
if (err) {
|
if (err) {
|
||||||
@ -1007,16 +1007,16 @@ ntfs_volume *ntfs_device_mount(struct ntfs_device *dev, ntfs_mount_flags flags)
|
|||||||
ntfs_log_perror("Failed to open inode FILE_Bitmap");
|
ntfs_log_perror("Failed to open inode FILE_Bitmap");
|
||||||
goto error_exit;
|
goto error_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
vol->lcnbmp_na = ntfs_attr_open(vol->lcnbmp_ni, AT_DATA, AT_UNNAMED, 0);
|
vol->lcnbmp_na = ntfs_attr_open(vol->lcnbmp_ni, AT_DATA, AT_UNNAMED, 0);
|
||||||
if (!vol->lcnbmp_na) {
|
if (!vol->lcnbmp_na) {
|
||||||
ntfs_log_perror("Failed to open ntfs attribute");
|
ntfs_log_perror("Failed to open ntfs attribute");
|
||||||
goto error_exit;
|
goto error_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vol->lcnbmp_na->data_size > vol->lcnbmp_na->allocated_size) {
|
if (vol->lcnbmp_na->data_size > vol->lcnbmp_na->allocated_size) {
|
||||||
ntfs_log_error("Corrupt cluster map size (%lld > %lld)\n",
|
ntfs_log_error("Corrupt cluster map size (%lld > %lld)\n",
|
||||||
(long long)vol->lcnbmp_na->data_size,
|
(long long)vol->lcnbmp_na->data_size,
|
||||||
(long long)vol->lcnbmp_na->allocated_size);
|
(long long)vol->lcnbmp_na->allocated_size);
|
||||||
goto io_error_exit;
|
goto io_error_exit;
|
||||||
}
|
}
|
||||||
@ -1172,7 +1172,7 @@ ntfs_volume *ntfs_device_mount(struct ntfs_device *dev, ntfs_mount_flags flags)
|
|||||||
vol->vol_name = ntfs_malloc(u + 1);
|
vol->vol_name = ntfs_malloc(u + 1);
|
||||||
if (!vol->vol_name)
|
if (!vol->vol_name)
|
||||||
goto error_exit;
|
goto error_exit;
|
||||||
|
|
||||||
for (j = 0; j < (s32)u; j++) {
|
for (j = 0; j < (s32)u; j++) {
|
||||||
u16 uc = le16_to_cpu(vname[j]);
|
u16 uc = le16_to_cpu(vname[j]);
|
||||||
if (uc > 0xff)
|
if (uc > 0xff)
|
||||||
@ -1639,7 +1639,7 @@ int ntfs_logfile_reset(ntfs_volume *vol)
|
|||||||
ntfs_attr_close(na);
|
ntfs_attr_close(na);
|
||||||
goto error_exit;
|
goto error_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
ntfs_attr_close(na);
|
ntfs_attr_close(na);
|
||||||
return ntfs_inode_close(ni);
|
return ntfs_inode_close(ni);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user