Actual source code: sysio.c

  1: #define PETSC_DLL

  3: /* 
  4:    This file contains simple binary read/write routines.
  5:  */

 7:  #include petsc.h
 8:  #include petscsys.h

 10: #include <errno.h>
 11: #include <fcntl.h>
 12: #if defined(PETSC_HAVE_UNISTD_H)
 13: #include <unistd.h>
 14: #endif
 15: #if defined (PETSC_HAVE_IO_H)
 16: #include <io.h>
 17: #endif
 18:  #include petscbt.h

 20: #if (PETSC_SIZEOF_INT == 8)
 21: #define PetscInt32 short
 22: #else
 23: #define PetscInt32 int
 24: #endif

 26: #if !defined(PETSC_WORDS_BIGENDIAN)

 30: /*
 31:   PetscByteSwapInt - Swap bytes in a 32 bit integer. NOT a PetscInt! Note that PETSc binary read and write
 32:       always store and read only 32 bit integers! (See PetscBinaryRead(), PetscBinaryWrite()).

 34: */
 35: PetscErrorCode PETSC_DLLEXPORT PetscByteSwapInt(PetscInt32 *buff,PetscInt n)
 36: {
 37:   PetscInt  i,j,tmp = 0;
 38:   PetscInt  *tptr = &tmp;                /* Need to access tmp indirectly to get */
 39:   char      *ptr1,*ptr2 = (char*)&tmp; /* arround the bug in DEC-ALPHA g++ */
 40: 
 42:   for (j=0; j<n; j++) {
 43:     ptr1 = (char*)(buff + j);
 44:     for (i=0; i<(int)sizeof(PetscInt32); i++) {
 45:       ptr2[i] = ptr1[sizeof(PetscInt32)-1-i];
 46:     }
 47:     buff[j] = *tptr;
 48:   }
 49:   return(0);
 50: }
 51: /* --------------------------------------------------------- */
 54: /*
 55:   PetscByteSwapShort - Swap bytes in a short
 56: */
 57: PetscErrorCode PETSC_DLLEXPORT PetscByteSwapShort(short *buff,PetscInt n)
 58: {
 59:   PetscInt   i,j;
 60:   short      tmp;
 61:   short      *tptr = &tmp;           /* take care pf bug in DEC-ALPHA g++ */
 62:   char       *ptr1,*ptr2 = (char*)&tmp;

 65:   for (j=0; j<n; j++) {
 66:     ptr1 = (char*)(buff + j);
 67:     for (i=0; i<(int) sizeof(short); i++) {
 68:       ptr2[i] = ptr1[sizeof(int)-1-i];
 69:     }
 70:     buff[j] = *tptr;
 71:   }
 72:   return(0);
 73: }
 74: /* --------------------------------------------------------- */
 77: /*
 78:   PetscByteSwapScalar - Swap bytes in a double
 79:   Complex is dealt with as if array of double twice as long.
 80: */
 81: PetscErrorCode PETSC_DLLEXPORT PetscByteSwapScalar(PetscScalar *buff,PetscInt n)
 82: {
 83:   PetscInt  i,j;
 84:   PetscReal tmp,*buff1 = (PetscReal*)buff;
 85:   PetscReal *tptr = &tmp;          /* take care pf bug in DEC-ALPHA g++ */
 86:   char      *ptr1,*ptr2 = (char*)&tmp;

 89: #if defined(PETSC_USE_COMPLEX)
 90:   n *= 2;
 91: #endif
 92:   for (j=0; j<n; j++) {
 93:     ptr1 = (char*)(buff1 + j);
 94:     for (i=0; i<(int) sizeof(PetscReal); i++) {
 95:       ptr2[i] = ptr1[sizeof(PetscReal)-1-i];
 96:     }
 97:     buff1[j] = *tptr;
 98:   }
 99:   return(0);
100: }
101: /* --------------------------------------------------------- */
104: /*
105:   PetscByteSwapDouble - Swap bytes in a double
106: */
107: PetscErrorCode PETSC_DLLEXPORT PetscByteSwapDouble(double *buff,PetscInt n)
108: {
109:   PetscInt i,j;
110:   double   tmp,*buff1 = (double*)buff;
111:   double   *tptr = &tmp;          /* take care pf bug in DEC-ALPHA g++ */
112:   char     *ptr1,*ptr2 = (char*)&tmp;

115:   for (j=0; j<n; j++) {
116:     ptr1 = (char*)(buff1 + j);
117:     for (i=0; i<(int) sizeof(double); i++) {
118:       ptr2[i] = ptr1[sizeof(double)-1-i];
119:     }
120:     buff1[j] = *tptr;
121:   }
122:   return(0);
123: }
124: #endif
125: /* --------------------------------------------------------- */
128: /*@C
129:    PetscBinaryRead - Reads from a binary file.

131:    Not Collective

133:    Input Parameters:
134: +  fd - the file
135: .  n  - the number of items to read 
136: -  type - the type of items to read (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)

138:    Output Parameters:
139: .  p - the buffer



143:    Level: developer

145:    Notes: 
146:    PetscBinaryRead() uses byte swapping to work on all machines; the files
147:    are written to file ALWAYS using big-endian ordering. On small-endian machines the numbers
148:    are converted to the small-endian format when they are read in from the file.
149:    Integers are stored on the file as 32 bits long, regardless of whether
150:    they are stored in the machine as 32 bits or 64 bits, this means the same
151:    binary file may be read on any machine.

153:    Concepts: files^reading binary
154:    Concepts: binary files^reading

156: .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose()
157: @*/
158: PetscErrorCode PETSC_DLLEXPORT PetscBinaryRead(int fd,void *p,PetscInt n,PetscDataType type)
159: {
160: #if (PETSC_SIZEOF_INT == 8) || defined(PETSC_USE_64BIT_INT) || !defined(PETSC_WORDS_BIGENDIAN)
161:   PetscErrorCode    ierr;
162: #endif
163:   int               wsize,err;
164:   size_t            m = (size_t) n,maxblock = 65536;
165:   char              *pp = (char*)p;
166: #if (PETSC_SIZEOF_INT == 8) || !defined(PETSC_WORDS_BIGENDIAN) || defined(PETSC_USE_64BIT_INT)
167:   void              *ptmp = p;
168: #endif

171:   if (!n) return(0);

173:   if (type == PETSC_INT){
174:     m   *= sizeof(PetscInt32);
175: #if (PETSC_SIZEOF_INT == 8) || defined(PETSC_USE_64BIT_INT)
176:     /* read them in as 32 bit ints, later stretch into ints */
177:     PetscMalloc(m,&pp);
178:     ptmp = (void*)pp;
179: #endif
180:   }
181:   else if (type == PETSC_SCALAR)  m *= sizeof(PetscScalar);
182:   else if (type == PETSC_DOUBLE)  m *= sizeof(double);
183:   else if (type == PETSC_SHORT)   m *= sizeof(short);
184:   else if (type == PETSC_CHAR)    m *= sizeof(char);
185:   else if (type == PETSC_ENUM)    m *= sizeof(PetscEnum);
186:   else if (type == PETSC_TRUTH)   m *= sizeof(PetscTruth);
187:   else if (type == PETSC_LOGICAL) m  = PetscBTLength(m)*sizeof(char);
188:   else SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Unknown type");
189: 
190:   while (m) {
191:     wsize = (m < maxblock) ? m : maxblock;
192:     err = read(fd,pp,wsize);
193:     if (err < 0 && errno == EINTR) continue;
194:     if (!err && wsize > 0) SETERRQ(PETSC_ERR_FILE_READ,"Read past end of file");
195:     if (err < 0) SETERRQ(PETSC_ERR_FILE_READ,"Error reading from file");
196:     m  -= err;
197:     pp += err;
198:   }
199: #if !defined(PETSC_WORDS_BIGENDIAN)
200:   if      (type == PETSC_INT)    {PetscByteSwapInt((PetscInt32*)ptmp,n);}
201:   else if (type == PETSC_ENUM)   {PetscByteSwapInt((PetscInt32*)ptmp,n);}
202:   else if (type == PETSC_TRUTH)  {PetscByteSwapInt((PetscInt32*)ptmp,n);}
203:   else if (type == PETSC_SCALAR) {PetscByteSwapScalar((PetscScalar*)ptmp,n);}
204:   else if (type == PETSC_DOUBLE) {PetscByteSwapDouble((double*)ptmp,n);}
205:   else if (type == PETSC_SHORT)  {PetscByteSwapShort((short*)ptmp,n);}
206: #endif

208: #if (PETSC_SIZEOF_INT == 8) || defined(PETSC_USE_64BIT_INT)
209:   if (type == PETSC_INT) {
210:     PetscInt   *p_int = (PetscInt*)p,i;
211:     PetscInt32 *p_short = (PetscInt32 *)ptmp;
212:     for (i=0; i<n; i++) {
213:       p_int[i] = (PetscInt)p_short[i];
214:     }
215:     PetscFree(ptmp);
216:   }
217: #endif
218:   return(0);
219: }
220: /* --------------------------------------------------------- */
223: /*@C
224:    PetscBinaryWrite - Writes to a binary file.

226:    Not Collective

228:    Input Parameters:
229: +  fd     - the file
230: .  p      - the buffer
231: .  n      - the number of items to write
232: .  type   - the type of items to read (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)
233: -  istemp - PETSC_FALSE if buffer data should be preserved, PETSC_TRUE otherwise.

235:    Level: advanced

237:    Notes: 
238:    PetscBinaryWrite() uses byte swapping to work on all machines; the files
239:    are written using big-endian ordering to the file. On small-endian machines the numbers
240:    are converted to the big-endian format when they are written to disk.
241:    Integers are stored on the file as 32 bits long, regardless of whether
242:    they are stored in the machine as 32 bits or 64 bits, this means the same
243:    binary file may be read on any machine. It also means that 64 bit integers larger than
244:    roughly 2 billion are TRUNCATED/WRONG when written to the file.

246:    The Buffer p should be read-write buffer, and not static data.
247:    This way, byte-swapping is done in-place, and then the buffer is
248:    written to the file.
249:    
250:    This routine restores the original contents of the buffer, after 
251:    it is written to the file. This is done by byte-swapping in-place 
252:    the second time. If the flag istemp is set to PETSC_TRUE, the second
253:    byte-swapping operation is not done, thus saving some computation,
254:    but the buffer corrupted is corrupted.

256:    Concepts: files^writing binary
257:    Concepts: binary files^writing

259: .seealso: PetscBinaryRead(), PetscBinaryOpen(), PetscBinaryClose()
260: @*/
261: PetscErrorCode PETSC_DLLEXPORT PetscBinaryWrite(int fd,void *p,PetscInt n,PetscDataType type,PetscTruth istemp)
262: {
263:   char           *pp = (char*)p;
264:   int            err,wsize;
265:   size_t         m = (size_t)n,maxblock=65536;
266: #if !defined(PETSC_WORDS_BIGENDIAN) || (PETSC_SIZEOF_INT == 8) ||  defined(PETSC_USE_64BIT_INT)
268:   void           *ptmp = p;
269: #endif

272:   if (n < 0) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Trying to write a negative amount of data %D",n);
273:   if (!n) return(0);

275:   if (type == PETSC_INT){
276:     m   *= sizeof(PetscInt32);
277: #if (PETSC_SIZEOF_INT == 8) || defined(PETSC_USE_64BIT_INT)
278:     PetscInt   *p_int = (PetscInt*)p,i;
279:     PetscInt32 *p_short;
280:     PetscMalloc(m,&pp);
281:     ptmp    = (void*)pp;
282:     p_short = (PetscInt32*)pp;

284:     for (i=0; i<n; i++) {
285:       p_short[i] = (PetscInt32) p_int[i];
286:     }
287:     istemp = PETSC_TRUE;
288: #endif
289:   }
290:   else if (type == PETSC_SCALAR)  m *= sizeof(PetscScalar);
291:   else if (type == PETSC_DOUBLE)  m *= sizeof(double);
292:   else if (type == PETSC_SHORT)   m *= sizeof(short);
293:   else if (type == PETSC_CHAR)    m *= sizeof(char);
294:   else if (type == PETSC_ENUM)    m *= sizeof(PetscEnum);
295:   else if (type == PETSC_TRUTH)   m *= sizeof(PetscTruth);
296:   else if (type == PETSC_LOGICAL) m = PetscBTLength(m)*sizeof(char);
297:   else SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Unknown type");

299: #if !defined(PETSC_WORDS_BIGENDIAN)
300:   if      (type == PETSC_INT)    {PetscByteSwapInt((PetscInt32*)ptmp,n);}
301:   else if (type == PETSC_ENUM)   {PetscByteSwapInt((PetscInt32*)ptmp,n);}
302:   else if (type == PETSC_TRUTH)  {PetscByteSwapInt((PetscInt32*)ptmp,n);}
303:   else if (type == PETSC_SCALAR) {PetscByteSwapScalar((PetscScalar*)ptmp,n);}
304:   else if (type == PETSC_DOUBLE) {PetscByteSwapDouble((double*)ptmp,n);}
305:   else if (type == PETSC_SHORT)  {PetscByteSwapShort((short*)ptmp,n);}
306: #endif

308:   while (m) {
309:     wsize = (m < maxblock) ? m : maxblock;
310:     err = write(fd,pp,wsize);
311:     if (err < 0 && errno == EINTR) continue;
312:     if (err != wsize) SETERRQ(PETSC_ERR_FILE_WRITE,"Error writing to file.");
313:     m -= wsize;
314:     pp += wsize;
315:   }

317: #if !defined(PETSC_WORDS_BIGENDIAN) && !(PETSC_SIZEOF_INT == 8) && !defined(PETSC_USE_64BIT_INT)
318:   if (!istemp) {
319:     if      (type == PETSC_SCALAR) {PetscByteSwapScalar((PetscScalar*)ptmp,n);}
320:     else if (type == PETSC_SHORT)  {PetscByteSwapShort((short*)ptmp,n);}
321:     else if (type == PETSC_INT)    {PetscByteSwapInt((PetscInt32*)ptmp,n);}
322:     else if (type == PETSC_ENUM)   {PetscByteSwapInt((PetscInt32*)ptmp,n);}
323:     else if (type == PETSC_TRUTH)  {PetscByteSwapInt((PetscInt32*)ptmp,n);}
324:   }
325: #endif

327: #if (PETSC_SIZEOF_INT == 8) || defined(PETSC_USE_64BIT_INT)
328:   if (type == PETSC_INT){
329:     PetscFree(ptmp);
330:   }
331: #endif
332:   return(0);
333: }

337: /*@C
338:    PetscBinaryOpen - Opens a PETSc binary file.

340:    Not Collective

342:    Input Parameters:
343: +  name - filename
344: -  type - type of binary file, on of PETSC_FILE_RDONLY, PETSC_FILE_WRONLY, PETSC_FILE_CREATE

346:    Output Parameter:
347: .  fd - the file

349:    Level: advanced

351:   Concepts: files^opening binary
352:   Concepts: binary files^opening

354:    Notes: Files access with PetscBinaryRead() and PetscBinaryWrite() are ALWAYS written in
355:    big-endian format. This means the file can be accessed using PetscBinaryOpen() and
356:    PetscBinaryRead() and PetscBinaryWrite() on any machine.

358: .seealso: PetscBinaryRead(), PetscBinaryWrite()
359: @*/
360: PetscErrorCode PETSC_DLLEXPORT PetscBinaryOpen(const char name[],int type,int *fd)
361: {
363: #if defined(PETSC_HAVE_O_BINARY) 
364:   if (type == PETSC_FILE_CREATE) {
365:     if ((*fd = open(name,O_WRONLY|O_CREAT|O_TRUNC|O_BINARY,0666)) == -1) {
366:       SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot create file for writing: %s",name);
367:     }
368:   } else if (type == PETSC_FILE_RDONLY) {
369:     if ((*fd = open(name,O_RDONLY|O_BINARY,0)) == -1) {
370:       SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open file for reading: %s",name);
371:     }
372:   } else if (type == PETSC_FILE_WRONLY) {
373:     if ((*fd = open(name,O_WRONLY|O_BINARY,0)) == -1) {
374:       SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open file for writing: %s",name);
375:     }
376: #else
377:   if (type == PETSC_FILE_CREATE) {
378:     if ((*fd = creat(name,0666)) == -1) {
379:       SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot create file for writing: %s",name);
380:     }
381:   } else if (type == PETSC_FILE_RDONLY) {
382:     if ((*fd = open(name,O_RDONLY,0)) == -1) {
383:       SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open file for reading: %s",name);
384:     }
385:   }
386:   else if (type == PETSC_FILE_WRONLY) {
387:     if ((*fd = open(name,O_WRONLY,0)) == -1) {
388:       SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open file for writing: %s",name);
389:     }
390: #endif
391:   } else SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Unknown file type");
392:   return(0);
393: }

397: /*@C
398:    PetscBinaryClose - Closes a PETSc binary file.

400:    Not Collective

402:    Output Parameter:
403: .  fd - the file

405:    Level: advanced

407: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen()
408: @*/
409: PetscErrorCode PETSC_DLLEXPORT PetscBinaryClose(int fd)
410: {
412:   close(fd);
413:   return(0);
414: }


419: /*@C
420:    PetscBinarySeek - Moves the file pointer on a PETSc binary file.

422:    Not Collective

424:    Input Parameters:
425: +  fd - the file
426: .  whence - if PETSC_BINARY_SEEK_SET then size is an absolute location in the file
427:             if PETSC_BINARY_SEEK_CUR then size is offset from current location
428:             if PETSC_BINARY_SEEK_END then size is offset from end of file
429: -  size - number of bytes to move. Use PETSC_BINARY_INT_SIZE, PETSC_BINARY_SCALAR_SIZE,
430:             etc. in your calculation rather than sizeof() to compute byte lengths.

432:    Output Parameter:
433: .   offset - new offset in file

435:    Level: developer

437:    Notes: 
438:    Integers are stored on the file as 32 long, regardless of whether
439:    they are stored in the machine as 32 or 64, this means the same
440:    binary file may be read on any machine. Hence you CANNOT use sizeof()
441:    to determine the offset or location.

443:    Concepts: files^binary seeking
444:    Concepts: binary files^seeking

446: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen()
447: @*/
448: PetscErrorCode PETSC_DLLEXPORT PetscBinarySeek(int fd,off_t off,PetscBinarySeekType whence,off_t *offset)
449: {
450: #if defined(PETSC_HAVE_LSEEK) || defined(PETSC_HAVE__LSEEK) 
451:   int iwhence=0;
452: #endif

455:   if (whence == PETSC_BINARY_SEEK_SET) {
456:     iwhence = SEEK_SET;
457:   } else if (whence == PETSC_BINARY_SEEK_CUR) {
458:     iwhence = SEEK_CUR;
459:   } else if (whence == PETSC_BINARY_SEEK_END) {
460:     iwhence = SEEK_END;
461:   } else {
462:     SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Unknown seek location");
463:   }
464: #if defined(PETSC_HAVE_LSEEK)
465:   *offset = lseek(fd,off,iwhence);
466: #elif defined(PETSC_HAVE__LSEEK)
467:   *offset = _lseek(fd,(long)off,iwhence);
468: #else
469:   SETERRQ(PETSC_ERR_SUP_SYS,"System does not have a way of seeking on a file");
470: #endif
471:   return(0);
472: }

476: /*@C
477:    PetscSynchronizedBinaryRead - Reads from a binary file.

479:    Collective on MPI_Comm

481:    Input Parameters:
482: +  comm - the MPI communicator 
483: .  fd - the file
484: .  n  - the number of items to read 
485: -  type - the type of items to read (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)

487:    Output Parameters:
488: .  p - the buffer

490:    Options Database Key:
491: .   -binary_longints - indicates the file was generated on a Cray vector 
492:          machine (not the T3E/D) and the ints are stored as 64 bit 
493:          quantities, otherwise they are stored as 32 bit

495:    Level: developer

497:    Notes: 
498:    Does a PetscBinaryRead() followed by an MPI_Bcast()

500:    PetscSynchronizedBinaryRead() uses byte swapping to work on all machines.
501:    Integers are stored on the file as 32 long, regardless of whether
502:    they are stored in the machine as 32 or 64, this means the same
503:    binary file may be read on any machine.

505:    Concepts: files^synchronized reading of binary files
506:    Concepts: binary files^reading, synchronized

508: .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscBinaryRead()
509: @*/
510: PetscErrorCode PETSC_DLLEXPORT PetscSynchronizedBinaryRead(MPI_Comm comm,int fd,void *p,PetscInt n,PetscDataType type)
511: {
513:   PetscMPIInt    rank;
514:   MPI_Datatype   mtype;

517:   MPI_Comm_rank(comm,&rank);
518:   if (!rank) {
519:     PetscBinaryRead(fd,p,n,type);
520:   }
521:   PetscDataTypeToMPIDataType(type,&mtype);
522:   MPI_Bcast(p,n,mtype,0,comm);
523:   return(0);
524: }

528: /*@C
529:    PetscSynchronizedBinaryWrite - writes to a binary file.

531:    Collective on MPI_Comm

533:    Input Parameters:
534: +  comm - the MPI communicator 
535: .  fd - the file
536: .  n  - the number of items to write
537: .  p - the buffer
538: .  istemp - the buffer may be changed
539: -  type - the type of items to write (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)

541:    Level: developer

543:    Notes: 
544:    Process 0 does a PetscBinaryWrite()

546:    PetscSynchronizedBinaryWrite() uses byte swapping to work on all machines.
547:    Integers are stored on the file as 32 long, regardless of whether
548:    they are stored in the machine as 32 or 64, this means the same
549:    binary file may be read on any machine.

551:    Concepts: files^synchronized writing of binary files
552:    Concepts: binary files^reading, synchronized

554: .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscBinaryRead()
555: @*/
556: PetscErrorCode PETSC_DLLEXPORT PetscSynchronizedBinaryWrite(MPI_Comm comm,int fd,void *p,PetscInt n,PetscDataType type,PetscTruth istemp)
557: {
559:   PetscMPIInt    rank;

562:   MPI_Comm_rank(comm,&rank);
563:   if (!rank) {
564:     PetscBinaryWrite(fd,p,n,type,istemp);
565:   }
566:   return(0);
567: }

571: /*@C
572:    PetscSynchronizedBinarySeek - Moves the file pointer on a PETSc binary file.


575:    Input Parameters:
576: +  fd - the file
577: .  whence - if PETSC_BINARY_SEEK_SET then size is an absolute location in the file
578:             if PETSC_BINARY_SEEK_CUR then size is offset from current location
579:             if PETSC_BINARY_SEEK_END then size is offset from end of file
580: -  off    - number of bytes to move. Use PETSC_BINARY_INT_SIZE, PETSC_BINARY_SCALAR_SIZE,
581:             etc. in your calculation rather than sizeof() to compute byte lengths.

583:    Output Parameter:
584: .   offset - new offset in file

586:    Level: developer

588:    Notes: 
589:    Integers are stored on the file as 32 long, regardless of whether
590:    they are stored in the machine as 32 or 64, this means the same
591:    binary file may be read on any machine. Hence you CANNOT use sizeof()
592:    to determine the offset or location.

594:    Concepts: binary files^seeking
595:    Concepts: files^seeking in binary 

597: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen()
598: @*/
599: PetscErrorCode PETSC_DLLEXPORT PetscSynchronizedBinarySeek(MPI_Comm comm,int fd,off_t off,PetscBinarySeekType whence,off_t *offset)
600: {
602:   PetscMPIInt    rank;

605:   MPI_Comm_rank(comm,&rank);
606:   if (!rank) {
607:     PetscBinarySeek(fd,off,whence,offset);
608:   }
609:   return(0);
610: }