Import 2.4.0-test2pre7
[davej-history.git] / fs / ntfs / inode.c
blob910ffe095030d06d4a525c3671d4f0adc92263d4
1 /*
2 * inode.c
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"
14 #include "struct.h"
15 #include "inode.h"
17 #include <linux/errno.h>
18 #ifdef HAVE_STRING_H
19 #include <string.h>
20 #endif
21 #include "macros.h"
22 #include "attr.h"
23 #include "super.h"
24 #include "dir.h"
25 #include "support.h"
26 #include "util.h"
28 typedef struct {
29 int recno;
30 unsigned char* record;
31 } ntfs_mft_record;
33 typedef struct {
34 int size;
35 int count;
36 ntfs_mft_record* records;
37 } ntfs_disk_inode;
39 void
40 ntfs_fill_mft_header(ntfs_u8*mft,int record_size,int blocksize,
41 int sequence_number)
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 */
62 ntfs_attribute*
63 ntfs_find_attr(ntfs_inode *ino,int type,char *name)
65 int i;
66 if(!ino){
67 ntfs_error("ntfs_find_attr: NO INODE!\n");
68 return 0;
70 for(i=0;i<ino->attr_count;i++)
72 if(type==ino->attrs[i].type)
74 if(!name && !ino->attrs[i].name)
75 return ino->attrs+i;
76 if(name && !ino->attrs[i].name)
77 return 0;
78 if(!name && ino->attrs[i].name)
79 return 0;
80 if(ntfs_ua_strncmp(ino->attrs[i].name,name,strlen(name))==0)
81 return ino->attrs+i;
83 if(type<ino->attrs[i].type)
84 return 0;
86 return 0;
89 /* FIXME: need better strategy to extend the MFT */
90 static int
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
95 inode is requested.
97 int size,rcount,error,block;
98 ntfs_attribute* mdata,*bmp;
99 ntfs_u8 *buf;
100 ntfs_io io;
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,
111 ALLOC_REQUIRE_SIZE);
112 /* Try again, now we have the largest available fragment */
113 if(error==ENOSPC){
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,
118 ALLOC_REQUIRE_SIZE);
120 if(error)
121 return error;
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 */
131 ntfs_u8 buf[1];
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 */
136 buf[0]=0;
137 io.fn_put=ntfs_put;
138 io.fn_get=ntfs_get;
139 io.param=buf;
140 io.size=1;
141 error=ntfs_write_attr(vol->mft_ino,vol->at_bitmap,0,
142 bmp->size-1,&io);
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);
152 io.param=buf;
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;
162 return 0;
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)
168 int i;
169 char *it;
170 int type,len;
171 /* check for duplicate */
172 for(i=0;i<ino->record_count;i++)
173 if(ino->records[i]==mftno)
174 return;
175 /* (re-)allocate space if necessary */
176 if(ino->record_count % 8==0)
178 int *new;
179 new = ntfs_malloc((ino->record_count+8)*sizeof(int));
180 if( !new )
181 return;
182 if( ino->records ) {
183 for(i=0;i<ino->record_count;i++)
184 new[i] = ino->records[i];
185 ntfs_free( ino->records );
187 ino->records = new;
189 ino->records[ino->record_count]=mftno;
190 ino->record_count++;
191 it = mft + NTFS_GETU16(mft + 0x14);
193 type=NTFS_GETU32(it);
194 len=NTFS_GETU32(it+4);
195 if(type!=-1) {
196 /* FIXME: check ntfs_insert_attribute for failure (e.g. no mem)? */
197 ntfs_insert_attribute(ino,it);
199 it+=len;
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)
208 char *mft;
209 int mftno,l,error;
210 int last_mft=-1;
211 int len=*plen;
212 mft=ntfs_malloc(ino->vol->mft_recordsize);
213 if( !mft )
214 return ENOMEM;
215 while(len>8)
217 l=NTFS_GETU16(alist+4);
218 if(l>len)break;
219 /* process an attribute description */
220 mftno=NTFS_GETU32(alist+0x10); /* BUG: this is u64 */
221 if(mftno!=last_mft){
222 last_mft=mftno;
223 /* FIXME: avoid loading record if it's
224 already processed */
225 error=ntfs_read_mft_record(ino->vol,mftno,mft);
226 if(error)return error;
227 ntfs_insert_mft_attributes(ino,mft,mftno);
229 len-=l;
230 alist+=l;
232 ntfs_free(mft);
233 *plen=len;
234 return 0;
237 static void ntfs_load_attributes(ntfs_inode* ino)
239 ntfs_attribute *alist;
240 int datasize;
241 int offset,len,delta;
242 char *buf;
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);
249 if(!alist)
250 return;
251 ntfs_debug(DEBUG_FILE2, "load_attributes %x 4\n",ino->i_number);
252 datasize=alist->size;
253 if(alist->resident)
255 parse_attributes(ino,alist->d.data,&datasize);
256 return;
258 buf=ntfs_malloc(1024);
259 if( !buf )
260 return;
261 delta=0;
262 for(offset=0;datasize;datasize-=len,offset+=len)
264 ntfs_io io;
265 io.fn_put=ntfs_put;
266 io.fn_get=0;
267 io.param=buf+delta;
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");
272 delta+=len;
273 parse_attributes(ino,buf,&delta);
274 if(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);
279 ntfs_free(buf);
282 int ntfs_init_inode(ntfs_inode *ino,ntfs_volume *vol,int inum)
284 char *buf;
285 int error;
287 ntfs_debug(DEBUG_FILE1, "Initializing inode %x\n",inum);
288 if(!vol)
289 ntfs_error("NO VOLUME!\n");
290 ino->i_number=inum;
291 ino->vol=vol;
292 ino->attr=buf=ntfs_malloc(vol->mft_recordsize);
293 if( !buf )
294 return ENOMEM;
295 error=ntfs_read_mft_record(vol,inum,ino->attr);
296 if(error){
297 ntfs_debug(DEBUG_OTHER, "init inode: %x failed\n",inum);
298 return error;
300 ntfs_debug(DEBUG_FILE2, "Init: got mft %x\n",inum);
301 ino->sequence_number=NTFS_GETU16(buf+0x10);
302 ino->attr_count=0;
303 ino->record_count=0;
304 ino->records=0;
305 ino->attrs=0;
306 ntfs_load_attributes(ino);
307 ntfs_debug(DEBUG_FILE2, "Init: done %x\n",inum);
308 return 0;
311 void ntfs_clear_inode(ntfs_inode *ino)
313 int i;
314 if(!ino->attr){
315 ntfs_error("ntfs_clear_inode: double free\n");
316 return;
318 ntfs_free(ino->attr);
319 ino->attr=0;
320 ntfs_free(ino->records);
321 ino->records=0;
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);
330 }else{
331 if(ino->attrs[i].d.r.runlist)
332 ntfs_free(ino->attrs[i].d.r.runlist);
335 ntfs_free(ino->attrs);
336 ino->attrs=0;
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)
350 return EOPNOTSUPP;
351 *result=NTFS_GETU16(ino->attr+0x28);
352 NTFS_PUTU16(ino->attr+0x28, (*result)+1);
353 return 0;
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 */
358 char *
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);
363 int type;
364 int len;
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? */
371 if(type==attr)
373 int namelen=NTFS_GETU8(it+9);
374 char *name_it;
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;
380 if(!namelen)break;
382 it+=len;
383 }while(type!=-1); /* attribute list end with type -1 */
384 if(type==-1)return 0;
385 return it;
388 int
389 ntfs_get_attr_size(ntfs_inode*ino,int type,char*name)
391 ntfs_attribute *attr=ntfs_find_attr(ino,type,name);
392 if(!attr)return 0;
393 return attr->size;
396 int
397 ntfs_attr_is_resident(ntfs_inode*ino,int type,char*name)
399 ntfs_attribute *attr=ntfs_find_attr(ino,type,name);
400 if(!attr)return 0;
401 return attr->resident;
405 * A run is coded as a type indicator, an unsigned length, and a signed cluster
406 * offset.
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,
417 int *ctype)
419 unsigned char type=*(*data)++;
420 *ctype=0;
421 switch(type & 0xF)
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
431 throughout */
432 default:
433 ntfs_error("Can't decode run type field %x\n",type);
434 return -1;
436 *data+=(type & 0xF);
438 switch(type & 0xF0)
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;
450 #endif
451 default:
452 ntfs_error("Can't decode run type field %x\n",type);
453 return -1;
455 *data+=(type >> 4);
456 return 0;
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,
463 ntfs_io *dest)
465 int rnum;
466 ntfs_cluster_t cluster,s_cluster,vcn,len;
467 int l,chunk,copied;
468 int s_vcn;
469 int clustersize;
470 int error;
472 clustersize=ino->vol->clustersize;
473 l=dest->size;
474 if(l==0)
475 return 0;
476 if(dest->do_read)
478 /* if read _starts_ beyond end of stream, return nothing */
479 if(offset>=attr->size){
480 dest->size=0;
481 return 0;
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;
489 }else {
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);
495 if(error)
496 return error;
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;
507 if(attr->resident)
509 if(dest->do_read)
510 dest->fn_put(dest,(ntfs_u8*)attr->d.data+offset,l);
511 else
512 dest->fn_get((ntfs_u8*)attr->d.data+offset,dest,l);
513 dest->size=l;
514 return 0;
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);
523 if(error)
524 return error;
525 return ntfs_read_zero(dest,l-chunk);
527 if(attr->compressed){
528 if(dest->do_read)
529 return ntfs_read_compressed(ino,attr,offset,dest);
530 else
531 return ntfs_write_compressed(ino,attr,offset,dest);
533 vcn=0;
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 */
540 return EOPNOTSUPP;
542 copied=0;
543 while(l)
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);
552 dest->size=chunk;
553 error=ntfs_getput_clusters(ino->vol,s_cluster,
554 offset-s_vcn*clustersize,dest);
555 if(error)
557 ntfs_error("Read error\n");
558 dest->size=copied;
559 return error;
561 l-=chunk;
562 copied+=chunk;
563 offset+=chunk;
564 if(l && offset>=((vcn+len)*clustersize))
566 rnum++;
567 vcn+=len;
568 cluster = attr->d.r.runlist[rnum].cluster;
569 len = attr->d.r.runlist[rnum].len;
572 dest->size=copied;
573 return 0;
576 int ntfs_read_attr(ntfs_inode *ino, int type, char *name, int offset,
577 ntfs_io *buf)
579 ntfs_attribute *attr;
580 buf->do_read=1;
581 attr=ntfs_find_attr(ino,type,name);
582 if(!attr)
583 return EINVAL;
584 return ntfs_readwrite_attr(ino,attr,offset,buf);
587 int ntfs_write_attr(ntfs_inode *ino, int type, char *name, int offset,
588 ntfs_io *buf)
590 ntfs_attribute *attr;
591 buf->do_read=0;
592 attr=ntfs_find_attr(ino,type,name);
593 if(!attr)
594 return EINVAL;
595 return ntfs_readwrite_attr(ino,attr,offset,buf);
598 int ntfs_vcn_to_lcn(ntfs_inode *ino,int vcn)
600 int rnum;
601 ntfs_attribute *data;
602 data=ntfs_find_attr(ino,ino->vol->at_data,0);
603 /* It's hard to give an error code */
604 if(!data)return -1;
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)
613 return 0;
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;
622 static int
623 allocate_store(ntfs_volume *vol,ntfs_disk_inode *store,int count)
625 int i;
626 if(store->count>count)
627 return 0;
628 if(store->size<count){
629 ntfs_mft_record* n=ntfs_malloc((count+4)*sizeof(ntfs_mft_record));
630 if(!n)
631 return ENOMEM;
632 if(store->size){
633 for(i=0;i<store->size;i++)
634 n[i]=store->records[i];
635 ntfs_free(store->records);
637 store->size=count+4;
638 store->records=n;
640 for(i=store->count;i<count;i++){
641 store->records[i].record=ntfs_malloc(vol->mft_recordsize);
642 if(!store->records[i].record)
643 return ENOMEM;
644 store->count++;
646 return 0;
649 static void
650 deallocate_store(ntfs_disk_inode* store)
652 int i;
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;
657 store->records=0;
660 int
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;
666 cluster=0;
667 offset=*offs;
668 for(i=0;i<attr->d.r.len;i++){
669 rclus=rl[i].cluster-cluster;
670 len=rl[i].len;
671 rec[offset]=0;
672 if(offset+8>size)
673 return E2BIG; /* it might still fit, but this simplifies testing */
674 if(len<0x100){
675 NTFS_PUTU8(rec+offset+1,len);
676 coffs=1;
677 }else if(len<0x10000){
678 NTFS_PUTU16(rec+offset+1,len);
679 coffs=2;
680 }else if(len<0x1000000){
681 NTFS_PUTU24(rec+offset+1,len);
682 coffs=3;
683 }else{
684 NTFS_PUTU32(rec+offset+1,len);
685 coffs=4;
688 *(rec+offset)|=coffs++;
690 if(rl[i].cluster==MAX_CLUSTER_T) /*compressed run*/
691 /*nothing*/;
692 else if(rclus>-0x80 && rclus<0x7F){
693 *(rec+offset)|=0x10;
694 NTFS_PUTS8(rec+offset+coffs,rclus);
695 coffs+=1;
696 }else if(rclus>-0x8000 && rclus<0x7FFF){
697 *(rec+offset)|=0x20;
698 NTFS_PUTS16(rec+offset+coffs,rclus);
699 coffs+=2;
700 }else if(rclus>-0x800000 && rclus<0x7FFFFF){
701 *(rec+offset)|=0x30;
702 NTFS_PUTS24(rec+offset+coffs,rclus);
703 coffs+=3;
704 }else
705 #if 0 /* In case ntfs_cluster_t ever becomes 64bit */
706 if (rclus>-0x80000000LL && rclus<0x7FFFFFFF)
707 #endif
709 *(rec+offset)|=0x40;
710 NTFS_PUTS32(rec+offset+coffs,rclus);
711 coffs+=4;
713 #if 0 /* For 64-bit ntfs_cluster_t */
714 else if (rclus>-0x8000000000 && rclus<0x7FFFFFFFFF){
715 *(rec+offset)|=0x50;
716 NTFS_PUTS40(rec+offset+coffs,rclus);
717 coffs+=5;
718 }else if (rclus>-0x800000000000 && rclus<0x7FFFFFFFFFFF){
719 *(rec+offset)|=0x60;
720 NTFS_PUTS48(rec+offset+coffs,rclus);
721 coffs+=6;
722 }else if (rclus>-0x80000000000000 && rclus<0x7FFFFFFFFFFFFF){
723 *(rec+offset)|=0x70;
724 NTFS_PUTS56(rec+offset+coffs,rclus);
725 coffs+=7;
726 }else{
727 *(rec+offset)|=0x80;
728 NTFS_PUTS64(rec+offset+coffs,rclus);
729 coffs+=8;
731 #endif
732 offset+=coffs;
733 if(rl[i].cluster)
734 cluster=rl[i].cluster;
736 if(offset>=size)
737 return E2BIG;
738 /* terminating null */
739 *(rec+offset++)=0;
740 *offs=offset;
741 return 0;
744 static void
745 count_runs(ntfs_attribute *attr,char *buf)
747 ntfs_u32 first,count,last,i;
748 first=0;
749 for(i=0,count=0;i<attr->d.r.len;i++)
750 count+=attr->d.r.runlist[i].len;
751 last=first+count-1;
753 NTFS_PUTU64(buf+0x10,first);
754 NTFS_PUTU64(buf+0x18,last);
757 static int
758 layout_attr(ntfs_attribute* attr,char*buf, int size,int *psize)
760 int asize,error;
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);
771 if(attr->resident){
772 if(size<attr->size+0x18+attr->namelen)return E2BIG;
773 asize=0x18;
774 NTFS_PUTU32(buf+0x10,attr->size);
775 NTFS_PUTU16(buf+0x16,attr->indexed);
776 if(attr->name){
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);
784 asize+=attr->size;
785 }else{
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);
796 asize=0x48;
797 }else
798 asize=0x40;
799 if(attr->name){
800 NTFS_PUTU16(buf+0xA,asize);
801 ntfs_memcpy(buf+asize,attr->name,2*attr->namelen);
802 asize+=2*attr->namelen;
803 /* SRD: you whaaa?
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 */
810 if(error)
811 return error;
813 asize=(asize+7) & ~7;
814 NTFS_PUTU32(buf+4,asize);
815 *psize=asize;
816 return 0;
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
826 int
827 layout_inode(ntfs_inode *ino,ntfs_disk_inode *store)
829 int offset,i;
830 ntfs_attribute *attr;
831 unsigned char *rec;
832 int size,psize;
833 int error;
835 if(ino->record_count>1)
837 ntfs_error("layout_inode: attribute lists not supported\n");
838 return EOPNOTSUPP;
840 error=allocate_store(ino->vol,store,1);
841 if(error)
842 return error;
843 rec=store->records[0].record;
844 size=ino->vol->mft_recordsize;
845 store->records[0].recno=ino->records[0];
846 /* copy header */
847 offset=NTFS_GETU16(ino->attr+0x14);
848 ntfs_memcpy(rec,ino->attr,offset);
849 for(i=0;i<ino->attr_count;i++){
850 attr=ino->attrs+i;
851 error=layout_attr(attr,rec+offset,size-offset,&psize);
852 if(error)return error;
853 offset+=psize;
854 #if 0
855 /* copy attribute header */
856 ntfs_memcpy(rec+offset,attr->header,
857 min(sizeof(attr->header),size-offset)); /* consider overrun */
858 if(attr->namelen)
859 /* named attributes are added later */
860 return EOPNOTSUPP;
861 /* FIXME: assign attribute ID??? */
862 if(attr->resident){
863 asize=attr->size;
864 aoffset=NTFS_GETU16(rec+offset+0x14);
865 if(offset+aoffset+asize>size)
866 return E2BIG;
867 ntfs_memcpy(rec+offset+aoffset,attr->d.data,asize);
868 next=offset+aoffset+asize;
869 }else{
870 count_runs(attr,rec+offset);
871 aoffset=NTFS_GETU16(rec+offset+0x20);
872 next=offset+aoffset;
873 error=layout_runs(attr,rec,&next,size);
874 if(error)
875 return error;
877 /* SRD: umm..
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);
884 offset=next;
885 #endif
887 /* terminating attribute */
888 if(offset+8<size){
889 NTFS_PUTU32(rec+offset,0xFFFFFFFF);
890 offset+=4;
891 NTFS_PUTU32(rec+offset,0);
892 offset+=4;
893 }else
894 return E2BIG;
895 NTFS_PUTU32(rec+0x18,offset);
896 return 0;
899 int ntfs_update_inode(ntfs_inode *ino)
901 int error;
902 ntfs_disk_inode store;
903 ntfs_io io;
904 int i;
906 store.count=store.size=0;
907 store.records=0;
908 error=layout_inode(ino,&store);
909 if(error==E2BIG){
910 error = ntfs_split_indexroot(ino);
911 if(!error)
912 error = layout_inode(ino,&store);
914 if(error == E2BIG){
915 error = ntfs_attr_allnonresident(ino);
916 if(!error)
917 error = layout_inode(ino,&store);
919 if(error == E2BIG){
920 /* should try:
921 introduce extension records
923 ntfs_error("cannot handle saving inode %x\n",ino->i_number);
924 deallocate_store(&store);
925 return EOPNOTSUPP;
927 if(error){
928 deallocate_store(&store);
929 return error;
931 io.fn_get=ntfs_get;
932 io.fn_put=0;
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;
948 return 0;
952 void ntfs_decompress(unsigned char *dest, unsigned char *src, ntfs_size_t l)
954 int head,comp;
955 int copied=0;
956 unsigned char *stop;
957 int bits;
958 int tag=0;
959 int clear_pos;
960 while(1)
962 head = NTFS_GETU16(src) & 0xFFF;
963 /* high bit indicates that compression was performed */
964 comp = NTFS_GETU16(src) & 0x8000;
965 src += 2;
966 stop = src+head;
967 bits = 0;
968 clear_pos=0;
969 if(head==0)
970 /* block is not used */
971 return;/* FIXME: copied */
972 if(!comp) /* uncompressible */
974 ntfs_memcpy(dest,src,0x1000);
975 dest+=0x1000;
976 copied+=0x1000;
977 src+=0x1000;
978 if(l==copied)
979 return;
980 continue;
982 while(src<=stop)
984 if(clear_pos>4096)
986 ntfs_error("Error 1 in decompress\n");
987 return;
989 if(!bits){
990 tag=NTFS_GETU8(src);
991 bits=8;
992 src++;
993 if(src>stop)
994 break;
996 if(tag & 1){
997 int i,len,delta,code,lmask,dshift;
998 code = NTFS_GETU16(src);
999 src+=2;
1000 if(!clear_pos)
1002 ntfs_error("Error 2 in decompress\n");
1003 return;
1005 for(i=clear_pos-1,lmask=0xFFF,dshift=12;i>=0x10;i>>=1)
1007 lmask >>= 1;
1008 dshift--;
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];
1015 clear_pos++;
1016 copied++;
1017 if(copied==l)
1018 return;
1020 }else{
1021 dest[clear_pos++]=NTFS_GETU8(src);
1022 src++;
1023 copied++;
1024 if(copied==l)
1025 return;
1027 tag>>=1;
1028 bits--;
1030 dest+=clear_pos;
1034 /* Caveat: No range checking in either ntfs_set_bit or ntfs_clear_bit */
1035 void
1036 ntfs_set_bit (unsigned char *byte, int bit)
1038 byte += (bit >> 3);
1039 bit &= 7;
1040 *byte |= (1 << bit);
1043 void
1044 ntfs_clear_bit (unsigned char *byte, int bit)
1046 byte += (bit >> 3);
1047 bit &= 7;
1048 *byte &= ~(1 << bit);
1051 /* We have to skip the 16 metafiles and the 8 reserved entries */
1052 static int
1053 new_inode (ntfs_volume* vol,int* result)
1055 int byte,error;
1056 int bit;
1057 int size,length;
1058 unsigned char value;
1059 ntfs_u8 *buffer;
1060 ntfs_io io;
1061 ntfs_attribute *data;
1063 buffer=ntfs_malloc(2048);
1064 if(!buffer)return ENOMEM;
1065 io.fn_put=ntfs_put;
1066 io.fn_get=ntfs_get;
1067 io.param=buffer;
1068 /* FIXME: bitmaps larger than 2048 bytes */
1069 io.size=2048;
1070 error=ntfs_read_attr(vol->mft_ino,vol->at_bitmap,0,0,&io);
1071 if(error){
1072 ntfs_free(buffer);
1073 return error;
1075 size=io.size;
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];
1083 if(value==0xFF)
1084 continue;
1085 for (bit = 0; (bit < 8) && (8*byte+bit<length);
1086 bit++, value >>= 1)
1088 if (!(value & 1)){
1089 *result=byte*8+bit;
1090 return 0;
1094 /* There is no free space. We must first extend the MFT. */
1095 return ENOSPC;
1098 static int
1099 add_mft_header (ntfs_inode *ino)
1101 unsigned char* mft;
1102 ntfs_volume *vol=ino->vol;
1103 mft=ino->attr;
1105 ntfs_bzero(mft, vol->mft_recordsize);
1106 ntfs_fill_mft_header(mft,vol->mft_recordsize,vol->blocksize,
1107 ino->sequence_number);
1108 return 0;
1111 /* We need 0x48 bytes in total */
1112 static int
1113 add_standard_information (ntfs_inode *ino)
1115 ntfs_time64_t now;
1116 char data[0x30];
1117 char *position=data;
1118 int error;
1119 ntfs_attribute *si;
1121 now = ntfs_now();
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);
1132 return error;
1135 static int
1136 add_filename (ntfs_inode* ino, ntfs_inode* dir,
1137 const unsigned char *filename, int length, ntfs_u32 flags)
1139 unsigned char *position;
1140 unsigned int size;
1141 ntfs_time64_t now;
1142 int count;
1143 int error;
1144 unsigned char* data;
1145 ntfs_attribute *fn;
1147 /* work out the size */
1148 size = 0x42 + 2 * length;
1149 data = ntfs_malloc(size);
1150 if( !data )
1151 return ENOMEM;
1152 ntfs_bzero(data,size);
1154 /* search for a position */
1155 position = data;
1157 NTFS_PUTINUM(position, dir); /* Inode num of dir */
1159 now = ntfs_now();
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 */
1165 /* Don't know */
1166 NTFS_PUTU32(position+0x38, flags);
1168 NTFS_PUTU8(position + 0x40, length); /* Filename length */
1169 NTFS_PUTU8(position + 0x41, 0x0); /* only long name */
1171 position += 0x42;
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);
1178 if(!error)
1179 error=ntfs_dir_add(dir,ino,fn);
1180 ntfs_free(data);
1181 return error;
1184 int
1185 add_security (ntfs_inode* ino, ntfs_inode* dir)
1187 int error;
1188 char *buf;
1189 int size;
1190 ntfs_attribute* attr;
1191 ntfs_io io;
1192 ntfs_attribute *se;
1194 attr=ntfs_find_attr(dir,ino->vol->at_security_descriptor,0);
1195 if(!attr)
1196 return EOPNOTSUPP; /* need security in directory */
1197 size = attr->size;
1198 if(size>512)
1199 return EOPNOTSUPP;
1200 buf=ntfs_malloc(size);
1201 if(!buf)
1202 return ENOMEM;
1203 io.fn_get=ntfs_get;
1204 io.fn_put=ntfs_put;
1205 io.param=buf;
1206 io.size=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");
1209 if(error){
1210 ntfs_free(buf);
1211 return error;
1213 /* FIXME: consider ACL inheritance */
1214 error=ntfs_create_attr(ino,ino->vol->at_security_descriptor,
1215 0,buf,size,&se);
1216 ntfs_free(buf);
1217 return error;
1220 static int
1221 add_data (ntfs_inode* ino, unsigned char *data, int length)
1223 int error;
1224 ntfs_attribute *da;
1225 error=ntfs_create_attr(ino,ino->vol->at_data,0,data,length,&da);
1226 return error;
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)
1233 ntfs_io io;
1234 int error;
1235 ntfs_u8 buffer[2];
1236 ntfs_volume* vol=dir->vol;
1237 int byte,bit;
1239 error=new_inode (vol,&(result->i_number));
1240 if(error==ENOSPC){
1241 error=ntfs_extend_mft(vol);
1242 if(error)return error;
1243 error=new_inode(vol,&(result->i_number));
1245 if(error){
1246 ntfs_error ("ntfs_get_empty_inode: no free inodes\n");
1247 return error;
1249 byte=result->i_number/8;
1250 bit=result->i_number & 7;
1252 io.fn_put = ntfs_put;
1253 io.fn_get = ntfs_get;
1254 io.param = buffer;
1255 io.size=1;
1256 /* set a single bit */
1257 error=ntfs_read_attr(vol->mft_ino,vol->at_bitmap,0,byte,&io);
1258 if(error)return error;
1259 if(io.size!=1)
1260 return EIO;
1261 ntfs_set_bit (buffer, bit);
1262 io.param = buffer;
1263 io.size = 1;
1264 error = ntfs_write_attr (vol->mft_ino, vol->at_bitmap, 0, byte, &io);
1265 if(error)return error;
1266 if (io.size != 1)
1267 return EIO;
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 */
1273 io.param = buffer;
1274 io.size = 2;
1275 error = ntfs_read_attr(vol->mft_ino, vol->at_data, 0,
1276 result->i_number*vol->mft_recordsize+0x10,&io);
1277 if(error)
1278 return error;
1279 result->sequence_number=NTFS_GETU16(buffer)+1;
1280 result->vol=vol;
1281 result->attr=ntfs_malloc(vol->mft_recordsize);
1282 if( !result->attr )
1283 return ENOMEM;
1284 result->attr_count=0;
1285 result->attrs=0;
1286 result->record_count=1;
1287 result->records=ntfs_malloc(8*sizeof(int));
1288 if( !result->records ) {
1289 ntfs_free( result->attr );
1290 result->attr = 0;
1291 return ENOMEM;
1293 result->records[0]=result->i_number;
1294 error=add_mft_header(result);
1295 if(error)
1296 return error;
1297 error=add_standard_information(result);
1298 if(error)
1299 return error;
1300 error=add_filename(result,dir,filename,namelen,flags);
1301 if(error)
1302 return error;
1303 error=add_security(result,dir);
1304 /*FIXME: check error */
1305 return 0;
1309 ntfs_alloc_file(ntfs_inode *dir, ntfs_inode *result, char *filename,
1310 int namelen)
1312 int error = ntfs_alloc_inode(dir,result,filename,namelen,0);
1313 if(error)
1314 return error;
1315 error = add_data(result,0,0);
1316 return error;
1320 * Local variables:
1321 * c-file-style: "linux"
1322 * End: