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