diff options
| author | root <root@dc13.lemmi> | 2020-07-21 10:00:46 +0200 |
|---|---|---|
| committer | root <root@dc13.lemmi> | 2020-07-21 10:00:46 +0200 |
| commit | 1192c4575ea7afdf38e3fa0df4587a08620af11e (patch) | |
| tree | 6910a62487c282d0840d2e668aa7eb40b7c8a3fd /project/src/lib-pack.c | |
| parent | 76de8a89f7c1d1b4522eb66e8f89d248e8c1781f (diff) | |
SZS v2.18a
Diffstat (limited to '')
| -rw-r--r-- | project/src/lib-pack.c | 255 |
1 files changed, 255 insertions, 0 deletions
diff --git a/project/src/lib-pack.c b/project/src/lib-pack.c new file mode 100644 index 0000000..5961839 --- /dev/null +++ b/project/src/lib-pack.c @@ -0,0 +1,255 @@ + +/*************************************************************************** + * _______ _______ _______ * + * | ___ |____ | ___ | * + * | | |_| / /| | |_| * + * | |_____ / / | |_____ * + * |_____ | / / |_____ | * + * _ | | / / _ | | * + * | |___| |/ /____| |___| | * + * |_______|_______|_______| * + * * + * Wiimms SZS Tools * + * https://szs.wiimm.de/ * + * * + *************************************************************************** + * * + * This file is part of the SZS project. * + * Visit https://szs.wiimm.de/ for project details and sources. * + * * + * Copyright (c) 2011-2020 by Dirk Clemens <wiimm@wiimm.de> * + * * + *************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * See file gpl-2.0.txt or http://www.gnu.org/licenses/gpl-2.0.txt * + * * + ***************************************************************************/ + +#include "lib-pack.h" + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// IterateFilesPACK() /////////////// +/////////////////////////////////////////////////////////////////////////////// + +int IterateFilesPACK +( + struct szs_iterator_t *it, // iterator struct with all infos + bool term // true: termination hint +) +{ + if (term) + return 0; + + DASSERT(it); + DASSERT(it->func_it); + szs_file_t * szs = it->szs; + DASSERT(szs); + + if ( !szs->data || szs->size <= sizeof(pack_header_t) ) + return -1; + + //--- analyze file header + + const pack_header_t * pack = (pack_header_t*)szs->data; + const uint size = ntohl(pack->file_size); + const uint n_files = ntohl(pack->n_files); + const uint offset_metric = ntohl(pack->offset_metric); + + if + ( ntohl(pack->magic) != PACK_MAGIC_NUM + || size < szs->size + || offset_metric < 0x20 + || offset_metric + n_files * sizeof(pack_metric_t) >= size + ) + return -1; + + + //--- cut file header + + if (it->cut_files) + { + it->index = 0; + it->fst_item = 0; + it->is_dir = 0; + + it->off = 0; + it->size = sizeof(pack_header_t); + StringCopyS(it->path,sizeof(it->path),".PACK.header"); + it->func_it(it,false); + + it->off = sizeof(pack_header_t); + it->size = offset_metric; + StringCopyS(it->path,sizeof(it->path),".PACK.filenames"); + it->func_it(it,false); + + it->off = offset_metric; + it->size = offset_metric + n_files * sizeof(pack_metric_t); + StringCopyS(it->path,sizeof(it->path),".PACK.metric"); + it->func_it(it,false); + } + + + //--- sub files + + const pack_metric_t *metric = (pack_metric_t*)(szs->data+offset_metric); + ccp name = pack->name_pool; + + uint idx; + for ( idx = 0; idx < n_files; idx++, metric++ ) + { + while ( *name == '/' ) // skip leading slashes (security) + name++; + StringCopyS(it->path,sizeof(it->path),name); + name += strlen(name) + 1; + + it->index = idx+1; + it->fst_item = 0; + it->is_dir = 0; + + it->off = ntohl(metric->offset); + if ( it->off >= size ) + { + it->off = size; + it->size = 0; + } + else + { + it->size = ntohl(metric->size); + if ( it->size > size - it->off ) + it->size = size - it->off; + } + + it->func_it(it,false); + } + + return 0; +} + +/////////////////////////////////////////////////////////////////////////////// + +enumError CreatePACK +( + szs_file_t * szs, // valid szs + ccp source_dir, // NULL or path to source dir + u8 * source_data, // NULL or source data + u32 total_fsize, // total file size + SetupParam_t * setup_param // NULL or setup parameters +) +{ + DASSERT(szs); + PRINT("CreatePACK() ndir=%d, totfsize=%x, align=%x,%x\n", + szs->subfile.used, total_fsize, opt_align_breff, opt_align_pack ); + + //--- setup + + enumError max_err = ERR_OK; + const endian_func_t * endian = &be_func; + szs->endian = endian; + + szs->fform_arch = FF_PACK; + szs->ff_attrib = GetAttribFF(szs->fform_arch); + + SortSubFilesSZS(szs,SORT_AUTO); + + if ( logging > 1 ) + { + printf("\nsorted file list:\n"); + int i; + for ( i = 0; i < szs->subfile.used; i++ ) + { + szs_subfile_t * f = szs->subfile.list + i; + printf("%3d.: %u %6x %6x %s\n", i, f->is_dir, f->offset, f->size, f->path ); + } + } + + //--- calc segment sizes and alloc data + + u32 spool_size = 0, n_files = 0; + + int i; + szs_subfile_t * fptr; + for ( i = 0, fptr = szs->subfile.list; i < szs->subfile.used; i++, fptr++ ) + { + if (!fptr->is_dir) + { + n_files++; + spool_size += strlen(fptr->path) + 1; + } + } + + spool_size = ALIGN32(spool_size,PACK_METRIC_ALIGN); + const u32 metric_offset = sizeof(pack_header_t) + spool_size; + const u32 metric_size + = ALIGN32( n_files * sizeof(pack_metric_t), + opt_align_pack > PACK_METRIC_ALIGN ? opt_align_pack : PACK_METRIC_ALIGN ); + + total_fsize = ALIGN32(total_fsize,opt_align_pack); + u32 file_offset = ALIGN32(metric_offset+metric_size,opt_align_pack); + + szs->size = file_offset + total_fsize; + szs->data = CALLOC(1,szs->size); + + noPRINT(">>> SIZE=%zu=%#zx, N=%u,%u\n", + szs->size, szs->size, n_files, szs->subfile.used ); + + + //--- setup header + + pack_header_t *ph = (pack_header_t*)szs->data; + ph->magic = htonl(PACK_MAGIC_NUM); + ph->file_size = htonl(szs->size); + ph->n_files = htonl(n_files); + ph->offset_metric = htonl(metric_offset); + + + //--- copy files + + pack_metric_t *metric = (pack_metric_t*)(szs->data+metric_offset); + char *name = ph->name_pool; + char *name_end = (char*)metric; + + for ( i = 0, fptr = szs->subfile.list; i < szs->subfile.used; i++, fptr++ ) + { + MARK_USED(name,name_end); + if (!fptr->is_dir) + { + name = StringCopyE(name,name_end,fptr->path); + name++; + + metric->offset = htonl(file_offset); + metric->size = htonl(fptr->size); + metric++; + + if (fptr->data) + memcpy(szs->data + file_offset, fptr->data, fptr->size ); + else + { + PRINT("LOAD: %x+%x %s\n",file_offset,fptr->size,fptr->path); + enumError err = LoadFILE( source_dir, fptr->path, 0, + szs->data + file_offset, fptr->size, 0, &szs->fatt, true ); + if ( max_err < err ) + max_err = err; + } + file_offset += ALIGN32(fptr->size,opt_align_pack); + } + } + + return max_err; +} + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// END /////////////// +/////////////////////////////////////////////////////////////////////////////// + |
