Beispiel #1
0
void extractBLKX(AbstractFile* in, AbstractFile* out, BLKXTable* blkx) {
	unsigned char* inBuffer;
	unsigned char* outBuffer;
	unsigned char zero;
	size_t bufferSize;
	size_t bufferRead;
	size_t have;
	off_t initialOffset;
	int i;
	int ret;
	
	z_stream strm;
	
	bufferSize = SECTOR_SIZE * blkx->decompressBufferRequested;
	
	ASSERT(inBuffer = (unsigned char*) malloc(bufferSize), "malloc");
	ASSERT(outBuffer = (unsigned char*) malloc(bufferSize), "malloc");
		 
	initialOffset =	out->tell(out);
	ASSERT(initialOffset != -1, "ftello");
	
	zero = 0;
	
	for(i = 0; i < blkx->blocksRunCount; i++) {
		ASSERT(in->seek(in, blkx->dataStart + blkx->runs[i].compOffset) == 0, "fseeko");
		ASSERT(out->seek(out, initialOffset + (blkx->runs[i].sectorStart * SECTOR_SIZE)) == 0, "mSeek");
		
		if(blkx->runs[i].sectorCount > 0) {
			ASSERT(out->seek(out, initialOffset + (blkx->runs[i].sectorStart + blkx->runs[i].sectorCount) * SECTOR_SIZE - 1) == 0, "mSeek");
			ASSERT(out->write(out, &zero, 1) == 1, "mWrite");
			ASSERT(out->seek(out, initialOffset + (blkx->runs[i].sectorStart * SECTOR_SIZE)) == 0, "mSeek");
		}
		
		if(blkx->runs[i].type == BLOCK_TERMINATOR) {
			break;
		}
		
		if( blkx->runs[i].compLength == 0) {
			continue;
		}
		
		printf("run %d: start=%" PRId64 " sectors=%" PRId64 ", length=%" PRId64 ", fileOffset=0x%" PRIx64 "\n", i, initialOffset + (blkx->runs[i].sectorStart * SECTOR_SIZE), blkx->runs[i].sectorCount, blkx->runs[i].compLength, blkx->runs[i].compOffset);
		
		switch(blkx->runs[i].type) {
			case BLOCK_ADC:
				do {
					ASSERT((strm.avail_in = in->read(in, inBuffer, blkx->runs[i].compLength)) == blkx->runs[i].compLength, "fread");
					strm.avail_out = adc_decompress(strm.avail_in, inBuffer, bufferSize, outBuffer, &have);
					ASSERT(out->write(out, outBuffer, have) == have, "mWrite");
					bufferRead+=strm.avail_out;
				} while (bufferRead < blkx->runs[i].compLength);
				break;
			case BLOCK_ZLIB:
				strm.zalloc = Z_NULL;
				strm.zfree = Z_NULL;
				strm.opaque = Z_NULL;
				strm.avail_in = 0;
				strm.next_in = Z_NULL;
				
				ASSERT(inflateInit(&strm) == Z_OK, "inflateInit");
				
				ASSERT((strm.avail_in = in->read(in, inBuffer, blkx->runs[i].compLength)) == blkx->runs[i].compLength, "fread");
				strm.next_in = inBuffer;
				
				do {
					strm.avail_out = bufferSize;
					strm.next_out = outBuffer;
					ASSERT((ret = inflate(&strm, Z_NO_FLUSH)) != Z_STREAM_ERROR, "inflate/Z_STREAM_ERROR");
					if(ret != Z_OK && ret != Z_BUF_ERROR && ret != Z_STREAM_END) {
						ASSERT(FALSE, "inflate");
					}
					have = bufferSize - strm.avail_out;
					ASSERT(out->write(out, outBuffer, have) == have, "mWrite");
				} while (strm.avail_out == 0);
				
				ASSERT(inflateEnd(&strm) == Z_OK, "inflateEnd");
				break;
			case BLOCK_RAW:
				if(blkx->runs[i].compLength > bufferSize) {
					uint64_t left = blkx->runs[i].compLength;
					void* pageBuffer = malloc(DEFAULT_BUFFER_SIZE);
					while(left > 0) {
						size_t thisRead;
						if(left > DEFAULT_BUFFER_SIZE) {
							thisRead = DEFAULT_BUFFER_SIZE;
						} else {
							thisRead = left;
						}
						ASSERT((have = in->read(in, pageBuffer, thisRead)) == thisRead, "fread");
						ASSERT(out->write(out, pageBuffer, have) == have, "mWrite");
						left -= have;
					}
					free(pageBuffer);
				} else {
					ASSERT((have = in->read(in, inBuffer, blkx->runs[i].compLength)) == blkx->runs[i].compLength, "fread");
					ASSERT(out->write(out, inBuffer, have) == have, "mWrite");
				}
				break;
			case BLOCK_IGNORE:
				break;
			case BLOCK_COMMENT:
				break;
			case BLOCK_TERMINATOR:
				break;
			default:
				break;
		}
	}
	
	free(inBuffer);
	free(outBuffer);
}
Beispiel #2
0
int main(int argc, char *argv[])
{
	int i, err, partnum = 0, scb;
	Bytef *tmp = NULL, *otmp = NULL, *dtmp = NULL;
	char *input_file = NULL, *output_file = NULL;
	char *plist = NULL;
	char *blkx = NULL;
	unsigned int blkx_size;
	struct _mishblk *parts = NULL;
	char *data_begin = NULL, *data_end = NULL;
	char *partname_begin = NULL, *partname_end = NULL;
	char *mish_begin = NULL;
	char partname[255] = "";
	unsigned int *partlen = NULL;
	unsigned int data_size;
	uint64_t out_offs, out_size, in_offs, in_size, in_offs_add, add_offs, to_read,
	      to_write, chunk;
	char reserved[5] = "    ";
	char sztype[64] = "";
	unsigned int block_type, dw_reserved;

	for (i = 1; i < argc; i++) {
		if (!strcmp(argv[i], "-s"))
			verbose = 0;
		else if (!strcmp(argv[i], "-v"))
			verbose = 2;
		else if (!strcmp(argv[i], "-V"))
			verbose = 3;
		else if (!strcmp(argv[i], "-d"))
			debug = 1;
		else if (!strcmp(argv[i], "-l"))
			listparts = 1;
		else if (!strcmp(argv[i], "-p"))
			sscanf(argv[++i], "%d", &extractpart);
		else if (!strcmp(argv[i], "-i") && i < argc - 1)
			input_file = argv[++i];
		else if (!strcmp(argv[i], "-o") && i < argc - 1)
			output_file = argv[++i];
		else if (!input_file)
			input_file = argv[i];
		else if (!output_file)
			output_file = argv[i];
	}

	if (!input_file) {
		printf("\n%s\n\n%s\n\n", VERSION, USAGE);
		return 0;
	}
	if (!output_file) {
		i = strlen(input_file);
		output_file = (char *)malloc(i + 6);
		if (output_file) {
			strcpy(output_file, input_file);
			if (strcasecmp(&output_file[i - 4], ".dmg"))
				strcat(output_file, ".img");
			else
				strcpy(&output_file[i - 4], ".img");
		}
	}
	if (verbose)
		printf("\n%s\n\n", VERSION);
	if (debug) {
		FDBG = fopen("dmg2img.log", "wb");
		if (FDBG == NULL) {
			debug = 0;
			printf("ERROR: Can't create dmg2img.log. No debug info will be written.\n");
		}
	}
	FIN = fopen(input_file, "rb");
	if (FIN == NULL) {
		printf("ERROR: Can't open input file %s\n", input_file);
		return 0;
	}
	if (output_file)
		FOUT = fopen(output_file, "wb");
	else
		FOUT = NULL;
	if (FOUT == NULL) {
		printf("ERROR: Can't create output file %s\n", output_file);
		fclose(FIN);
		return 0;
	}
	//parsing koly block
	fseeko(FIN, -0x200, SEEK_END);
	read_kolyblk(FIN, &kolyblk);
	if (kolyblk.Signature != 0x6b6f6c79) {
		fseeko(FIN, 0, SEEK_SET);
		read_kolyblk(FIN, &kolyblk);
	}
	char szSignature[5];
	szSignature[4] = '\0';
	int rSignature = convert_int(kolyblk.Signature);
	memcpy(szSignature, &rSignature, 4);

	if (debug) {
		fprintf(FDBG, "Signature:\t\t0x%08" PRIX32 " (%s)\n", kolyblk.Signature, szSignature);
		fprintf(FDBG, "Version:\t\t0x%08" PRIX32 "\n", kolyblk.Version);
		fprintf(FDBG, "HeaderSize:\t\t0x%08" PRIX32 "\n", kolyblk.HeaderSize);
		fprintf(FDBG, "Flags:\t\t\t0x%08" PRIX32 "\n", kolyblk.Flags);
		fprintf(FDBG, "RunningDataForkOffset:\t0x%016" PRIX64 "\n", kolyblk.RunningDataForkOffset);
		fprintf(FDBG, "DataForkOffset:\t\t0x%016" PRIX64 "\n", kolyblk.DataForkOffset);
		fprintf(FDBG, "DataForkLength:\t\t0x%016" PRIX64 "\n", kolyblk.DataForkLength);
		fprintf(FDBG, "RsrcForkOffset:\t\t0x%016" PRIX64 "\n", kolyblk.RsrcForkOffset);
		fprintf(FDBG, "RsrcForkLength:\t\t0x%016" PRIX64 "\n", kolyblk.RsrcForkLength);
		fprintf(FDBG, "SegmentNumber:\t\t0x%08" PRIX32 "\n", kolyblk.SegmentNumber);
		fprintf(FDBG, "SegmentCount:\t\t0x%08" PRIX32 "\n", kolyblk.SegmentCount);
		fprintf(FDBG, "SegmentID:\t\t0x%08" PRIX32 "%08" PRIX32 "%08" PRIX32 "%08" PRIX32 "\n", kolyblk.SegmentID1, kolyblk.SegmentID2, kolyblk.SegmentID3, kolyblk.SegmentID4);
		fprintf(FDBG, "DataForkChecksumType:\t0x%08" PRIX32 " %s\n", kolyblk.DataForkChecksumType, kolyblk.DataForkChecksumType == 0x02 ? "CRC-32" : "");
		fprintf(FDBG, "DataForkChecksum:\t0x%08" PRIX32 "\n", kolyblk.DataForkChecksum);
		fprintf(FDBG, "XMLOffset:\t\t0x%016" PRIX64 "\n", kolyblk.XMLOffset);
		fprintf(FDBG, "XMLLength:\t\t0x%016" PRIX64 "\n", kolyblk.XMLLength);
		fprintf(FDBG, "MasterChecksumType:\t0x%08" PRIX32 " %s\n", kolyblk.MasterChecksumType, kolyblk.MasterChecksumType == 0x02 ? "CRC-32" : "");
		fprintf(FDBG, "MasterChecksum:\t\t0x%08" PRIX32 "\n", kolyblk.MasterChecksum);
		fprintf(FDBG, "ImageVariant:\t\t0x%08" PRIX32 "\n", kolyblk.ImageVariant);
		fprintf(FDBG, "SectorCount:\t\t0x%016" PRIX64 "\n", kolyblk.SectorCount);

		fprintf(FDBG, "\n");
	}
	if (kolyblk.Signature != 0x6b6f6c79) {
		error_dmg_corrupted();
	}
	if (verbose) {
		if (input_file && output_file)
			printf("%s --> %s\n\n", input_file, listparts ? "(partition list)" : output_file);
	}
	if (debug)
		printf("Debug info will be written to dmg2img.log\n\n");

	if (kolyblk.XMLOffset != 0 && kolyblk.XMLLength != 0) {
		//We have a plist to parse
			if (verbose > 1)
			printf("reading property list, %llu bytes from address %llu ...\n", (unsigned long long)kolyblk.XMLLength, (unsigned long long)kolyblk.XMLOffset);

		plist = (char *)malloc(kolyblk.XMLLength + 1);

		if (!plist)
			mem_overflow();

		fseeko(FIN, kolyblk.XMLOffset, SEEK_SET);
		fread(plist, kolyblk.XMLLength, 1, FIN);
		plist[kolyblk.XMLLength] = '\0';

		if (debug && verbose >= 3) {
			fprintf(FDBG, "%s\n", plist);
		}
		char *_blkx_begin = strstr(plist, blkx_begin);
		blkx_size = strstr(_blkx_begin, list_end) - _blkx_begin;
		blkx = (char *)malloc(blkx_size + 1);
		memcpy(blkx, _blkx_begin, blkx_size);
		blkx[blkx_size] = '\0';

		if (!strstr(plist, plist_begin) ||
		    !strstr(&plist[kolyblk.XMLLength - 20], plist_end)) {
			printf("ERROR: Property list is corrupted.\n");
			exit(-1);
		}
		data_begin = blkx;
		partnum = 0;
		scb = strlen(chunk_begin);
		while (1) {
			unsigned int tmplen;
			data_begin = strstr(data_begin, chunk_begin);
			if (!data_begin)
				break;
			data_begin += scb;
			data_end = strstr(data_begin, chunk_end);
			if (!data_end)
				break;
			data_size = data_end - data_begin;
			i = partnum;
			++partnum;
			parts = (struct _mishblk *)realloc(parts, partnum * sizeof(struct _mishblk));
			if (!parts)
				mem_overflow();

			char *base64data = (char *)malloc(data_size + 1);
			if (!base64data)
				mem_overflow();
			base64data[data_size] = '\0';
			memcpy(base64data, data_begin, data_size);
			if (verbose >= 3)
				printf("%s\n", base64data);
			cleanup_base64(base64data, data_size);
			decode_base64(base64data, strlen(base64data), base64data, &tmplen);
			fill_mishblk(base64data, &parts[i]);
			if (parts[i].BlocksSignature != 0x6D697368)
				break;

			parts[i].Data = (char *)malloc(parts[i].BlocksRunCount * 0x28);
			if (!parts[i].Data)
				mem_overflow();
			memcpy(parts[i].Data, base64data + 0xCC, parts[i].BlocksRunCount * 0x28);

			free(base64data);
	
			partname_begin = strstr(data_begin, name_key);
			partname_begin = strstr(partname_begin, name_begin) + strlen(name_begin);
			partname_end = strstr(partname_begin, name_end);
			memset(partname, 0, 255);
			memcpy(partname, partname_begin, partname_end - partname_begin);
			if (verbose >= 2) {
				printf("partition %d: begin=%d, size=%d, decoded=%d\n", i, (int)(data_begin - blkx), data_size, tmplen);
				if (listparts)
					printf("             %s\n", partname);
			} else if (listparts)
				printf("partition %d: %s\n", i, partname);
		}
	} else if (kolyblk.RsrcForkOffset != 0 && kolyblk.RsrcForkLength != 0) {
		//We have a binary resource fork to parse
			plist = (char *)malloc(kolyblk.RsrcForkLength);
		if (!plist)
			mem_overflow();
		fseeko(FIN, kolyblk.RsrcForkOffset, SEEK_SET);
		fread(plist, kolyblk.RsrcForkLength, 1, FIN);
		partnum = 0;
		struct _mishblk mishblk;
		int next_mishblk = 0;
		mish_begin = plist + 0x104;
		while (1) {
			mish_begin += next_mishblk;
			if (mish_begin - plist + 0xCC > kolyblk.RsrcForkLength)
				break;

			fill_mishblk(mish_begin, &mishblk);
			if (mishblk.BlocksSignature != 0x6D697368)
				break;

			next_mishblk = 0xCC + 0x28 * mishblk.BlocksRunCount + 0x04;
			i = partnum;
			++partnum;
			parts = (struct _mishblk *)realloc(parts, partnum * sizeof(struct _mishblk));
			if (!parts)
				mem_overflow();
			memcpy(&parts[i], &mishblk, sizeof(struct _mishblk));
			parts[i].Data = (char *)malloc(0x28 * mishblk.BlocksRunCount);
			if (!parts[i].Data)
				mem_overflow();
			memcpy(parts[i].Data, mish_begin + 0xCC, 0x28 * mishblk.BlocksRunCount);
			if (verbose >= 2)
				printf("partition %d: begin=%d, size=%" PRIu32 "\n", i, (int)(mish_begin - plist), 0xCC + mishblk.BlocksRunCount * 0x28);
		}
	} else {
		error_dmg_corrupted();
	}
	
	if (listparts || extractpart > partnum-1) {
		if (extractpart > partnum-1)
			printf("partition %d not found\n", extractpart);
		
		for (i = 0; i < partnum; i++)
			if (parts[i].Data != NULL)
				free(parts[i].Data);
		if (parts != NULL)
			free(parts);
		if (plist != NULL)
			free(plist);
		if (blkx != NULL)
			free(blkx);
		
		return 0;
	}
		
	if (verbose)
		printf("\ndecompressing:\n");

	tmp = (Bytef *) malloc(CHUNKSIZE);
	otmp = (Bytef *) malloc(CHUNKSIZE);
	dtmp = (Bytef *) malloc(DECODEDSIZE);
	if (!tmp || !otmp || !dtmp)
		mem_overflow();
	z.zalloc = (alloc_func) 0;
	z.zfree = (free_func) 0;
	z.opaque = (voidpf) 0;
	bz.bzalloc = NULL;
	bz.bzfree = NULL;
	bz.opaque = NULL;

	in_offs = add_offs = in_offs_add = kolyblk.DataForkOffset;

	for (i = extractpart==-1?0:extractpart; i < (extractpart==-1?partnum:extractpart+1) && in_offs < kolyblk.DataForkLength - kolyblk.DataForkOffset; i++) {
		if (verbose)
			printf("opening partition %d ...           ", i);
		if (verbose >= 3)
			printf("\n");
		else if (verbose)
			printf("         ");
		fflush(stdout);
		offset = 0;
		add_offs = in_offs_add;
		block_type = 0;
		if (debug) {
			fprintf(FDBG, "\n   run..... ..type.... ..reserved ..sectorStart..... ..sectorCount..... ..compOffset...... ..compLength......\n");
		}
		unsigned long bi = 0;
		while (block_type != BT_TERM && offset < parts[i].BlocksRunCount * 0x28) {
			block_type = convert_char4((unsigned char *)parts[i].Data + offset);
			dw_reserved = convert_char4((unsigned char *)parts[i].Data + offset + 4);
			memcpy(&reserved, parts[i].Data + offset + 4, 4);
			out_offs = convert_char8((unsigned char *)parts[i].Data + offset + 8) * 0x200;
			out_size = convert_char8((unsigned char *)parts[i].Data + offset + 16) * 0x200;
			in_offs = convert_char8((unsigned char *)parts[i].Data + offset + 24);
			in_size = convert_char8((unsigned char *)parts[i].Data + offset + 32);
			if (block_type != BT_TERM)
				in_offs_add = add_offs + in_offs + in_size;
			if (debug) {
				switch (block_type) {
				case BT_ADC:
					strcpy(sztype, "adc");
					break;
				case BT_ZLIB:
					strcpy(sztype, "zlib");
					break;
				case BT_BZLIB:
					strcpy(sztype, "bzlib");
					break;
				case BT_ZERO:
					strcpy(sztype, "zero");
					break;
				case BT_IGNORE:
					strcpy(sztype, "ignore");
					break;
				case BT_RAW:
					strcpy(sztype, "raw");
					break;
				case BT_COMMENT:
					strcpy(sztype, "comment ");
					strcat(sztype, reserved);
					break;
				case BT_TERM:
					strcpy(sztype, "terminator");
					break;
				default:
					sztype[0] = '\0';
				}
				fprintf(FDBG, " 0x%08lX 0x%08lX 0x%08lX 0x%016llX 0x%016llX 0x%016llX 0x%016llX %s\n",
					(unsigned long)bi,
					(unsigned long)block_type,
					(unsigned long)dw_reserved,
					(unsigned long long)out_offs / 0x200,
					(unsigned long long)out_size / 0x200,
					(unsigned long long)in_offs,
					(unsigned long long)in_size,
					sztype
					);
				fflush(FDBG);
				bi++;
			}
			if (verbose >= 3)
				printf("offset = %u  block_type = 0x%08x\n", offset, block_type);

			if (block_type == BT_ZLIB) {
				if (verbose >= 3)
					printf("zlib inflate (in_addr=%llu in_size=%llu out_addr=%llu out_size=%llu)\n", (unsigned long long)in_offs, (unsigned long long)in_size, (unsigned long long)out_offs, (unsigned long long)out_size);
				if (inflateInit(&z) != Z_OK) {
					printf("ERROR: Can't initialize inflate stream\n");
					return 0;
				}
				fseeko(FIN, in_offs + add_offs, SEEK_SET);
				to_read = in_size;
				do {
					if (!to_read)
						break;
					if (to_read > CHUNKSIZE)
						chunk = CHUNKSIZE;
					else
						chunk = to_read;
					z.avail_in = fread(tmp, 1, chunk, FIN);
					if (ferror(FIN)) {
						(void)inflateEnd(&z);
						printf("ERROR: reading file %s \n", input_file);
						return 0;
					}
					if (z.avail_in == 0)
						break;
					to_read -= z.avail_in;
					z.next_in = tmp;
					do {
						z.avail_out = CHUNKSIZE;
						z.next_out = otmp;
						err = inflate(&z, Z_NO_FLUSH);
						assert(err != Z_STREAM_ERROR);	/* state not clobbered */
						switch (err) {
						case Z_NEED_DICT:
							err = Z_DATA_ERROR;	/* and fall through */
						case Z_DATA_ERROR:
						case Z_MEM_ERROR:
							(void)inflateEnd(&z);
							printf("ERROR: Inflation failed\n");
							return 0;
						}
						to_write = CHUNKSIZE - z.avail_out;
						if (fwrite(otmp, 1, to_write, FOUT) != to_write || ferror(FOUT)) {
							(void)inflateEnd(&z);
							printf("ERROR: writing file %s \n", output_file);
							return 0;
						}
					} while (z.avail_out == 0);
				} while (err != Z_STREAM_END);

				(void)inflateEnd(&z);
			} else if (block_type == BT_BZLIB) {
				if (verbose >= 3)
					printf("bzip2 decompress (in_addr=%llu in_size=%llu out_addr=%llu out_size=%llu)\n", (unsigned long long)in_offs, (unsigned long long)in_size, (unsigned long long)out_offs, (unsigned long long)out_size);
				if (BZ2_bzDecompressInit(&bz, 0, 0) != BZ_OK) {
					printf("ERROR: Can't initialize inflate stream\n");
					return 0;
				}
				fseeko(FIN, in_offs + add_offs, SEEK_SET);
				to_read = in_size;
				do {
					if (!to_read)
						break;
					if (to_read > CHUNKSIZE)
						chunk = CHUNKSIZE;
					else
						chunk = to_read;
					bz.avail_in = fread(tmp, 1, chunk, FIN);
					if (ferror(FIN)) {
						(void)BZ2_bzCompressEnd(&bz);
						printf("ERROR: reading file %s \n", input_file);
						return 0;
					}
					if (bz.avail_in == 0)
						break;
					to_read -= bz.avail_in;
					bz.next_in = (char *)tmp;
					do {
						bz.avail_out = CHUNKSIZE;
						bz.next_out = (char *)otmp;
						err = BZ2_bzDecompress(&bz);
						switch (err) {
						case BZ_PARAM_ERROR:
						case BZ_DATA_ERROR:
						case BZ_DATA_ERROR_MAGIC:
						case BZ_MEM_ERROR:
							(void)BZ2_bzDecompressEnd(&bz);
							printf("ERROR: Inflation failed\n");
							return 0;
						}
						to_write = CHUNKSIZE - bz.avail_out;
						if (fwrite(otmp, 1, to_write, FOUT) != to_write || ferror(FOUT)) {
							(void)BZ2_bzDecompressEnd(&bz);
							printf("ERROR: writing file %s \n", output_file);
							return 0;
						}
					} while (bz.avail_out == 0);
				} while (err != BZ_STREAM_END);

				(void)BZ2_bzDecompressEnd(&bz);
			} else if (block_type == BT_ADC) {
				if (verbose >= 3)
					printf("ADC decompress (in_addr=%llu in_size=%llu out_addr=%llu out_size=%llu)\n", (unsigned long long)in_offs, (unsigned long long)in_size, (unsigned long long)out_offs, (unsigned long long)out_size);
				fseeko(FIN, in_offs + add_offs, SEEK_SET);
				to_read = in_size;
				while (to_read > 0) {
					chunk = to_read > CHUNKSIZE ? CHUNKSIZE : to_read;
					to_write = fread(tmp, 1, chunk, FIN);
					if (ferror(FIN) || to_write < chunk) {
						printf("ERROR: reading file %s\n", input_file);
						return 0;
					}
					int bytes_written;
					int read_from_input = adc_decompress(to_write, tmp, DECODEDSIZE, dtmp, &bytes_written);
					fwrite(dtmp, 1, bytes_written, FOUT);
					to_read -= read_from_input;
				}
			} else if (block_type == BT_RAW) {
				fseeko(FIN, in_offs + add_offs, SEEK_SET);
				to_read = in_size;
				while (to_read > 0) {
					if (to_read > CHUNKSIZE)
						chunk = CHUNKSIZE;
					else
						chunk = to_read;
					to_write = fread(tmp, 1, chunk, FIN);
					if (ferror(FIN) || to_write < chunk) {
						printf("ERROR: reading file %s \n", input_file);
						return 0;
					}
					fwrite(tmp, 1, chunk, FOUT);
					//copy
						to_read -= chunk;
				}
				if (verbose >= 3)
					printf("copy data  (in_addr=%llu in_size=%llu out_size=%llu)\n", (unsigned long long)in_offs, (unsigned long long)in_size, (unsigned long long)out_size);
			} else if (block_type == BT_ZERO || block_type == BT_IGNORE) {
				memset(tmp, 0, CHUNKSIZE);
				to_write = out_size;
				while (to_write > 0) {
					if (to_write > CHUNKSIZE)
						chunk = CHUNKSIZE;
					else
						chunk = to_write;
					fwrite(tmp, 1, chunk, FOUT);
					to_write -= chunk;
				}
				if (verbose >= 3)
					printf("null bytes (out_size=%llu)\n",
						   (unsigned long long)out_size);
			} else if (block_type == BT_COMMENT) {
				if (verbose >= 3)
					printf("0x%08x (in_addr=%llu in_size=%llu out_addr=%llu out_size=%llu) comment %s\n", block_type, (unsigned long long)in_offs,
						   (unsigned long long)in_size,
						   (unsigned long long)out_offs,
						   (unsigned long long)out_size, reserved);
			} else if (block_type == BT_TERM) {
				if (in_offs == 0 && partnum > i+1) {
					if (convert_char8((unsigned char *)parts[i+1].Data + 24) != 0)
						in_offs_add = kolyblk.DataForkOffset;
				} else
					in_offs_add = kolyblk.DataForkOffset;

				if (verbose >= 3)
					printf("terminator\n");
			} else {
				if (verbose)
					printf("\n Unsupported or corrupted block found: %d\n", block_type);
			}
			offset += 0x28;
			if (verbose) {
				percent = 100 * (double)offset / ((double)parts[i].BlocksRunCount * 0x28);
				percentage();
			}
		}
		if (verbose)
			printf("  ok\n");
	}
	if (verbose)
		printf("\nArchive successfully decompressed as %s\n", output_file);

	if (tmp != NULL)
		free(tmp);
	if (otmp != NULL)
		free(otmp);
	if (dtmp != NULL)
		free(dtmp);
	for (i = 0; i < partnum; i++) {
		if (parts[i].Data != NULL)
			free(parts[i].Data);
	}
	if (parts != NULL)
		free(parts);
	if (partlen != NULL)
		free(partlen);
	if (plist != NULL)
		free(plist);
	if (blkx != NULL)
		free(blkx);
	if (FIN != NULL)
		fclose(FIN);
	if (FOUT != NULL)
		fclose(FOUT);
	if (FDBG != NULL)
		fclose(FDBG);

#if defined(__linux__)
	if (verbose && extractpart > -1)
		print_mountcmd(output_file);
#endif

	return 0;
}
Beispiel #3
0
static void cacheRun(DMG* dmg, BLKXTable* blkx, int run) {
	size_t bufferSize;
	size_t bufferRead;
	z_stream strm;
	void* inBuffer;
	int ret;
	size_t have;
	
	if(dmg->runData) {
		free(dmg->runData);
	}
	
	bufferSize = SECTOR_SIZE * blkx->runs[run].sectorCount;
	
	dmg->runData = (void*) malloc(bufferSize);
	inBuffer = (void*) malloc(bufferSize);
	memset(dmg->runData, 0, bufferSize);
	
	ASSERT(dmg->dmg->seek(dmg->dmg, blkx->dataStart + blkx->runs[run].compOffset) == 0, "fseeko");
	
    switch(blkx->runs[run].type) {
		case BLOCK_ADC:
			bufferRead = 0;
			do {
				strm.avail_in = dmg->dmg->read(dmg->dmg, inBuffer, blkx->runs[run].compLength);
				strm.avail_out = adc_decompress(strm.avail_in, inBuffer, bufferSize, dmg->runData, &have);
				bufferRead+=strm.avail_out;
			} while (bufferRead < blkx->runs[run].compLength);
			break;
		case BLOCK_ZLIB:
			strm.zalloc = Z_NULL;
			strm.zfree = Z_NULL;
			strm.opaque = Z_NULL;
			strm.avail_in = 0;
			strm.next_in = Z_NULL;
			
			ASSERT(inflateInit(&strm) == Z_OK, "inflateInit");
			
			ASSERT((strm.avail_in = dmg->dmg->read(dmg->dmg, inBuffer, blkx->runs[run].compLength)) == blkx->runs[run].compLength, "fread");
			strm.next_in = (unsigned char*) inBuffer;
			
			do {
				strm.avail_out = bufferSize;
				strm.next_out = (unsigned char*) dmg->runData;
				ASSERT((ret = inflate(&strm, Z_NO_FLUSH)) != Z_STREAM_ERROR, "inflate/Z_STREAM_ERROR");
				if(ret != Z_OK && ret != Z_BUF_ERROR && ret != Z_STREAM_END) {
					ASSERT(FALSE, "inflate");
				}
				have = bufferSize - strm.avail_out;
			} while (strm.avail_out == 0);
			
			ASSERT(inflateEnd(&strm) == Z_OK, "inflateEnd");
			break;
		case BLOCK_RAW:
			ASSERT((have = dmg->dmg->read(dmg->dmg, dmg->runData, blkx->runs[run].compLength)) == blkx->runs[run].compLength, "fread");
			break;
		case BLOCK_IGNORE:
			break;
		case BLOCK_COMMENT:
			break;
		case BLOCK_TERMINATOR:
			break;
		default:
			break;
    }
	
	dmg->runStart = (blkx->runs[run].sectorStart + blkx->firstSectorNumber) * SECTOR_SIZE;
	dmg->runEnd = dmg->runStart + (blkx->runs[run].sectorCount * SECTOR_SIZE);
}
Beispiel #4
0
/* Stripe handling: ADC block (type 0x80000004) */
static int dmg_stripe_adc(cli_ctx *ctx, int fd, uint32_t index, struct dmg_mish_with_stripes *mish_set)
{
    int ret = CL_CLEAN, adcret;
    adc_stream strm;
    size_t off = mish_set->stripes[index].dataOffset;
    size_t len = mish_set->stripes[index].dataLength;
    uint64_t size_so_far = 0;
    uint64_t expected_len = mish_set->stripes[index].sectorCount * DMG_SECTOR_SIZE;
    uint8_t obuf[BUFSIZ];

    cli_dbgmsg("dmg_stripe_adc: stripe " STDu32 " initial len " STDu64 " expected len " STDu64 "\n",
            index, (uint64_t)len, (uint64_t)expected_len);
    if (len == 0)
        return CL_CLEAN;

    memset(&strm, 0, sizeof(strm));
    strm.next_in = (uint8_t *)fmap_need_off_once(*ctx->fmap, off, len);
    if (!strm.next_in) {
        cli_warnmsg("dmg_stripe_adc: fmap need failed on stripe " STDu32 "\n", index);
        return CL_EMAP;
    }
    strm.avail_in = len;
    strm.next_out = obuf;
    strm.avail_out = sizeof(obuf);

    adcret = adc_decompressInit(&strm);
    if(adcret != ADC_OK) {
        cli_warnmsg("dmg_stripe_adc: adc_decompressInit failed\n");
        return CL_EMEM;
    }

    while(adcret == ADC_OK) {
        int written;
        if (size_so_far > expected_len) {
            cli_warnmsg("dmg_stripe_adc: expected size exceeded!\n");
            adc_decompressEnd(&strm);
            return CL_EFORMAT;
        }
        adcret = adc_decompress(&strm);
        switch(adcret) {
            case ADC_OK:
                if(strm.avail_out == 0) {
                    if ((written=cli_writen(fd, obuf, sizeof(obuf)))!=sizeof(obuf)) {
                        cli_errmsg("dmg_stripe_adc: failed write to output file\n");
                        adc_decompressEnd(&strm);
                        return CL_EWRITE;
                    }
                    size_so_far += written;
                    strm.next_out = obuf;
                    strm.avail_out = sizeof(obuf);
                }
                continue;
            case ADC_STREAM_END:
            default:
                written = sizeof(obuf) - strm.avail_out;
                if (written) {
                    if ((cli_writen(fd, obuf, written))!=written) {
                        cli_errmsg("dmg_stripe_adc: failed write to output file\n");
                        adc_decompressEnd(&strm);
                        return CL_EWRITE;
                    }
                    size_so_far += written;
                    strm.next_out = obuf;
                    strm.avail_out = sizeof(obuf);
                }
                if (adcret == ADC_STREAM_END)
                    break;
                cli_dbgmsg("dmg_stripe_adc: after writing " STDu64 " bytes, "
                           "got error %d decompressing stripe " STDu32 "\n",
                           size_so_far, adcret, index);
                adc_decompressEnd(&strm);
                return CL_EFORMAT;
        }
        break;
    }

    adc_decompressEnd(&strm);
    cli_dbgmsg("dmg_stripe_adc: stripe " STDu32 " actual len " STDu64 " expected len " STDu64 "\n",
            index, size_so_far, expected_len);
    return CL_CLEAN;
}