mirror of
https://github.com/wiidev/usbloadergx.git
synced 2024-11-15 16:05:10 +01:00
branches:
*updated libntfs-wii to version 2012.1.15 *updated libext2fs to e2fsprogs 1.42 *updated libfat to R4883
This commit is contained in:
parent
afb3b68349
commit
d90a6f0429
@ -7,3 +7,4 @@ to the Nintendo GameCube/Wii port of ext2fs.
|
|||||||
Michael "Chishm" Chisholm
|
Michael "Chishm" Chisholm
|
||||||
rodries
|
rodries
|
||||||
Rhys "Shareese" Koedijk
|
Rhys "Shareese" Koedijk
|
||||||
|
Dimok
|
||||||
|
@ -25,7 +25,3 @@ clean:
|
|||||||
install: cube-release wii-release
|
install: cube-release wii-release
|
||||||
$(MAKE) -C source install
|
$(MAKE) -C source install
|
||||||
|
|
||||||
run: install
|
|
||||||
$(MAKE) -C example
|
|
||||||
$(MAKE) -C example run
|
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ LIBDIR := ../lib
|
|||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
# options for code generation
|
# 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)
|
CXXFLAGS = $(CFLAGS)
|
||||||
ASFLAGS := -g
|
ASFLAGS := -g
|
||||||
export EXT2BIN := $(LIBDIR)/$(PLATFORM)/libext2fs.a
|
export EXT2BIN := $(LIBDIR)/$(PLATFORM)/libext2fs.a
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
#define N_(a) a
|
#define N_(a) a
|
||||||
|
|
||||||
static const char * const text[] = {
|
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 ext2_filsys structure"),
|
||||||
N_( "Wrong magic number for badblocks_list structure"),
|
N_( "Wrong magic number for badblocks_list structure"),
|
||||||
N_( "Wrong magic number for badblocks_iterate structure"),
|
N_( "Wrong magic number for badblocks_iterate structure"),
|
||||||
|
@ -247,6 +247,13 @@ struct struct_ext2_filsys {
|
|||||||
struct ext2_inode_cache *icache;
|
struct ext2_inode_cache *icache;
|
||||||
io_channel image_io;
|
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.
|
* Buffers for Multiple mount protection(MMP) block.
|
||||||
*/
|
*/
|
||||||
@ -258,13 +265,6 @@ struct struct_ext2_filsys {
|
|||||||
* Time at which e2fsck last updated the MMP block.
|
* Time at which e2fsck last updated the MMP block.
|
||||||
*/
|
*/
|
||||||
long mmp_last_written;
|
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"
|
#include "bitops.h"
|
||||||
@ -558,6 +558,7 @@ typedef struct ext2_icount *ext2_icount_t;
|
|||||||
EXT4_FEATURE_INCOMPAT_MMP|\
|
EXT4_FEATURE_INCOMPAT_MMP|\
|
||||||
EXT4_FEATURE_INCOMPAT_64BIT)
|
EXT4_FEATURE_INCOMPAT_64BIT)
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef CONFIG_QUOTA
|
||||||
#define EXT2_LIB_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER|\
|
#define EXT2_LIB_FEATURE_RO_COMPAT_SUPP (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER|\
|
||||||
EXT4_FEATURE_RO_COMPAT_HUGE_FILE|\
|
EXT4_FEATURE_RO_COMPAT_HUGE_FILE|\
|
||||||
EXT2_FEATURE_RO_COMPAT_LARGE_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_GDT_CSUM|\
|
||||||
EXT4_FEATURE_RO_COMPAT_BIGALLOC|\
|
EXT4_FEATURE_RO_COMPAT_BIGALLOC|\
|
||||||
EXT4_FEATURE_RO_COMPAT_QUOTA)
|
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
|
* 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)) >> \
|
#define EXT2FS_NUM_B2C(fs, blks) (((blks) + EXT2FS_CLUSTER_MASK(fs)) >> \
|
||||||
(fs)->cluster_ratio_bits)
|
(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;
|
typedef struct stat64 ext2fs_struct_stat;
|
||||||
#else
|
#else
|
||||||
typedef struct stat ext2fs_struct_stat;
|
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)
|
_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);
|
return stat64(path, buf);
|
||||||
#else
|
#else
|
||||||
return stat(path, buf);
|
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)
|
_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);
|
return fstat64(fd, buf);
|
||||||
#else
|
#else
|
||||||
return fstat(fd, buf);
|
return fstat(fd, buf);
|
||||||
|
@ -11,6 +11,8 @@
|
|||||||
|
|
||||||
#include "ext2fs.h"
|
#include "ext2fs.h"
|
||||||
|
|
||||||
|
#define EXT2FS_MAX_NESTED_LINKS 8
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Badblocks list
|
* Badblocks list
|
||||||
*/
|
*/
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
|
|
||||||
#include "ext2_fs.h"
|
#include "ext2_fs.h"
|
||||||
#include "ext2fs.h"
|
#include "ext2fs.h"
|
||||||
|
#include "ext2fsP.h"
|
||||||
|
|
||||||
struct dir_list {
|
struct dir_list {
|
||||||
char *name;
|
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 *list = 0, *new_list = 0;
|
||||||
struct dir_list *current;
|
struct dir_list *current;
|
||||||
char *ret_path = 0;
|
char *ret_path = 0;
|
||||||
|
int level = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add the starting directories to search...
|
* Add the starting directories to search...
|
||||||
@ -154,6 +156,9 @@ char *ext2fs_find_block_device(dev_t device)
|
|||||||
if (list == 0) {
|
if (list == 0) {
|
||||||
list = new_list;
|
list = new_list;
|
||||||
new_list = 0;
|
new_list = 0;
|
||||||
|
/* Avoid infinite loop */
|
||||||
|
if (++level >= EXT2FS_MAX_NESTED_LINKS)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free_dirlist(&list);
|
free_dirlist(&list);
|
||||||
|
@ -180,6 +180,7 @@ errcode_t ext2fs_create_icount_tdb(ext2_filsys fs, char *tdb_dir,
|
|||||||
ext2_icount_t icount;
|
ext2_icount_t icount;
|
||||||
errcode_t retval;
|
errcode_t retval;
|
||||||
char *fn, uuid[40];
|
char *fn, uuid[40];
|
||||||
|
ext2_ino_t num_inodes;
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
retval = alloc_icount(fs, flags, &icount);
|
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);
|
sprintf(fn, "%s/%s-icount-XXXXXX", tdb_dir, uuid);
|
||||||
fd = mkstemp(fn);
|
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_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);
|
O_RDWR | O_CREAT | O_TRUNC, 0600);
|
||||||
if (icount->tdb) {
|
if (icount->tdb) {
|
||||||
close(fd);
|
close(fd);
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
* %End-Header%
|
* %End-Header%
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#if HAVE_UNISTD_H
|
#if HAVE_UNISTD_H
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
@ -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
|
/* 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. */
|
* 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
|
#ifdef WORDS_BIGENDIAN
|
||||||
ext2fs_swap_mmp(mmp_s);
|
ext2fs_swap_mmp(mmp_s);
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
#include "ext2_fs.h"
|
#include "ext2_fs.h"
|
||||||
#include "ext2fs.h"
|
#include "ext2fs.h"
|
||||||
|
#include "ext2fsP.h"
|
||||||
|
|
||||||
static errcode_t open_namei(ext2_filsys fs, ext2_ino_t root, ext2_ino_t base,
|
static errcode_t open_namei(ext2_filsys fs, ext2_ino_t root, ext2_ino_t base,
|
||||||
const char *pathname, size_t pathlen, int follow,
|
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;
|
*res_inode = inode;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (link_count++ > 5) {
|
if (link_count++ >= EXT2FS_MAX_NESTED_LINKS)
|
||||||
return EXT2_ET_SYMLINK_LOOP;
|
return EXT2_ET_SYMLINK_LOOP;
|
||||||
}
|
|
||||||
/* FIXME-64: Actually, this is FIXME EXTENTS */
|
/* FIXME-64: Actually, this is FIXME EXTENTS */
|
||||||
if (ext2fs_inode_data_blocks(fs,&ei)) {
|
if (ext2fs_inode_data_blocks(fs,&ei)) {
|
||||||
retval = ext2fs_get_mem(fs->blocksize, &buffer);
|
retval = ext2fs_get_mem(fs->blocksize, &buffer);
|
||||||
|
@ -358,8 +358,8 @@ errcode_t ext2fs_open2(const char *name, const char *io_options,
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
#ifdef WORDS_BIGENDIAN
|
#ifdef WORDS_BIGENDIAN
|
||||||
for (j=0; j < groups_per_block; j++) {
|
for (j=0; j < groups_per_block; j++) {
|
||||||
/* The below happens to work... be careful. */
|
gdp = ext2fs_group_desc(fs, fs->group_desc,
|
||||||
gdp = ext2fs_group_desc(fs, fs->group_desc, j);
|
i * groups_per_block + j);
|
||||||
ext2fs_swap_group_desc2(fs, gdp);
|
ext2fs_swap_group_desc2(fs, gdp);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -108,6 +108,8 @@ typedef int bool;
|
|||||||
|
|
||||||
#include "tdb.h"
|
#include "tdb.h"
|
||||||
|
|
||||||
|
static TDB_DATA tdb_null;
|
||||||
|
|
||||||
#ifndef u32
|
#ifndef u32
|
||||||
#define u32 unsigned
|
#define u32 unsigned
|
||||||
#endif
|
#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"));
|
TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction: fsync failed\n"));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
#ifdef MS_SYNC
|
#if defined(HAVE_MSYNC) && defined(MS_SYNC)
|
||||||
if (tdb->map_ptr) {
|
if (tdb->map_ptr) {
|
||||||
tdb_off_t moffset = offset & ~(tdb->page_size-1);
|
tdb_off_t moffset = offset & ~(tdb->page_size-1);
|
||||||
if (msync(moffset + (char *)tdb->map_ptr,
|
if (msync(moffset + (char *)tdb->map_ptr,
|
||||||
@ -3060,8 +3062,6 @@ int tdb_printfreelist(struct tdb_context *tdb)
|
|||||||
|
|
||||||
/* file: tdb.c */
|
/* file: tdb.c */
|
||||||
|
|
||||||
TDB_DATA tdb_null;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
non-blocking increment of the tdb sequence number if the tdb has been opened using
|
non-blocking increment of the tdb sequence number if the tdb has been opened using
|
||||||
the TDB_SEQNUM flag
|
the TDB_SEQNUM flag
|
||||||
@ -3713,17 +3713,17 @@ void tdb_enable_seqnum(struct tdb_context *tdb)
|
|||||||
static struct tdb_context *tdbs = NULL;
|
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)
|
static unsigned int default_tdb_hash(TDB_DATA *key)
|
||||||
{
|
{
|
||||||
u32 value; /* Used to compute the hash value. */
|
u32 value; /* Used to compute the hash value. */
|
||||||
u32 i; /* Used to cycle through random values. */
|
u32 i; /* Used to cycle through random values. */
|
||||||
|
|
||||||
/* Set the initial value from the key size. */
|
/* Set the initial value from the key size. */
|
||||||
for (value = 0x238F13AF * key->dsize, i=0; i < key->dsize; i++)
|
for (value = 0, i=0; i < key->dsize; i++)
|
||||||
value = (value + (key->dptr[i] << (i*5 % 24)));
|
value = value * 256 + key->dptr[i] + (value >> 24) * 241;
|
||||||
|
|
||||||
return (1103515243 * value + 12345);
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -206,8 +206,6 @@ void tdb_dump_all(struct tdb_context *tdb);
|
|||||||
int tdb_printfreelist(struct tdb_context *tdb);
|
int tdb_printfreelist(struct tdb_context *tdb);
|
||||||
int tdb_validate_freelist(struct tdb_context *tdb, int *pnum_entries);
|
int tdb_validate_freelist(struct tdb_context *tdb, int *pnum_entries);
|
||||||
|
|
||||||
extern TDB_DATA tdb_null;
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -20,9 +20,10 @@
|
|||||||
#include "ext2_fs.h"
|
#include "ext2_fs.h"
|
||||||
#include "ext2fs.h"
|
#include "ext2fs.h"
|
||||||
|
|
||||||
|
#include "version.h"
|
||||||
|
|
||||||
static const char *lib_version = "";
|
static const char *lib_version = E2FSPROGS_VERSION;
|
||||||
static const char *lib_date = "";
|
static const char *lib_date = E2FSPROGS_DATE;
|
||||||
|
|
||||||
int ext2fs_parse_version_string(const char *ver_string)
|
int ext2fs_parse_version_string(const char *ver_string)
|
||||||
{
|
{
|
||||||
|
11
libcustomext2fs/source/version.h
Normal file
11
libcustomext2fs/source/version.h
Normal 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"
|
@ -1,32 +1,31 @@
|
|||||||
# Quick'n'dirty makefile [BC] v2
|
ifeq ($(strip $(DEVKITPRO)),)
|
||||||
|
$(error "Please set DEVKITPRO in your environment. export DEVKITPRO=<path to>devkitPro)
|
||||||
ifeq ($(strip $(DEVKITPPC)),)
|
|
||||||
$(error "Please set DEVKITPPC in your environment. export DEVKITPPC=<path to>devkitPPC")
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
include $(DEVKITPPC)/wii_rules
|
export TOPDIR := $(CURDIR)
|
||||||
|
|
||||||
LIBOGC_INC := $(DEVKITPRO)/libogc/include
|
export LIBFAT_MAJOR := 1
|
||||||
LIBOGC_LIB := $(DEVKITPRO)/libogc/lib/wii
|
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)
|
default: release
|
||||||
$(AR) -r $(ARC) $(OFILES)
|
|
||||||
|
|
||||||
clean :
|
all: release
|
||||||
rm -f $(OFILES) $(ARC)
|
|
||||||
|
|
||||||
install :
|
release: include/libfatversion.h wii-release
|
||||||
mkdir -p $(LIBOGC_LIB) $(LIBOGC_INC)
|
|
||||||
cp -f $(ARC) $(LIBOGC_LIB)/
|
|
||||||
cp -f $(HDR) $(LIBOGC_INC)/
|
|
||||||
|
|
||||||
%.o : %.c
|
wii-release:
|
||||||
$(CC) $(CFLAGS) -c $< -o $@
|
$(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
|
||||||
|
10
libcustomfat/include/libfatversion.h
Normal file
10
libcustomfat/include/libfatversion.h
Normal 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__
|
1
libcustomfat/libfat.pnproj
Normal file
1
libcustomfat/libfat.pnproj
Normal 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
1
libcustomfat/libfat.pnps
Normal 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>
|
132
libcustomfat/libogc/Makefile
Normal file
132
libcustomfat/libogc/Makefile
Normal 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
|
||||||
|
#---------------------------------------------------------------------------------------
|
||||||
|
|
86
libcustomfat/libogc/include/fat.h
Normal file
86
libcustomfat/libogc/include/fat.h
Normal 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
|
@ -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) {
|
static bool _FAT_directory_entryGetAlias (const u8* entryData, char* destName) {
|
||||||
int i=0;
|
char c;
|
||||||
int j=0;
|
bool caseInfo;
|
||||||
|
int i = 0;
|
||||||
|
int j = 0;
|
||||||
|
|
||||||
destName[0] = '\0';
|
destName[0] = '\0';
|
||||||
if (entryData[0] != DIR_ENTRY_FREE) {
|
if (entryData[0] != DIR_ENTRY_FREE) {
|
||||||
@ -219,14 +221,18 @@ static bool _FAT_directory_entryGetAlias (const u8* entryData, char* destName) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Copy the filename from the dirEntry to the string
|
// 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++) {
|
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
|
// Copy the extension from the dirEntry to the string
|
||||||
if (entryData[DIR_ENTRY_extension] != ' ') {
|
if (entryData[DIR_ENTRY_extension] != ' ') {
|
||||||
destName[i++] = '.';
|
destName[i++] = '.';
|
||||||
|
caseInfo = entryData[DIR_ENTRY_caseInfo] & CASE_LOWER_EXT;
|
||||||
for ( j = 0; (j < 3) && (entryData[DIR_ENTRY_extension + j] != ' '); j++) {
|
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';
|
destName[i] = '\0';
|
@ -57,6 +57,9 @@
|
|||||||
#define ATTRIB_HID 0x02 // Hidden
|
#define ATTRIB_HID 0x02 // Hidden
|
||||||
#define ATTRIB_RO 0x01 // Read only
|
#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 enum {FT_DIRECTORY, FT_FILE} FILE_TYPE;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -77,7 +80,7 @@ enum DIR_ENTRY_offset {
|
|||||||
DIR_ENTRY_name = 0x00,
|
DIR_ENTRY_name = 0x00,
|
||||||
DIR_ENTRY_extension = 0x08,
|
DIR_ENTRY_extension = 0x08,
|
||||||
DIR_ENTRY_attributes = 0x0B,
|
DIR_ENTRY_attributes = 0x0B,
|
||||||
DIR_ENTRY_reserved = 0x0C,
|
DIR_ENTRY_caseInfo = 0x0C,
|
||||||
DIR_ENTRY_cTime_ms = 0x0D,
|
DIR_ENTRY_cTime_ms = 0x0D,
|
||||||
DIR_ENTRY_cTime = 0x0E,
|
DIR_ENTRY_cTime = 0x0E,
|
||||||
DIR_ENTRY_cDate = 0x10,
|
DIR_ENTRY_cDate = 0x10,
|
@ -465,16 +465,16 @@ int _FAT_statvfs_r (struct _reent *r, const char *path, struct statvfs *buf)
|
|||||||
|
|
||||||
_FAT_lock(&partition->lock);
|
_FAT_lock(&partition->lock);
|
||||||
|
|
||||||
if(memcmp(&buf->f_flag, "SCAN", 4) == 0)
|
if(memcmp(&buf->f_flag, "SCAN", 4) == 0)
|
||||||
{
|
{
|
||||||
//Special command was given to sync the numberFreeCluster
|
//Special command was given to sync the numberFreeCluster
|
||||||
_FAT_partition_createFSinfo(partition);
|
_FAT_partition_createFSinfo(partition);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(partition->filesysType == FS_FAT32)
|
if(partition->filesysType == FS_FAT32)
|
||||||
freeClusterCount = partition->fat.numberFreeCluster;
|
freeClusterCount = partition->fat.numberFreeCluster;
|
||||||
else
|
else
|
||||||
freeClusterCount = _FAT_fat_freeClusterCount (partition);
|
freeClusterCount = _FAT_fat_freeClusterCount (partition);
|
||||||
|
|
||||||
// FAT clusters = POSIX blocks
|
// FAT clusters = POSIX blocks
|
||||||
buf->f_bsize = partition->bytesPerCluster; // File system block size.
|
buf->f_bsize = partition->bytesPerCluster; // File system block size.
|
@ -45,6 +45,37 @@
|
|||||||
#include "filetime.h"
|
#include "filetime.h"
|
||||||
#include "lock.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) {
|
int _FAT_open_r (struct _reent *r, void *fileStruct, const char *path, int flags, int mode) {
|
||||||
PARTITION* partition = NULL;
|
PARTITION* partition = NULL;
|
||||||
bool fileExists;
|
bool fileExists;
|
@ -247,7 +247,7 @@ uint32_t _FAT_fat_linkFreeCluster(PARTITION* partition, uint32_t cluster) {
|
|||||||
}
|
}
|
||||||
partition->fat.firstFree = firstFree;
|
partition->fat.firstFree = firstFree;
|
||||||
if(partition->fat.numberFreeCluster)
|
if(partition->fat.numberFreeCluster)
|
||||||
partition->fat.numberFreeCluster--;
|
partition->fat.numberFreeCluster--;
|
||||||
partition->fat.numberLastAllocCluster = firstFree;
|
partition->fat.numberLastAllocCluster = firstFree;
|
||||||
|
|
||||||
if ((cluster >= CLUSTER_FIRST) && (cluster <= lastCluster))
|
if ((cluster >= CLUSTER_FIRST) && (cluster <= lastCluster))
|
||||||
@ -279,7 +279,7 @@ uint32_t _FAT_fat_linkFreeClusterCleared (PARTITION* partition, uint32_t cluster
|
|||||||
return CLUSTER_ERROR;
|
return CLUSTER_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
emptySector = (uint8_t*) _FAT_mem_allocate(partition->bytesPerSector);
|
emptySector = (uint8_t*) _FAT_mem_allocate(partition->bytesPerSector);
|
||||||
|
|
||||||
// Clear all the sectors within the cluster
|
// Clear all the sectors within the cluster
|
||||||
memset (emptySector, 0, partition->bytesPerSector);
|
memset (emptySector, 0, partition->bytesPerSector);
|
||||||
@ -317,8 +317,8 @@ bool _FAT_fat_clearLinks (PARTITION* partition, uint32_t cluster) {
|
|||||||
// Erase the link
|
// Erase the link
|
||||||
_FAT_fat_writeFatEntry (partition, cluster, CLUSTER_FREE);
|
_FAT_fat_writeFatEntry (partition, cluster, CLUSTER_FREE);
|
||||||
|
|
||||||
if(partition->fat.numberFreeCluster < (partition->numberOfSectors/partition->sectorsPerCluster))
|
if(partition->fat.numberFreeCluster < (partition->numberOfSectors/partition->sectorsPerCluster))
|
||||||
partition->fat.numberFreeCluster++;
|
partition->fat.numberFreeCluster++;
|
||||||
// Move onto next cluster
|
// Move onto next cluster
|
||||||
cluster = nextCluster;
|
cluster = nextCluster;
|
||||||
}
|
}
|
@ -38,8 +38,6 @@
|
|||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <sys/iosupport.h>
|
#include <sys/iosupport.h>
|
||||||
|
|
||||||
sec_t _FAT_startSector;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Data offsets
|
Data offsets
|
||||||
*/
|
*/
|
||||||
@ -93,10 +91,10 @@ enum BPB {
|
|||||||
// File system information block offsets
|
// File system information block offsets
|
||||||
enum FSIB
|
enum FSIB
|
||||||
{
|
{
|
||||||
FSIB_SIG1 = 0x00,
|
FSIB_SIG1 = 0x00,
|
||||||
FSIB_SIG2 = 0x1e4,
|
FSIB_SIG2 = 0x1e4,
|
||||||
FSIB_numberOfFreeCluster = 0x1e8,
|
FSIB_numberOfFreeCluster = 0x1e8,
|
||||||
FSIB_numberLastAllocCluster = 0x1ec,
|
FSIB_numberLastAllocCluster = 0x1ec,
|
||||||
FSIB_bootSig_55 = 0x1FE,
|
FSIB_bootSig_55 = 0x1FE,
|
||||||
FSIB_bootSig_AA = 0x1FF
|
FSIB_bootSig_AA = 0x1FF
|
||||||
};
|
};
|
||||||
@ -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_SIG1[4] = {'R', 'R', 'a', 'A'};
|
||||||
static const char FS_INFO_SIG2[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 part_table[16*4];
|
||||||
uint8_t *ptr;
|
uint8_t *ptr;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
uint8_t *sectorBuffer = (uint8_t*) _FAT_mem_allocate(MAX_SECTOR_SIZE);
|
|
||||||
if(!sectorBuffer) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read first sector of disc
|
// Read first sector of disc
|
||||||
if (!_FAT_disc_readSectors (disc, 0, 1, sectorBuffer)) {
|
if (!_FAT_disc_readSectors (disc, 0, 1, sectorBuffer)) {
|
||||||
_FAT_mem_free(sectorBuffer);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,7 +122,6 @@ sec_t FindFirstValidPartition(const DISC_INTERFACE* disc)
|
|||||||
|
|
||||||
if (!memcmp(sectorBuffer + BPB_FAT16_fileSysType, FAT_SIG, sizeof(FAT_SIG)) ||
|
if (!memcmp(sectorBuffer + BPB_FAT16_fileSysType, FAT_SIG, sizeof(FAT_SIG)) ||
|
||||||
!memcmp(sectorBuffer + BPB_FAT32_fileSysType, FAT_SIG, sizeof(FAT_SIG))) {
|
!memcmp(sectorBuffer + BPB_FAT32_fileSysType, FAT_SIG, sizeof(FAT_SIG))) {
|
||||||
_FAT_mem_free(sectorBuffer);
|
|
||||||
return part_lba;
|
return part_lba;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,61 +134,53 @@ sec_t FindFirstValidPartition(const DISC_INTERFACE* disc)
|
|||||||
|
|
||||||
for(n=0;n<8;n++) // max 8 logic partitions
|
for(n=0;n<8;n++) // max 8 logic partitions
|
||||||
{
|
{
|
||||||
if(!_FAT_disc_readSectors (disc, part_lba+next_lba2, 1, sectorBuffer)) {
|
if(!_FAT_disc_readSectors (disc, part_lba+next_lba2, 1, sectorBuffer)) return 0;
|
||||||
_FAT_mem_free(sectorBuffer);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
part_lba2 = part_lba + next_lba2 + u8array_to_u32(sectorBuffer, 0x1C6) ;
|
part_lba2 = part_lba + next_lba2 + u8array_to_u32(sectorBuffer, 0x1C6) ;
|
||||||
next_lba2 = u8array_to_u32(sectorBuffer, 0x1D6);
|
next_lba2 = u8array_to_u32(sectorBuffer, 0x1D6);
|
||||||
|
|
||||||
if(!_FAT_disc_readSectors (disc, part_lba2, 1, sectorBuffer)) {
|
if(!_FAT_disc_readSectors (disc, part_lba2, 1, sectorBuffer)) return 0;
|
||||||
_FAT_mem_free(sectorBuffer);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!memcmp(sectorBuffer + BPB_FAT16_fileSysType, FAT_SIG, sizeof(FAT_SIG)) ||
|
if (!memcmp(sectorBuffer + BPB_FAT16_fileSysType, FAT_SIG, sizeof(FAT_SIG)) ||
|
||||||
!memcmp(sectorBuffer + BPB_FAT32_fileSysType, FAT_SIG, sizeof(FAT_SIG))) {
|
!memcmp(sectorBuffer + BPB_FAT32_fileSysType, FAT_SIG, sizeof(FAT_SIG)))
|
||||||
_FAT_mem_free(sectorBuffer);
|
{
|
||||||
return part_lba2;
|
return part_lba2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(next_lba2==0) break;
|
if(next_lba2==0) break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if(!_FAT_disc_readSectors (disc, part_lba, 1, sectorBuffer)) {
|
if(!_FAT_disc_readSectors (disc, part_lba, 1, sectorBuffer)) return 0;
|
||||||
_FAT_mem_free(sectorBuffer);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (!memcmp(sectorBuffer + BPB_FAT16_fileSysType, FAT_SIG, sizeof(FAT_SIG)) ||
|
if (!memcmp(sectorBuffer + BPB_FAT16_fileSysType, FAT_SIG, sizeof(FAT_SIG)) ||
|
||||||
!memcmp(sectorBuffer + BPB_FAT32_fileSysType, FAT_SIG, sizeof(FAT_SIG))) {
|
!memcmp(sectorBuffer + BPB_FAT32_fileSysType, FAT_SIG, sizeof(FAT_SIG))) {
|
||||||
_FAT_mem_free(sectorBuffer);
|
|
||||||
return part_lba;
|
return part_lba;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_FAT_mem_free(sectorBuffer);
|
|
||||||
return 0;
|
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;
|
PARTITION* partition;
|
||||||
|
|
||||||
uint8_t *sectorBuffer = (uint8_t*) _FAT_mem_allocate(MAX_SECTOR_SIZE);
|
|
||||||
if(!sectorBuffer) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read first sector of disc
|
// Read first sector of disc
|
||||||
if (!_FAT_disc_readSectors (disc, startSector, 1, sectorBuffer)) {
|
if (!_FAT_disc_readSectors (disc, startSector, 1, sectorBuffer)) {
|
||||||
_FAT_mem_free(sectorBuffer);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure it is a valid MBR or boot sector
|
// Make sure it is a valid MBR or boot sector
|
||||||
if ( (sectorBuffer[BPB_bootSig_55] != 0x55) || (sectorBuffer[BPB_bootSig_AA] != 0xAA)) {
|
if ( (sectorBuffer[BPB_bootSig_55] != 0x55) || (sectorBuffer[BPB_bootSig_AA] != 0xAA)) {
|
||||||
_FAT_mem_free(sectorBuffer);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -210,25 +193,21 @@ PARTITION* _FAT_partition_constructor (const DISC_INTERFACE* disc, uint32_t cach
|
|||||||
// Check for FAT32
|
// Check for FAT32
|
||||||
startSector = 0;
|
startSector = 0;
|
||||||
} else {
|
} else {
|
||||||
startSector = FindFirstValidPartition(disc);
|
startSector = FindFirstValidPartition_buf(disc, sectorBuffer);
|
||||||
if (!_FAT_disc_readSectors (disc, startSector, 1, sectorBuffer)) {
|
if (!_FAT_disc_readSectors (disc, startSector, 1, sectorBuffer)) {
|
||||||
_FAT_mem_free(sectorBuffer);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_FAT_startSector = startSector;
|
|
||||||
|
|
||||||
// Now verify that this is indeed a FAT partition
|
// Now verify that this is indeed a FAT partition
|
||||||
if (memcmp(sectorBuffer + BPB_FAT16_fileSysType, FAT_SIG, sizeof(FAT_SIG)) &&
|
if (memcmp(sectorBuffer + BPB_FAT16_fileSysType, FAT_SIG, sizeof(FAT_SIG)) &&
|
||||||
memcmp(sectorBuffer + BPB_FAT32_fileSysType, FAT_SIG, sizeof(FAT_SIG))) {
|
memcmp(sectorBuffer + BPB_FAT32_fileSysType, FAT_SIG, sizeof(FAT_SIG)))
|
||||||
_FAT_mem_free(sectorBuffer);
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
partition = (PARTITION*) _FAT_mem_allocate (sizeof(PARTITION));
|
partition = (PARTITION*) _FAT_mem_allocate (sizeof(PARTITION));
|
||||||
if (partition == NULL) {
|
if (partition == NULL) {
|
||||||
_FAT_mem_free(sectorBuffer);
|
|
||||||
return NULL;
|
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);
|
partition->numberOfSectors = u8array_to_u32( sectorBuffer, BPB_numSectors);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(disc->features & FEATURE_WII_USB)
|
partition->bytesPerSector = u8array_to_u16(sectorBuffer, BPB_bytesPerSector);
|
||||||
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) {
|
if(partition->bytesPerSector < MIN_SECTOR_SIZE || partition->bytesPerSector > MAX_SECTOR_SIZE) {
|
||||||
// Unsupported sector size
|
// Unsupported sector size
|
||||||
_FAT_mem_free(sectorBuffer);
|
_FAT_mem_free(partition);
|
||||||
_FAT_mem_free(partition);
|
return NULL;
|
||||||
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->bytesPerCluster = partition->bytesPerSector * partition->sectorsPerCluster;
|
||||||
partition->fat.fatStart = startSector + u8array_to_u16(sectorBuffer, BPB_reservedSectors);
|
partition->fat.fatStart = startSector + u8array_to_u16(sectorBuffer, BPB_reservedSectors);
|
||||||
|
|
||||||
@ -277,14 +251,14 @@ PARTITION* _FAT_partition_constructor (const DISC_INTERFACE* disc, uint32_t cach
|
|||||||
|
|
||||||
partition->totalSize = ((uint64_t)partition->numberOfSectors - (partition->dataStart - startSector)) * (uint64_t)partition->bytesPerSector;
|
partition->totalSize = ((uint64_t)partition->numberOfSectors - (partition->dataStart - startSector)) * (uint64_t)partition->bytesPerSector;
|
||||||
|
|
||||||
//FS info sector
|
//FS info sector
|
||||||
partition->fsInfoSector = startSector + (u8array_to_u16(sectorBuffer, BPB_FAT32_fsInfo) ? u8array_to_u16(sectorBuffer, BPB_FAT32_fsInfo) : 1);
|
partition->fsInfoSector = startSector + (u8array_to_u16(sectorBuffer, BPB_FAT32_fsInfo) ? u8array_to_u16(sectorBuffer, BPB_FAT32_fsInfo) : 1);
|
||||||
|
|
||||||
// Store info about FAT
|
// Store info about FAT
|
||||||
uint32_t clusterCount = (partition->numberOfSectors - (uint32_t)(partition->dataStart - startSector)) / partition->sectorsPerCluster;
|
uint32_t clusterCount = (partition->numberOfSectors - (uint32_t)(partition->dataStart - startSector)) / partition->sectorsPerCluster;
|
||||||
partition->fat.lastCluster = clusterCount + CLUSTER_FIRST - 1;
|
partition->fat.lastCluster = clusterCount + CLUSTER_FIRST - 1;
|
||||||
partition->fat.firstFree = CLUSTER_FIRST;
|
partition->fat.firstFree = CLUSTER_FIRST;
|
||||||
partition->fat.numberFreeCluster = 0;
|
partition->fat.numberFreeCluster = 0;
|
||||||
partition->fat.numberLastAllocCluster = 0;
|
partition->fat.numberLastAllocCluster = 0;
|
||||||
|
|
||||||
if (clusterCount < CLUSTERS_PER_FAT12) {
|
if (clusterCount < CLUSTERS_PER_FAT12) {
|
||||||
@ -322,11 +296,20 @@ PARTITION* _FAT_partition_constructor (const DISC_INTERFACE* disc, uint32_t cach
|
|||||||
|
|
||||||
_FAT_partition_readFSinfo(partition);
|
_FAT_partition_readFSinfo(partition);
|
||||||
|
|
||||||
_FAT_mem_free(sectorBuffer);
|
|
||||||
|
|
||||||
return partition;
|
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) {
|
void _FAT_partition_destructor (PARTITION* partition) {
|
||||||
FILE_STRUCT* nextFile;
|
FILE_STRUCT* nextFile;
|
||||||
|
|
||||||
@ -339,8 +322,8 @@ void _FAT_partition_destructor (PARTITION* partition) {
|
|||||||
nextFile = nextFile->nextOpenFile;
|
nextFile = nextFile->nextOpenFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write out the fs info sector
|
// Write out the fs info sector
|
||||||
_FAT_partition_writeFSinfo(partition);
|
_FAT_partition_writeFSinfo(partition);
|
||||||
|
|
||||||
// Free memory used by the cache, writing it to disc at the same time
|
// Free memory used by the cache, writing it to disc at the same time
|
||||||
_FAT_cache_destructor (partition->cache);
|
_FAT_cache_destructor (partition->cache);
|
||||||
@ -367,89 +350,82 @@ PARTITION* _FAT_partition_getPartitionFromPath (const char* path) {
|
|||||||
|
|
||||||
void _FAT_partition_createFSinfo(PARTITION * partition)
|
void _FAT_partition_createFSinfo(PARTITION * partition)
|
||||||
{
|
{
|
||||||
if(partition->readOnly || partition->filesysType != FS_FAT32)
|
if(partition->readOnly || partition->filesysType != FS_FAT32)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
uint8_t *sectorBuffer = (uint8_t*) _FAT_mem_allocate(partition->bytesPerSector);
|
uint8_t *sectorBuffer = (uint8_t*) _FAT_mem_align(partition->bytesPerSector);
|
||||||
if(!sectorBuffer) {
|
if (!sectorBuffer) return;
|
||||||
return;
|
memset(sectorBuffer, 0, partition->bytesPerSector);
|
||||||
|
|
||||||
|
int i;
|
||||||
|
for(i = 0; i < 4; ++i)
|
||||||
|
{
|
||||||
|
sectorBuffer[FSIB_SIG1+i] = FS_INFO_SIG1[i];
|
||||||
|
sectorBuffer[FSIB_SIG2+i] = FS_INFO_SIG2[i];
|
||||||
}
|
}
|
||||||
memset(sectorBuffer, 0, partition->bytesPerSector);
|
|
||||||
|
|
||||||
int i;
|
partition->fat.numberFreeCluster = _FAT_fat_freeClusterCount(partition);
|
||||||
for(i = 0; i < 4; ++i)
|
u32_to_u8array(sectorBuffer, FSIB_numberOfFreeCluster, partition->fat.numberFreeCluster);
|
||||||
{
|
u32_to_u8array(sectorBuffer, FSIB_numberLastAllocCluster, partition->fat.numberLastAllocCluster);
|
||||||
sectorBuffer[FSIB_SIG1+i] = FS_INFO_SIG1[i];
|
|
||||||
sectorBuffer[FSIB_SIG2+i] = FS_INFO_SIG2[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
partition->fat.numberFreeCluster = _FAT_fat_freeClusterCount(partition);
|
sectorBuffer[FSIB_bootSig_55] = 0x55;
|
||||||
u32_to_u8array(sectorBuffer, FSIB_numberOfFreeCluster, partition->fat.numberFreeCluster);
|
sectorBuffer[FSIB_bootSig_AA] = 0xAA;
|
||||||
u32_to_u8array(sectorBuffer, FSIB_numberLastAllocCluster, partition->fat.numberLastAllocCluster);
|
|
||||||
|
|
||||||
sectorBuffer[FSIB_bootSig_55] = 0x55;
|
_FAT_disc_writeSectors (partition->disc, partition->fsInfoSector, 1, sectorBuffer);
|
||||||
sectorBuffer[FSIB_bootSig_AA] = 0xAA;
|
|
||||||
|
|
||||||
_FAT_disc_writeSectors (partition->disc, partition->fsInfoSector, 1, sectorBuffer);
|
_FAT_mem_free(sectorBuffer);
|
||||||
|
|
||||||
_FAT_mem_free(sectorBuffer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _FAT_partition_readFSinfo(PARTITION * partition)
|
void _FAT_partition_readFSinfo(PARTITION * partition)
|
||||||
{
|
{
|
||||||
if(partition->filesysType != FS_FAT32)
|
if(partition->filesysType != FS_FAT32)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
uint8_t *sectorBuffer = (uint8_t*) _FAT_mem_allocate(partition->bytesPerSector);
|
uint8_t *sectorBuffer = (uint8_t*) _FAT_mem_align(partition->bytesPerSector);
|
||||||
if(!sectorBuffer) {
|
if (!sectorBuffer) return;
|
||||||
return;
|
memset(sectorBuffer, 0, partition->bytesPerSector);
|
||||||
}
|
|
||||||
memset(sectorBuffer, 0, partition->bytesPerSector);
|
|
||||||
// Read first sector of disc
|
// Read first sector of disc
|
||||||
if (!_FAT_disc_readSectors (partition->disc, partition->fsInfoSector, 1, sectorBuffer)) {
|
if (!_FAT_disc_readSectors (partition->disc, partition->fsInfoSector, 1, sectorBuffer)) {
|
||||||
_FAT_mem_free(sectorBuffer);
|
_FAT_mem_free(sectorBuffer);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(memcmp(sectorBuffer+FSIB_SIG1, FS_INFO_SIG1, 4) != 0 ||
|
if(memcmp(sectorBuffer+FSIB_SIG1, FS_INFO_SIG1, 4) != 0 ||
|
||||||
memcmp(sectorBuffer+FSIB_SIG2, FS_INFO_SIG2, 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);
|
//sector does not yet exist, create one!
|
||||||
_FAT_mem_free(sectorBuffer);
|
_FAT_partition_createFSinfo(partition);
|
||||||
return;
|
} else {
|
||||||
}
|
partition->fat.numberFreeCluster = u8array_to_u32(sectorBuffer, FSIB_numberOfFreeCluster);
|
||||||
|
partition->fat.numberLastAllocCluster = u8array_to_u32(sectorBuffer, FSIB_numberLastAllocCluster);
|
||||||
partition->fat.numberFreeCluster = u8array_to_u32(sectorBuffer, FSIB_numberOfFreeCluster);
|
}
|
||||||
partition->fat.numberLastAllocCluster = u8array_to_u32(sectorBuffer, FSIB_numberLastAllocCluster);
|
_FAT_mem_free(sectorBuffer);
|
||||||
_FAT_mem_free(sectorBuffer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _FAT_partition_writeFSinfo(PARTITION * partition)
|
void _FAT_partition_writeFSinfo(PARTITION * partition)
|
||||||
{
|
{
|
||||||
if(partition->filesysType != FS_FAT32)
|
if(partition->filesysType != FS_FAT32)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
uint8_t *sectorBuffer = (uint8_t*) _FAT_mem_allocate(partition->bytesPerSector);
|
uint8_t *sectorBuffer = (uint8_t*) _FAT_mem_align(partition->bytesPerSector);
|
||||||
if(!sectorBuffer) {
|
if (!sectorBuffer) return;
|
||||||
return;
|
memset(sectorBuffer, 0, partition->bytesPerSector);
|
||||||
}
|
|
||||||
memset(sectorBuffer, 0, partition->bytesPerSector);
|
|
||||||
// Read first sector of disc
|
// Read first sector of disc
|
||||||
if (!_FAT_disc_readSectors (partition->disc, partition->fsInfoSector, 1, sectorBuffer)) {
|
if (!_FAT_disc_readSectors (partition->disc, partition->fsInfoSector, 1, sectorBuffer)) {
|
||||||
_FAT_mem_free(sectorBuffer);
|
_FAT_mem_free(sectorBuffer);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(memcmp(sectorBuffer+FSIB_SIG1, FS_INFO_SIG1, 4) || memcmp(sectorBuffer+FSIB_SIG2, FS_INFO_SIG2, 4)) {
|
if(memcmp(sectorBuffer+FSIB_SIG1, FS_INFO_SIG1, 4) || memcmp(sectorBuffer+FSIB_SIG2, FS_INFO_SIG2, 4)) {
|
||||||
_FAT_mem_free(sectorBuffer);
|
_FAT_mem_free(sectorBuffer);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32_to_u8array(sectorBuffer, FSIB_numberOfFreeCluster, partition->fat.numberFreeCluster);
|
u32_to_u8array(sectorBuffer, FSIB_numberOfFreeCluster, partition->fat.numberFreeCluster);
|
||||||
u32_to_u8array(sectorBuffer, FSIB_numberLastAllocCluster, partition->fat.numberLastAllocCluster);
|
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_disc_writeSectors (partition->disc, partition->fsInfoSector, 1, sectorBuffer);
|
||||||
_FAT_mem_free(sectorBuffer);
|
_FAT_mem_free(sectorBuffer);
|
||||||
}
|
}
|
27
libcustomntfs/AUTHORS
Normal file
27
libcustomntfs/AUTHORS
Normal 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
50
libcustomntfs/CREDITS
Normal 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
340
libcustomntfs/LICENSE
Normal 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.
|
@ -1,32 +1,31 @@
|
|||||||
# Quick'n'dirty makefile [BC] v2
|
|
||||||
|
|
||||||
ifeq ($(strip $(DEVKITPPC)),)
|
default: cube-release wii-release
|
||||||
$(error "Please set DEVKITPPC in your environment. export DEVKITPPC=<path to>devkitPPC")
|
|
||||||
endif
|
|
||||||
|
|
||||||
include $(DEVKITPPC)/wii_rules
|
all: debug release
|
||||||
|
|
||||||
LIBOGC_INC := $(DEVKITPRO)/libogc/include
|
debug: cube-debug wii-debug
|
||||||
LIBOGC_LIB := $(DEVKITPRO)/libogc/lib/wii
|
|
||||||
|
|
||||||
CFLAGS := -O3 $(MACHDEP) -I$(LIBOGC_INC) -DHAVE_CONFIG_H
|
release: cube-release wii-release
|
||||||
|
|
||||||
LIB := ntfs
|
cube-debug:
|
||||||
CFILES := $(wildcard *.c)
|
$(MAKE) -C source PLATFORM=cube BUILD=cube_debug
|
||||||
OFILES := $(CFILES:.c=.o)
|
|
||||||
ARC := lib$(LIB).a
|
|
||||||
HDR := ntfs.h
|
|
||||||
|
|
||||||
all : $(OFILES)
|
wii-debug:
|
||||||
$(AR) -r $(ARC) $(OFILES)
|
$(MAKE) -C source PLATFORM=wii BUILD=wii_debug
|
||||||
|
|
||||||
clean :
|
cube-release:
|
||||||
rm -f $(OFILES) $(ARC)
|
$(MAKE) -C source PLATFORM=cube BUILD=cube_release
|
||||||
|
|
||||||
install :
|
wii-release:
|
||||||
mkdir -p $(LIBOGC_LIB) $(LIBOGC_INC)
|
$(MAKE) -C source PLATFORM=wii BUILD=wii_release
|
||||||
cp -f $(ARC) $(LIBOGC_LIB)/
|
|
||||||
cp -f $(HDR) $(LIBOGC_INC)/
|
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
54
libcustomntfs/READMII
Normal 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.
|
148
libcustomntfs/include/ntfs.h
Normal file
148
libcustomntfs/include/ntfs.h
Normal 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 */
|
130
libcustomntfs/source/Makefile
Normal file
130
libcustomntfs/source/Makefile
Normal 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
|
||||||
|
#---------------------------------------------------------------------------------------
|
||||||
|
|
@ -522,9 +522,7 @@ gid_t ntfs_find_group(const struct MAPPING* groupmapping, const SID * gsid)
|
|||||||
{
|
{
|
||||||
gid_t gid;
|
gid_t gid;
|
||||||
const struct MAPPING *p;
|
const struct MAPPING *p;
|
||||||
int gsidsz;
|
|
||||||
|
|
||||||
gsidsz = ntfs_sid_size(gsid);
|
|
||||||
p = groupmapping;
|
p = groupmapping;
|
||||||
while (p && p->xid && !ntfs_same_sid(gsid, p->sid))
|
while (p && p->xid && !ntfs_same_sid(gsid, p->sid))
|
||||||
p = p->next;
|
p = p->next;
|
||||||
@ -1901,7 +1899,6 @@ static int buildacls_posix(struct MAPPING* const mapping[],
|
|||||||
const SID *sid;
|
const SID *sid;
|
||||||
int acecnt;
|
int acecnt;
|
||||||
int usidsz;
|
int usidsz;
|
||||||
int gsidsz;
|
|
||||||
int wsidsz;
|
int wsidsz;
|
||||||
int asidsz;
|
int asidsz;
|
||||||
int ssidsz;
|
int ssidsz;
|
||||||
@ -1909,7 +1906,6 @@ static int buildacls_posix(struct MAPPING* const mapping[],
|
|||||||
le32 grants;
|
le32 grants;
|
||||||
|
|
||||||
usidsz = ntfs_sid_size(usid);
|
usidsz = ntfs_sid_size(usid);
|
||||||
gsidsz = ntfs_sid_size(gsid);
|
|
||||||
wsidsz = ntfs_sid_size(worldsid);
|
wsidsz = ntfs_sid_size(worldsid);
|
||||||
asidsz = ntfs_sid_size(adminsid);
|
asidsz = ntfs_sid_size(adminsid);
|
||||||
ssidsz = ntfs_sid_size(systemsid);
|
ssidsz = ntfs_sid_size(systemsid);
|
||||||
@ -3132,7 +3128,6 @@ static int norm_ownadmin_permissions_posix(struct POSIX_SECURITY *posix_desc,
|
|||||||
u16 tag;
|
u16 tag;
|
||||||
u16 tagsset;
|
u16 tagsset;
|
||||||
struct POSIX_ACE *pxace;
|
struct POSIX_ACE *pxace;
|
||||||
int acccnt;
|
|
||||||
mode_t denywrld;
|
mode_t denywrld;
|
||||||
mode_t allow;
|
mode_t allow;
|
||||||
mode_t deny;
|
mode_t deny;
|
||||||
@ -3141,7 +3136,6 @@ static int norm_ownadmin_permissions_posix(struct POSIX_SECURITY *posix_desc,
|
|||||||
|
|
||||||
mode = 0;
|
mode = 0;
|
||||||
pxace = posix_desc->acl.ace;
|
pxace = posix_desc->acl.ace;
|
||||||
acccnt = posix_desc->acccnt;
|
|
||||||
tagsset = 0;
|
tagsset = 0;
|
||||||
denywrld = 0;
|
denywrld = 0;
|
||||||
/*
|
/*
|
||||||
@ -3881,12 +3875,10 @@ struct POSIX_SECURITY *ntfs_build_permissions_posix(
|
|||||||
int ntfs_build_permissions(const char *securattr,
|
int ntfs_build_permissions(const char *securattr,
|
||||||
const SID *usid, const SID *gsid, BOOL isdir)
|
const SID *usid, const SID *gsid, BOOL isdir)
|
||||||
{
|
{
|
||||||
const SECURITY_DESCRIPTOR_RELATIVE *phead;
|
|
||||||
int perm;
|
int perm;
|
||||||
BOOL adminowns;
|
BOOL adminowns;
|
||||||
BOOL groupowns;
|
BOOL groupowns;
|
||||||
|
|
||||||
phead = (const SECURITY_DESCRIPTOR_RELATIVE*)securattr;
|
|
||||||
adminowns = ntfs_same_sid(usid,adminsid)
|
adminowns = ntfs_same_sid(usid,adminsid)
|
||||||
|| ntfs_same_sid(gsid,adminsid);
|
|| ntfs_same_sid(gsid,adminsid);
|
||||||
groupowns = !adminowns && ntfs_same_sid(gsid,usid);
|
groupowns = !adminowns && ntfs_same_sid(gsid,usid);
|
||||||
@ -3969,7 +3961,6 @@ static struct MAPLIST *getmappingitem(FILEREADER reader, void *fileid,
|
|||||||
{
|
{
|
||||||
int src;
|
int src;
|
||||||
int dst;
|
int dst;
|
||||||
char *p;
|
|
||||||
char *q;
|
char *q;
|
||||||
char *pu;
|
char *pu;
|
||||||
char *pg;
|
char *pg;
|
||||||
@ -4003,7 +3994,6 @@ static struct MAPLIST *getmappingitem(FILEREADER reader, void *fileid,
|
|||||||
if (gotend) {
|
if (gotend) {
|
||||||
pu = pg = (char*)NULL;
|
pu = pg = (char*)NULL;
|
||||||
/* decompose into uid, gid and sid */
|
/* decompose into uid, gid and sid */
|
||||||
p = item->maptext;
|
|
||||||
item->uidstr = item->maptext;
|
item->uidstr = item->maptext;
|
||||||
item->gidstr = strchr(item->uidstr, ':');
|
item->gidstr = strchr(item->uidstr, ':');
|
||||||
if (item->gidstr) {
|
if (item->gidstr) {
|
@ -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);
|
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 &&
|
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)))) {
|
(!(a->flags & ATTR_IS_ENCRYPTED) != !NAttrEncrypted(na)))) {
|
||||||
errno = EIO;
|
errno = EIO;
|
||||||
ntfs_log_perror("Inode %lld has corrupt attribute flags "
|
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 };
|
} need_to = { 0, 0 };
|
||||||
BOOL wasnonresident = FALSE;
|
BOOL wasnonresident = FALSE;
|
||||||
BOOL compressed;
|
BOOL compressed;
|
||||||
BOOL sparse;
|
|
||||||
BOOL updatemap;
|
BOOL updatemap;
|
||||||
|
|
||||||
ntfs_log_enter("Entering for inode %lld, attr 0x%x, pos 0x%llx, count "
|
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;
|
goto errno_set;
|
||||||
}
|
}
|
||||||
#else
|
#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");
|
ntfs_log_perror("Failed to enlarge attribute");
|
||||||
goto errno_set;
|
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);
|
!= const_cpu_to_le16(0);
|
||||||
need_to.undo_data_size = 1;
|
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
|
* For compressed data, a single full block was allocated
|
||||||
* to deal with compression, possibly in a previous call.
|
* to deal with compression, possibly in a previous call.
|
||||||
@ -2221,7 +2220,7 @@ done:
|
|||||||
updatemap = (compressed
|
updatemap = (compressed
|
||||||
? NAttrFullyMapped(na) != 0 : update_from != -1);
|
? NAttrFullyMapped(na) != 0 : update_from != -1);
|
||||||
#endif
|
#endif
|
||||||
if (updatemap)
|
if (updatemap) {
|
||||||
if (ntfs_attr_update_mapping_pairs(na,
|
if (ntfs_attr_update_mapping_pairs(na,
|
||||||
(update_from < 0 ? 0 : update_from))) {
|
(update_from < 0 ? 0 : update_from))) {
|
||||||
/*
|
/*
|
||||||
@ -2231,6 +2230,10 @@ done:
|
|||||||
total = -1;
|
total = -1;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
if (!wasnonresident)
|
||||||
|
NAttrClearBeingNonResident(na);
|
||||||
|
NAttrClearDataAppending(na);
|
||||||
|
}
|
||||||
out:
|
out:
|
||||||
ntfs_log_leave("\n");
|
ntfs_log_leave("\n");
|
||||||
return total;
|
return total;
|
||||||
@ -2292,7 +2295,8 @@ err_out:
|
|||||||
if (updatemap)
|
if (updatemap)
|
||||||
ntfs_attr_update_mapping_pairs(na, 0);
|
ntfs_attr_update_mapping_pairs(na, 0);
|
||||||
/* Restore original data_size if needed. */
|
/* 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");
|
ntfs_log_perror("Failed to restore data_size");
|
||||||
errno = eo;
|
errno = eo;
|
||||||
errno_set:
|
errno_set:
|
||||||
@ -2310,7 +2314,6 @@ int ntfs_attr_pclose(ntfs_attr *na)
|
|||||||
ntfs_attr_search_ctx *ctx = NULL;
|
ntfs_attr_search_ctx *ctx = NULL;
|
||||||
runlist_element *rl;
|
runlist_element *rl;
|
||||||
int eo;
|
int eo;
|
||||||
s64 hole;
|
|
||||||
int compressed_part;
|
int compressed_part;
|
||||||
BOOL compressed;
|
BOOL compressed;
|
||||||
|
|
||||||
@ -2422,7 +2425,6 @@ int ntfs_attr_pclose(ntfs_attr *na)
|
|||||||
goto rl_err_out;
|
goto rl_err_out;
|
||||||
}
|
}
|
||||||
if (rl->lcn < (LCN)0) {
|
if (rl->lcn < (LCN)0) {
|
||||||
hole = rl->vcn + rl->length;
|
|
||||||
if (rl->lcn != (LCN)LCN_HOLE) {
|
if (rl->lcn != (LCN)LCN_HOLE) {
|
||||||
errno = EIO;
|
errno = EIO;
|
||||||
ntfs_log_perror("%s: Unexpected LCN (%lld)",
|
ntfs_log_perror("%s: Unexpected LCN (%lld)",
|
||||||
@ -2475,6 +2477,7 @@ retry:
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
|
NAttrClearComprClosing(na);
|
||||||
ntfs_log_leave("\n");
|
ntfs_log_leave("\n");
|
||||||
return (!ok);
|
return (!ok);
|
||||||
rl_err_out:
|
rl_err_out:
|
||||||
@ -2531,6 +2534,7 @@ s64 ntfs_attr_mst_pread(ntfs_attr *na, const s64 pos, const s64 bk_cnt,
|
|||||||
{
|
{
|
||||||
s64 br;
|
s64 br;
|
||||||
u8 *end;
|
u8 *end;
|
||||||
|
BOOL warn;
|
||||||
|
|
||||||
ntfs_log_trace("Entering for inode 0x%llx, attr type 0x%x, pos 0x%llx.\n",
|
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,
|
(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)
|
if (br <= 0)
|
||||||
return br;
|
return br;
|
||||||
br /= bk_size;
|
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 +
|
for (end = (u8*)dst + br * bk_size; (u8*)dst < end; dst = (u8*)dst +
|
||||||
bk_size)
|
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. */
|
/* Finally, return the number of blocks read. */
|
||||||
return br;
|
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);
|
min_size = sle64_to_cpu(ad->min_size);
|
||||||
max_size = sle64_to_cpu(ad->max_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)) ||
|
if ((min_size && (size < min_size)) ||
|
||||||
((max_size > 0) && (size > max_size))) {
|
((max_size > 0) && (size > max_size))) {
|
||||||
errno = ERANGE;
|
errno = ERANGE;
|
||||||
@ -4296,7 +4310,7 @@ add_non_resident:
|
|||||||
goto rm_attr_err_out;
|
goto rm_attr_err_out;
|
||||||
}
|
}
|
||||||
/* Resize and set attribute value. */
|
/* 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))) {
|
(val && (ntfs_attr_pwrite(na, 0, size, val) != size))) {
|
||||||
err = errno;
|
err = errno;
|
||||||
ntfs_log_perror("Failed to initialize just added attribute");
|
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 "
|
ntfs_log_trace("Eeek! Failed to release allocated clusters in error "
|
||||||
"code path. Leaving inconsistent metadata...\n");
|
"code path. Leaving inconsistent metadata...\n");
|
||||||
NAttrClearNonResident(na);
|
NAttrClearNonResident(na);
|
||||||
|
NAttrClearFullyMapped(na);
|
||||||
na->allocated_size = na->data_size;
|
na->allocated_size = na->data_size;
|
||||||
na->rl = NULL;
|
na->rl = NULL;
|
||||||
free(rl);
|
free(rl);
|
||||||
@ -5000,7 +5015,7 @@ static int ntfs_resident_attr_resize_i(ntfs_attr *na, const s64 newsize,
|
|||||||
return (ret);
|
return (ret);
|
||||||
}
|
}
|
||||||
/* Resize non-resident attribute */
|
/* 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) {
|
} else if (errno != ENOSPC && errno != EPERM) {
|
||||||
err = errno;
|
err = errno;
|
||||||
ntfs_log_perror("Failed to make attribute non-resident");
|
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.
|
* record is in a transiently corrupted state at this moment in time.
|
||||||
*/
|
*/
|
||||||
if (ntfs_cluster_free(vol, na, 0, -1) < 0) {
|
if (ntfs_cluster_free(vol, na, 0, -1) < 0) {
|
||||||
err = errno;
|
|
||||||
ntfs_log_perror("Eeek! Failed to release allocated clusters");
|
ntfs_log_perror("Eeek! Failed to release allocated clusters");
|
||||||
ntfs_log_trace("Ignoring error and leaving behind wasted "
|
ntfs_log_trace("Ignoring error and leaving behind wasted "
|
||||||
"clusters.\n");
|
"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. */
|
/* Update in-memory struct ntfs_attr. */
|
||||||
NAttrClearNonResident(na);
|
NAttrClearNonResident(na);
|
||||||
|
NAttrClearFullyMapped(na);
|
||||||
NAttrClearSparse(na);
|
NAttrClearSparse(na);
|
||||||
NAttrClearEncrypted(na);
|
NAttrClearEncrypted(na);
|
||||||
na->initialized_size = na->data_size;
|
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);
|
NAttrClearSparse(na);
|
||||||
a->flags &= ~ATTR_IS_SPARSE;
|
a->flags &= ~ATTR_IS_SPARSE;
|
||||||
|
na->data_flags = a->flags;
|
||||||
a->compression_unit = 0;
|
a->compression_unit = 0;
|
||||||
|
|
||||||
memmove((u8*)a + le16_to_cpu(a->name_offset) - 8,
|
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)
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
@ -376,7 +376,6 @@ int ntfs_invalidate_cache(struct CACHE_HEADER *cache,
|
|||||||
int flags)
|
int flags)
|
||||||
{
|
{
|
||||||
struct CACHED_GENERIC *current;
|
struct CACHED_GENERIC *current;
|
||||||
struct CACHED_GENERIC *previous;
|
|
||||||
struct CACHED_GENERIC *next;
|
struct CACHED_GENERIC *next;
|
||||||
struct HASH_ENTRY *link;
|
struct HASH_ENTRY *link;
|
||||||
int count;
|
int count;
|
||||||
@ -412,7 +411,6 @@ int ntfs_invalidate_cache(struct CACHE_HEADER *cache,
|
|||||||
* Search sequentially in LRU list
|
* Search sequentially in LRU list
|
||||||
*/
|
*/
|
||||||
current = cache->most_recent_entry;
|
current = cache->most_recent_entry;
|
||||||
previous = (struct CACHED_GENERIC*)NULL;
|
|
||||||
while (current) {
|
while (current) {
|
||||||
if (!compare(current, item)) {
|
if (!compare(current, item)) {
|
||||||
next = current->next;
|
next = current->next;
|
||||||
@ -423,7 +421,6 @@ int ntfs_invalidate_cache(struct CACHE_HEADER *cache,
|
|||||||
current = next;
|
current = next;
|
||||||
count++;
|
count++;
|
||||||
} else {
|
} else {
|
||||||
previous = current;
|
|
||||||
current = current->next;
|
current = current->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -81,259 +81,215 @@ typedef enum {
|
|||||||
NTFS_SB_IS_COMPRESSED = 0x8000,
|
NTFS_SB_IS_COMPRESSED = 0x8000,
|
||||||
} ntfs_compression_constants;
|
} ntfs_compression_constants;
|
||||||
|
|
||||||
#define THRESHOLD 3 /* minimal match length for compression */
|
|
||||||
#define NIL NTFS_SB_SIZE /* End of tree's node */
|
|
||||||
|
|
||||||
struct COMPRESS_CONTEXT {
|
struct COMPRESS_CONTEXT {
|
||||||
const unsigned char *inbuf;
|
const unsigned char *inbuf;
|
||||||
unsigned int len;
|
int bufsize;
|
||||||
unsigned int nbt;
|
int size;
|
||||||
int match_position;
|
int rel;
|
||||||
unsigned int match_length;
|
int mxsz;
|
||||||
u16 lson[NTFS_SB_SIZE + 1];
|
s16 head[256];
|
||||||
u16 rson[NTFS_SB_SIZE + 257];
|
s16 lson[NTFS_SB_SIZE];
|
||||||
u16 dad[NTFS_SB_SIZE + 1];
|
s16 rson[NTFS_SB_SIZE];
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize the match tree
|
* Search for the longest sequence matching current position
|
||||||
*/
|
|
||||||
|
|
||||||
static void ntfs_init_compress_tree(struct COMPRESS_CONTEXT *pctx)
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
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 */
|
|
||||||
do {
|
|
||||||
} while ((p1[i] == p2[i]) && (++i < mxi));
|
|
||||||
less = (i < mxi) && (p1[i] < p2[i]);
|
|
||||||
}
|
|
||||||
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;
|
|
||||||
else
|
|
||||||
pctx->lson[i] = r;
|
|
||||||
/* remove pp */
|
|
||||||
pctx->dad[pp] = NIL;
|
|
||||||
done = TRUE;
|
|
||||||
pctx->match_length = mxl;
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
if ((i == pctx->match_length)
|
|
||||||
&& ((c = (r - pp + 2*NTFS_SB_SIZE - 1))
|
|
||||||
< pctx->match_position))
|
|
||||||
pctx->match_position = c;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} while (!done);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Search for the longest previous string matching the
|
|
||||||
* current one
|
|
||||||
*
|
*
|
||||||
* Returns the end of the longest current string which matched
|
* A binary tree is maintained to locate all previously met sequences,
|
||||||
* or zero if there was a bug
|
* 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 unsigned int ntfs_nextmatch(struct COMPRESS_CONTEXT *pctx,
|
static int ntfs_best_match(struct COMPRESS_CONTEXT *pctx, int i)
|
||||||
unsigned int rr, int dd)
|
|
||||||
{
|
{
|
||||||
unsigned int bestlen = 0;
|
s16 *prev;
|
||||||
|
int node;
|
||||||
|
register long j;
|
||||||
|
long maxpos;
|
||||||
|
long startj;
|
||||||
|
long bestj;
|
||||||
|
int bufsize;
|
||||||
|
int bestnode;
|
||||||
|
register const unsigned char *p1,*p2;
|
||||||
|
|
||||||
do {
|
p1 = pctx->inbuf;
|
||||||
rr++;
|
node = pctx->head[p1[i] & 255];
|
||||||
if (pctx->match_length > 0)
|
if (node >= 0) {
|
||||||
pctx->match_length--;
|
/* search the best match at current position */
|
||||||
if (!pctx->len) {
|
bestnode = node;
|
||||||
ntfs_log_error("compress bug : void run\n");
|
bufsize = pctx->bufsize;
|
||||||
goto bug;
|
/* restrict matches to the longest allowed sequence */
|
||||||
}
|
maxpos = bufsize;
|
||||||
if (--pctx->len) {
|
if ((i + pctx->mxsz) < maxpos)
|
||||||
if (rr >= NTFS_SB_SIZE) {
|
maxpos = i + pctx->mxsz;
|
||||||
ntfs_log_error("compress bug : buffer overflow\n");
|
startj = i + 1 - maxpos;
|
||||||
goto bug;
|
bestj = startj;
|
||||||
}
|
/* make indexes relative to end of allowed position */
|
||||||
if (((rr + bestlen) < NTFS_SB_SIZE)) {
|
p1 = &p1[maxpos];
|
||||||
while ((unsigned int)(1 << pctx->nbt)
|
if (startj < 0) {
|
||||||
<= (rr - 1))
|
do {
|
||||||
pctx->nbt++;
|
/* indexes are negative */
|
||||||
ntfs_new_node(pctx,rr);
|
p2 = &p1[node - i];
|
||||||
if (pctx->match_length > bestlen)
|
/* no need to compare the first byte */
|
||||||
bestlen = pctx->match_length;
|
j = startj;
|
||||||
} else
|
/* the second byte cannot lead to useful compression */
|
||||||
if (dd > 0) {
|
if (p1[j] == p2[j]) {
|
||||||
rr += dd;
|
j++;
|
||||||
if ((int)pctx->match_length > dd)
|
if (j < 0) {
|
||||||
pctx->match_length -= dd;
|
do {
|
||||||
else
|
} while ((p1[j] == p2[j])
|
||||||
pctx->match_length = 0;
|
&& (++j < 0));
|
||||||
if ((int)pctx->len < dd) {
|
}
|
||||||
ntfs_log_error("compress bug : run overflows\n");
|
/* remember the match, if better */
|
||||||
goto bug;
|
if (j > bestj) {
|
||||||
|
bestj = j;
|
||||||
|
bestnode = node;
|
||||||
}
|
}
|
||||||
pctx->len -= dd;
|
|
||||||
dd = 0;
|
|
||||||
}
|
}
|
||||||
|
/* walk in the tree in the right direction */
|
||||||
|
if ((j < 0) && (p1[j] < p2[j]))
|
||||||
|
prev = &pctx->lson[node];
|
||||||
|
else
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
} while (dd-- > 0);
|
/* done, return the best match */
|
||||||
return (rr);
|
pctx->size = bestj + maxpos - i;
|
||||||
bug :
|
pctx->rel = bestnode - i;
|
||||||
return (0);
|
} else {
|
||||||
|
pctx->head[p1[i] & 255] = i;
|
||||||
|
pctx->size = 0;
|
||||||
|
pctx->rel = 0;
|
||||||
|
}
|
||||||
|
return (pctx->size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Compress an input block
|
* Compress a 4096-byte block
|
||||||
*
|
*
|
||||||
* Returns the size of the compressed block (including header)
|
* Returns a header of two bytes followed by the compressed data.
|
||||||
* or zero if there was an error
|
* 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_compress_block(const char *inbuf,
|
static unsigned int ntfs_compress_block(const char *inbuf, int bufsize,
|
||||||
unsigned int size, char *outbuf)
|
char *outbuf)
|
||||||
{
|
{
|
||||||
struct COMPRESS_CONTEXT *pctx;
|
struct COMPRESS_CONTEXT *pctx;
|
||||||
char *ptag;
|
int i; /* current position */
|
||||||
int dd;
|
int j; /* end of best match from current position */
|
||||||
unsigned int rr;
|
int k; /* end of best match from next position */
|
||||||
unsigned int last_match_length;
|
int offs; /* offset to best match */
|
||||||
unsigned int q;
|
int n;
|
||||||
|
int bp; /* bits to store offset */
|
||||||
|
int mxoff; /* max match offset : 1 << bp */
|
||||||
|
int mxsz2;
|
||||||
unsigned int xout;
|
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));
|
pctx = (struct COMPRESS_CONTEXT*)ntfs_malloc(sizeof(struct COMPRESS_CONTEXT));
|
||||||
if (pctx) {
|
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;
|
pctx->inbuf = (const unsigned char*)inbuf;
|
||||||
ntfs_init_compress_tree(pctx);
|
pctx->bufsize = bufsize;
|
||||||
xout = 2;
|
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 = &outbuf[xout++];
|
||||||
*ptag = 0;
|
while ((i < bufsize) && (xout < (NTFS_SB_SIZE + 2))) {
|
||||||
rr = 0;
|
/* adjust the longest match we can output */
|
||||||
pctx->nbt = 4;
|
while (mxoff < i) {
|
||||||
pctx->len = size;
|
bp++;
|
||||||
pctx->match_length = 0;
|
mxoff <<= 1;
|
||||||
ntfs_new_node(pctx,0);
|
pctx->mxsz = (pctx->mxsz + 2) >> 1;
|
||||||
do {
|
}
|
||||||
if (pctx->match_length > pctx->len)
|
/* search the best match at current position */
|
||||||
pctx->match_length = pctx->len;
|
if (done < i)
|
||||||
if (pctx->match_length < THRESHOLD) {
|
do {
|
||||||
pctx->match_length = 1;
|
ntfs_best_match(pctx,++done);
|
||||||
if (ntag >= 8) {
|
} while (done < i);
|
||||||
ntag = 0;
|
j = i + pctx->size;
|
||||||
ptag = &outbuf[xout++];
|
if ((j - i) > pctx->mxsz)
|
||||||
*ptag = 0;
|
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 {
|
||||||
|
q = (~offs << (16 - bp))
|
||||||
|
+ (j - i - 3);
|
||||||
|
outbuf[xout++] = q & 255;
|
||||||
|
outbuf[xout++] = (q >> 8) & 255;
|
||||||
|
tag |= (1 << (8 - ntag));
|
||||||
|
i = j;
|
||||||
}
|
}
|
||||||
outbuf[xout++] = inbuf[rr];
|
|
||||||
ntag++;
|
|
||||||
} else {
|
} else {
|
||||||
while ((unsigned int)(1 << pctx->nbt)
|
outbuf[xout++] = inbuf[i];
|
||||||
<= (rr - 1))
|
i++;
|
||||||
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++;
|
|
||||||
outbuf[xout++] = q & 255;
|
|
||||||
outbuf[xout++] = (q >> 8) & 255;
|
|
||||||
}
|
}
|
||||||
last_match_length = pctx->match_length;
|
/* store the tag if fully used */
|
||||||
dd = last_match_length;
|
if (!--ntag) {
|
||||||
if (dd-- > 0) {
|
*ptag = tag;
|
||||||
rr = ntfs_nextmatch(pctx,rr,dd);
|
ntag = 8;
|
||||||
if (!rr)
|
ptag = &outbuf[xout++];
|
||||||
goto bug;
|
tag = 0;
|
||||||
}
|
}
|
||||||
/*
|
}
|
||||||
* stop if input is exhausted or output has exceeded
|
/* store the last tag, if partially used */
|
||||||
* the maximum size. Two extra bytes have to be
|
if (ntag == 8)
|
||||||
* reserved in output buffer, as 3 bytes may be
|
xout--;
|
||||||
* output in a loop.
|
else
|
||||||
*/
|
*ptag = tag;
|
||||||
} while ((pctx->len > 0)
|
/* uncompressed must be full size, accept if better */
|
||||||
&& (rr < size) && (xout < (NTFS_SB_SIZE + 2)));
|
if ((i >= bufsize) && (xout < (NTFS_SB_SIZE + 2))) {
|
||||||
/* uncompressed must be full size, so accept if better */
|
|
||||||
if (xout < (NTFS_SB_SIZE + 2)) {
|
|
||||||
outbuf[0] = (xout - 3) & 255;
|
outbuf[0] = (xout - 3) & 255;
|
||||||
outbuf[1] = 0xb0 + (((xout - 3) >> 8) & 15);
|
outbuf[1] = 0xb0 + (((xout - 3) >> 8) & 15);
|
||||||
} else {
|
} else {
|
||||||
memcpy(&outbuf[2],inbuf,size);
|
memcpy(&outbuf[2],inbuf,bufsize);
|
||||||
if (size < NTFS_SB_SIZE)
|
if (bufsize < NTFS_SB_SIZE)
|
||||||
memset(&outbuf[size+2],0,NTFS_SB_SIZE - size);
|
memset(&outbuf[bufsize+2], 0,
|
||||||
|
NTFS_SB_SIZE - bufsize);
|
||||||
outbuf[0] = 0xff;
|
outbuf[0] = 0xff;
|
||||||
outbuf[1] = 0x3f;
|
outbuf[1] = 0x3f;
|
||||||
xout = NTFS_SB_SIZE + 2;
|
xout = NTFS_SB_SIZE + 2;
|
||||||
@ -343,9 +299,7 @@ static unsigned int ntfs_compress_block(const char *inbuf,
|
|||||||
xout = 0;
|
xout = 0;
|
||||||
errno = ENOMEM;
|
errno = ENOMEM;
|
||||||
}
|
}
|
||||||
return (xout); /* 0 for an error, > size if cannot compress */
|
return (xout);
|
||||||
bug :
|
|
||||||
return (0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -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)
|
* 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,
|
const char *outbuf, s32 count, BOOL compress,
|
||||||
BOOL appending, VCN *update_from)
|
BOOL appending, VCN *update_from)
|
||||||
{
|
{
|
||||||
int rounded;
|
s32 rounded;
|
||||||
int written;
|
s32 written;
|
||||||
int clsz;
|
int clsz;
|
||||||
|
|
||||||
if (compress) {
|
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)
|
* (we are reopening an existing file to append to it)
|
||||||
* Decompress the data and append
|
* 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);
|
outbuf = (char*)ntfs_malloc(na->compression_block_size);
|
||||||
if (outbuf) {
|
if (outbuf) {
|
||||||
if (appending) {
|
if (appending) {
|
@ -226,6 +226,9 @@
|
|||||||
/* Define to 1 if you have the <sys/byteorder.h> header file. */
|
/* Define to 1 if you have the <sys/byteorder.h> header file. */
|
||||||
#undef HAVE_SYS_BYTEORDER_H
|
#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. */
|
/* Define to 1 if you have the <sys/endian.h> header file. */
|
||||||
#undef HAVE_SYS_ENDIAN_H
|
#undef HAVE_SYS_ENDIAN_H
|
||||||
|
|
||||||
@ -309,13 +312,13 @@
|
|||||||
#define PACKAGE_NAME "ntfs-3g"
|
#define PACKAGE_NAME "ntfs-3g"
|
||||||
|
|
||||||
/* Define to the full name and version of this package. */
|
/* 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 to the one symbol short name of this package. */
|
||||||
#define PACKAGE_TARNAME "ntfs-3g"
|
#define PACKAGE_TARNAME "ntfs-3g"
|
||||||
|
|
||||||
/* Define to the version of this package. */
|
/* Define to the version of this package. */
|
||||||
#define PACKAGE_VERSION "2011.4.12"
|
#define PACKAGE_VERSION "2012.1.15"
|
||||||
|
|
||||||
/* POSIX ACL support */
|
/* POSIX ACL support */
|
||||||
#undef POSIXACLS
|
#undef POSIXACLS
|
||||||
@ -345,7 +348,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Version number of package */
|
/* Version number of package */
|
||||||
#define VERSION "2011.4.12"
|
#define VERSION "2012.1.15"
|
||||||
|
|
||||||
/* Define to 1 if this is a Windows OS */
|
/* Define to 1 if this is a Windows OS */
|
||||||
#undef WINDOWS
|
#undef WINDOWS
|
||||||
@ -375,6 +378,9 @@
|
|||||||
/* Required define if using POSIX threads */
|
/* Required define if using POSIX threads */
|
||||||
#undef _REENTRANT
|
#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
|
/* 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. */
|
calls it, or to nothing if 'inline' is not supported under any name. */
|
||||||
#ifndef __cplusplus
|
#ifndef __cplusplus
|
@ -38,10 +38,10 @@ static __inline__ void ntfs_debug_runlist_dump(const struct _runlist_element *rl
|
|||||||
|
|
||||||
#define NTFS_BUG(msg) \
|
#define NTFS_BUG(msg) \
|
||||||
{ \
|
{ \
|
||||||
int ___i; \
|
int ___i = 1; \
|
||||||
ntfs_log_critical("Bug in %s(): %s\n", __FUNCTION__, msg); \
|
ntfs_log_critical("Bug in %s(): %s\n", __FUNCTION__, msg); \
|
||||||
ntfs_log_debug("Forcing segmentation fault!"); \
|
ntfs_log_debug("Forcing segmentation fault!"); \
|
||||||
___i = ((int*)NULL)[1]; \
|
___i = ((int*)NULL)[___i]; \
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* defined _NTFS_DEBUG_H */
|
#endif /* defined _NTFS_DEBUG_H */
|
@ -58,6 +58,9 @@
|
|||||||
#ifdef HAVE_SYS_MOUNT_H
|
#ifdef HAVE_SYS_MOUNT_H
|
||||||
#include <sys/mount.h>
|
#include <sys/mount.h>
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAVE_SYS_DISK_H
|
||||||
|
#include <sys/disk.h>
|
||||||
|
#endif
|
||||||
#ifdef HAVE_LINUX_FD_H
|
#ifdef HAVE_LINUX_FD_H
|
||||||
#include <linux/fd.h>
|
#include <linux/fd.h>
|
||||||
#endif
|
#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;
|
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
|
#endif
|
||||||
/*
|
/*
|
||||||
* We couldn't figure it out by using a specialized ioctl,
|
* 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;
|
return sect_size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#elif defined(DIOCGSECTORSIZE)
|
||||||
|
{
|
||||||
|
/* FreeBSD */
|
||||||
|
size_t sect_size = 0;
|
||||||
|
|
||||||
|
if (!dev->d_ops->ioctl(dev, DIOCGSECTORSIZE, §_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, §_size)) {
|
||||||
|
ntfs_log_debug("DKIOCGETBLOCKSIZE sector size = %d bytes\n",
|
||||||
|
(int) sect_size);
|
||||||
|
return sect_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
errno = EOPNOTSUPP;
|
errno = EOPNOTSUPP;
|
||||||
#endif
|
#endif
|
@ -257,7 +257,7 @@ u64 ntfs_inode_lookup_by_name(ntfs_inode *dir_ni,
|
|||||||
u8 *index_end;
|
u8 *index_end;
|
||||||
ntfs_attr *ia_na;
|
ntfs_attr *ia_na;
|
||||||
int eo, rc;
|
int eo, rc;
|
||||||
u32 index_block_size, index_vcn_size;
|
u32 index_block_size;
|
||||||
u8 index_vcn_size_bits;
|
u8 index_vcn_size_bits;
|
||||||
|
|
||||||
ntfs_log_trace("Entering\n");
|
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. */
|
/* Determine the size of a vcn in the directory index. */
|
||||||
if (vol->cluster_size <= index_block_size) {
|
if (vol->cluster_size <= index_block_size) {
|
||||||
index_vcn_size = vol->cluster_size;
|
|
||||||
index_vcn_size_bits = vol->cluster_size_bits;
|
index_vcn_size_bits = vol->cluster_size_bits;
|
||||||
} else {
|
} else {
|
||||||
index_vcn_size = vol->sector_size;
|
index_vcn_size_bits = NTFS_BLOCK_SIZE_BITS;
|
||||||
index_vcn_size_bits = vol->sector_size_bits;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the starting vcn of the index_block holding the child node. */
|
/* 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_ENTRY *ie;
|
||||||
INDEX_ALLOCATION *ia = NULL;
|
INDEX_ALLOCATION *ia = NULL;
|
||||||
int rc, ir_pos, bmp_buf_size, bmp_buf_pos, eo;
|
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;
|
u8 index_block_size_bits, index_vcn_size_bits;
|
||||||
|
|
||||||
ntfs_log_trace("Entering.\n");
|
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;
|
index_block_size_bits = ffs(index_block_size) - 1;
|
||||||
if (vol->cluster_size <= index_block_size) {
|
if (vol->cluster_size <= index_block_size) {
|
||||||
index_vcn_size = vol->cluster_size;
|
|
||||||
index_vcn_size_bits = vol->cluster_size_bits;
|
index_vcn_size_bits = vol->cluster_size_bits;
|
||||||
} else {
|
} else {
|
||||||
index_vcn_size = vol->sector_size;
|
index_vcn_size_bits = NTFS_BLOCK_SIZE_BITS;
|
||||||
index_vcn_size_bits = vol->sector_size_bits;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Are we jumping straight into the index allocation attribute? */
|
/* 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
|
else
|
||||||
ir->clusters_per_index_block =
|
ir->clusters_per_index_block =
|
||||||
ni->vol->indx_record_size >>
|
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.entries_offset = cpu_to_le32(sizeof(INDEX_HEADER));
|
||||||
ir->index.index_length = cpu_to_le32(index_len);
|
ir->index.index_length = cpu_to_le32(index_len);
|
||||||
ir->index.allocated_size = 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 res = 0;
|
||||||
int longlen = 0;
|
int longlen = 0;
|
||||||
int shortlen = 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];
|
ntfschar oldname[MAX_DOS_NAME_LENGTH];
|
||||||
int oldlen;
|
int oldlen;
|
||||||
ntfs_volume *vol;
|
|
||||||
u64 fnum;
|
|
||||||
u64 dnum;
|
u64 dnum;
|
||||||
BOOL closed = FALSE;
|
BOOL closed = FALSE;
|
||||||
ntfschar *shortname = NULL;
|
ntfschar *shortname = NULL;
|
||||||
ntfschar longname[NTFS_MAX_NAME_LEN];
|
ntfschar longname[NTFS_MAX_NAME_LEN];
|
||||||
|
|
||||||
vol = ni->vol;
|
/* copy the string to insert a null char, and truncate */
|
||||||
fnum = ni->mft_no;
|
if (size > 3*MAX_DOS_NAME_LENGTH)
|
||||||
/* convert the string to the NTFS wide chars */
|
size = 3*MAX_DOS_NAME_LENGTH;
|
||||||
if (size > MAX_DOS_NAME_LENGTH)
|
|
||||||
size = MAX_DOS_NAME_LENGTH;
|
|
||||||
strncpy(newname, value, size);
|
strncpy(newname, value, size);
|
||||||
|
/* a long name may be truncated badly and be untranslatable */
|
||||||
newname[size] = 0;
|
newname[size] = 0;
|
||||||
|
/* convert the string to the NTFS wide chars, and truncate */
|
||||||
shortlen = ntfs_mbstoucs(newname, &shortname);
|
shortlen = ntfs_mbstoucs(newname, &shortname);
|
||||||
|
if (shortlen > MAX_DOS_NAME_LENGTH)
|
||||||
|
shortlen = MAX_DOS_NAME_LENGTH;
|
||||||
/* make sure the short name has valid chars */
|
/* make sure the short name has valid chars */
|
||||||
if ((shortlen < 0) || ntfs_forbidden_chars(shortname,shortlen)) {
|
if ((shortlen < 0) || ntfs_forbidden_chars(shortname,shortlen)) {
|
||||||
ntfs_inode_close_in_dir(ni,dir_ni);
|
ntfs_inode_close_in_dir(ni,dir_ni);
|
@ -139,7 +139,6 @@ static int fixup_loop(ntfs_inode *ni)
|
|||||||
ntfs_attr *na;
|
ntfs_attr *na;
|
||||||
ATTR_RECORD *a;
|
ATTR_RECORD *a;
|
||||||
BOOL restart;
|
BOOL restart;
|
||||||
BOOL first;
|
|
||||||
int cnt;
|
int cnt;
|
||||||
int maxcnt;
|
int maxcnt;
|
||||||
int res = 0;
|
int res = 0;
|
||||||
@ -200,7 +199,6 @@ static int fixup_loop(ntfs_inode *ni)
|
|||||||
if (na)
|
if (na)
|
||||||
ntfs_attr_close(na);
|
ntfs_attr_close(na);
|
||||||
}
|
}
|
||||||
first = FALSE;
|
|
||||||
} while (restart && !res);
|
} while (restart && !res);
|
||||||
if (ctx)
|
if (ctx)
|
||||||
ntfs_attr_put_search_ctx(ctx);
|
ntfs_attr_put_search_ctx(ctx);
|
@ -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)
|
if (ni->vol->cluster_size <= icx->block_size)
|
||||||
icx->vcn_size_bits = ni->vol->cluster_size_bits;
|
icx->vcn_size_bits = ni->vol->cluster_size_bits;
|
||||||
else
|
else
|
||||||
icx->vcn_size_bits = ni->vol->sector_size_bits;
|
icx->vcn_size_bits = NTFS_BLOCK_SIZE_BITS;
|
||||||
/* get the appropriate collation function */
|
/* get the appropriate collation function */
|
||||||
icx->collate = ntfs_get_collate_function(ir->collation_rule);
|
icx->collate = ntfs_get_collate_function(ir->collation_rule);
|
||||||
if (!icx->collate) {
|
if (!icx->collate) {
|
@ -365,7 +365,7 @@ int ntfs_inode_real_close(ntfs_inode *ni)
|
|||||||
*/
|
*/
|
||||||
if (base_ni->nr_extents) {
|
if (base_ni->nr_extents) {
|
||||||
/* Resize the memory buffer. */
|
/* 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 *));
|
sizeof(ntfs_inode *));
|
||||||
/* Ignore errors, they don't really matter. */
|
/* Ignore errors, they don't really matter. */
|
||||||
if (tmp_nis)
|
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)
|
void ntfs_inode_invalidate(ntfs_volume *vol, const MFT_REF mref)
|
||||||
{
|
{
|
||||||
struct CACHED_NIDATA item;
|
struct CACHED_NIDATA item;
|
||||||
int count;
|
|
||||||
|
|
||||||
item.inum = MREF(mref);
|
item.inum = MREF(mref);
|
||||||
item.ni = (ntfs_inode*)NULL;
|
item.ni = (ntfs_inode*)NULL;
|
||||||
item.pathname = (const char*)NULL;
|
item.pathname = (const char*)NULL;
|
||||||
item.varsize = 0;
|
item.varsize = 0;
|
||||||
count = ntfs_invalidate_cache(vol->nidata_cache,
|
ntfs_invalidate_cache(vol->nidata_cache,
|
||||||
GENERIC(&item),idata_cache_compare,CACHE_FREE);
|
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)
|
ntfs_inode *ntfs_extent_inode_open(ntfs_inode *base_ni, const MFT_REF mref)
|
||||||
{
|
{
|
||||||
u64 mft_no = MREF_LE(mref);
|
u64 mft_no = MREF_LE(mref);
|
||||||
|
VCN extent_vcn;
|
||||||
|
runlist_element *rl;
|
||||||
|
ntfs_volume *vol;
|
||||||
ntfs_inode *ni = NULL;
|
ntfs_inode *ni = NULL;
|
||||||
ntfs_inode **extent_nis;
|
ntfs_inode **extent_nis;
|
||||||
int i;
|
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)mft_no,
|
||||||
(unsigned long long)base_ni->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? */
|
/* Is the extent inode already open and attached to the base inode? */
|
||||||
if (base_ni->nr_extents > 0) {
|
if (base_ni->nr_extents > 0) {
|
||||||
extent_nis = base_ni->extent_nis;
|
extent_nis = base_ni->extent_nis;
|
||||||
@ -1115,7 +1148,7 @@ int ntfs_inode_add_attrlist(ntfs_inode *ni)
|
|||||||
ctx->attr->name_length + 7) & ~7;
|
ctx->attr->name_length + 7) & ~7;
|
||||||
al_len += ale_size;
|
al_len += ale_size;
|
||||||
|
|
||||||
aln = MEM2_realloc(al, al_len);
|
aln = realloc(al, al_len);
|
||||||
if (!aln) {
|
if (!aln) {
|
||||||
err = errno;
|
err = errno;
|
||||||
ntfs_log_perror("Failed to realloc %d bytes", al_len);
|
ntfs_log_perror("Failed to realloc %d bytes", al_len);
|
@ -2223,11 +2223,11 @@ typedef struct {
|
|||||||
/* The below field is NOT present for the quota defaults entry. */
|
/* The below field is NOT present for the quota defaults entry. */
|
||||||
SID sid; /* The SID of the user/object associated with
|
SID sid; /* The SID of the user/object associated with
|
||||||
this quota entry. If this field is missing
|
this quota entry. If this field is missing
|
||||||
then the INDEX_ENTRY is padded with zeros
|
then the INDEX_ENTRY is padded to a multiple
|
||||||
to multiply of 8 which are not counted in
|
of 8 with zeros which are not counted in
|
||||||
the data_length field. If the sid is present
|
the data_length field. If the sid is present
|
||||||
then this structure is padded with zeros to
|
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. */
|
the INDEX_ENTRY's data_length. */
|
||||||
} __attribute__((__packed__)) QUOTA_CONTROL_ENTRY;
|
} __attribute__((__packed__)) QUOTA_CONTROL_ENTRY;
|
||||||
|
|
@ -468,7 +468,7 @@ BOOL ntfs_check_logfile(ntfs_attr *log_na, RESTART_PAGE_HEADER **rp)
|
|||||||
u8 *kaddr = NULL;
|
u8 *kaddr = NULL;
|
||||||
RESTART_PAGE_HEADER *rstr1_ph = NULL;
|
RESTART_PAGE_HEADER *rstr1_ph = NULL;
|
||||||
RESTART_PAGE_HEADER *rstr2_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;
|
BOOL logfile_is_empty = TRUE;
|
||||||
u8 log_page_bits;
|
u8 log_page_bits;
|
||||||
|
|
||||||
@ -481,7 +481,6 @@ BOOL ntfs_check_logfile(ntfs_attr *log_na, RESTART_PAGE_HEADER **rp)
|
|||||||
if (size > (s64)MaxLogFileSize)
|
if (size > (s64)MaxLogFileSize)
|
||||||
size = MaxLogFileSize;
|
size = MaxLogFileSize;
|
||||||
log_page_size = DefaultLogPageSize;
|
log_page_size = DefaultLogPageSize;
|
||||||
log_page_mask = log_page_size - 1;
|
|
||||||
/*
|
/*
|
||||||
* Use generic_ffs() instead of ffs() to enable the compiler to
|
* Use generic_ffs() instead of ffs() to enable the compiler to
|
||||||
* optimize log_page_size and log_page_bits into constants.
|
* 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
Loading…
Reference in New Issue
Block a user