📄 fsys_ntfs.c.org
字号:
/* 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., 675 Mass Ave, Cambridge, MA 02139, 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*//*#ifdef STAGE1_5*/#include <shared.h>#include <filesys.h>#include "ntfs.h"/* 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#define index_data ((char *)FSYS_BUF)#define bitmap_data ((unsigned char *)(FSYS_BUF+MAX_INDEX_RECORD_SIZE))#define dcdbuf ((unsigned char *)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 ((unsigned long *)(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 ((unsigned char *)cluster16[26])#define is_ads_completion cluster16[27]typedef struct run_list { char *start; char *ptr; unsigned long svcn; unsigned long evcn; unsigned long vcn; unsigned long cnum0; unsigned long cnum; unsigned long clen;} RUNL;typedef struct ntfs_mft_record { char mft[MAX_MFT_RECORD_SIZE]; char mft2[MAX_MFT_RECORD_SIZE]; unsigned long attr_type; char *attr_name; unsigned long attr_flag; unsigned long attr_size; char *attr; unsigned long attr_len; RUNL runl; char *attr_list; unsigned long attr_list_len; unsigned long attr_list_size; unsigned long attr_list_off; unsigned long attr_inited; char attr_list_buf[2*BLOCK_SIZE]; RUNL attr_list_runl;} MFTR;static int read_mft_record(unsigned long mftno, char *mft, unsigned long self);static unsigned long read_attribute(MFTR *mftr, unsigned long offset, char *buf, unsigned long len, RUNL *from_rl);static int get_next_run(RUNL *runl);#if 0static inline intnsubstring (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;}#endifstatic intfixup_record (char *record, char *magic, unsigned long size){ unsigned long start, count, offset; unsigned short fixup; if (*(int *)record != *(int *)magic) return 0; start = *(unsigned short *)(record + 4); count = *(unsigned short *)(record + 6); count--; if (size && blocksize * count != size) return 0; fixup = *(unsigned short *)(record + start); start += 2; offset = blocksize - 2; while (count--) { if(*(unsigned short *)(record + offset) != fixup) return 0; *(unsigned short *)(record + offset) = *(unsigned short *)(record + start); start += 2; offset += blocksize; } return 1;}static voidrewind_run_list( RUNL *runl){ runl->vcn = runl->svcn; runl->ptr = runl->start; runl->cnum0 = 0; runl->cnum = 0; runl->clen = 0;}static intget_next_run (RUNL *runl){ unsigned long 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 * (*(unsigned char *)((runl->ptr)++)); v <<= 8; } n = (t >> 4) & 0xf; if (n == 0) runl->cnum = 0; else { unsigned long c = 0; v = 1; while(n--) { c += v * (*(unsigned char *)((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_LISTstatic voidinit_run_list (char *attr, unsigned long len, RUNL *runl, unsigned long *initp){ unsigned long allocated; /* int inited; */ runl->svcn = *(unsigned long *)(attr + 0x10); /* only support 32 bit */ runl->evcn = *(unsigned long *)(attr + 0x18); /* only support 32 bit */ runl->start = attr + (*(unsigned short *)(attr + 0x20)); allocated = *(unsigned long *)(attr + 0x28); if (initp) *initp = *(unsigned long *)(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*/ *(unsigned long *)(attr+0x30), /*allocated*/ *(unsigned long *)(attr+0x28), /*attr_inited*/ *(unsigned long *)(attr+0x38), /*cengin*/ *(unsigned short *)(attr+0x22), /*csize*/ *(unsigned short *)(attr+0x40), runl->svcn, runl->evcn);#endif rewind_run_list(runl);}#endifstatic intfind_attribute (char *mft, unsigned long type, char *name, char **attr, unsigned long *size, unsigned long *len, unsigned long *flag){ unsigned long t, l, r, n, i, namelen; unsigned short *attr_name; n = strlen (name); r = mft_record_size - *(unsigned short *)(mft + 0x14); mft += *(unsigned short *)(mft + 0x14); while ((t = *(unsigned long *)mft) != -1) { l = *(unsigned long *)(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 = (unsigned short *)(mft + *(unsigned short *)(mft+10)), /*resident */ (*(mft+8) == 0), /*compressed*/ *(unsigned short *)(mft+12), /*attrno*/ *(unsigned short *)(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*/ || ! *(unsigned long *)(attr + 0x10)/*svcn==0*/)) { for (i = 0, attr_name = (unsigned short *)(mft + *(unsigned short *)(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 = (unsigned short *)(mft + *(unsigned short *)(mft + 10)); i < n; i++) if(tolower(name[i]) != tolower(attr_name[i])) break; if (i >= n) { if (flag) *flag = *(unsigned short *)(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*/ *(unsigned short *)(mft+0x14), /*attr_size*/ *(unsigned short *)(mft+0x10), /*indexed*/ *(unsigned short *)(mft+0x16));#endif if (attr) *attr = mft + (*(unsigned short *)(mft + 0x14)); if (size) *size = (*(unsigned short *)(mft + 0x10)); if (len) *len = (*(unsigned short *)(mft + 0x10)); } else { if (attr) *attr = mft; if (size) *size = *(unsigned long *)(mft+0x30); if (len) *len = l; } return 1; } } } mft += l; r -= l; } return 0;}#ifndef NO_ATTRIBUTE_LISTstatic unsigned longget_next_attribute_list (MFTR *mftr, unsigned long *size){ unsigned long l, t, mftno;#ifdef DEBUG_NTFS printf("get_next_attribute_list: type=%x\n",mftr->attr_type);#endifagain: while (mftr->attr_list_len > 0x14) { t = *(unsigned long *)(mftr->attr_list + 0); l = *(unsigned short *)(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 = *(unsigned long *)(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) { unsigned long 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");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -