diff options
Diffstat (limited to 'qemu/roms/openbios/fs/grubfs/fsys_ntfs.c')
-rw-r--r-- | qemu/roms/openbios/fs/grubfs/fsys_ntfs.c | 1255 |
1 files changed, 0 insertions, 1255 deletions
diff --git a/qemu/roms/openbios/fs/grubfs/fsys_ntfs.c b/qemu/roms/openbios/fs/grubfs/fsys_ntfs.c deleted file mode 100644 index a244f5c6b..000000000 --- a/qemu/roms/openbios/fs/grubfs/fsys_ntfs.c +++ /dev/null @@ -1,1255 +0,0 @@ -/* vim: set sw=4 :*/ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 1999 Free Software Foundation, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, - * MA 02110-1301, USA. - */ - -/* - * Samuel Leo <samuel@_.remove.me._szonline.net> - * Limitations: - * 1. Only 32 bit size support - * 2. don't support >1k MFT record size, >16k INDEX record size - * 3. don't support recursive at_attribute_list - * 4. don't support compressed attribute other than Datastream - * 5. all MFT's at_attribute_list must resident at first run list - * 6. don't support journaling - * 7. don't support EFS encryption - * 8. don't support mount point and junction - */ -#ifdef FSYS_NTFS - -//#define DEBUG_NTFS 1 - -/* -#define NO_ATTRIBUTE_LIST 1 - totally disable at_attribute_list support, - if no compressed/fragment file and MFT, - not recommended -#define NO_NON_RESIDENT_ATTRIBUTE_LIST 1 - disable non-resident at_attribute_list support, - if no huge compressed/fragment file and MFT -#define NO_NTFS_DECOMPRESSION 1 - disable ntfs compressed file support -#define NO_ALTERNATE_DATASTREAM 1 - disable ntfs alternate datastream support -*/ - -#include "shared.h" -#include "filesys.h" - -#ifdef STAGE1_5 -/* safe turn off non-resident attribute list if MFT fragments < 4000 */ -//#define NO_NON_RESIDENT_ATTRIBUTE_LIST 1 -#define NO_NTFS_DECOMPRESSION 1 -#endif - -#define MAX_MFT_RECORD_SIZE 1024 -#define MAX_INDEX_RECORD_SIZE 16384 -#define MAX_INDEX_BITMAP_SIZE 4096 -#define DECOMP_DEST_BUFFER_SIZE 16384 -#define DECOMP_SOURCE_BUFFER_SIZE (8192+2) -#define MAX_DIR_DEPTH 64 - -/* sizes are always in bytes, BLOCK values are always in DEV_BSIZE (sectors) */ -#define DEV_BSIZE 512 - -/* include/linux/fs.h */ -#define BLOCK_SIZE 512 - -#define WHICH_SUPER 1 -#define SBLOCK (WHICH_SUPER * BLOCK_SIZE / DEV_BSIZE) /* = 2 */ - -/* include/asm-i386/type.h */ -typedef __signed__ char __s8; -typedef unsigned char __u8; -typedef __signed__ short __s16; -typedef unsigned short __u16; -typedef __signed__ int __s32; -typedef unsigned int __u32; -typedef __signed__ long long __s64; -typedef unsigned long long __u64; - -#define FILE_MFT 0 -#define FILE_MFTMIRR 1 -#define FILE_LOGFILE 2 -#define FILE_VOLUME 3 -#define FILE_ATTRDEF 4 -#define FILE_ROOT 5 -#define FILE_BITMAP 6 -#define FILE_BOOT 7 -#define FILE_BADCLUS 8 -#define FILE_QUOTA 9 -#define FILE_UPCASE 10 - -#define at_standard_information 0x10 -#define at_attribute_list 0x20 -#define at_filename 0x30 -#define at_security_descriptor 0x50 -#define at_data 0x80 -#define at_index_root 0x90 -#define at_index_allocation 0xa0 -#define at_bitmap 0xb0 -#define at_symlink 0xc0 - -#define NONAME "" -#define ATTR_NORMAL 0 -#define ATTR_COMPRESSED 1 -#define ATTR_RESIDENT 2 -#define ATTR_ENCRYPTED 16384 -#define ATTR_SPARSE 32768 - -typedef struct run_list { - char *start; - char *ptr; - int svcn; - int evcn; - int vcn; - int cnum0; - int cnum; - int clen; -} RUNL; - -typedef struct ntfs_mft_record { - char mft[MAX_MFT_RECORD_SIZE]; - char mft2[MAX_MFT_RECORD_SIZE]; - int attr_type; - char *attr_name; - int attr_flag; - int attr_size; - char *attr; - int attr_len; - RUNL runl; - char *attr_list; - int attr_list_len; - int attr_list_size; - int attr_list_off; - int attr_inited; - char attr_list_buf[2*BLOCK_SIZE]; - RUNL attr_list_runl; -} MFTR; - - -#define index_data ((char *)FSYS_BUF) -#define bitmap_data ((__u8 *)(FSYS_BUF+MAX_INDEX_RECORD_SIZE)) -#define dcdbuf ((__u8 *)index_data) -#define dcsbuf (bitmap_data) -#define dcend (dcsbuf+DECOMP_SOURCE_BUFFER_SIZE) -#define fnbuf ((char *)(bitmap_data+MAX_INDEX_BITMAP_SIZE)) -#define mmft ((MFTR *)dcend) -#define cmft ((MFTR *)(dcend+sizeof(MFTR))) -#define mft_run ((RUNL *)(dcend+2*sizeof(MFTR))) -#define path_ino ((int *)(dcend+2*sizeof(MFTR)+sizeof(RUNL))) -#define cluster16 (path_ino+MAX_DIR_DEPTH) -#define index16 cluster16[16] -#define blocksize cluster16[17] -#define clustersize cluster16[18] -#define mft_record_size cluster16[19] -#define index_record_size cluster16[20] -#define dcvcn cluster16[21] -#define dcoff cluster16[22] -#define dclen cluster16[23] -#define dcrem cluster16[24] -#define dcslen cluster16[25] -#define dcsptr ((__u8 *)cluster16[26]) -#define is_ads_completion cluster16[27] - -static int read_mft_record(int mftno, char *mft, int self); -static int read_attribute(MFTR *mftr, int offset, char *buf, int len, RUNL *from_rl); -static int get_next_run(RUNL *runl); - -static inline int -nsubstring (char *s1, char *s2) -{ - while (tolower(*s1) == tolower(*s2)) - { - /* The strings match exactly. */ - if (! *(s1++)) - return 0; - s2 ++; - } - - /* S1 is a substring of S2. */ - if (*s1 == 0) - return -1; - - /* S1 isn't a substring. */ - return 1; -} - -static int fixup_record(char *record, char *magic, int size) -{ - int start, count, offset; - __u16 fixup; - - if(*(int *)record != *(int *)magic) - return 0; - start=*(__u16 *)(record+4); - count=*(__u16 *)(record+6); - count--; - if(size && blocksize*count != size) - return 0; - fixup = *(__u16 *)(record+start); - start+=2; - offset=blocksize-2; - while(count--){ - if(*(__u16 *)(record+offset)!=fixup) - return 0; - *(__u16 *)(record+offset) = *(__u16 *)(record+start); - start+=2; - offset+=blocksize; - } - return 1; -} - -static void rewind_run_list( RUNL *runl) { - runl->vcn = runl->svcn; - runl->ptr = runl->start; - runl->cnum0 = 0; - runl->cnum = 0; - runl->clen = 0; -} - -static int get_next_run(RUNL *runl){ - int t, n, v; - -#ifdef DEBUG_NTFS - printf("get_next_run: s=%d e=%d c=%d start=%x ptr=%x\n", - runl->svcn, runl->evcn, runl->vcn, runl->start, runl->ptr); -#endif - - runl->vcn += runl->clen; - if(runl->vcn > runl->evcn) { - return 0; - } - - t = *(runl->ptr)++; - n = t&0xf; - runl->clen = 0; v = 1; - while(n--) { - runl->clen += v * *((__u8 *)runl->ptr)++; - v <<= 8; - } - n = (t>>4)&0xf; - if(n==0) - runl->cnum = 0; - else { - int c = 0; - v = 1; - while(n--) { - c += v * *((__u8 *)runl->ptr)++; - v <<= 8; - } - if(c & (v>>1)) c -= v; - runl->cnum0 += c; - runl->cnum = runl->cnum0; - } -#ifdef DEBUG_NTFS - printf("got_next_run: t=%x cluster %x len %x vcn=%x ecn=%x\n", - t, runl->cnum, runl->clen, runl->vcn, runl->evcn); -#endif - return 1; -} - -#ifndef NO_ATTRIBUTE_LIST -static void init_run_list(char *attr, int len, RUNL *runl, __u32 *initp) { - int allocated; - - runl->svcn = *(__u32 *)(attr+0x10); /* only support 32 bit */ - runl->evcn = *(__u32 *)(attr+0x18); /* only support 32 bit */ - runl->start = attr + *(__u16 *)(attr+0x20); - allocated = *(__u32 *)(attr+0x28); - if(initp) *initp = *(__u32 *)(attr+0x38); - if(!runl->evcn) runl->evcn = (allocated - 1) / clustersize; -#ifdef DEBUG_NTFS - printf("size %d allocated=%d inited=%d cegin=%x csize=%d vcn=%d-%d\n", - /*attr_size*/ *(__u32 *)(attr+0x30), - /*allocated*/ *(__u32 *)(attr+0x28), - /*attr_inited*/ *(__u32 *)(attr+0x38), - /*cengin*/ *(__u16 *)(attr+0x22), - /*csize*/ *(__u16 *)(attr+0x40), - runl->svcn, runl->evcn); -#endif - rewind_run_list(runl); -} -#endif - - -static int find_attribute(char *mft, int type, char *name, char **attr, int *size, int *len, int *flag) { - int t, l, r, n, i, namelen; - unsigned short *attr_name; - - n = strlen(name); - r = mft_record_size - *(__u16 *)(mft+0x14); - mft += *(__u16 *)(mft+0x14); - while( (t = *(__s32 *)mft) != -1 ) { - l = *(__u32 *)(mft+4); - if(l>r) break; -#ifdef DEBUG_NTFS - printf("type = %x len = %d namelen=%d resident=%d compresed=%d attrno=%d\n", - t, l, - /*namelen*/ *(mft+9), - //name = (__u16 *)(mft + *(__u16 *)(mft+10)), - /*resident */ (*(mft+8) == 0), - /*compressed*/ *(__u16 *)(mft+12), - /*attrno*/ *(__u16 *)(mft+14)); -#endif - namelen = *(mft+9); - if(t == type) { -#ifndef STAGE1_5 -#ifndef NO_ALTERNATE_DATASTREAM - if(is_ads_completion && type == at_data) { - if(namelen && namelen >= n && - (!*(mft+8)/*resident*/ || !*(__u32 *)(attr+0x10)/*svcn==0*/)) - { - for(i=0, attr_name=(__u16 *)(mft + *(__u16 *)(mft+10)); i < n; i++) - if(tolower(name[i]) != tolower(attr_name[i])) - break; - if(i >= n) { - for(; i < namelen; i++) - name[i] = attr_name[i]; - name[i] = '\0'; - if(print_possibilities > 0) - print_possibilities = -print_possibilities; - print_a_completion(fnbuf); - name[n] = '\0'; - } - } - } else -#endif -#endif - if(namelen == n) { - - for(i=0, attr_name=(__u16 *)(mft + *(__u16 *)(mft+10)); i<n; i++) - if(tolower(name[i]) != tolower(attr_name[i])) - break; - if(i>=n) { - if(flag) *flag = *(__u16 *)(mft+12); - if(*(mft+8) == 0) { - if(flag) *flag |= ATTR_RESIDENT; -#ifdef DEBUG_NTFS - printf("resident data at %x size %x indexed=%d\n", - /*data*/ *(__u16 *)(mft+0x14), - /*attr_size*/ *(__u16 *)(mft+0x10), - /*indexed*/ *(__u16 *)(mft+0x16)); -#endif - if(attr) *attr = mft + *(__u16 *)(mft+0x14); - if(size) *size = *(__u16 *)(mft+0x10); - if(len) *len = *(__u16 *)(mft+0x10); - } else { - if(attr) *attr = mft; - if(size) *size = *(__u32 *)(mft+0x30); - if(len) *len = l; - } - return 1; - } - } - } - mft += l; - r -= l; - } - return 0; -} - -#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, &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; -#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_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; -#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; - - default: -#ifdef DEBUG_NTFS -printf("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_NTFS -printf("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; -} - -int -ntfs_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_NTFS -int 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 */ |