ufs_inode_t* ufs_traverse_path(ufs_t *mount, const char *_path) { uint32_t i; uint32_t inum = 2; // 2 == root ufs_inode_t *inode = p_alloc(mount->pool, sizeof(ufs_inode_t)); char *path = p_alloc(mount->pool, strlen(_path)+1); strcpy(path, _path); if (!ufs_load_inode(mount, inode, inum)) goto fail; char *last, *elem; for (elem = strtok_r(path, "/", &last); elem; elem = strtok_r(NULL, "/", &last)) { uint32_t next_inum = 0; uint8_t *dir = ufs_read_inode_data(mount, inode); if (!dir) goto fail; for (i=0; inode->size; ) { ufs_dir_t *entry = (ufs_dir_t*)&dir[i]; fix_endian(entry->inum); fix_endian(entry->len); fix_endian(entry->namelen); if (entry->inum == 0) break; if ((entry->namelen == strlen(elem)) && (strncmp(elem, entry->name, entry->namelen) == 0)) { next_inum = entry->inum; break; } i += entry->len; } p_free(dir); if (next_inum == 0) { sprintf(mount->error_str, "'%s' in '%s' doesn't exist", elem, _path); goto fail; } inum = next_inum; if (!ufs_load_inode(mount, inode, inum)) goto fail; } p_free(path); return inode; fail: p_free(inode); p_free(path); return NULL; }
void make_bmp_header(t_bmp_header *header, size_t size) { memset(header, 0, sizeof(*header)); header->magic = BMP_MAGIC; header->size = size * size * sizeof(int) + sizeof(t_bmp_header) + sizeof(t_bmp_info_header); header->offset = sizeof(t_bmp_header) + sizeof(t_bmp_info_header); fix_endian(&header->magic, sizeof(header->magic)); }
static void ReadWAVE( char *filename, Wave *wave ) { int fd = open( filename, O_RDWR ); RIFFHeader riff_header = ReadRIFFHeader( fd ); FmtHeader fmt_header = ReadFmtHeader( fd ); read( fd, &wave->Subchunk2ID, sizeof(uint32_t)); read( fd, &wave->Subchunk2Size, sizeof(uint32_t)); fix_endian( &riff_header, &fmt_header, wave ); ReadSamples( fd, wave ); close( fd ); }
static void ReadBMP ( char* filename, Bitmap* bmp ) { int fd = open( filename, O_RDWR ); BMPHeader bmp_header = ReadBMPHeader( fd ); DIBHeader dib_header = ReadDIBHeader( fd ); uint8_t buffer[BUFFER_SIZE]; #ifndef __APPLE__ fix_endian( &bmp_header, &dib_header ); #endif int offset = bmp_header.offset; int size = bmp_header.size; int width = dib_header.width; int height = dib_header.height; // Read pixels lseek( fd, offset, SEEK_SET); uint8_t *data = malloc(size); uint8_t *ptr = (uint8_t*)data; for (int i=0; i < (size - offset) / BUFFER_SIZE; i++ ) { read( fd, buffer, BUFFER_SIZE ); for (int i=0; i<BUFFER_SIZE; i++) { (*ptr++) = buffer[i]; } } int remaining = (size - offset) % BUFFER_SIZE; if (remaining) { read( fd, buffer, remaining); for (int i=0; i<remaining; i++) { (*ptr++) = buffer[i]; } } close( fd ); flip( data, width, height ); bmp->width = width; bmp->height = height; bmp->pixels = data; }
static uint8_t svfs_load_inode(svfs_t *mount, svfs_inode_t *inode, uint32_t inum) { uint32_t i; uint8_t block[4096]; const uint32_t max_inode_blocks = mount->superblock.isize - 2; const uint32_t max_inodes = (max_inode_blocks * mount->blocksize) / 64; if (inum > max_inodes) { sprintf(mount->error_str, "svfs_load_inode: inode %u too big (max=%u)", inum, max_inodes); return 0; } const uint32_t inum_byte_idx_in_partition = ((inum-1) * 64) + (2 * mount->blocksize); const uint32_t inum_block = inum_byte_idx_in_partition / mount->blocksize; const uint32_t inum_byte_idx_in_block = inum_byte_idx_in_partition % mount->blocksize; if (!svfs_read_block(mount, block, inum_block)) return 0; memcpy(inode, &block[inum_byte_idx_in_block], 64); fix_endian(inode->mode); fix_endian(inode->nlink); fix_endian(inode->uid); fix_endian(inode->gid); fix_endian(inode->size); fix_endian(inode->atime); fix_endian(inode->mtime); fix_endian(inode->ctime); for (i=0; i<13; i++) { uint32_t addr = inode->__addr[i*3 + 0]; addr = (addr << 8) + inode->__addr[i*3 + 1]; addr = (addr << 8) + inode->__addr[i*3 + 2]; inode->addr[i] = addr; } return 1; }
static uint8_t ufs_load_inode(ufs_t *mount, ufs_inode_t *inode, uint32_t inum) { assert(sizeof(ufs_inode_t) == 128); /* Which cylinder group is this inode in? */ const uint32_t group_num = inum / mount->superblock.ipg; /* Index of this inode in its cylinder group's inode table */ const uint32_t group_ino_offset = inum % mount->superblock.ipg; /* Fragment address that contains inode */ const uint32_t frag_addr = ufs_group_base(mount, group_num) + mount->superblock.iblkno + ((group_ino_offset * 128) / mount->frag_size); /* Byte offset into the fragment where the inode begins */ const uint32_t frag_offset = (group_ino_offset * 128) % mount->frag_size; uint32_t i; uint8_t *buf = p_alloc(mount->pool, mount->frag_size); // slog("group_num = %u, ino_offset=%u, addr = 0x%08x, offset = 0x%08x\n", group_num, group_ino_offset, frag_addr, frag_offset); // slog("mount->superblock.iblkno = 0x%08x\n", mount->superblock.iblkno); if (!ufs_read_frag(mount, buf, frag_addr)) goto fail; memcpy(inode, buf + frag_offset, 128); fix_endian(inode->mode); fix_endian(inode->nlink); fix_endian(inode->uid); fix_endian(inode->gid); fix_endian(inode->size_hi); fix_endian(inode->size); fix_endian(inode->atime); fix_endian(inode->mtime); fix_endian(inode->ctime); for (i=0; i<12; i++) fix_endian(inode->direct[i]); for (i=0; i<3; i++) fix_endian(inode->indirect[i]); fix_endian(inode->flags); fix_endian(inode->blocks); fix_endian(inode->gen); p_free(buf); return 1; fail: if (buf) p_free(buf); return 0; }
static uint8_t ufs_load_cylinder_group(ufs_t *mount, uint32_t frag_offset, ufs_cylinder_group_t *group) { uint32_t numfrags = sizeof(ufs_cylinder_group_t) / mount->frag_size; numfrags += ((sizeof(ufs_cylinder_group_t) % mount->frag_size) != 0); uint8_t *buf = p_alloc(mount->pool, (numfrags+1) * mount->frag_size); uint32_t i; for (i=0; i <= numfrags; i++) ufs_read_frag(mount, &buf[i * mount->frag_size], frag_offset + i); memcpy(group, buf, sizeof(ufs_cylinder_group_t)); fix_endian(group->link); fix_endian(group->rlink); fix_endian(group->time); fix_endian(group->cgx); fix_endian(group->ncyl); fix_endian(group->niblk); fix_endian(group->ndblk); fix_endian(group->csum_ndir); fix_endian(group->csum_nbfree); fix_endian(group->csum_nifree); fix_endian(group->csum_nffree); fix_endian(group->rotor); fix_endian(group->frotor); fix_endian(group->irotor); for (i=0; i<8; i++) fix_endian(group->frsum[i]); for (i=0; i<(32*8); i++) fix_endian(group->b[i/8][i%8]); fix_endian(group->magic); p_free(buf); return 1; fail: p_free(buf); return 0; }
static svfs_t* svfs_mount(partition_t *part) { assert(sizeof(svfs_superblock_t) == 512); uint32_t i; svfs_t *mount = p_alloc(part->pool, sizeof(svfs_t)); mount->pool = part->pool; mount->error_str = part->error_str; mount->part = part; part_get_block(part, (uint8_t*)&mount->superblock, 1); fix_endian(mount->superblock.isize); fix_endian(mount->superblock.fsize); fix_endian(mount->superblock.nfree); for (i=0; i<50; i++) { fix_endian(mount->superblock.free[i]); } fix_endian(mount->superblock.ninode); for (i=0; i<100; i++) { fix_endian(mount->superblock.inode[i]); } fix_endian(mount->superblock.time); for (i=0; i<4; i++) { fix_endian(mount->superblock.dinfo[i]); } fix_endian(mount->superblock.tfree); fix_endian(mount->superblock.tinode); fix_endian(mount->superblock.state); fix_endian(mount->superblock.lasti); fix_endian(mount->superblock.nbehind); fix_endian(mount->superblock.magic); fix_endian(mount->superblock.type); if (mount->superblock.magic != 0xfd187e20) { sprintf(part->error_str, "Magic doesn't match svfs"); goto fail; } // It is SVFS! const uint32_t type = mount->superblock.type; if ((type != 1) && (type != 2) && (type != 4) && (type != 8)) { sprintf(part->error_str, "Unknown SVFS type (%u)", type); goto fail; } mount->blocksize = 512 * type; return mount; fail: if (mount) p_free(mount); return NULL; }
static disk_t* open_disk (const char *disk_path, char *error_str) { disk_t *disk; uint8_t block[512]; apple_partition_map_t apm; uint32_t i; alloc_pool_t *pool = p_new_pool(NULL); FILE *f; disk = p_alloc(pool, sizeof(disk_t)); disk->pool = pool; disk->block_size = 512; disk->error_str = error_str; disk->path = disk_path; f = fopen(disk_path, "rb"); if (f == NULL) { sprintf(error_str, "Can't open that path"); goto fail; } disk->f = f; // Load the driver descriptor record disk_get_block(disk, block, 0); memcpy(&disk->ddr, block, sizeof(disk->ddr)); fix_endian(disk->ddr.sbBlkSize); fix_endian(disk->ddr.sbBlkCount); fix_endian(disk->ddr.sbDevType); fix_endian(disk->ddr.sbDevId); fix_endian(disk->ddr.sbData); fix_endian(disk->ddr.sbDrvrCount); fix_endian(disk->ddr.ddBlock); fix_endian(disk->ddr.ddSize); fix_endian(disk->ddr.ddType); // If the DDR block exists, (it doesn't have to necessarially) if (memcmp(disk->ddr.sbSig, "ER", 2) == 0) { // Can't handle non-512 byte block sizes if (disk->ddr.sbBlkSize != 512) { sprintf(error_str, "This disk uses blkSize=%u and I can't handle that", disk->ddr.sbBlkSize); goto fail; } } // slog("sizeof(apple_part_map_t) = %lu\n", sizeof(apple_partition_map_t)); // Load the partition maps if (!disk_load_partition_map(disk, &apm, 0)) goto fail; else if ((apm.pmMapBlkCnt > 256) || (apm.pmMapBlkCnt == 0)) { sprintf(error_str, "Crazy number of partitions on this disk %u", apm.pmMapBlkCnt); goto fail; } disk->num_partitions = apm.pmMapBlkCnt; disk->partition_maps = p_alloc(disk->pool, disk->num_partitions * sizeof(apple_partition_map_t)); disk->partitions = p_alloc(disk->pool, disk->num_partitions * sizeof(partition_t)); for (i=0; i<disk->num_partitions; i++) { if (!disk_load_partition_map(disk, &disk->partition_maps[i], i)) goto fail; memset(&disk->partitions[i], 0, sizeof(partition_t)); disk->partitions[i].disk = disk; disk->partitions[i].pool = disk->pool; disk->partitions[i].error_str = error_str; disk->partitions[i].start_block = disk->partition_maps[i].pmPyPartStart; disk->partitions[i].num_blocks = disk->partition_maps[i].pmPartBlkCnt; memcpy(disk->partitions[i].name, disk->partition_maps[i].pmPartName, 32); memcpy(disk->partitions[i].type, disk->partition_maps[i].pmPartType, 32); slog("%u type:%s name:%s\n", i, disk->partitions[i].type, disk->partitions[i].name); slog("bz_magic=0x%08x slice=%u\n", disk->partition_maps[i].bz.magic, disk->partition_maps[i].bz.slice); } return disk; fail: if (f) fclose(f); p_free_pool(pool); return NULL; }
static uint8_t disk_load_partition_map(disk_t *disk, apple_partition_map_t *apm, uint32_t idx) { uint8_t block[512]; disk_get_block(disk, block, 1 + idx); memcpy(apm, block, sizeof(apple_partition_map_t)); fix_endian(apm->pmSigPad); fix_endian(apm->pmMapBlkCnt); fix_endian(apm->pmPyPartStart); fix_endian(apm->pmPartBlkCnt); fix_endian(apm->pmLgDataStart); fix_endian(apm->pmDataCnt); fix_endian(apm->pmPartStatus); fix_endian(apm->pmLgBootStart); fix_endian(apm->pmBootSize); fix_endian(apm->pmBootAddr); fix_endian(apm->pmBootAddr2); fix_endian(apm->pmBootEntry); fix_endian(apm->pmBootEntry2); fix_endian(apm->pmBootCksum); fix_endian(apm->bz.magic); fix_endian(apm->bz.inode); fix_endian(apm->bz.tmade); fix_endian(apm->bz.tmount); fix_endian(apm->bz.tunmount); fix_endian(apm->bz.abm_size); fix_endian(apm->bz.abm_ents); fix_endian(apm->bz.abm_start); if (memcmp(apm->pmSig, "PM", 2) != 0) { sprintf(disk->error_str, "partition index %u has bad magic %02x%02x", idx, apm->pmSig[0], apm->pmSig[1]); return 0; } return 1; }
static ufs_t* ufs_mount(partition_t *part) { ufs_t *mount = p_alloc(part->pool, sizeof(ufs_t)); uint8_t *buf = p_alloc(part->pool, 32 * 512); uint32_t i; mount->pool = part->pool; mount->part = part; mount->error_str = part->error_str; for (i=0; i<4; i++) part_get_block(part, &buf[i*512], 16 + i); memcpy(&mount->superblock, buf, sizeof(ufs_superblock_t)); fix_endian(mount->superblock.link); fix_endian(mount->superblock.rlink); fix_endian(mount->superblock.sblkno); fix_endian(mount->superblock.cblkno); fix_endian(mount->superblock.iblkno); fix_endian(mount->superblock.dblkno); fix_endian(mount->superblock.cgoffset); fix_endian(mount->superblock.cgmask); fix_endian(mount->superblock.time); fix_endian(mount->superblock.size); fix_endian(mount->superblock.dsize); fix_endian(mount->superblock.ncg); fix_endian(mount->superblock.bsize); fix_endian(mount->superblock.fsize); fix_endian(mount->superblock.frag); fix_endian(mount->superblock.minfree); fix_endian(mount->superblock.rotdelay); fix_endian(mount->superblock.rps); fix_endian(mount->superblock.bmask); fix_endian(mount->superblock.fmask); fix_endian(mount->superblock.bshift); fix_endian(mount->superblock.fshift); fix_endian(mount->superblock.maxcontig); fix_endian(mount->superblock.maxbpg); fix_endian(mount->superblock.fragshift); fix_endian(mount->superblock.fsbtodb); fix_endian(mount->superblock.sbsize); fix_endian(mount->superblock.csmask); fix_endian(mount->superblock.csshift); fix_endian(mount->superblock.nindir); fix_endian(mount->superblock.inopb); fix_endian(mount->superblock.nspf); fix_endian(mount->superblock.optim); fix_endian(mount->superblock.state); fix_endian(mount->superblock.id[0]); fix_endian(mount->superblock.id[1]); fix_endian(mount->superblock.csaddr); fix_endian(mount->superblock.cssize); fix_endian(mount->superblock.cgsize); fix_endian(mount->superblock.ntrak); fix_endian(mount->superblock.nsect); fix_endian(mount->superblock.spc); fix_endian(mount->superblock.ncyl); fix_endian(mount->superblock.cpg); fix_endian(mount->superblock.ipg); fix_endian(mount->superblock.fpg); fix_endian(mount->superblock.csum_ndir); fix_endian(mount->superblock.csum_nbfree); fix_endian(mount->superblock.csum_nifree); fix_endian(mount->superblock.csum_nffree); fix_endian(mount->superblock.cgrotor); fix_endian(mount->superblock.cpc); for (i=0; i<(32*8); i++) fix_endian(mount->superblock.postbl[i/8][i%8]); fix_endian(mount->superblock.magic); if (mount->superblock.magic != 0x00011954) { sprintf(part->error_str, "Magic doesn't match ufs"); goto fail; } // It is UFS! mount->frag_size = mount->superblock.fsize; mount->frag_per_block = mount->superblock.frag; mount->block_size = mount->frag_size * mount->frag_per_block; assert(mount->block_size == mount->superblock.bsize); mount->num_groups = mount->superblock.ncg; mount->groups = (ufs_cylinder_group_t*)p_alloc(mount->pool, mount->num_groups * sizeof(ufs_cylinder_group_t)); for (i=0; i<mount->num_groups; i++) { uint32_t group_base = ufs_group_base(mount, i) + mount->superblock.cblkno; ufs_load_cylinder_group(mount, group_base, &mount->groups[i]); if ((mount->groups[i].cgx != i) || (mount->groups[i].magic != 0x00090255)) { sprintf(mount->error_str, "bad cylinder group %u frag_offset=0x%x", i, group_base); goto fail; } } if (buf) p_free(buf); return mount; fail: if (mount) { if (mount->groups) p_free(mount->groups); p_free(mount); } if (buf) p_free(buf); return NULL; }