1 /* vim: set sw=4 :*/
2 /*
3  *  GRUB  --  GRand Unified Bootloader
4  *  Copyright (C) 1999  Free Software Foundation, Inc.
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
19  *  MA 02110-1301, USA.
20  */
21 
22 /*
23  * Samuel Leo <samuel@_.remove.me._szonline.net>
24  * Limitations:
25  * 1. Only 32 bit size support
26  * 2. don't support >1k MFT record size, >16k INDEX record size
27  * 3. don't support recursive at_attribute_list
28  * 4. don't support compressed attribute other than Datastream
29  * 5. all MFT's at_attribute_list must resident at first run list
30  * 6. don't support journaling
31  * 7. don't support EFS encryption
32  * 8. don't support mount point and junction
33  */
34 #ifdef FSYS_NTFS
35 
36 //#define DEBUG_NTFS 1
37 
38 /*
39 #define NO_ATTRIBUTE_LIST 1
40    totally disable at_attribute_list support,
41    if no compressed/fragment file and MFT,
42    not recommended
43 #define NO_NON_RESIDENT_ATTRIBUTE_LIST 1
44    disable non-resident at_attribute_list support,
45    if no huge compressed/fragment file and MFT
46 #define NO_NTFS_DECOMPRESSION 1
47    disable ntfs compressed file support
48 #define NO_ALTERNATE_DATASTREAM 1
49    disable ntfs alternate datastream support
50 */
51 
52 #include "shared.h"
53 #include "filesys.h"
54 
55 #ifdef STAGE1_5
56 /* safe turn off non-resident attribute list if MFT fragments < 4000 */
57 //#define NO_NON_RESIDENT_ATTRIBUTE_LIST 1
58 #define NO_NTFS_DECOMPRESSION 1
59 #endif
60 
61 #define MAX_MFT_RECORD_SIZE 1024
62 #define MAX_INDEX_RECORD_SIZE 16384
63 #define MAX_INDEX_BITMAP_SIZE 4096
64 #define DECOMP_DEST_BUFFER_SIZE 16384
65 #define DECOMP_SOURCE_BUFFER_SIZE (8192+2)
66 #define MAX_DIR_DEPTH 64
67 
68 /* sizes are always in bytes, BLOCK values are always in DEV_BSIZE (sectors) */
69 #define DEV_BSIZE 512
70 
71 /* include/linux/fs.h */
72 #define BLOCK_SIZE 	512
73 
74 #define WHICH_SUPER 1
75 #define SBLOCK (WHICH_SUPER * BLOCK_SIZE / DEV_BSIZE)	/* = 2 */
76 
77 /* include/asm-i386/type.h */
78 typedef __signed__ char __s8;
79 typedef unsigned char __u8;
80 typedef __signed__ short __s16;
81 typedef unsigned short __u16;
82 typedef __signed__ int __s32;
83 typedef unsigned int __u32;
84 typedef __signed__ long long __s64;
85 typedef unsigned long long __u64;
86 
87 #define FILE_MFT      0
88 #define FILE_MFTMIRR  1
89 #define FILE_LOGFILE  2
90 #define FILE_VOLUME   3
91 #define FILE_ATTRDEF  4
92 #define FILE_ROOT     5
93 #define FILE_BITMAP   6
94 #define FILE_BOOT     7
95 #define FILE_BADCLUS  8
96 #define FILE_QUOTA    9
97 #define FILE_UPCASE  10
98 
99 #define at_standard_information 0x10
100 #define at_attribute_list 	0x20
101 #define at_filename		0x30
102 #define at_security_descriptor	0x50
103 #define at_data			0x80
104 #define at_index_root		0x90
105 #define at_index_allocation	0xa0
106 #define at_bitmap		0xb0
107 #define at_symlink		0xc0
108 
109 #define NONAME	""
110 #define ATTR_NORMAL	0
111 #define ATTR_COMPRESSED	1
112 #define ATTR_RESIDENT	2
113 #define ATTR_ENCRYPTED	16384
114 #define ATTR_SPARSE	32768
115 
116 typedef struct run_list {
117 	char *start;
118 	char *ptr;
119 	int svcn;
120 	int evcn;
121 	int vcn;
122 	int cnum0;
123 	int cnum;
124 	int clen;
125 } RUNL;
126 
127 typedef struct ntfs_mft_record {
128 	char mft[MAX_MFT_RECORD_SIZE];
129 	char mft2[MAX_MFT_RECORD_SIZE];
130 	int attr_type;
131 	char *attr_name;
132 	int attr_flag;
133 	int attr_size;
134 	char *attr;
135 	int attr_len;
136 	RUNL runl;
137 	char *attr_list;
138 	int attr_list_len;
139 	int attr_list_size;
140 	int attr_list_off;
141 	int attr_inited;
142 	char attr_list_buf[2*BLOCK_SIZE];
143 	RUNL attr_list_runl;
144 } MFTR;
145 
146 
147 #define index_data	((char *)FSYS_BUF)
148 #define bitmap_data	((__u8 *)(FSYS_BUF+MAX_INDEX_RECORD_SIZE))
149 #define dcdbuf	((__u8 *)index_data)
150 #define dcsbuf	(bitmap_data)
151 #define dcend	(dcsbuf+DECOMP_SOURCE_BUFFER_SIZE)
152 #define fnbuf ((char *)(bitmap_data+MAX_INDEX_BITMAP_SIZE))
153 #define mmft	((MFTR *)dcend)
154 #define cmft	((MFTR *)(dcend+sizeof(MFTR)))
155 #define mft_run	((RUNL *)(dcend+2*sizeof(MFTR)))
156 #define path_ino ((int *)(dcend+2*sizeof(MFTR)+sizeof(RUNL)))
157 #define cluster16 (path_ino+MAX_DIR_DEPTH)
158 #define index16 cluster16[16]
159 #define blocksize cluster16[17]
160 #define clustersize cluster16[18]
161 #define mft_record_size cluster16[19]
162 #define index_record_size cluster16[20]
163 #define dcvcn cluster16[21]
164 #define dcoff cluster16[22]
165 #define dclen cluster16[23]
166 #define dcrem cluster16[24]
167 #define dcslen cluster16[25]
168 #define dcsptr ((__u8 *)cluster16[26])
169 #define is_ads_completion cluster16[27]
170 
171 static int read_mft_record(int mftno, char *mft, int self);
172 static int read_attribute(MFTR *mftr, int offset, char *buf, int len, RUNL *from_rl);
173 static int get_next_run(RUNL *runl);
174 
175 static inline int
nsubstring(char * s1,char * s2)176 nsubstring (char *s1, char *s2)
177 {
178     while (tolower(*s1) == tolower(*s2))
179     {
180 	/* The strings match exactly. */
181 	if (! *(s1++))
182 	    return 0;
183 	s2 ++;
184     }
185 
186     /* S1 is a substring of S2. */
187     if (*s1 == 0)
188 	return -1;
189 
190     /* S1 isn't a substring. */
191     return 1;
192 }
193 
fixup_record(char * record,char * magic,int size)194 static int fixup_record(char *record, char *magic, int size)
195 {
196     int start, count, offset;
197     __u16 fixup;
198 
199     if(*(int *)record != *(int *)magic)
200 	return 0;
201     start=*(__u16 *)(record+4);
202     count=*(__u16 *)(record+6);
203     count--;
204     if(size && blocksize*count != size)
205 	return 0;
206     fixup = *(__u16 *)(record+start);
207     start+=2;
208     offset=blocksize-2;
209     while(count--){
210 	if(*(__u16 *)(record+offset)!=fixup)
211 	    return 0;
212 	*(__u16 *)(record+offset) = *(__u16 *)(record+start);
213 	start+=2;
214 	offset+=blocksize;
215     }
216     return 1;
217 }
218 
rewind_run_list(RUNL * runl)219 static void rewind_run_list( RUNL *runl) {
220     runl->vcn = runl->svcn;
221     runl->ptr = runl->start;
222     runl->cnum0 = 0;
223     runl->cnum = 0;
224     runl->clen = 0;
225 }
226 
get_next_run(RUNL * runl)227 static int get_next_run(RUNL *runl){
228     int t, n, v;
229 
230 #ifdef DEBUG_NTFS
231     printf("get_next_run: s=%d e=%d c=%d start=%x ptr=%x\n",
232 	   runl->svcn, runl->evcn, runl->vcn, runl->start, runl->ptr);
233 #endif
234 
235     runl->vcn += runl->clen;
236     if(runl->vcn > runl->evcn) {
237     	return 0;
238     }
239 
240     t = *(runl->ptr)++;
241     n = t&0xf;
242     runl->clen = 0; v = 1;
243     while(n--) {
244 	runl->clen += v * *((__u8 *)runl->ptr)++;
245 	v <<= 8;
246     }
247     n = (t>>4)&0xf;
248     if(n==0)
249 	runl->cnum = 0;
250     else {
251 	int c = 0;
252 	v = 1;
253 	while(n--) {
254 	    c += v * *((__u8 *)runl->ptr)++;
255 	    v <<= 8;
256 	}
257 	if(c & (v>>1)) c -= v;
258 	runl->cnum0 += c;
259 	runl->cnum = runl->cnum0;
260     }
261 #ifdef DEBUG_NTFS
262     printf("got_next_run: t=%x cluster %x len %x vcn=%x ecn=%x\n",
263     	t, runl->cnum, runl->clen, runl->vcn, runl->evcn);
264 #endif
265     return 1;
266 }
267 
268 #ifndef NO_ATTRIBUTE_LIST
init_run_list(char * attr,int len,RUNL * runl,__u32 * initp)269 static void init_run_list(char *attr, int len, RUNL *runl, __u32 *initp) {
270     int allocated;
271 
272     runl->svcn = *(__u32 *)(attr+0x10); /* only support 32 bit */
273     runl->evcn = *(__u32 *)(attr+0x18); /* only support 32 bit */
274     runl->start = attr + *(__u16 *)(attr+0x20);
275     allocated = *(__u32 *)(attr+0x28);
276     if(initp) *initp = *(__u32 *)(attr+0x38);
277     if(!runl->evcn) runl->evcn = (allocated - 1) / clustersize;
278 #ifdef DEBUG_NTFS
279     printf("size %d allocated=%d inited=%d cegin=%x csize=%d vcn=%d-%d\n",
280 	    /*attr_size*/ *(__u32 *)(attr+0x30),
281 	    /*allocated*/ *(__u32 *)(attr+0x28),
282 	    /*attr_inited*/ *(__u32 *)(attr+0x38),
283 	    /*cengin*/ *(__u16 *)(attr+0x22),
284 	    /*csize*/ *(__u16 *)(attr+0x40),
285 	    runl->svcn, runl->evcn);
286 #endif
287     rewind_run_list(runl);
288 }
289 #endif
290 
291 
find_attribute(char * mft,int type,char * name,char ** attr,int * size,int * len,int * flag)292 static int find_attribute(char *mft, int type, char *name, char **attr, int *size, int *len, int *flag) {
293     int t, l, r, n, i, namelen;
294     unsigned short *attr_name;
295 
296     n = strlen(name);
297     r = mft_record_size - *(__u16 *)(mft+0x14);
298     mft += *(__u16 *)(mft+0x14);
299     while( (t = *(__s32 *)mft) != -1 ) {
300 	l = *(__u32 *)(mft+4);
301 	if(l>r) break;
302 #ifdef DEBUG_NTFS
303 	printf("type = %x len = %d namelen=%d resident=%d compresed=%d attrno=%d\n",
304 		t, l,
305 		/*namelen*/ *(mft+9),
306 		//name = (__u16 *)(mft + *(__u16 *)(mft+10)),
307 		/*resident */ (*(mft+8) == 0),
308 		/*compressed*/ *(__u16 *)(mft+12),
309 		/*attrno*/ *(__u16 *)(mft+14));
310 #endif
311 	namelen = *(mft+9);
312 	if(t == type) {
313 #ifndef STAGE1_5
314 #ifndef NO_ALTERNATE_DATASTREAM
315 	    if(is_ads_completion && type == at_data) {
316 		if(namelen && namelen >= n &&
317 		   (!*(mft+8)/*resident*/ || !*(__u32 *)(attr+0x10)/*svcn==0*/))
318 		{
319 		    for(i=0, attr_name=(__u16 *)(mft + *(__u16 *)(mft+10)); i < n; i++)
320 			if(tolower(name[i]) != tolower(attr_name[i]))
321 			    break;
322 		    if(i >= n) {
323 			for(; i < namelen; i++)
324 			    name[i] = attr_name[i];
325 			name[i] = '\0';
326 			if(print_possibilities > 0)
327 			    print_possibilities = -print_possibilities;
328 			print_a_completion(fnbuf);
329 			name[n] = '\0';
330 		    }
331 		}
332 	    } else
333 #endif
334 #endif
335 		if(namelen == n) {
336 
337 		for(i=0, attr_name=(__u16 *)(mft + *(__u16 *)(mft+10)); i<n; i++)
338 		    if(tolower(name[i]) != tolower(attr_name[i]))
339 			break;
340 		if(i>=n) {
341 		    if(flag) *flag = *(__u16 *)(mft+12);
342 		    if(*(mft+8) == 0) {
343 			if(flag) *flag |= ATTR_RESIDENT;
344 #ifdef DEBUG_NTFS
345 			printf("resident data at %x size %x indexed=%d\n",
346 			       /*data*/ *(__u16 *)(mft+0x14),
347 			       /*attr_size*/ *(__u16 *)(mft+0x10),
348 			       /*indexed*/ *(__u16 *)(mft+0x16));
349 #endif
350 			if(attr) *attr = mft + *(__u16 *)(mft+0x14);
351 			if(size) *size = *(__u16 *)(mft+0x10);
352 			if(len) *len = *(__u16 *)(mft+0x10);
353 		    } else {
354 			if(attr) *attr = mft;
355 			if(size) *size = *(__u32 *)(mft+0x30);
356 			if(len) *len = l;
357 		    }
358 		    return 1;
359 		}
360 	    }
361 	}
362 	mft += l;
363 	r -= l;
364     }
365     return 0;
366 }
367 
368 #ifndef NO_ATTRIBUTE_LIST
get_next_attribute_list(MFTR * mftr,int * size)369 static __u32 get_next_attribute_list(MFTR *mftr, int *size) {
370     int l, t, mftno;
371 #ifdef DEBUG_NTFS
372     printf("get_next_attribute_list: type=%x\n",mftr->attr_type);
373 #endif
374 again:
375     while(mftr->attr_list_len>0x14) {
376 	t = *(__u32 *)(mftr->attr_list + 0);
377 	l = *(__u16 *)(mftr->attr_list + 4);
378 #ifdef DEBUG_NTFS
379 	printf("attr_list type=%x len=%x remain=%x\n", t, l, mftr->attr_list_len);
380 #endif
381 	if(l==0 || l>mftr->attr_list_len) return 0;
382 	mftno = *(__u32 *)(mftr->attr_list + 0x10);
383 	mftr->attr_list_len -= l;
384 	mftr->attr_list += l;
385 	if(t==mftr->attr_type)
386 	{
387 #ifdef DEBUG_NTFS
388 	printf("attr_list mftno=%x\n", mftno);
389 #endif
390 	    if(read_mft_record(mftno, mftr->mft2, (mftr==mmft))==0)
391 		break;
392 	    if(find_attribute(mftr->mft2, mftr->attr_type, mftr->attr_name,
393 			&mftr->attr, size, &mftr->attr_len, &mftr->attr_flag))
394 		return 1;
395 	}
396     }
397 #ifndef NO_NON_RESIDENT_ATTRIBUTE_LIST
398     if(mftr->attr_list_off < mftr->attr_list_size) {
399 	int len = mftr->attr_list_size - mftr->attr_list_off;
400 	if(len > BLOCK_SIZE) len = BLOCK_SIZE;
401 
402 	if(mftr->attr_list_len)
403 	    memmove(mftr->attr_list_buf, mftr->attr_list, mftr->attr_list_len);
404 	mftr->attr_list = mftr->attr_list_buf;
405 
406 	if(read_attribute( NULL, mftr->attr_list_off,
407 			mftr->attr_list_buf + mftr->attr_list_len,
408 			len, &mftr->attr_list_runl) != len)
409 	{
410 #ifdef DEBUG_NTFS
411 	    printf("CORRUPT NON-RESIDENT ATTRIBUTE_LIST\n");
412 #endif
413 	    /* corrupt */
414 	    errnum = ERR_FSYS_CORRUPT;
415 	    mftr->attr_list_size = 0;
416 	    mftr->attr_len = 0;
417 	    mftr->attr_list = NULL;
418 	    return 0;
419 	}
420 
421 	mftr->attr_list_len += len;
422 	mftr->attr_list_off += len;
423 	goto again;
424     }
425 #endif
426     mftr->attr_list = NULL;
427     return 0;
428 }
429 #endif
430 
search_attribute(MFTR * mftr,int type,char * name)431 static int search_attribute( MFTR *mftr, int type, char *name)
432 {
433 #ifdef DEBUG_NTFS
434     printf("searching attribute %x <%s>\n", type, name);
435 #endif
436 
437     mftr->attr_type = type;
438     mftr->attr_name = name;
439     mftr->attr_list = NULL;
440     mftr->attr_list_len = 0;
441     mftr->attr_list_size = 0;
442     mftr->attr_list_off = 0;
443     dcrem = dclen = 0;
444 
445 #ifndef NO_ATTRIBUTE_LIST
446     if(find_attribute(mftr->mft, at_attribute_list, NONAME,
447 		      &mftr->attr_list, &mftr->attr_list_size,
448 		      &mftr->attr_list_len, &mftr->attr_list_off)) {
449 	if(mftr->attr_list_off&ATTR_RESIDENT) {
450 	    /* resident at_attribute_list */
451 	    mftr->attr_list_size = 0;
452 #ifdef DEBUG_NTFS
453 	    printf("resident attribute_list len=%x\n", mftr->attr_list_len);
454 #endif
455 	} else {
456 #ifdef DEBUG_NTFS
457 	    printf("non-resident attribute_list len=%x size=%x\n",
458 		   mftr->attr_list_len, mftr->attr_list_size);
459 #endif
460 #ifndef NO_NON_RESIDENT_ATTRIBUTE_LIST
461 	    init_run_list(mftr->attr_list, mftr->attr_list_len, &mftr->attr_list_runl, NULL);
462 	    if(get_next_run(&mftr->attr_list_runl)==0 ||
463 	       mftr->attr_list_runl.cnum==0)
464 		mftr->attr_list_size = 0;
465 #endif
466 	    mftr->attr_list = NULL;
467 	    mftr->attr_list_len = 0;
468 	}
469     }
470 #endif
471 
472     if(find_attribute(mftr->mft, type, name,
473 		      &mftr->attr, &mftr->attr_size, &mftr->attr_len,
474 		      &mftr->attr_flag)
475 #ifndef NO_ATTRIBUTE_LIST
476        || get_next_attribute_list(mftr, &mftr->attr_size)
477 #endif
478        )
479     {
480 #ifndef NO_ATTRIBUTE_LIST
481 	if(!(mftr->attr_flag&ATTR_RESIDENT)){
482 	    init_run_list(mftr->attr, mftr->attr_len, &mftr->runl, &mftr->attr_inited);
483 	    if(mftr->attr_inited > mftr->attr_size)
484 	    	mftr->attr_inited = mftr->attr_size;
485 	    if(get_next_run(&mftr->runl)==0) {
486 		mftr->attr_flag |= ATTR_RESIDENT;
487 		mftr->attr_len = 0;
488 	    }
489 	} else
490 	    mftr->attr_inited = mftr->attr_size;
491 #endif
492 
493 	return 1;
494     }
495 
496     mftr->attr_type = 0;
497     return 0;
498 }
499 
get_run(RUNL * rl,int vcn,int * clp,int * lenp)500 static int get_run( RUNL *rl, int vcn, int *clp, int *lenp) {
501     if(rl->evcn < vcn)
502 	return 0;
503 
504     if(rl->vcn > vcn) {
505     	rewind_run_list(rl);
506 	get_next_run(rl);
507     }
508 
509     while(rl->vcn+rl->clen <= vcn)
510     {
511 	if(get_next_run(rl)==0)
512 	    return 0;
513     }
514 
515     if(clp) *clp = rl->cnum == 0 ? 0 : rl->cnum + vcn - rl->vcn;
516     if(lenp) *lenp = rl->clen - vcn + rl->vcn;
517     return 1;
518 }
519 
search_run(MFTR * mftr,int vcn)520 static int search_run(MFTR *mftr, int vcn) {
521 
522     if( mftr->attr==NULL && !search_attribute(mftr, mftr->attr_type, mftr->attr_name))
523 	return 0;
524 
525     if(mftr->runl.svcn > vcn)
526 	search_attribute(mftr, mftr->attr_type, mftr->attr_name);
527 
528 #ifdef NO_ATTRIBUTE_LIST
529     if(mftr->runl.evcn < vcn)
530 	return 0;
531 #else
532     while(mftr->runl.evcn < vcn) {
533 	if(get_next_attribute_list(mftr, NULL)==0) {
534 	    mftr->attr = NULL;
535 	    return 0;
536 	}
537 	init_run_list(mftr->attr, mftr->attr_len, &mftr->runl, NULL);
538 	if(get_next_run(&mftr->runl)==0) {
539 	    mftr->attr = NULL;
540 	    return 0;
541 	}
542     }
543 #endif
544 
545     return 1;
546 }
547 
read_attribute(MFTR * mftr,int offset,char * buf,int len,RUNL * from_rl)548 static int read_attribute(MFTR *mftr, int offset, char *buf, int len, RUNL *from_rl) {
549     int vcn;
550     int cnum, clen;
551     int done = 0;
552     int n;
553     RUNL *rl;
554 
555     if(!from_rl && (mftr->attr_flag & ATTR_RESIDENT)) {
556 	/* resident attribute */
557 	if(offset > mftr->attr_len)
558 	    return 0;
559 	if(offset+len > mftr->attr_len)
560 	    len = mftr->attr_len - offset;
561 	memmove( buf, mftr->attr + offset, len);
562 	return len;
563     }
564 
565     vcn = offset / clustersize;
566     offset %= clustersize;
567 
568     while(len>0) {
569 	if(from_rl)
570 	    rl = from_rl;
571 	else if(search_run(mftr, vcn) == 0)
572 	    break;
573 	else
574 	    rl = &mftr->runl;
575 	if(get_run(rl, vcn, &cnum, &clen) == 0)
576 	    break;
577 	if(cnum==0 && from_rl)
578 	    break;
579 	n = clen * clustersize - offset;
580 	if(n > len) n = len;
581 	if(cnum==0) {
582 	    memset( buf, 0, n);
583 	} else if(!devread(cnum*(clustersize>>9)+(offset>>9), offset&0x1ff, n, buf))
584 	    break;
585 
586 	buf += n;
587 	vcn += (offset+n)/clustersize;
588 	done += n;
589 	offset = 0;
590 	len -= n;
591     }
592     return done;
593 }
594 
read_mft_record(int mftno,char * mft,int self)595 static int read_mft_record(int mftno, char *mft, int self){
596 #ifdef DEBUG_NTFS
597     printf("Reading MFT record: mftno=%d\n", mftno);
598 #endif
599     if( read_attribute( mmft, mftno * mft_record_size,
600 	    mft, mft_record_size, self?mft_run:NULL) != mft_record_size)
601 	return 0;
602     if(!fixup_record( mft, "FILE", mft_record_size))
603 	return 0;
604     return 1;
605 }
606 
607 #ifndef NO_NTFS_DECOMPRESSION
get_16_cluster(MFTR * mftr,int vcn)608 static int get_16_cluster(MFTR *mftr, int vcn) {
609     int n = 0, cnum, clen;
610     while(n < 16 && search_run(mftr, vcn) && get_run(&mftr->runl, vcn, &cnum, &clen) && cnum) {
611 	if(clen > 16 - n)
612 	    clen = 16 - n;
613 	vcn += clen;
614 	while(clen--)
615 	    cluster16[n++] = cnum++;
616     }
617     cluster16[n] = 0;
618     return n;
619 }
620 
compressed_block_size(unsigned char * src)621 static inline int compressed_block_size( unsigned char *src ) {
622     return 3 + (*(__u16 *)src & 0xfff);
623 }
624 
decompress_block(unsigned char * dest,unsigned char * src)625 static int decompress_block(unsigned char *dest, unsigned char *src) {
626     int head;
627     int copied=0;
628     unsigned char *last;
629     int bits;
630     int tag=0;
631 
632     /* high bit indicates that compression was performed */
633     if(!(*(__u16 *)src & 0x8000)) {
634 	memmove(dest,src+2,0x1000);
635 	return 0x1000;
636     }
637 
638     if((head = *(__u16 *)src & 0xFFF)==0)
639 	/* block is not used */
640 	return 0;
641 
642     src += 2;
643     last = src+head;
644     bits = 0;
645 
646     while(src<=last)
647     {
648 	if(copied>4096)
649 	{
650 #ifdef DEBUG_NTFS
651 	    printf("decompress error 1\n");
652 #endif
653 	    errnum = ERR_FSYS_CORRUPT;
654 	    return 0;
655 	}
656 	if(!bits){
657 	    tag=*(__u8 *)src;
658 	    bits=8;
659 	    src++;
660 	    if(src>last)
661 		break;
662 	}
663 	if(tag & 1){
664 	    int i,len,delta,code,lmask,dshift;
665 	    code = *(__u16 *)src;
666 	    src+=2;
667 	    if(!copied)
668 	    {
669 #ifdef DEBUG_NTFS
670 		printf("decompress error 2\n");
671 #endif
672 		errnum = ERR_FSYS_CORRUPT;
673 		return 0;
674 	    }
675 	    for(i=copied-1,lmask=0xFFF,dshift=12;i>=0x10;i>>=1)
676 	    {
677 		lmask >>= 1;
678 		dshift--;
679 	    }
680 	    delta = code >> dshift;
681 	    len = (code & lmask) + 3;
682 	    for(i=0; i<len; i++)
683 	    {
684 		dest[copied]=dest[copied-delta-1];
685 		copied++;
686 	    }
687 	} else
688 	    dest[copied++]=*(__u8 *)src++;
689 	tag>>=1;
690 	bits--;
691     }
692 
693     return copied;
694 }
695 #endif
696 
ntfs_read(char * buf,int len)697 int ntfs_read(char *buf, int len){
698     int ret;
699 #ifdef STAGE1_5
700 /* stage2 can't be resident/compressed/encrypted files,
701  * but does sparse flag, cause stage2 never sparsed
702  */
703     if((cmft->attr_flag&~ATTR_SPARSE) != ATTR_NORMAL)
704 	return 0;
705     disk_read_func = disk_read_hook;
706     ret = read_attribute(cmft, filepos, buf, len, 0);
707     disk_read_func = NULL;
708     filepos += ret;
709 #else
710 
711 #ifndef NO_NTFS_DECOMPRESSION
712     int off;
713     int vcn;
714     int size;
715     int len0;
716 #endif
717 
718     if(len<=0 || filepos >= cmft->attr_size || (cmft->attr_flag&ATTR_ENCRYPTED))
719 	return 0;
720 
721     if(filepos+len > cmft->attr_size)
722 	len = cmft->attr_size - filepos;
723     if(filepos >= cmft->attr_inited) {
724 #ifdef DEBUG_NTFS
725 printf("reading uninitialized data 1\n");
726 #endif
727     	memset(buf, 0, len);
728 	return len;
729     } else if(filepos+len > cmft->attr_inited) {
730     	len0 = len;
731 	len = cmft->attr_inited - filepos;
732 	len0 -= len;
733     } else
734     	len0 = 0;
735 #ifdef DEBUG_NTFS
736 printf("read filepos=%x filemax=%x inited=%x len=%x len0=%x\n",filepos,filemax,cmft->attr_inited,len,len0);
737 #endif
738 
739     if((cmft->attr_flag&(ATTR_COMPRESSED|ATTR_RESIDENT)) != ATTR_COMPRESSED) {
740 	if(cmft->attr_flag==ATTR_NORMAL)
741 	    disk_read_func = disk_read_hook;
742 	ret = read_attribute(cmft, filepos, buf, len, 0);
743 	if(cmft->attr_flag==ATTR_NORMAL)
744 	    disk_read_func = NULL;
745 	filepos += ret;
746 	if(ret==len && len0) {
747 		memset(buf+len, 0, len0);
748 		filepos += len0;
749 		ret += len0;
750 	}
751 	return ret;
752     }
753 
754     ret = 0;
755 
756 #ifndef NO_NTFS_DECOMPRESSION
757     /* NTFS don't support compression if cluster size > 4k */
758     if(clustersize > 4096) {
759 	errnum = ERR_FSYS_CORRUPT;
760 	return 0;
761     }
762 
763     while(len > 0){
764 #ifdef DEBUG_NTFS
765 printf("Reading filepos=%x len=%x\n", filepos, len);
766 #endif
767 	if(filepos >= dcoff && filepos < (dcoff+dclen)) {
768 #ifdef DEBUG_NTFS
769 printf("decompress cache %x+%x\n", dcoff, dclen);
770 #endif
771 	    size = dcoff + dclen - filepos;
772 	    if(size > len) size = len;
773 	    memmove( buf, dcdbuf + filepos - dcoff, size);
774 	    filepos += size;
775 	    len -= size;
776 	    ret += size;
777 	    buf += size;
778 	    if(len==0) {
779 		if(len0) {
780 #ifdef DEBUG_NTFS
781 printf("reading uninitialized data 2\n");
782 #endif
783 		    memset(buf, 0, len0);
784 		    filepos += len0;
785 		    ret += len0;
786 		}
787 		return ret;
788 	    }
789 	}
790 
791 	vcn = filepos / clustersize / 16;
792 	vcn *= 16;
793 	off = filepos % (16 * clustersize);
794 	if( dcvcn != vcn || filepos < dcoff)
795 	    dcrem = 0;
796 
797 #ifdef DEBUG_NTFS
798 printf("vcn %x off %x dcrem %x\n", vcn, off, dcrem);
799 #endif
800 	if(dcrem) {
801 	    int head;
802 
803 	    /* reading source */
804 	    if(dcslen < 2 || compressed_block_size(dcsptr) > dcslen) {
805 		if(cluster16[index16]==0) {
806 		    errnum = ERR_FSYS_CORRUPT;
807 		    return ret;
808 		}
809 		if(dcslen)
810 		    memmove(dcsbuf, dcsptr, dcslen);
811 		dcsptr = dcsbuf;
812 		while((dcslen+clustersize) < DECOMP_SOURCE_BUFFER_SIZE) {
813 		    if(cluster16[index16]==0)
814 			break;
815 #ifdef DEBUG_NTFS
816 printf("reading dcslen=%x cluster %x\n", dcslen, cluster16[index16]);
817 #endif
818 		    if(!devread(cluster16[index16]*(clustersize>>9), 0, clustersize, dcsbuf+dcslen))
819 			return ret;
820 		    dcslen += clustersize;
821 		    index16++;
822 		}
823 	    }
824 	    /* flush destination */
825 	    dcoff += dclen;
826 	    dclen = 0;
827 
828 	    while(dcrem && dclen < DECOMP_DEST_BUFFER_SIZE &&
829 		  dcslen >= 2 && (head=compressed_block_size(dcsptr)) <= dcslen) {
830 		size = decompress_block(dcdbuf+dclen, dcsptr);
831 		if(dcrem>=0x1000 && size!=0x1000) {
832 		    errnum = ERR_FSYS_CORRUPT;
833 		    return ret;
834 		}
835 		dcrem -= size;
836 		dclen += size;
837 		dcsptr += head;
838 		dcslen -= head;
839 	    }
840 	    continue;
841 	}
842 	dclen = dcrem = 0;
843 #ifdef DEBUG_NTFS
844 printf("get next 16 clusters\n");
845 #endif
846 	switch(get_16_cluster(cmft, vcn)) {
847 	case 0:
848 #ifdef DEBUG_NTFS
849 printf("sparse\n");
850 #endif
851 	    /* sparse */
852 	    size = 16 * clustersize - off;
853 	    if( len < size )
854 		size = len;
855 #ifndef STAGE1_5
856 	    memset( buf, 0, size);
857 #endif
858 	    filepos += size;
859 	    len -= size;
860 	    ret += size;
861 	    buf += size;
862 	    break;
863 
864 	case 16:
865 #ifdef DEBUG_NTFS
866 printf("uncompressed\n");
867 #endif
868 	    /* uncompressed */
869 	    index16 = off / clustersize;
870 	    off %= clustersize;
871 	    while(index16 < 16) {
872 		size = clustersize - off;
873 		if( len < size )
874 		    size = len;
875 		if(!devread(cluster16[index16]*(clustersize>>9)+(off>>9), off&0x1ff, size, buf))
876 		    return ret;
877 		filepos += size;
878 		len -= size;
879 		ret += size;
880 		if(len==0)
881 		    return ret;
882 		off = 0;
883 		buf += size;
884 		index16++;
885 	    }
886 	    break;
887 
888 	default:
889 #ifdef DEBUG_NTFS
890 printf("compressed\n");
891 #endif
892 	    index16 = 0;
893 	    dcvcn = vcn;
894 	    dcoff = vcn * clustersize;
895 	    dcrem = cmft->attr_inited - dcoff;
896 	    if(dcrem > 16 * clustersize)
897 		dcrem = 16 * clustersize;
898 	    dcsptr = dcsbuf;
899 	    dcslen = 0;
900 	}
901     }
902     if(len0) {
903 #ifdef DEBUG_NTFS
904 printf("reading uninitialized data 3\n");
905 #endif
906 	memset(buf, 0, len0);
907 	filepos += len0;
908 	ret += len0;
909     }
910 #else
911     errnum = FSYS_CORRUPT;
912 #endif /*NO_NTFS_DECOMPRESSION*/
913 #endif /*STAGE1_5*/
914     return ret;
915 }
916 
ntfs_mount(void)917 int ntfs_mount (void)
918 {
919     char *sb = (char *)FSYS_BUF;
920     int mft_record;
921     int spc;
922 
923   if (((current_drive & 0x80) || (current_slice != 0))
924        && (current_slice != /*PC_SLICE_TYPE_NTFS*/7)
925        && (current_slice != /*PC_SLICE_TYPE_NTFS*/0x17))
926       return 0;
927 
928     if (!devread (0, 0, 512, (char *) FSYS_BUF))
929 	return 0;			/* Cannot read superblock */
930 
931     if(sb[3]!='N' || sb[4]!='T' || sb[5]!='F' || sb[6]!='S')
932 	return 0;
933     blocksize = *(__u16 *)(sb+0xb);
934     spc = *(unsigned char *)(sb+0xd);
935     clustersize = spc * blocksize;
936     mft_record_size = *(char *)(sb+0x40);
937     index_record_size = *(char *)(sb+0x44);
938     if(mft_record_size>0)
939 	mft_record_size *= clustersize;
940     else
941 	mft_record_size = 1 << (-mft_record_size);
942 
943     index_record_size *= clustersize;
944     mft_record = *(__u32 *)(sb+0x30); /* only support 32 bit */
945     spc = clustersize / 512;
946 
947     if(mft_record_size > MAX_MFT_RECORD_SIZE || index_record_size > MAX_INDEX_RECORD_SIZE) {
948 	/* only support 1k MFT record, 4k INDEX record */
949 	return 0;
950     }
951 
952 #ifdef DEBUG_NTFS
953     printf("spc=%x mft_record=%x:%x\n", spc, *(__s64 *)(sb+0x30));
954 #endif
955 
956     if (!devread (mft_record*spc, 0, mft_record_size, mmft->mft))
957 	return 0;			/* Cannot read superblock */
958 
959     if(!fixup_record( mmft->mft, "FILE", mft_record_size))
960 	return 0;
961 
962 #ifndef NO_ALTERNATE_DATASTREAM
963     is_ads_completion = 0;
964 #endif
965     if(!search_attribute(mmft, at_data, NONAME)) return 0;
966 
967     *mft_run = mmft->runl;
968 
969     *path_ino = FILE_ROOT;
970 
971     return 1;
972 }
973 
974 int
ntfs_dir(char * dirname)975 ntfs_dir (char *dirname)
976 {
977     char *rest, ch;
978     int namelen;
979     int depth = 0;
980     int chk_sfn = 1;
981     int flag = 0;
982     int record_offset;
983     int my_index_record_size;
984     unsigned char *index_entry = 0, *entry, *index_end;
985     int i;
986 
987     /* main loop to find desired directory entry */
988 loop:
989 
990 #ifdef DEBUG_NTFS
991     printf("dirname=%s\n", dirname);
992 #endif
993     if(!read_mft_record(path_ino[depth], cmft->mft, 0))
994     {
995 #ifdef DEBUG_NTFS
996 	printf("MFT error 1\n");
997 #endif
998 	errnum = ERR_FSYS_CORRUPT;
999 	return 0;
1000     }
1001 
1002     /* if we have a real file (and we're not just printing possibilities),
1003        then this is where we want to exit */
1004 
1005     if (!*dirname || isspace (*dirname) || *dirname==':')
1006     {
1007 #ifndef STAGE1_5
1008 #ifndef NO_ALTERNATE_DATASTREAM
1009 	if (*dirname==':' && print_possibilities) {
1010 	    char *tmp;
1011 
1012 	    /* preparing ADS name completion */
1013 	    for(tmp = dirname; *tmp != '/'; tmp--);
1014 	    for(tmp++, rest=fnbuf; *tmp && !isspace(*tmp); *rest++ = *tmp++)
1015 		if(*tmp==':') dirname = rest;
1016 	    *rest++ = '\0';
1017 
1018 	    is_ads_completion = 1;
1019 	    search_attribute(cmft, at_data, dirname+1);
1020 	    is_ads_completion = 0;
1021 
1022 	    if(errnum==0) {
1023 		if(print_possibilities < 0)
1024 		    return 1;
1025 		errnum = ERR_FILE_NOT_FOUND;
1026 	    }
1027 	    return 0;
1028 	}
1029 #endif
1030 #endif
1031 
1032 	if (*dirname==':') dirname++;
1033 	for (rest = dirname; (ch = *rest) && !isspace (ch); rest++);
1034 	*rest = 0;
1035 
1036 #ifdef DEBUG_NTFS
1037 	printf("got file: search at_data\n");
1038 #endif
1039 
1040 	if (!search_attribute(cmft, at_data, dirname)) {
1041 	    errnum = *(dirname-1)==':'?ERR_FILE_NOT_FOUND:ERR_BAD_FILETYPE;
1042 	    *rest = ch;
1043 	    return 0;
1044 	}
1045 	*rest = ch;
1046 
1047 	filemax = cmft->attr_size;
1048 #ifdef DEBUG_NTFS
1049 	printf("filemax=%x\n", filemax);
1050 #endif
1051 	return 1;
1052     }
1053 
1054     if(depth >= (MAX_DIR_DEPTH-1)) {
1055 	errnum = ERR_FSYS_CORRUPT;
1056 	return 0;
1057     }
1058 
1059     /* continue with the file/directory name interpretation */
1060 
1061     while (*dirname == '/')
1062 	dirname++;
1063 
1064     for (rest = dirname; (ch = *rest) && !isspace (ch) && ch != '/' && ch != ':'; rest++);
1065 
1066     *rest = 0;
1067 
1068     if (!search_attribute(cmft, at_index_root, "$I30"))
1069     {
1070 	errnum = ERR_BAD_FILETYPE;
1071 	return 0;
1072     }
1073 
1074     read_attribute(cmft, 0, fnbuf, 16, 0);
1075     my_index_record_size = *(__u32 *)(fnbuf+8);
1076 
1077     if(my_index_record_size > MAX_INDEX_RECORD_SIZE) {
1078 	errnum = ERR_FSYS_CORRUPT;
1079 	return 0;
1080     }
1081 
1082 #ifdef DEBUG_NTFS
1083     printf("index_record_size=%x\n", my_index_record_size);
1084 #endif
1085 
1086     if(cmft->attr_size > MAX_INDEX_RECORD_SIZE) {
1087 	errnum = ERR_FSYS_CORRUPT;
1088 	return 0;
1089     }
1090     read_attribute(cmft, 0, index_data, cmft->attr_size, 0);
1091     index_end = index_data + cmft->attr_size;
1092     index_entry = index_data + 0x20;
1093     record_offset = -1;
1094 
1095 #ifndef STAGE1_5
1096     if (print_possibilities && ch != '/' && ch != ':' && !*dirname)
1097     {
1098 	print_possibilities = -print_possibilities;
1099 	/* fake '.' for empty directory */
1100 	print_a_completion (".");
1101     }
1102 #endif
1103 
1104     if (search_attribute(cmft, at_bitmap, "$I30")) {
1105 	if(cmft->attr_size > MAX_INDEX_BITMAP_SIZE) {
1106 	    errnum = ERR_FSYS_CORRUPT;
1107 	    return 0;
1108 	}
1109 
1110 	read_attribute(cmft, 0, bitmap_data, cmft->attr_size, 0);
1111 
1112 	if (search_attribute(cmft, at_index_allocation, "$I30")==0) {
1113 	    errnum = ERR_FSYS_CORRUPT;
1114 	    return 0;
1115 	}
1116 
1117 	for(record_offset = 0; record_offset*my_index_record_size<cmft->attr_size; record_offset++){
1118 	    int bit = 1 << (record_offset&3);
1119 	    int byte = record_offset>>3;
1120 #ifdef DEBUG_NTFS
1121 	    printf("record_offset=%x\n", record_offset);
1122 #endif
1123 	    if((bitmap_data[byte]&bit))
1124 		break;
1125 	}
1126 
1127 	if(record_offset*my_index_record_size>=cmft->attr_size) record_offset = -1;
1128     }
1129 
1130     do
1131     {
1132 	entry = index_entry; index_entry += *(__u16 *)(entry+8);
1133 	if(entry+0x50>=index_entry||entry>=index_end||
1134 	   index_entry>=index_end||(entry[0x12]&2)){
1135 	    if(record_offset < 0 ||
1136 	       !read_attribute(cmft, record_offset*my_index_record_size, index_data, my_index_record_size, 0)){
1137 		if (!errnum)
1138 		{
1139 		    if (print_possibilities < 0)
1140 		    {
1141 #if 0
1142 			putchar ('\n');
1143 #endif
1144 			return 1;
1145 		    }
1146 
1147 		    errnum = ERR_FILE_NOT_FOUND;
1148 		    *rest = ch;
1149 		}
1150 
1151 		return 0;
1152 	    }
1153 	    if(!fixup_record( index_data, "INDX", my_index_record_size))
1154 	    {
1155 #ifdef DEBUG_NTFS
1156 		printf("index error\n");
1157 #endif
1158 		errnum = ERR_FSYS_CORRUPT;
1159 		return 0;
1160 	    }
1161 	    entry = index_data + 0x18 + *(__u16 *)(index_data+0x18);
1162 	    index_entry = entry + *(__u16 *)(entry+8);
1163 	    index_end = index_data + my_index_record_size - 0x52;
1164 	    for(record_offset++; record_offset*my_index_record_size<cmft->attr_size; record_offset++){
1165 		int bit = 1 << (record_offset&3);
1166 		int byte = record_offset>>3;
1167 		if((bitmap_data[byte]&bit)) break;
1168 	    }
1169 	    if(record_offset*my_index_record_size>=cmft->attr_size) record_offset = -1;
1170 #ifdef DEBUG_NTFS
1171 	    printf("record_offset=%x\n", record_offset);
1172 #endif
1173 	}
1174 	flag = entry[0x51];
1175 	path_ino[depth+1] = *(__u32 *)entry;
1176 	if(path_ino[depth+1] < 16)
1177 	    continue;
1178 	namelen = entry[0x50];
1179 	//if(index_data[0x48]&2) printf("hidden file\n");
1180 #ifndef STAGE1_5
1181 	/* skip short file name */
1182 	if( flag == 2 && print_possibilities && ch != '/' && ch != ':' )
1183 	    continue;
1184 #endif
1185 
1186 	for( i = 0, entry+=0x52; i < namelen; i++, entry+=2 )
1187 	{
1188 	    int c = *(__u16 *)entry;
1189 	    if(c==' '||c>=0x100)
1190 		fnbuf[i] = '_';
1191 	    else
1192 		fnbuf[i] = c;
1193 	}
1194 	fnbuf[namelen] = 0;
1195 #ifdef DEBUG_NTFS
1196 	printf("FLAG: %d  NAME: %s  inum=%d\n", flag,fnbuf,path_ino[depth+1]);
1197 #endif
1198 
1199 	//uncntrl(fnbuf);
1200 
1201 	chk_sfn = nsubstring(dirname,fnbuf);
1202 #ifndef STAGE1_5
1203 	if (print_possibilities && ch != '/' && ch != ':'
1204 	    && (!*dirname || chk_sfn <= 0))
1205 	{
1206 	    if (print_possibilities > 0)
1207 		print_possibilities = -print_possibilities;
1208 	    print_a_completion (fnbuf);
1209 	}
1210 #endif /* STAGE1_5 */
1211     }
1212     while (chk_sfn != 0 ||
1213 	   (print_possibilities && ch != '/' && ch != ':'));
1214 
1215     *(dirname = rest) = ch;
1216 
1217     depth++;
1218 
1219     /* go back to main loop at top of function */
1220     goto loop;
1221 }
1222 
1223 #ifdef DEBUG_NTFS
dump_block(char * msg,char * buf,int size)1224 int dump_block(char *msg, char *buf, int size){
1225     int l = (size+15)/16;
1226     int off;
1227     int i, j;
1228     int c;
1229     printf("----- %s -----\n", msg);
1230     for( i = 0, off = 0; i < l; i++, off+=16)
1231     {
1232 	if(off<16)
1233 	    printf("000%x:", off);
1234 	else if(off<256)
1235 	    printf("00%x:", off);
1236 	else
1237 	    printf("0%x:", off);
1238 	for(j=0;j<16;j++)
1239 	{
1240 	    c = buf[off+j]&0xff;
1241 	    if( c >= 16 )
1242 		printf("%c%x",j==8?'-':' ',c);
1243 	    else
1244 		printf("%c0%x",j==8?'-':' ',c);
1245 	}
1246 	printf("  ");
1247 	for(j=0;j<16;j++) {
1248 	    char c = buf[off+j];
1249 	    printf("%c",c<' '||c>='\x7f'?'.':c);
1250 	}
1251 	printf("\n");
1252     }
1253 }
1254 #endif
1255 #endif /* FSYS_NTFS */
1256