patch-2.4.7 linux/fs/ntfs/attr.c
Next file: linux/fs/ntfs/attr.h
Previous file: linux/fs/ntfs/Makefile
Back to the patch index
Back to the overall index
- Lines: 728
- Date:
Mon Jul 16 15:14:10 2001
- Orig file:
v2.4.6/linux/fs/ntfs/attr.c
- Orig date:
Wed Apr 18 11:49:13 2001
diff -u --recursive --new-file v2.4.6/linux/fs/ntfs/attr.c linux/fs/ntfs/attr.c
@@ -1,10 +1,11 @@
-/* attr.c
+/*
+ * attr.c
*
- * Copyright (C) 1996-1999 Martin von Löwis
- * Copyright (C) 1996-1997 Régis Duchesne
- * Copyright (C) 1998 Joseph Malicki
- * Copyright (C) 1999 Steve Dodd
- * Copyright (C) 2001 Anton Altaparmakov (AIA)
+ * Copyright (C) 1996-1999 Martin von Löwis
+ * Copyright (C) 1996-1997 Régis Duchesne
+ * Copyright (C) 1998 Joseph Malicki
+ * Copyright (C) 1999 Steve Dodd
+ * Copyright (C) 2001 Anton Altaparmakov (AIA)
*/
#include "ntfstypes.h"
@@ -17,37 +18,156 @@
#include "util.h"
#include "super.h"
#include "inode.h"
+#include "unistr.h"
+
+/**
+ * ntfs_find_attr_in_mft_rec - find attribute in mft record
+ * @vol: volume on which attr resides
+ * @m: mft record to search
+ * @type: attribute type to find
+ * @name: attribute name to find (optional, i.e. NULL means don't care)
+ * @name_len: attribute name length (only needed if @name present)
+ * @ic: ignore case if 1 or case sensitive if 0 (ignored if @name NULL)
+ * @instance: instance number to find
+ *
+ * Only search the specified mft record and it ignores the presence of an
+ * attribute list attribute (unless it is the one being searched for,
+ * obviously, in which case it is returned).
+ */
+ntfs_u8* ntfs_find_attr_in_mft_rec(ntfs_volume *vol, ntfs_u8 *m, __u32 type,
+ wchar_t *name, __u32 name_len, int ic, __u16 instance)
+{
+ ntfs_u8 *a;
+
+ /* Iterate over attributes in mft record @m. */
+ a = m + NTFS_GETU16(m + 20); /* attrs_offset */
+ for (; a >= m && a <= m + vol->mft_record_size;
+ a += NTFS_GETU32(a + 4 /* length */)) {
+ /* We catch $END with this more general check, too... */
+ if (NTFS_GETU32(a + 0 /* type */) > type)
+ return NULL;
+ if (!NTFS_GETU32(a + 4 /* length */))
+ break;
+ if (NTFS_GETU32(a + 0 /* type */) != type)
+ continue;
+ /* If @name is present, compare the two names. */
+ if (name && !ntfs_are_names_equal(name, name_len, (wchar_t*)
+ (a + NTFS_GETU16(a + 10 /* name_offset */)),
+ a[9] /* name_length */, ic, vol->upcase,
+ vol->upcase_length)) {
+ register int rc;
+
+ rc = ntfs_collate_names(vol->upcase, vol->upcase_length,
+ name, name_len, (wchar_t*)(a +
+ NTFS_GETU16(a + 10 /* name_offset */)),
+ a[9] /* name_length */, 1, 1);
+ /*
+ * If @name collates before a->name, there is no
+ * matching attribute.
+ */
+ if (rc == -1)
+ return NULL;
+ /* If the strings are not equal, continue search. */
+ if (rc)
+ continue;
+ rc = ntfs_collate_names(vol->upcase, vol->upcase_length,
+ name, name_len, (wchar_t*)(a +
+ NTFS_GETU16(a + 10 /* name_offset */)),
+ a[9] /* name_length */, 0, 1);
+ if (rc == -1)
+ return NULL;
+ if (rc)
+ continue;
+ }
+ /*
+ * The names match or @name not present. Check instance number.
+ * and if it matches we have found the attribute and are done.
+ */
+ if (instance != NTFS_GETU16(a + 14 /* instance */))
+ continue;
+ ntfs_debug(DEBUG_FILE3, "ntfs_find_attr_in_mft_record: found: "
+ "attr type 0x%x, instance number = 0x%x.\n",
+ NTFS_GETU32(a + 0), instance);
+ return a;
+ }
+ ntfs_error("ntfs_find_attr_in_mft_record: mft record 0x%x is corrupt"
+ ". Run chkdsk.\n", m);
+ return NULL;
+}
/* Look if an attribute already exists in the inode, and if not, create it. */
-int ntfs_new_attr(ntfs_inode *ino, int type, void *name, int namelen, int *pos,
- int *found, int do_search)
+int ntfs_new_attr(ntfs_inode *ino, int type, void *name, int namelen,
+ void *value, int value_len, int *pos, int *found)
{
int do_insert = 0;
- int i;
+ int i, m;
+ ntfs_attribute *a;
for (i = 0; i < ino->attr_count; i++)
{
- int n = min(namelen, ino->attrs[i].namelen);
- int s = ntfs_uni_strncmp(ino->attrs[i].name, name, n);
- if (do_search) {
- /* We assume that each attribute can be uniquely
- * identified by inode number, attribute type and
- * attribute name. */
- if (ino->attrs[i].type == type &&
- ino->attrs[i].namelen == namelen && !s) {
- *found = 1;
- *pos = i;
- return 0;
- }
- }
- /* Attributes are ordered by type, then by name. */
- if (ino->attrs[i].type > type ||
- (ino->attrs[i].type == type && s == 1)) {
+ a = ino->attrs + i;
+ if (a->type < type)
+ continue;
+ if (a->type > type) {
do_insert = 1;
break;
}
+ /* If @name is present, compare the two names. */
+ if (namelen && !ntfs_are_names_equal((wchar_t*)name, namelen,
+ a->name, a->namelen /* name_length */,
+ 1 /* ignore case*/, ino->vol->upcase,
+ ino->vol->upcase_length)) {
+ register int rc;
+
+ rc = ntfs_collate_names(ino->vol->upcase,
+ ino->vol->upcase_length, a->name,
+ a->namelen, (wchar_t*)name, namelen,
+ 1 /* ignore case */, 1);
+ if (rc == -1)
+ continue;
+ if (rc == 1) {
+ do_insert = 1;
+ break;
+ }
+ rc = ntfs_collate_names(ino->vol->upcase,
+ ino->vol->upcase_length, a->name,
+ a->namelen, (wchar_t*)name, namelen,
+ 0 /* case sensitive */, 1);
+ if (rc == -1)
+ continue;
+ if (rc == 1) {
+ do_insert = 1;
+ break;
+ }
+ }
+ /* Names are equal or no name was asked for. */
+ /* If a value was specified compare the values. */
+ if (value_len && a->resident) {
+ if (!a->resident) {
+ ntfs_error("ntfs_new_attr: Value specified but "
+ "attribute non-resident. Bug!\n");
+ return -EINVAL;
+ }
+ m = memcmp(value, a->d.data, min(value_len, a->size));
+ if (m > 0)
+ continue;
+ if (m < 0) {
+ do_insert = 1;
+ break;
+ }
+ /* Values match until min of value lengths. */
+ if (value_len > a->size)
+ continue;
+ if (value_len < a->size) {
+ do_insert = 1;
+ break;
+ }
+ }
+ /* Full match! */
+ *found = 1;
+ *pos = i;
+ return 0;
}
-
/* Re-allocate space. */
if (ino->attr_count % 8 == 0)
{
@@ -77,7 +197,7 @@
int ntfs_make_attr_resident(ntfs_inode *ino, ntfs_attribute *attr)
{
- int size = attr->size;
+ __s64 size = attr->size;
if (size > 0) {
/* FIXME: read data, free clusters */
return -EOPNOTSUPP;
@@ -87,19 +207,35 @@
}
/* Store in the inode readable information about a run. */
-void ntfs_insert_run(ntfs_attribute *attr, int cnum, ntfs_cluster_t cluster,
+int ntfs_insert_run(ntfs_attribute *attr, int cnum, ntfs_cluster_t cluster,
int len)
{
/* (re-)allocate space if necessary. */
- if (attr->d.r.len % 8 == 0) {
+ if ((attr->d.r.len * sizeof(ntfs_runlist)) % PAGE_SIZE == 0) {
ntfs_runlist* new;
- new = ntfs_malloc((attr->d.r.len + 8) * sizeof(ntfs_runlist));
- if (!new)
- return;
+ unsigned long new_size;
+
+ ntfs_debug(DEBUG_MALLOC, "ntfs_insert_run: re-allocating "
+ "space: old attr->d.r.len = 0x%x\n",
+ attr->d.r.len);
+ new_size = attr->d.r.len * sizeof(ntfs_runlist) + PAGE_SIZE;
+ if ((new_size >> PAGE_SHIFT) > num_physpages) {
+ ntfs_error("ntfs_insert_run: attempted to allocate "
+ "more pages than num_physpages."
+ "This might be a bug or a corrupt"
+ "file system.\n");
+ return -1;
+ }
+ new = ntfs_vmalloc(new_size);
+ if (!new) {
+ ntfs_error("ntfs_insert_run: ntfs_vmalloc(new_size = "
+ "0x%x) failed\n", new_size);
+ return -1;
+ }
if (attr->d.r.runlist) {
ntfs_memcpy(new, attr->d.r.runlist, attr->d.r.len
* sizeof(ntfs_runlist));
- ntfs_free(attr->d.r.runlist);
+ ntfs_vfree(attr->d.r.runlist);
}
attr->d.r.runlist = new;
}
@@ -110,6 +246,7 @@
attr->d.r.runlist[cnum].cluster = cluster;
attr->d.r.runlist[cnum].len = len;
attr->d.r.len++;
+ return 0;
}
/* Extends an attribute. Another run will be added if necessary, but we try to
@@ -119,7 +256,7 @@
*
* *len: the desired new length of the attr (_not_ the amount to extend by)
*/
-int ntfs_extend_attr(ntfs_inode *ino, ntfs_attribute *attr, int *len, int flags)
+int ntfs_extend_attr(ntfs_inode *ino, ntfs_attribute *attr, __s64 *len, int flags)
{
int error = 0;
ntfs_runlist *rl;
@@ -145,8 +282,8 @@
cluster = 0;
/* Calculate the extra space we need, and round up to multiple of
* cluster size to get number of new clusters needed */
- clen = ((*len - attr->allocated) + ino->vol->clustersize - 1) /
- ino->vol->clustersize;
+ clen = ((*len - attr->allocated) + ino->vol->cluster_size - 1) >>
+ ino->vol->cluster_size_bits;
if (clen == 0)
return 0;
/* FIXME: try to allocate smaller pieces */
@@ -154,13 +291,17 @@
flags | ALLOC_REQUIRE_SIZE);
if (error)
return error;
- attr->allocated += clen * ino->vol->clustersize;
+ attr->allocated += (__s64)clen << ino->vol->cluster_size_bits;
*len = attr->allocated;
/* Contiguous chunk. */
if (rlen >= 0 && cluster == rl[rlen].cluster + rl[rlen].len) {
rl[rlen].len += clen;
return 0;
}
+ /*
+ * FIXME: if ntfs_insert_run fails we need to deallocate the cluster
+ * to revert to state before we were called...
+ */
ntfs_insert_run(attr, rlen + 1, cluster, clen);
return 0;
}
@@ -168,13 +309,14 @@
int ntfs_make_attr_nonresident(ntfs_inode *ino, ntfs_attribute *attr)
{
void *data = attr->d.data;
- int len = attr->size;
- int error, alen;
+ __s64 len = attr->size;
+ int error;
+ __s64 alen;
ntfs_io io;
attr->d.r.len = 0;
attr->d.r.runlist = 0;
attr->resident = 0;
- attr->allocated=attr->initialized = 0;
+ attr->allocated = attr->initialized = 0;
alen = len;
error = ntfs_extend_attr(ino, attr, &alen, ALLOC_REQUIRE_SIZE);
if (error)
@@ -203,13 +345,14 @@
}
/* Resize the attribute to a newsize. */
-int ntfs_resize_attr(ntfs_inode *ino, ntfs_attribute *attr, int newsize)
+int ntfs_resize_attr(ntfs_inode *ino, ntfs_attribute *attr, __s64 newsize)
{
int error = 0;
- int oldsize = attr->size;
- int clustersize = ino->vol->clustersize;
- int i, count, newlen, newcount;
+ __s64 oldsize = attr->size;
+ int clustersizebits = ino->vol->cluster_size_bits;
+ int i, count, newcount;
ntfs_runlist *rl;
+ __s64 newlen;
if (newsize == oldsize)
return 0;
@@ -219,7 +362,7 @@
return -EOPNOTSUPP;
if (attr->resident) {
void *v;
- if (newsize > ino->vol->mft_recordsize) {
+ if (newsize > ino->vol->mft_record_size) {
error = ntfs_make_attr_nonresident(ino, attr);
if (error)
return error;
@@ -247,16 +390,19 @@
rl = attr->d.r.runlist;
if (newsize < oldsize) {
for (i = 0, count = 0; i < attr->d.r.len; i++) {
- if ((count + rl[i].len) * clustersize > newsize)
+ if ((__s64)(count + rl[i].len) << clustersizebits >
+ newsize)
break;
count += (int)rl[i].len;
}
newlen = i + 1;
/* Free unused clusters in current run, unless sparse. */
newcount = count;
- if (rl[i].cluster != MAX_CLUSTER_T) {
- int rounded = newsize - count * clustersize;
- rounded = (rounded + clustersize - 1) / clustersize;
+ if (rl[i].cluster != (ntfs_cluster_t)-1) {
+ int rounded = newsize - ((__s64)count <<
+ clustersizebits);
+ rounded = (rounded + ino->vol->cluster_size - 1) >>
+ clustersizebits;
error = ntfs_deallocate_clusters(ino->vol,
rl[i].cluster + rounded,
(int)rl[i].len - rounded);
@@ -267,7 +413,7 @@
}
/* Free all other runs. */
for (i++; i < attr->d.r.len; i++)
- if (rl[i].cluster != MAX_CLUSTER_T) {
+ if (rl[i].cluster != (ntfs_cluster_t)-1) {
error = ntfs_deallocate_clusters(ino->vol,
rl[i].cluster,
(int)rl[i].len);
@@ -283,10 +429,10 @@
ALLOC_REQUIRE_SIZE);
if (error)
return error; /* FIXME: Incomplete operation. */
- newcount = newlen / clustersize;
+ newcount = newlen >> clustersizebits;
}
/* Fill in new sizes. */
- attr->allocated = newcount * clustersize;
+ attr->allocated = (__s64)newcount << clustersizebits;
attr->size = newsize;
/* attr->initialized does not change. */
if (!newsize)
@@ -303,7 +449,7 @@
int error;
ntfs_attribute *attr;
- if (dsize > ino->vol->mft_recordsize)
+ if (dsize > ino->vol->mft_record_size)
/* FIXME: Non-resident attributes. */
return -EOPNOTSUPP;
if (aname) {
@@ -316,14 +462,11 @@
name = 0;
namelen = 0;
}
- error = ntfs_new_attr(ino, anum, name, namelen, &i, &found, 1);
- if (error) {
+ error = ntfs_new_attr(ino, anum, name, namelen, data, dsize, &i,
+ &found);
+ if (error || found) {
ntfs_free(name);
- return error;
- }
- if (found) {
- ntfs_free(name);
- return -EEXIST;
+ return error ? error : -EEXIST;
}
*rattr = attr = ino->attrs + i;
/* Allocate a new number.
@@ -333,6 +476,10 @@
if (error)
return error;
attr->attrno = i;
+ if (attr->attrno + 1 != NTFS_GETU16(ino->attr + 0x28))
+ ntfs_error("UH OH! attr->attrno (%i) != NTFS_GETU16(ino->attr "
+ "+ 0x28) (%i)\n", attr->attrno,
+ NTFS_GETU16(ino->attr + 0x28));
attr->resident = 1;
attr->compressed = attr->cengine = 0;
attr->size = attr->allocated = attr->initialized = dsize;
@@ -340,9 +487,9 @@
/* FIXME: INDEXED information should come from $AttrDef
* Currently, only file names are indexed. As of NTFS v3.0 (Win2k),
* this is no longer true. Different attributes can be indexed now. */
- if (anum == ino->vol->at_file_name) {
+ if (anum == ino->vol->at_file_name)
attr->indexed = 1;
- } else
+ else
attr->indexed = 0;
attr->d.data = ntfs_malloc(dsize);
if (!attr->d.data)
@@ -354,7 +501,8 @@
/* Non-resident attributes are stored in runs (intervals of clusters).
*
* This function stores in the inode readable information about a non-resident
- * attribute. */
+ * attribute.
+ */
static int ntfs_process_runs(ntfs_inode *ino, ntfs_attribute* attr,
unsigned char *data)
{
@@ -362,33 +510,71 @@
int vcn, cnum;
ntfs_cluster_t cluster;
int len, ctype;
- startvcn = NTFS_GETU64(data + 0x10);
- endvcn = NTFS_GETU64(data + 0x18);
-
- /* Check whether this chunk really belongs to the end. */
+ int er = 0;
+ startvcn = NTFS_GETS64(data + 0x10);
+ endvcn = NTFS_GETS64(data + 0x18);
+
+ /* Check whether this chunk really belongs to the end. Problem with
+ * this: this functions can get called on the last extent first, before
+ * it is called on the other extents in sequence. This happens when the
+ * base mft record contains the last extent instead of the first one
+ * and the first extent is stored, like any intermediate extents in
+ * extension mft records. This would be difficult to allow the way the
+ * run list is stored in memory. Thus we fix else where by causing the
+ * attribute list attribute to be processed immediately when found. The
+ * extents will then be processed starting with the first one. */
for (cnum = 0, vcn = 0; cnum < attr->d.r.len; cnum++)
vcn += attr->d.r.runlist[cnum].len;
if (vcn != startvcn) {
- ntfs_error("Problem with runlist in extended record\n");
- return -1;
+ ntfs_debug(DEBUG_FILE3, "ntfs_process_runs: ino = 0x%x, "
+ "attr->type = 0x%x, startvcn = 0x%x, endvcn = 0x%x, "
+ "vcn = 0x%x, cnum = 0x%x\n", ino->i_number, attr->type,
+ startvcn, endvcn, vcn, cnum);
+ if (vcn < startvcn) {
+ ntfs_error("Problem with runlist in extended record\n");
+ return -1;
+ }
+ /* Tried to insert an already inserted run list. */
+ return 0;
}
if (!endvcn) {
- endvcn = NTFS_GETU64(data + 0x28) - 1; /* Allocated length. */
- endvcn /= ino->vol->clustersize;
+ if (!startvcn) {
+ /* Allocated length. */
+ endvcn = NTFS_GETS64(data + 0x28) - 1;
+ endvcn >>= ino->vol->cluster_size_bits;
+ } else {
+ /* This is an extent. Allocated length is not defined!
+ * Extents must have an endvcn though so this is an
+ * error. */
+ ntfs_error("Corrupt attribute extent. (endvcn is "
+ "missing)\n");
+ return -1;
+ }
}
data = data + NTFS_GETU16(data + 0x20);
cnum = attr->d.r.len;
cluster = 0;
for (vcn = startvcn; vcn <= endvcn; vcn += len) {
- if (ntfs_decompress_run(&data, &len, &cluster, &ctype))
+ if (ntfs_decompress_run(&data, &len, &cluster, &ctype)) {
+ ntfs_debug(DEBUG_FILE3, "ntfs_process_runs: "
+ "ntfs_decompress_run failed. i_number = 0x%x\n",
+ ino->i_number);
return -1;
+ }
if (ctype)
- ntfs_insert_run(attr, cnum, -1, len);
+ er = ntfs_insert_run(attr, cnum, -1, len);
else
- ntfs_insert_run(attr, cnum, cluster, len);
+ er = ntfs_insert_run(attr, cnum, cluster, len);
+ if (er)
+ break;
cnum++;
}
- return 0;
+ if (er)
+ ntfs_error("ntfs_process_runs: ntfs_insert_run failed\n");
+ ntfs_debug(DEBUG_FILE3, "ntfs_process_runs: startvcn = 0x%x, vcn = 0x%x"
+ ", endvcn = 0x%x, cnum = %i\n", startvcn, vcn,
+ endvcn, cnum);
+ return er;
}
/* Insert the attribute starting at attr in the inode ino. */
@@ -404,6 +590,8 @@
type = NTFS_GETU32(attrdata);
namelen = NTFS_GETU8(attrdata + 9);
+ ntfs_debug(DEBUG_FILE3, "ntfs_insert_attribute: ino->i_number 0x%x, "
+ "attr type 0x%x\n", ino->i_number, type);
/* Read the attribute's name if it has one. */
if (!namelen)
name = 0;
@@ -415,25 +603,30 @@
ntfs_memcpy(name, attrdata + NTFS_GETU16(attrdata + 10),
2 * namelen);
}
- error = ntfs_new_attr(ino, type, name, namelen, &i, &found, 1);
+ /* If resident look for value, too. */
+ if (NTFS_GETU8(attrdata + 8) == 0)
+ error = ntfs_new_attr(ino, type, name, namelen,
+ attrdata + NTFS_GETU16(attrdata + 0x14),
+ NTFS_GETU16(attrdata + 0x10), &i, &found);
+ else
+ error = ntfs_new_attr(ino, type, name, namelen, NULL, 0, &i,
+ &found);
if (error) {
+ ntfs_debug(DEBUG_FILE3, "ntfs_insert_attribute: ntfs_new_attr "
+ "failed.\n");
if (name)
ntfs_free(name);
return error;
}
- /* We can have in one inode two attributes with type 0x00000030 (File
- * Name) and without name. FIXME: We can have a lot more than two!
- * That is how hard links are implemented. (AIA) */
- if (found && /*FIXME*/ type != ino->vol->at_file_name)
- {
- ntfs_process_runs(ino, ino->attrs + i, attrdata);
+ if (found) {
+ /* It's already there, if not resident just process the runs. */
+ if (!ino->attrs[i].resident) {
+ ntfs_debug(DEBUG_FILE3, "ntfs_insert_attribute:"
+ " processing runs 1.\n");
+ /* FIXME: Check error code! (AIA) */
+ ntfs_process_runs(ino, ino->attrs + i, attrdata);
+ }
return 0;
- } else if (found) {
- /* Don't understand the above, but I know it leaks memory below
- * as it overwrites a found entry without freeing it. So here
- * we call ntfs_new_attr again but this time ask it to always
- * allocate a new entry. */
- ntfs_new_attr(ino, type, name, namelen, &i, &found, 0);
}
attr = ino->attrs + i;
attr->resident = NTFS_GETU8(attrdata + 8) == 0;
@@ -449,14 +642,21 @@
ntfs_memcpy(attr->d.data, data, attr->size);
attr->indexed = NTFS_GETU16(attrdata + 0x16);
} else {
- attr->allocated = NTFS_GETU32(attrdata + 0x28);
- attr->size = NTFS_GETU32(attrdata + 0x30);
- attr->initialized = NTFS_GETU32(attrdata + 0x38);
+ attr->allocated = NTFS_GETS64(attrdata + 0x28);
+ attr->size = NTFS_GETS64(attrdata + 0x30);
+ attr->initialized = NTFS_GETS64(attrdata + 0x38);
attr->cengine = NTFS_GETU16(attrdata + 0x22);
if (attr->compressed)
- attr->compsize = NTFS_GETU32(attrdata + 0x40);
+ attr->compsize = NTFS_GETS64(attrdata + 0x40);
+ ntfs_debug(DEBUG_FILE3, "ntfs_insert_attribute: "
+ "attr->allocated = 0x%Lx, attr->size = 0x%Lx, "
+ "attr->initialized = 0x%Lx\n", attr->allocated,
+ attr->size, attr->initialized);
ino->attrs[i].d.r.runlist = 0;
ino->attrs[i].d.r.len = 0;
+ ntfs_debug(DEBUG_FILE3, "ntfs_insert_attribute: processing "
+ "runs 2.\n");
+ /* FIXME: Check error code! (AIA) */
ntfs_process_runs(ino, attr, attrdata);
}
return 0;
@@ -477,12 +677,13 @@
}
/* Process compressed attributes. */
-int ntfs_read_compressed(ntfs_inode *ino, ntfs_attribute *attr, int offset,
+int ntfs_read_compressed(ntfs_inode *ino, ntfs_attribute *attr, __s64 offset,
ntfs_io *dest)
{
int error = 0;
- int clustersize, l;
- int s_vcn, rnum, vcn, len, chunk, got, l1, offs1, copied;
+ int clustersizebits;
+ int s_vcn, rnum, vcn, got, l1;
+ __s64 copied, len, chunk, offs1, l;
ntfs_cluster_t cluster, cl1;
char *comp = 0, *comp1;
char *decomp = 0;
@@ -490,13 +691,13 @@
ntfs_runlist *rl;
l = dest->size;
- clustersize = ino->vol->clustersize;
+ clustersizebits = ino->vol->cluster_size_bits;
/* Starting cluster of potential chunk. There are three situations:
a) In a large uncompressible or sparse chunk, s_vcn is in the middle
of a run.
b) s_vcn is right on a run border.
c) When several runs make a chunk, s_vcn is before the chunks. */
- s_vcn = offset / clustersize;
+ s_vcn = offset >> clustersizebits;
/* Round down to multiple of 16. */
s_vcn &= ~15;
rl = attr->d.r.runlist;
@@ -517,18 +718,19 @@
copied = 0;
while (l) {
chunk = 0;
- if (cluster == MAX_CLUSTER_T) {
+ if (cluster == (ntfs_cluster_t)-1) {
/* Sparse cluster. */
- int l1;
+ __s64 l1;
if ((len - (s_vcn - vcn)) & 15)
ntfs_error("Unexpected sparse chunk size.");
- l1 = chunk = min((vcn + len) * clustersize - offset, l);
+ l1 = chunk = min(((__s64)(vcn + len) << clustersizebits)
+ - offset, l);
error = ntfs_read_zero(dest, l1);
if (error)
goto out;
} else if (dest->do_read) {
if (!comp) {
- comp = ntfs_malloc(16 * clustersize);
+ comp = ntfs_malloc(16 << clustersizebits);
if (!comp) {
error = -ENOMEM;
goto out;
@@ -541,7 +743,7 @@
do {
io.param = comp1;
l1 = min(len - max(s_vcn - vcn, 0), 16 - got);
- io.size = l1 * clustersize;
+ io.size = (__s64)l1 << clustersizebits;
error = ntfs_getput_clusters(ino->vol, cl1, 0,
&io);
if (error)
@@ -554,16 +756,17 @@
len = rl->len;
}
got += l1;
- comp1 += l1 * clustersize;
- } while (cluster != MAX_CLUSTER_T && got < 16);
+ comp1 += (__s64)l1 << clustersizebits;
+ } while (cluster != (ntfs_cluster_t)-1 && got < 16);
/* Until empty run. */
- chunk = 16 * clustersize;
- if (cluster != MAX_CLUSTER_T || got == 16)
+ chunk = 16 << clustersizebits;
+ if (cluster != (ntfs_cluster_t)-1 || got == 16)
/* Uncompressible */
comp1 = comp;
else {
if (!decomp) {
- decomp = ntfs_malloc(16 * clustersize);
+ decomp = ntfs_malloc(16 <<
+ clustersizebits);
if (!decomp) {
error = -ENOMEM;
goto out;
@@ -575,16 +778,16 @@
ntfs_decompress(decomp, comp, chunk);
comp1 = decomp;
}
- offs1 = offset - s_vcn * clustersize;
- chunk = min(16 * clustersize - offs1, chunk);
+ offs1 = offset - ((__s64)s_vcn << clustersizebits);
+ chunk = min((16 << clustersizebits) - offs1, chunk);
chunk = min(l, chunk);
dest->fn_put(dest, comp1 + offs1, chunk);
}
l -= chunk;
copied += chunk;
offset += chunk;
- s_vcn = offset / clustersize & ~15;
- if (l && offset >= ((vcn + len) * clustersize)) {
+ s_vcn = (offset >> clustersizebits) & ~15;
+ if (l && offset >= ((__s64)(vcn + len) << clustersizebits)) {
rnum++;
rl++;
vcn += len;
@@ -601,7 +804,7 @@
return error;
}
-int ntfs_write_compressed(ntfs_inode *ino, ntfs_attribute *attr, int offset,
+int ntfs_write_compressed(ntfs_inode *ino, ntfs_attribute *attr, __s64 offset,
ntfs_io *dest)
{
return -EOPNOTSUPP;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)