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 !defined(PETSC_WORDS_BIGENDIAN)

 22: /* --------------------------------------------------------- */
 25: /*
 26:   PetscByteSwapEnum - Swap bytes in a  PETSc Enum

 28: */
 29: PetscErrorCode  PetscByteSwapEnum(PetscEnum *buff,PetscInt n)
 30: {
 31:   PetscInt   i,j;
 32:   PetscEnum   tmp = ENUM_DUMMY;
 33:   PetscEnum  *tptr = &tmp;             /* Need to access tmp indirectly to get */
 34:   char       *ptr1,*ptr2 = (char*)&tmp; /* arround the bug in DEC-ALPHA g++ */
 35: 
 37:   for (j=0; j<n; j++) {
 38:     ptr1 = (char*)(buff + j);
 39:     for (i=0; i<(PetscInt)sizeof(PetscEnum); i++) {
 40:       ptr2[i] = ptr1[sizeof(PetscEnum)-1-i];
 41:     }
 42:     buff[j] = *tptr;
 43:   }
 44:   return(0);
 45: }

 49: /*
 50:   PetscByteSwapTruth - Swap bytes in a  PETSc Truth

 52: */
 53: PetscErrorCode  PetscByteSwapTruth(PetscTruth *buff,PetscInt n)
 54: {
 55:   PetscInt    i,j;
 56:   PetscTruth  tmp = PETSC_FALSE;
 57:   PetscTruth  *tptr = &tmp;             /* Need to access tmp indirectly to get */
 58:   char        *ptr1,*ptr2 = (char*)&tmp; /* arround the bug in DEC-ALPHA g++ */
 59: 
 61:   for (j=0; j<n; j++) {
 62:     ptr1 = (char*)(buff + j);
 63:     for (i=0; i<(PetscInt)sizeof(PetscTruth); i++) {
 64:       ptr2[i] = ptr1[sizeof(PetscTruth)-1-i];
 65:     }
 66:     buff[j] = *tptr;
 67:   }
 68:   return(0);
 69: }

 73: /*
 74:   PetscByteSwapInt - Swap bytes in a  PETSc integer (which may be 32 or 64 bits) 

 76: */
 77: PetscErrorCode  PetscByteSwapInt(PetscInt *buff,PetscInt n)
 78: {
 79:   PetscInt  i,j,tmp = 0;
 80:   PetscInt  *tptr = &tmp;             /* Need to access tmp indirectly to get */
 81:   char       *ptr1,*ptr2 = (char*)&tmp; /* arround the bug in DEC-ALPHA g++ */
 82: 
 84:   for (j=0; j<n; j++) {
 85:     ptr1 = (char*)(buff + j);
 86:     for (i=0; i<(PetscInt)sizeof(PetscInt); i++) {
 87:       ptr2[i] = ptr1[sizeof(PetscInt)-1-i];
 88:     }
 89:     buff[j] = *tptr;
 90:   }
 91:   return(0);
 92: }
 93: /* --------------------------------------------------------- */
 96: /*
 97:   PetscByteSwapShort - Swap bytes in a short
 98: */
 99: PetscErrorCode  PetscByteSwapShort(short *buff,PetscInt n)
100: {
101:   PetscInt   i,j;
102:   short      tmp;
103:   short      *tptr = &tmp;           /* take care pf bug in DEC-ALPHA g++ */
104:   char       *ptr1,*ptr2 = (char*)&tmp;

107:   for (j=0; j<n; j++) {
108:     ptr1 = (char*)(buff + j);
109:     for (i=0; i<(PetscInt) sizeof(short); i++) {
110:       ptr2[i] = ptr1[sizeof(int)-1-i];
111:     }
112:     buff[j] = *tptr;
113:   }
114:   return(0);
115: }
116: /* --------------------------------------------------------- */
119: /*
120:   PetscByteSwapScalar - Swap bytes in a double
121:   Complex is dealt with as if array of double twice as long.
122: */
123: PetscErrorCode  PetscByteSwapScalar(PetscScalar *buff,PetscInt n)
124: {
125:   PetscInt  i,j;
126:   PetscReal tmp,*buff1 = (PetscReal*)buff;
127:   PetscReal *tptr = &tmp;          /* take care pf bug in DEC-ALPHA g++ */
128:   char      *ptr1,*ptr2 = (char*)&tmp;

131: #if defined(PETSC_USE_COMPLEX)
132:   n *= 2;
133: #endif
134:   for (j=0; j<n; j++) {
135:     ptr1 = (char*)(buff1 + j);
136:     for (i=0; i<(PetscInt) sizeof(PetscReal); i++) {
137:       ptr2[i] = ptr1[sizeof(PetscReal)-1-i];
138:     }
139:     buff1[j] = *tptr;
140:   }
141:   return(0);
142: }
143: /* --------------------------------------------------------- */
146: /*
147:   PetscByteSwapDouble - Swap bytes in a double
148: */
149: PetscErrorCode  PetscByteSwapDouble(double *buff,PetscInt n)
150: {
151:   PetscInt i,j;
152:   double   tmp,*buff1 = (double*)buff;
153:   double   *tptr = &tmp;          /* take care pf bug in DEC-ALPHA g++ */
154:   char     *ptr1,*ptr2 = (char*)&tmp;

157:   for (j=0; j<n; j++) {
158:     ptr1 = (char*)(buff1 + j);
159:     for (i=0; i<(PetscInt) sizeof(double); i++) {
160:       ptr2[i] = ptr1[sizeof(double)-1-i];
161:     }
162:     buff1[j] = *tptr;
163:   }
164:   return(0);
165: }
166: #endif
167: /* --------------------------------------------------------- */
170: /*@
171:    PetscBinaryRead - Reads from a binary file.

173:    Not Collective

175:    Input Parameters:
176: +  fd - the file
177: .  n  - the number of items to read 
178: -  type - the type of items to read (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)

180:    Output Parameters:
181: .  p - the buffer



185:    Level: developer

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

195:    Concepts: files^reading binary
196:    Concepts: binary files^reading

198: .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscViewerBinaryGetDescriptor(), PetscBinarySynchronizedWrite(),
199:           PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()
200: @*/
201: PetscErrorCode  PetscBinaryRead(int fd,void *p,PetscInt n,PetscDataType type)
202: {
203:   int               wsize,err;
204:   size_t            m = (size_t) n,maxblock = 65536;
205:   char              *pp = (char*)p;
206: #if !defined(PETSC_WORDS_BIGENDIAN)
207:   PetscErrorCode    ierr;
208:   void              *ptmp = p;
209: #endif

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

214:   if (type == PETSC_INT)          m *= sizeof(PetscInt);
215:   else if (type == PETSC_SCALAR)  m *= sizeof(PetscScalar);
216:   else if (type == PETSC_DOUBLE)  m *= sizeof(double);
217:   else if (type == PETSC_SHORT)   m *= sizeof(short);
218:   else if (type == PETSC_CHAR)    m *= sizeof(char);
219:   else if (type == PETSC_ENUM)    m *= sizeof(PetscEnum);
220:   else if (type == PETSC_TRUTH)   m *= sizeof(PetscTruth);
221:   else if (type == PETSC_LOGICAL) m  = PetscBTLength(m)*sizeof(char);
222:   else SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Unknown type");
223: 
224:   while (m) {
225:     wsize = (m < maxblock) ? m : maxblock;
226:     err = read(fd,pp,wsize);
227:     if (err < 0 && errno == EINTR) continue;
228:     if (!err && wsize > 0) SETERRQ(PETSC_ERR_FILE_READ,"Read past end of file");
229:     if (err < 0) SETERRQ1(PETSC_ERR_FILE_READ,"Error reading from file, errno %d",errno);
230:     m  -= err;
231:     pp += err;
232:   }
233: #if !defined(PETSC_WORDS_BIGENDIAN)
234:   if      (type == PETSC_INT)    {PetscByteSwapInt((PetscInt*)ptmp,n);}
235:   else if (type == PETSC_ENUM)   {PetscByteSwapEnum((PetscEnum*)ptmp,n);}
236:   else if (type == PETSC_TRUTH)  {PetscByteSwapTruth((PetscTruth*)ptmp,n);}
237:   else if (type == PETSC_SCALAR) {PetscByteSwapScalar((PetscScalar*)ptmp,n);}
238:   else if (type == PETSC_DOUBLE) {PetscByteSwapDouble((double*)ptmp,n);}
239:   else if (type == PETSC_SHORT)  {PetscByteSwapShort((short*)ptmp,n);}
240: #endif

242:   return(0);
243: }
244: /* --------------------------------------------------------- */
247: /*@
248:    PetscBinaryWrite - Writes to a binary file.

250:    Not Collective

252:    Input Parameters:
253: +  fd     - the file
254: .  p      - the buffer
255: .  n      - the number of items to write
256: .  type   - the type of items to read (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)
257: -  istemp - PETSC_FALSE if buffer data should be preserved, PETSC_TRUE otherwise.

259:    Level: advanced

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

270:    The Buffer p should be read-write buffer, and not static data.
271:    This way, byte-swapping is done in-place, and then the buffer is
272:    written to the file.
273:    
274:    This routine restores the original contents of the buffer, after 
275:    it is written to the file. This is done by byte-swapping in-place 
276:    the second time. If the flag istemp is set to PETSC_TRUE, the second
277:    byte-swapping operation is not done, thus saving some computation,
278:    but the buffer corrupted is corrupted.

280:    Concepts: files^writing binary
281:    Concepts: binary files^writing

283: .seealso: PetscBinaryRead(), PetscBinaryOpen(), PetscBinaryClose(), PetscViewerBinaryGetDescriptor(), PetscBinarySynchronizedWrite(), 
284:           PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()
285: @*/
286: PetscErrorCode  PetscBinaryWrite(int fd,void *p,PetscInt n,PetscDataType type,PetscTruth istemp)
287: {
288:   char           *pp = (char*)p;
289:   int            err,wsize;
290:   size_t         m = (size_t)n,maxblock=65536;
291: #if !defined(PETSC_WORDS_BIGENDIAN)
293:   void           *ptmp = p;
294: #endif

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

300:   if (type == PETSC_INT)          m *= sizeof(PetscInt);
301:   else if (type == PETSC_SCALAR)  m *= sizeof(PetscScalar);
302:   else if (type == PETSC_DOUBLE)  m *= sizeof(double);
303:   else if (type == PETSC_SHORT)   m *= sizeof(short);
304:   else if (type == PETSC_CHAR)    m *= sizeof(char);
305:   else if (type == PETSC_ENUM)    m *= sizeof(PetscEnum);
306:   else if (type == PETSC_TRUTH)   m *= sizeof(PetscTruth);
307:   else if (type == PETSC_LOGICAL) m = PetscBTLength(m)*sizeof(char);
308:   else SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Unknown type");

310: #if !defined(PETSC_WORDS_BIGENDIAN)
311:   if      (type == PETSC_INT)    {PetscByteSwapInt((PetscInt*)ptmp,n);}
312:   else if (type == PETSC_ENUM)   {PetscByteSwapEnum((PetscEnum*)ptmp,n);}
313:   else if (type == PETSC_TRUTH)  {PetscByteSwapTruth((PetscTruth*)ptmp,n);}
314:   else if (type == PETSC_SCALAR) {PetscByteSwapScalar((PetscScalar*)ptmp,n);}
315:   else if (type == PETSC_DOUBLE) {PetscByteSwapDouble((double*)ptmp,n);}
316:   else if (type == PETSC_SHORT)  {PetscByteSwapShort((short*)ptmp,n);}
317: #endif

319:   while (m) {
320:     wsize = (m < maxblock) ? m : maxblock;
321:     err = write(fd,pp,wsize);
322:     if (err < 0 && errno == EINTR) continue;
323:     if (err != wsize) SETERRQ(PETSC_ERR_FILE_WRITE,"Error writing to file.");
324:     m -= wsize;
325:     pp += wsize;
326:   }

328: #if !defined(PETSC_WORDS_BIGENDIAN)
329:   if (!istemp) {
330:     if      (type == PETSC_INT)    {PetscByteSwapInt((PetscInt*)ptmp,n);}
331:     else if (type == PETSC_SCALAR) {PetscByteSwapScalar((PetscScalar*)ptmp,n);}
332:     else if (type == PETSC_DOUBLE) {PetscByteSwapDouble((double*)ptmp,n);}
333:     else if (type == PETSC_SHORT)  {PetscByteSwapShort((short*)ptmp,n);}
334:     else if (type == PETSC_ENUM)   {PetscByteSwapEnum((PetscEnum*)ptmp,n);}
335:     else if (type == PETSC_TRUTH)  {PetscByteSwapTruth((PetscTruth*)ptmp,n);}
336:   }
337: #endif
338:   return(0);
339: }

343: /*@C
344:    PetscBinaryOpen - Opens a PETSc binary file.

346:    Not Collective

348:    Input Parameters:
349: +  name - filename
350: -  type - type of binary file, one of FILE_MODE_READ, FILE_MODE_APPEND, FILE_MODE_WRITE

352:    Output Parameter:
353: .  fd - the file

355:    Level: advanced

357:   Concepts: files^opening binary
358:   Concepts: binary files^opening

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

364: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscFileMode, PetscViewerFileSetMode(), PetscViewerBinaryGetDescriptor(), 
365:           PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()

367: @*/
368: PetscErrorCode  PetscBinaryOpen(const char name[],PetscFileMode mode,int *fd)
369: {
371: #if defined(PETSC_HAVE_O_BINARY) 
372:   if (mode == FILE_MODE_WRITE) {
373:     if ((*fd = open(name,O_WRONLY|O_CREAT|O_TRUNC|O_BINARY,0666)) == -1) {
374:       SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot create file for writing: %s",name);
375:     }
376:   } else if (mode == FILE_MODE_READ) {
377:     if ((*fd = open(name,O_RDONLY|O_BINARY,0)) == -1) {
378:       SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open file for reading: %s",name);
379:     }
380:   } else if (mode == FILE_MODE_APPEND) {
381:     if ((*fd = open(name,O_WRONLY|O_BINARY,0)) == -1) {
382:       SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open file for writing: %s",name);
383:     }
384: #else
385:   if (mode == FILE_MODE_WRITE) {
386:     if ((*fd = creat(name,0666)) == -1) {
387:       SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot create file for writing: %s",name);
388:     }
389:   } else if (mode == FILE_MODE_READ) {
390:     if ((*fd = open(name,O_RDONLY,0)) == -1) {
391:       SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open file for reading: %s",name);
392:     }
393:   }
394:   else if (mode == FILE_MODE_APPEND) {
395:     if ((*fd = open(name,O_WRONLY,0)) == -1) {
396:       SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open file for writing: %s",name);
397:     }
398: #endif
399:   } else SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Unknown file mode");
400:   return(0);
401: }

405: /*@
406:    PetscBinaryClose - Closes a PETSc binary file.

408:    Not Collective

410:    Output Parameter:
411: .  fd - the file

413:    Level: advanced

415: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
416:           PetscBinarySynchronizedSeek()
417: @*/
418: PetscErrorCode  PetscBinaryClose(int fd)
419: {
421:   close(fd);
422:   return(0);
423: }


428: /*@
429:    PetscBinarySeek - Moves the file pointer on a PETSc binary file.

431:    Not Collective

433:    Input Parameters:
434: +  fd - the file
435: .  off - number of bytes to move. Use PETSC_BINARY_INT_SIZE, PETSC_BINARY_SCALAR_SIZE,
436:             etc. in your calculation rather than sizeof() to compute byte lengths.
437: -  whence - if PETSC_BINARY_SEEK_SET then off is an absolute location in the file
438:             if PETSC_BINARY_SEEK_CUR then off is an offset from the current location
439:             if PETSC_BINARY_SEEK_END then off is an offset from the end of file

441:    Output Parameter:
442: .   offset - new offset in file

444:    Level: developer

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

452:    Concepts: files^binary seeking
453:    Concepts: binary files^seeking

455: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
456:           PetscBinarySynchronizedSeek()
457: @*/
458: PetscErrorCode  PetscBinarySeek(int fd,off_t off,PetscBinarySeekType whence,off_t *offset)
459: {
460:   int iwhence = 0;

463:   if (whence == PETSC_BINARY_SEEK_SET) {
464:     iwhence = SEEK_SET;
465:   } else if (whence == PETSC_BINARY_SEEK_CUR) {
466:     iwhence = SEEK_CUR;
467:   } else if (whence == PETSC_BINARY_SEEK_END) {
468:     iwhence = SEEK_END;
469:   } else {
470:     SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Unknown seek location");
471:   }
472: #if defined(PETSC_HAVE_LSEEK)
473:   *offset = lseek(fd,off,iwhence);
474: #elif defined(PETSC_HAVE__LSEEK)
475:   *offset = _lseek(fd,(long)off,iwhence);
476: #else
477:   SETERRQ(PETSC_ERR_SUP_SYS,"System does not have a way of seeking on a file");
478: #endif
479:   return(0);
480: }

484: /*@C
485:    PetscBinarySynchronizedRead - Reads from a binary file.

487:    Collective on MPI_Comm

489:    Input Parameters:
490: +  comm - the MPI communicator 
491: .  fd - the file
492: .  n  - the number of items to read 
493: -  type - the type of items to read (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)

495:    Output Parameters:
496: .  p - the buffer

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

503:    Level: developer

505:    Notes: 
506:    Does a PetscBinaryRead() followed by an MPI_Bcast()

508:    PetscBinarySynchronizedRead() uses byte swapping to work on all machines.
509:    Integers are stored on the file as 32 long, regardless of whether
510:    they are stored in the machine as 32 or 64, this means the same
511:    binary file may be read on any machine.

513:    Concepts: files^synchronized reading of binary files
514:    Concepts: binary files^reading, synchronized

516: .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscBinaryRead(), PetscBinarySynchronizedWrite(), 
517:           PetscBinarySynchronizedSeek()
518: @*/
519: PetscErrorCode  PetscBinarySynchronizedRead(MPI_Comm comm,int fd,void *p,PetscInt n,PetscDataType type)
520: {
522:   PetscMPIInt    rank;
523:   MPI_Datatype   mtype;

526:   MPI_Comm_rank(comm,&rank);
527:   if (!rank) {
528:     PetscBinaryRead(fd,p,n,type);
529:   }
530:   PetscDataTypeToMPIDataType(type,&mtype);
531:   MPI_Bcast(p,n,mtype,0,comm);
532:   return(0);
533: }

537: /*@C
538:    PetscBinarySynchronizedWrite - writes to a binary file.

540:    Collective on MPI_Comm

542:    Input Parameters:
543: +  comm - the MPI communicator 
544: .  fd - the file
545: .  n  - the number of items to write
546: .  p - the buffer
547: .  istemp - the buffer may be changed
548: -  type - the type of items to write (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)

550:    Level: developer

552:    Notes: 
553:    Process 0 does a PetscBinaryWrite()

555:    PetscBinarySynchronizedWrite() uses byte swapping to work on all machines.
556:    Integers are stored on the file as 32 long, regardless of whether
557:    they are stored in the machine as 32 or 64, this means the same
558:    binary file may be read on any machine.

560:    WARNING: This is NOT like PetscSynchronizedFPrintf()! This routine ignores calls on all but process 0,
561:    while PetscSynchronizedFPrintf() has all processes print their strings in order.

563:    Concepts: files^synchronized writing of binary files
564:    Concepts: binary files^reading, synchronized

566: .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscBinaryRead(), PetscBinarySynchronizedRead(),
567:           PetscBinarySynchronizedSeek()
568: @*/
569: PetscErrorCode  PetscBinarySynchronizedWrite(MPI_Comm comm,int fd,void *p,PetscInt n,PetscDataType type,PetscTruth istemp)
570: {
572:   PetscMPIInt    rank;

575:   MPI_Comm_rank(comm,&rank);
576:   if (!rank) {
577:     PetscBinaryWrite(fd,p,n,type,istemp);
578:   }
579:   return(0);
580: }

584: /*@C
585:    PetscBinarySynchronizedSeek - Moves the file pointer on a PETSc binary file.


588:    Input Parameters:
589: +  fd - the file
590: .  whence - if PETSC_BINARY_SEEK_SET then size is an absolute location in the file
591:             if PETSC_BINARY_SEEK_CUR then size is offset from current location
592:             if PETSC_BINARY_SEEK_END then size is offset from end of file
593: -  off    - number of bytes to move. Use PETSC_BINARY_INT_SIZE, PETSC_BINARY_SCALAR_SIZE,
594:             etc. in your calculation rather than sizeof() to compute byte lengths.

596:    Output Parameter:
597: .   offset - new offset in file

599:    Level: developer

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

607:    Concepts: binary files^seeking
608:    Concepts: files^seeking in binary 

610: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
611:           PetscBinarySynchronizedSeek()
612: @*/
613: PetscErrorCode  PetscBinarySynchronizedSeek(MPI_Comm comm,int fd,off_t off,PetscBinarySeekType whence,off_t *offset)
614: {
616:   PetscMPIInt    rank;

619:   MPI_Comm_rank(comm,&rank);
620:   if (!rank) {
621:     PetscBinarySeek(fd,off,whence,offset);
622:   }
623:   return(0);
624: }