patch-2.4.4 linux/fs/ntfs/inode.c
Next file: linux/fs/ntfs/inode.h
Previous file: linux/fs/ntfs/fs.c
Back to the patch index
Back to the overall index
- Lines: 2245
- Date:
Wed Apr 18 11:49:13 2001
- Orig file:
v2.4.3/linux/fs/ntfs/inode.c
- Orig date:
Fri Nov 17 11:35:27 2000
diff -u --recursive --new-file v2.4.3/linux/fs/ntfs/inode.c linux/fs/ntfs/inode.c
@@ -1,23 +1,18 @@
-/*
- * inode.c
+/* inode.c
*
* Copyright (C) 1995-1999 Martin von Löwis
* Copyright (C) 1996 Albert D. Cahalan
* Copyright (C) 1996-1997 Régis Duchesne
* Copyright (C) 1998 Joseph Malicki
* Copyright (C) 1999 Steve Dodd
- * Copyright (C) 2000 Anton Altaparmakov
+ * Copyright (C) 2000-2001 Anton Altaparmakov (AIA)
*/
#include "ntfstypes.h"
#include "ntfsendian.h"
#include "struct.h"
#include "inode.h"
-
#include <linux/errno.h>
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
#include "macros.h"
#include "attr.h"
#include "super.h"
@@ -27,210 +22,229 @@
typedef struct {
int recno;
- unsigned char* record;
+ unsigned char *record;
} ntfs_mft_record;
typedef struct {
int size;
int count;
- ntfs_mft_record* records;
+ ntfs_mft_record *records;
} ntfs_disk_inode;
-void
-ntfs_fill_mft_header(ntfs_u8*mft,int record_size,int blocksize,
- int sequence_number)
+void ntfs_fill_mft_header(ntfs_u8 *mft, int record_size, int blocksize,
+ int sequence_number)
{
int fixup_count = record_size / blocksize + 1;
int attr_offset = (0x2a + (2 * fixup_count) + 7) & ~7;
int fixup_offset = 0x2a;
NTFS_PUTU32(mft + 0x00, 0x454c4946); /* FILE */
- NTFS_PUTU16(mft + 0x04, 0x2a); /* offset to fixup */
- NTFS_PUTU16(mft + 0x06, fixup_count); /* Number of fixups */
- NTFS_PUTU16(mft + 0x10, sequence_number);
- NTFS_PUTU16(mft + 0x12, 1); /* hard link count */
- NTFS_PUTU16(mft + 0x14, attr_offset); /* Offset to attributes */
- NTFS_PUTU16(mft + 0x16, 1); /*FIXME: flags ?? */
- NTFS_PUTU32(mft + 0x18, attr_offset + 0x08); /* In use */
- NTFS_PUTU32(mft + 0x1c, record_size); /* Total size */
-
- NTFS_PUTU16(mft + fixup_offset, 1); /* Fixup word */
- NTFS_PUTU32(mft + attr_offset, 0xffffffff); /* End marker */
-}
-
-/* Search in an inode an attribute by type and name */
-ntfs_attribute*
-ntfs_find_attr(ntfs_inode *ino,int type,char *name)
+ NTFS_PUTU16(mft + 0x04, 0x2a); /* Offset to fixup. */
+ NTFS_PUTU16(mft + 0x06, fixup_count); /* Number of fixups. */
+ NTFS_PUTU16(mft + 0x10, sequence_number); /* Sequence number. */
+ NTFS_PUTU16(mft + 0x12, 1); /* Hard link count. */
+ NTFS_PUTU16(mft + 0x14, attr_offset); /* Offset to attributes. */
+ NTFS_PUTU16(mft + 0x16, 1); /* Flags: 1 = In use,
+ 2 = Directory. */
+ NTFS_PUTU32(mft + 0x18, attr_offset + 0x08); /* Bytes in use. */
+ NTFS_PUTU32(mft + 0x1c, record_size); /* Total allocated size. */
+ NTFS_PUTU16(mft + fixup_offset, 1); /* Fixup word. */
+ NTFS_PUTU32(mft + attr_offset, 0xffffffff); /* End marker. */
+}
+
+/* Search in an inode an attribute by type and name.
+ * FIXME: Check that when attributes are inserted all attribute list
+ * attributes are expanded otherwise need to modify this function to deal
+ * with attribute lists. (AIA) */
+ntfs_attribute *ntfs_find_attr(ntfs_inode *ino, int type, char *name)
{
int i;
- if(!ino){
+
+ if (!ino) {
ntfs_error("ntfs_find_attr: NO INODE!\n");
return 0;
}
- for(i=0;i<ino->attr_count;i++)
- {
- if(type==ino->attrs[i].type)
- {
- if(!name && !ino->attrs[i].name)
- return ino->attrs+i;
- if(name && !ino->attrs[i].name)
- return 0;
- if(!name && ino->attrs[i].name)
- return 0;
- if(ntfs_ua_strncmp(ino->attrs[i].name,name,strlen(name))==0)
- return ino->attrs+i;
- }
- if(type<ino->attrs[i].type)
+ for (i = 0; i < ino->attr_count; i++) {
+ if (type < ino->attrs[i].type)
return 0;
+ if (type == ino->attrs[i].type) {
+ if (!name) {
+ if (!ino->attrs[i].name)
+ return ino->attrs + i;
+ } else if (ino->attrs[i].name &&
+ !ntfs_ua_strncmp(ino->attrs[i].name, name,
+ strlen(name)))
+ return ino->attrs + i;
+ }
}
return 0;
}
-/* FIXME: need better strategy to extend the MFT */
-static int
-ntfs_extend_mft(ntfs_volume *vol)
-{
- /* Try to allocate at least 0.1% of the remaining disk space
- for inodes. If the disk is almost full, make sure at least one
- inode is requested.
- */
- int size,rcount,error,block;
- ntfs_attribute* mdata,*bmp;
+/* FIXME: Need better strategy to extend the MFT. */
+static int ntfs_extend_mft(ntfs_volume *vol)
+{
+ /* Try to allocate at least 0.1% of the remaining disk space for
+ * inodes. If the disk is almost full, make sure at least one inode is
+ * requested. */
+ int size, rcount, error, block;
+ ntfs_attribute *mdata, *bmp;
ntfs_u8 *buf;
ntfs_io io;
- mdata=ntfs_find_attr(vol->mft_ino,vol->at_data,0);
- /* first check whether there is uninitialized space */
- if(mdata->allocated<mdata->size+vol->mft_recordsize){
- size=ntfs_get_free_cluster_count(vol->bitmap)*vol->clustersize;
- block=vol->mft_recordsize;
- size=max(size/1000,mdata->size+vol->mft_recordsize);
- size=((size+block-1)/block)*block;
- /* require this to be a single chunk */
- error=ntfs_extend_attr(vol->mft_ino,mdata,&size,
- ALLOC_REQUIRE_SIZE);
- /* Try again, now we have the largest available fragment */
- if(error==ENOSPC){
- /* round down to multiple of mft record size */
- size=(size/vol->mft_recordsize)*vol->mft_recordsize;
- if(!size)return ENOSPC;
- error=ntfs_extend_attr(vol->mft_ino,mdata,&size,
- ALLOC_REQUIRE_SIZE);
+ mdata = ntfs_find_attr(vol->mft_ino, vol->at_data, 0);
+ /* First check whether there is uninitialized space. */
+ if (mdata->allocated < mdata->size + vol->mft_recordsize) {
+ size = ntfs_get_free_cluster_count(vol->bitmap) *
+ vol->clustersize;
+ block = vol->mft_recordsize;
+ size = max(size / 1000, mdata->size + vol->mft_recordsize);
+ size = ((size + block - 1) / block) * block;
+ /* Require this to be a single chunk. */
+ error = ntfs_extend_attr(vol->mft_ino, mdata, &size,
+ ALLOC_REQUIRE_SIZE);
+ /* Try again, now we have the largest available fragment. */
+ if (error == -ENOSPC) {
+ /* Round down to multiple of mft record size. */
+ size = (size / vol->mft_recordsize) *
+ vol->mft_recordsize;
+ if (!size)
+ return -ENOSPC;
+ error = ntfs_extend_attr(vol->mft_ino, mdata, &size,
+ ALLOC_REQUIRE_SIZE);
}
- if(error)
+ if (error)
return error;
}
- /* even though we might have allocated more than needed,
- we initialize only one record */
- mdata->size+=vol->mft_recordsize;
-
- /* now extend the bitmap if necessary*/
- rcount=mdata->size/vol->mft_recordsize;
- bmp=ntfs_find_attr(vol->mft_ino,vol->at_bitmap,0);
- if(bmp->size*8<rcount){ /* less bits than MFT records */
+ /* Even though we might have allocated more than needed, we initialize
+ * only one record. */
+ mdata->size += vol->mft_recordsize;
+ /* Now extend the bitmap if necessary. */
+ rcount = mdata->size / vol->mft_recordsize;
+ bmp = ntfs_find_attr(vol->mft_ino, vol->at_bitmap, 0);
+ if (bmp->size * 8 < rcount) { /* Less bits than MFT records. */
ntfs_u8 buf[1];
- /* extend bitmap by one byte */
- error=ntfs_resize_attr(vol->mft_ino,bmp,bmp->size+1);
- if(error)return error;
- /* write the single byte */
- buf[0]=0;
- io.fn_put=ntfs_put;
- io.fn_get=ntfs_get;
- io.param=buf;
- io.size=1;
- error=ntfs_write_attr(vol->mft_ino,vol->at_bitmap,0,
- bmp->size-1,&io);
- if(error)return error;
- if(io.size!=1)return EIO;
- }
-
- /* now fill in the MFT header for the new block */
- buf=ntfs_calloc(vol->mft_recordsize);
- if(!buf)return ENOMEM;
- ntfs_fill_mft_header(buf,vol->mft_recordsize,vol->blocksize,0);
- ntfs_insert_fixups(buf,vol->blocksize);
- io.param=buf;
- io.size=vol->mft_recordsize;
+ /* Extend bitmap by one byte. */
+ error = ntfs_resize_attr(vol->mft_ino, bmp, bmp->size + 1);
+ if (error)
+ return error;
+ /* Write the single byte. */
+ buf[0] = 0;
+ io.fn_put = ntfs_put;
+ io.fn_get = ntfs_get;
+ io.param = buf;
+ io.size = 1;
+ error = ntfs_write_attr(vol->mft_ino, vol->at_bitmap, 0,
+ bmp->size - 1, &io);
+ if (error)
+ return error;
+ if (io.size != 1)
+ return -EIO;
+ }
+ /* Now fill in the MFT header for the new block. */
+ buf = ntfs_calloc(vol->mft_recordsize);
+ if (!buf)
+ return -ENOMEM;
+ ntfs_fill_mft_header(buf, vol->mft_recordsize, vol->blocksize, 0);
+ ntfs_insert_fixups(buf, vol->blocksize);
+ io.param = buf;
+ io.size = vol->mft_recordsize;
io.fn_put = ntfs_put;
io.fn_get = ntfs_get;
- error=ntfs_write_attr(vol->mft_ino,vol->at_data,0,
- (rcount-1)*vol->mft_recordsize,&io);
- if(error)return error;
- if(io.size!=vol->mft_recordsize)return EIO;
- error=ntfs_update_inode(vol->mft_ino);
- if(error)return error;
+ error = ntfs_write_attr(vol->mft_ino, vol->at_data, 0,
+ (rcount - 1) * vol->mft_recordsize, &io);
+ if (error)
+ return error;
+ if (io.size != vol->mft_recordsize)
+ return -EIO;
+ error = ntfs_update_inode(vol->mft_ino);
+ if (error)
+ return error;
return 0;
}
-/* Insert all attributes from the record mftno of the MFT in the inode ino */
-void ntfs_insert_mft_attributes(ntfs_inode* ino,char *mft,int mftno)
+/* Insert all attributes from the record mftno of the MFT in the inode ino.
+ * FIXME: We should be performing structural consistency checks. (AIA)
+ * Return 0 on success or -errno on error. */
+static int ntfs_insert_mft_attributes(ntfs_inode* ino, char *mft, int mftno)
{
- int i;
+ int i, error, type, len;
char *it;
- int type,len;
- /* check for duplicate */
- for(i=0;i<ino->record_count;i++)
- if(ino->records[i]==mftno)
- return;
- /* (re-)allocate space if necessary */
- if(ino->record_count % 8==0)
- {
+
+ /* Check for duplicate. */
+ for(i = 0; i < ino->record_count; i++)
+ if (ino->records[i] == mftno)
+ return 0;
+ /* (re-)allocate space if necessary. */
+ if (ino->record_count % 8 == 0) {
int *new;
- new = ntfs_malloc((ino->record_count+8)*sizeof(int));
- if( !new )
- return;
- if( ino->records ) {
- for(i=0;i<ino->record_count;i++)
+
+ new = ntfs_malloc((ino->record_count + 8) * sizeof(int));
+ if (!new)
+ return -ENOMEM;
+ if (ino->records) {
+ for (i = 0; i < ino->record_count; i++)
new[i] = ino->records[i];
- ntfs_free( ino->records );
+ ntfs_free(ino->records);
}
ino->records = new;
}
- ino->records[ino->record_count]=mftno;
+ ino->records[ino->record_count] = mftno;
ino->record_count++;
it = mft + NTFS_GETU16(mft + 0x14);
- do{
- type=NTFS_GETU32(it);
- len=NTFS_GETU32(it+4);
- if(type!=-1) {
- /* FIXME: check ntfs_insert_attribute for failure (e.g. no mem)? */
- ntfs_insert_attribute(ino,it);
- }
- it+=len;
- }while(type!=-1); /* attribute list ends with type -1 */
+ do {
+ type = NTFS_GETU32(it);
+ len = NTFS_GETU32(it + 4);
+ if (type != -1) {
+ error = ntfs_insert_attribute(ino, it);
+ if (error)
+ return error;
+ }
+ it += len;
+ } while (type != -1); /* Attribute list ends with type -1. */
+ return 0;
}
-/* Read and insert all the attributes of an 'attribute list' attribute
- Return the number of remaining bytes in *plen
-*/
+/* Read and insert all the attributes of an 'attribute list' attribute.
+ * Return the number of remaining bytes in *plen. */
static int parse_attributes(ntfs_inode *ino, ntfs_u8 *alist, int *plen)
{
char *mft;
- int mftno,l,error;
- int last_mft=-1;
- int len=*plen;
- mft=ntfs_malloc(ino->vol->mft_recordsize);
- if( !mft )
- return ENOMEM;
- while(len>8)
- {
- l=NTFS_GETU16(alist+4);
- if(l>len)break;
- /* process an attribute description */
- mftno=NTFS_GETU32(alist+0x10); /* BUG: this is u64 */
- if(mftno!=last_mft){
- last_mft=mftno;
- /* FIXME: avoid loading record if it's
- already processed */
- error=ntfs_read_mft_record(ino->vol,mftno,mft);
- if(error)return error;
- ntfs_insert_mft_attributes(ino,mft,mftno);
+ int mftno, l, error;
+ int last_mft = -1;
+ int len = *plen;
+
+ mft = ntfs_malloc(ino->vol->mft_recordsize);
+ if (!mft)
+ return -ENOMEM;
+ while (len > 8) {
+ l = NTFS_GETU16(alist + 4);
+ if (l > len)
+ break;
+ /* Process an attribute description. */
+ mftno = NTFS_GETU32(alist + 0x10);
+ /* FIXME: The mft reference (alist + 0x10) is __u64.
+ * - Not a problem unless we encounter a huge partition.
+ * - Should be consistency checking the sequence numbers
+ * though! This should maybe happen in
+ * ntfs_read_mft_record() itself and a hotfix could
+ * then occur there or the user notified to run
+ * ntfsck. (AIA) */
+ if (mftno != last_mft){
+ last_mft = mftno;
+ /* FIXME: Avoid loading record if it's already
+ * processed. */
+ error = ntfs_read_mft_record(ino->vol, mftno, mft);
+ if (error)
+ return error;
+ error = ntfs_insert_mft_attributes(ino, mft, mftno);
+ if (error)
+ return error;
}
- len-=l;
- alist+=l;
+ len -= l;
+ alist += l;
}
ntfs_free(mft);
- *plen=len;
+ *plen = len;
return 0;
}
@@ -238,167 +252,176 @@
{
ntfs_attribute *alist;
int datasize;
- int offset,len,delta;
+ int offset, len, delta;
char *buf;
- ntfs_volume *vol=ino->vol;
- ntfs_debug(DEBUG_FILE2, "load_attributes %x 1\n",ino->i_number);
- ntfs_insert_mft_attributes(ino,ino->attr,ino->i_number);
- ntfs_debug(DEBUG_FILE2, "load_attributes %x 2\n",ino->i_number);
- alist=ntfs_find_attr(ino,vol->at_attribute_list,0);
- ntfs_debug(DEBUG_FILE2, "load_attributes %x 3\n",ino->i_number);
- if(!alist)
+ ntfs_volume *vol = ino->vol;
+
+ ntfs_debug(DEBUG_FILE2, "load_attributes %x 1\n", ino->i_number);
+ if (ntfs_insert_mft_attributes(ino, ino->attr, ino->i_number))
return;
- ntfs_debug(DEBUG_FILE2, "load_attributes %x 4\n",ino->i_number);
- datasize=alist->size;
- if(alist->resident)
- {
- parse_attributes(ino,alist->d.data,&datasize);
+ ntfs_debug(DEBUG_FILE2, "load_attributes %x 2\n", ino->i_number);
+ alist = ntfs_find_attr(ino, vol->at_attribute_list, 0);
+ ntfs_debug(DEBUG_FILE2, "load_attributes %x 3\n", ino->i_number);
+ if (!alist)
+ return;
+ ntfs_debug(DEBUG_FILE2, "load_attributes %x 4\n", ino->i_number);
+ datasize = alist->size;
+ if (alist->resident) {
+ parse_attributes(ino, alist->d.data, &datasize);
return;
}
- buf=ntfs_malloc(1024);
- if( !buf )
+ buf = ntfs_malloc(1024);
+ if (!buf) /* FIXME: Should be passing error code to caller. (AIA) */
return;
- delta=0;
- for(offset=0;datasize;datasize-=len,offset+=len)
- {
+ delta = 0;
+ for (offset = 0; datasize; datasize -= len, offset += len) {
ntfs_io io;
- io.fn_put=ntfs_put;
- io.fn_get=0;
- io.param=buf+delta;
- io.size=len=min(datasize,1024-delta);
- if(ntfs_read_attr(ino,vol->at_attribute_list,0,offset,&io)){
+
+ io.fn_put = ntfs_put;
+ io.fn_get = 0;
+ io.param = buf + delta;
+ io.size = len = min(datasize, 1024 - delta);
+ if (ntfs_read_attr(ino, vol->at_attribute_list, 0, offset,
+ &io))
ntfs_error("error in load_attributes\n");
- }
- delta+=len;
- parse_attributes(ino,buf,&delta);
- if(delta)
- /* move remaining bytes to buffer start */
- ntfs_memmove(buf,buf+len-delta,delta);
+ delta += len;
+ parse_attributes(ino, buf, &delta);
+ if (delta)
+ /* Move remaining bytes to buffer start. */
+ ntfs_memmove(buf, buf + len - delta, delta);
}
- ntfs_debug(DEBUG_FILE2, "load_attributes %x 5\n",ino->i_number);
+ ntfs_debug(DEBUG_FILE2, "load_attributes %x 5\n", ino->i_number);
ntfs_free(buf);
}
-int ntfs_init_inode(ntfs_inode *ino,ntfs_volume *vol,int inum)
+int ntfs_init_inode(ntfs_inode *ino, ntfs_volume *vol, int inum)
{
char *buf;
int error;
- ntfs_debug(DEBUG_FILE1, "Initializing inode %x\n",inum);
- if(!vol)
+ ntfs_debug(DEBUG_FILE1, "Initializing inode %x\n", inum);
+ if (!vol)
ntfs_error("NO VOLUME!\n");
- ino->i_number=inum;
- ino->vol=vol;
- ino->attr=buf=ntfs_malloc(vol->mft_recordsize);
- if( !buf )
- return ENOMEM;
- error=ntfs_read_mft_record(vol,inum,ino->attr);
- if(error){
- ntfs_debug(DEBUG_OTHER, "init inode: %x failed\n",inum);
+ ino->i_number = inum;
+ ino->vol = vol;
+ ino->attr = buf = ntfs_malloc(vol->mft_recordsize);
+ if (!buf)
+ return -ENOMEM;
+ error = ntfs_read_mft_record(vol, inum, ino->attr);
+ if (error) {
+ ntfs_debug(DEBUG_OTHER, "Init inode: %x failed\n", inum);
return error;
}
- ntfs_debug(DEBUG_FILE2, "Init: got mft %x\n",inum);
- ino->sequence_number=NTFS_GETU16(buf+0x10);
- ino->attr_count=0;
- ino->record_count=0;
- ino->records=0;
- ino->attrs=0;
+ ntfs_debug(DEBUG_FILE2, "Init inode: got mft %x\n", inum);
+ ino->sequence_number = NTFS_GETU16(buf + 0x10);
+ ino->attr_count = 0;
+ ino->record_count = 0;
+ ino->records = 0;
+ ino->attrs = 0;
ntfs_load_attributes(ino);
- ntfs_debug(DEBUG_FILE2, "Init: done %x\n",inum);
+ ntfs_debug(DEBUG_FILE2, "Init inode: done %x\n", inum);
return 0;
}
void ntfs_clear_inode(ntfs_inode *ino)
{
int i;
- if(!ino->attr){
+ if (!ino->attr) {
ntfs_error("ntfs_clear_inode: double free\n");
return;
}
ntfs_free(ino->attr);
- ino->attr=0;
+ ino->attr = 0;
ntfs_free(ino->records);
- ino->records=0;
- for(i=0;i<ino->attr_count;i++)
- {
- if(ino->attrs[i].name)
+ ino->records = 0;
+ for (i = 0; i < ino->attr_count; i++) {
+ if (ino->attrs[i].name)
ntfs_free(ino->attrs[i].name);
- if(ino->attrs[i].resident)
- {
- if(ino->attrs[i].d.data)
+ if (ino->attrs[i].resident) {
+ if (ino->attrs[i].d.data)
ntfs_free(ino->attrs[i].d.data);
- }else{
- if(ino->attrs[i].d.r.runlist)
+ } else {
+ if (ino->attrs[i].d.r.runlist)
ntfs_free(ino->attrs[i].d.r.runlist);
}
}
ntfs_free(ino->attrs);
- ino->attrs=0;
+ ino->attrs = 0;
}
-/* Check and fixup a MFT record */
-int ntfs_check_mft_record(ntfs_volume *vol,char *record)
+/* Check and fixup a MFT record. */
+int ntfs_check_mft_record(ntfs_volume *vol, char *record)
{
return ntfs_fixup_record(vol, record, "FILE", vol->mft_recordsize);
}
/* Return (in result) the value indicating the next available attribute
- chunk number. Works for inodes w/o extension records only */
+ * chunk number. Works for inodes w/o extension records only. */
int ntfs_allocate_attr_number(ntfs_inode *ino, int *result)
{
- if(ino->record_count!=1)
- return EOPNOTSUPP;
- *result=NTFS_GETU16(ino->attr+0x28);
- NTFS_PUTU16(ino->attr+0x28, (*result)+1);
+ if (ino->record_count != 1)
+ return -EOPNOTSUPP;
+ *result = NTFS_GETU16(ino->attr + 0x28);
+ NTFS_PUTU16(ino->attr + 0x28, (*result) + 1);
return 0;
}
-/* find the location of an attribute in the inode. A name of NULL indicates
- unnamed attributes. Return pointer to attribute or NULL if not found */
-char *
-ntfs_get_attr(ntfs_inode *ino,int attr,char *name)
+/* Find the location of an attribute in the inode. A name of NULL indicates
+ * unnamed attributes. Return pointer to attribute or NULL if not found. */
+char *ntfs_get_attr(ntfs_inode *ino, int attr, char *name)
{
- /* location of first attribute */
- char *it= ino->attr + NTFS_GETU16(ino->attr + 0x14);
+ /* Location of first attribute. */
+ char *it = ino->attr + NTFS_GETU16(ino->attr + 0x14);
int type;
int len;
- /* Only check for magic DWORD here, fixup should have happened before */
- if(!IS_MFT_RECORD(ino->attr))return 0;
- do{
- type=NTFS_GETU32(it);
- len=NTFS_GETU16(it+4);
+
+ /* Only check for magic DWORD here, fixup should have happened before.*/
+ if (!IS_MFT_RECORD(ino->attr))
+ return 0;
+ do {
+ type = NTFS_GETU32(it);
+ len = NTFS_GETU16(it + 4);
/* We found the attribute type. Is the name correct, too? */
- if(type==attr)
- {
- int namelen=NTFS_GETU8(it+9);
- char *name_it;
- /* match given name and attribute name if present,
- make sure attribute name is Unicode */
- for(name_it=it+NTFS_GETU16(it+10);namelen;
- name++,name_it+=2,namelen--)
- if(*name_it!=*name || name_it[1])break;
- if(!namelen)break;
- }
- it+=len;
- }while(type!=-1); /* attribute list end with type -1 */
- if(type==-1)return 0;
+ if (type == attr) {
+ int namelen = NTFS_GETU8(it + 9);
+ char *name_it, *n = name;
+ /* Match given name and attribute name if present.
+ Make sure attribute name is Unicode. */
+ if (!name) {
+ goto check_namelen;
+ } else if (namelen) {
+ for (name_it = it + NTFS_GETU16(it + 10);
+ namelen; n++, name_it += 2, namelen--)
+ if (*name_it != *n || name_it[1])
+ break;
+check_namelen:
+ if (!namelen)
+ break;
+ }
+ }
+ it += len;
+ } while (type != -1); /* List of attributes ends with type -1. */
+ if (type == -1)
+ return 0;
return it;
}
-int
-ntfs_get_attr_size(ntfs_inode*ino,int type,char*name)
+int ntfs_get_attr_size(ntfs_inode *ino, int type, char *name)
{
- ntfs_attribute *attr=ntfs_find_attr(ino,type,name);
- if(!attr)return 0;
- return attr->size;
+ ntfs_attribute *attr = ntfs_find_attr(ino, type, name);
+ if (!attr)
+ return 0;
+ return
+ attr->size;
}
-int
-ntfs_attr_is_resident(ntfs_inode*ino,int type,char*name)
+int ntfs_attr_is_resident(ntfs_inode *ino, int type, char *name)
{
- ntfs_attribute *attr=ntfs_find_attr(ino,type,name);
- if(!attr)return 0;
- return attr->resident;
+ ntfs_attribute *attr = ntfs_find_attr(ino, type, name);
+ if (!attr)
+ return 0;
+ return
+ attr->resident;
}
/*
@@ -413,489 +436,520 @@
* This function decodes a run. Length is an output parameter, data and cluster
* are in/out parameters.
*/
-int ntfs_decompress_run(unsigned char **data, int *length, ntfs_cluster_t *cluster,
- int *ctype)
+int ntfs_decompress_run(unsigned char **data, int *length,
+ ntfs_cluster_t *cluster, int *ctype)
{
- unsigned char type=*(*data)++;
- *ctype=0;
- switch(type & 0xF)
- {
- case 1: *length=NTFS_GETU8(*data);break;
- case 2: *length=NTFS_GETU16(*data);break;
- case 3: *length=NTFS_GETU24(*data);break;
- case 4: *length=NTFS_GETU32(*data);break;
- /* Note: cases 5-8 are probably pointless to code,
- since how many runs > 4GB of length are there?
- at the most, cases 5 and 6 are probably necessary,
- and would also require making length 64-bit
- throughout */
+ unsigned char type = *(*data)++;
+ *ctype = 0;
+ switch (type & 0xF) {
+ case 1:
+ *length = NTFS_GETS8(*data);
+ break;
+ case 2:
+ *length = NTFS_GETS16(*data);
+ break;
+ case 3:
+ *length = NTFS_GETS24(*data);
+ break;
+ case 4:
+ *length = NTFS_GETS32(*data);
+ break;
+ /* Note: cases 5-8 are probably pointless to code, since how
+ * many runs > 4GB of length are there? At the most, cases 5
+ * and 6 are probably necessary, and would also require making
+ * length 64-bit throughout. */
default:
- ntfs_error("Can't decode run type field %x\n",type);
+ ntfs_error("Can't decode run type field %x\n", type);
return -1;
}
- *data+=(type & 0xF);
-
- switch(type & 0xF0)
+ if (*length < 0)
{
- case 0: *ctype=2; break;
- case 0x10: *cluster += NTFS_GETS8(*data);break;
- case 0x20: *cluster += NTFS_GETS16(*data);break;
- case 0x30: *cluster += NTFS_GETS24(*data);break;
- case 0x40: *cluster += NTFS_GETS32(*data);break;
-#if 0 /* Keep for future, in case ntfs_cluster_t ever becomes 64bit */
- case 0x50: *cluster += NTFS_GETS40(*data);break;
- case 0x60: *cluster += NTFS_GETS48(*data);break;
- case 0x70: *cluster += NTFS_GETS56(*data);break;
- case 0x80: *cluster += NTFS_GETS64(*data);break;
+ ntfs_error("Negative run length decoded\n");
+ return -1;
+ }
+ *data += (type & 0xF);
+ switch (type & 0xF0) {
+ case 0:
+ *ctype = 2;
+ break;
+ case 0x10:
+ *cluster += NTFS_GETS8(*data);
+ break;
+ case 0x20:
+ *cluster += NTFS_GETS16(*data);
+ break;
+ case 0x30:
+ *cluster += NTFS_GETS24(*data);
+ break;
+ case 0x40:
+ *cluster += NTFS_GETS32(*data);
+ break;
+#if 0 /* Keep for future, in case ntfs_cluster_t ever becomes 64bit. */
+ case 0x50:
+ *cluster += NTFS_GETS40(*data);
+ break;
+ case 0x60:
+ *cluster += NTFS_GETS48(*data);
+ break;
+ case 0x70:
+ *cluster += NTFS_GETS56(*data);
+ break;
+ case 0x80:
+ *cluster += NTFS_GETS64(*data);
+ break;
#endif
default:
- ntfs_error("Can't decode run type field %x\n",type);
+ ntfs_error("Can't decode run type field %x\n", type);
return -1;
}
- *data+=(type >> 4);
+ *data += (type >> 4);
return 0;
}
-/* Reads l bytes of the attribute (attr,name) of ino starting at offset
- on vol into buf. Returns the number of bytes read in the ntfs_io struct.
- Returns 0 on success, errno on failure */
+/*
+ * FIXME: ntfs_readwrite_attr() has the effect of writing @dest to @offset of
+ * the attribute value of the attribute @attr in the in memory inode @ino.
+ * If the attribute value of @attr is non-resident the value's contents at
+ * @offset are actually written to disk (from @dest). The on disk mft record
+ * describing the non-resident attribute value is not updated!
+ * If the attribute value is resident then the value is written only in
+ * memory. The on disk mft record containing the value is not written to disk.
+ * A possible fix would be to call ntfs_update_inode() before returning. (AIA)
+ */
+/* Reads l bytes of the attribute (attr, name) of ino starting at offset on
+ * vol into buf. Returns the number of bytes read in the ntfs_io struct.
+ * Returns 0 on success, errno on failure */
int ntfs_readwrite_attr(ntfs_inode *ino, ntfs_attribute *attr, int offset,
- ntfs_io *dest)
+ ntfs_io *dest)
{
int rnum;
- ntfs_cluster_t cluster,s_cluster,vcn,len;
- int l,chunk,copied;
+ ntfs_cluster_t cluster, s_cluster, vcn, len;
+ int l, chunk, copied;
int s_vcn;
int clustersize;
int error;
- clustersize=ino->vol->clustersize;
- l=dest->size;
- if(l==0)
+ clustersize = ino->vol->clustersize;
+ l = dest->size;
+ if (l == 0)
return 0;
- if(dest->do_read)
- {
- /* if read _starts_ beyond end of stream, return nothing */
- if(offset>=attr->size){
- dest->size=0;
+ if (dest->do_read) {
+ /* If read _starts_ beyond end of stream, return nothing. */
+ if (offset >= attr->size) {
+ dest->size = 0;
return 0;
}
-
- /* if read _extends_ beyond end of stream, return as much
- initialised data as we have */
- if(offset+l>=attr->size)
- l=dest->size=attr->size-offset;
-
- }else {
- /* fixed by CSA: if writing beyond end, extend attribute */
-
- /* if write extends beyond _allocated_ size, extend attrib */
- if (offset+l>attr->allocated) {
- error=ntfs_resize_attr(ino,attr,offset+l);
- if(error)
+ /* If read _extends_ beyond end of stream, return as much
+ * initialised data as we have. */
+ if (offset + l >= attr->size)
+ l = dest->size = attr->size - offset;
+ } else {
+ /* Fixed by CSA: If writing beyond end, extend attribute. */
+ /* If write extends beyond _allocated_ size, extend attrib. */
+ if (offset + l > attr->allocated) {
+ error = ntfs_resize_attr(ino, attr, offset + l);
+ if (error)
return error;
}
-
- /* the amount of initialised data has increased; update */
- /* FIXME: shouldn't we zero-out the section between the old
- initialised length and the write start? */
- if (offset+l > attr->initialized) {
- attr->initialized = offset+l;
- attr->size = offset+l;
+ /* The amount of initialised data has increased: update. */
+ /* FIXME: Shouldn't we zero-out the section between the old
+ * initialised length and the write start? */
+ if (offset + l > attr->initialized) {
+ attr->initialized = offset + l;
+ attr->size = offset + l;
}
}
- if(attr->resident)
- {
- if(dest->do_read)
- dest->fn_put(dest,(ntfs_u8*)attr->d.data+offset,l);
+ if (attr->resident) {
+ if (dest->do_read)
+ dest->fn_put(dest, (ntfs_u8*)attr->d.data + offset, l);
else
- dest->fn_get((ntfs_u8*)attr->d.data+offset,dest,l);
- dest->size=l;
+ dest->fn_get((ntfs_u8*)attr->d.data + offset, dest, l);
+ dest->size = l;
return 0;
}
- /* read uninitialized data */
- if(offset>=attr->initialized && dest->do_read)
- return ntfs_read_zero(dest,l);
- if(offset+l>attr->initialized && dest->do_read)
- {
- dest->size = chunk = offset+l - attr->initialized;
- error = ntfs_readwrite_attr(ino,attr,offset,dest);
- if(error)
+ /* Read uninitialized data. */
+ if (offset >= attr->initialized && dest->do_read)
+ return ntfs_read_zero(dest, l);
+ if (offset + l > attr->initialized && dest->do_read) {
+ dest->size = chunk = offset + l - attr->initialized;
+ error = ntfs_readwrite_attr(ino, attr, offset, dest);
+ if (error)
return error;
- return ntfs_read_zero(dest,l-chunk);
+ return ntfs_read_zero(dest, l - chunk);
}
- if(attr->compressed){
- if(dest->do_read)
- return ntfs_read_compressed(ino,attr,offset,dest);
+ if (attr->compressed) {
+ if (dest->do_read)
+ return ntfs_read_compressed(ino, attr, offset, dest);
else
- return ntfs_write_compressed(ino,attr,offset,dest);
+ return ntfs_write_compressed(ino, attr, offset, dest);
}
- vcn=0;
- s_vcn = offset/clustersize;
- for(rnum=0;rnum<attr->d.r.len &&
- vcn+attr->d.r.runlist[rnum].len<=s_vcn;rnum++)
- vcn+=attr->d.r.runlist[rnum].len;
- if(rnum==attr->d.r.len)
- /*FIXME: should extend runlist */
- return EOPNOTSUPP;
-
- copied=0;
- while(l)
- {
- s_vcn = offset/clustersize;
- cluster=attr->d.r.runlist[rnum].cluster;
- len=attr->d.r.runlist[rnum].len;
-
- s_cluster = cluster+s_vcn-vcn;
-
- chunk=min((vcn+len)*clustersize-offset,l);
- dest->size=chunk;
- error=ntfs_getput_clusters(ino->vol,s_cluster,
- offset-s_vcn*clustersize,dest);
- if(error)
- {
- ntfs_error("Read error\n");
- dest->size=copied;
+ vcn = 0;
+ s_vcn = offset / clustersize;
+ for (rnum = 0; rnum < attr->d.r.len &&
+ vcn + attr->d.r.runlist[rnum].len <= s_vcn; rnum++)
+ vcn += attr->d.r.runlist[rnum].len;
+ if (rnum == attr->d.r.len)
+ /*FIXME: Should extend runlist. */
+ return -EOPNOTSUPP;
+ copied = 0;
+ while (l) {
+ s_vcn = offset / clustersize;
+ cluster = attr->d.r.runlist[rnum].cluster;
+ len = attr->d.r.runlist[rnum].len;
+ s_cluster = cluster + s_vcn - vcn;
+ chunk = min((vcn + len) * clustersize - offset, l);
+ dest->size = chunk;
+ error = ntfs_getput_clusters(ino->vol, s_cluster,
+ offset - s_vcn * clustersize, dest);
+ if (error) {
+ ntfs_error("Read/write error\n");
+ dest->size = copied;
return error;
}
- l-=chunk;
- copied+=chunk;
- offset+=chunk;
- if(l && offset>=((vcn+len)*clustersize))
- {
+ l -= chunk;
+ copied += chunk;
+ offset += chunk;
+ if (l && offset >= ((vcn + len) * clustersize)) {
rnum++;
- vcn+=len;
+ vcn += len;
cluster = attr->d.r.runlist[rnum].cluster;
len = attr->d.r.runlist[rnum].len;
}
}
- dest->size=copied;
+ dest->size = copied;
return 0;
}
int ntfs_read_attr(ntfs_inode *ino, int type, char *name, int offset,
- ntfs_io *buf)
+ ntfs_io *buf)
{
ntfs_attribute *attr;
- buf->do_read=1;
- attr=ntfs_find_attr(ino,type,name);
- if(!attr)
- return EINVAL;
- return ntfs_readwrite_attr(ino,attr,offset,buf);
+
+ buf->do_read = 1;
+ attr = ntfs_find_attr(ino, type, name);
+ if (!attr)
+ return -EINVAL;
+ return ntfs_readwrite_attr(ino, attr, offset, buf);
}
int ntfs_write_attr(ntfs_inode *ino, int type, char *name, int offset,
- ntfs_io *buf)
+ ntfs_io *buf)
{
ntfs_attribute *attr;
- buf->do_read=0;
- attr=ntfs_find_attr(ino,type,name);
- if(!attr)
- return EINVAL;
- return ntfs_readwrite_attr(ino,attr,offset,buf);
+
+ buf->do_read = 0;
+ attr = ntfs_find_attr(ino, type, name);
+ if (!attr)
+ return -EINVAL;
+ return ntfs_readwrite_attr(ino, attr, offset, buf);
}
-int ntfs_vcn_to_lcn(ntfs_inode *ino,int vcn)
+int ntfs_vcn_to_lcn(ntfs_inode *ino, int vcn)
{
int rnum;
ntfs_attribute *data;
- data=ntfs_find_attr(ino,ino->vol->at_data,0);
- /* It's hard to give an error code */
- if(!data)return -1;
- if(data->resident)return -1;
- if(data->compressed)return -1;
- if(data->size <= vcn*ino->vol->clustersize)return -1;
-
-
+
+ data = ntfs_find_attr(ino, ino->vol->at_data, 0);
+ /* It's hard to give an error code. */
+ if (!data || data->resident || data->compressed)
+ return -1;
+ if (data->size <= vcn*ino->vol->clustersize)
+ return -1;
/* For Linux, block number 0 represents a hole.
- Hopefully, nobody will attempt to bmap $Boot. */
- if(data->initialized <= vcn*ino->vol->clustersize)
+ * Hopefully, nobody will attempt to bmap $Boot. */
+ if (data->initialized <= vcn * ino->vol->clustersize)
return 0;
-
- for(rnum=0;rnum<data->d.r.len &&
- vcn>=data->d.r.runlist[rnum].len;rnum++)
- vcn-=data->d.r.runlist[rnum].len;
-
- return data->d.r.runlist[rnum].cluster+vcn;
+ for (rnum = 0; rnum < data->d.r.len &&
+ vcn >= data->d.r.runlist[rnum].len; rnum++)
+ vcn -= data->d.r.runlist[rnum].len;
+ return data->d.r.runlist[rnum].cluster + vcn;
}
-static int
-allocate_store(ntfs_volume *vol,ntfs_disk_inode *store,int count)
+static int allocate_store(ntfs_volume *vol, ntfs_disk_inode *store, int count)
{
int i;
- if(store->count>count)
+
+ if (store->count > count)
return 0;
- if(store->size<count){
- ntfs_mft_record* n=ntfs_malloc((count+4)*sizeof(ntfs_mft_record));
- if(!n)
- return ENOMEM;
- if(store->size){
- for(i=0;i<store->size;i++)
- n[i]=store->records[i];
+ if (store->size < count) {
+ ntfs_mft_record *n = ntfs_malloc((count + 4) *
+ sizeof(ntfs_mft_record));
+ if (!n)
+ return -ENOMEM;
+ if (store->size) {
+ for (i = 0; i < store->size; i++)
+ n[i] = store->records[i];
ntfs_free(store->records);
}
- store->size=count+4;
- store->records=n;
+ store->size = count + 4;
+ store->records = n;
}
- for(i=store->count;i<count;i++){
- store->records[i].record=ntfs_malloc(vol->mft_recordsize);
- if(!store->records[i].record)
- return ENOMEM;
+ for (i = store->count; i < count; i++) {
+ store->records[i].record = ntfs_malloc(vol->mft_recordsize);
+ if (!store->records[i].record)
+ return -ENOMEM;
store->count++;
}
return 0;
}
-static void
-deallocate_store(ntfs_disk_inode* store)
+static void deallocate_store(ntfs_disk_inode* store)
{
int i;
- for(i=0;i<store->count;i++)
+
+ for (i = 0; i < store->count; i++)
ntfs_free(store->records[i].record);
ntfs_free(store->records);
- store->count=store->size=0;
- store->records=0;
+ store->count = store->size = 0;
+ store->records = 0;
}
-int
-layout_runs(ntfs_attribute *attr,char* rec,int* offs,int size)
+/**
+ * layout_runs - compress runlist into mapping pairs array
+ * @attr: attribute containing the runlist to compress
+ * @rec: destination buffer to hold the mapping pairs array
+ * @offs: current position in @rec (in/out variable)
+ * @size: size of the buffer @rec
+ *
+ * layout_runs walks the runlist in @attr, compresses it and writes it out the
+ * resulting mapping pairs array into @rec (up to a maximum of @size bytes are
+ * written). On entry @offs is the offset in @rec at which to begin writting the
+ * mapping pairs array. On exit, it contains the offset in @rec of the first
+ * byte after the end of the mapping pairs array.
+ */
+static int layout_runs(ntfs_attribute *attr, char* rec, int* offs, int size)
{
- int i,len,offset,coffs;
- ntfs_cluster_t cluster,rclus;
- ntfs_runlist *rl=attr->d.r.runlist;
- cluster=0;
- offset=*offs;
- for(i=0;i<attr->d.r.len;i++){
- rclus=rl[i].cluster-cluster;
- len=rl[i].len;
- rec[offset]=0;
- if(offset+8>size)
- return E2BIG; /* it might still fit, but this simplifies testing */
- if(len<0x100){
- NTFS_PUTU8(rec+offset+1,len);
- coffs=1;
- }else if(len<0x10000){
- NTFS_PUTU16(rec+offset+1,len);
- coffs=2;
- }else if(len<0x1000000){
- NTFS_PUTU24(rec+offset+1,len);
- coffs=3;
- }else{
- NTFS_PUTU32(rec+offset+1,len);
- coffs=4;
- }
-
- *(rec+offset)|=coffs++;
-
- if(rl[i].cluster==MAX_CLUSTER_T) /*compressed run*/
- /*nothing*/;
- else if(rclus>-0x80 && rclus<0x7F){
- *(rec+offset)|=0x10;
- NTFS_PUTS8(rec+offset+coffs,rclus);
- coffs+=1;
- }else if(rclus>-0x8000 && rclus<0x7FFF){
- *(rec+offset)|=0x20;
- NTFS_PUTS16(rec+offset+coffs,rclus);
- coffs+=2;
- }else if(rclus>-0x800000 && rclus<0x7FFFFF){
- *(rec+offset)|=0x30;
- NTFS_PUTS24(rec+offset+coffs,rclus);
- coffs+=3;
- }else
-#if 0 /* In case ntfs_cluster_t ever becomes 64bit */
- if (rclus>-0x80000000LL && rclus<0x7FFFFFFF)
+ int i, len, offset, coffs;
+ ntfs_cluster_t cluster, rclus;
+ ntfs_runlist *rl = attr->d.r.runlist;
+ cluster = 0;
+ offset = *offs;
+ for (i = 0; i < attr->d.r.len; i++) {
+ rclus = rl[i].cluster - cluster;
+ len = rl[i].len;
+ rec[offset] = 0;
+ if (offset + 9 > size)
+ return -E2BIG; /* It might still fit, but this
+ * simplifies testing. */
+ /* Run length is stored as signed number. */
+ if (len <= 0x7F) {
+ NTFS_PUTU8(rec + offset + 1, len);
+ coffs = 1;
+ } else if (len <= 0x7FFF) {
+ NTFS_PUTU16(rec + offset + 1, len);
+ coffs = 2;
+ } else if (len <= 0x7FFFFF) {
+ NTFS_PUTU24(rec + offset + 1, len);
+ coffs = 3;
+ } else {
+ NTFS_PUTU32(rec + offset + 1, len);
+ coffs = 4;
+ }
+ *(rec + offset) |= coffs++;
+ if (rl[i].cluster == MAX_CLUSTER_T) /* Compressed run. */
+ /* Nothing */;
+ else if (rclus >= -0x80 && rclus <= 0x7F) {
+ *(rec + offset) |= 0x10;
+ NTFS_PUTS8(rec + offset + coffs, rclus);
+ coffs += 1;
+ } else if(rclus >= -0x8000 && rclus <= 0x7FFF) {
+ *(rec + offset) |= 0x20;
+ NTFS_PUTS16(rec + offset + coffs, rclus);
+ coffs += 2;
+ } else if(rclus >= -0x800000 && rclus <= 0x7FFFFF) {
+ *(rec + offset) |= 0x30;
+ NTFS_PUTS24(rec + offset + coffs, rclus);
+ coffs += 3;
+ } else
+#if 0 /* In case ntfs_cluster_t ever becomes 64bit. */
+ if (rclus >= -0x80000000LL && rclus <= 0x7FFFFFFF)
#endif
{
- *(rec+offset)|=0x40;
- NTFS_PUTS32(rec+offset+coffs,rclus);
- coffs+=4;
+ *(rec + offset) |= 0x40;
+ NTFS_PUTS32(rec + offset + coffs, rclus);
+ coffs += 4;
}
#if 0 /* For 64-bit ntfs_cluster_t */
- else if (rclus>-0x8000000000 && rclus<0x7FFFFFFFFF){
- *(rec+offset)|=0x50;
- NTFS_PUTS40(rec+offset+coffs,rclus);
- coffs+=5;
- }else if (rclus>-0x800000000000 && rclus<0x7FFFFFFFFFFF){
- *(rec+offset)|=0x60;
- NTFS_PUTS48(rec+offset+coffs,rclus);
- coffs+=6;
- }else if (rclus>-0x80000000000000 && rclus<0x7FFFFFFFFFFFFF){
- *(rec+offset)|=0x70;
- NTFS_PUTS56(rec+offset+coffs,rclus);
- coffs+=7;
- }else{
- *(rec+offset)|=0x80;
- NTFS_PUTS64(rec+offset+coffs,rclus);
- coffs+=8;
+ else if (rclus >= -0x8000000000 && rclus <= 0x7FFFFFFFFF) {
+ *(rec + offset) |= 0x50;
+ NTFS_PUTS40(rec + offset + coffs, rclus);
+ coffs += 5;
+ } else if (rclus >= -0x800000000000 &&
+ rclus <= 0x7FFFFFFFFFFF) {
+ *(rec + offset) |= 0x60;
+ NTFS_PUTS48(rec + offset + coffs, rclus);
+ coffs += 6;
+ } else if (rclus >= -0x80000000000000 &&
+ rclus <= 0x7FFFFFFFFFFFFF) {
+ *(rec + offset) |= 0x70;
+ NTFS_PUTS56(rec + offset + coffs, rclus);
+ coffs += 7;
+ } else {
+ *(rec + offset) |= 0x80;
+ NTFS_PUTS64(rec + offset + coffs, rclus);
+ coffs += 8;
}
#endif
- offset+=coffs;
- if(rl[i].cluster)
- cluster=rl[i].cluster;
- }
- if(offset>=size)
- return E2BIG;
- /* terminating null */
- *(rec+offset++)=0;
- *offs=offset;
+ offset += coffs;
+ if (rl[i].cluster)
+ cluster = rl[i].cluster;
+ }
+ if (offset >= size)
+ return -E2BIG;
+ /* Terminating null. */
+ *(rec + offset++) = 0;
+ *offs = offset;
return 0;
}
-static void
-count_runs(ntfs_attribute *attr,char *buf)
+static void count_runs(ntfs_attribute *attr, char *buf)
{
- ntfs_u32 first,count,last,i;
- first=0;
- for(i=0,count=0;i<attr->d.r.len;i++)
- count+=attr->d.r.runlist[i].len;
- last=first+count-1;
-
- NTFS_PUTU64(buf+0x10,first);
- NTFS_PUTU64(buf+0x18,last);
+ ntfs_u32 first, count, last, i;
+
+ first = 0;
+ for (i = 0, count = 0; i < attr->d.r.len; i++)
+ count += attr->d.r.runlist[i].len;
+ last = first + count - 1;
+ NTFS_PUTU64(buf + 0x10, first);
+ NTFS_PUTU64(buf + 0x18, last);
}
-static int
-layout_attr(ntfs_attribute* attr,char*buf, int size,int *psize)
+/**
+ * layout_attr - convert in memory attribute to on disk attribute record
+ * @attr: in memory attribute to convert
+ * @buf: destination buffer for on disk attribute record
+ * @size: size of the destination buffer
+ * @psize: size of converted on disk attribute record (out variable)
+ *
+ * layout_attr takes the attribute @attr and converts it into the appropriate
+ * on disk structure, writing it into @buf (up to @size bytes are written).
+ * On return, @psize contains the actual size of the on disk attribute written
+ * into @buf.
+ */
+static int layout_attr(ntfs_attribute* attr, char *buf, int size, int *psize)
{
- int asize,error;
- if(size<10)return E2BIG;
- NTFS_PUTU32(buf,attr->type);
- /* fill in length later */
- NTFS_PUTU8(buf+8,attr->resident ? 0:1);
- NTFS_PUTU8(buf+9,attr->namelen);
- /* fill in offset to name later */
- NTFS_PUTU16(buf+0xA,0);
- NTFS_PUTU16(buf+0xC,attr->compressed);
- /* FIXME: assign attribute ID??? */
- NTFS_PUTU16(buf+0xE,attr->attrno);
- if(attr->resident){
- if(size<attr->size+0x18+attr->namelen)return E2BIG;
- asize=0x18;
- NTFS_PUTU32(buf+0x10,attr->size);
- NTFS_PUTU16(buf+0x16,attr->indexed);
- if(attr->name){
- ntfs_memcpy(buf+asize,attr->name,2*attr->namelen);
- NTFS_PUTU16(buf+0xA,asize);
- asize+=2*attr->namelen;
- asize=(asize+7) & ~7;
- }
- NTFS_PUTU16(buf+0x14,asize);
- ntfs_memcpy(buf+asize,attr->d.data,attr->size);
- asize+=attr->size;
- }else{
+ int asize, error;
+ if (size < 10)
+ return -E2BIG;
+ NTFS_PUTU32(buf, attr->type);
+ /* Fill in length later. */
+ NTFS_PUTU8(buf + 8, attr->resident ? 0 : 1);
+ NTFS_PUTU8(buf + 9, attr->namelen);
+ /* Fill in offset to name later. */
+ NTFS_PUTU16(buf + 0xA, 0);
+ NTFS_PUTU16(buf + 0xC, attr->compressed);
+ /* Assign attribute instance. */
+ NTFS_PUTU16(buf + 0xE, attr->attrno);
+ if (attr->resident) {
+ if (size < attr->size + 0x18 + attr->namelen)
+ return -E2BIG;
+ asize = 0x18;
+ NTFS_PUTU32(buf + 0x10, attr->size);
+ NTFS_PUTU16(buf + 0x16, attr->indexed);
+ if (attr->name) {
+ ntfs_memcpy(buf + asize, attr->name, 2 * attr->namelen);
+ NTFS_PUTU16(buf + 0xA, asize);
+ asize += 2 * attr->namelen;
+ asize = (asize + 7) & ~7;
+ }
+ NTFS_PUTU16(buf + 0x14, asize);
+ ntfs_memcpy(buf + asize, attr->d.data, attr->size);
+ asize += attr->size;
+ } else {
/* FIXME: fragments */
- count_runs(attr,buf);
- /* offset to data is added later */
- NTFS_PUTU16(buf+0x22,attr->cengine);
- NTFS_PUTU32(buf+0x24,0);
- NTFS_PUTU64(buf+0x28,attr->allocated);
- NTFS_PUTU64(buf+0x30,attr->size);
- NTFS_PUTU64(buf+0x38,attr->initialized);
- if(attr->compressed){
- NTFS_PUTU64(buf+0x40,attr->compsize);
- asize=0x48;
- }else
- asize=0x40;
- if(attr->name){
- NTFS_PUTU16(buf+0xA,asize);
- ntfs_memcpy(buf+asize,attr->name,2*attr->namelen);
- asize+=2*attr->namelen;
- /* SRD: you whaaa?
- asize=(asize+7) & ~7;*/
- }
- /* asize points at the beginning of the data */
- NTFS_PUTU16(buf+0x20,asize);
- error=layout_runs(attr,buf,&asize,size);
- /* now asize pointes at the end of the data */
- if(error)
+ count_runs(attr, buf);
+ /* Offset to data is added later. */
+ NTFS_PUTU16(buf + 0x22, attr->cengine);
+ NTFS_PUTU32(buf + 0x24, 0);
+ NTFS_PUTU64(buf + 0x28, attr->allocated);
+ NTFS_PUTU64(buf + 0x30, attr->size);
+ NTFS_PUTU64(buf + 0x38, attr->initialized);
+ if (attr->compressed) {
+ NTFS_PUTU64(buf + 0x40, attr->compsize);
+ asize = 0x48;
+ } else
+ asize = 0x40;
+ if (attr->name) {
+ NTFS_PUTU16(buf + 0xA, asize);
+ ntfs_memcpy(buf + asize, attr->name, 2 * attr->namelen);
+ asize += 2 * attr->namelen;
+ /* SRD: you whaaa? - AIA: Align to next 8 byte boundary
+ * as required by NTFS design and implementation. */
+ asize = (asize + 7) & ~7;
+ }
+ /* asize points at the beginning of the data. */
+ NTFS_PUTU16(buf + 0x20, asize);
+ error = layout_runs(attr, buf, &asize, size);
+ /* Now asize points at the end of the data. */
+ if (error)
return error;
}
- asize=(asize+7) & ~7;
- NTFS_PUTU32(buf+4,asize);
- *psize=asize;
+ asize = (asize + 7) & ~7;
+ NTFS_PUTU32(buf + 4, asize);
+ *psize = asize;
return 0;
}
-
-
-/* Try to layout ino into store. Return 0 on success,
- E2BIG if it does not fit,
- ENOMEM if memory allocation problem,
- EOPNOTSUP if beyond our capabilities
-*/
-int
-layout_inode(ntfs_inode *ino,ntfs_disk_inode *store)
+/**
+ * layout_inode - convert an in memory inode into on disk mft record(s)
+ * @ino: in memory inode to convert
+ * @store: on disk inode, contain buffers for the on disk mft record(s)
+ *
+ * layout_inode takes the in memory inode @ino, converts it into a (sequence of)
+ * mft record(s) and writes them to the appropriate buffers in the @store.
+ *
+ * Return 0 on success,
+ * the required mft record count (>0) if the inode does not fit,
+ * -ENOMEM if memory allocation problem or
+ * -EOPNOTSUP if beyond our capabilities.
+ */
+int layout_inode(ntfs_inode *ino, ntfs_disk_inode *store)
{
- int offset,i;
+ int offset, i;
ntfs_attribute *attr;
unsigned char *rec;
- int size,psize;
+ int size, psize;
int error;
- if(ino->record_count>1)
- {
+ if (ino->record_count > 1) {
ntfs_error("layout_inode: attribute lists not supported\n");
- return EOPNOTSUPP;
+ return -EOPNOTSUPP;
}
- error=allocate_store(ino->vol,store,1);
- if(error)
+ error = allocate_store(ino->vol, store, 1);
+ if (error)
return error;
- rec=store->records[0].record;
- size=ino->vol->mft_recordsize;
- store->records[0].recno=ino->records[0];
- /* copy header */
- offset=NTFS_GETU16(ino->attr+0x14);
- ntfs_memcpy(rec,ino->attr,offset);
- for(i=0;i<ino->attr_count;i++){
- attr=ino->attrs+i;
- error=layout_attr(attr,rec+offset,size-offset,&psize);
- if(error)return error;
- offset+=psize;
-#if 0
- /* copy attribute header */
- ntfs_memcpy(rec+offset,attr->header,
- min(sizeof(attr->header),size-offset)); /* consider overrun */
- if(attr->namelen)
- /* named attributes are added later */
- return EOPNOTSUPP;
- /* FIXME: assign attribute ID??? */
- if(attr->resident){
- asize=attr->size;
- aoffset=NTFS_GETU16(rec+offset+0x14);
- if(offset+aoffset+asize>size)
- return E2BIG;
- ntfs_memcpy(rec+offset+aoffset,attr->d.data,asize);
- next=offset+aoffset+asize;
- }else{
- count_runs(attr,rec+offset);
- aoffset=NTFS_GETU16(rec+offset+0x20);
- next=offset+aoffset;
- error=layout_runs(attr,rec,&next,size);
- if(error)
- return error;
- }
- /* SRD: umm..
- next=(next+7) & ~7; */
- /* is this setting the length? if so maybe we could get
- away with rounding up so long as we set the length first..
- ..except, is the length the only way to get to the next attr?
- */
- NTFS_PUTU16(rec+offset+4,next-offset);
- offset=next;
-#endif
+ rec = store->records[0].record;
+ size = ino->vol->mft_recordsize;
+ store->records[0].recno = ino->records[0];
+ /* Copy header. */
+ offset = NTFS_GETU16(ino->attr + 0x14);
+ ntfs_memcpy(rec, ino->attr, offset);
+ for (i = 0; i < ino->attr_count; i++) {
+ attr = ino->attrs + i;
+ error = layout_attr(attr, rec + offset, size - offset, &psize);
+ if (error)
+ return error;
+ offset += psize;
}
- /* terminating attribute */
- if(offset+8<size){
- NTFS_PUTU32(rec+offset,0xFFFFFFFF);
- offset+=4;
- NTFS_PUTU32(rec+offset,0);
- offset+=4;
- }else
- return E2BIG;
- NTFS_PUTU32(rec+0x18,offset);
+ /* Terminating attribute. */
+ if (offset + 8 < size) {
+ NTFS_PUTU32(rec + offset, 0xFFFFFFFF);
+ offset += 4;
+ NTFS_PUTU32(rec + offset, 0);
+ offset += 4;
+ } else
+ return -E2BIG;
+ NTFS_PUTU32(rec + 0x18, offset);
return 0;
}
-
+
+/*
+ * FIXME: ntfs_update_inode() calls layout_inode() to create the mft record on
+ * disk structure corresponding to the inode @ino. After that, ntfs_write_attr()
+ * is called to write out the created mft record to disk.
+ * We shouldn't need to re-layout every single time we are updating an mft
+ * record. No wonder the ntfs driver is slow like hell. (AIA)
+ */
int ntfs_update_inode(ntfs_inode *ino)
{
int error;
@@ -903,218 +957,217 @@
ntfs_io io;
int i;
- store.count=store.size=0;
- store.records=0;
- error=layout_inode(ino,&store);
- if(error==E2BIG){
+ store.count = store.size = 0;
+ store.records = 0;
+ error = layout_inode(ino, &store);
+ if (error == -E2BIG) {
error = ntfs_split_indexroot(ino);
- if(!error)
- error = layout_inode(ino,&store);
+ if (!error)
+ error = layout_inode(ino, &store);
}
- if(error == E2BIG){
+ if (error == -E2BIG) {
error = ntfs_attr_allnonresident(ino);
- if(!error)
- error = layout_inode(ino,&store);
+ if (!error)
+ error = layout_inode(ino, &store);
}
- if(error == E2BIG){
- /* should try:
- introduce extension records
- */
- ntfs_error("cannot handle saving inode %x\n",ino->i_number);
+ if (error == -E2BIG) {
+ /* FIXME: should try: introduce extension records */
+ ntfs_error("cannot handle saving inode %x\n", ino->i_number);
deallocate_store(&store);
- return EOPNOTSUPP;
+ return -EOPNOTSUPP;
}
- if(error){
+ if (error) {
deallocate_store(&store);
return error;
}
- io.fn_get=ntfs_get;
- io.fn_put=0;
- for(i=0;i<store.count;i++){
- ntfs_insert_fixups(store.records[i].record,ino->vol->blocksize);
- io.param=store.records[i].record;
- io.size=ino->vol->mft_recordsize;
- /* FIXME: is this the right way? */
- error=ntfs_write_attr(
- ino->vol->mft_ino,ino->vol->at_data,0,
- store.records[i].recno*ino->vol->mft_recordsize,&io);
- if(error || io.size!=ino->vol->mft_recordsize){
- /* big trouble, partially written file */
- ntfs_error("Please unmount: write error in inode %x\n",ino->i_number);
+ io.fn_get = ntfs_get;
+ io.fn_put = 0;
+ for (i = 0; i < store.count; i++) {
+ ntfs_insert_fixups(store.records[i].record,
+ ino->vol->blocksize);
+ io.param = store.records[i].record;
+ io.size = ino->vol->mft_recordsize;
+ /* FIXME: Is this the right way? */
+ error = ntfs_write_attr(ino->vol->mft_ino, ino->vol->at_data,
+ 0, store.records[i].recno *
+ ino->vol->mft_recordsize, &io);
+ if (error || io.size != ino->vol->mft_recordsize) {
+ /* Big trouble, partially written file. */
+ ntfs_error("Please unmount: Write error in inode %x\n",
+ ino->i_number);
deallocate_store(&store);
- return error?error:EIO;
+ return error ? error : -EIO;
}
}
return 0;
}
-
void ntfs_decompress(unsigned char *dest, unsigned char *src, ntfs_size_t l)
{
- int head,comp;
- int copied=0;
+ int head, comp;
+ int copied = 0;
unsigned char *stop;
int bits;
- int tag=0;
+ int tag = 0;
int clear_pos;
- while(1)
- {
+
+ while (1) {
head = NTFS_GETU16(src) & 0xFFF;
- /* high bit indicates that compression was performed */
+ /* High bit indicates that compression was performed. */
comp = NTFS_GETU16(src) & 0x8000;
src += 2;
- stop = src+head;
+ stop = src + head;
bits = 0;
- clear_pos=0;
- if(head==0)
- /* block is not used */
+ clear_pos = 0;
+ if (head == 0)
+ /* Block is not used. */
return;/* FIXME: copied */
- if(!comp) /* uncompressible */
- {
- ntfs_memcpy(dest,src,0x1000);
- dest+=0x1000;
- copied+=0x1000;
- src+=0x1000;
- if(l==copied)
+ if (!comp) { /* uncompressible */
+ ntfs_memcpy(dest, src, 0x1000);
+ dest += 0x1000;
+ copied += 0x1000;
+ src += 0x1000;
+ if (l == copied)
return;
continue;
}
- while(src<=stop)
- {
- if(clear_pos>4096)
- {
+ while (src <= stop) {
+ if (clear_pos > 4096) {
ntfs_error("Error 1 in decompress\n");
return;
}
- if(!bits){
- tag=NTFS_GETU8(src);
- bits=8;
+ if (!bits) {
+ tag = NTFS_GETU8(src);
+ bits = 8;
src++;
- if(src>stop)
+ if (src > stop)
break;
}
- if(tag & 1){
- int i,len,delta,code,lmask,dshift;
+ if (tag & 1) {
+ int i, len, delta, code, lmask, dshift;
code = NTFS_GETU16(src);
- src+=2;
- if(!clear_pos)
- {
+ src += 2;
+ if (!clear_pos) {
ntfs_error("Error 2 in decompress\n");
return;
}
- for(i=clear_pos-1,lmask=0xFFF,dshift=12;i>=0x10;i>>=1)
- {
+ for (i = clear_pos - 1, lmask = 0xFFF,
+ dshift = 12; i >= 0x10; i >>= 1) {
lmask >>= 1;
dshift--;
}
delta = code >> dshift;
len = (code & lmask) + 3;
- for(i=0; i<len; i++)
- {
- dest[clear_pos]=dest[clear_pos-delta-1];
+ for (i = 0; i < len; i++) {
+ dest[clear_pos] = dest[clear_pos -
+ delta - 1];
clear_pos++;
copied++;
- if(copied==l)
+ if (copied==l)
return;
}
- }else{
- dest[clear_pos++]=NTFS_GETU8(src);
+ } else {
+ dest[clear_pos++] = NTFS_GETU8(src);
src++;
copied++;
- if(copied==l)
+ if (copied==l)
return;
}
- tag>>=1;
+ tag >>= 1;
bits--;
}
- dest+=clear_pos;
+ dest += clear_pos;
}
}
-/* Caveat: No range checking in either ntfs_set_bit or ntfs_clear_bit */
-void
-ntfs_set_bit (unsigned char *byte, int bit)
+/* Caveat: No range checking in either ntfs_set_bit or ntfs_clear_bit. */
+void ntfs_set_bit(unsigned char *byte, int bit)
{
byte += (bit >> 3);
bit &= 7;
*byte |= (1 << bit);
}
-void
-ntfs_clear_bit (unsigned char *byte, int bit)
+void ntfs_clear_bit(unsigned char *byte, int bit)
{
byte += (bit >> 3);
bit &= 7;
*byte &= ~(1 << bit);
}
-/* We have to skip the 16 metafiles and the 8 reserved entries */
-static int
-ntfs_new_inode (ntfs_volume* vol,int* result)
+/**
+ * ntfs_new_inode - allocate an mft record
+ * @vol: volume to allocate an mft record on
+ * @result: the mft record number allocated
+ *
+ * Allocate a new mft record on disk by finding the first free mft record
+ * and allocating it in the mft bitmap.
+ * Return 0 on success or -ERRNO on error.
+ *
+ * TODO(AIA): Implement mft bitmap caching. Replace function by race safe one.
+ */
+static int ntfs_new_inode(ntfs_volume* vol, int* result)
{
- int byte,error;
+ int byte, error;
int bit;
- int size,length;
+ int size, length;
unsigned char value;
ntfs_u8 *buffer;
ntfs_io io;
ntfs_attribute *data;
- buffer=ntfs_malloc(2048);
- if(!buffer)return ENOMEM;
- io.fn_put=ntfs_put;
- io.fn_get=ntfs_get;
- io.param=buffer;
- /* FIXME: bitmaps larger than 2048 bytes */
- io.size=2048;
- error=ntfs_read_attr(vol->mft_ino,vol->at_bitmap,0,0,&io);
- if(error){
+ buffer = ntfs_malloc(2048);
+ if (!buffer)
+ return -ENOMEM;
+ io.fn_put = ntfs_put;
+ io.fn_get = ntfs_get;
+ io.param = buffer;
+ /* FIXME: Bitmaps larger than 2048 bytes. */
+ io.size = 2048;
+ error = ntfs_read_attr(vol->mft_ino, vol->at_bitmap, 0, 0, &io);
+ if (error) {
ntfs_free(buffer);
return error;
}
- size=io.size;
- data=ntfs_find_attr(vol->mft_ino,vol->at_data,0);
- length=data->size/vol->mft_recordsize;
-
- /* SRD: start at byte 0: bits for system files _are_ already set in bitmap */
- for (byte = 0; 8*byte < length; byte++)
- {
+ size = io.size;
+ data = ntfs_find_attr(vol->mft_ino, vol->at_data, 0);
+ length = data->size / vol->mft_recordsize;
+ /* SRD: Start at byte 0: bits for system files _are_ already set in
+ * bitmap. AIA: This includes the reserved entries as well. */
+ for (byte = 0; 8 * byte < length; byte++) {
value = buffer[byte];
- if(value==0xFF)
+ if (value == 0xFF)
continue;
- for (bit = 0; (bit < 8) && (8*byte+bit<length);
- bit++, value >>= 1)
- {
- if (!(value & 1)){
- *result=byte*8+bit;
+ for (bit = 0; (bit < 8) && (8 * byte + bit < length);
+ bit++, value >>= 1) {
+ if (!(value & 1)) {
+ *result = byte * 8 + bit;
return 0;
}
}
}
- /* There is no free space. We must first extend the MFT. */
- return ENOSPC;
+ /* There is no free space. We must first extend the MFT. */
+ return -ENOSPC;
}
-static int
-add_mft_header (ntfs_inode *ino)
+static int add_mft_header(ntfs_inode *ino)
{
- unsigned char* mft;
- ntfs_volume *vol=ino->vol;
- mft=ino->attr;
+ unsigned char *mft;
+ ntfs_volume *vol = ino->vol;
+ mft = ino->attr;
ntfs_bzero(mft, vol->mft_recordsize);
- ntfs_fill_mft_header(mft,vol->mft_recordsize,vol->blocksize,
- ino->sequence_number);
+ ntfs_fill_mft_header(mft, vol->mft_recordsize, vol->blocksize,
+ ino->sequence_number);
return 0;
}
-/* We need 0x48 bytes in total */
-static int
-add_standard_information (ntfs_inode *ino)
+/* We need 0x48 bytes in total. */
+static int add_standard_information(ntfs_inode *ino)
{
ntfs_time64_t now;
char data[0x30];
- char *position=data;
+ char *position = data;
int error;
ntfs_attribute *si;
@@ -1123,66 +1176,63 @@
NTFS_PUTU64(position + 0x08, now); /* Last modification */
NTFS_PUTU64(position + 0x10, now); /* Last mod for MFT */
NTFS_PUTU64(position + 0x18, now); /* Last access */
-
- NTFS_PUTU64(position + 0x20, 0x00); /* MSDOS file perms */
- NTFS_PUTU64(position + 0x28, 0); /* unknown */
- error=ntfs_create_attr(ino,ino->vol->at_standard_information,0,
- data,sizeof(data),&si);
-
+ NTFS_PUTU64(position + 0x20, 0); /* MSDOS file perms */
+ NTFS_PUTU64(position + 0x28, 0); /* unknown */
+ error = ntfs_create_attr(ino, ino->vol->at_standard_information, 0,
+ data, sizeof(data), &si);
return error;
}
-static int
-add_filename (ntfs_inode* ino, ntfs_inode* dir,
- const unsigned char *filename, int length, ntfs_u32 flags)
-{
- unsigned char *position;
- unsigned int size;
- ntfs_time64_t now;
- int count;
- int error;
+/* FIXME: Need to pass in the size of the file (Data size) as well as the
+ * allocated size for file data on disk (Allocated size). (AIA) */
+static int add_filename(ntfs_inode* ino, ntfs_inode* dir,
+ const unsigned char *filename, int length,
+ ntfs_u32 flags)
+{
+ unsigned char *position;
+ unsigned int size;
+ ntfs_time64_t now;
+ int count, error;
unsigned char* data;
ntfs_attribute *fn;
- /* work out the size */
+ /* Work out the size. */
size = 0x42 + 2 * length;
data = ntfs_malloc(size);
- if( !data )
- return ENOMEM;
- ntfs_bzero(data,size);
-
- /* search for a position */
+ if (!data)
+ return -ENOMEM;
+ ntfs_bzero(data, size);
+ /* Search for a position. */
position = data;
-
- NTFS_PUTINUM(position, dir); /* Inode num of dir */
-
+ NTFS_PUTINUM(position, dir); /* Inode num of dir */
now = ntfs_now();
NTFS_PUTU64(position + 0x08, now); /* File creation */
NTFS_PUTU64(position + 0x10, now); /* Last modification */
NTFS_PUTU64(position + 0x18, now); /* Last mod for MFT */
NTFS_PUTU64(position + 0x20, now); /* Last access */
-
- /* Don't know */
- NTFS_PUTU32(position+0x38, flags);
-
- NTFS_PUTU8(position + 0x40, length); /* Filename length */
- NTFS_PUTU8(position + 0x41, 0x0); /* only long name */
-
+ /*NTFS_PUTU64(position + 0x28, 0);*/ /* Allocated size */
+ /*NTFS_PUTU64(position + 0x30, 0);*/ /* Data size */
+ NTFS_PUTU32(position + 0x38, flags); /* File flags */
+ /*NTFS_PUTU32(position + 0x3c, 0);*/ /* We don't use these
+ * features yet. */
+ NTFS_PUTU8(position + 0x40, length); /* Filename length */
+ NTFS_PUTU8(position + 0x41, 0); /* Only long name */
+ /* FIXME: This is madness. We are defining the POSIX namespace
+ * for the filename here which can mean that the file will be
+ * invisible when in Windows NT/2k! )-: (AIA) */
position += 0x42;
- for (count = 0; count < length; count++)
- {
+ for (count = 0; count < length; count++) {
NTFS_PUTU16(position + 2 * count, filename[count]);
}
-
- error=ntfs_create_attr(ino,ino->vol->at_file_name,0,data,size,&fn);
- if(!error)
- error=ntfs_dir_add(dir,ino,fn);
+ error = ntfs_create_attr(ino, ino->vol->at_file_name, 0, data, size,
+ &fn);
+ if (!error)
+ error = ntfs_dir_add(dir, ino, fn);
ntfs_free(data);
return error;
}
-int
-add_security (ntfs_inode* ino, ntfs_inode* dir)
+int add_security(ntfs_inode* ino, ntfs_inode* dir)
{
int error;
char *buf;
@@ -1191,133 +1241,138 @@
ntfs_io io;
ntfs_attribute *se;
- attr=ntfs_find_attr(dir,ino->vol->at_security_descriptor,0);
- if(!attr)
- return EOPNOTSUPP; /* need security in directory */
+ attr = ntfs_find_attr(dir, ino->vol->at_security_descriptor, 0);
+ if (!attr)
+ return -EOPNOTSUPP; /* Need security in directory. */
size = attr->size;
- if(size>512)
- return EOPNOTSUPP;
- buf=ntfs_malloc(size);
- if(!buf)
- return ENOMEM;
- io.fn_get=ntfs_get;
- io.fn_put=ntfs_put;
- io.param=buf;
- io.size=size;
- error=ntfs_read_attr(dir,ino->vol->at_security_descriptor,0,0,&io);
- if(!error && io.size!=size)ntfs_error("wrong size in add_security");
- if(error){
+ if (size > 512)
+ return -EOPNOTSUPP;
+ buf = ntfs_malloc(size);
+ if (!buf)
+ return -ENOMEM;
+ io.fn_get = ntfs_get;
+ io.fn_put = ntfs_put;
+ io.param = buf;
+ io.size = size;
+ error = ntfs_read_attr(dir, ino->vol->at_security_descriptor, 0, 0,&io);
+ if (!error && io.size != size)
+ ntfs_error("wrong size in add_security");
+ if (error) {
ntfs_free(buf);
return error;
}
- /* FIXME: consider ACL inheritance */
- error=ntfs_create_attr(ino,ino->vol->at_security_descriptor,
- 0,buf,size,&se);
+ /* FIXME: Consider ACL inheritance. */
+ error = ntfs_create_attr(ino, ino->vol->at_security_descriptor,
+ 0, buf, size, &se);
ntfs_free(buf);
return error;
}
-static int
-add_data (ntfs_inode* ino, unsigned char *data, int length)
+static int add_data(ntfs_inode* ino, unsigned char *data, int length)
{
int error;
ntfs_attribute *da;
- error=ntfs_create_attr(ino,ino->vol->at_data,0,data,length,&da);
+
+ error = ntfs_create_attr(ino, ino->vol->at_data, 0, data, length, &da);
return error;
}
-/* We _could_ use 'dir' to help optimise inode allocation */
-int ntfs_alloc_inode (ntfs_inode *dir, ntfs_inode *result,
- const char *filename, int namelen, ntfs_u32 flags)
+/* We _could_ use 'dir' to help optimise inode allocation. */
+int ntfs_alloc_inode(ntfs_inode *dir, ntfs_inode *result, const char *filename,
+ int namelen, ntfs_u32 flags)
{
ntfs_io io;
int error;
ntfs_u8 buffer[2];
- ntfs_volume* vol=dir->vol;
- int byte,bit;
+ ntfs_volume *vol = dir->vol;
+ int byte, bit;
- error=ntfs_new_inode (vol,&(result->i_number));
- if(error==ENOSPC){
- error=ntfs_extend_mft(vol);
- if(error)return error;
- error=ntfs_new_inode(vol,&(result->i_number));
+ error = ntfs_new_inode(vol, &(result->i_number));
+ if (error == -ENOSPC) {
+ error = ntfs_extend_mft(vol);
+ if (error)
+ return error;
+ error = ntfs_new_inode(vol, &(result->i_number));
}
- if(error){
- ntfs_error ("ntfs_get_empty_inode: no free inodes\n");
+ if (error) {
+ ntfs_error("ntfs_get_empty_inode: no free inodes\n");
return error;
}
- byte=result->i_number/8;
- bit=result->i_number & 7;
-
+ byte = result->i_number / 8;
+ bit = result->i_number & 7;
io.fn_put = ntfs_put;
io.fn_get = ntfs_get;
io.param = buffer;
- io.size=1;
- /* set a single bit */
- error=ntfs_read_attr(vol->mft_ino,vol->at_bitmap,0,byte,&io);
- if(error)return error;
- if(io.size!=1)
- return EIO;
- ntfs_set_bit (buffer, bit);
+ io.size = 1;
+ /* Set a single bit. */
+ error = ntfs_read_attr(vol->mft_ino, vol->at_bitmap, 0, byte, &io);
+ if (error)
+ return error;
+ if (io.size != 1)
+ return -EIO;
+ ntfs_set_bit(buffer, bit);
io.param = buffer;
io.size = 1;
- error = ntfs_write_attr (vol->mft_ino, vol->at_bitmap, 0, byte, &io);
- if(error)return error;
+ error = ntfs_write_attr(vol->mft_ino, vol->at_bitmap, 0, byte, &io);
+ if (error)
+ return error;
if (io.size != 1)
- return EIO;
- /*FIXME: Should change MFT on disk
- error=ntfs_update_inode(vol->mft_ino);
- if(error)return error;
- */
- /* get the sequence number */
+ return -EIO;
+ /* FIXME: Should change $Mft on disk.
+ * error = ntfs_update_inode(vol->mft_ino);
+ * if (error)
+ * return error;
+ * FIXME: And don't forget $MftMirr, though this probably belongs
+ * in ntfs_update_inode() (or even deeper). (AIA) */
+ /* Get the sequence number. */
io.param = buffer;
io.size = 2;
error = ntfs_read_attr(vol->mft_ino, vol->at_data, 0,
- result->i_number*vol->mft_recordsize+0x10,&io);
- if(error)
+ result->i_number * vol->mft_recordsize + 0x10,
+ &io);
+ if (error)
return error;
- result->sequence_number=NTFS_GETU16(buffer)+1;
- result->vol=vol;
- result->attr=ntfs_malloc(vol->mft_recordsize);
- if( !result->attr )
- return ENOMEM;
- result->attr_count=0;
- result->attrs=0;
- result->record_count=1;
- result->records=ntfs_malloc(8*sizeof(int));
- if( !result->records ) {
- ntfs_free( result->attr );
+ /* Increment the sequence number skipping zero. */
+ if (NTFS_GETU16(buffer) == 0xffff)
+ result->sequence_number = 1;
+ else
+ result->sequence_number = NTFS_GETU16(buffer) + 1;
+ result->vol = vol;
+ result->attr = ntfs_malloc(vol->mft_recordsize);
+ if (!result->attr)
+ return -ENOMEM;
+ result->attr_count = 0;
+ result->attrs = 0;
+ result->record_count = 1;
+ result->records = ntfs_malloc(8 * sizeof(int));
+ if (!result->records) {
+ ntfs_free(result->attr);
result->attr = 0;
- return ENOMEM;
+ return -ENOMEM;
}
- result->records[0]=result->i_number;
- error=add_mft_header(result);
- if(error)
+ result->records[0] = result->i_number;
+ error = add_mft_header(result);
+ if (error)
+ return error;
+ error = add_standard_information(result);
+ if (error)
return error;
- error=add_standard_information(result);
- if(error)
+ error = add_filename(result, dir, filename, namelen, flags);
+ if (error)
return error;
- error=add_filename(result,dir,filename,namelen,flags);
- if(error)
+ error = add_security(result, dir);
+ if (error)
return error;
- error=add_security(result,dir);
- /*FIXME: check error */
return 0;
}
-int
-ntfs_alloc_file(ntfs_inode *dir, ntfs_inode *result, char *filename,
- int namelen)
+int ntfs_alloc_file(ntfs_inode *dir, ntfs_inode *result, char *filename,
+ int namelen)
{
- int error = ntfs_alloc_inode(dir,result,filename,namelen,0);
- if(error)
+ int error = ntfs_alloc_inode(dir, result, filename, namelen, 0);
+ if (error)
return error;
- error = add_data(result,0,0);
+ error = add_data(result, 0, 0);
return error;
}
-/*
- * 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)