You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
503 lines
14 KiB
C
503 lines
14 KiB
C
2 years ago
|
/*
|
||
|
* Sp3MM_for_AlgebraicMultiGrid
|
||
|
* (C) Copyright 2021-2022
|
||
|
* Andrea Di Iorio
|
||
|
*
|
||
|
* Redistribution and use in source and binary forms, with or without
|
||
|
* modification, are permitted provided that the following conditions
|
||
|
* are met:
|
||
|
* 1. Redistributions of source code must retain the above copyright
|
||
|
* notice, this list of conditions and the following disclaimer.
|
||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||
|
* notice, this list of conditions, and the following disclaimer in the
|
||
|
* documentation and/or other materials provided with the distribution.
|
||
|
* 3. The name of the Sp3MM_for_AlgebraicMultiGrid or the names of its contributors may
|
||
|
* not be used to endorse or promote products derived from this
|
||
|
* software without specific written permission.
|
||
|
*
|
||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||
|
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE Sp3MM_for_AlgebraicMultiGrid GROUP OR ITS CONTRIBUTORS
|
||
|
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||
|
*/
|
||
|
|
||
|
//various aux functions
|
||
|
#include <unistd.h>
|
||
|
#include <sys/types.h>
|
||
|
#include <sys/stat.h>
|
||
|
#include <fcntl.h>
|
||
|
//#include <stddef.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <stdio.h>
|
||
|
#include <string.h>
|
||
|
#include <math.h>
|
||
|
#include <errno.h>
|
||
|
#include <limits.h>
|
||
|
|
||
|
#include "macros.h"
|
||
|
#include "sparseMatrix.h"
|
||
|
#include "utils.h"
|
||
|
|
||
|
|
||
|
int urndFd; //will point to urandom device file
|
||
|
|
||
|
///IO
|
||
|
//UNBUFFERED IO
|
||
|
int write_wrap(int fd,void* src,size_t count){
|
||
|
ssize_t wr;
|
||
|
size_t written=0;
|
||
|
while (written < count){
|
||
|
wr=write(fd,src+written,count-written);
|
||
|
if (wr<0){
|
||
|
perror("write");
|
||
|
return wr;
|
||
|
}
|
||
|
written+=wr;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int read_wrap(int fd,void* dst,size_t count){
|
||
|
ssize_t rd;
|
||
|
size_t readed=0;
|
||
|
while (readed < count){
|
||
|
rd=read(fd,dst+readed,count-readed);
|
||
|
if (rd<0){
|
||
|
perror("read");
|
||
|
return rd;
|
||
|
}
|
||
|
readed+=rd;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int readALL_wrap(int fd,char** dst,size_t* count){
|
||
|
ssize_t rd=!0; //to allow count > fsize
|
||
|
size_t readed=0;
|
||
|
char allocated=0; //flag if required *dst allocation
|
||
|
if (!(*dst)){ //allocate dst buffer of same size of file
|
||
|
off_t seekCurr=lseek(fd,0,SEEK_CUR);
|
||
|
off_t fsize=lseek(fd,0,SEEK_END);
|
||
|
if( seekCurr==-1 || fsize==-1 || lseek(fd,seekCurr,SEEK_SET)==-1){
|
||
|
perror("lseek");
|
||
|
return EXIT_FAILURE;
|
||
|
}
|
||
|
*count=fsize;
|
||
|
if (!(*dst=malloc(fsize))){
|
||
|
fprintf(stderr,"malloc read_wrap file size buf error\n");
|
||
|
return EXIT_FAILURE;
|
||
|
}
|
||
|
allocated=!0;
|
||
|
}
|
||
|
//read loop
|
||
|
while (readed < *count && rd > 0){
|
||
|
rd=read(fd,(*dst)+readed,*count-readed);
|
||
|
if (rd<0){
|
||
|
perror("read");
|
||
|
if (allocated) free(*dst);
|
||
|
return rd;
|
||
|
}
|
||
|
readed+=rd;
|
||
|
}
|
||
|
if (readed < *count) (*dst)[readed]='\0'; //TODO NEEDED?
|
||
|
return EXIT_SUCCESS;
|
||
|
}
|
||
|
int init_urndfd(){ // wrap init urndFd
|
||
|
if((urndFd=open(DRNG_DEVFILE,O_RDONLY))<0){
|
||
|
perror("open DRNG_DEVFILE");
|
||
|
return EXIT_FAILURE;
|
||
|
}
|
||
|
return EXIT_SUCCESS;
|
||
|
}
|
||
|
int createNewFile(char* const outFpath){
|
||
|
int mode=S_IRWXU;
|
||
|
errno = 0;
|
||
|
int outFd=open(outFpath, O_WRONLY | O_CREAT | O_TRUNC, mode);
|
||
|
if (errno==EEXIST) outFd=open(outFpath, O_WRONLY | O_TRUNC, mode);
|
||
|
if (outFd<0) perror("open outFd failed ");
|
||
|
return outFd;
|
||
|
}
|
||
|
///BUFFERED IO
|
||
|
//TODO series of 0 returns.... fix
|
||
|
int fread_wrap(FILE* fp,void* dst,size_t count){
|
||
|
int rd=0,toRead;
|
||
|
size_t readed=0;
|
||
|
while (readed < count){
|
||
|
toRead = count - readed;
|
||
|
rd=fread(dst+readed,1,toRead,fp);
|
||
|
if (rd != toRead){ //TODO SHORT ITEM COUNT
|
||
|
if (feof(fp)) return EOF;
|
||
|
else if (ferror(fp)){
|
||
|
ERRPRINT("fread_wrap errd\n");
|
||
|
return -2;
|
||
|
}
|
||
|
//else ERRPRINT("W** SHORT ITEM COUNT RETURN MEANS!?"); //TODO OO
|
||
|
}
|
||
|
readed+=rd;
|
||
|
}
|
||
|
return rd;
|
||
|
}
|
||
|
///STRUCTURED DATA IO
|
||
|
int writeDoubleVector(char* fpath,double* v,ulong size){
|
||
|
int fd,out=EXIT_FAILURE;
|
||
|
if ( (fd = createNewFile(fpath) ) < 0 ) goto _end;
|
||
|
write_wrap(fd,v,size * sizeof(*v)); //raw write of vector
|
||
|
out = EXIT_SUCCESS;
|
||
|
DEBUG printf("written double vector into %s RAW of %lu elements\n",fpath,size);
|
||
|
|
||
|
_end:
|
||
|
if (close(fd) == EOF) perror("close errd\n");
|
||
|
return out;
|
||
|
}
|
||
|
|
||
|
///STRUCTURED DATA IO -- BUFFERED: FSCANF - FPRINTF
|
||
|
int writeDoubleVectorAsStr(char* fpath,double* v,ulong size){
|
||
|
int out=EXIT_FAILURE;
|
||
|
FILE* fp = fopen(fpath,"w");
|
||
|
if (!fp){
|
||
|
perror("fopen vector file write");
|
||
|
return EXIT_FAILURE;
|
||
|
}
|
||
|
for (ulong i=0; i<size; i++){
|
||
|
if (fprintf(fp,DOUBLE_STR_FORMAT,v[i]) < 0){
|
||
|
ERRPRINT("fprintf to out vector file errd\n");
|
||
|
goto _end;
|
||
|
}
|
||
|
}
|
||
|
out = EXIT_SUCCESS;
|
||
|
DEBUG printf("written vector into %s of %lu elements\n",fpath,size);
|
||
|
|
||
|
_end:
|
||
|
if (fclose(fp) == EOF) perror("fclose errd\n");
|
||
|
return out;
|
||
|
|
||
|
}
|
||
|
|
||
|
double* readDoubleVector(char* fpath,ulong* size){
|
||
|
int rd,hleft;
|
||
|
double *out,*tmp;
|
||
|
ulong i=0,vectorSize=RNDVECTORSIZE;
|
||
|
if (*size) vectorSize = *size;
|
||
|
FILE* fp = fopen(fpath,"r");
|
||
|
if (!fp){
|
||
|
perror("fopen vector file");
|
||
|
return NULL;
|
||
|
}
|
||
|
if (!(out = malloc(vectorSize * sizeof(*out)))){
|
||
|
ERRPRINT("vector read malloc fail for file\n");
|
||
|
goto _err;
|
||
|
}
|
||
|
while (1){
|
||
|
if (i >= vectorSize ){ //realloc the array
|
||
|
vectorSize *= VECTOR_STEP_REALLOC;
|
||
|
if (!(tmp=realloc(out,vectorSize*sizeof(*out)))){
|
||
|
ERRPRINTS("realloc errd to ~~ %lu MB\n",vectorSize >> 20);
|
||
|
goto _err;
|
||
|
}
|
||
|
out = tmp;
|
||
|
DEBUG printf("reallocd to ~~ %lu MB\n",vectorSize >> 20);
|
||
|
}
|
||
|
ulong toRead = MIN(VECTOR_READ_BLOCK,(vectorSize-i));
|
||
|
if((rd = fread_wrap(fp,out + i,sizeof(*out)*toRead)) == -2){
|
||
|
ERRPRINT("fread_wrap errd\n");
|
||
|
goto _err;
|
||
|
}
|
||
|
if(feof(fp)) //TODO rd == EOF not work always != W*F???
|
||
|
break;
|
||
|
i += rd/sizeof(out);
|
||
|
if( (hleft = rd % sizeof(out)) ){
|
||
|
DEBUG hprintf("half left double read... rounding down fptr\n");
|
||
|
if(fseek(fp,-hleft,SEEK_CUR)){
|
||
|
perror("fseek in readDoubleVector");
|
||
|
goto _err;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
//REALLOC THE ARRAY TO THE FINAL SIZE
|
||
|
assert( i > 0 );
|
||
|
if (!(tmp = realloc(out,*size*sizeof(*out)))){
|
||
|
ERRPRINT("realloc errd\n");
|
||
|
goto _err;
|
||
|
}
|
||
|
out = tmp;
|
||
|
DEBUG printf("readed vector from %s of %lu elements\n",fpath,*size);
|
||
|
goto _free;
|
||
|
|
||
|
_err:
|
||
|
free(out);
|
||
|
out = NULL;
|
||
|
_free:
|
||
|
if (fclose(fp) == EOF) perror("fclose errd\n");
|
||
|
return out;
|
||
|
}
|
||
|
|
||
|
double* readDoubleVectorStr(char* fpath,ulong* size){
|
||
|
int fscanfOut;
|
||
|
double *out,*tmp;
|
||
|
ulong i=0,vectorSize=RNDVECTORSIZE;
|
||
|
if (*size) vectorSize = *size;
|
||
|
FILE* fp = fopen(fpath,"r");
|
||
|
if (!fp){
|
||
|
perror("fopen vector file");
|
||
|
return NULL;
|
||
|
}
|
||
|
if (!(out = malloc(vectorSize * sizeof(*out)))){
|
||
|
ERRPRINT("vector read malloc fail for file\n");
|
||
|
goto _err;
|
||
|
}
|
||
|
while (1){
|
||
|
if (i >= vectorSize ){ //realloc the array
|
||
|
vectorSize *= VECTOR_STEP_REALLOC;
|
||
|
if (!(tmp=realloc(out,vectorSize*sizeof(*out)))){
|
||
|
ERRPRINTS("realloc errd to ~~ %lu MB\n",vectorSize >> 20);
|
||
|
goto _err;
|
||
|
}
|
||
|
out = tmp;
|
||
|
DEBUG printf("reallocd to ~~ %lu MB\n",vectorSize >> 20);
|
||
|
}
|
||
|
fscanfOut = fscanf(fp,DOUBLE_STR_FORMAT,out + i++ );
|
||
|
if ( fscanfOut == EOF && ferror(fp)){
|
||
|
perror("invalid fscanf");
|
||
|
goto _err;
|
||
|
}
|
||
|
if ( fscanfOut != 1 || fscanfOut == EOF ) break; //end of vector
|
||
|
}
|
||
|
//REALLOC THE ARRAY TO THE FINAL SIZE
|
||
|
assert( i > 0 );
|
||
|
*size = --i;
|
||
|
if (!(tmp = realloc(out,*size*sizeof(*out)))){
|
||
|
ERRPRINT("realloc errd\n");
|
||
|
goto _err;
|
||
|
}
|
||
|
out = tmp;
|
||
|
DEBUG printf("readed vector from %s of %lu elements\n",fpath,*size);
|
||
|
goto _free;
|
||
|
|
||
|
_err:
|
||
|
free(out);
|
||
|
out = NULL;
|
||
|
_free:
|
||
|
if (fclose(fp) == EOF) perror("fclose errd\n");
|
||
|
return out;
|
||
|
}
|
||
|
|
||
|
///CFG-AUX
|
||
|
int getConfig(CONFIG* conf){
|
||
|
int changes=EXIT_FAILURE;
|
||
|
char *varVal,*ptr;
|
||
|
ulong val;
|
||
|
if ((varVal = getenv(GRID_ROWS))){
|
||
|
val=strtoul(varVal,&ptr,10);
|
||
|
if (ptr==varVal || val>= UINT_MAX){
|
||
|
perror("strtol errd");
|
||
|
} else {
|
||
|
conf->gridRows = val;
|
||
|
}
|
||
|
changes = EXIT_SUCCESS;
|
||
|
}
|
||
|
if ((varVal = getenv(GRID_COLS))){
|
||
|
val=strtoul(varVal,&ptr,10);
|
||
|
if (ptr==varVal || val>= UINT_MAX){
|
||
|
perror("strtol errd");
|
||
|
} else {
|
||
|
conf->gridCols = val;
|
||
|
}
|
||
|
changes = EXIT_SUCCESS;
|
||
|
}
|
||
|
return changes;
|
||
|
}
|
||
|
|
||
|
/////LIB-SORTING -- WRAPPERS
|
||
|
//comparing functions
|
||
|
static inline int cmp_idx_t(const void* a, const void*b){
|
||
|
idx_t aa=*((ulong*) a), bb = *((ulong*) b);
|
||
|
return aa==bb?0:aa>bb?1:-1;
|
||
|
}
|
||
|
static inline int cmpulong(const void* a, const void*b){
|
||
|
ulong aa=*((ulong*) a), bb = *((ulong*) b);
|
||
|
return aa==bb?0:aa>bb?1:-1;
|
||
|
}
|
||
|
static inline int cmpuint(const void* a, const void*b){
|
||
|
uint aa=*((uint*) a), bb = *((uint*) b);
|
||
|
return aa==bb?0:aa>bb?1:-1;
|
||
|
}
|
||
|
static inline int cmpRbNode(const void* a, const void* b){
|
||
|
rbNode *aa=(rbNode*) a, *bb = (rbNode*) b;
|
||
|
return cmp_idx_t(&aa->key,&bb->key);
|
||
|
}
|
||
|
//sorting functions
|
||
|
void sort_idx_t(idx_t* arr, idx_t len){
|
||
|
qsort(arr,len,sizeof(*arr),cmp_idx_t);
|
||
|
}
|
||
|
void sortulong(ulong* arr, ulong len){
|
||
|
qsort(arr,len,sizeof(*arr),cmpulong);
|
||
|
}
|
||
|
void sortuint(uint* arr, uint len){
|
||
|
qsort(arr,len,sizeof(*arr),cmpuint);
|
||
|
}
|
||
|
void sortRbNode(rbNode* arr, idx_t len){
|
||
|
qsort(arr,len,sizeof(*arr),cmpRbNode);
|
||
|
}
|
||
|
|
||
|
////Tests AUX
|
||
|
inline void assertArrNoRepetitions(idx_t* arrSorted, idx_t arrLen){
|
||
|
if (arrLen > 0 ) return;
|
||
|
for (idx_t i=1,last=arrSorted[0]; i<arrLen; last = arrSorted[i++])
|
||
|
assert( arrSorted[i] != last );
|
||
|
}
|
||
|
///MATH UTILS
|
||
|
|
||
|
static inline int rndDouble_sinAll(double* d){
|
||
|
if(read_wrap(urndFd,(void*) d,sizeof(*d))){
|
||
|
ERRPRINT("read_wrap failed to read rnd double\n");
|
||
|
return EXIT_FAILURE;
|
||
|
}
|
||
|
*d = sin(*d) * MAXRND;
|
||
|
return EXIT_SUCCESS;
|
||
|
}
|
||
|
long _rndHold; //permanent storage of rnd longs
|
||
|
static inline int rndDouble_sinDecimal(double* d){
|
||
|
if(read_wrap(urndFd,(void*) &_rndHold,sizeof(_rndHold))){
|
||
|
ERRPRINT("read_wrap failed to read holder for rnd double\n");
|
||
|
return EXIT_FAILURE;
|
||
|
}
|
||
|
*d = (_rndHold % (ulong) ceil(MAXRND)) + sin(_rndHold);
|
||
|
return EXIT_SUCCESS;
|
||
|
}
|
||
|
|
||
|
void statsAvgVar(double* values,uint numVals, double* out){
|
||
|
double sum=0,sumSquare=0;
|
||
|
for (uint i=0; i<numVals; i++){
|
||
|
sum += values[i];
|
||
|
sumSquare += values[i]*values[i];
|
||
|
}
|
||
|
out[0] = sum/numVals; //AVG
|
||
|
out[1] = sumSquare/numVals - (out[0] * out[0]); //VAR
|
||
|
}
|
||
|
|
||
|
/// MATRIX - VECTOR COMPUTE UTILS
|
||
|
int fillRndVector(ulong size, double* v){
|
||
|
for( ulong x=0; x<size; ++x ){
|
||
|
if(rndDouble_sinAll( v+x )) return EXIT_FAILURE;
|
||
|
#ifdef RNDVECTMIN
|
||
|
v[x] += RNDVECTMIN;
|
||
|
#endif
|
||
|
}
|
||
|
return EXIT_SUCCESS;
|
||
|
}
|
||
|
|
||
|
//convention true result in @a, toCheck in @b
|
||
|
int doubleVectorsDiff(double* a, double* b, ulong n,double* diffMax){
|
||
|
int out = EXIT_SUCCESS;
|
||
|
double diff,diffAbs,_diffMax=0;
|
||
|
if (diffMax) *diffMax = 0;
|
||
|
else diffMax = &_diffMax;
|
||
|
for (ulong i=0; i<n; i++){
|
||
|
diff = a[i] - b[i];
|
||
|
diffAbs = ABS( diff );
|
||
|
if( diffAbs > DOUBLE_DIFF_THREASH ){
|
||
|
out = EXIT_FAILURE;
|
||
|
ERRPRINTS("DOUBLE VECTORS DIFF: DOUBLE_DIFF_THREASH=%lf\t<\t"
|
||
|
"|%13lg| = %lf %% of @a[%lu]\n",
|
||
|
DOUBLE_DIFF_THREASH,diff,100*diffAbs/ABS(a[i]),i);
|
||
|
#ifdef DOUBLE_VECT_DIFF_EARLY_EXIT
|
||
|
/*#pragma message("DOUBLE_VECT_DIFF_EARLY_EXIT: only first diff double reported")*/
|
||
|
return EXIT_FAILURE;
|
||
|
#endif
|
||
|
}
|
||
|
if ( ABS(*diffMax) < diffAbs ) *diffMax = diff;
|
||
|
}
|
||
|
DEBUG{
|
||
|
printf("\nchecked diff %s"CEND" between 2 double vector of %lu elements"
|
||
|
"\tmax diff: %le %s threash: %le\n", !out?CCC"OK":CCCERR"ERR!",
|
||
|
n,*diffMax,*diffMax<DOUBLE_DIFF_THREASH?"<":">=",
|
||
|
DOUBLE_DIFF_THREASH);
|
||
|
if (!*diffMax){ //self diff check uselss TODO REMOVE
|
||
|
if (!memcpy(a,b,n*sizeof(*a)))
|
||
|
printf("EXACT MATCHING AMONG THE 2 DOUBLE VECTORS\n!");
|
||
|
}
|
||
|
}
|
||
|
return out;
|
||
|
}
|
||
|
|
||
|
void printMatrix(double* mat,ulong m,ulong n,char justNZMarkers){
|
||
|
printf("printing matrix: %lu x %lu\n",m,n);
|
||
|
ulong i,j;
|
||
|
for (i=0;i<m;i++){
|
||
|
for (j=0;j<n;j++){
|
||
|
if (justNZMarkers) printf("%s",mat[IDX2D(i,j,n)]?".":" ");
|
||
|
else printf("%1.1lf ",mat[IDX2D(i,j,n)]);
|
||
|
}
|
||
|
printf("\n");
|
||
|
}
|
||
|
printf("\n");
|
||
|
}
|
||
|
|
||
|
|
||
|
void printVector(double* v,ulong size){
|
||
|
for( ulong i=0;i<size;i++) printf("%1.1lf ",v[i]);
|
||
|
printf("\n");
|
||
|
}
|
||
|
|
||
|
////VAR -- MISC
|
||
|
/* search for pattern in @str from NULL terminated @patterns array
|
||
|
* return pointer of pattern in @str if any, otherwise NULL
|
||
|
*/
|
||
|
static inline char* searchPatternsInStr(char** patterns,char* str){
|
||
|
char* out = NULL;
|
||
|
for (char** p=patterns; !out && *p; p++) out = strstr(str,*p);
|
||
|
return out;
|
||
|
}
|
||
|
/* search for pattern in @str from NULL terminated @patterns array
|
||
|
* return pointer of pattern in @str if any, otherwise NULL
|
||
|
*/
|
||
|
static inline char* searchPatternInStrs(char* pattern,char** strings){
|
||
|
char* out = NULL;
|
||
|
for (char** str=strings; !out && *str; str++) out = strstr(*str,pattern);
|
||
|
return out;
|
||
|
}
|
||
|
|
||
|
inline int appendArr(ulong val,APPENDARRAY* list){
|
||
|
return 0; //TODO
|
||
|
}
|
||
|
|
||
|
///DECOMPRESSION IN TMPFS ; TODO vector not puttable here... figure out nicer way..
|
||
|
char* COMPRESS_EXTENSIONS[] = { ".gz", ".xz", ".bz2", ".zip", NULL};
|
||
|
#define STD_DECOMPR_FLAGS " -d -c "
|
||
|
char* DECOMPRESS_CMDS[] = {"gzip" STD_DECOMPR_FLAGS, "xz" STD_DECOMPR_FLAGS, "bzip2" STD_DECOMPR_FLAGS,
|
||
|
"unzip -c", NULL }; //zip is too old ;)
|
||
|
|
||
|
int extractInTmpFS(char* path, char* tmpFsDecompressPath){
|
||
|
char* ext = searchPatternsInStr(COMPRESS_EXTENSIONS,path);
|
||
|
if (!ext) return -1; //NOT SUPPORTED COMPRESS EXTENSION -> TRY REGULAR PATH
|
||
|
//search first 2 char after dot of ext in DECOMPRESS_CMDS to get the decompress cmd
|
||
|
if (strlen(ext) < 3 ){
|
||
|
ERRPRINTS("NOT SUPPORTED DECOMPRESSION:\textension %s too short to be matched",ext);
|
||
|
return -1;
|
||
|
}
|
||
|
char extStart[3];
|
||
|
extStart[0] = ext[1];
|
||
|
extStart[1] = ext[2];
|
||
|
extStart[2] = '\0';
|
||
|
char* decompressCmdBase = searchPatternInStrs(extStart,DECOMPRESS_CMDS);
|
||
|
if (!decompressCmdBase){
|
||
|
ERRPRINTS("NOT SUPPORTED DECOMPRESS FOR %s\n",ext);
|
||
|
return -1;
|
||
|
}
|
||
|
uint cmdLen = strlen(decompressCmdBase) + strlen(path) + 4 + strlen(tmpFsDecompressPath);
|
||
|
char* decompressCmd = alloca(cmdLen+1);
|
||
|
if (snprintf(decompressCmd,cmdLen+1,"%s %s > %s",
|
||
|
decompressCmdBase,path,tmpFsDecompressPath) < 0){
|
||
|
ERRPRINT("extractInTmpFS, snprintf errd\n");
|
||
|
}
|
||
|
VERBOSE printf("decompressing %s --> %s\ncmd:\t%s\n",path,tmpFsDecompressPath,decompressCmd);
|
||
|
return system(decompressCmd);
|
||
|
}
|