Merge release-5-0 into master
[alexxy/gromacs.git] / src / gromacs / utility / 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,2014, 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 #include "gromacs/utility/futil.h"
38
39 #ifdef HAVE_CONFIG_H
40 #include "config.h"
41 #endif
42
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46
47 #include <sys/types.h>
48 #include <sys/stat.h>
49 #include <fcntl.h>
50
51 #ifdef HAVE_DIRENT_H
52 /* POSIX */
53 #include <dirent.h>
54 #endif
55
56 #ifdef HAVE_UNISTD_H
57 #include <unistd.h>
58 #endif
59
60 #ifdef GMX_NATIVE_WINDOWS
61 #include <direct.h>
62 #include <io.h>
63 #endif
64
65 /* Windows file stuff, only necessary for visual studio */
66 #ifdef _MSC_VER
67 #include <windows.h>
68 #endif
69
70 #include "thread_mpi/threads.h"
71
72 #include "gromacs/utility/cstringutil.h"
73 #include "gromacs/utility/exceptions.h"
74 #include "gromacs/utility/fatalerror.h"
75 #include "gromacs/utility/path.h"
76 #include "gromacs/utility/programcontext.h"
77 #include "gromacs/utility/smalloc.h"
78 #include "gromacs/utility/stringutil.h"
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 /* 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
96 void no_buffers(void)
97 {
98     bUnbuffered = TRUE;
99 }
100
101 void push_ps(FILE *fp)
102 {
103     t_pstack *ps;
104
105     tMPI_Thread_mutex_lock(&pstack_mutex);
106
107     snew(ps, 1);
108     ps->fp   = fp;
109     ps->prev = pstack;
110     pstack   = ps;
111
112     tMPI_Thread_mutex_unlock(&pstack_mutex);
113 }
114
115 #ifdef GMX_FAHCORE
116 /* don't use pipes!*/
117 #define popen fah_fopen
118 #define pclose fah_fclose
119 #define SKIP_FFOPS 1
120 #else
121 #ifdef gmx_ffclose
122 #undef gmx_ffclose
123 #endif
124 #if (!defined(HAVE_PIPES) && !defined(__native_client__))
125 static FILE *popen(const char *nm, const char *mode)
126 {
127     gmx_impl("Sorry no pipes...");
128
129     return NULL;
130 }
131
132 static int pclose(FILE *fp)
133 {
134     gmx_impl("Sorry no pipes...");
135
136     return 0;
137 }
138 #endif /* !defined(HAVE_PIPES) && !defined(__native_client__) */
139 #endif /* GMX_FAHCORE */
140
141 int gmx_ffclose(FILE *fp)
142 {
143 #ifdef SKIP_FFOPS
144     return fclose(fp);
145 #else
146     t_pstack *ps, *tmp;
147     int       ret = 0;
148
149     tMPI_Thread_mutex_lock(&pstack_mutex);
150
151     ps = pstack;
152     if (ps == NULL)
153     {
154         if (fp != NULL)
155         {
156             ret = fclose(fp);
157         }
158     }
159     else if (ps->fp == fp)
160     {
161         if (fp != NULL)
162         {
163             ret = pclose(fp);
164         }
165         pstack = pstack->prev;
166         sfree(ps);
167     }
168     else
169     {
170         while ((ps->prev != NULL) && (ps->prev->fp != fp))
171         {
172             ps = ps->prev;
173         }
174         if ((ps->prev != NULL) && ps->prev->fp == fp)
175         {
176             if (ps->prev->fp != NULL)
177             {
178                 ret = pclose(ps->prev->fp);
179             }
180             tmp      = ps->prev;
181             ps->prev = ps->prev->prev;
182             sfree(tmp);
183         }
184         else
185         {
186             if (fp != NULL)
187             {
188                 ret = fclose(fp);
189             }
190         }
191     }
192
193     tMPI_Thread_mutex_unlock(&pstack_mutex);
194     return ret;
195 #endif
196 }
197
198
199 void frewind(FILE *fp)
200 {
201     tMPI_Thread_mutex_lock(&pstack_mutex);
202
203     t_pstack *ps = pstack;
204     while (ps != NULL)
205     {
206         if (ps->fp == fp)
207         {
208             fprintf(stderr, "Cannot rewind compressed file!\n");
209             tMPI_Thread_mutex_unlock(&pstack_mutex);
210             return;
211         }
212         ps = ps->prev;
213     }
214     rewind(fp);
215     tMPI_Thread_mutex_unlock(&pstack_mutex);
216 }
217
218 int gmx_fseek(FILE *stream, gmx_off_t offset, int whence)
219 {
220 #ifdef HAVE_FSEEKO
221     return fseeko(stream, offset, whence);
222 #else
223 #ifdef HAVE__FSEEKI64
224     return _fseeki64(stream, offset, whence);
225 #else
226     return fseek(stream, offset, whence);
227 #endif
228 #endif
229 }
230
231 gmx_off_t gmx_ftell(FILE *stream)
232 {
233 #ifdef HAVE_FSEEKO
234     return ftello(stream);
235 #else
236 #ifdef HAVE__FSEEKI64
237     return _ftelli64(stream);
238 #else
239     return ftell(stream);
240 #endif
241 #endif
242 }
243
244
245 //! Check whether the file (opened by gmx_ffopen()) is a pipe.
246 static bool is_pipe(FILE *fp)
247 {
248     tMPI_Thread_mutex_lock(&pstack_mutex);
249
250     t_pstack *ps = pstack;
251     while (ps != NULL)
252     {
253         if (ps->fp == fp)
254         {
255             tMPI_Thread_mutex_unlock(&pstack_mutex);
256             return true;
257         }
258         ps = ps->prev;
259     }
260     tMPI_Thread_mutex_unlock(&pstack_mutex);
261     return false;
262 }
263
264
265 static FILE *uncompress(const char *fn, const char *mode)
266 {
267     FILE *fp;
268     char  buf[256];
269
270     sprintf(buf, "uncompress -c < %s", fn);
271     fprintf(stderr, "Going to execute '%s'\n", buf);
272     if ((fp = popen(buf, mode)) == NULL)
273     {
274         gmx_open(fn);
275     }
276     push_ps(fp);
277
278     return fp;
279 }
280
281 static FILE *gunzip(const char *fn, const char *mode)
282 {
283     FILE *fp;
284     char  buf[256];
285
286     sprintf(buf, "gunzip -c < %s", fn);
287     fprintf(stderr, "Going to execute '%s'\n", buf);
288     if ((fp = popen(buf, mode)) == NULL)
289     {
290         gmx_open(fn);
291     }
292     push_ps(fp);
293
294     return fp;
295 }
296
297 gmx_bool gmx_fexist(const char *fname)
298 {
299     FILE *test;
300
301     if (fname == NULL)
302     {
303         return FALSE;
304     }
305     test = fopen(fname, "r");
306     if (test == NULL)
307     {
308         /*Windows doesn't allow fopen of directory - so we need to check this seperately */
309         #ifdef GMX_NATIVE_WINDOWS
310         DWORD attr = GetFileAttributes(fname);
311         return (attr != INVALID_FILE_ATTRIBUTES) && (attr & FILE_ATTRIBUTE_DIRECTORY);
312         #else
313         return FALSE;
314         #endif
315     }
316     else
317     {
318         fclose(test);
319         return TRUE;
320     }
321 }
322
323 gmx_bool gmx_eof(FILE *fp)
324 {
325     char     data[4];
326     gmx_bool beof;
327
328     if (is_pipe(fp))
329     {
330         return feof(fp);
331     }
332     else
333     {
334         if ((beof = fread(data, 1, 1, fp)) == 1)
335         {
336             gmx_fseek(fp, -1, SEEK_CUR);
337         }
338         return !beof;
339     }
340 }
341
342 static char *backup_fn(const char *file, int count_max)
343 {
344     /* Use a reasonably low value for countmax; we might
345      * generate 4-5 files in each round, and we dont
346      * want to hit directory limits of 1024 or 2048 files.
347      */
348 #define COUNTMAX 99
349     int          i, count = 1;
350     char        *directory, *fn;
351     char        *buf;
352
353     if (count_max == -1)
354     {
355         count_max = COUNTMAX;
356     }
357
358     smalloc(buf, GMX_PATH_MAX);
359
360     for (i = strlen(file)-1; ((i > 0) && (file[i] != DIR_SEPARATOR)); i--)
361     {
362         ;
363     }
364     /* Must check whether i > 0, i.e. whether there is a directory
365      * in the file name. In that case we overwrite the / sign with
366      * a '\0' to end the directory string .
367      */
368     if (i > 0)
369     {
370         directory    = gmx_strdup(file);
371         directory[i] = '\0';
372         fn           = gmx_strdup(file+i+1);
373     }
374     else
375     {
376         directory    = gmx_strdup(".");
377         fn           = gmx_strdup(file);
378     }
379     do
380     {
381         sprintf(buf, "%s/#%s.%d#", directory, fn, count);
382         count++;
383     }
384     while ((count <= count_max) && gmx_fexist(buf));
385
386     /* Arbitrarily bail out */
387     if (count > count_max)
388     {
389         gmx_fatal(FARGS, "Won't make more than %d backups of %s for you.\n"
390                   "The env.var. GMX_MAXBACKUP controls this maximum, -1 disables backups.",
391                   count_max, fn);
392     }
393
394     sfree(directory);
395     sfree(fn);
396
397     return buf;
398 }
399
400 gmx_bool make_backup(const char * name)
401 {
402     char * env;
403     int    count_max;
404     char * backup;
405
406 #ifdef GMX_FAHCORE
407     return FALSE; /* skip making backups */
408 #else
409
410     if (gmx_fexist(name))
411     {
412         env = getenv("GMX_MAXBACKUP");
413         if (env != NULL)
414         {
415             count_max = strtol(env, NULL, 10);
416             if (count_max == -1)
417             {
418                 /* Do not make backups and possibly overwrite old files */
419                 return TRUE;
420             }
421         }
422         else
423         {
424             /* Use the default maximum */
425             count_max = -1;
426         }
427         backup = backup_fn(name, count_max);
428         if (rename(name, backup) == 0)
429         {
430             fprintf(stderr, "\nBack Off! I just backed up %s to %s\n",
431                     name, backup);
432         }
433         else
434         {
435             fprintf(stderr, "Sorry couldn't backup %s to %s\n", name, backup);
436             return FALSE;
437         }
438         sfree(backup);
439     }
440     return TRUE;
441 #endif
442 }
443
444 FILE *gmx_ffopen(const char *file, const char *mode)
445 {
446 #ifdef SKIP_FFOPS
447     return fopen(file, mode);
448 #else
449     FILE    *ff = NULL;
450     char     buf[256], *bufsize = 0, *ptr;
451     gmx_bool bRead;
452     int      bs;
453
454     if (file == NULL)
455     {
456         return NULL;
457     }
458
459     if (mode[0] == 'w')
460     {
461         make_backup(file);
462     }
463     where();
464
465     bRead = (mode[0] == 'r' && mode[1] != '+');
466     strcpy(buf, file);
467     if (!bRead || gmx_fexist(buf))
468     {
469         if ((ff = fopen(buf, mode)) == NULL)
470         {
471             gmx_file(buf);
472         }
473         where();
474         /* Check whether we should be using buffering (default) or not
475          * (for debugging)
476          */
477         if (bUnbuffered || ((bufsize = getenv("LOG_BUFS")) != NULL))
478         {
479             /* Check whether to use completely unbuffered */
480             if (bUnbuffered)
481             {
482                 bs = 0;
483             }
484             else
485             {
486                 bs = strtol(bufsize, NULL, 10);
487             }
488             if (bs <= 0)
489             {
490                 setbuf(ff, NULL);
491             }
492             else
493             {
494                 snew(ptr, bs+8);
495                 if (setvbuf(ff, ptr, _IOFBF, bs) != 0)
496                 {
497                     gmx_file("Buffering File");
498                 }
499             }
500         }
501         where();
502     }
503     else
504     {
505         sprintf(buf, "%s.Z", file);
506         if (gmx_fexist(buf))
507         {
508             ff = uncompress(buf, mode);
509         }
510         else
511         {
512             sprintf(buf, "%s.gz", file);
513             if (gmx_fexist(buf))
514             {
515                 ff = gunzip(buf, mode);
516             }
517             else
518             {
519                 gmx_file(file);
520             }
521         }
522     }
523     return ff;
524 #endif
525 }
526
527 /* Our own implementation of dirent-like functionality to scan directories. */
528 struct gmx_directory
529 {
530 #ifdef HAVE_DIRENT_H
531     DIR  *               dirent_handle;
532 #elif (defined GMX_NATIVE_WINDOWS)
533     intptr_t             windows_handle;
534     struct _finddata_t   finddata;
535     int                  first;
536 #else
537     int                  dummy;
538 #endif
539 };
540
541
542 int
543 gmx_directory_open(gmx_directory_t *p_gmxdir, const char *dirname)
544 {
545     struct gmx_directory *  gmxdir;
546     int                     rc;
547
548     snew(gmxdir, 1);
549
550     *p_gmxdir = gmxdir;
551
552 #ifdef HAVE_DIRENT_H
553     if ( (gmxdir->dirent_handle = opendir(dirname)) != NULL)
554     {
555         rc = 0;
556     }
557     else
558     {
559         sfree(gmxdir);
560         *p_gmxdir = NULL;
561         rc        = EINVAL;
562     }
563 #elif (defined GMX_NATIVE_WINDOWS)
564
565     if (dirname != NULL && strlen(dirname) > 0)
566     {
567         char *     tmpname;
568         int        len;
569
570         len = strlen(dirname);
571         snew(tmpname, len+3);
572
573         strncpy(tmpname, dirname, len+1);
574
575         /* Remove possible trailing directory separator */
576         if (tmpname[len] == '/' || tmpname[len] == '\\')
577         {
578             tmpname[len] = '\0';
579         }
580
581         /* Add wildcard */
582         strcat(tmpname, "/*");
583
584         gmxdir->first = 1;
585         if ( (gmxdir->windows_handle = _findfirst(tmpname, &gmxdir->finddata)) > 0L)
586         {
587             rc = 0;
588         }
589         else
590         {
591             if (errno == EINVAL)
592             {
593                 sfree(gmxdir);
594                 *p_gmxdir = NULL;
595                 rc        = EINVAL;
596             }
597             else
598             {
599                 rc        = 0;
600             }
601         }
602     }
603     else
604     {
605         rc = EINVAL;
606     }
607 #else
608     gmx_fatal(FARGS,
609               "Source compiled without POSIX dirent or windows support - cannot scan directories.\n"
610               "In the very unlikely event this is not a compile-time mistake you could consider\n"
611               "implementing support for your platform in futil.c, but contact the developers\n"
612               "to make sure it's really necessary!\n");
613     rc = -1;
614 #endif
615     return rc;
616 }
617
618
619 int
620 gmx_directory_nextfile(gmx_directory_t gmxdir, char *name, int maxlength_name)
621 {
622     int                     rc;
623
624 #ifdef HAVE_DIRENT_H
625
626     struct dirent *         direntp_large;
627     struct dirent *         p;
628
629
630     if (gmxdir != NULL && gmxdir->dirent_handle != NULL)
631     {
632         /* On some platforms no space is present for d_name in dirent.
633          * Since d_name is guaranteed to be the last entry, allocating
634          * extra space for dirent will allow more size for d_name.
635          * GMX_MAX_PATH should always be >= the max possible d_name.
636          */
637         smalloc(direntp_large, sizeof(*direntp_large) + GMX_PATH_MAX);
638         rc = readdir_r(gmxdir->dirent_handle, direntp_large, &p);
639
640         if (p != NULL && rc == 0)
641         {
642             strncpy(name, direntp_large->d_name, maxlength_name);
643         }
644         else
645         {
646             name[0] = '\0';
647             rc      = ENOENT;
648         }
649         sfree(direntp_large);
650     }
651     else
652     {
653         name[0] = '\0';
654         rc      = EINVAL;
655     }
656
657 #elif (defined GMX_NATIVE_WINDOWS)
658
659     if (gmxdir != NULL)
660     {
661         if (gmxdir->windows_handle <= 0)
662         {
663
664             name[0] = '\0';
665             rc      = ENOENT;
666         }
667         else if (gmxdir->first == 1)
668         {
669             strncpy(name, gmxdir->finddata.name, maxlength_name);
670             rc            = 0;
671             gmxdir->first = 0;
672         }
673         else
674         {
675             if (_findnext(gmxdir->windows_handle, &gmxdir->finddata) == 0)
676             {
677                 strncpy(name, gmxdir->finddata.name, maxlength_name);
678                 rc      = 0;
679             }
680             else
681             {
682                 name[0] = '\0';
683                 rc      = ENOENT;
684             }
685         }
686     }
687
688 #else
689     gmx_fatal(FARGS,
690               "Source compiled without POSIX dirent or windows support - cannot scan directories.\n");
691     rc = -1;
692 #endif
693     return rc;
694 }
695
696
697 int
698 gmx_directory_close(gmx_directory_t gmxdir)
699 {
700     int                     rc;
701 #ifdef HAVE_DIRENT_H
702     rc = (gmxdir != NULL) ? closedir(gmxdir->dirent_handle) : EINVAL;
703 #elif (defined GMX_NATIVE_WINDOWS)
704     rc = (gmxdir != NULL) ? _findclose(gmxdir->windows_handle) : EINVAL;
705 #else
706     gmx_fatal(FARGS,
707               "Source compiled without POSIX dirent or windows support - cannot scan directories.\n");
708     rc = -1;
709 #endif
710
711     sfree(gmxdir);
712     return rc;
713 }
714
715
716 char *low_gmxlibfn(const char *file, gmx_bool bAddCWD, gmx_bool bFatal)
717 {
718     bool bEnvIsSet = false;
719     try
720     {
721         if (bAddCWD && gmx_fexist(file))
722         {
723             return gmx_strdup(file);
724         }
725         else
726         {
727             std::string  libpath;
728             // GMXLIB can be a path.
729             const char  *lib = getenv("GMXLIB");
730             if (lib != NULL)
731             {
732                 bEnvIsSet = true;
733                 libpath   = lib;
734             }
735             else
736             {
737                 libpath = gmx::getProgramContext().defaultLibraryDataPath();
738             }
739
740             std::vector<std::string>                 pathEntries;
741             gmx::Path::splitPathEnvironment(libpath, &pathEntries);
742             std::vector<std::string>::const_iterator i;
743             for (i = pathEntries.begin(); i != pathEntries.end(); ++i)
744             {
745                 std::string testPath = gmx::Path::join(*i, file);
746                 if (gmx::Path::exists(testPath))
747                 {
748                     return gmx_strdup(testPath.c_str());
749                 }
750             }
751         }
752     }
753     GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR;
754     if (bFatal)
755     {
756         if (bEnvIsSet)
757         {
758             gmx_fatal(FARGS,
759                       "Library file %s not found %sin your GMXLIB path.",
760                       file, bAddCWD ? "in current dir nor " : "");
761         }
762         else
763         {
764             gmx_fatal(FARGS,
765                       "Library file %s not found %sin default directories.\n"
766                       "(You can set the directories to search with the GMXLIB path variable)",
767                       file, bAddCWD ? "in current dir nor " : "");
768         }
769     }
770     return NULL;
771 }
772
773 FILE *low_libopen(const char *file, gmx_bool bFatal)
774 {
775     FILE *ff;
776     char *fn;
777
778     fn = low_gmxlibfn(file, TRUE, bFatal);
779
780     if (fn == NULL)
781     {
782         ff = NULL;
783     }
784     else
785     {
786         if (debug)
787         {
788             fprintf(debug, "Opening library file %s\n", fn);
789         }
790         ff = fopen(fn, "r");
791     }
792     sfree(fn);
793
794     return ff;
795 }
796
797 char *gmxlibfn(const char *file)
798 {
799     return low_gmxlibfn(file, TRUE, TRUE);
800 }
801
802 FILE *libopen(const char *file)
803 {
804     return low_libopen(file, TRUE);
805 }
806
807 void gmx_tmpnam(char *buf)
808 {
809     int i, len;
810
811     if ((len = strlen(buf)) < 7)
812     {
813         gmx_fatal(FARGS, "Buf passed to gmx_tmpnam must be at least 7 bytes long");
814     }
815     for (i = len-6; (i < len); i++)
816     {
817         buf[i] = 'X';
818     }
819     /* mktemp is dangerous and we should use mkstemp instead, but
820      * since windows doesnt support it we have to separate the cases.
821      * 20090307: mktemp deprecated, use iso c++ _mktemp instead.
822      */
823 #ifdef GMX_NATIVE_WINDOWS
824     _mktemp(buf);
825 #else
826     int fd = mkstemp(buf);
827
828     switch (fd)
829     {
830         case EINVAL:
831             gmx_fatal(FARGS, "Invalid template %s for mkstemp", buf);
832             break;
833         case EEXIST:
834             gmx_fatal(FARGS, "mkstemp created existing file", buf);
835             break;
836         case EACCES:
837             gmx_fatal(FARGS, "Permission denied for opening %s", buf);
838             break;
839         default:
840             break;
841     }
842     close(fd);
843 #endif
844     /* name in Buf should now be OK */
845 }
846
847 int gmx_file_rename(const char *oldname, const char *newname)
848 {
849 #ifndef GMX_NATIVE_WINDOWS
850     /* under unix, rename() is atomic (at least, it should be). */
851     return rename(oldname, newname);
852 #else
853     if (MoveFileEx(oldname, newname,
854                    MOVEFILE_REPLACE_EXISTING|MOVEFILE_WRITE_THROUGH))
855     {
856         return 0;
857     }
858     else
859     {
860         return 1;
861     }
862 #endif
863 }
864
865 int gmx_file_copy(const char *oldname, const char *newname, gmx_bool copy_if_empty)
866 {
867 /* the full copy buffer size: */
868 #define FILECOPY_BUFSIZE (1<<16)
869     FILE *in  = NULL;
870     FILE *out = NULL;
871     char *buf;
872
873     snew(buf, FILECOPY_BUFSIZE);
874
875     in = fopen(oldname, "rb");
876     if (!in)
877     {
878         goto error;
879     }
880
881     /* If we don't copy when empty, we postpone opening the file
882        until we're actually ready to write. */
883     if (copy_if_empty)
884     {
885         out = fopen(newname, "wb");
886         if (!out)
887         {
888             goto error;
889         }
890     }
891
892     while (!feof(in))
893     {
894         size_t nread;
895
896         nread = fread(buf, sizeof(char), FILECOPY_BUFSIZE, in);
897         if (nread > 0)
898         {
899             size_t ret;
900             if (!out)
901             {
902                 /* so this is where we open when copy_if_empty is false:
903                    here we know we read something. */
904                 out = fopen(newname, "wb");
905                 if (!out)
906                 {
907                     goto error;
908                 }
909             }
910             ret = fwrite(buf, sizeof(char), nread, out);
911             if (ret != nread)
912             {
913                 goto error;
914             }
915         }
916         if (ferror(in))
917         {
918             goto error;
919         }
920     }
921     sfree(buf);
922     fclose(in);
923     fclose(out);
924     return 0;
925 error:
926     sfree(buf);
927     if (in)
928     {
929         fclose(in);
930     }
931     if (out)
932     {
933         fclose(out);
934     }
935     return 1;
936 #undef FILECOPY_BUFSIZE
937 }
938
939
940 int gmx_fsync(FILE *fp)
941 {
942     int rc = 0;
943
944 #ifdef GMX_FAHCORE
945     /* the fahcore defines its own os-independent fsync */
946     rc = fah_fsync(fp);
947 #else /* GMX_FAHCORE */
948     {
949         int fn = -1;
950
951         /* get the file number */
952 #if defined(HAVE_FILENO)
953         fn = fileno(fp);
954 #elif defined(HAVE__FILENO)
955         fn = _fileno(fp);
956 #endif
957
958         /* do the actual fsync */
959         if (fn >= 0)
960         {
961 #if (defined(HAVE_FSYNC))
962             rc = fsync(fn);
963 #elif (defined(HAVE__COMMIT))
964             rc = _commit(fn);
965 #endif
966         }
967     }
968 #endif /* GMX_FAHCORE */
969
970     /* We check for these error codes this way because POSIX requires them
971        to be defined, and using anything other than macros is unlikely: */
972 #ifdef EINTR
973     /* we don't want to report an error just because fsync() caught a signal.
974        For our purposes, we can just ignore this. */
975     if (rc && errno == EINTR)
976     {
977         rc = 0;
978     }
979 #endif
980 #ifdef EINVAL
981     /* we don't want to report an error just because we tried to fsync()
982        stdout, a socket or a pipe. */
983     if (rc && errno == EINVAL)
984     {
985         rc = 0;
986     }
987 #endif
988     return rc;
989 }
990
991 void gmx_chdir(const char *directory)
992 {
993 #ifdef GMX_NATIVE_WINDOWS
994     int rc = _chdir(directory);
995 #else
996     int rc = chdir(directory);
997 #endif
998     if (rc != 0)
999     {
1000         gmx_fatal(FARGS, "Cannot change directory to '%s'. Reason: %s",
1001                   directory, strerror(errno));
1002     }
1003 }
1004
1005 void gmx_getcwd(char *buffer, size_t size)
1006 {
1007 #ifdef GMX_NATIVE_WINDOWS
1008     char *pdum = _getcwd(buffer, size);
1009 #else
1010     char *pdum = getcwd(buffer, size);
1011 #endif
1012     if (pdum == NULL)
1013     {
1014         gmx_fatal(FARGS, "Cannot get working directory. Reason: %s",
1015                   strerror(errno));
1016     }
1017 }