Revised wording in pdb2gmx.c, hopefully clearer now.
[gromacs/rigid-bodies.git] / src / gmxlib / futil.c
bloba653b083b0868a9387599a1a877362dafbc61b58
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 #ifdef HAVE_DIRENT_H
48 /* POSIX */
49 #include <dirent.h>
50 #endif
53 #if ((defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64) && !defined __CYGWIN__ && !defined __CYGWIN32__)
54 #include <direct.h>
55 #include <io.h>
56 #endif
58 #include "sysstuff.h"
59 #include "string2.h"
60 #include "futil.h"
61 #include "network.h"
62 #include "gmx_fatal.h"
63 #include "smalloc.h"
64 #include "statutil.h"
67 #ifdef GMX_THREADS
68 #include "thread_mpi.h"
69 #endif
71 /* Windows file stuff, only necessary for visual studio */
72 #ifdef _MSC_VER
73 #include "windows.h"
74 #endif
76 /* we keep a linked list of all files opened through pipes (i.e.
77 compressed or .gzipped files. This way we can distinguish between them
78 without having to change the semantics of reading from/writing to files)
80 typedef struct t_pstack {
81 FILE *fp;
82 struct t_pstack *prev;
83 } t_pstack;
85 static t_pstack *pstack=NULL;
86 static gmx_bool bUnbuffered=FALSE;
88 #ifdef GMX_THREADS
89 /* this linked list is an intrinsically globally shared object, so we have
90 to protect it with mutexes */
91 static tMPI_Thread_mutex_t pstack_mutex=TMPI_THREAD_MUTEX_INITIALIZER;
92 #endif
94 void no_buffers(void)
96 bUnbuffered=TRUE;
99 void push_ps(FILE *fp)
101 t_pstack *ps;
103 #ifdef GMX_THREADS
104 tMPI_Thread_mutex_lock(&pstack_mutex);
105 #endif
107 snew(ps,1);
108 ps->fp = fp;
109 ps->prev = pstack;
110 pstack = ps;
111 #ifdef GMX_THREADS
112 tMPI_Thread_mutex_unlock(&pstack_mutex);
113 #endif
116 #ifdef GMX_FAHCORE
117 /* don't use pipes!*/
118 #define popen fah_fopen
119 #define pclose fah_fclose
120 #define SKIP_FFOPS 1
121 #else
122 #ifdef ffclose
123 #undef ffclose
124 #endif
125 #endif
127 #ifndef GMX_FAHCORE
128 #ifndef HAVE_PIPES
129 static FILE *popen(const char *nm,const char *mode)
131 gmx_impl("Sorry no pipes...");
133 return NULL;
136 static int pclose(FILE *fp)
138 gmx_impl("Sorry no pipes...");
140 return 0;
142 #endif
143 #endif
145 int ffclose(FILE *fp)
147 #ifdef SKIP_FFOPS
148 return fclose(fp);
149 #else
150 t_pstack *ps,*tmp;
151 int ret=0;
152 #ifdef GMX_THREADS
153 tMPI_Thread_mutex_lock(&pstack_mutex);
154 #endif
156 ps=pstack;
157 if (ps == NULL) {
158 if (fp != NULL)
159 ret = fclose(fp);
161 else if (ps->fp == fp) {
162 if (fp != NULL)
163 ret = pclose(fp);
164 pstack=pstack->prev;
165 sfree(ps);
167 else {
168 while ((ps->prev != NULL) && (ps->prev->fp != fp))
169 ps=ps->prev;
170 if (ps->prev->fp == fp) {
171 if (ps->prev->fp != NULL)
172 ret = pclose(ps->prev->fp);
173 tmp=ps->prev;
174 ps->prev=ps->prev->prev;
175 sfree(tmp);
177 else {
178 if (fp != NULL)
179 ret = fclose(fp);
182 #ifdef GMX_THREADS
183 tMPI_Thread_mutex_unlock(&pstack_mutex);
184 #endif
185 return ret;
186 #endif
190 #ifdef rewind
191 #undef rewind
192 #endif
194 void frewind(FILE *fp)
196 t_pstack *ps;
197 #ifdef GMX_THREADS
198 tMPI_Thread_mutex_lock(&pstack_mutex);
199 #endif
201 ps=pstack;
202 while (ps != NULL) {
203 if (ps->fp == fp) {
204 fprintf(stderr,"Cannot rewind compressed file!\n");
205 #ifdef GMX_THREADS
206 tMPI_Thread_mutex_unlock(&pstack_mutex);
207 #endif
208 return;
210 ps=ps->prev;
212 rewind(fp);
213 #ifdef GMX_THREADS
214 tMPI_Thread_mutex_unlock(&pstack_mutex);
215 #endif
218 int gmx_fseek(FILE *stream, gmx_off_t offset, int whence)
220 #ifdef HAVE_FSEEKO
221 return fseeko(stream, offset, whence);
222 #else
223 #ifdef HAVE__FSEEKI64
224 return _fseeki64(stream, offset, whence);
225 #else
226 return fseek(stream, offset, whence);
227 #endif
228 #endif
231 gmx_off_t gmx_ftell(FILE *stream)
233 #ifdef HAVE_FSEEKO
234 return ftello(stream);
235 #else
236 #ifdef HAVE__FSEEKI64
237 return _ftelli64(stream);
238 #else
239 return ftell(stream);
240 #endif
241 #endif
245 gmx_bool is_pipe(FILE *fp)
247 t_pstack *ps;
248 #ifdef GMX_THREADS
249 tMPI_Thread_mutex_lock(&pstack_mutex);
250 #endif
252 ps=pstack;
253 while (ps != NULL) {
254 if (ps->fp == fp) {
255 #ifdef GMX_THREADS
256 tMPI_Thread_mutex_unlock(&pstack_mutex);
257 #endif
258 return TRUE;
260 ps=ps->prev;
262 #ifdef GMX_THREADS
263 tMPI_Thread_mutex_unlock(&pstack_mutex);
264 #endif
265 return FALSE;
269 static FILE *uncompress(const char *fn,const char *mode)
271 FILE *fp;
272 char buf[256];
274 sprintf(buf,"uncompress -c < %s",fn);
275 fprintf(stderr,"Going to execute '%s'\n",buf);
276 if ((fp=popen(buf,mode)) == NULL)
277 gmx_open(fn);
278 push_ps(fp);
280 return fp;
283 static FILE *gunzip(const char *fn,const char *mode)
285 FILE *fp;
286 char buf[256];
288 sprintf(buf,"gunzip -c < %s",fn);
289 fprintf(stderr,"Going to execute '%s'\n",buf);
290 if ((fp=popen(buf,mode)) == NULL)
291 gmx_open(fn);
292 push_ps(fp);
294 return fp;
297 gmx_bool gmx_fexist(const char *fname)
299 FILE *test;
301 if (fname == NULL)
302 return FALSE;
303 test=fopen(fname,"r");
304 if (test == NULL) {
305 /*Windows doesn't allow fopen of directory - so we need to check this seperately */
306 #if ((defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64) && !defined __CYGWIN__ && !defined __CYGWIN32__)
307 DWORD attr = GetFileAttributes(fname);
308 return (attr != INVALID_FILE_ATTRIBUTES) && (attr & FILE_ATTRIBUTE_DIRECTORY);
309 #else
310 return FALSE;
311 #endif
312 } else {
313 fclose(test);
314 return TRUE;
319 gmx_bool gmx_fexist_master(const char *fname, t_commrec *cr)
321 gmx_bool bExist;
323 if (SIMMASTER(cr))
325 bExist = gmx_fexist(fname);
327 if (PAR(cr))
329 gmx_bcast(sizeof(bExist),&bExist,cr);
331 return bExist;
334 gmx_bool gmx_eof(FILE *fp)
336 char data[4];
337 gmx_bool beof;
339 if (is_pipe(fp))
340 return feof(fp);
341 else {
342 if ((beof=fread(data,1,1,fp))==1)
343 gmx_fseek(fp,-1,SEEK_CUR);
344 return !beof;
348 static char *backup_fn(const char *file,int count_max)
350 /* Use a reasonably low value for countmax; we might
351 * generate 4-5 files in each round, and we dont
352 * want to hit directory limits of 1024 or 2048 files.
354 #define COUNTMAX 99
355 int i,count=1;
356 char *directory,*fn;
357 char *buf;
359 if (count_max == -1)
361 count_max = COUNTMAX;
364 smalloc(buf, GMX_PATH_MAX);
366 for(i=strlen(file)-1; ((i > 0) && (file[i] != DIR_SEPARATOR)); i--)
368 /* Must check whether i > 0, i.e. whether there is a directory
369 * in the file name. In that case we overwrite the / sign with
370 * a '\0' to end the directory string .
372 if (i > 0) {
373 directory = gmx_strdup(file);
374 directory[i] = '\0';
375 fn = gmx_strdup(file+i+1);
377 else {
378 directory = gmx_strdup(".");
379 fn = gmx_strdup(file);
381 do {
382 sprintf(buf,"%s/#%s.%d#",directory,fn,count);
383 count++;
384 } while ((count <= count_max) && gmx_fexist(buf));
386 /* Arbitrarily bail out */
387 if (count > count_max)
388 gmx_fatal(FARGS,"Won't make more than %d backups of %s for you.\n"
389 "The env.var. GMX_MAXBACKUP controls this maximum, -1 disables backups.",
390 count_max,fn);
392 sfree(directory);
393 sfree(fn);
395 return buf;
398 gmx_bool make_backup(const char * name)
400 char * env;
401 int count_max;
402 char * backup;
404 #ifdef GMX_FAHCORE
405 return FALSE; /* skip making backups */
406 #else
408 if (gmx_fexist(name))
410 env = getenv("GMX_MAXBACKUP");
411 if (env != NULL)
413 count_max = 0;
414 sscanf(env,"%d",&count_max);
415 if (count_max == -1)
417 /* Do not make backups and possibly overwrite old files */
418 return TRUE;
421 else
423 /* Use the default maximum */
424 count_max = -1;
426 backup = backup_fn(name,count_max);
427 if(rename(name, backup) == 0) {
428 fprintf(stderr, "\nBack Off! I just backed up %s to %s\n",
429 name, backup);
430 } else {
431 fprintf(stderr, "Sorry couldn't backup %s to %s\n", name, backup);
432 return FALSE;
434 sfree(backup);
436 return TRUE;
437 #endif
440 FILE *ffopen(const char *file,const char *mode)
442 #ifdef SKIP_FFOPS
443 return fopen(file,mode);
444 #else
445 FILE *ff=NULL;
446 char buf[256],*bf,*bufsize=0,*ptr;
447 gmx_bool bRead;
448 int bs;
450 if (mode[0]=='w') {
451 make_backup(file);
453 where();
455 bRead= (mode[0]=='r'&&mode[1]!='+');
456 strcpy(buf,file);
457 if (!bRead || gmx_fexist(buf)) {
458 if ((ff=fopen(buf,mode))==NULL)
459 gmx_file(buf);
460 where();
461 /* Check whether we should be using buffering (default) or not
462 * (for debugging)
464 if (bUnbuffered || ((bufsize=getenv("LOG_BUFS")) != NULL)) {
465 /* Check whether to use completely unbuffered */
466 if (bUnbuffered)
467 bs = 0;
468 else
469 bs=strtol(bufsize, NULL, 10);
470 if (bs <= 0)
471 setbuf(ff,NULL);
472 else {
473 snew(ptr,bs+8);
474 if (setvbuf(ff,ptr,_IOFBF,bs) != 0)
475 gmx_file("Buffering File");
478 where();
480 else {
481 sprintf(buf,"%s.Z",file);
482 if (gmx_fexist(buf)) {
483 ff=uncompress(buf,mode);
485 else {
486 sprintf(buf,"%s.gz",file);
487 if (gmx_fexist(buf)) {
488 ff=gunzip(buf,mode);
490 else
491 gmx_file(file);
494 return ff;
495 #endif
498 /* Our own implementation of dirent-like functionality to scan directories. */
499 struct gmx_directory
501 #ifdef HAVE_DIRENT_H
502 DIR * dirent_handle;
503 #elif (defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64)
504 intptr_t windows_handle;
505 struct _finddata_t finddata;
506 int first;
507 #else
508 int dummy;
509 #endif
514 gmx_directory_open(gmx_directory_t *p_gmxdir,const char *dirname)
516 struct gmx_directory * gmxdir;
517 int rc;
519 snew(gmxdir,1);
521 *p_gmxdir = gmxdir;
523 #ifdef HAVE_DIRENT_H
524 if( (gmxdir->dirent_handle = opendir(dirname)) != NULL)
526 rc = 0;
528 else
530 sfree(gmxdir);
531 *p_gmxdir = NULL;
532 rc = EINVAL;
534 #elif (defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64)
536 if(dirname!=NULL && strlen(dirname)>0)
538 char * tmpname;
539 size_t namelength;
540 int len;
542 len = strlen(dirname);
543 snew(tmpname,len+3);
545 strncpy(tmpname,dirname,len+1);
547 /* Remove possible trailing directory separator */
548 if(tmpname[len]=='/' || tmpname[len]=='\\')
550 tmpname[len]='\0';
553 /* Add wildcard */
554 strcat(tmpname,"/*");
556 gmxdir->first = 1;
557 if( (gmxdir->windows_handle=_findfirst(tmpname,&gmxdir->finddata))>0L)
559 rc = 0;
561 else
563 if(errno=EINVAL)
565 sfree(gmxdir);
566 *p_gmxdir = NULL;
567 rc = EINVAL;
569 else
571 rc = 0;
575 else
577 rc = EINVAL;
579 #else
580 gmx_fatal(FARGS,
581 "Source compiled without POSIX dirent or windows support - cannot scan directories.\n"
582 "In the very unlikely event this is not a compile-time mistake you could consider\n"
583 "implementing support for your platform in futil.c, but contact the developers\n"
584 "to make sure it's really necessary!\n");
585 rc = -1;
586 #endif
587 return rc;
592 gmx_directory_nextfile(gmx_directory_t gmxdir,char *name,int maxlength_name)
594 int rc;
596 #ifdef HAVE_DIRENT_H
598 struct dirent tmp_dirent;
599 struct dirent * p;
602 if(gmxdir!=NULL && gmxdir->dirent_handle!=NULL)
604 rc = readdir_r(gmxdir->dirent_handle,&tmp_dirent,&p);
605 if(p!=NULL && rc==0)
607 strncpy(name,tmp_dirent.d_name,maxlength_name);
609 else
611 name[0] = '\0';
612 rc = ENOENT;
615 else
617 name[0] = '\0';
618 rc = EINVAL;
621 #elif (defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64)
623 if(gmxdir!=NULL)
625 if(gmxdir->windows_handle<=0)
628 name[0] = '\0';
629 rc = ENOENT;
631 else if(gmxdir->first==1)
633 strncpy(name,gmxdir->finddata.name,maxlength_name);
634 rc = 0;
635 gmxdir->first = 0;
637 else
639 if(_findnext(gmxdir->windows_handle,&gmxdir->finddata)==0)
641 strncpy(name,gmxdir->finddata.name,maxlength_name);
642 rc = 0;
644 else
646 name[0] = '\0';
647 rc = ENOENT;
652 #else
653 gmx_fatal(FARGS,
654 "Source compiled without POSIX dirent or windows support - cannot scan directories.\n");
655 rc = -1;
656 #endif
657 return rc;
661 int
662 gmx_directory_close(gmx_directory_t gmxdir)
664 int rc;
665 #ifdef HAVE_DIRENT_H
666 rc = (gmxdir != NULL) ? closedir(gmxdir->dirent_handle) : EINVAL;
667 #elif (defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64)
668 rc = (gmxdir != NULL) ? _findclose(gmxdir->windows_handle) : EINVAL;
669 #else
670 gmx_fatal(FARGS,
671 "Source compiled without POSIX dirent or windows support - cannot scan directories.\n");
672 rc = -1;
673 #endif
675 sfree(gmxdir);
676 return rc;
682 gmx_bool search_subdirs(const char *parent, char *libdir)
684 char *ptr;
685 gmx_bool found;
687 /* Search a few common subdirectory names for the gromacs library dir */
688 sprintf(libdir,"%s%cshare%ctop%cgurgle.dat",parent,
689 DIR_SEPARATOR,DIR_SEPARATOR,DIR_SEPARATOR);
690 found=gmx_fexist(libdir);
691 if(!found) {
692 sprintf(libdir,"%s%cshare%cgromacs%ctop%cgurgle.dat",parent,
693 DIR_SEPARATOR,DIR_SEPARATOR,
694 DIR_SEPARATOR,DIR_SEPARATOR);
695 found=gmx_fexist(libdir);
697 if(!found) {
698 sprintf(libdir,"%s%cshare%cgromacs-%s%ctop%cgurgle.dat",parent,
699 DIR_SEPARATOR,DIR_SEPARATOR,VERSION,
700 DIR_SEPARATOR,DIR_SEPARATOR);
701 found=gmx_fexist(libdir);
703 if(!found) {
704 sprintf(libdir,"%s%cshare%cgromacs%cgromacs-%s%ctop%cgurgle.dat",parent,
705 DIR_SEPARATOR,DIR_SEPARATOR,DIR_SEPARATOR,
706 VERSION,DIR_SEPARATOR,DIR_SEPARATOR);
707 found=gmx_fexist(libdir);
710 /* Remove the gurgle.dat part from libdir if we found something */
711 if(found) {
712 ptr=strrchr(libdir,DIR_SEPARATOR); /* slash or backslash always present, no check necessary */
713 *ptr='\0';
715 return found;
719 /* Check if the program name begins with "/" on unix/cygwin, or
720 * with "\" or "X:\" on windows. If not, the program name
721 * is relative to the current directory.
723 static gmx_bool filename_is_absolute(char *name)
725 #if ((defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64) && !defined __CYGWIN__ && !defined __CYGWIN32__)
726 return ((name[0] == DIR_SEPARATOR) || ((strlen(name)>3) && strncmp(name+1,":\\",2)) == 0);
727 #else
728 return (name[0] == DIR_SEPARATOR);
729 #endif
732 gmx_bool get_libdir(char *libdir)
734 #define GMX_BINNAME_MAX 512
735 char bin_name[GMX_BINNAME_MAX];
736 char buf[GMX_BINNAME_MAX];
737 char full_path[GMX_PATH_MAX+GMX_BINNAME_MAX];
738 char system_path[GMX_PATH_MAX];
739 char *dir,*ptr,*s,*pdum;
740 gmx_bool found=FALSE;
741 int i;
743 if (Program() != NULL)
746 /* First - detect binary name */
747 if (strlen(Program()) >= GMX_BINNAME_MAX)
749 gmx_fatal(FARGS,"The name of the binary is longer than the allowed buffer size (%d):\n'%s'",GMX_BINNAME_MAX,Program());
751 strncpy(bin_name,Program(),GMX_BINNAME_MAX-1);
753 /* On windows & cygwin we need to add the .exe extension
754 * too, or we wont be able to detect that the file exists
756 #if (defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64 || defined __CYGWIN__ || defined __CYGWIN32__)
757 if(strlen(bin_name)<3 || gmx_strncasecmp(bin_name+strlen(bin_name)-4,".exe",4))
758 strcat(bin_name,".exe");
759 #endif
761 /* Only do the smart search part if we got a real name */
762 if (NULL!=bin_name && strncmp(bin_name,"GROMACS",GMX_BINNAME_MAX)) {
764 if (!strchr(bin_name,DIR_SEPARATOR)) {
765 /* No slash or backslash in name means it must be in the path - search it! */
766 /* Add the local dir since it is not in the path on windows */
767 #if ((defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64) && !defined __CYGWIN__ && !defined __CYGWIN32__)
768 pdum=_getcwd(system_path,sizeof(system_path)-1);
769 #else
770 pdum=getcwd(system_path,sizeof(system_path)-1);
771 #endif
772 sprintf(full_path,"%s%c%s",system_path,DIR_SEPARATOR,bin_name);
773 found = gmx_fexist(full_path);
774 if (!found && (s=getenv("PATH")) != NULL)
776 char *dupped;
778 dupped=gmx_strdup(s);
779 s=dupped;
780 while(!found && (dir=gmx_strsep(&s, PATH_SEPARATOR)) != NULL)
782 sprintf(full_path,"%s%c%s",dir,DIR_SEPARATOR,bin_name);
783 found = gmx_fexist(full_path);
785 sfree(dupped);
787 if (!found)
789 return FALSE;
791 } else if (!filename_is_absolute(bin_name)) {
792 /* name contains directory separators, but
793 * it does not start at the root, i.e.
794 * name is relative to the current dir
796 #if ((defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64) && !defined __CYGWIN__ && !defined __CYGWIN32__)
797 pdum=_getcwd(buf,sizeof(buf)-1);
798 #else
799 pdum=getcwd(buf,sizeof(buf)-1);
800 #endif
801 sprintf(full_path,"%s%c%s",buf,DIR_SEPARATOR,bin_name);
802 } else {
803 strncpy(full_path,bin_name,GMX_PATH_MAX);
806 /* Now we should have a full path and name in full_path,
807 * but on unix it might be a link, or a link to a link to a link..
809 #if (!defined WIN32 && !defined _WIN32 && !defined WIN64 && !defined _WIN64)
810 while( (i=readlink(full_path,buf,sizeof(buf)-1)) > 0 ) {
811 buf[i]='\0';
812 /* If it doesn't start with "/" it is relative */
813 if (buf[0]!=DIR_SEPARATOR) {
814 strncpy(strrchr(full_path,DIR_SEPARATOR)+1,buf,GMX_PATH_MAX);
815 } else
816 strncpy(full_path,buf,GMX_PATH_MAX);
818 #endif
820 /* Remove the executable name - it always contains at least one slash */
821 *(strrchr(full_path,DIR_SEPARATOR)+1)='\0';
822 /* Now we have the full path to the gromacs executable.
823 * Use it to find the library dir.
825 found=FALSE;
826 while(!found && ( (ptr=strrchr(full_path,DIR_SEPARATOR)) != NULL ) ) {
827 *ptr='\0';
828 found=search_subdirs(full_path,libdir);
832 /* End of smart searching. If we didn't find it in our parent tree,
833 * or if the program name wasn't set, at least try some standard
834 * locations before giving up, in case we are running from e.g.
835 * a users home directory. This only works on unix or cygwin...
837 #if ((!defined WIN32 && !defined _WIN32 && !defined WIN64 && !defined _WIN64) || defined __CYGWIN__ || defined __CYGWIN32__)
838 if(!found)
839 found=search_subdirs("/usr/local",libdir);
840 if(!found)
841 found=search_subdirs("/usr",libdir);
842 if(!found)
843 found=search_subdirs("/opt",libdir);
844 #endif
845 return found;
849 char *low_gmxlibfn(const char *file, gmx_bool bAddCWD, gmx_bool bFatal)
851 char *ret;
852 char *lib,*dir;
853 char buf[1024];
854 char libpath[GMX_PATH_MAX];
855 gmx_bool env_is_set=FALSE;
856 char *s,tmppath[GMX_PATH_MAX];
858 /* GMXLIB can be a path now */
859 lib=getenv("GMXLIB");
860 if (lib != NULL)
862 env_is_set=TRUE;
863 strncpy(libpath,lib,GMX_PATH_MAX);
865 else if (!get_libdir(libpath))
867 strncpy(libpath,GMXLIBDIR,GMX_PATH_MAX);
870 ret = NULL;
871 if (bAddCWD && gmx_fexist(file))
873 ret = gmx_strdup(file);
875 else
877 strncpy(tmppath,libpath,GMX_PATH_MAX);
878 s=tmppath;
879 while(ret == NULL && (dir=gmx_strsep(&s, PATH_SEPARATOR)) != NULL )
881 sprintf(buf,"%s%c%s",dir,DIR_SEPARATOR,file);
882 if (gmx_fexist(buf))
884 ret = gmx_strdup(buf);
887 if (ret == NULL && bFatal)
889 if (env_is_set)
891 gmx_fatal(FARGS,
892 "Library file %s not found %sin your GMXLIB path.",
893 file, bAddCWD ? "in current dir nor " : "");
895 else
897 gmx_fatal(FARGS,
898 "Library file %s not found %sin default directories.\n"
899 "(You can set the directories to search with the GMXLIB path variable)",
900 file, bAddCWD ? "in current dir nor " : "");
905 return ret;
912 FILE *low_libopen(const char *file,gmx_bool bFatal)
914 FILE *ff;
915 char *fn;
917 fn=low_gmxlibfn(file,TRUE,bFatal);
919 if (fn==NULL) {
920 ff=NULL;
921 } else {
922 if (debug)
923 fprintf(debug,"Opening library file %s\n",fn);
924 ff=fopen(fn,"r");
926 sfree(fn);
928 return ff;
931 char *gmxlibfn(const char *file)
933 return low_gmxlibfn(file,TRUE,TRUE);
936 FILE *libopen(const char *file)
938 return low_libopen(file,TRUE);
941 void gmx_tmpnam(char *buf)
943 int i,len,fd;
945 if ((len = strlen(buf)) < 7)
946 gmx_fatal(FARGS,"Buf passed to gmx_tmpnam must be at least 7 bytes long");
947 for(i=len-6; (i<len); i++) {
948 buf[i] = 'X';
950 /* mktemp is dangerous and we should use mkstemp instead, but
951 * since windows doesnt support it we have to separate the cases.
952 * 20090307: mktemp deprecated, use iso c++ _mktemp instead.
954 #if ((defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64) && !defined __CYGWIN__ && !defined __CYGWIN32__)
955 _mktemp(buf);
956 #else
957 fd = mkstemp(buf);
959 switch (fd) {
960 case EINVAL:
961 gmx_fatal(FARGS,"Invalid template %s for mkstemp",buf);
962 break;
963 case EEXIST:
964 gmx_fatal(FARGS,"mkstemp created existing file",buf);
965 break;
966 case EACCES:
967 gmx_fatal(FARGS,"Permission denied for opening %s",buf);
968 break;
969 default:
970 break;
972 close(fd);
973 #endif
974 /* name in Buf should now be OK */
977 int gmx_truncatefile(char *path, gmx_off_t length)
979 #ifdef _MSC_VER
980 /* Microsoft visual studio does not have "truncate" */
981 HANDLE fh;
982 LARGE_INTEGER win_length;
984 win_length.QuadPart = length;
986 fh = CreateFile(path,GENERIC_READ | GENERIC_WRITE,0,NULL,
987 OPEN_EXISTING,0,NULL);
988 SetFilePointerEx(fh,win_length,NULL,FILE_BEGIN);
989 SetEndOfFile(fh);
990 CloseHandle(fh);
992 return 0;
993 #else
994 return truncate(path,length);
995 #endif
999 int gmx_file_rename(const char *oldname, const char *newname)
1001 #if (!(defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64)))
1002 /* under unix, rename() is atomic (at least, it should be). */
1003 return rename(oldname, newname);
1004 #else
1005 if (MoveFileEx(oldname, newname,
1006 MOVEFILE_REPLACE_EXISTING|MOVEFILE_WRITE_THROUGH))
1007 return 0;
1008 else
1009 return 1;
1010 #endif
1013 int gmx_file_copy(const char *oldname, const char *newname, gmx_bool copy_if_empty)
1015 /* the full copy buffer size: */
1016 #define FILECOPY_BUFSIZE (1<<16)
1017 FILE *in=NULL;
1018 FILE *out=NULL;
1019 char *buf;
1021 snew(buf, FILECOPY_BUFSIZE);
1023 in=fopen(oldname, "rb");
1024 if (!in)
1025 goto error;
1027 /* If we don't copy when empty, we postpone opening the file
1028 until we're actually ready to write. */
1029 if (copy_if_empty)
1031 out=fopen(newname, "wb");
1032 if (!out)
1033 goto error;
1036 while(!feof(in))
1038 size_t nread;
1040 nread=fread(buf, sizeof(char), FILECOPY_BUFSIZE, in);
1041 if (nread>0)
1043 size_t ret;
1044 if (!out)
1046 /* so this is where we open when copy_if_empty is false:
1047 here we know we read something. */
1048 out=fopen(newname, "wb");
1049 if (!out)
1050 goto error;
1052 ret=fwrite(buf, sizeof(char), nread, out);
1053 if (ret!=nread)
1055 goto error;
1058 if (ferror(in))
1059 goto error;
1061 sfree(buf);
1062 fclose(in);
1063 fclose(out);
1064 return 0;
1065 error:
1066 sfree(buf);
1067 if (in)
1068 fclose(in);
1069 if (out)
1070 fclose(out);
1071 return 1;
1072 #undef FILECOPY_BUFSIZE
1076 int gmx_fsync(FILE *fp)
1078 int rc=0;
1080 #ifdef GMX_FAHCORE
1081 /* the fahcore defines its own os-independent fsync */
1082 rc=fah_fsync(fp);
1083 #else /* GMX_FAHCORE */
1085 int fn=-1;
1087 /* get the file number */
1088 #if defined(HAVE_FILENO)
1089 fn= fileno(fp);
1090 #elif defined(HAVE__FILENO)
1091 fn= _fileno(fp);
1092 #endif
1094 /* do the actual fsync */
1095 if (fn >= 0)
1097 #if (defined(HAVE_FSYNC))
1098 rc=fsync(fn);
1099 #elif (defined(HAVE__COMMIT))
1100 rc=_commit(fn);
1101 #endif
1104 #endif /* GMX_FAHCORE */
1106 /* We check for these error codes this way because POSIX requires them
1107 to be defined, and using anything other than macros is unlikely: */
1108 #ifdef EINTR
1109 /* we don't want to report an error just because fsync() caught a signal.
1110 For our purposes, we can just ignore this. */
1111 if (rc && errno==EINTR)
1112 rc=0;
1113 #endif
1114 #ifdef EINVAL
1115 /* we don't want to report an error just because we tried to fsync()
1116 stdout, a socket or a pipe. */
1117 if (rc && errno==EINVAL)
1118 rc=0;
1119 #endif
1120 return rc;