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  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  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  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  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: /*@
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(), PetscViewerBinaryGetDescriptor(), PetscBinarySynchronizedWrite(),
157:           PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()
158: @*/
159: PetscErrorCode  PetscBinaryRead(int fd,void *p,PetscInt n,PetscDataType type)
160: {
161: #if (PETSC_SIZEOF_INT == 8) || defined(PETSC_USE_64BIT_INDICES) || !defined(PETSC_WORDS_BIGENDIAN)
162:   PetscErrorCode    ierr;
163: #endif
164:   int               wsize,err;
165:   size_t            m = (size_t) n,maxblock = 65536;
166:   char              *pp = (char*)p;
167: #if (PETSC_SIZEOF_INT == 8) || !defined(PETSC_WORDS_BIGENDIAN) || defined(PETSC_USE_64BIT_INDICES)
168:   void              *ptmp = p;
169: #endif

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

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

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

227:    Not Collective

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

236:    Level: advanced

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

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

257:    Concepts: files^writing binary
258:    Concepts: binary files^writing

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

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

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

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

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

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

319: #if !defined(PETSC_WORDS_BIGENDIAN)
320:   if (!istemp) {
321:     if      (type == PETSC_SCALAR) {PetscByteSwapScalar((PetscScalar*)ptmp,n);}
322:     else if (type == PETSC_DOUBLE) {PetscByteSwapDouble((double*)ptmp,n);}
323:     else if (type == PETSC_SHORT)  {PetscByteSwapShort((short*)ptmp,n);}
324:     else if (type == PETSC_INT)    {PetscByteSwapInt((PetscInt32*)ptmp,n);}
325:     else if (type == PETSC_ENUM)   {PetscByteSwapInt((PetscInt32*)ptmp,n);}
326:     else if (type == PETSC_TRUTH)  {PetscByteSwapInt((PetscInt32*)ptmp,n);}
327:   }
328: #endif

330: #if (PETSC_SIZEOF_INT == 8) || defined(PETSC_USE_64BIT_INDICES)
331:   if (type == PETSC_INT){
332:     PetscFree(ptmp);
333:   }
334: #endif
335:   return(0);
336: }

340: /*@C
341:    PetscBinaryOpen - Opens a PETSc binary file.

343:    Not Collective

345:    Input Parameters:
346: +  name - filename
347: -  type - type of binary file, one of FILE_MODE_READ, FILE_MODE_APPEND, FILE_MODE_WRITE

349:    Output Parameter:
350: .  fd - the file

352:    Level: advanced

354:   Concepts: files^opening binary
355:   Concepts: binary files^opening

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

361: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscFileMode, PetscViewerFileSetMode(), PetscViewerBinaryGetDescriptor(), 
362:           PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()

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

402: /*@
403:    PetscBinaryClose - Closes a PETSc binary file.

405:    Not Collective

407:    Output Parameter:
408: .  fd - the file

410:    Level: advanced

412: .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
413:           PetscBinarySynchronizedSeek()
414: @*/
415: PetscErrorCode  PetscBinaryClose(int fd)
416: {
418:   close(fd);
419:   return(0);
420: }


425: /*@
426:    PetscBinarySeek - Moves the file pointer on a PETSc binary file.

428:    Not Collective

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

438:    Output Parameter:
439: .   offset - new offset in file

441:    Level: developer

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

449:    Concepts: files^binary seeking
450:    Concepts: binary files^seeking

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

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

481: /*@C
482:    PetscBinarySynchronizedRead - Reads from a binary file.

484:    Collective on MPI_Comm

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

492:    Output Parameters:
493: .  p - the buffer

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

500:    Level: developer

502:    Notes: 
503:    Does a PetscBinaryRead() followed by an MPI_Bcast()

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

510:    Concepts: files^synchronized reading of binary files
511:    Concepts: binary files^reading, synchronized

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

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

534: /*@C
535:    PetscBinarySynchronizedWrite - writes to a binary file.

537:    Collective on MPI_Comm

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

547:    Level: developer

549:    Notes: 
550:    Process 0 does a PetscBinaryWrite()

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

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

560:    Concepts: files^synchronized writing of binary files
561:    Concepts: binary files^reading, synchronized

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

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

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


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

593:    Output Parameter:
594: .   offset - new offset in file

596:    Level: developer

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

604:    Concepts: binary files^seeking
605:    Concepts: files^seeking in binary 

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

616:   MPI_Comm_rank(comm,&rank);
617:   if (!rank) {
618:     PetscBinarySeek(fd,off,whence,offset);
619:   }
620:   return(0);
621: }