3 * This source code is part of
7 * GROningen MAchine for Chemical Simulations
10 * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
11 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
12 * Copyright (c) 2001-2004, The GROMACS development team,
13 * check out http://www.gromacs.org for more information.
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
20 * If you want to redistribute modifications, please consider that
21 * scientific software is very special. Version control is crucial -
22 * bugs must be traceable. We will be happy to consider code for
23 * inclusion in the official distribution, but derived work must not
24 * be called official GROMACS. Details are found in the README & COPYING
25 * files - if they are missing, get the official version at www.gromacs.org.
27 * To help us fund GROMACS development, we humbly ask that you cite
28 * the papers on the package - you can find them in the top README file.
30 * For more info, check our website at http://www.gromacs.org
33 * GROningen Mixture of Alchemy and Childrens' Stories
42 #include <sys/types.h>
46 #if ((defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64) && !defined __CYGWIN__ && !defined __CYGWIN32__)
55 #include "gmx_fatal.h"
60 #include "thread_mpi.h"
63 /* Windows file stuff, only necessary for visual studio */
68 #define MAX_PATHBUF 4096
70 /* we keep a linked list of all files opened through pipes (i.e.
71 compressed or .gzipped files. This way we can distinguish between them
72 without having to change the semantics of reading from/writing to files)
74 typedef struct t_pstack {
76 struct t_pstack *prev;
79 static t_pstack *pstack=NULL;
80 static bool bUnbuffered=FALSE;
83 /* this linked list is an intrinsically globally shared object, so we have
84 to protect it with mutexes */
85 static tMPI_Thread_mutex_t pstack_mutex=TMPI_THREAD_MUTEX_INITIALIZER;
93 void push_ps(FILE *fp)
98 tMPI_Thread_mutex_lock(&pstack_mutex);
106 tMPI_Thread_mutex_unlock(&pstack_mutex);
111 /* redefine fclose */
112 #define fclose fah_fclose
121 static FILE *popen(const char *nm,const char *mode)
123 gmx_impl("Sorry no pipes...");
128 static int pclose(FILE *fp)
130 gmx_impl("Sorry no pipes...");
138 void ffclose(FILE *fp)
142 tMPI_Thread_mutex_lock(&pstack_mutex);
150 else if (ps->fp == fp) {
157 while ((ps->prev != NULL) && (ps->prev->fp != fp))
159 if (ps->prev->fp == fp) {
160 if (ps->prev->fp != NULL)
161 pclose(ps->prev->fp);
163 ps->prev=ps->prev->prev;
172 tMPI_Thread_mutex_unlock(&pstack_mutex);
180 void frewind(FILE *fp)
184 tMPI_Thread_mutex_lock(&pstack_mutex);
190 fprintf(stderr,"Cannot rewind compressed file!\n");
192 tMPI_Thread_mutex_unlock(&pstack_mutex);
200 tMPI_Thread_mutex_unlock(&pstack_mutex);
204 bool is_pipe(FILE *fp)
208 tMPI_Thread_mutex_lock(&pstack_mutex);
215 tMPI_Thread_mutex_unlock(&pstack_mutex);
222 tMPI_Thread_mutex_unlock(&pstack_mutex);
228 static FILE *uncompress(const char *fn,const char *mode)
233 sprintf(buf,"uncompress -c < %s",fn);
234 fprintf(stderr,"Going to execute '%s'\n",buf);
235 if ((fp=popen(buf,mode)) == NULL)
242 static FILE *gunzip(const char *fn,const char *mode)
247 sprintf(buf,"gunzip -c < %s",fn);
248 fprintf(stderr,"Going to execute '%s'\n",buf);
249 if ((fp=popen(buf,mode)) == NULL)
256 bool gmx_fexist(const char *fname)
262 test=fopen(fname,"r");
271 bool gmx_eof(FILE *fp)
279 if ((beof=fread(data,1,1,fp))==1)
280 fseek(fp,-1,SEEK_CUR);
285 char *backup_fn(const char *file)
287 /* Use a reasonably low value for countmax; we might
288 * generate 4-5 files in each round, and we dont
289 * want to hit directory limits of 1024 or 2048 files.
296 smalloc(buf, MAX_PATHBUF);
298 for(i=strlen(file)-1; ((i > 0) && (file[i] != '/')); i--)
300 /* Must check whether i > 0, i.e. whether there is a directory
301 * in the file name. In that case we overwrite the / sign with
302 * a '\0' to end the directory string .
305 directory = strdup(file);
307 fn = strdup(file+i+1);
310 directory = strdup(".");
314 sprintf(buf,"%s/#%s.%d#",directory,fn,count);
316 } while ((count < COUNTMAX) && gmx_fexist(buf));
318 /* Arbitrarily bail out */
319 if (count == COUNTMAX)
320 gmx_fatal(FARGS,"Won't make more than %d backups of %s for you",
329 bool make_backup(const char * name)
334 return FALSE; /* skip making backups */
337 if(gmx_fexist(name)) {
338 backup = backup_fn(name);
339 if(rename(name, backup) == 0) {
340 fprintf(stderr, "\nBack Off! I just backed up %s to %s\n",
343 fprintf(stderr, "Sorry couldn't backup %s to %s\n", name, backup);
352 FILE *ffopen(const char *file,const char *mode)
355 char buf[256],*bf,*bufsize=0,*ptr;
366 if (gmx_fexist(buf) || !bRead) {
367 if ((ff=fopen(buf,mode))==NULL)
370 /* Check whether we should be using buffering (default) or not
373 if (bUnbuffered || ((bufsize=getenv("LOG_BUFS")) != NULL)) {
374 /* Check whether to use completely unbuffered */
378 bs=strtol(bufsize, NULL, 0);
383 if (setvbuf(ff,ptr,_IOFBF,bs) != 0)
384 gmx_file("Buffering File");
390 sprintf(buf,"%s.Z",file);
391 if (gmx_fexist(buf)) {
392 ff=uncompress(buf,mode);
395 sprintf(buf,"%s.gz",file);
396 if (gmx_fexist(buf)) {
408 bool search_subdirs(const char *parent, char *libdir)
413 /* Search a few common subdirectory names for the gromacs library dir */
414 sprintf(libdir,"%s%cshare%ctop%cgurgle.dat",parent,
415 DIR_SEPARATOR,DIR_SEPARATOR,DIR_SEPARATOR);
416 found=gmx_fexist(libdir);
418 sprintf(libdir,"%s%cshare%cgromacs%ctop%cgurgle.dat",parent,
419 DIR_SEPARATOR,DIR_SEPARATOR,
420 DIR_SEPARATOR,DIR_SEPARATOR);
421 found=gmx_fexist(libdir);
424 sprintf(libdir,"%s%cshare%cgromacs-%s%ctop%cgurgle.dat",parent,
425 DIR_SEPARATOR,DIR_SEPARATOR,VERSION,
426 DIR_SEPARATOR,DIR_SEPARATOR);
427 found=gmx_fexist(libdir);
430 sprintf(libdir,"%s%cshare%cgromacs%cgromacs-%s%ctop%cgurgle.dat",parent,
431 DIR_SEPARATOR,DIR_SEPARATOR,DIR_SEPARATOR,
432 VERSION,DIR_SEPARATOR,DIR_SEPARATOR);
433 found=gmx_fexist(libdir);
436 /* Remove the gurgle.dat part from libdir if we found something */
438 ptr=strrchr(libdir,DIR_SEPARATOR); /* slash or backslash always present, no check necessary */
445 /* Check if the program name begins with "/" on unix/cygwin, or
446 * with "\" or "X:\" on windows. If not, the program name
447 * is relative to the current directory.
449 static bool filename_is_absolute(char *name)
451 #if ((defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64) && !defined __CYGWIN__ && !defined __CYGWIN32__)
452 return ((name[0] == DIR_SEPARATOR) || ((strlen(name)>3) && strncmp(name+1,":\\",2)));
454 return (name[0] == DIR_SEPARATOR);
458 bool get_libdir(char *libdir)
462 char full_path[MAX_PATHBUF];
463 char test_file[MAX_PATHBUF];
464 char system_path[MAX_PATHBUF];
465 char *dir,*ptr,*s,*pdum;
469 /* First - detect binary name */
470 strncpy(bin_name,Program(),512);
472 /* On windows & cygwin we need to add the .exe extension
473 * too, or we wont be able to detect that the file exists
475 #if (defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64 || defined __CYGWIN__ || defined __CYGWIN32__)
476 if(strlen(bin_name)<3 || strncasecmp(bin_name+strlen(bin_name)-4,".exe",4))
477 strcat(bin_name,".exe");
480 /* Only do the smart search part if we got a real name */
481 if (NULL!=bin_name && strncmp(bin_name,"GROMACS",512)) {
483 if (!strchr(bin_name,DIR_SEPARATOR)) {
484 /* No slash or backslash in name means it must be in the path - search it! */
487 /* Add the local dir since it is not in the path on windows */
488 #if ((defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64) && !defined __CYGWIN__ && !defined __CYGWIN32__)
489 pdum=_getcwd(system_path,sizeof(system_path)-1);
491 pdum=getcwd(system_path,sizeof(system_path)-1);
493 strcat(system_path,PATH_SEPARATOR);
495 strcat(system_path,s);
498 while(!found && (dir=gmx_strsep(&s, PATH_SEPARATOR)) != NULL)
500 sprintf(full_path,"%s%c%s",dir,DIR_SEPARATOR,bin_name);
501 found=gmx_fexist(full_path);
505 } else if (!filename_is_absolute(bin_name)) {
506 /* name contains directory separators, but
507 * it does not start at the root, i.e.
508 * name is relative to the current dir
510 #if ((defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64) && !defined __CYGWIN__ && !defined __CYGWIN32__)
511 pdum=_getcwd(buf,sizeof(buf)-1);
513 pdum=getcwd(buf,sizeof(buf)-1);
515 strncpy(full_path,buf,MAX_PATHBUF);
516 strcat(full_path,"/");
517 strcat(full_path,bin_name);
519 strncpy(full_path,bin_name,MAX_PATHBUF);
522 /* Now we should have a full path and name in full_path,
523 * but on unix it might be a link, or a link to a link to a link..
525 #if (!defined WIN32 && !defined _WIN32 && !defined WIN64 && !defined _WIN64)
526 while( (i=readlink(full_path,buf,sizeof(buf)-1)) > 0 ) {
528 /* If it doesn't start with "/" it is relative */
529 if (buf[0]!=DIR_SEPARATOR) {
530 strncpy(strrchr(full_path,DIR_SEPARATOR)+1,buf,MAX_PATHBUF);
532 strncpy(full_path,buf,MAX_PATHBUF);
536 /* Remove the executable name - it always contains at least one slash */
537 *(strrchr(full_path,DIR_SEPARATOR)+1)='\0';
538 /* Now we have the full path to the gromacs executable.
539 * Use it to find the library dir.
542 while(!found && ( (ptr=strrchr(full_path,DIR_SEPARATOR)) != NULL ) ) {
544 found=search_subdirs(full_path,libdir);
547 /* End of smart searching. If we didn't find it in our parent tree,
548 * or if the program name wasn't set, at least try some standard
549 * locations before giving up, in case we are running from e.g.
550 * a users home directory. This only works on unix or cygwin...
552 #if ((!defined WIN32 && !defined _WIN32 && !defined WIN64 && !defined _WIN64) || defined __CYGWIN__ || defined __CYGWIN32__)
554 found=search_subdirs("/usr/local",libdir);
556 found=search_subdirs("/usr",libdir);
558 found=search_subdirs("/opt",libdir);
564 char *low_libfn(const char *file, bool bFatal)
569 char libpath[MAX_PATHBUF];
570 bool env_is_set=FALSE;
571 char *s,tmppath[MAX_PATHBUF];
574 /* GMXLIB can be a path now */
575 lib=getenv("GMXLIB");
578 strncpy(libpath,lib,MAX_PATHBUF);
580 else if (!get_libdir(libpath))
581 strncpy(libpath,GMXLIBDIR,MAX_PATHBUF);
583 if (gmx_fexist(file))
590 strncpy(tmppath,libpath,MAX_PATHBUF);
592 while(!found && (dir=gmx_strsep(&s, PATH_SEPARATOR)) != NULL )
594 sprintf(buf,"%s%c%s",dir,DIR_SEPARATOR,file);
595 found=gmx_fexist(buf);
597 if (bFatal && !found)
600 gmx_fatal(FARGS,"Library file %s not found in current dir nor in your GMXLIB path.\n",file);
602 gmx_fatal(FARGS,"Library file %s not found in current dir nor in default directories.\n"
603 "(You can set the directories to search with the GMXLIB path variable)",file);
614 FILE *low_libopen(const char *file,bool bFatal)
619 fn=low_libfn(file,bFatal);
625 fprintf(stderr,"Opening library file %s\n",fn);
633 char *libfn(const char *file)
635 return low_libfn(file,TRUE);
638 FILE *libopen(const char *file)
640 return low_libopen(file,TRUE);
643 void gmx_tmpnam(char *buf)
647 if ((len = strlen(buf)) < 7)
648 gmx_fatal(FARGS,"Buf passed to gmx_tmpnam must be at least 7 bytes long");
649 for(i=len-6; (i<len); i++) {
652 /* mktemp is dangerous and we should use mkstemp instead, but
653 * since windows doesnt support it we have to separate the cases.
654 * 20090307: mktemp deprecated, use iso c++ _mktemp instead.
656 #if ((defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64) && !defined __CYGWIN__ && !defined __CYGWIN32__)
663 gmx_fatal(FARGS,"Invalid template %s for mkstemp",buf);
666 gmx_fatal(FARGS,"mkstemp created existing file",buf);
669 gmx_fatal(FARGS,"Permission denied for opening %s",buf);
676 /* name in Buf should now be OK */
680 gmx_truncatefile(char *path, off_t length)
683 /* Microsoft visual studio does not have "truncate" */
685 LARGE_INTEGER win_length;
687 win_length.QuadPart = length;
689 fh = CreateFile(path,GENERIC_READ | GENERIC_WRITE,0,NULL,
690 OPEN_EXISTING,0,NULL);
691 SetFilePointerEx(fh,win_length,NULL,FILE_BEGIN);
697 return truncate(path,length);