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