From f8705b2c395b4cc654f85dcc48ce7c6bf3c29225 Mon Sep 17 00:00:00 2001 From: Maschell Date: Sun, 6 Dec 2020 23:06:22 +0100 Subject: [PATCH] Wii U support --- .github/workflows/push_image.yml | 26 ++ .gitignore | 5 + Dockerfile.wiiu | 11 + Makefile | 17 +- README.md | 20 ++ include/ntfs.h | 15 +- source/Makefile | 37 ++- source/bootsect.c | 20 +- source/cache2.c | 6 +- source/cache2.h | 20 +- source/compat.h | 6 +- source/device_io.c | 2 +- source/device_io.h | 10 +- source/dir.c | 99 +++--- source/gekko_io.c | 21 +- source/gekko_io.h | 15 +- source/index.c | 516 +++++++++++++++---------------- source/inode.c | 66 ++-- source/lock.c | 28 ++ source/lock.h | 108 +++++++ source/mft.c | 146 ++++----- source/mst.c | 2 +- source/ntfs.c | 26 +- source/ntfsfile.c | 14 +- source/ntfsfile.h | 14 +- source/ntfsinternal.c | 14 +- source/ntfsinternal.h | 19 +- source/ntfstime.h | 2 +- source/volume.c | 64 ++-- 29 files changed, 830 insertions(+), 519 deletions(-) create mode 100644 .github/workflows/push_image.yml create mode 100644 .gitignore create mode 100644 Dockerfile.wiiu create mode 100644 README.md create mode 100644 source/lock.c create mode 100644 source/lock.h diff --git a/.github/workflows/push_image.yml b/.github/workflows/push_image.yml new file mode 100644 index 0000000..d723de9 --- /dev/null +++ b/.github/workflows/push_image.yml @@ -0,0 +1,26 @@ +name: Publish Docker Image +on: + push: + branches: + - main +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@master + - name: Get release version + id: get_release_tag + run: | + echo RELEASE_VERSION=$(echo $(date '+%Y%m%d')) >> $GITHUB_ENV + echo REPOSITORY_NAME=$(echo "$GITHUB_REPOSITORY" | awk -F / '{print $2}' | sed -e "s/:refs//" | tr '[:upper:]' '[:lower:]') >> $GITHUB_ENV + echo REPOSITORY_OWNER=$(echo "$GITHUB_REPOSITORY" | awk -F / '{print $1}' | sed 's/[^a-zA-Z0-9]//g' | tr '[:upper:]' '[:lower:]') >> $GITHUB_ENV + - name: Publish to Registry + uses: elgohr/Publish-Docker-Github-Action@master + with: + name: ${{ env.REPOSITORY_OWNER }}/${{ env.REPOSITORY_NAME }} + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + snapshot: true + cache: true + tags: "latest, ${{ env.RELEASE_VERSION }}" + dockerfile: Dockerfile.wiiu \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..54e7791 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +source/wiiu_release/* +source/wii_release/* +source/cube_release/* +lib/* +.idea/* \ No newline at end of file diff --git a/Dockerfile.wiiu b/Dockerfile.wiiu new file mode 100644 index 0000000..b6595f0 --- /dev/null +++ b/Dockerfile.wiiu @@ -0,0 +1,11 @@ +FROM wiiuenv/devkitppc:20200810 + +COPY --from=wiiuenv/libiosuhax:20200812 /artifacts $DEVKITPRO + +WORKDIR tmp_build +COPY . . +RUN make clean && make wiiu-release && mkdir -p /artifacts/wut/usr && cp -r lib /artifacts/wut/usr && cp -r include //artifacts/wut/usr +WORKDIR /artifacts + +FROM scratch +COPY --from=0 /artifacts /artifacts \ No newline at end of file diff --git a/Makefile b/Makefile index 1af50f9..eda2013 100644 --- a/Makefile +++ b/Makefile @@ -1,11 +1,11 @@ -default: cube-release wii-release +default: cube-release wii-release wiiu-release all: debug release -debug: cube-debug wii-debug +debug: cube-debug wii-debug wiiu-debug -release: cube-release wii-release +release: cube-release wii-release wiiu-release cube-debug: $(MAKE) -C source PLATFORM=cube BUILD=cube_debug @@ -13,12 +13,18 @@ cube-debug: wii-debug: $(MAKE) -C source PLATFORM=wii BUILD=wii_debug +wiiu-debug: + $(MAKE) -C source PLATFORM=wiiu BUILD=wiiu_debug + cube-release: $(MAKE) -C source PLATFORM=cube BUILD=cube_release wii-release: $(MAKE) -C source PLATFORM=wii BUILD=wii_release +wiiu-release: + $(MAKE) -C source PLATFORM=wiiu BUILD=wiiu_release + clean: $(MAKE) -C source clean @@ -28,7 +34,10 @@ cube-install: cube-release wii-install: wii-release $(MAKE) -C source wii-install PLATFORM=wii -install: wii-install +wiiu-install: wiiu-release + $(MAKE) -C source wiiu-install PLATFORM=wiiu + +install: wiiu-install run: install $(MAKE) -C example diff --git a/README.md b/README.md new file mode 100644 index 0000000..1c42e0b --- /dev/null +++ b/README.md @@ -0,0 +1,20 @@ +# libntfs for the Wii U [![Build Status](https://travis-ci.org/Maschell/libntfs-wiiu.svg)](https://travis-ci.org/Maschell/libntfs-wiiu) + +## Usage +Link the application with: +``` +-lntfs -liosuhax +``` + +## Dependencies +To be able to use libntfs for the Wii u, you need to install the following dependencies: + +- [libiosuhax](https://github.com/dimok789/libiosuhax) + +# Use the prebuilt files from a Docker image. +The image `wiiulegacy/libntfs` on [Docker Hub](https://hub.docker.com/r/wiiulegacy/libntfs/) provides a prebuilt library in the `/artifacts` directory. Copy it into your DevkitPPC portlibs folder. + +Example: +``` +COPY --from=wiiulegacy/libntfs:2013.1.13 /artifacts $DEVKITPRO/portlibs +``` diff --git a/include/ntfs.h b/include/ntfs.h index 62f2f71..5c42114 100644 --- a/include/ntfs.h +++ b/include/ntfs.h @@ -27,9 +27,18 @@ extern "C" { #endif -#include -#include -#include +#if defined(__gamecube__) || defined (__wii__) + #include + #include + #include +#elif defined (__WIIU__) + #include + typedef uint8_t u8; + typedef uint16_t u16; + typedef int32_t s32; + typedef uint32_t u32; + typedef int mutex_t; +#endif /* NTFS errno values */ #define ENOPART 3000 /* No partition was found */ diff --git a/source/Makefile b/source/Makefile index 6a6bbec..f899d54 100644 --- a/source/Makefile +++ b/source/Makefile @@ -7,12 +7,17 @@ ifeq ($(strip $(DEVKITPPC)),) $(error "Please set DEVKITPPC in your environment. export DEVKITPPC=devkitPPC") endif +ifeq ($(PLATFORM),wiiu) + include $(DEVKITPRO)/wut/share/wut_rules + MACHDEP += -D__WIIU__ +endif + ifeq ($(PLATFORM),wii) -include $(DEVKITPPC)/wii_rules + include $(DEVKITPPC)/wii_rules endif ifeq ($(PLATFORM),cube) -include $(DEVKITPPC)/gamecube_rules + include $(DEVKITPPC)/gamecube_rules endif #--------------------------------------------------------------------------------- @@ -20,7 +25,7 @@ endif # SOURCES is a list of directories containing source code # INCLUDES is a list of directories containing extra header files #--------------------------------------------------------------------------------- -BUILD ?= wii_release +BUILD ?= wiiu_release SOURCES := . INCLUDES := ../include LIBDIR := ../lib @@ -28,7 +33,7 @@ LIBDIR := ../lib #--------------------------------------------------------------------------------- # options for code generation #--------------------------------------------------------------------------------- -CFLAGS = -Os -Wall -ffast-math -pipe $(MACHDEP) $(INCLUDE) -DHAVE_CONFIG_H +CFLAGS = -Wall -ffast-math -pipe $(MACHDEP) $(INCLUDE) -ffunction-sections -DHAVE_CONFIG_H CXXFLAGS = $(CFLAGS) ASFLAGS := -g export NTFSBIN := $(LIBDIR)/$(PLATFORM)/libntfs.a @@ -37,21 +42,29 @@ ifeq ($(BUILD),cube_debug) CFLAGS += -DDEBUG CXXFLAGS += -DDEBUG endif + ifeq ($(BUILD),wii_debug) CFLAGS += -DDEBUG CXXFLAGS += -DDEBUG endif +ifeq ($(BUILD),wiiu_debug) +CFLAGS += -DDEBUG +CXXFLAGS += -DDEBUG +endif + #--------------------------------------------------------------------------------- # any extra libraries we wish to link with the project #--------------------------------------------------------------------------------- -LIBS := +LIBS := #--------------------------------------------------------------------------------- # list of directories containing libraries, this must be the top level containing # include and lib #--------------------------------------------------------------------------------- -LIBDIRS := +ifeq ($(PLATFORM),wiiu) +LIBDIRS := $(WUT_ROOT)/usr +endif #--------------------------------------------------------------------------------- # no real need to edit anything past this point unless you need to add additional @@ -77,11 +90,9 @@ export OFILES := $(addsuffix .o,$(BINFILES)) \ export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ - -I$(CURDIR)/$(BUILD) \ - -I$(LIBOGC_INC) + -I$(CURDIR)/$(BUILD) -I$(PORTLIBS)/include -export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) \ - -L$(LIBOGC_LIB) +export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) $(PORTLIBS)/lib .PHONY: $(BUILD) clean @@ -93,7 +104,7 @@ $(BUILD): #--------------------------------------------------------------------------------- clean: @echo clean ... - @rm -fr wii_debug wii_release cube_debug cube_release $(LIBDIR) + @rm -fr wii_debug wii_release wiiu_release cube_debug cube_release $(LIBDIR) all: $(NTFSBIN) @@ -105,6 +116,10 @@ wii-install: cp ../include/ntfs.h $(PORTLIBS)/include cp ../lib/wii/libntfs.a $(PORTLIBS)/lib +wiiu-install: + cp ../include/ntfs.h $(WUT_ROOT)/usr/include + cp ../lib/wiiu/libntfs.a $(WUT_ROOT)/usr/lib + #--------------------------------------------------------------------------------- else diff --git a/source/bootsect.c b/source/bootsect.c index e9be072..502e3b9 100644 --- a/source/bootsect.c +++ b/source/bootsect.c @@ -73,7 +73,7 @@ BOOL ntfs_boot_sector_is_ntfs(NTFS_BOOT_SECTOR *b) ntfs_log_debug("Checking bytes per sector.\n"); if (le16_to_cpu(b->bpb.bytes_per_sector) < 256 || 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)); goto not_ntfs; } @@ -89,10 +89,10 @@ BOOL ntfs_boot_sector_is_ntfs(NTFS_BOOT_SECTOR *b) } 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; 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; } @@ -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.sectors), 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); goto not_ntfs; } @@ -193,14 +193,14 @@ int ntfs_boot_sector_parse(ntfs_volume *vol, const NTFS_BOOT_SECTOR *bs) "\n", sectors_per_cluster); return -1; } - + sectors = sle64_to_cpu(bs->number_of_sectors); ntfs_log_debug("NumberOfSectors = %lld\n", (long long)sectors); if (!sectors) { ntfs_log_error("Volume size is set to zero.\n"); return -1; } - if (vol->dev->d_ops->seek(vol->dev, + if (vol->dev->d_ops->seek(vol->dev, (sectors - 1) << vol->sector_size_bits, SEEK_SET) == -1) { 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); return -1; } - + vol->nr_clusters = sectors >> (ffs(sectors_per_cluster) - 1); 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); return -1; } - + vol->cluster_size = sectors_per_cluster * vol->sector_size; if (vol->cluster_size & (vol->cluster_size - 1)) { ntfs_log_error("cluster_size (%d) is not a power of 2.\n", - vol->cluster_size); + (int)vol->cluster_size); return -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; if (vol->mft_record_size & (vol->mft_record_size - 1)) { 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; } vol->mft_record_size_bits = ffs(vol->mft_record_size) - 1; diff --git a/source/cache2.c b/source/cache2.c index 872f1a5..870e4ab 100644 --- a/source/cache2.c +++ b/source/cache2.c @@ -35,7 +35,11 @@ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include +#if defined (__WIIU__) + +#elif defined(__gamecube__) || defined (__wii__) + #include +#endif #include #include diff --git a/source/cache2.h b/source/cache2.h index 21daca7..0b2f8c2 100644 --- a/source/cache2.h +++ b/source/cache2.h @@ -42,9 +42,21 @@ #include #include -#include -#include -#include + +#if defined (__WIIU__) + #include + typedef uint8_t u8; + typedef uint16_t u16; + typedef int32_t s32; + typedef uint32_t u32; + typedef uint64_t u64; + typedef uint32_t sec_t; + typedef int mutex_t; +#elif defined(__gamecube__) || defined (__wii__) + #include + #include + #include +#endif typedef struct { sec_t sector; @@ -54,7 +66,7 @@ typedef struct { u8* cache; } NTFS_CACHE_ENTRY; -typedef struct { +typedef struct NTFS_CACHE_{ const DISC_INTERFACE* disc; sec_t endOfPartition; unsigned int numberOfPages; diff --git a/source/compat.h b/source/compat.h index d680c20..698a4b7 100644 --- a/source/compat.h +++ b/source/compat.h @@ -69,11 +69,11 @@ extern char *strsep(char **stringp, const char *delim); #define O_BINARY 0 /* unix is binary by default */ #endif -#ifdef GEKKO +#if defined(GEKKO) || defined (__WIIU__) #include "mem_allocate.h" -#define XATTR_CREATE 1 +#define XATTR_CREATE 1 #define XATTR_REPLACE 2 #define MINORBITS 20 @@ -81,7 +81,7 @@ extern char *strsep(char **stringp, const char *delim); #define major(dev) ((unsigned int) ((dev) >> MINORBITS)) #define minor(dev) ((unsigned int) ((dev) & MINORMASK)) -#define mkdev(ma,mi) (((ma) << MINORBITS) | (mi)) +#define mkdev(ma,mi) (((ma) << MINORBITS) | (mi)) #define random rand #endif /* defined GEKKO */ diff --git a/source/device_io.c b/source/device_io.c index f76bf70..5ecd08d 100644 --- a/source/device_io.c +++ b/source/device_io.c @@ -27,7 +27,7 @@ #ifndef __CYGWIN32__ /* Not on Cygwin; use standard Unix style low level device operations. */ -#include "unix_io.c" +//#include "unix_io.c" #else /* __CYGWIN32__ */ diff --git a/source/device_io.h b/source/device_io.h index fad4d85..6030232 100644 --- a/source/device_io.h +++ b/source/device_io.h @@ -30,12 +30,12 @@ #ifndef __CYGWIN32__ -#ifndef GEKKO -/* Not on Cygwin; use standard Unix style low level device operations. */ -#define ntfs_device_default_io_ops ntfs_device_unix_io_ops +#if defined(GEKKO) || defined (__WIIU__) + /* Wii i/o device. */ + #define ntfs_device_default_io_ops ntfs_device_gekko_io_ops #else -/* Wii i/o device. */ -#define ntfs_device_default_io_ops ntfs_device_gekko_io_ops + /* Not on Cygwin; use standard Unix style low level device operations. */ + #define ntfs_device_default_io_ops ntfs_device_unix_io_ops #endif #else /* __CYGWIN32__ */ diff --git a/source/dir.c b/source/dir.c index 2539586..f486f16 100644 --- a/source/dir.c +++ b/source/dir.c @@ -66,6 +66,11 @@ #include #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" * 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) break; - + if (!le16_to_cpu(ie->length)) { ntfs_log_error("Zero length index entry in inode %lld" "\n", (unsigned long long)dir_ni->mft_no); @@ -441,7 +446,7 @@ descend_into_child_node: (u8*)ie + le16_to_cpu(ie->key_length) > index_end) { ntfs_log_error("Index entry out of bounds in directory " - "inode %lld.\n", + "inode %lld.\n", (unsigned long long)dir_ni->mft_no); errno = EIO; goto close_err_out; @@ -452,7 +457,7 @@ descend_into_child_node: */ if (ie->ie_flags & INDEX_ENTRY_END) break; - + if (!le16_to_cpu(ie->length)) { errno = EIO; 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; return NULL; } - + ntfs_log_trace("path: '%s'\n", pathname); - + ascii = strdup(pathname); if (!ascii) { 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; goto close; } - + free(unicode); unicode = NULL; @@ -974,7 +979,7 @@ static int ntfs_filldir(ntfs_inode *dir_ni, s64 *pos, u8 ivcn_bits, MFT_REF mref; ntfs_log_trace("Entering.\n"); - + /* Advance the position even if going to skip the entry. */ if (index_type == INDEX_TYPE_ALLOCATION) *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; ntfs_log_trace("Entering.\n"); - + if (!ni) { errno = EINVAL; return ERR_MREF(-1); @@ -1065,7 +1070,7 @@ static MFT_REF ntfs_mft_get_parent_ref(ntfs_inode *ni) if (!ctx) return ERR_MREF(-1); if (ntfs_attr_lookup(AT_FILE_NAME, AT_UNNAMED, 0, 0, 0, NULL, 0, ctx)) { - ntfs_log_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); 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; ntfs_log_trace("Entering.\n"); - + if (!dir_ni || !pos || !filldir) { errno = EINVAL; return -1; @@ -1246,10 +1251,10 @@ int ntfs_readdir(ntfs_inode *dir_ni, s64 *pos, /* The last entry cannot contain a name. */ if (ie->ie_flags & INDEX_ENTRY_END) break; - + if (!le16_to_cpu(ie->length)) goto dir_err_out; - + /* Skip index root entry if continuing previous readdir. */ if (ir_pos > (u8*)ie - (u8*)ir) continue; @@ -1402,10 +1407,10 @@ find_next_index_buffer: /* The last entry cannot contain a name. */ if (ie->ie_flags & INDEX_ENTRY_END) break; - + if (!le16_to_cpu(ie->length)) goto dir_err_out; - + /* Skip index entry if continuing previous readdir. */ if (ia_pos - ia_start > (u8*)ie - (u8*)ia) continue; @@ -1492,19 +1497,19 @@ static ntfs_inode *__ntfs_create(ntfs_inode *dir_ni, le32 securid, int err, fn_len, si_len; ntfs_log_trace("Entering.\n"); - + /* Sanity checks. */ if (!dir_ni || !name || !name_len) { ntfs_log_error("Invalid arguments.\n"); errno = EINVAL; return NULL; } - + if (dir_ni->flags & FILE_ATTR_REPARSE_POINT) { errno = EOPNOTSUPP; return NULL; } - + ni = ntfs_mft_record_alloc(dir_ni->vol, NULL); if (!ni) return NULL; @@ -1596,7 +1601,7 @@ static ntfs_inode *__ntfs_create(ntfs_inode *dir_ni, le32 securid, ni->vol->indx_record_size >> ni->vol->cluster_size_bits; else - ir->clusters_per_index_block = + ir->clusters_per_index_block = ni->vol->indx_record_size >> NTFS_BLOCK_SIZE_BITS; ir->index.entries_offset = cpu_to_le32(sizeof(INDEX_HEADER)); @@ -1725,7 +1730,7 @@ err_out: if (rollback_sd) ntfs_attr_remove(ni, AT_SECURITY_DESCRIPTOR, AT_UNNAMED, 0); - + if (rollback_data) ntfs_attr_remove(ni, AT_DATA, AT_UNNAMED, 0); /* @@ -1790,7 +1795,7 @@ int ntfs_check_empty_dir(ntfs_inode *ni) { ntfs_attr *na; int ret = 0; - + if (!(ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)) return 0; @@ -1800,7 +1805,7 @@ int ntfs_check_empty_dir(ntfs_inode *ni) ntfs_log_perror("Failed to open directory"); return -1; } - + /* Non-empty directory? */ if ((na->data_size != sizeof(INDEX_ROOT) + sizeof(INDEX_ENTRY_HEADER))){ /* 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"); ret = -1; } - + ntfs_attr_close(na); 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 ret; - + ret = ntfs_check_empty_dir(ni); if (!ret || errno != ENOTEMPTY) return ret; - /* + /* * 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 */ - if ((link_count == 1) || + if ((link_count == 1) || (link_count == 2 && fn->file_name_type == FILE_NAME_DOS)) { errno = ENOTEMPTY; ntfs_log_debug("Non-empty directory without hard links\n"); goto no_hardlink; } - + ret = 0; -no_hardlink: +no_hardlink: return ret; } @@ -1872,7 +1877,7 @@ int ntfs_delete(ntfs_volume *vol, const char *pathname, #endif ntfs_log_trace("Entering.\n"); - + if (!ni || !dir_ni || !name || !name_len) { ntfs_log_error("Invalid arguments.\n"); errno = EINVAL; @@ -1918,12 +1923,12 @@ search: else continue; } - + /* Ignore hard links from other directories */ if (dir_ni->mft_no != MREF_LE(fn->parent_directory)) { ntfs_log_debug("MFT record numbers don't match " - "(%llu != %llu)\n", - (long long unsigned)dir_ni->mft_no, + "(%llu != %llu)\n", + (long long unsigned)dir_ni->mft_no, (long long unsigned)MREF_LE(fn->parent_directory)); continue; } @@ -1931,11 +1936,11 @@ search: || ((fn->file_name_type == FILE_NAME_POSIX) && NVolCaseSensitive(ni->vol))) case_sensitive = CASE_SENSITIVE; - + if (ntfs_names_are_equal(fn->file_name, fn->file_name_length, - name, name_len, case_sensitive, + name, name_len, case_sensitive, ni->vol->upcase, ni->vol->upcase_len)){ - + if (fn->file_name_type == FILE_NAME_WIN32) { looking_for_dos_name = TRUE; ntfs_attr_reinit_search_ctx(actx); @@ -1958,13 +1963,13 @@ search: } goto err_out; } - + if (ntfs_check_unlinkable_dir(ni, fn) < 0) goto err_out; - + if (ntfs_index_remove(dir_ni, ni, fn, le32_to_cpu(actx->attr->value_length))) goto err_out; - + /* * Keep the last name in place, this is useful for undeletion * (Windows also does so), however delete the name if it were @@ -1977,10 +1982,10 @@ search: if (ntfs_attr_record_rm(actx)) goto err_out; } - + ni->mrec->link_count = cpu_to_le16(le16_to_cpu( ni->mrec->link_count) - 1); - + ntfs_inode_mark_dirty(ni); if (looking_for_dos_name) { looking_for_dos_name = FALSE; @@ -2106,7 +2111,7 @@ search: "Leaving inconsistent metadata.\n"); } ni = NULL; -ok: +ok: ntfs_inode_update_times(dir_ni, NTFS_UPDATE_MCTIME); out: 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; 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) { err = EINVAL; ntfs_log_perror("ntfs_link wrong arguments"); goto err_out; } - + if ((ni->flags & FILE_ATTR_REPARSE_POINT) && !ntfs_possible_symlink(ni)) { err = EOPNOTSUPP; @@ -2171,7 +2176,7 @@ static int ntfs_link_i(ntfs_inode *ni, ntfs_inode *dir_ni, const ntfschar *name, else ni->flags &= ~FILE_ATTR_HIDDEN; } - + /* Create FILE_NAME attribute. */ fn_len = sizeof(FILE_NAME_ATTR) + name_len * sizeof(ntfschar); 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, FILE_NAME_WIN32_AND_DOS) >= 0) { if (!ntfs_delete(vol, - (const char*)NULL, ni, dir_ni, + (const char*)NULL, ni, dir_ni, deletename, deletelen)) res = 0; deleted = TRUE; @@ -2580,7 +2585,7 @@ static int set_dos_name(ntfs_inode *ni, ntfs_inode *dir_ni, res = -1; } } else { - if (!ntfs_link_i(ni, dir_ni, shortname, shortlen, + if (!ntfs_link_i(ni, dir_ni, shortname, shortlen, FILE_NAME_DOS) /* make sure a new link was recorded */ && (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 { /* * DOS name has been found, but cannot - * migrate to Posix : something bad + * migrate to Posix : something bad * has happened */ errno = EIO; diff --git a/source/gekko_io.c b/source/gekko_io.c index 7ac24c7..a452de1 100644 --- a/source/gekko_io.c +++ b/source/gekko_io.c @@ -54,6 +54,8 @@ #include #endif +typedef double f64; + #include "ntfs.h" #include "types.h" #include "logging.h" @@ -62,6 +64,7 @@ #include "cache.h" #include "device.h" #include "bootsect.h" +#include "mem_allocate.h" #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)) { - ntfs_log_perror("read failure @ sector %d\n", fd->startSector); + ntfs_log_perror("read failure @ sector %d\n", (int)fd->startSector); errno = EIO; ntfs_free(boot); return -1; @@ -318,7 +321,7 @@ static s64 ntfs_device_gekko_io_readbytes(struct ntfs_device *dev, s64 offset, s // Read from the device 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)) { - 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; return -1; } @@ -336,10 +339,10 @@ static s64 ntfs_device_gekko_io_readbytes(struct ntfs_device *dev, s64 offset, s } // 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); 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); errno = EIO; 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)) { // 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)) { - 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; return -1; } @@ -428,7 +431,7 @@ static s64 ntfs_device_gekko_io_writebytes(struct ntfs_device *dev, s64 offset, if(buffer_offset != 0) { 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); errno = EIO; 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 (!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); errno = EIO; return -1; @@ -450,7 +453,7 @@ static s64 ntfs_device_gekko_io_writebytes(struct ntfs_device *dev, s64 offset, // Write to the device 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)) { - 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); errno = EIO; return -1; diff --git a/source/gekko_io.h b/source/gekko_io.h index bc5516a..f10e377 100644 --- a/source/gekko_io.h +++ b/source/gekko_io.h @@ -27,8 +27,18 @@ #include "types.h" #include "cache2.h" -#include -#include + +#if defined (__WIIU__) + #include + typedef uint8_t u8; + typedef uint16_t u16; + typedef int32_t s32; + typedef uint32_t u32; + typedef int mutex_t; +#elif defined(__gamecube__) || defined (__wii__) + #include + #include +#endif #define MAX_SECTOR_SIZE 4096 @@ -49,6 +59,7 @@ typedef struct _gekko_fd { u32 cachePageSize; /* The number of sectors per cache page */ } gekko_fd; + /* Forward declarations */ struct ntfs_device_operations; diff --git a/source/index.c b/source/index.c index d498dde..d05e2cc 100644 --- a/source/index.c +++ b/source/index.c @@ -83,9 +83,9 @@ static VCN ntfs_ib_pos_to_vcn(ntfs_index_context *icx, s64 pos) static int ntfs_ib_write(ntfs_index_context *icx, INDEX_BLOCK *ib) { s64 ret, vcn = sle64_to_cpu(ib->index_block_vcn); - + ntfs_log_trace("vcn: %lld\n", (long long)vcn); - + ret = ntfs_attr_mst_pwrite(icx->ia_na, ntfs_ib_vcn_to_pos(icx, vcn), 1, icx->block_size, ib); if (ret != 1) { @@ -93,7 +93,7 @@ static int ntfs_ib_write(ntfs_index_context *icx, INDEX_BLOCK *ib) (long long)vcn, (unsigned long long)icx->ni->mft_no); return STATUS_ERROR; } - + return STATUS_OK; } @@ -101,9 +101,9 @@ static int ntfs_icx_ib_write(ntfs_index_context *icx) { if (ntfs_ib_write(icx, icx->ib)) return STATUS_ERROR; - + icx->ib_dirty = FALSE; - + return STATUS_OK; } @@ -122,7 +122,7 @@ ntfs_index_context *ntfs_index_ctx_get(ntfs_inode *ni, ntfs_index_context *icx; ntfs_log_trace("Entering\n"); - + if (!ni) { errno = EINVAL; return NULL; @@ -142,7 +142,7 @@ ntfs_index_context *ntfs_index_ctx_get(ntfs_inode *ni, static void ntfs_index_ctx_free(ntfs_index_context *icx) { ntfs_log_trace("Entering\n"); - + if (!icx->entry) return; @@ -156,7 +156,7 @@ static void ntfs_index_ctx_free(ntfs_index_context *icx) } free(icx->ib); } - + ntfs_attr_close(icx->ia_na); } @@ -181,9 +181,9 @@ void ntfs_index_ctx_put(ntfs_index_context *icx) void ntfs_index_ctx_reinit(ntfs_index_context *icx) { ntfs_log_trace("Entering\n"); - + ntfs_index_ctx_free(icx); - + *icx = (ntfs_index_context) { .ni = icx->ni, .name = icx->name, @@ -225,30 +225,30 @@ static int ntfs_ie_end(INDEX_ENTRY *ie) return ie->ie_flags & INDEX_ENTRY_END || !ie->length; } -/** +/** * Find the last entry in the index block */ static INDEX_ENTRY *ntfs_ie_get_last(INDEX_ENTRY *ie, char *ies_end) { ntfs_log_trace("Entering\n"); - + while ((char *)ie < ies_end && !ntfs_ie_end(ie)) ie = ntfs_ie_get_next(ie); - + return ie; } static INDEX_ENTRY *ntfs_ie_get_by_pos(INDEX_HEADER *ih, int pos) { INDEX_ENTRY *ie; - + ntfs_log_trace("pos: %d\n", pos); - + ie = ntfs_ie_get_first(ih); - + while (pos-- > 0) ie = ntfs_ie_get_next(ie); - + return ie; } @@ -256,16 +256,16 @@ static INDEX_ENTRY *ntfs_ie_prev(INDEX_HEADER *ih, INDEX_ENTRY *ie) { INDEX_ENTRY *ie_prev = NULL; INDEX_ENTRY *tmp; - + ntfs_log_trace("Entering\n"); - + tmp = ntfs_ie_get_first(ih); - + while (tmp != ie) { ie_prev = tmp; tmp = ntfs_ie_get_next(tmp); } - + return ie_prev; } @@ -289,9 +289,9 @@ void ntfs_ie_filename_dump(INDEX_ENTRY *ie) void ntfs_ih_filename_dump(INDEX_HEADER *ih) { INDEX_ENTRY *ie; - + ntfs_log_trace("Entering\n"); - + ie = ntfs_ie_get_first(ih); while (!ntfs_ie_end(ie)) { ntfs_ie_filename_dump(ie); @@ -304,9 +304,9 @@ static int ntfs_ih_numof_entries(INDEX_HEADER *ih) int n; INDEX_ENTRY *ie; u8 *end; - + ntfs_log_trace("Entering\n"); - + end = ntfs_ie_get_end(ih); ie = ntfs_ie_get_first(ih); for (n = 0; !ntfs_ie_end(ie) && (u8 *)ie < end; n++) @@ -327,9 +327,9 @@ static int ntfs_ih_zero_entry(INDEX_HEADER *ih) static void ntfs_ie_delete(INDEX_HEADER *ih, INDEX_ENTRY *ie) { u32 new_size; - + ntfs_log_trace("Entering\n"); - + new_size = le32_to_cpu(ih->index_length) - le16_to_cpu(ie->length); ih->index_length = cpu_to_le32(new_size); memmove(ie, (u8 *)ie + le16_to_cpu(ie->length), @@ -347,9 +347,9 @@ static void ntfs_ie_set_vcn(INDEX_ENTRY *ie, VCN vcn) static void ntfs_ie_insert(INDEX_HEADER *ih, INDEX_ENTRY *ie, INDEX_ENTRY *pos) { int ie_size = le16_to_cpu(ie->length); - + ntfs_log_trace("Entering\n"); - + ih->index_length = cpu_to_le32(le32_to_cpu(ih->index_length) + ie_size); memmove((u8 *)pos + ie_size, pos, le32_to_cpu(ih->index_length) - ((u8 *)pos - (u8 *)ih) - ie_size); @@ -359,13 +359,13 @@ static void ntfs_ie_insert(INDEX_HEADER *ih, INDEX_ENTRY *ie, INDEX_ENTRY *pos) static INDEX_ENTRY *ntfs_ie_dup(INDEX_ENTRY *ie) { INDEX_ENTRY *dup; - + ntfs_log_trace("Entering\n"); - + dup = ntfs_malloc(le16_to_cpu(ie->length)); if (dup) memcpy(dup, ie, le16_to_cpu(ie->length)); - + return dup; } @@ -373,12 +373,12 @@ static INDEX_ENTRY *ntfs_ie_dup_novcn(INDEX_ENTRY *ie) { INDEX_ENTRY *dup; int size = le16_to_cpu(ie->length); - + ntfs_log_trace("Entering\n"); - + if (ie->ie_flags & INDEX_ENTRY_NODE) size -= sizeof(VCN); - + dup = ntfs_malloc(size); if (dup) { memcpy(dup, ie, size); @@ -391,19 +391,19 @@ static INDEX_ENTRY *ntfs_ie_dup_novcn(INDEX_ENTRY *ie) static int ntfs_ia_check(ntfs_index_context *icx, INDEX_BLOCK *ib, VCN vcn) { u32 ib_size = (unsigned)le32_to_cpu(ib->index.allocated_size) + 0x18; - + ntfs_log_trace("Entering\n"); - + if (!ntfs_is_indx_record(ib->magic)) { - + ntfs_log_error("Corrupt index block signature: vcn %lld inode " "%llu\n", (long long)vcn, (unsigned long long)icx->ni->mft_no); return -1; } - + if (sle64_to_cpu(ib->index_block_vcn) != vcn) { - + ntfs_log_error("Corrupt index block: VCN (%lld) is different " "from expected VCN (%lld) in inode %llu\n", (long long)sle64_to_cpu(ib->index_block_vcn), @@ -411,14 +411,14 @@ static int ntfs_ia_check(ntfs_index_context *icx, INDEX_BLOCK *ib, VCN vcn) (unsigned long long)icx->ni->mft_no); return -1; } - + if (ib_size != icx->block_size) { - + ntfs_log_error("Corrupt index block : VCN (%lld) of inode %llu " "has a size (%u) differing from the index " - "specified size (%u)\n", (long long)vcn, - (unsigned long long)icx->ni->mft_no, ib_size, - icx->block_size); + "specified size (%u)\n", (long long)vcn, + (unsigned long long)icx->ni->mft_no, (unsigned int) ib_size, + (unsigned int) icx->block_size); return -1; } return 0; @@ -431,24 +431,24 @@ static INDEX_ROOT *ntfs_ir_lookup(ntfs_inode *ni, ntfschar *name, INDEX_ROOT *ir = NULL; ntfs_log_trace("Entering\n"); - + *ctx = ntfs_attr_get_search_ctx(ni, NULL); if (!*ctx) return NULL; - - if (ntfs_attr_lookup(AT_INDEX_ROOT, name, name_len, CASE_SENSITIVE, + + if (ntfs_attr_lookup(AT_INDEX_ROOT, name, name_len, CASE_SENSITIVE, 0, NULL, 0, *ctx)) { ntfs_log_perror("Failed to lookup $INDEX_ROOT"); goto err_out; } - + a = (*ctx)->attr; if (a->non_resident) { errno = EINVAL; ntfs_log_perror("Non-resident $INDEX_ROOT detected"); goto err_out; } - + ir = (INDEX_ROOT *)((char *)a + le16_to_cpu(a->value_offset)); err_out: if (!ir) { @@ -469,11 +469,11 @@ static INDEX_ROOT *ntfs_ir_lookup2(ntfs_inode *ni, ntfschar *name, u32 len) return ir; } -/** +/** * Find a key in the index block. - * + * * Return values: - * STATUS_OK with errno set to ESUCCESS if we know for sure that the + * STATUS_OK with errno set to ESUCCESS if we know for sure that the * entry exists and @ie_out points to this entry. * STATUS_NOT_FOUND with errno set to ENOENT if we know for sure the * entry doesn't exist and @ie_out is the insertion point. @@ -488,11 +488,11 @@ static int ntfs_ie_lookup(const void *key, const int key_len, INDEX_ENTRY *ie; u8 *index_end; int rc, item = 0; - + ntfs_log_trace("Entering\n"); - + index_end = ntfs_ie_get_end(ih); - + /* * Loop until we exceed valid memory (corruption case) or until we * reach the last entry. @@ -537,14 +537,14 @@ static int ntfs_ie_lookup(const void *key, const int key_len, */ if (rc == -1) break; - + if (!rc) { *ie_out = ie; errno = 0; icx->parent_pos[icx->pindex] = item; return STATUS_OK; } - + item++; } /* @@ -558,7 +558,7 @@ static int ntfs_ie_lookup(const void *key, const int key_len, errno = ENOENT; return STATUS_NOT_FOUND; } - + /* Get the starting vcn of the index_block holding the child node. */ *vcn = ntfs_ie_get_vcn(ie); if (*vcn < 0) { @@ -570,21 +570,21 @@ static int ntfs_ie_lookup(const void *key, const int key_len, ntfs_log_trace("Parent entry number %d\n", item); icx->parent_pos[icx->pindex] = item; - + return STATUS_KEEP_SEARCHING; } static ntfs_attr *ntfs_ia_open(ntfs_index_context *icx, ntfs_inode *ni) { ntfs_attr *na; - + na = ntfs_attr_open(ni, AT_INDEX_ALLOCATION, icx->name, icx->name_len); if (!na) { ntfs_log_perror("Failed to open index allocation of inode " "%llu", (unsigned long long)ni->mft_no); return NULL; } - + return na; } @@ -593,22 +593,22 @@ static int ntfs_ib_read(ntfs_index_context *icx, VCN vcn, INDEX_BLOCK *dst) s64 pos, ret; ntfs_log_trace("vcn: %lld\n", (long long)vcn); - + pos = ntfs_ib_vcn_to_pos(icx, vcn); ret = ntfs_attr_mst_pread(icx->ia_na, pos, 1, icx->block_size, (u8 *)dst); if (ret != 1) { if (ret == -1) ntfs_log_perror("Failed to read index block"); - else + else ntfs_log_error("Failed to read full index block at " "%lld\n", (long long)pos); return -1; } - + if (ntfs_ia_check(icx, dst, vcn)) return -1; - + return 0; } @@ -633,7 +633,7 @@ static int ntfs_icx_parent_dec(ntfs_index_context *icx) } return STATUS_OK; } - + /** * ntfs_index_lookup - find a key in an index and return its index entry * @key: [IN] key for which to search in the index @@ -676,7 +676,7 @@ int ntfs_index_lookup(const void *key, const int key_len, ntfs_index_context *ic int ret, err = 0; ntfs_log_trace("Entering\n"); - + if (!key || key_len <= 0) { errno = EINVAL; ntfs_log_perror("key: %p key_len: %d", key, key_len); @@ -689,12 +689,12 @@ int ntfs_index_lookup(const void *key, const int key_len, ntfs_index_context *ic errno = EIO; return -1; } - + icx->block_size = le32_to_cpu(ir->index_block_size); if (icx->block_size < NTFS_BLOCK_SIZE) { errno = EINVAL; ntfs_log_perror("Index block size (%d) is smaller than the " - "sector size (%d)", icx->block_size, NTFS_BLOCK_SIZE); + "sector size (%d)", (int) icx->block_size, NTFS_BLOCK_SIZE); goto err_out; } @@ -706,13 +706,13 @@ int ntfs_index_lookup(const void *key, const int key_len, ntfs_index_context *ic icx->collate = ntfs_get_collate_function(ir->collation_rule); if (!icx->collate) { err = errno = EOPNOTSUPP; - ntfs_log_perror("Unknown collation rule 0x%x", + ntfs_log_perror("Unknown collation rule 0x%x", (unsigned)le32_to_cpu(ir->collation_rule)); goto err_out; } - + old_vcn = VCN_INDEX_ROOT_PARENT; - /* + /* * FIXME: check for both ir and ib that the first index entry is * within the index block. */ @@ -721,9 +721,9 @@ int ntfs_index_lookup(const void *key, const int key_len, ntfs_index_context *ic err = errno; goto err_out; } - + icx->ir = ir; - + if (ret != STATUS_KEEP_SEARCHING) { /* STATUS_OK or STATUS_NOT_FOUND */ err = errno; @@ -731,19 +731,19 @@ int ntfs_index_lookup(const void *key, const int key_len, ntfs_index_context *ic icx->parent_vcn[icx->pindex] = old_vcn; goto done; } - + /* Child node present, descend into it. */ - + icx->ia_na = ntfs_ia_open(icx, ni); if (!icx->ia_na) goto err_out; - + ib = ntfs_malloc(icx->block_size); if (!ib) { err = errno; goto err_out; } - + descend_into_child_node: icx->parent_vcn[icx->pindex] = old_vcn; @@ -754,16 +754,16 @@ descend_into_child_node: old_vcn = vcn; ntfs_log_debug("Descend into node with VCN %lld\n", (long long)vcn); - + if (ntfs_ib_read(icx, vcn, ib)) goto err_out; - + ret = ntfs_ie_lookup(key, key_len, icx, &ib->index, &vcn, &ie); if (ret != STATUS_KEEP_SEARCHING) { err = errno; if (ret == STATUS_ERROR) goto err_out; - + /* STATUS_OK or STATUS_NOT_FOUND */ icx->is_in_root = FALSE; icx->ib = ib; @@ -777,7 +777,7 @@ descend_into_child_node: (unsigned long long)ni->mft_no); goto err_out; } - + goto descend_into_child_node; err_out: free(ib); @@ -798,38 +798,38 @@ done: } -static INDEX_BLOCK *ntfs_ib_alloc(VCN ib_vcn, u32 ib_size, +static INDEX_BLOCK *ntfs_ib_alloc(VCN ib_vcn, u32 ib_size, INDEX_HEADER_FLAGS node_type) { INDEX_BLOCK *ib; int ih_size = sizeof(INDEX_HEADER); - + ntfs_log_trace("ib_vcn: %lld ib_size: %u\n", (long long)ib_vcn, ib_size); - + ib = ntfs_calloc(ib_size); if (!ib) return NULL; - + ib->magic = magic_INDX; ib->usa_ofs = cpu_to_le16(sizeof(INDEX_BLOCK)); ib->usa_count = cpu_to_le16(ib_size / NTFS_BLOCK_SIZE + 1); /* Set USN to 1 */ *(u16 *)((char *)ib + le16_to_cpu(ib->usa_ofs)) = cpu_to_le16(1); ib->lsn = cpu_to_le64(0); - + ib->index_block_vcn = cpu_to_sle64(ib_vcn); - + ib->index.entries_offset = cpu_to_le32((ih_size + le16_to_cpu(ib->usa_count) * 2 + 7) & ~7); ib->index.index_length = 0; - ib->index.allocated_size = cpu_to_le32(ib_size - + ib->index.allocated_size = cpu_to_le32(ib_size - (sizeof(INDEX_BLOCK) - ih_size)); ib->index.ih_flags = node_type; - - return ib; -} -/** + return ib; +} + +/** * Find the median by going through all the entries */ static INDEX_ENTRY *ntfs_ie_get_median(INDEX_HEADER *ih) @@ -837,12 +837,12 @@ static INDEX_ENTRY *ntfs_ie_get_median(INDEX_HEADER *ih) INDEX_ENTRY *ie, *ie_start; u8 *ie_end; int i = 0, median; - + ntfs_log_trace("Entering\n"); - + ie = ie_start = ntfs_ie_get_first(ih); ie_end = (u8 *)ntfs_ie_get_end(ih); - + while ((u8 *)ie < ie_end && !ntfs_ie_end(ie)) { ie = ntfs_ie_get_next(ie); i++; @@ -851,12 +851,12 @@ static INDEX_ENTRY *ntfs_ie_get_median(INDEX_HEADER *ih) * NOTE: this could be also the entry at the half of the index block. */ median = i / 2 - 1; - + ntfs_log_trace("Entries: %d median: %d\n", i, median); - + for (i = 0, ie = ie_start; i <= median; i++) ie = ntfs_ie_get_next(ie); - + return ie; } @@ -875,7 +875,7 @@ static int ntfs_ibm_add(ntfs_index_context *icx) u8 bmp[8]; ntfs_log_trace("Entering\n"); - + if (ntfs_attr_exist(icx->ni, AT_BITMAP, icx->name, icx->name_len)) return STATUS_OK; /* @@ -887,7 +887,7 @@ static int ntfs_ibm_add(ntfs_index_context *icx) ntfs_log_perror("Failed to add AT_BITMAP"); return STATUS_ERROR; } - + return STATUS_OK; } @@ -901,7 +901,7 @@ static int ntfs_ibm_modify(ntfs_index_context *icx, VCN vcn, int set) int ret = STATUS_ERROR; ntfs_log_trace("%s vcn: %lld\n", set ? "set" : "clear", (long long)vcn); - + na = ntfs_attr_open(icx->ni, AT_BITMAP, icx->name, icx->name_len); if (!na) { ntfs_log_perror("Failed to open $BITMAP attribute"); @@ -916,17 +916,17 @@ static int ntfs_ibm_modify(ntfs_index_context *icx, VCN vcn, int set) } } } - + if (ntfs_attr_pread(na, bpos, 1, &byte) != 1) { ntfs_log_perror("Failed to read $BITMAP"); goto err_na; } - if (set) + if (set) byte |= bit; else byte &= ~bit; - + if (ntfs_attr_pwrite(na, bpos, 1, &byte) != 1) { ntfs_log_perror("Failed to write $Bitmap"); goto err_na; @@ -956,17 +956,17 @@ static VCN ntfs_ibm_get_free(ntfs_index_context *icx) s64 vcn, byte, size; ntfs_log_trace("Entering\n"); - + bm = ntfs_attr_readall(icx->ni, AT_BITMAP, icx->name, icx->name_len, &size); if (!bm) return (VCN)-1; - + for (byte = 0; byte < size; byte++) { - + if (bm[byte] == 255) continue; - + for (bit = 0; bit < 8; bit++) { if (!(bm[byte] & (1 << bit))) { vcn = ntfs_ibm_pos_to_vcn(icx, byte * 8 + bit); @@ -974,14 +974,14 @@ static VCN ntfs_ibm_get_free(ntfs_index_context *icx) } } } - + vcn = ntfs_ibm_pos_to_vcn(icx, size * 8); -out: +out: ntfs_log_trace("allocated vcn: %lld\n", (long long)vcn); if (ntfs_ibm_set(icx, vcn)) vcn = (VCN)-1; - + free(bm); return vcn; } @@ -992,23 +992,23 @@ static INDEX_BLOCK *ntfs_ir_to_ib(INDEX_ROOT *ir, VCN ib_vcn) INDEX_ENTRY *ie_last; char *ies_start, *ies_end; int i; - + ntfs_log_trace("Entering\n"); - + ib = ntfs_ib_alloc(ib_vcn, le32_to_cpu(ir->index_block_size), LEAF_NODE); if (!ib) return NULL; - + ies_start = (char *)ntfs_ie_get_first(&ir->index); ies_end = (char *)ntfs_ie_get_end(&ir->index); ie_last = ntfs_ie_get_last((INDEX_ENTRY *)ies_start, ies_end); - /* + /* * Copy all entries, including the termination entry * as well, which can never have any data. */ i = (char *)ie_last - ies_start + le16_to_cpu(ie_last->length); memcpy(ntfs_ie_get_first(&ib->index), ies_start, i); - + ib->index.ih_flags = ir->index.ih_flags; ib->index.index_length = cpu_to_le32(i + le32_to_cpu(ib->index.entries_offset)); @@ -1019,7 +1019,7 @@ static void ntfs_ir_nill(INDEX_ROOT *ir) { INDEX_ENTRY *ie_last; char *ies_start, *ies_end; - + ntfs_log_trace("Entering\n"); /* * TODO: This function could be much simpler. @@ -1027,7 +1027,7 @@ static void ntfs_ir_nill(INDEX_ROOT *ir) ies_start = (char *)ntfs_ie_get_first(&ir->index); ies_end = (char *)ntfs_ie_get_end(&ir->index); ie_last = ntfs_ie_get_last((INDEX_ENTRY *)ies_start, ies_end); - /* + /* * Move the index root termination entry forward */ if ((char *)ie_last > ies_start) { @@ -1043,21 +1043,21 @@ static int ntfs_ib_copy_tail(ntfs_index_context *icx, INDEX_BLOCK *src, INDEX_ENTRY *ie_head; /* first entry after the median */ int tail_size, ret; INDEX_BLOCK *dst; - + ntfs_log_trace("Entering\n"); - - dst = ntfs_ib_alloc(new_vcn, icx->block_size, + + dst = ntfs_ib_alloc(new_vcn, icx->block_size, src->index.ih_flags & NODE_MASK); if (!dst) return STATUS_ERROR; - + ie_head = ntfs_ie_get_next(median); - + ies_end = (u8 *)ntfs_ie_get_end(&src->index); tail_size = ies_end - (u8 *)ie_head; memcpy(ntfs_ie_get_first(&dst->index), ie_head, tail_size); - - dst->index.index_length = cpu_to_le32(tail_size + + + dst->index.index_length = cpu_to_le32(tail_size + le32_to_cpu(dst->index.entries_offset)); ret = ntfs_ib_write(icx, dst); @@ -1070,43 +1070,43 @@ static int ntfs_ib_cut_tail(ntfs_index_context *icx, INDEX_BLOCK *ib, { char *ies_start, *ies_end; INDEX_ENTRY *ie_last; - + ntfs_log_trace("Entering\n"); - + ies_start = (char *)ntfs_ie_get_first(&ib->index); ies_end = (char *)ntfs_ie_get_end(&ib->index); - + ie_last = ntfs_ie_get_last((INDEX_ENTRY *)ies_start, ies_end); if (ie_last->ie_flags & INDEX_ENTRY_NODE) ntfs_ie_set_vcn(ie_last, ntfs_ie_get_vcn(ie)); - + memcpy(ie, ie_last, le16_to_cpu(ie_last->length)); - - ib->index.index_length = cpu_to_le32(((char *)ie - ies_start) + + + ib->index.index_length = cpu_to_le32(((char *)ie - ies_start) + le16_to_cpu(ie->length) + le32_to_cpu(ib->index.entries_offset)); - + if (ntfs_ib_write(icx, ib)) return STATUS_ERROR; - + return STATUS_OK; } - + static int ntfs_ia_add(ntfs_index_context *icx) { ntfs_log_trace("Entering\n"); if (ntfs_ibm_add(icx)) return -1; - + if (!ntfs_attr_exist(icx->ni, AT_INDEX_ALLOCATION, icx->name, icx->name_len)) { - + if (ntfs_attr_add(icx->ni, AT_INDEX_ALLOCATION, icx->name, icx->name_len, NULL, 0)) { ntfs_log_perror("Failed to add AT_INDEX_ALLOCATION"); return -1; } } - + icx->ia_na = ntfs_ia_open(icx, icx->ni); if (!icx->ia_na) return -1; @@ -1125,43 +1125,43 @@ static int ntfs_ir_reparent(ntfs_index_context *icx) int ret = STATUS_ERROR; ntfs_log_trace("Entering\n"); - + ir = ntfs_ir_lookup2(icx->ni, icx->name, icx->name_len); if (!ir) goto out; - + if ((ir->index.ih_flags & NODE_MASK) == SMALL_INDEX) if (ntfs_ia_add(icx)) goto out; - + new_ib_vcn = ntfs_ibm_get_free(icx); if (new_ib_vcn == -1) goto out; - + ir = ntfs_ir_lookup2(icx->ni, icx->name, icx->name_len); if (!ir) goto clear_bmp; - + ib = ntfs_ir_to_ib(ir, new_ib_vcn); if (ib == NULL) { ntfs_log_perror("Failed to move index root to index block"); goto clear_bmp; } - + if (ntfs_ib_write(icx, ib)) goto clear_bmp; - + retry : ir = ntfs_ir_lookup(icx->ni, icx->name, icx->name_len, &ctx); if (!ir) goto clear_bmp; - + ntfs_ir_nill(ir); - + ie = ntfs_ie_get_first(&ir->index); ie->ie_flags |= INDEX_ENTRY_NODE; ie->length = cpu_to_le16(sizeof(INDEX_ENTRY_HEADER) + sizeof(VCN)); - + ir->index.ih_flags = LARGE_INDEX; ir->index.index_length = cpu_to_le32(le32_to_cpu(ir->index.entries_offset) + le16_to_cpu(ie->length)); @@ -1197,7 +1197,7 @@ retry : * so in error case we wouldn't lose the IB. */ ntfs_ie_set_vcn(ie, new_ib_vcn); - + ret = STATUS_OK; err_out: free(ib); @@ -1211,56 +1211,56 @@ clear_bmp: /** * ntfs_ir_truncate - Truncate index root attribute - * + * * Returns STATUS_OK, STATUS_RESIDENT_ATTRIBUTE_FILLED_MFT or STATUS_ERROR. */ static int ntfs_ir_truncate(ntfs_index_context *icx, int data_size) -{ +{ ntfs_attr *na; int ret; ntfs_log_trace("Entering\n"); - + na = ntfs_attr_open(icx->ni, AT_INDEX_ROOT, icx->name, icx->name_len); if (!na) { ntfs_log_perror("Failed to open INDEX_ROOT"); return STATUS_ERROR; } /* - * INDEX_ROOT must be resident and its entries can be moved to + * INDEX_ROOT must be resident and its entries can be moved to * INDEX_BLOCK, so ENOSPC isn't a real error. */ ret = ntfs_attr_truncate(na, data_size + offsetof(INDEX_ROOT, index)); if (ret == STATUS_OK) { - + icx->ir = ntfs_ir_lookup2(icx->ni, icx->name, icx->name_len); if (!icx->ir) return STATUS_ERROR; - + icx->ir->index.allocated_size = cpu_to_le32(data_size); - + } else if (ret == STATUS_ERROR) ntfs_log_perror("Failed to truncate INDEX_ROOT"); - + ntfs_attr_close(na); return ret; } - + /** * ntfs_ir_make_space - Make more space for the index root attribute - * + * * On success return STATUS_OK or STATUS_KEEP_SEARCHING. * On error return STATUS_ERROR. */ static int ntfs_ir_make_space(ntfs_index_context *icx, int data_size) -{ +{ int ret; ntfs_log_trace("Entering\n"); ret = ntfs_ir_truncate(icx, data_size); if (ret == STATUS_RESIDENT_ATTRIBUTE_FILLED_MFT) { - + ret = ntfs_ir_reparent(icx); if (ret == STATUS_OK) ret = STATUS_KEEP_SEARCHING; @@ -1277,31 +1277,31 @@ static int ntfs_ir_make_space(ntfs_index_context *icx, int data_size) static int ntfs_ie_add_vcn(INDEX_ENTRY **ie) { INDEX_ENTRY *p, *old = *ie; - + old->length = cpu_to_le16(le16_to_cpu(old->length) + sizeof(VCN)); p = realloc(old, le16_to_cpu(old->length)); if (!p) return STATUS_ERROR; - + p->ie_flags |= INDEX_ENTRY_NODE; *ie = p; return STATUS_OK; } -static int ntfs_ih_insert(INDEX_HEADER *ih, INDEX_ENTRY *orig_ie, VCN new_vcn, +static int ntfs_ih_insert(INDEX_HEADER *ih, INDEX_ENTRY *orig_ie, VCN new_vcn, int pos) { INDEX_ENTRY *ie_node, *ie; int ret = STATUS_ERROR; VCN old_vcn; - + ntfs_log_trace("Entering\n"); - + ie = ntfs_ie_dup(orig_ie); if (!ie) return STATUS_ERROR; - + if (!(ie->ie_flags & INDEX_ENTRY_NODE)) if (ntfs_ie_add_vcn(&ie)) goto out; @@ -1309,13 +1309,13 @@ static int ntfs_ih_insert(INDEX_HEADER *ih, INDEX_ENTRY *orig_ie, VCN new_vcn, ie_node = ntfs_ie_get_by_pos(ih, pos); old_vcn = ntfs_ie_get_vcn(ie_node); ntfs_ie_set_vcn(ie_node, new_vcn); - + ntfs_ie_insert(ih, ie, ie_node); ntfs_ie_set_vcn(ie_node, old_vcn); ret = STATUS_OK; -out: +out: free(ie); - + return ret; } @@ -1335,14 +1335,14 @@ static int ntfs_ir_insert_median(ntfs_index_context *icx, INDEX_ENTRY *median, { u32 new_size; int ret; - + ntfs_log_trace("Entering\n"); - + icx->ir = ntfs_ir_lookup2(icx->ni, icx->name, icx->name_len); if (!icx->ir) return STATUS_ERROR; - new_size = le32_to_cpu(icx->ir->index.index_length) + + new_size = le32_to_cpu(icx->ir->index.index_length) + le16_to_cpu(median->length); if (!(median->ie_flags & INDEX_ENTRY_NODE)) new_size += sizeof(VCN); @@ -1350,12 +1350,12 @@ static int ntfs_ir_insert_median(ntfs_index_context *icx, INDEX_ENTRY *median, ret = ntfs_ir_make_space(icx, new_size); if (ret != STATUS_OK) return ret; - + icx->ir = ntfs_ir_lookup2(icx->ni, icx->name, icx->name_len); if (!icx->ir) return STATUS_ERROR; - return ntfs_ih_insert(&icx->ir->index, median, new_vcn, + return ntfs_ih_insert(&icx->ir->index, median, new_vcn, ntfs_icx_parent_pos(icx)); } @@ -1366,20 +1366,20 @@ static int ntfs_ib_split(ntfs_index_context *icx, INDEX_BLOCK *ib); * On error return STATUS_ERROR. */ static int ntfs_ib_insert(ntfs_index_context *icx, INDEX_ENTRY *ie, VCN new_vcn) -{ +{ INDEX_BLOCK *ib; u32 idx_size, allocated_size; int err = STATUS_ERROR; VCN old_vcn; ntfs_log_trace("Entering\n"); - + ib = ntfs_malloc(icx->block_size); if (!ib) return -1; - + old_vcn = ntfs_icx_parent_vcn(icx); - + if (ntfs_ib_read(icx, old_vcn, ib)) goto err_out; @@ -1392,58 +1392,58 @@ static int ntfs_ib_insert(ntfs_index_context *icx, INDEX_ENTRY *ie, VCN new_vcn) err = STATUS_KEEP_SEARCHING; goto err_out; } - + if (ntfs_ih_insert(&ib->index, ie, new_vcn, ntfs_icx_parent_pos(icx))) goto err_out; - + if (ntfs_ib_write(icx, ib)) goto err_out; - + err = STATUS_OK; -err_out: +err_out: free(ib); return err; } /** * ntfs_ib_split - Split an index block - * + * * On success return STATUS_OK or STATUS_KEEP_SEARCHING. * On error return is STATUS_ERROR. */ static int ntfs_ib_split(ntfs_index_context *icx, INDEX_BLOCK *ib) -{ +{ INDEX_ENTRY *median; VCN new_vcn; int ret; ntfs_log_trace("Entering\n"); - + if (ntfs_icx_parent_dec(icx)) return STATUS_ERROR; - + median = ntfs_ie_get_median(&ib->index); new_vcn = ntfs_ibm_get_free(icx); if (new_vcn == -1) return STATUS_ERROR; - + if (ntfs_ib_copy_tail(icx, ib, median, new_vcn)) { ntfs_ibm_clear(icx, new_vcn); return STATUS_ERROR; } - + if (ntfs_icx_parent_vcn(icx) == VCN_INDEX_ROOT_PARENT) ret = ntfs_ir_insert_median(icx, median, new_vcn); else ret = ntfs_ib_insert(icx, median, new_vcn); - + if (ret != STATUS_OK) { ntfs_ibm_clear(icx, new_vcn); return ret; } - + ret = ntfs_ib_cut_tail(icx, ib, median); - + return ret; } @@ -1453,7 +1453,7 @@ int ntfs_ie_add(ntfs_index_context *icx, INDEX_ENTRY *ie) INDEX_HEADER *ih; int allocated_size, new_size; int ret = STATUS_ERROR; - + #ifdef DEBUG /* removed by JPA to make function usable for security indexes char *fn; @@ -1462,9 +1462,9 @@ int ntfs_ie_add(ntfs_index_context *icx, INDEX_ENTRY *ie) ntfs_attr_name_free(&fn); */ #endif - + while (1) { - + if (!ntfs_index_lookup(&ie->key, le16_to_cpu(ie->key_length), icx)) { errno = EEXIST; ntfs_log_perror("Index already have such entry"); @@ -1474,21 +1474,21 @@ int ntfs_ie_add(ntfs_index_context *icx, INDEX_ENTRY *ie) ntfs_log_perror("Failed to find place for new entry"); goto err_out; } - + if (icx->is_in_root) ih = &icx->ir->index; else ih = &icx->ib->index; - + allocated_size = le32_to_cpu(ih->allocated_size); new_size = le32_to_cpu(ih->index_length) + le16_to_cpu(ie->length); - + if (new_size <= allocated_size) break; - + ntfs_log_trace("index block sizes: allocated: %d needed: %d\n", allocated_size, new_size); - + if (icx->is_in_root) { if (ntfs_ir_make_space(icx, new_size) == STATUS_ERROR) goto err_out; @@ -1496,14 +1496,14 @@ int ntfs_ie_add(ntfs_index_context *icx, INDEX_ENTRY *ie) if (ntfs_ib_split(icx, icx->ib) == STATUS_ERROR) goto err_out; } - + ntfs_inode_mark_dirty(icx->actx->ntfs_ino); ntfs_index_ctx_reinit(icx); } - + ntfs_ie_insert(ih, ie, icx->entry); ntfs_index_entry_mark_dirty(icx); - + ret = STATUS_OK; err_out: ntfs_log_trace("%s\n", ret ? "Failed" : "Done"); @@ -1525,17 +1525,17 @@ int ntfs_index_add_filename(ntfs_inode *ni, FILE_NAME_ATTR *fn, MFT_REF mref) int fn_size, ie_size, err, ret = -1; ntfs_log_trace("Entering\n"); - + if (!ni || !fn) { ntfs_log_error("Invalid arguments.\n"); errno = EINVAL; return -1; } - + fn_size = (fn->file_name_length * sizeof(ntfschar)) + sizeof(FILE_NAME_ATTR); ie_size = (sizeof(INDEX_ENTRY_HEADER) + fn_size + 7) & ~7; - + ie = ntfs_calloc(ie_size); if (!ie) return -1; @@ -1544,11 +1544,11 @@ int ntfs_index_add_filename(ntfs_inode *ni, FILE_NAME_ATTR *fn, MFT_REF mref) ie->length = cpu_to_le16(ie_size); ie->key_length = cpu_to_le16(fn_size); memcpy(&ie->key, fn, fn_size); - + icx = ntfs_index_ctx_get(ni, NTFS_INDEX_I30, 4); if (!icx) goto out; - + ret = ntfs_ie_add(icx, ie); err = errno; ntfs_index_ctx_put(icx); @@ -1563,9 +1563,9 @@ static int ntfs_ih_takeout(ntfs_index_context *icx, INDEX_HEADER *ih, { INDEX_ENTRY *ie_roam; int ret = STATUS_ERROR; - + ntfs_log_trace("Entering\n"); - + ie_roam = ntfs_ie_dup_novcn(ie); if (!ie_roam) return STATUS_ERROR; @@ -1577,7 +1577,7 @@ static int ntfs_ih_takeout(ntfs_index_context *icx, INDEX_HEADER *ih, else if (ntfs_ib_write(icx, ib)) goto out; - + ntfs_index_ctx_reinit(icx); ret = ntfs_ie_add(icx, ie_roam); @@ -1593,36 +1593,36 @@ out: static void ntfs_ir_leafify(ntfs_index_context *icx, INDEX_HEADER *ih) { INDEX_ENTRY *ie; - + ntfs_log_trace("Entering\n"); - + ie = ntfs_ie_get_first(ih); ie->ie_flags &= ~INDEX_ENTRY_NODE; ie->length = cpu_to_le16(le16_to_cpu(ie->length) - sizeof(VCN)); - + ih->index_length = cpu_to_le32(le32_to_cpu(ih->index_length) - sizeof(VCN)); ih->ih_flags &= ~LARGE_INDEX; - + /* Not fatal error */ ntfs_ir_truncate(icx, le32_to_cpu(ih->index_length)); } /** - * Used if an empty index block to be deleted has END entry as the parent + * Used if an empty index block to be deleted has END entry as the parent * in the INDEX_ROOT which is not the only one there. */ static int ntfs_ih_reparent_end(ntfs_index_context *icx, INDEX_HEADER *ih, INDEX_BLOCK *ib) { INDEX_ENTRY *ie, *ie_prev; - + ntfs_log_trace("Entering\n"); - + ie = ntfs_ie_get_by_pos(ih, ntfs_icx_parent_pos(icx)); ie_prev = ntfs_ie_prev(ih, ie); - + ntfs_ie_set_vcn(ie, ntfs_ie_get_vcn(ie_prev)); - + return ntfs_ih_takeout(icx, ih, ie_prev, ib); } @@ -1632,48 +1632,48 @@ static int ntfs_index_rm_leaf(ntfs_index_context *icx) INDEX_HEADER *parent_ih; INDEX_ENTRY *ie; int ret = STATUS_ERROR; - + ntfs_log_trace("pindex: %d\n", icx->pindex); - + if (ntfs_icx_parent_dec(icx)) return STATUS_ERROR; if (ntfs_ibm_clear(icx, icx->parent_vcn[icx->pindex + 1])) return STATUS_ERROR; - + if (ntfs_icx_parent_vcn(icx) == VCN_INDEX_ROOT_PARENT) parent_ih = &icx->ir->index; else { ib = ntfs_malloc(icx->block_size); if (!ib) return STATUS_ERROR; - + if (ntfs_ib_read(icx, ntfs_icx_parent_vcn(icx), ib)) goto out; - + parent_ih = &ib->index; } - + ie = ntfs_ie_get_by_pos(parent_ih, ntfs_icx_parent_pos(icx)); if (!ntfs_ie_end(ie)) { ret = ntfs_ih_takeout(icx, parent_ih, ie, ib); goto out; } - + if (ntfs_ih_zero_entry(parent_ih)) { - + if (ntfs_icx_parent_vcn(icx) == VCN_INDEX_ROOT_PARENT) { ntfs_ir_leafify(icx, parent_ih); goto ok; } - + ret = ntfs_index_rm_leaf(icx); goto out; } - + if (ntfs_ih_reparent_end(icx, parent_ih, ib)) goto out; -ok: +ok: ret = STATUS_OK; out: free(ib); @@ -1691,7 +1691,7 @@ static int ntfs_index_rm_node(ntfs_index_context *icx) int delta, ret = STATUS_ERROR; ntfs_log_trace("Entering\n"); - + if (!icx->ia_na) { icx->ia_na = ntfs_ia_open(icx, icx->ni); if (!icx->ia_na) @@ -1701,7 +1701,7 @@ static int ntfs_index_rm_node(ntfs_index_context *icx) ib = ntfs_malloc(icx->block_size); if (!ib) return STATUS_ERROR; - + ie_succ = ntfs_ie_get_next(icx->entry); entry_pos = icx->parent_pos[icx->pindex]++; pindex = icx->pindex; @@ -1709,12 +1709,12 @@ descend: vcn = ntfs_ie_get_vcn(ie_succ); if (ntfs_ib_read(icx, vcn, ib)) goto out; - + ie_succ = ntfs_ie_get_first(&ib->index); if (ntfs_icx_parent_inc(icx)) goto out; - + icx->parent_vcn[icx->pindex] = vcn; icx->parent_pos[icx->pindex] = 0; @@ -1730,7 +1730,7 @@ descend: ie = ntfs_ie_dup(ie_succ); if (!ie) goto out; - + if (ntfs_ie_add_vcn(&ie)) goto out2; @@ -1748,10 +1748,10 @@ descend: ret = ntfs_ir_make_space(icx, new_size); if (ret != STATUS_OK) goto out2; - + ih = &icx->ir->index; entry = ntfs_ie_get_by_pos(ih, entry_pos); - + } else if (new_size > le32_to_cpu(ih->allocated_size)) { icx->pindex = pindex; ret = ntfs_ib_split(icx, icx->ib); @@ -1763,20 +1763,20 @@ descend: ntfs_ie_delete(ih, entry); ntfs_ie_insert(ih, ie, entry); - + if (icx->is_in_root) { if (ntfs_ir_truncate(icx, new_size)) goto out2; } else if (ntfs_icx_ib_write(icx)) goto out2; - + ntfs_ie_delete(&ib->index, ie_succ); - + if (ntfs_ih_zero_entry(&ib->index)) { if (ntfs_index_rm_leaf(icx)) goto out2; - } else + } else if (ntfs_ib_write(icx, ib)) goto out2; @@ -1792,8 +1792,8 @@ out: * ntfs_index_rm - remove entry from the index * @icx: index context describing entry to delete * - * Delete entry described by @icx from the index. Index context is always - * reinitialized after use of this function, so it can be used for index + * Delete entry described by @icx from the index. Index context is always + * reinitialized after use of this function, so it can be used for index * lookup once again. * * Return 0 on success or -1 on error with errno set to the error code. @@ -1805,7 +1805,7 @@ int ntfs_index_rm(ntfs_index_context *icx) int err, ret = STATUS_OK; ntfs_log_trace("Entering\n"); - + if (!icx || (!icx->ib && !icx->ir) || ntfs_ie_end(icx->entry)) { ntfs_log_error("Invalid arguments.\n"); errno = EINVAL; @@ -1815,15 +1815,15 @@ int ntfs_index_rm(ntfs_index_context *icx) ih = &icx->ir->index; else ih = &icx->ib->index; - + if (icx->entry->ie_flags & INDEX_ENTRY_NODE) { - + ret = ntfs_index_rm_node(icx); } else if (icx->is_in_root || !ntfs_ih_one_entry(ih)) { - + ntfs_ie_delete(ih, icx->entry); - + if (icx->is_in_root) { err = ntfs_ir_truncate(icx, le32_to_cpu(ih->index_length)); if (err != STATUS_OK) @@ -1853,7 +1853,7 @@ int ntfs_index_remove(ntfs_inode *dir_ni, ntfs_inode *ni, return -1; while (1) { - + if (ntfs_index_lookup(key, keylen, icx)) goto err_out; @@ -1869,13 +1869,13 @@ int ntfs_index_remove(ntfs_inode *dir_ni, ntfs_inode *ni, goto err_out; else if (ret == STATUS_OK) break; - + ntfs_inode_mark_dirty(icx->actx->ntfs_ino); ntfs_index_ctx_reinit(icx); } ntfs_inode_mark_dirty(icx->actx->ntfs_ino); -out: +out: ntfs_index_ctx_put(icx); return ret; err_out: @@ -1887,7 +1887,7 @@ err_out: /** * ntfs_index_root_get - read the index root of an attribute * @ni: open ntfs inode in which the ntfs attribute resides - * @attr: attribute for which we want its index root + * @attr: attribute for which we want its index root * * This function will read the related index root an ntfs attribute. * @@ -1906,14 +1906,14 @@ INDEX_ROOT *ntfs_index_root_get(ntfs_inode *ni, ATTR_RECORD *attr) if (!ntfs_ir_lookup(ni, name, attr->name_length, &ctx)) return NULL; - + root = ntfs_malloc(sizeof(INDEX_ROOT)); if (!root) goto out; - + *root = *((INDEX_ROOT *)((u8 *)ctx->attr + le16_to_cpu(ctx->attr->value_offset))); -out: +out: ntfs_attr_put_search_ctx(ctx); return root; } @@ -1945,7 +1945,7 @@ static INDEX_ENTRY *ntfs_index_walk_down(INDEX_ENTRY *ie, } else { /* down from non-zero level */ - + ictx->pindex++; } ictx->parent_pos[ictx->pindex] = 0; diff --git a/source/inode.c b/source/inode.c index a4a0134..1341166 100644 --- a/source/inode.c +++ b/source/inode.c @@ -124,7 +124,7 @@ ntfs_inode *ntfs_inode_allocate(ntfs_volume *vol) static void __ntfs_inode_release(ntfs_inode *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); if (NInoAttrList(ni) && 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) { errno = EIO; 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)); goto put_err_out; } @@ -273,7 +273,7 @@ get_size: set_nino_flag(ni,KnownSize); } ntfs_attr_put_search_ctx(ctx); -out: +out: ntfs_log_leave("\n"); return ni; @@ -313,7 +313,7 @@ err_out: int ntfs_inode_real_close(ntfs_inode *ni) { int ret = -1; - + if (!ni) return 0; @@ -378,8 +378,8 @@ int ntfs_inode_real_close(ntfs_inode *ni) i = -1; break; } - - /* + + /* * We could successfully sync, so only log this error * 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", (long long)ni->mft_no); } - + __ntfs_inode_release(ni); ret = 0; err: @@ -585,11 +585,11 @@ ntfs_inode *ntfs_extent_inode_open(ntfs_inode *base_ni, const MFT_REF mref) ntfs_log_perror("%s", __FUNCTION__); return NULL; } - + ntfs_log_enter("Opening extent inode %lld (base mft record %lld).\n", (unsigned long long)mft_no, (unsigned long long)base_ni->mft_no); - + if (!base_ni->mft_no) { /* * 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) index_ni = dir_ni; else - index_ni = ntfs_inode_open(ni->vol, + index_ni = ntfs_inode_open(ni->vol, le64_to_cpu(fn->parent_directory)); if (!index_ni) { if (!err) @@ -996,8 +996,8 @@ static int ntfs_inode_sync_in_dir(ntfs_inode *ni, ntfs_inode *dir_ni) } NInoAttrListSetDirty(ni); goto sync_inode; - } - + } + if (na->data_size == ni->attr_list_size) { if (ntfs_attr_pwrite(na, 0, 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); } - + sync_inode: /* Write this inode out to the $MFT (and $MFTMirr if applicable). */ if (NInoTestAndClearDirty(ni)) { @@ -1045,8 +1045,8 @@ sync_inode: eni = ni->extent_nis[i]; if (!NInoTestAndClearDirty(eni)) continue; - - if (ntfs_mft_record_write(eni->vol, eni->mft_no, + + if (ntfs_mft_record_write(eni->vol, eni->mft_no, eni->mrec)) { if (!err || errno == EIO) { err = errno; @@ -1066,7 +1066,7 @@ sync_inode: errno = err; ret = -1; } - + ntfs_log_leave("\n"); return ret; } @@ -1135,19 +1135,19 @@ int ntfs_inode_add_attrlist(ntfs_inode *ni) } /* Walk through all attributes. */ while (!ntfs_attr_lookup(AT_UNUSED, NULL, 0, 0, 0, NULL, 0, ctx)) { - + int ale_size; - + if (ctx->attr->type == AT_ATTRIBUTE_LIST) { err = EIO; ntfs_log_perror("Attribute list already present"); goto put_err_out; } - + ale_size = (sizeof(ATTR_LIST_ENTRY) + sizeof(ntfschar) * ctx->attr->name_length + 7) & ~7; al_len += ale_size; - + aln = realloc(al, al_len); if (!aln) { err = errno; @@ -1156,9 +1156,9 @@ int ntfs_inode_add_attrlist(ntfs_inode *ni) } ale = (ATTR_LIST_ENTRY *)(aln + ((u8 *)ale - al)); al = aln; - + memset(ale, 0, ale_size); - + /* Add attribute to attribute list. */ ale->type = ctx->attr->type; 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); goto remove_attrlist_record;; } - + ntfs_attr_put_search_ctx(ctx); ntfs_attr_close(na); return 0; @@ -1326,12 +1326,12 @@ int ntfs_inode_free_space(ntfs_inode *ni, int size) * find next, because we don't need such. */ while (ctx->ntfs_ino->mft_no != ni->mft_no) { -retry: +retry: if (ntfs_attr_position(AT_UNUSED, ctx)) 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) goto retry; @@ -1352,10 +1352,10 @@ retry: return 0; } /* - * Reposition to first attribute after $STANDARD_INFORMATION - * and $ATTRIBUTE_LIST instead of simply skipping this 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 + * Reposition to first attribute after $STANDARD_INFORMATION + * and $ATTRIBUTE_LIST instead of simply skipping this 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 * $ATTRIBUTE_LIST. */ 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; if (mask & NTFS_UPDATE_CTIME) ni->last_mft_change_time = now; - + NInoFileNameSetDirty(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 * list. Please note that mft record numbers describing $Badclus extent inodes * will not match the current $Badclus:$Bad check. - * + * * On success return 1 if the file is $Badclus:$Bad, otherwise return 0. * 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; return -1; } - + if (mft_no != FILE_BadClus) return 0; @@ -1498,7 +1498,7 @@ int ntfs_inode_get_times(ntfs_inode *ni, char *value, size_t size) ret = -ERANGE; } ntfs_attr_put_search_ctx(ctx); - } + } return (ret ? ret : -errno); } diff --git a/source/lock.c b/source/lock.c new file mode 100644 index 0000000..6708f9c --- /dev/null +++ b/source/lock.c @@ -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 diff --git a/source/lock.h b/source/lock.h new file mode 100644 index 0000000..dd69984 --- /dev/null +++ b/source/lock.h @@ -0,0 +1,108 @@ +/* + lock.h + + Copyright (c) 2008 Sven Peter + + 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); +} +/* //not working. +#elif defined(__WIIU__) +#ifndef mutex_t +typedef int mutex_t; +#endif + +#define OS_MUTEX_SIZE 44 + +extern void (* OSInitMutex)(void* mutex); +extern void (* OSLockMutex)(void* mutex); +extern void (* OSUnlockMutex)(void* mutex); +extern void (* OSFatal)(const char *msg); + +static inline void _NTFS_lock_init(mutex_t *mutex,int unkwn){ + void* new_mutex = malloc(OS_MUTEX_SIZE); + if(new_mutex == NULL){ + OSFatal("_NTFS_lock_init malloc fail"); + } + + *mutex = (mutex_t) new_mutex; + OSInitMutex(new_mutex); +} + +static inline void _NTFS_lock_deinit(mutex_t *mutex){ + free((void*)(*mutex)); + *mutex = 0; +} + +static inline void _NTFS_lock(mutex_t *mutex) +{ + OSLockMutex((void*)*mutex); +} + +static inline void _NTFS_unlock(mutex_t *mutex) +{ + OSUnlockMutex((void*)*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 + diff --git a/source/mft.c b/source/mft.c index 0640efe..7e61218 100644 --- a/source/mft.c +++ b/source/mft.c @@ -85,7 +85,7 @@ int ntfs_mft_records_read(const ntfs_volume *vol, const MFT_REF mref, VCN m; ntfs_log_trace("inode %llu\n", (unsigned long long)MREF(mref)); - + if (!vol || !vol->mft_na || !b || count < 0) { errno = EINVAL; 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; } -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) -{ +{ ATTR_RECORD *a; int ret = -1; - + if (!ntfs_is_file_record(m->magic)) { if (!NVolNoFixupWarn(vol)) 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)); goto err_out; } - + if (le32_to_cpu(m->bytes_allocated) != vol->mft_record_size) { ntfs_log_error("Record %llu has corrupt allocation size " "(%u <> %u)\n", (unsigned long long)MREF(mref), - vol->mft_record_size, - le32_to_cpu(m->bytes_allocated)); + (unsigned int) vol->mft_record_size, + (unsigned int) le32_to_cpu(m->bytes_allocated)); goto err_out; } - + a = (ATTR_RECORD *)((char *)m + le16_to_cpu(m->attrs_offset)); if (p2n(a) < p2n(m) || (char *)a > (char *)m + vol->mft_record_size) { ntfs_log_error("Record %llu is corrupt\n", (unsigned long long)MREF(mref)); goto err_out; } - + ret = 0; err_out: 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); return -1; } - + m = *mrec; if (!m) { 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)) goto err_out; - + if (MSEQNO(mref) && MSEQNO(mref) != le16_to_cpu(m->sequence_number)) { ntfs_log_error("Record %llu has wrong SeqNo (%d <> %d)\n", (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; ntfs_log_enter("Entering\n"); - + m = ntfs_calloc(vol->mft_record_size); if (!m) goto out; - + if (ntfs_mft_record_layout(vol, mref, m)) goto free_m; - + if (ntfs_mft_record_write(vol, mref, m)) goto free_m; - + ret = 0; free_m: free(m); -out: +out: ntfs_log_leave("\n"); return ret; } @@ -486,7 +486,7 @@ static int ntfs_mft_bitmap_find_free_rec(ntfs_volume *vol, ntfs_inode *base_ni) int ret = -1; ntfs_log_enter("Entering\n"); - + mftbmp_na = vol->mftbmp_na; /* * 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); if (!buf) goto leave; - + ntfs_log_debug("Starting bitmap search: pass %u, pass_start 0x%llx, " "pass_end 0x%llx, data_pos 0x%llx.\n", pass, (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); for (; bit < size && data_pos + bit < pass_end; bit &= ~7ull, bit += 8) { - /* + /* * If we're extending $MFT and running out of the first * mft record (base record) then give up searching since * no guarantee that the found record will be accessible. */ if (ntfs_is_mft(base_ni) && bit > 400) goto out; - + byte = buf + (bit >> 3); if (*byte == 0xff) continue; - + /* Note: ffz() result must be zero based. */ b = ntfs_ffz((unsigned long)*byte); 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. */ -out: +out: free(buf); errno = ENOSPC; leave: @@ -633,9 +633,9 @@ static int ntfs_mft_attr_extend(ntfs_attr *na) ntfs_log_perror("%s: MP update failed", __FUNCTION__); goto out; } - + ret = STATUS_OK; -out: +out: ntfs_log_leave("\n"); return ret; } @@ -673,7 +673,7 @@ static int ntfs_mft_bitmap_extend_allocation_i(ntfs_volume *vol) return STATUS_ERROR; } lcn = rl->lcn + rl->length; - + rl2 = ntfs_cluster_alloc(vol, rl[1].vcn, 1, lcn, DATA_ZONE); if (!rl2) { ntfs_log_error("Failed to allocate a cluster for " @@ -809,7 +809,7 @@ undo_alloc: lcn = rl->lcn; rl->lcn = rl[1].lcn; rl->length = 0; - + /* FIXME: use an ntfs_cluster_free_* function */ if (ntfs_bitmap_clear_bit(vol->lcnbmp_na, lcn)) 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) { int ret; - + ntfs_log_enter("Entering\n"); ret = ntfs_mft_bitmap_extend_allocation_i(vol); ntfs_log_leave("\n"); @@ -879,7 +879,7 @@ static int ntfs_mft_bitmap_extend_initialized(ntfs_volume *vol) int ret = -1; ntfs_log_enter("Entering\n"); - + mftbmp_na = vol->mftbmp_na; ctx = ntfs_attr_get_search_ctx(mftbmp_na->ni, NULL); 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); if (ll == 8) { 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; goto out; } @@ -981,7 +981,7 @@ static int ntfs_mft_data_extend_allocation(ntfs_volume *vol) BOOL update_mp = FALSE; ntfs_log_enter("Extending mft data allocation.\n"); - + mft_na = vol->mft_na; /* * 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, (mft_na->allocated_size - 1) >> vol->cluster_size_bits); - + if (!rl || !rl->length || rl->lcn < 0) { ntfs_log_error("Failed to determine last allocated " "cluster of mft data attribute.\n"); @@ -998,7 +998,7 @@ static int ntfs_mft_data_extend_allocation(ntfs_volume *vol) errno = EIO; goto out; } - + lcn = rl->lcn + rl->length; 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. */ @@ -1009,7 +1009,7 @@ static int ntfs_mft_data_extend_allocation(ntfs_volume *vol) nr = vol->mft_record_size << 4 >> vol->cluster_size_bits; if (!nr) nr = min_nr; - + old_last_vcn = rl[1].vcn; do { 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 " "count %lli.\n", (long long)nr); } while (1); - + ntfs_log_debug("Allocated %lld clusters.\n", (long long)nr); - + rl = ntfs_runlists_merge(mft_na->rl, rl2); if (!rl) { err = errno; @@ -1045,7 +1045,7 @@ static int ntfs_mft_data_extend_allocation(ntfs_volume *vol) goto out; } mft_na->rl = rl; - + /* Find the last run in the new runlist. */ for (; rl[1].length; rl++) ; @@ -1195,13 +1195,13 @@ static int ntfs_mft_record_init(ntfs_volume *vol, s64 size) ntfs_attr *mft_na; s64 old_data_initialized, old_data_size; ntfs_attr_search_ctx *ctx; - + ntfs_log_enter("Entering\n"); - + /* NOTE: Caller must sanity check vol, vol->mft_na and vol->mftbmp_na */ - + mft_na = vol->mft_na; - + /* * The mft record is outside the initialized data. Extend the mft data * 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->initialized_size); } - + old_data_initialized = mft_na->initialized_size; old_data_size = mft_na->data_size; - + /* * Extend mft data initialized size (and data size of course) to reach * 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; } } - + /* Update the mft data attribute record to reflect the new sizes. */ ctx = ntfs_attr_get_search_ctx(mft_na->ni, NULL); 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->data_size = cpu_to_sle64(mft_na->data_size); ctx->attr->allocated_size = cpu_to_sle64(mft_na->allocated_size); - + /* Ensure the changes make it to disk. */ ntfs_inode_mark_dirty(ctx->ntfs_ino); 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->data_size, (long long)mft_na->initialized_size); - + /* Sanity checks. */ if (mft_na->data_size > mft_na->allocated_size || mft_na->initialized_size > mft_na->data_size) NTFS_BUG("mft_na sanity checks failed"); - + /* Sync MFT to minimize data loss if there won't be clean unmount. */ if (ntfs_inode_sync(mft_na->ni)) goto undo_data_init; - + ret = 0; -out: +out: ntfs_log_leave("\n"); return ret; - + undo_data_init: mft_na->initialized_size = old_data_initialized; 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; s64 old_data_initialized, old_data_size; ntfs_attr_search_ctx *ctx; - + ntfs_log_enter("Entering\n"); - + mft_na = vol->mft_na; - + if (size > mft_na->allocated_size || size > mft_na->initialized_size) { errno = EIO; 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); goto out; } - + old_data_initialized = mft_na->initialized_size; old_data_size = mft_na->data_size; - + /* Update the mft data attribute record to reflect the new sizes. */ ctx = ntfs_attr_get_search_ctx(mft_na->ni, NULL); 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); /* CHECKME: ctx->attr->allocation_size is already ok? */ - + /* Ensure the changes make it to disk. */ ntfs_inode_mark_dirty(ctx->ntfs_ino); ntfs_attr_put_search_ctx(ctx); - + /* Sanity checks. */ if (mft_na->data_size > mft_na->allocated_size || mft_na->initialized_size > mft_na->data_size) NTFS_BUG("mft_na sanity checks failed"); -out: +out: ntfs_log_leave("\n"); return ret; - + undo_data_init: mft_na->initialized_size = old_data_initialized; mft_na->data_size = old_data_size; @@ -1377,7 +1377,7 @@ static ntfs_inode *ntfs_mft_rec_alloc(ntfs_volume *vol) if (errno != ENOSPC) goto out; - + errno = ENOSPC; /* strerror() is intentionally used below, we want to log this error. */ 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"); goto err_out; } - + ll = (bit + 1) << vol->mft_record_size_bits; if (ll > mft_na->initialized_size) if (ntfs_mft_rec_init(vol, ll) < 0) @@ -1402,7 +1402,7 @@ found_free_rec: m = ntfs_malloc(vol->mft_record_size); if (!m) goto undo_mftbmp_alloc; - + if (ntfs_mft_record_read(vol, bit, m)) { free(m); goto undo_mftbmp_alloc; @@ -1470,7 +1470,7 @@ found_free_rec: base_ni->extent_nis = extent_nis; } base_ni->extent_nis[base_ni->nr_extents++] = ni; - + /* Make sure the allocated inode is written out to disk later. */ ntfs_inode_mark_dirty(ni); /* Initialize time, allocated and data size in ntfs_inode struct. */ @@ -1486,7 +1486,7 @@ found_free_rec: ntfs_log_error("allocated %sinode %lld\n", base_ni ? "extent " : "", (long long)bit); out: - ntfs_log_leave("\n"); + ntfs_log_leave("\n"); return ni; undo_mftbmp_alloc: @@ -1498,7 +1498,7 @@ err_out: if (!errno) errno = EIO; 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) 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); else 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; goto out; } - + if (ntfs_is_mft(base_ni)) { ni = ntfs_mft_rec_alloc(vol); goto out; @@ -1611,7 +1611,7 @@ ntfs_inode *ntfs_mft_record_alloc(ntfs_volume *vol, ntfs_inode *base_ni) mft_na = vol->mft_na; mftbmp_na = vol->mftbmp_na; -retry: +retry: bit = ntfs_mft_bitmap_find_free_rec(vol, base_ni); if (bit >= 0) { 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"); goto err_out; } - + /* The mft bitmap is now uptodate. Deal with mft data attribute now. */ ll = (bit + 1) << vol->mft_record_size_bits; if (ll > mft_na->initialized_size) @@ -1704,7 +1704,7 @@ found_free_rec: m = ntfs_malloc(vol->mft_record_size); if (!m) goto undo_mftbmp_alloc; - + if (ntfs_mft_record_read(vol, bit, m)) { free(m); goto undo_mftbmp_alloc; @@ -1787,9 +1787,9 @@ found_free_rec: /* Return the opened, allocated inode of the allocated mft record. */ ntfs_log_debug("allocated %sinode 0x%llx.\n", base_ni ? "extent " : "", (long long)bit); - vol->free_mft_records--; + vol->free_mft_records--; out: - ntfs_log_leave("\n"); + ntfs_log_leave("\n"); return ni; undo_mftbmp_alloc: @@ -1801,7 +1801,7 @@ err_out: if (!errno) errno = EIO; ni = NULL; - goto out; + goto out; } /** @@ -1865,7 +1865,7 @@ int ntfs_mft_record_free(ntfs_volume *vol, ntfs_inode *ni) #else if (!ntfs_inode_close(ni)) { #endif - vol->free_mft_records++; + vol->free_mft_records++; return 0; } err = errno; diff --git a/source/mst.c b/source/mst.c index b7937b7..ac02c2b 100644 --- a/source/mst.c +++ b/source/mst.c @@ -101,7 +101,7 @@ int ntfs_mst_post_read_fixup_warn(NTFS_RECORD *b, const u32 size, errno = EIO; ntfs_log_perror("Incomplete multi-sector transfer: " "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); b->magic = magic_BAAD; return -1; diff --git a/source/ntfs.c b/source/ntfs.c index 115c8b8..50a8a8e 100644 --- a/source/ntfs.c +++ b/source/ntfs.c @@ -37,9 +37,12 @@ #include "ntfsinternal.h" #include "ntfsfile.h" #include "ntfsdir.h" + #include "gekko_io.h" + #include "cache.h" + // NTFS device driver devoptab static const devoptab_t devops_ntfs = { NULL, /* Device name */ @@ -197,7 +200,7 @@ int ntfsFindPartitions (const DISC_INTERFACE *interface, sec_t **partitions) if (sector.boot.oem_id == NTFS_OEM_ID) { ntfs_log_debug("Logical Partition @ %d: Valid NTFS boot sector found\n", part_lba); 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) { partition_starts[partition_count] = part_lba; @@ -317,6 +320,27 @@ int ntfsMountAll (ntfs_md **mounts, u32 flags) } ntfs_free(partitions); + }else if(partition_count == 0){ + int k = 0; + // Find the next unused mount name + do { + sprintf(name, "%s%i", NTFS_MOUNT_PREFIX, k++); + if (k >= NTFS_MAX_MOUNTS) { + ntfs_free(partitions); + errno = EADDRNOTAVAIL; + return -1; + } + } while (ntfsGetDevice(name, false)); + + // Mount the partition + if (mount_count < NTFS_MAX_MOUNTS) { + if (ntfsMount(name, disc->interface, 0, CACHE_DEFAULT_PAGE_SIZE, CACHE_DEFAULT_PAGE_COUNT, flags)) { + strcpy(mount_points[mount_count].name, name); + mount_points[mount_count].interface = disc->interface; + mount_points[mount_count].startSector = 0; + mount_count++; + } + } } } diff --git a/source/ntfsfile.c b/source/ntfsfile.c index f361812..c336a53 100644 --- a/source/ntfsfile.c +++ b/source/ntfsfile.c @@ -220,7 +220,7 @@ int ntfs_open_r (struct _reent *r, void *fileStruct, const char *path, int flags 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); @@ -253,7 +253,7 @@ int ntfs_close_r (struct _reent *r, int fd) 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); @@ -319,7 +319,7 @@ ssize_t ntfs_write_r (struct _reent *r, int fd, const char *ptr, size_t len) 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); @@ -378,7 +378,7 @@ ssize_t ntfs_read_r (struct _reent *r, int fd, char *ptr, size_t len) 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); @@ -406,7 +406,7 @@ off_t ntfs_seek_r (struct _reent *r, int fd, off_t pos, int dir) 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); @@ -431,7 +431,7 @@ int ntfs_fstat_r (struct _reent *r, int fd, struct stat *st) 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); @@ -498,7 +498,7 @@ int ntfs_ftruncate_r (struct _reent *r, int fd, off_t len) 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); diff --git a/source/ntfsfile.h b/source/ntfsfile.h index 8e5ffcc..041290a 100644 --- a/source/ntfsfile.h +++ b/source/ntfsfile.h @@ -53,13 +53,13 @@ void ntfsCloseFile (ntfs_file_state *file); /* 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_close_r (struct _reent *r, int fd); -extern ssize_t ntfs_write_r (struct _reent *r, int fd, const char *ptr, size_t len); -extern ssize_t ntfs_read_r (struct _reent *r, int fd, char *ptr, size_t len); -extern off_t ntfs_seek_r (struct _reent *r, int fd, off_t pos, int dir); -extern int ntfs_fstat_r (struct _reent *r, int fd, struct stat *st); -extern int ntfs_ftruncate_r (struct _reent *r, int fd, off_t len); -extern int ntfs_fsync_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, void * fd, const 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, void * fd, off_t pos, int dir); +extern int ntfs_fstat_r (struct _reent *r, void * fd, struct stat *st); +extern int ntfs_ftruncate_r (struct _reent *r, void * fd, off_t len); +extern int ntfs_fsync_r (struct _reent *r, void * fd); #endif /* _NTFSFILE_H */ diff --git a/source/ntfsinternal.c b/source/ntfsinternal.c index 58f35c1..b660fa8 100644 --- a/source/ntfsinternal.c +++ b/source/ntfsinternal.c @@ -37,6 +37,7 @@ #include "ntfsinternal.h" #include "ntfsdir.h" #include "ntfsfile.h" +#include "lock.h" #if defined(__wii__) #include @@ -51,6 +52,15 @@ const INTERFACE_ID ntfs_disc_interfaces[] = { { NULL, NULL } }; +#elif defined (__WIIU__) + #include + +const INTERFACE_ID ntfs_disc_interfaces[] = { + {"sd", &IOSUHAX_sdio_disc_interface}, + {"usb", &IOSUHAX_usb_disc_interface}, + {NULL, NULL} +}; + #elif defined(__gamecube__) #include @@ -190,7 +200,7 @@ int ntfsInitVolume (ntfs_vd *vd) } // Initialise the volume lock - LWP_MutexInit(&vd->lock, false); + _NTFS_lock_init(&vd->lock, false); // Reset the volumes name cache vd->name[0] = '\0'; @@ -253,7 +263,7 @@ void ntfsDeinitVolume (ntfs_vd *vd) ntfsUnlock(vd); // Deinitialise the volume lock - LWP_MutexDestroy(vd->lock); + _NTFS_lock_deinit((mutex_t *)vd->lock); return; } diff --git a/source/ntfsinternal.h b/source/ntfsinternal.h index 11dfb8f..cb3dd15 100644 --- a/source/ntfsinternal.h +++ b/source/ntfsinternal.h @@ -38,10 +38,21 @@ #include "reparse.h" #include "security.h" #include "efs.h" +#include "lock.h" #include "unistr.h" -#include -#include +#if defined (__WIIU__) + #include + typedef uint8_t u8; + typedef uint16_t u16; + typedef int32_t s32; + typedef uint32_t u32; + typedef int mutex_t; +#elif defined(__gamecube__) || defined (__wii__) + #include + #include +#endif + #include #define NTFS_MOUNT_PREFIX "ntfs" /* Device name prefix to use when auto-mounting */ @@ -141,13 +152,13 @@ typedef struct _ntfs_vd { /* Lock volume */ static inline void ntfsLock (ntfs_vd *vd) { - LWP_MutexLock(vd->lock); + _NTFS_lock((mutex_t *)&vd->lock); } /* Unlock volume */ static inline void ntfsUnlock (ntfs_vd *vd) { - LWP_MutexUnlock(vd->lock); + _NTFS_unlock((mutex_t *)&vd->lock); } /* Gekko device related routines */ diff --git a/source/ntfstime.h b/source/ntfstime.h index 21c222d..d9ef87a 100644 --- a/source/ntfstime.h +++ b/source/ntfstime.h @@ -40,7 +40,7 @@ /* * 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 { time_t tv_sec; long tv_nsec; diff --git a/source/volume.c b/source/volume.c index 5bb266f..a8d3b72 100644 --- a/source/volume.c +++ b/source/volume.c @@ -75,7 +75,7 @@ #include "realpath.h" #include "misc.h" -const char *ntfs_home = +const char *ntfs_home = "News, support and information: http://tuxera.com\n"; static const char *invalid_ntfs_msg = @@ -108,7 +108,7 @@ static const char *opened_volume_msg = static const char *fakeraid_msg = "Either the device is missing or it's powered down, or you have\n" -"SoftRAID hardware and must use an activated, different device under\n" +"SoftRAID hardware and must use an activated, different device under\n" "/dev/mapper/, (e.g. /dev/mapper/nvidia_eahaabcc1) to mount NTFS.\n" "Please see the 'dmraid' documentation for help.\n"; @@ -144,8 +144,8 @@ static int ntfs_inode_free(ntfs_inode **ni) if (ni && *ni) { ret = ntfs_inode_close(*ni); *ni = NULL; - } - + } + return ret; } @@ -169,7 +169,7 @@ static int __ntfs_volume_release(ntfs_volume *v) if (ntfs_inode_free(&v->vol_ni)) ntfs_error_set(&err); - /* + /* * FIXME: Inodes must be synced before closing * attributes, otherwise unmount could fail. */ @@ -178,20 +178,20 @@ static int __ntfs_volume_release(ntfs_volume *v) ntfs_attr_free(&v->lcnbmp_na); if (ntfs_inode_free(&v->lcnbmp_ni)) ntfs_error_set(&err); - + if (v->mft_ni && NInoDirty(v->mft_ni)) ntfs_inode_sync(v->mft_ni); ntfs_attr_free(&v->mftbmp_na); ntfs_attr_free(&v->mft_na); if (ntfs_inode_free(&v->mft_ni)) ntfs_error_set(&err); - + if (v->mftmirr_ni && NInoDirty(v->mftmirr_ni)) ntfs_inode_sync(v->mftmirr_ni); ntfs_attr_free(&v->mftmirr_na); if (ntfs_inode_free(&v->mftmirr_ni)) ntfs_error_set(&err); - + if (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"); goto error_exit; } - + if (ntfs_mft_record_check(vol, 0, mb)) goto error_exit; - + ctx = ntfs_attr_get_search_ctx(vol->mft_ni, NULL); if (!ctx) goto error_exit; @@ -288,7 +288,7 @@ static int ntfs_mft_load(ntfs_volume *vol) vol->mft_ni->attr_list = ntfs_malloc(l); if (!vol->mft_ni->attr_list) goto error_exit; - + l = ntfs_get_attribute_value(vol, ctx->attr, vol->mft_ni->attr_list); if (!l) { 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) { ntfs_log_error("Partial read of $MFT/$ATTR_LIST (%lld != " "%u).\n", (long long)l, - vol->mft_ni->attr_list_size); + (unsigned int) vol->mft_ni->attr_list_size); goto io_error_exit; } mft_has_no_attr_list: ntfs_attr_setup_flag(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. */ vol->mft_na = ntfs_attr_open(vol->mft_ni, AT_DATA, AT_UNNAMED, 0); if (!vol->mft_na) { @@ -428,18 +428,18 @@ static int ntfs_mftmirr_load(ntfs_volume *vol) ntfs_log_perror("Failed to open inode $MFTMirr"); return -1; } - + vol->mftmirr_na = ntfs_attr_open(vol->mftmirr_ni, AT_DATA, AT_UNNAMED, 0); if (!vol->mftmirr_na) { ntfs_log_perror("Failed to open $MFTMirr/$DATA"); goto error_exit; } - + if (ntfs_attr_map_runlist(vol->mftmirr_na, 0) < 0) { ntfs_log_perror("Failed to map runlist of $MFTMirr/$DATA"); goto error_exit; } - + return 0; error_exit: @@ -484,12 +484,12 @@ ntfs_volume *ntfs_volume_startup(struct ntfs_device *dev, bs = ntfs_malloc(sizeof(NTFS_BOOT_SECTOR)); if (!bs) return NULL; - + /* Allocate the volume structure. */ vol = ntfs_volume_alloc(); if (!vol) goto error_exit; - + /* Create the default upcase table. */ vol->upcase_len = ntfs_upcase_build_default(&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 */ vol->locase = (ntfschar*)NULL; NVolSetCaseSensitive(vol); - + /* by default, all files are shown and not marked hidden */ NVolSetShowSysFiles(vol); NVolSetShowHidFiles(vol); @@ -511,7 +511,7 @@ ntfs_volume *ntfs_volume_startup(struct ntfs_device *dev, #endif if (flags & NTFS_MNT_RDONLY) NVolSetReadOnly(vol); - + /* ...->open needs bracketing to compile with glibc 2.7 */ if ((dev->d_ops->open)(dev, NVolReadOnly(vol) ? O_RDONLY: O_RDWR)) { if (!NVolReadOnly(vol) && (errno == EROFS)) { @@ -531,7 +531,7 @@ ntfs_volume *ntfs_volume_startup(struct ntfs_device *dev, } /* Attach the device to the volume. */ vol->dev = dev; - + /* Now read the bootsector. */ br = ntfs_pread(dev, 0, sizeof(NTFS_BOOT_SECTOR), bs); 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) goto error_exit; - + free(bs); bs = NULL; /* 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 " "but should be harmless otherwise. Error: " "%s\n", strerror(errno)); - + /* We now initialize the cluster allocator. */ vol->full_zones = 0; mft_zone_size = vol->nr_clusters >> 3; /* 12.5% */ @@ -652,14 +652,14 @@ static int ntfs_volume_check_logfile(ntfs_volume *vol) errno = EIO; return -1; } - + na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0); if (!na) { ntfs_log_perror("Failed to open $FILE_LogFile/$DATA"); err = EIO; goto out; } - + if (!ntfs_check_logfile(na, &rp) || !ntfs_is_logfile_clean(na, rp)) err = EOPNOTSUPP; /* @@ -682,7 +682,7 @@ static int ntfs_volume_check_logfile(ntfs_volume *vol) } free(rp); ntfs_attr_close(na); -out: +out: if (ntfs_inode_close(ni)) ntfs_error_set(&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"); goto error_exit; } - + vol->lcnbmp_na = ntfs_attr_open(vol->lcnbmp_ni, AT_DATA, AT_UNNAMED, 0); if (!vol->lcnbmp_na) { ntfs_log_perror("Failed to open ntfs attribute"); goto error_exit; } - + if (vol->lcnbmp_na->data_size > vol->lcnbmp_na->allocated_size) { 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); 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); if (!vol->vol_name) goto error_exit; - + for (j = 0; j < (s32)u; j++) { u16 uc = le16_to_cpu(vname[j]); if (uc > 0xff) @@ -1639,7 +1639,7 @@ int ntfs_logfile_reset(ntfs_volume *vol) ntfs_attr_close(na); goto error_exit; } - + ntfs_attr_close(na); return ntfs_inode_close(ni);