*Updated libntfs to version 2011.1.15:

http://code.google.com/p/libntfs-wii/
*Deleted wiki pages because they are really outdated
*Updated some language files
This commit is contained in:
dimok321 2011-01-26 18:53:27 +00:00
parent 9d46977121
commit 718245adcd
28 changed files with 670 additions and 292 deletions

View File

@ -67,7 +67,7 @@
#define USE_LWP_LOCK #define USE_LWP_LOCK
#define USE_RTC_TIME #define USE_RTC_TIME
#elif defined (NDS) #elif defined (NDS)
#define DEFAULT_CACHE_PAGES 4 #define DEFAULT_CACHE_PAGES 16
#define DEFAULT_SECTORS_PAGE 8 #define DEFAULT_SECTORS_PAGE 8
#define USE_RTC_TIME #define USE_RTC_TIME
#elif defined (GBA) #elif defined (GBA)

View File

@ -245,7 +245,8 @@ uint32_t _FAT_fat_linkFreeCluster(PARTITION* partition, uint32_t cluster) {
} }
} }
partition->fat.firstFree = firstFree; partition->fat.firstFree = firstFree;
partition->fat.numberFreeCluster--; if(partition->fat.numberFreeCluster)
partition->fat.numberFreeCluster--;
partition->fat.numberLastAllocCluster = firstFree; partition->fat.numberLastAllocCluster = firstFree;
if ((cluster >= CLUSTER_FIRST) && (cluster <= lastCluster)) if ((cluster >= CLUSTER_FIRST) && (cluster <= lastCluster))
@ -311,7 +312,8 @@ bool _FAT_fat_clearLinks (PARTITION* partition, uint32_t cluster) {
// Erase the link // Erase the link
_FAT_fat_writeFatEntry (partition, cluster, CLUSTER_FREE); _FAT_fat_writeFatEntry (partition, cluster, CLUSTER_FREE);
partition->fat.numberFreeCluster++; if(partition->fat.numberFreeCluster < (partition->numberOfSectors/partition->sectorsPerCluster))
partition->fat.numberFreeCluster++;
// Move onto next cluster // Move onto next cluster
cluster = nextCluster; cluster = nextCluster;
} }

View File

@ -4,7 +4,7 @@
* This module is part of ntfs-3g library, but may also be * This module is part of ntfs-3g library, but may also be
* integrated in tools running over Linux or Windows * integrated in tools running over Linux or Windows
* *
* Copyright (c) 2007-2009 Jean-Pierre Andre * Copyright (c) 2007-2010 Jean-Pierre Andre
* *
* This program/include file is free software; you can redistribute it and/or * This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published * modify it under the terms of the GNU General Public License as published
@ -3956,33 +3956,6 @@ static SID *encodesid(const char *sidstr)
return (sid); return (sid);
} }
/*
* Early logging before the logs are redirected
*
* (not quite satisfactory : this appears before the ntfs-g banner,
* and with a different pid)
*/
static void log_early_error(const char *format, ...)
__attribute__((format(printf, 1, 2)));
static void log_early_error(const char *format, ...)
{
va_list args;
va_start(args, format);
#ifdef HAVE_SYSLOG_H
openlog("ntfs-3g", LOG_PID, LOG_USER);
ntfs_log_handler_syslog(NULL, NULL, 0,
NTFS_LOG_LEVEL_ERROR, NULL,
format, args);
#else
vfprintf(stderr,format,args);
#endif
va_end(args);
}
/* /*
* Get a single mapping item from buffer * Get a single mapping item from buffer
* *
@ -4045,7 +4018,7 @@ static struct MAPLIST *getmappingitem(FILEREADER reader, void *fileid,
if (pu && pg) if (pu && pg)
*pu = *pg = '\0'; *pu = *pg = '\0';
else { else {
log_early_error("Bad mapping item \"%s\"\n", ntfs_log_early_error("Bad mapping item \"%s\"\n",
item->maptext); item->maptext);
free(item); free(item);
item = (struct MAPLIST*)NULL; item = (struct MAPLIST*)NULL;
@ -4174,7 +4147,7 @@ struct MAPPING *ntfs_do_user_mapping(struct MAPLIST *firstitem)
if (pwd) if (pwd)
uid = pwd->pw_uid; uid = pwd->pw_uid;
else else
log_early_error("Invalid user \"%s\"\n", ntfs_log_early_error("Invalid user \"%s\"\n",
item->uidstr); item->uidstr);
} }
} }
@ -4254,7 +4227,7 @@ struct MAPPING *ntfs_do_group_mapping(struct MAPLIST *firstitem)
if (grp) if (grp)
gid = grp->gr_gid; gid = grp->gr_gid;
else else
log_early_error("Invalid group \"%s\"\n", ntfs_log_early_error("Invalid group \"%s\"\n",
item->gidstr); item->gidstr);
} }
} }

View File

@ -402,7 +402,7 @@ ntfs_attr *ntfs_attr_open(ntfs_inode *ni, const ATTR_TYPES type,
ntfs_attr *na = NULL; ntfs_attr *na = NULL;
ntfschar *newname = NULL; ntfschar *newname = NULL;
ATTR_RECORD *a; ATTR_RECORD *a;
BOOL cs; le16 cs;
ntfs_log_enter("Entering for inode %lld, attr 0x%x.\n", ntfs_log_enter("Entering for inode %lld, attr 0x%x.\n",
(unsigned long long)ni->mft_no, type); (unsigned long long)ni->mft_no, type);
@ -588,6 +588,74 @@ int ntfs_attr_map_runlist(ntfs_attr *na, VCN vcn)
return -1; return -1;
} }
#if PARTIAL_RUNLIST_UPDATING
/*
* Map the runlist of an attribute from some point to the end
*
* Returns 0 if success,
* -1 if it failed (errno telling why)
*/
static int ntfs_attr_map_partial_runlist(ntfs_attr *na, VCN vcn)
{
LCN lcn;
VCN last_vcn;
VCN highest_vcn;
VCN needed;
runlist_element *rl;
ATTR_RECORD *a;
BOOL startseen;
ntfs_attr_search_ctx *ctx;
lcn = ntfs_rl_vcn_to_lcn(na->rl, vcn);
if (lcn >= 0 || lcn == LCN_HOLE || lcn == LCN_ENOENT)
return 0;
ctx = ntfs_attr_get_search_ctx(na->ni, NULL);
if (!ctx)
return -1;
/* Get the last vcn in the attribute. */
last_vcn = na->allocated_size >> na->ni->vol->cluster_size_bits;
needed = vcn;
highest_vcn = 0;
startseen = FALSE;
do {
/* Find the attribute in the mft record. */
if (!ntfs_attr_lookup(na->type, na->name, na->name_len, CASE_SENSITIVE,
needed, NULL, 0, ctx)) {
a = ctx->attr;
/* Decode and merge the runlist. */
rl = ntfs_mapping_pairs_decompress(na->ni->vol, a,
na->rl);
if (rl) {
na->rl = rl;
highest_vcn = le64_to_cpu(a->highest_vcn);
/* corruption detection */
if (((highest_vcn + 1) < last_vcn)
&& ((highest_vcn + 1) <= needed)) {
ntfs_log_error("Corrupt attribute list\n");
rl = (runlist_element*)NULL;
}
needed = highest_vcn + 1;
if (!a->lowest_vcn)
startseen = TRUE;
}
} else
rl = (runlist_element*)NULL;
} while (rl && (needed < last_vcn));
ntfs_attr_put_search_ctx(ctx);
/* mark fully mapped if we did so */
if (rl && startseen)
NAttrSetFullyMapped(na);
return (rl ? 0 : -1);
}
#endif
/** /**
* ntfs_attr_map_whole_runlist - map the whole runlist of an ntfs attribute * ntfs_attr_map_whole_runlist - map the whole runlist of an ntfs attribute
* @na: ntfs attribute for which to map the runlist * @na: ntfs attribute for which to map the runlist
@ -1149,9 +1217,27 @@ static int ntfs_attr_fill_hole(ntfs_attr *na, s64 count, s64 *ofs,
"%lld\n", (long long)count, (long long)cur_vcn, "%lld\n", (long long)count, (long long)cur_vcn,
(long long)from_vcn, (long long)to_write, (long long)*ofs); (long long)from_vcn, (long long)to_write, (long long)*ofs);
/* Map whole runlist to be able update mapping pairs later. */ /* Map the runlist to be able to update mapping pairs later. */
#if PARTIAL_RUNLIST_UPDATING
if ((!na->rl
|| !NAttrDataAppending(na))) {
if (ntfs_attr_map_whole_runlist(na))
goto err_out;
} else {
/* make sure the previous non-hole is mapped */
rlc = *rl;
rlc--;
if (((*rl)->lcn == LCN_HOLE)
&& cur_vcn
&& (rlc->vcn < 0)) {
if (ntfs_attr_map_partial_runlist(na, cur_vcn - 1))
goto err_out;
}
}
#else
if (ntfs_attr_map_whole_runlist(na)) if (ntfs_attr_map_whole_runlist(na))
goto err_out; goto err_out;
#endif
/* Restore @*rl, it probably get lost during runlist mapping. */ /* Restore @*rl, it probably get lost during runlist mapping. */
*rl = ntfs_attr_find_vcn(na, cur_vcn); *rl = ntfs_attr_find_vcn(na, cur_vcn);
@ -1510,14 +1596,27 @@ static int borrow_from_hole(ntfs_attr *na, runlist_element **prl,
if (undecided || nothole) { if (undecided || nothole) {
runlist_element *orl = na->rl; runlist_element *orl = na->rl;
s64 olcn = (*prl)->lcn; s64 olcn = (*prl)->lcn;
#if PARTIAL_RUNLIST_UPDATING
VCN prevblock;
#endif
/* /*
* Map the full runlist (needed to compute the * Map the runlist, unless it has not been created.
* compressed size), unless the runlist has not * If appending data, a partial mapping from the
* yet been created (data just made non-resident) * end of previous block will do.
*/ */
irl = *prl - na->rl; irl = *prl - na->rl;
#if PARTIAL_RUNLIST_UPDATING
prevblock = pos >> cluster_size_bits;
if (prevblock)
prevblock--;
if (!NAttrBeingNonResident(na)
&& (NAttrDataAppending(na)
? ntfs_attr_map_partial_runlist(na,prevblock)
: ntfs_attr_map_whole_runlist(na))) {
#else
if (!NAttrBeingNonResident(na) if (!NAttrBeingNonResident(na)
&& ntfs_attr_map_whole_runlist(na)) { && ntfs_attr_map_whole_runlist(na)) {
#endif
rl = (runlist_element*)NULL; rl = (runlist_element*)NULL;
} else { } else {
/* /*
@ -1649,6 +1748,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 "
@ -1703,16 +1803,38 @@ s64 ntfs_attr_pwrite(ntfs_attr *na, const s64 pos, s64 count, const void *b)
fullcount = count; fullcount = count;
/* If the write reaches beyond the end, extend the attribute. */ /* If the write reaches beyond the end, extend the attribute. */
old_data_size = na->data_size; old_data_size = na->data_size;
/* identify whether this is appending to a non resident data attribute */
if ((na->type == AT_DATA) && (pos >= old_data_size)
&& NAttrNonResident(na))
NAttrSetDataAppending(na);
if (pos + count > na->data_size) { if (pos + count > na->data_size) {
#if PARTIAL_RUNLIST_UPDATING
/*
* When appending data, the attribute is first extended
* before being filled with data. This may cause the
* attribute to be made temporarily sparse, which
* implies reformating the inode and reorganizing the
* full runlist. To avoid unnecessary reorganization,
* we delay sparse testing until the data is filled in.
*
* Note : should add a specific argument to truncate()
* instead of the hackish test of a flag...
*/
if (NAttrDataAppending(na))
NAttrSetDelaySparsing(na);
#endif
if (ntfs_attr_truncate(na, pos + count)) { if (ntfs_attr_truncate(na, pos + count)) {
NAttrClearDelaySparsing(na);
ntfs_log_perror("Failed to enlarge attribute"); ntfs_log_perror("Failed to enlarge attribute");
goto errno_set; goto errno_set;
} }
NAttrClearDelaySparsing(na);
/* resizing may change the compression mode */ /* resizing may change the compression mode */
compressed = (na->data_flags & ATTR_COMPRESSION_MASK) compressed = (na->data_flags & ATTR_COMPRESSION_MASK)
!= 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.
@ -1768,8 +1890,29 @@ s64 ntfs_attr_pwrite(ntfs_attr *na, const s64 pos, s64 count, const void *b)
/* Handle writes beyond initialized_size. */ /* Handle writes beyond initialized_size. */
if (pos + count > na->initialized_size) { if (pos + count > na->initialized_size) {
if (ntfs_attr_map_whole_runlist(na)) #if PARTIAL_RUNLIST_UPDATING
goto err_out; /*
* When appending, we only need to map the end of the runlist,
* starting at the last previously allocated run, so that
* we are able a new one to it.
* However, for compressed file, we need the full compression
* block, which may be split in several extents.
*/
if (NAttrDataAppending(na)) {
VCN block_begin = pos >> vol->cluster_size_bits;
if (compressed)
block_begin &= -na->compression_block_clusters;
if (block_begin)
block_begin--;
if (ntfs_attr_map_partial_runlist(na, block_begin))
goto err_out;
if ((update_from == -1) || (block_begin < update_from))
update_from = block_begin;
} else
#endif
if (ntfs_attr_map_whole_runlist(na))
goto err_out;
/* /*
* For a compressed attribute, we must be sure there is an * For a compressed attribute, we must be sure there is an
* available entry, and, when reopening a compressed file, * available entry, and, when reopening a compressed file,
@ -2046,8 +2189,12 @@ done:
* of the mapping list. This makes a difference only if * of the mapping list. This makes a difference only if
* inode extents were needed. * inode extents were needed.
*/ */
#if PARTIAL_RUNLIST_UPDATING
updatemap = NAttrFullyMapped(na) || NAttrDataAppending(na);
#else
updatemap = (compressed updatemap = (compressed
? NAttrFullyMapped(na) != 0 : update_from != -1); ? NAttrFullyMapped(na) != 0 : update_from != -1);
#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))) {
@ -4864,6 +5011,15 @@ static int ntfs_resident_attr_resize_i(ntfs_attr *na, const s64 newsize,
ntfs_attr_close(tna); ntfs_attr_close(tna);
continue; continue;
} }
if ((tna->type == AT_DATA) && !tna->name_len) {
/*
* If we had to make the unnamed data attribute
* non-resident, propagate its new allocated size
* to all name attributes and directory indexes
*/
tna->ni->allocated_size = tna->allocated_size;
NInoFileNameSetDirty(tna->ni);
}
if (((tna->data_flags & ATTR_COMPRESSION_MASK) if (((tna->data_flags & ATTR_COMPRESSION_MASK)
== ATTR_IS_COMPRESSED) == ATTR_IS_COMPRESSED)
&& ntfs_attr_pclose(tna)) { && ntfs_attr_pclose(tna)) {
@ -5204,15 +5360,21 @@ static int ntfs_attr_update_meta(ATTR_RECORD *a, ntfs_attr *na, MFT_RECORD *m,
a->allocated_size = cpu_to_sle64(na->allocated_size); a->allocated_size = cpu_to_sle64(na->allocated_size);
/* Update sparse bit. */ /* Update sparse bit, unless this is an intermediate state */
sparse = ntfs_rl_sparse(na->rl); if (NAttrDelaySparsing(na))
if (sparse == -1) { sparse = (a->flags & ATTR_IS_SPARSE) != const_cpu_to_le16(0);
errno = EIO; else {
goto error; sparse = ntfs_rl_sparse(na->rl);
if (sparse == -1) {
errno = EIO;
goto error;
}
} }
/* Attribute become sparse. */ /* Check whether attribute becomes sparse, unless check is delayed. */
if (sparse && !(a->flags & (ATTR_IS_SPARSE | ATTR_IS_COMPRESSED))) { if (!NAttrDelaySparsing(na)
&& sparse
&& !(a->flags & (ATTR_IS_SPARSE | ATTR_IS_COMPRESSED))) {
/* /*
* Move attribute to another mft record, if attribute is too * Move attribute to another mft record, if attribute is too
* small to add compressed_size field to it and we have no * small to add compressed_size field to it and we have no
@ -5245,6 +5407,7 @@ static int ntfs_attr_update_meta(ATTR_RECORD *a, ntfs_attr *na, MFT_RECORD *m,
NAttrSetSparse(na); NAttrSetSparse(na);
a->flags |= ATTR_IS_SPARSE; a->flags |= ATTR_IS_SPARSE;
na->data_flags = a->flags;
a->compression_unit = STANDARD_COMPRESSION_UNIT; /* Windows a->compression_unit = STANDARD_COMPRESSION_UNIT; /* Windows
set it so, even if attribute is not actually compressed. */ set it so, even if attribute is not actually compressed. */
@ -5278,7 +5441,8 @@ static int ntfs_attr_update_meta(ATTR_RECORD *a, ntfs_attr *na, MFT_RECORD *m,
} }
/* Update compressed size if required. */ /* Update compressed size if required. */
if (sparse || (na->data_flags & ATTR_COMPRESSION_MASK)) { if (NAttrFullyMapped(na)
&& (sparse || (na->data_flags & ATTR_COMPRESSION_MASK))) {
s64 new_compr_size; s64 new_compr_size;
new_compr_size = ntfs_rl_get_compressed_size(na->ni->vol, na->rl); new_compr_size = ntfs_rl_get_compressed_size(na->ni->vol, na->rl);
@ -5338,6 +5502,59 @@ retry:
return -1; return -1;
} }
#if PARTIAL_RUNLIST_UPDATING
/*
* For a file just been made sparse, we will have
* to reformat the first extent, so be sure the
* runlist is fully mapped and fully processed.
* Same if the file was sparse and is not any more.
* Note : not needed if the full runlist is to be processed
*/
if (!NAttrDelaySparsing(na)
&& (!NAttrFullyMapped(na) || from_vcn)
&& !(na->data_flags & ATTR_IS_COMPRESSED)) {
BOOL changed;
if (!(na->data_flags & ATTR_IS_SPARSE)) {
int sparse;
runlist_element *xrl;
/*
* If attribute was not sparse, we only
* have to check whether there is a hole
* in the updated region.
*/
xrl = na->rl;
if (xrl->lcn == LCN_RL_NOT_MAPPED)
xrl++;
sparse = ntfs_rl_sparse(xrl);
if (sparse < 0) {
ntfs_log_error("Could not check whether sparse\n");
errno = EIO;
return (-1);
}
changed = sparse > 0;
} else {
/*
* If attribute was sparse, the compressed
* size has been maintained, and it gives
* and easy way to check whether the
* attribute is still sparse.
*/
changed = (((na->data_size - 1)
| (na->ni->vol->cluster_size - 1)) + 1)
== na->compressed_size;
}
if (changed) {
if (ntfs_attr_map_whole_runlist(na)) {
ntfs_log_error("Could not map whole for sparse change\n");
errno = EIO;
return (-1);
}
from_vcn = 0;
}
}
#endif
if (na->ni->nr_extents == -1) if (na->ni->nr_extents == -1)
base_ni = na->ni->base_ni; base_ni = na->ni->base_ni;
else else
@ -5534,6 +5751,34 @@ retry:
goto put_err_out; goto put_err_out;
} }
} }
/*
* If the base extent was skipped in the above process,
* we still may have to update the sizes.
*/
if (!first_updated) {
le16 spcomp;
ntfs_attr_reinit_search_ctx(ctx);
if (!ntfs_attr_lookup(na->type, na->name, na->name_len,
CASE_SENSITIVE, 0, NULL, 0, ctx)) {
a = ctx->attr;
a->allocated_size = cpu_to_sle64(na->allocated_size);
spcomp = na->data_flags
& (ATTR_IS_COMPRESSED | ATTR_IS_SPARSE);
if (spcomp)
a->compressed_size = cpu_to_sle64(na->compressed_size);
if ((na->type == AT_DATA) && (na->name == AT_UNNAMED)) {
na->ni->allocated_size
= (spcomp
? na->compressed_size
: na->allocated_size);
NInoFileNameSetDirty(na->ni);
}
} else {
ntfs_log_error("Failed to update sizes in base extent\n");
goto put_err_out;
}
}
/* Deallocate not used attribute extents and return with success. */ /* Deallocate not used attribute extents and return with success. */
if (finished_build) { if (finished_build) {
@ -5864,6 +6109,8 @@ static int ntfs_non_resident_attr_expand_i(ntfs_attr *na, const s64 newsize)
return -1; return -1;
} }
if (na->type == AT_DATA)
NAttrSetDataAppending(na);
/* Save for future use. */ /* Save for future use. */
org_alloc_size = na->allocated_size; org_alloc_size = na->allocated_size;
/* The first cluster outside the new allocation. */ /* The first cluster outside the new allocation. */
@ -5874,10 +6121,26 @@ static int ntfs_non_resident_attr_expand_i(ntfs_attr *na, const s64 newsize)
* clusters if there is a change. * clusters if there is a change.
*/ */
if ((na->allocated_size >> vol->cluster_size_bits) < first_free_vcn) { if ((na->allocated_size >> vol->cluster_size_bits) < first_free_vcn) {
#if PARTIAL_RUNLIST_UPDATING
s64 start_update;
/*
* Update from the last previously allocated run,
* as we may have to expand an existing hole.
*/
start_update = na->allocated_size >> vol->cluster_size_bits;
if (start_update)
start_update--;
if (ntfs_attr_map_partial_runlist(na, start_update)) {
ntfs_log_perror("failed to map partial runlist");
return -1;
}
#else
if (ntfs_attr_map_whole_runlist(na)) { if (ntfs_attr_map_whole_runlist(na)) {
ntfs_log_perror("ntfs_attr_map_whole_runlist failed"); ntfs_log_perror("ntfs_attr_map_whole_runlist failed");
return -1; return -1;
} }
#endif
/* /*
* If we extend $DATA attribute on NTFS 3+ volume, we can add * If we extend $DATA attribute on NTFS 3+ volume, we can add
@ -5953,8 +6216,11 @@ static int ntfs_non_resident_attr_expand_i(ntfs_attr *na, const s64 newsize)
/* Prepare to mapping pairs update. */ /* Prepare to mapping pairs update. */
na->allocated_size = first_free_vcn << vol->cluster_size_bits; na->allocated_size = first_free_vcn << vol->cluster_size_bits;
/* Write mapping pairs for new runlist. */ /* Write mapping pairs for new runlist. */
if (ntfs_attr_update_mapping_pairs(na, 0 /*na->allocated_size >> #if PARTIAL_RUNLIST_UPDATING
vol->cluster_size_bits*/)) { if (ntfs_attr_update_mapping_pairs(na, start_update)) {
#else
if (ntfs_attr_update_mapping_pairs(na, 0)) {
#endif
err = errno; err = errno;
ntfs_log_perror("Mapping pairs update failed"); ntfs_log_perror("Mapping pairs update failed");
goto rollback; goto rollback;
@ -6285,6 +6551,89 @@ err_exit:
return ret; return ret;
} }
/*
* Read some data from a data attribute
*
* Returns the amount of data read, negative if there was an error
*/
int ntfs_attr_data_read(ntfs_inode *ni,
ntfschar *stream_name, int stream_name_len,
char *buf, size_t size, off_t offset)
{
ntfs_attr *na = NULL;
int res, total = 0;
na = ntfs_attr_open(ni, AT_DATA, stream_name, stream_name_len);
if (!na) {
res = -errno;
goto exit;
}
if ((size_t)offset < (size_t)na->data_size) {
if (offset + size > (size_t)na->data_size)
size = na->data_size - offset;
while (size) {
res = ntfs_attr_pread(na, offset, size, buf + total);
if ((off_t)res < (off_t)size)
ntfs_log_perror("ntfs_attr_pread partial read "
"(%lld : %lld <> %d)",
(long long)offset,
(long long)size, res);
if (res <= 0) {
res = -errno;
goto exit;
}
size -= res;
offset += res;
total += res;
}
}
res = total;
exit:
if (na)
ntfs_attr_close(na);
return res;
}
/*
* Write some data into a data attribute
*
* Returns the amount of data written, negative if there was an error
*/
int ntfs_attr_data_write(ntfs_inode *ni,
ntfschar *stream_name, int stream_name_len,
char *buf, size_t size, off_t offset)
{
ntfs_attr *na = NULL;
int res, total = 0;
na = ntfs_attr_open(ni, AT_DATA, stream_name, stream_name_len);
if (!na) {
res = -errno;
goto exit;
}
while (size) {
res = ntfs_attr_pwrite(na, offset, size, buf + total);
if (res < (s64)size)
ntfs_log_perror("ntfs_attr_pwrite partial write (%lld: "
"%lld <> %d)", (long long)offset,
(long long)size, res);
if (res <= 0) {
res = -errno;
goto exit;
}
size -= res;
offset += res;
total += res;
}
res = total;
exit:
if (na)
ntfs_attr_close(na);
return res;
}
int ntfs_attr_exist(ntfs_inode *ni, const ATTR_TYPES type, ntfschar *name, int ntfs_attr_exist(ntfs_inode *ni, const ATTR_TYPES type, ntfschar *name,

View File

@ -4,6 +4,7 @@
* Copyright (c) 2000-2004 Anton Altaparmakov * Copyright (c) 2000-2004 Anton Altaparmakov
* Copyright (c) 2004-2005 Yura Pakhuchiy * Copyright (c) 2004-2005 Yura Pakhuchiy
* Copyright (c) 2006-2007 Szabolcs Szakacsits * Copyright (c) 2006-2007 Szabolcs Szakacsits
* Copyright (c) 2010 Jean-Pierre Andre
* *
* This program/include file is free software; you can redistribute it and/or * This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published * modify it under the terms of the GNU General Public License as published
@ -201,6 +202,8 @@ typedef enum {
NA_NonResident, /* 1: Attribute is not resident. */ NA_NonResident, /* 1: Attribute is not resident. */
NA_BeingNonResident, /* 1: Attribute is being made not resident. */ NA_BeingNonResident, /* 1: Attribute is being made not resident. */
NA_FullyMapped, /* 1: Attribute has been fully mapped */ NA_FullyMapped, /* 1: Attribute has been fully mapped */
NA_DataAppending, /* 1: Attribute is being appended to */
NA_DelaySparsing, /* 1: Delay checking attribute being sparse */
NA_ComprClosing, /* 1: Compressed attribute is being closed */ NA_ComprClosing, /* 1: Compressed attribute is being closed */
} ntfs_attr_state_bits; } ntfs_attr_state_bits;
@ -224,6 +227,14 @@ typedef enum {
#define NAttrSetFullyMapped(na) set_nattr_flag(na, FullyMapped) #define NAttrSetFullyMapped(na) set_nattr_flag(na, FullyMapped)
#define NAttrClearFullyMapped(na) clear_nattr_flag(na, FullyMapped) #define NAttrClearFullyMapped(na) clear_nattr_flag(na, FullyMapped)
#define NAttrDataAppending(na) test_nattr_flag(na, DataAppending)
#define NAttrSetDataAppending(na) set_nattr_flag(na, DataAppending)
#define NAttrClearDataAppending(na) clear_nattr_flag(na, DataAppending)
#define NAttrDelaySparsing(na) test_nattr_flag(na, DelaySparsing)
#define NAttrSetDelaySparsing(na) set_nattr_flag(na, DelaySparsing)
#define NAttrClearDelaySparsing(na) clear_nattr_flag(na, DelaySparsing)
#define NAttrComprClosing(na) test_nattr_flag(na, ComprClosing) #define NAttrComprClosing(na) test_nattr_flag(na, ComprClosing)
#define NAttrSetComprClosing(na) set_nattr_flag(na, ComprClosing) #define NAttrSetComprClosing(na) set_nattr_flag(na, ComprClosing)
#define NAttrClearComprClosing(na) clear_nattr_flag(na, ComprClosing) #define NAttrClearComprClosing(na) clear_nattr_flag(na, ComprClosing)
@ -370,6 +381,12 @@ extern int ntfs_attr_exist(ntfs_inode *ni, const ATTR_TYPES type,
extern int ntfs_attr_remove(ntfs_inode *ni, const ATTR_TYPES type, extern int ntfs_attr_remove(ntfs_inode *ni, const ATTR_TYPES type,
ntfschar *name, u32 name_len); ntfschar *name, u32 name_len);
extern s64 ntfs_attr_get_free_bits(ntfs_attr *na); extern s64 ntfs_attr_get_free_bits(ntfs_attr *na);
extern int ntfs_attr_data_read(ntfs_inode *ni,
ntfschar *stream_name, int stream_name_len,
char *buf, size_t size, off_t offset);
extern int ntfs_attr_data_write(ntfs_inode *ni,
ntfschar *stream_name, int stream_name_len,
char *buf, size_t size, off_t offset);
#endif /* defined _NTFS_ATTRIB_H */ #endif /* defined _NTFS_ATTRIB_H */

View File

@ -1,7 +1,7 @@
/** /**
* cache.c : deal with LRU caches * cache.c : deal with LRU caches
* *
* Copyright (c) 2008-2009 Jean-Pierre Andre * Copyright (c) 2008-2010 Jean-Pierre Andre
* *
* This program/include file is free software; you can redistribute it and/or * This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published * modify it under the terms of the GNU General Public License as published
@ -298,7 +298,7 @@ struct CACHED_GENERIC *ntfs_enter_cache(struct CACHE_HEADER *cache,
if (cache->most_recent_entry) if (cache->most_recent_entry)
cache->most_recent_entry->previous = current; cache->most_recent_entry->previous = current;
cache->most_recent_entry = current; cache->most_recent_entry = current;
memcpy(current->fixed, item->fixed, cache->fixed_size); memcpy(current->payload, item->payload, cache->fixed_size);
if (item->varsize) { if (item->varsize) {
if (current->variable) { if (current->variable) {
memcpy(current->variable, memcpy(current->variable,

View File

@ -1,7 +1,7 @@
/* /*
* cache.h : deal with indexed LRU caches * cache.h : deal with indexed LRU caches
* *
* Copyright (c) 2008-2009 Jean-Pierre Andre * Copyright (c) 2008-2010 Jean-Pierre Andre
* *
* This program/include file is free software; you can redistribute it and/or * This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published * modify it under the terms of the GNU General Public License as published
@ -29,11 +29,7 @@ struct CACHED_GENERIC {
struct CACHED_GENERIC *previous; struct CACHED_GENERIC *previous;
void *variable; void *variable;
size_t varsize; size_t varsize;
union { union ALIGNMENT payload[0];
/* force alignment for pointers and u64 */
u64 u64align;
void *ptralign;
} fixed[0];
} ; } ;
struct CACHED_INODE { struct CACHED_INODE {
@ -41,6 +37,7 @@ struct CACHED_INODE {
struct CACHED_INODE *previous; struct CACHED_INODE *previous;
const char *pathname; const char *pathname;
size_t varsize; size_t varsize;
union ALIGNMENT payload[0];
/* above fields must match "struct CACHED_GENERIC" */ /* above fields must match "struct CACHED_GENERIC" */
u64 inum; u64 inum;
} ; } ;
@ -50,6 +47,7 @@ struct CACHED_NIDATA {
struct CACHED_NIDATA *previous; struct CACHED_NIDATA *previous;
const char *pathname; /* not used */ const char *pathname; /* not used */
size_t varsize; /* not used */ size_t varsize; /* not used */
union ALIGNMENT payload[0];
/* above fields must match "struct CACHED_GENERIC" */ /* above fields must match "struct CACHED_GENERIC" */
u64 inum; u64 inum;
ntfs_inode *ni; ntfs_inode *ni;
@ -60,6 +58,7 @@ struct CACHED_LOOKUP {
struct CACHED_LOOKUP *previous; struct CACHED_LOOKUP *previous;
const char *name; const char *name;
size_t namesize; size_t namesize;
union ALIGNMENT payload[0];
/* above fields must match "struct CACHED_GENERIC" */ /* above fields must match "struct CACHED_GENERIC" */
u64 parent; u64 parent;
u64 inum; u64 inum;

View File

@ -62,6 +62,10 @@
#include "logging.h" #include "logging.h"
#include "misc.h" #include "misc.h"
#undef le16_to_cpup
/* the standard le16_to_cpup() crashes for unaligned data on some processors */
#define le16_to_cpup(p) (*(u8*)(p) + (((u8*)(p))[1] << 8))
/** /**
* enum ntfs_compression_constants - constants used in the compression code * enum ntfs_compression_constants - constants used in the compression code
*/ */

View File

@ -298,13 +298,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 2010.8.8" #define PACKAGE_STRING "ntfs-3g 2011.1.15"
/* Define to the one symbol short name of this package. */ /* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "ntfs-3g" #define PACKAGE_TARNAME "ntfs-3g"
/* Define to the version of this package. */ /* Define to the version of this package. */
#define PACKAGE_VERSION "2010.8.8" #define PACKAGE_VERSION "2011.1.15"
/* POSIX ACL support */ /* POSIX ACL support */
#undef POSIXACLS #undef POSIXACLS
@ -347,6 +347,9 @@
first (like Intel and VAX, unlike Motorola and SPARC). */ first (like Intel and VAX, unlike Motorola and SPARC). */
#undef WORDS_LITTLEENDIAN #undef WORDS_LITTLEENDIAN
/* system extended attributes mappings */
#undef XATTR_MAPPINGS
/* Number of bits in a file offset, on hosts where this is settable. */ /* Number of bits in a file offset, on hosts where this is settable. */
#define _FILE_OFFSET_BITS 64 #define _FILE_OFFSET_BITS 64

View File

@ -3,6 +3,7 @@
* *
* Copyright (c) 2004-2006 Anton Altaparmakov * Copyright (c) 2004-2006 Anton Altaparmakov
* Copyright (c) 2004-2006 Szabolcs Szakacsits * Copyright (c) 2004-2006 Szabolcs Szakacsits
* Copyright (c) 2010 Jean-Pierre Andre
* *
* This program/include file is free software; you can redistribute it and/or * This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published * modify it under the terms of the GNU General Public License as published
@ -154,6 +155,25 @@ int ntfs_device_free(struct ntfs_device *dev)
return 0; return 0;
} }
/*
* Sync the device
*
* returns zero if successful.
*/
int ntfs_device_sync(struct ntfs_device *dev)
{
int ret;
struct ntfs_device_operations *dops;
if (NDevDirty(dev)) {
dops = dev->d_ops;
ret = dops->sync(dev);
} else
ret = 0;
return ret;
}
/** /**
* ntfs_pread - positioned read from disk * ntfs_pread - positioned read from disk
* @dev: device to read from * @dev: device to read from
@ -260,6 +280,9 @@ s64 ntfs_pwrite(struct ntfs_device *dev, const s64 pos, s64 count,
total = written; total = written;
break; break;
} }
if (NDevSync(dev) && total && dops->sync(dev)) {
total--; /* on sync error, return partially written */
}
ret = total; ret = total;
out: out:
return ret; return ret;

View File

@ -41,6 +41,7 @@ typedef enum {
ND_ReadOnly, /* 1: Device is read-only. */ ND_ReadOnly, /* 1: Device is read-only. */
ND_Dirty, /* 1: Device is dirty, needs sync. */ ND_Dirty, /* 1: Device is dirty, needs sync. */
ND_Block, /* 1: Device is a block device. */ ND_Block, /* 1: Device is a block device. */
ND_Sync, /* 1: Device is mounted with "-o sync" */
} ntfs_device_state_bits; } ntfs_device_state_bits;
#define test_ndev_flag(nd, flag) test_bit(ND_##flag, (nd)->d_state) #define test_ndev_flag(nd, flag) test_bit(ND_##flag, (nd)->d_state)
@ -63,6 +64,10 @@ typedef enum {
#define NDevSetBlock(nd) set_ndev_flag(nd, Block) #define NDevSetBlock(nd) set_ndev_flag(nd, Block)
#define NDevClearBlock(nd) clear_ndev_flag(nd, Block) #define NDevClearBlock(nd) clear_ndev_flag(nd, Block)
#define NDevSync(nd) test_ndev_flag(nd, Sync)
#define NDevSetSync(nd) set_ndev_flag(nd, Sync)
#define NDevClearSync(nd) clear_ndev_flag(nd, Sync)
/** /**
* struct ntfs_device - * struct ntfs_device -
* *
@ -102,6 +107,7 @@ struct ntfs_device_operations {
extern struct ntfs_device *ntfs_device_alloc(const char *name, const long state, extern struct ntfs_device *ntfs_device_alloc(const char *name, const long state,
struct ntfs_device_operations *dops, void *priv_data); struct ntfs_device_operations *dops, void *priv_data);
extern int ntfs_device_free(struct ntfs_device *dev); extern int ntfs_device_free(struct ntfs_device *dev);
extern int ntfs_device_sync(struct ntfs_device *dev);
extern s64 ntfs_pread(struct ntfs_device *dev, const s64 pos, s64 count, extern s64 ntfs_pread(struct ntfs_device *dev, const s64 pos, s64 count,
void *b); void *b);

View File

@ -356,7 +356,7 @@ u64 ntfs_inode_lookup_by_name(ntfs_inode *dir_ni,
ntfs_attr_put_search_ctx(ctx); ntfs_attr_put_search_ctx(ctx);
if (mref) if (mref)
return mref; return mref;
ntfs_log_debug("Entry not found.\n"); ntfs_log_debug("Entry not found - between root entries.\n");
errno = ENOENT; errno = ENOENT;
return -1; return -1;
} /* Child node present, descend into it. */ } /* Child node present, descend into it. */
@ -1812,7 +1812,7 @@ search:
while (!ntfs_attr_lookup(AT_FILE_NAME, AT_UNNAMED, 0, CASE_SENSITIVE, while (!ntfs_attr_lookup(AT_FILE_NAME, AT_UNNAMED, 0, CASE_SENSITIVE,
0, NULL, 0, actx)) { 0, NULL, 0, actx)) {
char *s; char *s;
BOOL case_sensitive = IGNORE_CASE; IGNORE_CASE_BOOL case_sensitive = IGNORE_CASE;
errno = 0; errno = 0;
fn = (FILE_NAME_ATTR*)((u8*)actx->attr + fn = (FILE_NAME_ATTR*)((u8*)actx->attr +
@ -1844,8 +1844,9 @@ search:
(long long unsigned)MREF_LE(fn->parent_directory)); (long long unsigned)MREF_LE(fn->parent_directory));
continue; continue;
} }
if (case_sensitive_match
if (fn->file_name_type == FILE_NAME_POSIX || case_sensitive_match) || ((fn->file_name_type == FILE_NAME_POSIX)
&& NVolCaseSensitive(ni->vol)))
case_sensitive = CASE_SENSITIVE; case_sensitive = CASE_SENSITIVE;
if (ntfs_names_are_equal(fn->file_name, fn->file_name_length, if (ntfs_names_are_equal(fn->file_name, fn->file_name_length,

View File

@ -481,6 +481,9 @@ ntfs_inode *ntfs_inode_open(ntfs_volume *vol, const MFT_REF mref)
} else { } else {
ni = ntfs_inode_real_open(vol, mref); ni = ntfs_inode_real_open(vol, mref);
} }
if (!ni) {
debug_double_inode(item.inum, 0);
}
#else #else
ni = ntfs_inode_real_open(vol, mref); ni = ntfs_inode_real_open(vol, mref);
#endif #endif
@ -842,6 +845,12 @@ static int ntfs_inode_sync_file_name(ntfs_inode *ni, ntfs_inode *dir_ni)
else { else {
fnx->allocated_size = cpu_to_sle64(ni->allocated_size); fnx->allocated_size = cpu_to_sle64(ni->allocated_size);
fnx->data_size = cpu_to_sle64(ni->data_size); fnx->data_size = cpu_to_sle64(ni->data_size);
/*
* The file name record has also to be fixed if some
* attribute update implied the unnamed data to be
* made non-resident
*/
fn->allocated_size = fnx->allocated_size;
} }
/* update or clear the reparse tag in the index */ /* update or clear the reparse tag in the index */
fnx->reparse_point_tag = reparse_tag; fnx->reparse_point_tag = reparse_tag;

View File

@ -703,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;
@ -717,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;
@ -729,9 +729,10 @@ int ntfs_empty_logfile(ntfs_attr *na)
return -1; return -1;
} }
pos += count; pos += count;
if(pos>=64*1024) break; //only clear first 64kb
} }
NVolSetLogFileEmpty(na->ni->vol); NVolSetLogFileEmpty(na->ni->vol);
return 0; return 0;
} }

View File

@ -3,6 +3,7 @@
* *
* Copyright (c) 2005 Richard Russon * Copyright (c) 2005 Richard Russon
* Copyright (c) 2005-2008 Szabolcs Szakacsits * Copyright (c) 2005-2008 Szabolcs Szakacsits
* Copyright (c) 2010 Jean-Pierre Andre
* *
* This program/include file is free software; you can redistribute it and/or * This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published * modify it under the terms of the GNU General Public License as published
@ -388,6 +389,29 @@ out:
} }
#endif #endif
/*
* Early logging before the logs are redirected
*
* (not quite satisfactory : this appears before the ntfs-g banner,
* and with a different pid)
*/
void ntfs_log_early_error(const char *format, ...)
{
va_list args;
va_start(args, format);
#ifdef HAVE_SYSLOG_H
openlog("ntfs-3g", LOG_PID, LOG_USER);
ntfs_log_handler_syslog(NULL, NULL, 0,
NTFS_LOG_LEVEL_ERROR, NULL,
format, args);
#else
vfprintf(stderr,format,args);
#endif
va_end(args);
}
/** /**
* ntfs_log_handler_fprintf - Basic logging handler * ntfs_log_handler_fprintf - Basic logging handler
* @function: Function in which the log line occurred * @function: Function in which the log line occurred

View File

@ -114,5 +114,8 @@ int ntfs_log_redirect(const char *function, const char *file, int line,
#define ntfs_log_leave(FORMAT, ARGS...)do {} while (0) #define ntfs_log_leave(FORMAT, ARGS...)do {} while (0)
#endif /* DEBUG */ #endif /* DEBUG */
void ntfs_log_early_error(const char *format, ...)
__attribute__((format(printf, 1, 2)));
#endif /* _LOGGING_H_ */ #endif /* _LOGGING_H_ */

View File

@ -186,7 +186,7 @@ int ntfsFindPartitions (const DISC_INTERFACE *interface, sec_t **partitions)
// Read and validate the extended boot record // Read and validate the extended boot record
if (interface->readSectors(ebr_lba + next_erb_lba, 1, &sector)) { if (interface->readSectors(ebr_lba + next_erb_lba, 1, &sector)) {
if (sector.ebr.signature == EBR_SIGNATURE) { if (sector.ebr.signature == EBR_SIGNATURE) {
ntfs_log_debug("Logical Partition @ %d: type 0x%x\n", ebr_lba + next_erb_lba, ntfs_log_debug("Logical Partition @ %d: %s type 0x%x\n", ebr_lba + next_erb_lba,
sector.ebr.partition.status == PARTITION_STATUS_BOOTABLE ? "bootable (active)" : "non-bootable", sector.ebr.partition.status == PARTITION_STATUS_BOOTABLE ? "bootable (active)" : "non-bootable",
sector.ebr.partition.type); sector.ebr.partition.type);
@ -265,9 +265,6 @@ int ntfsFindPartitions (const DISC_INTERFACE *interface, sec_t **partitions)
} }
// Shutdown the device
/*interface->shutdown();*/
// Return the found partitions (if any) // Return the found partitions (if any)
if (partition_count > 0) { if (partition_count > 0) {
*partitions = (sec_t*)ntfs_alloc(sizeof(sec_t) * partition_count); *partitions = (sec_t*)ntfs_alloc(sizeof(sec_t) * partition_count);
@ -560,9 +557,6 @@ void ntfsUnmount (const char *name, bool force)
const char *ntfsGetVolumeName (const char *name) const char *ntfsGetVolumeName (const char *name)
{ {
ntfs_vd *vd = NULL; ntfs_vd *vd = NULL;
//ntfs_attr *na = NULL;
//ntfschar *ulabel = NULL;
//char *volumeName = NULL;
// Sanity check // Sanity check
if (!name) { if (!name) {
@ -577,64 +571,6 @@ const char *ntfsGetVolumeName (const char *name)
return NULL; return NULL;
} }
return vd->vol->vol_name; return vd->vol->vol_name;
/*
// If the volume name has already been cached then just use that
if (vd->name[0])
return vd->name;
// Lock
ntfsLock(vd);
// Check if the volume name attribute exists
na = ntfs_attr_open(vd->vol->vol_ni, AT_VOLUME_NAME, NULL, 0);
if (!na) {
ntfsUnlock(vd);
errno = ENOENT;
return false;
}
// Allocate a buffer to store the raw volume name
ulabel = ntfs_alloc(na->data_size * sizeof(ntfschar));
if (!ulabel) {
ntfsUnlock(vd);
errno = ENOMEM;
return false;
}
// Read the volume name
if (ntfs_attr_pread(na, 0, na->data_size, ulabel) != na->data_size) {
ntfs_free(ulabel);
ntfsUnlock(vd);
errno = EIO;
return false;
}
// Convert the volume name to the current local
if (ntfsUnicodeToLocal(ulabel, na->data_size, &volumeName, 0) < 0) {
errno = EINVAL;
ntfs_free(ulabel);
ntfsUnlock(vd);
return false;
}
// If the volume name was read then cache it (for future fetches)
if (volumeName)
strcpy(vd->name, volumeName);
// Close the volume name attribute
if (na)
ntfs_attr_close(na);
// Clean up
ntfs_free(volumeName);
ntfs_free(ulabel);
// Unlock
ntfsUnlock(vd);
return vd->name;
*/
} }
bool ntfsSetVolumeName (const char *name, const char *volumeName) bool ntfsSetVolumeName (const char *name, const char *volumeName)

View File

@ -91,7 +91,7 @@ void ntfsCloseFile (ntfs_file_state *file)
int ntfs_open_r (struct _reent *r, void *fileStruct, const char *path, int flags, int mode) int ntfs_open_r (struct _reent *r, void *fileStruct, const char *path, int flags, int mode)
{ {
ntfs_log_trace("fileStruct %p, path %s, flags %i, mode %i\n", fileStruct, path, flags, mode); ntfs_log_trace("fileStruct %p, path %s, flags %i, mode %i\n", (void *) fileStruct, path, flags, mode);
ntfs_file_state* file = STATE(fileStruct); ntfs_file_state* file = STATE(fileStruct);
@ -198,7 +198,7 @@ int ntfs_open_r (struct _reent *r, void *fileStruct, const char *path, int flags
file->pos = 0; file->pos = 0;
file->len = file->data_na->data_size; file->len = file->data_na->data_size;
ntfs_log_trace("file->len %d\n", file->len); ntfs_log_trace("file->len %llu\n", file->len);
// Update file times // Update file times
ntfsUpdateTimes(file->vd, file->ni, NTFS_UPDATE_ATIME); ntfsUpdateTimes(file->vd, file->ni, NTFS_UPDATE_ATIME);
@ -222,7 +222,7 @@ int ntfs_open_r (struct _reent *r, void *fileStruct, const char *path, int flags
int ntfs_close_r (struct _reent *r, int fd) int ntfs_close_r (struct _reent *r, int fd)
{ {
ntfs_log_trace("fd %p\n", fd); ntfs_log_trace("fd %p\n", (void *) fd);
ntfs_file_state* file = STATE(fd); ntfs_file_state* file = STATE(fd);
@ -255,7 +255,7 @@ int ntfs_close_r (struct _reent *r, int fd)
ssize_t ntfs_write_r (struct _reent *r, int fd, const char *ptr, size_t len) ssize_t ntfs_write_r (struct _reent *r, int fd, const char *ptr, size_t len)
{ {
ntfs_log_trace("fd %p, ptr %p, len %Li\n", fd, ptr, len); ntfs_log_trace("fd %p, ptr %p, len %u\n", (void *) fd, ptr, len);
ntfs_file_state* file = STATE(fd); ntfs_file_state* file = STATE(fd);
ssize_t written = 0; ssize_t written = 0;
@ -321,7 +321,7 @@ ssize_t ntfs_write_r (struct _reent *r, int fd, const char *ptr, size_t len)
ssize_t ntfs_read_r (struct _reent *r, int fd, char *ptr, size_t len) ssize_t ntfs_read_r (struct _reent *r, int fd, char *ptr, size_t len)
{ {
ntfs_log_trace("fd %p, ptr %p, len %Li\n", fd, ptr, len); ntfs_log_trace("fd %p, ptr %p, len %u\n", (void *) fd, ptr, len);
ntfs_file_state* file = STATE(fd); ntfs_file_state* file = STATE(fd);
ssize_t read = 0; ssize_t read = 0;
@ -380,7 +380,7 @@ ssize_t ntfs_read_r (struct _reent *r, int fd, char *ptr, size_t len)
off_t ntfs_seek_r (struct _reent *r, int fd, off_t pos, int dir) off_t ntfs_seek_r (struct _reent *r, int fd, off_t pos, int dir)
{ {
ntfs_log_trace("fd %p, pos %Li, dir %i\n", fd, pos, dir); ntfs_log_trace("fd %p, pos %llu, dir %i\n", (void *) fd, pos, dir);
ntfs_file_state* file = STATE(fd); ntfs_file_state* file = STATE(fd);
off_t position = 0; off_t position = 0;
@ -408,7 +408,7 @@ off_t ntfs_seek_r (struct _reent *r, int fd, off_t pos, int dir)
} }
int ntfs_fstat_r (struct _reent *r, int fd, struct stat *st) int ntfs_fstat_r (struct _reent *r, int fd, struct stat *st)
{ {
ntfs_log_trace("fd %p\n", fd); ntfs_log_trace("fd %p\n", (void *) fd);
ntfs_file_state* file = STATE(fd); ntfs_file_state* file = STATE(fd);
int ret = 0; int ret = 0;
@ -433,7 +433,7 @@ int ntfs_fstat_r (struct _reent *r, int fd, struct stat *st)
int ntfs_ftruncate_r (struct _reent *r, int fd, off_t len) int ntfs_ftruncate_r (struct _reent *r, int fd, off_t len)
{ {
ntfs_log_trace("fd %p, len %Li\n", fd, len); ntfs_log_trace("fd %p, len %llu\n", (void *) fd, (u64) len);
ntfs_file_state* file = STATE(fd); ntfs_file_state* file = STATE(fd);
@ -500,7 +500,7 @@ int ntfs_ftruncate_r (struct _reent *r, int fd, off_t len)
int ntfs_fsync_r (struct _reent *r, int fd) int ntfs_fsync_r (struct _reent *r, int fd)
{ {
ntfs_log_trace("fd %p\n", fd); ntfs_log_trace("fd %p\n", (void *) fd);
ntfs_file_state* file = STATE(fd); ntfs_file_state* file = STATE(fd);
int ret = 0; int ret = 0;

View File

@ -107,7 +107,11 @@
*/ */
typedef struct { typedef struct {
GUID object_id; union {
/* alignment may be needed to evaluate collations */
u32 alignment;
GUID guid;
} object_id;
} OBJECT_ID_INDEX_KEY; } OBJECT_ID_INDEX_KEY;
typedef struct { typedef struct {

View File

@ -1,7 +1,7 @@
/* /*
* param.h - Parameter values for ntfs-3g * param.h - Parameter values for ntfs-3g
* *
* Copyright (c) 2009 Jean-Pierre Andre * Copyright (c) 2009-2010 Jean-Pierre Andre
* *
* This program/include file is free software; you can redistribute it and/or * This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published * modify it under the terms of the GNU General Public License as published
@ -50,6 +50,20 @@ 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
/*
* Parameters for runlists
*/
/* only update the final extent of a runlist when appending data */
#define PARTIAL_RUNLIST_UPDATING 1
/*
* Parameters for user and xattr mappings
*/
#define XATTRMAPPINGFILE ".NTFS-3G/XattrMapping" /* default mapping file */
/* /*
* Permission checking modes for high level and low level * Permission checking modes for high level and low level
* *
@ -58,7 +72,8 @@ enum {
* *
* Stick to the recommended values unless you understand the consequences * Stick to the recommended values unless you understand the consequences
* on protection and performances. Use of cacheing is good for * on protection and performances. Use of cacheing is good for
* performances, but bad on security. * performances, but bad on security with internal fuse or external
* fuse older than 2.8
* *
* Possible values for high level : * Possible values for high level :
* 1 : no cache, kernel control (recommended) * 1 : no cache, kernel control (recommended)
@ -67,7 +82,7 @@ enum {
* *
* Possible values for low level : * Possible values for low level :
* 2 : no cache, kernel control * 2 : no cache, kernel control
* 3 : use kernel/fuse cache, kernel control * 3 : use kernel/fuse cache, kernel control (external fuse >= 2.8)
* 5 : no cache, file system control (recommended) * 5 : no cache, file system control (recommended)
* 8 : no cache, kernel control for ACLs * 8 : no cache, kernel control for ACLs
* *
@ -77,6 +92,10 @@ enum {
*/ */
#define HPERMSCONFIG 1 #define HPERMSCONFIG 1
#if defined(FUSE_INTERNAL) || !defined(FUSE_VERSION) || (FUSE_VERSION < 28)
#define LPERMSCONFIG 5 #define LPERMSCONFIG 5
#else
#define LPERMSCONFIG 3
#endif
#endif /* defined _NTFS_PARAM_H */ #endif /* defined _NTFS_PARAM_H */

View File

@ -5,7 +5,7 @@
* Copyright (c) 2002-2005 Richard Russon * Copyright (c) 2002-2005 Richard Russon
* Copyright (c) 2002-2008 Szabolcs Szakacsits * Copyright (c) 2002-2008 Szabolcs Szakacsits
* Copyright (c) 2004 Yura Pakhuchiy * Copyright (c) 2004 Yura Pakhuchiy
* Copyright (c) 2007-2009 Jean-Pierre Andre * Copyright (c) 2007-2010 Jean-Pierre Andre
* *
* This program/include file is free software; you can redistribute it and/or * This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published * modify it under the terms of the GNU General Public License as published
@ -101,15 +101,14 @@ static void ntfs_rl_mc(runlist_element *dstbase, int dst,
* On success, return a pointer to the newly allocated, or recycled, memory. * On success, return a pointer to the newly allocated, or recycled, memory.
* On error, return NULL with errno set to the error code. * On error, return NULL with errno set to the error code.
*/ */
#include "mem2.h" static runlist_element *ntfs_rl_realloc(runlist_element *rl, int old_size,
static runlist_element *ntfs_rl_realloc(runlist_element *rl, int old_size,
int new_size) int new_size)
{ {
old_size = (old_size * sizeof(runlist_element) + 0xfff) & ~0xfff; old_size = (old_size * sizeof(runlist_element) + 0xfff) & ~0xfff;
new_size = (new_size * sizeof(runlist_element) + 0xfff) & ~0xfff; new_size = (new_size * sizeof(runlist_element) + 0xfff) & ~0xfff;
if (old_size == new_size) if (old_size == new_size)
return rl; return rl;
return MEM2_realloc(rl, new_size); return realloc(rl, new_size);
} }
/* /*
@ -382,7 +381,7 @@ static runlist_element *ntfs_rl_insert(runlist_element *dst, int dsize,
* left unmodified. * left unmodified.
*/ */
static runlist_element *ntfs_rl_replace(runlist_element *dst, int dsize, static runlist_element *ntfs_rl_replace(runlist_element *dst, int dsize,
runlist_element *src, int ssize, runlist_element *src, int ssize,
int loc) int loc)
{ {
signed delta; signed delta;
@ -503,7 +502,7 @@ static runlist_element *ntfs_rl_split(runlist_element *dst, int dsize,
/** /**
* ntfs_runlists_merge_i - see ntfs_runlists_merge * ntfs_runlists_merge_i - see ntfs_runlists_merge
*/ */
static runlist_element *ntfs_runlists_merge_i(runlist_element *drl, static runlist_element *ntfs_runlists_merge_i(runlist_element *drl,
runlist_element *srl) runlist_element *srl)
{ {
int di, si; /* Current index into @[ds]rl. */ int di, si; /* Current index into @[ds]rl. */
@ -745,8 +744,8 @@ critical_error:
runlist_element *ntfs_runlists_merge(runlist_element *drl, runlist_element *ntfs_runlists_merge(runlist_element *drl,
runlist_element *srl) runlist_element *srl)
{ {
runlist_element *rl; runlist_element *rl;
ntfs_log_enter("Entering\n"); ntfs_log_enter("Entering\n");
rl = ntfs_runlists_merge_i(drl, srl); rl = ntfs_runlists_merge_i(drl, srl);
ntfs_log_leave("\n"); ntfs_log_leave("\n");
@ -836,7 +835,7 @@ static runlist_element *ntfs_mapping_pairs_decompress_i(const ntfs_volume *vol,
runlist_element *rl2; runlist_element *rl2;
rlsize += 0x1000; rlsize += 0x1000;
rl2 = MEM2_realloc(rl, rlsize); rl2 = realloc(rl, rlsize);
if (!rl2) { if (!rl2) {
int eo = errno; int eo = errno;
free(rl); free(rl);
@ -1007,8 +1006,8 @@ err_out:
runlist_element *ntfs_mapping_pairs_decompress(const ntfs_volume *vol, runlist_element *ntfs_mapping_pairs_decompress(const ntfs_volume *vol,
const ATTR_RECORD *attr, runlist_element *old_rl) const ATTR_RECORD *attr, runlist_element *old_rl)
{ {
runlist_element *rle; runlist_element *rle;
ntfs_log_enter("Entering\n"); ntfs_log_enter("Entering\n");
rle = ntfs_mapping_pairs_decompress_i(vol, attr, old_rl); rle = ntfs_mapping_pairs_decompress_i(vol, attr, old_rl);
ntfs_log_leave("\n"); ntfs_log_leave("\n");
@ -1212,10 +1211,10 @@ s64 ntfs_rl_pwrite(const ntfs_volume *vol, const runlist_element *rl,
if (rl->lcn != (LCN)LCN_HOLE) if (rl->lcn != (LCN)LCN_HOLE)
goto rl_err_out; goto rl_err_out;
to_write = min(count, (rl->length << to_write = min(count, (rl->length <<
vol->cluster_size_bits) - ofs); vol->cluster_size_bits) - ofs);
total += to_write; total += to_write;
count -= to_write; count -= to_write;
b = (u8*)b + to_write; b = (u8*)b + to_write;
@ -1385,14 +1384,14 @@ int ntfs_get_size_for_mapping_pairs(const ntfs_volume *vol,
prev_lcn = rl->lcn; prev_lcn = rl->lcn;
} }
} }
out: out:
return rls; return rls;
err_out: err_out:
if (rl->lcn == LCN_RL_NOT_MAPPED) if (rl->lcn == LCN_RL_NOT_MAPPED)
errno = EINVAL; errno = EINVAL;
else else
errno = EIO; errno = EIO;
errno_set: errno_set:
rls = -1; rls = -1;
goto out; goto out;
} }
@ -1419,28 +1418,18 @@ int ntfs_write_significant_bytes(u8 *dst, const u8 *dst_max, const s64 n)
{ {
s64 l = n; s64 l = n;
int i; int i;
s8 j;
i = 0; i = 0;
do { if (dst > dst_max)
goto err_out;
*dst++ = l;
i++;
while ((l > 0x7f) || (l < -0x80)) {
if (dst > dst_max) if (dst > dst_max)
goto err_out; goto err_out;
*dst++ = l & 0xffLL;
l >>= 8; l >>= 8;
*dst++ = l;
i++; i++;
} while (l != 0LL && l != -1LL);
j = (n >> 8 * (i - 1)) & 0xff;
/* If the sign bit is wrong, we need an extra byte. */
if (n < 0LL && j >= 0) {
if (dst > dst_max)
goto err_out;
i++;
*dst = (u8)-1;
} else if (n > 0LL && j < 0) {
if (dst > dst_max)
goto err_out;
i++;
*dst = 0;
} }
return i; return i;
err_out: err_out:
@ -1591,7 +1580,7 @@ int ntfs_mapping_pairs_build(const ntfs_volume *vol, u8 *dst,
/* Set stop vcn. */ /* Set stop vcn. */
if (stop_rl) if (stop_rl)
*stop_rl = rl; *stop_rl = rl;
ok: ok:
/* Add terminator byte. */ /* Add terminator byte. */
*dst = 0; *dst = 0;
out: out:
@ -1645,31 +1634,31 @@ int ntfs_rl_truncate(runlist **arl, const VCN start_vcn)
" arl: %p *arl: %p", arl, *arl); " arl: %p *arl: %p", arl, *arl);
return -1; return -1;
} }
rl = *arl; rl = *arl;
if (start_vcn < rl->vcn) { if (start_vcn < rl->vcn) {
errno = EINVAL; errno = EINVAL;
ntfs_log_perror("Start_vcn lies outside front of runlist"); ntfs_log_perror("Start_vcn lies outside front of runlist");
return -1; return -1;
} }
/* Find the starting vcn in the run list. */ /* Find the starting vcn in the run list. */
while (rl->length) { while (rl->length) {
if (start_vcn < rl[1].vcn) if (start_vcn < rl[1].vcn)
break; break;
rl++; rl++;
} }
if (!rl->length) { if (!rl->length) {
errno = EIO; errno = EIO;
ntfs_log_trace("Truncating already truncated runlist?\n"); ntfs_log_trace("Truncating already truncated runlist?\n");
return -1; return -1;
} }
/* Truncate the run. */ /* Truncate the run. */
rl->length = start_vcn - rl->vcn; rl->length = start_vcn - rl->vcn;
/* /*
* If a run was partially truncated, make the following runlist * If a run was partially truncated, make the following runlist
* element a terminator instead of the truncated runlist * element a terminator instead of the truncated runlist
@ -1685,10 +1674,10 @@ int ntfs_rl_truncate(runlist **arl, const VCN start_vcn)
rl->lcn = (LCN)LCN_ENOENT; rl->lcn = (LCN)LCN_ENOENT;
/** /**
* 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 multiply of 4096. The code caused crashes and corruptions. * a multiply of 4096. The code caused crashes and corruptions.
*/ */
/* /*
if (!is_end) { if (!is_end) {
size_t new_size = (rl - *arl + 1) * sizeof(runlist_element); size_t new_size = (rl - *arl + 1) * sizeof(runlist_element);
rl = realloc(*arl, new_size); rl = realloc(*arl, new_size);
@ -1901,7 +1890,7 @@ static runlist_element * test_rl_pure_src(BOOL contig, BOOL multi, int vcn, int
result = ntfs_malloc(4096); result = ntfs_malloc(4096);
if (!result) if (!result)
return NULL; return NULL;
if (multi) { if (multi) {
MKRL(result+0, vcn + (0*len/4), fudge + vcn + 1000 + (0*len/4), len / 4) MKRL(result+0, vcn + (0*len/4), fudge + vcn + 1000 + (0*len/4), len / 4)
MKRL(result+1, vcn + (1*len/4), fudge + vcn + 1000 + (1*len/4), len / 4) MKRL(result+1, vcn + (1*len/4), fudge + vcn + 1000 + (1*len/4), len / 4)

View File

@ -4,7 +4,7 @@
* Copyright (c) 2004 Anton Altaparmakov * Copyright (c) 2004 Anton Altaparmakov
* Copyright (c) 2005-2006 Szabolcs Szakacsits * Copyright (c) 2005-2006 Szabolcs Szakacsits
* Copyright (c) 2006 Yura Pakhuchiy * Copyright (c) 2006 Yura Pakhuchiy
* Copyright (c) 2007-2009 Jean-Pierre Andre * Copyright (c) 2007-2010 Jean-Pierre Andre
* *
* This program/include file is free software; you can redistribute it and/or * This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published * modify it under the terms of the GNU General Public License as published
@ -404,91 +404,6 @@ le32 ntfs_security_hash(const SECURITY_DESCRIPTOR_RELATIVE *sd, const u32 len)
return cpu_to_le32(hash); return cpu_to_le32(hash);
} }
/*
* Internal read
* copied and pasted from ntfs_fuse_read() and made independent
* of fuse context
*/
static int ntfs_local_read(ntfs_inode *ni,
ntfschar *stream_name, int stream_name_len,
char *buf, size_t size, off_t offset)
{
ntfs_attr *na = NULL;
int res, total = 0;
na = ntfs_attr_open(ni, AT_DATA, stream_name, stream_name_len);
if (!na) {
res = -errno;
goto exit;
}
if ((size_t)offset < (size_t)na->data_size) {
if (offset + size > (size_t)na->data_size)
size = na->data_size - offset;
while (size) {
res = ntfs_attr_pread(na, offset, size, buf);
if ((off_t)res < (off_t)size)
ntfs_log_perror("ntfs_attr_pread partial read "
"(%lld : %lld <> %d)",
(long long)offset,
(long long)size, res);
if (res <= 0) {
res = -errno;
goto exit;
}
size -= res;
offset += res;
total += res;
}
}
res = total;
exit:
if (na)
ntfs_attr_close(na);
return res;
}
/*
* Internal write
* copied and pasted from ntfs_fuse_write() and made independent
* of fuse context
*/
static int ntfs_local_write(ntfs_inode *ni,
ntfschar *stream_name, int stream_name_len,
char *buf, size_t size, off_t offset)
{
ntfs_attr *na = NULL;
int res, total = 0;
na = ntfs_attr_open(ni, AT_DATA, stream_name, stream_name_len);
if (!na) {
res = -errno;
goto exit;
}
while (size) {
res = ntfs_attr_pwrite(na, offset, size, buf);
if (res < (s64)size)
ntfs_log_perror("ntfs_attr_pwrite partial write (%lld: "
"%lld <> %d)", (long long)offset,
(long long)size, res);
if (res <= 0) {
res = -errno;
goto exit;
}
size -= res;
offset += res;
total += res;
}
res = total;
exit:
if (na)
ntfs_attr_close(na);
return res;
}
/* /*
* Get the first entry of current index block * Get the first entry of current index block
* cut and pasted form ntfs_ie_get_first() in index.c * cut and pasted form ntfs_ie_get_first() in index.c
@ -531,7 +446,7 @@ static int entersecurity_stuff(ntfs_volume *vol, off_t offs)
if (stuff) { if (stuff) {
memset(stuff, 0, STUFFSZ); memset(stuff, 0, STUFFSZ);
do { do {
written = ntfs_local_write(vol->secure_ni, written = ntfs_attr_data_write(vol->secure_ni,
STREAM_SDS, 4, stuff, STUFFSZ, offs); STREAM_SDS, 4, stuff, STUFFSZ, offs);
if (written == STUFFSZ) { if (written == STUFFSZ) {
total += STUFFSZ; total += STUFFSZ;
@ -589,10 +504,10 @@ static int entersecurity_data(ntfs_volume *vol,
phsds->security_id = keyid; phsds->security_id = keyid;
phsds->offset = cpu_to_le64(offs); phsds->offset = cpu_to_le64(offs);
phsds->length = cpu_to_le32(fullsz - gap); phsds->length = cpu_to_le32(fullsz - gap);
written1 = ntfs_local_write(vol->secure_ni, written1 = ntfs_attr_data_write(vol->secure_ni,
STREAM_SDS, 4, fullattr, fullsz, STREAM_SDS, 4, fullattr, fullsz,
offs - gap); offs - gap);
written2 = ntfs_local_write(vol->secure_ni, written2 = ntfs_attr_data_write(vol->secure_ni,
STREAM_SDS, 4, fullattr, fullsz, STREAM_SDS, 4, fullattr, fullsz,
offs - gap + ALIGN_SDS_BLOCK); offs - gap + ALIGN_SDS_BLOCK);
if ((written1 == fullsz) if ((written1 == fullsz)
@ -950,7 +865,7 @@ static le32 setsecurityattr(ntfs_volume *vol,
+ sizeof(SECURITY_DESCRIPTOR_HEADER); + sizeof(SECURITY_DESCRIPTOR_HEADER);
oldattr = (char*)ntfs_malloc(size); oldattr = (char*)ntfs_malloc(size);
if (oldattr) { if (oldattr) {
rdsize = ntfs_local_read( rdsize = ntfs_attr_data_read(
vol->secure_ni, vol->secure_ni,
STREAM_SDS, 4, STREAM_SDS, 4,
oldattr, size, offs); oldattr, size, offs);
@ -1772,7 +1687,7 @@ static char *retrievesecurityattr(ntfs_volume *vol, SII_INDEX_KEY id)
securattr = (char*)ntfs_malloc(size); securattr = (char*)ntfs_malloc(size);
if (securattr) { if (securattr) {
rdsize = ntfs_local_read( rdsize = ntfs_attr_data_read(
ni, STREAM_SDS, 4, ni, STREAM_SDS, 4,
securattr, size, offs); securattr, size, offs);
if ((rdsize != size) if ((rdsize != size)
@ -3891,7 +3806,7 @@ le32 ntfs_inherited_id(struct SECURITY_CONTEXT *scx,
* *
* Returns 0 if OK, -1 (and errno set) if error * Returns 0 if OK, -1 (and errno set) if error
*/ */
#include "mem2.h"
static int link_single_group(struct MAPPING *usermapping, struct passwd *user, static int link_single_group(struct MAPPING *usermapping, struct passwd *user,
gid_t gid) gid_t gid)
{ {
@ -4097,7 +4012,7 @@ static int basicread(void *fileid, char *buf, size_t size, off_t offs __attribut
static int localread(void *fileid, char *buf, size_t size, off_t offs) static int localread(void *fileid, char *buf, size_t size, off_t offs)
{ {
return (ntfs_local_read((ntfs_inode*)fileid, return (ntfs_attr_data_read((ntfs_inode*)fileid,
AT_UNNAMED, 0, buf, size, offs)); AT_UNNAMED, 0, buf, size, offs));
} }
@ -4919,7 +4834,7 @@ int ntfs_read_sds(struct SECURITY_API *scapi,
got = -1; /* default return */ got = -1; /* default return */
if (scapi && (scapi->magic == MAGIC_API)) { if (scapi && (scapi->magic == MAGIC_API)) {
if (scapi->security.vol->secure_ni) if (scapi->security.vol->secure_ni)
got = ntfs_local_read(scapi->security.vol->secure_ni, got = ntfs_attr_data_read(scapi->security.vol->secure_ni,
STREAM_SDS, 4, buf, size, offset); STREAM_SDS, 4, buf, size, offset);
else else
errno = EOPNOTSUPP; errno = EOPNOTSUPP;

View File

@ -4,7 +4,7 @@
* *
* Copyright (c) 2004 Anton Altaparmakov * Copyright (c) 2004 Anton Altaparmakov
* Copyright (c) 2005-2006 Szabolcs Szakacsits * Copyright (c) 2005-2006 Szabolcs Szakacsits
* Copyright (c) 2007-2008 Jean-Pierre Andre * Copyright (c) 2007-2010 Jean-Pierre Andre
* *
* This program/include file is free software; you can redistribute it and/or * This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published * modify it under the terms of the GNU General Public License as published
@ -85,6 +85,7 @@ struct CACHED_PERMISSIONS_LEGACY {
struct CACHED_PERMISSIONS_LEGACY *previous; struct CACHED_PERMISSIONS_LEGACY *previous;
void *variable; void *variable;
size_t varsize; size_t varsize;
union ALIGNMENT payload[0];
/* above fields must match "struct CACHED_GENERIC" */ /* above fields must match "struct CACHED_GENERIC" */
u64 mft_no; u64 mft_no;
struct CACHED_PERMISSIONS perm; struct CACHED_PERMISSIONS perm;
@ -99,6 +100,7 @@ struct CACHED_SECURID {
struct CACHED_SECURID *previous; struct CACHED_SECURID *previous;
void *variable; void *variable;
size_t varsize; size_t varsize;
union ALIGNMENT payload[0];
/* above fields must match "struct CACHED_GENERIC" */ /* above fields must match "struct CACHED_GENERIC" */
uid_t uid; uid_t uid;
gid_t gid; gid_t gid;
@ -181,6 +183,7 @@ struct POSIX_SECURITY {
int defcnt; int defcnt;
int firstdef; int firstdef;
u16 tagsset; u16 tagsset;
s32 alignment[0];
struct POSIX_ACL acl; struct POSIX_ACL acl;
} ; } ;

View File

@ -129,5 +129,13 @@ typedef enum {
#define STATUS_KEEP_SEARCHING (-3) #define STATUS_KEEP_SEARCHING (-3)
#define STATUS_NOT_FOUND (-4) #define STATUS_NOT_FOUND (-4)
/*
* Force alignment in a struct if required by processor
*/
union ALIGNMENT {
u64 u64align;
void *ptralign;
} ;
#endif /* defined _NTFS_TYPES_H */ #endif /* defined _NTFS_TYPES_H */

View File

@ -3,7 +3,7 @@
* *
* Copyright (c) 2000-2004 Anton Altaparmakov * Copyright (c) 2000-2004 Anton Altaparmakov
* Copyright (c) 2002-2009 Szabolcs Szakacsits * Copyright (c) 2002-2009 Szabolcs Szakacsits
* Copyright (c) 2008-2009 Jean-Pierre Andre * Copyright (c) 2008-2010 Jean-Pierre Andre
* Copyright (c) 2008 Bernhard Kaindl * Copyright (c) 2008 Bernhard Kaindl
* *
* This program/include file is free software; you can redistribute it and/or * This program/include file is free software; you can redistribute it and/or
@ -166,24 +166,22 @@ int ntfs_names_full_collate(const ntfschar *name1, const u32 name1_len,
cnt = min(name1_len, name2_len); cnt = min(name1_len, name2_len);
if (cnt > 0) { if (cnt > 0) {
if (ic == CASE_SENSITIVE) { if (ic == CASE_SENSITIVE) {
do { while (--cnt && (*name1 == *name2)) {
c1 = le16_to_cpu(*name1);
name1++; name1++;
c2 = le16_to_cpu(*name2);
name2++; name2++;
} while (--cnt && (c1 == c2)); }
u1 = c1; u1 = c1 = le16_to_cpu(*name1);
u2 = c2; u2 = c2 = le16_to_cpu(*name2);
if (u1 < upcase_len) if (u1 < upcase_len)
u1 = le16_to_cpu(upcase[u1]); u1 = le16_to_cpu(upcase[u1]);
if (u2 < upcase_len) if (u2 < upcase_len)
u2 = le16_to_cpu(upcase[u2]); u2 = le16_to_cpu(upcase[u2]);
if ((u1 == u2) && cnt) if ((u1 == u2) && cnt)
do { do {
u1 = le16_to_cpu(*name1);
name1++; name1++;
u2 = le16_to_cpu(*name2); u1 = le16_to_cpu(*name1);
name2++; name2++;
u2 = le16_to_cpu(*name2);
if (u1 < upcase_len) if (u1 < upcase_len)
u1 = le16_to_cpu(upcase[u1]); u1 = le16_to_cpu(upcase[u1]);
if (u2 < upcase_len) if (u2 < upcase_len)

View File

@ -868,6 +868,7 @@ ntfs_volume *ntfs_device_mount(struct ntfs_device *dev, unsigned long flags)
VOLUME_INFORMATION *vinf; VOLUME_INFORMATION *vinf;
ntfschar *vname; ntfschar *vname;
int i, j, eo; int i, j, eo;
unsigned int k;
u32 u; u32 u;
vol = ntfs_volume_startup(dev, flags); vol = ntfs_volume_startup(dev, flags);
@ -1025,6 +1026,17 @@ ntfs_volume *ntfs_device_mount(struct ntfs_device *dev, unsigned long flags)
ntfs_log_perror("Failed to close $UpCase"); ntfs_log_perror("Failed to close $UpCase");
goto error_exit; goto error_exit;
} }
/* Consistency check of $UpCase, restricted to plain ASCII chars */
k = 0x20;
while ((k < vol->upcase_len)
&& (k < 0x7f)
&& (le16_to_cpu(vol->upcase[k])
== ((k < 'a') || (k > 'z') ? k : k + 'A' - 'a')))
k++;
if (k < 0x7f) {
ntfs_log_error("Corrupted file $UpCase\n");
goto io_error_exit;
}
/* /*
* Now load $Volume and set the version information and flags in the * Now load $Volume and set the version information and flags in the

View File

@ -5,6 +5,7 @@
* Copyright (c) 2004-2005 Richard Russon * Copyright (c) 2004-2005 Richard Russon
* Copyright (c) 2005-2006 Yura Pakhuchiy * Copyright (c) 2005-2006 Yura Pakhuchiy
* Copyright (c) 2005-2009 Szabolcs Szakacsits * Copyright (c) 2005-2009 Szabolcs Szakacsits
* Copyright (c) 2010 Jean-Pierre Andre
* *
* This program/include file is free software; you can redistribute it and/or * This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published * modify it under the terms of the GNU General Public License as published
@ -251,7 +252,9 @@ struct _ntfs_volume {
s64 free_mft_records; /* Same for free mft records (see above) */ s64 free_mft_records; /* Same for free mft records (see above) */
BOOL efs_raw; /* volume is mounted for raw access to BOOL efs_raw; /* volume is mounted for raw access to
efs-encrypted files */ efs-encrypted files */
#ifdef XATTR_MAPPINGS
struct XATTRMAPPING *xattr_mapping;
#endif /* XATTR_MAPPINGS */
#if CACHE_INODE_SIZE #if CACHE_INODE_SIZE
struct CACHE_HEADER *xinode_cache; struct CACHE_HEADER *xinode_cache;
#endif #endif

77
libcustomntfs/xattrs.h Normal file
View File

@ -0,0 +1,77 @@
/*
* xattrs.h : definitions related to system extended attributes
*
* Copyright (c) 2010 Jean-Pierre Andre
*
* This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
* by the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program/include file is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program (in the main directory of the NTFS-3G
* distribution in the file COPYING); if not, write to the Free Software
* Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _NTFS_XATTR_H_
#define _NTFS_XATTR_H_
/*
* Identification of data mapped to the system name space
*/
enum SYSTEMXATTRS {
XATTR_UNMAPPED,
XATTR_NTFS_ACL,
XATTR_NTFS_ATTRIB,
XATTR_NTFS_ATTRIB_BE,
XATTR_NTFS_EFSINFO,
XATTR_NTFS_REPARSE_DATA,
XATTR_NTFS_OBJECT_ID,
XATTR_NTFS_DOS_NAME,
XATTR_NTFS_TIMES,
XATTR_NTFS_TIMES_BE,
XATTR_NTFS_CRTIME,
XATTR_NTFS_CRTIME_BE,
XATTR_POSIX_ACC,
XATTR_POSIX_DEF
} ;
struct XATTRMAPPING {
struct XATTRMAPPING *next;
enum SYSTEMXATTRS xattr;
char name[1]; /* variable length */
} ;
#ifdef XATTR_MAPPINGS
struct XATTRMAPPING *ntfs_xattr_build_mapping(ntfs_volume *vol,
const char *path);
void ntfs_xattr_free_mapping(struct XATTRMAPPING*);
#endif /* XATTR_MAPPINGS */
enum SYSTEMXATTRS ntfs_xattr_system_type(const char *name,
ntfs_volume *vol);
int ntfs_xattr_listxattr(ntfs_inode *ni, ntfs_attr_search_ctx *actx,
char *list, size_t size, BOOL prefixing);
int ntfs_xattr_system_getxattr(struct SECURITY_CONTEXT *scx,
enum SYSTEMXATTRS attr,
ntfs_inode *ni, ntfs_inode *dir_ni,
char *value, size_t size);
int ntfs_xattr_system_setxattr(struct SECURITY_CONTEXT *scx,
enum SYSTEMXATTRS attr,
ntfs_inode *ni, ntfs_inode *dir_ni,
const char *value, size_t size, int flags);
int ntfs_xattr_system_removexattr(struct SECURITY_CONTEXT *scx,
enum SYSTEMXATTRS attr,
ntfs_inode *ni, ntfs_inode *dir_ni);
#endif /* _NTFS_XATTR_H_ */