?? grub-0.97-patch3-ntfs
字號:
++#ifndef NO_ATTRIBUTE_LIST+static __u32 get_next_attribute_list(MFTR *mftr, int *size) {+ int l, t, mftno;+#ifdef DEBUG_NTFS+ printf("get_next_attribute_list: type=%x\n",mftr->attr_type);+#endif+again:+ while(mftr->attr_list_len>0x14) {+ t = *(__u32 *)(mftr->attr_list + 0);+ l = *(__u16 *)(mftr->attr_list + 4);+#ifdef DEBUG_NTFS+ printf("attr_list type=%x len=%x remain=%x\n", t, l, mftr->attr_list_len);+#endif+ if(l==0 || l>mftr->attr_list_len) return 0;+ mftno = *(__u32 *)(mftr->attr_list + 0x10);+ mftr->attr_list_len -= l;+ mftr->attr_list += l;+ if(t==mftr->attr_type)+ {+#ifdef DEBUG_NTFS+ printf("attr_list mftno=%x\n", mftno);+#endif+ if(read_mft_record(mftno, mftr->mft2, (mftr==mmft))==0)+ break;+ if(find_attribute(mftr->mft2, mftr->attr_type, mftr->attr_name,+ &mftr->attr, size, &mftr->attr_len, &mftr->attr_flag))+ return 1;+ }+ }+#ifndef NO_NON_RESIDENT_ATTRIBUTE_LIST+ if(mftr->attr_list_off < mftr->attr_list_size) {+ int len = mftr->attr_list_size - mftr->attr_list_off;+ if(len > BLOCK_SIZE) len = BLOCK_SIZE;++ if(mftr->attr_list_len)+ memmove(mftr->attr_list_buf, mftr->attr_list, mftr->attr_list_len);+ mftr->attr_list = mftr->attr_list_buf;++ if(read_attribute( NULL, mftr->attr_list_off,+ mftr->attr_list_buf + mftr->attr_list_len,+ len, &mftr->attr_list_runl) != len)+ {+#ifdef DEBUG_NTFS+ printf("CORRUPT NON-RESIDENT ATTRIBUTE_LIST\n");+#endif+ /* corrupt */+ errnum = ERR_FSYS_CORRUPT;+ mftr->attr_list_size = 0;+ mftr->attr_len = 0;+ mftr->attr_list = NULL;+ return 0;+ }++ mftr->attr_list_len += len;+ mftr->attr_list_off += len;+ goto again;+ }+#endif+ mftr->attr_list = NULL;+ return 0;+}+#endif++static int search_attribute( MFTR *mftr, int type, char *name)+{+#ifdef DEBUG_NTFS+ printf("searching attribute %x <%s>\n", type, name);+#endif ++ mftr->attr_type = type;+ mftr->attr_name = name;+ mftr->attr_list = NULL;+ mftr->attr_list_len = 0;+ mftr->attr_list_size = 0;+ mftr->attr_list_off = 0;+ dcrem = dclen = 0;++#ifndef NO_ATTRIBUTE_LIST+ if(find_attribute(mftr->mft, at_attribute_list, NONAME,+ &mftr->attr_list, &mftr->attr_list_size,+ &mftr->attr_list_len, &mftr->attr_list_off)) {+ if(mftr->attr_list_off&ATTR_RESIDENT) {+ /* resident at_attribute_list */+ mftr->attr_list_size = 0;+#ifdef DEBUG_NTFS+ printf("resident attribute_list len=%x\n", mftr->attr_list_len);+#endif+ } else {+#ifdef DEBUG_NTFS+ printf("non-resident attribute_list len=%x size=%x\n",+ mftr->attr_list_len, mftr->attr_list_size);+#endif+#ifndef NO_NON_RESIDENT_ATTRIBUTE_LIST+ init_run_list(mftr->attr_list, mftr->attr_list_len, &mftr->attr_list_runl, NULL);+ if(get_next_run(&mftr->attr_list_runl)==0 ||+ mftr->attr_list_runl.cnum==0)+ mftr->attr_list_size = 0;+#endif+ mftr->attr_list = NULL;+ mftr->attr_list_len = 0;+ }+ }+#endif++ if(find_attribute(mftr->mft, type, name,+ &mftr->attr, &mftr->attr_size, &mftr->attr_len,+ &mftr->attr_flag)+#ifndef NO_ATTRIBUTE_LIST+ || get_next_attribute_list(mftr, &mftr->attr_size)+#endif+ )+ {+#ifndef NO_ATTRIBUTE_LIST+ if(!(mftr->attr_flag&ATTR_RESIDENT)){+ init_run_list(mftr->attr, mftr->attr_len, &mftr->runl, (__u32 *)&mftr->attr_inited);+ if(mftr->attr_inited > mftr->attr_size)+ mftr->attr_inited = mftr->attr_size;+ if(get_next_run(&mftr->runl)==0) {+ mftr->attr_flag |= ATTR_RESIDENT;+ mftr->attr_len = 0;+ }+ } else+ mftr->attr_inited = mftr->attr_size;+#endif++ return 1;+ }++ mftr->attr_type = 0;+ return 0;+}++static int get_run( RUNL *rl, int vcn, int *clp, int *lenp) {+ if(rl->evcn < vcn)+ return 0;++ if(rl->vcn > vcn) {+ rewind_run_list(rl);+ get_next_run(rl);+ }++ while(rl->vcn+rl->clen <= vcn)+ {+ if(get_next_run(rl)==0)+ return 0;+ }++ if(clp) *clp = rl->cnum == 0 ? 0 : rl->cnum + vcn - rl->vcn;+ if(lenp) *lenp = rl->clen - vcn + rl->vcn;+ return 1;+}++static int search_run(MFTR *mftr, int vcn) {++ if( mftr->attr==NULL && !search_attribute(mftr, mftr->attr_type, mftr->attr_name))+ return 0;++ if(mftr->runl.svcn > vcn)+ search_attribute(mftr, mftr->attr_type, mftr->attr_name);++#ifdef NO_ATTRIBUTE_LIST+ if(mftr->runl.evcn < vcn)+ return 0;+#else+ while(mftr->runl.evcn < vcn) {+ if(get_next_attribute_list(mftr, NULL)==0) {+ mftr->attr = NULL;+ return 0;+ }+ init_run_list(mftr->attr, mftr->attr_len, &mftr->runl, NULL);+ if(get_next_run(&mftr->runl)==0) {+ mftr->attr = NULL;+ return 0;+ }+ }+#endif++ return 1;+}++static int read_attribute(MFTR *mftr, int offset, char *buf, int len, RUNL *from_rl) {+ int vcn;+ int cnum, clen;+ int done = 0;+ int n;+ RUNL *rl;++ if(!from_rl && (mftr->attr_flag & ATTR_RESIDENT)) {+ /* resident attribute */+ if(offset > mftr->attr_len)+ return 0;+ if(offset+len > mftr->attr_len)+ len = mftr->attr_len - offset;+ memmove( buf, mftr->attr + offset, len);+ return len;+ }++ vcn = offset / clustersize;+ offset %= clustersize;++ while(len>0) {+ if(from_rl)+ rl = from_rl;+ else if(search_run(mftr, vcn) == 0)+ break;+ else+ rl = &mftr->runl;+ if(get_run(rl, vcn, &cnum, &clen) == 0)+ break;+ if(cnum==0 && from_rl)+ break;+ n = clen * clustersize - offset;+ if(n > len) n = len;+ if(cnum==0) {+ memset( buf, 0, n);+ } else if(!devread(cnum*(clustersize>>9)+(offset>>9), offset&0x1ff, n, buf))+ break;++ buf += n;+ vcn += (offset+n)/clustersize;+ done += n;+ offset = 0;+ len -= n;+ }+ return done;+}++static int read_mft_record(int mftno, char *mft, int self){+#ifdef DEBUG_NTFS+ printf("Reading MFT record: mftno=%d\n", mftno);+#endif+ if( read_attribute( mmft, mftno * mft_record_size,+ mft, mft_record_size, self?mft_run:NULL) != mft_record_size)+ return 0;+ if(!fixup_record( mft, "FILE", mft_record_size))+ return 0;+ return 1;+}++#ifndef NO_NTFS_DECOMPRESSION+static int get_16_cluster(MFTR *mftr, int vcn) {+ int n = 0, cnum, clen;+ while(n < 16 && search_run(mftr, vcn) && get_run(&mftr->runl, vcn, &cnum, &clen) && cnum) {+ if(clen > 16 - n)+ clen = 16 - n;+ vcn += clen;+ while(clen--)+ cluster16[n++] = cnum++;+ }+ cluster16[n] = 0;+ return n;+}++static inline int compressed_block_size( unsigned char *src ) {+ return 3 + (*(__u16 *)src & 0xfff);+}++static int decompress_block(unsigned char *dest, unsigned char *src) {+ int head;+ int copied=0;+ unsigned char *last;+ int bits;+ int tag=0;++ /* high bit indicates that compression was performed */+ if(!(*(__u16 *)src & 0x8000)) {+ memmove(dest,src+2,0x1000);+ return 0x1000;+ }++ if((head = *(__u16 *)src & 0xFFF)==0)+ /* block is not used */+ return 0;++ src += 2;+ last = src+head;+ bits = 0;++ while(src<=last)+ {+ if(copied>4096)+ {+#ifdef DEBUG_NTFS+ printf("decompress error 1\n");+#endif+ errnum = ERR_FSYS_CORRUPT;+ return 0;+ }+ if(!bits){+ tag=*(__u8 *)src;+ bits=8;+ src++;+ if(src>last)+ break;+ }+ if(tag & 1){+ int i,len,delta,code,lmask,dshift;+ code = *(__u16 *)src;+ src+=2;+ if(!copied)+ {+#ifdef DEBUG_NTFS+ printf("decompress error 2\n");+#endif+ errnum = ERR_FSYS_CORRUPT;+ return 0;+ }+ for(i=copied-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[copied]=dest[copied-delta-1];+ copied++;+ }+ } else+ dest[copied++]=*(__u8 *)src++;+ tag>>=1;+ bits--;+ }++ return copied;+}+#endif++int ntfs_read(char *buf, int len){+ int ret;+#ifdef STAGE1_5+/* stage2 can't be resident/compressed/encrypted files,+ * but does sparse flag, cause stage2 never sparsed+ */+ if((cmft->attr_flag&~ATTR_SPARSE) != ATTR_NORMAL)+ return 0;+ disk_read_func = disk_read_hook;+ ret = read_attribute(cmft, filepos, buf, len, 0);+ disk_read_func = NULL;+ filepos += ret;+#else++/*#ifndef NO_NTFS_DECOMPRESSION*/+ //int off;+ //int vcn;+ //int size;+ int len0 = 0;+/*endif*/++ if(len<=0 || filepos >= cmft->attr_size || (cmft->attr_flag&ATTR_ENCRYPTED))+ return 0;++ if(filepos+len > cmft->attr_size)+ len = cmft->attr_size - filepos;+#if 0+ if(filepos >= cmft->attr_inited) {+#ifdef DEBUG_NTFS+printf("reading uninitialized data 1\n");+#endif+ memset(buf, 0, len);+ return len;+ } else if(filepos+len > cmft->attr_inited) {+ len0 = len;+ len = cmft->attr_inited - filepos;+ len0 -= len;+ } else+ len0 = 0;+#endif+#ifdef DEBUG_NTFS+printf("read filepos=%x filemax=%x inited=%x len=%x len0=%x\n",filepos,filemax,cmft->attr_inited,len,len0);+#endif++ if((cmft->attr_flag&(ATTR_COMPRESSED|ATTR_RESIDENT)) != ATTR_COMPRESSED) {+ if(cmft->attr_flag==ATTR_NORMAL)+ disk_read_func = disk_read_hook;+ ret = read_attribute(cmft, filepos, buf, len, 0);+ if(cmft->attr_flag==ATTR_NORMAL)+ disk_read_func = NULL;+ filepos += ret;+ if(ret==len && len0) {+ memset(buf+len, 0, len0);+ filepos += len0;+ ret += len0;+ }+ return ret;+ }++ ret = 0;++#ifndef NO_NTFS_DECOMPRESSION+ /* NTFS don't support compression if cluster size > 4k */+ if(clustersize > 4096) {+ errnum = ERR_FSYS_CORRUPT;+ return 0;+ }++ while(len > 0){+#ifdef DEBUG_NTFS+printf("Reading filepos=%x len=%x\n", filepos, len);+#endif+ if(filepos >= dcoff && filepos < (dcoff+dclen)) {+#ifdef DEBUG_NTFS+printf("decompress cache %x+%x\n", dcoff, dclen);+#endif+ size = dcoff + dclen - filepos;+ if(size > len) size = len;+ memmove( buf, dcdbuf + filepos - dcoff, size);+ filepos += size;+ len -= size;+ ret += size;+ buf += size;+ if(len==0) {+ if(len0) {+#ifdef DEBUG_NTFS+printf("reading uninitialized data 2\n");+#endif+ memset(buf, 0, len0);+ filepos += len0;+ ret += len0;+ }+ return ret;+ }+ }++ vcn = filepos / clustersize / 16;+ vcn *= 16;+ off = filepos % (16 * clustersize);+ if( dcvcn != vcn || filepos < dcoff)+ dcrem = 0;++#ifdef DEBUG_NTFS+printf("vcn %x off %x dcrem %x\n", vcn, off, dcrem);+#endif+ if(dcrem) {+ int head;++ /* reading source */+ if(dcslen < 2 || compressed_block_size(dcsptr) > dcslen) {+ if(cluster16[index16]==0) {+ errnum = ERR_FSYS_CORRUPT;+ return ret;+ }+ if(dcslen)+ memmove(dcsbuf, dcsptr, dcslen);+ dcsptr = dcsbuf;+ while((dcslen+clustersize) < DECOMP_SOURCE_BUFFER_SIZE) {+ if(cluster16[index16]==0)+ break;+#ifdef DEBUG_NTFS+printf("reading dcslen=%x cluster %x\n", dcslen, cluster16[index16]);+#endif+ if(!devread(cluster16[index16]*(clustersize>>9), 0, clustersize, dcsbuf+dcslen))+ return ret;+ dcslen += clustersize;+ index16++;+ }+ }+ /* flush destination */+ dcoff += dclen;+ dclen = 0;++ while(dcrem && dclen < DECOMP_DEST_BUFFER_SIZE &&+ dcslen >= 2 && (head=compressed_block_size(dcsptr)) <= dcslen) {+ size = decompress_block(dcdbuf+dclen, dcsptr);+ if(dcrem>=0x1000 && size!=0x1000) {+ errnum = ERR_FSYS_CORRUPT;+ return ret;+ }+ dcrem -= size;+ dclen += size;+ dcsptr += head;+ dcslen -= head;+ }+ continue;+ }+ dclen = dcrem = 0;+#ifdef DEBUG_NTFS+printf("get next 16 clusters\n");+#endif+ switch(get_16_cluster(cmft, vcn)) {+ case 0:+#ifdef DEBUG_NTFS+printf("sparse\n");+#endif+ /* sparse */+ size = 16 * clustersize - off;+ if( len < size )+ size = len;+#ifndef STAGE1_5+ memset( buf, 0, size);+#endif+ filepos += size;+ len -= size;+ ret += size;+ buf += size;+ break;++ case 16:+#ifdef DEBUG_NTFS+printf("uncompressed\n");+#endif+ /* uncompressed */+ index16 = off / clustersize;+ off %= clustersize;+ while(index16 < 16) {+ size = clustersize - off;+ if( len < size )+ size = len;+ if(!devread(cluster16[index16]*(clustersize>>9)+(off>>9), off&0x1ff, size, buf))+ return ret;+ filepos += size;+ len -= size;+ ret += size;+ if(len==0)+ return ret;+ off = 0;+ buf += size;+ index16++;+ }+ break;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -