a1fb7aa930093b99bb233a324b5bf7092a3dd6f1
[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%c%s%cgurgle.dat", parent,
803                 DIR_SEPARATOR, GMXLIB_SEARCH_DIR, DIR_SEPARATOR);
804         found = gmx_fexist(libdir);
805     }
806
807     /* Remove the gurgle.dat part from libdir if we found something */
808     if (found)
809     {
810         ptr  = strrchr(libdir, DIR_SEPARATOR); /* slash or backslash always present, no check necessary */
811         *ptr = '\0';
812     }
813     return found;
814 }
815
816
817 /* Check if the program name begins with "/" on unix/cygwin, or
818  * with "\" or "X:\" on windows. If not, the program name
819  * is relative to the current directory.
820  */
821 static gmx_bool filename_is_absolute(char *name)
822 {
823 #ifdef GMX_NATIVE_WINDOWS
824     return ((name[0] == DIR_SEPARATOR) || ((strlen(name) > 3) && strncmp(name+1, ":\\", 2)) == 0);
825 #else
826     return (name[0] == DIR_SEPARATOR);
827 #endif
828 }
829
830 void get_libdir(char *libdir)
831 {
832 #define GMX_BINNAME_MAX 512
833     char     bin_name[GMX_BINNAME_MAX];
834     char     buf[GMX_BINNAME_MAX];
835     char     full_path[GMX_PATH_MAX+GMX_BINNAME_MAX];
836     char     system_path[GMX_PATH_MAX];
837     char    *dir, *ptr, *s;
838     gmx_bool found = FALSE;
839     int      i;
840
841     if (Program() != NULL)
842     {
843
844         /* First - detect binary name */
845         if (strlen(Program()) >= GMX_BINNAME_MAX)
846         {
847             gmx_fatal(FARGS, "The name of the binary is longer than the allowed buffer size (%d):\n'%s'", GMX_BINNAME_MAX, Program());
848         }
849         strncpy(bin_name, Program(), GMX_BINNAME_MAX-1);
850
851         /* On windows & cygwin we need to add the .exe extension
852          * too, or we wont be able to detect that the file exists
853          */
854 #if (defined GMX_NATIVE_WINDOWS || defined GMX_CYGWIN)
855         if (strlen(bin_name) < 3 || gmx_strncasecmp(bin_name+strlen(bin_name)-4, ".exe", 4))
856         {
857             strcat(bin_name, ".exe");
858         }
859 #endif
860
861         /* Only do the smart search part if we got a real name */
862         if (NULL != bin_name && strncmp(bin_name, "GROMACS", GMX_BINNAME_MAX))
863         {
864
865             if (!strchr(bin_name, DIR_SEPARATOR))
866             {
867                 /* No slash or backslash in name means it must be in the path - search it! */
868                 /* Add the local dir since it is not in the path on windows */
869                 gmx_getcwd(system_path, sizeof(system_path));
870                 sprintf(full_path, "%s%c%s", system_path, DIR_SEPARATOR, bin_name);
871                 found = gmx_is_file(full_path);
872                 if (!found && (s = getenv("PATH")) != NULL)
873                 {
874                     char *dupped;
875
876                     dupped = gmx_strdup(s);
877                     s      = dupped;
878                     while (!found && (dir = gmx_strsep(&s, PATH_SEPARATOR)) != NULL)
879                     {
880                         sprintf(full_path, "%s%c%s", dir, DIR_SEPARATOR, bin_name);
881                         found = gmx_is_file(full_path);
882                     }
883                     sfree(dupped);
884                 }
885                 if (!found)
886                 {
887                     strcpy(libdir, GMXLIB_FALLBACK);
888                     return;
889                 }
890             }
891             else if (!filename_is_absolute(bin_name))
892             {
893                 /* name contains directory separators, but
894                  * it does not start at the root, i.e.
895                  * name is relative to the current dir
896                  */
897                 gmx_getcwd(buf, sizeof(buf));
898                 sprintf(full_path, "%s%c%s", buf, DIR_SEPARATOR, bin_name);
899             }
900             else
901             {
902                 strncpy(full_path, bin_name, GMX_PATH_MAX);
903             }
904
905             /* Now we should have a full path and name in full_path,
906              * but on unix it might be a link, or a link to a link to a link..
907              */
908 #ifndef GMX_NATIVE_WINDOWS
909             while ( (i = readlink(full_path, buf, sizeof(buf)-1)) > 0)
910             {
911                 buf[i] = '\0';
912                 /* If it doesn't start with "/" it is relative */
913                 if (buf[0] != DIR_SEPARATOR)
914                 {
915                     strncpy(strrchr(full_path, DIR_SEPARATOR)+1, buf, GMX_PATH_MAX);
916                 }
917                 else
918                 {
919                     strncpy(full_path, buf, GMX_PATH_MAX);
920                 }
921             }
922 #endif
923
924             /* If running directly from the build tree, try to use the source
925              * directory.
926              */
927 #if (defined CMAKE_SOURCE_DIR && defined CMAKE_BINARY_DIR)
928             if (strncmp(full_path, CMAKE_BINARY_DIR, strlen(CMAKE_BINARY_DIR)) == 0)
929             {
930                 if (search_subdirs(CMAKE_SOURCE_DIR, libdir))
931                 {
932                     return;
933                 }
934             }
935 #endif
936
937             /* Remove the executable name - it always contains at least one slash */
938             *(strrchr(full_path, DIR_SEPARATOR)+1) = '\0';
939             /* Now we have the full path to the gromacs executable.
940              * Use it to find the library dir.
941              */
942             found = FALSE;
943             while (!found && ( (ptr = strrchr(full_path, DIR_SEPARATOR)) != NULL ) )
944             {
945                 *ptr  = '\0';
946                 found = search_subdirs(full_path, libdir);
947             }
948         }
949     }
950     /* End of smart searching. If we didn't find it in our parent tree,
951      * or if the program name wasn't set, at least try some standard
952      * locations before giving up, in case we are running from e.g.
953      * a users home directory. This only works on unix or cygwin...
954      */
955 #ifndef GMX_NATIVE_WINDOWS
956     if (!found)
957     {
958         found = search_subdirs("/usr/local", libdir);
959     }
960     if (!found)
961     {
962         found = search_subdirs("/usr", libdir);
963     }
964     if (!found)
965     {
966         found = search_subdirs("/opt", libdir);
967     }
968 #endif
969     if (!found)
970     {
971         strcpy(libdir, GMXLIB_FALLBACK);
972     }
973 }
974
975
976 char *low_gmxlibfn(const char *file, gmx_bool bAddCWD, gmx_bool bFatal)
977 {
978     char    *ret;
979     char    *lib, *dir;
980     char     buf[1024];
981     char     libpath[GMX_PATH_MAX];
982     gmx_bool env_is_set = FALSE;
983     char    *s, tmppath[GMX_PATH_MAX];
984
985     /* GMXLIB can be a path now */
986     lib = getenv("GMXLIB");
987     if (lib != NULL)
988     {
989         env_is_set = TRUE;
990         strncpy(libpath, lib, GMX_PATH_MAX);
991     }
992     else
993     {
994         get_libdir(libpath);
995     }
996
997     ret = NULL;
998     if (bAddCWD && gmx_fexist(file))
999     {
1000         ret = gmx_strdup(file);
1001     }
1002     else
1003     {
1004         strncpy(tmppath, libpath, GMX_PATH_MAX);
1005         s = tmppath;
1006         while (ret == NULL && (dir = gmx_strsep(&s, PATH_SEPARATOR)) != NULL)
1007         {
1008             sprintf(buf, "%s%c%s", dir, DIR_SEPARATOR, file);
1009             if (gmx_fexist(buf))
1010             {
1011                 ret = gmx_strdup(buf);
1012             }
1013         }
1014         if (ret == NULL && bFatal)
1015         {
1016             if (env_is_set)
1017             {
1018                 gmx_fatal(FARGS,
1019                           "Library file %s not found %sin your GMXLIB path.",
1020                           file, bAddCWD ? "in current dir nor " : "");
1021             }
1022             else
1023             {
1024                 gmx_fatal(FARGS,
1025                           "Library file %s not found %sin default directories.\n"
1026                           "(You can set the directories to search with the GMXLIB path variable)",
1027                           file, bAddCWD ? "in current dir nor " : "");
1028             }
1029         }
1030     }
1031
1032     return ret;
1033 }
1034
1035
1036
1037
1038
1039 FILE *low_libopen(const char *file, gmx_bool bFatal)
1040 {
1041     FILE *ff;
1042     char *fn;
1043
1044     fn = low_gmxlibfn(file, TRUE, bFatal);
1045
1046     if (fn == NULL)
1047     {
1048         ff = NULL;
1049     }
1050     else
1051     {
1052         if (debug)
1053         {
1054             fprintf(debug, "Opening library file %s\n", fn);
1055         }
1056         ff = fopen(fn, "r");
1057     }
1058     sfree(fn);
1059
1060     return ff;
1061 }
1062
1063 char *gmxlibfn(const char *file)
1064 {
1065     return low_gmxlibfn(file, TRUE, TRUE);
1066 }
1067
1068 FILE *libopen(const char *file)
1069 {
1070     return low_libopen(file, TRUE);
1071 }
1072
1073 void gmx_tmpnam(char *buf)
1074 {
1075     int i, len, fd;
1076
1077     if ((len = strlen(buf)) < 7)
1078     {
1079         gmx_fatal(FARGS, "Buf passed to gmx_tmpnam must be at least 7 bytes long");
1080     }
1081     for (i = len-6; (i < len); i++)
1082     {
1083         buf[i] = 'X';
1084     }
1085     /* mktemp is dangerous and we should use mkstemp instead, but
1086      * since windows doesnt support it we have to separate the cases.
1087      * 20090307: mktemp deprecated, use iso c++ _mktemp instead.
1088      */
1089 #ifdef GMX_NATIVE_WINDOWS
1090     _mktemp(buf);
1091 #else
1092     fd = mkstemp(buf);
1093
1094     switch (fd)
1095     {
1096         case EINVAL:
1097             gmx_fatal(FARGS, "Invalid template %s for mkstemp", buf);
1098             break;
1099         case EEXIST:
1100             gmx_fatal(FARGS, "mkstemp created existing file", buf);
1101             break;
1102         case EACCES:
1103             gmx_fatal(FARGS, "Permission denied for opening %s", buf);
1104             break;
1105         default:
1106             break;
1107     }
1108     close(fd);
1109 #endif
1110     /* name in Buf should now be OK */
1111 }
1112
1113 int gmx_truncatefile(char *path, gmx_off_t length)
1114 {
1115 #ifdef _MSC_VER
1116     /* Microsoft visual studio does not have "truncate" */
1117     HANDLE        fh;
1118     LARGE_INTEGER win_length;
1119
1120     win_length.QuadPart = length;
1121
1122     fh = CreateFile(path, GENERIC_READ | GENERIC_WRITE, 0, NULL,
1123                     OPEN_EXISTING, 0, NULL);
1124     SetFilePointerEx(fh, win_length, NULL, FILE_BEGIN);
1125     SetEndOfFile(fh);
1126     CloseHandle(fh);
1127
1128     return 0;
1129 #else
1130     return truncate(path, length);
1131 #endif
1132 }
1133
1134
1135 int gmx_file_rename(const char *oldname, const char *newname)
1136 {
1137 #ifndef GMX_NATIVE_WINDOWS
1138     /* under unix, rename() is atomic (at least, it should be). */
1139     return rename(oldname, newname);
1140 #else
1141     if (MoveFileEx(oldname, newname,
1142                    MOVEFILE_REPLACE_EXISTING|MOVEFILE_WRITE_THROUGH))
1143     {
1144         return 0;
1145     }
1146     else
1147     {
1148         return 1;
1149     }
1150 #endif
1151 }
1152
1153 int gmx_file_copy(const char *oldname, const char *newname, gmx_bool copy_if_empty)
1154 {
1155 /* the full copy buffer size: */
1156 #define FILECOPY_BUFSIZE (1<<16)
1157     FILE *in  = NULL;
1158     FILE *out = NULL;
1159     char *buf;
1160
1161     snew(buf, FILECOPY_BUFSIZE);
1162
1163     in = fopen(oldname, "rb");
1164     if (!in)
1165     {
1166         goto error;
1167     }
1168
1169     /* If we don't copy when empty, we postpone opening the file
1170        until we're actually ready to write. */
1171     if (copy_if_empty)
1172     {
1173         out = fopen(newname, "wb");
1174         if (!out)
1175         {
1176             goto error;
1177         }
1178     }
1179
1180     while (!feof(in))
1181     {
1182         size_t nread;
1183
1184         nread = fread(buf, sizeof(char), FILECOPY_BUFSIZE, in);
1185         if (nread > 0)
1186         {
1187             size_t ret;
1188             if (!out)
1189             {
1190                 /* so this is where we open when copy_if_empty is false:
1191                    here we know we read something. */
1192                 out = fopen(newname, "wb");
1193                 if (!out)
1194                 {
1195                     goto error;
1196                 }
1197             }
1198             ret = fwrite(buf, sizeof(char), nread, out);
1199             if (ret != nread)
1200             {
1201                 goto error;
1202             }
1203         }
1204         if (ferror(in))
1205         {
1206             goto error;
1207         }
1208     }
1209     sfree(buf);
1210     fclose(in);
1211     fclose(out);
1212     return 0;
1213 error:
1214     sfree(buf);
1215     if (in)
1216     {
1217         fclose(in);
1218     }
1219     if (out)
1220     {
1221         fclose(out);
1222     }
1223     return 1;
1224 #undef FILECOPY_BUFSIZE
1225 }
1226
1227
1228 int gmx_fsync(FILE *fp)
1229 {
1230     int rc = 0;
1231
1232 #ifdef GMX_FAHCORE
1233     /* the fahcore defines its own os-independent fsync */
1234     rc = fah_fsync(fp);
1235 #else /* GMX_FAHCORE */
1236     {
1237         int fn = -1;
1238
1239         /* get the file number */
1240 #if defined(HAVE_FILENO)
1241         fn = fileno(fp);
1242 #elif defined(HAVE__FILENO)
1243         fn = _fileno(fp);
1244 #endif
1245
1246         /* do the actual fsync */
1247         if (fn >= 0)
1248         {
1249 #if (defined(HAVE_FSYNC))
1250             rc = fsync(fn);
1251 #elif (defined(HAVE__COMMIT))
1252             rc = _commit(fn);
1253 #endif
1254         }
1255     }
1256 #endif /* GMX_FAHCORE */
1257
1258     /* We check for these error codes this way because POSIX requires them
1259        to be defined, and using anything other than macros is unlikely: */
1260 #ifdef EINTR
1261     /* we don't want to report an error just because fsync() caught a signal.
1262        For our purposes, we can just ignore this. */
1263     if (rc && errno == EINTR)
1264     {
1265         rc = 0;
1266     }
1267 #endif
1268 #ifdef EINVAL
1269     /* we don't want to report an error just because we tried to fsync()
1270        stdout, a socket or a pipe. */
1271     if (rc && errno == EINVAL)
1272     {
1273         rc = 0;
1274     }
1275 #endif
1276     return rc;
1277 }
1278
1279 void gmx_chdir(const char *directory)
1280 {
1281 #ifdef GMX_NATIVE_WINDOWS
1282     int rc = _chdir(directory);
1283 #else
1284     int rc = chdir(directory);
1285 #endif
1286     if (rc != 0)
1287     {
1288         gmx_fatal(FARGS, "Cannot change directory to '%s'. Reason: %s",
1289                   directory, strerror(errno));
1290     }
1291 }
1292
1293 void gmx_getcwd(char *buffer, size_t size)
1294 {
1295 #ifdef GMX_NATIVE_WINDOWS
1296     char *pdum = _getcwd(buffer, size);
1297 #else
1298     char *pdum = getcwd(buffer, size);
1299 #endif
1300     if (pdum == NULL)
1301     {
1302         gmx_fatal(FARGS, "Cannot get working directory. Reason: %s",
1303                   strerror(errno));
1304     }
1305 }