branches:

*updated libntfs-wii to version 2012.1.15
*updated libext2fs to e2fsprogs 1.42
*updated libfat to R4883
This commit is contained in:
strtoul 2012-02-13 20:26:22 +00:00
parent afb3b68349
commit d90a6f0429
140 changed files with 2378 additions and 1008 deletions

View File

@ -7,3 +7,4 @@ to the Nintendo GameCube/Wii port of ext2fs.
Michael "Chishm" Chisholm
rodries
Rhys "Shareese" Koedijk
Dimok

View File

@ -25,7 +25,3 @@ clean:
install: cube-release wii-release
$(MAKE) -C source install
run: install
$(MAKE) -C example
$(MAKE) -C example run

View File

@ -28,7 +28,7 @@ LIBDIR := ../lib
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
CFLAGS = -Os -Wall -Wno-unused $(MACHDEP) $(INCLUDE) -DGEKKO -DWORDS_BIGENDIAN
CFLAGS = -O2 -Wall -Wno-unused $(MACHDEP) $(INCLUDE) -DGEKKO -DWORDS_BIGENDIAN
CXXFLAGS = $(CFLAGS)
ASFLAGS := -g
export EXT2BIN := $(LIBDIR)/$(PLATFORM)/libext2fs.a

View File

@ -8,7 +8,7 @@
#define N_(a) a
static const char * const text[] = {
N_( "EXT2FS Library version 1.42-WIP"),
N_( "EXT2FS Library version 1.42"),
N_( "Wrong magic number for ext2_filsys structure"),
N_( "Wrong magic number for badblocks_list structure"),
N_( "Wrong magic number for badblocks_iterate structure"),

View File

@ -247,6 +247,13 @@ struct struct_ext2_filsys {
struct ext2_inode_cache *icache;
io_channel image_io;
/*
* More callback functions
*/
errcode_t (*get_alloc_block)(ext2_filsys fs, blk64_t goal,
blk64_t *ret);
void (*block_alloc_stats)(ext2_filsys fs, blk64_t blk, int inuse);
/*
* Buffers for Multiple mount protection(MMP) block.
*/
@ -258,13 +265,6 @@ struct struct_ext2_filsys {
* Time at which e2fsck last updated the MMP block.
*/
long mmp_last_written;
/*
* More callback functions
*/
errcode_t (*get_alloc_block)(ext2_filsys fs, blk64_t goal,
blk64_t *ret);
void (*block_alloc_stats)(ext2_filsys fs, blk64_t blk, int inuse);
};
#include "bitops.h"
@ -558,6 +558,7 @@ typedef struct ext2_icount *ext2_icount_t;
EXT4_FEATURE_INCOMPAT_MMP|\
EXT4_FEATURE_INCOMPAT_64BIT)
#endif
#ifdef CONFIG_QUOTA
#define EXT2_LIB_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER|\
EXT4_FEATURE_RO_COMPAT_HUGE_FILE|\
EXT2_FEATURE_RO_COMPAT_LARGE_FILE|\
@ -566,6 +567,15 @@ typedef struct ext2_icount *ext2_icount_t;
EXT4_FEATURE_RO_COMPAT_GDT_CSUM|\
EXT4_FEATURE_RO_COMPAT_BIGALLOC|\
EXT4_FEATURE_RO_COMPAT_QUOTA)
#else
#define EXT2_LIB_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER|\
EXT4_FEATURE_RO_COMPAT_HUGE_FILE|\
EXT2_FEATURE_RO_COMPAT_LARGE_FILE|\
EXT4_FEATURE_RO_COMPAT_DIR_NLINK|\
EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE|\
EXT4_FEATURE_RO_COMPAT_GDT_CSUM|\
EXT4_FEATURE_RO_COMPAT_BIGALLOC)
#endif
/*
* These features are only allowed if EXT2_FLAG_SOFTSUPP_FEATURES is passed
@ -585,7 +595,7 @@ typedef struct ext2_icount *ext2_icount_t;
#define EXT2FS_NUM_B2C(fs, blks) (((blks) + EXT2FS_CLUSTER_MASK(fs)) >> \
(fs)->cluster_ratio_bits)
#if defined(HAVE_STAT64) && !defined(__OSX_AVAILABLE_BUT_DEPRECATED)
#if defined(HAVE_FSTAT64) && !defined(__OSX_AVAILABLE_BUT_DEPRECATED)
typedef struct stat64 ext2fs_struct_stat;
#else
typedef struct stat ext2fs_struct_stat;
@ -1679,7 +1689,7 @@ _INLINE_ int ext2fs_open_file(const char *pathname, int flags, mode_t mode)
_INLINE_ int ext2fs_stat(const char *path, ext2fs_struct_stat *buf)
{
#if defined(HAVE_STAT64) && !defined(__OSX_AVAILABLE_BUT_DEPRECATED)
#if defined(HAVE_FSTAT64) && !defined(__OSX_AVAILABLE_BUT_DEPRECATED)
return stat64(path, buf);
#else
return stat(path, buf);
@ -1688,7 +1698,7 @@ _INLINE_ int ext2fs_stat(const char *path, ext2fs_struct_stat *buf)
_INLINE_ int ext2fs_fstat(int fd, ext2fs_struct_stat *buf)
{
#if defined(HAVE_STAT64) && !defined(__OSX_AVAILABLE_BUT_DEPRECATED)
#if defined(HAVE_FSTAT64) && !defined(__OSX_AVAILABLE_BUT_DEPRECATED)
return fstat64(fd, buf);
#else
return fstat(fd, buf);

View File

@ -11,6 +11,8 @@
#include "ext2fs.h"
#define EXT2FS_MAX_NESTED_LINKS 8
/*
* Badblocks list
*/

View File

@ -34,6 +34,7 @@
#include "ext2_fs.h"
#include "ext2fs.h"
#include "ext2fsP.h"
struct dir_list {
char *name;
@ -128,6 +129,7 @@ char *ext2fs_find_block_device(dev_t device)
struct dir_list *list = 0, *new_list = 0;
struct dir_list *current;
char *ret_path = 0;
int level = 0;
/*
* Add the starting directories to search...
@ -154,6 +156,9 @@ char *ext2fs_find_block_device(dev_t device)
if (list == 0) {
list = new_list;
new_list = 0;
/* Avoid infinite loop */
if (++level >= EXT2FS_MAX_NESTED_LINKS)
break;
}
}
free_dirlist(&list);

View File

@ -180,6 +180,7 @@ errcode_t ext2fs_create_icount_tdb(ext2_filsys fs, char *tdb_dir,
ext2_icount_t icount;
errcode_t retval;
char *fn, uuid[40];
ext2_ino_t num_inodes;
int fd;
retval = alloc_icount(fs, flags, &icount);
@ -193,8 +194,18 @@ errcode_t ext2fs_create_icount_tdb(ext2_filsys fs, char *tdb_dir,
sprintf(fn, "%s/%s-icount-XXXXXX", tdb_dir, uuid);
fd = mkstemp(fn);
/*
* This is an overestimate of the size that we will need; the
* ideal value is the number of used inodes with a count
* greater than 1. OTOH the times when we really need this is
* with the backup programs that use lots of hard links, in
* which case the number of inodes in use approaches the ideal
* value.
*/
num_inodes = fs->super->s_inodes_count - fs->super->s_free_inodes_count;
icount->tdb_fn = fn;
icount->tdb = tdb_open(fn, 0, TDB_CLEAR_IF_FIRST,
icount->tdb = tdb_open(fn, num_inodes, TDB_NOLOCK | TDB_NOSYNC,
O_RDWR | O_CREAT | O_TRUNC, 0600);
if (icount->tdb) {
close(fd);

View File

@ -9,6 +9,7 @@
* %End-Header%
*/
#include "config.h"
#include <stdio.h>
#if HAVE_UNISTD_H
#include <unistd.h>

View File

@ -130,7 +130,7 @@ errcode_t ext2fs_mmp_write(ext2_filsys fs, blk64_t mmp_blk, void *buf)
/* I was tempted to make this use O_DIRECT and the mmp_fd, but
* this caused no end of grief, while leaving it as-is works. */
retval = io_channel_write_blk64(fs->io, mmp_blk, -fs->blocksize, buf);
retval = io_channel_write_blk64(fs->io, mmp_blk, -(int)sizeof(struct mmp_struct), buf);
#ifdef WORDS_BIGENDIAN
ext2fs_swap_mmp(mmp_s);

View File

@ -20,6 +20,7 @@
#include "ext2_fs.h"
#include "ext2fs.h"
#include "ext2fsP.h"
static errcode_t open_namei(ext2_filsys fs, ext2_ino_t root, ext2_ino_t base,
const char *pathname, size_t pathlen, int follow,
@ -45,9 +46,9 @@ static errcode_t follow_link(ext2_filsys fs, ext2_ino_t root, ext2_ino_t dir,
*res_inode = inode;
return 0;
}
if (link_count++ > 5) {
if (link_count++ >= EXT2FS_MAX_NESTED_LINKS)
return EXT2_ET_SYMLINK_LOOP;
}
/* FIXME-64: Actually, this is FIXME EXTENTS */
if (ext2fs_inode_data_blocks(fs,&ei)) {
retval = ext2fs_get_mem(fs->blocksize, &buffer);

View File

@ -358,8 +358,8 @@ errcode_t ext2fs_open2(const char *name, const char *io_options,
goto cleanup;
#ifdef WORDS_BIGENDIAN
for (j=0; j < groups_per_block; j++) {
/* The below happens to work... be careful. */
gdp = ext2fs_group_desc(fs, fs->group_desc, j);
gdp = ext2fs_group_desc(fs, fs->group_desc,
i * groups_per_block + j);
ext2fs_swap_group_desc2(fs, gdp);
}
#endif

View File

@ -108,6 +108,8 @@ typedef int bool;
#include "tdb.h"
static TDB_DATA tdb_null;
#ifndef u32
#define u32 unsigned
#endif
@ -1752,7 +1754,7 @@ static int transaction_sync(struct tdb_context *tdb, tdb_off_t offset, tdb_len_t
TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction: fsync failed\n"));
return -1;
}
#ifdef MS_SYNC
#if defined(HAVE_MSYNC) && defined(MS_SYNC)
if (tdb->map_ptr) {
tdb_off_t moffset = offset & ~(tdb->page_size-1);
if (msync(moffset + (char *)tdb->map_ptr,
@ -3060,8 +3062,6 @@ int tdb_printfreelist(struct tdb_context *tdb)
/* file: tdb.c */
TDB_DATA tdb_null;
/*
non-blocking increment of the tdb sequence number if the tdb has been opened using
the TDB_SEQNUM flag
@ -3713,17 +3713,17 @@ void tdb_enable_seqnum(struct tdb_context *tdb)
static struct tdb_context *tdbs = NULL;
/* This is based on the hash algorithm from gdbm */
/* This is from a hash algorithm suggested by Rogier Wolff */
static unsigned int default_tdb_hash(TDB_DATA *key)
{
u32 value; /* Used to compute the hash value. */
u32 i; /* Used to cycle through random values. */
/* Set the initial value from the key size. */
for (value = 0x238F13AF * key->dsize, i=0; i < key->dsize; i++)
value = (value + (key->dptr[i] << (i*5 % 24)));
for (value = 0, i=0; i < key->dsize; i++)
value = value * 256 + key->dptr[i] + (value >> 24) * 241;
return (1103515243 * value + 12345);
return value;
}

View File

@ -206,8 +206,6 @@ void tdb_dump_all(struct tdb_context *tdb);
int tdb_printfreelist(struct tdb_context *tdb);
int tdb_validate_freelist(struct tdb_context *tdb, int *pnum_entries);
extern TDB_DATA tdb_null;
#ifdef __cplusplus
}
#endif

View File

@ -20,9 +20,10 @@
#include "ext2_fs.h"
#include "ext2fs.h"
#include "version.h"
static const char *lib_version = "";
static const char *lib_date = "";
static const char *lib_version = E2FSPROGS_VERSION;
static const char *lib_date = E2FSPROGS_DATE;
int ext2fs_parse_version_string(const char *ver_string)
{

View File

@ -0,0 +1,11 @@
/*
* version.h --- controls the version number printed by the e2fs
* programs.
*
* Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
* 2004, 2005, 2006, 2007, 2008, 2009, 2010 by Theodore Ts'o. This
* file may be redistributed under the GNU Public License v2.
*/
#define E2FSPROGS_VERSION "1.42"
#define E2FSPROGS_DATE "29-Nov-2011"

View File

@ -1,32 +1,31 @@
# Quick'n'dirty makefile [BC] v2
ifeq ($(strip $(DEVKITPPC)),)
$(error "Please set DEVKITPPC in your environment. export DEVKITPPC=<path to>devkitPPC")
ifeq ($(strip $(DEVKITPRO)),)
$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=<path to>devkitPro)
endif
include $(DEVKITPPC)/wii_rules
export TOPDIR := $(CURDIR)
LIBOGC_INC := $(DEVKITPRO)/libogc/include
LIBOGC_LIB := $(DEVKITPRO)/libogc/lib/wii
export LIBFAT_MAJOR := 1
export LIBFAT_MINOR := 0
export LIBFAT_PATCH := 10
CFLAGS := -O3 $(MACHDEP) -I$(LIBOGC_INC)
export VERSTRING := $(LIBFAT_MAJOR).$(LIBFAT_MINOR).$(LIBFAT_PATCH)
LIB := fat
CFILES := $(wildcard *.c)
OFILES := $(CFILES:.c=.o)
ARC := lib$(LIB).a
HDR := fat.h
all : $(OFILES)
$(AR) -r $(ARC) $(OFILES)
default: release
clean :
rm -f $(OFILES) $(ARC)
all: release
install :
mkdir -p $(LIBOGC_LIB) $(LIBOGC_INC)
cp -f $(ARC) $(LIBOGC_LIB)/
cp -f $(HDR) $(LIBOGC_INC)/
release: include/libfatversion.h wii-release
%.o : %.c
$(CC) $(CFLAGS) -c $< -o $@
wii-release:
$(MAKE) -C libogc PLATFORM=wii BUILD=wii_release
clean: ogc-clean
ogc-clean:
$(MAKE) -C libogc clean
install: ogc-install
ogc-install: cube-release wii-release
$(MAKE) -C libogc install

View File

@ -0,0 +1,10 @@
#ifndef __LIBFATVERSION_H__
#define __LIBFATVERSION_H__
#define _LIBFAT_MAJOR_ 1
#define _LIBFAT_MINOR_ 0
#define _LIBFAT_PATCH_ 10
#define _LIBFAT_STRING "libFAT Release 1.0.10"
#endif // __LIBFATVERSION_H__

View File

@ -0,0 +1 @@
<Project name="libfat"><MagicFolder excludeFolders="CVS;.svn" filter="*.c;*.h" name="source" path="source\"><File path="bit_ops.h"></File><File path="cache.c"></File><File path="cache.h"></File><File path="common.h"></File><File path="directory.c"></File><File path="directory.h"></File><File path="disc.c"></File><File path="disc.h"></File><File path="fatdir.c"></File><File path="fatdir.h"></File><File path="fatfile.c"></File><File path="fatfile.h"></File><File path="fatfile_frag.c"></File><File path="fatfile_frag.h"></File><File path="filetime.c"></File><File path="filetime.h"></File><File path="file_allocation_table.c"></File><File path="file_allocation_table.h"></File><File path="libfat.c"></File><File path="lock.c"></File><File path="lock.h"></File><File path="mem_allocate.h"></File><File path="partition.c"></File><File path="partition.h"></File></MagicFolder><Folder name="nds"><Folder name="include"><File path="nds\include\fat.h"></File><File path="nds\include\nitrofs.h"></File></Folder><Folder name="source"><File path="nds\source\nitrofs.c"></File></Folder><File path="nds\Makefile"></File></Folder><Folder name="libogc"><Folder name="include"><File path="libogc\include\fat.h"></File></Folder><File path="libogc\Makefile"></File></Folder><Folder name="gba"><Folder name="include"><File path="gba\include\fat.h"></File></Folder><File path="gba\Makefile"></File></Folder><MagicFolder excludeFolders="CVS;.svn" filter="*.h" name="include" path="include\"><File path="fat.h"></File><File path="libfatversion.h"></File></MagicFolder><File path="Makefile"></File></Project>

1
libcustomfat/libfat.pnps Normal file
View File

@ -0,0 +1 @@
<pd><ViewState><e p="libfat\include" x="false"></e><e p="libfat\libogc" x="false"></e><e p="libfat\nds" x="false"></e><e p="libfat" x="true"></e><e p="libfat\gba" x="false"></e><e p="libfat\source" x="false"></e></ViewState></pd>

View File

@ -0,0 +1,132 @@
#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITPPC)),)
$(error "Please set DEVKITPPC in your environment. export DEVKITPPC=<path to>devkitPPC)
endif
ifeq ($(PLATFORM),wii)
include $(DEVKITPPC)/wii_rules
endif
ifeq ($(PLATFORM),cube)
include $(DEVKITPPC)/gamecube_rules
endif
#---------------------------------------------------------------------------------
# BUILD is the directory where object files & intermediate files will be placed
# SOURCES is a list of directories containing source code
# INCLUDES is a list of directories containing extra header files
# DATA is a list of directories containing binary files
# LIBDIR is where the built library will be placed
# all directories are relative to this makefile
#---------------------------------------------------------------------------------
BUILD ?= wii_release
SOURCES := ../source
INCLUDES := ../include
DATA :=
LIBDIR := $(TOPDIR)/libogc/lib
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
CFLAGS = -g -O2 -Wall $(MACHDEP) $(INCLUDE)
CXXFLAGS = $(CFLAGS)
ASFLAGS := -g
ifneq ($(BUILD),debug)
export CUBEBIN := $(LIBDIR)/$(PLATFORM)/libfat.a
else
export CUBEBIN := $(LIBDIR)/$(PLATFORM)/libfatd.a
CFLAGS += -DFAT_DEBUG
endif
#---------------------------------------------------------------------------------
# any extra libraries we wish to link with the project
#---------------------------------------------------------------------------------
LIBS :=
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS :=
#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export TOPDIR ?= $(CURDIR)/..
export DEPSDIR := $(CURDIR)/$(BUILD)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
export OFILES := $(addsuffix .o,$(BINFILES)) \
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
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)
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) \
-L$(LIBOGC_LIB)
.PHONY: $(BUILD) clean
#---------------------------------------------------------------------------------
$(BUILD):
@[ -d $@ ] || mkdir -p $@
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr wii_debug wii_release cube_debug cube_release $(LIBDIR)
all: $(CUBEBIN)
dist-bin:
@tar --exclude=.svn --exclude=*CVS* -cvjf $(TOPDIR)/distribute/$(VERSTRING)/libfat-ogc-$(VERSTRING).tar.bz2 include lib
install:
cp lib/wii/libfat.a $(DEVKITPRO)/libogc/lib/wii
cp lib/cube/libfat.a $(DEVKITPRO)/libogc/lib/cube
cp include/fat.h $(DEVKITPRO)/libogc/include
#---------------------------------------------------------------------------------
else
DEPENDS := $(OFILES:.o=.d)
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
$(CUBEBIN) : $(OFILES) $(LIBDIR)/$(PLATFORM)
@rm -f "$(CUBEBIN)"
@$(AR) rcs "$(CUBEBIN)" $(OFILES)
@echo built ... $(notdir $@)
$(LIBDIR)/$(PLATFORM):
mkdir -p $(LIBDIR)/$(PLATFORM)
-include $(DEPENDS)
#---------------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------------

View File

@ -0,0 +1,86 @@
/*
fat.h
Simple functionality for startup, mounting and unmounting of FAT-based devices.
Copyright (c) 2006 Michael "Chishm" Chisholm
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 _LIBFAT_H
#define _LIBFAT_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <ogc/disc_io.h>
/*
Initialise any inserted block-devices.
Add the fat device driver to the devoptab, making it available for standard file functions.
cacheSize: The number of pages to allocate for each inserted block-device
setAsDefaultDevice: if true, make this the default device driver for file operations
*/
extern bool fatInit (uint32_t cacheSize, bool setAsDefaultDevice);
/*
Calls fatInit with setAsDefaultDevice = true and cacheSize optimised for the host system.
*/
extern bool fatInitDefault (void);
/*
Mount the device pointed to by interface, and set up a devoptab entry for it as "name:".
You can then access the filesystem using "name:/".
This will mount the active partition or the first valid partition on the disc,
and will use a cache size optimized for the host system.
*/
extern bool fatMountSimple (const char* name, const DISC_INTERFACE* interface);
/*
Mount the device pointed to by interface, and set up a devoptab entry for it as "name:".
You can then access the filesystem using "name:/".
If startSector = 0, it will mount the active partition of the first valid partition on
the disc. Otherwise it will try to mount the partition starting at startSector.
cacheSize specifies the number of pages to allocate for the cache.
This will not startup the disc, so you need to call interface->startup(); first.
*/
extern bool fatMount (const char* name, const DISC_INTERFACE* interface, sec_t startSector, uint32_t cacheSize, uint32_t SectorsPerPage);
/*
Unmount the partition specified by name.
If there are open files, it will attempt to synchronise them to disc.
*/
extern void fatUnmount (const char* name);
/*
Get Volume Label
*/
extern void fatGetVolumeLabel (const char* name, char *label);
#ifdef __cplusplus
}
#endif
#endif // _LIBFAT_H

View File

@ -204,8 +204,10 @@ static int _FAT_directory_mbsncasecmp (const char* s1, const char* s2, size_t le
static bool _FAT_directory_entryGetAlias (const u8* entryData, char* destName) {
int i=0;
int j=0;
char c;
bool caseInfo;
int i = 0;
int j = 0;
destName[0] = '\0';
if (entryData[0] != DIR_ENTRY_FREE) {
@ -219,14 +221,18 @@ static bool _FAT_directory_entryGetAlias (const u8* entryData, char* destName) {
}
} else {
// Copy the filename from the dirEntry to the string
caseInfo = entryData[DIR_ENTRY_caseInfo] & CASE_LOWER_BASE;
for (i = 0; (i < 8) && (entryData[DIR_ENTRY_name + i] != ' '); i++) {
destName[i] = entryData[DIR_ENTRY_name + i];
c = entryData[DIR_ENTRY_name + i];
destName[i] = (caseInfo ? tolower((unsigned char)c) : c);
}
// Copy the extension from the dirEntry to the string
if (entryData[DIR_ENTRY_extension] != ' ') {
destName[i++] = '.';
caseInfo = entryData[DIR_ENTRY_caseInfo] & CASE_LOWER_EXT;
for ( j = 0; (j < 3) && (entryData[DIR_ENTRY_extension + j] != ' '); j++) {
destName[i++] = entryData[DIR_ENTRY_extension + j];
c = entryData[DIR_ENTRY_extension + j];
destName[i++] = (caseInfo ? tolower((unsigned char)c) : c);
}
}
destName[i] = '\0';

View File

@ -57,6 +57,9 @@
#define ATTRIB_HID 0x02 // Hidden
#define ATTRIB_RO 0x01 // Read only
#define CASE_LOWER_EXT 0x10 // WinNT lowercase extension
#define CASE_LOWER_BASE 0x08 // WinNT lowercase basename
typedef enum {FT_DIRECTORY, FT_FILE} FILE_TYPE;
typedef struct {
@ -77,7 +80,7 @@ enum DIR_ENTRY_offset {
DIR_ENTRY_name = 0x00,
DIR_ENTRY_extension = 0x08,
DIR_ENTRY_attributes = 0x0B,
DIR_ENTRY_reserved = 0x0C,
DIR_ENTRY_caseInfo = 0x0C,
DIR_ENTRY_cTime_ms = 0x0D,
DIR_ENTRY_cTime = 0x0E,
DIR_ENTRY_cDate = 0x10,

View File

@ -45,6 +45,37 @@
#include "filetime.h"
#include "lock.h"
bool _FAT_findEntry(const char *path, DIR_ENTRY *dirEntry) {
PARTITION *partition = _FAT_partition_getPartitionFromPath(path);
// Move the path pointer to the start of the actual path
if (strchr (path, ':') != NULL) {
path = strchr (path, ':') + 1;
}
if (strchr (path, ':') != NULL) {
return false;
}
// Search for the file on the disc
return _FAT_directory_entryFromPath (partition, dirEntry, path, NULL);
}
int FAT_getAttr(const char *file) {
DIR_ENTRY dirEntry;
if (!_FAT_findEntry(file,&dirEntry)) return -1;
return dirEntry.entryData[DIR_ENTRY_attributes];
}
int FAT_setAttr(const char *file, int attr) {
DIR_ENTRY dirEntry;
if (!_FAT_findEntry(file,&dirEntry)) return -1;
return 0;
}
int _FAT_open_r (struct _reent *r, void *fileStruct, const char *path, int flags, int mode) {
PARTITION* partition = NULL;
bool fileExists;

View File

@ -38,8 +38,6 @@
#include <ctype.h>
#include <sys/iosupport.h>
sec_t _FAT_startSector;
/*
Data offsets
*/
@ -105,20 +103,14 @@ static const char FAT_SIG[3] = {'F', 'A', 'T'};
static const char FS_INFO_SIG1[4] = {'R', 'R', 'a', 'A'};
static const char FS_INFO_SIG2[4] = {'r', 'r', 'A', 'a'};
sec_t FindFirstValidPartition(const DISC_INTERFACE* disc)
sec_t FindFirstValidPartition_buf(const DISC_INTERFACE* disc, uint8_t *sectorBuffer)
{
uint8_t part_table[16*4];
uint8_t *ptr;
int i;
uint8_t *sectorBuffer = (uint8_t*) _FAT_mem_allocate(MAX_SECTOR_SIZE);
if(!sectorBuffer) {
return 0;
}
// Read first sector of disc
if (!_FAT_disc_readSectors (disc, 0, 1, sectorBuffer)) {
_FAT_mem_free(sectorBuffer);
return 0;
}
@ -130,7 +122,6 @@ sec_t FindFirstValidPartition(const DISC_INTERFACE* disc)
if (!memcmp(sectorBuffer + BPB_FAT16_fileSysType, FAT_SIG, sizeof(FAT_SIG)) ||
!memcmp(sectorBuffer + BPB_FAT32_fileSysType, FAT_SIG, sizeof(FAT_SIG))) {
_FAT_mem_free(sectorBuffer);
return part_lba;
}
@ -143,61 +134,53 @@ sec_t FindFirstValidPartition(const DISC_INTERFACE* disc)
for(n=0;n<8;n++) // max 8 logic partitions
{
if(!_FAT_disc_readSectors (disc, part_lba+next_lba2, 1, sectorBuffer)) {
_FAT_mem_free(sectorBuffer);
return 0;
}
if(!_FAT_disc_readSectors (disc, part_lba+next_lba2, 1, sectorBuffer)) return 0;
part_lba2 = part_lba + next_lba2 + u8array_to_u32(sectorBuffer, 0x1C6) ;
next_lba2 = u8array_to_u32(sectorBuffer, 0x1D6);
if(!_FAT_disc_readSectors (disc, part_lba2, 1, sectorBuffer)) {
_FAT_mem_free(sectorBuffer);
return 0;
}
if(!_FAT_disc_readSectors (disc, part_lba2, 1, sectorBuffer)) return 0;
if (!memcmp(sectorBuffer + BPB_FAT16_fileSysType, FAT_SIG, sizeof(FAT_SIG)) ||
!memcmp(sectorBuffer + BPB_FAT32_fileSysType, FAT_SIG, sizeof(FAT_SIG))) {
_FAT_mem_free(sectorBuffer);
!memcmp(sectorBuffer + BPB_FAT32_fileSysType, FAT_SIG, sizeof(FAT_SIG)))
{
return part_lba2;
}
if(next_lba2==0) break;
}
} else {
if(!_FAT_disc_readSectors (disc, part_lba, 1, sectorBuffer)) {
_FAT_mem_free(sectorBuffer);
return 0;
}
if(!_FAT_disc_readSectors (disc, part_lba, 1, sectorBuffer)) return 0;
if (!memcmp(sectorBuffer + BPB_FAT16_fileSysType, FAT_SIG, sizeof(FAT_SIG)) ||
!memcmp(sectorBuffer + BPB_FAT32_fileSysType, FAT_SIG, sizeof(FAT_SIG))) {
_FAT_mem_free(sectorBuffer);
return part_lba;
}
}
}
_FAT_mem_free(sectorBuffer);
return 0;
}
sec_t FindFirstValidPartition(const DISC_INTERFACE* disc)
{
uint8_t *sectorBuffer = (uint8_t*) _FAT_mem_align(MAX_SECTOR_SIZE);
if (!sectorBuffer) return 0;
sec_t ret = FindFirstValidPartition_buf(disc, sectorBuffer);
_FAT_mem_free(sectorBuffer);
return ret;
}
PARTITION* _FAT_partition_constructor (const DISC_INTERFACE* disc, uint32_t cacheSize, uint32_t sectorsPerPage, sec_t startSector) {
PARTITION* _FAT_partition_constructor_buf (const DISC_INTERFACE* disc, uint32_t cacheSize, uint32_t sectorsPerPage, sec_t startSector, uint8_t *sectorBuffer)
{
PARTITION* partition;
uint8_t *sectorBuffer = (uint8_t*) _FAT_mem_allocate(MAX_SECTOR_SIZE);
if(!sectorBuffer) {
return NULL;
}
// Read first sector of disc
if (!_FAT_disc_readSectors (disc, startSector, 1, sectorBuffer)) {
_FAT_mem_free(sectorBuffer);
return NULL;
}
// Make sure it is a valid MBR or boot sector
if ( (sectorBuffer[BPB_bootSig_55] != 0x55) || (sectorBuffer[BPB_bootSig_AA] != 0xAA)) {
_FAT_mem_free(sectorBuffer);
return NULL;
}
@ -210,25 +193,21 @@ PARTITION* _FAT_partition_constructor (const DISC_INTERFACE* disc, uint32_t cach
// Check for FAT32
startSector = 0;
} else {
startSector = FindFirstValidPartition(disc);
startSector = FindFirstValidPartition_buf(disc, sectorBuffer);
if (!_FAT_disc_readSectors (disc, startSector, 1, sectorBuffer)) {
_FAT_mem_free(sectorBuffer);
return NULL;
}
}
_FAT_startSector = startSector;
// Now verify that this is indeed a FAT partition
if (memcmp(sectorBuffer + BPB_FAT16_fileSysType, FAT_SIG, sizeof(FAT_SIG)) &&
memcmp(sectorBuffer + BPB_FAT32_fileSysType, FAT_SIG, sizeof(FAT_SIG))) {
_FAT_mem_free(sectorBuffer);
memcmp(sectorBuffer + BPB_FAT32_fileSysType, FAT_SIG, sizeof(FAT_SIG)))
{
return NULL;
}
partition = (PARTITION*) _FAT_mem_allocate (sizeof(PARTITION));
if (partition == NULL) {
_FAT_mem_free(sectorBuffer);
return NULL;
}
@ -255,19 +234,14 @@ PARTITION* _FAT_partition_constructor (const DISC_INTERFACE* disc, uint32_t cach
partition->numberOfSectors = u8array_to_u32( sectorBuffer, BPB_numSectors);
}
if(disc->features & FEATURE_WII_USB)
partition->bytesPerSector = u8array_to_u16(sectorBuffer, BPB_bytesPerSector);
else
partition->bytesPerSector = MIN_SECTOR_SIZE;
if(partition->bytesPerSector < MIN_SECTOR_SIZE || partition->bytesPerSector > MAX_SECTOR_SIZE) {
// Unsupported sector size
_FAT_mem_free(sectorBuffer);
_FAT_mem_free(partition);
return NULL;
}
partition->sectorsPerCluster = sectorBuffer[BPB_sectorsPerCluster] * u8array_to_u16(sectorBuffer, BPB_bytesPerSector) / partition->bytesPerSector;
partition->sectorsPerCluster = sectorBuffer[BPB_sectorsPerCluster];
partition->bytesPerCluster = partition->bytesPerSector * partition->sectorsPerCluster;
partition->fat.fatStart = startSector + u8array_to_u16(sectorBuffer, BPB_reservedSectors);
@ -322,11 +296,20 @@ PARTITION* _FAT_partition_constructor (const DISC_INTERFACE* disc, uint32_t cach
_FAT_partition_readFSinfo(partition);
_FAT_mem_free(sectorBuffer);
return partition;
}
PARTITION* _FAT_partition_constructor (const DISC_INTERFACE* disc, uint32_t cacheSize, uint32_t sectorsPerPage, sec_t startSector)
{
uint8_t *sectorBuffer = (uint8_t*) _FAT_mem_align(MAX_SECTOR_SIZE);
if (!sectorBuffer) return NULL;
PARTITION *ret = _FAT_partition_constructor_buf(disc, cacheSize,
sectorsPerPage, startSector, sectorBuffer);
_FAT_mem_free(sectorBuffer);
return ret;
}
void _FAT_partition_destructor (PARTITION* partition) {
FILE_STRUCT* nextFile;
@ -370,10 +353,8 @@ void _FAT_partition_createFSinfo(PARTITION * partition)
if(partition->readOnly || partition->filesysType != FS_FAT32)
return;
uint8_t *sectorBuffer = (uint8_t*) _FAT_mem_allocate(partition->bytesPerSector);
if(!sectorBuffer) {
return;
}
uint8_t *sectorBuffer = (uint8_t*) _FAT_mem_align(partition->bytesPerSector);
if (!sectorBuffer) return;
memset(sectorBuffer, 0, partition->bytesPerSector);
int i;
@ -400,10 +381,8 @@ void _FAT_partition_readFSinfo(PARTITION * partition)
if(partition->filesysType != FS_FAT32)
return;
uint8_t *sectorBuffer = (uint8_t*) _FAT_mem_allocate(partition->bytesPerSector);
if(!sectorBuffer) {
return;
}
uint8_t *sectorBuffer = (uint8_t*) _FAT_mem_align(partition->bytesPerSector);
if (!sectorBuffer) return;
memset(sectorBuffer, 0, partition->bytesPerSector);
// Read first sector of disc
if (!_FAT_disc_readSectors (partition->disc, partition->fsInfoSector, 1, sectorBuffer)) {
@ -413,15 +392,14 @@ void _FAT_partition_readFSinfo(PARTITION * partition)
if(memcmp(sectorBuffer+FSIB_SIG1, FS_INFO_SIG1, 4) != 0 ||
memcmp(sectorBuffer+FSIB_SIG2, FS_INFO_SIG2, 4) != 0 ||
u8array_to_u32(sectorBuffer, FSIB_numberOfFreeCluster) == 0) {
u8array_to_u32(sectorBuffer, FSIB_numberOfFreeCluster) == 0)
{
//sector does not yet exist, create one!
_FAT_partition_createFSinfo(partition);
_FAT_mem_free(sectorBuffer);
return;
}
} else {
partition->fat.numberFreeCluster = u8array_to_u32(sectorBuffer, FSIB_numberOfFreeCluster);
partition->fat.numberLastAllocCluster = u8array_to_u32(sectorBuffer, FSIB_numberLastAllocCluster);
}
_FAT_mem_free(sectorBuffer);
}
@ -430,10 +408,8 @@ void _FAT_partition_writeFSinfo(PARTITION * partition)
if(partition->filesysType != FS_FAT32)
return;
uint8_t *sectorBuffer = (uint8_t*) _FAT_mem_allocate(partition->bytesPerSector);
if(!sectorBuffer) {
return;
}
uint8_t *sectorBuffer = (uint8_t*) _FAT_mem_align(partition->bytesPerSector);
if (!sectorBuffer) return;
memset(sectorBuffer, 0, partition->bytesPerSector);
// Read first sector of disc
if (!_FAT_disc_readSectors (partition->disc, partition->fsInfoSector, 1, sectorBuffer)) {
@ -449,7 +425,7 @@ void _FAT_partition_writeFSinfo(PARTITION * partition)
u32_to_u8array(sectorBuffer, FSIB_numberOfFreeCluster, partition->fat.numberFreeCluster);
u32_to_u8array(sectorBuffer, FSIB_numberLastAllocCluster, partition->fat.numberLastAllocCluster);
// Read first sector of disc
// Write first sector of disc
_FAT_disc_writeSectors (partition->disc, partition->fsInfoSector, 1, sectorBuffer);
_FAT_mem_free(sectorBuffer);
}

27
libcustomntfs/AUTHORS Normal file
View File

@ -0,0 +1,27 @@
Present authors of ntfs-3g in alphabetical order:
Jean-Pierre Andre
Alon Bar-Lev
Dominique L Bouix
Csaba Henk
Bernhard Kaindl
Erik Larsson
Alejandro Pulver
Szabolcs Szakacsits
Miklos Szeredi
Past authors in alphabetical order:
Anton Altaparmakov
Mario Emmenlauer
Yuval Fledel
Yura Pakhuchiy
Richard Russon
Nintendo GameCube/Wii port authors in alphabetical order:
Rhys "Shareese" Koedijk
Dimok

50
libcustomntfs/CREDITS Normal file
View File

@ -0,0 +1,50 @@
The following people have contributed directly or indirectly
to the ntfs-3g project.
Please let ntfs-3g-devel@lists.sf.net know if you believe
someone is missing, or if you prefer not to be listed.
Dominique L Bouix
Csaba Henk
Max Khon
Auri Hautam<61>ki
Gergely Erdelyi
Anton Altaparmakov
Peter Boross
Don Bright
Mario Emmenlauer
Yuval Fledel
Kano from Kanotix
Roland Kletzing
Maarten Lankhorst
Gergely Madarasz
Patrick McLean
Florent Mertens
Yura Pakhuchiy
Miklos Szeredi
Bartosz Taudul
Zhanglinbao
Wade Fitzpatrick
Carsten Einig
Adam Cecile
Bruno Damour
Ales Fruman
Curt McDowell
Thomas Franken
Jonatan Lambert
Klaus Knopper
Zhanglinbao
Ismail Donmez
Laszlo Dvornik
Pallaghy Ajtony
Szabolcs Szakacsits
Jean-Pierre Andre
Alejandro Pulver
Erik Larsson
Alon Bar-Lev
The following people have contributed directly or indirectly
to the Nintendo GameCube/Wii port of ntfs-3g.
Michael "Chishm" Chisholm
rodries

340
libcustomntfs/LICENSE Normal file
View File

@ -0,0 +1,340 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

View File

@ -1,32 +1,31 @@
# Quick'n'dirty makefile [BC] v2
ifeq ($(strip $(DEVKITPPC)),)
$(error "Please set DEVKITPPC in your environment. export DEVKITPPC=<path to>devkitPPC")
endif
default: cube-release wii-release
include $(DEVKITPPC)/wii_rules
all: debug release
LIBOGC_INC := $(DEVKITPRO)/libogc/include
LIBOGC_LIB := $(DEVKITPRO)/libogc/lib/wii
debug: cube-debug wii-debug
CFLAGS := -O3 $(MACHDEP) -I$(LIBOGC_INC) -DHAVE_CONFIG_H
release: cube-release wii-release
LIB := ntfs
CFILES := $(wildcard *.c)
OFILES := $(CFILES:.c=.o)
ARC := lib$(LIB).a
HDR := ntfs.h
cube-debug:
$(MAKE) -C source PLATFORM=cube BUILD=cube_debug
all : $(OFILES)
$(AR) -r $(ARC) $(OFILES)
wii-debug:
$(MAKE) -C source PLATFORM=wii BUILD=wii_debug
clean :
rm -f $(OFILES) $(ARC)
cube-release:
$(MAKE) -C source PLATFORM=cube BUILD=cube_release
install :
mkdir -p $(LIBOGC_LIB) $(LIBOGC_INC)
cp -f $(ARC) $(LIBOGC_LIB)/
cp -f $(HDR) $(LIBOGC_INC)/
wii-release:
$(MAKE) -C source PLATFORM=wii BUILD=wii_release
clean:
$(MAKE) -C source clean
install: cube-release wii-release
$(MAKE) -C source install
run: install
$(MAKE) -C example
$(MAKE) -C example run
%.o : %.c
$(CC) $(CFLAGS) -c $< -o $@

54
libcustomntfs/READMII Normal file
View File

@ -0,0 +1,54 @@
INTRODUCTION
============
The NTFS-3G driver is an open source, freely available read/write NTFS driver
for Linux, FreeBSD, Mac OS X, NetBSD, Solaris and Haiku. It provides safe and
fast handling of the Windows XP, Windows Server 2003, Windows 2000, Windows
Vista, and Windows Server 2008 file systems.
The purpose of the project is to develop, continuously quality test and
support a trustable, featureful and high performance solution for hardware
platforms and operating systems whose users need to reliably interoperate
with NTFS. Besides this practical goal, the project also aims to explore
the limits of the hybrid, kernel/user space filesystem driver approach,
performance, reliability and feature richness per invested effort wise.
The driver is in STABLE status. The test methods, the test suites used
can be found at
http://ntfs-3g.org/quality.html
News, support answers, problem submission instructions, support and discussion
forums, performance numbers and other information are available on the project
web site at
http://ntfs-3g.org
For more details on the NTFS-3G project see the 'original' folder included
with this package.
COMPILING AND INSTALLATION
==========================
Make sure you have devKitPPC and the latest libogc installed. Then type:
make
make install # or 'sudo make install' if you aren't root.
USAGE
=====
NTFS related routines can be accessed by adding the following line to your
source file(s).
#include <ntfs.h>
When compiling you must also link against the libntfs. To do this add -lntfs
to the LIBS section of your application Makefile. For example:
LIBS := -lwiiuse -lbte -lntfs -lfat -logc -lm
For a more practical example of using NTFS in your application,
see the included 'example' folder.

View File

@ -0,0 +1,148 @@
/**
* ntfs.h - Simple functionality for startup, mounting and unmounting of NTFS-based devices.
*
* Copyright (c) 2010 Dimok
* Copyright (c) 2009 Rhys "Shareese" Koedijk
* Copyright (c) 2006 Michael "Chishm" Chisholm
*
* This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program/include file is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _LIBNTFS_H
#define _LIBNTFS_H
#ifdef __cplusplus
extern "C" {
#endif
#include <gctypes.h>
#include <gccore.h>
#include <ogc/disc_io.h>
/* NTFS errno values */
#define ENOPART 3000 /* No partition was found */
#define EINVALPART 3001 /* Specified partition is invalid or not supported */
#define EDIRTY 3002 /* Volume is dirty and NTFS_RECOVER was not specified during mount */
#define EHIBERNATED 3003 /* Volume is hibernated and NTFS_IGNORE_HIBERFILE was not specified during mount */
/* NTFS cache options */
#define CACHE_DEFAULT_PAGE_COUNT 8 /* The default number of pages in the cache */
#define CACHE_DEFAULT_PAGE_SIZE 128 /* The default number of sectors per cache page */
/* NTFS mount flags */
#define NTFS_DEFAULT 0x00000000 /* Standard mount, expects a clean, non-hibernated volume */
#define NTFS_SHOW_HIDDEN_FILES 0x00000001 /* Display hidden files when enumerating directories */
#define NTFS_SHOW_SYSTEM_FILES 0x00000002 /* Display system files when enumerating directories */
#define NTFS_UPDATE_ACCESS_TIMES 0x00000004 /* Update file and directory access times */
#define NTFS_RECOVER 0x00000008 /* Reset $LogFile if dirty (i.e. from unclean disconnect) */
#define NTFS_IGNORE_HIBERFILE 0x00000010 /* Mount even if volume is hibernated */
#define NTFS_READ_ONLY 0x00000020 /* Mount in read only mode */
#define NTFS_IGNORE_CASE 0x00000040 /* Ignore case sensitivity. Everything must be and will be provided in lowercase. */
#define NTFS_SU NTFS_SHOW_HIDDEN_FILES | NTFS_SHOW_SYSTEM_FILES
#define NTFS_FORCE NTFS_RECOVER | NTFS_IGNORE_HIBERFILE
/**
* ntfs_md - NTFS mount descriptor
*/
typedef struct _ntfs_md {
char name[32]; /* Mount name (can be accessed as "name:/") */
const DISC_INTERFACE *interface; /* Block device containing the mounted partition */
sec_t startSector; /* Local block address to first sector of partition */
} ntfs_md;
/**
* Find all NTFS partitions on a block device.
*
* @param INTERFACE The block device to search
* @param PARTITIONS (out) A pointer to receive the array of partition start sectors
*
* @return The number of entries in PARTITIONS or -1 if an error occurred (see errno)
* @note The caller is responsible for freeing PARTITIONS when finished with it
*/
extern int ntfsFindPartitions (const DISC_INTERFACE *interface, sec_t **partitions);
/**
* Mount all NTFS partitions on all inserted block devices.
*
* @param MOUNTS (out) A pointer to receive the array of mount descriptors
* @param FLAGS Additional mounting flags. (see above)
*
* @return The number of entries in MOUNTS or -1 if an error occurred (see errno)
* @note The caller is responsible for freeing MOUNTS when finished with it
* @note All device caches are setup using default values (see above)
*/
extern int ntfsMountAll (ntfs_md **mounts, u32 flags);
/**
* Mount all NTFS partitions on a block devices.
*
* @param INTERFACE The block device to mount.
* @param MOUNTS (out) A pointer to receive the array of mount descriptors
* @param FLAGS Additional mounting flags. (see above)
*
* @return The number of entries in MOUNTS or -1 if an error occurred (see errno)
* @note The caller is responsible for freeing MOUNTS when finished with it
* @note The device cache is setup using default values (see above)
*/
extern int ntfsMountDevice (const DISC_INTERFACE* interface, ntfs_md **mounts, u32 flags);
/**
* Mount a NTFS partition from a specific sector on a block device.
*
* @param NAME The name to mount the device under (can then be accessed as "NAME:/")
* @param INTERFACE The block device to mount
* @param STARTSECTOR The sector the partition begins at (see @ntfsFindPartitions)
* @param CACHEPAGECOUNT The total number of pages in the device cache
* @param CACHEPAGESIZE The number of sectors per cache page
* @param FLAGS Additional mounting flags (see above)
*
* @return True if mount was successful, false if no partition was found or an error occurred (see errno)
* @note ntfsFindPartitions should be used first to locate the partitions start sector
*/
extern bool ntfsMount (const char *name, const DISC_INTERFACE *interface, sec_t startSector, u32 cachePageCount, u32 cachePageSize, u32 flags);
/**
* Unmount a NTFS partition.
*
* @param NAME The name of mount used in ntfsMountSimple() and ntfsMount()
* @param FORCE If true unmount even if the device is busy (may lead to data lose)
*/
extern void ntfsUnmount (const char *name, bool force);
/**
* Get the volume name of a mounted NTFS partition.
*
* @param NAME The name of mount (see @ntfsMountAll, @ntfsMountDevice, and @ntfsMount)
*
* @return The volumes name if successful or NULL if an error occurred (see errno)
*/
extern const char *ntfsGetVolumeName (const char *name);
/**
* Set the volume name of a mounted NTFS partition.
*
* @param NAME The name of mount (see @ntfsMountAll, @ntfsMountDevice, and @ntfsMount)
* @param VOLUMENAME The new volume name
*
* @return True if mount was successful, false if an error occurred (see errno)
* @note The mount must be write-enabled else this will fail
*/
extern bool ntfsSetVolumeName (const char *name, const char *volumeName);
#ifdef __cplusplus
}
#endif
#endif /* _LIBNTFS_H */

View File

@ -0,0 +1,130 @@
#---------------------------------------------------------------------------------
# Clear the implicit built in rules
#---------------------------------------------------------------------------------
.SUFFIXES:
#---------------------------------------------------------------------------------
ifeq ($(strip $(DEVKITPPC)),)
$(error "Please set DEVKITPPC in your environment. export DEVKITPPC=<path to>devkitPPC")
endif
ifeq ($(PLATFORM),wii)
include $(DEVKITPPC)/wii_rules
endif
ifeq ($(PLATFORM),cube)
include $(DEVKITPPC)/gamecube_rules
endif
#---------------------------------------------------------------------------------
# BUILD is the directory where object files & intermediate files will be placed
# SOURCES is a list of directories containing source code
# INCLUDES is a list of directories containing extra header files
#---------------------------------------------------------------------------------
BUILD ?= wii_release
SOURCES := .
INCLUDES := ../include
LIBDIR := ../lib
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
CFLAGS = -O2 -Wall -ffast-math -pipe $(MACHDEP) $(INCLUDE) -DHAVE_CONFIG_H
CXXFLAGS = $(CFLAGS)
ASFLAGS := -g
export NTFSBIN := $(LIBDIR)/$(PLATFORM)/libntfs.a
ifeq ($(BUILD),cube_debug)
CFLAGS += -DDEBUG
CXXFLAGS += -DDEBUG
endif
ifeq ($(BUILD),wii_debug)
CFLAGS += -DDEBUG
CXXFLAGS += -DDEBUG
endif
#---------------------------------------------------------------------------------
# any extra libraries we wish to link with the project
#---------------------------------------------------------------------------------
LIBS :=
#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS :=
#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export DEPSDIR := $(CURDIR)/$(BUILD)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
export OFILES := $(addsuffix .o,$(BINFILES)) \
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
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)
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) \
-L$(LIBOGC_LIB)
.PHONY: $(BUILD) clean
#---------------------------------------------------------------------------------
$(BUILD):
@[ -d $@ ] || mkdir -p $@
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr wii_debug wii_release cube_debug cube_release $(LIBDIR)
all: $(NTFSBIN)
install:
cp ../include/ntfs.h $(DEVKITPRO)/libogc/include
cp ../lib/wii/libntfs.a $(DEVKITPRO)/libogc/lib/wii
cp ../lib/cube/libntfs.a $(DEVKITPRO)/libogc/lib/cube
wii-install:
cp ../include/ntfs.h $(DEVKITPRO)/libogc/include
cp ../lib/wii/libntfs.a $(DEVKITPRO)/libogc/lib/wii
#---------------------------------------------------------------------------------
else
DEPENDS := $(OFILES:.o=.d)
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
$(NTFSBIN): $(OFILES) $(LIBDIR)/$(PLATFORM)
@rm -f "../$(NTFSBIN)"
@$(AR) rcs "../$(NTFSBIN)" $(OFILES)
@echo built ... $(notdir $@)
$(LIBDIR)/$(PLATFORM):
mkdir -p ../$(LIBDIR)/$(PLATFORM)
-include $(DEPENDS)
#---------------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------------

View File

@ -522,9 +522,7 @@ gid_t ntfs_find_group(const struct MAPPING* groupmapping, const SID * gsid)
{
gid_t gid;
const struct MAPPING *p;
int gsidsz;
gsidsz = ntfs_sid_size(gsid);
p = groupmapping;
while (p && p->xid && !ntfs_same_sid(gsid, p->sid))
p = p->next;
@ -1901,7 +1899,6 @@ static int buildacls_posix(struct MAPPING* const mapping[],
const SID *sid;
int acecnt;
int usidsz;
int gsidsz;
int wsidsz;
int asidsz;
int ssidsz;
@ -1909,7 +1906,6 @@ static int buildacls_posix(struct MAPPING* const mapping[],
le32 grants;
usidsz = ntfs_sid_size(usid);
gsidsz = ntfs_sid_size(gsid);
wsidsz = ntfs_sid_size(worldsid);
asidsz = ntfs_sid_size(adminsid);
ssidsz = ntfs_sid_size(systemsid);
@ -3132,7 +3128,6 @@ static int norm_ownadmin_permissions_posix(struct POSIX_SECURITY *posix_desc,
u16 tag;
u16 tagsset;
struct POSIX_ACE *pxace;
int acccnt;
mode_t denywrld;
mode_t allow;
mode_t deny;
@ -3141,7 +3136,6 @@ static int norm_ownadmin_permissions_posix(struct POSIX_SECURITY *posix_desc,
mode = 0;
pxace = posix_desc->acl.ace;
acccnt = posix_desc->acccnt;
tagsset = 0;
denywrld = 0;
/*
@ -3881,12 +3875,10 @@ struct POSIX_SECURITY *ntfs_build_permissions_posix(
int ntfs_build_permissions(const char *securattr,
const SID *usid, const SID *gsid, BOOL isdir)
{
const SECURITY_DESCRIPTOR_RELATIVE *phead;
int perm;
BOOL adminowns;
BOOL groupowns;
phead = (const SECURITY_DESCRIPTOR_RELATIVE*)securattr;
adminowns = ntfs_same_sid(usid,adminsid)
|| ntfs_same_sid(gsid,adminsid);
groupowns = !adminowns && ntfs_same_sid(gsid,usid);
@ -3969,7 +3961,6 @@ static struct MAPLIST *getmappingitem(FILEREADER reader, void *fileid,
{
int src;
int dst;
char *p;
char *q;
char *pu;
char *pg;
@ -4003,7 +3994,6 @@ static struct MAPLIST *getmappingitem(FILEREADER reader, void *fileid,
if (gotend) {
pu = pg = (char*)NULL;
/* decompose into uid, gid and sid */
p = item->maptext;
item->uidstr = item->maptext;
item->gidstr = strchr(item->uidstr, ':');
if (item->gidstr) {

View File

@ -476,8 +476,9 @@ ntfs_attr *ntfs_attr_open(ntfs_inode *ni, const ATTR_TYPES type,
cs = a->flags & (ATTR_IS_COMPRESSED | ATTR_IS_SPARSE);
/* a file may be sparse though its unnamed data is not (cf $UsnJrnl) */
if (na->type == AT_DATA && na->name == AT_UNNAMED &&
((!(a->flags & ATTR_IS_SPARSE) != !NAttrSparse(na)) ||
(((a->flags & ATTR_IS_SPARSE) && !NAttrSparse(na)) ||
(!(a->flags & ATTR_IS_ENCRYPTED) != !NAttrEncrypted(na)))) {
errno = EIO;
ntfs_log_perror("Inode %lld has corrupt attribute flags "
@ -1774,7 +1775,6 @@ s64 ntfs_attr_pwrite(ntfs_attr *na, const s64 pos, s64 count, const void *b)
} need_to = { 0, 0 };
BOOL wasnonresident = FALSE;
BOOL compressed;
BOOL sparse;
BOOL updatemap;
ntfs_log_enter("Entering for inode %lld, attr 0x%x, pos 0x%llx, count "
@ -1850,7 +1850,7 @@ s64 ntfs_attr_pwrite(ntfs_attr *na, const s64 pos, s64 count, const void *b)
goto errno_set;
}
#else
if (ntfs_attr_truncate(na, pos + count)) {
if (ntfs_attr_truncate_i(na, pos + count, HOLES_OK)) {
ntfs_log_perror("Failed to enlarge attribute");
goto errno_set;
}
@ -1860,7 +1860,6 @@ s64 ntfs_attr_pwrite(ntfs_attr *na, const s64 pos, s64 count, const void *b)
!= const_cpu_to_le16(0);
need_to.undo_data_size = 1;
}
sparse = (na->data_flags & ATTR_IS_SPARSE) != const_cpu_to_le16(0);
/*
* For compressed data, a single full block was allocated
* to deal with compression, possibly in a previous call.
@ -2221,7 +2220,7 @@ done:
updatemap = (compressed
? NAttrFullyMapped(na) != 0 : update_from != -1);
#endif
if (updatemap)
if (updatemap) {
if (ntfs_attr_update_mapping_pairs(na,
(update_from < 0 ? 0 : update_from))) {
/*
@ -2231,6 +2230,10 @@ done:
total = -1;
goto out;
}
if (!wasnonresident)
NAttrClearBeingNonResident(na);
NAttrClearDataAppending(na);
}
out:
ntfs_log_leave("\n");
return total;
@ -2292,7 +2295,8 @@ err_out:
if (updatemap)
ntfs_attr_update_mapping_pairs(na, 0);
/* Restore original data_size if needed. */
if (need_to.undo_data_size && ntfs_attr_truncate(na, old_data_size))
if (need_to.undo_data_size
&& ntfs_attr_truncate_i(na, old_data_size, HOLES_OK))
ntfs_log_perror("Failed to restore data_size");
errno = eo;
errno_set:
@ -2310,7 +2314,6 @@ int ntfs_attr_pclose(ntfs_attr *na)
ntfs_attr_search_ctx *ctx = NULL;
runlist_element *rl;
int eo;
s64 hole;
int compressed_part;
BOOL compressed;
@ -2422,7 +2425,6 @@ int ntfs_attr_pclose(ntfs_attr *na)
goto rl_err_out;
}
if (rl->lcn < (LCN)0) {
hole = rl->vcn + rl->length;
if (rl->lcn != (LCN)LCN_HOLE) {
errno = EIO;
ntfs_log_perror("%s: Unexpected LCN (%lld)",
@ -2475,6 +2477,7 @@ retry:
goto out;
}
out:
NAttrClearComprClosing(na);
ntfs_log_leave("\n");
return (!ok);
rl_err_out:
@ -2531,6 +2534,7 @@ s64 ntfs_attr_mst_pread(ntfs_attr *na, const s64 pos, const s64 bk_cnt,
{
s64 br;
u8 *end;
BOOL warn;
ntfs_log_trace("Entering for inode 0x%llx, attr type 0x%x, pos 0x%llx.\n",
(unsigned long long)na->ni->mft_no, na->type,
@ -2544,9 +2548,11 @@ s64 ntfs_attr_mst_pread(ntfs_attr *na, const s64 pos, const s64 bk_cnt,
if (br <= 0)
return br;
br /= bk_size;
/* log errors unless silenced */
warn = !na->ni || !na->ni->vol || !NVolNoFixupWarn(na->ni->vol);
for (end = (u8*)dst + br * bk_size; (u8*)dst < end; dst = (u8*)dst +
bk_size)
ntfs_mst_post_read_fixup((NTFS_RECORD*)dst, bk_size);
ntfs_mst_post_read_fixup_warn((NTFS_RECORD*)dst, bk_size, warn);
/* Finally, return the number of blocks read. */
return br;
}
@ -3545,6 +3551,14 @@ int ntfs_attr_size_bounds_check(const ntfs_volume *vol, const ATTR_TYPES type,
min_size = sle64_to_cpu(ad->min_size);
max_size = sle64_to_cpu(ad->max_size);
/* The $AttrDef generated by Windows specifies 2 as min_size for the
* volume name attribute, but in reality Windows sets it to 0 when
* clearing the volume name. If we want to be able to clear the volume
* name we must also accept 0 as min_size, despite the $AttrDef
* definition. */
if(type == AT_VOLUME_NAME)
min_size = 0;
if ((min_size && (size < min_size)) ||
((max_size > 0) && (size > max_size))) {
errno = ERANGE;
@ -4296,7 +4310,7 @@ add_non_resident:
goto rm_attr_err_out;
}
/* Resize and set attribute value. */
if (ntfs_attr_truncate(na, size) ||
if (ntfs_attr_truncate_i(na, size, HOLES_OK) ||
(val && (ntfs_attr_pwrite(na, 0, size, val) != size))) {
err = errno;
ntfs_log_perror("Failed to initialize just added attribute");
@ -4877,6 +4891,7 @@ cluster_free_err_out:
ntfs_log_trace("Eeek! Failed to release allocated clusters in error "
"code path. Leaving inconsistent metadata...\n");
NAttrClearNonResident(na);
NAttrClearFullyMapped(na);
na->allocated_size = na->data_size;
na->rl = NULL;
free(rl);
@ -5000,7 +5015,7 @@ static int ntfs_resident_attr_resize_i(ntfs_attr *na, const s64 newsize,
return (ret);
}
/* Resize non-resident attribute */
return ntfs_attr_truncate(na, newsize);
return ntfs_attr_truncate_i(na, newsize, HOLES_OK);
} else if (errno != ENOSPC && errno != EPERM) {
err = errno;
ntfs_log_perror("Failed to make attribute non-resident");
@ -5348,7 +5363,6 @@ static int ntfs_attr_make_resident(ntfs_attr *na, ntfs_attr_search_ctx *ctx)
* record is in a transiently corrupted state at this moment in time.
*/
if (ntfs_cluster_free(vol, na, 0, -1) < 0) {
err = errno;
ntfs_log_perror("Eeek! Failed to release allocated clusters");
ntfs_log_trace("Ignoring error and leaving behind wasted "
"clusters.\n");
@ -5360,6 +5374,7 @@ static int ntfs_attr_make_resident(ntfs_attr *na, ntfs_attr_search_ctx *ctx)
/* Update in-memory struct ntfs_attr. */
NAttrClearNonResident(na);
NAttrClearFullyMapped(na);
NAttrClearSparse(na);
NAttrClearEncrypted(na);
na->initialized_size = na->data_size;
@ -5453,6 +5468,7 @@ static int ntfs_attr_update_meta(ATTR_RECORD *a, ntfs_attr *na, MFT_RECORD *m,
NAttrClearSparse(na);
a->flags &= ~ATTR_IS_SPARSE;
na->data_flags = a->flags;
a->compression_unit = 0;
memmove((u8*)a + le16_to_cpu(a->name_offset) - 8,
@ -6422,7 +6438,12 @@ out:
int ntfs_attr_truncate(ntfs_attr *na, const s64 newsize)
{
return (ntfs_attr_truncate_i(na, newsize, HOLES_OK));
int r;
r = ntfs_attr_truncate_i(na, newsize, HOLES_OK);
NAttrClearDataAppending(na);
NAttrClearBeingNonResident(na);
return (r);
}
/*

View File

@ -376,7 +376,6 @@ int ntfs_invalidate_cache(struct CACHE_HEADER *cache,
int flags)
{
struct CACHED_GENERIC *current;
struct CACHED_GENERIC *previous;
struct CACHED_GENERIC *next;
struct HASH_ENTRY *link;
int count;
@ -412,7 +411,6 @@ int ntfs_invalidate_cache(struct CACHE_HEADER *cache,
* Search sequentially in LRU list
*/
current = cache->most_recent_entry;
previous = (struct CACHED_GENERIC*)NULL;
while (current) {
if (!compare(current, item)) {
next = current->next;
@ -423,7 +421,6 @@ int ntfs_invalidate_cache(struct CACHE_HEADER *cache,
current = next;
count++;
} else {
previous = current;
current = current->next;
}
}

View File

@ -81,259 +81,215 @@ typedef enum {
NTFS_SB_IS_COMPRESSED = 0x8000,
} ntfs_compression_constants;
#define THRESHOLD 3 /* minimal match length for compression */
#define NIL NTFS_SB_SIZE /* End of tree's node */
struct COMPRESS_CONTEXT {
const unsigned char *inbuf;
unsigned int len;
unsigned int nbt;
int match_position;
unsigned int match_length;
u16 lson[NTFS_SB_SIZE + 1];
u16 rson[NTFS_SB_SIZE + 257];
u16 dad[NTFS_SB_SIZE + 1];
int bufsize;
int size;
int rel;
int mxsz;
s16 head[256];
s16 lson[NTFS_SB_SIZE];
s16 rson[NTFS_SB_SIZE];
} ;
/*
* Initialize the match tree
* Search for the longest sequence matching current position
*
* A binary tree is maintained to locate all previously met sequences,
* and this function has to be called for all of them.
*
* This function is heavily used, it has to be optimized carefully
*
* Returns the size of the longest match,
* zero if no match is found.
*/
static void ntfs_init_compress_tree(struct COMPRESS_CONTEXT *pctx)
static int ntfs_best_match(struct COMPRESS_CONTEXT *pctx, int i)
{
int i;
for (i = NTFS_SB_SIZE + 1; i <= NTFS_SB_SIZE + 256; i++)
pctx->rson[i] = NIL; /* root */
for (i = 0; i < NTFS_SB_SIZE; i++)
pctx->dad[i] = NIL; /* node */
}
/*
* Insert a new node into match tree for quickly locating
* further similar strings
*/
static void ntfs_new_node (struct COMPRESS_CONTEXT *pctx,
unsigned int r)
{
unsigned int pp;
BOOL less;
BOOL done;
const unsigned char *key;
int c;
unsigned long mxi;
unsigned int mxl;
mxl = (1 << (16 - pctx->nbt)) + 2;
less = FALSE;
done = FALSE;
key = &pctx->inbuf[r];
pp = NTFS_SB_SIZE + 1 + key[0];
pctx->rson[r] = pctx->lson[r] = NIL;
pctx->match_length = 0;
do {
if (!less) {
if (pctx->rson[pp] != NIL)
pp = pctx->rson[pp];
else {
pctx->rson[pp] = r;
pctx->dad[r] = pp;
done = TRUE;
}
} else {
if (pctx->lson[pp] != NIL)
pp = pctx->lson[pp];
else {
pctx->lson[pp] = r;
pctx->dad[r] = pp;
done = TRUE;
}
}
if (!done) {
register unsigned long i;
s16 *prev;
int node;
register long j;
long maxpos;
long startj;
long bestj;
int bufsize;
int bestnode;
register const unsigned char *p1,*p2;
i = 1;
mxi = NTFS_SB_SIZE - r;
if (mxi < 2)
less = FALSE;
else {
p1 = key;
p2 = &pctx->inbuf[pp];
/* this loop has a significant impact on performances */
p1 = pctx->inbuf;
node = pctx->head[p1[i] & 255];
if (node >= 0) {
/* search the best match at current position */
bestnode = node;
bufsize = pctx->bufsize;
/* restrict matches to the longest allowed sequence */
maxpos = bufsize;
if ((i + pctx->mxsz) < maxpos)
maxpos = i + pctx->mxsz;
startj = i + 1 - maxpos;
bestj = startj;
/* make indexes relative to end of allowed position */
p1 = &p1[maxpos];
if (startj < 0) {
do {
} while ((p1[i] == p2[i]) && (++i < mxi));
less = (i < mxi) && (p1[i] < p2[i]);
/* indexes are negative */
p2 = &p1[node - i];
/* no need to compare the first byte */
j = startj;
/* the second byte cannot lead to useful compression */
if (p1[j] == p2[j]) {
j++;
if (j < 0) {
do {
} while ((p1[j] == p2[j])
&& (++j < 0));
}
if (i >= THRESHOLD) {
if (i > pctx->match_length) {
pctx->match_position =
r - pp + 2*NTFS_SB_SIZE - 1;
if ((pctx->match_length = i) > mxl) {
i = pctx->rson[pp];
pctx->rson[r] = i;
pctx->dad[i] = r;
i = pctx->lson[pp];
pctx->lson[r] = i;
pctx->dad[i] = r;
i = pctx->dad[pp];
pctx->dad[r] = i;
if (pctx->rson[i] == pp)
pctx->rson[i] = r;
/* remember the match, if better */
if (j > bestj) {
bestj = j;
bestnode = node;
}
}
/* walk in the tree in the right direction */
if ((j < 0) && (p1[j] < p2[j]))
prev = &pctx->lson[node];
else
pctx->lson[i] = r;
/* remove pp */
pctx->dad[pp] = NIL;
done = TRUE;
pctx->match_length = mxl;
prev = &pctx->rson[node];
node = *prev;
/* stop if reaching a leaf or maximum length */
} while ((node >= 0) && (j < 0));
/* put the node into the tree if we reached a leaf */
if (node < 0)
*prev = i;
}
} else
if ((i == pctx->match_length)
&& ((c = (r - pp + 2*NTFS_SB_SIZE - 1))
< pctx->match_position))
pctx->match_position = c;
/* done, return the best match */
pctx->size = bestj + maxpos - i;
pctx->rel = bestnode - i;
} else {
pctx->head[p1[i] & 255] = i;
pctx->size = 0;
pctx->rel = 0;
}
}
} while (!done);
return (pctx->size);
}
/*
* Search for the longest previous string matching the
* current one
* Compress a 4096-byte block
*
* Returns the end of the longest current string which matched
* or zero if there was a bug
* Returns a header of two bytes followed by the compressed data.
* If compression is not effective, the header and an uncompressed
* block is returned.
*
* Note : two bytes may be output before output buffer overflow
* is detected, so a 4100-bytes output buffer must be reserved.
*
* Returns the size of the compressed block, including the
* header (minimal size is 2, maximum size is 4098)
* 0 if an error has been met.
*/
static unsigned int ntfs_nextmatch(struct COMPRESS_CONTEXT *pctx,
unsigned int rr, int dd)
{
unsigned int bestlen = 0;
do {
rr++;
if (pctx->match_length > 0)
pctx->match_length--;
if (!pctx->len) {
ntfs_log_error("compress bug : void run\n");
goto bug;
}
if (--pctx->len) {
if (rr >= NTFS_SB_SIZE) {
ntfs_log_error("compress bug : buffer overflow\n");
goto bug;
}
if (((rr + bestlen) < NTFS_SB_SIZE)) {
while ((unsigned int)(1 << pctx->nbt)
<= (rr - 1))
pctx->nbt++;
ntfs_new_node(pctx,rr);
if (pctx->match_length > bestlen)
bestlen = pctx->match_length;
} else
if (dd > 0) {
rr += dd;
if ((int)pctx->match_length > dd)
pctx->match_length -= dd;
else
pctx->match_length = 0;
if ((int)pctx->len < dd) {
ntfs_log_error("compress bug : run overflows\n");
goto bug;
}
pctx->len -= dd;
dd = 0;
}
}
} while (dd-- > 0);
return (rr);
bug :
return (0);
}
/*
* Compress an input block
*
* Returns the size of the compressed block (including header)
* or zero if there was an error
*/
static unsigned int ntfs_compress_block(const char *inbuf,
unsigned int size, char *outbuf)
static unsigned int ntfs_compress_block(const char *inbuf, int bufsize,
char *outbuf)
{
struct COMPRESS_CONTEXT *pctx;
char *ptag;
int dd;
unsigned int rr;
unsigned int last_match_length;
unsigned int q;
int i; /* current position */
int j; /* end of best match from current position */
int k; /* end of best match from next position */
int offs; /* offset to best match */
int n;
int bp; /* bits to store offset */
int mxoff; /* max match offset : 1 << bp */
int mxsz2;
unsigned int xout;
unsigned int ntag;
unsigned int q; /* aggregated offset and size */
int done;
char *ptag; /* location reserved for a tag */
int tag; /* current value of tag */
int ntag; /* count of bits still undefined in tag */
pctx = (struct COMPRESS_CONTEXT*)ntfs_malloc(sizeof(struct COMPRESS_CONTEXT));
if (pctx) {
for (n=0; n<NTFS_SB_SIZE; n++)
pctx->lson[n] = pctx->rson[n] = -1;
for (n=0; n<256; n++)
pctx->head[n] = -1;
pctx->inbuf = (const unsigned char*)inbuf;
ntfs_init_compress_tree(pctx);
pctx->bufsize = bufsize;
xout = 2;
ntag = 0;
n = 0;
i = 0;
bp = 4;
mxoff = 1 << bp;
pctx->mxsz = (1 << (16 - bp)) + 2;
tag = 0;
done = -1;
ntag = 8;
ptag = &outbuf[xout++];
*ptag = 0;
rr = 0;
pctx->nbt = 4;
pctx->len = size;
pctx->match_length = 0;
ntfs_new_node(pctx,0);
while ((i < bufsize) && (xout < (NTFS_SB_SIZE + 2))) {
/* adjust the longest match we can output */
while (mxoff < i) {
bp++;
mxoff <<= 1;
pctx->mxsz = (pctx->mxsz + 2) >> 1;
}
/* search the best match at current position */
if (done < i)
do {
if (pctx->match_length > pctx->len)
pctx->match_length = pctx->len;
if (pctx->match_length < THRESHOLD) {
pctx->match_length = 1;
if (ntag >= 8) {
ntag = 0;
ptag = &outbuf[xout++];
*ptag = 0;
}
outbuf[xout++] = inbuf[rr];
ntag++;
ntfs_best_match(pctx,++done);
} while (done < i);
j = i + pctx->size;
if ((j - i) > pctx->mxsz)
j = i + pctx->mxsz;
if ((j - i) > 2) {
offs = pctx->rel;
/* check whether there is a better run at i+1 */
ntfs_best_match(pctx,i+1);
done = i+1;
k = i + 1 + pctx->size;
mxsz2 = pctx->mxsz;
if (mxoff <= i)
mxsz2 = (pctx->mxsz + 2) >> 1;
if ((k - i) > mxsz2)
k = i + mxsz2;
if (k > (j + 1)) {
/* issue a single byte */
outbuf[xout++] = inbuf[i];
i++;
} else {
while ((unsigned int)(1 << pctx->nbt)
<= (rr - 1))
pctx->nbt++;
q = (pctx->match_position << (16 - pctx->nbt))
+ pctx->match_length - THRESHOLD;
if (ntag >= 8) {
ntag = 0;
ptag = &outbuf[xout++];
*ptag = 0;
}
*ptag |= 1 << ntag++;
q = (~offs << (16 - bp))
+ (j - i - 3);
outbuf[xout++] = q & 255;
outbuf[xout++] = (q >> 8) & 255;
tag |= (1 << (8 - ntag));
i = j;
}
last_match_length = pctx->match_length;
dd = last_match_length;
if (dd-- > 0) {
rr = ntfs_nextmatch(pctx,rr,dd);
if (!rr)
goto bug;
} else {
outbuf[xout++] = inbuf[i];
i++;
}
/*
* stop if input is exhausted or output has exceeded
* the maximum size. Two extra bytes have to be
* reserved in output buffer, as 3 bytes may be
* output in a loop.
*/
} while ((pctx->len > 0)
&& (rr < size) && (xout < (NTFS_SB_SIZE + 2)));
/* uncompressed must be full size, so accept if better */
if (xout < (NTFS_SB_SIZE + 2)) {
/* store the tag if fully used */
if (!--ntag) {
*ptag = tag;
ntag = 8;
ptag = &outbuf[xout++];
tag = 0;
}
}
/* store the last tag, if partially used */
if (ntag == 8)
xout--;
else
*ptag = tag;
/* uncompressed must be full size, accept if better */
if ((i >= bufsize) && (xout < (NTFS_SB_SIZE + 2))) {
outbuf[0] = (xout - 3) & 255;
outbuf[1] = 0xb0 + (((xout - 3) >> 8) & 15);
} else {
memcpy(&outbuf[2],inbuf,size);
if (size < NTFS_SB_SIZE)
memset(&outbuf[size+2],0,NTFS_SB_SIZE - size);
memcpy(&outbuf[2],inbuf,bufsize);
if (bufsize < NTFS_SB_SIZE)
memset(&outbuf[bufsize+2], 0,
NTFS_SB_SIZE - bufsize);
outbuf[0] = 0xff;
outbuf[1] = 0x3f;
xout = NTFS_SB_SIZE + 2;
@ -343,9 +299,7 @@ static unsigned int ntfs_compress_block(const char *inbuf,
xout = 0;
errno = ENOMEM;
}
return (xout); /* 0 for an error, > size if cannot compress */
bug :
return (0);
return (xout);
}
/**
@ -1512,12 +1466,12 @@ static int ntfs_read_append(ntfs_attr *na, const runlist_element *rl,
* or -1 if there were an irrecoverable error (errno set)
*/
static int ntfs_flush(ntfs_attr *na, runlist_element *rl, s64 offs,
static s32 ntfs_flush(ntfs_attr *na, runlist_element *rl, s64 offs,
const char *outbuf, s32 count, BOOL compress,
BOOL appending, VCN *update_from)
{
int rounded;
int written;
s32 rounded;
s32 written;
int clsz;
if (compress) {
@ -1655,7 +1609,7 @@ s64 ntfs_compressed_pwrite(ntfs_attr *na, runlist_element *wrl, s64 wpos,
* (we are reopening an existing file to append to it)
* Decompress the data and append
*/
compsz = compressed_part << vol->cluster_size_bits;
compsz = (s32)compressed_part << vol->cluster_size_bits;
outbuf = (char*)ntfs_malloc(na->compression_block_size);
if (outbuf) {
if (appending) {

View File

@ -226,6 +226,9 @@
/* Define to 1 if you have the <sys/byteorder.h> header file. */
#undef HAVE_SYS_BYTEORDER_H
/* Define to 1 if you have the <sys/disk.h> header file. */
#undef HAVE_SYS_DISK_H
/* Define to 1 if you have the <sys/endian.h> header file. */
#undef HAVE_SYS_ENDIAN_H
@ -309,13 +312,13 @@
#define PACKAGE_NAME "ntfs-3g"
/* Define to the full name and version of this package. */
#define PACKAGE_STRING "ntfs-3g 2011.4.12"
#define PACKAGE_STRING "ntfs-3g 2012.1.15"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "ntfs-3g"
/* Define to the version of this package. */
#define PACKAGE_VERSION "2011.4.12"
#define PACKAGE_VERSION "2012.1.15"
/* POSIX ACL support */
#undef POSIXACLS
@ -345,7 +348,7 @@
#endif
/* Version number of package */
#define VERSION "2011.4.12"
#define VERSION "2012.1.15"
/* Define to 1 if this is a Windows OS */
#undef WINDOWS
@ -375,6 +378,9 @@
/* Required define if using POSIX threads */
#undef _REENTRANT
/* Define to empty if `const' does not conform to ANSI C. */
#undef const
/* Define to `__inline__' or `__inline' if that's what the C compiler
calls it, or to nothing if 'inline' is not supported under any name. */
#ifndef __cplusplus

View File

@ -38,10 +38,10 @@ static __inline__ void ntfs_debug_runlist_dump(const struct _runlist_element *rl
#define NTFS_BUG(msg) \
{ \
int ___i; \
int ___i = 1; \
ntfs_log_critical("Bug in %s(): %s\n", __FUNCTION__, msg); \
ntfs_log_debug("Forcing segmentation fault!"); \
___i = ((int*)NULL)[1]; \
___i = ((int*)NULL)[___i]; \
}
#endif /* defined _NTFS_DEBUG_H */

View File

@ -58,6 +58,9 @@
#ifdef HAVE_SYS_MOUNT_H
#include <sys/mount.h>
#endif
#ifdef HAVE_SYS_DISK_H
#include <sys/disk.h>
#endif
#ifdef HAVE_LINUX_FD_H
#include <linux/fd.h>
#endif
@ -556,6 +559,36 @@ s64 ntfs_device_size_get(struct ntfs_device *dev, int block_size)
return (s64)this_floppy.size * 512 / block_size;
}
}
#endif
#ifdef DIOCGMEDIASIZE
{
/* FreeBSD */
off_t size;
if (dev->d_ops->ioctl(dev, DIOCGMEDIASIZE, &size) >= 0) {
ntfs_log_debug("DIOCGMEDIASIZE nr bytes = %llu (0x%llx)\n",
(unsigned long long)size,
(unsigned long long)size);
return (s64)size / block_size;
}
}
#endif
#ifdef DKIOCGETBLOCKCOUNT
{
/* Mac OS X */
uint64_t blocks;
int sector_size;
sector_size = ntfs_device_sector_size_get(dev);
if (sector_size >= 0 && dev->d_ops->ioctl(dev,
DKIOCGETBLOCKCOUNT, &blocks) >= 0)
{
ntfs_log_debug("DKIOCGETBLOCKCOUNT nr blocks = %llu (0x%llx)\n",
(unsigned long long) blocks,
(unsigned long long) blocks);
return blocks * sector_size / block_size;
}
}
#endif
/*
* We couldn't figure it out by using a specialized ioctl,
@ -705,6 +738,28 @@ int ntfs_device_sector_size_get(struct ntfs_device *dev)
return sect_size;
}
}
#elif defined(DIOCGSECTORSIZE)
{
/* FreeBSD */
size_t sect_size = 0;
if (!dev->d_ops->ioctl(dev, DIOCGSECTORSIZE, &sect_size)) {
ntfs_log_debug("DIOCGSECTORSIZE sector size = %d bytes\n",
(int) sect_size);
return sect_size;
}
}
#elif defined(DKIOCGETBLOCKSIZE)
{
/* Mac OS X */
uint32_t sect_size = 0;
if (!dev->d_ops->ioctl(dev, DKIOCGETBLOCKSIZE, &sect_size)) {
ntfs_log_debug("DKIOCGETBLOCKSIZE sector size = %d bytes\n",
(int) sect_size);
return sect_size;
}
}
#else
errno = EOPNOTSUPP;
#endif

View File

@ -257,7 +257,7 @@ u64 ntfs_inode_lookup_by_name(ntfs_inode *dir_ni,
u8 *index_end;
ntfs_attr *ia_na;
int eo, rc;
u32 index_block_size, index_vcn_size;
u32 index_block_size;
u8 index_vcn_size_bits;
ntfs_log_trace("Entering\n");
@ -378,11 +378,9 @@ u64 ntfs_inode_lookup_by_name(ntfs_inode *dir_ni,
/* Determine the size of a vcn in the directory index. */
if (vol->cluster_size <= index_block_size) {
index_vcn_size = vol->cluster_size;
index_vcn_size_bits = vol->cluster_size_bits;
} else {
index_vcn_size = vol->sector_size;
index_vcn_size_bits = vol->sector_size_bits;
index_vcn_size_bits = NTFS_BLOCK_SIZE_BITS;
}
/* Get the starting vcn of the index_block holding the child node. */
@ -1039,7 +1037,7 @@ int ntfs_readdir(ntfs_inode *dir_ni, s64 *pos,
INDEX_ENTRY *ie;
INDEX_ALLOCATION *ia = NULL;
int rc, ir_pos, bmp_buf_size, bmp_buf_pos, eo;
u32 index_block_size, index_vcn_size;
u32 index_block_size;
u8 index_block_size_bits, index_vcn_size_bits;
ntfs_log_trace("Entering.\n");
@ -1131,11 +1129,9 @@ int ntfs_readdir(ntfs_inode *dir_ni, s64 *pos,
}
index_block_size_bits = ffs(index_block_size) - 1;
if (vol->cluster_size <= index_block_size) {
index_vcn_size = vol->cluster_size;
index_vcn_size_bits = vol->cluster_size_bits;
} else {
index_vcn_size = vol->sector_size;
index_vcn_size_bits = vol->sector_size_bits;
index_vcn_size_bits = NTFS_BLOCK_SIZE_BITS;
}
/* Are we jumping straight into the index allocation attribute? */
@ -1517,7 +1513,7 @@ static ntfs_inode *__ntfs_create(ntfs_inode *dir_ni, le32 securid,
else
ir->clusters_per_index_block =
ni->vol->indx_record_size >>
ni->vol->sector_size_bits;
NTFS_BLOCK_SIZE_BITS;
ir->index.entries_offset = cpu_to_le32(sizeof(INDEX_HEADER));
ir->index.index_length = cpu_to_le32(index_len);
ir->index.allocated_size = cpu_to_le32(index_len);
@ -2508,24 +2504,24 @@ int ntfs_set_ntfs_dos_name(ntfs_inode *ni, ntfs_inode *dir_ni,
int res = 0;
int longlen = 0;
int shortlen = 0;
char newname[MAX_DOS_NAME_LENGTH + 1];
char newname[3*MAX_DOS_NAME_LENGTH + 1];
ntfschar oldname[MAX_DOS_NAME_LENGTH];
int oldlen;
ntfs_volume *vol;
u64 fnum;
u64 dnum;
BOOL closed = FALSE;
ntfschar *shortname = NULL;
ntfschar longname[NTFS_MAX_NAME_LEN];
vol = ni->vol;
fnum = ni->mft_no;
/* convert the string to the NTFS wide chars */
if (size > MAX_DOS_NAME_LENGTH)
size = MAX_DOS_NAME_LENGTH;
/* copy the string to insert a null char, and truncate */
if (size > 3*MAX_DOS_NAME_LENGTH)
size = 3*MAX_DOS_NAME_LENGTH;
strncpy(newname, value, size);
/* a long name may be truncated badly and be untranslatable */
newname[size] = 0;
/* convert the string to the NTFS wide chars, and truncate */
shortlen = ntfs_mbstoucs(newname, &shortname);
if (shortlen > MAX_DOS_NAME_LENGTH)
shortlen = MAX_DOS_NAME_LENGTH;
/* make sure the short name has valid chars */
if ((shortlen < 0) || ntfs_forbidden_chars(shortname,shortlen)) {
ntfs_inode_close_in_dir(ni,dir_ni);

View File

@ -139,7 +139,6 @@ static int fixup_loop(ntfs_inode *ni)
ntfs_attr *na;
ATTR_RECORD *a;
BOOL restart;
BOOL first;
int cnt;
int maxcnt;
int res = 0;
@ -200,7 +199,6 @@ static int fixup_loop(ntfs_inode *ni)
if (na)
ntfs_attr_close(na);
}
first = FALSE;
} while (restart && !res);
if (ctx)
ntfs_attr_put_search_ctx(ctx);

View File

@ -701,7 +701,7 @@ int ntfs_index_lookup(const void *key, const int key_len, ntfs_index_context *ic
if (ni->vol->cluster_size <= icx->block_size)
icx->vcn_size_bits = ni->vol->cluster_size_bits;
else
icx->vcn_size_bits = ni->vol->sector_size_bits;
icx->vcn_size_bits = NTFS_BLOCK_SIZE_BITS;
/* get the appropriate collation function */
icx->collate = ntfs_get_collate_function(ir->collation_rule);
if (!icx->collate) {

View File

@ -365,7 +365,7 @@ int ntfs_inode_real_close(ntfs_inode *ni)
*/
if (base_ni->nr_extents) {
/* Resize the memory buffer. */
tmp_nis = MEM2_realloc(tmp_nis, base_ni->nr_extents *
tmp_nis = realloc(tmp_nis, base_ni->nr_extents *
sizeof(ntfs_inode *));
/* Ignore errors, they don't really matter. */
if (tmp_nis)
@ -437,13 +437,12 @@ static int idata_cache_compare(const struct CACHED_GENERIC *cached,
void ntfs_inode_invalidate(ntfs_volume *vol, const MFT_REF mref)
{
struct CACHED_NIDATA item;
int count;
item.inum = MREF(mref);
item.ni = (ntfs_inode*)NULL;
item.pathname = (const char*)NULL;
item.varsize = 0;
count = ntfs_invalidate_cache(vol->nidata_cache,
ntfs_invalidate_cache(vol->nidata_cache,
GENERIC(&item),idata_cache_compare,CACHE_FREE);
}
@ -574,6 +573,9 @@ int ntfs_inode_close(ntfs_inode *ni)
ntfs_inode *ntfs_extent_inode_open(ntfs_inode *base_ni, const MFT_REF mref)
{
u64 mft_no = MREF_LE(mref);
VCN extent_vcn;
runlist_element *rl;
ntfs_volume *vol;
ntfs_inode *ni = NULL;
ntfs_inode **extent_nis;
int i;
@ -588,6 +590,37 @@ ntfs_inode *ntfs_extent_inode_open(ntfs_inode *base_ni, const MFT_REF mref)
(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
* they are in the MFT part which has already
* been mapped, otherwise we fall into an endless
* recursion.
* Situations have been met where extents locations
* are described in themselves.
* This is a severe error which chkdsk cannot fix.
*/
vol = base_ni->vol;
extent_vcn = mft_no << vol->mft_record_size_bits
>> vol->cluster_size_bits;
rl = vol->mft_na->rl;
if (rl) {
while (rl->length
&& ((rl->vcn + rl->length) <= extent_vcn))
rl++;
}
if (!rl || (rl->lcn < 0)) {
ntfs_log_error("MFT is corrupt, cannot read"
" its unmapped extent record %lld\n",
(long long)mft_no);
ntfs_log_error("Note : chkdsk cannot fix this,"
" try ntfsfix\n");
errno = EIO;
ni = (ntfs_inode*)NULL;
goto out;
}
}
/* Is the extent inode already open and attached to the base inode? */
if (base_ni->nr_extents > 0) {
extent_nis = base_ni->extent_nis;
@ -1115,7 +1148,7 @@ int ntfs_inode_add_attrlist(ntfs_inode *ni)
ctx->attr->name_length + 7) & ~7;
al_len += ale_size;
aln = MEM2_realloc(al, al_len);
aln = realloc(al, al_len);
if (!aln) {
err = errno;
ntfs_log_perror("Failed to realloc %d bytes", al_len);

View File

@ -2223,11 +2223,11 @@ typedef struct {
/* The below field is NOT present for the quota defaults entry. */
SID sid; /* The SID of the user/object associated with
this quota entry. If this field is missing
then the INDEX_ENTRY is padded with zeros
to multiply of 8 which are not counted in
then the INDEX_ENTRY is padded to a multiple
of 8 with zeros which are not counted in
the data_length field. If the sid is present
then this structure is padded with zeros to
multiply of 8 and the padding is counted in
a multiple of 8 and the padding is counted in
the INDEX_ENTRY's data_length. */
} __attribute__((__packed__)) QUOTA_CONTROL_ENTRY;

View File

@ -468,7 +468,7 @@ BOOL ntfs_check_logfile(ntfs_attr *log_na, RESTART_PAGE_HEADER **rp)
u8 *kaddr = NULL;
RESTART_PAGE_HEADER *rstr1_ph = NULL;
RESTART_PAGE_HEADER *rstr2_ph = NULL;
int log_page_size, log_page_mask, err;
int log_page_size, err;
BOOL logfile_is_empty = TRUE;
u8 log_page_bits;
@ -481,7 +481,6 @@ BOOL ntfs_check_logfile(ntfs_attr *log_na, RESTART_PAGE_HEADER **rp)
if (size > (s64)MaxLogFileSize)
size = MaxLogFileSize;
log_page_size = DefaultLogPageSize;
log_page_mask = log_page_size - 1;
/*
* Use generic_ffs() instead of ffs() to enable the compiler to
* optimize log_page_size and log_page_bits into constants.

Some files were not shown because too many files have changed in this diff Show More