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