📄 fsys_ntfs.c
字号:
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;}#endifint 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;#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(filepos >= cmft->attr_inited) {#ifdef DEBUG_NTFSprintf("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;#ifdef DEBUG_NTFSprintf("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_NTFSprintf("Reading filepos=%x len=%x\n", filepos, len);#endif if(filepos >= dcoff && filepos < (dcoff+dclen)) {#ifdef DEBUG_NTFSprintf("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_NTFSprintf("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_NTFSprintf("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_NTFSprintf("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_NTFSprintf("get next 16 clusters\n");#endif switch(get_16_cluster(cmft, vcn)) { case 0:#ifdef DEBUG_NTFSprintf("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_NTFSprintf("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; default:#ifdef DEBUG_NTFSprintf("compressed\n");#endif index16 = 0; dcvcn = vcn; dcoff = vcn * clustersize; dcrem = cmft->attr_inited - dcoff; if(dcrem > 16 * clustersize) dcrem = 16 * clustersize; dcsptr = dcsbuf; dcslen = 0; } } if(len0) {#ifdef DEBUG_NTFSprintf("reading uninitialized data 3\n");#endif memset(buf, 0, len0); filepos += len0; ret += len0; }#else errnum = FSYS_CORRUPT; #endif /*NO_NTFS_DECOMPRESSION*/#endif /*STAGE1_5*/ return ret;}int ntfs_mount (void){ char *sb = (char *)FSYS_BUF; int mft_record; int spc; if (((current_drive & 0x80) || (current_slice != 0)) && (current_slice != /*PC_SLICE_TYPE_NTFS*/7) && (current_slice != /*PC_SLICE_TYPE_NTFS*/0x17)) return 0; if (!devread (0, 0, 512, (char *) FSYS_BUF)) return 0; /* Cannot read superblock */ if(sb[3]!='N' || sb[4]!='T' || sb[5]!='F' || sb[6]!='S') return 0; blocksize = *(__u16 *)(sb+0xb); spc = *(unsigned char *)(sb+0xd); clustersize = spc * blocksize; mft_record_size = *(char *)(sb+0x40); index_record_size = *(char *)(sb+0x44); if(mft_record_size>0) mft_record_size *= clustersize; else mft_record_size = 1 << (-mft_record_size); index_record_size *= clustersize; mft_record = *(__u32 *)(sb+0x30); /* only support 32 bit */ spc = clustersize / 512; if(mft_record_size > MAX_MFT_RECORD_SIZE || index_record_size > MAX_INDEX_RECORD_SIZE) { /* only support 1k MFT record, 4k INDEX record */ return 0; }#ifdef DEBUG_NTFS printf("spc=%x mft_record=%x:%x\n", spc, *(__s64 *)(sb+0x30));#endif if (!devread (mft_record*spc, 0, mft_record_size, mmft->mft)) return 0; /* Cannot read superblock */ if(!fixup_record( mmft->mft, "FILE", mft_record_size)) return 0;#ifndef NO_ALTERNATE_DATASTREAM is_ads_completion = 0;#endif if(!search_attribute(mmft, at_data, NONAME)) return 0; *mft_run = mmft->runl; *path_ino = FILE_ROOT; return 1;}intntfs_dir (char *dirname){ char *rest, ch; int namelen; int depth = 0; int chk_sfn = 1; int flag = 0; int record_offset; int my_index_record_size; unsigned char *index_entry = 0, *entry, *index_end; int i; /* main loop to find desired directory entry */loop:#ifdef DEBUG_NTFS printf("dirname=%s\n", dirname);#endif if(!read_mft_record(path_ino[depth], cmft->mft, 0)) {#ifdef DEBUG_NTFS printf("MFT error 1\n");#endif errnum = ERR_FSYS_CORRUPT; return 0; } /* if we have a real file (and we're not just printing possibilities), then this is where we want to exit */ if (!*dirname || isspace (*dirname) || *dirname==':') {#ifndef STAGE1_5#ifndef NO_ALTERNATE_DATASTREAM if (*dirname==':' && print_possibilities) { char *tmp; /* preparing ADS name completion */ for(tmp = dirname; *tmp != '/'; tmp--); for(tmp++, rest=fnbuf; *tmp && !isspace(*tmp); *rest++ = *tmp++) if(*tmp==':') dirname = rest; *rest++ = '\0'; is_ads_completion = 1; search_attribute(cmft, at_data, dirname+1); is_ads_completion = 0; if(errnum==0) { if(print_possibilities < 0) return 1; errnum = ERR_FILE_NOT_FOUND; } return 0; }#endif#endif if (*dirname==':') dirname++; for (rest = dirname; (ch = *rest) && !isspace (ch); rest++); *rest = 0;#ifdef DEBUG_NTFS printf("got file: search at_data\n");#endif if (!search_attribute(cmft, at_data, dirname)) { errnum = *(dirname-1)==':'?ERR_FILE_NOT_FOUND:ERR_BAD_FILETYPE; *rest = ch; return 0; } *rest = ch; filemax = cmft->attr_size;#ifdef DEBUG_NTFS printf("filemax=%x\n", filemax);#endif return 1; } if(depth >= (MAX_DIR_DEPTH-1)) { errnum = ERR_FSYS_CORRUPT; return 0; } /* continue with the file/directory name interpretation */ while (*dirname == '/') dirname++; for (rest = dirname; (ch = *rest) && !isspace (ch) && ch != '/' && ch != ':'; rest++); *rest = 0; if (!search_attribute(cmft, at_index_root, "$I30")) { errnum = ERR_BAD_FILETYPE; return 0; } read_attribute(cmft, 0, fnbuf, 16, 0); my_index_record_size = *(__u32 *)(fnbuf+8); if(my_index_record_size > MAX_INDEX_RECORD_SIZE) { errnum = ERR_FSYS_CORRUPT; return 0; }#ifdef DEBUG_NTFS printf("index_record_size=%x\n", my_index_record_size);#endif if(cmft->attr_size > MAX_INDEX_RECORD_SIZE) { errnum = ERR_FSYS_CORRUPT; return 0; } read_attribute(cmft, 0, index_data, cmft->attr_size, 0); index_end = index_data + cmft->attr_size; index_entry = index_data + 0x20; record_offset = -1;#ifndef STAGE1_5 if (print_possibilities && ch != '/' && ch != ':' && !*dirname) { print_possibilities = -print_possibilities; /* fake '.' for empty directory */ print_a_completion ("."); }#endif if (search_attribute(cmft, at_bitmap, "$I30")) { if(cmft->attr_size > MAX_INDEX_BITMAP_SIZE) { errnum = ERR_FSYS_CORRUPT; return 0; } read_attribute(cmft, 0, bitmap_data, cmft->attr_size, 0); if (search_attribute(cmft, at_index_allocation, "$I30")==0) { errnum = ERR_FSYS_CORRUPT; return 0; } for(record_offset = 0; record_offset*my_index_record_size<cmft->attr_size; record_offset++){ int bit = 1 << (record_offset&3); int byte = record_offset>>3;#ifdef DEBUG_NTFS printf("record_offset=%x\n", record_offset);#endif if((bitmap_data[byte]&bit)) break; } if(record_offset*my_index_record_size>=cmft->attr_size) record_offset = -1; } do { entry = index_entry; index_entry += *(__u16 *)(entry+8); if(entry+0x50>=index_entry||entry>=index_end|| index_entry>=index_end||(entry[0x12]&2)){ if(record_offset < 0 || !read_attribute(cmft, record_offset*my_index_record_size, index_data, my_index_record_size, 0)){ if (!errnum) { if (print_possibilities < 0) {#if 0 putchar ('\n');#endif return 1; } errnum = ERR_FILE_NOT_FOUND; *rest = ch; } return 0; } if(!fixup_record( index_data, "INDX", my_index_record_size)) {#ifdef DEBUG_NTFS printf("index error\n");#endif errnum = ERR_FSYS_CORRUPT; return 0; } entry = index_data + 0x18 + *(__u16 *)(index_data+0x18); index_entry = entry + *(__u16 *)(entry+8); index_end = index_data + my_index_record_size - 0x52; for(record_offset++; record_offset*my_index_record_size<cmft->attr_size; record_offset++){ int bit = 1 << (record_offset&3); int byte = record_offset>>3; if((bitmap_data[byte]&bit)) break; } if(record_offset*my_index_record_size>=cmft->attr_size) record_offset = -1;#ifdef DEBUG_NTFS printf("record_offset=%x\n", record_offset);#endif } flag = entry[0x51]; path_ino[depth+1] = *(__u32 *)entry; if(path_ino[depth+1] < 16) continue; namelen = entry[0x50]; //if(index_data[0x48]&2) printf("hidden file\n");#ifndef STAGE1_5 /* skip short file name */ if( flag == 2 && print_possibilities && ch != '/' && ch != ':' ) continue;#endif for( i = 0, entry+=0x52; i < namelen; i++, entry+=2 ) { int c = *(__u16 *)entry; if(c==' '||c>=0x100) fnbuf[i] = '_'; else fnbuf[i] = c; } fnbuf[namelen] = 0;#ifdef DEBUG_NTFS printf("FLAG: %d NAME: %s inum=%d\n", flag,fnbuf,path_ino[depth+1]);#endif //uncntrl(fnbuf); chk_sfn = nsubstring(dirname,fnbuf);#ifndef STAGE1_5 if (print_possibilities && ch != '/' && ch != ':' && (!*dirname || chk_sfn <= 0)) { if (print_possibilities > 0) print_possibilities = -print_possibilities; print_a_completion (fnbuf); }#endif /* STAGE1_5 */ } while (chk_sfn != 0 || (print_possibilities && ch != '/' && ch != ':')); *(dirname = rest) = ch; depth++; /* go back to main loop at top of function */ goto loop;}#ifdef DEBUG_NTFSint dump_block(char *msg, char *buf, int size){ int l = (size+15)/16; int off; int i, j; int c; printf("----- %s -----\n", msg); for( i = 0, off = 0; i < l; i++, off+=16) { if(off<16) printf("000%x:", off); else if(off<256) printf("00%x:", off); else printf("0%x:", off); for(j=0;j<16;j++) { c = buf[off+j]&0xff; if( c >= 16 ) printf("%c%x",j==8?'-':' ',c); else printf("%c0%x",j==8?'-':' ',c); } printf(" "); for(j=0;j<16;j++) { char c = buf[off+j]; printf("%c",c<' '||c>='\x7f'?'.':c); } printf("\n"); }}#endif#endif /* FSYS_NTFS */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -