xref: /petsc/src/sys/fileio/sysio.c (revision f3be49ca30a5b63307daac95dd3149ecefeed79a)
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) SETERRQ1(PETSC_ERR_FILE_READ,"Error reading from file, errno %d",errno);
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)
318   if (!istemp) {
319     if      (type == PETSC_SCALAR) {ierr = PetscByteSwapScalar((PetscScalar*)ptmp,n);CHKERRQ(ierr);}
320     else if (type == PETSC_DOUBLE) {ierr = PetscByteSwapDouble((double*)ptmp,n);CHKERRQ(ierr);}
321     else if (type == PETSC_SHORT)  {ierr = PetscByteSwapShort((short*)ptmp,n);CHKERRQ(ierr);}
322     else if (type == PETSC_INT)    {ierr = PetscByteSwapInt((PetscInt32*)ptmp,n);CHKERRQ(ierr);}
323     else if (type == PETSC_ENUM)   {ierr = PetscByteSwapInt((PetscInt32*)ptmp,n);CHKERRQ(ierr);}
324     else if (type == PETSC_TRUTH)  {ierr = PetscByteSwapInt((PetscInt32*)ptmp,n);CHKERRQ(ierr);}
325   }
326 #endif
327 
328 #if (PETSC_SIZEOF_INT == 8) || defined(PETSC_USE_64BIT_INDICES)
329   if (type == PETSC_INT){
330     ierr = PetscFree(ptmp);CHKERRQ(ierr);
331   }
332 #endif
333   PetscFunctionReturn(0);
334 }
335 
336 #undef __FUNCT__
337 #define __FUNCT__ "PetscBinaryOpen"
338 /*@C
339    PetscBinaryOpen - Opens a PETSc binary file.
340 
341    Not Collective
342 
343    Input Parameters:
344 +  name - filename
345 -  type - type of binary file, one of FILE_MODE_READ, FILE_MODE_APPEND, FILE_MODE_WRITE
346 
347    Output Parameter:
348 .  fd - the file
349 
350    Level: advanced
351 
352   Concepts: files^opening binary
353   Concepts: binary files^opening
354 
355    Notes: Files access with PetscBinaryRead() and PetscBinaryWrite() are ALWAYS written in
356    big-endian format. This means the file can be accessed using PetscBinaryOpen() and
357    PetscBinaryRead() and PetscBinaryWrite() on any machine.
358 
359 .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscFileMode, PetscViewerFileSetMode(), PetscViewerBinaryGetDescriptor()
360 
361 @*/
362 PetscErrorCode PETSC_DLLEXPORT PetscBinaryOpen(const char name[],PetscFileMode mode,int *fd)
363 {
364   PetscFunctionBegin;
365 #if defined(PETSC_HAVE_O_BINARY)
366   if (mode == FILE_MODE_WRITE) {
367     if ((*fd = open(name,O_WRONLY|O_CREAT|O_TRUNC|O_BINARY,0666)) == -1) {
368       SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot create file for writing: %s",name);
369     }
370   } else if (mode == FILE_MODE_READ) {
371     if ((*fd = open(name,O_RDONLY|O_BINARY,0)) == -1) {
372       SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open file for reading: %s",name);
373     }
374   } else if (mode == FILE_MODE_APPEND) {
375     if ((*fd = open(name,O_WRONLY|O_BINARY,0)) == -1) {
376       SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open file for writing: %s",name);
377     }
378 #else
379   if (mode == FILE_MODE_WRITE) {
380     if ((*fd = creat(name,0666)) == -1) {
381       SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot create file for writing: %s",name);
382     }
383   } else if (mode == FILE_MODE_READ) {
384     if ((*fd = open(name,O_RDONLY,0)) == -1) {
385       SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open file for reading: %s",name);
386     }
387   }
388   else if (mode == FILE_MODE_APPEND) {
389     if ((*fd = open(name,O_WRONLY,0)) == -1) {
390       SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open file for writing: %s",name);
391     }
392 #endif
393   } else SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Unknown file mode");
394   PetscFunctionReturn(0);
395 }
396 
397 #undef __FUNCT__
398 #define __FUNCT__ "PetscBinaryClose"
399 /*@
400    PetscBinaryClose - Closes a PETSc binary file.
401 
402    Not Collective
403 
404    Output Parameter:
405 .  fd - the file
406 
407    Level: advanced
408 
409 .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen()
410 @*/
411 PetscErrorCode PETSC_DLLEXPORT PetscBinaryClose(int fd)
412 {
413   PetscFunctionBegin;
414   close(fd);
415   PetscFunctionReturn(0);
416 }
417 
418 
419 #undef __FUNCT__
420 #define __FUNCT__ "PetscBinarySeek"
421 /*@
422    PetscBinarySeek - Moves the file pointer on a PETSc binary file.
423 
424    Not Collective
425 
426    Input Parameters:
427 +  fd - the file
428 .  off - number of bytes to move. Use PETSC_BINARY_INT_SIZE, PETSC_BINARY_SCALAR_SIZE,
429             etc. in your calculation rather than sizeof() to compute byte lengths.
430 -  whence - if PETSC_BINARY_SEEK_SET then off is an absolute location in the file
431             if PETSC_BINARY_SEEK_CUR then off is an offset from the current location
432             if PETSC_BINARY_SEEK_END then off is an offset from the end of file
433 
434    Output Parameter:
435 .   offset - new offset in file
436 
437    Level: developer
438 
439    Notes:
440    Integers are stored on the file as 32 long, regardless of whether
441    they are stored in the machine as 32 or 64, this means the same
442    binary file may be read on any machine. Hence you CANNOT use sizeof()
443    to determine the offset or location.
444 
445    Concepts: files^binary seeking
446    Concepts: binary files^seeking
447 
448 .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen()
449 @*/
450 PetscErrorCode PETSC_DLLEXPORT PetscBinarySeek(int fd,off_t off,PetscBinarySeekType whence,off_t *offset)
451 {
452   int iwhence = 0;
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__ "PetscBinarySynchronizedRead"
476 /*@C
477    PetscBinarySynchronizedRead - 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    PetscBinarySynchronizedRead() 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 PetscBinarySynchronizedRead(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__ "PetscBinarySynchronizedWrite"
528 /*@C
529    PetscBinarySynchronizedWrite - 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    PetscBinarySynchronizedWrite() 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    WARNING: This is NOT like PetscSynchronizedFPrintf()! This routine ignores calls on all but process 0,
552    while PetscSynchronizedFPrintf() has all processes print their strings in order.
553 
554    Concepts: files^synchronized writing of binary files
555    Concepts: binary files^reading, synchronized
556 
557 .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscBinaryRead()
558 @*/
559 PetscErrorCode PETSC_DLLEXPORT PetscBinarySynchronizedWrite(MPI_Comm comm,int fd,void *p,PetscInt n,PetscDataType type,PetscTruth istemp)
560 {
561   PetscErrorCode ierr;
562   PetscMPIInt    rank;
563 
564   PetscFunctionBegin;
565   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
566   if (!rank) {
567     ierr = PetscBinaryWrite(fd,p,n,type,istemp);CHKERRQ(ierr);
568   }
569   PetscFunctionReturn(0);
570 }
571 
572 #undef __FUNCT__
573 #define __FUNCT__ "PetscBinarySynchronizedSeek"
574 /*@C
575    PetscBinarySynchronizedSeek - Moves the file pointer on a PETSc binary file.
576 
577 
578    Input Parameters:
579 +  fd - the file
580 .  whence - if PETSC_BINARY_SEEK_SET then size is an absolute location in the file
581             if PETSC_BINARY_SEEK_CUR then size is offset from current location
582             if PETSC_BINARY_SEEK_END then size is offset from end of file
583 -  off    - number of bytes to move. Use PETSC_BINARY_INT_SIZE, PETSC_BINARY_SCALAR_SIZE,
584             etc. in your calculation rather than sizeof() to compute byte lengths.
585 
586    Output Parameter:
587 .   offset - new offset in file
588 
589    Level: developer
590 
591    Notes:
592    Integers are stored on the file as 32 long, regardless of whether
593    they are stored in the machine as 32 or 64, this means the same
594    binary file may be read on any machine. Hence you CANNOT use sizeof()
595    to determine the offset or location.
596 
597    Concepts: binary files^seeking
598    Concepts: files^seeking in binary
599 
600 .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen()
601 @*/
602 PetscErrorCode PETSC_DLLEXPORT PetscBinarySynchronizedSeek(MPI_Comm comm,int fd,off_t off,PetscBinarySeekType whence,off_t *offset)
603 {
604   PetscErrorCode ierr;
605   PetscMPIInt    rank;
606 
607   PetscFunctionBegin;
608   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
609   if (!rank) {
610     ierr = PetscBinarySeek(fd,off,whence,offset);CHKERRQ(ierr);
611   }
612   PetscFunctionReturn(0);
613 }
614 
615