xref: /petsc/src/sys/fileio/sysio.c (revision 62903a643c6f3b806cfd2df6dfd11354dcefb6c2)
1 #define PETSC_DLL
2 
3 /*
4    This file contains simple binary read/write routines.
5  */
6 
7 #include "petsc.h"
8 #include "petscsys.h"     /*I          "petscsys.h"    I*/
9 
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"
19 
20 #if (PETSC_SIZEOF_INT == 8)
21 #define PetscInt32 short
22 #else
23 #define PetscInt32 int
24 #endif
25 
26 #if !defined(PETSC_WORDS_BIGENDIAN)
27 
28 #undef __FUNCT__
29 #define __FUNCT__ "PetscByteSwapInt"
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()).
33 
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 
41   PetscFunctionBegin;
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   PetscFunctionReturn(0);
50 }
51 /* --------------------------------------------------------- */
52 #undef __FUNCT__
53 #define __FUNCT__ "PetscByteSwapShort"
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;
63 
64   PetscFunctionBegin;
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   PetscFunctionReturn(0);
73 }
74 /* --------------------------------------------------------- */
75 #undef __FUNCT__
76 #define __FUNCT__ "PetscByteSwapScalar"
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;
87 
88   PetscFunctionBegin;
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   PetscFunctionReturn(0);
100 }
101 /* --------------------------------------------------------- */
102 #undef __FUNCT__
103 #define __FUNCT__ "PetscByteSwapDouble"
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;
113 
114   PetscFunctionBegin;
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   PetscFunctionReturn(0);
123 }
124 #endif
125 /* --------------------------------------------------------- */
126 #undef __FUNCT__
127 #define __FUNCT__ "PetscBinaryRead"
128 /*@
129    PetscBinaryRead - Reads from a binary file.
130 
131    Not Collective
132 
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)
137 
138    Output Parameters:
139 .  p - the buffer
140 
141 
142 
143    Level: developer
144 
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.
152 
153    Concepts: files^reading binary
154    Concepts: binary files^reading
155 
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
169 
170   PetscFunctionBegin;
171   if (!n) PetscFunctionReturn(0);
172 
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     ierr = PetscMalloc(m,&pp);CHKERRQ(ierr);
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)    {ierr = PetscByteSwapInt((PetscInt32*)ptmp,n);CHKERRQ(ierr);}
201   else if (type == PETSC_ENUM)   {ierr = PetscByteSwapInt((PetscInt32*)ptmp,n);CHKERRQ(ierr);}
202   else if (type == PETSC_TRUTH)  {ierr = PetscByteSwapInt((PetscInt32*)ptmp,n);CHKERRQ(ierr);}
203   else if (type == PETSC_SCALAR) {ierr = PetscByteSwapScalar((PetscScalar*)ptmp,n);CHKERRQ(ierr);}
204   else if (type == PETSC_DOUBLE) {ierr = PetscByteSwapDouble((double*)ptmp,n);CHKERRQ(ierr);}
205   else if (type == PETSC_SHORT)  {ierr = PetscByteSwapShort((short*)ptmp,n);CHKERRQ(ierr);}
206 #endif
207 
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     ierr = PetscFree(ptmp);CHKERRQ(ierr);
216   }
217 #endif
218   PetscFunctionReturn(0);
219 }
220 /* --------------------------------------------------------- */
221 #undef __FUNCT__
222 #define __FUNCT__ "PetscBinaryWrite"
223 /*@
224    PetscBinaryWrite - Writes to a binary file.
225 
226    Not Collective
227 
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.
234 
235    Level: advanced
236 
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.
245 
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.
255 
256    Concepts: files^writing binary
257    Concepts: binary files^writing
258 
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)
267   PetscErrorCode ierr;
268   void           *ptmp = p;
269 #endif
270 
271   PetscFunctionBegin;
272   if (n < 0) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Trying to write a negative amount of data %D",n);
273   if (!n) PetscFunctionReturn(0);
274 
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     ierr    = PetscMalloc(m,&pp);CHKERRQ(ierr);
281     ptmp    = (void*)pp;
282     p_short = (PetscInt32*)pp;
283 
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");
298 
299 #if !defined(PETSC_WORDS_BIGENDIAN)
300   if      (type == PETSC_INT)    {ierr = PetscByteSwapInt((PetscInt32*)ptmp,n);CHKERRQ(ierr);}
301   else if (type == PETSC_ENUM)   {ierr = PetscByteSwapInt((PetscInt32*)ptmp,n);CHKERRQ(ierr);}
302   else if (type == PETSC_TRUTH)  {ierr = PetscByteSwapInt((PetscInt32*)ptmp,n);CHKERRQ(ierr);}
303   else if (type == PETSC_SCALAR) {ierr = PetscByteSwapScalar((PetscScalar*)ptmp,n);CHKERRQ(ierr);}
304   else if (type == PETSC_DOUBLE) {ierr = PetscByteSwapDouble((double*)ptmp,n);CHKERRQ(ierr);}
305   else if (type == PETSC_SHORT)  {ierr = PetscByteSwapShort((short*)ptmp,n);CHKERRQ(ierr);}
306 #endif
307 
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   }
316 
317 #if !defined(PETSC_WORDS_BIGENDIAN) && !(PETSC_SIZEOF_INT == 8) && !defined(PETSC_USE_64BIT_INT)
318   if (!istemp) {
319     if      (type == PETSC_SCALAR) {ierr = PetscByteSwapScalar((PetscScalar*)ptmp,n);CHKERRQ(ierr);}
320     else if (type == PETSC_SHORT)  {ierr = PetscByteSwapShort((short*)ptmp,n);CHKERRQ(ierr);}
321     else if (type == PETSC_INT)    {ierr = PetscByteSwapInt((PetscInt32*)ptmp,n);CHKERRQ(ierr);}
322     else if (type == PETSC_ENUM)   {ierr = PetscByteSwapInt((PetscInt32*)ptmp,n);CHKERRQ(ierr);}
323     else if (type == PETSC_TRUTH)  {ierr = PetscByteSwapInt((PetscInt32*)ptmp,n);CHKERRQ(ierr);}
324   }
325 #endif
326 
327 #if (PETSC_SIZEOF_INT == 8) || defined(PETSC_USE_64BIT_INT)
328   if (type == PETSC_INT){
329     ierr = PetscFree(ptmp);CHKERRQ(ierr);
330   }
331 #endif
332   PetscFunctionReturn(0);
333 }
334 
335 #undef __FUNCT__
336 #define __FUNCT__ "PetscBinaryOpen"
337 /*@C
338    PetscBinaryOpen - Opens a PETSc binary file.
339 
340    Not Collective
341 
342    Input Parameters:
343 +  name - filename
344 -  type - type of binary file, on of PETSC_FILE_RDONLY, PETSC_FILE_WRONLY, PETSC_FILE_CREATE
345 
346    Output Parameter:
347 .  fd - the file
348 
349    Level: advanced
350 
351   Concepts: files^opening binary
352   Concepts: binary files^opening
353 
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.
357 
358 .seealso: PetscBinaryRead(), PetscBinaryWrite()
359 @*/
360 PetscErrorCode PETSC_DLLEXPORT PetscBinaryOpen(const char name[],int type,int *fd)
361 {
362   PetscFunctionBegin;
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   PetscFunctionReturn(0);
393 }
394 
395 #undef __FUNCT__
396 #define __FUNCT__ "PetscBinaryClose"
397 /*@
398    PetscBinaryClose - Closes a PETSc binary file.
399 
400    Not Collective
401 
402    Output Parameter:
403 .  fd - the file
404 
405    Level: advanced
406 
407 .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen()
408 @*/
409 PetscErrorCode PETSC_DLLEXPORT PetscBinaryClose(int fd)
410 {
411   PetscFunctionBegin;
412   close(fd);
413   PetscFunctionReturn(0);
414 }
415 
416 
417 #undef __FUNCT__
418 #define __FUNCT__ "PetscBinarySeek"
419 /*@
420    PetscBinarySeek - Moves the file pointer on a PETSc binary file.
421 
422    Not Collective
423 
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.
431 
432    Output Parameter:
433 .   offset - new offset in file
434 
435    Level: developer
436 
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.
442 
443    Concepts: files^binary seeking
444    Concepts: binary files^seeking
445 
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
453 
454   PetscFunctionBegin;
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   PetscFunctionReturn(0);
472 }
473 
474 #undef __FUNCT__
475 #define __FUNCT__ "PetscSynchronizedBinaryRead"
476 /*@C
477    PetscSynchronizedBinaryRead - Reads from a binary file.
478 
479    Collective on MPI_Comm
480 
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)
486 
487    Output Parameters:
488 .  p - the buffer
489 
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
494 
495    Level: developer
496 
497    Notes:
498    Does a PetscBinaryRead() followed by an MPI_Bcast()
499 
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.
504 
505    Concepts: files^synchronized reading of binary files
506    Concepts: binary files^reading, synchronized
507 
508 .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscBinaryRead()
509 @*/
510 PetscErrorCode PETSC_DLLEXPORT PetscSynchronizedBinaryRead(MPI_Comm comm,int fd,void *p,PetscInt n,PetscDataType type)
511 {
512   PetscErrorCode ierr;
513   PetscMPIInt    rank;
514   MPI_Datatype   mtype;
515 
516   PetscFunctionBegin;
517   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
518   if (!rank) {
519     ierr = PetscBinaryRead(fd,p,n,type);CHKERRQ(ierr);
520   }
521   ierr = PetscDataTypeToMPIDataType(type,&mtype);CHKERRQ(ierr);
522   ierr = MPI_Bcast(p,n,mtype,0,comm);CHKERRQ(ierr);
523   PetscFunctionReturn(0);
524 }
525 
526 #undef __FUNCT__
527 #define __FUNCT__ "PetscSynchronizedBinaryWrite"
528 /*@C
529    PetscSynchronizedBinaryWrite - writes to a binary file.
530 
531    Collective on MPI_Comm
532 
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)
540 
541    Level: developer
542 
543    Notes:
544    Process 0 does a PetscBinaryWrite()
545 
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.
550 
551    Concepts: files^synchronized writing of binary files
552    Concepts: binary files^reading, synchronized
553 
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 {
558   PetscErrorCode ierr;
559   PetscMPIInt    rank;
560 
561   PetscFunctionBegin;
562   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
563   if (!rank) {
564     ierr = PetscBinaryWrite(fd,p,n,type,istemp);CHKERRQ(ierr);
565   }
566   PetscFunctionReturn(0);
567 }
568 
569 #undef __FUNCT__
570 #define __FUNCT__ "PetscSynchronizedBinarySeek"
571 /*@C
572    PetscSynchronizedBinarySeek - Moves the file pointer on a PETSc binary file.
573 
574 
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.
582 
583    Output Parameter:
584 .   offset - new offset in file
585 
586    Level: developer
587 
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.
593 
594    Concepts: binary files^seeking
595    Concepts: files^seeking in binary
596 
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 {
601   PetscErrorCode ierr;
602   PetscMPIInt    rank;
603 
604   PetscFunctionBegin;
605   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
606   if (!rank) {
607     ierr = PetscBinarySeek(fd,off,whence,offset);CHKERRQ(ierr);
608   }
609   PetscFunctionReturn(0);
610 }
611 
612