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: }