#include "mrilib.h" /*----------------------------------------------------------------------------*/ static char *tmpdir = NULL ; /*! Function to get name of the directory to store TIM_* mri_purge() files. */ char * mri_purge_get_tmpdir(void) { if( tmpdir == NULL ){ tmpdir = getenv( "TMPDIR" ) ; if( tmpdir == NULL || *tmpdir == '\0' ) tmpdir = getenv( "TEMPDIR" ) ; if( tmpdir == NULL || *tmpdir == '\0' ) tmpdir = "/tmp" ; if( !THD_is_directory(tmpdir) ) tmpdir = "." ; } return tmpdir ; } /*----------------------------------------------------------------------------*/ static char tsuf[8] = "\0" ; /*! Function to set TIM suffix for this process */ static void purge_set_tsuf(void) /* 01 Feb 2007 */ { int ii ; if( tsuf[0] != '\0' ) return ; ii = (lrand48()>>5) % 52 ; tsuf[0] = (ii < 26) ? (ii+'A') : (ii-26+'a') ; ii = (lrand48()>>5) % 52 ; tsuf[1] = (ii < 26) ? (ii+'A') : (ii-26+'a') ; ii = (lrand48()>>5) % 52 ; tsuf[2] = (ii < 26) ? (ii+'A') : (ii-26+'a') ; tsuf[3] = '\0' ; return ; } /*----------------------------------------------------------------------------*/ /* Functions to save a list of TIM_* mri_purge() files, so that they can be deleted at program rundown, if they weren't mri_free()-ed already. If mainENTRY() was used, then even a program crash might do cleanup, since the most common fatal signals are caught and will end up invoking exit(), which will in turn invoke purge_atexit(). ------------------------------------------------------------------------------*/ static int atexit_called = 0 ; /* was atexit() already called for this? */ static int npurge = 0 ; /* number of filenames in qpurge array */ static char **qpurge = NULL ; /* filenames of TIM_* files still alive */ static void purge_atexit(void) /*--- called by exit(): delete TIM_* files ---*/ { int ii , nn ; for( nn=ii=0 ; ii < npurge ; ii++ ){ if( qpurge[ii] != NULL ){ INFO_message("removing temporary image file %s",qpurge[ii]) ; remove(qpurge[ii]) ; nn++ ; } } if( tmpdir != NULL && nn > 0 && tsuf[0] != '\0' ) WARNING_message("-usetemp: Check %s/ for other TIM_%s* files",tmpdir,tsuf); return ; } /*----------------------------------------------------------------------------*/ static void add_purge( char *fn ) /*-------- add fn to the qpurge list ----*/ { int ii ; if( fn == NULL || *fn == '\0' ) return ; for( ii=0 ; ii < npurge ; ii++ ) /* see if already in list */ if( qpurge[ii] != NULL && strcmp(qpurge[ii],fn) == 0 ) break ; if( ii < npurge ) return ; /* already in list! */ for( ii=0 ; ii < npurge ; ii++ ) /* find an empty slot */ if( qpurge[ii] == NULL ) break ; if( ii == npurge ) /* make new empty slot */ qpurge = (char **)realloc(qpurge,sizeof(char *)*(++npurge)) ; qpurge[ii] = strdup(fn) ; /* fill empty slot */ return ; } /*----------------------------------------------------------------------------*/ static void kill_purge( char *fn ) /*---- remove fn from the qpurge list ----*/ { int ii ; if( fn == NULL || *fn == '\0' || qpurge == NULL ) return ; for( ii=0 ; ii < npurge ; ii++ ) /* find in list */ if( qpurge[ii] != NULL && strcmp(qpurge[ii],fn) == 0 ) break ; if( ii < npurge ){ free(qpurge[ii]) ; qpurge[ii] = NULL ; } return ; } /*----------------------------------------------------------------------------*/ /*! Purge an image file to disk, to a random filename. - If the write to disk works, the image array is free()-ed. - If the write to disk fails, the image array is not free()-ed. - Call mri_unpurge() to read the file back in and delete it. - Call mri_killpurge() to just delete the file from disk. ------------------------------------------------------------------------------*/ void mri_purge( MRI_IMAGE *im ) { void *iar ; FILE *fp ; size_t npix ; char *pg , *un ; ENTRY("mri_purge") ; if( im == NULL ) EXRETURN ; iar = mri_data_pointer(im) ; if( iar == NULL ) EXRETURN ; if( im->fondisk == IS_PURGED ){ /* should not happen */ if( im->fname != NULL ) remove(im->fname) ; im->fondisk = 0 ; } if( im->fname != NULL ) free(im->fname) ; /* make up a unique name for the purge file */ pg = mri_purge_get_tmpdir() ; purge_set_tsuf() ; im->fname = malloc(strlen(pg)+64) ; un = UNIQ_idcode(); un[0] = 'T' ; un[1] = 'I' ; un[2] = 'M' ; un[3] = '_' ; un[4] = tsuf[0] ; un[5] = tsuf[1] ; un[6] = tsuf[2] ; strcpy(im->fname,pg); strcat(im->fname,"/"); strcat(im->fname,un); free(un) ; fp = fopen( im->fname , "wb" ) ; if( fp == NULL ){ ERROR_message("mri_purge: Can't open file %s",im->fname) ; EXRETURN ; } npix = fwrite( iar , (size_t)im->pixel_size , (size_t)im->nvox , fp ) ; fclose(fp) ; if( npix < (size_t)im->nvox ){ long long nb = ((long long)im->pixel_size) * ((long long)im->nvox) ; ERROR_message("mri_purge: Can't write %lld bytes to %s",nb,im->fname) ; remove(im->fname) ; } else { free(iar) ; mri_clear_data_pointer(im) ; im->fondisk = IS_PURGED ; add_purge(im->fname) ; if( !atexit_called ){ atexit(purge_atexit); atexit_called = 1; } if( PRINT_TRACING ){ long long nb = ((long long)im->pixel_size) * ((long long)im->nvox) ; char str[256] ; sprintf(str,"wrote %lld bytes to file %s",nb,im->fname); STATUS(str); } } EXRETURN ; } /*----------------------------------------------------------------------------*/ /*! Retrieve a mri_purge()-ed image from disk. The temp file will be deleted. ------------------------------------------------------------------------------*/ void mri_unpurge( MRI_IMAGE *im ) { void *iar ; FILE *fp ; size_t npix ; ENTRY("mri_unpurge") ; if( im == NULL || !MRI_IS_PURGED(im) ) EXRETURN ; iar = mri_data_pointer_unvarnished(im) ; if( iar != NULL ) EXRETURN ; fp = fopen( im->fname , "rb" ) ; if( fp == NULL ){ ERROR_message("mri_unpurge: Can't open file %s",im->fname) ; EXRETURN ; } /* make space for data we are about to receive */ iar = calloc( (size_t)im->pixel_size , (size_t)im->nvox ) ; if( iar == NULL ){ long long nb = ((long long)im->pixel_size) * ((long long)im->nvox) ; ERROR_message("mri_unpurge: Can't malloc() %lld bytes",nb) ; fclose(fp); remove(im->fname); im->fondisk = 0; kill_purge(im->fname); EXRETURN; } mri_fix_data_pointer( iar , im ) ; /* get the data, babeee! */ npix = fread( iar , (size_t)im->pixel_size , (size_t)im->nvox , fp ) ; fclose(fp); remove(im->fname); im->fondisk = 0; kill_purge(im->fname); if( npix < (size_t)im->nvox ){ /* didn't get enuf data? */ long long nb = ((long long)im->pixel_size) * ((long long)im->nvox) ; WARNING_message("mri_unpurge: Can't read %lld bytes from %s",nb,im->fname); } else if( PRINT_TRACING ){ /* debug tracing output? */ long long nb = ((long long)im->pixel_size) * ((long long)im->nvox) ; char str[256] ; sprintf(str,"read %lld bytes from file %s",nb,im->fname); STATUS(str); } EXRETURN ; } /*----------------------------------------------------------------------------*/ /*! If the image is purged to disk, kill the purge file. Called from mri_free() to make sure that purged images are cleaned up. ------------------------------------------------------------------------------*/ void mri_killpurge( MRI_IMAGE *im ) { if( MRI_IS_PURGED(im) ){ ENTRY("mri_killpurge") ; /* only do traceback if work to do */ remove(im->fname); im->fondisk = 0; kill_purge(im->fname); if( PRINT_TRACING ){ char str[256]; sprintf(str,"removed file %s",im->fname); STATUS(str); } EXRETURN ; } return ; }