1 #include "mrilib.h"
2 
3 /*----------------------------------------------------------------------------*/
4 static char *tmpdir = NULL ;
5 
test_tmpdir_write(void)6 static int test_tmpdir_write(void)
7 {
8    char *un , *tf ; FILE *fp ; size_t bb=0 ;
9    if( tmpdir==NULL || *tmpdir=='\0' || !THD_is_directory(tmpdir) ) return 0 ;
10    un = UNIQ_idcode() ;
11    tf = malloc(strlen(un)+strlen(tmpdir)+8) ;
12    strcpy(tf,tmpdir) ; strcat(tf,"/") ; strcat(tf,un) ; free(un) ;
13    fp = fopen(tf,"w+b") ;
14    if( fp == NULL ){ free(tf) ; return 0 ; }
15    bb = fwrite( &bb , sizeof(size_t) , 1 , fp ) ;
16    fclose(fp) ; remove(tf) ; free(tf) ;
17    return ( bb == 1 ) ;
18 }
19 
20 /*----------------------------------------------------------------------------*/
21 /*! Function to get name of the directory to store TIM_* mri_purge() files.
22     The return pointer should NOT be free()-ed!
23 *//*--------------------------------------------------------------------------*/
24 
mri_purge_get_tmpdir(void)25 char * mri_purge_get_tmpdir(void)
26 {
27    if( tmpdir == NULL ){
28                                 tmpdir = getenv( "TMPDIR" ) ;
29      if( !test_tmpdir_write() ) tmpdir = getenv( "TEMPDIR" ) ;
30      if( !test_tmpdir_write() ) tmpdir = "/tmp" ;
31      if( !test_tmpdir_write() ) tmpdir = "." ;    /* the last resort */
32    }
33    return tmpdir ;
34 }
35 
36 /*----------------------------------------------------------------------------*/
37 /*! Function to return a unique name for temporary file, with the
38     given prefix attached (if it isn't NULL, that is).
39     The return pointer should be free()-ed when you are done with it.
40 *//*--------------------------------------------------------------------------*/
41 
mri_get_tempfilename(char * pref)42 char * mri_get_tempfilename( char *pref )
43 {
44    char *tdir , *unam , *fnam ; int nn ;
45 
46    tdir = mri_purge_get_tmpdir() ;
47 
48    do{
49      unam = UNIQ_idcode() ;                        /* unique part of filename */
50      nn   = (pref != NULL) ? strlen(pref) : 0 ;           /* length of prefix */
51      fnam = (char *)malloc(sizeof(char)*(strlen(tdir)+strlen(unam)+nn+4)) ;
52      strcpy(fnam,tdir) ;                    /* start with temp directory name */
53      nn = strlen(fnam) ; if( fnam[nn-1] != '/' ) strcat(fnam,"/") ;
54      if( pref != NULL ){ strcat(fnam,pref); strcat(fnam,"_"); } /* add prefix */
55      strcat(fnam,unam) ; free(unam) ;                 /* append unique string */
56      nn = THD_is_ondisk(fnam) ;                        /* should never happen */
57      if( nn ) free(fnam) ;
58    } while(nn) ;                                         /* should never loop */
59 
60    return fnam ;
61 }
62 
63 
64 /*----------------------------------------------------------------------------*/
65 static char tsuf[8] = "\0" ;
66 
67 /*! Function to set TIM suffix for this process */
68 
purge_set_tsuf(int v)69 static void purge_set_tsuf(int v)  /* 01 Feb 2007 */
70 {
71    char *un ;
72    if( tsuf[0] != '\0' ) return ;
73    un = UNIQ_idcode();
74    tsuf[0] = un[5] ; tsuf[1] = un[6] ; tsuf[2] = un[7] ; tsuf[3] = '\0' ;
75    if( v )
76      INFO_message("temp files: if program crashes, do /bin/rm -f %s/TIM_%s*",
77                   mri_purge_get_tmpdir() , tsuf ) ;
78    return ;
79 }
80 
mri_purge_get_tsuf(void)81 char * mri_purge_get_tsuf(void){ purge_set_tsuf(0); return tsuf; }
82 
83 /*----------------------------------------------------------------------------*/
84 /* Functions to save a list of TIM_* mri_purge() files, so that they can
85    be deleted at program rundown, if they weren't mri_free()-ed already.
86    If mainENTRY() was used, then even a program crash might do cleanup, since
87    the most common fatal signals are caught and will end up invoking exit(),
88    which will in turn invoke purge_atexit().
89 ------------------------------------------------------------------------------*/
90 
91 static int atexit_called = 0 ;   /* was atexit() already called for this? */
92 
93 static int    npurge = 0 ;       /* number of filenames in qpurge array */
94 static char **qpurge = NULL ;    /* filenames of TIM_* files still alive */
95 
purge_atexit(void)96 static void purge_atexit(void) /*--- called by exit(): delete TIM_* files ---*/
97 {
98    int ii , nn ;
99    for( nn=ii=0 ; ii < npurge ; ii++ ){
100      if( qpurge[ii] != NULL ){
101        INFO_message("removing temporary image file %s",qpurge[ii]) ;
102        remove(qpurge[ii]) ; nn++ ;
103      }
104    }
105    if( tmpdir != NULL && nn > 0 && tsuf[0] != '\0' )
106      WARNING_message("-usetemp: Check %s/ for other TIM_%s* files",tmpdir,tsuf);
107    return ;
108 }
109 
110 /*----------------------------------------------------------------------------*/
111 
add_purge(char * fn)112 static void add_purge( char *fn ) /*-------- add fn to the qpurge list ----*/
113 {
114    int ii ;
115    if( fn == NULL || *fn == '\0' ) return ;
116    for( ii=0 ; ii < npurge ; ii++ )  /* see if already in list */
117      if( qpurge[ii] != NULL && strcmp(qpurge[ii],fn) == 0 ) break ;
118    if( ii < npurge ) return ;        /* already in list! */
119    for( ii=0 ; ii < npurge ; ii++ )  /* find an empty slot */
120      if( qpurge[ii] == NULL ) break ;
121    if( ii == npurge )                /* make new empty slot */
122      qpurge = (char **)realloc(qpurge,sizeof(char *)*(++npurge)) ;
123    qpurge[ii] = strdup(fn) ;         /* fill empty slot */
124    return ;
125 }
126 
127 /*----------------------------------------------------------------------------*/
128 
kill_purge(char * fn)129 static void kill_purge( char *fn ) /*---- remove fn from the qpurge list ----*/
130 {
131    int ii ;
132    if( fn == NULL || *fn == '\0' || qpurge == NULL ) return ;
133    for( ii=0 ; ii < npurge ; ii++ )  /* find in list */
134      if( qpurge[ii] != NULL && strcmp(qpurge[ii],fn) == 0 ) break ;
135    if( ii < npurge ){ free(qpurge[ii]) ; qpurge[ii] = NULL ; }
136    return ;
137 }
138 
139 /*----------------------------------------------------------------------------*/
140 /*! Purge an image file to disk, to a random filename.
141      - If the write to disk works, the image array is free()-ed.
142      - If the write to disk fails, the image array is not free()-ed.
143      - Call mri_unpurge() to read the file back in and delete it.
144      - Call mri_killpurge() to just delete the file from disk.
145 ------------------------------------------------------------------------------*/
146 
mri_purge(MRI_IMAGE * im)147 void mri_purge( MRI_IMAGE *im )
148 {
149    void *iar ;
150    FILE *fp ;
151    size_t npix ;
152    char *pg , *un ;
153 
154 ENTRY("mri_purge") ;
155 
156    if( im == NULL ) EXRETURN ;
157    iar = mri_data_pointer(im) ; if( iar == NULL ) EXRETURN ;
158 
159    if( im->fondisk == IS_PURGED ){   /* should not happen */
160      if( im->fname != NULL ) remove(im->fname) ;
161      im->fondisk = 0 ;
162    }
163 
164    if( im->fname != NULL ) free(im->fname) ;
165 
166    /* make up a unique name for the purge file */
167 
168    pg        = mri_purge_get_tmpdir() ; purge_set_tsuf(1) ;
169    im->fname = malloc(strlen(pg)+64) ;
170    un = UNIQ_idcode();
171    un[0] = 'T'     ; un[1] = 'I'     ; un[2] = 'M'     ; un[3] = '_' ;
172    un[4] = tsuf[0] ; un[5] = tsuf[1] ; un[6] = tsuf[2] ;
173    strcpy(im->fname,pg); strcat(im->fname,"/"); strcat(im->fname,un);
174    free(un) ;
175 
176    fp = fopen( im->fname , "wb" ) ;
177    if( fp == NULL ){
178      ERROR_message("mri_purge: Can't open file %s",im->fname) ;
179      EXRETURN ;
180    }
181 
182    npix = fwrite( iar , (size_t)im->pixel_size , (size_t)im->nvox , fp ) ;
183    fclose(fp) ;
184 
185    if( npix < (size_t)im->nvox ){
186      long long nb = ((long long)im->pixel_size) * ((long long)im->nvox) ;
187      ERROR_message("mri_purge: Can't write %lld bytes to %s",nb,im->fname) ;
188      remove(im->fname) ;
189    } else {
190      free(iar) ; mri_clear_data_pointer(im) ; im->fondisk = IS_PURGED ;
191      add_purge(im->fname) ;
192      if( !atexit_called ){ atexit(purge_atexit); atexit_called = 1; }
193      if( PRINT_TRACING ){
194        long long nb = ((long long)im->pixel_size) * ((long long)im->nvox) ;
195        char str[256] ;
196        sprintf(str,"wrote %lld bytes to file %s",nb,im->fname); STATUS(str);
197      }
198    }
199 
200    EXRETURN ;
201 }
202 
203 /*----------------------------------------------------------------------------*/
204 /*! Retrieve a mri_purge()-ed image from disk.  The temp file will be deleted.
205 ------------------------------------------------------------------------------*/
206 
mri_unpurge(MRI_IMAGE * im)207 void mri_unpurge( MRI_IMAGE *im )
208 {
209    void *iar ;
210    FILE *fp ;
211    size_t npix ;
212 
213 ENTRY("mri_unpurge") ;
214 
215    if( im == NULL || !MRI_IS_PURGED(im) ) EXRETURN ;
216    iar = im->im ; if( iar != NULL ) EXRETURN ;
217 
218    fp = fopen( im->fname , "rb" ) ;
219    if( fp == NULL ){
220      ERROR_message("mri_unpurge: Can't open file %s",im->fname) ;
221      EXRETURN ;
222    }
223 
224    /* make space for data we are about to receive */
225 
226    iar = calloc( (size_t)im->pixel_size , (size_t)im->nvox ) ;
227    if( iar == NULL ){
228      long long nb = ((long long)im->pixel_size) * ((long long)im->nvox) ;
229      ERROR_message("mri_unpurge: Can't malloc() %lld bytes",nb) ;
230      fclose(fp); remove(im->fname); im->fondisk = 0; kill_purge(im->fname);
231      EXRETURN;
232    }
233    mri_fix_data_pointer( iar , im ) ;
234 
235    /* get the data, babeee! */
236 
237    npix = fread( iar , (size_t)im->pixel_size , (size_t)im->nvox , fp ) ;
238    fclose(fp); remove(im->fname); im->fondisk = 0; kill_purge(im->fname);
239 
240    if( npix < (size_t)im->nvox ){  /* didn't get enuf data? */
241      long long nb = ((long long)im->pixel_size) * ((long long)im->nvox) ;
242      WARNING_message("mri_unpurge: Can't read %lld bytes from %s",nb,im->fname);
243    } else if( PRINT_TRACING ){     /* debug tracing output? */
244      long long nb = ((long long)im->pixel_size) * ((long long)im->nvox) ;
245      char str[256] ;
246      sprintf(str,"read %lld bytes from file %s",nb,im->fname); STATUS(str);
247    }
248 
249    EXRETURN ;
250 }
251 
252 /*----------------------------------------------------------------------------*/
253 /*! If the image is purged to disk, kill the purge file.
254     Called from mri_free() to make sure that purged images are cleaned up.
255 ------------------------------------------------------------------------------*/
256 
mri_killpurge(MRI_IMAGE * im)257 void mri_killpurge( MRI_IMAGE *im )
258 {
259 ENTRY("mri_killpurge") ;
260 #if 1
261    STATUSp("check if im==NULL",im) ; if( im == NULL ) EXRETURN ;
262    if( PRINT_TRACING ){
263      char str[256] ;
264      STATUS("check fondisk") ; sprintf(str,"fondisk = %d",im->fondisk) ; STATUS(str) ;
265    }
266    if( PRINT_TRACING ){
267      char str[256] ;
268      STATUS("check fname") ; sprintf(str,"fname = %s",(im->fname!=NULL) ? im->fname : "NULL") ; STATUS(str) ;
269    }
270    if( im->fname == NULL ){ STATUS("can't killpurge NULL fname!") ; EXRETURN ; }
271    STATUS("check if purged") ;
272 #endif
273    if( MRI_IS_PURGED(im) ){
274 #if 1
275      STATUS(" is purged to following filename") ; STATUS(im->fname) ;
276 #endif
277      remove(im->fname); im->fondisk = 0; kill_purge(im->fname);
278      if( PRINT_TRACING ){
279        char str[256]; sprintf(str,"removed file %s",im->fname); STATUS(str);
280      }
281    }
282    EXRETURN ;
283 }
284