minor fixes in ditribution files
[gromacs/qmmm-gamess-us.git] / src / gmxlib / futil.c
blob2a040682483674c45157d0f1d61b5823d2272388
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 <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <sys/types.h>
44 #include <sys/stat.h>
45 #include <fcntl.h>
47 #if ((defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64) && !defined __CYGWIN__ && !defined __CYGWIN32__)
48 #include <direct.h>
49 #include <io.h>
50 #endif
52 #include "sysstuff.h"
53 #include "string2.h"
54 #include "futil.h"
55 #include "network.h"
56 #include "gmx_fatal.h"
57 #include "smalloc.h"
58 #include "statutil.h"
60 #ifdef GMX_THREADS
61 #include "thread_mpi.h"
62 #endif
64 /* Windows file stuff, only necessary for visual studio */
65 #ifdef _MSC_VER
66 #include "windows.h"
67 #endif
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 {
74 FILE *fp;
75 struct t_pstack *prev;
76 } t_pstack;
78 static t_pstack *pstack=NULL;
79 static bool bUnbuffered=FALSE;
81 #ifdef GMX_THREADS
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;
85 #endif
87 void no_buffers(void)
89 bUnbuffered=TRUE;
92 void push_ps(FILE *fp)
94 t_pstack *ps;
96 #ifdef GMX_THREADS
97 tMPI_Thread_mutex_lock(&pstack_mutex);
98 #endif
100 snew(ps,1);
101 ps->fp = fp;
102 ps->prev = pstack;
103 pstack = ps;
104 #ifdef GMX_THREADS
105 tMPI_Thread_mutex_unlock(&pstack_mutex);
106 #endif
109 #ifdef GMX_FAHCORE
110 /* don't use pipes!*/
111 #define popen fah_fopen
112 #define pclose fah_fclose
113 #define SKIP_FFOPS 1
114 #else
115 #ifdef ffclose
116 #undef ffclose
117 #endif
118 #endif
120 #ifndef GMX_FAHCORE
121 #ifndef HAVE_PIPES
122 static FILE *popen(const char *nm,const char *mode)
124 gmx_impl("Sorry no pipes...");
126 return NULL;
129 static int pclose(FILE *fp)
131 gmx_impl("Sorry no pipes...");
133 return 0;
135 #endif
136 #endif
138 int ffclose(FILE *fp)
140 #ifndef SKIP_FFOPS
141 return fclose(fp);
142 #else
143 t_pstack *ps,*tmp;
144 int ret=0;
145 #ifdef GMX_THREADS
146 tMPI_Thread_mutex_lock(&pstack_mutex);
147 #endif
149 ps=pstack;
150 if (ps == NULL) {
151 if (fp != NULL)
152 ret = fclose(fp);
154 else if (ps->fp == fp) {
155 if (fp != NULL)
156 ret = pclose(fp);
157 pstack=pstack->prev;
158 sfree(ps);
160 else {
161 while ((ps->prev != NULL) && (ps->prev->fp != fp))
162 ps=ps->prev;
163 if (ps->prev->fp == fp) {
164 if (ps->prev->fp != NULL)
165 ret = pclose(ps->prev->fp);
166 tmp=ps->prev;
167 ps->prev=ps->prev->prev;
168 sfree(tmp);
170 else {
171 if (fp != NULL)
172 ret = fclose(fp);
175 #ifdef GMX_THREADS
176 tMPI_Thread_mutex_unlock(&pstack_mutex);
177 #endif
178 return ret;
179 #endif
183 #ifdef rewind
184 #undef rewind
185 #endif
187 void frewind(FILE *fp)
189 t_pstack *ps;
190 #ifdef GMX_THREADS
191 tMPI_Thread_mutex_lock(&pstack_mutex);
192 #endif
194 ps=pstack;
195 while (ps != NULL) {
196 if (ps->fp == fp) {
197 fprintf(stderr,"Cannot rewind compressed file!\n");
198 #ifdef GMX_THREADS
199 tMPI_Thread_mutex_unlock(&pstack_mutex);
200 #endif
201 return;
203 ps=ps->prev;
205 rewind(fp);
206 #ifdef GMX_THREADS
207 tMPI_Thread_mutex_unlock(&pstack_mutex);
208 #endif
211 bool is_pipe(FILE *fp)
213 t_pstack *ps;
214 #ifdef GMX_THREADS
215 tMPI_Thread_mutex_lock(&pstack_mutex);
216 #endif
218 ps=pstack;
219 while (ps != NULL) {
220 if (ps->fp == fp) {
221 #ifdef GMX_THREADS
222 tMPI_Thread_mutex_unlock(&pstack_mutex);
223 #endif
224 return TRUE;
226 ps=ps->prev;
228 #ifdef GMX_THREADS
229 tMPI_Thread_mutex_unlock(&pstack_mutex);
230 #endif
231 return FALSE;
235 static FILE *uncompress(const char *fn,const char *mode)
237 FILE *fp;
238 char buf[256];
240 sprintf(buf,"uncompress -c < %s",fn);
241 fprintf(stderr,"Going to execute '%s'\n",buf);
242 if ((fp=popen(buf,mode)) == NULL)
243 gmx_open(fn);
244 push_ps(fp);
246 return fp;
249 static FILE *gunzip(const char *fn,const char *mode)
251 FILE *fp;
252 char buf[256];
254 sprintf(buf,"gunzip -c < %s",fn);
255 fprintf(stderr,"Going to execute '%s'\n",buf);
256 if ((fp=popen(buf,mode)) == NULL)
257 gmx_open(fn);
258 push_ps(fp);
260 return fp;
263 bool gmx_fexist(const char *fname)
265 FILE *test;
267 if (fname == NULL)
268 return FALSE;
269 test=fopen(fname,"r");
270 if (test == NULL)
271 return FALSE;
272 else {
273 ffclose(test);
274 return TRUE;
279 bool gmx_fexist_master(const char *fname, t_commrec *cr)
281 bool bExist;
283 if (SIMMASTER(cr))
285 bExist = gmx_fexist(fname);
287 if (PAR(cr))
289 gmx_bcast(sizeof(bExist),&bExist,cr);
291 return bExist;
294 bool gmx_eof(FILE *fp)
296 char data[4];
297 bool beof;
299 if (is_pipe(fp))
300 return feof(fp);
301 else {
302 if ((beof=fread(data,1,1,fp))==1)
303 fseek(fp,-1,SEEK_CUR);
304 return !beof;
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.
314 #define COUNTMAX 128
315 int i,count=1;
316 char *directory,*fn;
317 char *buf;
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 .
327 if (i > 0) {
328 directory = strdup(file);
329 directory[i] = '\0';
330 fn = strdup(file+i+1);
332 else {
333 directory = strdup(".");
334 fn = strdup(file);
336 do {
337 sprintf(buf,"%s/#%s.%d#",directory,fn,count);
338 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",
344 COUNTMAX,fn);
346 sfree(directory);
347 sfree(fn);
349 return buf;
352 bool make_backup(const char * name)
354 char * backup;
356 #ifdef GMX_FAHCORE
357 return FALSE; /* skip making backups */
358 #else
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",
364 name, backup);
365 } else {
366 fprintf(stderr, "Sorry couldn't backup %s to %s\n", name, backup);
367 return FALSE;
369 sfree(backup);
371 return TRUE;
372 #endif
375 FILE *ffopen(const char *file,const char *mode)
377 #ifdef SKIP_FFOPS
378 return fopen(file,mode);
379 #else
380 FILE *ff=NULL;
381 char buf[256],*bf,*bufsize=0,*ptr;
382 bool bRead;
383 int bs;
385 if (mode[0]=='w') {
386 make_backup(file);
388 where();
390 bRead= (mode[0]=='r'&&mode[1]!='+');
391 strcpy(buf,file);
392 if (gmx_fexist(buf) || !bRead) {
393 if ((ff=fopen(buf,mode))==NULL)
394 gmx_file(buf);
395 where();
396 /* Check whether we should be using buffering (default) or not
397 * (for debugging)
399 if (bUnbuffered || ((bufsize=getenv("LOG_BUFS")) != NULL)) {
400 /* Check whether to use completely unbuffered */
401 if (bUnbuffered)
402 bs = 0;
403 else
404 bs=strtol(bufsize, NULL, 10);
405 if (bs <= 0)
406 setbuf(ff,NULL);
407 else {
408 snew(ptr,bs+8);
409 if (setvbuf(ff,ptr,_IOFBF,bs) != 0)
410 gmx_file("Buffering File");
413 where();
415 else {
416 sprintf(buf,"%s.Z",file);
417 if (gmx_fexist(buf)) {
418 ff=uncompress(buf,mode);
420 else {
421 sprintf(buf,"%s.gz",file);
422 if (gmx_fexist(buf)) {
423 ff=gunzip(buf,mode);
425 else
426 gmx_file(file);
429 return ff;
430 #endif
434 bool search_subdirs(const char *parent, char *libdir)
436 char *ptr;
437 bool found;
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);
443 if(!found) {
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);
449 if(!found) {
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);
455 if(!found) {
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 */
463 if(found) {
464 ptr=strrchr(libdir,DIR_SEPARATOR); /* slash or backslash always present, no check necessary */
465 *ptr='\0';
467 return found;
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)));
479 #else
480 return (name[0] == DIR_SEPARATOR);
481 #endif
484 bool get_libdir(char *libdir)
486 char bin_name[512];
487 char buf[512];
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;
492 bool found=FALSE;
493 int i;
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");
507 #endif
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! */
514 s=getenv("PATH");
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);
519 #else
520 pdum=getcwd(system_path,sizeof(system_path)-1);
521 #endif
522 strcat(system_path,PATH_SEPARATOR);
523 if (s != NULL)
524 strcat(system_path,s);
525 s=system_path;
526 found=FALSE;
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);
532 if (!found)
533 return FALSE;
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);
541 #else
542 pdum=getcwd(buf,sizeof(buf)-1);
543 #endif
544 strncpy(full_path,buf,GMX_PATH_MAX);
545 strcat(full_path,"/");
546 strcat(full_path,bin_name);
547 } else {
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 ) {
556 buf[i]='\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);
560 } else
561 strncpy(full_path,buf,GMX_PATH_MAX);
563 #endif
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.
570 found=FALSE;
571 while(!found && ( (ptr=strrchr(full_path,DIR_SEPARATOR)) != NULL ) ) {
572 *ptr='\0';
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__)
583 if(!found)
584 found=search_subdirs("/usr/local",libdir);
585 if(!found)
586 found=search_subdirs("/usr",libdir);
587 if(!found)
588 found=search_subdirs("/opt",libdir);
589 #endif
590 return found;
594 char *low_gmxlibfn(const char *file, bool bFatal)
596 char *ret;
597 char *lib,*dir;
598 char buf[1024];
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");
605 if (lib != NULL)
607 env_is_set=TRUE;
608 strncpy(libpath,lib,GMX_PATH_MAX);
610 else if (!get_libdir(libpath))
612 strncpy(libpath,GMXLIBDIR,GMX_PATH_MAX);
615 ret = NULL;
616 if (gmx_fexist(file))
618 ret = strdup(file);
620 else
622 strncpy(tmppath,libpath,GMX_PATH_MAX);
623 s=tmppath;
624 while(ret == NULL && (dir=gmx_strsep(&s, PATH_SEPARATOR)) != NULL )
626 sprintf(buf,"%s%c%s",dir,DIR_SEPARATOR,file);
627 if (gmx_fexist(buf))
629 ret = strdup(buf);
632 if (ret == NULL && bFatal)
634 if (env_is_set)
636 gmx_fatal(FARGS,"Library file %s not found in current dir nor in your GMXLIB path.\n",file);
638 else
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);
646 return ret;
652 FILE *low_libopen(const char *file,bool bFatal)
654 FILE *ff;
655 char *fn;
657 fn=low_gmxlibfn(file,bFatal);
659 if (fn==NULL) {
660 ff=NULL;
661 } else {
662 if (debug)
663 fprintf(debug,"Opening library file %s\n",fn);
664 ff=fopen(fn,"r");
666 sfree(fn);
668 return ff;
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)
683 int i,len,fd;
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++) {
688 buf[i] = 'X';
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__)
695 _mktemp(buf);
696 #else
697 fd = mkstemp(buf);
699 switch (fd) {
700 case EINVAL:
701 gmx_fatal(FARGS,"Invalid template %s for mkstemp",buf);
702 break;
703 case EEXIST:
704 gmx_fatal(FARGS,"mkstemp created existing file",buf);
705 break;
706 case EACCES:
707 gmx_fatal(FARGS,"Permission denied for opening %s",buf);
708 break;
709 default:
710 break;
712 close(fd);
713 #endif
714 /* name in Buf should now be OK */
718 gmx_truncatefile(char *path, off_t length)
720 #ifdef _MSC_VER
721 /* Microsoft visual studio does not have "truncate" */
722 HANDLE fh;
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);
730 SetEndOfFile(fh);
731 CloseHandle(fh);
733 return 0;
734 #else
735 return truncate(path,length);
736 #endif