4 * Copyright (C) 1995-1999 Martin von Löwis
5 * Copyright (C) 1996 Albert D. Cahalan
6 * Copyright (C) 1996-1997 Régis Duchesne
7 * Copyright (C) 1998 Joseph Malicki
8 * Copyright (C) 1999 Steve Dodd
9 * Copyright (C) 2000 Anton Altaparmakov
12 #include "ntfstypes.h"
13 #include "ntfsendian.h"
17 #include <linux/errno.h>
30 unsigned char* record
;
36 ntfs_mft_record
* records
;
40 ntfs_fill_mft_header(ntfs_u8
*mft
,int record_size
,int blocksize
,
43 int fixup_count
= record_size
/ blocksize
+ 1;
44 int attr_offset
= (0x2a + (2 * fixup_count
) + 7) & ~7;
45 int fixup_offset
= 0x2a;
47 NTFS_PUTU32(mft
+ 0x00, 0x454c4946); /* FILE */
48 NTFS_PUTU16(mft
+ 0x04, 0x2a); /* offset to fixup */
49 NTFS_PUTU16(mft
+ 0x06, fixup_count
); /* Number of fixups */
50 NTFS_PUTU16(mft
+ 0x10, sequence_number
);
51 NTFS_PUTU16(mft
+ 0x12, 1); /* hard link count */
52 NTFS_PUTU16(mft
+ 0x14, attr_offset
); /* Offset to attributes */
53 NTFS_PUTU16(mft
+ 0x16, 1); /*FIXME: flags ?? */
54 NTFS_PUTU32(mft
+ 0x18, attr_offset
+ 0x08); /* In use */
55 NTFS_PUTU32(mft
+ 0x1c, record_size
); /* Total size */
57 NTFS_PUTU16(mft
+ fixup_offset
, 1); /* Fixup word */
58 NTFS_PUTU32(mft
+ attr_offset
, 0xffffffff); /* End marker */
61 /* Search in an inode an attribute by type and name */
63 ntfs_find_attr(ntfs_inode
*ino
,int type
,char *name
)
67 ntfs_error("ntfs_find_attr: NO INODE!\n");
70 for(i
=0;i
<ino
->attr_count
;i
++)
72 if(type
==ino
->attrs
[i
].type
)
74 if(!name
&& !ino
->attrs
[i
].name
)
76 if(name
&& !ino
->attrs
[i
].name
)
78 if(!name
&& ino
->attrs
[i
].name
)
80 if(ntfs_ua_strncmp(ino
->attrs
[i
].name
,name
,strlen(name
))==0)
83 if(type
<ino
->attrs
[i
].type
)
89 /* FIXME: need better strategy to extend the MFT */
91 ntfs_extend_mft(ntfs_volume
*vol
)
93 /* Try to allocate at least 0.1% of the remaining disk space
94 for inodes. If the disk is almost full, make sure at least one
97 int size
,rcount
,error
,block
;
98 ntfs_attribute
* mdata
,*bmp
;
102 mdata
=ntfs_find_attr(vol
->mft_ino
,vol
->at_data
,0);
103 /* first check whether there is uninitialized space */
104 if(mdata
->allocated
<mdata
->size
+vol
->mft_recordsize
){
105 size
=ntfs_get_free_cluster_count(vol
->bitmap
)*vol
->clustersize
;
106 block
=vol
->mft_recordsize
;
107 size
=max(size
/1000,mdata
->size
+vol
->mft_recordsize
);
108 size
=((size
+block
-1)/block
)*block
;
109 /* require this to be a single chunk */
110 error
=ntfs_extend_attr(vol
->mft_ino
,mdata
,&size
,
112 /* Try again, now we have the largest available fragment */
114 /* round down to multiple of mft record size */
115 size
=(size
/vol
->mft_recordsize
)*vol
->mft_recordsize
;
116 if(!size
)return ENOSPC
;
117 error
=ntfs_extend_attr(vol
->mft_ino
,mdata
,&size
,
123 /* even though we might have allocated more than needed,
124 we initialize only one record */
125 mdata
->size
+=vol
->mft_recordsize
;
127 /* now extend the bitmap if necessary*/
128 rcount
=mdata
->size
/vol
->mft_recordsize
;
129 bmp
=ntfs_find_attr(vol
->mft_ino
,vol
->at_bitmap
,0);
130 if(bmp
->size
*8<rcount
){ /* less bits than MFT records */
132 /* extend bitmap by one byte */
133 error
=ntfs_resize_attr(vol
->mft_ino
,bmp
,bmp
->size
+1);
134 if(error
)return error
;
135 /* write the single byte */
141 error
=ntfs_write_attr(vol
->mft_ino
,vol
->at_bitmap
,0,
143 if(error
)return error
;
144 if(io
.size
!=1)return EIO
;
147 /* now fill in the MFT header for the new block */
148 buf
=ntfs_calloc(vol
->mft_recordsize
);
149 if(!buf
)return ENOMEM
;
150 ntfs_fill_mft_header(buf
,vol
->mft_recordsize
,vol
->blocksize
,0);
151 ntfs_insert_fixups(buf
,vol
->blocksize
);
153 io
.size
=vol
->mft_recordsize
;
154 io
.fn_put
= ntfs_put
;
155 io
.fn_get
= ntfs_get
;
156 error
=ntfs_write_attr(vol
->mft_ino
,vol
->at_data
,0,
157 (rcount
-1)*vol
->mft_recordsize
,&io
);
158 if(error
)return error
;
159 if(io
.size
!=vol
->mft_recordsize
)return EIO
;
160 error
=ntfs_update_inode(vol
->mft_ino
);
161 if(error
)return error
;
165 /* Insert all attributes from the record mftno of the MFT in the inode ino */
166 void ntfs_insert_mft_attributes(ntfs_inode
* ino
,char *mft
,int mftno
)
171 /* check for duplicate */
172 for(i
=0;i
<ino
->record_count
;i
++)
173 if(ino
->records
[i
]==mftno
)
175 /* (re-)allocate space if necessary */
176 if(ino
->record_count
% 8==0)
179 new = ntfs_malloc((ino
->record_count
+8)*sizeof(int));
183 for(i
=0;i
<ino
->record_count
;i
++)
184 new[i
] = ino
->records
[i
];
185 ntfs_free( ino
->records
);
189 ino
->records
[ino
->record_count
]=mftno
;
191 it
= mft
+ NTFS_GETU16(mft
+ 0x14);
193 type
=NTFS_GETU32(it
);
194 len
=NTFS_GETU32(it
+4);
196 /* FIXME: check ntfs_insert_attribute for failure (e.g. no mem)? */
197 ntfs_insert_attribute(ino
,it
);
200 }while(type
!=-1); /* attribute list ends with type -1 */
203 /* Read and insert all the attributes of an 'attribute list' attribute
204 Return the number of remaining bytes in *plen
206 static int parse_attributes(ntfs_inode
*ino
, ntfs_u8
*alist
, int *plen
)
212 mft
=ntfs_malloc(ino
->vol
->mft_recordsize
);
217 l
=NTFS_GETU16(alist
+4);
219 /* process an attribute description */
220 mftno
=NTFS_GETU32(alist
+0x10); /* BUG: this is u64 */
223 /* FIXME: avoid loading record if it's
225 error
=ntfs_read_mft_record(ino
->vol
,mftno
,mft
);
226 if(error
)return error
;
227 ntfs_insert_mft_attributes(ino
,mft
,mftno
);
237 static void ntfs_load_attributes(ntfs_inode
* ino
)
239 ntfs_attribute
*alist
;
241 int offset
,len
,delta
;
243 ntfs_volume
*vol
=ino
->vol
;
244 ntfs_debug(DEBUG_FILE2
, "load_attributes %x 1\n",ino
->i_number
);
245 ntfs_insert_mft_attributes(ino
,ino
->attr
,ino
->i_number
);
246 ntfs_debug(DEBUG_FILE2
, "load_attributes %x 2\n",ino
->i_number
);
247 alist
=ntfs_find_attr(ino
,vol
->at_attribute_list
,0);
248 ntfs_debug(DEBUG_FILE2
, "load_attributes %x 3\n",ino
->i_number
);
251 ntfs_debug(DEBUG_FILE2
, "load_attributes %x 4\n",ino
->i_number
);
252 datasize
=alist
->size
;
255 parse_attributes(ino
,alist
->d
.data
,&datasize
);
258 buf
=ntfs_malloc(1024);
262 for(offset
=0;datasize
;datasize
-=len
,offset
+=len
)
268 io
.size
=len
=min(datasize
,1024-delta
);
269 if(ntfs_read_attr(ino
,vol
->at_attribute_list
,0,offset
,&io
)){
270 ntfs_error("error in load_attributes\n");
273 parse_attributes(ino
,buf
,&delta
);
275 /* move remaining bytes to buffer start */
276 ntfs_memmove(buf
,buf
+len
-delta
,delta
);
278 ntfs_debug(DEBUG_FILE2
, "load_attributes %x 5\n",ino
->i_number
);
282 int ntfs_init_inode(ntfs_inode
*ino
,ntfs_volume
*vol
,int inum
)
287 ntfs_debug(DEBUG_FILE1
, "Initializing inode %x\n",inum
);
289 ntfs_error("NO VOLUME!\n");
292 ino
->attr
=buf
=ntfs_malloc(vol
->mft_recordsize
);
295 error
=ntfs_read_mft_record(vol
,inum
,ino
->attr
);
297 ntfs_debug(DEBUG_OTHER
, "init inode: %x failed\n",inum
);
300 ntfs_debug(DEBUG_FILE2
, "Init: got mft %x\n",inum
);
301 ino
->sequence_number
=NTFS_GETU16(buf
+0x10);
306 ntfs_load_attributes(ino
);
307 ntfs_debug(DEBUG_FILE2
, "Init: done %x\n",inum
);
311 void ntfs_clear_inode(ntfs_inode
*ino
)
315 ntfs_error("ntfs_clear_inode: double free\n");
318 ntfs_free(ino
->attr
);
320 ntfs_free(ino
->records
);
322 for(i
=0;i
<ino
->attr_count
;i
++)
324 if(ino
->attrs
[i
].name
)
325 ntfs_free(ino
->attrs
[i
].name
);
326 if(ino
->attrs
[i
].resident
)
328 if(ino
->attrs
[i
].d
.data
)
329 ntfs_free(ino
->attrs
[i
].d
.data
);
331 if(ino
->attrs
[i
].d
.r
.runlist
)
332 ntfs_free(ino
->attrs
[i
].d
.r
.runlist
);
335 ntfs_free(ino
->attrs
);
339 /* Check and fixup a MFT record */
340 int ntfs_check_mft_record(ntfs_volume
*vol
,char *record
)
342 return ntfs_fixup_record(vol
, record
, "FILE", vol
->mft_recordsize
);
345 /* Return (in result) the value indicating the next available attribute
346 chunk number. Works for inodes w/o extension records only */
347 int ntfs_allocate_attr_number(ntfs_inode
*ino
, int *result
)
349 if(ino
->record_count
!=1)
351 *result
=NTFS_GETU16(ino
->attr
+0x28);
352 NTFS_PUTU16(ino
->attr
+0x28, (*result
)+1);
356 /* find the location of an attribute in the inode. A name of NULL indicates
357 unnamed attributes. Return pointer to attribute or NULL if not found */
359 ntfs_get_attr(ntfs_inode
*ino
,int attr
,char *name
)
361 /* location of first attribute */
362 char *it
= ino
->attr
+ NTFS_GETU16(ino
->attr
+ 0x14);
365 /* Only check for magic DWORD here, fixup should have happened before */
366 if(!IS_MFT_RECORD(ino
->attr
))return 0;
368 type
=NTFS_GETU32(it
);
369 len
=NTFS_GETU16(it
+4);
370 /* We found the attribute type. Is the name correct, too? */
373 int namelen
=NTFS_GETU8(it
+9);
375 /* match given name and attribute name if present,
376 make sure attribute name is Unicode */
377 for(name_it
=it
+NTFS_GETU16(it
+10);namelen
;
378 name
++,name_it
+=2,namelen
--)
379 if(*name_it
!=*name
|| name_it
[1])break;
383 }while(type
!=-1); /* attribute list end with type -1 */
384 if(type
==-1)return 0;
389 ntfs_get_attr_size(ntfs_inode
*ino
,int type
,char*name
)
391 ntfs_attribute
*attr
=ntfs_find_attr(ino
,type
,name
);
397 ntfs_attr_is_resident(ntfs_inode
*ino
,int type
,char*name
)
399 ntfs_attribute
*attr
=ntfs_find_attr(ino
,type
,name
);
401 return attr
->resident
;
405 * A run is coded as a type indicator, an unsigned length, and a signed cluster
407 * . To save space, length and offset are fields of variable length. The low
408 * nibble of the type indicates the width of the length :), the high nibble
409 * the width of the offset.
410 * . The first offset is relative to cluster 0, later offsets are relative to
411 * the previous cluster.
413 * This function decodes a run. Length is an output parameter, data and cluster
414 * are in/out parameters.
416 int ntfs_decompress_run(unsigned char **data
, int *length
, ntfs_cluster_t
*cluster
,
419 unsigned char type
=*(*data
)++;
423 case 1: *length
=NTFS_GETU8(*data
);break;
424 case 2: *length
=NTFS_GETU16(*data
);break;
425 case 3: *length
=NTFS_GETU24(*data
);break;
426 case 4: *length
=NTFS_GETU32(*data
);break;
427 /* Note: cases 5-8 are probably pointless to code,
428 since how many runs > 4GB of length are there?
429 at the most, cases 5 and 6 are probably necessary,
430 and would also require making length 64-bit
433 ntfs_error("Can't decode run type field %x\n",type
);
440 case 0: *ctype
=2; break;
441 case 0x10: *cluster
+= NTFS_GETS8(*data
);break;
442 case 0x20: *cluster
+= NTFS_GETS16(*data
);break;
443 case 0x30: *cluster
+= NTFS_GETS24(*data
);break;
444 case 0x40: *cluster
+= NTFS_GETS32(*data
);break;
445 #if 0 /* Keep for future, in case ntfs_cluster_t ever becomes 64bit */
446 case 0x50: *cluster
+= NTFS_GETS40(*data
);break;
447 case 0x60: *cluster
+= NTFS_GETS48(*data
);break;
448 case 0x70: *cluster
+= NTFS_GETS56(*data
);break;
449 case 0x80: *cluster
+= NTFS_GETS64(*data
);break;
452 ntfs_error("Can't decode run type field %x\n",type
);
459 /* Reads l bytes of the attribute (attr,name) of ino starting at offset
460 on vol into buf. Returns the number of bytes read in the ntfs_io struct.
461 Returns 0 on success, errno on failure */
462 int ntfs_readwrite_attr(ntfs_inode
*ino
, ntfs_attribute
*attr
, int offset
,
466 ntfs_cluster_t cluster
,s_cluster
,vcn
,len
;
472 clustersize
=ino
->vol
->clustersize
;
478 /* if read _starts_ beyond end of stream, return nothing */
479 if(offset
>=attr
->size
){
484 /* if read _extends_ beyond end of stream, return as much
485 initialised data as we have */
486 if(offset
+l
>=attr
->size
)
487 l
=dest
->size
=attr
->size
-offset
;
490 /* fixed by CSA: if writing beyond end, extend attribute */
492 /* if write extends beyond _allocated_ size, extend attrib */
493 if (offset
+l
>attr
->allocated
) {
494 error
=ntfs_resize_attr(ino
,attr
,offset
+l
);
499 /* the amount of initialised data has increased; update */
500 /* FIXME: shouldn't we zero-out the section between the old
501 initialised length and the write start? */
502 if (offset
+l
> attr
->initialized
) {
503 attr
->initialized
= offset
+l
;
504 attr
->size
= offset
+l
;
510 dest
->fn_put(dest
,(ntfs_u8
*)attr
->d
.data
+offset
,l
);
512 dest
->fn_get((ntfs_u8
*)attr
->d
.data
+offset
,dest
,l
);
516 /* read uninitialized data */
517 if(offset
>=attr
->initialized
&& dest
->do_read
)
518 return ntfs_read_zero(dest
,l
);
519 if(offset
+l
>attr
->initialized
&& dest
->do_read
)
521 dest
->size
= chunk
= offset
+l
- attr
->initialized
;
522 error
= ntfs_readwrite_attr(ino
,attr
,offset
,dest
);
525 return ntfs_read_zero(dest
,l
-chunk
);
527 if(attr
->compressed
){
529 return ntfs_read_compressed(ino
,attr
,offset
,dest
);
531 return ntfs_write_compressed(ino
,attr
,offset
,dest
);
534 s_vcn
= offset
/clustersize
;
535 for(rnum
=0;rnum
<attr
->d
.r
.len
&&
536 vcn
+attr
->d
.r
.runlist
[rnum
].len
<=s_vcn
;rnum
++)
537 vcn
+=attr
->d
.r
.runlist
[rnum
].len
;
538 if(rnum
==attr
->d
.r
.len
)
539 /*FIXME: should extend runlist */
545 s_vcn
= offset
/clustersize
;
546 cluster
=attr
->d
.r
.runlist
[rnum
].cluster
;
547 len
=attr
->d
.r
.runlist
[rnum
].len
;
549 s_cluster
= cluster
+s_vcn
-vcn
;
551 chunk
=min((vcn
+len
)*clustersize
-offset
,l
);
553 error
=ntfs_getput_clusters(ino
->vol
,s_cluster
,
554 offset
-s_vcn
*clustersize
,dest
);
557 ntfs_error("Read error\n");
564 if(l
&& offset
>=((vcn
+len
)*clustersize
))
568 cluster
= attr
->d
.r
.runlist
[rnum
].cluster
;
569 len
= attr
->d
.r
.runlist
[rnum
].len
;
576 int ntfs_read_attr(ntfs_inode
*ino
, int type
, char *name
, int offset
,
579 ntfs_attribute
*attr
;
581 attr
=ntfs_find_attr(ino
,type
,name
);
584 return ntfs_readwrite_attr(ino
,attr
,offset
,buf
);
587 int ntfs_write_attr(ntfs_inode
*ino
, int type
, char *name
, int offset
,
590 ntfs_attribute
*attr
;
592 attr
=ntfs_find_attr(ino
,type
,name
);
595 return ntfs_readwrite_attr(ino
,attr
,offset
,buf
);
598 int ntfs_vcn_to_lcn(ntfs_inode
*ino
,int vcn
)
601 ntfs_attribute
*data
;
602 data
=ntfs_find_attr(ino
,ino
->vol
->at_data
,0);
603 /* It's hard to give an error code */
605 if(data
->resident
)return -1;
606 if(data
->compressed
)return -1;
607 if(data
->size
<= vcn
*ino
->vol
->clustersize
)return -1;
610 /* For Linux, block number 0 represents a hole.
611 Hopefully, nobody will attempt to bmap $Boot. */
612 if(data
->initialized
<= vcn
*ino
->vol
->clustersize
)
615 for(rnum
=0;rnum
<data
->d
.r
.len
&&
616 vcn
>=data
->d
.r
.runlist
[rnum
].len
;rnum
++)
617 vcn
-=data
->d
.r
.runlist
[rnum
].len
;
619 return data
->d
.r
.runlist
[rnum
].cluster
+vcn
;
623 allocate_store(ntfs_volume
*vol
,ntfs_disk_inode
*store
,int count
)
626 if(store
->count
>count
)
628 if(store
->size
<count
){
629 ntfs_mft_record
* n
=ntfs_malloc((count
+4)*sizeof(ntfs_mft_record
));
633 for(i
=0;i
<store
->size
;i
++)
634 n
[i
]=store
->records
[i
];
635 ntfs_free(store
->records
);
640 for(i
=store
->count
;i
<count
;i
++){
641 store
->records
[i
].record
=ntfs_malloc(vol
->mft_recordsize
);
642 if(!store
->records
[i
].record
)
650 deallocate_store(ntfs_disk_inode
* store
)
653 for(i
=0;i
<store
->count
;i
++)
654 ntfs_free(store
->records
[i
].record
);
655 ntfs_free(store
->records
);
656 store
->count
=store
->size
=0;
661 layout_runs(ntfs_attribute
*attr
,char* rec
,int* offs
,int size
)
663 int i
,len
,offset
,coffs
;
664 ntfs_cluster_t cluster
,rclus
;
665 ntfs_runlist
*rl
=attr
->d
.r
.runlist
;
668 for(i
=0;i
<attr
->d
.r
.len
;i
++){
669 rclus
=rl
[i
].cluster
-cluster
;
673 return E2BIG
; /* it might still fit, but this simplifies testing */
675 NTFS_PUTU8(rec
+offset
+1,len
);
677 }else if(len
<0x10000){
678 NTFS_PUTU16(rec
+offset
+1,len
);
680 }else if(len
<0x1000000){
681 NTFS_PUTU24(rec
+offset
+1,len
);
684 NTFS_PUTU32(rec
+offset
+1,len
);
688 *(rec
+offset
)|=coffs
++;
690 if(rl
[i
].cluster
==MAX_CLUSTER_T
) /*compressed run*/
692 else if(rclus
>-0x80 && rclus
<0x7F){
694 NTFS_PUTS8(rec
+offset
+coffs
,rclus
);
696 }else if(rclus
>-0x8000 && rclus
<0x7FFF){
698 NTFS_PUTS16(rec
+offset
+coffs
,rclus
);
700 }else if(rclus
>-0x800000 && rclus
<0x7FFFFF){
702 NTFS_PUTS24(rec
+offset
+coffs
,rclus
);
705 #if 0 /* In case ntfs_cluster_t ever becomes 64bit */
706 if (rclus
>-0x80000000LL
&& rclus
<0x7FFFFFFF)
710 NTFS_PUTS32(rec
+offset
+coffs
,rclus
);
713 #if 0 /* For 64-bit ntfs_cluster_t */
714 else if (rclus
>-0x8000000000 && rclus
<0x7FFFFFFFFF){
716 NTFS_PUTS40(rec
+offset
+coffs
,rclus
);
718 }else if (rclus
>-0x800000000000 && rclus
<0x7FFFFFFFFFFF){
720 NTFS_PUTS48(rec
+offset
+coffs
,rclus
);
722 }else if (rclus
>-0x80000000000000 && rclus
<0x7FFFFFFFFFFFFF){
724 NTFS_PUTS56(rec
+offset
+coffs
,rclus
);
728 NTFS_PUTS64(rec
+offset
+coffs
,rclus
);
734 cluster
=rl
[i
].cluster
;
738 /* terminating null */
745 count_runs(ntfs_attribute
*attr
,char *buf
)
747 ntfs_u32 first
,count
,last
,i
;
749 for(i
=0,count
=0;i
<attr
->d
.r
.len
;i
++)
750 count
+=attr
->d
.r
.runlist
[i
].len
;
753 NTFS_PUTU64(buf
+0x10,first
);
754 NTFS_PUTU64(buf
+0x18,last
);
758 layout_attr(ntfs_attribute
* attr
,char*buf
, int size
,int *psize
)
761 if(size
<10)return E2BIG
;
762 NTFS_PUTU32(buf
,attr
->type
);
763 /* fill in length later */
764 NTFS_PUTU8(buf
+8,attr
->resident
? 0:1);
765 NTFS_PUTU8(buf
+9,attr
->namelen
);
766 /* fill in offset to name later */
767 NTFS_PUTU16(buf
+0xA,0);
768 NTFS_PUTU16(buf
+0xC,attr
->compressed
);
769 /* FIXME: assign attribute ID??? */
770 NTFS_PUTU16(buf
+0xE,attr
->attrno
);
772 if(size
<attr
->size
+0x18+attr
->namelen
)return E2BIG
;
774 NTFS_PUTU32(buf
+0x10,attr
->size
);
775 NTFS_PUTU16(buf
+0x16,attr
->indexed
);
777 ntfs_memcpy(buf
+asize
,attr
->name
,2*attr
->namelen
);
778 NTFS_PUTU16(buf
+0xA,asize
);
779 asize
+=2*attr
->namelen
;
780 asize
=(asize
+7) & ~7;
782 NTFS_PUTU16(buf
+0x14,asize
);
783 ntfs_memcpy(buf
+asize
,attr
->d
.data
,attr
->size
);
786 /* FIXME: fragments */
787 count_runs(attr
,buf
);
788 /* offset to data is added later */
789 NTFS_PUTU16(buf
+0x22,attr
->cengine
);
790 NTFS_PUTU32(buf
+0x24,0);
791 NTFS_PUTU64(buf
+0x28,attr
->allocated
);
792 NTFS_PUTU64(buf
+0x30,attr
->size
);
793 NTFS_PUTU64(buf
+0x38,attr
->initialized
);
794 if(attr
->compressed
){
795 NTFS_PUTU64(buf
+0x40,attr
->compsize
);
800 NTFS_PUTU16(buf
+0xA,asize
);
801 ntfs_memcpy(buf
+asize
,attr
->name
,2*attr
->namelen
);
802 asize
+=2*attr
->namelen
;
804 asize=(asize+7) & ~7;*/
806 /* asize points at the beginning of the data */
807 NTFS_PUTU16(buf
+0x20,asize
);
808 error
=layout_runs(attr
,buf
,&asize
,size
);
809 /* now asize pointes at the end of the data */
813 asize
=(asize
+7) & ~7;
814 NTFS_PUTU32(buf
+4,asize
);
821 /* Try to layout ino into store. Return 0 on success,
822 E2BIG if it does not fit,
823 ENOMEM if memory allocation problem,
824 EOPNOTSUP if beyond our capabilities
827 layout_inode(ntfs_inode
*ino
,ntfs_disk_inode
*store
)
830 ntfs_attribute
*attr
;
835 if(ino
->record_count
>1)
837 ntfs_error("layout_inode: attribute lists not supported\n");
840 error
=allocate_store(ino
->vol
,store
,1);
843 rec
=store
->records
[0].record
;
844 size
=ino
->vol
->mft_recordsize
;
845 store
->records
[0].recno
=ino
->records
[0];
847 offset
=NTFS_GETU16(ino
->attr
+0x14);
848 ntfs_memcpy(rec
,ino
->attr
,offset
);
849 for(i
=0;i
<ino
->attr_count
;i
++){
851 error
=layout_attr(attr
,rec
+offset
,size
-offset
,&psize
);
852 if(error
)return error
;
855 /* copy attribute header */
856 ntfs_memcpy(rec
+offset
,attr
->header
,
857 min(sizeof(attr
->header
),size
-offset
)); /* consider overrun */
859 /* named attributes are added later */
861 /* FIXME: assign attribute ID??? */
864 aoffset
=NTFS_GETU16(rec
+offset
+0x14);
865 if(offset
+aoffset
+asize
>size
)
867 ntfs_memcpy(rec
+offset
+aoffset
,attr
->d
.data
,asize
);
868 next
=offset
+aoffset
+asize
;
870 count_runs(attr
,rec
+offset
);
871 aoffset
=NTFS_GETU16(rec
+offset
+0x20);
873 error
=layout_runs(attr
,rec
,&next
,size
);
878 next=(next+7) & ~7; */
879 /* is this setting the length? if so maybe we could get
880 away with rounding up so long as we set the length first..
881 ..except, is the length the only way to get to the next attr?
883 NTFS_PUTU16(rec
+offset
+4,next
-offset
);
887 /* terminating attribute */
889 NTFS_PUTU32(rec
+offset
,0xFFFFFFFF);
891 NTFS_PUTU32(rec
+offset
,0);
895 NTFS_PUTU32(rec
+0x18,offset
);
899 int ntfs_update_inode(ntfs_inode
*ino
)
902 ntfs_disk_inode store
;
906 store
.count
=store
.size
=0;
908 error
=layout_inode(ino
,&store
);
910 error
= ntfs_split_indexroot(ino
);
912 error
= layout_inode(ino
,&store
);
915 error
= ntfs_attr_allnonresident(ino
);
917 error
= layout_inode(ino
,&store
);
921 introduce extension records
923 ntfs_error("cannot handle saving inode %x\n",ino
->i_number
);
924 deallocate_store(&store
);
928 deallocate_store(&store
);
933 for(i
=0;i
<store
.count
;i
++){
934 ntfs_insert_fixups(store
.records
[i
].record
,ino
->vol
->blocksize
);
935 io
.param
=store
.records
[i
].record
;
936 io
.size
=ino
->vol
->mft_recordsize
;
937 /* FIXME: is this the right way? */
938 error
=ntfs_write_attr(
939 ino
->vol
->mft_ino
,ino
->vol
->at_data
,0,
940 store
.records
[i
].recno
*ino
->vol
->mft_recordsize
,&io
);
941 if(error
|| io
.size
!=ino
->vol
->mft_recordsize
){
942 /* big trouble, partially written file */
943 ntfs_error("Please unmount: write error in inode %x\n",ino
->i_number
);
944 deallocate_store(&store
);
945 return error
?error
:EIO
;
952 void ntfs_decompress(unsigned char *dest
, unsigned char *src
, ntfs_size_t l
)
962 head
= NTFS_GETU16(src
) & 0xFFF;
963 /* high bit indicates that compression was performed */
964 comp
= NTFS_GETU16(src
) & 0x8000;
970 /* block is not used */
971 return;/* FIXME: copied */
972 if(!comp
) /* uncompressible */
974 ntfs_memcpy(dest
,src
,0x1000);
986 ntfs_error("Error 1 in decompress\n");
997 int i
,len
,delta
,code
,lmask
,dshift
;
998 code
= NTFS_GETU16(src
);
1002 ntfs_error("Error 2 in decompress\n");
1005 for(i
=clear_pos
-1,lmask
=0xFFF,dshift
=12;i
>=0x10;i
>>=1)
1010 delta
= code
>> dshift
;
1011 len
= (code
& lmask
) + 3;
1012 for(i
=0; i
<len
; i
++)
1014 dest
[clear_pos
]=dest
[clear_pos
-delta
-1];
1021 dest
[clear_pos
++]=NTFS_GETU8(src
);
1034 /* Caveat: No range checking in either ntfs_set_bit or ntfs_clear_bit */
1036 ntfs_set_bit (unsigned char *byte
, int bit
)
1040 *byte
|= (1 << bit
);
1044 ntfs_clear_bit (unsigned char *byte
, int bit
)
1048 *byte
&= ~(1 << bit
);
1051 /* We have to skip the 16 metafiles and the 8 reserved entries */
1053 new_inode (ntfs_volume
* vol
,int* result
)
1058 unsigned char value
;
1061 ntfs_attribute
*data
;
1063 buffer
=ntfs_malloc(2048);
1064 if(!buffer
)return ENOMEM
;
1068 /* FIXME: bitmaps larger than 2048 bytes */
1070 error
=ntfs_read_attr(vol
->mft_ino
,vol
->at_bitmap
,0,0,&io
);
1076 data
=ntfs_find_attr(vol
->mft_ino
,vol
->at_data
,0);
1077 length
=data
->size
/vol
->mft_recordsize
;
1079 /* SRD: start at byte 0: bits for system files _are_ already set in bitmap */
1080 for (byte
= 0; 8*byte
< length
; byte
++)
1082 value
= buffer
[byte
];
1085 for (bit
= 0; (bit
< 8) && (8*byte
+bit
<length
);
1094 /* There is no free space. We must first extend the MFT. */
1099 add_mft_header (ntfs_inode
*ino
)
1102 ntfs_volume
*vol
=ino
->vol
;
1105 ntfs_bzero(mft
, vol
->mft_recordsize
);
1106 ntfs_fill_mft_header(mft
,vol
->mft_recordsize
,vol
->blocksize
,
1107 ino
->sequence_number
);
1111 /* We need 0x48 bytes in total */
1113 add_standard_information (ntfs_inode
*ino
)
1117 char *position
=data
;
1122 NTFS_PUTU64(position
+ 0x00, now
); /* File creation */
1123 NTFS_PUTU64(position
+ 0x08, now
); /* Last modification */
1124 NTFS_PUTU64(position
+ 0x10, now
); /* Last mod for MFT */
1125 NTFS_PUTU64(position
+ 0x18, now
); /* Last access */
1127 NTFS_PUTU64(position
+ 0x20, 0x00); /* MSDOS file perms */
1128 NTFS_PUTU64(position
+ 0x28, 0); /* unknown */
1129 error
=ntfs_create_attr(ino
,ino
->vol
->at_standard_information
,0,
1130 data
,sizeof(data
),&si
);
1136 add_filename (ntfs_inode
* ino
, ntfs_inode
* dir
,
1137 const unsigned char *filename
, int length
, ntfs_u32 flags
)
1139 unsigned char *position
;
1144 unsigned char* data
;
1147 /* work out the size */
1148 size
= 0x42 + 2 * length
;
1149 data
= ntfs_malloc(size
);
1152 ntfs_bzero(data
,size
);
1154 /* search for a position */
1157 NTFS_PUTINUM(position
, dir
); /* Inode num of dir */
1160 NTFS_PUTU64(position
+ 0x08, now
); /* File creation */
1161 NTFS_PUTU64(position
+ 0x10, now
); /* Last modification */
1162 NTFS_PUTU64(position
+ 0x18, now
); /* Last mod for MFT */
1163 NTFS_PUTU64(position
+ 0x20, now
); /* Last access */
1166 NTFS_PUTU32(position
+0x38, flags
);
1168 NTFS_PUTU8(position
+ 0x40, length
); /* Filename length */
1169 NTFS_PUTU8(position
+ 0x41, 0x0); /* only long name */
1172 for (count
= 0; count
< length
; count
++)
1174 NTFS_PUTU16(position
+ 2 * count
, filename
[count
]);
1177 error
=ntfs_create_attr(ino
,ino
->vol
->at_file_name
,0,data
,size
,&fn
);
1179 error
=ntfs_dir_add(dir
,ino
,fn
);
1185 add_security (ntfs_inode
* ino
, ntfs_inode
* dir
)
1190 ntfs_attribute
* attr
;
1194 attr
=ntfs_find_attr(dir
,ino
->vol
->at_security_descriptor
,0);
1196 return EOPNOTSUPP
; /* need security in directory */
1200 buf
=ntfs_malloc(size
);
1207 error
=ntfs_read_attr(dir
,ino
->vol
->at_security_descriptor
,0,0,&io
);
1208 if(!error
&& io
.size
!=size
)ntfs_error("wrong size in add_security");
1213 /* FIXME: consider ACL inheritance */
1214 error
=ntfs_create_attr(ino
,ino
->vol
->at_security_descriptor
,
1221 add_data (ntfs_inode
* ino
, unsigned char *data
, int length
)
1225 error
=ntfs_create_attr(ino
,ino
->vol
->at_data
,0,data
,length
,&da
);
1229 /* We _could_ use 'dir' to help optimise inode allocation */
1230 int ntfs_alloc_inode (ntfs_inode
*dir
, ntfs_inode
*result
,
1231 const char *filename
, int namelen
, ntfs_u32 flags
)
1236 ntfs_volume
* vol
=dir
->vol
;
1239 error
=new_inode (vol
,&(result
->i_number
));
1241 error
=ntfs_extend_mft(vol
);
1242 if(error
)return error
;
1243 error
=new_inode(vol
,&(result
->i_number
));
1246 ntfs_error ("ntfs_get_empty_inode: no free inodes\n");
1249 byte
=result
->i_number
/8;
1250 bit
=result
->i_number
& 7;
1252 io
.fn_put
= ntfs_put
;
1253 io
.fn_get
= ntfs_get
;
1256 /* set a single bit */
1257 error
=ntfs_read_attr(vol
->mft_ino
,vol
->at_bitmap
,0,byte
,&io
);
1258 if(error
)return error
;
1261 ntfs_set_bit (buffer
, bit
);
1264 error
= ntfs_write_attr (vol
->mft_ino
, vol
->at_bitmap
, 0, byte
, &io
);
1265 if(error
)return error
;
1268 /*FIXME: Should change MFT on disk
1269 error=ntfs_update_inode(vol->mft_ino);
1270 if(error)return error;
1272 /* get the sequence number */
1275 error
= ntfs_read_attr(vol
->mft_ino
, vol
->at_data
, 0,
1276 result
->i_number
*vol
->mft_recordsize
+0x10,&io
);
1279 result
->sequence_number
=NTFS_GETU16(buffer
)+1;
1281 result
->attr
=ntfs_malloc(vol
->mft_recordsize
);
1284 result
->attr_count
=0;
1286 result
->record_count
=1;
1287 result
->records
=ntfs_malloc(8*sizeof(int));
1288 if( !result
->records
) {
1289 ntfs_free( result
->attr
);
1293 result
->records
[0]=result
->i_number
;
1294 error
=add_mft_header(result
);
1297 error
=add_standard_information(result
);
1300 error
=add_filename(result
,dir
,filename
,namelen
,flags
);
1303 error
=add_security(result
,dir
);
1304 /*FIXME: check error */
1309 ntfs_alloc_file(ntfs_inode
*dir
, ntfs_inode
*result
, char *filename
,
1312 int error
= ntfs_alloc_inode(dir
,result
,filename
,namelen
,0);
1315 error
= add_data(result
,0,0);
1321 * c-file-style: "linux"