📄 inode.c
字号:
} /* 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;} int ntfs_update_inode(ntfs_inode *ino){ int error; ntfs_disk_inode store; ntfs_io io; int i; 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 == E2BIG){ error = ntfs_attr_allnonresident(ino); 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); deallocate_store(&store); return EOPNOTSUPP; } 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); deallocate_store(&store); 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; unsigned char *stop; int bits; int tag=0; int clear_pos; while(1) { head = NTFS_GETU16(src) & 0xFFF; /* high bit indicates that compression was performed */ comp = NTFS_GETU16(src) & 0x8000; src += 2; stop = src+head; bits = 0; 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) return; continue; } while(src<=stop) { if(clear_pos>4096) { ntfs_error("Error 1 in decompress\n"); return; } if(!bits){ tag=NTFS_GETU8(src); bits=8; src++; if(src>stop) break; } if(tag & 1){ int i,len,delta,code,lmask,dshift; code = NTFS_GETU16(src); 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) { lmask >>= 1; dshift--; } delta = code >> dshift; len = (code & lmask) + 3; for(i=0; i<len; i++) { dest[clear_pos]=dest[clear_pos-delta-1]; clear_pos++; copied++; if(copied==l) return; } }else{ dest[clear_pos++]=NTFS_GETU8(src); src++; copied++; if(copied==l) return; } tag>>=1; bits--; } 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){ byte += (bit >> 3); bit &= 7; *byte |= (1 << 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 new_inode (ntfs_volume* vol,int* result){ int byte,error; int bit; 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){ 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++) { value = buffer[byte]; if(value==0xFF) continue; 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;}static int add_mft_header (ntfs_inode *ino){ 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); return 0;}/* We need 0x48 bytes in total */static int add_standard_information (ntfs_inode *ino){ ntfs_time64_t now; char data[0x30]; char *position=data; int error; ntfs_attribute *si; now = ntfs_now(); NTFS_PUTU64(position + 0x00, now); /* File creation */ 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); 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; unsigned char* data; ntfs_attribute *fn; /* work out the size */ size = 0x42 + 2 * length; data = ntfs_malloc(size); if( !data ) return ENOMEM; ntfs_bzero(data,size); /* search for a position */ position = data; 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 */ position += 0x42; 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); ntfs_free(data); return error;}int add_security (ntfs_inode* ino, ntfs_inode* dir){ int error; char *buf; int size; ntfs_attribute* attr; 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 */ 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){ ntfs_free(buf); return error; } /* 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){ int error; ntfs_attribute *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){ ntfs_io io; int error; ntfs_u8 buffer[2]; ntfs_volume* vol=dir->vol; int byte,bit; error=new_inode (vol,&(result->i_number)); if(error==ENOSPC){ error=ntfs_extend_mft(vol); if(error)return error; error=new_inode(vol,&(result->i_number)); } if(error){ ntfs_error ("ntfs_get_empty_inode: no free inodes\n"); return error; } 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.param = buffer; io.size = 1; 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 */ 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) 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 ); result->attr = 0; return ENOMEM; } 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_filename(result,dir,filename,namelen,flags); if(error) return error; error=add_security(result,dir); /*FIXME: check error */ return 0;}intntfs_alloc_file(ntfs_inode *dir, ntfs_inode *result, char *filename, int namelen){ int error = ntfs_alloc_inode(dir,result,filename,namelen,0); if(error) return error; error = add_data(result,0,0); return error;}/* * Local variables: * c-file-style: "linux" * End: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -