Revised wording in pdb2gmx.c, hopefully clearer now.
[gromacs/rigid-bodies.git] / src / gmxlib / gmxfio.c
blobe83788d870ac83321ee78ea4fc77a642e185470f
1 /* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
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.
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.
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.
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.
31 * For more info, check our website at http://www.gromacs.org
33 * And Hey:
34 * GROningen Mixture of Alchemy and Childrens' Stories
36 #ifdef HAVE_CONFIG_H
37 #include <config.h>
38 #endif
40 #include <ctype.h>
41 #include <stdio.h>
42 #include <errno.h>
43 #ifdef HAVE_IO_H
44 #include <io.h>
45 #endif
47 #include "gmx_fatal.h"
48 #include "macros.h"
49 #include "smalloc.h"
50 #include "futil.h"
51 #include "filenm.h"
52 #include "string2.h"
53 #include "gmxfio.h"
54 #include "md5.h"
56 #ifdef GMX_THREADS
57 #include "thread_mpi.h"
58 #endif
60 #include "gmxfio_int.h"
62 /* This is the new improved and thread safe version of gmxfio. */
66 /* the list of open files is a linked list, with a dummy element at its head;
67 it is initialized when the first file is opened. */
68 static t_fileio *open_files = NULL;
71 #ifdef GMX_THREADS
72 /* this mutex locks the open_files structure so that no two threads can
73 modify it.
75 For now, we use this as a coarse grained lock on all file
76 insertion/deletion operations because it makes avoiding deadlocks
77 easier, and adds almost no overhead: the only overhead is during
78 opening and closing of files, or during global operations like
79 iterating along all open files. All these cases should be rare
80 during the simulation. */
81 static tMPI_Thread_mutex_t open_file_mutex=TMPI_THREAD_MUTEX_INITIALIZER;
82 #endif
85 /* These simple lists define the I/O type for these files */
86 static const int ftpXDR[] =
87 { efTPR, efTRR, efEDR, efXTC, efMTX, efCPT };
88 static const int ftpASC[] =
89 { efTPA, efGRO, efPDB };
90 static const int ftpBIN[] =
91 { efTPB, efTRJ };
92 #ifdef HAVE_XML
93 static const int ftpXML[] =
94 { efXML};
95 #endif
97 const char *itemstr[eitemNR] =
98 { "[header]", "[inputrec]", "[box]", "[topology]", "[coordinates]",
99 "[velocities]", "[forces]" };
101 const char *eioNames[eioNR] =
102 { "REAL", "INT", "GMX_STE_T", "UCHAR", "NUCHAR", "USHORT", "RVEC", "NRVEC",
103 "IVEC", "STRING" };
107 /* Comment strings for TPA only */
108 const char *comment_str[eitemNR] = {
109 "; The header holds information on the number of atoms etc. and on whether\n"
110 "; certain items are present in the file or not.\n"
111 "; \n"
112 "; WARNING\n"
113 "; DO NOT EDIT THIS FILE BY HAND\n"
114 "; The GROMACS preprocessor performs a lot of checks on your input that\n"
115 "; you ignore when editing this. Your simulation may crash because of this\n",
116 "; The inputrec holds the parameters for MD such as the number of steps,\n"
117 "; the timestep and the cut-offs.\n",
118 "; The simulation box in nm.\n",
119 "; The topology section describes the topology of the molecules\n"
120 "; i.e. bonds, angles and dihedrals etc. and also holds the force field\n"
121 "; parameters.\n",
122 "; The atomic coordinates in nm\n",
123 "; The atomic velocities in nm/ps\n",
124 "; The forces on the atoms in nm/ps^2\n" };
129 /******************************************************************
131 * Internal functions:
133 ******************************************************************/
135 static int gmx_fio_int_flush(t_fileio* fio)
137 int rc = 0;
139 if (fio->fp)
141 rc = fflush(fio->fp);
143 else if (fio->xdr)
145 rc = fflush((FILE *) fio->xdr->x_private);
148 return rc;
151 /* returns TRUE if the file type ftp is in the set set */
152 static gmx_bool in_ftpset(int ftp, int nset, const int set[])
154 int i;
155 gmx_bool bResult;
157 bResult = FALSE;
158 for (i = 0; (i < nset); i++)
159 if (ftp == set[i])
160 bResult = TRUE;
162 return bResult;
167 extern void gmx_fio_set_comment(t_fileio *fio, const char *comment)
169 fio->comment=comment;
172 extern void gmx_fio_unset_comment(t_fileio *fio)
174 fio->comment=NULL;
178 const char *gmx_fio_dbgstr(t_fileio *fio, const char *desc, char *buf)
180 if (!fio->bDebug)
182 /* set to empty string */
183 buf[0]=0;
185 else
187 snprintf(buf, GMX_FIO_BUFLEN, " ; %s %s", fio->comment ? fio->comment : "", desc);
189 return buf;
193 /* check the number of items given against the type */
194 void gmx_fio_check_nitem(t_fileio *fio, int eio, int nitem, const char *file,
195 int line)
197 if ((nitem != 1) && !((eio == eioNRVEC) || (eio == eioNUCHAR)))
198 gmx_fatal(FARGS,
199 "nitem (%d) may differ from 1 only for %s or %s, not for %s"
200 "(%s, %d)",nitem,eioNames[eioNUCHAR],eioNames[eioNRVEC],
201 eioNames[eio],file,line);
205 /* output a data type error. */
206 void gmx_fio_fe(t_fileio *fio, int eio, const char *desc,
207 const char *srcfile, int line)
210 gmx_fatal(FARGS, "Trying to %s %s type %d (%s), src %s, line %d",
211 fio->bRead ? "read" : "write",desc,eio,
212 ((eio >= 0) && (eio < eioNR)) ? eioNames[eio] : "unknown",
213 srcfile,line);
217 /* set the reader/writer functions based on the file type */
218 static void gmx_fio_set_iotype(t_fileio *fio)
220 if (in_ftpset(fio->iFTP, asize(ftpXDR), ftpXDR))
222 #ifdef USE_XDR
223 fio->iotp=&xdr_iotype;
224 #else
225 gmx_fatal(FARGS,"Sorry, no XDR");
226 #endif
228 else if (in_ftpset(fio->iFTP, asize(ftpASC), ftpASC))
230 fio->iotp=&asc_iotype;
232 else if (in_ftpset(fio->iFTP, asize(ftpBIN), ftpBIN))
234 fio->iotp=&bin_iotype;
236 #ifdef HAVE_XMl
237 else if (in_ftpset(fio->iFTP,asize(ftpXML),ftpXML))
239 fio->iotp=&dummy_iotype;
241 #endif
242 else
243 fio->iotp=&dummy_iotype;
247 /* lock the mutex associated with this fio. This needs to be done for every
248 type of access to the fio's elements. */
249 void gmx_fio_lock(t_fileio *fio)
251 #ifdef GMX_THREADS
252 tMPI_Lock_lock(&(fio->mtx));
253 #endif
255 /* unlock the mutex associated with this fio. */
256 void gmx_fio_unlock(t_fileio *fio)
258 #ifdef GMX_THREADS
259 tMPI_Lock_unlock(&(fio->mtx));
260 #endif
263 /* make a dummy head element, assuming we locked everything. */
264 static void gmx_fio_make_dummy(void)
266 if (!open_files)
268 snew(open_files,1);
269 open_files->fp=NULL;
270 open_files->fn=NULL;
271 open_files->next=open_files;
272 open_files->prev=open_files;
273 #ifdef GMX_THREADS
274 tMPI_Lock_init(&(open_files->mtx));
275 #endif
285 /***********************************************************************
287 * FILE LIST OPERATIONS
289 ***********************************************************************/
292 /* insert a new t_fileio into the list */
293 static void gmx_fio_insert(t_fileio *fio)
295 t_fileio *prev;
296 #ifdef GMX_THREADS
297 /* first lock the big open_files mutex. */
298 tMPI_Thread_mutex_lock(&open_file_mutex);
299 #endif
300 /* now check whether the dummy element has been allocated,
301 and allocate it if it hasn't */
302 gmx_fio_make_dummy();
304 /* and lock the fio we got and the list's head **/
305 gmx_fio_lock(fio);
306 gmx_fio_lock(open_files);
307 prev=open_files->prev;
308 /* lock the element after the current one */
309 if (prev != open_files)
311 gmx_fio_lock(prev);
314 /* now do the actual insertion: */
315 fio->next=open_files;
316 open_files->prev=fio;
317 prev->next=fio;
318 fio->prev=prev;
320 /* now unlock all our locks */
321 if (prev != open_files)
323 gmx_fio_unlock(prev);
325 gmx_fio_unlock(open_files);
326 gmx_fio_unlock(fio);
328 #ifdef GMX_THREADS
329 /* now unlock the big open_files mutex. */
330 tMPI_Thread_mutex_unlock(&open_file_mutex);
331 #endif
334 /* remove a t_fileio into the list. We assume the fio is locked, and we leave
335 it locked.
336 NOTE: We also assume that the open_file_mutex has been locked */
337 static void gmx_fio_remove(t_fileio *fio)
339 t_fileio *prev;
341 /* lock prev, because we're changing it */
342 gmx_fio_lock(fio->prev);
344 /* now set the prev's pointer */
345 fio->prev->next=fio->next;
346 gmx_fio_unlock(fio->prev);
348 /* with the next ptr, we can simply lock while the original was locked */
349 gmx_fio_lock(fio->next);
350 fio->next->prev=fio->prev;
351 gmx_fio_unlock(fio->next);
353 /* and make sure we point nowhere in particular */
354 fio->next=fio->prev=fio;
358 /* get the first open file, or NULL if there is none.
359 Returns a locked fio. */
360 static t_fileio *gmx_fio_get_first(void)
362 t_fileio *ret;
363 /* first lock the big open_files mutex and the dummy's mutex */
365 #ifdef GMX_THREADS
366 /* first lock the big open_files mutex. */
367 tMPI_Thread_mutex_lock(&open_file_mutex);
368 #endif
369 gmx_fio_make_dummy();
371 gmx_fio_lock(open_files);
372 ret=open_files->next;
375 /* check whether there were any to begin with */
376 if (ret==open_files)
378 /* after this, the open_file pointer should never change */
379 ret=NULL;
381 else
383 gmx_fio_lock(open_files->next);
385 gmx_fio_unlock(open_files);
388 return ret;
391 /* get the next open file, or NULL if there is none.
392 Unlocks the previous fio and locks the next one. */
393 static t_fileio *gmx_fio_get_next(t_fileio *fio)
395 t_fileio *ret;
397 ret=fio->next;
398 /* check if that was the last one */
399 if (fio->next==open_files)
401 ret=NULL;
402 #ifdef GMX_THREADS
403 tMPI_Thread_mutex_unlock(&open_file_mutex);
404 #endif
406 else
408 gmx_fio_lock(ret);
410 gmx_fio_unlock(fio);
412 return ret;
415 /* Stop looping through the open_files. Unlocks the global lock. */
416 static void gmx_fio_stop_getting_next(t_fileio *fio)
418 gmx_fio_unlock(fio);
419 #ifdef GMX_THREADS
420 tMPI_Thread_mutex_unlock(&open_file_mutex);
421 #endif
427 /*****************************************************************
429 * EXPORTED SECTION
431 *****************************************************************/
432 t_fileio *gmx_fio_open(const char *fn, const char *mode)
434 t_fileio *fio = NULL;
435 int i;
436 char newmode[5];
437 gmx_bool bRead, bReadWrite;
438 int xdrid;
440 if (fn2ftp(fn) == efTPA)
442 strcpy(newmode, mode);
444 else
446 /* sanitize the mode string */
447 if (strncmp(mode, "r+", 2) == 0)
449 strcpy(newmode, "r+");
451 else if (mode[0] == 'r')
453 strcpy(newmode, "r");
455 else if (strncmp(mode, "w+", 2) == 0)
457 strcpy(newmode, "w+");
459 else if (mode[0] == 'w')
461 strcpy(newmode, "w");
463 else if (strncmp(mode, "a+", 2) == 0)
465 strcpy(newmode, "a+");
467 else if (mode[0] == 'a')
469 strcpy(newmode, "a");
471 else
473 gmx_fatal(FARGS, "DEATH HORROR in gmx_fio_open, mode is '%s'",mode);
477 /* Check if it should be opened as a binary file */
478 if (strncmp(ftp2ftype(fn2ftp(fn)),"ASCII",5))
480 /* Not ascii, add b to file mode */
481 if ((strchr(newmode,'b')==NULL) && (strchr(newmode,'B')==NULL))
483 strcat(newmode,"b");
487 snew(fio, 1);
488 #ifdef GMX_THREADS
489 tMPI_Lock_init(&(fio->mtx));
490 #endif
491 bRead = (newmode[0]=='r' && newmode[1]!='+');
492 bReadWrite = (newmode[1]=='+');
493 fio->fp = NULL;
494 fio->xdr = NULL;
495 if (fn)
497 fio->iFTP = fn2ftp(fn);
498 fio->fn = strdup(fn);
499 fio->bStdio = FALSE;
501 /* If this file type is in the list of XDR files, open it like that */
502 if (in_ftpset(fio->iFTP,asize(ftpXDR),ftpXDR))
504 /* First check whether we have to make a backup,
505 * only for writing, not for read or append.
507 if (newmode[0]=='w')
509 #ifndef GMX_FAHCORE
510 /* only make backups for normal gromacs */
511 make_backup(fn);
512 #endif
514 else
516 /* Check whether file exists */
517 if (!gmx_fexist(fn))
519 gmx_open(fn);
522 /* Open the file */
523 fio->fp = ffopen(fn,newmode);
525 /* determine the XDR direction */
526 if (newmode[0] == 'w' || newmode[0]=='a')
528 fio->xdrmode=XDR_ENCODE;
530 else
532 fio->xdrmode=XDR_DECODE;
535 snew(fio->xdr,1);
536 xdrstdio_create(fio->xdr, fio->fp, fio->xdrmode);
538 else
540 /* If it is not, open it as a regular file */
541 fio->fp = ffopen(fn,newmode);
544 else
546 /* Use stdin/stdout for I/O */
547 fio->iFTP = efTPA;
548 fio->fp = bRead ? stdin : stdout;
549 fio->fn = strdup("STDIO");
550 fio->bStdio = TRUE;
552 fio->bRead = bRead;
553 fio->bReadWrite = bReadWrite;
554 fio->bDouble= (sizeof(real) == sizeof(double));
555 fio->bDebug = FALSE;
556 fio->bOpen = TRUE;
557 fio->bLargerThan_off_t = FALSE;
559 /* set the reader/writer functions */
560 gmx_fio_set_iotype(fio);
562 /* and now insert this file into the list of open files. */
563 gmx_fio_insert(fio);
564 return fio;
567 static int gmx_fio_close_locked(t_fileio *fio)
569 int rc = 0;
571 if (!fio->bOpen)
573 gmx_fatal(FARGS,"File %s closed twice!\n", fio->fn);
576 if (in_ftpset(fio->iFTP, asize(ftpXDR), ftpXDR))
578 xdr_destroy(fio->xdr);
579 sfree(fio->xdr);
582 /* Don't close stdin and stdout! */
583 if (!fio->bStdio && fio->fp!=NULL)
584 rc = ffclose(fio->fp); /* fclose returns 0 if happy */
586 fio->bOpen = FALSE;
588 return rc;
591 int gmx_fio_close(t_fileio *fio)
593 int rc = 0;
595 #ifdef GMX_THREADS
596 /* first lock the big open_files mutex. */
597 /* We don't want two processes operating on the list at the same time */
598 tMPI_Thread_mutex_lock(&open_file_mutex);
599 #endif
601 gmx_fio_lock(fio);
602 /* first remove it from the list */
603 gmx_fio_remove(fio);
604 rc=gmx_fio_close_locked(fio);
605 gmx_fio_unlock(fio);
607 sfree(fio);
609 #ifdef GMX_THREADS
610 tMPI_Thread_mutex_unlock(&open_file_mutex);
611 #endif
613 return rc;
616 /* close only fp but keep FIO entry. */
617 int gmx_fio_fp_close(t_fileio *fio)
619 int rc=0;
620 gmx_fio_lock(fio);
621 if (!in_ftpset(fio->iFTP,asize(ftpXDR),ftpXDR) && !fio->bStdio)
623 rc = ffclose(fio->fp); /* fclose returns 0 if happy */
624 fio->fp = NULL;
626 gmx_fio_unlock(fio);
628 return rc;
631 FILE * gmx_fio_fopen(const char *fn, const char *mode)
633 FILE *fp, *ret;
634 t_fileio *fio;
636 fio = gmx_fio_open(fn, mode);
637 gmx_fio_lock(fio);
638 ret = fio->fp;
639 gmx_fio_unlock(fio);
641 return ret;
644 int gmx_fio_fclose(FILE *fp)
646 t_fileio *cur;
647 t_fileio *found=NULL;
648 int rc=-1;
650 cur=gmx_fio_get_first();
651 while(cur)
653 if (cur->fp == fp)
655 rc=gmx_fio_close_locked(cur);
656 gmx_fio_remove(cur);
657 gmx_fio_stop_getting_next(cur);
658 break;
660 cur=gmx_fio_get_next(cur);
663 return rc;
666 /* internal variant of get_file_md5 that operates on a locked file */
667 static int gmx_fio_int_get_file_md5(t_fileio *fio, gmx_off_t offset,
668 unsigned char digest[])
670 /*1MB: large size important to catch almost identical files */
671 #define CPT_CHK_LEN 1048576
672 md5_state_t state;
673 unsigned char buf[CPT_CHK_LEN];
674 gmx_off_t read_len;
675 gmx_off_t seek_offset;
676 int ret = -1;
678 seek_offset = offset - CPT_CHK_LEN;
679 if (seek_offset < 0)
681 seek_offset = 0;
683 read_len = offset - seek_offset;
686 if (fio->fp && fio->bReadWrite)
688 ret=gmx_fseek(fio->fp, seek_offset, SEEK_SET);
689 if (ret)
691 gmx_fseek(fio->fp, 0, SEEK_END);
694 if (ret) /*either no fp, not readwrite, or fseek not successful */
696 return -1;
699 /* the read puts the file position back to offset */
700 if ((gmx_off_t)fread(buf, 1, read_len, fio->fp) != read_len)
702 /* not fatal: md5sum check to prevent overwriting files
703 * works (less safe) without
704 * */
705 if (ferror(fio->fp))
707 fprintf(stderr, "\nTrying to get md5sum: %s: %s\n", fio->fn,
708 strerror(errno));
710 else if (feof(fio->fp))
713 * For long runs that checkpoint frequently but write e.g. logs
714 * infrequently we don't want to issue lots of warnings before we
715 * have written anything to the log.
717 if(0)
719 fprintf(stderr, "\nTrying to get md5sum: EOF: %s\n", fio->fn);
722 else
724 fprintf(
725 stderr,
726 "\nTrying to get md5sum: Unknown reason for short read: %s\n",
727 fio->fn);
730 gmx_fseek(fio->fp, 0, SEEK_END);
732 ret = -1;
734 gmx_fseek(fio->fp, 0, SEEK_END); /*is already at end, but under windows
735 it gives problems otherwise*/
737 if (debug)
739 fprintf(debug, "chksum %s readlen %ld\n", fio->fn, (long int)read_len);
742 if (!ret)
744 md5_init(&state);
745 md5_append(&state, buf, read_len);
746 md5_finish(&state, digest);
747 return read_len;
749 else
751 return ret;
757 * fio: file to compute md5 for
758 * offset: starting pointer of region to use for md5
759 * digest: return array of md5 sum
761 int gmx_fio_get_file_md5(t_fileio *fio, gmx_off_t offset,
762 unsigned char digest[])
764 int ret;
766 gmx_fio_lock(fio);
767 ret=gmx_fio_int_get_file_md5(fio, offset, digest);
768 gmx_fio_unlock(fio);
770 return ret;
773 /* The fio_mutex should ALWAYS be locked when this function is called */
774 static int gmx_fio_int_get_file_position(t_fileio *fio, gmx_off_t *offset)
776 char buf[STRLEN];
778 /* Flush the file, so we are sure it is written */
779 if (gmx_fio_int_flush(fio))
781 char buf[STRLEN];
782 sprintf(
783 buf,
784 "Cannot write file '%s'; maybe you are out of disk space or quota?",
785 fio->fn);
786 gmx_file(buf);
789 /* We cannot count on XDR being able to write 64-bit integers,
790 so separate into high/low 32-bit values.
791 In case the filesystem has 128-bit offsets we only care
792 about the first 64 bits - we'll have to fix
793 this when exabyte-size output files are common...
795 *offset=gmx_ftell(fio->fp);
797 return 0;
800 int gmx_fio_check_file_position(t_fileio *fio)
802 /* If gmx_off_t is 4 bytes we can not store file offset > 2 GB.
803 * If we do not have ftello, we will play it safe.
805 #if (SIZEOF_GMX_OFF_T == 4 || !defined HAVE_FSEEKO)
806 gmx_off_t offset;
808 gmx_fio_lock(fio);
809 gmx_fio_int_get_file_position(fio,&offset);
810 /* We have a 4 byte offset,
811 * make sure that we will detect out of range for all possible cases.
813 if (offset < 0 || offset > 2147483647)
815 fio->bLargerThan_off_t = TRUE;
817 gmx_fio_unlock(fio);
818 #endif
820 return 0;
823 int gmx_fio_get_output_file_positions(gmx_file_position_t **p_outputfiles,
824 int *p_nfiles)
826 int i, nfiles, rc, nalloc;
827 int pos_hi, pos_lo;
828 long pos;
829 gmx_file_position_t * outputfiles;
830 char buf[STRLEN];
831 t_fileio *cur;
833 nfiles = 0;
835 /* pre-allocate 100 files */
836 nalloc = 100;
837 snew(outputfiles,nalloc);
839 cur=gmx_fio_get_first();
840 while(cur)
842 /* Skip the checkpoint files themselves, since they could be open when
843 we call this routine... */
844 /* also skip debug files (shoud be the only iFTP==efNR) */
845 if (cur->bOpen &&
846 !cur->bRead &&
847 !cur->bStdio &&
848 cur->iFTP != efCPT &&
849 cur->iFTP != efNR)
851 int ret;
852 /* This is an output file currently open for writing, add it */
853 if (nfiles == nalloc)
855 nalloc += 100;
856 srenew(outputfiles,nalloc);
859 strncpy(outputfiles[nfiles].filename, cur->fn, STRLEN - 1);
861 /* Get the file position */
862 if (cur->bLargerThan_off_t)
864 /* -1 signals out of range */
865 outputfiles[nfiles].offset = -1;
866 outputfiles[nfiles].chksum_size = -1;
868 else
870 gmx_fio_int_get_file_position(cur, &outputfiles[nfiles].offset);
871 #ifndef GMX_FAHCORE
872 outputfiles[nfiles].chksum_size
873 = gmx_fio_int_get_file_md5(cur,
874 outputfiles[nfiles].offset,
875 outputfiles[nfiles].chksum);
876 #endif
879 nfiles++;
882 cur=gmx_fio_get_next(cur);
884 *p_nfiles = nfiles;
885 *p_outputfiles = outputfiles;
887 return 0;
891 void gmx_fio_checktype(t_fileio *fio)
893 if (in_ftpset(fio->iFTP, asize(ftpXDR), ftpXDR))
895 return;
897 else if (in_ftpset(fio->iFTP, asize(ftpASC), ftpASC))
899 return;
901 else if (in_ftpset(fio->iFTP, asize(ftpBIN), ftpBIN))
903 return;
905 #ifdef HAVE_XMl
906 else if (in_ftpset(fio->iFTP,asize(ftpXML),ftpXML))
908 return;
910 #endif
911 else
912 gmx_fatal(FARGS, "Can not read/write topologies to file type %s",
913 ftp2ext(fio->iFTP));
918 void gmx_fio_setprecision(t_fileio *fio, gmx_bool bDouble)
920 gmx_fio_lock(fio);
921 fio->bDouble = bDouble;
922 gmx_fio_unlock(fio);
925 gmx_bool gmx_fio_getdebug(t_fileio *fio)
927 gmx_bool ret;
929 gmx_fio_lock(fio);
930 ret = fio->bDebug;
931 gmx_fio_unlock(fio);
933 return ret;
936 void gmx_fio_setdebug(t_fileio *fio, gmx_bool bDebug)
938 gmx_fio_lock(fio);
939 fio->bDebug = bDebug;
940 gmx_fio_unlock(fio);
943 char *gmx_fio_getname(t_fileio *fio)
945 char *ret;
946 gmx_fio_lock(fio);
947 ret = fio->fn;
948 gmx_fio_unlock(fio);
950 return ret;
953 int gmx_fio_getftp(t_fileio* fio)
955 int ret;
957 gmx_fio_lock(fio);
958 ret = fio->iFTP;
959 gmx_fio_unlock(fio);
961 return ret;
964 void gmx_fio_rewind(t_fileio* fio)
966 gmx_fio_lock(fio);
968 if (fio->xdr)
970 xdr_destroy(fio->xdr);
971 frewind(fio->fp);
972 xdrstdio_create(fio->xdr, fio->fp, fio->xdrmode);
974 else
976 frewind(fio->fp);
978 gmx_fio_unlock(fio);
982 int gmx_fio_flush(t_fileio* fio)
984 int ret;
986 gmx_fio_lock(fio);
987 ret=gmx_fio_int_flush(fio);
988 gmx_fio_unlock(fio);
990 return ret;
995 static int gmx_fio_int_fsync(t_fileio *fio)
997 int rc = 0;
998 int filen=-1;
1001 if (fio->fp)
1003 rc=gmx_fsync(fio->fp);
1005 else if (fio->xdr) /* this should normally not happen */
1007 rc=gmx_fsync((FILE*) fio->xdr->x_private);
1008 /* ^ is this actually OK? */
1011 return rc;
1015 int gmx_fio_fsync(t_fileio *fio)
1017 int rc;
1019 gmx_fio_lock(fio);
1020 rc=gmx_fio_int_fsync(fio);
1021 gmx_fio_unlock(fio);
1023 return rc;
1028 t_fileio *gmx_fio_all_output_fsync(void)
1030 t_fileio *ret=NULL;
1031 t_fileio *cur;
1033 cur=gmx_fio_get_first();
1034 while(cur)
1036 /* skip debug files (shoud be the only iFTP==efNR) */
1037 if (cur->bOpen &&
1038 !cur->bRead &&
1039 !cur->bStdio &&
1040 cur->iFTP != efNR)
1042 /* if any of them fails, return failure code */
1043 int rc=gmx_fio_int_fsync(cur);
1044 if (rc != 0 && !ret)
1046 ret=cur;
1049 cur=gmx_fio_get_next(cur);
1052 /* in addition, we force these to be written out too, if they're being
1053 redirected. We don't check for errors because errors most likely mean
1054 that they're not redirected. */
1055 fflush(stdout);
1056 fflush(stderr);
1057 #if (defined(HAVE_FSYNC))
1058 /* again, fahcore defines HAVE_FSYNC and fsync() */
1059 fsync(STDOUT_FILENO);
1060 fsync(STDERR_FILENO);
1061 #endif
1063 return ret;
1067 gmx_off_t gmx_fio_ftell(t_fileio* fio)
1069 gmx_off_t ret = 0;
1071 gmx_fio_lock(fio);
1072 if (fio->fp)
1073 ret = gmx_ftell(fio->fp);
1074 gmx_fio_unlock(fio);
1075 return ret;
1078 int gmx_fio_seek(t_fileio* fio, gmx_off_t fpos)
1080 int rc;
1082 gmx_fio_lock(fio);
1083 if (fio->fp)
1085 rc = gmx_fseek(fio->fp, fpos, SEEK_SET);
1087 else
1089 gmx_file(fio->fn);
1090 rc = -1;
1092 gmx_fio_unlock(fio);
1093 return rc;
1096 FILE *gmx_fio_getfp(t_fileio *fio)
1098 FILE *ret = NULL;
1100 gmx_fio_lock(fio);
1101 if (fio->fp)
1102 ret = fio->fp;
1103 gmx_fio_unlock(fio);
1104 return ret;
1107 XDR *gmx_fio_getxdr(t_fileio* fio)
1109 XDR *ret = NULL;
1111 gmx_fio_lock(fio);
1112 if (fio->xdr)
1113 ret = fio->xdr;
1114 gmx_fio_unlock(fio);
1116 return ret;
1119 gmx_bool gmx_fio_getread(t_fileio* fio)
1121 gmx_bool ret;
1123 gmx_fio_lock(fio);
1124 ret = fio->bRead;
1125 gmx_fio_unlock(fio);
1127 return ret;
1130 int xtc_seek_frame(t_fileio *fio, int frame, int natoms)
1132 int ret;
1134 gmx_fio_lock(fio);
1135 ret=xdr_xtc_seek_frame(frame, fio->fp, fio->xdr, natoms);
1136 gmx_fio_unlock(fio);
1138 return ret;
1141 int xtc_seek_time(t_fileio *fio, real time, int natoms)
1143 int ret;
1145 gmx_fio_lock(fio);
1146 ret=xdr_xtc_seek_time(time, fio->fp, fio->xdr, natoms);
1147 gmx_fio_unlock(fio);
1149 return ret;