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