static char *loadstring(FILE *f) { ULONG l; char buf[4], *p=buf; if(1!=fread(buf, 4, 1, f) || (l=getu32(&p))>SANITYMAXLEN || !(p=malloc(l))) return NULL; fread(p, 1, l, f); return p; }
static struct Image *loadimage(FILE *f) { char buf[20], *p=buf; WORD le, te, w, h, d; int imgsz; struct Image *im; if(1!=fread(buf, 20, 1, f)) return NULL; le=get16(&p); te=get16(&p); w=get16(&p); h=get16(&p); d=get16(&p); if(w<=0 || w>MAXICONSIZE || h<=0 || h>MAXICONSIZE || d<1 || d>8) return NULL; imgsz=2*((w+15)>>4)*h*d; if(!(im=malloc(imgsz+sizeof(struct Image)))) return NULL; im->LeftEdge=le; im->TopEdge=te; im->Width=w; im->Height=h; im->Depth=d; im->ImageData=(UWORD*)getu32(&p); im->PlanePick=*p++; im->PlaneOnOff=*p++; im->NextImage=(struct Image *)getu32(&p); if(im->ImageData) { im->ImageData=(UWORD *)(im+1); fread(im->ImageData, 1, imgsz, f); } return im; }
static void decode_glowicon(struct DiskObject *diskobj, char *glow, LONG len) { int imgno=0, gotface=0; struct { char width, height; UWORD dunno1, dunno2; } face; while(len>=8) { ULONG id = getu32(&glow); LONG clen = get32(&glow); char *chunk = glow; len -= 8; if(clen<0) clen = len; if(clen>len) break; switch(id) { case 0x46414345: /* FACE */ if(clen>=6) { face.width = 1+*chunk++; face.height = 1+*chunk++; face.dunno1 = getu16(&chunk); face.dunno2 = getu16(&chunk); gotface = 1; diskobj->do_Gadget.Width = face.width; diskobj->do_Gadget.Height = face.height; break; } break; case 0x494d4147: /* IMAG */ if(!gotface || imgno>1) break; decode_IMAG((unsigned char *)chunk, clen, face.width, face.height, (imgno++? &diskobj->do_Gadget.SelectRender : &diskobj->do_Gadget.GadgetRender)); break; } if(clen&1) clen++; len -= clen; glow += clen; } }
static struct DiskObject *int_load_do(char *filename) { FILE *f; struct DiskObject *diskobj; char buf[78], *p=buf; int error=0; if((f=fopen(filename, "r"))) { if(1==fread(buf, 78, 1, f) && (diskobj=calloc(1, sizeof(struct DiskObject)))) { diskobj->do_Magic=getu16(&p); diskobj->do_Version=getu16(&p); if(diskobj->do_Magic!=WB_DISKMAGIC) { free(diskobj); return NULL; } diskobj->do_Gadget.NextGadget=(struct Gadget *)getu32(&p); diskobj->do_Gadget.LeftEdge=get16(&p); diskobj->do_Gadget.TopEdge=get16(&p); diskobj->do_Gadget.Width=get16(&p); diskobj->do_Gadget.Height=get16(&p); diskobj->do_Gadget.Flags=getu16(&p); diskobj->do_Gadget.Activation=getu16(&p); diskobj->do_Gadget.GadgetType=getu16(&p); diskobj->do_Gadget.GadgetRender=(APTR)getu32(&p); diskobj->do_Gadget.SelectRender=(APTR)getu32(&p); diskobj->do_Gadget.GadgetText=(struct IntuiText *)getu32(&p); diskobj->do_Gadget.MutualExclude=get32(&p); diskobj->do_Gadget.SpecialInfo=(APTR)getu32(&p); diskobj->do_Gadget.GadgetID=getu16(&p); diskobj->do_Gadget.UserData=(APTR)getu32(&p); diskobj->do_Type=*p; p+=2; diskobj->do_DefaultTool=(char *)getu32(&p); diskobj->do_ToolTypes=(char **)getu32(&p); diskobj->do_CurrentX=get32(&p); diskobj->do_CurrentY=get32(&p); diskobj->do_DrawerData=(struct DrawerData *)getu32(&p); diskobj->do_ToolWindow=(char *)getu32(&p); diskobj->do_StackSize=get32(&p); if(diskobj->do_DrawerData) { struct DrawerData *dd; if(1==fread(buf, 56, 1, f) && (diskobj->do_DrawerData=dd=calloc(1, sizeof(struct DrawerData)))) { p=buf; dd->dd_NewWindow.LeftEdge=get16(&p); dd->dd_NewWindow.TopEdge=get16(&p); dd->dd_NewWindow.Width=get16(&p); dd->dd_NewWindow.Height=get16(&p); dd->dd_NewWindow.DetailPen=*p++; dd->dd_NewWindow.BlockPen=*p++; dd->dd_NewWindow.IDCMPFlags=getu32(&p); dd->dd_NewWindow.Flags=getu32(&p); dd->dd_NewWindow.FirstGadget=(struct Gadget *)getu32(&p); dd->dd_NewWindow.CheckMark=(struct Image *)getu32(&p); dd->dd_NewWindow.Title=(UBYTE *)getu32(&p); dd->dd_NewWindow.Screen=(struct Screen *)getu32(&p); dd->dd_NewWindow.BitMap=(struct BitMap *)getu32(&p); dd->dd_NewWindow.MinWidth=get16(&p); dd->dd_NewWindow.MinHeight=get16(&p); dd->dd_NewWindow.MaxWidth=getu16(&p); dd->dd_NewWindow.MaxHeight=getu16(&p); dd->dd_NewWindow.Type=getu16(&p); dd->dd_CurrentX=get32(&p); dd->dd_CurrentY=get32(&p); } else error++; } if(!(diskobj->do_Gadget.GadgetRender=loadimage(f))) error++; if(diskobj->do_Gadget.Flags&2) if(!(diskobj->do_Gadget.SelectRender=loadimage(f))) error++; else ; else if(diskobj->do_Gadget.Flags&1) if(!(diskobj->do_Gadget.SelectRender= backfillimage((struct Image *)diskobj->do_Gadget.GadgetRender))) error++; else ; else diskobj->do_Gadget.SelectRender=NULL; if(diskobj->do_DefaultTool) if(!(diskobj->do_DefaultTool=loadstring(f))) error++; if(diskobj->do_ToolTypes) if(!(diskobj->do_ToolTypes=loadtooltypes(f))) error++; if(diskobj->do_ToolWindow) if(!(diskobj->do_ToolWindow=loadstring(f))) error++; if(diskobj->do_DrawerData && diskobj->do_Version) { char buf[6], *p=buf; if(1==fread(buf, 6, 1, f)) { diskobj->do_DrawerData->dd_Flags=getu32(&p); diskobj->do_DrawerData->dd_ViewModes=getu16(&p); } } if(diskobj->do_Version) { /* Check for GlowIcon */ char buf[8], *p = buf, *glowicon; LONG len; if(1==fread(buf, 4, 1, f) && !strncmp(buf, "FORM", 4) && 1==fread(buf, 8, 1, f) && !strncmp(buf+4, "ICON", 4) && (len = get32(&p))>4 && (glowicon = malloc(len))!=NULL) { if(1==fread(glowicon, len-4, 1, f)) decode_glowicon(diskobj, glowicon, len-4); free(glowicon); } } if(!error) { fclose(f); return diskobj; } FreeDiskObject(diskobj); } fclose(f); } return NULL; }
uint pzip_Encode( u08* input_buf, uint input_len, u08* encode_buf ) { /* This is the top-level compression function. */ /* input_buf: Contents of file to be compressed. */ /* encode_buf: Where to leave the result. */ /* return val: Compressed length -- count of valid bytes in encode_buf. */ int num_chose_loe[ PZIP_ORDER +1 ]; int num_tried_by_order[ PZIP_ORDER +1 ]; int num_coded_by_order[ PZIP_ORDER +1 ]; int num_coded_det = 0; clock_t began_at = clock(); Pzip* pzip = pzip_create(); Arith* arith = pzip->arith; u08* input_ptr = input_buf; u08* input_buf_end = input_buf + input_len; assert( PZIP_SEED_BYTES > 0 ); /* Seed a preamble: */ memcpy( encode_buf, input_ptr, PZIP_SEED_BYTES ); memset( input_ptr - PZIP_MAX_CONTEXT_LEN, PZIP_SEED_BYTE, PZIP_MAX_CONTEXT_LEN ); input_ptr += PZIP_SEED_BYTES; arith_Start_Encoding( arith, encode_buf + PZIP_SEED_BYTES ); memset( num_chose_loe, 0, (PZIP_ORDER +1) * sizeof(int) ); memset( num_tried_by_order, 0, (PZIP_ORDER +1) * sizeof(int) ); memset( num_coded_by_order, 0, (PZIP_ORDER +1) * sizeof(int) ); while (input_ptr < input_buf_end) { int symbol = *input_ptr; /* Current symbol to encode. */ u32 key = getu32( input_ptr -4 ); /* Last four chars seen on input stream. */ trie_Fill_Active_Contexts( input_ptr ); /* Must come before det_Enc(), cuz that uses the top Context node */ excluded_symbols_Clear( pzip->excluded_symbols ); if (deterministic_Encode( pzip->det, arith, input_ptr, input_buf, symbol, pzip->excluded_symbols, active_contexts.c[ PZIP_ORDER ] )) { ++ num_coded_det; } else { /* Try selected contexts until one encodes 'symbol': */ int order = PZIP_ORDER+1; for(order = choose_context( active_contexts.c, order, key, pzip->excluded_symbols, pzip->see ), ++ num_chose_loe[ order ]; ; order = choose_context( active_contexts.c, order, key, pzip->excluded_symbols, pzip->see ) ){ ++ num_tried_by_order[ order ]; /* Try to code symbol using selected order model: */ if (context_Encode( active_contexts.c[order], arith, pzip->excluded_symbols, pzip->see, key, symbol )) { ++ num_coded_by_order[ order ]; break; } if (order == 0) { /* Encode raw with order -1: */ order_minus_one_Encode( symbol, 256, arith, pzip->excluded_symbols ); break; } } /* Did encode, now update the stats: */ { int coded_order = max( order, 0 ); for (order = 0; order <= PZIP_ORDER; order++) { context_Update( active_contexts.c[order], symbol, key, pzip->see, coded_order ); } } } deterministic_Update( pzip->det, input_ptr, symbol, active_contexts.c[ PZIP_ORDER ] ); ++ input_ptr; /* Maybe assure user we haven't crashed: */ if (verbose && (input_ptr - input_buf) % PZIP_PRINTF_INTERVAL == 0) { fprintf(stderr, "%d/%d\r", (input_ptr - input_buf), input_len ); fflush( stderr ); } } if (verbose) { clock_t clocks = clock() - began_at; /* Do NOT combine */ double secs = (double)clocks / (double)CLOCKS_PER_SEC; /* these two lines! */ fprintf(stderr, "%d/%d\n", input_len, input_len ); fprintf(stderr,"%s : %f secs = %2.1f %ss/sec\n", "encode", secs, (double)input_len / secs, "byte" ); } { uint encode_len = (arith_Finish_Encoding( arith ) - (encode_buf + PZIP_SEED_BYTES)) + PZIP_SEED_BYTES; #ifdef OLD pzip_destroy( pzip ); #endif /* The arithc has stuffed 1 byte; put it back: */ encode_buf[ PZIP_SEED_BYTES-1 ] = input_buf[ PZIP_SEED_BYTES-1 ]; if (verbose) { printf( "o : %7s : %7s : %7s\n", "loe", "tried", "coded" ); printf("d : %7d : %7d : %7d\n", input_len, input_len, num_coded_det ); { int i; for (i = PZIP_ORDER+1; i --> 0; ) { printf( "%d : %7d : %7d : %7d\n", i, num_chose_loe[i], num_tried_by_order[i], num_coded_by_order[i] ); } } } return encode_len; } }
void pzip_Decode( u08* output_buf, uint output_len, u08* encode_buf ) { clock_t began_at = clock(); Pzip* pzip = pzip_create(); Arith* arith = pzip->arith; u08* output_ptr = output_buf; u08* output_buf_end = output_buf + output_len; memcpy( output_ptr, encode_buf, PZIP_SEED_BYTES ); memset( output_ptr - PZIP_MAX_CONTEXT_LEN, PZIP_SEED_BYTE, PZIP_MAX_CONTEXT_LEN ); output_ptr += PZIP_SEED_BYTES; encode_buf += PZIP_SEED_BYTES; arith_Start_Decoding( arith, encode_buf ); while (output_ptr < output_buf_end) { int symbol; u32 key = getu32( output_ptr - 4 );; trie_Fill_Active_Contexts( output_ptr ); excluded_symbols_Clear( pzip->excluded_symbols ); if (!deterministic_Decode( pzip->det, arith, output_ptr, output_buf, &symbol, pzip->excluded_symbols, active_contexts.c[PZIP_ORDER] )) { /* Go down the orders: */ int order = PZIP_ORDER+1; for(order = choose_context( active_contexts.c, order, key, pzip->excluded_symbols, pzip->see ); ; order = choose_context( active_contexts.c, order, key, pzip->excluded_symbols, pzip->see ) ){ /* Try to coder from order: */ if (context_Decode( active_contexts.c[order], arith, pzip->excluded_symbols, pzip->see, key, &symbol )) { break; } if (order == 0) { /* Decode raw with order -1: */ symbol = order_minus_one_Decode( 256, arith, pzip->excluded_symbols ); break; } } /* Did decode, now update the stats: */ { int coded_order = max( order, 0 ); for (order = 0; order <= PZIP_ORDER; ++order) { context_Update( active_contexts.c[order], symbol, key, pzip->see, coded_order ); } } } deterministic_Update( pzip->det, output_ptr, symbol, active_contexts.c[ PZIP_ORDER ] ); *output_ptr++ = symbol; /* Maybe assure user we haven't crashed: */ if (verbose && (output_ptr - output_buf) % PZIP_PRINTF_INTERVAL == 0) { fprintf(stderr, "%d/%d\r", (output_ptr - output_buf), output_len ); fflush( stderr ); } } if (verbose) { clock_t clocks = clock() - began_at; /* Do NOT combine */ double secs = (double)clocks / (double)CLOCKS_PER_SEC; /* these two lines! */ fprintf(stderr, "%d/%d\n", output_len, output_len ); fprintf(stderr,"%s : %f secs = %2.1f %ss/sec\n", "decode", secs, (double)output_len / secs, "byte" ); } pzip_destroy( pzip ); }
/* return 1 on error and 0 on success */ static uint8_t ext2fs_dent_copy(EXT2FS_INFO * ext2fs, EXT2FS_DINFO * dinfo, char *ext2_dent, FS_DENT * fs_dent) { FS_INFO *fs = &(ext2fs->fs_info); if (ext2fs->deentry_type == EXT2_DE_V1) { ext2fs_dentry1 *dir = (ext2fs_dentry1 *) ext2_dent; fs_dent->inode = getu32(fs, dir->inode); /* ext2 does not null terminate */ if (getu16(fs, dir->name_len) >= fs_dent->name_max) { tsk_errno = TSK_ERR_FS_ARG; snprintf(tsk_errstr, TSK_ERRSTR_L, "ext2fs_dent_copy: Name Space too Small %d %lu", getu16(fs, dir->name_len), fs_dent->name_max); tsk_errstr2[0] = '\0'; return 1; } /* Copy and Null Terminate */ strncpy(fs_dent->name, dir->name, getu16(fs, dir->name_len)); fs_dent->name[getu16(fs, dir->name_len)] = '\0'; fs_dent->ent_type = FS_DENT_UNDEF; } else { ext2fs_dentry2 *dir = (ext2fs_dentry2 *) ext2_dent; fs_dent->inode = getu32(fs, dir->inode); /* ext2 does not null terminate */ if (dir->name_len >= fs_dent->name_max) { tsk_errno = TSK_ERR_FS_ARG; snprintf(tsk_errstr, TSK_ERRSTR_L, "ext2_dent_copy: Name Space too Small %d %lu", dir->name_len, fs_dent->name_max); tsk_errstr2[0] = '\0'; return 1; } /* Copy and Null Terminate */ strncpy(fs_dent->name, dir->name, dir->name_len); fs_dent->name[dir->name_len] = '\0'; switch (dir->type) { case EXT2_DE_REG_FILE: fs_dent->ent_type = FS_DENT_REG; break; case EXT2_DE_DIR: fs_dent->ent_type = FS_DENT_DIR; break; case EXT2_DE_CHRDEV: fs_dent->ent_type = FS_DENT_CHR; break; case EXT2_DE_BLKDEV: fs_dent->ent_type = FS_DENT_BLK; break; case EXT2_DE_FIFO: fs_dent->ent_type = FS_DENT_FIFO; break; case EXT2_DE_SOCK: fs_dent->ent_type = FS_DENT_SOCK; break; case EXT2_DE_SYMLINK: fs_dent->ent_type = FS_DENT_LNK; break; case EXT2_DE_UNKNOWN: default: fs_dent->ent_type = FS_DENT_UNDEF; break; } } fs_dent->path = dinfo->dirs; fs_dent->pathdepth = dinfo->depth; if ((fs != NULL) && (fs_dent->inode) && (fs_dent->inode <= fs->last_inum)) { /* Get inode */ if (fs_dent->fsi) fs_inode_free(fs_dent->fsi); if ((fs_dent->fsi = fs->inode_lookup(fs, fs_dent->inode)) == NULL) { strncat(tsk_errstr2, " - ext2fs_dent_copy", TSK_ERRSTR_L - strlen(tsk_errstr2)); return 1; } } else { if (fs_dent->fsi) fs_inode_free(fs_dent->fsi); fs_dent->fsi = NULL; } return 0; }
/* ** ** Read contents of directory block ** ** if entry is active call action with myflags set to FS_FLAG_NAME_ALLOC, if ** it is deleted then call action with FS_FLAG_NAME_UNALLOC. ** len is the size of buf ** ** return 1 to stop, 0 on success, and -1 on error */ static int ext2fs_dent_parse_block(EXT2FS_INFO * ext2fs, EXT2FS_DINFO * dinfo, char *buf, int len, int flags, FS_DENT_WALK_FN action, void *ptr) { FS_INFO *fs = &(ext2fs->fs_info); int dellen = 0; int idx; uint16_t reclen; uint32_t inode; char *dirPtr; FS_DENT *fs_dent; int minreclen = 4; if ((fs_dent = fs_dent_alloc(EXT2FS_MAXNAMLEN + 1, 0)) == NULL) return -1; /* update each time by the actual length instead of the ** recorded length so we can view the deleted entries */ for (idx = 0; idx <= len - EXT2FS_DIRSIZ_lcl(1); idx += minreclen) { unsigned int namelen; int myflags = 0; dirPtr = &buf[idx]; if (ext2fs->deentry_type == EXT2_DE_V1) { ext2fs_dentry1 *dir = (ext2fs_dentry1 *) dirPtr; inode = getu32(fs, dir->inode); namelen = getu16(fs, dir->name_len); reclen = getu16(fs, dir->rec_len); } else { ext2fs_dentry2 *dir = (ext2fs_dentry2 *) dirPtr; inode = getu32(fs, dir->inode); namelen = dir->name_len; reclen = getu16(fs, dir->rec_len); } minreclen = EXT2FS_DIRSIZ_lcl(namelen); /* ** Check if we may have a valid directory entry. If we don't, ** then increment to the next word and try again. */ if ((inode > fs->last_inum) || (inode < 0) || (namelen > EXT2FS_MAXNAMLEN) || (namelen <= 0) || (reclen < minreclen) || (reclen % 4) || (idx + reclen > len)) { minreclen = 4; if (dellen > 0) dellen -= 4; continue; } /* Before we process an entry in unallocated space, make * sure that it also ends in the unalloc space */ if ((dellen) && (dellen < minreclen)) { minreclen = 4; if (dellen > 0) dellen -= 4; continue; } if (ext2fs_dent_copy(ext2fs, dinfo, dirPtr, fs_dent)) { fs_dent_free(fs_dent); return -1; } myflags = 0; /* Do we have a deleted entry? */ if ((dellen > 0) || (inode == 0)) { myflags |= FS_FLAG_NAME_UNALLOC; if (dellen > 0) dellen -= minreclen; if (flags & FS_FLAG_NAME_UNALLOC) { int retval; retval = action(fs, fs_dent, myflags, ptr); if (retval == WALK_STOP) { fs_dent_free(fs_dent); return 1; } else if (retval == WALK_ERROR) { fs_dent_free(fs_dent); return -1; } } } /* We have a non-deleted entry */ else { myflags |= FS_FLAG_NAME_ALLOC; if (flags & FS_FLAG_NAME_ALLOC) { int retval; retval = action(fs, fs_dent, myflags, ptr); if (retval == WALK_STOP) { fs_dent_free(fs_dent); return 1; } else if (retval == WALK_ERROR) { fs_dent_free(fs_dent); return -1; } } } /* If the actual length is shorter then the ** recorded length, then the next entry(ies) have been ** deleted. Set dellen to the length of data that ** has been deleted ** ** Because we aren't guaranteed with Ext2FS that the next ** entry begins right after this one, we will check to ** see if the difference is less than a possible entry ** before we waste time searching it */ if ((reclen - minreclen >= EXT2FS_DIRSIZ_lcl(1)) && (dellen <= 0)) dellen = reclen - minreclen; /* we will be recursing directories */ if ((myflags & FS_FLAG_NAME_ALLOC) && (flags & FS_FLAG_NAME_RECURSE) && (!ISDOT(fs_dent->name)) && ((fs_dent->fsi->mode & FS_INODE_FMT) == FS_INODE_DIR)) { if (dinfo->depth < MAX_DEPTH) { dinfo->didx[dinfo->depth] = &dinfo->dirs[strlen(dinfo->dirs)]; strncpy(dinfo->didx[dinfo->depth], fs_dent->name, DIR_STRSZ - strlen(dinfo->dirs)); strncat(dinfo->dirs, "/", DIR_STRSZ); } dinfo->depth++; if (ext2fs_dent_walk_lcl(&(ext2fs->fs_info), dinfo, fs_dent->inode, flags, action, ptr)) { /* If this fails because the directory could not be * loaded, then we still continue */ if (verbose) { fprintf(stderr, "ffs_dent_parse_block: error reading directory: %" PRIuINUM "\n", fs_dent->inode); tsk_error_print(stderr); } tsk_errno = 0; tsk_errstr[0] = '\0'; tsk_errstr2[0] = '\0'; } dinfo->depth--; if (dinfo->depth < MAX_DEPTH) *dinfo->didx[dinfo->depth] = '\0'; } } fs_dent_free(fs_dent); return 0; } /* end ext2fs_dent_parse_block() */
/* * Load the primary partition table (MBR) into the internal * data structures in MM_INFO * * This will automatically call load_ext_table for extended * partitions * * sect_cur is the addres of the table to load * * 0 is returned if the load is successful and 1 if error */ static uint8_t dos_load_prim_table(MM_INFO * mm, uint8_t test) { dos_sect sect; int i; char *table_str; SSIZE_T cnt; DADDR_T taddr = mm->offset / mm->block_size + DOS_PART_SOFFSET; DADDR_T max_addr = (mm->img_info->size - mm->offset) / mm->block_size; // max sector if (verbose) fprintf(stderr, "dos_load_prim: Table Sector: %" PRIuDADDR "\n", taddr); /* Read the table */ cnt = mm_read_block_nobuf (mm, (char *) §, sizeof(sect), DOS_PART_SOFFSET); if (cnt != sizeof(sect)) { snprintf(tsk_errstr2, TSK_ERRSTR_L, "Primary DOS table sector %" PRIuDADDR, taddr); if (cnt != -1) { tsk_errno = TSK_ERR_MM_READ; tsk_errstr[0] = '\0'; } return 1; } /* Sanity Check */ if (mm_guessu16(mm, sect.magic, DOS_MAGIC)) { tsk_errno = TSK_ERR_MM_MAGIC; snprintf(tsk_errstr, TSK_ERRSTR_L, "File is not a DOS partition (invalid primary magic) (Sector: %" PRIuDADDR ")", taddr); tsk_errstr2[0] = '\0'; return 1; } /* Because FAT and NTFS use the same magic - check for a * standard MS OEM name and sizes. Not a great check, but we can't * really test the table entries. */ if (test) { if (verbose) fprintf(stderr, "dos_load_prim_table: Testing FAT/NTFS conditions\n"); if (strncmp("MSDOS", sect.oemname, 5) == 0) { tsk_errno = TSK_ERR_MM_MAGIC; snprintf(tsk_errstr, TSK_ERRSTR_L, "dos_load_prim_table: MSDOS OEM name exists"); tsk_errstr2[0] = '\0'; return 1; } else if (strncmp("MSWIN", sect.oemname, 5) == 0) { tsk_errno = TSK_ERR_MM_MAGIC; snprintf(tsk_errstr, TSK_ERRSTR_L, "dos_load_prim_table: MSWIN OEM name exists"); tsk_errstr2[0] = '\0'; return 1; } else if (strncmp("NTFS", sect.oemname, 4) == 0) { tsk_errno = TSK_ERR_MM_MAGIC; snprintf(tsk_errstr, TSK_ERRSTR_L, "dos_load_prim_table: NTFS OEM name exists"); tsk_errstr2[0] = '\0'; return 1; } } /* Add an entry of 1 sector for the table to the internal structure */ if ((table_str = mymalloc(32)) == NULL) return 1; snprintf(table_str, 32, "Primary Table (#0)"); if (NULL == mm_part_add(mm, DOS_PART_SOFFSET, (DADDR_T) 1, MM_TYPE_DESC, table_str, -1, -1)) return 1; /* Cycle through the partition table */ for (i = 0; i < 4; i++) { dos_part *part = §.ptable[i]; /* We currently ignore CHS */ uint32_t part_start = getu32(mm, part->start_sec); uint32_t part_size = getu32(mm, part->size_sec); if (verbose) fprintf(stderr, "load_pri:0:%d Start: %" PRIu32 " Size: %" PRIu32 " Type: %d\n", i, part_start, part_size, part->ptype); if (part_size == 0) continue; if (part_start > max_addr) { tsk_errno = TSK_ERR_MM_BLK_NUM; snprintf(tsk_errstr, TSK_ERRSTR_L, "dos_load_prim_table: Starting sector too large for image"); tsk_errstr2[0] = '\0'; return 1; } #if 0 // I'm not sure if this is too strict ... else if ((part_start + part_size) > max_addr) { tsk_errno = TSK_ERR_MM_BLK_NUM snprintf(tsk_errstr, TSK_ERRSTR_L, "dos_load_prim_table: Partition ends after image"); tsk_errstr2[0] = '\0'; return 1; } #endif /* Add the partition to the internal structure * If it is an extended partition, process it now */ if (dos_is_ext(part->ptype)) { if (NULL == mm_part_add(mm, (DADDR_T) part_start, (DADDR_T) part_size, MM_TYPE_DESC, dos_get_desc(part->ptype), 0, i)) return 1; if (dos_load_ext_table(mm, part_start, part_start, 1)) return 1; } else { if (NULL == mm_part_add(mm, (DADDR_T) part_start, (DADDR_T) part_size, MM_TYPE_VOL, dos_get_desc(part->ptype), 0, i)) return 1; } } return 0; }
/* * Load an extended partition table into the structure in MM_INFO. * * sect_cur: The sector where the extended table is located * sect_ext_base: The sector of the primary extended table (this does * not change for recursive calls) * table: a counter that identifies the table depth * (increases by 1 for each recursive call) * * For the primary extended table, sect_cur == sect_ext_base * * Return 1 on error and 0 on success * */ static uint8_t dos_load_ext_table(MM_INFO * mm, DADDR_T sect_cur, DADDR_T sect_ext_base, int table) { dos_sect sect; int i; char *table_str; SSIZE_T cnt; DADDR_T max_addr = (mm->img_info->size - mm->offset) / mm->block_size; // max sector if (verbose) fprintf(stderr, "dos_load_ext: Table Sector: %" PRIuDADDR ", Primary Base Sector: %" PRIuDADDR "\n", sect_cur, sect_ext_base); /* Read the partition table sector */ cnt = mm_read_block_nobuf (mm, (char *) §, sizeof(sect), (DADDR_T) sect_cur); if (cnt != sizeof(sect)) { snprintf(tsk_errstr2, TSK_ERRSTR_L, "Extended DOS table sector %" PRIuDADDR, sect_cur); if (cnt != -1) { tsk_errno = TSK_ERR_MM_READ; tsk_errstr[0] = '\0'; } return 1; } /* Sanity Check */ if (getu16(mm, sect.magic) != DOS_MAGIC) { tsk_errno = TSK_ERR_MM_MAGIC; snprintf(tsk_errstr, TSK_ERRSTR_L, "Extended DOS partition table in sector %" PRIuDADDR, sect_cur); tsk_errstr2[0] = '\0'; return 1; } /* Add an entry of 1 length for the table to the internal structure */ if ((table_str = mymalloc(32)) == NULL) return 1; snprintf(table_str, 32, "Extended Table (#%d)", table); if (NULL == mm_part_add(mm, (DADDR_T) sect_cur, (DADDR_T) 1, MM_TYPE_DESC, table_str, table, -1)) { return 1; } /* Cycle through the four partitions in the table * * When another extended partition is found, it is processed * inside of the loop */ for (i = 0; i < 4; i++) { dos_part *part = §.ptable[i]; /* Get the starting sector and size, we currently * ignore CHS */ uint32_t part_start = getu32(mm, part->start_sec); uint32_t part_size = getu32(mm, part->size_sec); if (verbose) fprintf(stderr, "load_ext: %d:%d Start: %" PRIu32 " Size: %" PRIu32 " Type: %d\n", table, i, part_start, part_size, part->ptype); if (part_size == 0) continue; /* partitions are addressed differently * in extended partitions */ if (dos_is_ext(part->ptype)) { /* part start is added to the start of the * first extended partition (the primary * extended partition) */ if (sect_ext_base + part_start > max_addr) { tsk_errno = TSK_ERR_MM_BLK_NUM; snprintf(tsk_errstr, TSK_ERRSTR_L, "dos_load_ext_table: Starting sector too large for image"); tsk_errstr2[0] = '\0'; return 1; } if (NULL == mm_part_add(mm, (DADDR_T) (sect_ext_base + part_start), (DADDR_T) part_size, MM_TYPE_DESC, dos_get_desc(part->ptype), table, i)) return 1; /* Process the extended partition */ if (dos_load_ext_table(mm, sect_ext_base + part_start, sect_ext_base, table + 1)) return 1; } else { /* part_start is added to the start of the * current partition for the actual * starting location */ if (sect_cur + part_start > max_addr) { tsk_errno = TSK_ERR_MM_BLK_NUM; snprintf(tsk_errstr, TSK_ERRSTR_L, "dos_load_ext_table: Starting sector too large for image"); tsk_errstr2[0] = '\0'; return 1; } if (NULL == mm_part_add(mm, (DADDR_T) (sect_cur + part_start), (DADDR_T) part_size, MM_TYPE_VOL, dos_get_desc(part->ptype), table, i)) return 1; } } return 0; }
main() { char path[20]; int fd; //super block read fatfs_sb *s1; struct Image_info i1; uint16_t ssize; uint8_t numfat; uint8_t numroot; uint64_t sectors; uint64_t lastCount; uint32_t secperfat; //cluster size uint8_t csize; uint64_t firstFactSector; uint64_t firstDataSector; uint64_t firstClusterSec; uint64_t clusterCnt; uint64_t lastCluster; uint32_t mask; uint64_t sectorRoot; uint16_t ssize_sh=9;//must be changed for different sector size uint32_t dentry_cnt_se; uint32_t dentry_cnt_cl; uint64_t inumCnt; uint64_t firstInum; uint64_t lastInum; uint64_t rootInum; uint64_t block_count; uint64_t first_block; uint64_t last_block; uint64_t last_block_act; char *dinodes;//inodes data structure int cnt; int flag_for_end; printf("Please provide the path \n"); scanf("%s",path); if((fd=open(path,O_RDONLY|O_BINARY))<0) { printf("Issue with the file open"); } //going for calculating the image lenght i1.len=lseek(fd,0,SEEK_END); lseek(fd,0,SEEK_SET); printf("%"PRId64"\n",i1.len); cnt=read(fd,(char *)s1,sizeof(* s1)); //code to get endian format check_endian_format(&flag_for_end,s1->magic,FATFS_FS_MAGIC); if(flag_for_end==0) { printf("Big endian \n"); } else { printf("Little endian \n "); } ssize=getu16(flag_for_end,s1->ssize); printf("Size of sector is %" PRIu16 "\n",ssize); csize=s1->csize; numfat=s1->numfat; numroot=getu16(flag_for_end,s1->numroot); //sectors=getu16(0,s1->sectors16); //if(sectors==0) //{ sectors=getu32(flag_for_end,s1->sectors32); lastCount=sectors-1; printf("sectors are %" PRIu64 "\n",sectors); //} //secperfat=getu16(flag_for_end,s1->sectors16); //printf("sectors per fat are %" PRIu32 "\n",secperfat); if(secperfat==0) { secperfat=getu32(flag_for_end,s1->a.f32.sectperfat32); printf("sectors per fat are %" PRIu32 "\n",secperfat); } firstFactSector=getu16(flag_for_end,s1->reserved); firstDataSector=firstFactSector+secperfat*numfat; firstClusterSec=firstDataSector+(((numroot) * 32 + ssize - 1) / ssize); printf("first cluster sector %" PRIu64 "\n",firstClusterSec); clusterCnt=(sectors-firstClusterSec)/csize; lastCluster=clusterCnt+1; if(clusterCnt > 65525) { printf("\n Setting mask for FAT 32 system"); mask=FATFS_32_MASK; } sectorRoot=getu32(flag_for_end,s1->rootclust); dinodes=(char *)malloc(sizeof(csize<<ssize_sh)); //calculating number of d entries dentry_cnt_se=ssize/sizeof(fatfs_dentry); dentry_cnt_cl=csize*dentry_cnt_se; //working with block first_block = 0; block_count = sectors; last_block = last_block_act = block_count - 1; block_size = ssize; last_block_act =i1.len/block_size - 1; //calculation of inode number root_inum = FATFS_ROOTINO; first_inum = FATFS_FIRSTINO; last_inum =(FATFS_SECT_2_INODE(firstDataSector,last_block_act + 1) - 1) + FATFS_NUM_SPECFILE; inum_count = last_inum - first_inum + 1; }