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