-back to a cache of 8, libntfs 2011.4.12 and the old

ntfs mount settings (new libntfs makes problems)
This commit is contained in:
fix94.1 2012-04-29 09:03:06 +00:00
parent d714ded900
commit 70e3df6d5d
31 changed files with 825 additions and 1038 deletions

View File

@ -1,7 +1,6 @@
/** /**
* ntfs.h - Simple functionality for startup, mounting and unmounting of NTFS-based devices. * 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) 2009 Rhys "Shareese" Koedijk
* Copyright (c) 2006 Michael "Chishm" Chisholm * Copyright (c) 2006 Michael "Chishm" Chisholm
* *

Binary file not shown.

View File

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

View File

@ -1,7 +1,6 @@
/** /**
* ntfs.h - Simple functionality for startup, mounting and unmounting of NTFS-based devices. * 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) 2009 Rhys "Shareese" Koedijk
* Copyright (c) 2006 Michael "Chishm" Chisholm * Copyright (c) 2006 Michael "Chishm" Chisholm
* *

View File

@ -522,7 +522,9 @@ 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;
@ -878,7 +880,7 @@ BOOL ntfs_valid_posix(const struct POSIX_SECURITY *pxdesc)
} }
} }
if ((pxdesc->acccnt > 0) if ((pxdesc->acccnt > 0)
&& ((checks[0].owners != 1) || (checks[0].groups != 1) && ((checks[0].owners != 1) || (checks[0].groups != 1)
|| (checks[0].others != 1))) || (checks[0].others != 1)))
ok = FALSE; ok = FALSE;
/* do not check owner, group or other are present in */ /* do not check owner, group or other are present in */
@ -1804,7 +1806,7 @@ static BOOL build_group_denials_grant(ACL *pacl,
* - grants to owner (always present - first grant) * - grants to owner (always present - first grant)
* + grants to designated user * + grants to designated user
* + mask denial to group (unless mask allows all) * + mask denial to group (unless mask allows all)
* - denials to group (preventing grants to world to apply) * - denials to group (preventing grants to world to apply)
* - grants to group (unless group has no more than world rights) * - grants to group (unless group has no more than world rights)
* + mask denials to designated group (unless mask allows all) * + mask denials to designated group (unless mask allows all)
* + grants to designated group * + grants to designated group
@ -1899,6 +1901,7 @@ 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;
@ -1906,6 +1909,7 @@ 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);
@ -3128,6 +3132,7 @@ 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;
@ -3136,6 +3141,7 @@ 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;
/* /*
@ -3875,10 +3881,12 @@ 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);
@ -3961,6 +3969,7 @@ 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;
@ -3994,6 +4003,7 @@ 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) {

View File

@ -475,10 +475,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 "
@ -1775,6 +1774,7 @@ 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_i(na, pos + count, HOLES_OK)) { if (ntfs_attr_truncate(na, pos + count)) {
ntfs_log_perror("Failed to enlarge attribute"); ntfs_log_perror("Failed to enlarge attribute");
goto errno_set; goto errno_set;
} }
@ -1860,6 +1860,7 @@ 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.
@ -2220,7 +2221,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))) {
/* /*
@ -2230,10 +2231,6 @@ 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;
@ -2295,8 +2292,7 @@ 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 if (need_to.undo_data_size && ntfs_attr_truncate(na, old_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:
@ -2314,6 +2310,7 @@ 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;
@ -2425,6 +2422,7 @@ 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)",
@ -2477,7 +2475,6 @@ 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:
@ -2534,7 +2531,6 @@ 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,
@ -2548,11 +2544,9 @@ 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_warn((NTFS_RECORD*)dst, bk_size, warn); ntfs_mst_post_read_fixup((NTFS_RECORD*)dst, bk_size);
/* Finally, return the number of blocks read. */ /* Finally, return the number of blocks read. */
return br; return br;
} }
@ -3550,14 +3544,6 @@ 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))) {
@ -4310,7 +4296,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_i(na, size, HOLES_OK) || if (ntfs_attr_truncate(na, size) ||
(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");
@ -4891,7 +4877,6 @@ 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);
@ -5015,7 +5000,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_i(na, newsize, HOLES_OK); return ntfs_attr_truncate(na, newsize);
} 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");
@ -5363,6 +5348,7 @@ 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");
@ -5374,7 +5360,6 @@ 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;
@ -5468,7 +5453,6 @@ 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,
@ -6438,12 +6422,7 @@ out:
int ntfs_attr_truncate(ntfs_attr *na, const s64 newsize) int ntfs_attr_truncate(ntfs_attr *na, const s64 newsize)
{ {
int r; return (ntfs_attr_truncate_i(na, newsize, HOLES_OK));
r = ntfs_attr_truncate_i(na, newsize, HOLES_OK);
NAttrClearDataAppending(na);
NAttrClearBeingNonResident(na);
return (r);
} }
/* /*

View File

@ -376,6 +376,7 @@ 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;
@ -411,6 +412,7 @@ 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;
@ -421,6 +423,7 @@ int ntfs_invalidate_cache(struct CACHE_HEADER *cache,
current = next; current = next;
count++; count++;
} else { } else {
previous = current;
current = current->next; current = current->next;
} }
} }

View File

@ -28,7 +28,7 @@
* this was put into public domain in 1988 by Haruhiko OKUMURA). * this was put into public domain in 1988 by Haruhiko OKUMURA).
* *
* LZHUF.C English version 1.0 * LZHUF.C English version 1.0
* Based on Japanese version 29-NOV-1988 * Based on Japanese version 29-NOV-1988
* LZSS coded by Haruhiko OKUMURA * LZSS coded by Haruhiko OKUMURA
* Adaptive Huffman Coding coded by Haruyasu YOSHIZAKI * Adaptive Huffman Coding coded by Haruyasu YOSHIZAKI
* Edited and translated to English by Kenji RIKITAKE * Edited and translated to English by Kenji RIKITAKE
@ -62,8 +62,8 @@
#include "logging.h" #include "logging.h"
#include "misc.h" #include "misc.h"
#undef le16_to_cpup #undef le16_to_cpup
/* the standard le16_to_cpup() crashes for unaligned data on some processors */ /* the standard le16_to_cpup() crashes for unaligned data on some processors */
#define le16_to_cpup(p) (*(u8*)(p) + (((u8*)(p))[1] << 8)) #define le16_to_cpup(p) (*(u8*)(p) + (((u8*)(p))[1] << 8))
/** /**
@ -81,215 +81,259 @@ 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;
int bufsize; unsigned int len;
int size; unsigned int nbt;
int rel; int match_position;
int mxsz; unsigned int match_length;
s16 head[256]; u16 lson[NTFS_SB_SIZE + 1];
s16 lson[NTFS_SB_SIZE]; u16 rson[NTFS_SB_SIZE + 257];
s16 rson[NTFS_SB_SIZE]; u16 dad[NTFS_SB_SIZE + 1];
} ; } ;
/* /*
* Search for the longest sequence matching current position * Initialize the match tree
*
* A binary tree is maintained to locate all previously met sequences,
* and this function has to be called for all of them.
*
* This function is heavily used, it has to be optimized carefully
*
* Returns the size of the longest match,
* zero if no match is found.
*/ */
static int ntfs_best_match(struct COMPRESS_CONTEXT *pctx, int i) static void ntfs_init_compress_tree(struct COMPRESS_CONTEXT *pctx)
{ {
s16 *prev; int i;
int node;
register long j;
long maxpos;
long startj;
long bestj;
int bufsize;
int bestnode;
register const unsigned char *p1,*p2;
p1 = pctx->inbuf; for (i = NTFS_SB_SIZE + 1; i <= NTFS_SB_SIZE + 256; i++)
node = pctx->head[p1[i] & 255]; pctx->rson[i] = NIL; /* root */
if (node >= 0) { for (i = 0; i < NTFS_SB_SIZE; i++)
/* search the best match at current position */ pctx->dad[i] = NIL; /* node */
bestnode = node;
bufsize = pctx->bufsize;
/* restrict matches to the longest allowed sequence */
maxpos = bufsize;
if ((i + pctx->mxsz) < maxpos)
maxpos = i + pctx->mxsz;
startj = i + 1 - maxpos;
bestj = startj;
/* make indexes relative to end of allowed position */
p1 = &p1[maxpos];
if (startj < 0) {
do {
/* indexes are negative */
p2 = &p1[node - i];
/* no need to compare the first byte */
j = startj;
/* the second byte cannot lead to useful compression */
if (p1[j] == p2[j]) {
j++;
if (j < 0) {
do {
} while ((p1[j] == p2[j])
&& (++j < 0));
}
/* remember the match, if better */
if (j > bestj) {
bestj = j;
bestnode = node;
}
}
/* walk in the tree in the right direction */
if ((j < 0) && (p1[j] < p2[j]))
prev = &pctx->lson[node];
else
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;
}
/* done, return the best match */
pctx->size = bestj + maxpos - i;
pctx->rel = bestnode - i;
} else {
pctx->head[p1[i] & 255] = i;
pctx->size = 0;
pctx->rel = 0;
}
return (pctx->size);
} }
/* /*
* Compress a 4096-byte block * Insert a new node into match tree for quickly locating
* * further similar strings
* Returns a header of two bytes followed by the compressed data.
* If compression is not effective, the header and an uncompressed
* block is returned.
*
* Note : two bytes may be output before output buffer overflow
* is detected, so a 4100-bytes output buffer must be reserved.
*
* Returns the size of the compressed block, including the
* header (minimal size is 2, maximum size is 4098)
* 0 if an error has been met.
*/ */
static unsigned int ntfs_compress_block(const char *inbuf, int bufsize, static void ntfs_new_node (struct COMPRESS_CONTEXT *pctx,
char *outbuf) 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
* or zero if there was a bug
*/
static unsigned int ntfs_nextmatch(struct COMPRESS_CONTEXT *pctx,
unsigned int rr, int dd)
{
unsigned int bestlen = 0;
do {
rr++;
if (pctx->match_length > 0)
pctx->match_length--;
if (!pctx->len) {
ntfs_log_error("compress bug : void run\n");
goto bug;
}
if (--pctx->len) {
if (rr >= NTFS_SB_SIZE) {
ntfs_log_error("compress bug : buffer overflow\n");
goto bug;
}
if (((rr + bestlen) < NTFS_SB_SIZE)) {
while ((unsigned int)(1 << pctx->nbt)
<= (rr - 1))
pctx->nbt++;
ntfs_new_node(pctx,rr);
if (pctx->match_length > bestlen)
bestlen = pctx->match_length;
} else
if (dd > 0) {
rr += dd;
if ((int)pctx->match_length > dd)
pctx->match_length -= dd;
else
pctx->match_length = 0;
if ((int)pctx->len < dd) {
ntfs_log_error("compress bug : run overflows\n");
goto bug;
}
pctx->len -= dd;
dd = 0;
}
}
} while (dd-- > 0);
return (rr);
bug :
return (0);
}
/*
* Compress an input block
*
* Returns the size of the compressed block (including header)
* or zero if there was an error
*/
static unsigned int ntfs_compress_block(const char *inbuf,
unsigned int size, char *outbuf)
{ {
struct COMPRESS_CONTEXT *pctx; struct COMPRESS_CONTEXT *pctx;
int i; /* current position */ char *ptag;
int j; /* end of best match from current position */ int dd;
int k; /* end of best match from next position */ unsigned int rr;
int offs; /* offset to best match */ unsigned int last_match_length;
int n; unsigned int q;
int bp; /* bits to store offset */
int mxoff; /* max match offset : 1 << bp */
int mxsz2;
unsigned int xout; unsigned int xout;
unsigned int q; /* aggregated offset and size */ unsigned int ntag;
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;
pctx->bufsize = bufsize; ntfs_init_compress_tree(pctx);
xout = 2; xout = 2;
n = 0; ntag = 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++];
while ((i < bufsize) && (xout < (NTFS_SB_SIZE + 2))) { *ptag = 0;
/* adjust the longest match we can output */ rr = 0;
while (mxoff < i) { pctx->nbt = 4;
bp++; pctx->len = size;
mxoff <<= 1; pctx->match_length = 0;
pctx->mxsz = (pctx->mxsz + 2) >> 1; ntfs_new_node(pctx,0);
} do {
/* search the best match at current position */ if (pctx->match_length > pctx->len)
if (done < i) pctx->match_length = pctx->len;
do { if (pctx->match_length < THRESHOLD) {
ntfs_best_match(pctx,++done); pctx->match_length = 1;
} while (done < i); if (ntag >= 8) {
j = i + pctx->size; ntag = 0;
if ((j - i) > pctx->mxsz) ptag = &outbuf[xout++];
j = i + pctx->mxsz; *ptag = 0;
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 {
outbuf[xout++] = inbuf[i]; while ((unsigned int)(1 << pctx->nbt)
i++; <= (rr - 1))
pctx->nbt++;
q = (pctx->match_position << (16 - pctx->nbt))
+ pctx->match_length - THRESHOLD;
if (ntag >= 8) {
ntag = 0;
ptag = &outbuf[xout++];
*ptag = 0;
}
*ptag |= 1 << ntag++;
outbuf[xout++] = q & 255;
outbuf[xout++] = (q >> 8) & 255;
} }
/* store the tag if fully used */ last_match_length = pctx->match_length;
if (!--ntag) { dd = last_match_length;
*ptag = tag; if (dd-- > 0) {
ntag = 8; rr = ntfs_nextmatch(pctx,rr,dd);
ptag = &outbuf[xout++]; if (!rr)
tag = 0; goto bug;
} }
} /*
/* store the last tag, if partially used */ * stop if input is exhausted or output has exceeded
if (ntag == 8) * the maximum size. Two extra bytes have to be
xout--; * reserved in output buffer, as 3 bytes may be
else * output in a loop.
*ptag = tag; */
/* uncompressed must be full size, accept if better */ } while ((pctx->len > 0)
if ((i >= bufsize) && (xout < (NTFS_SB_SIZE + 2))) { && (rr < size) && (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,bufsize); memcpy(&outbuf[2],inbuf,size);
if (bufsize < NTFS_SB_SIZE) if (size < NTFS_SB_SIZE)
memset(&outbuf[bufsize+2], 0, memset(&outbuf[size+2],0,NTFS_SB_SIZE - size);
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;
@ -299,7 +343,9 @@ static unsigned int ntfs_compress_block(const char *inbuf, int bufsize,
xout = 0; xout = 0;
errno = ENOMEM; errno = ENOMEM;
} }
return (xout); return (xout); /* 0 for an error, > size if cannot compress */
bug :
return (0);
} }
/** /**
@ -501,7 +547,7 @@ return_overflow:
* code. Might be a bit confusing to debug but there really should never be * code. Might be a bit confusing to debug but there really should never be
* errors coming from here. * errors coming from here.
*/ */
static BOOL ntfs_is_cb_compressed(ntfs_attr *na, runlist_element *rl, static BOOL ntfs_is_cb_compressed(ntfs_attr *na, runlist_element *rl,
VCN cb_start_vcn, int cb_clusters) VCN cb_start_vcn, int cb_clusters)
{ {
/* /*
@ -621,12 +667,12 @@ s64 ntfs_compressed_attr_pread(ntfs_attr *na, s64 pos, s64 count, void *b)
cb_size = na->compression_block_size; cb_size = na->compression_block_size;
cb_size_mask = cb_size - 1UL; cb_size_mask = cb_size - 1UL;
cb_clusters = na->compression_block_clusters; cb_clusters = na->compression_block_clusters;
/* Need a temporary buffer for each loaded compression block. */ /* Need a temporary buffer for each loaded compression block. */
cb = (u8*)ntfs_malloc(cb_size); cb = (u8*)ntfs_malloc(cb_size);
if (!cb) if (!cb)
return -1; return -1;
/* Need a temporary buffer for each uncompressed block. */ /* Need a temporary buffer for each uncompressed block. */
dest = (u8*)ntfs_malloc(cb_size); dest = (u8*)ntfs_malloc(cb_size);
if (!dest) { if (!dest) {
@ -1466,12 +1512,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 s32 ntfs_flush(ntfs_attr *na, runlist_element *rl, s64 offs, static int 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)
{ {
s32 rounded; int rounded;
s32 written; int written;
int clsz; int clsz;
if (compress) { if (compress) {
@ -1609,7 +1655,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 = (s32)compressed_part << vol->cluster_size_bits; compsz = 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) {

View File

@ -226,9 +226,6 @@
/* 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
@ -312,13 +309,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 2012.1.15" #define PACKAGE_STRING "ntfs-3g 2011.4.12"
/* 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 "2012.1.15" #define PACKAGE_VERSION "2011.4.12"
/* POSIX ACL support */ /* POSIX ACL support */
#undef POSIXACLS #undef POSIXACLS
@ -348,7 +345,7 @@
#endif #endif
/* Version number of package */ /* Version number of package */
#define VERSION "2012.1.15" #define VERSION "2011.4.12"
/* Define to 1 if this is a Windows OS */ /* Define to 1 if this is a Windows OS */
#undef WINDOWS #undef WINDOWS
@ -378,9 +375,6 @@
/* 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

View File

@ -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 = 1; \ int ___i; \
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)[___i]; \ ___i = ((int*)NULL)[1]; \
} }
#endif /* defined _NTFS_DEBUG_H */ #endif /* defined _NTFS_DEBUG_H */

View File

@ -58,9 +58,6 @@
#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
@ -559,36 +556,6 @@ 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,
@ -738,28 +705,6 @@ 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, &sect_size)) {
ntfs_log_debug("DIOCGSECTORSIZE sector size = %d bytes\n",
(int) sect_size);
return sect_size;
}
}
#elif defined(DKIOCGETBLOCKSIZE)
{
/* Mac OS X */
uint32_t sect_size = 0;
if (!dev->d_ops->ioctl(dev, DKIOCGETBLOCKSIZE, &sect_size)) {
ntfs_log_debug("DKIOCGETBLOCKSIZE sector size = %d bytes\n",
(int) sect_size);
return sect_size;
}
}
#else #else
errno = EOPNOTSUPP; errno = EOPNOTSUPP;
#endif #endif

View File

@ -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; u32 index_block_size, index_vcn_size;
u8 index_vcn_size_bits; u8 index_vcn_size_bits;
ntfs_log_trace("Entering\n"); ntfs_log_trace("Entering\n");
@ -378,9 +378,11 @@ 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_bits = NTFS_BLOCK_SIZE_BITS; index_vcn_size = vol->sector_size;
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. */
@ -1037,7 +1039,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; u32 index_block_size, index_vcn_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");
@ -1129,9 +1131,11 @@ 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_bits = NTFS_BLOCK_SIZE_BITS; index_vcn_size = vol->sector_size;
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? */
@ -1513,7 +1517,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 >>
NTFS_BLOCK_SIZE_BITS; ni->vol->sector_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);
@ -2504,24 +2508,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[3*MAX_DOS_NAME_LENGTH + 1]; char newname[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];
/* copy the string to insert a null char, and truncate */ vol = ni->vol;
if (size > 3*MAX_DOS_NAME_LENGTH) fnum = ni->mft_no;
size = 3*MAX_DOS_NAME_LENGTH; /* convert the string to the NTFS wide chars */
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);

View File

@ -139,6 +139,7 @@ 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;
@ -199,6 +200,7 @@ 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);

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -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 to a multiple then the INDEX_ENTRY is padded with zeros
of 8 with zeros which are not counted in to multiply of 8 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
a multiple of 8 and the padding is counted in multiply 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;

View File

@ -48,7 +48,7 @@
/* /*
* Plenty possibilities for big optimizations all over in the cluster * Plenty possibilities for big optimizations all over in the cluster
* allocation, however at the moment the dominant bottleneck (~ 90%) is * allocation, however at the moment the dominant bottleneck (~ 90%) is
* the update of the mapping pairs which converges to the cubic Faulhaber's * the update of the mapping pairs which converges to the cubic Faulhaber's
* formula as the function of the number of extents (fragments, runs). * formula as the function of the number of extents (fragments, runs).
*/ */
@ -74,7 +74,7 @@ static void ntfs_cluster_set_zone_pos(LCN start, LCN end, LCN *pos, LCN tc)
static void ntfs_cluster_update_zone_pos(ntfs_volume *vol, u8 zone, LCN tc) static void ntfs_cluster_update_zone_pos(ntfs_volume *vol, u8 zone, LCN tc)
{ {
ntfs_log_trace("tc = %lld, zone = %d\n", (long long)tc, zone); ntfs_log_trace("tc = %lld, zone = %d\n", (long long)tc, zone);
if (zone == ZONE_MFT) if (zone == ZONE_MFT)
ntfs_cluster_set_zone_pos(vol->mft_lcn, vol->mft_zone_end, ntfs_cluster_set_zone_pos(vol->mft_lcn, vol->mft_zone_end,
&vol->mft_zone_pos, tc); &vol->mft_zone_pos, tc);
@ -82,7 +82,7 @@ static void ntfs_cluster_update_zone_pos(ntfs_volume *vol, u8 zone, LCN tc)
ntfs_cluster_set_zone_pos(vol->mft_zone_end, vol->nr_clusters, ntfs_cluster_set_zone_pos(vol->mft_zone_end, vol->nr_clusters,
&vol->data1_zone_pos, tc); &vol->data1_zone_pos, tc);
else /* zone == ZONE_DATA2 */ else /* zone == ZONE_DATA2 */
ntfs_cluster_set_zone_pos(0, vol->mft_zone_start, ntfs_cluster_set_zone_pos(0, vol->mft_zone_start,
&vol->data2_zone_pos, tc); &vol->data2_zone_pos, tc);
} }
@ -112,15 +112,15 @@ static void update_full_status(ntfs_volume *vol, LCN lcn)
} }
} }
} }
static s64 max_empty_bit_range(unsigned char *buf, int size) static s64 max_empty_bit_range(unsigned char *buf, int size)
{ {
int i, j, run = 0; int i, j, run = 0;
int max_range = 0; int max_range = 0;
s64 start_pos = -1; s64 start_pos = -1;
ntfs_log_trace("Entering\n"); ntfs_log_trace("Entering\n");
i = 0; i = 0;
while (i < size) { while (i < size) {
switch (*buf) { switch (*buf) {
@ -144,42 +144,42 @@ static s64 max_empty_bit_range(unsigned char *buf, int size)
break; break;
default : default :
for (j = 0; j < 8; j++) { for (j = 0; j < 8; j++) {
int bit = *buf & (1 << j); int bit = *buf & (1 << j);
if (bit) { if (bit) {
if (run > max_range) { if (run > max_range) {
max_range = run; max_range = run;
start_pos = (s64)i * 8 + (j - run); start_pos = (s64)i * 8 + (j - run);
} }
run = 0; run = 0;
} else } else
run++; run++;
} }
i++; i++;
buf++; buf++;
} }
} }
if (run > max_range) if (run > max_range)
start_pos = (s64)i * 8 - run; start_pos = (s64)i * 8 - run;
return start_pos; return start_pos;
} }
static int bitmap_writeback(ntfs_volume *vol, s64 pos, s64 size, void *b, static int bitmap_writeback(ntfs_volume *vol, s64 pos, s64 size, void *b,
u8 *writeback) u8 *writeback)
{ {
s64 written; s64 written;
ntfs_log_trace("Entering\n"); ntfs_log_trace("Entering\n");
if (!*writeback) if (!*writeback)
return 0; return 0;
*writeback = 0; *writeback = 0;
written = ntfs_attr_pwrite(vol->lcnbmp_na, pos, size, b); written = ntfs_attr_pwrite(vol->lcnbmp_na, pos, size, b);
if (written != size) { if (written != size) {
if (!written) if (!written)
@ -220,16 +220,16 @@ static int bitmap_writeback(ntfs_volume *vol, s64 pos, s64 size, void *b,
* expanded to cover the start of the volume in order to reserve space for the * expanded to cover the start of the volume in order to reserve space for the
* mft bitmap attribute. * mft bitmap attribute.
* *
* The complexity stems from the need of implementing the mft vs data zoned * The complexity stems from the need of implementing the mft vs data zoned
* approach and from the fact that we have access to the lcn bitmap via up to * approach and from the fact that we have access to the lcn bitmap via up to
* NTFS_LCNALLOC_BSIZE bytes at a time, so we need to cope with crossing over * NTFS_LCNALLOC_BSIZE bytes at a time, so we need to cope with crossing over
* boundaries of two buffers. Further, the fact that the allocator allows for * boundaries of two buffers. Further, the fact that the allocator allows for
* caller supplied hints as to the location of where allocation should begin * caller supplied hints as to the location of where allocation should begin
* and the fact that the allocator keeps track of where in the data zones the * and the fact that the allocator keeps track of where in the data zones the
* next natural allocation should occur, contribute to the complexity of the * next natural allocation should occur, contribute to the complexity of the
* function. But it should all be worthwhile, because this allocator: * function. But it should all be worthwhile, because this allocator:
* 1) implements MFT zone reservation * 1) implements MFT zone reservation
* 2) causes reduction in fragmentation. * 2) causes reduction in fragmentation.
* The code is not optimized for speed. * The code is not optimized for speed.
*/ */
runlist *ntfs_cluster_alloc(ntfs_volume *vol, VCN start_vcn, s64 count, runlist *ntfs_cluster_alloc(ntfs_volume *vol, VCN start_vcn, s64 count,
@ -251,12 +251,12 @@ runlist *ntfs_cluster_alloc(ntfs_volume *vol, VCN start_vcn, s64 count,
ntfs_log_enter("Entering with count = 0x%llx, start_lcn = 0x%llx, " ntfs_log_enter("Entering with count = 0x%llx, start_lcn = 0x%llx, "
"zone = %s_ZONE.\n", (long long)count, (long long) "zone = %s_ZONE.\n", (long long)count, (long long)
start_lcn, zone == MFT_ZONE ? "MFT" : "DATA"); start_lcn, zone == MFT_ZONE ? "MFT" : "DATA");
if (!vol || count < 0 || start_lcn < -1 || !vol->lcnbmp_na || if (!vol || count < 0 || start_lcn < -1 || !vol->lcnbmp_na ||
(s8)zone < FIRST_ZONE || zone > LAST_ZONE) { (s8)zone < FIRST_ZONE || zone > LAST_ZONE) {
errno = EINVAL; errno = EINVAL;
ntfs_log_perror("%s: vcn: %lld, count: %lld, lcn: %lld", ntfs_log_perror("%s: vcn: %lld, count: %lld, lcn: %lld",
__FUNCTION__, (long long)start_vcn, __FUNCTION__, (long long)start_vcn,
(long long)count, (long long)start_lcn); (long long)count, (long long)start_lcn);
goto out; goto out;
} }
@ -281,7 +281,7 @@ runlist *ntfs_cluster_alloc(ntfs_volume *vol, VCN start_vcn, s64 count,
*/ */
has_guess = 1; has_guess = 1;
zone_start = start_lcn; zone_start = start_lcn;
if (zone_start < 0) { if (zone_start < 0) {
if (zone == DATA_ZONE) if (zone == DATA_ZONE)
zone_start = vol->data1_zone_pos; zone_start = vol->data1_zone_pos;
@ -289,13 +289,13 @@ runlist *ntfs_cluster_alloc(ntfs_volume *vol, VCN start_vcn, s64 count,
zone_start = vol->mft_zone_pos; zone_start = vol->mft_zone_pos;
has_guess = 0; has_guess = 0;
} }
used_zone_pos = has_guess ? 0 : 1; used_zone_pos = has_guess ? 0 : 1;
if (!zone_start || zone_start == vol->mft_zone_start || if (!zone_start || zone_start == vol->mft_zone_start ||
zone_start == vol->mft_zone_end) zone_start == vol->mft_zone_end)
pass = 2; pass = 2;
if (zone_start < vol->mft_zone_start) { if (zone_start < vol->mft_zone_start) {
zone_end = vol->mft_zone_start; zone_end = vol->mft_zone_start;
search_zone = ZONE_DATA2; search_zone = ZONE_DATA2;
@ -306,7 +306,7 @@ runlist *ntfs_cluster_alloc(ntfs_volume *vol, VCN start_vcn, s64 count,
zone_end = vol->nr_clusters; zone_end = vol->nr_clusters;
search_zone = ZONE_DATA1; search_zone = ZONE_DATA1;
} }
bmp_pos = zone_start; bmp_pos = zone_start;
/* Loop until all clusters are allocated. */ /* Loop until all clusters are allocated. */
@ -317,7 +317,7 @@ runlist *ntfs_cluster_alloc(ntfs_volume *vol, VCN start_vcn, s64 count,
if (search_zone & vol->full_zones) if (search_zone & vol->full_zones)
goto zone_pass_done; goto zone_pass_done;
last_read_pos = bmp_pos >> 3; last_read_pos = bmp_pos >> 3;
br = ntfs_attr_pread(vol->lcnbmp_na, last_read_pos, br = ntfs_attr_pread(vol->lcnbmp_na, last_read_pos,
NTFS_LCNALLOC_BSIZE, buf); NTFS_LCNALLOC_BSIZE, buf);
if (br <= 0) { if (br <= 0) {
if (!br) if (!br)
@ -334,7 +334,7 @@ runlist *ntfs_cluster_alloc(ntfs_volume *vol, VCN start_vcn, s64 count,
lcn = bmp_pos & 7; lcn = bmp_pos & 7;
bmp_pos &= ~7; bmp_pos &= ~7;
writeback = 0; writeback = 0;
while (lcn < buf_size) { while (lcn < buf_size) {
byte = buf + (lcn >> 3); byte = buf + (lcn >> 3);
bit = 1 << (lcn & 7); bit = 1 << (lcn & 7);
@ -352,7 +352,7 @@ runlist *ntfs_cluster_alloc(ntfs_volume *vol, VCN start_vcn, s64 count,
} }
/* First free bit is at lcn + bmp_pos. */ /* First free bit is at lcn + bmp_pos. */
/* Reallocate memory if necessary. */ /* Reallocate memory if necessary. */
if ((rlpos + 2) * (int)sizeof(runlist) >= rlsize) { if ((rlpos + 2) * (int)sizeof(runlist) >= rlsize) {
rlsize += 4096; rlsize += 4096;
@ -364,17 +364,17 @@ runlist *ntfs_cluster_alloc(ntfs_volume *vol, VCN start_vcn, s64 count,
} }
rl = trl; rl = trl;
} }
/* Allocate the bitmap bit. */ /* Allocate the bitmap bit. */
*byte |= bit; *byte |= bit;
writeback = 1; writeback = 1;
if (vol->free_clusters <= 0) if (vol->free_clusters <= 0)
ntfs_log_error("Non-positive free clusters " ntfs_log_error("Non-positive free clusters "
"(%lld)!\n", "(%lld)!\n",
(long long)vol->free_clusters); (long long)vol->free_clusters);
else else
vol->free_clusters--; vol->free_clusters--;
/* /*
* Coalesce with previous run if adjacent LCNs. * Coalesce with previous run if adjacent LCNs.
* Otherwise, append a new run. * Otherwise, append a new run.
@ -382,9 +382,9 @@ runlist *ntfs_cluster_alloc(ntfs_volume *vol, VCN start_vcn, s64 count,
if (prev_lcn == lcn + bmp_pos - prev_run_len && rlpos) { if (prev_lcn == lcn + bmp_pos - prev_run_len && rlpos) {
ntfs_log_debug("Cluster coalesce: prev_lcn: " ntfs_log_debug("Cluster coalesce: prev_lcn: "
"%lld lcn: %lld bmp_pos: %lld " "%lld lcn: %lld bmp_pos: %lld "
"prev_run_len: %lld\n", "prev_run_len: %lld\n",
(long long)prev_lcn, (long long)prev_lcn,
(long long)lcn, (long long)bmp_pos, (long long)lcn, (long long)bmp_pos,
(long long)prev_run_len); (long long)prev_run_len);
rl[rlpos - 1].length = ++prev_run_len; rl[rlpos - 1].length = ++prev_run_len;
} else { } else {
@ -393,54 +393,54 @@ runlist *ntfs_cluster_alloc(ntfs_volume *vol, VCN start_vcn, s64 count,
prev_run_len; prev_run_len;
else { else {
rl[rlpos].vcn = start_vcn; rl[rlpos].vcn = start_vcn;
ntfs_log_debug("Start_vcn: %lld\n", ntfs_log_debug("Start_vcn: %lld\n",
(long long)start_vcn); (long long)start_vcn);
} }
rl[rlpos].lcn = prev_lcn = lcn + bmp_pos; rl[rlpos].lcn = prev_lcn = lcn + bmp_pos;
rl[rlpos].length = prev_run_len = 1; rl[rlpos].length = prev_run_len = 1;
rlpos++; rlpos++;
} }
ntfs_log_debug("RUN: %-16lld %-16lld %-16lld\n", ntfs_log_debug("RUN: %-16lld %-16lld %-16lld\n",
(long long)rl[rlpos - 1].vcn, (long long)rl[rlpos - 1].vcn,
(long long)rl[rlpos - 1].lcn, (long long)rl[rlpos - 1].lcn,
(long long)rl[rlpos - 1].length); (long long)rl[rlpos - 1].length);
/* Done? */ /* Done? */
if (!--clusters) { if (!--clusters) {
if (used_zone_pos) if (used_zone_pos)
ntfs_cluster_update_zone_pos(vol, ntfs_cluster_update_zone_pos(vol,
search_zone, lcn + bmp_pos + 1 + search_zone, lcn + bmp_pos + 1 +
NTFS_LCNALLOC_SKIP); NTFS_LCNALLOC_SKIP);
goto done_ret; goto done_ret;
} }
lcn++; lcn++;
} }
if (bitmap_writeback(vol, last_read_pos, br, buf, &writeback)) { if (bitmap_writeback(vol, last_read_pos, br, buf, &writeback)) {
err = errno; err = errno;
goto err_ret; goto err_ret;
} }
if (!used_zone_pos) { if (!used_zone_pos) {
used_zone_pos = 1; used_zone_pos = 1;
if (search_zone == ZONE_MFT) if (search_zone == ZONE_MFT)
zone_start = vol->mft_zone_pos; zone_start = vol->mft_zone_pos;
else if (search_zone == ZONE_DATA1) else if (search_zone == ZONE_DATA1)
zone_start = vol->data1_zone_pos; zone_start = vol->data1_zone_pos;
else else
zone_start = vol->data2_zone_pos; zone_start = vol->data2_zone_pos;
if (!zone_start || zone_start == vol->mft_zone_start || if (!zone_start || zone_start == vol->mft_zone_start ||
zone_start == vol->mft_zone_end) zone_start == vol->mft_zone_end)
pass = 2; pass = 2;
bmp_pos = zone_start; bmp_pos = zone_start;
} else } else
bmp_pos += buf_size; bmp_pos += buf_size;
if (bmp_pos < zone_end) if (bmp_pos < zone_end)
continue; continue;
@ -449,22 +449,22 @@ zone_pass_done:
if (pass == 1) { if (pass == 1) {
pass = 2; pass = 2;
zone_end = zone_start; zone_end = zone_start;
if (search_zone == ZONE_MFT) if (search_zone == ZONE_MFT)
zone_start = vol->mft_zone_start; zone_start = vol->mft_zone_start;
else if (search_zone == ZONE_DATA1) else if (search_zone == ZONE_DATA1)
zone_start = vol->mft_zone_end; zone_start = vol->mft_zone_end;
else else
zone_start = 0; zone_start = 0;
/* Sanity check. */ /* Sanity check. */
if (zone_end < zone_start) if (zone_end < zone_start)
zone_end = zone_start; zone_end = zone_start;
bmp_pos = zone_start; bmp_pos = zone_start;
continue; continue;
} }
/* pass == 2 */ /* pass == 2 */
done_zones_check: done_zones_check:
done_zones |= search_zone; done_zones |= search_zone;
@ -473,14 +473,14 @@ done_zones_check:
ntfs_log_trace("Switching zone.\n"); ntfs_log_trace("Switching zone.\n");
pass = 1; pass = 1;
if (rlpos) { if (rlpos) {
LCN tc = rl[rlpos - 1].lcn + LCN tc = rl[rlpos - 1].lcn +
rl[rlpos - 1].length + NTFS_LCNALLOC_SKIP; rl[rlpos - 1].length + NTFS_LCNALLOC_SKIP;
if (used_zone_pos) if (used_zone_pos)
ntfs_cluster_update_zone_pos(vol, ntfs_cluster_update_zone_pos(vol,
search_zone, tc); search_zone, tc);
} }
switch (search_zone) { switch (search_zone) {
case ZONE_MFT: case ZONE_MFT:
ntfs_log_trace("Zone switch: mft -> data1\n"); ntfs_log_trace("Zone switch: mft -> data1\n");
@ -511,17 +511,17 @@ switch_to_data1_zone: search_zone = ZONE_DATA1;
pass = 2; pass = 2;
break; break;
} }
bmp_pos = zone_start; bmp_pos = zone_start;
if (zone_start == zone_end) { if (zone_start == zone_end) {
ntfs_log_trace("Empty zone, skipped.\n"); ntfs_log_trace("Empty zone, skipped.\n");
goto done_zones_check; goto done_zones_check;
} }
continue; continue;
} }
ntfs_log_trace("All zones are finished, no space on device.\n"); ntfs_log_trace("All zones are finished, no space on device.\n");
err = ENOSPC; err = ENOSPC;
goto err_ret; goto err_ret;
@ -543,7 +543,7 @@ done_err_ret:
ntfs_log_perror("Failed to allocate clusters"); ntfs_log_perror("Failed to allocate clusters");
rl = NULL; rl = NULL;
} }
out: out:
ntfs_log_leave("\n"); ntfs_log_leave("\n");
return rl; return rl;
@ -585,26 +585,26 @@ int ntfs_cluster_free_from_rl(ntfs_volume *vol, runlist *rl)
ntfs_log_trace("Dealloc lcn 0x%llx, len 0x%llx.\n", ntfs_log_trace("Dealloc lcn 0x%llx, len 0x%llx.\n",
(long long)rl->lcn, (long long)rl->length); (long long)rl->lcn, (long long)rl->length);
if (rl->lcn >= 0) { if (rl->lcn >= 0) {
update_full_status(vol,rl->lcn); update_full_status(vol,rl->lcn);
if (ntfs_bitmap_clear_run(vol->lcnbmp_na, rl->lcn, if (ntfs_bitmap_clear_run(vol->lcnbmp_na, rl->lcn,
rl->length)) { rl->length)) {
ntfs_log_perror("Cluster deallocation failed " ntfs_log_perror("Cluster deallocation failed "
"(%lld, %lld)", "(%lld, %lld)",
(long long)rl->lcn, (long long)rl->lcn,
(long long)rl->length); (long long)rl->length);
goto out; goto out;
} }
nr_freed += rl->length ; nr_freed += rl->length ;
} }
} }
ret = 0; ret = 0;
out: out:
vol->free_clusters += nr_freed; vol->free_clusters += nr_freed;
if (vol->free_clusters > vol->nr_clusters) if (vol->free_clusters > vol->nr_clusters)
ntfs_log_error("Too many free clusters (%lld > %lld)!", ntfs_log_error("Too many free clusters (%lld > %lld)!",
(long long)vol->free_clusters, (long long)vol->free_clusters,
(long long)vol->nr_clusters); (long long)vol->nr_clusters);
return ret; return ret;
} }
@ -623,24 +623,24 @@ int ntfs_cluster_free_basic(ntfs_volume *vol, s64 lcn, s64 count)
ntfs_log_trace("Dealloc lcn 0x%llx, len 0x%llx.\n", ntfs_log_trace("Dealloc lcn 0x%llx, len 0x%llx.\n",
(long long)lcn, (long long)count); (long long)lcn, (long long)count);
if (lcn >= 0) { if (lcn >= 0) {
update_full_status(vol,lcn); update_full_status(vol,lcn);
if (ntfs_bitmap_clear_run(vol->lcnbmp_na, lcn, if (ntfs_bitmap_clear_run(vol->lcnbmp_na, lcn,
count)) { count)) {
ntfs_log_perror("Cluster deallocation failed " ntfs_log_perror("Cluster deallocation failed "
"(%lld, %lld)", "(%lld, %lld)",
(long long)lcn, (long long)lcn,
(long long)count); (long long)count);
goto out; goto out;
} }
nr_freed += count; nr_freed += count;
} }
ret = 0; ret = 0;
out: out:
vol->free_clusters += nr_freed; vol->free_clusters += nr_freed;
if (vol->free_clusters > vol->nr_clusters) if (vol->free_clusters > vol->nr_clusters)
ntfs_log_error("Too many free clusters (%lld > %lld)!", ntfs_log_error("Too many free clusters (%lld > %lld)!",
(long long)vol->free_clusters, (long long)vol->free_clusters,
(long long)vol->nr_clusters); (long long)vol->nr_clusters);
return ret; return ret;
} }
@ -673,7 +673,7 @@ int ntfs_cluster_free(ntfs_volume *vol, ntfs_attr *na, VCN start_vcn, s64 count)
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }
ntfs_log_enter("Entering for inode 0x%llx, attr 0x%x, count 0x%llx, " ntfs_log_enter("Entering for inode 0x%llx, attr 0x%x, count 0x%llx, "
"vcn 0x%llx.\n", (unsigned long long)na->ni->mft_no, "vcn 0x%llx.\n", (unsigned long long)na->ni->mft_no,
na->type, (long long)count, (long long)start_vcn); na->type, (long long)count, (long long)start_vcn);
@ -687,7 +687,7 @@ int ntfs_cluster_free(ntfs_volume *vol, ntfs_attr *na, VCN start_vcn, s64 count)
if (rl->lcn < 0 && rl->lcn != LCN_HOLE) { if (rl->lcn < 0 && rl->lcn != LCN_HOLE) {
errno = EIO; errno = EIO;
ntfs_log_perror("%s: Unexpected lcn (%lld)", __FUNCTION__, ntfs_log_perror("%s: Unexpected lcn (%lld)", __FUNCTION__,
(long long)rl->lcn); (long long)rl->lcn);
goto leave; goto leave;
} }
@ -707,7 +707,7 @@ int ntfs_cluster_free(ntfs_volume *vol, ntfs_attr *na, VCN start_vcn, s64 count)
to_free)) to_free))
goto leave; goto leave;
nr_freed = to_free; nr_freed = to_free;
} }
/* Go to the next run and adjust the number of clusters left to free. */ /* Go to the next run and adjust the number of clusters left to free. */
++rl; ++rl;
@ -724,7 +724,7 @@ int ntfs_cluster_free(ntfs_volume *vol, ntfs_attr *na, VCN start_vcn, s64 count)
if (rl->lcn < 0 && rl->lcn != LCN_HOLE) { if (rl->lcn < 0 && rl->lcn != LCN_HOLE) {
// FIXME: Eeek! We need rollback! (AIA) // FIXME: Eeek! We need rollback! (AIA)
errno = EIO; errno = EIO;
ntfs_log_perror("%s: Invalid lcn (%lli)", ntfs_log_perror("%s: Invalid lcn (%lli)",
__FUNCTION__, (long long)rl->lcn); __FUNCTION__, (long long)rl->lcn);
goto out; goto out;
} }
@ -760,12 +760,12 @@ int ntfs_cluster_free(ntfs_volume *vol, ntfs_attr *na, VCN start_vcn, s64 count)
ret = nr_freed; ret = nr_freed;
out: out:
vol->free_clusters += nr_freed ; vol->free_clusters += nr_freed ;
if (vol->free_clusters > vol->nr_clusters) if (vol->free_clusters > vol->nr_clusters)
ntfs_log_error("Too many free clusters (%lld > %lld)!", ntfs_log_error("Too many free clusters (%lld > %lld)!",
(long long)vol->free_clusters, (long long)vol->free_clusters,
(long long)vol->nr_clusters); (long long)vol->nr_clusters);
leave: leave:
ntfs_log_leave("\n"); ntfs_log_leave("\n");
return ret; return ret;
} }

View File

@ -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, err; int log_page_size, log_page_mask, err;
BOOL logfile_is_empty = TRUE; BOOL logfile_is_empty = TRUE;
u8 log_page_bits; u8 log_page_bits;
@ -481,6 +481,7 @@ 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.
@ -702,7 +703,7 @@ int ntfs_empty_logfile(ntfs_attr *na)
char buf[NTFS_BUF_SIZE]; char buf[NTFS_BUF_SIZE];
ntfs_log_trace("Entering.\n"); ntfs_log_trace("Entering.\n");
if (NVolLogFileEmpty(na->ni->vol)) if (NVolLogFileEmpty(na->ni->vol))
return 0; return 0;
@ -716,7 +717,7 @@ int ntfs_empty_logfile(ntfs_attr *na)
pos = 0; pos = 0;
while ((count = na->data_size - pos) > 0) { while ((count = na->data_size - pos) > 0) {
if (count > NTFS_BUF_SIZE) if (count > NTFS_BUF_SIZE)
count = NTFS_BUF_SIZE; count = NTFS_BUF_SIZE;
@ -732,6 +733,6 @@ int ntfs_empty_logfile(ntfs_attr *na)
} }
NVolSetLogFileEmpty(na->ni->vol); NVolSetLogFileEmpty(na->ni->vol);
return 0; return 0;
} }

View File

@ -216,10 +216,8 @@ int ntfs_mft_record_check(const ntfs_volume *vol, const MFT_REF mref,
int ret = -1; int ret = -1;
if (!ntfs_is_file_record(m->magic)) { if (!ntfs_is_file_record(m->magic)) {
if (!NVolNoFixupWarn(vol)) ntfs_log_error("Record %llu has no FILE magic (0x%x)\n",
ntfs_log_error("Record %llu has no FILE magic (0x%x)\n", (unsigned long long)MREF(mref), *(le32 *)m);
(unsigned long long)MREF(mref),
(int)le32_to_cpu(*(le32*)m));
goto err_out; goto err_out;
} }
@ -1192,7 +1190,7 @@ undo_alloc:
static int ntfs_mft_record_init(ntfs_volume *vol, s64 size) static int ntfs_mft_record_init(ntfs_volume *vol, s64 size)
{ {
int ret = -1; int ret = -1;
ntfs_attr *mft_na; ntfs_attr *mft_na, *mftbmp_na;
s64 old_data_initialized, old_data_size; s64 old_data_initialized, old_data_size;
ntfs_attr_search_ctx *ctx; ntfs_attr_search_ctx *ctx;
@ -1201,6 +1199,7 @@ static int ntfs_mft_record_init(ntfs_volume *vol, s64 size)
/* NOTE: Caller must sanity check vol, vol->mft_na and vol->mftbmp_na */ /* NOTE: Caller must sanity check vol, vol->mft_na and vol->mftbmp_na */
mft_na = vol->mft_na; mft_na = vol->mft_na;
mftbmp_na = vol->mftbmp_na;
/* /*
* The mft record is outside the initialized data. Extend the mft data * The mft record is outside the initialized data. Extend the mft data
@ -1296,13 +1295,14 @@ undo_data_init:
static int ntfs_mft_rec_init(ntfs_volume *vol, s64 size) static int ntfs_mft_rec_init(ntfs_volume *vol, s64 size)
{ {
int ret = -1; int ret = -1;
ntfs_attr *mft_na; ntfs_attr *mft_na, *mftbmp_na;
s64 old_data_initialized, old_data_size; s64 old_data_initialized, old_data_size;
ntfs_attr_search_ctx *ctx; ntfs_attr_search_ctx *ctx;
ntfs_log_enter("Entering\n"); ntfs_log_enter("Entering\n");
mft_na = vol->mft_na; mft_na = vol->mft_na;
mftbmp_na = vol->mftbmp_na;
if (size > mft_na->allocated_size || size > mft_na->initialized_size) { if (size > mft_na->allocated_size || size > mft_na->initialized_size) {
errno = EIO; errno = EIO;

View File

@ -47,8 +47,7 @@
* EIO Multi sector transfer error was detected. Magic of the NTFS * EIO Multi sector transfer error was detected. Magic of the NTFS
* record in @b will have been set to "BAAD". * record in @b will have been set to "BAAD".
*/ */
int ntfs_mst_post_read_fixup_warn(NTFS_RECORD *b, const u32 size, int ntfs_mst_post_read_fixup(NTFS_RECORD *b, const u32 size)
BOOL warn)
{ {
u16 usa_ofs, usa_count, usn; u16 usa_ofs, usa_count, usn;
u16 *usa_pos, *data_pos; u16 *usa_pos, *data_pos;
@ -64,14 +63,9 @@ int ntfs_mst_post_read_fixup_warn(NTFS_RECORD *b, const u32 size,
(u32)(usa_ofs + (usa_count * 2)) > size || (u32)(usa_ofs + (usa_count * 2)) > size ||
(size >> NTFS_BLOCK_SIZE_BITS) != usa_count) { (size >> NTFS_BLOCK_SIZE_BITS) != usa_count) {
errno = EINVAL; errno = EINVAL;
if (warn) { ntfs_log_perror("%s: magic: 0x%08x size: %d usa_ofs: %d "
ntfs_log_perror("%s: magic: 0x%08lx size: %ld " "usa_count: %d", __FUNCTION__, *(le32 *)b,
" usa_ofs: %d usa_count: %u", size, usa_ofs, usa_count);
__FUNCTION__,
(long)le32_to_cpu(*(le32 *)b),
(long)size, (int)usa_ofs,
(unsigned int)usa_count);
}
return -1; return -1;
} }
/* Position of usn in update sequence array. */ /* Position of usn in update sequence array. */
@ -124,16 +118,6 @@ int ntfs_mst_post_read_fixup_warn(NTFS_RECORD *b, const u32 size,
return 0; return 0;
} }
/*
* Deprotect multi sector transfer protected data
* with a warning if an error is found.
*/
int ntfs_mst_post_read_fixup(NTFS_RECORD *b, const u32 size)
{
return (ntfs_mst_post_read_fixup_warn(b,size,TRUE));
}
/** /**
* ntfs_mst_pre_write_fixup - apply multi sector transfer protection * ntfs_mst_pre_write_fixup - apply multi sector transfer protection
* @b: pointer to the data to protect * @b: pointer to the data to protect

View File

@ -25,11 +25,8 @@
#include "types.h" #include "types.h"
#include "layout.h" #include "layout.h"
#include "volume.h"
extern int ntfs_mst_post_read_fixup(NTFS_RECORD *b, const u32 size); extern int ntfs_mst_post_read_fixup(NTFS_RECORD *b, const u32 size);
extern int ntfs_mst_post_read_fixup_warn(NTFS_RECORD *b, const u32 size,
BOOL warn);
extern int ntfs_mst_pre_write_fixup(NTFS_RECORD *b, const u32 size); extern int ntfs_mst_pre_write_fixup(NTFS_RECORD *b, const u32 size);
extern void ntfs_mst_post_write_fixup(NTFS_RECORD *b); extern void ntfs_mst_post_write_fixup(NTFS_RECORD *b);

View File

@ -36,18 +36,6 @@
#include "types.h" #include "types.h"
#ifndef GEKKO
/*
* assume "struct timespec" is not defined if st_mtime is not defined
*/
#if !defined(st_mtime) & !defined(__timespec_defined)
struct timespec {
time_t tv_sec;
long tv_nsec;
} ;
#endif
#endif
/* /*
* There are four times more conversions of internal representation * There are four times more conversions of internal representation
* to ntfs representation than any other conversion, so the most * to ntfs representation than any other conversion, so the most

View File

@ -287,6 +287,7 @@ static int remove_object_id_index(ntfs_attr *na, ntfs_index_context *xo,
if (size >= (s64)sizeof(GUID)) { if (size >= (s64)sizeof(GUID)) {
memcpy(&key.object_id, memcpy(&key.object_id,
&old_attr->object_id,sizeof(GUID)); &old_attr->object_id,sizeof(GUID));
size = sizeof(GUID);
if (!ntfs_index_lookup(&key, if (!ntfs_index_lookup(&key,
sizeof(OBJECT_ID_INDEX_KEY), xo)) { sizeof(OBJECT_ID_INDEX_KEY), xo)) {
entry = (struct OBJECT_ID_INDEX*)xo->entry; entry = (struct OBJECT_ID_INDEX*)xo->entry;
@ -299,6 +300,7 @@ static int remove_object_id_index(ntfs_attr *na, ntfs_index_context *xo,
memcpy(&old_attr->domain_id, memcpy(&old_attr->domain_id,
&entry->data.domain_id, &entry->data.domain_id,
sizeof(GUID)); sizeof(GUID));
size = sizeof(OBJECT_ID_ATTR);
if (ntfs_index_rm(xo)) if (ntfs_index_rm(xo))
ret = -1; ret = -1;
} }

View File

@ -50,19 +50,6 @@ enum {
/* maximum cluster size for allowing compression for new files */ /* maximum cluster size for allowing compression for new files */
#define MAX_COMPRESSION_CLUSTER_SIZE 4096 #define MAX_COMPRESSION_CLUSTER_SIZE 4096
/*
* Use of big write buffers
*
* With small volumes, the cluster allocator may fail to allocate
* enough clusters when the volume is nearly full. At most a run
* can be allocated per bitmap chunk. So, there is a danger when the
* number of chunks (capacity/(32768*clsiz)) is less than the number
* of clusters in the biggest write buffer (131072/clsiz). Hence
* a safe minimal capacity is 4GB
*/
#define SAFE_CAPACITY_FOR_BIG_WRITES 0x100000000LL
/* /*
* Parameters for runlists * Parameters for runlists
*/ */
@ -76,11 +63,6 @@ enum {
#define XATTRMAPPINGFILE ".NTFS-3G/XattrMapping" /* default mapping file */ #define XATTRMAPPINGFILE ".NTFS-3G/XattrMapping" /* default mapping file */
/*
* Parameters for path canonicalization
*/
#define MAPPERNAMELTH 256
/* /*
* Permission checking modes for high level and low level * Permission checking modes for high level and low level

View File

@ -136,10 +136,9 @@ runlist_element *ntfs_rl_extend(ntfs_attr *na, runlist_element *rl,
if (!newrl) { if (!newrl) {
errno = ENOMEM; errno = ENOMEM;
rl = (runlist_element*)NULL; rl = (runlist_element*)NULL;
} else { } else
na->rl = newrl; na->rl = newrl;
rl = &newrl[irl]; rl = &newrl[irl];
}
} else { } else {
ntfs_log_error("Cannot extend unmapped runlist"); ntfs_log_error("Cannot extend unmapped runlist");
errno = EIO; errno = EIO;
@ -1624,7 +1623,7 @@ errno_set:
int ntfs_rl_truncate(runlist **arl, const VCN start_vcn) int ntfs_rl_truncate(runlist **arl, const VCN start_vcn)
{ {
runlist *rl; runlist *rl;
/* BOOL is_end = FALSE; */ BOOL is_end = FALSE;
if (!arl || !*arl) { if (!arl || !*arl) {
errno = EINVAL; errno = EINVAL;
@ -1667,10 +1666,8 @@ int ntfs_rl_truncate(runlist **arl, const VCN start_vcn)
*/ */
if (rl->length) { if (rl->length) {
++rl; ++rl;
/*
if (!rl->length) if (!rl->length)
is_end = TRUE; is_end = TRUE;
*/
rl->vcn = start_vcn; rl->vcn = start_vcn;
rl->length = 0; rl->length = 0;
} }
@ -1678,7 +1675,7 @@ int ntfs_rl_truncate(runlist **arl, const VCN start_vcn)
/** /**
* Reallocate memory if necessary. * Reallocate memory if necessary.
* FIXME: Below code is broken, because runlist allocations must be * FIXME: Below code is broken, because runlist allocations must be
* a multiple of 4096. The code caused crashes and corruptions. * a multiply of 4096. The code caused crashes and corruptions.
*/ */
/* /*
if (!is_end) { if (!is_end) {

View File

@ -127,8 +127,8 @@ struct SDH { /* this is an image of an $SDH index entry */
static ntfschar sii_stream[] = { const_cpu_to_le16('$'), static ntfschar sii_stream[] = { const_cpu_to_le16('$'),
const_cpu_to_le16('S'), const_cpu_to_le16('S'),
const_cpu_to_le16('I'), const_cpu_to_le16('I'),
const_cpu_to_le16('I'), const_cpu_to_le16('I'),
const_cpu_to_le16(0) }; const_cpu_to_le16(0) };
static ntfschar sdh_stream[] = { const_cpu_to_le16('$'), static ntfschar sdh_stream[] = { const_cpu_to_le16('$'),
const_cpu_to_le16('S'), const_cpu_to_le16('S'),
@ -684,7 +684,7 @@ static le32 entersecurityattr(ntfs_volume *vol,
retries = 0; retries = 0;
while (entry) { while (entry) {
next = ntfs_index_next(entry,xsii); next = ntfs_index_next(entry,xsii);
if (next) { if (next) {
psii = (struct SII*)next; psii = (struct SII*)next;
/* save last key and */ /* save last key and */
/* available position */ /* available position */
@ -1024,7 +1024,7 @@ static int update_secur_descr(ntfs_volume *vol,
* This is intended to allow graceful upgrades for files which * This is intended to allow graceful upgrades for files which
* were created in previous versions, with a security attributes * were created in previous versions, with a security attributes
* and no security id. * and no security id.
* *
* It will allocate a security id and replace the individual * It will allocate a security id and replace the individual
* security attribute by a reference to the global one * security attribute by a reference to the global one
* *
@ -1064,6 +1064,7 @@ static int upgrade_secur_desc(ntfs_volume *vol,
na = ntfs_attr_open(ni, AT_STANDARD_INFORMATION, na = ntfs_attr_open(ni, AT_STANDARD_INFORMATION,
AT_UNNAMED, 0); AT_UNNAMED, 0);
if (na) { if (na) {
res = 0;
/* expand standard information attribute to v3.x */ /* expand standard information attribute to v3.x */
res = ntfs_attr_truncate(na, res = ntfs_attr_truncate(na,
(s64)sizeof(STANDARD_INFORMATION)); (s64)sizeof(STANDARD_INFORMATION));
@ -1372,7 +1373,7 @@ static int leg_compare(const struct CACHED_PERMISSIONS_LEGACY *cached,
/* /*
* Resize permission cache table * Resize permission cache table
* do not call unless resizing is needed * do not call unless resizing is needed
* *
* If allocation fails, the cache size is not updated * If allocation fails, the cache size is not updated
* Lack of memory is not considered as an error, the cache is left * Lack of memory is not considered as an error, the cache is left
* consistent and errno is not set. * consistent and errno is not set.
@ -1468,7 +1469,7 @@ static struct CACHED_PERMISSIONS *enter_cache(struct SECURITY_CONTEXT *scx,
if (pxdesc) { if (pxdesc) {
pxsize = sizeof(struct POSIX_SECURITY) pxsize = sizeof(struct POSIX_SECURITY)
+ (pxdesc->acccnt + pxdesc->defcnt)*sizeof(struct POSIX_ACE); + (pxdesc->acccnt + pxdesc->defcnt)*sizeof(struct POSIX_ACE);
pxcached = (struct POSIX_SECURITY*)malloc(pxsize); pxcached = (struct POSIX_SECURITY*)ntfs_malloc(pxsize);
if (pxcached) { if (pxcached) {
memcpy(pxcached, pxdesc, pxsize); memcpy(pxcached, pxdesc, pxsize);
cacheentry->pxdesc = pxcached; cacheentry->pxdesc = pxcached;
@ -1499,7 +1500,7 @@ static struct CACHED_PERMISSIONS *enter_cache(struct SECURITY_CONTEXT *scx,
/* allocate block, if cache table was allocated */ /* allocate block, if cache table was allocated */
if (pcache && (index1 <= pcache->head.last)) { if (pcache && (index1 <= pcache->head.last)) {
cacheblock = (struct CACHED_PERMISSIONS*) cacheblock = (struct CACHED_PERMISSIONS*)
malloc(sizeof(struct CACHED_PERMISSIONS) ntfs_malloc(sizeof(struct CACHED_PERMISSIONS)
<< CACHE_PERMISSIONS_BITS); << CACHE_PERMISSIONS_BITS);
pcache->cachetable[index1] = cacheblock; pcache->cachetable[index1] = cacheblock;
for (i=0; i<(1 << CACHE_PERMISSIONS_BITS); i++) for (i=0; i<(1 << CACHE_PERMISSIONS_BITS); i++)
@ -1512,7 +1513,7 @@ static struct CACHED_PERMISSIONS *enter_cache(struct SECURITY_CONTEXT *scx,
if (pxdesc) { if (pxdesc) {
pxsize = sizeof(struct POSIX_SECURITY) pxsize = sizeof(struct POSIX_SECURITY)
+ (pxdesc->acccnt + pxdesc->defcnt)*sizeof(struct POSIX_ACE); + (pxdesc->acccnt + pxdesc->defcnt)*sizeof(struct POSIX_ACE);
pxcached = (struct POSIX_SECURITY*)malloc(pxsize); pxcached = (struct POSIX_SECURITY*)ntfs_malloc(pxsize);
if (pxcached) { if (pxcached) {
memcpy(pxcached, pxdesc, pxsize); memcpy(pxcached, pxdesc, pxsize);
cacheentry->pxdesc = pxcached; cacheentry->pxdesc = pxcached;
@ -2002,7 +2003,7 @@ static int ntfs_get_perm(struct SECURITY_CONTEXT *scx,
*/ */
int ntfs_get_posix_acl(struct SECURITY_CONTEXT *scx, ntfs_inode *ni, int ntfs_get_posix_acl(struct SECURITY_CONTEXT *scx, ntfs_inode *ni,
const char *name, char *value, size_t size) const char *name, char *value, size_t size)
{ {
const SECURITY_DESCRIPTOR_RELATIVE *phead; const SECURITY_DESCRIPTOR_RELATIVE *phead;
struct POSIX_SECURITY *pxdesc; struct POSIX_SECURITY *pxdesc;
@ -2012,6 +2013,7 @@ int ntfs_get_posix_acl(struct SECURITY_CONTEXT *scx, ntfs_inode *ni,
const SID *gsid; /* group of file/directory */ const SID *gsid; /* group of file/directory */
uid_t uid; uid_t uid;
gid_t gid; gid_t gid;
int perm;
BOOL isdir; BOOL isdir;
size_t outsize; size_t outsize;
@ -2046,6 +2048,7 @@ int ntfs_get_posix_acl(struct SECURITY_CONTEXT *scx, ntfs_inode *ni,
* fetch owner and group for cacheing * fetch owner and group for cacheing
*/ */
if (pxdesc) { if (pxdesc) {
perm = pxdesc->mode & 07777;
/* /*
* Create a security id if there were none * Create a security id if there were none
* and upgrade option is selected * and upgrade option is selected
@ -2059,10 +2062,11 @@ int ntfs_get_posix_acl(struct SECURITY_CONTEXT *scx, ntfs_inode *ni,
#if OWNERFROMACL #if OWNERFROMACL
uid = ntfs_find_user(scx->mapping[MAPUSERS],usid); uid = ntfs_find_user(scx->mapping[MAPUSERS],usid);
#else #else
if (!(pxdesc->mode & 07777) if (!perm && ntfs_same_sid(usid, adminsid)) {
&& ntfs_same_sid(usid, adminsid)) {
uid = find_tenant(scx, uid = find_tenant(scx,
securattr); securattr);
if (uid)
perm = 0700;
} else } else
uid = ntfs_find_user(scx->mapping[MAPUSERS],usid); uid = ntfs_find_user(scx->mapping[MAPUSERS],usid);
#endif #endif
@ -2340,7 +2344,7 @@ int ntfs_get_owner_mode(struct SECURITY_CONTEXT *scx,
stbuf->st_uid = ntfs_find_user(scx->mapping[MAPUSERS],usid); stbuf->st_uid = ntfs_find_user(scx->mapping[MAPUSERS],usid);
#else #else
if (!perm && ntfs_same_sid(usid, adminsid)) { if (!perm && ntfs_same_sid(usid, adminsid)) {
stbuf->st_uid = stbuf->st_uid =
find_tenant(scx, find_tenant(scx,
securattr); securattr);
if (stbuf->st_uid) if (stbuf->st_uid)
@ -2452,7 +2456,7 @@ static struct POSIX_SECURITY *inherit_posix(struct SECURITY_CONTEXT *scx,
/* /*
* Allocate a security_id for a file being created * Allocate a security_id for a file being created
* *
* Returns zero if not possible (NTFS v3.x required) * Returns zero if not possible (NTFS v3.x required)
*/ */
@ -2674,7 +2678,7 @@ le32 ntfs_alloc_securid(struct SECURITY_CONTEXT *scx,
/* /*
* Update ownership and mode of a file, reusing an existing * Update ownership and mode of a file, reusing an existing
* security descriptor when possible * security descriptor when possible
* *
* Returns zero if successful * Returns zero if successful
*/ */
@ -2889,6 +2893,7 @@ int ntfs_set_posix_acl(struct SECURITY_CONTEXT *scx, ntfs_inode *ni,
uid_t uid; uid_t uid;
uid_t gid; uid_t gid;
int res; int res;
mode_t mode;
BOOL isdir; BOOL isdir;
BOOL deflt; BOOL deflt;
BOOL exist; BOOL exist;
@ -2914,6 +2919,7 @@ int ntfs_set_posix_acl(struct SECURITY_CONTEXT *scx, ntfs_inode *ni,
gid = cached->gid; gid = cached->gid;
oldpxdesc = cached->pxdesc; oldpxdesc = cached->pxdesc;
if (oldpxdesc) { if (oldpxdesc) {
mode = oldpxdesc->mode;
newpxdesc = ntfs_replace_acl(oldpxdesc, newpxdesc = ntfs_replace_acl(oldpxdesc,
(const struct POSIX_ACL*)value,count,deflt); (const struct POSIX_ACL*)value,count,deflt);
} }
@ -2940,6 +2946,7 @@ int ntfs_set_posix_acl(struct SECURITY_CONTEXT *scx, ntfs_inode *ni,
|| (!exist && (flags & XATTR_REPLACE))) { || (!exist && (flags & XATTR_REPLACE))) {
errno = (exist ? EEXIST : ENODATA); errno = (exist ? EEXIST : ENODATA);
} else { } else {
mode = oldpxdesc->mode;
newpxdesc = ntfs_replace_acl(oldpxdesc, newpxdesc = ntfs_replace_acl(oldpxdesc,
(const struct POSIX_ACL*)value,count,deflt); (const struct POSIX_ACL*)value,count,deflt);
} }
@ -3085,7 +3092,7 @@ int ntfs_set_mode(struct SECURITY_CONTEXT *scx, ntfs_inode *ni, mode_t mode)
/* must copy before merging */ /* must copy before merging */
pxsize = sizeof(struct POSIX_SECURITY) pxsize = sizeof(struct POSIX_SECURITY)
+ (oldpxdesc->acccnt + oldpxdesc->defcnt)*sizeof(struct POSIX_ACE); + (oldpxdesc->acccnt + oldpxdesc->defcnt)*sizeof(struct POSIX_ACE);
newpxdesc = (struct POSIX_SECURITY*)malloc(pxsize); newpxdesc = (struct POSIX_SECURITY*)ntfs_malloc(pxsize);
if (newpxdesc) { if (newpxdesc) {
memcpy(newpxdesc, oldpxdesc, pxsize); memcpy(newpxdesc, oldpxdesc, pxsize);
if (ntfs_merge_mode_posix(newpxdesc, mode)) if (ntfs_merge_mode_posix(newpxdesc, mode))
@ -3173,7 +3180,7 @@ int ntfs_sd_add_everyone(ntfs_inode *ni)
ACCESS_ALLOWED_ACE *ace; ACCESS_ALLOWED_ACE *ace;
SID *sid; SID *sid;
int ret, sd_len; int ret, sd_len;
/* Create SECURITY_DESCRIPTOR attribute (everyone has full access). */ /* Create SECURITY_DESCRIPTOR attribute (everyone has full access). */
/* /*
* Calculate security descriptor length. We have 2 sub-authorities in * Calculate security descriptor length. We have 2 sub-authorities in
@ -3181,14 +3188,14 @@ int ntfs_sd_add_everyone(ntfs_inode *ni)
* 4 bytes to every SID. * 4 bytes to every SID.
*/ */
sd_len = sizeof(SECURITY_DESCRIPTOR_ATTR) + 2 * (sizeof(SID) + 4) + sd_len = sizeof(SECURITY_DESCRIPTOR_ATTR) + 2 * (sizeof(SID) + 4) +
sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE); sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE);
sd = (SECURITY_DESCRIPTOR_RELATIVE*)ntfs_calloc(sd_len); sd = (SECURITY_DESCRIPTOR_RELATIVE*)ntfs_calloc(sd_len);
if (!sd) if (!sd)
return -1; return -1;
sd->revision = SECURITY_DESCRIPTOR_REVISION; sd->revision = SECURITY_DESCRIPTOR_REVISION;
sd->control = SE_DACL_PRESENT | SE_SELF_RELATIVE; sd->control = SE_DACL_PRESENT | SE_SELF_RELATIVE;
sid = (SID*)((u8*)sd + sizeof(SECURITY_DESCRIPTOR_ATTR)); sid = (SID*)((u8*)sd + sizeof(SECURITY_DESCRIPTOR_ATTR));
sid->revision = SID_REVISION; sid->revision = SID_REVISION;
sid->sub_authority_count = 2; sid->sub_authority_count = 2;
@ -3196,21 +3203,21 @@ int ntfs_sd_add_everyone(ntfs_inode *ni)
sid->sub_authority[1] = const_cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS); sid->sub_authority[1] = const_cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS);
sid->identifier_authority.value[5] = 5; sid->identifier_authority.value[5] = 5;
sd->owner = cpu_to_le32((u8*)sid - (u8*)sd); sd->owner = cpu_to_le32((u8*)sid - (u8*)sd);
sid = (SID*)((u8*)sid + sizeof(SID) + 4); sid = (SID*)((u8*)sid + sizeof(SID) + 4);
sid->revision = SID_REVISION; sid->revision = SID_REVISION;
sid->sub_authority_count = 2; sid->sub_authority_count = 2;
sid->sub_authority[0] = const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID); sid->sub_authority[0] = const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID);
sid->sub_authority[1] = const_cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS); sid->sub_authority[1] = const_cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS);
sid->identifier_authority.value[5] = 5; sid->identifier_authority.value[5] = 5;
sd->group = cpu_to_le32((u8*)sid - (u8*)sd); sd->group = cpu_to_le32((u8*)sid - (u8*)sd);
acl = (ACL*)((u8*)sid + sizeof(SID) + 4); acl = (ACL*)((u8*)sid + sizeof(SID) + 4);
acl->revision = ACL_REVISION; acl->revision = ACL_REVISION;
acl->size = const_cpu_to_le16(sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE)); acl->size = const_cpu_to_le16(sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE));
acl->ace_count = const_cpu_to_le16(1); acl->ace_count = const_cpu_to_le16(1);
sd->dacl = cpu_to_le32((u8*)acl - (u8*)sd); sd->dacl = cpu_to_le32((u8*)acl - (u8*)sd);
ace = (ACCESS_ALLOWED_ACE*)((u8*)acl + sizeof(ACL)); ace = (ACCESS_ALLOWED_ACE*)((u8*)acl + sizeof(ACL));
ace->type = ACCESS_ALLOWED_ACE_TYPE; ace->type = ACCESS_ALLOWED_ACE_TYPE;
ace->flags = OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE; ace->flags = OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE;
@ -3225,7 +3232,7 @@ int ntfs_sd_add_everyone(ntfs_inode *ni)
sd_len); sd_len);
if (ret) if (ret)
ntfs_log_perror("Failed to add initial SECURITY_DESCRIPTOR"); ntfs_log_perror("Failed to add initial SECURITY_DESCRIPTOR");
free(sd); free(sd);
return ret; return ret;
} }
@ -3324,7 +3331,7 @@ int ntfs_allowed_access(struct SECURITY_CONTEXT *scx,
* *
* Returns true if access is allowed, including user is root and * Returns true if access is allowed, including user is root and
* no user mapping defined * no user mapping defined
* *
* Sets errno if there is a problem or if not allowed * Sets errno if there is a problem or if not allowed
* *
* This is used for Posix ACL and checking creation of DOS file names * This is used for Posix ACL and checking creation of DOS file names
@ -3472,7 +3479,7 @@ int ntfs_set_owner(struct SECURITY_CONTEXT *scx, ntfs_inode *ni,
if (uid && (fileuid != uid)) if (uid && (fileuid != uid))
mode &= 01777; mode &= 01777;
#if POSIXACLS #if POSIXACLS
res = ntfs_set_owner_mode(scx, ni, uid, gid, res = ntfs_set_owner_mode(scx, ni, uid, gid,
mode, pxdesc); mode, pxdesc);
#else #else
res = ntfs_set_owner_mode(scx, ni, uid, gid, mode); res = ntfs_set_owner_mode(scx, ni, uid, gid, mode);
@ -3506,16 +3513,16 @@ int ntfs_set_owner(struct SECURITY_CONTEXT *scx, ntfs_inode *ni,
int ntfs_set_ownmod(struct SECURITY_CONTEXT *scx, ntfs_inode *ni, int ntfs_set_ownmod(struct SECURITY_CONTEXT *scx, ntfs_inode *ni,
uid_t uid, gid_t gid, const mode_t mode) uid_t uid, gid_t gid, const mode_t mode)
{ {
const SECURITY_DESCRIPTOR_RELATIVE *phead;
const struct CACHED_PERMISSIONS *cached; const struct CACHED_PERMISSIONS *cached;
char *oldattr; char *oldattr;
uid_t fileuid;
uid_t filegid;
int res;
#if POSIXACLS
const SECURITY_DESCRIPTOR_RELATIVE *phead;
const SID *usid; const SID *usid;
const SID *gsid; const SID *gsid;
uid_t fileuid;
uid_t filegid;
BOOL isdir; BOOL isdir;
int res;
#if POSIXACLS
const struct POSIX_SECURITY *oldpxdesc; const struct POSIX_SECURITY *oldpxdesc;
struct POSIX_SECURITY *newpxdesc = (struct POSIX_SECURITY*)NULL; struct POSIX_SECURITY *newpxdesc = (struct POSIX_SECURITY*)NULL;
int pxsize; int pxsize;
@ -3534,7 +3541,7 @@ int ntfs_set_ownmod(struct SECURITY_CONTEXT *scx, ntfs_inode *ni,
/* must copy before merging */ /* must copy before merging */
pxsize = sizeof(struct POSIX_SECURITY) pxsize = sizeof(struct POSIX_SECURITY)
+ (oldpxdesc->acccnt + oldpxdesc->defcnt)*sizeof(struct POSIX_ACE); + (oldpxdesc->acccnt + oldpxdesc->defcnt)*sizeof(struct POSIX_ACE);
newpxdesc = (struct POSIX_SECURITY*)malloc(pxsize); newpxdesc = (struct POSIX_SECURITY*)ntfs_malloc(pxsize);
if (newpxdesc) { if (newpxdesc) {
memcpy(newpxdesc, oldpxdesc, pxsize); memcpy(newpxdesc, oldpxdesc, pxsize);
if (ntfs_merge_mode_posix(newpxdesc, mode)) if (ntfs_merge_mode_posix(newpxdesc, mode))
@ -3548,7 +3555,6 @@ int ntfs_set_ownmod(struct SECURITY_CONTEXT *scx, ntfs_inode *ni,
filegid = 0; filegid = 0;
oldattr = getsecurityattr(scx->vol, ni); oldattr = getsecurityattr(scx->vol, ni);
if (oldattr) { if (oldattr) {
#if POSIXACLS
isdir = (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY) isdir = (ni->mrec->flags & MFT_RECORD_IS_DIRECTORY)
!= const_cpu_to_le16(0); != const_cpu_to_le16(0);
phead = (const SECURITY_DESCRIPTOR_RELATIVE*) phead = (const SECURITY_DESCRIPTOR_RELATIVE*)
@ -3561,6 +3567,7 @@ int ntfs_set_ownmod(struct SECURITY_CONTEXT *scx, ntfs_inode *ni,
usid = (const SID*) usid = (const SID*)
&oldattr[le32_to_cpu(phead->owner)]; &oldattr[le32_to_cpu(phead->owner)];
#endif #endif
#if POSIXACLS
newpxdesc = ntfs_build_permissions_posix(scx->mapping, oldattr, newpxdesc = ntfs_build_permissions_posix(scx->mapping, oldattr,
usid, gsid, isdir); usid, gsid, isdir);
if (!newpxdesc || ntfs_merge_mode_posix(newpxdesc, mode)) if (!newpxdesc || ntfs_merge_mode_posix(newpxdesc, mode))
@ -3588,7 +3595,7 @@ int ntfs_set_ownmod(struct SECURITY_CONTEXT *scx, ntfs_inode *ni,
if ((int)gid < 0) if ((int)gid < 0)
gid = filegid; gid = filegid;
#if POSIXACLS #if POSIXACLS
res = ntfs_set_owner_mode(scx, ni, uid, gid, res = ntfs_set_owner_mode(scx, ni, uid, gid,
mode, newpxdesc); mode, newpxdesc);
#else #else
res = ntfs_set_owner_mode(scx, ni, uid, gid, mode); res = ntfs_set_owner_mode(scx, ni, uid, gid, mode);
@ -3819,9 +3826,9 @@ static int link_single_group(struct MAPPING *usermapping, struct passwd *user,
grmem++; grmem++;
if (*grmem) { if (*grmem) {
if (!grcnt) if (!grcnt)
groups = (gid_t*)malloc(sizeof(gid_t)); groups = (gid_t*)ntfs_malloc(sizeof(gid_t));
else else
groups = (gid_t*)realloc(groups, groups = (gid_t*)MEM2_realloc(groups,
(grcnt+1)*sizeof(gid_t)); (grcnt+1)*sizeof(gid_t));
if (groups) if (groups)
groups[grcnt++] = gid; groups[grcnt++] = gid;
@ -4231,7 +4238,7 @@ void ntfs_close_secure(struct SECURITY_CONTEXT *scx)
ntfs_index_ctx_put(vol->secure_xsii); ntfs_index_ctx_put(vol->secure_xsii);
ntfs_index_ctx_put(vol->secure_xsdh); ntfs_index_ctx_put(vol->secure_xsdh);
ntfs_inode_close(vol->secure_ni); ntfs_inode_close(vol->secure_ni);
} }
ntfs_free_mapping(scx->mapping); ntfs_free_mapping(scx->mapping);
free_caches(scx); free_caches(scx);
@ -4777,7 +4784,6 @@ BOOL ntfs_set_file_attributes(struct SECURITY_API *scapi,
ni->flags = (ni->flags & ~settable) ni->flags = (ni->flags & ~settable)
| (cpu_to_le32(attrib) & settable); | (cpu_to_le32(attrib) & settable);
NInoSetDirty(ni); NInoSetDirty(ni);
NInoFileNameSetDirty(ni);
} }
if (!ntfs_inode_close(ni)) if (!ntfs_inode_close(ni))
res = -1; res = -1;

View File

@ -1,5 +1,5 @@
/* /*
* types.h - Misc type definitions not related to on-disk structure. * types.h - Misc type definitions not related to on-disk structure.
* Originated from the Linux-NTFS project. * Originated from the Linux-NTFS project.
* *
* Copyright (c) 2000-2004 Anton Altaparmakov * Copyright (c) 2000-2004 Anton Altaparmakov

View File

@ -432,18 +432,18 @@ void ntfs_file_value_upcase(FILE_NAME_ATTR *file_name_attr,
so this patch fixes the resulting issues for systems which use so this patch fixes the resulting issues for systems which use
UTF-8 and for others, specifying the locale in fstab brings them UTF-8 and for others, specifying the locale in fstab brings them
the encoding which they want. the encoding which they want.
If no locale is defined or there was a problem with setting one If no locale is defined or there was a problem with setting one
up and whenever nl_langinfo(CODESET) returns a sting starting with up and whenever nl_langinfo(CODESET) returns a sting starting with
"ANSI", use an internal UCS-2LE <-> UTF-8 codeset converter to fix "ANSI", use an internal UCS-2LE <-> UTF-8 codeset converter to fix
the bug where NTFS-3G does not show any path names which include the bug where NTFS-3G does not show any path names which include
international characters!!! (and also fails on creating them) as result. international characters!!! (and also fails on creating them) as result.
Author: Bernhard Kaindl <bk@suse.de> Author: Bernhard Kaindl <bk@suse.de>
Jean-Pierre Andre made it compliant with RFC3629/RFC2781. Jean-Pierre Andre made it compliant with RFC3629/RFC2781.
*/ */
/* /*
* Return the amount of 8-bit elements in UTF-8 needed (without the terminating * Return the amount of 8-bit elements in UTF-8 needed (without the terminating
* null) to store a given UTF-16LE string. * null) to store a given UTF-16LE string.
* *
@ -462,7 +462,7 @@ static int utf16_to_utf8_size(const ntfschar *ins, const int ins_len, int outs_l
if ((c >= 0xdc00) && (c < 0xe000)) { if ((c >= 0xdc00) && (c < 0xe000)) {
surrog = FALSE; surrog = FALSE;
count += 4; count += 4;
} else } else
goto fail; goto fail;
} else } else
if (c < 0x80) if (c < 0x80)
@ -479,14 +479,14 @@ static int utf16_to_utf8_size(const ntfschar *ins, const int ins_len, int outs_l
else if (c >= 0xe000) else if (c >= 0xe000)
#endif #endif
count += 3; count += 3;
else else
goto fail; goto fail;
if (count > outs_len) { if (count > outs_len) {
errno = ENAMETOOLONG; errno = ENAMETOOLONG;
goto out; goto out;
} }
} }
if (surrog) if (surrog)
goto fail; goto fail;
ret = count; ret = count;
@ -548,7 +548,7 @@ static int ntfs_utf16_to_utf8(const ntfschar *ins, const int ins_len,
*t++ = 0x80 + ((c >> 6) & 15) + ((halfpair & 3) << 4); *t++ = 0x80 + ((c >> 6) & 15) + ((halfpair & 3) << 4);
*t++ = 0x80 + (c & 63); *t++ = 0x80 + (c & 63);
halfpair = 0; halfpair = 0;
} else } else
goto fail; goto fail;
} else if (c < 0x80) { } else if (c < 0x80) {
*t++ = c; *t++ = c;
@ -566,12 +566,12 @@ static int ntfs_utf16_to_utf8(const ntfschar *ins, const int ins_len,
*t++ = 0xe0 | (c >> 12); *t++ = 0xe0 | (c >> 12);
*t++ = 0x80 | ((c >> 6) & 0x3f); *t++ = 0x80 | ((c >> 6) & 0x3f);
*t++ = 0x80 | (c & 0x3f); *t++ = 0x80 | (c & 0x3f);
} else } else
goto fail; goto fail;
} }
} }
*t = '\0'; *t = '\0';
#if defined(__APPLE__) || defined(__DARWIN__) #if defined(__APPLE__) || defined(__DARWIN__)
#ifdef ENABLE_NFCONV #ifdef ENABLE_NFCONV
if(nfconvert_utf8 && (t - *outs) > 0) { if(nfconvert_utf8 && (t - *outs) > 0) {
@ -600,7 +600,7 @@ static int ntfs_utf16_to_utf8(const ntfschar *ins, const int ins_len,
} }
#endif /* ENABLE_NFCONV */ #endif /* ENABLE_NFCONV */
#endif /* defined(__APPLE__) || defined(__DARWIN__) */ #endif /* defined(__APPLE__) || defined(__DARWIN__) */
ret = t - *outs; ret = t - *outs;
out: out:
return ret; return ret;
@ -609,8 +609,8 @@ fail:
goto out; goto out;
} }
/* /*
* Return the amount of 16-bit elements in UTF-16LE needed * Return the amount of 16-bit elements in UTF-16LE needed
* (without the terminating null) to store given UTF-8 string. * (without the terminating null) to store given UTF-8 string.
* *
* Return -1 with errno set if it's longer than PATH_MAX or string is invalid. * Return -1 with errno set if it's longer than PATH_MAX or string is invalid.
@ -625,22 +625,22 @@ static int utf8_to_utf16_size(const char *s)
size_t count = 0; size_t count = 0;
while ((byte = *((const unsigned char *)s++))) { while ((byte = *((const unsigned char *)s++))) {
if (++count >= PATH_MAX) if (++count >= PATH_MAX)
goto fail; goto fail;
if (byte >= 0xc0) { if (byte >= 0xc0) {
if (byte >= 0xF5) { if (byte >= 0xF5) {
errno = EILSEQ; errno = EILSEQ;
goto out; goto out;
} }
if (!*s) if (!*s)
break; break;
if (byte >= 0xC0) if (byte >= 0xC0)
s++; s++;
if (!*s) if (!*s)
break; break;
if (byte >= 0xE0) if (byte >= 0xE0)
s++; s++;
if (!*s) if (!*s)
break; break;
if (byte >= 0xF0) { if (byte >= 0xF0) {
s++; s++;
@ -656,11 +656,11 @@ fail:
errno = ENAMETOOLONG; errno = ENAMETOOLONG;
goto out; goto out;
} }
/* /*
* This converts one UTF-8 sequence to cpu-endian Unicode value * This converts one UTF-8 sequence to cpu-endian Unicode value
* within range U+0 .. U+10ffff and excluding U+D800 .. U+DFFF * within range U+0 .. U+10ffff and excluding U+D800 .. U+DFFF
* *
* Return the number of used utf8 bytes or -1 with errno set * Return the number of used utf8 bytes or -1 with errno set
* if sequence is invalid. * if sequence is invalid.
*/ */
static int utf8_to_unicode(u32 *wc, const char *s) static int utf8_to_unicode(u32 *wc, const char *s)
@ -726,7 +726,7 @@ fail:
* @ins: input multibyte string buffer * @ins: input multibyte string buffer
* @outs: on return contains the (allocated) output utf16 string * @outs: on return contains the (allocated) output utf16 string
* @outs_len: length of output buffer in utf16 characters * @outs_len: length of output buffer in utf16 characters
* *
* Return -1 with errno set. * Return -1 with errno set.
*/ */
static int ntfs_utf8_to_utf16(const char *ins, ntfschar **outs) static int ntfs_utf8_to_utf16(const char *ins, ntfschar **outs)
@ -787,7 +787,7 @@ static int ntfs_utf8_to_utf16(const char *ins, ntfschar **outs)
} }
t += m; t += m;
} }
ret = --outpos - *outs; ret = --outpos - *outs;
fail: fail:
#if defined(__APPLE__) || defined(__DARWIN__) #if defined(__APPLE__) || defined(__DARWIN__)
@ -930,7 +930,7 @@ err_out:
* Convert the input multibyte string @ins, from the current locale into the * Convert the input multibyte string @ins, from the current locale into the
* corresponding little endian, 2-byte Unicode string. * corresponding little endian, 2-byte Unicode string.
* *
* The function allocates the string and the caller is responsible for calling * The function allocates the string and the caller is responsible for calling
* free(*@outs); when finished with it. * free(*@outs); when finished with it.
* *
* On success the function returns the number of Unicode characters written to * On success the function returns the number of Unicode characters written to
@ -961,7 +961,7 @@ int ntfs_mbstoucs(const char *ins, ntfschar **outs)
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }
if (use_utf8) if (use_utf8)
return ntfs_utf8_to_utf16(ins, outs); return ntfs_utf8_to_utf16(ins, outs);
@ -1137,8 +1137,8 @@ void ntfs_upcase_table_build(ntfschar *uc, u32 uc_len)
* value of "Add" added to it. * value of "Add" added to it.
*/ */
static int uc_run_table[][3] = { /* Start, End, Add */ static int uc_run_table[][3] = { /* Start, End, Add */
{0x0061, 0x007b, -32}, {0x00e0, 0x00f7, -32}, {0x00f8, 0x00ff, -32}, {0x0061, 0x007b, -32}, {0x00e0, 0x00f7, -32}, {0x00f8, 0x00ff, -32},
{0x0256, 0x0258, -205}, {0x028a, 0x028c, -217}, {0x037b, 0x037e, 130}, {0x0256, 0x0258, -205}, {0x028a, 0x028c, -217}, {0x037b, 0x037e, 130},
{0x03ac, 0x03ad, -38}, {0x03ad, 0x03b0, -37}, {0x03b1, 0x03c2, -32}, {0x03ac, 0x03ad, -38}, {0x03ad, 0x03b0, -37}, {0x03b1, 0x03c2, -32},
{0x03c2, 0x03c3, -31}, {0x03c3, 0x03cc, -32}, {0x03cc, 0x03cd, -64}, {0x03c2, 0x03c3, -31}, {0x03c3, 0x03cc, -32}, {0x03cc, 0x03cd, -64},
{0x03cd, 0x03cf, -63}, {0x0430, 0x0450, -32}, {0x0450, 0x0460, -80}, {0x03cd, 0x03cf, -63}, {0x0430, 0x0450, -32}, {0x0450, 0x0460, -80},
@ -1262,7 +1262,7 @@ void ntfs_upcase_table_build(ntfschar *uc, u32 uc_len)
u32 ntfs_upcase_build_default(ntfschar **upcase) u32 ntfs_upcase_build_default(ntfschar **upcase)
{ {
u32 upcase_len = 0; u32 upcase_len;
*upcase = (ntfschar*)ntfs_malloc(UPCASE_LEN*2); *upcase = (ntfschar*)ntfs_malloc(UPCASE_LEN*2);
if (*upcase) { if (*upcase) {
@ -1310,12 +1310,12 @@ ntfschar *ntfs_locase_table_build(const ntfschar *uc, u32 uc_cnt)
* @len: length of output buffer in Unicode characters * @len: length of output buffer in Unicode characters
* *
* Convert the input @s string into the corresponding little endian, * Convert the input @s string into the corresponding little endian,
* 2-byte Unicode string. The length of the converted string is less * 2-byte Unicode string. The length of the converted string is less
* or equal to the maximum length allowed by the NTFS format (255). * or equal to the maximum length allowed by the NTFS format (255).
* *
* If @s is NULL then return AT_UNNAMED. * If @s is NULL then return AT_UNNAMED.
* *
* On success the function returns the Unicode string in an allocated * On success the function returns the Unicode string in an allocated
* buffer and the caller is responsible to free it when it's not needed * buffer and the caller is responsible to free it when it's not needed
* anymore. * anymore.
* *
@ -1406,18 +1406,16 @@ BOOL ntfs_collapsible_chars(ntfs_volume *vol,
{ {
BOOL collapsible; BOOL collapsible;
unsigned int ch; unsigned int ch;
unsigned int cs;
int i; int i;
collapsible = shortlen == longlen; collapsible = shortlen == longlen;
for (i=0; collapsible && (i<shortlen); i++) { if (collapsible)
ch = le16_to_cpu(longname[i]); for (i=0; i<shortlen; i++) {
cs = le16_to_cpu(shortname[i]); ch = le16_to_cpu(longname[i]);
if ((cs != ch) if ((ch >= vol->upcase_len)
&& ((ch >= vol->upcase_len) || ((shortname[i] != longname[i])
|| (cs >= vol->upcase_len) && (shortname[i] != vol->upcase[ch])))
|| (vol->upcase[cs] != vol->upcase[ch]))) collapsible = FALSE;
collapsible = FALSE;
} }
return (collapsible); return (collapsible);
} }
@ -1456,7 +1454,7 @@ int ntfs_macosx_normalize_filenames(int normalize) {
#else #else
return -1; return -1;
#endif /* ENABLE_NFCONV */ #endif /* ENABLE_NFCONV */
} }
int ntfs_macosx_normalize_utf8(const char *utf8_string, char **target, int ntfs_macosx_normalize_utf8(const char *utf8_string, char **target,
int composed) { int composed) {
@ -1468,14 +1466,14 @@ int ntfs_macosx_normalize_utf8(const char *utf8_string, char **target,
CFIndex requiredBufferLength; CFIndex requiredBufferLength;
char *result = NULL; char *result = NULL;
int resultLength = -1; int resultLength = -1;
/* Convert the UTF-8 string to a CFString. */ /* Convert the UTF-8 string to a CFString. */
cfSourceString = CFStringCreateWithCString(kCFAllocatorDefault, utf8_string, kCFStringEncodingUTF8); cfSourceString = CFStringCreateWithCString(kCFAllocatorDefault, utf8_string, kCFStringEncodingUTF8);
if(cfSourceString == NULL) { if(cfSourceString == NULL) {
ntfs_log_error("CFStringCreateWithCString failed!\n"); ntfs_log_error("CFStringCreateWithCString failed!\n");
return -2; return -2;
} }
/* Create a mutable string from cfSourceString that we are free to modify. */ /* Create a mutable string from cfSourceString that we are free to modify. */
cfMutableString = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, cfSourceString); cfMutableString = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, cfSourceString);
CFRelease(cfSourceString); /* End-of-life. */ CFRelease(cfSourceString); /* End-of-life. */
@ -1483,16 +1481,16 @@ int ntfs_macosx_normalize_utf8(const char *utf8_string, char **target,
ntfs_log_error("CFStringCreateMutableCopy failed!\n"); ntfs_log_error("CFStringCreateMutableCopy failed!\n");
return -3; return -3;
} }
/* Normalize the mutable string to the desired normalization form. */ /* Normalize the mutable string to the desired normalization form. */
CFStringNormalize(cfMutableString, (composed != 0 ? kCFStringNormalizationFormC : kCFStringNormalizationFormD)); CFStringNormalize(cfMutableString, (composed != 0 ? kCFStringNormalizationFormC : kCFStringNormalizationFormD));
/* Store the resulting string in a '\0'-terminated UTF-8 encoded char* buffer. */ /* Store the resulting string in a '\0'-terminated UTF-8 encoded char* buffer. */
rangeToProcess = CFRangeMake(0, CFStringGetLength(cfMutableString)); rangeToProcess = CFRangeMake(0, CFStringGetLength(cfMutableString));
if(CFStringGetBytes(cfMutableString, rangeToProcess, kCFStringEncodingUTF8, 0, false, NULL, 0, &requiredBufferLength) > 0) { if(CFStringGetBytes(cfMutableString, rangeToProcess, kCFStringEncodingUTF8, 0, false, NULL, 0, &requiredBufferLength) > 0) {
resultLength = sizeof(char)*(requiredBufferLength + 1); resultLength = sizeof(char)*(requiredBufferLength + 1);
result = ntfs_calloc(resultLength); result = ntfs_calloc(resultLength);
if(result != NULL) { if(result != NULL) {
if(CFStringGetBytes(cfMutableString, rangeToProcess, kCFStringEncodingUTF8, if(CFStringGetBytes(cfMutableString, rangeToProcess, kCFStringEncodingUTF8,
0, false, (UInt8*)result, resultLength-1, &requiredBufferLength) <= 0) { 0, false, (UInt8*)result, resultLength-1, &requiredBufferLength) <= 0) {
@ -1507,9 +1505,9 @@ int ntfs_macosx_normalize_utf8(const char *utf8_string, char **target,
else else
ntfs_log_error("Could not perform check for required length of UTF-8 conversion of normalized CFMutableString.\n"); ntfs_log_error("Could not perform check for required length of UTF-8 conversion of normalized CFMutableString.\n");
CFRelease(cfMutableString); CFRelease(cfMutableString);
if(result != NULL) { if(result != NULL) {
*target = result; *target = result;
return resultLength - 1; return resultLength - 1;

View File

@ -54,7 +54,6 @@
#include <locale.h> #include <locale.h>
#endif #endif
#include "param.h"
#include "compat.h" #include "compat.h"
#include "volume.h" #include "volume.h"
#include "attrib.h" #include "attrib.h"
@ -68,7 +67,6 @@
#include "dir.h" #include "dir.h"
#include "logging.h" #include "logging.h"
#include "cache.h" #include "cache.h"
#include "realpath.h"
#include "misc.h" #include "misc.h"
const char *ntfs_home = const char *ntfs_home =
@ -375,12 +373,6 @@ mft_has_no_attr_list:
/* Done with the $Mft mft record. */ /* Done with the $Mft mft record. */
ntfs_attr_put_search_ctx(ctx); ntfs_attr_put_search_ctx(ctx);
ctx = NULL; ctx = NULL;
/* Update the size fields in the inode. */
vol->mft_ni->data_size = vol->mft_na->data_size;
vol->mft_ni->allocated_size = vol->mft_na->allocated_size;
set_nino_flag(vol->mft_ni, KnownSize);
/* /*
* The volume is now setup so we can use all read access functions. * The volume is now setup so we can use all read access functions.
*/ */
@ -502,12 +494,6 @@ ntfs_volume *ntfs_volume_startup(struct ntfs_device *dev, unsigned long flags)
NVolSetShowSysFiles(vol); NVolSetShowSysFiles(vol);
NVolSetShowHidFiles(vol); NVolSetShowHidFiles(vol);
NVolClearHideDotFiles(vol); NVolClearHideDotFiles(vol);
/* set default compression */
#if DEFAULT_COMPRESSION
NVolSetCompression(vol);
#else
NVolClearCompression(vol);
#endif
if (flags & MS_RDONLY) if (flags & MS_RDONLY)
NVolSetReadOnly(vol); NVolSetReadOnly(vol);
@ -1373,6 +1359,18 @@ int ntfs_umount(ntfs_volume *vol, const BOOL force __attribute__((unused)))
#ifdef HAVE_MNTENT_H #ifdef HAVE_MNTENT_H
#ifndef HAVE_REALPATH
/**
* realpath - If there is no realpath on the system
*/
static char *realpath(const char *path, char *resolved_path)
{
strncpy(resolved_path, path, PATH_MAX);
resolved_path[PATH_MAX] = '\0';
return resolved_path;
}
#endif
/** /**
* ntfs_mntent_check - desc * ntfs_mntent_check - desc
* *
@ -1396,7 +1394,7 @@ static int ntfs_mntent_check(const char *file, unsigned long *mnt_flags)
err = errno; err = errno;
goto exit; goto exit;
} }
if (!ntfs_realpath_canonicalize(file, real_file)) { if (!realpath(file, real_file)) {
err = errno; err = errno;
goto exit; goto exit;
} }
@ -1405,7 +1403,7 @@ static int ntfs_mntent_check(const char *file, unsigned long *mnt_flags)
goto exit; goto exit;
} }
while ((mnt = getmntent(f))) { while ((mnt = getmntent(f))) {
if (!ntfs_realpath_canonicalize(mnt->mnt_fsname, real_fsname)) if (!realpath(mnt->mnt_fsname, real_fsname))
continue; continue;
if (!strcmp(real_file, real_fsname)) if (!strcmp(real_file, real_fsname))
break; break;
@ -1732,113 +1730,3 @@ int ntfs_volume_get_free_space(ntfs_volume *vol)
} }
return (ret); return (ret);
} }
/**
* ntfs_volume_rename - change the current label on a volume
* @vol: volume to change the label on
* @label: the new label
* @label_len: the length of @label in ntfschars including the terminating NULL
* character, which is mandatory (the value can not exceed 128)
*
* Change the label on the volume @vol to @label.
*/
int ntfs_volume_rename(ntfs_volume *vol, ntfschar *label, int label_len)
{
ntfs_attr *na;
char *old_vol_name;
char *new_vol_name = NULL;
int new_vol_name_len;
int err;
if (NVolReadOnly(vol)) {
ntfs_log_error("Refusing to change label on read-only mounted "
"volume.\n");
errno = EROFS;
return -1;
}
label_len *= sizeof(ntfschar);
if (label_len > 0x100) {
ntfs_log_error("New label is too long. Maximum %u characters "
"allowed.\n",
(unsigned)(0x100 / sizeof(ntfschar)));
errno = ERANGE;
return -1;
}
na = ntfs_attr_open(vol->vol_ni, AT_VOLUME_NAME, AT_UNNAMED, 0);
if (!na) {
if (errno != ENOENT) {
err = errno;
ntfs_log_perror("Lookup of $VOLUME_NAME attribute "
"failed");
goto err_out;
}
/* The volume name attribute does not exist. Need to add it. */
if (ntfs_attr_add(vol->vol_ni, AT_VOLUME_NAME, AT_UNNAMED, 0,
(u8*) label, label_len))
{
err = errno;
ntfs_log_perror("Encountered error while adding "
"$VOLUME_NAME attribute");
goto err_out;
}
}
else {
s64 written;
if (NAttrNonResident(na)) {
err = errno;
ntfs_log_error("Error: Attribute $VOLUME_NAME must be "
"resident.\n");
goto err_out;
}
if (na->data_size != label_len) {
if (ntfs_attr_truncate(na, label_len)) {
err = errno;
ntfs_log_perror("Error resizing resident "
"attribute");
goto err_out;
}
}
if (label_len) {
written = ntfs_attr_pwrite(na, 0, label_len, label);
if (written == -1) {
err = errno;
ntfs_log_perror("Error when writing "
"$VOLUME_NAME data");
goto err_out;
}
else if (written != label_len) {
err = EIO;
ntfs_log_error("Partial write when writing "
"$VOLUME_NAME data.");
goto err_out;
}
}
}
new_vol_name_len =
ntfs_ucstombs(label, label_len, &new_vol_name, 0);
if (new_vol_name_len == -1) {
err = errno;
ntfs_log_perror("Error while decoding new volume name");
goto err_out;
}
old_vol_name = vol->vol_name;
vol->vol_name = new_vol_name;
free(old_vol_name);
err = 0;
err_out:
if (na)
ntfs_attr_close(na);
if (err)
errno = err;
return err ? -1 : 0;
}

View File

@ -113,7 +113,6 @@ typedef enum {
NV_ShowHidFiles, /* 1: Show files marked hidden. */ NV_ShowHidFiles, /* 1: Show files marked hidden. */
NV_HideDotFiles, /* 1: Set hidden flag on dot files */ NV_HideDotFiles, /* 1: Set hidden flag on dot files */
NV_Compression, /* 1: allow compression */ NV_Compression, /* 1: allow compression */
NV_NoFixupWarn, /* 1: Do not log fixup errors */
} ntfs_volume_state_bits; } ntfs_volume_state_bits;
#define test_nvol_flag(nv, flag) test_bit(NV_##flag, (nv)->state) #define test_nvol_flag(nv, flag) test_bit(NV_##flag, (nv)->state)
@ -148,10 +147,6 @@ typedef enum {
#define NVolSetCompression(nv) set_nvol_flag(nv, Compression) #define NVolSetCompression(nv) set_nvol_flag(nv, Compression)
#define NVolClearCompression(nv) clear_nvol_flag(nv, Compression) #define NVolClearCompression(nv) clear_nvol_flag(nv, Compression)
#define NVolNoFixupWarn(nv) test_nvol_flag(nv, NoFixupWarn)
#define NVolSetNoFixupWarn(nv) set_nvol_flag(nv, NoFixupWarn)
#define NVolClearNoFixupWarn(nv) clear_nvol_flag(nv, NoFixupWarn)
/* /*
* NTFS version 1.1 and 1.2 are used by Windows NT4. * NTFS version 1.1 and 1.2 are used by Windows NT4.
* NTFS version 2.x is used by Windows 2000 Beta * NTFS version 2.x is used by Windows 2000 Beta
@ -302,7 +297,6 @@ extern int ntfs_volume_error(int err);
extern void ntfs_mount_error(const char *vol, const char *mntpoint, int err); extern void ntfs_mount_error(const char *vol, const char *mntpoint, int err);
extern int ntfs_volume_get_free_space(ntfs_volume *vol); extern int ntfs_volume_get_free_space(ntfs_volume *vol);
extern int ntfs_volume_rename(ntfs_volume *vol, ntfschar *label, int label_len);
extern int ntfs_set_shown_files(ntfs_volume *vol, extern int ntfs_set_shown_files(ntfs_volume *vol,
BOOL show_sys_files, BOOL show_hid_files, BOOL hide_dot_files); BOOL show_sys_files, BOOL show_hid_files, BOOL hide_dot_files);

View File

@ -42,7 +42,7 @@
#define PARTITION_TYPE_WIN95_EXTENDED 0x0F /* Windows 95 extended partition */ #define PARTITION_TYPE_WIN95_EXTENDED 0x0F /* Windows 95 extended partition */
#define PARTITION_TYPE_GPT_TABLE 0xEE /* New Standard */ #define PARTITION_TYPE_GPT_TABLE 0xEE /* New Standard */
#define CACHE 32 #define CACHE 8
#define SECTORS 64 #define SECTORS 64
extern const DISC_INTERFACE __io_sdhc; extern const DISC_INTERFACE __io_sdhc;
@ -128,7 +128,7 @@ bool PartitionHandle::Mount(int pos, const char * name)
} }
else if(strncmp(GetFSName(pos), "NTFS", 4) == 0) else if(strncmp(GetFSName(pos), "NTFS", 4) == 0)
{ {
if(ntfsMount(MountNameList[pos].c_str(), interface, GetLBAStart(pos), CACHE, SECTORS, NTFS_SHOW_HIDDEN_FILES | NTFS_RECOVER)) if(ntfsMount(MountNameList[pos].c_str(), interface, GetLBAStart(pos), CACHE, SECTORS, NTFS_SU | NTFS_RECOVER | NTFS_IGNORE_CASE))
return true; return true;
} }
else if(strncmp(GetFSName(pos), "LINUX", 5) == 0) else if(strncmp(GetFSName(pos), "LINUX", 5) == 0)