mirror of
https://github.com/wiidev/usbloadergx.git
synced 2024-11-15 16:05:10 +01:00
*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:
parent
9d46977121
commit
718245adcd
@ -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)
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
@ -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 */
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
*/
|
*/
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
@ -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,
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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_ */
|
||||||
|
|
||||||
|
@ -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, §or)) {
|
if (interface->readSectors(ebr_lba + next_erb_lba, 1, §or)) {
|
||||||
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)
|
||||||
|
@ -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;
|
||||||
|
@ -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 {
|
||||||
|
@ -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 */
|
||||||
|
@ -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)
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
|
@ -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 */
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
@ -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
77
libcustomntfs/xattrs.h
Normal 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_ */
|
Loading…
Reference in New Issue
Block a user