renamed GMX_THREADS to GMX_THREAD_MPI
[alexxy/gromacs.git] / src / gmxlib / futil.c
1 /* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
2  *
3  * 
4  *                This source code is part of
5  * 
6  *                 G   R   O   M   A   C   S
7  * 
8  *          GROningen MAchine for Chemical Simulations
9  * 
10  *                        VERSION 3.2.0
11  * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
12  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
13  * Copyright (c) 2001-2004, The GROMACS development team,
14  * check out http://www.gromacs.org for more information.
15
16  * This program is free software; you can redistribute it and/or
17  * modify it under the terms of the GNU General Public License
18  * as published by the Free Software Foundation; either version 2
19  * of the License, or (at your option) any later version.
20  * 
21  * If you want to redistribute modifications, please consider that
22  * scientific software is very special. Version control is crucial -
23  * bugs must be traceable. We will be happy to consider code for
24  * inclusion in the official distribution, but derived work must not
25  * be called official GROMACS. Details are found in the README & COPYING
26  * files - if they are missing, get the official version at www.gromacs.org.
27  * 
28  * To help us fund GROMACS development, we humbly ask that you cite
29  * the papers on the package - you can find them in the top README file.
30  * 
31  * For more info, check our website at http://www.gromacs.org
32  * 
33  * And Hey:
34  * GROningen Mixture of Alchemy and Childrens' Stories
35  */
36 #ifdef HAVE_CONFIG_H
37 #include <config.h>
38 #endif
39
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <sys/types.h>
44 #include <sys/stat.h>
45 #include <fcntl.h>
46
47 #ifdef HAVE_DIRENT_H
48 /* POSIX */
49 #include <dirent.h>
50 #endif
51
52
53 #if ((defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64) && !defined __CYGWIN__ && !defined __CYGWIN32__)
54 #include <direct.h>
55 #include <io.h>
56 #endif
57
58 #include "sysstuff.h"
59 #include "string2.h"
60 #include "futil.h"
61 #include "network.h"
62 #include "gmx_fatal.h"
63 #include "smalloc.h"
64 #include "statutil.h"
65
66
67 #ifdef GMX_THREAD_MPI
68 #include "thread_mpi.h"
69 #endif
70
71 /* Windows file stuff, only necessary for visual studio */
72 #ifdef _MSC_VER
73 #include "windows.h"
74 #endif
75
76 /* we keep a linked list of all files opened through pipes (i.e. 
77    compressed or .gzipped files. This way we can distinguish between them
78    without having to change the semantics of reading from/writing to files) 
79    */
80 typedef struct t_pstack {
81     FILE   *fp;
82     struct t_pstack *prev;
83 } t_pstack;
84
85 static t_pstack *pstack=NULL;
86 static gmx_bool     bUnbuffered=FALSE;
87
88 #ifdef GMX_THREAD_MPI
89 /* this linked list is an intrinsically globally shared object, so we have
90    to protect it with mutexes */
91 static tMPI_Thread_mutex_t pstack_mutex=TMPI_THREAD_MUTEX_INITIALIZER;
92 #endif
93
94 void no_buffers(void)
95 {
96     bUnbuffered=TRUE;
97 }
98
99 void push_ps(FILE *fp)
100 {
101     t_pstack *ps;
102
103 #ifdef GMX_THREAD_MPI
104     tMPI_Thread_mutex_lock(&pstack_mutex);
105 #endif
106
107     snew(ps,1);
108     ps->fp   = fp;
109     ps->prev = pstack;
110     pstack   = ps;
111 #ifdef GMX_THREAD_MPI
112     tMPI_Thread_mutex_unlock(&pstack_mutex);
113 #endif
114 }
115
116 #ifdef GMX_FAHCORE
117 /* don't use pipes!*/
118 #define popen fah_fopen
119 #define pclose fah_fclose
120 #define SKIP_FFOPS 1
121 #else
122 #ifdef ffclose
123 #undef ffclose
124 #endif
125 #endif
126
127 #ifndef GMX_FAHCORE
128 #ifndef HAVE_PIPES
129 static FILE *popen(const char *nm,const char *mode)
130 {
131     gmx_impl("Sorry no pipes...");
132
133     return NULL;
134 }
135
136 static int pclose(FILE *fp)
137 {
138     gmx_impl("Sorry no pipes...");
139
140     return 0;
141 }
142 #endif
143 #endif
144
145 int ffclose(FILE *fp)
146 {
147 #ifdef SKIP_FFOPS
148     return fclose(fp);
149 #else
150     t_pstack *ps,*tmp;
151     int ret=0;
152 #ifdef GMX_THREAD_MPI
153     tMPI_Thread_mutex_lock(&pstack_mutex);
154 #endif
155
156     ps=pstack;
157     if (ps == NULL) {
158         if (fp != NULL) 
159             ret = fclose(fp);
160     }
161     else if (ps->fp == fp) {
162         if (fp != NULL)
163             ret = pclose(fp);
164         pstack=pstack->prev;
165         sfree(ps);
166     }
167     else {
168         while ((ps->prev != NULL) && (ps->prev->fp != fp))
169             ps=ps->prev;
170         if (ps->prev->fp == fp) {
171             if (ps->prev->fp != NULL)
172                 ret = pclose(ps->prev->fp);
173             tmp=ps->prev;
174             ps->prev=ps->prev->prev;
175             sfree(tmp);
176         }
177         else {
178             if (fp != NULL)
179                 ret = fclose(fp);
180         }
181     }
182 #ifdef GMX_THREAD_MPI
183     tMPI_Thread_mutex_unlock(&pstack_mutex);
184 #endif
185     return ret;
186 #endif
187 }
188
189
190 #ifdef rewind
191 #undef rewind
192 #endif
193
194 void frewind(FILE *fp)
195 {
196     t_pstack *ps;
197 #ifdef GMX_THREAD_MPI
198     tMPI_Thread_mutex_lock(&pstack_mutex);
199 #endif
200
201     ps=pstack;
202     while (ps != NULL) {
203         if (ps->fp == fp) {
204             fprintf(stderr,"Cannot rewind compressed file!\n");
205 #ifdef GMX_THREAD_MPI
206             tMPI_Thread_mutex_unlock(&pstack_mutex);
207 #endif
208             return;
209         }
210         ps=ps->prev;
211     }
212     rewind(fp);
213 #ifdef GMX_THREAD_MPI
214     tMPI_Thread_mutex_unlock(&pstack_mutex);
215 #endif
216 }
217
218 int gmx_fseek(FILE *stream, gmx_off_t offset, int whence)
219 {
220 #ifdef HAVE_FSEEKO
221     return fseeko(stream, offset, whence);
222 #else
223 #ifdef HAVE__FSEEKI64
224     return _fseeki64(stream, offset, whence);
225 #else
226     return fseek(stream, offset, whence);
227 #endif
228 #endif
229 }
230
231 gmx_off_t gmx_ftell(FILE *stream)
232 {
233 #ifdef HAVE_FSEEKO
234     return ftello(stream);
235 #else
236 #ifdef HAVE__FSEEKI64 
237     return _ftelli64(stream);
238 #else
239     return ftell(stream);
240 #endif
241 #endif
242 }
243
244
245 gmx_bool is_pipe(FILE *fp)
246 {
247     t_pstack *ps;
248 #ifdef GMX_THREAD_MPI
249     tMPI_Thread_mutex_lock(&pstack_mutex);
250 #endif
251
252     ps=pstack;
253     while (ps != NULL) {
254         if (ps->fp == fp) {
255 #ifdef GMX_THREAD_MPI
256             tMPI_Thread_mutex_unlock(&pstack_mutex);
257 #endif
258             return TRUE;
259         }
260         ps=ps->prev;
261     }
262 #ifdef GMX_THREAD_MPI
263     tMPI_Thread_mutex_unlock(&pstack_mutex);
264 #endif
265     return FALSE;
266 }
267
268
269 static FILE *uncompress(const char *fn,const char *mode)
270 {
271     FILE *fp;
272     char buf[256];
273
274     sprintf(buf,"uncompress -c < %s",fn);
275     fprintf(stderr,"Going to execute '%s'\n",buf);
276     if ((fp=popen(buf,mode)) == NULL)
277         gmx_open(fn);
278     push_ps(fp);
279
280     return fp;
281 }
282
283 static FILE *gunzip(const char *fn,const char *mode)
284 {
285     FILE *fp;
286     char buf[256];
287
288     sprintf(buf,"gunzip -c < %s",fn);
289     fprintf(stderr,"Going to execute '%s'\n",buf);
290     if ((fp=popen(buf,mode)) == NULL)
291         gmx_open(fn);
292     push_ps(fp);
293
294     return fp;
295 }
296
297 gmx_bool gmx_fexist(const char *fname)
298 {
299     FILE *test;
300
301     if (fname == NULL)
302         return FALSE;
303     test=fopen(fname,"r");
304     if (test == NULL) {
305         /*Windows doesn't allow fopen of directory - so we need to check this seperately */
306         #if ((defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64) && !defined __CYGWIN__ && !defined __CYGWIN32__) 
307             DWORD attr = GetFileAttributes(fname);
308             return (attr != INVALID_FILE_ATTRIBUTES) && (attr & FILE_ATTRIBUTE_DIRECTORY);
309         #else 
310             return FALSE;
311         #endif
312     } else {
313         fclose(test);
314         return TRUE;
315     }
316 }
317
318
319 gmx_bool gmx_fexist_master(const char *fname, t_commrec *cr)
320 {
321   gmx_bool bExist;
322   
323   if (SIMMASTER(cr)) 
324   {
325       bExist = gmx_fexist(fname);
326   }
327   if (PAR(cr)) 
328   {
329       gmx_bcast(sizeof(bExist),&bExist,cr);
330   }
331   return bExist;
332 }
333
334 gmx_bool gmx_eof(FILE *fp)
335 {
336     char data[4];
337     gmx_bool beof;
338
339     if (is_pipe(fp))
340         return feof(fp);
341     else {
342         if ((beof=fread(data,1,1,fp))==1)
343             gmx_fseek(fp,-1,SEEK_CUR);
344         return !beof;
345     }
346 }
347
348 static char *backup_fn(const char *file,int count_max)
349 {
350     /* Use a reasonably low value for countmax; we might
351      * generate 4-5 files in each round, and we dont
352      * want to hit directory limits of 1024 or 2048 files.
353      */
354 #define COUNTMAX 99
355     int         i,count=1;
356     char        *directory,*fn;
357     char        *buf;
358
359     if (count_max == -1)
360     {
361         count_max = COUNTMAX;
362     }
363
364     smalloc(buf, GMX_PATH_MAX);
365
366     for(i=strlen(file)-1; ((i > 0) && (file[i] != DIR_SEPARATOR)); i--)
367         ;
368     /* Must check whether i > 0, i.e. whether there is a directory
369      * in the file name. In that case we overwrite the / sign with
370      * a '\0' to end the directory string .
371      */
372     if (i > 0) {
373         directory    = gmx_strdup(file);
374         directory[i] = '\0';
375         fn           = gmx_strdup(file+i+1);
376     }
377     else {
378         directory    = gmx_strdup(".");
379         fn           = gmx_strdup(file);
380     }
381     do {
382         sprintf(buf,"%s/#%s.%d#",directory,fn,count);
383         count++;
384     } while ((count <= count_max) && gmx_fexist(buf));
385
386     /* Arbitrarily bail out */
387     if (count > count_max) 
388         gmx_fatal(FARGS,"Won't make more than %d backups of %s for you.\n"
389                   "The env.var. GMX_MAXBACKUP controls this maximum, -1 disables backups.",
390                   count_max,fn);
391
392     sfree(directory);
393     sfree(fn);
394
395     return buf;
396 }
397
398 gmx_bool make_backup(const char * name)
399 {
400     char * env;
401     int  count_max;
402     char * backup;
403
404 #ifdef GMX_FAHCORE
405     return FALSE; /* skip making backups */
406 #else
407
408     if (gmx_fexist(name))
409     {
410         env = getenv("GMX_MAXBACKUP");
411         if (env != NULL)
412         {
413             count_max = 0;
414             sscanf(env,"%d",&count_max);
415             if (count_max == -1)
416             {
417                 /* Do not make backups and possibly overwrite old files */
418                 return TRUE;
419             }
420         }
421         else
422         {
423             /* Use the default maximum */
424             count_max = -1;
425         }
426         backup = backup_fn(name,count_max);
427         if(rename(name, backup) == 0) {
428             fprintf(stderr, "\nBack Off! I just backed up %s to %s\n",
429                     name, backup);
430         } else {
431             fprintf(stderr, "Sorry couldn't backup %s to %s\n", name, backup);
432             return FALSE;
433         }
434         sfree(backup);
435     }
436     return TRUE;
437 #endif
438 }
439
440 FILE *ffopen(const char *file,const char *mode)
441 {
442 #ifdef SKIP_FFOPS
443     return fopen(file,mode);
444 #else
445     FILE *ff=NULL;
446     char buf[256],*bf,*bufsize=0,*ptr;
447     gmx_bool bRead;
448     int  bs;
449
450     if (mode[0]=='w') {
451         make_backup(file);
452     }
453     where();
454
455     bRead= (mode[0]=='r'&&mode[1]!='+');
456     strcpy(buf,file);
457     if (!bRead || gmx_fexist(buf)) {
458         if ((ff=fopen(buf,mode))==NULL)
459             gmx_file(buf);
460         where();
461         /* Check whether we should be using buffering (default) or not
462          * (for debugging)
463          */
464         if (bUnbuffered || ((bufsize=getenv("LOG_BUFS")) != NULL)) {
465             /* Check whether to use completely unbuffered */
466             if (bUnbuffered)
467                 bs = 0;
468             else
469                 bs=strtol(bufsize, NULL, 10); 
470             if (bs <= 0)
471                 setbuf(ff,NULL); 
472             else {
473                 snew(ptr,bs+8);
474                 if (setvbuf(ff,ptr,_IOFBF,bs) != 0)
475                     gmx_file("Buffering File");
476             }
477         }
478         where();
479     }
480     else {
481         sprintf(buf,"%s.Z",file);
482         if (gmx_fexist(buf)) {
483             ff=uncompress(buf,mode);
484         }
485         else {
486             sprintf(buf,"%s.gz",file);
487             if (gmx_fexist(buf)) {
488                 ff=gunzip(buf,mode);
489             }
490             else 
491                 gmx_file(file);
492         }
493     }
494     return ff;
495 #endif
496 }
497
498 /* Our own implementation of dirent-like functionality to scan directories. */
499 struct gmx_directory
500 {
501 #ifdef HAVE_DIRENT_H
502     DIR  *               dirent_handle;
503 #elif (defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64)
504     intptr_t             windows_handle;
505     struct _finddata_t   finddata;
506     int                  first;
507 #else
508     int      dummy;
509 #endif
510 };
511
512
513 int
514 gmx_directory_open(gmx_directory_t *p_gmxdir,const char *dirname)
515 {
516     struct gmx_directory *  gmxdir;
517     int                     rc;
518     
519     snew(gmxdir,1);
520     
521     *p_gmxdir = gmxdir;
522     
523 #ifdef HAVE_DIRENT_H
524     if( (gmxdir->dirent_handle = opendir(dirname)) != NULL)
525     {
526         rc = 0;
527     }
528     else 
529     {
530         sfree(gmxdir);
531         *p_gmxdir = NULL;
532         rc        = EINVAL;
533     }
534 #elif (defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64)
535     
536     if(dirname!=NULL && strlen(dirname)>0)
537     {
538         char *     tmpname;
539         size_t     namelength;
540         int        len;
541         
542         len = strlen(dirname);
543         snew(tmpname,len+3);
544         
545         strncpy(tmpname,dirname,len+1);
546         
547         /* Remove possible trailing directory separator */
548         if(tmpname[len]=='/' || tmpname[len]=='\\')
549         {
550             tmpname[len]='\0';
551         }
552         
553         /* Add wildcard */
554         strcat(tmpname,"/*");
555         
556         gmxdir->first = 1;
557         if( (gmxdir->windows_handle=_findfirst(tmpname,&gmxdir->finddata))>0L)
558         {
559             rc = 0;
560         }
561         else
562         {
563             if(errno==EINVAL)
564             {
565                 sfree(gmxdir);
566                 *p_gmxdir = NULL;
567                 rc        = EINVAL;                
568             }
569             else
570             {
571                 rc        = 0;
572             }
573         }
574     }
575     else
576     {
577         rc = EINVAL;
578     }
579 #else
580     gmx_fatal(FARGS,
581               "Source compiled without POSIX dirent or windows support - cannot scan directories.\n"
582               "In the very unlikely event this is not a compile-time mistake you could consider\n"
583               "implementing support for your platform in futil.c, but contact the developers\n"
584               "to make sure it's really necessary!\n");
585     rc = -1;
586 #endif
587     return rc;
588 }
589
590
591 int
592 gmx_directory_nextfile(gmx_directory_t gmxdir,char *name,int maxlength_name)
593 {
594     int                     rc;
595     
596 #ifdef HAVE_DIRENT_H
597     
598     struct dirent *         direntp_large;
599     struct dirent *         p;
600     
601     
602     if(gmxdir!=NULL && gmxdir->dirent_handle!=NULL)
603     {
604         /* On some platforms no space is present for d_name in dirent.
605          * Since d_name is guaranteed to be the last entry, allocating
606          * extra space for dirent will allow more size for d_name.
607          * GMX_MAX_PATH should always be >= the max possible d_name.
608          */
609         smalloc(direntp_large, sizeof(*direntp_large) + GMX_PATH_MAX);
610         rc = readdir_r(gmxdir->dirent_handle,direntp_large,&p);
611
612         if(p!=NULL && rc==0)
613         {
614             strncpy(name,direntp_large->d_name,maxlength_name);
615         }
616         else
617         {
618             name[0] = '\0';
619             rc      = ENOENT;
620         }
621         sfree(direntp_large);
622     }
623     else 
624     {
625         name[0] = '\0';
626         rc      = EINVAL;
627     }
628     
629 #elif (defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64)
630     
631     if(gmxdir!=NULL)
632     {
633         if(gmxdir->windows_handle<=0)
634         {
635             
636             name[0] = '\0';
637             rc      = ENOENT;
638         }
639         else if(gmxdir->first==1)
640         {
641             strncpy(name,gmxdir->finddata.name,maxlength_name);
642             rc            = 0;
643             gmxdir->first = 0;
644         }
645         else
646         {
647             if(_findnext(gmxdir->windows_handle,&gmxdir->finddata)==0)
648             {
649                 strncpy(name,gmxdir->finddata.name,maxlength_name);
650                 rc      = 0;
651             }
652             else
653             {
654                 name[0] = '\0';
655                 rc      = ENOENT;
656             }
657         }
658     }
659     
660 #else
661     gmx_fatal(FARGS,
662               "Source compiled without POSIX dirent or windows support - cannot scan directories.\n");
663     rc = -1;
664 #endif
665     return rc;
666 }
667
668
669 int 
670 gmx_directory_close(gmx_directory_t gmxdir)
671 {
672     int                     rc;
673 #ifdef HAVE_DIRENT_H
674     rc = (gmxdir != NULL) ? closedir(gmxdir->dirent_handle) : EINVAL;
675 #elif (defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64)
676     rc = (gmxdir != NULL) ? _findclose(gmxdir->windows_handle) : EINVAL;
677 #else
678     gmx_fatal(FARGS,
679               "Source compiled without POSIX dirent or windows support - cannot scan directories.\n");
680     rc = -1;
681 #endif
682     
683     sfree(gmxdir);
684     return rc;
685 }
686
687
688
689
690 gmx_bool search_subdirs(const char *parent, char *libdir)
691 {
692     char *ptr;
693     gmx_bool found;
694
695     /* Search a few common subdirectory names for the gromacs library dir */
696     sprintf(libdir,"%s%cshare%ctop%cgurgle.dat",parent,
697             DIR_SEPARATOR,DIR_SEPARATOR,DIR_SEPARATOR);
698     found=gmx_fexist(libdir);
699     if(!found) {
700         sprintf(libdir,"%s%cshare%cgromacs%ctop%cgurgle.dat",parent,
701                 DIR_SEPARATOR,DIR_SEPARATOR,
702                 DIR_SEPARATOR,DIR_SEPARATOR);
703         found=gmx_fexist(libdir);
704     }    
705     if(!found) {
706         sprintf(libdir,"%s%cshare%cgromacs-%s%ctop%cgurgle.dat",parent,
707                 DIR_SEPARATOR,DIR_SEPARATOR,VERSION,
708                 DIR_SEPARATOR,DIR_SEPARATOR);
709         found=gmx_fexist(libdir);
710     }    
711     if(!found) {
712         sprintf(libdir,"%s%cshare%cgromacs%cgromacs-%s%ctop%cgurgle.dat",parent,
713                 DIR_SEPARATOR,DIR_SEPARATOR,DIR_SEPARATOR,
714                 VERSION,DIR_SEPARATOR,DIR_SEPARATOR);
715         found=gmx_fexist(libdir);
716     }    
717
718     /* Remove the gurgle.dat part from libdir if we found something */
719     if(found) {
720         ptr=strrchr(libdir,DIR_SEPARATOR); /* slash or backslash always present, no check necessary */
721         *ptr='\0';
722     }
723     return found;
724 }
725
726
727 /* Check if the program name begins with "/" on unix/cygwin, or
728  * with "\" or "X:\" on windows. If not, the program name
729  * is relative to the current directory.
730  */
731 static gmx_bool filename_is_absolute(char *name)
732 {
733 #if ((defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64) && !defined __CYGWIN__ && !defined __CYGWIN32__)
734     return ((name[0] == DIR_SEPARATOR) || ((strlen(name)>3) && strncmp(name+1,":\\",2)) == 0);
735 #else
736     return (name[0] == DIR_SEPARATOR);
737 #endif
738 }
739
740 gmx_bool get_libdir(char *libdir)
741 {
742 #define GMX_BINNAME_MAX 512
743     char bin_name[GMX_BINNAME_MAX];
744     char buf[GMX_BINNAME_MAX];
745     char full_path[GMX_PATH_MAX+GMX_BINNAME_MAX];
746     char system_path[GMX_PATH_MAX];
747     char *dir,*ptr,*s,*pdum;
748     gmx_bool found=FALSE;
749     int i;
750
751     if (Program() != NULL)
752     {
753
754     /* First - detect binary name */
755     if (strlen(Program()) >= GMX_BINNAME_MAX)
756     {
757         gmx_fatal(FARGS,"The name of the binary is longer than the allowed buffer size (%d):\n'%s'",GMX_BINNAME_MAX,Program());
758     }
759     strncpy(bin_name,Program(),GMX_BINNAME_MAX-1);
760
761     /* On windows & cygwin we need to add the .exe extension
762      * too, or we wont be able to detect that the file exists
763      */
764 #if (defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64 || defined __CYGWIN__ || defined __CYGWIN32__)
765     if(strlen(bin_name)<3 || gmx_strncasecmp(bin_name+strlen(bin_name)-4,".exe",4))
766         strcat(bin_name,".exe");
767 #endif
768
769     /* Only do the smart search part if we got a real name */
770     if (NULL!=bin_name && strncmp(bin_name,"GROMACS",GMX_BINNAME_MAX)) {
771
772         if (!strchr(bin_name,DIR_SEPARATOR)) {
773             /* No slash or backslash in name means it must be in the path - search it! */
774             /* Add the local dir since it is not in the path on windows */
775 #if ((defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64) && !defined __CYGWIN__ && !defined __CYGWIN32__)
776             pdum=_getcwd(system_path,sizeof(system_path)-1);
777 #else
778             pdum=getcwd(system_path,sizeof(system_path)-1);
779 #endif
780             sprintf(full_path,"%s%c%s",system_path,DIR_SEPARATOR,bin_name);
781             found = gmx_fexist(full_path);
782             if (!found && (s=getenv("PATH")) != NULL)
783             {
784                 char *dupped;
785                 
786                 dupped=gmx_strdup(s);
787                 s=dupped;
788                 while(!found && (dir=gmx_strsep(&s, PATH_SEPARATOR)) != NULL)
789                 {
790                     sprintf(full_path,"%s%c%s",dir,DIR_SEPARATOR,bin_name);
791                     found = gmx_fexist(full_path);
792                 }
793                 sfree(dupped);
794             }
795             if (!found)
796             {
797                 return FALSE;
798             }
799         } else if (!filename_is_absolute(bin_name)) {
800             /* name contains directory separators, but 
801              * it does not start at the root, i.e.
802              * name is relative to the current dir 
803              */
804 #if ((defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64) && !defined __CYGWIN__ && !defined __CYGWIN32__)
805             pdum=_getcwd(buf,sizeof(buf)-1);
806 #else
807             pdum=getcwd(buf,sizeof(buf)-1);
808 #endif
809             sprintf(full_path,"%s%c%s",buf,DIR_SEPARATOR,bin_name);
810         } else {
811             strncpy(full_path,bin_name,GMX_PATH_MAX);
812         }
813
814         /* Now we should have a full path and name in full_path,
815          * but on unix it might be a link, or a link to a link to a link..
816          */
817 #if (!defined WIN32 && !defined _WIN32 && !defined WIN64 && !defined _WIN64)
818         while( (i=readlink(full_path,buf,sizeof(buf)-1)) > 0 ) {
819             buf[i]='\0';
820             /* If it doesn't start with "/" it is relative */
821             if (buf[0]!=DIR_SEPARATOR) {
822                 strncpy(strrchr(full_path,DIR_SEPARATOR)+1,buf,GMX_PATH_MAX);
823             } else
824                 strncpy(full_path,buf,GMX_PATH_MAX);
825         }
826 #endif
827
828         /* Remove the executable name - it always contains at least one slash */
829         *(strrchr(full_path,DIR_SEPARATOR)+1)='\0';
830         /* Now we have the full path to the gromacs executable.
831          * Use it to find the library dir. 
832          */
833         found=FALSE;
834         while(!found && ( (ptr=strrchr(full_path,DIR_SEPARATOR)) != NULL ) ) {
835             *ptr='\0';
836             found=search_subdirs(full_path,libdir);
837         }
838     }
839     }
840     /* End of smart searching. If we didn't find it in our parent tree,
841      * or if the program name wasn't set, at least try some standard 
842      * locations before giving up, in case we are running from e.g. 
843      * a users home directory. This only works on unix or cygwin...
844      */
845 #if ((!defined WIN32 && !defined _WIN32 && !defined WIN64 && !defined _WIN64) || defined __CYGWIN__ || defined __CYGWIN32__)
846     if(!found) 
847         found=search_subdirs("/usr/local",libdir);
848     if(!found) 
849         found=search_subdirs("/usr",libdir);
850     if(!found) 
851         found=search_subdirs("/opt",libdir);
852 #endif
853     return found;
854 }
855
856
857 char *low_gmxlibfn(const char *file, gmx_bool bAddCWD, gmx_bool bFatal)
858 {
859     char *ret;
860     char *lib,*dir;
861     char buf[1024];
862     char libpath[GMX_PATH_MAX];
863     gmx_bool env_is_set=FALSE;
864     char   *s,tmppath[GMX_PATH_MAX];
865
866     /* GMXLIB can be a path now */
867     lib=getenv("GMXLIB");
868     if (lib != NULL)
869     {
870         env_is_set=TRUE;
871         strncpy(libpath,lib,GMX_PATH_MAX);
872     } 
873     else if (!get_libdir(libpath))
874     {
875         strncpy(libpath,GMXLIBDIR,GMX_PATH_MAX);
876     }
877
878     ret = NULL;
879     if (bAddCWD && gmx_fexist(file))
880     {
881         ret = gmx_strdup(file);
882     }
883     else 
884     {
885         strncpy(tmppath,libpath,GMX_PATH_MAX);
886         s=tmppath;
887         while(ret == NULL && (dir=gmx_strsep(&s, PATH_SEPARATOR)) != NULL )
888         {
889             sprintf(buf,"%s%c%s",dir,DIR_SEPARATOR,file);
890             if (gmx_fexist(buf))
891             {
892                 ret = gmx_strdup(buf);
893             }
894         }
895         if (ret == NULL && bFatal) 
896         {
897             if (env_is_set) 
898             {
899                 gmx_fatal(FARGS,
900                           "Library file %s not found %sin your GMXLIB path.",
901                           file, bAddCWD ? "in current dir nor " : "");
902             }
903             else
904             {
905                 gmx_fatal(FARGS,
906                           "Library file %s not found %sin default directories.\n"
907                         "(You can set the directories to search with the GMXLIB path variable)",
908                           file, bAddCWD ? "in current dir nor " : "");
909             }
910         }
911     }
912
913     return ret;
914 }
915
916
917
918
919
920 FILE *low_libopen(const char *file,gmx_bool bFatal)
921 {
922     FILE *ff;
923     char *fn;
924
925     fn=low_gmxlibfn(file,TRUE,bFatal);
926
927     if (fn==NULL) {
928         ff=NULL;
929     } else {
930       if (debug)
931         fprintf(debug,"Opening library file %s\n",fn);
932       ff=fopen(fn,"r");
933     }
934     sfree(fn);
935
936     return ff;
937 }
938
939 char *gmxlibfn(const char *file)
940 {
941     return low_gmxlibfn(file,TRUE,TRUE);
942 }
943
944 FILE *libopen(const char *file)
945 {
946     return low_libopen(file,TRUE);
947 }
948
949 void gmx_tmpnam(char *buf)
950 {
951     int i,len,fd;
952
953     if ((len = strlen(buf)) < 7)
954         gmx_fatal(FARGS,"Buf passed to gmx_tmpnam must be at least 7 bytes long");
955     for(i=len-6; (i<len); i++) {
956         buf[i] = 'X';
957     }
958     /* mktemp is dangerous and we should use mkstemp instead, but 
959      * since windows doesnt support it we have to separate the cases.
960      * 20090307: mktemp deprecated, use iso c++ _mktemp instead.
961      */
962 #if ((defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64) && !defined __CYGWIN__ && !defined __CYGWIN32__)
963     _mktemp(buf);
964 #else
965     fd = mkstemp(buf);
966
967     switch (fd) {
968         case EINVAL:
969             gmx_fatal(FARGS,"Invalid template %s for mkstemp",buf);
970             break;
971         case EEXIST:
972             gmx_fatal(FARGS,"mkstemp created existing file",buf);
973             break;
974         case EACCES: 
975             gmx_fatal(FARGS,"Permission denied for opening %s",buf);
976             break;
977         default:
978             break;
979     }   
980     close(fd);
981 #endif
982     /* name in Buf should now be OK */
983 }
984
985 int gmx_truncatefile(char *path, gmx_off_t length)
986 {
987 #ifdef _MSC_VER
988     /* Microsoft visual studio does not have "truncate" */
989     HANDLE fh;
990     LARGE_INTEGER win_length;
991
992     win_length.QuadPart = length;
993
994     fh = CreateFile(path,GENERIC_READ | GENERIC_WRITE,0,NULL,
995             OPEN_EXISTING,0,NULL);
996     SetFilePointerEx(fh,win_length,NULL,FILE_BEGIN);
997     SetEndOfFile(fh);
998     CloseHandle(fh);
999
1000     return 0;
1001 #else
1002     return truncate(path,length);
1003 #endif
1004 }
1005
1006
1007 int gmx_file_rename(const char *oldname, const char *newname)
1008 {
1009 #if (!(defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64)))
1010     /* under unix, rename() is atomic (at least, it should be). */
1011     return rename(oldname, newname);
1012 #else
1013     if (MoveFileEx(oldname, newname, 
1014                    MOVEFILE_REPLACE_EXISTING|MOVEFILE_WRITE_THROUGH))
1015         return 0;
1016     else
1017         return 1;
1018 #endif
1019 }
1020
1021 int gmx_file_copy(const char *oldname, const char *newname, gmx_bool copy_if_empty)
1022 {
1023 /* the full copy buffer size: */
1024 #define FILECOPY_BUFSIZE (1<<16)
1025     FILE *in=NULL; 
1026     FILE *out=NULL;
1027     char *buf;
1028
1029     snew(buf, FILECOPY_BUFSIZE); 
1030
1031     in=fopen(oldname, "rb");
1032     if (!in)
1033         goto error;
1034
1035     /* If we don't copy when empty, we postpone opening the file
1036        until we're actually ready to write. */
1037     if (copy_if_empty)
1038     {
1039         out=fopen(newname, "wb");
1040         if (!out)
1041             goto error;
1042     }
1043
1044     while(!feof(in))
1045     {
1046         size_t nread;
1047         
1048         nread=fread(buf, sizeof(char), FILECOPY_BUFSIZE, in);
1049         if (nread>0)
1050         {
1051             size_t ret;
1052             if (!out)
1053             {
1054                 /* so this is where we open when copy_if_empty is false:
1055                    here we know we read something. */
1056                 out=fopen(newname, "wb");
1057                 if (!out)
1058                     goto error;
1059             }
1060             ret=fwrite(buf, sizeof(char), nread, out);
1061             if (ret!=nread)
1062             {
1063                 goto error;
1064             }
1065         }
1066         if (ferror(in))
1067             goto error;
1068     }
1069     sfree(buf);
1070     fclose(in);
1071     fclose(out);
1072     return 0;
1073 error:
1074     sfree(buf);
1075     if (in)
1076         fclose(in);
1077     if (out)
1078         fclose(out);
1079     return 1;
1080 #undef FILECOPY_BUFSIZE
1081 }
1082
1083
1084 int gmx_fsync(FILE *fp)
1085 {
1086     int rc=0;
1087
1088 #ifdef GMX_FAHCORE
1089     /* the fahcore defines its own os-independent fsync */
1090     rc=fah_fsync(fp);
1091 #else /* GMX_FAHCORE */
1092     {
1093         int fn=-1;
1094
1095         /* get the file number */
1096 #if defined(HAVE_FILENO)
1097         fn= fileno(fp);
1098 #elif defined(HAVE__FILENO)
1099         fn= _fileno(fp);
1100 #endif
1101
1102         /* do the actual fsync */
1103         if (fn >= 0)
1104         {
1105 #if (defined(HAVE_FSYNC))
1106             rc=fsync(fn);
1107 #elif (defined(HAVE__COMMIT)) 
1108             rc=_commit(fn);
1109 #endif
1110         }
1111     }
1112 #endif /* GMX_FAHCORE */
1113
1114     /* We check for these error codes this way because POSIX requires them
1115        to be defined, and using anything other than macros is unlikely: */
1116 #ifdef EINTR
1117     /* we don't want to report an error just because fsync() caught a signal.
1118        For our purposes, we can just ignore this. */
1119     if (rc && errno==EINTR)
1120         rc=0;
1121 #endif
1122 #ifdef EINVAL
1123     /* we don't want to report an error just because we tried to fsync() 
1124        stdout, a socket or a pipe. */
1125     if (rc && errno==EINVAL)
1126         rc=0;
1127 #endif
1128     return rc;
1129 }
1130
1131
1132