0b5fe92cfed5f0069e297426d027504229075e0d
[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,2015,2016, 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 "gmxpre.h"
38
39 #include "futil.h"
40
41 #include "config.h"
42
43 #include <errno.h>
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <string.h>
47
48 #include <fcntl.h>
49 #include <sys/stat.h>
50 #include <sys/types.h>
51
52 #ifdef HAVE_UNISTD_H
53 #include <unistd.h>
54 #endif
55 #if GMX_NATIVE_WINDOWS
56 #include <direct.h>   // For _chdir() and _getcwd()
57 #include <io.h>
58 #include <windows.h>
59 #endif
60
61 #include "thread_mpi/threads.h"
62
63 #include "gromacs/utility/cstringutil.h"
64 #include "gromacs/utility/datafilefinder.h"
65 #include "gromacs/utility/dir_separator.h"
66 #include "gromacs/utility/exceptions.h"
67 #include "gromacs/utility/fatalerror.h"
68 #include "gromacs/utility/path.h"
69 #include "gromacs/utility/programcontext.h"
70 #include "gromacs/utility/smalloc.h"
71 #include "gromacs/utility/stringutil.h"
72
73 /* we keep a linked list of all files opened through pipes (i.e.
74    compressed or .gzipped files. This way we can distinguish between them
75    without having to change the semantics of reading from/writing to files)
76  */
77 typedef struct t_pstack {
78     FILE            *fp;
79     struct t_pstack *prev;
80 } t_pstack;
81
82 static t_pstack    *pstack           = NULL;
83 static bool         bUnbuffered      = false;
84 static int          s_maxBackupCount = 0;
85
86 /* this linked list is an intrinsically globally shared object, so we have
87    to protect it with mutexes */
88 static tMPI_Thread_mutex_t pstack_mutex = TMPI_THREAD_MUTEX_INITIALIZER;
89
90 namespace gmx
91 {
92 namespace
93 {
94 //! Global library file finder; stores the object set with setLibraryFileFinder().
95 const DataFileFinder *g_libFileFinder;
96 //! Default library file finder if nothing is set.
97 const DataFileFinder  g_defaultLibFileFinder;
98 }   // namespace
99
100 const DataFileFinder &getLibraryFileFinder()
101 {
102     if (g_libFileFinder != NULL)
103     {
104         return *g_libFileFinder;
105     }
106     return g_defaultLibFileFinder;
107 }
108
109 void setLibraryFileFinder(const DataFileFinder *finder)
110 {
111     g_libFileFinder = finder;
112 }
113
114 } // namespace gmx
115
116 void gmx_disable_file_buffering(void)
117 {
118     bUnbuffered = true;
119 }
120
121 void gmx_set_max_backup_count(int count)
122 {
123     if (count < 0)
124     {
125         const char *env = getenv("GMX_MAXBACKUP");
126         if (env != NULL)
127         {
128             // TODO: Check that the value is converted properly.
129             count = strtol(env, NULL, 10);
130             if (count < 0)
131             {
132                 count = 0;
133             }
134         }
135         else
136         {
137             // Use a reasonably low value for countmax; we might
138             // generate 4-5 files in each round, and we don't
139             // want to hit directory limits of 1024 or 2048 files.
140             count = 99;
141         }
142     }
143     s_maxBackupCount = count;
144 }
145
146 void push_ps(FILE *fp)
147 {
148     t_pstack *ps;
149
150     tMPI_Thread_mutex_lock(&pstack_mutex);
151
152     snew(ps, 1);
153     ps->fp   = fp;
154     ps->prev = pstack;
155     pstack   = ps;
156
157     tMPI_Thread_mutex_unlock(&pstack_mutex);
158 }
159
160 #ifdef GMX_FAHCORE
161 /* don't use pipes!*/
162 #define popen fah_fopen
163 #define pclose fah_fclose
164 #define SKIP_FFOPS 1
165 #else
166 #ifdef gmx_ffclose
167 #undef gmx_ffclose
168 #endif
169 #if (!HAVE_PIPES && !defined(__native_client__))
170 static FILE *popen(const char *nm, const char *mode)
171 {
172     gmx_impl("Sorry no pipes...");
173
174     return NULL;
175 }
176
177 static int pclose(FILE *fp)
178 {
179     gmx_impl("Sorry no pipes...");
180
181     return 0;
182 }
183 #endif /* !HAVE_PIPES && !defined(__native_client__) */
184 #endif /* GMX_FAHCORE */
185
186 int gmx_ffclose(FILE *fp)
187 {
188 #ifdef SKIP_FFOPS
189     return fclose(fp);
190 #else
191     t_pstack *ps, *tmp;
192     int       ret = 0;
193
194     tMPI_Thread_mutex_lock(&pstack_mutex);
195
196     ps = pstack;
197     if (ps == NULL)
198     {
199         if (fp != NULL)
200         {
201             ret = fclose(fp);
202         }
203     }
204     else if (ps->fp == fp)
205     {
206         if (fp != NULL)
207         {
208             ret = pclose(fp);
209         }
210         pstack = pstack->prev;
211         sfree(ps);
212     }
213     else
214     {
215         while ((ps->prev != NULL) && (ps->prev->fp != fp))
216         {
217             ps = ps->prev;
218         }
219         if ((ps->prev != NULL) && ps->prev->fp == fp)
220         {
221             if (ps->prev->fp != NULL)
222             {
223                 ret = pclose(ps->prev->fp);
224             }
225             tmp      = ps->prev;
226             ps->prev = ps->prev->prev;
227             sfree(tmp);
228         }
229         else
230         {
231             if (fp != NULL)
232             {
233                 ret = fclose(fp);
234             }
235         }
236     }
237
238     tMPI_Thread_mutex_unlock(&pstack_mutex);
239     return ret;
240 #endif
241 }
242
243
244 void frewind(FILE *fp)
245 {
246     tMPI_Thread_mutex_lock(&pstack_mutex);
247
248     t_pstack *ps = pstack;
249     while (ps != NULL)
250     {
251         if (ps->fp == fp)
252         {
253             fprintf(stderr, "Cannot rewind compressed file!\n");
254             tMPI_Thread_mutex_unlock(&pstack_mutex);
255             return;
256         }
257         ps = ps->prev;
258     }
259     rewind(fp);
260     tMPI_Thread_mutex_unlock(&pstack_mutex);
261 }
262
263 int gmx_fseek(FILE *stream, gmx_off_t offset, int whence)
264 {
265 #if HAVE_FSEEKO
266     return fseeko(stream, offset, whence);
267 #else
268 #if HAVE__FSEEKI64
269     return _fseeki64(stream, offset, whence);
270 #else
271     return fseek(stream, offset, whence);
272 #endif
273 #endif
274 }
275
276 gmx_off_t gmx_ftell(FILE *stream)
277 {
278 #if HAVE_FSEEKO
279     return ftello(stream);
280 #else
281 #if HAVE__FSEEKI64
282 #ifndef __MINGW32__
283     return _ftelli64(stream);
284 #else
285     return ftello64(stream);
286 #endif
287 #else
288     return ftell(stream);
289 #endif
290 #endif
291 }
292
293 int gmx_truncate(const char *filename, gmx_off_t length)
294 {
295 #if GMX_NATIVE_WINDOWS
296     FILE *fp = fopen(filename, "rb+");
297     if (fp == NULL)
298     {
299         return -1;
300     }
301 #ifdef _MSC_VER
302     int rc = _chsize_s(fileno(fp), length);
303 #else
304     int rc = _chsize(fileno(fp), length);
305 #endif
306     fclose(fp);
307     return rc;
308 #else
309     return truncate(filename, length);
310 #endif
311 }
312
313 static FILE *uncompress(const char *fn, const char *mode)
314 {
315     FILE *fp;
316     char  buf[256];
317
318     sprintf(buf, "uncompress -c < %s", fn);
319     fprintf(stderr, "Going to execute '%s'\n", buf);
320     if ((fp = popen(buf, mode)) == NULL)
321     {
322         gmx_open(fn);
323     }
324     push_ps(fp);
325
326     return fp;
327 }
328
329 static FILE *gunzip(const char *fn, const char *mode)
330 {
331     FILE *fp;
332     char  buf[256];
333
334     sprintf(buf, "gunzip -c < %s", fn);
335     fprintf(stderr, "Going to execute '%s'\n", buf);
336     if ((fp = popen(buf, mode)) == NULL)
337     {
338         gmx_open(fn);
339     }
340     push_ps(fp);
341
342     return fp;
343 }
344
345 gmx_bool gmx_fexist(const char *fname)
346 {
347     FILE *test;
348
349     if (fname == NULL)
350     {
351         return FALSE;
352     }
353     test = fopen(fname, "r");
354     if (test == NULL)
355     {
356         /*Windows doesn't allow fopen of directory - so we need to check this seperately */
357         #if GMX_NATIVE_WINDOWS
358         DWORD attr = GetFileAttributes(fname);
359         return (attr != INVALID_FILE_ATTRIBUTES) && (attr & FILE_ATTRIBUTE_DIRECTORY);
360         #else
361         return FALSE;
362         #endif
363     }
364     else
365     {
366         fclose(test);
367         return TRUE;
368     }
369 }
370
371 static char *backup_fn(const char *file)
372 {
373     int          i, count = 1;
374     char        *directory, *fn;
375     char        *buf;
376
377     smalloc(buf, GMX_PATH_MAX);
378
379     for (i = strlen(file)-1; ((i > 0) && (file[i] != DIR_SEPARATOR)); i--)
380     {
381         ;
382     }
383     /* Must check whether i > 0, i.e. whether there is a directory
384      * in the file name. In that case we overwrite the / sign with
385      * a '\0' to end the directory string .
386      */
387     if (i > 0)
388     {
389         directory    = gmx_strdup(file);
390         directory[i] = '\0';
391         fn           = gmx_strdup(file+i+1);
392     }
393     else
394     {
395         directory    = gmx_strdup(".");
396         fn           = gmx_strdup(file);
397     }
398     do
399     {
400         sprintf(buf, "%s/#%s.%d#", directory, fn, count);
401         count++;
402     }
403     while ((count <= s_maxBackupCount) && gmx_fexist(buf));
404
405     /* Arbitrarily bail out */
406     if (count > s_maxBackupCount)
407     {
408         /* TODO: The error message is only accurate for code that starts with
409          * Gromacs command-line interface. */
410         gmx_fatal(FARGS, "Won't make more than %d backups of %s for you.\n"
411                   "The env.var. GMX_MAXBACKUP controls this maximum, -1 disables backups.",
412                   s_maxBackupCount, fn);
413     }
414
415     sfree(directory);
416     sfree(fn);
417
418     return buf;
419 }
420
421 void make_backup(const char *name)
422 {
423     if (s_maxBackupCount <= 0)
424     {
425         return;
426     }
427     if (gmx_fexist(name))
428     {
429         char *backup = backup_fn(name);
430         if (rename(name, backup) == 0)
431         {
432             fprintf(stderr, "\nBack Off! I just backed up %s to %s\n",
433                     name, backup);
434         }
435         else
436         {
437             fprintf(stderr, "\nSorry couldn't backup %s to %s\n", name, backup);
438         }
439         sfree(backup);
440     }
441 }
442
443 FILE *gmx_ffopen(const char *file, const char *mode)
444 {
445 #ifdef SKIP_FFOPS
446     return fopen(file, mode);
447 #else
448     FILE    *ff = NULL;
449     char     buf[256], *bufsize = 0, *ptr;
450     gmx_bool bRead;
451     int      bs;
452
453     if (file == NULL)
454     {
455         return NULL;
456     }
457
458     if (mode[0] == 'w')
459     {
460         make_backup(file);
461     }
462     where();
463
464     bRead = (mode[0] == 'r' && mode[1] != '+');
465     strcpy(buf, file);
466     if (!bRead || gmx_fexist(buf))
467     {
468         if ((ff = fopen(buf, mode)) == NULL)
469         {
470             gmx_file(buf);
471         }
472         where();
473         /* Check whether we should be using buffering (default) or not
474          * (for debugging)
475          */
476         if (bUnbuffered || ((bufsize = getenv("GMX_LOG_BUFFER")) != NULL))
477         {
478             /* Check whether to use completely unbuffered */
479             if (bUnbuffered)
480             {
481                 bs = 0;
482             }
483             else
484             {
485                 bs = strtol(bufsize, NULL, 10);
486             }
487             if (bs <= 0)
488             {
489                 setbuf(ff, NULL);
490             }
491             else
492             {
493                 snew(ptr, bs+8);
494                 if (setvbuf(ff, ptr, _IOFBF, bs) != 0)
495                 {
496                     gmx_file("Buffering File");
497                 }
498             }
499         }
500         where();
501     }
502     else
503     {
504         sprintf(buf, "%s.Z", file);
505         if (gmx_fexist(buf))
506         {
507             ff = uncompress(buf, mode);
508         }
509         else
510         {
511             sprintf(buf, "%s.gz", file);
512             if (gmx_fexist(buf))
513             {
514                 ff = gunzip(buf, mode);
515             }
516             else
517             {
518                 gmx_file(file);
519             }
520         }
521     }
522     return ff;
523 #endif
524 }
525
526
527 char *low_gmxlibfn(const char *file, gmx_bool bAddCWD, gmx_bool bFatal)
528 {
529     try
530     {
531         const gmx::DataFileFinder &finder = gmx::getLibraryFileFinder();
532         std::string                result =
533             finder.findFile(gmx::DataFileOptions(file)
534                                 .includeCurrentDir(bAddCWD)
535                                 .throwIfNotFound(bFatal));
536         if (!result.empty())
537         {
538             return gmx_strdup(result.c_str());
539         }
540     }
541     GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR;
542     return NULL;
543 }
544
545 FILE *low_libopen(const char *file, gmx_bool bFatal)
546 {
547     try
548     {
549         const gmx::DataFileFinder &finder = gmx::getLibraryFileFinder();
550         FILE *fp =
551             finder.openFile(gmx::DataFileOptions(file)
552                                 .includeCurrentDir(true)
553                                 .throwIfNotFound(bFatal));
554         return fp;
555     }
556     GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR;
557     return NULL;
558 }
559
560 char *gmxlibfn(const char *file)
561 {
562     return low_gmxlibfn(file, TRUE, TRUE);
563 }
564
565 FILE *libopen(const char *file)
566 {
567     return low_libopen(file, TRUE);
568 }
569
570 void gmx_tmpnam(char *buf)
571 {
572     int i, len;
573
574     if ((len = strlen(buf)) < 7)
575     {
576         gmx_fatal(FARGS, "Buf passed to gmx_tmpnam must be at least 7 bytes long");
577     }
578     for (i = len-6; (i < len); i++)
579     {
580         buf[i] = 'X';
581     }
582     /* mktemp is dangerous and we should use mkstemp instead, but
583      * since windows doesnt support it we have to separate the cases.
584      * 20090307: mktemp deprecated, use iso c++ _mktemp instead.
585      */
586 #if GMX_NATIVE_WINDOWS
587     _mktemp(buf);
588     if (buf == NULL)
589     {
590         gmx_fatal(FARGS, "Error creating temporary file %s: %s", buf,
591                   strerror(errno));
592     }
593 #else
594     int fd = mkstemp(buf);
595
596     if (fd < 0)
597     {
598         gmx_fatal(FARGS, "Error creating temporary file %s: %s", buf,
599                   strerror(errno));
600     }
601     close(fd);
602
603 #endif
604
605     /* name in Buf should now be OK and file is CLOSED */
606
607     return;
608 }
609
610 FILE *gmx_fopen_temporary(char *buf)
611 {
612     int   i, len;
613     FILE *fpout = NULL;
614
615     if ((len = strlen(buf)) < 7)
616     {
617         gmx_fatal(FARGS, "Buf passed to gmx_fopentmp must be at least 7 bytes long");
618     }
619     for (i = len-6; (i < len); i++)
620     {
621         buf[i] = 'X';
622     }
623     /* mktemp is dangerous and we should use mkstemp instead, but
624      * since windows doesnt support it we have to separate the cases.
625      * 20090307: mktemp deprecated, use iso c++ _mktemp instead.
626      */
627 #if GMX_NATIVE_WINDOWS
628     _mktemp(buf);
629     if (buf == NULL)
630     {
631         gmx_fatal(FARGS, "Error creating temporary file %s: %s", buf,
632                   strerror(errno));
633     }
634     if ((fpout = fopen(buf, "w")) == NULL)
635     {
636         gmx_fatal(FARGS, "Cannot open temporary file %s", buf);
637     }
638 #else
639     int fd = mkstemp(buf);
640     if (fd < 0)
641     {
642         gmx_fatal(FARGS, "Error creating temporary file %s: %s", buf,
643                   strerror(errno));
644     }
645     if ((fpout = fdopen(fd, "w")) == NULL)
646     {
647         gmx_fatal(FARGS, "Cannot open temporary file %s", buf);
648     }
649 #endif
650     /* name in Buf should now be OK and file is open */
651
652     return fpout;
653 }
654
655 int gmx_file_rename(const char *oldname, const char *newname)
656 {
657 #if !GMX_NATIVE_WINDOWS
658     /* under unix, rename() is atomic (at least, it should be). */
659     return rename(oldname, newname);
660 #else
661     if (MoveFileEx(oldname, newname,
662                    MOVEFILE_REPLACE_EXISTING|MOVEFILE_WRITE_THROUGH))
663     {
664         return 0;
665     }
666     else
667     {
668         return 1;
669     }
670 #endif
671 }
672
673 int gmx_file_copy(const char *oldname, const char *newname, gmx_bool copy_if_empty)
674 {
675 /* the full copy buffer size: */
676 #define FILECOPY_BUFSIZE (1<<16)
677     FILE *in  = NULL;
678     FILE *out = NULL;
679     char *buf;
680
681     snew(buf, FILECOPY_BUFSIZE);
682
683     in = fopen(oldname, "rb");
684     if (!in)
685     {
686         goto error;
687     }
688
689     /* If we don't copy when empty, we postpone opening the file
690        until we're actually ready to write. */
691     if (copy_if_empty)
692     {
693         out = fopen(newname, "wb");
694         if (!out)
695         {
696             goto error;
697         }
698     }
699
700     while (!feof(in))
701     {
702         size_t nread;
703
704         nread = fread(buf, sizeof(char), FILECOPY_BUFSIZE, in);
705         if (nread > 0)
706         {
707             size_t ret;
708             if (!out)
709             {
710                 /* so this is where we open when copy_if_empty is false:
711                    here we know we read something. */
712                 out = fopen(newname, "wb");
713                 if (!out)
714                 {
715                     goto error;
716                 }
717             }
718             ret = fwrite(buf, sizeof(char), nread, out);
719             if (ret != nread)
720             {
721                 goto error;
722             }
723         }
724         if (ferror(in))
725         {
726             goto error;
727         }
728     }
729     sfree(buf);
730     fclose(in);
731     fclose(out);
732     return 0;
733 error:
734     sfree(buf);
735     if (in)
736     {
737         fclose(in);
738     }
739     if (out)
740     {
741         fclose(out);
742     }
743     return 1;
744 #undef FILECOPY_BUFSIZE
745 }
746
747
748 int gmx_fsync(FILE *fp)
749 {
750     int rc = 0;
751
752 #ifdef GMX_FAHCORE
753     /* the fahcore defines its own os-independent fsync */
754     rc = fah_fsync(fp);
755 #else /* GMX_FAHCORE */
756     {
757         int fn;
758
759         /* get the file number */
760 #if HAVE_FILENO
761         fn = fileno(fp);
762 #elif HAVE__FILENO
763         fn = _fileno(fp);
764 #else
765         fn = -1;
766 #endif
767
768         /* do the actual fsync */
769         if (fn >= 0)
770         {
771 #if HAVE_FSYNC
772             rc = fsync(fn);
773 #elif HAVE__COMMIT
774             rc = _commit(fn);
775 #endif
776         }
777     }
778 #endif /* GMX_FAHCORE */
779
780     /* We check for these error codes this way because POSIX requires them
781        to be defined, and using anything other than macros is unlikely: */
782 #ifdef EINTR
783     /* we don't want to report an error just because fsync() caught a signal.
784        For our purposes, we can just ignore this. */
785     if (rc && errno == EINTR)
786     {
787         rc = 0;
788     }
789 #endif
790 #ifdef EINVAL
791     /* we don't want to report an error just because we tried to fsync()
792        stdout, a socket or a pipe. */
793     if (rc && errno == EINVAL)
794     {
795         rc = 0;
796     }
797 #endif
798     return rc;
799 }
800
801 void gmx_chdir(const char *directory)
802 {
803 #if GMX_NATIVE_WINDOWS
804     int rc = _chdir(directory);
805 #else
806     int rc = chdir(directory);
807 #endif
808     if (rc != 0)
809     {
810         gmx_fatal(FARGS, "Cannot change directory to '%s'. Reason: %s",
811                   directory, strerror(errno));
812     }
813 }
814
815 void gmx_getcwd(char *buffer, size_t size)
816 {
817 #if GMX_NATIVE_WINDOWS
818     char *pdum = _getcwd(buffer, size);
819 #else
820     char *pdum = getcwd(buffer, size);
821 #endif
822     if (pdum == NULL)
823     {
824         gmx_fatal(FARGS, "Cannot get working directory. Reason: %s",
825                   strerror(errno));
826     }
827 }