2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5 * Copyright (c) 2001-2004, The GROMACS development team.
6 * Copyright (c) 2013,2014,2015, 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.
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.
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.
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.
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.
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.
49 #include <sys/types.h>
58 #ifdef GMX_NATIVE_WINDOWS
64 #include "thread_mpi/threads.h"
66 #include "gromacs/utility/cstringutil.h"
67 #include "gromacs/utility/datafilefinder.h"
68 #include "gromacs/utility/exceptions.h"
69 #include "gromacs/utility/fatalerror.h"
70 #include "gromacs/utility/path.h"
71 #include "gromacs/utility/programcontext.h"
72 #include "gromacs/utility/smalloc.h"
73 #include "gromacs/utility/stringutil.h"
75 /* we keep a linked list of all files opened through pipes (i.e.
76 compressed or .gzipped files. This way we can distinguish between them
77 without having to change the semantics of reading from/writing to files)
79 typedef struct t_pstack {
81 struct t_pstack *prev;
84 static t_pstack *pstack = NULL;
85 static bool bUnbuffered = false;
86 static int s_maxBackupCount = 0;
88 /* this linked list is an intrinsically globally shared object, so we have
89 to protect it with mutexes */
90 static tMPI_Thread_mutex_t pstack_mutex = TMPI_THREAD_MUTEX_INITIALIZER;
96 //! Global library file finder; stores the object set with setLibraryFileFinder().
97 const DataFileFinder *g_libFileFinder;
98 //! Default library file finder if nothing is set.
99 const DataFileFinder g_defaultLibFileFinder;
102 const DataFileFinder &getLibraryFileFinder()
104 if (g_libFileFinder != NULL)
106 return *g_libFileFinder;
108 return g_defaultLibFileFinder;
111 void setLibraryFileFinder(const DataFileFinder *finder)
113 g_libFileFinder = finder;
118 void gmx_disable_file_buffering(void)
123 void gmx_set_max_backup_count(int count)
127 const char *env = getenv("GMX_MAXBACKUP");
130 // TODO: Check that the value is converted properly.
131 count = strtol(env, NULL, 10);
139 // Use a reasonably low value for countmax; we might
140 // generate 4-5 files in each round, and we don't
141 // want to hit directory limits of 1024 or 2048 files.
145 s_maxBackupCount = count;
148 void push_ps(FILE *fp)
152 tMPI_Thread_mutex_lock(&pstack_mutex);
159 tMPI_Thread_mutex_unlock(&pstack_mutex);
163 /* don't use pipes!*/
164 #define popen fah_fopen
165 #define pclose fah_fclose
171 #if (!defined(HAVE_PIPES) && !defined(__native_client__))
172 static FILE *popen(const char *nm, const char *mode)
174 gmx_impl("Sorry no pipes...");
179 static int pclose(FILE *fp)
181 gmx_impl("Sorry no pipes...");
185 #endif /* !defined(HAVE_PIPES) && !defined(__native_client__) */
186 #endif /* GMX_FAHCORE */
188 int gmx_ffclose(FILE *fp)
196 tMPI_Thread_mutex_lock(&pstack_mutex);
206 else if (ps->fp == fp)
212 pstack = pstack->prev;
217 while ((ps->prev != NULL) && (ps->prev->fp != fp))
221 if ((ps->prev != NULL) && ps->prev->fp == fp)
223 if (ps->prev->fp != NULL)
225 ret = pclose(ps->prev->fp);
228 ps->prev = ps->prev->prev;
240 tMPI_Thread_mutex_unlock(&pstack_mutex);
246 void frewind(FILE *fp)
248 tMPI_Thread_mutex_lock(&pstack_mutex);
250 t_pstack *ps = pstack;
255 fprintf(stderr, "Cannot rewind compressed file!\n");
256 tMPI_Thread_mutex_unlock(&pstack_mutex);
262 tMPI_Thread_mutex_unlock(&pstack_mutex);
265 int gmx_fseek(FILE *stream, gmx_off_t offset, int whence)
268 return fseeko(stream, offset, whence);
270 #ifdef HAVE__FSEEKI64
271 return _fseeki64(stream, offset, whence);
273 return fseek(stream, offset, whence);
278 gmx_off_t gmx_ftell(FILE *stream)
281 return ftello(stream);
283 #ifdef HAVE__FSEEKI64
285 return _ftelli64(stream);
287 return ftello64(stream);
290 return ftell(stream);
295 int gmx_truncate(const char *filename, gmx_off_t length)
297 #ifdef GMX_NATIVE_WINDOWS
298 FILE *fp = fopen(filename, "rb+");
304 int rc = _chsize_s(fileno(fp), length);
306 int rc = _chsize(fileno(fp), length);
311 return truncate(filename, length);
315 static FILE *uncompress(const char *fn, const char *mode)
320 sprintf(buf, "uncompress -c < %s", fn);
321 fprintf(stderr, "Going to execute '%s'\n", buf);
322 if ((fp = popen(buf, mode)) == NULL)
331 static FILE *gunzip(const char *fn, const char *mode)
336 sprintf(buf, "gunzip -c < %s", fn);
337 fprintf(stderr, "Going to execute '%s'\n", buf);
338 if ((fp = popen(buf, mode)) == NULL)
347 gmx_bool gmx_fexist(const char *fname)
355 test = fopen(fname, "r");
358 /*Windows doesn't allow fopen of directory - so we need to check this seperately */
359 #ifdef GMX_NATIVE_WINDOWS
360 DWORD attr = GetFileAttributes(fname);
361 return (attr != INVALID_FILE_ATTRIBUTES) && (attr & FILE_ATTRIBUTE_DIRECTORY);
373 static char *backup_fn(const char *file)
376 char *directory, *fn;
379 smalloc(buf, GMX_PATH_MAX);
381 for (i = strlen(file)-1; ((i > 0) && (file[i] != DIR_SEPARATOR)); i--)
385 /* Must check whether i > 0, i.e. whether there is a directory
386 * in the file name. In that case we overwrite the / sign with
387 * a '\0' to end the directory string .
391 directory = gmx_strdup(file);
393 fn = gmx_strdup(file+i+1);
397 directory = gmx_strdup(".");
398 fn = gmx_strdup(file);
402 sprintf(buf, "%s/#%s.%d#", directory, fn, count);
405 while ((count <= s_maxBackupCount) && gmx_fexist(buf));
407 /* Arbitrarily bail out */
408 if (count > s_maxBackupCount)
410 /* TODO: The error message is only accurate for code that starts with
411 * Gromacs command-line interface. */
412 gmx_fatal(FARGS, "Won't make more than %d backups of %s for you.\n"
413 "The env.var. GMX_MAXBACKUP controls this maximum, -1 disables backups.",
414 s_maxBackupCount, fn);
423 void make_backup(const char *name)
425 if (s_maxBackupCount <= 0)
429 if (gmx_fexist(name))
431 char *backup = backup_fn(name);
432 if (rename(name, backup) == 0)
434 fprintf(stderr, "\nBack Off! I just backed up %s to %s\n",
439 fprintf(stderr, "\nSorry couldn't backup %s to %s\n", name, backup);
445 FILE *gmx_ffopen(const char *file, const char *mode)
448 return fopen(file, mode);
451 char buf[256], *bufsize = 0, *ptr;
466 bRead = (mode[0] == 'r' && mode[1] != '+');
468 if (!bRead || gmx_fexist(buf))
470 if ((ff = fopen(buf, mode)) == NULL)
475 /* Check whether we should be using buffering (default) or not
478 if (bUnbuffered || ((bufsize = getenv("GMX_LOG_BUFFER")) != NULL))
480 /* Check whether to use completely unbuffered */
487 bs = strtol(bufsize, NULL, 10);
496 if (setvbuf(ff, ptr, _IOFBF, bs) != 0)
498 gmx_file("Buffering File");
506 sprintf(buf, "%s.Z", file);
509 ff = uncompress(buf, mode);
513 sprintf(buf, "%s.gz", file);
516 ff = gunzip(buf, mode);
528 /* Our own implementation of dirent-like functionality to scan directories. */
531 #if defined(GMX_NATIVE_WINDOWS)
532 intptr_t windows_handle;
533 struct _finddata_t finddata;
535 #elif defined(HAVE_DIRENT_H)
544 gmx_directory_open(gmx_directory_t *p_gmxdir, const char *dirname)
546 struct gmx_directory * gmxdir;
553 #if defined(GMX_NATIVE_WINDOWS)
554 if (dirname != NULL && strlen(dirname) > 0)
559 len = strlen(dirname);
560 snew(tmpname, len+3);
562 strncpy(tmpname, dirname, len+1);
564 /* Remove possible trailing directory separator */
565 if (tmpname[len] == '/' || tmpname[len] == '\\')
571 strcat(tmpname, "/*");
574 if ( (gmxdir->windows_handle = _findfirst(tmpname, &gmxdir->finddata)) > 0L)
596 #elif defined(HAVE_DIRENT_H)
597 if ( (gmxdir->dirent_handle = opendir(dirname)) != NULL)
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");
620 gmx_directory_nextfile(gmx_directory_t gmxdir, char *name, int maxlength_name)
624 #if defined(GMX_NATIVE_WINDOWS)
627 if (gmxdir->windows_handle <= 0)
633 else if (gmxdir->first == 1)
635 strncpy(name, gmxdir->finddata.name, maxlength_name);
641 if (_findnext(gmxdir->windows_handle, &gmxdir->finddata) == 0)
643 strncpy(name, gmxdir->finddata.name, maxlength_name);
658 #elif defined(HAVE_DIRENT_H)
659 struct dirent * direntp_large;
663 if (gmxdir != NULL && gmxdir->dirent_handle != NULL)
665 /* On some platforms no space is present for d_name in dirent.
666 * Since d_name is guaranteed to be the last entry, allocating
667 * extra space for dirent will allow more size for d_name.
668 * GMX_MAX_PATH should always be >= the max possible d_name.
670 smalloc(direntp_large, sizeof(*direntp_large) + GMX_PATH_MAX);
671 rc = readdir_r(gmxdir->dirent_handle, direntp_large, &p);
673 if (p != NULL && rc == 0)
675 strncpy(name, direntp_large->d_name, maxlength_name);
682 sfree(direntp_large);
691 "Source compiled without POSIX dirent or windows support - cannot scan directories.\n");
699 gmx_directory_close(gmx_directory_t gmxdir)
702 #if defined(GMX_NATIVE_WINDOWS)
703 rc = (gmxdir != NULL) ? _findclose(gmxdir->windows_handle) : EINVAL;
704 #elif defined(HAVE_DIRENT_H)
705 rc = (gmxdir != NULL) ? closedir(gmxdir->dirent_handle) : EINVAL;
708 "Source compiled without POSIX dirent or windows support - cannot scan directories.\n");
717 char *low_gmxlibfn(const char *file, gmx_bool bAddCWD, gmx_bool bFatal)
721 const gmx::DataFileFinder &finder = gmx::getLibraryFileFinder();
723 finder.findFile(gmx::DataFileOptions(file)
724 .includeCurrentDir(bAddCWD)
725 .throwIfNotFound(bFatal));
728 return gmx_strdup(result.c_str());
731 GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR;
735 FILE *low_libopen(const char *file, gmx_bool bFatal)
739 const gmx::DataFileFinder &finder = gmx::getLibraryFileFinder();
741 finder.openFile(gmx::DataFileOptions(file)
742 .includeCurrentDir(true)
743 .throwIfNotFound(bFatal));
746 GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR;
750 char *gmxlibfn(const char *file)
752 return low_gmxlibfn(file, TRUE, TRUE);
755 FILE *libopen(const char *file)
757 return low_libopen(file, TRUE);
760 void gmx_tmpnam(char *buf)
764 if ((len = strlen(buf)) < 7)
766 gmx_fatal(FARGS, "Buf passed to gmx_tmpnam must be at least 7 bytes long");
768 for (i = len-6; (i < len); i++)
772 /* mktemp is dangerous and we should use mkstemp instead, but
773 * since windows doesnt support it we have to separate the cases.
774 * 20090307: mktemp deprecated, use iso c++ _mktemp instead.
776 #ifdef GMX_NATIVE_WINDOWS
779 int fd = mkstemp(buf);
784 gmx_fatal(FARGS, "Invalid template %s for mkstemp", buf);
787 gmx_fatal(FARGS, "mkstemp created existing file", buf);
790 gmx_fatal(FARGS, "Permission denied for opening %s", buf);
797 /* name in Buf should now be OK */
800 int gmx_file_rename(const char *oldname, const char *newname)
802 #ifndef GMX_NATIVE_WINDOWS
803 /* under unix, rename() is atomic (at least, it should be). */
804 return rename(oldname, newname);
806 if (MoveFileEx(oldname, newname,
807 MOVEFILE_REPLACE_EXISTING|MOVEFILE_WRITE_THROUGH))
818 int gmx_file_copy(const char *oldname, const char *newname, gmx_bool copy_if_empty)
820 /* the full copy buffer size: */
821 #define FILECOPY_BUFSIZE (1<<16)
826 snew(buf, FILECOPY_BUFSIZE);
828 in = fopen(oldname, "rb");
834 /* If we don't copy when empty, we postpone opening the file
835 until we're actually ready to write. */
838 out = fopen(newname, "wb");
849 nread = fread(buf, sizeof(char), FILECOPY_BUFSIZE, in);
855 /* so this is where we open when copy_if_empty is false:
856 here we know we read something. */
857 out = fopen(newname, "wb");
863 ret = fwrite(buf, sizeof(char), nread, out);
889 #undef FILECOPY_BUFSIZE
893 int gmx_fsync(FILE *fp)
898 /* the fahcore defines its own os-independent fsync */
900 #else /* GMX_FAHCORE */
904 /* get the file number */
905 #if defined(HAVE_FILENO)
907 #elif defined(HAVE__FILENO)
913 /* do the actual fsync */
916 #if (defined(HAVE_FSYNC))
918 #elif (defined(HAVE__COMMIT))
923 #endif /* GMX_FAHCORE */
925 /* We check for these error codes this way because POSIX requires them
926 to be defined, and using anything other than macros is unlikely: */
928 /* we don't want to report an error just because fsync() caught a signal.
929 For our purposes, we can just ignore this. */
930 if (rc && errno == EINTR)
936 /* we don't want to report an error just because we tried to fsync()
937 stdout, a socket or a pipe. */
938 if (rc && errno == EINVAL)
946 void gmx_chdir(const char *directory)
948 #ifdef GMX_NATIVE_WINDOWS
949 int rc = _chdir(directory);
951 int rc = chdir(directory);
955 gmx_fatal(FARGS, "Cannot change directory to '%s'. Reason: %s",
956 directory, strerror(errno));
960 void gmx_getcwd(char *buffer, size_t size)
962 #ifdef GMX_NATIVE_WINDOWS
963 char *pdum = _getcwd(buffer, size);
965 char *pdum = getcwd(buffer, size);
969 gmx_fatal(FARGS, "Cannot get working directory. Reason: %s",