#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 ;
}
syntax highlighted by Code2HTML, v. 0.9.1