xref: /petsc/src/sys/fileio/sysio.c (revision a58c3bc3391eee32bc3fd94ac7edeea38fe57aae)
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(), PetscViewerBinaryGetDescriptor()
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_INDICES) || !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_INDICES)
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_INDICES)
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_INDICES)
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(), PetscViewerBinaryGetDescriptor()
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_INDICES)
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_INDICES)
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_INDICES)
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_INDICES)
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, one of FILE_MODE_READ, FILE_MODE_APPEND, FILE_MODE_WRITE
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(), PetscFileMode, PetscViewerFileSetMode(), PetscViewerBinaryGetDescriptor()
359 
360 @*/
361 PetscErrorCode PETSC_DLLEXPORT PetscBinaryOpen(const char name[],PetscFileMode mode,int *fd)
362 {
363   PetscFunctionBegin;
364 #if defined(PETSC_HAVE_O_BINARY)
365   if (mode == FILE_MODE_WRITE) {
366     if ((*fd = open(name,O_WRONLY|O_CREAT|O_TRUNC|O_BINARY,0666)) == -1) {
367       SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot create file for writing: %s",name);
368     }
369   } else if (mode == FILE_MODE_READ) {
370     if ((*fd = open(name,O_RDONLY|O_BINARY,0)) == -1) {
371       SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open file for reading: %s",name);
372     }
373   } else if (mode == FILE_MODE_APPEND) {
374     if ((*fd = open(name,O_WRONLY|O_BINARY,0)) == -1) {
375       SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open file for writing: %s",name);
376     }
377 #else
378   if (mode == FILE_MODE_WRITE) {
379     if ((*fd = creat(name,0666)) == -1) {
380       SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot create file for writing: %s",name);
381     }
382   } else if (mode == FILE_MODE_READ) {
383     if ((*fd = open(name,O_RDONLY,0)) == -1) {
384       SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open file for reading: %s",name);
385     }
386   }
387   else if (mode == FILE_MODE_APPEND) {
388     if ((*fd = open(name,O_WRONLY,0)) == -1) {
389       SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open file for writing: %s",name);
390     }
391 #endif
392   } else SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Unknown file mode");
393   PetscFunctionReturn(0);
394 }
395 
396 #undef __FUNCT__
397 #define __FUNCT__ "PetscBinaryClose"
398 /*@
399    PetscBinaryClose - Closes a PETSc binary file.
400 
401    Not Collective
402 
403    Output Parameter:
404 .  fd - the file
405 
406    Level: advanced
407 
408 .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen()
409 @*/
410 PetscErrorCode PETSC_DLLEXPORT PetscBinaryClose(int fd)
411 {
412   PetscFunctionBegin;
413   close(fd);
414   PetscFunctionReturn(0);
415 }
416 
417 
418 #undef __FUNCT__
419 #define __FUNCT__ "PetscBinarySeek"
420 /*@
421    PetscBinarySeek - Moves the file pointer on a PETSc binary file.
422 
423    Not Collective
424 
425    Input Parameters:
426 +  fd - the file
427 .  off - number of bytes to move. Use PETSC_BINARY_INT_SIZE, PETSC_BINARY_SCALAR_SIZE,
428             etc. in your calculation rather than sizeof() to compute byte lengths.
429 -  whence - if PETSC_BINARY_SEEK_SET then off is an absolute location in the file
430             if PETSC_BINARY_SEEK_CUR then off is an offset from the current location
431             if PETSC_BINARY_SEEK_END then off is an offset from the end of file
432 
433    Output Parameter:
434 .   offset - new offset in file
435 
436    Level: developer
437 
438    Notes:
439    Integers are stored on the file as 32 long, regardless of whether
440    they are stored in the machine as 32 or 64, this means the same
441    binary file may be read on any machine. Hence you CANNOT use sizeof()
442    to determine the offset or location.
443 
444    Concepts: files^binary seeking
445    Concepts: binary files^seeking
446 
447 .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen()
448 @*/
449 PetscErrorCode PETSC_DLLEXPORT PetscBinarySeek(int fd,off_t off,PetscBinarySeekType whence,off_t *offset)
450 {
451   int iwhence = 0;
452 
453   PetscFunctionBegin;
454   if (whence == PETSC_BINARY_SEEK_SET) {
455     iwhence = SEEK_SET;
456   } else if (whence == PETSC_BINARY_SEEK_CUR) {
457     iwhence = SEEK_CUR;
458   } else if (whence == PETSC_BINARY_SEEK_END) {
459     iwhence = SEEK_END;
460   } else {
461     SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Unknown seek location");
462   }
463 #if defined(PETSC_HAVE_LSEEK)
464   *offset = lseek(fd,off,iwhence);
465 #elif defined(PETSC_HAVE__LSEEK)
466   *offset = _lseek(fd,(long)off,iwhence);
467 #else
468   SETERRQ(PETSC_ERR_SUP_SYS,"System does not have a way of seeking on a file");
469 #endif
470   PetscFunctionReturn(0);
471 }
472 
473 #undef __FUNCT__
474 #define __FUNCT__ "PetscSynchronizedBinaryRead"
475 /*@C
476    PetscSynchronizedBinaryRead - Reads from a binary file.
477 
478    Collective on MPI_Comm
479 
480    Input Parameters:
481 +  comm - the MPI communicator
482 .  fd - the file
483 .  n  - the number of items to read
484 -  type - the type of items to read (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)
485 
486    Output Parameters:
487 .  p - the buffer
488 
489    Options Database Key:
490 .   -binary_longints - indicates the file was generated on a Cray vector
491          machine (not the T3E/D) and the ints are stored as 64 bit
492          quantities, otherwise they are stored as 32 bit
493 
494    Level: developer
495 
496    Notes:
497    Does a PetscBinaryRead() followed by an MPI_Bcast()
498 
499    PetscSynchronizedBinaryRead() uses byte swapping to work on all machines.
500    Integers are stored on the file as 32 long, regardless of whether
501    they are stored in the machine as 32 or 64, this means the same
502    binary file may be read on any machine.
503 
504    Concepts: files^synchronized reading of binary files
505    Concepts: binary files^reading, synchronized
506 
507 .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscBinaryRead()
508 @*/
509 PetscErrorCode PETSC_DLLEXPORT PetscSynchronizedBinaryRead(MPI_Comm comm,int fd,void *p,PetscInt n,PetscDataType type)
510 {
511   PetscErrorCode ierr;
512   PetscMPIInt    rank;
513   MPI_Datatype   mtype;
514 
515   PetscFunctionBegin;
516   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
517   if (!rank) {
518     ierr = PetscBinaryRead(fd,p,n,type);CHKERRQ(ierr);
519   }
520   ierr = PetscDataTypeToMPIDataType(type,&mtype);CHKERRQ(ierr);
521   ierr = MPI_Bcast(p,n,mtype,0,comm);CHKERRQ(ierr);
522   PetscFunctionReturn(0);
523 }
524 
525 #undef __FUNCT__
526 #define __FUNCT__ "PetscSynchronizedBinaryWrite"
527 /*@C
528    PetscSynchronizedBinaryWrite - writes to a binary file.
529 
530    Collective on MPI_Comm
531 
532    Input Parameters:
533 +  comm - the MPI communicator
534 .  fd - the file
535 .  n  - the number of items to write
536 .  p - the buffer
537 .  istemp - the buffer may be changed
538 -  type - the type of items to write (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)
539 
540    Level: developer
541 
542    Notes:
543    Process 0 does a PetscBinaryWrite()
544 
545    PetscSynchronizedBinaryWrite() uses byte swapping to work on all machines.
546    Integers are stored on the file as 32 long, regardless of whether
547    they are stored in the machine as 32 or 64, this means the same
548    binary file may be read on any machine.
549 
550    Concepts: files^synchronized writing of binary files
551    Concepts: binary files^reading, synchronized
552 
553 .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscBinaryRead()
554 @*/
555 PetscErrorCode PETSC_DLLEXPORT PetscSynchronizedBinaryWrite(MPI_Comm comm,int fd,void *p,PetscInt n,PetscDataType type,PetscTruth istemp)
556 {
557   PetscErrorCode ierr;
558   PetscMPIInt    rank;
559 
560   PetscFunctionBegin;
561   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
562   if (!rank) {
563     ierr = PetscBinaryWrite(fd,p,n,type,istemp);CHKERRQ(ierr);
564   }
565   PetscFunctionReturn(0);
566 }
567 
568 #undef __FUNCT__
569 #define __FUNCT__ "PetscSynchronizedBinarySeek"
570 /*@C
571    PetscSynchronizedBinarySeek - Moves the file pointer on a PETSc binary file.
572 
573 
574    Input Parameters:
575 +  fd - the file
576 .  whence - if PETSC_BINARY_SEEK_SET then size is an absolute location in the file
577             if PETSC_BINARY_SEEK_CUR then size is offset from current location
578             if PETSC_BINARY_SEEK_END then size is offset from end of file
579 -  off    - number of bytes to move. Use PETSC_BINARY_INT_SIZE, PETSC_BINARY_SCALAR_SIZE,
580             etc. in your calculation rather than sizeof() to compute byte lengths.
581 
582    Output Parameter:
583 .   offset - new offset in file
584 
585    Level: developer
586 
587    Notes:
588    Integers are stored on the file as 32 long, regardless of whether
589    they are stored in the machine as 32 or 64, this means the same
590    binary file may be read on any machine. Hence you CANNOT use sizeof()
591    to determine the offset or location.
592 
593    Concepts: binary files^seeking
594    Concepts: files^seeking in binary
595 
596 .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen()
597 @*/
598 PetscErrorCode PETSC_DLLEXPORT PetscSynchronizedBinarySeek(MPI_Comm comm,int fd,off_t off,PetscBinarySeekType whence,off_t *offset)
599 {
600   PetscErrorCode ierr;
601   PetscMPIInt    rank;
602 
603   PetscFunctionBegin;
604   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
605   if (!rank) {
606     ierr = PetscBinarySeek(fd,off,whence,offset);CHKERRQ(ierr);
607   }
608   PetscFunctionReturn(0);
609 }
610 
611