Wii U support

This commit is contained in:
Maschell 2020-12-06 23:06:22 +01:00
parent 968dee4aef
commit f8705b2c39
29 changed files with 830 additions and 519 deletions

26
.github/workflows/push_image.yml vendored Normal file
View File

@ -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

5
.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
source/wiiu_release/*
source/wii_release/*
source/cube_release/*
lib/*
.idea/*

11
Dockerfile.wiiu Normal file
View File

@ -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

View File

@ -1,11 +1,11 @@
default: cube-release wii-release default: cube-release wii-release wiiu-release
all: debug 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: cube-debug:
$(MAKE) -C source PLATFORM=cube BUILD=cube_debug $(MAKE) -C source PLATFORM=cube BUILD=cube_debug
@ -13,12 +13,18 @@ cube-debug:
wii-debug: wii-debug:
$(MAKE) -C source PLATFORM=wii BUILD=wii_debug $(MAKE) -C source PLATFORM=wii BUILD=wii_debug
wiiu-debug:
$(MAKE) -C source PLATFORM=wiiu BUILD=wiiu_debug
cube-release: cube-release:
$(MAKE) -C source PLATFORM=cube BUILD=cube_release $(MAKE) -C source PLATFORM=cube BUILD=cube_release
wii-release: wii-release:
$(MAKE) -C source PLATFORM=wii BUILD=wii_release $(MAKE) -C source PLATFORM=wii BUILD=wii_release
wiiu-release:
$(MAKE) -C source PLATFORM=wiiu BUILD=wiiu_release
clean: clean:
$(MAKE) -C source clean $(MAKE) -C source clean
@ -28,7 +34,10 @@ cube-install: cube-release
wii-install: wii-release wii-install: wii-release
$(MAKE) -C source wii-install PLATFORM=wii $(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 run: install
$(MAKE) -C example $(MAKE) -C example

20
README.md Normal file
View File

@ -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
```

View File

@ -27,9 +27,18 @@
extern "C" { extern "C" {
#endif #endif
#include <gctypes.h> #if defined(__gamecube__) || defined (__wii__)
#include <gccore.h> #include <gctypes.h>
#include <ogc/disc_io.h> #include <ogc/disc_io.h>
#include <gccore.h>
#elif defined (__WIIU__)
#include <iosuhax_disc_interface.h>
typedef uint8_t u8;
typedef uint16_t u16;
typedef int32_t s32;
typedef uint32_t u32;
typedef int mutex_t;
#endif
/* NTFS errno values */ /* NTFS errno values */
#define ENOPART 3000 /* No partition was found */ #define ENOPART 3000 /* No partition was found */

View File

@ -7,12 +7,17 @@ ifeq ($(strip $(DEVKITPPC)),)
$(error "Please set DEVKITPPC in your environment. export DEVKITPPC=<path to>devkitPPC") $(error "Please set DEVKITPPC in your environment. export DEVKITPPC=<path to>devkitPPC")
endif endif
ifeq ($(PLATFORM),wiiu)
include $(DEVKITPRO)/wut/share/wut_rules
MACHDEP += -D__WIIU__
endif
ifeq ($(PLATFORM),wii) ifeq ($(PLATFORM),wii)
include $(DEVKITPPC)/wii_rules include $(DEVKITPPC)/wii_rules
endif endif
ifeq ($(PLATFORM),cube) ifeq ($(PLATFORM),cube)
include $(DEVKITPPC)/gamecube_rules include $(DEVKITPPC)/gamecube_rules
endif endif
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
@ -20,7 +25,7 @@ endif
# SOURCES is a list of directories containing source code # SOURCES is a list of directories containing source code
# INCLUDES is a list of directories containing extra header files # INCLUDES is a list of directories containing extra header files
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
BUILD ?= wii_release BUILD ?= wiiu_release
SOURCES := . SOURCES := .
INCLUDES := ../include INCLUDES := ../include
LIBDIR := ../lib LIBDIR := ../lib
@ -28,7 +33,7 @@ LIBDIR := ../lib
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
# options for code generation # options for code generation
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
CFLAGS = -Os -Wall -ffast-math -pipe $(MACHDEP) $(INCLUDE) -DHAVE_CONFIG_H CFLAGS = -Wall -ffast-math -pipe $(MACHDEP) $(INCLUDE) -ffunction-sections -DHAVE_CONFIG_H
CXXFLAGS = $(CFLAGS) CXXFLAGS = $(CFLAGS)
ASFLAGS := -g ASFLAGS := -g
export NTFSBIN := $(LIBDIR)/$(PLATFORM)/libntfs.a export NTFSBIN := $(LIBDIR)/$(PLATFORM)/libntfs.a
@ -37,21 +42,29 @@ ifeq ($(BUILD),cube_debug)
CFLAGS += -DDEBUG CFLAGS += -DDEBUG
CXXFLAGS += -DDEBUG CXXFLAGS += -DDEBUG
endif endif
ifeq ($(BUILD),wii_debug) ifeq ($(BUILD),wii_debug)
CFLAGS += -DDEBUG CFLAGS += -DDEBUG
CXXFLAGS += -DDEBUG CXXFLAGS += -DDEBUG
endif endif
ifeq ($(BUILD),wiiu_debug)
CFLAGS += -DDEBUG
CXXFLAGS += -DDEBUG
endif
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
# any extra libraries we wish to link with the project # any extra libraries we wish to link with the project
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
LIBS := LIBS :=
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing # list of directories containing libraries, this must be the top level containing
# include and lib # 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 # 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)) \ export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \ $(foreach dir,$(LIBDIRS),-I$(dir)/include) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \ $(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(CURDIR)/$(BUILD) \ -I$(CURDIR)/$(BUILD) -I$(PORTLIBS)/include
-I$(LIBOGC_INC)
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) \ export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) $(PORTLIBS)/lib
-L$(LIBOGC_LIB)
.PHONY: $(BUILD) clean .PHONY: $(BUILD) clean
@ -93,7 +104,7 @@ $(BUILD):
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
clean: clean:
@echo 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) all: $(NTFSBIN)
@ -105,6 +116,10 @@ wii-install:
cp ../include/ntfs.h $(PORTLIBS)/include cp ../include/ntfs.h $(PORTLIBS)/include
cp ../lib/wii/libntfs.a $(PORTLIBS)/lib 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 else

View File

@ -73,7 +73,7 @@ BOOL ntfs_boot_sector_is_ntfs(NTFS_BOOT_SECTOR *b)
ntfs_log_debug("Checking bytes per sector.\n"); ntfs_log_debug("Checking bytes per sector.\n");
if (le16_to_cpu(b->bpb.bytes_per_sector) < 256 || if (le16_to_cpu(b->bpb.bytes_per_sector) < 256 ||
le16_to_cpu(b->bpb.bytes_per_sector) > 4096) { le16_to_cpu(b->bpb.bytes_per_sector) > 4096) {
ntfs_log_error("Unexpected bytes per sector value (%d).\n", ntfs_log_error("Unexpected bytes per sector value (%d).\n",
le16_to_cpu(b->bpb.bytes_per_sector)); le16_to_cpu(b->bpb.bytes_per_sector));
goto not_ntfs; goto not_ntfs;
} }
@ -89,10 +89,10 @@ BOOL ntfs_boot_sector_is_ntfs(NTFS_BOOT_SECTOR *b)
} }
ntfs_log_debug("Checking cluster size.\n"); ntfs_log_debug("Checking cluster size.\n");
i = (u32)le16_to_cpu(b->bpb.bytes_per_sector) * i = (u32)le16_to_cpu(b->bpb.bytes_per_sector) *
b->bpb.sectors_per_cluster; b->bpb.sectors_per_cluster;
if (i > 65536) { if (i > 65536) {
ntfs_log_error("Unexpected cluster size (%d).\n", i); ntfs_log_error("Unexpected cluster size (%d).\n", (int)i);
goto not_ntfs; goto not_ntfs;
} }
@ -109,7 +109,7 @@ BOOL ntfs_boot_sector_is_ntfs(NTFS_BOOT_SECTOR *b)
le16_to_cpu(b->bpb.root_entries), le16_to_cpu(b->bpb.root_entries),
le16_to_cpu(b->bpb.sectors), le16_to_cpu(b->bpb.sectors),
le16_to_cpu(b->bpb.sectors_per_fat), le16_to_cpu(b->bpb.sectors_per_fat),
le32_to_cpu(b->bpb.large_sectors), (int)le32_to_cpu(b->bpb.large_sectors),
b->bpb.fats); b->bpb.fats);
goto not_ntfs; goto not_ntfs;
} }
@ -193,14 +193,14 @@ int ntfs_boot_sector_parse(ntfs_volume *vol, const NTFS_BOOT_SECTOR *bs)
"\n", sectors_per_cluster); "\n", sectors_per_cluster);
return -1; return -1;
} }
sectors = sle64_to_cpu(bs->number_of_sectors); sectors = sle64_to_cpu(bs->number_of_sectors);
ntfs_log_debug("NumberOfSectors = %lld\n", (long long)sectors); ntfs_log_debug("NumberOfSectors = %lld\n", (long long)sectors);
if (!sectors) { if (!sectors) {
ntfs_log_error("Volume size is set to zero.\n"); ntfs_log_error("Volume size is set to zero.\n");
return -1; return -1;
} }
if (vol->dev->d_ops->seek(vol->dev, if (vol->dev->d_ops->seek(vol->dev,
(sectors - 1) << vol->sector_size_bits, (sectors - 1) << vol->sector_size_bits,
SEEK_SET) == -1) { SEEK_SET) == -1) {
ntfs_log_perror("Failed to read last sector (%lld)", ntfs_log_perror("Failed to read last sector (%lld)",
@ -208,7 +208,7 @@ int ntfs_boot_sector_parse(ntfs_volume *vol, const NTFS_BOOT_SECTOR *bs)
ntfs_log_error("%s", last_sector_error); ntfs_log_error("%s", last_sector_error);
return -1; return -1;
} }
vol->nr_clusters = sectors >> (ffs(sectors_per_cluster) - 1); vol->nr_clusters = sectors >> (ffs(sectors_per_cluster) - 1);
vol->mft_lcn = sle64_to_cpu(bs->mft_lcn); vol->mft_lcn = sle64_to_cpu(bs->mft_lcn);
@ -223,11 +223,11 @@ int ntfs_boot_sector_parse(ntfs_volume *vol, const NTFS_BOOT_SECTOR *bs)
(long long)vol->nr_clusters); (long long)vol->nr_clusters);
return -1; return -1;
} }
vol->cluster_size = sectors_per_cluster * vol->sector_size; vol->cluster_size = sectors_per_cluster * vol->sector_size;
if (vol->cluster_size & (vol->cluster_size - 1)) { if (vol->cluster_size & (vol->cluster_size - 1)) {
ntfs_log_error("cluster_size (%d) is not a power of 2.\n", ntfs_log_error("cluster_size (%d) is not a power of 2.\n",
vol->cluster_size); (int)vol->cluster_size);
return -1; return -1;
} }
vol->cluster_size_bits = ffs(vol->cluster_size) - 1; vol->cluster_size_bits = ffs(vol->cluster_size) - 1;
@ -252,7 +252,7 @@ int ntfs_boot_sector_parse(ntfs_volume *vol, const NTFS_BOOT_SECTOR *bs)
vol->mft_record_size = c << vol->cluster_size_bits; vol->mft_record_size = c << vol->cluster_size_bits;
if (vol->mft_record_size & (vol->mft_record_size - 1)) { if (vol->mft_record_size & (vol->mft_record_size - 1)) {
ntfs_log_error("mft_record_size (%d) is not a power of 2.\n", ntfs_log_error("mft_record_size (%d) is not a power of 2.\n",
vol->mft_record_size); (int)vol->mft_record_size);
return -1; return -1;
} }
vol->mft_record_size_bits = ffs(vol->mft_record_size) - 1; vol->mft_record_size_bits = ffs(vol->mft_record_size) - 1;

View File

@ -35,7 +35,11 @@
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <ogc/lwp_watchdog.h> #if defined (__WIIU__)
#elif defined(__gamecube__) || defined (__wii__)
#include <ogc/lwp_watchdog.h>
#endif
#include <string.h> #include <string.h>
#include <limits.h> #include <limits.h>

View File

@ -42,9 +42,21 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include <gctypes.h>
#include <ogc/disc_io.h> #if defined (__WIIU__)
#include <gccore.h> #include <iosuhax_disc_interface.h>
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 <gctypes.h>
#include <ogc/disc_io.h>
#include <gccore.h>
#endif
typedef struct { typedef struct {
sec_t sector; sec_t sector;
@ -54,7 +66,7 @@ typedef struct {
u8* cache; u8* cache;
} NTFS_CACHE_ENTRY; } NTFS_CACHE_ENTRY;
typedef struct { typedef struct NTFS_CACHE_{
const DISC_INTERFACE* disc; const DISC_INTERFACE* disc;
sec_t endOfPartition; sec_t endOfPartition;
unsigned int numberOfPages; unsigned int numberOfPages;

View File

@ -69,11 +69,11 @@ extern char *strsep(char **stringp, const char *delim);
#define O_BINARY 0 /* unix is binary by default */ #define O_BINARY 0 /* unix is binary by default */
#endif #endif
#ifdef GEKKO #if defined(GEKKO) || defined (__WIIU__)
#include "mem_allocate.h" #include "mem_allocate.h"
#define XATTR_CREATE 1 #define XATTR_CREATE 1
#define XATTR_REPLACE 2 #define XATTR_REPLACE 2
#define MINORBITS 20 #define MINORBITS 20
@ -81,7 +81,7 @@ extern char *strsep(char **stringp, const char *delim);
#define major(dev) ((unsigned int) ((dev) >> MINORBITS)) #define major(dev) ((unsigned int) ((dev) >> MINORBITS))
#define minor(dev) ((unsigned int) ((dev) & MINORMASK)) #define minor(dev) ((unsigned int) ((dev) & MINORMASK))
#define mkdev(ma,mi) (((ma) << MINORBITS) | (mi)) #define mkdev(ma,mi) (((ma) << MINORBITS) | (mi))
#define random rand #define random rand
#endif /* defined GEKKO */ #endif /* defined GEKKO */

View File

@ -27,7 +27,7 @@
#ifndef __CYGWIN32__ #ifndef __CYGWIN32__
/* Not on Cygwin; use standard Unix style low level device operations. */ /* Not on Cygwin; use standard Unix style low level device operations. */
#include "unix_io.c" //#include "unix_io.c"
#else /* __CYGWIN32__ */ #else /* __CYGWIN32__ */

View File

@ -30,12 +30,12 @@
#ifndef __CYGWIN32__ #ifndef __CYGWIN32__
#ifndef GEKKO #if defined(GEKKO) || defined (__WIIU__)
/* Not on Cygwin; use standard Unix style low level device operations. */ /* Wii i/o device. */
#define ntfs_device_default_io_ops ntfs_device_unix_io_ops #define ntfs_device_default_io_ops ntfs_device_gekko_io_ops
#else #else
/* Wii i/o device. */ /* Not on Cygwin; use standard Unix style low level device operations. */
#define ntfs_device_default_io_ops ntfs_device_gekko_io_ops #define ntfs_device_default_io_ops ntfs_device_unix_io_ops
#endif #endif
#else /* __CYGWIN32__ */ #else /* __CYGWIN32__ */

View File

@ -66,6 +66,11 @@
#include <sys/xattr.h> #include <sys/xattr.h>
#endif #endif
#if defined(__WIIU__)
#define major(dev) ((int)(((unsigned int) (dev) >> 8) & 0xff))
#define minor(dev) ((int)((dev) & 0xff))
#endif // defined
/* /*
* The little endian Unicode strings "$I30", "$SII", "$SDH", "$O" * The little endian Unicode strings "$I30", "$SII", "$SDH", "$O"
* and "$Q" as global constants. * and "$Q" as global constants.
@ -313,7 +318,7 @@ u64 ntfs_inode_lookup_by_name(ntfs_inode *dir_ni,
*/ */
if (ie->ie_flags & INDEX_ENTRY_END) if (ie->ie_flags & INDEX_ENTRY_END)
break; break;
if (!le16_to_cpu(ie->length)) { if (!le16_to_cpu(ie->length)) {
ntfs_log_error("Zero length index entry in inode %lld" ntfs_log_error("Zero length index entry in inode %lld"
"\n", (unsigned long long)dir_ni->mft_no); "\n", (unsigned long long)dir_ni->mft_no);
@ -441,7 +446,7 @@ descend_into_child_node:
(u8*)ie + le16_to_cpu(ie->key_length) > (u8*)ie + le16_to_cpu(ie->key_length) >
index_end) { index_end) {
ntfs_log_error("Index entry out of bounds in directory " ntfs_log_error("Index entry out of bounds in directory "
"inode %lld.\n", "inode %lld.\n",
(unsigned long long)dir_ni->mft_no); (unsigned long long)dir_ni->mft_no);
errno = EIO; errno = EIO;
goto close_err_out; goto close_err_out;
@ -452,7 +457,7 @@ descend_into_child_node:
*/ */
if (ie->ie_flags & INDEX_ENTRY_END) if (ie->ie_flags & INDEX_ENTRY_END)
break; break;
if (!le16_to_cpu(ie->length)) { if (!le16_to_cpu(ie->length)) {
errno = EIO; errno = EIO;
ntfs_log_error("Zero length index entry in inode %lld" ntfs_log_error("Zero length index entry in inode %lld"
@ -681,9 +686,9 @@ ntfs_inode *ntfs_pathname_to_inode(ntfs_volume *vol, ntfs_inode *parent,
errno = EINVAL; errno = EINVAL;
return NULL; return NULL;
} }
ntfs_log_trace("path: '%s'\n", pathname); ntfs_log_trace("path: '%s'\n", pathname);
ascii = strdup(pathname); ascii = strdup(pathname);
if (!ascii) { if (!ascii) {
ntfs_log_error("Out of memory.\n"); ntfs_log_error("Out of memory.\n");
@ -818,7 +823,7 @@ ntfs_inode *ntfs_pathname_to_inode(ntfs_volume *vol, ntfs_inode *parent,
err = EIO; err = EIO;
goto close; goto close;
} }
free(unicode); free(unicode);
unicode = NULL; unicode = NULL;
@ -974,7 +979,7 @@ static int ntfs_filldir(ntfs_inode *dir_ni, s64 *pos, u8 ivcn_bits,
MFT_REF mref; MFT_REF mref;
ntfs_log_trace("Entering.\n"); ntfs_log_trace("Entering.\n");
/* Advance the position even if going to skip the entry. */ /* Advance the position even if going to skip the entry. */
if (index_type == INDEX_TYPE_ALLOCATION) if (index_type == INDEX_TYPE_ALLOCATION)
*pos = (u8*)ie - (u8*)iu.ia + (sle64_to_cpu( *pos = (u8*)ie - (u8*)iu.ia + (sle64_to_cpu(
@ -1055,7 +1060,7 @@ static MFT_REF ntfs_mft_get_parent_ref(ntfs_inode *ni)
int eo; int eo;
ntfs_log_trace("Entering.\n"); ntfs_log_trace("Entering.\n");
if (!ni) { if (!ni) {
errno = EINVAL; errno = EINVAL;
return ERR_MREF(-1); return ERR_MREF(-1);
@ -1065,7 +1070,7 @@ static MFT_REF ntfs_mft_get_parent_ref(ntfs_inode *ni)
if (!ctx) if (!ctx)
return ERR_MREF(-1); return ERR_MREF(-1);
if (ntfs_attr_lookup(AT_FILE_NAME, AT_UNNAMED, 0, 0, 0, NULL, 0, ctx)) { if (ntfs_attr_lookup(AT_FILE_NAME, AT_UNNAMED, 0, 0, 0, NULL, 0, ctx)) {
ntfs_log_error("No file name found in inode %lld\n", ntfs_log_error("No file name found in inode %lld\n",
(unsigned long long)ni->mft_no); (unsigned long long)ni->mft_no);
goto err_out; goto err_out;
} }
@ -1126,7 +1131,7 @@ int ntfs_readdir(ntfs_inode *dir_ni, s64 *pos,
u8 index_block_size_bits, index_vcn_size_bits; u8 index_block_size_bits, index_vcn_size_bits;
ntfs_log_trace("Entering.\n"); ntfs_log_trace("Entering.\n");
if (!dir_ni || !pos || !filldir) { if (!dir_ni || !pos || !filldir) {
errno = EINVAL; errno = EINVAL;
return -1; return -1;
@ -1246,10 +1251,10 @@ int ntfs_readdir(ntfs_inode *dir_ni, s64 *pos,
/* The last entry cannot contain a name. */ /* The last entry cannot contain a name. */
if (ie->ie_flags & INDEX_ENTRY_END) if (ie->ie_flags & INDEX_ENTRY_END)
break; break;
if (!le16_to_cpu(ie->length)) if (!le16_to_cpu(ie->length))
goto dir_err_out; goto dir_err_out;
/* Skip index root entry if continuing previous readdir. */ /* Skip index root entry if continuing previous readdir. */
if (ir_pos > (u8*)ie - (u8*)ir) if (ir_pos > (u8*)ie - (u8*)ir)
continue; continue;
@ -1402,10 +1407,10 @@ find_next_index_buffer:
/* The last entry cannot contain a name. */ /* The last entry cannot contain a name. */
if (ie->ie_flags & INDEX_ENTRY_END) if (ie->ie_flags & INDEX_ENTRY_END)
break; break;
if (!le16_to_cpu(ie->length)) if (!le16_to_cpu(ie->length))
goto dir_err_out; goto dir_err_out;
/* Skip index entry if continuing previous readdir. */ /* Skip index entry if continuing previous readdir. */
if (ia_pos - ia_start > (u8*)ie - (u8*)ia) if (ia_pos - ia_start > (u8*)ie - (u8*)ia)
continue; continue;
@ -1492,19 +1497,19 @@ static ntfs_inode *__ntfs_create(ntfs_inode *dir_ni, le32 securid,
int err, fn_len, si_len; int err, fn_len, si_len;
ntfs_log_trace("Entering.\n"); ntfs_log_trace("Entering.\n");
/* Sanity checks. */ /* Sanity checks. */
if (!dir_ni || !name || !name_len) { if (!dir_ni || !name || !name_len) {
ntfs_log_error("Invalid arguments.\n"); ntfs_log_error("Invalid arguments.\n");
errno = EINVAL; errno = EINVAL;
return NULL; return NULL;
} }
if (dir_ni->flags & FILE_ATTR_REPARSE_POINT) { if (dir_ni->flags & FILE_ATTR_REPARSE_POINT) {
errno = EOPNOTSUPP; errno = EOPNOTSUPP;
return NULL; return NULL;
} }
ni = ntfs_mft_record_alloc(dir_ni->vol, NULL); ni = ntfs_mft_record_alloc(dir_ni->vol, NULL);
if (!ni) if (!ni)
return NULL; return NULL;
@ -1596,7 +1601,7 @@ static ntfs_inode *__ntfs_create(ntfs_inode *dir_ni, le32 securid,
ni->vol->indx_record_size >> ni->vol->indx_record_size >>
ni->vol->cluster_size_bits; ni->vol->cluster_size_bits;
else else
ir->clusters_per_index_block = ir->clusters_per_index_block =
ni->vol->indx_record_size >> ni->vol->indx_record_size >>
NTFS_BLOCK_SIZE_BITS; NTFS_BLOCK_SIZE_BITS;
ir->index.entries_offset = cpu_to_le32(sizeof(INDEX_HEADER)); ir->index.entries_offset = cpu_to_le32(sizeof(INDEX_HEADER));
@ -1725,7 +1730,7 @@ err_out:
if (rollback_sd) if (rollback_sd)
ntfs_attr_remove(ni, AT_SECURITY_DESCRIPTOR, AT_UNNAMED, 0); ntfs_attr_remove(ni, AT_SECURITY_DESCRIPTOR, AT_UNNAMED, 0);
if (rollback_data) if (rollback_data)
ntfs_attr_remove(ni, AT_DATA, AT_UNNAMED, 0); ntfs_attr_remove(ni, AT_DATA, AT_UNNAMED, 0);
/* /*
@ -1790,7 +1795,7 @@ int ntfs_check_empty_dir(ntfs_inode *ni)
{ {
ntfs_attr *na; ntfs_attr *na;
int ret = 0; int ret = 0;
if (!(ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)) if (!(ni->mrec->flags & MFT_RECORD_IS_DIRECTORY))
return 0; return 0;
@ -1800,7 +1805,7 @@ int ntfs_check_empty_dir(ntfs_inode *ni)
ntfs_log_perror("Failed to open directory"); ntfs_log_perror("Failed to open directory");
return -1; return -1;
} }
/* Non-empty directory? */ /* Non-empty directory? */
if ((na->data_size != sizeof(INDEX_ROOT) + sizeof(INDEX_ENTRY_HEADER))){ if ((na->data_size != sizeof(INDEX_ROOT) + sizeof(INDEX_ENTRY_HEADER))){
/* Both ENOTEMPTY and EEXIST are ok. We use the more common. */ /* Both ENOTEMPTY and EEXIST are ok. We use the more common. */
@ -1808,7 +1813,7 @@ int ntfs_check_empty_dir(ntfs_inode *ni)
ntfs_log_debug("Directory is not empty\n"); ntfs_log_debug("Directory is not empty\n");
ret = -1; ret = -1;
} }
ntfs_attr_close(na); ntfs_attr_close(na);
return ret; return ret;
} }
@ -1817,23 +1822,23 @@ static int ntfs_check_unlinkable_dir(ntfs_inode *ni, FILE_NAME_ATTR *fn)
{ {
int link_count = le16_to_cpu(ni->mrec->link_count); int link_count = le16_to_cpu(ni->mrec->link_count);
int ret; int ret;
ret = ntfs_check_empty_dir(ni); ret = ntfs_check_empty_dir(ni);
if (!ret || errno != ENOTEMPTY) if (!ret || errno != ENOTEMPTY)
return ret; return ret;
/* /*
* Directory is non-empty, so we can unlink only if there is more than * Directory is non-empty, so we can unlink only if there is more than
* one "real" hard link, i.e. links aren't different DOS and WIN32 names * one "real" hard link, i.e. links aren't different DOS and WIN32 names
*/ */
if ((link_count == 1) || if ((link_count == 1) ||
(link_count == 2 && fn->file_name_type == FILE_NAME_DOS)) { (link_count == 2 && fn->file_name_type == FILE_NAME_DOS)) {
errno = ENOTEMPTY; errno = ENOTEMPTY;
ntfs_log_debug("Non-empty directory without hard links\n"); ntfs_log_debug("Non-empty directory without hard links\n");
goto no_hardlink; goto no_hardlink;
} }
ret = 0; ret = 0;
no_hardlink: no_hardlink:
return ret; return ret;
} }
@ -1872,7 +1877,7 @@ int ntfs_delete(ntfs_volume *vol, const char *pathname,
#endif #endif
ntfs_log_trace("Entering.\n"); ntfs_log_trace("Entering.\n");
if (!ni || !dir_ni || !name || !name_len) { if (!ni || !dir_ni || !name || !name_len) {
ntfs_log_error("Invalid arguments.\n"); ntfs_log_error("Invalid arguments.\n");
errno = EINVAL; errno = EINVAL;
@ -1918,12 +1923,12 @@ search:
else else
continue; continue;
} }
/* Ignore hard links from other directories */ /* Ignore hard links from other directories */
if (dir_ni->mft_no != MREF_LE(fn->parent_directory)) { if (dir_ni->mft_no != MREF_LE(fn->parent_directory)) {
ntfs_log_debug("MFT record numbers don't match " ntfs_log_debug("MFT record numbers don't match "
"(%llu != %llu)\n", "(%llu != %llu)\n",
(long long unsigned)dir_ni->mft_no, (long long unsigned)dir_ni->mft_no,
(long long unsigned)MREF_LE(fn->parent_directory)); (long long unsigned)MREF_LE(fn->parent_directory));
continue; continue;
} }
@ -1931,11 +1936,11 @@ search:
|| ((fn->file_name_type == FILE_NAME_POSIX) || ((fn->file_name_type == FILE_NAME_POSIX)
&& NVolCaseSensitive(ni->vol))) && NVolCaseSensitive(ni->vol)))
case_sensitive = CASE_SENSITIVE; case_sensitive = CASE_SENSITIVE;
if (ntfs_names_are_equal(fn->file_name, fn->file_name_length, if (ntfs_names_are_equal(fn->file_name, fn->file_name_length,
name, name_len, case_sensitive, name, name_len, case_sensitive,
ni->vol->upcase, ni->vol->upcase_len)){ ni->vol->upcase, ni->vol->upcase_len)){
if (fn->file_name_type == FILE_NAME_WIN32) { if (fn->file_name_type == FILE_NAME_WIN32) {
looking_for_dos_name = TRUE; looking_for_dos_name = TRUE;
ntfs_attr_reinit_search_ctx(actx); ntfs_attr_reinit_search_ctx(actx);
@ -1958,13 +1963,13 @@ search:
} }
goto err_out; goto err_out;
} }
if (ntfs_check_unlinkable_dir(ni, fn) < 0) if (ntfs_check_unlinkable_dir(ni, fn) < 0)
goto err_out; goto err_out;
if (ntfs_index_remove(dir_ni, ni, fn, le32_to_cpu(actx->attr->value_length))) if (ntfs_index_remove(dir_ni, ni, fn, le32_to_cpu(actx->attr->value_length)))
goto err_out; goto err_out;
/* /*
* Keep the last name in place, this is useful for undeletion * Keep the last name in place, this is useful for undeletion
* (Windows also does so), however delete the name if it were * (Windows also does so), however delete the name if it were
@ -1977,10 +1982,10 @@ search:
if (ntfs_attr_record_rm(actx)) if (ntfs_attr_record_rm(actx))
goto err_out; goto err_out;
} }
ni->mrec->link_count = cpu_to_le16(le16_to_cpu( ni->mrec->link_count = cpu_to_le16(le16_to_cpu(
ni->mrec->link_count) - 1); ni->mrec->link_count) - 1);
ntfs_inode_mark_dirty(ni); ntfs_inode_mark_dirty(ni);
if (looking_for_dos_name) { if (looking_for_dos_name) {
looking_for_dos_name = FALSE; looking_for_dos_name = FALSE;
@ -2106,7 +2111,7 @@ search:
"Leaving inconsistent metadata.\n"); "Leaving inconsistent metadata.\n");
} }
ni = NULL; ni = NULL;
ok: ok:
ntfs_inode_update_times(dir_ni, NTFS_UPDATE_MCTIME); ntfs_inode_update_times(dir_ni, NTFS_UPDATE_MCTIME);
out: out:
if (actx) if (actx)
@ -2149,14 +2154,14 @@ static int ntfs_link_i(ntfs_inode *ni, ntfs_inode *dir_ni, const ntfschar *name,
int fn_len, err; int fn_len, err;
ntfs_log_trace("Entering.\n"); ntfs_log_trace("Entering.\n");
if (!ni || !dir_ni || !name || !name_len || if (!ni || !dir_ni || !name || !name_len ||
ni->mft_no == dir_ni->mft_no) { ni->mft_no == dir_ni->mft_no) {
err = EINVAL; err = EINVAL;
ntfs_log_perror("ntfs_link wrong arguments"); ntfs_log_perror("ntfs_link wrong arguments");
goto err_out; goto err_out;
} }
if ((ni->flags & FILE_ATTR_REPARSE_POINT) if ((ni->flags & FILE_ATTR_REPARSE_POINT)
&& !ntfs_possible_symlink(ni)) { && !ntfs_possible_symlink(ni)) {
err = EOPNOTSUPP; err = EOPNOTSUPP;
@ -2171,7 +2176,7 @@ static int ntfs_link_i(ntfs_inode *ni, ntfs_inode *dir_ni, const ntfschar *name,
else else
ni->flags &= ~FILE_ATTR_HIDDEN; ni->flags &= ~FILE_ATTR_HIDDEN;
} }
/* Create FILE_NAME attribute. */ /* Create FILE_NAME attribute. */
fn_len = sizeof(FILE_NAME_ATTR) + name_len * sizeof(ntfschar); fn_len = sizeof(FILE_NAME_ATTR) + name_len * sizeof(ntfschar);
fn = ntfs_calloc(fn_len); fn = ntfs_calloc(fn_len);
@ -2559,7 +2564,7 @@ static int set_dos_name(ntfs_inode *ni, ntfs_inode *dir_ni,
if (set_namespace(ni, dir_ni, longname, longlen, if (set_namespace(ni, dir_ni, longname, longlen,
FILE_NAME_WIN32_AND_DOS) >= 0) { FILE_NAME_WIN32_AND_DOS) >= 0) {
if (!ntfs_delete(vol, if (!ntfs_delete(vol,
(const char*)NULL, ni, dir_ni, (const char*)NULL, ni, dir_ni,
deletename, deletelen)) deletename, deletelen))
res = 0; res = 0;
deleted = TRUE; deleted = TRUE;
@ -2580,7 +2585,7 @@ static int set_dos_name(ntfs_inode *ni, ntfs_inode *dir_ni,
res = -1; res = -1;
} }
} else { } else {
if (!ntfs_link_i(ni, dir_ni, shortname, shortlen, if (!ntfs_link_i(ni, dir_ni, shortname, shortlen,
FILE_NAME_DOS) FILE_NAME_DOS)
/* make sure a new link was recorded */ /* make sure a new link was recorded */
&& (le16_to_cpu(ni->mrec->link_count) > linkcount)) { && (le16_to_cpu(ni->mrec->link_count) > linkcount)) {
@ -2756,7 +2761,7 @@ int ntfs_remove_ntfs_dos_name(ntfs_inode *ni, ntfs_inode *dir_ni)
} else { } else {
/* /*
* DOS name has been found, but cannot * DOS name has been found, but cannot
* migrate to Posix : something bad * migrate to Posix : something bad
* has happened * has happened
*/ */
errno = EIO; errno = EIO;

View File

@ -54,6 +54,8 @@
#include <locale.h> #include <locale.h>
#endif #endif
typedef double f64;
#include "ntfs.h" #include "ntfs.h"
#include "types.h" #include "types.h"
#include "logging.h" #include "logging.h"
@ -62,6 +64,7 @@
#include "cache.h" #include "cache.h"
#include "device.h" #include "device.h"
#include "bootsect.h" #include "bootsect.h"
#include "mem_allocate.h"
#define DEV_FD(dev) ((gekko_fd *)dev->d_private) #define DEV_FD(dev) ((gekko_fd *)dev->d_private)
@ -119,7 +122,7 @@ static int ntfs_device_gekko_io_open(struct ntfs_device *dev, int flags)
} }
if (!interface->readSectors(fd->startSector, 1, boot)) { if (!interface->readSectors(fd->startSector, 1, boot)) {
ntfs_log_perror("read failure @ sector %d\n", fd->startSector); ntfs_log_perror("read failure @ sector %d\n", (int)fd->startSector);
errno = EIO; errno = EIO;
ntfs_free(boot); ntfs_free(boot);
return -1; return -1;
@ -318,7 +321,7 @@ static s64 ntfs_device_gekko_io_readbytes(struct ntfs_device *dev, s64 offset, s
// Read from the device // Read from the device
ntfs_log_trace("direct read from sector %d (%d sector(s) long)\n", sec_start, sec_count); ntfs_log_trace("direct read from sector %d (%d sector(s) long)\n", sec_start, sec_count);
if (!ntfs_device_gekko_io_readsectors(dev, sec_start, sec_count, buf)) { if (!ntfs_device_gekko_io_readsectors(dev, sec_start, sec_count, buf)) {
ntfs_log_perror("direct read failure @ sector %d (%d sector(s) long)\n", sec_start, sec_count); ntfs_log_perror("direct read failure @ sector %d (%d sector(s) long)\n", (int)sec_start, (int)sec_count);
errno = EIO; errno = EIO;
return -1; return -1;
} }
@ -336,10 +339,10 @@ static s64 ntfs_device_gekko_io_readbytes(struct ntfs_device *dev, s64 offset, s
} }
// Read from the device // Read from the device
ntfs_log_trace("buffered read from sector %d (%d sector(s) long)\n", sec_start, sec_count); ntfs_log_trace("buffered read from sector %d (%d sector(s) long)\n", (int)sec_start, (int)sec_count);
ntfs_log_trace("count: %d sec_count:%d fd->sectorSize: %d )\n", (u32)count, (u32)sec_count,(u32)fd->sectorSize); ntfs_log_trace("count: %d sec_count:%d fd->sectorSize: %d )\n", (u32)count, (u32)sec_count,(u32)fd->sectorSize);
if (!ntfs_device_gekko_io_readsectors(dev, sec_start, sec_count, buffer)) { if (!ntfs_device_gekko_io_readsectors(dev, sec_start, sec_count, buffer)) {
ntfs_log_perror("buffered read failure @ sector %d (%d sector(s) long)\n", sec_start, sec_count); ntfs_log_perror("buffered read failure @ sector %d (%d sector(s) long)\n", (int)sec_start, (int)sec_count);
ntfs_free(buffer); ntfs_free(buffer);
errno = EIO; errno = EIO;
return -1; return -1;
@ -406,9 +409,9 @@ static s64 ntfs_device_gekko_io_writebytes(struct ntfs_device *dev, s64 offset,
if((buffer_offset == 0) && (count % fd->sectorSize == 0)) if((buffer_offset == 0) && (count % fd->sectorSize == 0))
{ {
// Write to the device // Write to the device
ntfs_log_trace("direct write to sector %d (%d sector(s) long)\n", sec_start, sec_count); ntfs_log_trace("direct write to sector %d (%d sector(s) long)\n", (int)sec_start, (int)sec_count);
if (!ntfs_device_gekko_io_writesectors(dev, sec_start, sec_count, buf)) { if (!ntfs_device_gekko_io_writesectors(dev, sec_start, sec_count, buf)) {
ntfs_log_perror("direct write failure @ sector %d (%d sector(s) long)\n", sec_start, sec_count); ntfs_log_perror("direct write failure @ sector %d (%d sector(s) long)\n", (int)sec_start, (int)sec_count);
errno = EIO; errno = EIO;
return -1; return -1;
} }
@ -428,7 +431,7 @@ static s64 ntfs_device_gekko_io_writebytes(struct ntfs_device *dev, s64 offset,
if(buffer_offset != 0) if(buffer_offset != 0)
{ {
if (!ntfs_device_gekko_io_readsectors(dev, sec_start, 1, buffer)) { if (!ntfs_device_gekko_io_readsectors(dev, sec_start, 1, buffer)) {
ntfs_log_perror("read failure @ sector %d\n", sec_start); ntfs_log_perror("read failure @ sector %d\n", (int)sec_start);
ntfs_free(buffer); ntfs_free(buffer);
errno = EIO; errno = EIO;
return -1; return -1;
@ -437,7 +440,7 @@ static s64 ntfs_device_gekko_io_writebytes(struct ntfs_device *dev, s64 offset,
if((buffer_offset+count) % fd->sectorSize != 0) if((buffer_offset+count) % fd->sectorSize != 0)
{ {
if (!ntfs_device_gekko_io_readsectors(dev, sec_start + sec_count - 1, 1, buffer + ((sec_count-1) * fd->sectorSize))) { if (!ntfs_device_gekko_io_readsectors(dev, sec_start + sec_count - 1, 1, buffer + ((sec_count-1) * fd->sectorSize))) {
ntfs_log_perror("read failure @ sector %d\n", sec_start + sec_count - 1); ntfs_log_perror("read failure @ sector %d\n", (int)sec_start + (int)sec_count - 1);
ntfs_free(buffer); ntfs_free(buffer);
errno = EIO; errno = EIO;
return -1; return -1;
@ -450,7 +453,7 @@ static s64 ntfs_device_gekko_io_writebytes(struct ntfs_device *dev, s64 offset,
// Write to the device // Write to the device
ntfs_log_trace("buffered write to sector %d (%d sector(s) long)\n", sec_start, sec_count); ntfs_log_trace("buffered write to sector %d (%d sector(s) long)\n", sec_start, sec_count);
if (!ntfs_device_gekko_io_writesectors(dev, sec_start, sec_count, buffer)) { if (!ntfs_device_gekko_io_writesectors(dev, sec_start, sec_count, buffer)) {
ntfs_log_perror("buffered write failure @ sector %d\n", sec_start); ntfs_log_perror("buffered write failure @ sector %d\n", (int)sec_start);
ntfs_free(buffer); ntfs_free(buffer);
errno = EIO; errno = EIO;
return -1; return -1;

View File

@ -27,8 +27,18 @@
#include "types.h" #include "types.h"
#include "cache2.h" #include "cache2.h"
#include <gccore.h>
#include <ogc/disc_io.h> #if defined (__WIIU__)
#include <iosuhax_disc_interface.h>
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 <ogc/disc_io.h>
#include <gccore.h>
#endif
#define MAX_SECTOR_SIZE 4096 #define MAX_SECTOR_SIZE 4096
@ -49,6 +59,7 @@ typedef struct _gekko_fd {
u32 cachePageSize; /* The number of sectors per cache page */ u32 cachePageSize; /* The number of sectors per cache page */
} gekko_fd; } gekko_fd;
/* Forward declarations */ /* Forward declarations */
struct ntfs_device_operations; struct ntfs_device_operations;

File diff suppressed because it is too large Load Diff

View File

@ -124,7 +124,7 @@ ntfs_inode *ntfs_inode_allocate(ntfs_volume *vol)
static void __ntfs_inode_release(ntfs_inode *ni) static void __ntfs_inode_release(ntfs_inode *ni)
{ {
if (NInoDirty(ni)) if (NInoDirty(ni))
ntfs_log_error("Releasing dirty inode %lld!\n", ntfs_log_error("Releasing dirty inode %lld!\n",
(long long)ni->mft_no); (long long)ni->mft_no);
if (NInoAttrList(ni) && ni->attr_list) if (NInoAttrList(ni) && ni->attr_list)
free(ni->attr_list); free(ni->attr_list);
@ -243,7 +243,7 @@ static ntfs_inode *ntfs_inode_real_open(ntfs_volume *vol, const MFT_REF mref)
if (l != ni->attr_list_size) { if (l != ni->attr_list_size) {
errno = EIO; errno = EIO;
ntfs_log_perror("Unexpected attrlist size (%lld <> %u), inode " ntfs_log_perror("Unexpected attrlist size (%lld <> %u), inode "
"%lld", (long long)l, ni->attr_list_size, "%lld", (long long)l, (unsigned int) ni->attr_list_size,
(long long)MREF(mref)); (long long)MREF(mref));
goto put_err_out; goto put_err_out;
} }
@ -273,7 +273,7 @@ get_size:
set_nino_flag(ni,KnownSize); set_nino_flag(ni,KnownSize);
} }
ntfs_attr_put_search_ctx(ctx); ntfs_attr_put_search_ctx(ctx);
out: out:
ntfs_log_leave("\n"); ntfs_log_leave("\n");
return ni; return ni;
@ -313,7 +313,7 @@ err_out:
int ntfs_inode_real_close(ntfs_inode *ni) int ntfs_inode_real_close(ntfs_inode *ni)
{ {
int ret = -1; int ret = -1;
if (!ni) if (!ni)
return 0; return 0;
@ -378,8 +378,8 @@ int ntfs_inode_real_close(ntfs_inode *ni)
i = -1; i = -1;
break; break;
} }
/* /*
* We could successfully sync, so only log this error * We could successfully sync, so only log this error
* and try to sync other inode extents too. * and try to sync other inode extents too.
*/ */
@ -387,7 +387,7 @@ int ntfs_inode_real_close(ntfs_inode *ni)
ntfs_log_error("Extent inode %lld was not found\n", ntfs_log_error("Extent inode %lld was not found\n",
(long long)ni->mft_no); (long long)ni->mft_no);
} }
__ntfs_inode_release(ni); __ntfs_inode_release(ni);
ret = 0; ret = 0;
err: err:
@ -585,11 +585,11 @@ ntfs_inode *ntfs_extent_inode_open(ntfs_inode *base_ni, const MFT_REF mref)
ntfs_log_perror("%s", __FUNCTION__); ntfs_log_perror("%s", __FUNCTION__);
return NULL; return NULL;
} }
ntfs_log_enter("Opening extent inode %lld (base mft record %lld).\n", ntfs_log_enter("Opening extent inode %lld (base mft record %lld).\n",
(unsigned long long)mft_no, (unsigned long long)mft_no,
(unsigned long long)base_ni->mft_no); (unsigned long long)base_ni->mft_no);
if (!base_ni->mft_no) { if (!base_ni->mft_no) {
/* /*
* When getting extents of MFT, we must be sure * When getting extents of MFT, we must be sure
@ -833,7 +833,7 @@ static int ntfs_inode_sync_file_name(ntfs_inode *ni, ntfs_inode *dir_ni)
if (dir_ni) if (dir_ni)
index_ni = dir_ni; index_ni = dir_ni;
else else
index_ni = ntfs_inode_open(ni->vol, index_ni = ntfs_inode_open(ni->vol,
le64_to_cpu(fn->parent_directory)); le64_to_cpu(fn->parent_directory));
if (!index_ni) { if (!index_ni) {
if (!err) if (!err)
@ -996,8 +996,8 @@ static int ntfs_inode_sync_in_dir(ntfs_inode *ni, ntfs_inode *dir_ni)
} }
NInoAttrListSetDirty(ni); NInoAttrListSetDirty(ni);
goto sync_inode; goto sync_inode;
} }
if (na->data_size == ni->attr_list_size) { if (na->data_size == ni->attr_list_size) {
if (ntfs_attr_pwrite(na, 0, ni->attr_list_size, if (ntfs_attr_pwrite(na, 0, ni->attr_list_size,
ni->attr_list) != ni->attr_list_size) { ni->attr_list) != ni->attr_list_size) {
@ -1019,7 +1019,7 @@ static int ntfs_inode_sync_in_dir(ntfs_inode *ni, ntfs_inode *dir_ni)
} }
ntfs_attr_close(na); ntfs_attr_close(na);
} }
sync_inode: sync_inode:
/* Write this inode out to the $MFT (and $MFTMirr if applicable). */ /* Write this inode out to the $MFT (and $MFTMirr if applicable). */
if (NInoTestAndClearDirty(ni)) { if (NInoTestAndClearDirty(ni)) {
@ -1045,8 +1045,8 @@ sync_inode:
eni = ni->extent_nis[i]; eni = ni->extent_nis[i];
if (!NInoTestAndClearDirty(eni)) if (!NInoTestAndClearDirty(eni))
continue; continue;
if (ntfs_mft_record_write(eni->vol, eni->mft_no, if (ntfs_mft_record_write(eni->vol, eni->mft_no,
eni->mrec)) { eni->mrec)) {
if (!err || errno == EIO) { if (!err || errno == EIO) {
err = errno; err = errno;
@ -1066,7 +1066,7 @@ sync_inode:
errno = err; errno = err;
ret = -1; ret = -1;
} }
ntfs_log_leave("\n"); ntfs_log_leave("\n");
return ret; return ret;
} }
@ -1135,19 +1135,19 @@ int ntfs_inode_add_attrlist(ntfs_inode *ni)
} }
/* Walk through all attributes. */ /* Walk through all attributes. */
while (!ntfs_attr_lookup(AT_UNUSED, NULL, 0, 0, 0, NULL, 0, ctx)) { while (!ntfs_attr_lookup(AT_UNUSED, NULL, 0, 0, 0, NULL, 0, ctx)) {
int ale_size; int ale_size;
if (ctx->attr->type == AT_ATTRIBUTE_LIST) { if (ctx->attr->type == AT_ATTRIBUTE_LIST) {
err = EIO; err = EIO;
ntfs_log_perror("Attribute list already present"); ntfs_log_perror("Attribute list already present");
goto put_err_out; goto put_err_out;
} }
ale_size = (sizeof(ATTR_LIST_ENTRY) + sizeof(ntfschar) * ale_size = (sizeof(ATTR_LIST_ENTRY) + sizeof(ntfschar) *
ctx->attr->name_length + 7) & ~7; ctx->attr->name_length + 7) & ~7;
al_len += ale_size; al_len += ale_size;
aln = realloc(al, al_len); aln = realloc(al, al_len);
if (!aln) { if (!aln) {
err = errno; err = errno;
@ -1156,9 +1156,9 @@ int ntfs_inode_add_attrlist(ntfs_inode *ni)
} }
ale = (ATTR_LIST_ENTRY *)(aln + ((u8 *)ale - al)); ale = (ATTR_LIST_ENTRY *)(aln + ((u8 *)ale - al));
al = aln; al = aln;
memset(ale, 0, ale_size); memset(ale, 0, ale_size);
/* Add attribute to attribute list. */ /* Add attribute to attribute list. */
ale->type = ctx->attr->type; ale->type = ctx->attr->type;
ale->length = cpu_to_le16((sizeof(ATTR_LIST_ENTRY) + ale->length = cpu_to_le16((sizeof(ATTR_LIST_ENTRY) +
@ -1225,7 +1225,7 @@ int ntfs_inode_add_attrlist(ntfs_inode *ni)
ntfs_attr_close(na); ntfs_attr_close(na);
goto remove_attrlist_record;; goto remove_attrlist_record;;
} }
ntfs_attr_put_search_ctx(ctx); ntfs_attr_put_search_ctx(ctx);
ntfs_attr_close(na); ntfs_attr_close(na);
return 0; return 0;
@ -1326,12 +1326,12 @@ int ntfs_inode_free_space(ntfs_inode *ni, int size)
* find next, because we don't need such. * find next, because we don't need such.
*/ */
while (ctx->ntfs_ino->mft_no != ni->mft_no) { while (ctx->ntfs_ino->mft_no != ni->mft_no) {
retry: retry:
if (ntfs_attr_position(AT_UNUSED, ctx)) if (ntfs_attr_position(AT_UNUSED, ctx))
goto put_err_out; goto put_err_out;
} }
if (ntfs_inode_base(ctx->ntfs_ino)->mft_no == FILE_MFT && if (ntfs_inode_base(ctx->ntfs_ino)->mft_no == FILE_MFT &&
ctx->attr->type == AT_DATA) ctx->attr->type == AT_DATA)
goto retry; goto retry;
@ -1352,10 +1352,10 @@ retry:
return 0; return 0;
} }
/* /*
* Reposition to first attribute after $STANDARD_INFORMATION * Reposition to first attribute after $STANDARD_INFORMATION
* and $ATTRIBUTE_LIST instead of simply skipping this attribute * and $ATTRIBUTE_LIST instead of simply skipping this attribute
* because in the case when we have got only in-memory attribute * because in the case when we have got only in-memory attribute
* list then ntfs_attr_lookup will fail when it tries to find * list then ntfs_attr_lookup will fail when it tries to find
* $ATTRIBUTE_LIST. * $ATTRIBUTE_LIST.
*/ */
ntfs_attr_reinit_search_ctx(ctx); ntfs_attr_reinit_search_ctx(ctx);
@ -1397,7 +1397,7 @@ void ntfs_inode_update_times(ntfs_inode *ni, ntfs_time_update_flags mask)
ni->last_data_change_time = now; ni->last_data_change_time = now;
if (mask & NTFS_UPDATE_CTIME) if (mask & NTFS_UPDATE_CTIME)
ni->last_mft_change_time = now; ni->last_mft_change_time = now;
NInoFileNameSetDirty(ni); NInoFileNameSetDirty(ni);
NInoSetDirty(ni); NInoSetDirty(ni);
} }
@ -1410,7 +1410,7 @@ void ntfs_inode_update_times(ntfs_inode *ni, ntfs_time_update_flags mask)
* Check if the mft record given by @mft_no and @attr contains the bad sector * Check if the mft record given by @mft_no and @attr contains the bad sector
* list. Please note that mft record numbers describing $Badclus extent inodes * list. Please note that mft record numbers describing $Badclus extent inodes
* will not match the current $Badclus:$Bad check. * will not match the current $Badclus:$Bad check.
* *
* On success return 1 if the file is $Badclus:$Bad, otherwise return 0. * On success return 1 if the file is $Badclus:$Bad, otherwise return 0.
* On error return -1 with errno set to the error code. * On error return -1 with errno set to the error code.
*/ */
@ -1424,7 +1424,7 @@ int ntfs_inode_badclus_bad(u64 mft_no, ATTR_RECORD *attr)
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }
if (mft_no != FILE_BadClus) if (mft_no != FILE_BadClus)
return 0; return 0;
@ -1498,7 +1498,7 @@ int ntfs_inode_get_times(ntfs_inode *ni, char *value, size_t size)
ret = -ERANGE; ret = -ERANGE;
} }
ntfs_attr_put_search_ctx(ctx); ntfs_attr_put_search_ctx(ctx);
} }
return (ret ? ret : -errno); return (ret ? ret : -errno);
} }

28
source/lock.c Normal file
View File

@ -0,0 +1,28 @@
#ifndef USE_LWP_LOCK
#ifndef mutex_t
typedef int mutex_t;
#endif
void __attribute__ ((weak)) _NTFS_lock_init(mutex_t *mutex, int unkwn)
{
return;
}
void __attribute__ ((weak)) _NTFS_lock_deinit(mutex_t *mutex)
{
return;
}
void __attribute__ ((weak)) _NTFS_lock(mutex_t *mutex)
{
return;
}
void __attribute__ ((weak)) _NTFS_unlock(mutex_t *mutex)
{
return;
}
#endif // USE_LWP_LOCK

108
source/lock.h Normal file
View File

@ -0,0 +1,108 @@
/*
lock.h
Copyright (c) 2008 Sven Peter <svpe@gmx.net>
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _LOCK_H
#define _LOCK_H
#ifdef USE_LWP_LOCK
static inline void _NTFS_lock_init(mutex_t *mutex, int unkwn)
{
LWP_MutexInit(mutex, false);
}
static inline void _NTFS_lock_deinit(mutex_t *mutex)
{
LWP_MutexDestroy(*mutex);
}
static inline void _NTFS_lock(mutex_t *mutex)
{
LWP_MutexLock(*mutex);
}
static inline void _NTFS_unlock(mutex_t *mutex)
{
LWP_MutexUnlock(*mutex);
}
/* //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

View File

@ -85,7 +85,7 @@ int ntfs_mft_records_read(const ntfs_volume *vol, const MFT_REF mref,
VCN m; VCN m;
ntfs_log_trace("inode %llu\n", (unsigned long long)MREF(mref)); ntfs_log_trace("inode %llu\n", (unsigned long long)MREF(mref));
if (!vol || !vol->mft_na || !b || count < 0) { if (!vol || !vol->mft_na || !b || count < 0) {
errno = EINVAL; errno = EINVAL;
ntfs_log_perror("%s: b=%p count=%lld mft=%llu", __FUNCTION__, ntfs_log_perror("%s: b=%p count=%lld mft=%llu", __FUNCTION__,
@ -209,12 +209,12 @@ int ntfs_mft_records_write(const ntfs_volume *vol, const MFT_REF mref,
return -1; return -1;
} }
int ntfs_mft_record_check(const ntfs_volume *vol, const MFT_REF mref, int ntfs_mft_record_check(const ntfs_volume *vol, const MFT_REF mref,
MFT_RECORD *m) MFT_RECORD *m)
{ {
ATTR_RECORD *a; ATTR_RECORD *a;
int ret = -1; int ret = -1;
if (!ntfs_is_file_record(m->magic)) { if (!ntfs_is_file_record(m->magic)) {
if (!NVolNoFixupWarn(vol)) if (!NVolNoFixupWarn(vol))
ntfs_log_error("Record %llu has no FILE magic (0x%x)\n", ntfs_log_error("Record %llu has no FILE magic (0x%x)\n",
@ -222,22 +222,22 @@ int ntfs_mft_record_check(const ntfs_volume *vol, const MFT_REF mref,
(int)le32_to_cpu(*(le32*)m)); (int)le32_to_cpu(*(le32*)m));
goto err_out; goto err_out;
} }
if (le32_to_cpu(m->bytes_allocated) != vol->mft_record_size) { if (le32_to_cpu(m->bytes_allocated) != vol->mft_record_size) {
ntfs_log_error("Record %llu has corrupt allocation size " ntfs_log_error("Record %llu has corrupt allocation size "
"(%u <> %u)\n", (unsigned long long)MREF(mref), "(%u <> %u)\n", (unsigned long long)MREF(mref),
vol->mft_record_size, (unsigned int) vol->mft_record_size,
le32_to_cpu(m->bytes_allocated)); (unsigned int) le32_to_cpu(m->bytes_allocated));
goto err_out; goto err_out;
} }
a = (ATTR_RECORD *)((char *)m + le16_to_cpu(m->attrs_offset)); a = (ATTR_RECORD *)((char *)m + le16_to_cpu(m->attrs_offset));
if (p2n(a) < p2n(m) || (char *)a > (char *)m + vol->mft_record_size) { if (p2n(a) < p2n(m) || (char *)a > (char *)m + vol->mft_record_size) {
ntfs_log_error("Record %llu is corrupt\n", ntfs_log_error("Record %llu is corrupt\n",
(unsigned long long)MREF(mref)); (unsigned long long)MREF(mref));
goto err_out; goto err_out;
} }
ret = 0; ret = 0;
err_out: err_out:
if (ret) if (ret)
@ -286,7 +286,7 @@ int ntfs_file_record_read(const ntfs_volume *vol, const MFT_REF mref,
ntfs_log_perror("%s: mrec=%p", __FUNCTION__, mrec); ntfs_log_perror("%s: mrec=%p", __FUNCTION__, mrec);
return -1; return -1;
} }
m = *mrec; m = *mrec;
if (!m) { if (!m) {
m = ntfs_malloc(vol->mft_record_size); m = ntfs_malloc(vol->mft_record_size);
@ -298,7 +298,7 @@ int ntfs_file_record_read(const ntfs_volume *vol, const MFT_REF mref,
if (ntfs_mft_record_check(vol, mref, m)) if (ntfs_mft_record_check(vol, mref, m))
goto err_out; goto err_out;
if (MSEQNO(mref) && MSEQNO(mref) != le16_to_cpu(m->sequence_number)) { if (MSEQNO(mref) && MSEQNO(mref) != le16_to_cpu(m->sequence_number)) {
ntfs_log_error("Record %llu has wrong SeqNo (%d <> %d)\n", ntfs_log_error("Record %llu has wrong SeqNo (%d <> %d)\n",
(unsigned long long)MREF(mref), MSEQNO(mref), (unsigned long long)MREF(mref), MSEQNO(mref),
@ -412,21 +412,21 @@ int ntfs_mft_record_format(const ntfs_volume *vol, const MFT_REF mref)
int ret = -1; int ret = -1;
ntfs_log_enter("Entering\n"); ntfs_log_enter("Entering\n");
m = ntfs_calloc(vol->mft_record_size); m = ntfs_calloc(vol->mft_record_size);
if (!m) if (!m)
goto out; goto out;
if (ntfs_mft_record_layout(vol, mref, m)) if (ntfs_mft_record_layout(vol, mref, m))
goto free_m; goto free_m;
if (ntfs_mft_record_write(vol, mref, m)) if (ntfs_mft_record_write(vol, mref, m))
goto free_m; goto free_m;
ret = 0; ret = 0;
free_m: free_m:
free(m); free(m);
out: out:
ntfs_log_leave("\n"); ntfs_log_leave("\n");
return ret; return ret;
} }
@ -486,7 +486,7 @@ static int ntfs_mft_bitmap_find_free_rec(ntfs_volume *vol, ntfs_inode *base_ni)
int ret = -1; int ret = -1;
ntfs_log_enter("Entering\n"); ntfs_log_enter("Entering\n");
mftbmp_na = vol->mftbmp_na; mftbmp_na = vol->mftbmp_na;
/* /*
* Set the end of the pass making sure we do not overflow the mft * Set the end of the pass making sure we do not overflow the mft
@ -521,7 +521,7 @@ static int ntfs_mft_bitmap_find_free_rec(ntfs_volume *vol, ntfs_inode *base_ni)
buf = ntfs_malloc(PAGE_SIZE); buf = ntfs_malloc(PAGE_SIZE);
if (!buf) if (!buf)
goto leave; goto leave;
ntfs_log_debug("Starting bitmap search: pass %u, pass_start 0x%llx, " ntfs_log_debug("Starting bitmap search: pass %u, pass_start 0x%llx, "
"pass_end 0x%llx, data_pos 0x%llx.\n", pass, "pass_end 0x%llx, data_pos 0x%llx.\n", pass,
(long long)pass_start, (long long)pass_end, (long long)pass_start, (long long)pass_end,
@ -556,18 +556,18 @@ static int ntfs_mft_bitmap_find_free_rec(ntfs_volume *vol, ntfs_inode *base_ni)
byte ? *byte : -1, b); byte ? *byte : -1, b);
for (; bit < size && data_pos + bit < pass_end; for (; bit < size && data_pos + bit < pass_end;
bit &= ~7ull, bit += 8) { bit &= ~7ull, bit += 8) {
/* /*
* If we're extending $MFT and running out of the first * If we're extending $MFT and running out of the first
* mft record (base record) then give up searching since * mft record (base record) then give up searching since
* no guarantee that the found record will be accessible. * no guarantee that the found record will be accessible.
*/ */
if (ntfs_is_mft(base_ni) && bit > 400) if (ntfs_is_mft(base_ni) && bit > 400)
goto out; goto out;
byte = buf + (bit >> 3); byte = buf + (bit >> 3);
if (*byte == 0xff) if (*byte == 0xff)
continue; continue;
/* Note: ffz() result must be zero based. */ /* Note: ffz() result must be zero based. */
b = ntfs_ffz((unsigned long)*byte); b = ntfs_ffz((unsigned long)*byte);
if (b < 8 && b >= (bit & 7)) { if (b < 8 && b >= (bit & 7)) {
@ -606,7 +606,7 @@ static int ntfs_mft_bitmap_find_free_rec(ntfs_volume *vol, ntfs_inode *base_ni)
} }
} }
/* No free mft records in currently initialized mft bitmap. */ /* No free mft records in currently initialized mft bitmap. */
out: out:
free(buf); free(buf);
errno = ENOSPC; errno = ENOSPC;
leave: leave:
@ -633,9 +633,9 @@ static int ntfs_mft_attr_extend(ntfs_attr *na)
ntfs_log_perror("%s: MP update failed", __FUNCTION__); ntfs_log_perror("%s: MP update failed", __FUNCTION__);
goto out; goto out;
} }
ret = STATUS_OK; ret = STATUS_OK;
out: out:
ntfs_log_leave("\n"); ntfs_log_leave("\n");
return ret; return ret;
} }
@ -673,7 +673,7 @@ static int ntfs_mft_bitmap_extend_allocation_i(ntfs_volume *vol)
return STATUS_ERROR; return STATUS_ERROR;
} }
lcn = rl->lcn + rl->length; lcn = rl->lcn + rl->length;
rl2 = ntfs_cluster_alloc(vol, rl[1].vcn, 1, lcn, DATA_ZONE); rl2 = ntfs_cluster_alloc(vol, rl[1].vcn, 1, lcn, DATA_ZONE);
if (!rl2) { if (!rl2) {
ntfs_log_error("Failed to allocate a cluster for " ntfs_log_error("Failed to allocate a cluster for "
@ -809,7 +809,7 @@ undo_alloc:
lcn = rl->lcn; lcn = rl->lcn;
rl->lcn = rl[1].lcn; rl->lcn = rl[1].lcn;
rl->length = 0; rl->length = 0;
/* FIXME: use an ntfs_cluster_free_* function */ /* FIXME: use an ntfs_cluster_free_* function */
if (ntfs_bitmap_clear_bit(vol->lcnbmp_na, lcn)) if (ntfs_bitmap_clear_bit(vol->lcnbmp_na, lcn))
ntfs_log_error("Failed to free cluster.%s\n", es); ntfs_log_error("Failed to free cluster.%s\n", es);
@ -851,7 +851,7 @@ undo_alloc:
static int ntfs_mft_bitmap_extend_allocation(ntfs_volume *vol) static int ntfs_mft_bitmap_extend_allocation(ntfs_volume *vol)
{ {
int ret; int ret;
ntfs_log_enter("Entering\n"); ntfs_log_enter("Entering\n");
ret = ntfs_mft_bitmap_extend_allocation_i(vol); ret = ntfs_mft_bitmap_extend_allocation_i(vol);
ntfs_log_leave("\n"); ntfs_log_leave("\n");
@ -879,7 +879,7 @@ static int ntfs_mft_bitmap_extend_initialized(ntfs_volume *vol)
int ret = -1; int ret = -1;
ntfs_log_enter("Entering\n"); ntfs_log_enter("Entering\n");
mftbmp_na = vol->mftbmp_na; mftbmp_na = vol->mftbmp_na;
ctx = ntfs_attr_get_search_ctx(mftbmp_na->ni, NULL); ctx = ntfs_attr_get_search_ctx(mftbmp_na->ni, NULL);
if (!ctx) if (!ctx)
@ -909,7 +909,7 @@ static int ntfs_mft_bitmap_extend_initialized(ntfs_volume *vol)
ll = ntfs_attr_pwrite(mftbmp_na, old_initialized_size, 8, &ll); ll = ntfs_attr_pwrite(mftbmp_na, old_initialized_size, 8, &ll);
if (ll == 8) { if (ll == 8) {
ntfs_log_debug("Wrote eight initialized bytes to mft bitmap.\n"); ntfs_log_debug("Wrote eight initialized bytes to mft bitmap.\n");
vol->free_mft_records += (8 * 8); vol->free_mft_records += (8 * 8);
ret = 0; ret = 0;
goto out; goto out;
} }
@ -981,7 +981,7 @@ static int ntfs_mft_data_extend_allocation(ntfs_volume *vol)
BOOL update_mp = FALSE; BOOL update_mp = FALSE;
ntfs_log_enter("Extending mft data allocation.\n"); ntfs_log_enter("Extending mft data allocation.\n");
mft_na = vol->mft_na; mft_na = vol->mft_na;
/* /*
* Determine the preferred allocation location, i.e. the last lcn of * Determine the preferred allocation location, i.e. the last lcn of
@ -990,7 +990,7 @@ static int ntfs_mft_data_extend_allocation(ntfs_volume *vol)
*/ */
rl = ntfs_attr_find_vcn(mft_na, rl = ntfs_attr_find_vcn(mft_na,
(mft_na->allocated_size - 1) >> vol->cluster_size_bits); (mft_na->allocated_size - 1) >> vol->cluster_size_bits);
if (!rl || !rl->length || rl->lcn < 0) { if (!rl || !rl->length || rl->lcn < 0) {
ntfs_log_error("Failed to determine last allocated " ntfs_log_error("Failed to determine last allocated "
"cluster of mft data attribute.\n"); "cluster of mft data attribute.\n");
@ -998,7 +998,7 @@ static int ntfs_mft_data_extend_allocation(ntfs_volume *vol)
errno = EIO; errno = EIO;
goto out; goto out;
} }
lcn = rl->lcn + rl->length; lcn = rl->lcn + rl->length;
ntfs_log_debug("Last lcn of mft data attribute is 0x%llx.\n", (long long)lcn); ntfs_log_debug("Last lcn of mft data attribute is 0x%llx.\n", (long long)lcn);
/* Minimum allocation is one mft record worth of clusters. */ /* Minimum allocation is one mft record worth of clusters. */
@ -1009,7 +1009,7 @@ static int ntfs_mft_data_extend_allocation(ntfs_volume *vol)
nr = vol->mft_record_size << 4 >> vol->cluster_size_bits; nr = vol->mft_record_size << 4 >> vol->cluster_size_bits;
if (!nr) if (!nr)
nr = min_nr; nr = min_nr;
old_last_vcn = rl[1].vcn; old_last_vcn = rl[1].vcn;
do { do {
rl2 = ntfs_cluster_alloc(vol, old_last_vcn, nr, lcn, MFT_ZONE); rl2 = ntfs_cluster_alloc(vol, old_last_vcn, nr, lcn, MFT_ZONE);
@ -1029,9 +1029,9 @@ static int ntfs_mft_data_extend_allocation(ntfs_volume *vol)
ntfs_log_debug("Retrying mft data allocation with minimal cluster " ntfs_log_debug("Retrying mft data allocation with minimal cluster "
"count %lli.\n", (long long)nr); "count %lli.\n", (long long)nr);
} while (1); } while (1);
ntfs_log_debug("Allocated %lld clusters.\n", (long long)nr); ntfs_log_debug("Allocated %lld clusters.\n", (long long)nr);
rl = ntfs_runlists_merge(mft_na->rl, rl2); rl = ntfs_runlists_merge(mft_na->rl, rl2);
if (!rl) { if (!rl) {
err = errno; err = errno;
@ -1045,7 +1045,7 @@ static int ntfs_mft_data_extend_allocation(ntfs_volume *vol)
goto out; goto out;
} }
mft_na->rl = rl; mft_na->rl = rl;
/* Find the last run in the new runlist. */ /* Find the last run in the new runlist. */
for (; rl[1].length; rl++) for (; rl[1].length; rl++)
; ;
@ -1195,13 +1195,13 @@ static int ntfs_mft_record_init(ntfs_volume *vol, s64 size)
ntfs_attr *mft_na; ntfs_attr *mft_na;
s64 old_data_initialized, old_data_size; s64 old_data_initialized, old_data_size;
ntfs_attr_search_ctx *ctx; ntfs_attr_search_ctx *ctx;
ntfs_log_enter("Entering\n"); ntfs_log_enter("Entering\n");
/* NOTE: Caller must sanity check vol, vol->mft_na and vol->mftbmp_na */ /* NOTE: Caller must sanity check vol, vol->mft_na and vol->mftbmp_na */
mft_na = vol->mft_na; mft_na = vol->mft_na;
/* /*
* The mft record is outside the initialized data. Extend the mft data * The mft record is outside the initialized data. Extend the mft data
* attribute until it covers the allocated record. The loop is only * attribute until it covers the allocated record. The loop is only
@ -1224,10 +1224,10 @@ static int ntfs_mft_record_init(ntfs_volume *vol, s64 size)
(long long)mft_na->data_size, (long long)mft_na->data_size,
(long long)mft_na->initialized_size); (long long)mft_na->initialized_size);
} }
old_data_initialized = mft_na->initialized_size; old_data_initialized = mft_na->initialized_size;
old_data_size = mft_na->data_size; old_data_size = mft_na->data_size;
/* /*
* Extend mft data initialized size (and data size of course) to reach * Extend mft data initialized size (and data size of course) to reach
* the allocated mft record, formatting the mft records along the way. * the allocated mft record, formatting the mft records along the way.
@ -1246,7 +1246,7 @@ static int ntfs_mft_record_init(ntfs_volume *vol, s64 size)
goto undo_data_init; goto undo_data_init;
} }
} }
/* Update the mft data attribute record to reflect the new sizes. */ /* Update the mft data attribute record to reflect the new sizes. */
ctx = ntfs_attr_get_search_ctx(mft_na->ni, NULL); ctx = ntfs_attr_get_search_ctx(mft_na->ni, NULL);
if (!ctx) if (!ctx)
@ -1262,7 +1262,7 @@ static int ntfs_mft_record_init(ntfs_volume *vol, s64 size)
ctx->attr->initialized_size = cpu_to_sle64(mft_na->initialized_size); ctx->attr->initialized_size = cpu_to_sle64(mft_na->initialized_size);
ctx->attr->data_size = cpu_to_sle64(mft_na->data_size); ctx->attr->data_size = cpu_to_sle64(mft_na->data_size);
ctx->attr->allocated_size = cpu_to_sle64(mft_na->allocated_size); ctx->attr->allocated_size = cpu_to_sle64(mft_na->allocated_size);
/* Ensure the changes make it to disk. */ /* Ensure the changes make it to disk. */
ntfs_inode_mark_dirty(ctx->ntfs_ino); ntfs_inode_mark_dirty(ctx->ntfs_ino);
ntfs_attr_put_search_ctx(ctx); ntfs_attr_put_search_ctx(ctx);
@ -1272,21 +1272,21 @@ static int ntfs_mft_record_init(ntfs_volume *vol, s64 size)
(long long)mft_na->allocated_size, (long long)mft_na->allocated_size,
(long long)mft_na->data_size, (long long)mft_na->data_size,
(long long)mft_na->initialized_size); (long long)mft_na->initialized_size);
/* Sanity checks. */ /* Sanity checks. */
if (mft_na->data_size > mft_na->allocated_size || if (mft_na->data_size > mft_na->allocated_size ||
mft_na->initialized_size > mft_na->data_size) mft_na->initialized_size > mft_na->data_size)
NTFS_BUG("mft_na sanity checks failed"); NTFS_BUG("mft_na sanity checks failed");
/* Sync MFT to minimize data loss if there won't be clean unmount. */ /* Sync MFT to minimize data loss if there won't be clean unmount. */
if (ntfs_inode_sync(mft_na->ni)) if (ntfs_inode_sync(mft_na->ni))
goto undo_data_init; goto undo_data_init;
ret = 0; ret = 0;
out: out:
ntfs_log_leave("\n"); ntfs_log_leave("\n");
return ret; return ret;
undo_data_init: undo_data_init:
mft_na->initialized_size = old_data_initialized; mft_na->initialized_size = old_data_initialized;
mft_na->data_size = old_data_size; mft_na->data_size = old_data_size;
@ -1299,11 +1299,11 @@ static int ntfs_mft_rec_init(ntfs_volume *vol, s64 size)
ntfs_attr *mft_na; ntfs_attr *mft_na;
s64 old_data_initialized, old_data_size; s64 old_data_initialized, old_data_size;
ntfs_attr_search_ctx *ctx; ntfs_attr_search_ctx *ctx;
ntfs_log_enter("Entering\n"); ntfs_log_enter("Entering\n");
mft_na = vol->mft_na; mft_na = vol->mft_na;
if (size > mft_na->allocated_size || size > mft_na->initialized_size) { if (size > mft_na->allocated_size || size > mft_na->initialized_size) {
errno = EIO; errno = EIO;
ntfs_log_perror("%s: unexpected $MFT sizes, see below", __FUNCTION__); ntfs_log_perror("%s: unexpected $MFT sizes, see below", __FUNCTION__);
@ -1315,10 +1315,10 @@ static int ntfs_mft_rec_init(ntfs_volume *vol, s64 size)
(long long)mft_na->initialized_size); (long long)mft_na->initialized_size);
goto out; goto out;
} }
old_data_initialized = mft_na->initialized_size; old_data_initialized = mft_na->initialized_size;
old_data_size = mft_na->data_size; old_data_size = mft_na->data_size;
/* Update the mft data attribute record to reflect the new sizes. */ /* Update the mft data attribute record to reflect the new sizes. */
ctx = ntfs_attr_get_search_ctx(mft_na->ni, NULL); ctx = ntfs_attr_get_search_ctx(mft_na->ni, NULL);
if (!ctx) if (!ctx)
@ -1335,19 +1335,19 @@ static int ntfs_mft_rec_init(ntfs_volume *vol, s64 size)
ctx->attr->data_size = cpu_to_sle64(mft_na->data_size); ctx->attr->data_size = cpu_to_sle64(mft_na->data_size);
/* CHECKME: ctx->attr->allocation_size is already ok? */ /* CHECKME: ctx->attr->allocation_size is already ok? */
/* Ensure the changes make it to disk. */ /* Ensure the changes make it to disk. */
ntfs_inode_mark_dirty(ctx->ntfs_ino); ntfs_inode_mark_dirty(ctx->ntfs_ino);
ntfs_attr_put_search_ctx(ctx); ntfs_attr_put_search_ctx(ctx);
/* Sanity checks. */ /* Sanity checks. */
if (mft_na->data_size > mft_na->allocated_size || if (mft_na->data_size > mft_na->allocated_size ||
mft_na->initialized_size > mft_na->data_size) mft_na->initialized_size > mft_na->data_size)
NTFS_BUG("mft_na sanity checks failed"); NTFS_BUG("mft_na sanity checks failed");
out: out:
ntfs_log_leave("\n"); ntfs_log_leave("\n");
return ret; return ret;
undo_data_init: undo_data_init:
mft_na->initialized_size = old_data_initialized; mft_na->initialized_size = old_data_initialized;
mft_na->data_size = old_data_size; mft_na->data_size = old_data_size;
@ -1377,7 +1377,7 @@ static ntfs_inode *ntfs_mft_rec_alloc(ntfs_volume *vol)
if (errno != ENOSPC) if (errno != ENOSPC)
goto out; goto out;
errno = ENOSPC; errno = ENOSPC;
/* strerror() is intentionally used below, we want to log this error. */ /* strerror() is intentionally used below, we want to log this error. */
ntfs_log_error("No free mft record for $MFT: %s\n", strerror(errno)); ntfs_log_error("No free mft record for $MFT: %s\n", strerror(errno));
@ -1388,7 +1388,7 @@ found_free_rec:
ntfs_log_error("Failed to allocate bit in mft bitmap #2\n"); ntfs_log_error("Failed to allocate bit in mft bitmap #2\n");
goto err_out; goto err_out;
} }
ll = (bit + 1) << vol->mft_record_size_bits; ll = (bit + 1) << vol->mft_record_size_bits;
if (ll > mft_na->initialized_size) if (ll > mft_na->initialized_size)
if (ntfs_mft_rec_init(vol, ll) < 0) if (ntfs_mft_rec_init(vol, ll) < 0)
@ -1402,7 +1402,7 @@ found_free_rec:
m = ntfs_malloc(vol->mft_record_size); m = ntfs_malloc(vol->mft_record_size);
if (!m) if (!m)
goto undo_mftbmp_alloc; goto undo_mftbmp_alloc;
if (ntfs_mft_record_read(vol, bit, m)) { if (ntfs_mft_record_read(vol, bit, m)) {
free(m); free(m);
goto undo_mftbmp_alloc; goto undo_mftbmp_alloc;
@ -1470,7 +1470,7 @@ found_free_rec:
base_ni->extent_nis = extent_nis; base_ni->extent_nis = extent_nis;
} }
base_ni->extent_nis[base_ni->nr_extents++] = ni; base_ni->extent_nis[base_ni->nr_extents++] = ni;
/* Make sure the allocated inode is written out to disk later. */ /* Make sure the allocated inode is written out to disk later. */
ntfs_inode_mark_dirty(ni); ntfs_inode_mark_dirty(ni);
/* Initialize time, allocated and data size in ntfs_inode struct. */ /* Initialize time, allocated and data size in ntfs_inode struct. */
@ -1486,7 +1486,7 @@ found_free_rec:
ntfs_log_error("allocated %sinode %lld\n", ntfs_log_error("allocated %sinode %lld\n",
base_ni ? "extent " : "", (long long)bit); base_ni ? "extent " : "", (long long)bit);
out: out:
ntfs_log_leave("\n"); ntfs_log_leave("\n");
return ni; return ni;
undo_mftbmp_alloc: undo_mftbmp_alloc:
@ -1498,7 +1498,7 @@ err_out:
if (!errno) if (!errno)
errno = EIO; errno = EIO;
ni = NULL; ni = NULL;
goto out; goto out;
} }
/** /**
@ -1595,7 +1595,7 @@ ntfs_inode *ntfs_mft_record_alloc(ntfs_volume *vol, ntfs_inode *base_ni)
if (base_ni) if (base_ni)
ntfs_log_enter("Entering (allocating an extent mft record for " ntfs_log_enter("Entering (allocating an extent mft record for "
"base mft record %lld).\n", "base mft record %lld).\n",
(long long)base_ni->mft_no); (long long)base_ni->mft_no);
else else
ntfs_log_enter("Entering (allocating a base mft record)\n"); ntfs_log_enter("Entering (allocating a base mft record)\n");
@ -1603,7 +1603,7 @@ ntfs_inode *ntfs_mft_record_alloc(ntfs_volume *vol, ntfs_inode *base_ni)
errno = EINVAL; errno = EINVAL;
goto out; goto out;
} }
if (ntfs_is_mft(base_ni)) { if (ntfs_is_mft(base_ni)) {
ni = ntfs_mft_rec_alloc(vol); ni = ntfs_mft_rec_alloc(vol);
goto out; goto out;
@ -1611,7 +1611,7 @@ ntfs_inode *ntfs_mft_record_alloc(ntfs_volume *vol, ntfs_inode *base_ni)
mft_na = vol->mft_na; mft_na = vol->mft_na;
mftbmp_na = vol->mftbmp_na; mftbmp_na = vol->mftbmp_na;
retry: retry:
bit = ntfs_mft_bitmap_find_free_rec(vol, base_ni); bit = ntfs_mft_bitmap_find_free_rec(vol, base_ni);
if (bit >= 0) { if (bit >= 0) {
ntfs_log_debug("found free record (#1) at %lld\n", ntfs_log_debug("found free record (#1) at %lld\n",
@ -1688,7 +1688,7 @@ found_free_rec:
ntfs_log_error("Failed to allocate bit in mft bitmap.\n"); ntfs_log_error("Failed to allocate bit in mft bitmap.\n");
goto err_out; goto err_out;
} }
/* The mft bitmap is now uptodate. Deal with mft data attribute now. */ /* The mft bitmap is now uptodate. Deal with mft data attribute now. */
ll = (bit + 1) << vol->mft_record_size_bits; ll = (bit + 1) << vol->mft_record_size_bits;
if (ll > mft_na->initialized_size) if (ll > mft_na->initialized_size)
@ -1704,7 +1704,7 @@ found_free_rec:
m = ntfs_malloc(vol->mft_record_size); m = ntfs_malloc(vol->mft_record_size);
if (!m) if (!m)
goto undo_mftbmp_alloc; goto undo_mftbmp_alloc;
if (ntfs_mft_record_read(vol, bit, m)) { if (ntfs_mft_record_read(vol, bit, m)) {
free(m); free(m);
goto undo_mftbmp_alloc; goto undo_mftbmp_alloc;
@ -1787,9 +1787,9 @@ found_free_rec:
/* Return the opened, allocated inode of the allocated mft record. */ /* Return the opened, allocated inode of the allocated mft record. */
ntfs_log_debug("allocated %sinode 0x%llx.\n", ntfs_log_debug("allocated %sinode 0x%llx.\n",
base_ni ? "extent " : "", (long long)bit); base_ni ? "extent " : "", (long long)bit);
vol->free_mft_records--; vol->free_mft_records--;
out: out:
ntfs_log_leave("\n"); ntfs_log_leave("\n");
return ni; return ni;
undo_mftbmp_alloc: undo_mftbmp_alloc:
@ -1801,7 +1801,7 @@ err_out:
if (!errno) if (!errno)
errno = EIO; errno = EIO;
ni = NULL; ni = NULL;
goto out; goto out;
} }
/** /**
@ -1865,7 +1865,7 @@ int ntfs_mft_record_free(ntfs_volume *vol, ntfs_inode *ni)
#else #else
if (!ntfs_inode_close(ni)) { if (!ntfs_inode_close(ni)) {
#endif #endif
vol->free_mft_records++; vol->free_mft_records++;
return 0; return 0;
} }
err = errno; err = errno;

View File

@ -101,7 +101,7 @@ int ntfs_mst_post_read_fixup_warn(NTFS_RECORD *b, const u32 size,
errno = EIO; errno = EIO;
ntfs_log_perror("Incomplete multi-sector transfer: " ntfs_log_perror("Incomplete multi-sector transfer: "
"magic: 0x%08x size: %d usa_ofs: %d usa_count:" "magic: 0x%08x size: %d usa_ofs: %d usa_count:"
" %d data: %d usn: %d", *(le32 *)b, size, " %d data: %d usn: %d", (unsigned int)*(le32 *)b, (int)size,
usa_ofs, usa_count, *data_pos, usn); usa_ofs, usa_count, *data_pos, usn);
b->magic = magic_BAAD; b->magic = magic_BAAD;
return -1; return -1;

View File

@ -37,9 +37,12 @@
#include "ntfsinternal.h" #include "ntfsinternal.h"
#include "ntfsfile.h" #include "ntfsfile.h"
#include "ntfsdir.h" #include "ntfsdir.h"
#include "gekko_io.h" #include "gekko_io.h"
#include "cache.h" #include "cache.h"
// NTFS device driver devoptab // NTFS device driver devoptab
static const devoptab_t devops_ntfs = { static const devoptab_t devops_ntfs = {
NULL, /* Device name */ NULL, /* Device name */
@ -197,7 +200,7 @@ int ntfsFindPartitions (const DISC_INTERFACE *interface, sec_t **partitions)
if (sector.boot.oem_id == NTFS_OEM_ID) { if (sector.boot.oem_id == NTFS_OEM_ID) {
ntfs_log_debug("Logical Partition @ %d: Valid NTFS boot sector found\n", part_lba); ntfs_log_debug("Logical Partition @ %d: Valid NTFS boot sector found\n", part_lba);
if(sector.ebr.partition.type != PARTITION_TYPE_NTFS) { if(sector.ebr.partition.type != PARTITION_TYPE_NTFS) {
ntfs_log_warning("Logical Partition @ %d: Is NTFS but type is 0x%x; 0x%x was expected\n", part_lba, sector.ebr.partition.type, PARTITION_TYPE_NTFS); ntfs_log_warning("Logical Partition @ %d: Is NTFS but type is 0x%x; 0x%x was expected\n", (int) part_lba, sector.ebr.partition.type, PARTITION_TYPE_NTFS);
} }
if (partition_count < NTFS_MAX_PARTITIONS) { if (partition_count < NTFS_MAX_PARTITIONS) {
partition_starts[partition_count] = part_lba; partition_starts[partition_count] = part_lba;
@ -317,6 +320,27 @@ int ntfsMountAll (ntfs_md **mounts, u32 flags)
} }
ntfs_free(partitions); 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++;
}
}
} }
} }

View File

@ -220,7 +220,7 @@ int ntfs_open_r (struct _reent *r, void *fileStruct, const char *path, int flags
return (int)fileStruct; return (int)fileStruct;
} }
int ntfs_close_r (struct _reent *r, int fd) int ntfs_close_r (struct _reent *r, void * fd)
{ {
ntfs_log_trace("fd %p\n", (void *) fd); ntfs_log_trace("fd %p\n", (void *) fd);
@ -253,7 +253,7 @@ int ntfs_close_r (struct _reent *r, int fd)
return 0; return 0;
} }
ssize_t ntfs_write_r (struct _reent *r, int fd, const char *ptr, size_t len) ssize_t ntfs_write_r (struct _reent *r, void * fd, const char *ptr, size_t len)
{ {
ntfs_log_trace("fd %p, ptr %p, len %u\n", (void *) fd, ptr, len); ntfs_log_trace("fd %p, ptr %p, len %u\n", (void *) fd, ptr, len);
@ -319,7 +319,7 @@ ssize_t ntfs_write_r (struct _reent *r, int fd, const char *ptr, size_t len)
return written; return written;
} }
ssize_t ntfs_read_r (struct _reent *r, int fd, char *ptr, size_t len) ssize_t ntfs_read_r (struct _reent *r, void * fd, char *ptr, size_t len)
{ {
ntfs_log_trace("fd %p, ptr %p, len %u\n", (void *) fd, ptr, len); ntfs_log_trace("fd %p, ptr %p, len %u\n", (void *) fd, ptr, len);
@ -378,7 +378,7 @@ ssize_t ntfs_read_r (struct _reent *r, int fd, char *ptr, size_t len)
return read; return read;
} }
off_t ntfs_seek_r (struct _reent *r, int fd, off_t pos, int dir) off_t ntfs_seek_r (struct _reent *r, void * fd, off_t pos, int dir)
{ {
ntfs_log_trace("fd %p, pos %llu, dir %i\n", (void *) fd, pos, dir); ntfs_log_trace("fd %p, pos %llu, dir %i\n", (void *) fd, pos, dir);
@ -406,7 +406,7 @@ off_t ntfs_seek_r (struct _reent *r, int fd, off_t pos, int dir)
return position; return position;
} }
int ntfs_fstat_r (struct _reent *r, int fd, struct stat *st) int ntfs_fstat_r (struct _reent *r, void * fd, struct stat *st)
{ {
ntfs_log_trace("fd %p\n", (void *) fd); ntfs_log_trace("fd %p\n", (void *) fd);
@ -431,7 +431,7 @@ int ntfs_fstat_r (struct _reent *r, int fd, struct stat *st)
return ret; return ret;
} }
int ntfs_ftruncate_r (struct _reent *r, int fd, off_t len) int ntfs_ftruncate_r (struct _reent *r, void * fd, off_t len)
{ {
ntfs_log_trace("fd %p, len %llu\n", (void *) fd, (u64) len); ntfs_log_trace("fd %p, len %llu\n", (void *) fd, (u64) len);
@ -498,7 +498,7 @@ int ntfs_ftruncate_r (struct _reent *r, int fd, off_t len)
return 0; return 0;
} }
int ntfs_fsync_r (struct _reent *r, int fd) int ntfs_fsync_r (struct _reent *r, void * fd)
{ {
ntfs_log_trace("fd %p\n", (void *) fd); ntfs_log_trace("fd %p\n", (void *) fd);

View File

@ -53,13 +53,13 @@ void ntfsCloseFile (ntfs_file_state *file);
/* Gekko devoptab file routines for NTFS-based devices */ /* Gekko devoptab file routines for NTFS-based devices */
extern int ntfs_open_r (struct _reent *r, void *fileStruct, const char *path, int flags, int mode); extern int ntfs_open_r (struct _reent *r, void *fileStruct, const char *path, int flags, int mode);
extern int ntfs_close_r (struct _reent *r, int fd); extern int ntfs_close_r (struct _reent *r, void *fd);
extern ssize_t ntfs_write_r (struct _reent *r, int fd, const char *ptr, size_t len); extern ssize_t ntfs_write_r (struct _reent *r, void * fd, const char *ptr, size_t len);
extern ssize_t ntfs_read_r (struct _reent *r, int fd, char *ptr, size_t len); extern ssize_t ntfs_read_r (struct _reent *r, void * fd, char *ptr, size_t len);
extern off_t ntfs_seek_r (struct _reent *r, int fd, off_t pos, int dir); extern off_t ntfs_seek_r (struct _reent *r, void * fd, off_t pos, int dir);
extern int ntfs_fstat_r (struct _reent *r, int fd, struct stat *st); extern int ntfs_fstat_r (struct _reent *r, void * fd, struct stat *st);
extern int ntfs_ftruncate_r (struct _reent *r, int fd, off_t len); extern int ntfs_ftruncate_r (struct _reent *r, void * fd, off_t len);
extern int ntfs_fsync_r (struct _reent *r, int fd); extern int ntfs_fsync_r (struct _reent *r, void * fd);
#endif /* _NTFSFILE_H */ #endif /* _NTFSFILE_H */

View File

@ -37,6 +37,7 @@
#include "ntfsinternal.h" #include "ntfsinternal.h"
#include "ntfsdir.h" #include "ntfsdir.h"
#include "ntfsfile.h" #include "ntfsfile.h"
#include "lock.h"
#if defined(__wii__) #if defined(__wii__)
#include <sdcard/wiisd_io.h> #include <sdcard/wiisd_io.h>
@ -51,6 +52,15 @@ const INTERFACE_ID ntfs_disc_interfaces[] = {
{ NULL, NULL } { NULL, NULL }
}; };
#elif defined (__WIIU__)
#include <iosuhax_disc_interface.h>
const INTERFACE_ID ntfs_disc_interfaces[] = {
{"sd", &IOSUHAX_sdio_disc_interface},
{"usb", &IOSUHAX_usb_disc_interface},
{NULL, NULL}
};
#elif defined(__gamecube__) #elif defined(__gamecube__)
#include <sdcard/gcsd.h> #include <sdcard/gcsd.h>
@ -190,7 +200,7 @@ int ntfsInitVolume (ntfs_vd *vd)
} }
// Initialise the volume lock // Initialise the volume lock
LWP_MutexInit(&vd->lock, false); _NTFS_lock_init(&vd->lock, false);
// Reset the volumes name cache // Reset the volumes name cache
vd->name[0] = '\0'; vd->name[0] = '\0';
@ -253,7 +263,7 @@ void ntfsDeinitVolume (ntfs_vd *vd)
ntfsUnlock(vd); ntfsUnlock(vd);
// Deinitialise the volume lock // Deinitialise the volume lock
LWP_MutexDestroy(vd->lock); _NTFS_lock_deinit((mutex_t *)vd->lock);
return; return;
} }

View File

@ -38,10 +38,21 @@
#include "reparse.h" #include "reparse.h"
#include "security.h" #include "security.h"
#include "efs.h" #include "efs.h"
#include "lock.h"
#include "unistr.h" #include "unistr.h"
#include <gccore.h> #if defined (__WIIU__)
#include <ogc/disc_io.h> #include <iosuhax_disc_interface.h>
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 <ogc/disc_io.h>
#include <gccore.h>
#endif
#include <sys/iosupport.h> #include <sys/iosupport.h>
#define NTFS_MOUNT_PREFIX "ntfs" /* Device name prefix to use when auto-mounting */ #define NTFS_MOUNT_PREFIX "ntfs" /* Device name prefix to use when auto-mounting */
@ -141,13 +152,13 @@ typedef struct _ntfs_vd {
/* Lock volume */ /* Lock volume */
static inline void ntfsLock (ntfs_vd *vd) static inline void ntfsLock (ntfs_vd *vd)
{ {
LWP_MutexLock(vd->lock); _NTFS_lock((mutex_t *)&vd->lock);
} }
/* Unlock volume */ /* Unlock volume */
static inline void ntfsUnlock (ntfs_vd *vd) static inline void ntfsUnlock (ntfs_vd *vd)
{ {
LWP_MutexUnlock(vd->lock); _NTFS_unlock((mutex_t *)&vd->lock);
} }
/* Gekko device related routines */ /* Gekko device related routines */

View File

@ -40,7 +40,7 @@
/* /*
* assume "struct timespec" is not defined if st_mtime is not defined * assume "struct timespec" is not defined if st_mtime is not defined
*/ */
#if !defined(st_mtime) & !defined(__timespec_defined) #if !defined(st_mtime) & !defined(__timespec_defined) & !defined(__WIIU__)
struct timespec { struct timespec {
time_t tv_sec; time_t tv_sec;
long tv_nsec; long tv_nsec;

View File

@ -75,7 +75,7 @@
#include "realpath.h" #include "realpath.h"
#include "misc.h" #include "misc.h"
const char *ntfs_home = const char *ntfs_home =
"News, support and information: http://tuxera.com\n"; "News, support and information: http://tuxera.com\n";
static const char *invalid_ntfs_msg = static const char *invalid_ntfs_msg =
@ -108,7 +108,7 @@ static const char *opened_volume_msg =
static const char *fakeraid_msg = static const char *fakeraid_msg =
"Either the device is missing or it's powered down, or you have\n" "Either the device is missing or it's powered down, or you have\n"
"SoftRAID hardware and must use an activated, different device under\n" "SoftRAID hardware and must use an activated, different device under\n"
"/dev/mapper/, (e.g. /dev/mapper/nvidia_eahaabcc1) to mount NTFS.\n" "/dev/mapper/, (e.g. /dev/mapper/nvidia_eahaabcc1) to mount NTFS.\n"
"Please see the 'dmraid' documentation for help.\n"; "Please see the 'dmraid' documentation for help.\n";
@ -144,8 +144,8 @@ static int ntfs_inode_free(ntfs_inode **ni)
if (ni && *ni) { if (ni && *ni) {
ret = ntfs_inode_close(*ni); ret = ntfs_inode_close(*ni);
*ni = NULL; *ni = NULL;
} }
return ret; return ret;
} }
@ -169,7 +169,7 @@ static int __ntfs_volume_release(ntfs_volume *v)
if (ntfs_inode_free(&v->vol_ni)) if (ntfs_inode_free(&v->vol_ni))
ntfs_error_set(&err); ntfs_error_set(&err);
/* /*
* FIXME: Inodes must be synced before closing * FIXME: Inodes must be synced before closing
* attributes, otherwise unmount could fail. * attributes, otherwise unmount could fail.
*/ */
@ -178,20 +178,20 @@ static int __ntfs_volume_release(ntfs_volume *v)
ntfs_attr_free(&v->lcnbmp_na); ntfs_attr_free(&v->lcnbmp_na);
if (ntfs_inode_free(&v->lcnbmp_ni)) if (ntfs_inode_free(&v->lcnbmp_ni))
ntfs_error_set(&err); ntfs_error_set(&err);
if (v->mft_ni && NInoDirty(v->mft_ni)) if (v->mft_ni && NInoDirty(v->mft_ni))
ntfs_inode_sync(v->mft_ni); ntfs_inode_sync(v->mft_ni);
ntfs_attr_free(&v->mftbmp_na); ntfs_attr_free(&v->mftbmp_na);
ntfs_attr_free(&v->mft_na); ntfs_attr_free(&v->mft_na);
if (ntfs_inode_free(&v->mft_ni)) if (ntfs_inode_free(&v->mft_ni))
ntfs_error_set(&err); ntfs_error_set(&err);
if (v->mftmirr_ni && NInoDirty(v->mftmirr_ni)) if (v->mftmirr_ni && NInoDirty(v->mftmirr_ni))
ntfs_inode_sync(v->mftmirr_ni); ntfs_inode_sync(v->mftmirr_ni);
ntfs_attr_free(&v->mftmirr_na); ntfs_attr_free(&v->mftmirr_na);
if (ntfs_inode_free(&v->mftmirr_ni)) if (ntfs_inode_free(&v->mftmirr_ni))
ntfs_error_set(&err); ntfs_error_set(&err);
if (v->dev) { if (v->dev) {
struct ntfs_device *dev = v->dev; struct ntfs_device *dev = v->dev;
@ -260,10 +260,10 @@ static int ntfs_mft_load(ntfs_volume *vol)
ntfs_log_perror("Error reading $MFT"); ntfs_log_perror("Error reading $MFT");
goto error_exit; goto error_exit;
} }
if (ntfs_mft_record_check(vol, 0, mb)) if (ntfs_mft_record_check(vol, 0, mb))
goto error_exit; goto error_exit;
ctx = ntfs_attr_get_search_ctx(vol->mft_ni, NULL); ctx = ntfs_attr_get_search_ctx(vol->mft_ni, NULL);
if (!ctx) if (!ctx)
goto error_exit; goto error_exit;
@ -288,7 +288,7 @@ static int ntfs_mft_load(ntfs_volume *vol)
vol->mft_ni->attr_list = ntfs_malloc(l); vol->mft_ni->attr_list = ntfs_malloc(l);
if (!vol->mft_ni->attr_list) if (!vol->mft_ni->attr_list)
goto error_exit; goto error_exit;
l = ntfs_get_attribute_value(vol, ctx->attr, vol->mft_ni->attr_list); l = ntfs_get_attribute_value(vol, ctx->attr, vol->mft_ni->attr_list);
if (!l) { if (!l) {
ntfs_log_error("Failed to get value of $MFT/$ATTR_LIST.\n"); ntfs_log_error("Failed to get value of $MFT/$ATTR_LIST.\n");
@ -297,16 +297,16 @@ static int ntfs_mft_load(ntfs_volume *vol)
if (l != vol->mft_ni->attr_list_size) { if (l != vol->mft_ni->attr_list_size) {
ntfs_log_error("Partial read of $MFT/$ATTR_LIST (%lld != " ntfs_log_error("Partial read of $MFT/$ATTR_LIST (%lld != "
"%u).\n", (long long)l, "%u).\n", (long long)l,
vol->mft_ni->attr_list_size); (unsigned int) vol->mft_ni->attr_list_size);
goto io_error_exit; goto io_error_exit;
} }
mft_has_no_attr_list: mft_has_no_attr_list:
ntfs_attr_setup_flag(vol->mft_ni); ntfs_attr_setup_flag(vol->mft_ni);
/* We now have a fully setup ntfs inode for $MFT in vol->mft_ni. */ /* We now have a fully setup ntfs inode for $MFT in vol->mft_ni. */
/* Get an ntfs attribute for $MFT/$DATA and set it up, too. */ /* Get an ntfs attribute for $MFT/$DATA and set it up, too. */
vol->mft_na = ntfs_attr_open(vol->mft_ni, AT_DATA, AT_UNNAMED, 0); vol->mft_na = ntfs_attr_open(vol->mft_ni, AT_DATA, AT_UNNAMED, 0);
if (!vol->mft_na) { if (!vol->mft_na) {
@ -428,18 +428,18 @@ static int ntfs_mftmirr_load(ntfs_volume *vol)
ntfs_log_perror("Failed to open inode $MFTMirr"); ntfs_log_perror("Failed to open inode $MFTMirr");
return -1; return -1;
} }
vol->mftmirr_na = ntfs_attr_open(vol->mftmirr_ni, AT_DATA, AT_UNNAMED, 0); vol->mftmirr_na = ntfs_attr_open(vol->mftmirr_ni, AT_DATA, AT_UNNAMED, 0);
if (!vol->mftmirr_na) { if (!vol->mftmirr_na) {
ntfs_log_perror("Failed to open $MFTMirr/$DATA"); ntfs_log_perror("Failed to open $MFTMirr/$DATA");
goto error_exit; goto error_exit;
} }
if (ntfs_attr_map_runlist(vol->mftmirr_na, 0) < 0) { if (ntfs_attr_map_runlist(vol->mftmirr_na, 0) < 0) {
ntfs_log_perror("Failed to map runlist of $MFTMirr/$DATA"); ntfs_log_perror("Failed to map runlist of $MFTMirr/$DATA");
goto error_exit; goto error_exit;
} }
return 0; return 0;
error_exit: error_exit:
@ -484,12 +484,12 @@ ntfs_volume *ntfs_volume_startup(struct ntfs_device *dev,
bs = ntfs_malloc(sizeof(NTFS_BOOT_SECTOR)); bs = ntfs_malloc(sizeof(NTFS_BOOT_SECTOR));
if (!bs) if (!bs)
return NULL; return NULL;
/* Allocate the volume structure. */ /* Allocate the volume structure. */
vol = ntfs_volume_alloc(); vol = ntfs_volume_alloc();
if (!vol) if (!vol)
goto error_exit; goto error_exit;
/* Create the default upcase table. */ /* Create the default upcase table. */
vol->upcase_len = ntfs_upcase_build_default(&vol->upcase); vol->upcase_len = ntfs_upcase_build_default(&vol->upcase);
if (!vol->upcase_len || !vol->upcase) if (!vol->upcase_len || !vol->upcase)
@ -498,7 +498,7 @@ ntfs_volume *ntfs_volume_startup(struct ntfs_device *dev,
/* Default with no locase table and case sensitive file names */ /* Default with no locase table and case sensitive file names */
vol->locase = (ntfschar*)NULL; vol->locase = (ntfschar*)NULL;
NVolSetCaseSensitive(vol); NVolSetCaseSensitive(vol);
/* by default, all files are shown and not marked hidden */ /* by default, all files are shown and not marked hidden */
NVolSetShowSysFiles(vol); NVolSetShowSysFiles(vol);
NVolSetShowHidFiles(vol); NVolSetShowHidFiles(vol);
@ -511,7 +511,7 @@ ntfs_volume *ntfs_volume_startup(struct ntfs_device *dev,
#endif #endif
if (flags & NTFS_MNT_RDONLY) if (flags & NTFS_MNT_RDONLY)
NVolSetReadOnly(vol); NVolSetReadOnly(vol);
/* ...->open needs bracketing to compile with glibc 2.7 */ /* ...->open needs bracketing to compile with glibc 2.7 */
if ((dev->d_ops->open)(dev, NVolReadOnly(vol) ? O_RDONLY: O_RDWR)) { if ((dev->d_ops->open)(dev, NVolReadOnly(vol) ? O_RDONLY: O_RDWR)) {
if (!NVolReadOnly(vol) && (errno == EROFS)) { if (!NVolReadOnly(vol) && (errno == EROFS)) {
@ -531,7 +531,7 @@ ntfs_volume *ntfs_volume_startup(struct ntfs_device *dev,
} }
/* Attach the device to the volume. */ /* Attach the device to the volume. */
vol->dev = dev; vol->dev = dev;
/* Now read the bootsector. */ /* Now read the bootsector. */
br = ntfs_pread(dev, 0, sizeof(NTFS_BOOT_SECTOR), bs); br = ntfs_pread(dev, 0, sizeof(NTFS_BOOT_SECTOR), bs);
if (br != sizeof(NTFS_BOOT_SECTOR)) { if (br != sizeof(NTFS_BOOT_SECTOR)) {
@ -549,7 +549,7 @@ ntfs_volume *ntfs_volume_startup(struct ntfs_device *dev,
} }
if (ntfs_boot_sector_parse(vol, bs) < 0) if (ntfs_boot_sector_parse(vol, bs) < 0)
goto error_exit; goto error_exit;
free(bs); free(bs);
bs = NULL; bs = NULL;
/* Now set the device block size to the sector size. */ /* Now set the device block size to the sector size. */
@ -558,7 +558,7 @@ ntfs_volume *ntfs_volume_startup(struct ntfs_device *dev,
"sector size. This may affect performance " "sector size. This may affect performance "
"but should be harmless otherwise. Error: " "but should be harmless otherwise. Error: "
"%s\n", strerror(errno)); "%s\n", strerror(errno));
/* We now initialize the cluster allocator. */ /* We now initialize the cluster allocator. */
vol->full_zones = 0; vol->full_zones = 0;
mft_zone_size = vol->nr_clusters >> 3; /* 12.5% */ mft_zone_size = vol->nr_clusters >> 3; /* 12.5% */
@ -652,14 +652,14 @@ static int ntfs_volume_check_logfile(ntfs_volume *vol)
errno = EIO; errno = EIO;
return -1; return -1;
} }
na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0); na = ntfs_attr_open(ni, AT_DATA, AT_UNNAMED, 0);
if (!na) { if (!na) {
ntfs_log_perror("Failed to open $FILE_LogFile/$DATA"); ntfs_log_perror("Failed to open $FILE_LogFile/$DATA");
err = EIO; err = EIO;
goto out; goto out;
} }
if (!ntfs_check_logfile(na, &rp) || !ntfs_is_logfile_clean(na, rp)) if (!ntfs_check_logfile(na, &rp) || !ntfs_is_logfile_clean(na, rp))
err = EOPNOTSUPP; err = EOPNOTSUPP;
/* /*
@ -682,7 +682,7 @@ static int ntfs_volume_check_logfile(ntfs_volume *vol)
} }
free(rp); free(rp);
ntfs_attr_close(na); ntfs_attr_close(na);
out: out:
if (ntfs_inode_close(ni)) if (ntfs_inode_close(ni))
ntfs_error_set(&err); ntfs_error_set(&err);
if (err) { if (err) {
@ -1007,16 +1007,16 @@ ntfs_volume *ntfs_device_mount(struct ntfs_device *dev, ntfs_mount_flags flags)
ntfs_log_perror("Failed to open inode FILE_Bitmap"); ntfs_log_perror("Failed to open inode FILE_Bitmap");
goto error_exit; goto error_exit;
} }
vol->lcnbmp_na = ntfs_attr_open(vol->lcnbmp_ni, AT_DATA, AT_UNNAMED, 0); vol->lcnbmp_na = ntfs_attr_open(vol->lcnbmp_ni, AT_DATA, AT_UNNAMED, 0);
if (!vol->lcnbmp_na) { if (!vol->lcnbmp_na) {
ntfs_log_perror("Failed to open ntfs attribute"); ntfs_log_perror("Failed to open ntfs attribute");
goto error_exit; goto error_exit;
} }
if (vol->lcnbmp_na->data_size > vol->lcnbmp_na->allocated_size) { if (vol->lcnbmp_na->data_size > vol->lcnbmp_na->allocated_size) {
ntfs_log_error("Corrupt cluster map size (%lld > %lld)\n", ntfs_log_error("Corrupt cluster map size (%lld > %lld)\n",
(long long)vol->lcnbmp_na->data_size, (long long)vol->lcnbmp_na->data_size,
(long long)vol->lcnbmp_na->allocated_size); (long long)vol->lcnbmp_na->allocated_size);
goto io_error_exit; goto io_error_exit;
} }
@ -1172,7 +1172,7 @@ ntfs_volume *ntfs_device_mount(struct ntfs_device *dev, ntfs_mount_flags flags)
vol->vol_name = ntfs_malloc(u + 1); vol->vol_name = ntfs_malloc(u + 1);
if (!vol->vol_name) if (!vol->vol_name)
goto error_exit; goto error_exit;
for (j = 0; j < (s32)u; j++) { for (j = 0; j < (s32)u; j++) {
u16 uc = le16_to_cpu(vname[j]); u16 uc = le16_to_cpu(vname[j]);
if (uc > 0xff) if (uc > 0xff)
@ -1639,7 +1639,7 @@ int ntfs_logfile_reset(ntfs_volume *vol)
ntfs_attr_close(na); ntfs_attr_close(na);
goto error_exit; goto error_exit;
} }
ntfs_attr_close(na); ntfs_attr_close(na);
return ntfs_inode_close(ni); return ntfs_inode_close(ni);