NAMD
common.C
Go to the documentation of this file.
1 
7 /*
8  global functions as declared in common.h
9 */
10 
11 #if !defined(WIN32) || defined(__CYGWIN__)
12 #include <unistd.h>
13 #endif
14 #include <errno.h>
15 #include <string.h>
16 #include <fcntl.h>
17 #include <sys/stat.h>
18 #include <ctype.h>
19 
20 #include "common.h"
21 #include "InfoStream.h"
22 
23 #include "charm++.h"
24 
25 #ifdef WIN32
26 #include <io.h>
27 #define access(PATH,MODE) _access(PATH,00)
28 #define NOCOMPRESSED
29 #endif
30 
31 #ifdef USESTDIOSTUBS
32 
33 // On the ASCI-Red, these functions have prototypes that don't match
34 // the standard, so I'll override them
35 
36 int write(int fd, const void* buf, int count)
37 {
38  return write(fd,(void*)buf,(size_t)count);
39 }
40 
41 int stat(const char* fn, struct stat* buf)
42 {
43  return stat((char*)fn, buf);
44 }
45 
46 #endif
47 
48 
49 // make a duplicate of a string
50 char *NAMD_stringdup(const char *s) {
51  char *rs;
52 
53  if(!s)
54  return NULL;
55 
56  rs = new char[strlen(s) + 1];
57  strcpy(rs,s);
58 
59  return rs;
60 }
61 
62 
63 // signal all nodes, it's time to quit
64 void NAMD_quit(const char *err_msg)
65 {
66  if ( ! err_msg ) err_msg = "(unknown error)";
67  CkPrintf("EXITING: %s\n", err_msg);
68  fflush(stdout);
69  char repstr[24] = "";
70  if (CmiNumPartitions() > 1) {
71  sprintf(repstr,"REPLICA %d ", CmiMyPartition());
72  // CkAbort ensures that all replicas die
73  CkAbort("%sEXITING: %s\n", repstr, err_msg);
74  }
75  CkError("%sEXITING: %s\n", repstr, err_msg);
76 #if CHARM_VERSION < 61000
77  CkExit();
78 #else
79  CkExit(0);
80 #endif
81 }
82 
83 
84 // signal all nodes, it's time to quit
85 void NAMD_die(const char *err_msg)
86 {
87  if ( ! err_msg ) err_msg = "(unknown error)";
88  CkPrintf("FATAL ERROR: %s\n", err_msg);
89  fflush(stdout);
90  char repstr[24] = "";
91  if (CmiNumPartitions() > 1) {
92  sprintf(repstr,"REPLICA %d ", CmiMyPartition());
93  // CkAbort ensures that all replicas die
94  CkAbort("%sFATAL ERROR: %s\n", repstr, err_msg);
95  }
96  CkError("%sFATAL ERROR: %s\n", repstr, err_msg);
97 #if CHARM_VERSION < 61000
98  CkExit();
99 #else
100  CkExit(1);
101 #endif
102 }
103 
104 
105 // signal all nodes, it's time to quit
106 void NAMD_err(const char *err_msg)
107 {
108  if ( ! err_msg ) err_msg = "(unknown error)";
109  const char *sys_err_msg = strerror(errno);
110  if ( ! sys_err_msg ) sys_err_msg = "(unknown error)";
111  CkPrintf("FATAL ERROR: %s: %s\n", err_msg, sys_err_msg);
112  fflush(stdout);
113  char repstr[24] = "";
114  if (CmiNumPartitions() > 1) {
115  sprintf(repstr,"REPLICA %d ", CmiMyPartition());
116  // CkAbort ensures that all replicas die
117  CkAbort("%sFATAL ERROR: %s: %s\n", repstr, err_msg, sys_err_msg);
118  }
119  CkError("%sFATAL ERROR: %s: %s\n", repstr, err_msg, sys_err_msg);
120 #if CHARM_VERSION < 61000
121  CkExit();
122 #else
123  CkExit(1);
124 #endif
125 }
126 
127 
128 // signal all nodes, it's time to quit and it's our own damn fault
129 void NAMD_bug(const char *err_msg)
130 {
131  if ( ! err_msg ) err_msg = "(unknown error)";
132  const char *bug_msg =
133  "FATAL ERROR: See http://www.ks.uiuc.edu/Research/namd/bugreport.html";
134  CkPrintf("FATAL ERROR: %s\n%s\n",err_msg, bug_msg);
135  fflush(stdout);
136  char repstr[24] = "";
137  if (CmiNumPartitions() > 1) {
138  sprintf(repstr,"REPLICA %d ", CmiMyPartition());
139  // CkAbort ensures that all replicas die
140  CkAbort("%sFATAL ERROR: %s\n%s\n", repstr, err_msg, bug_msg);
141  }
142  CkError("%sFATAL ERROR: %s\n%s\n", repstr, err_msg, bug_msg);
143 #if CHARM_VERSION < 61000
144  CkExit();
145 #else
146  CkExit(2);
147 #endif
148 }
149 
150 
151 int NAMD_file_exists(const char *filename) {
152  int rval;
153  do {
154  rval = access(filename, F_OK);
155  } while ( rval != 0 && errno == EINTR );
156  if ( rval != 0 && errno != ENOENT ) {
157  const char *sys_err_msg = strerror(errno);
158  if ( ! sys_err_msg ) sys_err_msg = "(unknown error)";
159  iout << iERROR << "Error on checking file "
160  << filename << ": " << sys_err_msg << "\n" << endi;
161  fflush(stdout);
162  }
163  return ! rval;
164 }
165 
166 // move filename to filename.BAK
167 void NAMD_backup_file(const char *filename, const char *extension)
168 {
169  if (NAMD_file_exists(filename)) {
170  if ( ! extension ) extension = ".BAK";
171  char *backup = new char[strlen(filename)+strlen(extension)+1];
172  strcpy(backup, filename);
173  strcat(backup, extension);
174 #if defined(WIN32) && !defined(__CYGWIN__)
175  if ( remove(backup) ) if ( errno != ENOENT ) {
176  char *sys_err_msg = strerror(errno);
177  if ( ! sys_err_msg ) sys_err_msg = "(unknown error)";
178  iout << iERROR << "Error on removing file "
179  << backup << ": " << sys_err_msg << "\n" << endi;
180  fflush(stdout);
181  }
182 #endif
183  while ( rename(filename,backup) )
184  {
185  if ( errno == EINTR ) continue;
186  const char *sys_err_msg = strerror(errno);
187  if ( ! sys_err_msg ) sys_err_msg = "(unknown error)";
188  iout << iERROR << "Error on renaming file " << filename
189  << " to " << backup << ": " << sys_err_msg << "\n" << endi;
190  fflush(stdout);
191  if ( errno == EXDEV ) continue;
192  break;
193  // char errmsg[256];
194  // sprintf(errmsg, "Error on renaming file %s to %s",filename,backup);
195  // NAMD_err(errmsg);
196  }
197  delete [] backup;
198  }
199 }
200 
201 // same as open, only does error checking internally
202 int NAMD_open_text(const char *fname, int append) {
203  int fd;
204 
205  // open the file and die if the open fails
206 #ifdef WIN32
207  while ( (fd = _open(fname, O_WRONLY|(append?O_APPEND:O_EXCL)|O_CREAT|O_TEXT,_S_IREAD|_S_IWRITE)) < 0) {
208 #else
209 #ifdef NAMD_NO_O_EXCL
210  while ( (fd = open(fname, O_WRONLY|(append?O_APPEND:O_TRUNC)|O_CREAT,
211 #else
212  while ( (fd = open(fname, O_WRONLY|(append?O_APPEND:O_EXCL)|O_CREAT,
213 #endif
214  S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0) {
215 #endif
216  if ( errno != EINTR ) {
217  char errmsg[1024];
218  sprintf(errmsg, "Unable to open text file %s", fname);
219  NAMD_err(errmsg);
220  }
221  }
222 
223  return fd;
224 }
225 
226 // same as write, only does error checking internally
227 void NAMD_write(int fd, const char *buf, size_t count, const char *fname) {
228  while ( count ) {
229 #if defined(WIN32) && !defined(__CYGWIN__)
230  long retval = _write(fd,buf,count);
231 #else
232  ssize_t retval = write(fd,buf,count);
233 #endif
234  if ( retval < 0 && errno == EINTR ) retval = 0;
235  if ( retval < 0 ) {
236  char errmsg[1024];
237  sprintf(errmsg, "Error on writing to file %s", fname);
238  NAMD_err(errmsg);
239  }
240  if ( retval > count ) NAMD_bug("extra bytes written in NAMD_write()");
241  buf += retval;
242  count -= retval;
243  }
244 }
245 
246 // same as close, only does error checking internally
247 void NAMD_close(int fd, const char *fname) {
248 #ifdef WIN32
249  while ( _close(fd) ) {
250 #else
251  while ( close(fd) ) {
252 #endif
253  if ( errno != EINTR ) {
254  char errmsg[1024];
255  sprintf(errmsg, "Error on closing file %s", fname);
256  NAMD_err(errmsg);
257  }
258  }
259 }
260 
261 
262 /***************************************************************************
263  Fopen(char *Filename, char *mode): similar to fopen(filename,mode) except
264  it checks for compressed file names too.
265  For example: Fopen("config");
266  This will first look for the filename "config" (and return "r" file handle
267  if it is found).
268  Then it will look for "config.Z" (and run "zcat config.Z", returning
269  a file handle to the uncompressed data if found).
270  Then it will look for "config.gz" (and run "gzip -d -c config.gz", returning
271  a file handle to the uncompressed data if found).
272  ***************************************************************************/
273 FILE *Fopen (const char *filename, const char *mode)
274 {
275  struct stat buf;
276  // check if basic filename exists (and not a directory)
277 
278 #if defined(NOCOMPRESSED)
279  if (!stat(filename,&buf))
280  {
281  FILE *rval;
282  while ( ! (rval = fopen(filename,mode)) ) {
283  if ( errno != EINTR ) break;
284  }
285  return(rval);
286  }
287 #else
288  if (!stat(filename,&buf))
289  {
290  if (!S_ISDIR(buf.st_mode)) {
291  FILE *rval;
292  while ( ! (rval = fopen(filename,mode)) ) {
293  if ( errno != EINTR ) break;
294  }
295  return(rval);
296  }
297  }
298  // check for a compressed file
299  char *realfilename;
300  char *command;
301  FILE *fout;
302  command = (char *)malloc(strlen(filename)+25);
303  // check for .Z (unix compress)
304  sprintf(command,"zcat %s.Z",filename);
305  realfilename = command+5;
306  iout << "Command = " << command << "\n" << endi;
307  iout << "Filename.Z = " << realfilename << "\n" << endi;
308  if (!stat(realfilename,&buf))
309  {
310  if (!S_ISDIR(buf.st_mode))
311  {
312  fout = popen(command,mode);
313  // on HP-UX, the first character(s) out of pipe may be
314  // garbage! (Argh!)
315  int C;
316  do
317  {
318  C = fgetc(fout);
319  // iout << "C is " << C << "\n" << endi;
320  if (isalnum(C) || isspace(C))
321  {
322  ungetc(C,fout);
323  C = -1; // outta loop
324  }
325  } while(C != -1);
326  free(command);
327  return(fout);
328  }
329  }
330  // check for .gz (gzip)
331  sprintf(command,"gzip -d -c %s.gz",filename);
332  realfilename = command+11;
333  iout << "Command = " << command << "\n" << endi;
334  iout << "Filename.gz = " << realfilename << "\n" << endi;
335  if (!stat(realfilename,&buf))
336  {
337  if (!S_ISDIR(buf.st_mode))
338  {
339  fout = popen(command,mode);
340  // on HP-UX, the first character(s) out of pipe may be
341  // garbage! (Argh!)
342  int C;
343  do
344  {
345  C = fgetc(fout);
346  // iout << "C is " << C << "\n" << endi;
347  if (isalnum(C) || isspace(C))
348  {
349  ungetc(C,fout);
350  C = -1; // outta loop
351  }
352  } while(C != -1);
353  free(command);
354  return(fout);
355  }
356  }
357  free(command);
358 #endif /* !defined(NOCOMPRESSED) */
359 
360  return(NULL);
361 } /* Fopen() */
362 
363 /***************************************************************************
364  Fclose(FILE *fout): similar to fclose(fout) except it first checks if the
365  file handle fout is a named pipe.
366  ***************************************************************************/
367 int Fclose (FILE *fout)
368 {
369  int rc = -1;
370 #if !defined(NOCOMPRESSED)
371  rc = pclose(fout);
372 #endif
373  if (rc == -1) // stream not associated with a popen()
374  {
375  rc = fclose(fout);
376  }
377  return rc;
378 } /* Fclose() */
379 
380 
void NAMD_err(const char *err_msg)
Definition: common.C:106
int NAMD_open_text(const char *fname, int append)
Definition: common.C:202
void NAMD_quit(const char *err_msg)
Definition: common.C:64
std::ostream & endi(std::ostream &s)
Definition: InfoStream.C:54
int NAMD_file_exists(const char *filename)
Definition: common.C:151
#define NAMD_write
Definition: dcdlib.C:24
#define NAMD_close
Definition: Output.C:52
#define iout
Definition: InfoStream.h:51
char * NAMD_stringdup(const char *s)
Definition: common.C:50
void NAMD_bug(const char *err_msg)
Definition: common.C:129
FILE * Fopen(const char *filename, const char *mode)
Definition: common.C:273
void NAMD_die(const char *err_msg)
Definition: common.C:85
void NAMD_backup_file(const char *filename, const char *extension)
Definition: common.C:167
int Fclose(FILE *fout)
Definition: common.C:367
std::ostream & iERROR(std::ostream &s)
Definition: InfoStream.C:83