1 /* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
4 * This source code is part of
8 * GROningen MAchine for Chemical Simulations
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
34 * GROningen Mixture of Alchemy and Childrens' Stories
43 #include <sys/types.h>
47 #if ((defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64) && !defined __CYGWIN__ && !defined __CYGWIN32__)
56 #include "gmx_fatal.h"
61 #include "thread_mpi.h"
64 /* Windows file stuff, only necessary for visual studio */
69 /* we keep a linked list of all files opened through pipes (i.e.
70 compressed or .gzipped files. This way we can distinguish between them
71 without having to change the semantics of reading from/writing to files)
73 typedef struct t_pstack
{
75 struct t_pstack
*prev
;
78 static t_pstack
*pstack
=NULL
;
79 static bool bUnbuffered
=FALSE
;
82 /* this linked list is an intrinsically globally shared object, so we have
83 to protect it with mutexes */
84 static tMPI_Thread_mutex_t pstack_mutex
=TMPI_THREAD_MUTEX_INITIALIZER
;
92 void push_ps(FILE *fp
)
97 tMPI_Thread_mutex_lock(&pstack_mutex
);
105 tMPI_Thread_mutex_unlock(&pstack_mutex
);
110 /* don't use pipes!*/
111 #define popen fah_fopen
112 #define pclose fah_fclose
122 static FILE *popen(const char *nm
,const char *mode
)
124 gmx_impl("Sorry no pipes...");
129 static int pclose(FILE *fp
)
131 gmx_impl("Sorry no pipes...");
138 int ffclose(FILE *fp
)
146 tMPI_Thread_mutex_lock(&pstack_mutex
);
154 else if (ps
->fp
== fp
) {
161 while ((ps
->prev
!= NULL
) && (ps
->prev
->fp
!= fp
))
163 if (ps
->prev
->fp
== fp
) {
164 if (ps
->prev
->fp
!= NULL
)
165 ret
= pclose(ps
->prev
->fp
);
167 ps
->prev
=ps
->prev
->prev
;
176 tMPI_Thread_mutex_unlock(&pstack_mutex
);
187 void frewind(FILE *fp
)
191 tMPI_Thread_mutex_lock(&pstack_mutex
);
197 fprintf(stderr
,"Cannot rewind compressed file!\n");
199 tMPI_Thread_mutex_unlock(&pstack_mutex
);
207 tMPI_Thread_mutex_unlock(&pstack_mutex
);
211 bool is_pipe(FILE *fp
)
215 tMPI_Thread_mutex_lock(&pstack_mutex
);
222 tMPI_Thread_mutex_unlock(&pstack_mutex
);
229 tMPI_Thread_mutex_unlock(&pstack_mutex
);
235 static FILE *uncompress(const char *fn
,const char *mode
)
240 sprintf(buf
,"uncompress -c < %s",fn
);
241 fprintf(stderr
,"Going to execute '%s'\n",buf
);
242 if ((fp
=popen(buf
,mode
)) == NULL
)
249 static FILE *gunzip(const char *fn
,const char *mode
)
254 sprintf(buf
,"gunzip -c < %s",fn
);
255 fprintf(stderr
,"Going to execute '%s'\n",buf
);
256 if ((fp
=popen(buf
,mode
)) == NULL
)
263 bool gmx_fexist(const char *fname
)
269 test
=fopen(fname
,"r");
279 bool gmx_fexist_master(const char *fname
, t_commrec
*cr
)
285 bExist
= gmx_fexist(fname
);
289 gmx_bcast(sizeof(bExist
),&bExist
,cr
);
294 bool gmx_eof(FILE *fp
)
302 if ((beof
=fread(data
,1,1,fp
))==1)
303 fseek(fp
,-1,SEEK_CUR
);
308 char *backup_fn(const char *file
)
310 /* Use a reasonably low value for countmax; we might
311 * generate 4-5 files in each round, and we dont
312 * want to hit directory limits of 1024 or 2048 files.
319 smalloc(buf
, GMX_PATH_MAX
);
321 for(i
=strlen(file
)-1; ((i
> 0) && (file
[i
] != '/')); i
--)
323 /* Must check whether i > 0, i.e. whether there is a directory
324 * in the file name. In that case we overwrite the / sign with
325 * a '\0' to end the directory string .
328 directory
= strdup(file
);
330 fn
= strdup(file
+i
+1);
333 directory
= strdup(".");
337 sprintf(buf
,"%s/#%s.%d#",directory
,fn
,count
);
339 } while ((count
< COUNTMAX
) && gmx_fexist(buf
));
341 /* Arbitrarily bail out */
342 if (count
== COUNTMAX
)
343 gmx_fatal(FARGS
,"Won't make more than %d backups of %s for you",
352 bool make_backup(const char * name
)
357 return FALSE
; /* skip making backups */
360 if(gmx_fexist(name
)) {
361 backup
= backup_fn(name
);
362 if(rename(name
, backup
) == 0) {
363 fprintf(stderr
, "\nBack Off! I just backed up %s to %s\n",
366 fprintf(stderr
, "Sorry couldn't backup %s to %s\n", name
, backup
);
375 FILE *ffopen(const char *file
,const char *mode
)
378 return fopen(file
,mode
);
381 char buf
[256],*bf
,*bufsize
=0,*ptr
;
390 bRead
= (mode
[0]=='r'&&mode
[1]!='+');
392 if (gmx_fexist(buf
) || !bRead
) {
393 if ((ff
=fopen(buf
,mode
))==NULL
)
396 /* Check whether we should be using buffering (default) or not
399 if (bUnbuffered
|| ((bufsize
=getenv("LOG_BUFS")) != NULL
)) {
400 /* Check whether to use completely unbuffered */
404 bs
=strtol(bufsize
, NULL
, 10);
409 if (setvbuf(ff
,ptr
,_IOFBF
,bs
) != 0)
410 gmx_file("Buffering File");
416 sprintf(buf
,"%s.Z",file
);
417 if (gmx_fexist(buf
)) {
418 ff
=uncompress(buf
,mode
);
421 sprintf(buf
,"%s.gz",file
);
422 if (gmx_fexist(buf
)) {
434 bool search_subdirs(const char *parent
, char *libdir
)
439 /* Search a few common subdirectory names for the gromacs library dir */
440 sprintf(libdir
,"%s%cshare%ctop%cgurgle.dat",parent
,
441 DIR_SEPARATOR
,DIR_SEPARATOR
,DIR_SEPARATOR
);
442 found
=gmx_fexist(libdir
);
444 sprintf(libdir
,"%s%cshare%cgromacs%ctop%cgurgle.dat",parent
,
445 DIR_SEPARATOR
,DIR_SEPARATOR
,
446 DIR_SEPARATOR
,DIR_SEPARATOR
);
447 found
=gmx_fexist(libdir
);
450 sprintf(libdir
,"%s%cshare%cgromacs-%s%ctop%cgurgle.dat",parent
,
451 DIR_SEPARATOR
,DIR_SEPARATOR
,VERSION
,
452 DIR_SEPARATOR
,DIR_SEPARATOR
);
453 found
=gmx_fexist(libdir
);
456 sprintf(libdir
,"%s%cshare%cgromacs%cgromacs-%s%ctop%cgurgle.dat",parent
,
457 DIR_SEPARATOR
,DIR_SEPARATOR
,DIR_SEPARATOR
,
458 VERSION
,DIR_SEPARATOR
,DIR_SEPARATOR
);
459 found
=gmx_fexist(libdir
);
462 /* Remove the gurgle.dat part from libdir if we found something */
464 ptr
=strrchr(libdir
,DIR_SEPARATOR
); /* slash or backslash always present, no check necessary */
471 /* Check if the program name begins with "/" on unix/cygwin, or
472 * with "\" or "X:\" on windows. If not, the program name
473 * is relative to the current directory.
475 static bool filename_is_absolute(char *name
)
477 #if ((defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64) && !defined __CYGWIN__ && !defined __CYGWIN32__)
478 return ((name
[0] == DIR_SEPARATOR
) || ((strlen(name
)>3) && strncmp(name
+1,":\\",2)));
480 return (name
[0] == DIR_SEPARATOR
);
484 bool get_libdir(char *libdir
)
488 char full_path
[GMX_PATH_MAX
];
489 char test_file
[GMX_PATH_MAX
];
490 char system_path
[GMX_PATH_MAX
];
491 char *dir
,*ptr
,*s
,*pdum
;
495 if (Program() != NULL
)
498 /* First - detect binary name */
499 strncpy(bin_name
,Program(),512);
501 /* On windows & cygwin we need to add the .exe extension
502 * too, or we wont be able to detect that the file exists
504 #if (defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64 || defined __CYGWIN__ || defined __CYGWIN32__)
505 if(strlen(bin_name
)<3 || strncasecmp(bin_name
+strlen(bin_name
)-4,".exe",4))
506 strcat(bin_name
,".exe");
509 /* Only do the smart search part if we got a real name */
510 if (NULL
!=bin_name
&& strncmp(bin_name
,"GROMACS",512)) {
512 if (!strchr(bin_name
,DIR_SEPARATOR
)) {
513 /* No slash or backslash in name means it must be in the path - search it! */
516 /* Add the local dir since it is not in the path on windows */
517 #if ((defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64) && !defined __CYGWIN__ && !defined __CYGWIN32__)
518 pdum
=_getcwd(system_path
,sizeof(system_path
)-1);
520 pdum
=getcwd(system_path
,sizeof(system_path
)-1);
522 strcat(system_path
,PATH_SEPARATOR
);
524 strcat(system_path
,s
);
527 while(!found
&& (dir
=gmx_strsep(&s
, PATH_SEPARATOR
)) != NULL
)
529 sprintf(full_path
,"%s%c%s",dir
,DIR_SEPARATOR
,bin_name
);
530 found
=gmx_fexist(full_path
);
534 } else if (!filename_is_absolute(bin_name
)) {
535 /* name contains directory separators, but
536 * it does not start at the root, i.e.
537 * name is relative to the current dir
539 #if ((defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64) && !defined __CYGWIN__ && !defined __CYGWIN32__)
540 pdum
=_getcwd(buf
,sizeof(buf
)-1);
542 pdum
=getcwd(buf
,sizeof(buf
)-1);
544 strncpy(full_path
,buf
,GMX_PATH_MAX
);
545 strcat(full_path
,"/");
546 strcat(full_path
,bin_name
);
548 strncpy(full_path
,bin_name
,GMX_PATH_MAX
);
551 /* Now we should have a full path and name in full_path,
552 * but on unix it might be a link, or a link to a link to a link..
554 #if (!defined WIN32 && !defined _WIN32 && !defined WIN64 && !defined _WIN64)
555 while( (i
=readlink(full_path
,buf
,sizeof(buf
)-1)) > 0 ) {
557 /* If it doesn't start with "/" it is relative */
558 if (buf
[0]!=DIR_SEPARATOR
) {
559 strncpy(strrchr(full_path
,DIR_SEPARATOR
)+1,buf
,GMX_PATH_MAX
);
561 strncpy(full_path
,buf
,GMX_PATH_MAX
);
565 /* Remove the executable name - it always contains at least one slash */
566 *(strrchr(full_path
,DIR_SEPARATOR
)+1)='\0';
567 /* Now we have the full path to the gromacs executable.
568 * Use it to find the library dir.
571 while(!found
&& ( (ptr
=strrchr(full_path
,DIR_SEPARATOR
)) != NULL
) ) {
573 found
=search_subdirs(full_path
,libdir
);
577 /* End of smart searching. If we didn't find it in our parent tree,
578 * or if the program name wasn't set, at least try some standard
579 * locations before giving up, in case we are running from e.g.
580 * a users home directory. This only works on unix or cygwin...
582 #if ((!defined WIN32 && !defined _WIN32 && !defined WIN64 && !defined _WIN64) || defined __CYGWIN__ || defined __CYGWIN32__)
584 found
=search_subdirs("/usr/local",libdir
);
586 found
=search_subdirs("/usr",libdir
);
588 found
=search_subdirs("/opt",libdir
);
594 char *low_gmxlibfn(const char *file
, bool bFatal
)
599 char libpath
[GMX_PATH_MAX
];
600 bool env_is_set
=FALSE
;
601 char *s
,tmppath
[GMX_PATH_MAX
];
603 /* GMXLIB can be a path now */
604 lib
=getenv("GMXLIB");
608 strncpy(libpath
,lib
,GMX_PATH_MAX
);
610 else if (!get_libdir(libpath
))
612 strncpy(libpath
,GMXLIBDIR
,GMX_PATH_MAX
);
616 if (gmx_fexist(file
))
622 strncpy(tmppath
,libpath
,GMX_PATH_MAX
);
624 while(ret
== NULL
&& (dir
=gmx_strsep(&s
, PATH_SEPARATOR
)) != NULL
)
626 sprintf(buf
,"%s%c%s",dir
,DIR_SEPARATOR
,file
);
632 if (ret
== NULL
&& bFatal
)
636 gmx_fatal(FARGS
,"Library file %s not found in current dir nor in your GMXLIB path.\n",file
);
640 gmx_fatal(FARGS
,"Library file %s not found in current dir nor in default directories.\n"
641 "(You can set the directories to search with the GMXLIB path variable)",file
);
652 FILE *low_libopen(const char *file
,bool bFatal
)
657 fn
=low_gmxlibfn(file
,bFatal
);
663 fprintf(debug
,"Opening library file %s\n",fn
);
671 char *gmxlibfn(const char *file
)
673 return low_gmxlibfn(file
,TRUE
);
676 FILE *libopen(const char *file
)
678 return low_libopen(file
,TRUE
);
681 void gmx_tmpnam(char *buf
)
685 if ((len
= strlen(buf
)) < 7)
686 gmx_fatal(FARGS
,"Buf passed to gmx_tmpnam must be at least 7 bytes long");
687 for(i
=len
-6; (i
<len
); i
++) {
690 /* mktemp is dangerous and we should use mkstemp instead, but
691 * since windows doesnt support it we have to separate the cases.
692 * 20090307: mktemp deprecated, use iso c++ _mktemp instead.
694 #if ((defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64) && !defined __CYGWIN__ && !defined __CYGWIN32__)
701 gmx_fatal(FARGS
,"Invalid template %s for mkstemp",buf
);
704 gmx_fatal(FARGS
,"mkstemp created existing file",buf
);
707 gmx_fatal(FARGS
,"Permission denied for opening %s",buf
);
714 /* name in Buf should now be OK */
718 gmx_truncatefile(char *path
, off_t length
)
721 /* Microsoft visual studio does not have "truncate" */
723 LARGE_INTEGER win_length
;
725 win_length
.QuadPart
= length
;
727 fh
= CreateFile(path
,GENERIC_READ
| GENERIC_WRITE
,0,NULL
,
728 OPEN_EXISTING
,0,NULL
);
729 SetFilePointerEx(fh
,win_length
,NULL
,FILE_BEGIN
);
735 return truncate(path
,length
);