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