patch-2.4.4 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: 1030
- Date:
Wed Apr 18 11:49:13 2001
- Orig file:
v2.4.3/linux/fs/ntfs/attr.c
- Orig date:
Mon Apr 12 10:05:58 1999
diff -u --recursive --new-file v2.4.3/linux/fs/ntfs/attr.c linux/fs/ntfs/attr.c
@@ -1,10 +1,10 @@
-/*
- * 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)
*/
#include "ntfstypes.h"
@@ -12,401 +12,389 @@
#include "attr.h"
#include <linux/errno.h>
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
#include "macros.h"
#include "support.h"
#include "util.h"
#include "super.h"
#include "inode.h"
-/* 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 )
+/* 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 do_insert=0;
+ int do_insert = 0;
int i;
- for(i=0;i<ino->attr_count;i++)
+ 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;
+ 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)){
- do_insert=1;
+ /* Attributes are ordered by type, then by name. */
+ if (ino->attrs[i].type > type ||
+ (ino->attrs[i].type == type && s == 1)) {
+ do_insert = 1;
break;
}
}
- /* re-allocate space */
- if(ino->attr_count % 8 ==0)
+ /* Re-allocate space. */
+ if (ino->attr_count % 8 == 0)
{
ntfs_attribute* new;
- new = (ntfs_attribute*)ntfs_malloc((ino->attr_count+8)*
- sizeof(ntfs_attribute));
- if( !new )
- return ENOMEM;
- if( ino->attrs ) {
- ntfs_memcpy( new, ino->attrs, ino->attr_count*sizeof(ntfs_attribute) );
- ntfs_free( ino->attrs );
+ new = (ntfs_attribute*)ntfs_malloc((ino->attr_count + 8) *
+ sizeof(ntfs_attribute));
+ if (!new)
+ return -ENOMEM;
+ if (ino->attrs) {
+ ntfs_memcpy(new, ino->attrs, ino->attr_count *
+ sizeof(ntfs_attribute));
+ ntfs_free(ino->attrs);
}
ino->attrs = new;
}
- if(do_insert)
- ntfs_memmove(ino->attrs+i+1,ino->attrs+i,(ino->attr_count-i)*
- sizeof(ntfs_attribute));
-
+ if (do_insert)
+ ntfs_memmove(ino->attrs + i + 1, ino->attrs + i,
+ (ino->attr_count - i) * sizeof(ntfs_attribute));
ino->attr_count++;
- ino->attrs[i].type=type;
- ino->attrs[i].namelen=namelen;
- ino->attrs[i].name=name;
- *pos=i;
- *found=0;
+ ino->attrs[i].type = type;
+ ino->attrs[i].namelen = namelen;
+ ino->attrs[i].name = name;
+ *pos = i;
+ *found = 0;
return 0;
}
-int
-ntfs_make_attr_resident(ntfs_inode *ino,ntfs_attribute *attr)
+int ntfs_make_attr_resident(ntfs_inode *ino, ntfs_attribute *attr)
{
- int size=attr->size;
- if(size>0){
+ int size = attr->size;
+ if (size > 0) {
/* FIXME: read data, free clusters */
- return EOPNOTSUPP;
+ return -EOPNOTSUPP;
}
- attr->resident=1;
+ attr->resident = 1;
return 0;
}
-/* Store in the inode readable information about a run */
-void
-ntfs_insert_run(ntfs_attribute *attr,int cnum,ntfs_cluster_t cluster,int len)
+/* Store in the inode readable information about a run. */
+void 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) {
+ /* (re-)allocate space if necessary. */
+ if (attr->d.r.len % 8 == 0) {
ntfs_runlist* new;
- new = ntfs_malloc((attr->d.r.len+8)*sizeof(ntfs_runlist));
- if( !new )
+ new = ntfs_malloc((attr->d.r.len + 8) * sizeof(ntfs_runlist));
+ if (!new)
return;
- if( attr->d.r.runlist ) {
+ 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 );
+ * sizeof(ntfs_runlist));
+ ntfs_free(attr->d.r.runlist);
}
attr->d.r.runlist = new;
}
- if(attr->d.r.len>cnum)
- ntfs_memmove(attr->d.r.runlist+cnum+1,attr->d.r.runlist+cnum,
- (attr->d.r.len-cnum)*sizeof(ntfs_runlist));
- attr->d.r.runlist[cnum].cluster=cluster;
- attr->d.r.runlist[cnum].len=len;
+ if (attr->d.r.len > cnum)
+ ntfs_memmove(attr->d.r.runlist + cnum + 1,
+ attr->d.r.runlist + cnum,
+ (attr->d.r.len - cnum) * sizeof(ntfs_runlist));
+ attr->d.r.runlist[cnum].cluster = cluster;
+ attr->d.r.runlist[cnum].len = len;
attr->d.r.len++;
}
-/* Extends an attribute. Another run will be added if necessary,
- * but we try to extend the last run in the runlist first.
+/* Extends an attribute. Another run will be added if necessary, but we try to
+ * extend the last run in the runlist first.
* FIXME: what if there isn't enough contiguous space, we don't create
* multiple runs?
*
* *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, int *len, int flags)
{
- int error=0;
+ int error = 0;
ntfs_runlist *rl;
int rlen;
ntfs_cluster_t cluster;
int clen;
- if(attr->compressed)return EOPNOTSUPP;
- if(ino->record_count>1)return EOPNOTSUPP;
-
- if(attr->resident) {
- error = ntfs_make_attr_nonresident(ino,attr);
- if(error)
+ if (attr->compressed || ino->record_count > 1)
+ return -EOPNOTSUPP;
+ if (attr->resident) {
+ error = ntfs_make_attr_nonresident(ino, attr);
+ if (error)
return error;
}
-
- if( *len <= attr->allocated )
- return 0; /* truely stupid things do sometimes happen */
-
- rl=attr->d.r.runlist;
- rlen=attr->d.r.len-1;
-
- if(rlen>=0)
- cluster=rl[rlen].cluster+rl[rlen].len;
+ if (*len <= attr->allocated)
+ return 0; /* Truely stupid things do sometimes happen. */
+ rl = attr->d.r.runlist;
+ rlen = attr->d.r.len - 1;
+ if (rlen >= 0)
+ cluster = rl[rlen].cluster + rl[rlen].len;
else
- /* no preference for allocation space */
- 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 ) /
+ /* No preference for allocation space. */
+ 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;
- if(clen==0)
+ if (clen == 0)
return 0;
-
/* FIXME: try to allocate smaller pieces */
- error=ntfs_allocate_clusters(ino->vol,&cluster,&clen,
- flags|ALLOC_REQUIRE_SIZE);
- if(error)return error;
- attr->allocated += clen*ino->vol->clustersize;
+ error = ntfs_allocate_clusters(ino->vol, &cluster, &clen,
+ flags | ALLOC_REQUIRE_SIZE);
+ if (error)
+ return error;
+ attr->allocated += clen * ino->vol->clustersize;
*len = attr->allocated;
-
- /* contiguous chunk */
- if(rlen>=0 && cluster==rl[rlen].cluster+rl[rlen].len){
+ /* Contiguous chunk. */
+ if (rlen >= 0 && cluster == rl[rlen].cluster + rl[rlen].len) {
rl[rlen].len += clen;
return 0;
}
- ntfs_insert_run(attr,rlen+1,cluster,clen);
+ ntfs_insert_run(attr, rlen + 1, cluster, clen);
return 0;
}
-int
-ntfs_make_attr_nonresident(ntfs_inode *ino, ntfs_attribute *attr)
+int ntfs_make_attr_nonresident(ntfs_inode *ino, ntfs_attribute *attr)
{
- void *data=attr->d.data;
- int len=attr->size;
- int error,alen;
+ void *data = attr->d.data;
+ int len = attr->size;
+ int error, alen;
ntfs_io io;
- attr->d.r.len=0;
- attr->d.r.runlist=0;
- attr->resident=0;
- attr->allocated=attr->initialized=0;
- alen=len;
- error=ntfs_extend_attr(ino,attr,&alen,ALLOC_REQUIRE_SIZE);
- if(error)return error;/* FIXME: On error, restore old values */
- io.fn_put=ntfs_put;
- io.fn_get=ntfs_get;
- io.param=data;
- io.size=len;
- io.do_read=0;
- return ntfs_readwrite_attr(ino,attr,0,&io);
+ attr->d.r.len = 0;
+ attr->d.r.runlist = 0;
+ attr->resident = 0;
+ attr->allocated=attr->initialized = 0;
+ alen = len;
+ error = ntfs_extend_attr(ino, attr, &alen, ALLOC_REQUIRE_SIZE);
+ if (error)
+ return error; /* FIXME: On error, restore old values. */
+ io.fn_put = ntfs_put;
+ io.fn_get = ntfs_get;
+ io.param = data;
+ io.size = len;
+ io.do_read = 0;
+ return ntfs_readwrite_attr(ino, attr, 0, &io);
}
-int
-ntfs_attr_allnonresident(ntfs_inode *ino)
+int ntfs_attr_allnonresident(ntfs_inode *ino)
{
- int i, error=0;
+ int i, error = 0;
ntfs_volume *vol = ino->vol;
- for (i=0; !error && i<ino->attr_count; i++)
+ for (i = 0; !error && i < ino->attr_count; i++)
{
- if (ino->attrs[i].type != vol->at_security_descriptor
- && ino->attrs[i].type != vol->at_data)
+ if (ino->attrs[i].type != vol->at_security_descriptor &&
+ ino->attrs[i].type != vol->at_data)
continue;
- error = ntfs_make_attr_nonresident (ino, ino->attrs+i);
+ error = ntfs_make_attr_nonresident(ino, ino->attrs + i);
}
return error;
}
-/* Resize the attribute to a newsize */
+/* Resize the attribute to a newsize. */
int ntfs_resize_attr(ntfs_inode *ino, ntfs_attribute *attr, int newsize)
{
- int error=0;
- int oldsize=attr->size;
- int clustersize=ino->vol->clustersize;
- int i,count,newlen,newcount;
+ int error = 0;
+ int oldsize = attr->size;
+ int clustersize = ino->vol->clustersize;
+ int i, count, newlen, newcount;
ntfs_runlist *rl;
- if(newsize==oldsize)
+ if (newsize == oldsize)
return 0;
- /* modifying compressed attributes not supported yet */
- if(attr->compressed)
- /* extending is easy: just insert sparse runs */
- return EOPNOTSUPP;
- if(attr->resident){
+ /* FIXME: Modifying compressed attributes not supported yet. */
+ if (attr->compressed)
+ /* FIXME: Extending is easy: just insert sparse runs. */
+ return -EOPNOTSUPP;
+ if (attr->resident) {
void *v;
- if(newsize>ino->vol->mft_recordsize){
- error=ntfs_make_attr_nonresident(ino,attr);
- if(error)return error;
- return ntfs_resize_attr(ino,attr,newsize);
+ if (newsize > ino->vol->mft_recordsize) {
+ error = ntfs_make_attr_nonresident(ino, attr);
+ if (error)
+ return error;
+ return ntfs_resize_attr(ino, attr, newsize);
}
- v=attr->d.data;
- if(newsize){
- attr->d.data=ntfs_malloc(newsize);
- if(!attr->d.data) {
+ v = attr->d.data;
+ if (newsize) {
+ attr->d.data = ntfs_malloc(newsize);
+ if (!attr->d.data) {
ntfs_free(v);
- return ENOMEM;
+ return -ENOMEM;
}
- if(newsize>oldsize)
- ntfs_bzero((char*)attr->d.data+oldsize,
- newsize-oldsize);
- ntfs_memcpy((char*)attr->d.data,v,min(newsize,oldsize));
- }else
- attr->d.data=0;
+ if (newsize > oldsize)
+ ntfs_bzero((char*)attr->d.data + oldsize,
+ newsize - oldsize);
+ ntfs_memcpy((char*)attr->d.data, v,
+ min(newsize, oldsize));
+ } else
+ attr->d.data = 0;
ntfs_free(v);
- attr->size=newsize;
+ attr->size = newsize;
return 0;
}
- /* non-resident attribute */
- 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)
+ /* Non-resident attribute. */
+ 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)
break;
- count+=(int)rl[i].len;
+ 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;
- error=ntfs_deallocate_clusters(ino->vol,rl[i].cluster+rounded,
- (int)rl[i].len-rounded);
- if(error)
- return error; /* FIXME: incomplete operation */
- rl[i].len=rounded;
- newcount=count+rounded;
+ 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;
+ error = ntfs_deallocate_clusters(ino->vol,
+ rl[i].cluster + rounded,
+ (int)rl[i].len - rounded);
+ if (error)
+ return error; /* FIXME: Incomplete operation. */
+ rl[i].len = rounded;
+ newcount = count + rounded;
}
- /* free all other runs */
- for(i++;i<attr->d.r.len;i++)
- if(rl[i].cluster!=MAX_CLUSTER_T){
- error=ntfs_deallocate_clusters(ino->vol,rl[i].cluster,(int)rl[i].len);
- if(error)
- return error; /* FIXME: incomplete operation */
+ /* Free all other runs. */
+ for (i++; i < attr->d.r.len; i++)
+ if (rl[i].cluster != MAX_CLUSTER_T) {
+ error = ntfs_deallocate_clusters(ino->vol,
+ rl[i].cluster,
+ (int)rl[i].len);
+ if (error)
+ return error; /* FIXME: Incomplete
+ * operation */
}
- /* FIXME? free space for extra runs in memory */
- attr->d.r.len=newlen;
- }else{
- newlen=newsize;
- error=ntfs_extend_attr(ino,attr,&newlen,ALLOC_REQUIRE_SIZE);
- if(error)return error; /* FIXME: incomplete */
- newcount=newlen/clustersize;
+ /* FIXME: Free space for extra runs in memory? */
+ attr->d.r.len = newlen;
+ } else {
+ newlen = newsize;
+ error = ntfs_extend_attr(ino, attr, &newlen,
+ ALLOC_REQUIRE_SIZE);
+ if (error)
+ return error; /* FIXME: Incomplete operation. */
+ newcount = newlen / clustersize;
}
- /* fill in new sizes */
- attr->allocated = newcount*clustersize;
+ /* Fill in new sizes. */
+ attr->allocated = newcount * clustersize;
attr->size = newsize;
/* attr->initialized does not change. */
- if(!newsize)
- error=ntfs_make_attr_resident(ino,attr);
+ if (!newsize)
+ error = ntfs_make_attr_resident(ino, attr);
return error;
}
int ntfs_create_attr(ntfs_inode *ino, int anum, char *aname, void *data,
- int dsize, ntfs_attribute **rattr)
+ int dsize, ntfs_attribute **rattr)
{
void *name;
int namelen;
- int found,i;
+ int found, i;
int error;
ntfs_attribute *attr;
- if(dsize>ino->vol->mft_recordsize)
- /* FIXME: non-resident attributes */
- return EOPNOTSUPP;
- if(aname){
- namelen=strlen(aname);
- name=ntfs_malloc(2*namelen);
- if( !name )
- return ENOMEM;
- ntfs_ascii2uni(name,aname,namelen);
- }else{
- name=0;
- namelen=0;
- }
-
- error = ntfs_new_attr(ino,anum,name,namelen,&i,&found,1);
- if( error ) {
- ntfs_free( name );
+
+ if (dsize > ino->vol->mft_recordsize)
+ /* FIXME: Non-resident attributes. */
+ return -EOPNOTSUPP;
+ if (aname) {
+ namelen = strlen(aname);
+ name = ntfs_malloc(2 * namelen);
+ if (!name)
+ return -ENOMEM;
+ ntfs_ascii2uni(name, aname, namelen);
+ } else {
+ name = 0;
+ namelen = 0;
+ }
+ error = ntfs_new_attr(ino, anum, name, namelen, &i, &found, 1);
+ if (error) {
+ ntfs_free(name);
return error;
}
-
- if(found){
+ if (found) {
ntfs_free(name);
- return EEXIST;
+ return -EEXIST;
}
- *rattr=attr=ino->attrs+i;
- /* allocate a new number.
- FIXME: Should this happen on inode writeback?
- FIXME: extensions records not supported */
- error=ntfs_allocate_attr_number(ino,&i);
- if(error)
+ *rattr = attr = ino->attrs + i;
+ /* Allocate a new number.
+ * FIXME: Should this happen on inode writeback?
+ * FIXME: Extension records not supported. */
+ error = ntfs_allocate_attr_number(ino, &i);
+ if (error)
return error;
- attr->attrno=i;
-
- attr->resident=1;
- attr->compressed=attr->cengine=0;
- attr->size=attr->allocated=attr->initialized=dsize;
+ attr->attrno = i;
+ attr->resident = 1;
+ attr->compressed = attr->cengine = 0;
+ attr->size = attr->allocated = attr->initialized = dsize;
/* FIXME: INDEXED information should come from $AttrDef
- Currently, only file names are indexed */
- if(anum==ino->vol->at_file_name){
- attr->indexed=1;
- }else
- attr->indexed=0;
- attr->d.data=ntfs_malloc(dsize);
-
- if( !attr->d.data )
- return ENOMEM;
-
- ntfs_memcpy(attr->d.data,data,dsize);
+ * 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) {
+ attr->indexed = 1;
+ } else
+ attr->indexed = 0;
+ attr->d.data = ntfs_malloc(dsize);
+ if (!attr->d.data)
+ return -ENOMEM;
+ ntfs_memcpy(attr->d.data, data, dsize);
return 0;
}
/* Non-resident attributes are stored in runs (intervals of clusters).
*
* This function stores in the inode readable information about a non-resident
- * attribute.
- */
-static int
-ntfs_process_runs(ntfs_inode *ino,ntfs_attribute* attr,unsigned char *data)
+ * attribute. */
+static int ntfs_process_runs(ntfs_inode *ino, ntfs_attribute* attr,
+ unsigned char *data)
{
- int startvcn,endvcn;
- int vcn,cnum;
+ int startvcn, endvcn;
+ 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 */
- for(cnum=0,vcn=0;cnum<attr->d.r.len;cnum++)
- vcn+=attr->d.r.runlist[cnum].len;
- if(vcn!=startvcn)
- {
+ int len, ctype;
+ startvcn = NTFS_GETU64(data + 0x10);
+ endvcn = NTFS_GETU64(data + 0x18);
+
+ /* Check whether this chunk really belongs to the end. */
+ 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;
}
- if(!endvcn)
- {
- endvcn = NTFS_GETU64(data+0x28)-1; /* allocated length */
+ if (!endvcn) {
+ endvcn = NTFS_GETU64(data + 0x28) - 1; /* Allocated length. */
endvcn /= ino->vol->clustersize;
}
- 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))
+ 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))
return -1;
- if(ctype)
- ntfs_insert_run(attr,cnum,-1,len);
+ if (ctype)
+ ntfs_insert_run(attr, cnum, -1, len);
else
- ntfs_insert_run(attr,cnum,cluster,len);
+ ntfs_insert_run(attr, cnum, cluster, len);
cnum++;
}
return 0;
}
-/* Insert the attribute starting at attr in the inode ino */
+/* Insert the attribute starting at attr in the inode ino. */
int ntfs_insert_attribute(ntfs_inode *ino, unsigned char* attrdata)
{
- int i,found;
+ int i, found;
int type;
short int *name;
int namelen;
@@ -415,208 +403,207 @@
int error;
type = NTFS_GETU32(attrdata);
- namelen = NTFS_GETU8(attrdata+9);
- /* read the attribute's name if it has one */
- if(!namelen)
- name=0;
- else
- {
- /* 1 Unicode character fits in 2 bytes */
- name=ntfs_malloc(2*namelen);
- if( !name )
- return ENOMEM;
-
- ntfs_memcpy(name,attrdata+NTFS_GETU16(attrdata+10),2*namelen);
- }
-
- error = ntfs_new_attr(ino,type,name,namelen,&i,&found,1);
- if( error ) {
- if( name ) ntfs_free( name );
+ namelen = NTFS_GETU8(attrdata + 9);
+ /* Read the attribute's name if it has one. */
+ if (!namelen)
+ name = 0;
+ else {
+ /* 1 Unicode character fits in 2 bytes. */
+ name = ntfs_malloc(2 * namelen);
+ if (!name)
+ return -ENOMEM;
+ ntfs_memcpy(name, attrdata + NTFS_GETU16(attrdata + 10),
+ 2 * namelen);
+ }
+ error = ntfs_new_attr(ino, type, name, namelen, &i, &found, 1);
+ if (error) {
+ if (name)
+ ntfs_free(name);
return error;
}
-
- /* We can have in one inode two attributes with type 0x00000030 (File Name)
- and without name */
- if(found && /*FIXME*/type!=ino->vol->at_file_name)
+ /* 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);
+ 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;
- attr->compressed=NTFS_GETU16(attrdata+0xC);
- attr->attrno=NTFS_GETU16(attrdata+0xE);
+ } 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;
+ attr->compressed = NTFS_GETU16(attrdata + 0xC);
+ attr->attrno = NTFS_GETU16(attrdata + 0xE);
- if(attr->resident) {
- attr->size=NTFS_GETU16(attrdata+0x10);
- data=attrdata+NTFS_GETU16(attrdata+0x14);
+ if (attr->resident) {
+ attr->size = NTFS_GETU16(attrdata + 0x10);
+ data = attrdata + NTFS_GETU16(attrdata + 0x14);
attr->d.data = (void*)ntfs_malloc(attr->size);
- if( !attr->d.data )
- return ENOMEM;
- 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->cengine=NTFS_GETU16(attrdata+0x22);
- if(attr->compressed)
- attr->compsize=NTFS_GETU32(attrdata+0x40);
- ino->attrs[i].d.r.runlist=0;
- ino->attrs[i].d.r.len=0;
- ntfs_process_runs(ino,attr,attrdata);
+ if (!attr->d.data)
+ return -ENOMEM;
+ 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->cengine = NTFS_GETU16(attrdata + 0x22);
+ if (attr->compressed)
+ attr->compsize = NTFS_GETU32(attrdata + 0x40);
+ ino->attrs[i].d.r.runlist = 0;
+ ino->attrs[i].d.r.len = 0;
+ ntfs_process_runs(ino, attr, attrdata);
}
return 0;
}
-int
-ntfs_read_zero(ntfs_io *dest,int size)
+int ntfs_read_zero(ntfs_io *dest, int size)
{
- char *sparse=ntfs_calloc(512);
- if(!sparse)
- return ENOMEM;
- while(size){
- int i=min(size,512);
- dest->fn_put(dest,sparse,i);
- size-=i;
+ char *sparse = ntfs_calloc(512);
+ if (!sparse)
+ return -ENOMEM;
+ while (size) {
+ int i = min(size, 512);
+ dest->fn_put(dest, sparse, i);
+ size -= i;
}
ntfs_free(sparse);
return 0;
}
-/* process compressed attributes */
+/* Process compressed attributes. */
int ntfs_read_compressed(ntfs_inode *ino, ntfs_attribute *attr, int offset,
- ntfs_io *dest)
+ ntfs_io *dest)
{
- int error=0;
- int clustersize,l;
- int s_vcn,rnum,vcn,len,chunk,got,l1,offs1,copied;
- ntfs_cluster_t cluster,cl1;
- char *comp=0,*comp1;
- char *decomp=0;
+ int error = 0;
+ int clustersize, l;
+ int s_vcn, rnum, vcn, len, chunk, got, l1, offs1, copied;
+ ntfs_cluster_t cluster, cl1;
+ char *comp = 0, *comp1;
+ char *decomp = 0;
ntfs_io io;
ntfs_runlist *rl;
- l=dest->size;
- clustersize=ino->vol->clustersize;
- /* 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;
- /* round down to multiple of 16 */
+ l = dest->size;
+ clustersize = ino->vol->clustersize;
+ /* 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;
+ /* Round down to multiple of 16. */
s_vcn &= ~15;
- rl=attr->d.r.runlist;
- for(rnum=vcn=0;rnum<attr->d.r.len && vcn+rl->len<=s_vcn;rnum++,rl++)
- vcn+=rl->len;
- if(rnum==attr->d.r.len){
- /* beyond end of file */
- /* FIXME: check allocated/initialized */
- dest->size=0;
+ rl = attr->d.r.runlist;
+ for (rnum = vcn = 0; rnum < attr->d.r.len && vcn + rl->len <= s_vcn;
+ rnum++, rl++)
+ vcn += rl->len;
+ if (rnum == attr->d.r.len) {
+ /* Beyond end of file. */
+ /* FIXME: Check allocated / initialized. */
+ dest->size = 0;
return 0;
}
- io.do_read=1;
- io.fn_put=ntfs_put;
- io.fn_get=0;
- cluster=rl->cluster;
- len=rl->len;
- copied=0;
- while(l){
- chunk=0;
- if(cluster==MAX_CLUSTER_T){
- /* sparse cluster */
+ io.do_read = 1;
+ io.fn_put = ntfs_put;
+ io.fn_get = 0;
+ cluster = rl->cluster;
+ len = rl->len;
+ copied = 0;
+ while (l) {
+ chunk = 0;
+ if (cluster == MAX_CLUSTER_T) {
+ /* Sparse cluster. */
int l1;
- if((len-(s_vcn-vcn)) & 15)
- ntfs_error("unexpected sparse chunk size");
- l1=chunk = min((vcn+len)*clustersize-offset,l);
- error = ntfs_read_zero(dest,l1);
- if(error)
+ if ((len - (s_vcn - vcn)) & 15)
+ ntfs_error("Unexpected sparse chunk size.");
+ l1 = chunk = min((vcn + len) * clustersize - offset, l);
+ error = ntfs_read_zero(dest, l1);
+ if (error)
goto out;
- }else if(dest->do_read){
- if(!comp){
- comp=ntfs_malloc(16*clustersize);
- if(!comp){
- error=ENOMEM;
+ } else if (dest->do_read) {
+ if (!comp) {
+ comp = ntfs_malloc(16 * clustersize);
+ if (!comp) {
+ error = -ENOMEM;
goto out;
}
}
- got=0;
- /* we might need to start in the middle of a run */
- cl1=cluster+s_vcn-vcn;
- comp1=comp;
- do{
- io.param=comp1;
- l1=min(len-max(s_vcn-vcn,0),16-got);
- io.size=l1*clustersize;
- error=ntfs_getput_clusters(ino->vol,cl1,0,&io);
- if(error)goto out;
- if(l1+max(s_vcn-vcn,0)==len){
- rnum++;rl++;
- vcn+=len;
- cluster=cl1=rl->cluster;
- len=rl->len;
+ got = 0;
+ /* We might need to start in the middle of a run. */
+ cl1 = cluster + s_vcn - vcn;
+ comp1 = comp;
+ do {
+ io.param = comp1;
+ l1 = min(len - max(s_vcn - vcn, 0), 16 - got);
+ io.size = l1 * clustersize;
+ error = ntfs_getput_clusters(ino->vol, cl1, 0,
+ &io);
+ if (error)
+ goto out;
+ if (l1 + max(s_vcn - vcn, 0) == len) {
+ rnum++;
+ rl++;
+ vcn += len;
+ cluster = cl1 = rl->cluster;
+ len = rl->len;
}
- got+=l1;
- comp1+=l1*clustersize;
- }while(cluster!=MAX_CLUSTER_T && got<16); /* until empty run */
- chunk=16*clustersize;
- if(cluster!=MAX_CLUSTER_T || got==16)
- /* uncompressible */
- comp1=comp;
- else{
- if(!decomp){
- decomp=ntfs_malloc(16*clustersize);
- if(!decomp){
- error=ENOMEM;
+ got += l1;
+ comp1 += l1 * clustersize;
+ } while (cluster != MAX_CLUSTER_T && got < 16);
+ /* Until empty run. */
+ chunk = 16 * clustersize;
+ if (cluster != MAX_CLUSTER_T || got == 16)
+ /* Uncompressible */
+ comp1 = comp;
+ else {
+ if (!decomp) {
+ decomp = ntfs_malloc(16 * clustersize);
+ if (!decomp) {
+ error = -ENOMEM;
goto out;
}
}
- /* make sure there are null bytes
- after the last block */
- *(ntfs_u32*)comp1=0;
- ntfs_decompress(decomp,comp,chunk);
- comp1=decomp;
+ /* Make sure there are null bytes after the
+ * last block. */
+ *(ntfs_u32*)comp1 = 0;
+ ntfs_decompress(decomp, comp, chunk);
+ comp1 = decomp;
}
- offs1=offset-s_vcn*clustersize;
- chunk=min(16*clustersize-offs1,chunk);
- chunk=min(l,chunk);
- dest->fn_put(dest,comp1+offs1,chunk);
+ offs1 = offset - s_vcn * clustersize;
+ chunk = min(16 * clustersize - 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)){
- rnum++;rl++;
- vcn+=len;
- cluster=rl->cluster;
- len=rl->len;
+ l -= chunk;
+ copied += chunk;
+ offset += chunk;
+ s_vcn = offset / clustersize & ~15;
+ if (l && offset >= ((vcn + len) * clustersize)) {
+ rnum++;
+ rl++;
+ vcn += len;
+ cluster = rl->cluster;
+ len = rl->len;
}
}
out:
- if(comp)ntfs_free(comp);
- if(decomp)ntfs_free(decomp);
- dest->size=copied;
+ if (comp)
+ ntfs_free(comp);
+ if (decomp)
+ ntfs_free(decomp);
+ dest->size = copied;
return error;
}
int ntfs_write_compressed(ntfs_inode *ino, ntfs_attribute *attr, int offset,
- ntfs_io *dest)
+ ntfs_io *dest)
{
- return EOPNOTSUPP;
+ return -EOPNOTSUPP;
}
-/*
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)