int main(int argc, char *argv[]) /* Process command line. */ { cgiSpoof(&argc, argv); if (argc != 3) usage(); padFile(argv[1], atoi(argv[2])); return 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; }
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; }
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; }
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; }