Example #1
0
// _InitFile
void
ResourceFile::_InitFile(BFile& file)
{
	status_t error = B_OK;
	fFile.Unset();
	// read the first four bytes, and check, if they identify a resource file
	char magic[4];
	read_exactly(file, 0, magic, 4, "Failed to read magic number.");
	if (!memcmp(magic, kX86ResourceFileMagic, 4)) {
		// x86 resource file
		fHostEndianess = B_HOST_IS_LENDIAN;
		fFileType = FILE_TYPE_X86_RESOURCE;
		fFile.SetTo(file, kX86ResourcesOffset);
	} else if (!memcmp(magic, kPEFFileMagic1, 4)) {
		PEFContainerHeader pefHeader;
		read_exactly(file, 0, &pefHeader, kPEFContainerHeaderSize,
					 "Failed to read PEF container header.");
		if (!memcmp(pefHeader.tag2, kPPCResourceFileMagic, 4)) {
			// PPC resource file
			fHostEndianess = B_HOST_IS_BENDIAN;
			fFileType = FILE_TYPE_PPC_RESOURCE;
			fFile.SetTo(file, kPPCResourcesOffset);
		} else if (!memcmp(pefHeader.tag2, kPEFFileMagic2, 4)) {
			// PEF file
			fFileType = FILE_TYPE_PEF;
			_InitPEFFile(file, pefHeader);
		} else
			throw Exception("File is not a resource file.");
	} else if (!memcmp(magic, kELFFileMagic, 4)) {
		// ELF file
		fFileType = FILE_TYPE_ELF;
		_InitELFFile(file);
	} else if (!memcmp(magic, kX86ResourceFileMagic, 2)) {
		// x86 resource file with screwed magic?
		Warnings::AddCurrentWarning("File magic is 0x%08lx. Should be 0x%08lx "
									"for x86 resource file. Try anyway.",
									ntohl(*(uint32*)magic),
									ntohl(*(uint32*)kX86ResourceFileMagic));
		fHostEndianess = B_HOST_IS_LENDIAN;
		fFileType = FILE_TYPE_X86_RESOURCE;
		fFile.SetTo(file, kX86ResourcesOffset);
	} else
		throw Exception("File is not a resource file.");
	error = fFile.InitCheck();
	if (error != B_OK)
		throw Exception(error, "Failed to initialize resource file.");
	// get the file size
	fFileSize = 0;
	error = fFile.GetSize(&fFileSize);
	if (error != B_OK)
		throw Exception(error, "Failed to get the file size.");
}
Example #2
0
void recording_frame_block_t::load_from(int fd, uint32 *n_frames)
{
	for (int i = 0; i < RECORDING_BLOCK_FRAMES; ++i) {
		if (!*n_frames) return;
		*n_frames -= 1;
		recording_frame_t *f = &frames[i];
		unsigned char op;
		read_exactly(&op, fd, sizeof op);
		f->op = (recording_op_t)op;
		read_exactly(&f->microseconds, fd, sizeof f->microseconds);
		read_exactly(&f->arg, fd, sizeof f->arg);
	}
}
Example #3
0
int helper_getreply(void *user)
{
    int v;
    int r = read_exactly(0, &v, sizeof(v));
    if (r<=0) exit(-2);
    return v;
}
Example #4
0
int main(void)
{
  unsigned size = 0;
  size_t cgc_read = 0;
  uint8_t buf[MAX_SIZE];
  cgc_memset(buf, 0, sizeof(buf));

  if (receive(STDIN, &size, sizeof(size), &cgc_read) != 0)
    cgc_exit(1);

  if (cgc_read != 4)
    cgc_exit(1);

  if (size > MAX_SIZE) {
    printf("too big\n");
    cgc_exit(1);
  }

  if (read_exactly(STDIN, buf, size) != 0)
    cgc_exit(1);

  element *e = decode(buf, (unsigned) buf + size);
  if (e == NULL)
    cgc_exit(1);

  pprint(e);
}
Example #5
0
// WriteTest
void
ResourceFile::WriteTest()
{
	uint32 size = GetResourcesSize();
	if (size != fFileSize) {
		throw Exception("Calculated resources size differs from actual size "
						"in file: %lu vs %Ld.", size, fFileSize);
	}
	char* buffer1 = new char[size];
	char* buffer2 = new char[size];
	try {
		WriteResources(buffer1, size);
		read_exactly(fFile, 0, buffer2, size,
					 "Write test: Error reading resources.");
		for (uint32 i = 0; i < size; i++) {
			if (buffer1[i] != buffer2[i]) {
				off_t filePosition = fFile.GetOffset() + i;
				throw Exception("Written resources differ from those in file. "
								"First difference at byte %lu (file position "
								"%Ld): %x vs %x.", i, filePosition,
								(int)buffer1[i] & 0xff,
								(int)buffer2[i] & 0xff);
			}
		}
	} catch (Exception exception) {
		delete[] buffer1;
		delete[] buffer2;
		throw exception;
	}
	delete[] buffer1;
	delete[] buffer2;
}
Example #6
0
void sheepshaver_state::load_descs(int fd)
{
	TMDesc *prev = NULL, *first = NULL, *cur;
#if PRECISE_TIMING
	timer_thread_suspend();
	pthread_mutex_lock(&wakeup_time_lock);
#endif
	clear_descs();
	while (1) {
		cur = new TMDesc;
		read_exactly(cur, fd, sizeof *cur);
		if (!cur->task && !cur->next) {
			delete cur;
			break;
		}
		if (prev) {
			prev->next = cur;
		}
		if (!first) {
			first = cur;
		}
		prev = cur;
	}
	if (prev) {
		prev->next = NULL;
	}
	tmDescList = first;
#if PRECISE_TIMING
	pthread_mutex_unlock(&wakeup_time_lock);
	timer_thread_resume();
	assert(suspend_count == 0);
#endif
}
Example #7
0
void recording_t::load_from(int fd)
{
	recording_frame_block_t *prev = NULL, *fb = NULL;
	time_state_t *t = &header.time_state;
	uint32 frames;
	read_exactly(&t->microseconds, fd, sizeof t->microseconds);
	read_exactly(&t->base_time, fd, sizeof t->base_time);
	read_exactly(&frames, fd, sizeof frames);
	while (frames) {
		fb = new recording_frame_block_t;
		fb->load_from(fd, &frames);
		if (prev) {
			prev->next = fb;
			fb->prev = prev;
		} else {
			first_block = current_block = fb;
		}
		prev = fb;
	}
	current_frame = 0;
	countdown = 0;
	done = false;
}
Example #8
0
// _ReadHeader
void
ResourceFile::_ReadHeader()
{
	// read the header
	resources_header header;
	read_exactly(fFile, 0, &header, kResourcesHeaderSize,
				 "Failed to read the header.");
	// check the header
	// magic
	uint32 magic = _GetUInt32(header.rh_resources_magic);
	if (magic == kResourcesHeaderMagic) {
		// everything is fine
	} else if (B_SWAP_INT32(magic) == kResourcesHeaderMagic) {
		const char* endianessStr[2] = { "little", "big" };
		int32 endianess
			= (fHostEndianess == ((bool)B_HOST_IS_LENDIAN ? 0 : 1));
		Warnings::AddCurrentWarning("Endianess seems to be %s, although %s "
									"was expected.",
									endianessStr[1 - endianess],
									endianessStr[endianess]);
		fHostEndianess = !fHostEndianess;
	} else
		throw Exception("Invalid resources header magic.");
	// resource count
	uint32 resourceCount = _GetUInt32(header.rh_resource_count);
	if (resourceCount > kMaxResourceCount)
		throw Exception("Bad number of resources.");
	// index section offset
	uint32 indexSectionOffset = _GetUInt32(header.rh_index_section_offset);
	if (indexSectionOffset != kResourceIndexSectionOffset) {
		throw Exception("Unexpected resource index section offset. Is: %lu, "
						"should be: %lu.", indexSectionOffset,
						kResourceIndexSectionOffset);
	}
	// admin section size
	uint32 indexSectionSize = kResourceIndexSectionHeaderSize
							  + kResourceIndexEntrySize * resourceCount;
	indexSectionSize = align_value(indexSectionSize,
								   kResourceIndexSectionAlignment);
	uint32 adminSectionSize = _GetUInt32(header.rh_admin_section_size);
	if (adminSectionSize != indexSectionOffset + indexSectionSize) {
		throw Exception("Unexpected resource admin section size. Is: %lu, "
						"should be: %lu.", adminSectionSize,
						indexSectionOffset + indexSectionSize);
	}
	// set the resource count
	fResourceCount = resourceCount;
}
Example #9
0
static int toolstack_save_cb(uint32_t domid, uint8_t **buf,
                             uint32_t *len, void *data)
{
    assert(toolstack_save_fd > 0);

    int r = lseek(toolstack_save_fd, 0, SEEK_SET);
    if (r) fail(errno,"rewind toolstack data tmpfile");

    *buf = xmalloc(toolstack_save_len);
    r = read_exactly(toolstack_save_fd, *buf, toolstack_save_len);
    if (r<0) fail(errno,"read toolstack data");
    if (r==0) fail(0,"read toolstack data eof");

    *len = toolstack_save_len;
    return 0;
}
Example #10
0
// _InitPEFFile
void
ResourceFile::_InitPEFFile(BFile& file, const PEFContainerHeader& pefHeader)
{
	status_t error = B_OK;
	// get the file size
	off_t fileSize = 0;
	error = file.GetSize(&fileSize);
	if (error != B_OK)
		throw Exception(error, "Failed to get the file size.");
	// check architecture -- we support PPC only
	if (memcmp(pefHeader.architecture, kPEFArchitecturePPC, 4))
		throw Exception("PEF file architecture is not PPC.");
	fHostEndianess = B_HOST_IS_BENDIAN;
	// get the section count
	uint16 sectionCount = _GetUInt16(pefHeader.sectionCount);
	// iterate through the PEF sections headers
	uint32 sectionHeaderTableOffset = kPEFContainerHeaderSize;
	uint32 sectionHeaderTableEnd
		= sectionHeaderTableOffset + sectionCount * kPEFSectionHeaderSize;
	uint32 resourceOffset = sectionHeaderTableEnd;
	for (int32 i = 0; i < (int32)sectionCount; i++) {
		uint32 shOffset = sectionHeaderTableOffset + i * kPEFSectionHeaderSize;
		PEFSectionHeader sectionHeader;
		read_exactly(file, shOffset, &sectionHeader, kPEFSectionHeaderSize,
					 "Failed to read PEF section header.");
		// get the header values
		uint32 offset	= _GetUInt32(sectionHeader.containerOffset);
		uint32 size		= _GetUInt32(sectionHeader.packedSize);
		// check the values
		if (offset < sectionHeaderTableEnd || offset > fileSize) {
			throw Exception("Invalid PEF section header: invalid "
							"section offset: %lu.", offset);
		}
		uint32 sectionEnd = offset + size;
		if (sectionEnd > fileSize) {
			throw Exception("Invalid PEF section header: section "
							"exceeds file: %lu.", sectionEnd);
		}
		resourceOffset = max(resourceOffset, sectionEnd);
	}
	// init the offset file
	fFile.SetTo(file, resourceOffset);
}
Example #11
0
// _ReadIndexEntry
bool
ResourceFile::_ReadIndexEntry(int32 index, uint32 tableOffset, bool peekAhead)
{
	bool result = true;
	resource_index_entry entry;
	// read one entry
	off_t entryOffset = tableOffset + index * kResourceIndexEntrySize;
	read_exactly(fFile, entryOffset, &entry, kResourceIndexEntrySize,
				 "Failed to read a resource index entry.");
	// check, if the end is reached early
	if (result && check_pattern(entryOffset, &entry,
								kResourceIndexEntrySize / 4, fHostEndianess)) {
		if (!peekAhead) {
			Warnings::AddCurrentWarning("Unexpected end of resource index "
										"table at index: %ld (/%ld).",
										index + 1, fResourceCount);
		}
		result = false;
	}
	uint32 offset = _GetUInt32(entry.rie_offset);
	uint32 size = _GetUInt32(entry.rie_size);
	// check the location
	if (result && offset + size > fFileSize) {
		if (peekAhead) {
			Warnings::AddCurrentWarning("Invalid data after resource index "
										"table.");
		} else {
			throw Exception("Invalid resource index entry: index: %ld, "
							"offset: %lu (%lx), size: %lu (%lx).", index + 1,
							offset, offset, size, size);
		}
		result = false;
	}
	// add the entry
	if (result) {
		ResourceItem* item = new ResourceItem;
		item->SetLocation(offset, size);
		AddItem(item, index);
	}
	return result;
}
Example #12
0
// _ReadIndex
void
ResourceFile::_ReadIndex()
{
	// read the header
	resource_index_section_header header;
	read_exactly(fFile, kResourceIndexSectionOffset, &header,
				 kResourceIndexSectionHeaderSize,
				 "Failed to read the resource index section header.");
	// check the header
	// index section offset
	uint32 indexSectionOffset = _GetUInt32(header.rish_index_section_offset);
	if (indexSectionOffset != kResourceIndexSectionOffset) {
		throw Exception("Unexpected resource index section offset. Is: %lu, "
						"should be: %lu.", indexSectionOffset,
						kResourceIndexSectionOffset);
	}
	// index section size
	uint32 expectedIndexSectionSize = kResourceIndexSectionHeaderSize
		+ kResourceIndexEntrySize * fResourceCount;
	expectedIndexSectionSize = align_value(expectedIndexSectionSize,
										   kResourceIndexSectionAlignment);
	uint32 indexSectionSize = _GetUInt32(header.rish_index_section_size);
	if (indexSectionSize != expectedIndexSectionSize) {
		throw Exception("Unexpected resource index section size. Is: %lu, "
						"should be: %lu.", indexSectionSize,
						expectedIndexSectionSize);
	}
	// unknown section offset
	uint32 unknownSectionOffset
		= _GetUInt32(header.rish_unknown_section_offset);
	if (unknownSectionOffset != indexSectionOffset + indexSectionSize) {
		throw Exception("Unexpected resource index section size. Is: %lu, "
						"should be: %lu.", unknownSectionOffset,
						indexSectionOffset + indexSectionSize);
	}
	// unknown section size
	uint32 unknownSectionSize = _GetUInt32(header.rish_unknown_section_size);
	if (unknownSectionSize != kUnknownResourceSectionSize) {
		throw Exception("Unexpected resource index section offset. Is: %lu, "
						"should be: %lu.", unknownSectionOffset,
						kUnknownResourceSectionSize);
	}
	// info table offset and size
	uint32 infoTableOffset = _GetUInt32(header.rish_info_table_offset);
	uint32 infoTableSize = _GetUInt32(header.rish_info_table_size);
	if (infoTableOffset + infoTableSize > fFileSize)
		throw Exception("Invalid info table location.");
	fInfoTableItem = new ResourceItem;
	fInfoTableItem->SetLocation(infoTableOffset, infoTableSize);
	// read the index entries
	uint32 indexTableOffset = indexSectionOffset
							  + kResourceIndexSectionHeaderSize;
	int32 maxResourceCount = (unknownSectionOffset - indexTableOffset)
							 / kResourceIndexEntrySize;
	int32 actualResourceCount = 0;
	bool tableEndReached = false;
	for (int32 i = 0; !tableEndReached && i < maxResourceCount; i++) {
		// read one entry
		tableEndReached = !_ReadIndexEntry(i, indexTableOffset,
										   (i >= fResourceCount));
		if (!tableEndReached)
			actualResourceCount++;
	}
	// check resource count
	if (actualResourceCount != fResourceCount) {
		if (actualResourceCount > fResourceCount) {
			Warnings::AddCurrentWarning("Resource index table contains "
										"%ld entries, although it should be "
										"%ld only.", actualResourceCount,
										fResourceCount);
		}
		fResourceCount = actualResourceCount;
	}
}
Example #13
0
// _InitELFFile
void
ResourceFile::_InitELFFile(BFile& file)
{
	status_t error = B_OK;
	// get the file size
	off_t fileSize = 0;
	error = file.GetSize(&fileSize);
	if (error != B_OK)
		throw Exception(error, "Failed to get the file size.");
	// read ELF header
	Elf32_Ehdr fileHeader;
	read_exactly(file, 0, &fileHeader, sizeof(Elf32_Ehdr),
				 "Failed to read ELF header.");
	// check data encoding (endianess)
	switch (fileHeader.e_ident[EI_DATA]) {
		case ELFDATA2LSB:
			fHostEndianess = B_HOST_IS_LENDIAN;
			break;
		case ELFDATA2MSB:
			fHostEndianess = B_HOST_IS_BENDIAN;
			break;
		default:
		case ELFDATANONE:
			throw Exception("Unsupported ELF data encoding.");
			break;
	}
	// get the header values
	uint32 headerSize				= _GetUInt16(fileHeader.e_ehsize);
	uint32 programHeaderTableOffset	= _GetUInt32(fileHeader.e_phoff);
	uint32 programHeaderSize		= _GetUInt16(fileHeader.e_phentsize);
	uint32 programHeaderCount		= _GetUInt16(fileHeader.e_phnum);
	uint32 sectionHeaderTableOffset	= _GetUInt32(fileHeader.e_shoff);
	uint32 sectionHeaderSize		= _GetUInt16(fileHeader.e_shentsize);
	uint32 sectionHeaderCount		= _GetUInt16(fileHeader.e_shnum);
	bool hasProgramHeaderTable = (programHeaderTableOffset != 0);
	bool hasSectionHeaderTable = (sectionHeaderTableOffset != 0);
//printf("headerSize              : %lu\n", headerSize);
//printf("programHeaderTableOffset: %lu\n", programHeaderTableOffset);
//printf("programHeaderSize       : %lu\n", programHeaderSize);
//printf("programHeaderCount      : %lu\n", programHeaderCount);
//printf("sectionHeaderTableOffset: %lu\n", sectionHeaderTableOffset);
//printf("sectionHeaderSize       : %lu\n", sectionHeaderSize);
//printf("sectionHeaderCount      : %lu\n", sectionHeaderCount);
	// check the sanity of the header values
	// ELF header size
	if (headerSize < sizeof(Elf32_Ehdr) || headerSize > kMaxELFHeaderSize) {
		throw Exception("Invalid ELF header: invalid ELF header size: %lu.",
						headerSize);
	}
	uint32 resourceOffset = headerSize;
	uint32 resourceAlignment = 0;
	// program header table offset and entry count/size
	uint32 programHeaderTableSize = 0;
	if (hasProgramHeaderTable) {
		if (programHeaderTableOffset < headerSize
			|| programHeaderTableOffset > fileSize) {
			throw Exception("Invalid ELF header: invalid program header table "
							"offset: %lu.", programHeaderTableOffset);
		}
		programHeaderTableSize = programHeaderSize * programHeaderCount;
		if (programHeaderSize < sizeof(Elf32_Phdr)
			|| programHeaderTableOffset + programHeaderTableSize > fileSize) {
			throw Exception("Invalid ELF header: program header table exceeds "
							"file: %lu.",
							programHeaderTableOffset + programHeaderTableSize);
		}
		resourceOffset = max(resourceOffset, programHeaderTableOffset
											 + programHeaderTableSize);
		// iterate through the program headers
		for (int32 i = 0; i < (int32)programHeaderCount; i++) {
			uint32 shOffset = programHeaderTableOffset + i * programHeaderSize;
			Elf32_Phdr programHeader;
			read_exactly(file, shOffset, &programHeader, sizeof(Elf32_Shdr),
						 "Failed to read ELF program header.");
			// get the header values
			uint32 type			= _GetUInt32(programHeader.p_type);
			uint32 offset		= _GetUInt32(programHeader.p_offset);
			uint32 size			= _GetUInt32(programHeader.p_filesz);
			uint32 alignment	= _GetUInt32(programHeader.p_align);
//printf("segment: type: %ld, offset: %lu, size: %lu, alignment: %lu\n",
//type, offset, size, alignment);
			// check the values
			// PT_NULL marks the header unused,
			if (type != PT_NULL) {
				if (/*offset < headerSize ||*/ offset > fileSize) {
					throw Exception("Invalid ELF program header: invalid "
									"program offset: %lu.", offset);
				}
				uint32 segmentEnd = offset + size;
				if (segmentEnd > fileSize) {
					throw Exception("Invalid ELF section header: segment "
									"exceeds file: %lu.", segmentEnd);
				}
				resourceOffset = max(resourceOffset, segmentEnd);
				resourceAlignment = max(resourceAlignment, alignment);
			}
		}
	}
	// section header table offset and entry count/size
	uint32 sectionHeaderTableSize = 0;
	if (hasSectionHeaderTable) {
		if (sectionHeaderTableOffset < headerSize
			|| sectionHeaderTableOffset > fileSize) {
			throw Exception("Invalid ELF header: invalid section header table "
							"offset: %lu.", sectionHeaderTableOffset);
		}
		sectionHeaderTableSize = sectionHeaderSize * sectionHeaderCount;
		if (sectionHeaderSize < sizeof(Elf32_Shdr)
			|| sectionHeaderTableOffset + sectionHeaderTableSize > fileSize) {
			throw Exception("Invalid ELF header: section header table exceeds "
							"file: %lu.",
							sectionHeaderTableOffset + sectionHeaderTableSize);
		}
		resourceOffset = max(resourceOffset, sectionHeaderTableOffset
											 + sectionHeaderTableSize);
		// iterate through the section headers
		for (int32 i = 0; i < (int32)sectionHeaderCount; i++) {
			uint32 shOffset = sectionHeaderTableOffset + i * sectionHeaderSize;
			Elf32_Shdr sectionHeader;
			read_exactly(file, shOffset, &sectionHeader, sizeof(Elf32_Shdr),
						 "Failed to read ELF section header.");
			// get the header values
			uint32 type		= _GetUInt32(sectionHeader.sh_type);
			uint32 offset	= _GetUInt32(sectionHeader.sh_offset);
			uint32 size		= _GetUInt32(sectionHeader.sh_size);
//printf("section: type: %ld, offset: %lu, size: %lu\n", type, offset, size);
			// check the values
			// SHT_NULL marks the header unused,
			// SHT_NOBITS sections take no space in the file
			if (type != SHT_NULL && type != SHT_NOBITS) {
				if (offset < headerSize || offset > fileSize) {
					throw Exception("Invalid ELF section header: invalid "
									"section offset: %lu.", offset);
				}
				uint32 sectionEnd = offset + size;
				if (sectionEnd > fileSize) {
					throw Exception("Invalid ELF section header: section "
									"exceeds file: %lu.", sectionEnd);
				}
				resourceOffset = max(resourceOffset, sectionEnd);
			}
		}
	}
//printf("resourceOffset: %lu\n", resourceOffset);
	// align the offset
	if (resourceAlignment < kELFMinResourceAlignment)
		resourceAlignment = kELFMinResourceAlignment;
	if (resourceAlignment > kELFMaxResourceAlignment) {
		throw Exception("The ELF object file requires an invalid alignment: "
						"%lu.", resourceAlignment);
	}
	resourceOffset = align_value(resourceOffset, resourceAlignment);
//printf("resourceOffset: %lu\n", resourceOffset);
	if (resourceOffset >= fileSize)
		throw Exception("The ELF object file does not contain resources.");
	// fine, init the offset file
	fFile.SetTo(file, resourceOffset);
}
static int run_client(FILE * si, FILE * so) {
    uint64_t length = 0;
    uint8_t type[20] = { 0 };
    size_t rlen;

    if (!read_exactly(si, &length, schema_length_word_size, &rlen)) {
        fprintf(stderr, "Length expected %lu bytes but got %lu bytes.\n",
                schema_length_word_size, rlen);
        return __LINE__;
    }

    if (0 == length) {
        fprintf(stderr, "Length is 0.\n");
        return __LINE__;
    }

    if (!read_exactly(si, type, schema_tag_size, &rlen)) {
        fprintf(stderr, "Type expected %lu bytes but got %lu bytes.\n",
                schema_tag_size, rlen);
        return __LINE__;
    }

    void * const buffer = calloc(length, sizeof(uint8_t));

    if (!read_exactly(si, buffer, length, &rlen)) {
        fprintf(stderr, "Header indicated %llu bytes are needed but only got %lu bytes.\n",
                length, rlen);
        return __LINE__;
    }

    struct type_descriptor const * const t = find_type(type, schema_tag_size);

    if (NULL == t) {
        fprintf(stderr, "Could not find type matching tag.\n");
        return __LINE__;
    }

    void * out_buffer = calloc(length, sizeof(uint8_t));
    int const tret = transcode(buffer, out_buffer, length, t);

    if (0 != tret) {
        free(out_buffer);
        return tret;
    }

    if (schema_length_word_size != fwrite(&length, 1, schema_length_word_size, so)) {
        fprintf(stderr, "Could not completely write length.\n");
        return __LINE__;
    }
    if (schema_tag_size != fwrite(type, 1, schema_tag_size, so)) {
        fprintf(stderr, "Could not completely write tag.\n");
        return __LINE__;
    }
    if (length != fwrite(out_buffer, 1, length, so)) {
        fprintf(stderr, "Could not completely write output buffer.\n");
        return __LINE__;
    }

    free(out_buffer);

    return 0;
}