Update copyright statements and change license to LGPL
[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 #include "gmx_header_config.h"
42
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <sys/types.h>
47 #include <sys/stat.h>
48 #include <fcntl.h>
49
50 #ifdef HAVE_DIRENT_H
51 /* POSIX */
52 #include <dirent.h>
53 #endif
54
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
727
728 gmx_bool search_subdirs(const char *parent, char *libdir)
729 {
730     char *ptr;
731     gmx_bool found;
732
733     /* Search a few common subdirectory names for the gromacs library dir */
734     sprintf(libdir,"%s%cshare%ctop%cgurgle.dat",parent,
735             DIR_SEPARATOR,DIR_SEPARATOR,DIR_SEPARATOR);
736     found=gmx_fexist(libdir);
737     if(!found) {
738         sprintf(libdir,"%s%cshare%cgromacs%ctop%cgurgle.dat",parent,
739                 DIR_SEPARATOR,DIR_SEPARATOR,
740                 DIR_SEPARATOR,DIR_SEPARATOR);
741         found=gmx_fexist(libdir);
742     }    
743     if(!found) {
744         sprintf(libdir,"%s%cshare%cgromacs-%s%ctop%cgurgle.dat",parent,
745                 DIR_SEPARATOR,DIR_SEPARATOR,VERSION,
746                 DIR_SEPARATOR,DIR_SEPARATOR);
747         found=gmx_fexist(libdir);
748     }    
749     if(!found) {
750         sprintf(libdir,"%s%cshare%cgromacs%cgromacs-%s%ctop%cgurgle.dat",parent,
751                 DIR_SEPARATOR,DIR_SEPARATOR,DIR_SEPARATOR,
752                 VERSION,DIR_SEPARATOR,DIR_SEPARATOR);
753         found=gmx_fexist(libdir);
754     }    
755
756     /* Remove the gurgle.dat part from libdir if we found something */
757     if(found) {
758         ptr=strrchr(libdir,DIR_SEPARATOR); /* slash or backslash always present, no check necessary */
759         *ptr='\0';
760     }
761     return found;
762 }
763
764
765 /* Check if the program name begins with "/" on unix/cygwin, or
766  * with "\" or "X:\" on windows. If not, the program name
767  * is relative to the current directory.
768  */
769 static gmx_bool filename_is_absolute(char *name)
770 {
771 #ifdef GMX_NATIVE_WINDOWS
772     return ((name[0] == DIR_SEPARATOR) || ((strlen(name)>3) && strncmp(name+1,":\\",2)) == 0);
773 #else
774     return (name[0] == DIR_SEPARATOR);
775 #endif
776 }
777
778 gmx_bool get_libdir(char *libdir)
779 {
780 #define GMX_BINNAME_MAX 512
781     char bin_name[GMX_BINNAME_MAX];
782     char buf[GMX_BINNAME_MAX];
783     char full_path[GMX_PATH_MAX+GMX_BINNAME_MAX];
784     char system_path[GMX_PATH_MAX];
785     char *dir,*ptr,*s,*pdum;
786     gmx_bool found=FALSE;
787     int i;
788
789     if (Program() != NULL)
790     {
791
792     /* First - detect binary name */
793     if (strlen(Program()) >= GMX_BINNAME_MAX)
794     {
795         gmx_fatal(FARGS,"The name of the binary is longer than the allowed buffer size (%d):\n'%s'",GMX_BINNAME_MAX,Program());
796     }
797     strncpy(bin_name,Program(),GMX_BINNAME_MAX-1);
798
799     /* On windows & cygwin we need to add the .exe extension
800      * too, or we wont be able to detect that the file exists
801      */
802 #if (defined GMX_NATIVE_WINDOWS || defined GMX_CYGWIN)
803     if(strlen(bin_name)<3 || gmx_strncasecmp(bin_name+strlen(bin_name)-4,".exe",4))
804         strcat(bin_name,".exe");
805 #endif
806
807     /* Only do the smart search part if we got a real name */
808     if (NULL!=bin_name && strncmp(bin_name,"GROMACS",GMX_BINNAME_MAX)) {
809
810         if (!strchr(bin_name,DIR_SEPARATOR)) {
811             /* No slash or backslash in name means it must be in the path - search it! */
812             /* Add the local dir since it is not in the path on windows */
813 #ifdef GMX_NATIVE_WINDOWS
814             pdum=_getcwd(system_path,sizeof(system_path)-1);
815 #else
816             pdum=getcwd(system_path,sizeof(system_path)-1);
817 #endif
818             sprintf(full_path,"%s%c%s",system_path,DIR_SEPARATOR,bin_name);
819             found = gmx_is_file(full_path);
820             if (!found && (s=getenv("PATH")) != NULL)
821             {
822                 char *dupped;
823                 
824                 dupped=gmx_strdup(s);
825                 s=dupped;
826                 while(!found && (dir=gmx_strsep(&s, PATH_SEPARATOR)) != NULL)
827                 {
828                     sprintf(full_path,"%s%c%s",dir,DIR_SEPARATOR,bin_name);
829                     found = gmx_is_file(full_path);
830                 }
831                 sfree(dupped);
832             }
833             if (!found)
834             {
835                 return FALSE;
836             }
837         } else if (!filename_is_absolute(bin_name)) {
838             /* name contains directory separators, but 
839              * it does not start at the root, i.e.
840              * name is relative to the current dir 
841              */
842 #ifdef GMX_NATIVE_WINDOWS
843             pdum=_getcwd(buf,sizeof(buf)-1);
844 #else
845             pdum=getcwd(buf,sizeof(buf)-1);
846 #endif
847             sprintf(full_path,"%s%c%s",buf,DIR_SEPARATOR,bin_name);
848         } else {
849             strncpy(full_path,bin_name,GMX_PATH_MAX);
850         }
851
852         /* Now we should have a full path and name in full_path,
853          * but on unix it might be a link, or a link to a link to a link..
854          */
855 #ifndef GMX_NATIVE_WINDOWS
856         while( (i=readlink(full_path,buf,sizeof(buf)-1)) > 0 ) {
857             buf[i]='\0';
858             /* If it doesn't start with "/" it is relative */
859             if (buf[0]!=DIR_SEPARATOR) {
860                 strncpy(strrchr(full_path,DIR_SEPARATOR)+1,buf,GMX_PATH_MAX);
861             } else
862                 strncpy(full_path,buf,GMX_PATH_MAX);
863         }
864 #endif
865
866         /* Remove the executable name - it always contains at least one slash */
867         *(strrchr(full_path,DIR_SEPARATOR)+1)='\0';
868         /* Now we have the full path to the gromacs executable.
869          * Use it to find the library dir. 
870          */
871         found=FALSE;
872         while(!found && ( (ptr=strrchr(full_path,DIR_SEPARATOR)) != NULL ) ) {
873             *ptr='\0';
874             found=search_subdirs(full_path,libdir);
875         }
876     }
877     }
878     /* End of smart searching. If we didn't find it in our parent tree,
879      * or if the program name wasn't set, at least try some standard 
880      * locations before giving up, in case we are running from e.g. 
881      * a users home directory. This only works on unix or cygwin...
882      */
883 #ifndef GMX_NATIVE_WINDOWS
884     if(!found) 
885         found=search_subdirs("/usr/local",libdir);
886     if(!found) 
887         found=search_subdirs("/usr",libdir);
888     if(!found) 
889         found=search_subdirs("/opt",libdir);
890 #endif
891     return found;
892 }
893
894
895 char *low_gmxlibfn(const char *file, gmx_bool bAddCWD, gmx_bool bFatal)
896 {
897     char *ret;
898     char *lib,*dir;
899     char buf[1024];
900     char libpath[GMX_PATH_MAX];
901     gmx_bool env_is_set=FALSE;
902     char   *s,tmppath[GMX_PATH_MAX];
903
904     /* GMXLIB can be a path now */
905     lib=getenv("GMXLIB");
906     if (lib != NULL)
907     {
908         env_is_set=TRUE;
909         strncpy(libpath,lib,GMX_PATH_MAX);
910     } 
911     else if (!get_libdir(libpath))
912     {
913         strncpy(libpath,GMXLIBDIR,GMX_PATH_MAX);
914     }
915
916     ret = NULL;
917     if (bAddCWD && gmx_fexist(file))
918     {
919         ret = gmx_strdup(file);
920     }
921     else 
922     {
923         strncpy(tmppath,libpath,GMX_PATH_MAX);
924         s=tmppath;
925         while(ret == NULL && (dir=gmx_strsep(&s, PATH_SEPARATOR)) != NULL )
926         {
927             sprintf(buf,"%s%c%s",dir,DIR_SEPARATOR,file);
928             if (gmx_fexist(buf))
929             {
930                 ret = gmx_strdup(buf);
931             }
932         }
933         if (ret == NULL && bFatal) 
934         {
935             if (env_is_set) 
936             {
937                 gmx_fatal(FARGS,
938                           "Library file %s not found %sin your GMXLIB path.",
939                           file, bAddCWD ? "in current dir nor " : "");
940             }
941             else
942             {
943                 gmx_fatal(FARGS,
944                           "Library file %s not found %sin default directories.\n"
945                         "(You can set the directories to search with the GMXLIB path variable)",
946                           file, bAddCWD ? "in current dir nor " : "");
947             }
948         }
949     }
950
951     return ret;
952 }
953
954
955
956
957
958 FILE *low_libopen(const char *file,gmx_bool bFatal)
959 {
960     FILE *ff;
961     char *fn;
962
963     fn=low_gmxlibfn(file,TRUE,bFatal);
964
965     if (fn==NULL) {
966         ff=NULL;
967     } else {
968       if (debug)
969         fprintf(debug,"Opening library file %s\n",fn);
970       ff=fopen(fn,"r");
971     }
972     sfree(fn);
973
974     return ff;
975 }
976
977 char *gmxlibfn(const char *file)
978 {
979     return low_gmxlibfn(file,TRUE,TRUE);
980 }
981
982 FILE *libopen(const char *file)
983 {
984     return low_libopen(file,TRUE);
985 }
986
987 void gmx_tmpnam(char *buf)
988 {
989     int i,len,fd;
990
991     if ((len = strlen(buf)) < 7)
992         gmx_fatal(FARGS,"Buf passed to gmx_tmpnam must be at least 7 bytes long");
993     for(i=len-6; (i<len); i++) {
994         buf[i] = 'X';
995     }
996     /* mktemp is dangerous and we should use mkstemp instead, but 
997      * since windows doesnt support it we have to separate the cases.
998      * 20090307: mktemp deprecated, use iso c++ _mktemp instead.
999      */
1000 #ifdef GMX_NATIVE_WINDOWS
1001     _mktemp(buf);
1002 #else
1003     fd = mkstemp(buf);
1004
1005     switch (fd) {
1006         case EINVAL:
1007             gmx_fatal(FARGS,"Invalid template %s for mkstemp",buf);
1008             break;
1009         case EEXIST:
1010             gmx_fatal(FARGS,"mkstemp created existing file",buf);
1011             break;
1012         case EACCES: 
1013             gmx_fatal(FARGS,"Permission denied for opening %s",buf);
1014             break;
1015         default:
1016             break;
1017     }   
1018     close(fd);
1019 #endif
1020     /* name in Buf should now be OK */
1021 }
1022
1023 int gmx_truncatefile(char *path, gmx_off_t length)
1024 {
1025 #ifdef _MSC_VER
1026     /* Microsoft visual studio does not have "truncate" */
1027     HANDLE fh;
1028     LARGE_INTEGER win_length;
1029
1030     win_length.QuadPart = length;
1031
1032     fh = CreateFile(path,GENERIC_READ | GENERIC_WRITE,0,NULL,
1033             OPEN_EXISTING,0,NULL);
1034     SetFilePointerEx(fh,win_length,NULL,FILE_BEGIN);
1035     SetEndOfFile(fh);
1036     CloseHandle(fh);
1037
1038     return 0;
1039 #else
1040     return truncate(path,length);
1041 #endif
1042 }
1043
1044
1045 int gmx_file_rename(const char *oldname, const char *newname)
1046 {
1047 #ifndef GMX_NATIVE_WINDOWS
1048     /* under unix, rename() is atomic (at least, it should be). */
1049     return rename(oldname, newname);
1050 #else
1051     if (MoveFileEx(oldname, newname, 
1052                    MOVEFILE_REPLACE_EXISTING|MOVEFILE_WRITE_THROUGH))
1053         return 0;
1054     else
1055         return 1;
1056 #endif
1057 }
1058
1059 int gmx_file_copy(const char *oldname, const char *newname, gmx_bool copy_if_empty)
1060 {
1061 /* the full copy buffer size: */
1062 #define FILECOPY_BUFSIZE (1<<16)
1063     FILE *in=NULL; 
1064     FILE *out=NULL;
1065     char *buf;
1066
1067     snew(buf, FILECOPY_BUFSIZE); 
1068
1069     in=fopen(oldname, "rb");
1070     if (!in)
1071         goto error;
1072
1073     /* If we don't copy when empty, we postpone opening the file
1074        until we're actually ready to write. */
1075     if (copy_if_empty)
1076     {
1077         out=fopen(newname, "wb");
1078         if (!out)
1079             goto error;
1080     }
1081
1082     while(!feof(in))
1083     {
1084         size_t nread;
1085         
1086         nread=fread(buf, sizeof(char), FILECOPY_BUFSIZE, in);
1087         if (nread>0)
1088         {
1089             size_t ret;
1090             if (!out)
1091             {
1092                 /* so this is where we open when copy_if_empty is false:
1093                    here we know we read something. */
1094                 out=fopen(newname, "wb");
1095                 if (!out)
1096                     goto error;
1097             }
1098             ret=fwrite(buf, sizeof(char), nread, out);
1099             if (ret!=nread)
1100             {
1101                 goto error;
1102             }
1103         }
1104         if (ferror(in))
1105             goto error;
1106     }
1107     sfree(buf);
1108     fclose(in);
1109     fclose(out);
1110     return 0;
1111 error:
1112     sfree(buf);
1113     if (in)
1114         fclose(in);
1115     if (out)
1116         fclose(out);
1117     return 1;
1118 #undef FILECOPY_BUFSIZE
1119 }
1120
1121
1122 int gmx_fsync(FILE *fp)
1123 {
1124     int rc=0;
1125
1126 #ifdef GMX_FAHCORE
1127     /* the fahcore defines its own os-independent fsync */
1128     rc=fah_fsync(fp);
1129 #else /* GMX_FAHCORE */
1130     {
1131         int fn=-1;
1132
1133         /* get the file number */
1134 #if defined(HAVE_FILENO)
1135         fn= fileno(fp);
1136 #elif defined(HAVE__FILENO)
1137         fn= _fileno(fp);
1138 #endif
1139
1140         /* do the actual fsync */
1141         if (fn >= 0)
1142         {
1143 #if (defined(HAVE_FSYNC))
1144             rc=fsync(fn);
1145 #elif (defined(HAVE__COMMIT)) 
1146             rc=_commit(fn);
1147 #endif
1148         }
1149     }
1150 #endif /* GMX_FAHCORE */
1151
1152     /* We check for these error codes this way because POSIX requires them
1153        to be defined, and using anything other than macros is unlikely: */
1154 #ifdef EINTR
1155     /* we don't want to report an error just because fsync() caught a signal.
1156        For our purposes, we can just ignore this. */
1157     if (rc && errno==EINTR)
1158         rc=0;
1159 #endif
1160 #ifdef EINVAL
1161     /* we don't want to report an error just because we tried to fsync() 
1162        stdout, a socket or a pipe. */
1163     if (rc && errno==EINVAL)
1164         rc=0;
1165 #endif
1166     return rc;
1167 }
1168
1169
1170