Example #1
0
int main(int argc, char *argv[])
/* Process command line. */
{
cgiSpoof(&argc, argv);
if (argc != 3)
    usage();
padFile(argv[1], atoi(argv[2]));
return 0;
}
Example #2
0
int BlockFileIO::truncate( loff_t size, FileIO *base )
{
    int partialBlock = size % _blockSize;
    int res = 0;

    loff_t oldSize = getSize();

    if( size > oldSize )
    {
	// truncate can be used to extend a file as well.  truncate man page
	// states that it will pad with 0's.
	// do the truncate so that the underlying filesystem can allocate
	// the space, and then we'll fill it in padFile..
	if(base)
	    base->truncate( size );

	const bool forceWrite = true;
	padFile( oldSize, size, forceWrite );
    } else
    if( size == oldSize )
    {
	// the easiest case, but least likely....
    } else
    if( partialBlock )
    {
	// partial block after truncate.  Need to read in the block being
	// truncated before the truncate.  Then write it back out afterwards,
	// since the encoding will change..
	loff_t blockNum = size / _blockSize;
	MemBlock mb = MemoryPool::allocate( _blockSize );

	IORequest req;
	req.offset = blockNum * _blockSize;
	req.dataLen = _blockSize;
	req.data = mb.data;

	ssize_t rdSz = cacheReadOneBlock( req );

	// do the truncate
	if(base)
	    res = base->truncate( size );

	// write back out partial block
	req.dataLen = partialBlock;
	bool wrRes = cacheWriteOneBlock( req );

	if((rdSz < 0) || (!wrRes))
	{
	    // rwarning - unlikely to ever occur..
	    rWarning(_("truncate failure: read %i bytes, partial block of %i"),
		    (int)rdSz, partialBlock );
	}

	MemoryPool::release( mb );
    } else
    {
	// truncating on a block bounday.  No need to re-encode the last
	// block..
	if(base)
	    res = base->truncate( size );
    }

    return res;
}
Example #3
0
bool BlockFileIO::write( const IORequest &req )
{
    rAssert( _blockSize != 0 );

    loff_t fileSize = getSize();

    // where write request begins
    loff_t blockNum = req.offset / _blockSize;
    int partialOffset = req.offset % _blockSize;

    // last block of file (for testing write overlaps with file boundary)
    loff_t lastFileBlock = fileSize / _blockSize;
    ssize_t lastBlockSize = fileSize % _blockSize;

    loff_t lastNonEmptyBlock = lastFileBlock;
    if(lastBlockSize == 0)
	--lastNonEmptyBlock;

    if( req.offset > fileSize )
    {
	// extend file first to fill hole with 0's..
	const bool forceWrite = false;
	padFile( fileSize, req.offset, forceWrite );
    }

    // check against edge cases where we can just let the base class handle the
    // request as-is..
    if(partialOffset == 0 && req.dataLen <= _blockSize)
    {
	// if writing a full block.. pretty safe..
	if( req.dataLen == _blockSize )
	    return cacheWriteOneBlock( req );
	
	// if writing a partial block, but at least as much as what is
	// already there..
	if(blockNum == lastFileBlock && req.dataLen >= lastBlockSize)
	    return cacheWriteOneBlock( req );
    } 

    // have to merge data with existing block(s)..
    MemBlock mb;

    IORequest blockReq;
    blockReq.data = NULL;
    blockReq.dataLen = _blockSize;
    
    bool ok = true;
    size_t size = req.dataLen;
    unsigned char *inPtr = req.data;
    while( size )
    {
	blockReq.offset = blockNum * _blockSize;
	int toCopy = min((size_t)(_blockSize - partialOffset), size);

	// if writing an entire block, or writing a partial block that requires
	// no merging with existing data..
	if(  (toCopy == _blockSize)
	   ||(partialOffset == 0 && blockReq.offset + toCopy >= fileSize))
	{
	    // write directly from buffer
	    blockReq.data = inPtr;
	    blockReq.dataLen = toCopy;
	} else
	{
	    // need a temporary buffer, since we have to either merge or pad
	    // the data.
	    if(!mb.data)
		mb = MemoryPool::allocate( _blockSize );
	    memset( mb.data, 0, _blockSize );
	    blockReq.data = mb.data;

	    if(blockNum > lastNonEmptyBlock)
	    {
		// just pad..
		blockReq.dataLen = toCopy + partialOffset;
	    } else
	    {
		// have to merge with existing block data..
		blockReq.dataLen = _blockSize;
		blockReq.dataLen = cacheReadOneBlock( blockReq );

		// extend data if necessary..
		if( partialOffset + toCopy > blockReq.dataLen )
		    blockReq.dataLen = partialOffset + toCopy;
	    }
	    // merge in the data to be written..
	    memcpy( blockReq.data + partialOffset, inPtr, toCopy );
	}

	// Finally, write the damn thing!
	if(!cacheWriteOneBlock( blockReq ))
	{
	    ok = false;
	    break;
	}

	// prepare to start all over with the next block..
	size -= toCopy;
	inPtr += toCopy;
	++blockNum;
	partialOffset = 0;
    }

    if(mb.data)
	MemoryPool::release( mb );

    return ok;
}
int main(int argc, char *argv[])
{
	FILE *f = NULL;
	FILE *out = NULL;
	FILE *sb = NULL;
	u32 i;
	header head;
	entry *entries = NULL;
	int r = 0;
	char name[1024];
	char soundboot[1024];
	char **filenames = NULL;

	if (argc != 3)
	{
		printf("bnk_pc_packer " VERSION "\n"
		       "usage: %s log.txt output.bnk_pc\n"
		       "log.txt is generated by bnk_pc_extractor, file filenames edited accordingly\n"
		       "only filename, id, dmav field are used in packing, the rest are recalculated\n"
		       "if packing dmav/wav combo files, the .dmav counterpart will be added\n"
		       "automatically\n", argv[0]);
		goto error;
	}

	f = fopen(argv[1], "r");

	if (f == NULL)
	{
		printf("log file %s can't be opened\n", argv[1]);
		goto error;
	}

	head.magic = BNK_PC_HEADER;

	fscanf(f, "ONLY EDIT THE FILENAMES\n");
	fscanf(f, "HEADER:\n");
	fscanf(f, "magic:  \"VWSBPC  \"\n");
	fscanf(f, "k1:     0x%08X\n", &(head.k1));
	fscanf(f, "k2:     0x%08X\n", &(head.k2));
	fscanf(f, "id:     0x%08X\n", &(head.id));
	fscanf(f, "k3:     0x%08X\n", &(head.k3));
	fscanf(f, "count:  0x%08X\n", &(head.count));

	// set this automatically, for hand-edited files
	head.k3 = sizeof(head) + (head.count + 1) * sizeof(entry);

	out = fopen(argv[2], "wb");
	fwrite(&head, sizeof(header), 1, out);
	entries = calloc(head.count, sizeof(entry));
	filenames = calloc(head.count, sizeof(char*));

	// loop 1: go through the log file and get the unknown metadata
	for (i = 0; i < head.count; i++)
	{
		u32 temp;
		u32 j;
		char _filename[1024];
		char *filename = _filename;

		fscanf(f, "\n%05u:", &temp);

		if (i != temp)
		{
			printf("entry count miss-match: expected %u, got %u\n", i, temp);
			goto error;
		}

		// needed for filenames with spaces
		fgets(_filename, sizeof(_filename), f);

		for (j = strlen(_filename) - 1; j > 0; j--)
		{
			if (is_whitespace(_filename[j]))
			{
				_filename[j] = 0;
			}
			else
			{
				break;
			}
		}

		for (j = 0; j < strlen(_filename); j++)
		{
			if (!is_whitespace(_filename[j]))
			{
				filename = &(_filename[j]);
				break;
			}
		}

		fscanf(f, "id:     0x%08X\n", &(entries[i].id));
		fscanf(f, "offset: 0x%08X\n", &(entries[i].offset));
		fscanf(f, "dmav:   0x%08X\n", &(entries[i].dmav));
		fscanf(f, "length: 0x%08X\n", &(entries[i].length));

		filenames[i] = calloc(strlen(filename) + 1, sizeof(char));
		memcpy(filenames[i], filename, strlen(filename) + 1);

		// write 0's for now, will come back and write actuall data later
		fwrite(padding, sizeof(entry), 1, out);
	}

	padFile(out);

	// loop 2: insert data
	for (i = 0; i < head.count; i++)
	{
		FILE *in;
		u8 *buffer;
		char _dmavname[1024];
		char dmavname[1024];
		entries[i].offset = ftell(out);

		if (entries[i].offset > 0x08000000)
		{
			printf("WARNING! audio bank is too long! Sound %05u (0x%08X) will not play\n", i, entries[i].id);
		}

		if (entries[i].dmav != 0)
		{
			u32 tell;
			memcpy(_dmavname, filenames[i], strlen(filenames[i]) + 1);
			_dmavname[strrchr(_dmavname, '.') - _dmavname] = 0;
			sprintf(dmavname, "%s.dmav", _dmavname);
			in = fopen(dmavname, "rb");

			if (in == NULL)
			{
				printf("could not open DMAV %s for reading\n", dmavname);
				goto error;
			}

			fseek(in, 0, SEEK_END);
			tell = ftell(in);

			if(tell != entries[i].dmav)
			{
				printf("DMAV (%s) wrong size; got %d, should be %d\n", dmavname, tell, entries[i].dmav);
				fclose(in);
				goto error;
			}

			fseek(in, 0, SEEK_SET);
			buffer = malloc(entries[i].dmav);
			fread(buffer, entries[i].dmav, 1, in);
			fclose(in);
			fwrite(buffer, entries[i].dmav, 1, out);
			free(buffer);
		}

		in = fopen(filenames[i], "rb");

		if (in == NULL)
		{
			printf("could not open %s for reading\n", filenames[i]);
			goto error;
		}

		fseek(in, 0, SEEK_END);
		entries[i].length = ftell(in);
		fseek(in, 0, SEEK_SET);
		buffer = malloc(entries[i].length);
		fread(buffer, entries[i].length, 1, in);
		fclose(in);
		fwrite(buffer, entries[i].length, 1, out);
		free(buffer);

		padFile(out);
	}

	// loop 3: go back and write updated entries
	fseek(out, sizeof(header), SEEK_SET);
	fwrite(entries, sizeof(entry), head.count, out);

	memcpy(name, argv[2], strlen(argv[2]) + 1);
	name[strrchr(name, '.') - name] = 0;
	sprintf(soundboot, "%s.mbnk_pc", name);
	sb = fopen(soundboot, "wb");
	fwrite(&head, sizeof(header), 1, sb);
	fwrite(entries, sizeof(entry), head.count, sb);

end:
	free(entries);

	if (filenames != NULL)
	{
		for (i = 0; i < head.count; i++)
		{
			free(filenames[i]);
		}

		free(filenames);
	}

	if (f != NULL)
	{
		fclose(f);
	}

	if (out != NULL)
	{
		fclose(out);
	}

	if (sb != NULL)
	{
		fclose(sb);
	}

	return r;

error:
	r = 1;
	goto end;
}
Example #5
0
void GmZipWriter::Write (unsigned char * pBuffer
						 , ubyte4 size
						 , bool bIsHeader/* = false*/
						 , bool bRightNow/* = false*/)
{
	if (bRightNow) {
		//
		// 在缓冲区内的数据保证在此这前已经被写入到文件,调用到这里只有在回写一个文件头时需要,
		// 所以,这里不需要对文件位置进行累加。
		//
		_pWriter->Write (pBuffer, size);
		return;
	}

	if (bIsHeader) {
		ubyte8 fileFree = getFileFree ();
		ubyte8 i64BufSpace = getBufferFree ();

		if (i64BufSpace >= size && fileFree >= size) {
			_pBlock->copy (reinterpret_cast<char *> (pBuffer), size);
			_stZipStat.ui64Position += size;
		}
		else if (fileFree < size) {
			// 文件空间已经不足,先将缓冲中的数据写入文件,再把pBuffer里的数据写入可用文件空间中。
			padFile ();
			createNewZipFile ();
		}
		else if (i64BufSpace < size) {
			//缓冲空间不足,先将数据写入文件。
			flush ();
			_pBlock->copy (reinterpret_cast<char *> (pBuffer), size);
			_stZipStat.ui64Position += size;
		}
    }
	else {
		while (true) {
			ubyte8 fileFree = getFileFree ();
			ubyte8 i64BufSpace = getBufferFree ();

			if (i64BufSpace >= size && fileFree >= size) {
				_pBlock->copy (reinterpret_cast<char *> (pBuffer), size);
				_stZipStat.ui64Position += size;
				break;
			}
			else if (fileFree < size) {
				// 文件空间已经不足,先将缓冲中的数据写入文件,再把pBuffer里的数据写入可用文件空间中。
				flush ();
				_pWriter->Write (pBuffer, (ubyte4) fileFree);
				pBuffer += (ubyte4) fileFree;
				size -= (ubyte4) fileFree;
				createNewZipFile ();
			}
			else if (i64BufSpace < size) {
				//缓冲空间不足,先将数据写入文件。
				flush ();
			}
		}
	}

	return;
}
Example #6
0
int C3dsTool::Action()
{
	if (m_eAction == kActionExtract)
	{
		if (!extractFile())
		{
			printf("ERROR: extract file failed\n\n");
			return 1;
		}
	}
	if (m_eAction == kActionCreate)
	{
		if (!createFile())
		{
			printf("ERROR: create file failed\n\n");
			return 1;
		}
	}
	if (m_eAction == kActionEncrypt)
	{
		if (!encryptFile())
		{
			printf("ERROR: encrypt file failed\n\n");
			return 1;
		}
	}
	if (m_eAction == kActionUncompress)
	{
		if (!uncompressFile())
		{
			printf("ERROR: uncompress file failed\n\n");
			return 1;
		}
	}
	if (m_eAction == kActionCompress)
	{
		if (!compressFile())
		{
			printf("ERROR: compress file failed\n\n");
			return 1;
		}
	}
	if (m_eAction == kActionTrim)
	{
		if (!trimFile())
		{
			printf("ERROR: trim file failed\n\n");
			return 1;
		}
	}
	if (m_eAction == kActionPad)
	{
		if (!padFile())
		{
			printf("ERROR: pad file failed\n\n");
			return 1;
		}
	}
	if (m_eAction == kActionDiff)
	{
		if (!diffFile())
		{
			printf("ERROR: create patch file failed\n\n");
			return 1;
		}
	}
	if (m_eAction == kActionPatch)
	{
		if (!patchFile())
		{
			printf("ERROR: apply patch file failed\n\n");
			return 1;
		}
	}
	if (m_eAction == kActionSample)
	{
		return sample();
	}
	if (m_eAction == kActionHelp)
	{
		return Help();
	}
	return 0;
}