📄 inode.c
字号:
#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); return -1; } *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 */int ntfs_readwrite_attr(ntfs_inode *ino, ntfs_attribute *attr, int offset, ntfs_io *dest){ int rnum; 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) return 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) 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; } } 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; 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) return error; return ntfs_read_zero(dest,l-chunk); } if(attr->compressed){ if(dest->do_read) return ntfs_read_compressed(ino,attr,offset,dest); else 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)/* FIXME: maybe return failure */ { ntfs_error("Read error\n"); dest->size=copied; return 0; } l-=chunk; copied+=chunk; offset+=chunk; if(l && offset>=((vcn+len)*clustersize)) { rnum++; vcn+=len; cluster = attr->d.r.runlist[rnum].cluster; len = attr->d.r.runlist[rnum].len; } } dest->size=copied; return 0;}int ntfs_read_attr(ntfs_inode *ino, int type, char *name, int offset, 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);}int ntfs_write_attr(ntfs_inode *ino, int type, char *name, int offset, 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);}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; /* For Linux, block number 0 represents a hole. 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;}static int allocate_store(ntfs_volume *vol,ntfs_disk_inode *store,int count){ int i; 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]; ntfs_free(store->records); } 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; store->count++; } return 0;}static void deallocate_store(ntfs_disk_inode* store){ int 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;}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)#endif { *(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; }#endif 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){ 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 intlayout_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{ /* 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) return error; } 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){ int offset,i; ntfs_attribute *attr; unsigned char *rec; int size,psize; int error; if(ino->record_count>1) { ntfs_error("layout_inode: attribute lists not supported\n"); return EOPNOTSUPP; } 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -