/***************************************************************************** Major portions of this software are copyrighted by the Medical College of Wisconsin, 1994-2000, and are released under the Gnu General Public License, Version 2. See the file README.Copyright for details. ******************************************************************************/ #include "mrilib.h" /*---- editable configuration variables [moved here 10 May 2013 -- RWcox] ----*/ static char *COMPRESS_program[] = { "gzip -1c > '%s'" , "bzip2 -1c > '%s'" , "compress > '%s'" , "pigz -1c > '%s'" , "cat > '%s'"} ; /* shouldn't be called */ static int COMPRESS_program_ok[] = { 1 , 1 , 1 , 1 , 0 } ; /* RWCox 03 Aug 1998 */ static char *COMPRESS_unprogram[] = { "gzip -dc '%s'" , "bzip2 -dc '%s'" , "uncompress -c '%s'", "pigz -dc '%s'" , "brikcomp -c '%s'" } ; /*----------------------------------------------------------------------------*/ /* Check if pigz can be used in place of gzip for compression, and if pbzip2 can be used in place of bzip2. *//*--------------------------------------------------------------------------*/ static void COMPRESS_setup_programs(void) /* 03 May 2013 */ { char *pgname=NULL ; static char *cprog_gzip=NULL , *cprog_bzip2=NULL ; static char *uprog_gzip=NULL , *uprog_bzip2=NULL ; static int first=1 ; int cind=-1; int skip_pigz=AFNI_yesenv("AFNI_DONT_USE_PIGZ") ; if( !first ) return ; first = 0 ; if( getenv("SKIP_COMPRESS_SETUP") ) return; /* Temp. fix. Strange R crash. ZSS 09 May 2013 */ /* for some symmetry, init pgname based on AFNI_COMPRESSOR * (for either gzip or pigz) 19 Sep 2013 [rickr] */ cind = THD_enviro_write_compression(); if ( cind == COMPRESS_GZIP ) pgname = THD_find_executable("gzip") ; else if ( cind == COMPRESS_PIGZ ) pgname = THD_find_executable("pigz") ; else pgname = NULL ; /* if that failed (ignore which), just start clean */ if( pgname == NULL && !skip_pigz ) pgname = THD_find_executable("pigz") ; if( pgname == NULL ) pgname = THD_find_executable("gzip") ; if( pgname == NULL ){ COMPRESS_program_ok[0] = COMPRESS_program_ok[3] = 0 ; } else { cprog_gzip = (char *)malloc(sizeof(char)*(strlen(pgname)+32)) ; sprintf(cprog_gzip,"%s -1c > '%%s'",pgname) ; COMPRESS_program[0] = COMPRESS_program[3] = cprog_gzip ; uprog_gzip = (char *)malloc(sizeof(char)*(strlen(pgname)+32)) ; sprintf(uprog_gzip,"%s -dc '%%s'",pgname) ; COMPRESS_unprogram[0] = COMPRESS_unprogram[3] = uprog_gzip ; } pgname = THD_find_executable("pbzip2") ; if( pgname == NULL ) pgname = THD_find_executable("bzip2") ; if( pgname == NULL ){ COMPRESS_program_ok[1] = 0 ; } else { cprog_bzip2 = (char *)malloc(sizeof(char)*(strlen(pgname)+32)) ; sprintf(cprog_bzip2,"%s -1c > '%%s'",pgname) ; COMPRESS_program[1] = cprog_bzip2 ; uprog_bzip2 = (char *)malloc(sizeof(char)*(strlen(pgname)+32)) ; sprintf(uprog_bzip2,"%s -dc '%%s'",pgname) ; COMPRESS_unprogram[1] = uprog_bzip2 ; } return ; } /*--------------------------------------------------------------*/ /*** check if the file exists on disk -- returns 1 if it does, 0 if it does not ***/ int COMPRESS_is_file( char * pathname ) { static struct stat buf ; int ii ; if( pathname == NULL ) return 0 ; ii = stat( pathname , &buf ) ; if( ii != 0 ) return 0 ; ii = (buf.st_mode & S_IFREG) != 0 ; return ii ; } /*--------------------------------------------------------------*/ /*** check if the filename has the apposite suffix for the compression mode given ***/ int COMPRESS_has_suffix( char * fname , int mode ) { int ll ; if( mode < 0 ) return 1 ; if( mode > COMPRESS_LASTCODE ) return 0 ; ll = strlen(fname) ; return ( ll > COMPRESS_suffix_len[mode] && strcmp(COMPRESS_suffix[mode] , fname+(ll-COMPRESS_suffix_len[mode])) == 0 ) ; } /*--------------------------------------------------------------*/ /*** return the compression code for the given filename; if the file doesn't exist, will return COMPRESS_NOFILE ***/ int COMPRESS_filecode( char * fname ) { int ii ; char * buf ; if( fname == NULL || fname[0] == '\0' ) return COMPRESS_NOFILE ; /** check the filename suffix **/ for( ii=0 ; ii <= COMPRESS_LASTCODE ; ii++ ){ if( COMPRESS_has_suffix(fname,ii) ){ if( COMPRESS_is_file(fname) ) return ii ; else return COMPRESS_NOFILE ; } } if( COMPRESS_is_file(fname) ) return COMPRESS_NONE ; /** add the suffixes to the name, and check again **/ buf = AFMALL(char, sizeof(char) * (strlen(fname)+16) ) ; for( ii=0 ; ii <= COMPRESS_LASTCODE ; ii++ ){ strcpy(buf,fname) ; strcat(buf,COMPRESS_suffix[ii]) ; if( COMPRESS_is_file(buf) ){ free(buf) ; return ii ; } } free(buf) ; return COMPRESS_NOFILE ; } /*--------------------------------------------------------------*/ /*** keep a table of which open files used fopen and which used popen -- because they must be closed differently ***/ #define NFOPMAX 16 static int fop_init = 0 ; static int fop_fileno[NFOPMAX] ; static int fop_popend[NFOPMAX] ; static void putin_fop_table( FILE * fp , int ppp ) { int ii ; if( fp == NULL ) return ; /* can't do much with nothing */ if( ! fop_init ){ /* initialize the table */ for( ii=0 ; ii < NFOPMAX ; ii++ ){ fop_fileno[ii] = -1 ; fop_popend[ii] = 0 ; } fop_init = 1 ; } for( ii=0 ; ii < NFOPMAX ; ii++ ) /* find an unused entry */ if( fop_fileno[ii] < 0 ) break ; if( ii == NFOPMAX ){ fprintf(stderr,"\n*** AFNI compressor table overflow!\n") ; return ; } fop_fileno[ii] = fileno(fp) ; /* save the file number */ fop_popend[ii] = ppp ; /* save the popen code */ return ; } /*** Use this to close a file, so that pclose or fclose can be called correctly ***/ int COMPRESS_fclose( FILE * fp ) { int fn , ii ; if( fp == NULL || ! fop_init ) return fclose(fp) ; fn = fileno(fp) ; for( ii=0 ; ii < NFOPMAX ; ii++ ){ /* find the file number */ if( fop_fileno[ii] == fn ){ /* found it! */ fop_fileno[ii] = -1 ; /* empty this table entry */ if( fop_popend[ii] ) return pclose(fp) ; else return fclose(fp) ; } } return fclose(fp) ; /* couldn't find it, so use fclose */ } /*--------------------------------------------------------------*/ /*** return a malloc-ed filename string that has the correct compression suffix attached. If NULL is returned, the file doesn't exist. The return string should be free()-ed after it is used. ***/ char * COMPRESS_filename( char * fname ) { char * buf ; int ll , mm ; if( fname == NULL || fname[0] == '\0' ) return NULL ; mm = COMPRESS_filecode( fname ) ; /* find compression mode */ if( mm == COMPRESS_NOFILE ) return NULL ; ll = strlen(fname) ; buf = AFMALL(char, sizeof(char) * (ll+16) ) ; /* worst case */ if( mm == COMPRESS_NONE ){ strcpy(buf,fname) ; } else { if( ! COMPRESS_has_suffix(fname,mm) ){ strcpy(buf,fname) ; strcat(buf,COMPRESS_suffix[mm]) ; } else { strcpy(buf,fname) ; } } return buf ; } /*--- May 1998: a simple routine ---*/ char * COMPRESS_add_suffix( char * fname , int mm ) { char * buf ; int ll ; if( fname == NULL || fname[0] == '\0' ) return NULL ; ll = strlen(fname) ; buf = AFMALL(char, sizeof(char) * (ll+16) ) ; strcpy(buf,fname) ; if( mm >= 0 && mm <= COMPRESS_LASTCODE && ! COMPRESS_has_suffix(fname,mm) ){ strcat(buf,COMPRESS_suffix[mm]) ; } return buf ; } /*--------------------------------------------------------------*/ /*** open a file for reading, possibly using compresson ***/ FILE * COMPRESS_fopen_read( char * fname ) { FILE * fp ; int mm ; char * buf , * cmd ; if( fname == NULL || fname[0] == '\0' ) return NULL ; COMPRESS_setup_programs() ; /* 03 May 2013 */ mm = COMPRESS_filecode( fname ) ; /* find compression mode */ if( mm == COMPRESS_NOFILE ) return NULL ; /* can't do nothing */ if( mm == COMPRESS_NONE ){ fp = fopen(fname,"r") ; /* open it normally */ putin_fop_table(fp,0) ; /* save its open method */ return fp ; } #if 1 if( ! COMPRESS_has_suffix(fname,mm) ){ buf = AFMALL(char, sizeof(char) * (strlen(fname)+16) ) ; strcpy(buf,fname) ; strcat(buf,COMPRESS_suffix[mm]) ; } else { buf = fname ; } #else buf = fname ; #endif /* allow for longer program names 16 May, 2014 [rickr] */ /* (problem noted by D. Thompson) */ cmd = AFMALL(char, sizeof(char) * (strlen(buf)+strlen(COMPRESS_unprogram[mm])+4) ) ; sprintf(cmd,COMPRESS_unprogram[mm],buf) ; fp = popen(cmd,"r") ; /* open a pipe to read the file */ putin_fop_table(fp,1) ; /* save its open method */ free(cmd) ; if( buf != fname ) free(buf) ; return fp ; } /*------------------------------------------------------------- open a file for writing, possibly using compresson; mm should be one of the COMPRESS_ codes at the top of file thd_compress.h ---------------------------------------------------------------*/ FILE * COMPRESS_fopen_write( char * fname , int mm ) { FILE * fp ; char * buf , * cmd ; if( fname == NULL || fname[0] == '\0' ) return NULL ; COMPRESS_setup_programs() ; /* 03 May 2013 */ /* Don't compress if the compression program isn't marked as OK */ /* [For modes that can only be compressed offline, like BRIKCOMP] */ if( mm < 0 || ! COMPRESS_program_ok[mm] ){ fp = fopen(fname,"w") ; /* open it normally */ putin_fop_table(fp,0) ; /* save its open method */ return fp ; } #if 1 if( ! COMPRESS_has_suffix(fname,mm) ){ buf = AFMALL(char, sizeof(char) * (strlen(fname)+16) ) ; strcpy(buf,fname) ; strcat(buf,COMPRESS_suffix[mm]) ; } else { buf = fname ; } #else buf = fname ; #endif /* allow for longer program names 16 May, 2014 [rickr] */ /* (problem noted by D. Thompson) */ cmd = AFMALL(char, sizeof(char) * (strlen(buf)+strlen(COMPRESS_program[mm])+4) ) ; sprintf(cmd,COMPRESS_program[mm],buf) ; fp = popen(cmd,"w") ; /* open a pipe to write the file */ putin_fop_table(fp,1) ; /* save its open method */ free(cmd) ; if( buf != fname ) free(buf) ; return fp ; } /*----------------------------------------------------------*/ int COMPRESS_unlink( char * fname ) { char * fff = COMPRESS_filename(fname) ; int ii = -1 ; if( fff != NULL ){ ii=unlink(fff); free(fff); } return ii ; }