Annotation of qemu/roms/openbios/fs/grubfs/fsys_ntfs.c, revision 1.1

1.1     ! root        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
        !           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: 
        !           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: 
        !           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: 
        !           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
        !           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: 
        !           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
        !           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: 
        !           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: 
        !           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: 
        !           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: 
        !           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: 
        !           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
        !           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: 
        !           621: static inline int compressed_block_size( unsigned char *src ) {
        !           622:     return 3 + (*(__u16 *)src & 0xfff);
        !           623: }
        !           624: 
        !           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: 
        !           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: 
        !           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
        !           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
        !          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 */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.