1 /*****************************************************************************
2 Major portions of this software are copyrighted by the Medical College
3 of Wisconsin, 1994-2000, and are released under the Gnu General Public
4 License, Version 2. See the file README.Copyright for details.
5 ******************************************************************************/
6
7 #include <pwd.h>
8 #include "mrilib.h"
9 #include "thd.h"
10
11 /*-------------------------------------------------------------*/
12 /*! Return the time at which the file was last modified. */
13
THD_file_mtime(char * pathname)14 time_t THD_file_mtime( char *pathname ) /* 05 Dec 2001 */
15 {
16 static struct stat buf ; int ii ;
17
18 if( pathname == NULL || *pathname == '\0' ) return 0 ;
19 ii = stat( pathname , &buf ) ; if( ii != 0 ) return 0 ;
20 return (time_t)buf.st_mtime ;
21 }
22
23 /*-----------------------------------------------------------*/
24 /*! Determine if this exists at all (file, directory, ...). */
25
THD_is_ondisk(char * pathname)26 int THD_is_ondisk( char *pathname ) /* 19 Dec 2002 */
27 {
28 static struct stat buf ; int ii ;
29
30 if( pathname == NULL || *pathname == '\0' ) return 0 ;
31 ii = stat( pathname , &buf ) ;
32 return (ii == 0) ;
33 }
34
35 /*-----------------------------------------------------------*/
36 /*! Determine if a prefix is that of a dset on disk. */
37
THD_is_prefix_ondisk(char * pathname,int stripsels)38 int THD_is_prefix_ondisk( char *pathname, int stripsels)
39 {
40 int ii, open1, open2, open3, open4;
41 char *ppp=pathname;
42
43 if (!pathname) return(0);
44
45 if (stripsels) {
46 ppp = strdup(pathname);
47 open1 = open2 = open3 = open4 = 0;
48 for (ii=strlen(ppp)-1; ii>=0; --ii) {
49 if (ppp[ii] == ']' && !open1) open1=1;
50 else if (ppp[ii] == '[' && open1) ppp[ii] = '\0';
51 else if (ppp[ii] == '>' && !open2) open2=1;
52 else if (ppp[ii] == '<' && open2) ppp[ii] = '\0';
53 else if (ppp[ii] == '}' && !open3) open3=1;
54 else if (ppp[ii] == '{' && open3) ppp[ii] = '\0';
55 else if (ppp[ii] == '#' && !open4) open4=1;
56 else if (ppp[ii] == '#' && open4) ppp[ii] = '\0';
57 }
58 }
59
60 if (THD_is_directory(ppp)) { if (ppp!=pathname) free(ppp); return(0); }
61 if (THD_is_ondisk(ppp)) { if (ppp!=pathname) free(ppp); return (1); }
62 ii = THD_is_dataset(THD_filepath(ppp), THD_trailname(ppp,0), -1);
63 if (ii ==-1) { if (ppp!=pathname) free(ppp); return(0); }
64 else { if (ppp!=pathname) free(ppp); return(1); }
65 }
66
67 /*-----------------------------------------------------------*/
68 /*! Change working directory. */
69
THD_cwd(char * pathname)70 int THD_cwd( char *pathname ) /* 19 Dec 2002 */
71 {
72 if( pathname == NULL || *pathname == '\0' ) return 0 ;
73 return ( chdir(pathname) == 0 ) ;
74 }
75
76 /*-----------------------------------------------------------*/
77 /*! Create a directory. Returns 1 if OK, 0 if not. */
78
THD_mkdir(char * pathname)79 int THD_mkdir( char *pathname ) /* 19 Dec 2002 */
80 {
81 int lp , ii , jj ;
82 char *pnam ;
83
84 /* check if input is OK, or if it already exists */
85
86 if( !THD_filename_ok(pathname) ) return 0 ;
87 if( THD_is_ondisk (pathname) ) return THD_is_directory(pathname) ;
88
89 pnam = strdup(pathname) ; /* modifiable copy */
90 lp = strlen(pnam) ; ii = 0 ;
91
92 /* loop over path segments, creating them if needed */
93
94 while(1){
95
96 /* advance ii to point to end of next path segment,
97 at the next '/' character, or at the end of pnam */
98
99 ii += strspn(pnam+ii,"/") ; ii += strcspn(pnam+ii,"/") ;
100
101 /* insert a NUL to replace the '/', temporarily */
102
103 if( ii < lp ) pnam[ii] = '\0' ;
104
105 /* if this segment doesn't already exist, create it */
106
107 if( !THD_is_directory(pnam) ){
108 jj = mkdir( pnam , 0755 ) ;
109 if( jj != 0 ){ free(pnam); return 0; } /* bad */
110 }
111
112 /* if reached end of path string, we're done */
113
114 if( ii == lp ){ free(pnam); return 1; } /* good */
115
116 /* reinsert '/' if it was excised */
117
118 pnam[ii] = '/' ;
119 }
120
121 return 0 ; /* unreachable */
122 }
123
124 /*-----------------------------------------------------------*/
125 /*! Determine if this is really a regular file or not. */
126
THD_is_file(char * pathname)127 int THD_is_file( char *pathname )
128 {
129 static struct stat buf ; int ii ;
130
131 if( pathname == NULL || *pathname == '\0' ) return 0 ;
132 ii = stat( pathname , &buf ) ; if( ii != 0 ) return 0 ;
133 ii = (buf.st_mode & S_IFREG) != 0 ; return ii ;
134 }
135
136 /*-----------------------------------------------------------*/
137 /*! Determine if this is a FIFO or not. [27 Aug 2019] */
138
THD_is_fifo(char * pathname)139 int THD_is_fifo( char *pathname )
140 {
141 static struct stat buf ; int ii ;
142
143 if( pathname == NULL || *pathname == '\0' ) return 0 ;
144 ii = stat( pathname , &buf ) ; if( ii != 0 ) return 0 ;
145 ii = (buf.st_mode & S_IFIFO) != 0 ; return ii ;
146 }
147
148 /*------------------------------------------------------------*/
149 /*! Determine if this is really a symbolic link or not. */
150
THD_is_symlink(char * pathname)151 int THD_is_symlink( char *pathname ) /* 03 Mar 1999 */
152 {
153 char buf[32] ; int ii ;
154
155 if( pathname == NULL || *pathname == '\0' ) return 0 ;
156 ii = readlink( pathname , buf , 32 ) ;
157 return (ii > 0) ;
158 }
159
160 /*-------------------------------------------------------*/
161 /*! Return the file length (0 if file not found). */
162
THD_filesize(char * pathname)163 long long THD_filesize( char *pathname )
164 {
165 static struct stat buf ; int ii ;
166
167 if( pathname == NULL || *pathname == '\0' ) return 0 ;
168 ii = stat( pathname , &buf ) ; if( ii != 0 ) return 0 ;
169 return (long long)buf.st_size ;
170 }
171
172 /*-------------------------------------------------------*/
173 /*! Return the file's last modified date in a string */
174
THD_filetime(char * pathname)175 char *THD_filetime( char *pathname )
176 {
177 static struct stat buf ; int ii ;
178 static char sout[10][64];
179 static int icall=0;
180 static struct tm *lt=NULL ;
181
182 ++icall; if (icall > 9) icall=0;
183 sout[icall][0]='\0';
184
185 if( pathname == NULL || *pathname == '\0' ) return (sout[icall]);
186 ii = stat( pathname , &buf ) ; if( ii != 0 ) return (sout[icall]) ;
187
188 lt = localtime(&buf.st_mtime);
189 sprintf(sout[icall], "%04d_%02d_%02d-%02d_%02d_%02d",
190 lt->tm_year+1900, lt->tm_mon+1, lt->tm_mday,
191 lt->tm_hour, lt->tm_min, lt->tm_sec);
192
193 return (sout[icall]) ;
194 }
195
196 /*-------------------------------------------------------*/
197 /*! Compare file's last modified date to reference
198 -1 file modification predates the specified day
199 0 same as specified day
200 1 newer
201 2 for error in input or file not found */
202
THD_filetime_diff(char * pathname,int year,int month,int day)203 int THD_filetime_diff( char *pathname,
204 int year, int month, int day )
205 {
206 static struct stat buf ; int ii ;
207 static struct tm *lt=NULL ;
208 int fday, Dday = year*10000+month*100+day;
209
210 if( pathname == NULL || *pathname == '\0' ) return (2);
211 ii = stat( pathname , &buf ) ; if( ii != 0 ) return (2) ;
212
213 lt = localtime(&buf.st_mtime);
214 fday = (lt->tm_year+1900)*10000+(lt->tm_mon+1)*100+lt->tm_mday;
215 if (Dday > fday) return(-1);
216 else if (Dday < fday) return(1);
217 else return(0);
218 }
219
220
THD_homedir(byte withslash)221 char *THD_homedir(byte withslash)
222 {
223 static char sout[3][520];
224 static int icall=0;
225 char *home=NULL;
226 int nn=0;
227 struct passwd *pw = NULL;
228
229 ++icall; if (icall>2) icall=0;
230 sout[icall][0]='\0';
231
232 home = getenv("HOME");
233 if (!home) {
234 pw = getpwuid(getuid());
235 if (pw) home = (char *)pw->pw_dir;
236 }
237 if (home) {
238 if (strlen(home) > 510) {
239 ERROR_message("Not enough space to store home dir of '%s'.\n");
240 } else {
241 sprintf(sout[icall], "%s", home);
242 }
243 }
244
245 /* remove slash */
246 while ( (nn=strlen(sout[icall])-1) && sout[icall][nn] == '/')
247 sout[icall][nn] = '\0';
248
249 if (withslash) {
250 nn=strlen(sout[icall]);
251 sout[icall][nn] = '/'; sout[icall][nn+1] = '\0';
252 }
253
254 return (sout[icall]) ;
255 }
256
THD_afnirc(void)257 char *THD_afnirc(void)
258 {
259 static char sout[3][520];
260 static int icall=0;
261
262 ++icall; if (icall>2) icall=0;
263 sout[icall][0]='\0';
264
265 strcpy(sout[icall],THD_homedir(1));
266 strcat(sout[icall],".afnirc");
267 return(sout[icall]);
268 }
269
THD_custom_atlas_dir(byte withslash)270 char *THD_custom_atlas_dir(byte withslash)
271 {
272 static char sout[3][520];
273 static int icall=0;
274 char *home=NULL;
275 int nn=0;
276 /* struct passwd *pw = NULL;*/
277
278 ++icall; if (icall>2) icall=0;
279 sout[icall][0]='\0';
280
281 if (!(home = getenv("AFNI_SUPP_ATLAS_DIR"))) {
282 return(sout[icall]);
283 }
284
285 if (strlen(home) > 510) {
286 ERROR_message("Not enough space to store AFNI_SUPP_ATLAS_DIR dir of '%s'.\n");
287 } else {
288 sprintf(sout[icall], "%s", home);
289 }
290
291 /* remove slash */
292 while ( (nn=strlen(sout[icall])-1)>=0 && sout[icall][nn] == '/')
293 sout[icall][nn] = '\0';
294
295 if (withslash) {
296 nn=strlen(sout[icall]);
297 sout[icall][nn] = '/'; sout[icall][nn+1] = '\0';
298 }
299
300 return (sout[icall]) ;
301 }
302
303 /* retrieve custom atlas directory and make sure it is present
304 Do not free returned pointer. Failure is a NULL pointer */
THD_get_custom_atlas_dir(byte withslash)305 char *THD_get_custom_atlas_dir(byte withslash)
306 {
307 char *cadir = NULL;
308 cadir = THD_custom_atlas_dir(withslash);
309 if (cadir[0] == '\0') {
310 ERROR_message("Have no custom atlas directory\n");
311 return(NULL);
312 }
313 if (!THD_mkdir(cadir)) {
314 ERROR_message("Cannot create %s directory\n", cadir);
315 return(NULL);
316 }
317 return(cadir);
318 }
319
THD_custom_atlas_file(char * name)320 char *THD_custom_atlas_file(char *name)
321 {
322 static char sout[3][1024];
323 static int icall=0;
324 /* struct passwd *pw = NULL;*/
325
326 ++icall; if (icall>2) icall=0;
327 sout[icall][0]='\0';
328
329 if (!name) name = getenv("AFNI_SUPP_ATLAS");
330 if (name) {
331 if (THD_is_file(name)) {
332 snprintf(sout[icall], 1020*sizeof(char),"%s",name);
333 return (sout[icall]) ;
334 } else {
335 snprintf(sout[icall], 1020*sizeof(char),
336 "%s/%s",THD_custom_atlas_dir(0),name);
337 if (!THD_is_file(sout[icall])) {
338 ERROR_message("Supp atlas file %s not found", name);
339 }
340 return (sout[icall]) ;
341 }
342 }
343 /* no name, try default */
344 name = "CustomAtlases.niml";
345 if (THD_is_file(name)) {
346 snprintf(sout[icall], 1020*sizeof(char),"%s",name);
347 return (sout[icall]) ;
348 } else {
349 snprintf(sout[icall], 1020*sizeof(char),
350 "%s/%s",THD_custom_atlas_dir(0),name);
351 if (THD_is_file(sout[icall])) {
352 return (sout[icall]) ;
353 } else {
354 sout[icall][0]='\0';
355 return (sout[icall]) ;
356 }
357 }
358
359 return (sout[icall]) ;
360 }
361
362 /* Return the name of the help directory, no guarantee that it exists
363 Consider THD_get_helpdir()
364 Do not free returned pointer. Failure results in an empty string.
365 */
THD_helpdir(byte withslash)366 char *THD_helpdir(byte withslash)
367 {
368 static char sout[3][610];
369 static int icall=0;
370 char *home=NULL;
371
372 ++icall; if (icall>2) icall=0;
373
374 sout[icall][0]='\0';
375
376 home = THD_homedir(0);
377 if (home[0]=='\0') return(sout[icall]);
378
379 if (withslash) snprintf(sout[icall],600*sizeof(char),"%s/.afni/help/",home);
380 else snprintf(sout[icall],599*sizeof(char),"%s/.afni/help",home);
381
382 return (sout[icall]) ;
383 }
384
385 /* Return the name of the data directory, no guarantee that it exists
386 Consider THD_get_datadir()
387 Do not free returned pointer. Failure results in an empty string.
388 */
THD_datadir(byte withslash)389 char *THD_datadir(byte withslash)
390 {
391 static char sout[3][610];
392 static int icall=0;
393 char *home=NULL;
394
395 ++icall; if (icall>2) icall=0;
396
397 sout[icall][0]='\0';
398
399 home = THD_homedir(0);
400 if (home[0]=='\0') return(sout[icall]);
401
402 if (withslash) snprintf(sout[icall],600*sizeof(char),"%s/.afni/data/",home);
403 else snprintf(sout[icall],599*sizeof(char),"%s/.afni/data",home);
404
405 return (sout[icall]) ;
406 }
407
408 /* retrieve help directory and make sure it is present
409 Do not free returned pointer. Failure is a NULL pointer */
THD_get_helpdir(byte withslash)410 char *THD_get_helpdir(byte withslash)
411 {
412 char *hdir = NULL;
413 hdir = THD_helpdir(withslash);
414 if (hdir[0] == '\0') {
415 ERROR_message("Have no help directory\n");
416 return(NULL);
417 }
418 if (!THD_mkdir(hdir)) {
419 ERROR_message("Cannot create %s directory\n", hdir);
420 return(NULL);
421 }
422 return(hdir);
423 }
424
425 /* retrieve data directory and make sure it is present
426 Do not free returned pointer. Failure is a NULL pointer */
THD_get_datadir(byte withslash)427 char *THD_get_datadir(byte withslash)
428 {
429 char *hdir = NULL;
430 hdir = THD_datadir(withslash);
431 if (hdir[0] == '\0') {
432 ERROR_message("Have no data directory\n");
433 return(NULL);
434 }
435 if (!THD_mkdir(hdir)) {
436 ERROR_message("Cannot create %s directory\n", hdir);
437 return(NULL);
438 }
439 return(hdir);
440 }
441
THD_helpsearchlog(int createpath)442 char *THD_helpsearchlog(int createpath)
443 {
444 static int bad = 0;
445 static char shelpname[256]={""};
446
447 if (!bad && createpath && !THD_mkdir(THD_helpdir(0))) {
448 ERROR_message("Cannot create %s help directory\n", THD_helpdir(0));
449 bad = 1;
450 }
451 snprintf(shelpname,255*sizeof(char),
452 "%s/aps.log.txt",THD_helpdir(0));
453 return(shelpname);
454 }
455
456
457 /*--------------------------------------------------------*/
458 /*! Determine if this is really a directory or not. */
459
THD_is_directory(char * pathname)460 int THD_is_directory( char *pathname )
461 {
462 static struct stat buf ; int ii ;
463
464 if( pathname == NULL || *pathname == '\0' ) return 0 ;
465 ii = stat( pathname , &buf ) ; if( ii != 0 ) return 0 ;
466 ii = (buf.st_mode & S_IFDIR) != 0 ; return ii ;
467 }
468
469 /*---------------------------------------------------------------*/
470 /*! Determine if this is really an executable file or not. */
471
THD_is_executable(char * pathname)472 int THD_is_executable( char *pathname ) /* 26 Jun 2001 */
473 {
474 static struct stat buf ; int ii ;
475
476 if( pathname == NULL || *pathname == '\0' ) return 0 ;
477 ii = stat( pathname , &buf ) ; if( ii ) return 0 ;
478 ii = (buf.st_mode & S_IXOTH) != 0 ; if( ii ) return ii ;
479
480 /* 15 Jul 2002: also check if file is owned & executable by user */
481
482 ii = ( getuid() == buf.st_uid &&
483 (buf.st_mode & S_IXUSR) != 0 ) ;
484 return ii ;
485 }
486
487 /*--------------------------------------------------------------*/
488 /*! Determine if two filenames are really the same thing. */
489
THD_equiv_files(char * path1,char * path2)490 int THD_equiv_files( char *path1 , char *path2 )
491 {
492 static struct stat buf1 , buf2 ; int ii ;
493
494 if( path1 == NULL || path2 == NULL ) return -1 ;
495 ii = stat( path1 , &buf1 ) ; if( ii != 0 ) return -1 ;
496 ii = stat( path2 , &buf2 ) ; if( ii != 0 ) return -1 ;
497
498 ii = (buf1.st_dev == buf2.st_dev) && (buf1.st_ino == buf2.st_ino) ;
499 return ii ;
500 }
501
502 /*-----------------------------------------------------------------*/
503 /*! Find a 'trailing name in a pathname.
504
505 For example, for fname = "/bob/cox/is/the/author/of/AFNI",
506 - the lev=0 trailing name is "AFNI",
507 - the lev=1 trailing name is "of/AFNI",
508 - the lev=2 trailing name is "author/of/AFNI", and so on.
509 That is, "lev" is the number of directory names above the
510 last name to keep. The pointer returned is to some place
511 in the middle of fname; that is, this is not a malloc()-ed
512 string, so don't try to free() it!.
513 -------------------------------------------------------------------*/
514
THD_trailname(char * fname,int lev)515 char * THD_trailname( char *fname , int lev )
516 {
517 int fpos , flen , flev ;
518
519 if( fname == NULL || (flen=strlen(fname)) <= 1 ) return fname ;
520
521 if( lev < 0 ) lev = 0 ;
522
523 flev = 0 ;
524 fpos = flen ;
525 if( fname[fpos-1] == '/' ) fpos-- ; /* skip trailing slash */
526
527 /* fpos = index of latest character I've accepted,
528 fpos-1 = index of next character to examine,
529 flev = number of directory levels found so far */
530
531 while( fpos > 0 ){
532
533 if( fname[fpos-1] == '/' ){
534 flev++ ; if( flev > lev ) break ; /* reached the lev we like */
535 }
536 fpos-- ; /* scan backwards */
537 }
538
539 return (fname+fpos) ;
540 }
541
542 /*----------------------------------------------------------------------*/
543 /*! Return the path to fname.
544 Do not free returned string.
545 */
THD_filepath(char * fname)546 char * THD_filepath( char *fname )
547 {
548 static int icall=-1;
549 static char pname[10][THD_MAX_NAME];
550 char *ppp = NULL;
551 long lend=0;
552
553 ++icall; if (icall > 9) icall = 0;
554 pname[icall][0]='.'; pname[icall][1]='/'; pname[icall][2]='\0';
555
556 if (!fname) return(pname[icall]);
557
558 lend = strlen(fname);
559 if (fname[lend-1] == '/') { /* fname is a path*/
560 if (lend >= THD_MAX_NAME-1) {
561 ERROR_message("Path name too long. Returning './' as the file path :(");
562 ERROR_message(" Offending input is:\n %s",fname) ;
563 ERROR_message("Almost certainly something bad will happen below here!") ;
564 } else {
565 strncpy(pname[icall], fname, lend);
566 pname[icall][lend]='\0';
567 }
568 return(pname[icall]);
569 }
570
571 if (!(ppp=THD_trailname(fname,0))) return(pname[icall]);
572 if (!(lend = ppp-fname)) return(pname[icall]); /* no path on name */
573
574 if (lend >= THD_MAX_NAME-1) {
575 ERROR_message("Path name too long. Returning './' as the file path :-(");
576 ERROR_message(" Offending input is:\n %s",fname) ;
577 ERROR_message("Almost certainly something bad will happen below here!") ;
578 return(pname[icall]);
579 }
580
581 strncpy(pname[icall], fname, lend);
582 pname[icall][lend]='\0';
583 if( pname[icall][lend-1] != '/' ){
584 pname[icall][lend-1] = '/';
585 pname[icall][lend] = '\0';
586 }
587 return(pname[icall]);
588 }
589
590 /*----------------------------------------------------------------------*/
591 /* Does filename have a path */
THD_filehaspath(char * fname)592 int THD_filehaspath ( char *fname)
593 {
594 if (!fname) return(0);
595 while (*fname!='\0') { if (*fname=='/') return(1); else ++fname; }
596 return(0);
597 }
598
599 /*----------------------------------------------------------------------*/
600
THD_character_ok(char c)601 int THD_character_ok( char c ) /* 04 Feb 2010 */
602 {
603 if( iscntrl(c) || isspace(c) ||
604 c == ';' ||
605 c == '*' || c == '?' ||
606 c == '&' || c == '|' ||
607 c == '"' || c == '>' ||
608 c == '<' || c == '\'' ||
609 c == '[' || c == ']' ||
610 c == '(' || c == ')' ||
611 c == '{' || c == '}' ||
612 c == '!' || (c & 128) != 0 ) return 0 ;
613 return 1 ;
614 }
615
616 /*----------------------------------------------------------------------*/
617
THD_filename_fix(char * name)618 int THD_filename_fix( char *name ) /* 04 Feb 2010 */
619 {
620 int ll , ii , nfix ;
621
622 if( name == NULL ) return -1 ;
623 ll = strlen( name ) ; if( ll == 0 ) return -1 ;
624 for( nfix=ii=0 ; ii < ll ; ii++ ){
625 if( !THD_character_ok(name[ii]) ){ name[ii] = '_' ; nfix++ ; }
626 }
627 return nfix ;
628 }
629
630 /*----------------------------------------------------------------------*/
631 /*! Check if a filename is OK - that is, has no crummy characters.
632
633 The filename can have a '/' in it. To insist that there be not '/',
634 use THD_filename_pure().
635 The list of crummy characters can be inferred from the source code.
636 */
637
THD_filename_ok(char * name)638 int THD_filename_ok( char *name ) /* 24 Apr 1997 */
639 {
640 int ll , ii ;
641
642 if( name == NULL ) return 0 ;
643 ll = strlen( name ) ; if( ll == 0 ) return 0 ;
644 if (ll > 6 && strstr(name, "3dcalc") == name) {
645 return 1; /* have a 3dcalc command, let it be*/
646 }
647 if( AFNI_yesenv("AFNI_ALLOW_ARBITRARY_FILENAMES") ) return 1 ; /* 08 Apr 2009 */
648 for( ii=0 ; ii < ll ; ii++ )
649 if( iscntrl(name[ii]) || isspace(name[ii]) ||
650 name[ii] == ';' ||
651 name[ii] == '*' || name[ii] == '?' ||
652 name[ii] == '&' || name[ii] == '|' ||
653 name[ii] == '"' || name[ii] == '>' ||
654 name[ii] == '<' || name[ii] == '\'' ||
655 name[ii] == '[' || name[ii] == ']' ||
656 name[ii] == '(' || name[ii] == ')' ||
657 name[ii] == '{' || name[ii] == '}' ||
658 name[ii] == '!' || (name[ii] & 128) != 0 ) return 0 ;
659
660 return 1 ;
661 }
662
663 /*--------------------------------------------------------------------*/
664 /*! Check if a filename is pure - no crummy characters, no '/'. */
665
THD_filename_pure(char * name)666 int THD_filename_pure( char *name ) /* 28 Feb 2001 */
667 {
668 int ii ;
669
670 ii = THD_filename_ok( name ) ;
671 if( ii ) ii = (strstr(name,"/") == NULL) ;
672 return ii ;
673 }
674
675 /*--------------------------------------------------------------*/
676
677 #undef FNAME
678 #undef FSTYP
679 #undef BSIZE
680 #undef BFREE
681
682 #if defined(DARWIN) || defined(FreeBSD) /* Mac or BSD */
683 # include <sys/param.h>
684 # include <sys/mount.h>
685 # define FNAME(a,b) statfs(a,b)
686 # define FSTYP statfs
687 # define BSIZE f_bsize
688 # define BFREE f_bavail
689 #elif defined(LINUX) /* Linux */
690 # include <sys/vfs.h>
691 # define FNAME(a,b) statfs(a,b)
692 # define FSTYP statfs
693 # define BSIZE f_bsize
694 # define BFREE f_bavail
695 #elif defined(SOLARIS) || defined(SGI) /* Sun or SGI */
696 # include <sys/types.h>
697 # include <sys/statvfs.h>
698 # define FNAME(a,b) statvfs64(a,b)
699 # define FSTYP statvfs64
700 # define BSIZE f_bsize
701 # define BFREE f_bavail
702 #endif
703
704 /*--------------------------------------------------------------*/
705 /*! Get free space (in megabytes) on a disk partition.
706 Return value is -1 if can't be determined.
707 ----------------------------------------------------------------*/
708
THD_freemegabytes(char * pathname)709 int THD_freemegabytes( char *pathname )
710 {
711 #ifdef FNAME
712 int ii ; struct FSTYP buf ;
713 if( pathname == NULL || *pathname == '\0' ) return -1 ;
714 ii = FNAME( pathname , &buf ) ;
715 if( ii ) return -1 ;
716 ii = (int)((double)(buf.BFREE) * (double)(buf.BSIZE) / (1024.0*1024.0)) ;
717 return ii ;
718 #else
719 return -1 ;
720 #endif
721 }
722
723 /*----------------------------------------------------------------------*/
724 /*! Check a list of dataset names for duplicates. Return value is number
725 of duplicates found.
726 - ns = number of strings
727 - sar = string array
728 - flag = 1 to print warnings, 0 to be silent
729 ------------------------------------------------------------------------*/
730
THD_check_for_duplicates(int ns,char ** sar,int flag)731 int THD_check_for_duplicates( int ns , char **sar , int flag )
732 {
733 int verb = (flag & 1) != 0 ;
734 int ii,jj,li,lj,nw=0 ; char *di, *dj ;
735
736 ENTRY("THD_check_for_duplicates") ;
737
738 if( sar == NULL ) RETURN(0) ;
739
740 for( ii=0 ; ii < ns-1 ; ii++ ){
741
742 if( sar[ii] == NULL ) continue ;
743 di = strdup(sar[ii] ) ; li = strlen(di) ;
744 if( strcmp(di+li-5,".HEAD" ) == 0 ) di[li-5] = '\0' ;
745 else if( strcmp(di+li-5,".BRIK" ) == 0 ) di[li-5] = '\0' ;
746 else if( strcmp(di+li-8,".BRIK.gz") == 0 ) di[li-8] = '\0' ;
747 else if( strcmp(di+li-7,".nii.gz" ) == 0 ) di[li-3] = '\0' ;
748 else if( strcmp(di+li-1,"." ) == 0 ) di[li-1] = '\0' ;
749
750 for( jj=ii+1 ; jj < ns ; jj++ ){
751
752 if( sar[jj] == NULL ) continue ;
753 dj = strdup(sar[jj]) ; lj = strlen(dj) ;
754 if( strcmp(dj+lj-5,".HEAD" ) == 0 ) dj[lj-5] = '\0' ;
755 else if( strcmp(dj+lj-5,".BRIK" ) == 0 ) dj[lj-5] = '\0' ;
756 else if( strcmp(dj+lj-8,".BRIK.gz") == 0 ) dj[lj-8] = '\0' ;
757 else if( strcmp(dj+lj-7,".nii.gz" ) == 0 ) dj[lj-3] = '\0' ;
758 else if( strcmp(dj+lj-1,"." ) == 0 ) dj[lj-1] = '\0' ;
759
760 if( strcmp(di,dj) == 0 ){
761 nw++ ;
762 if( verb ) WARNING_message("Datasets '%s' and '%s' are the same?!?",
763 sar[ii] , sar[jj] ) ;
764 }
765 free(dj) ;
766 }
767 free(di) ;
768 }
769
770 RETURN(nw) ;
771 }
772
773 /*----------------------------------------------------------------------*/
774 /* Check if this directory name is forbidden fruit. */
775 /*----------------------------------------------------------------------*/
776
THD_forbidden_directory(char * dname)777 int THD_forbidden_directory( char *dname )
778 {
779 if( dname == NULL || *dname == '\0' ) return 1 ;
780
781 #ifdef DARWIN
782 /* skip system name directories if on MacOS X [18 Sep 2020] */
783 if(
784 strcasestr(dname,"Applications") != NULL ||
785 strcasestr(dname,"Desktop") != NULL ||
786 strcasestr(dname,"Documents") != NULL ||
787 strcasestr(dname,"Downloads") != NULL ||
788 strcasestr(dname,"Library") != NULL ||
789 strcasestr(dname,"Movies") != NULL ||
790 strcasestr(dname,"Music") != NULL ||
791 strcasestr(dname,"Pictures") != NULL
792 ) return 1 ;
793 #endif
794
795 /** Other possibilities could go here **/
796
797 return 0 ;
798 }
799