xref: /petsc/src/sys/fileio/sysio.c (revision 0229d381f29c2373b217b24be63e1a0d5f59aeeb)
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__ "PetscByteSwapInt32"
30 /*
31   PetscByteSwapInt32 - Swap bytes in a 32 bit integer.
32 
33 */
34 PetscErrorCode PETSC_DLLEXPORT PetscByteSwapInt32(PetscInt32 *buff,PetscInt n)
35 {
36   PetscInt  i,j,tmp = 0;
37   PetscInt  *tptr = &tmp;                /* Need to access tmp indirectly to get */
38   char      *ptr1,*ptr2 = (char*)&tmp; /* arround the bug in DEC-ALPHA g++ */
39 
40   PetscFunctionBegin;
41   for (j=0; j<n; j++) {
42     ptr1 = (char*)(buff + j);
43     for (i=0; i<(int)sizeof(PetscInt32); i++) {
44       ptr2[i] = ptr1[sizeof(PetscInt32)-1-i];
45     }
46     buff[j] = *tptr;
47   }
48   PetscFunctionReturn(0);
49 }
50 /* --------------------------------------------------------- */
51 #undef __FUNCT__
52 #define __FUNCT__ "PetscByteSwapInt"
53 /*
54   PetscByteSwapInt - Swap bytes in a  bit integer.
55 
56 */
57 PetscErrorCode PETSC_DLLEXPORT PetscByteSwapInt64(PetscInt *buff,PetscInt n)
58 {
59   PetscInt  i,j,tmp = 0;
60   PetscInt  *tptr = &tmp;             /* Need to access tmp indirectly to get */
61   char       *ptr1,*ptr2 = (char*)&tmp; /* arround the bug in DEC-ALPHA g++ */
62 
63   PetscFunctionBegin;
64   for (j=0; j<n; j++) {
65     ptr1 = (char*)(buff + j);
66     for (i=0; i<(int)sizeof(PetscInt); i++) {
67       ptr2[i] = ptr1[sizeof(PetscInt)-1-i];
68     }
69     buff[j] = *tptr;
70   }
71   PetscFunctionReturn(0);
72 }
73 /* --------------------------------------------------------- */
74 #undef __FUNCT__
75 #define __FUNCT__ "PetscByteSwapShort"
76 /*
77   PetscByteSwapShort - Swap bytes in a short
78 */
79 PetscErrorCode PETSC_DLLEXPORT PetscByteSwapShort(short *buff,PetscInt n)
80 {
81   PetscInt   i,j;
82   short      tmp;
83   short      *tptr = &tmp;           /* take care pf bug in DEC-ALPHA g++ */
84   char       *ptr1,*ptr2 = (char*)&tmp;
85 
86   PetscFunctionBegin;
87   for (j=0; j<n; j++) {
88     ptr1 = (char*)(buff + j);
89     for (i=0; i<(int) sizeof(short); i++) {
90       ptr2[i] = ptr1[sizeof(int)-1-i];
91     }
92     buff[j] = *tptr;
93   }
94   PetscFunctionReturn(0);
95 }
96 /* --------------------------------------------------------- */
97 #undef __FUNCT__
98 #define __FUNCT__ "PetscByteSwapScalar"
99 /*
100   PetscByteSwapScalar - Swap bytes in a double
101   Complex is dealt with as if array of double twice as long.
102 */
103 PetscErrorCode PETSC_DLLEXPORT PetscByteSwapScalar(PetscScalar *buff,PetscInt n)
104 {
105   PetscInt  i,j;
106   PetscReal tmp,*buff1 = (PetscReal*)buff;
107   PetscReal *tptr = &tmp;          /* take care pf bug in DEC-ALPHA g++ */
108   char      *ptr1,*ptr2 = (char*)&tmp;
109 
110   PetscFunctionBegin;
111 #if defined(PETSC_USE_COMPLEX)
112   n *= 2;
113 #endif
114   for (j=0; j<n; j++) {
115     ptr1 = (char*)(buff1 + j);
116     for (i=0; i<(int) sizeof(PetscReal); i++) {
117       ptr2[i] = ptr1[sizeof(PetscReal)-1-i];
118     }
119     buff1[j] = *tptr;
120   }
121   PetscFunctionReturn(0);
122 }
123 /* --------------------------------------------------------- */
124 #undef __FUNCT__
125 #define __FUNCT__ "PetscByteSwapDouble"
126 /*
127   PetscByteSwapDouble - Swap bytes in a double
128 */
129 PetscErrorCode PETSC_DLLEXPORT PetscByteSwapDouble(double *buff,PetscInt n)
130 {
131   PetscInt i,j;
132   double   tmp,*buff1 = (double*)buff;
133   double   *tptr = &tmp;          /* take care pf bug in DEC-ALPHA g++ */
134   char     *ptr1,*ptr2 = (char*)&tmp;
135 
136   PetscFunctionBegin;
137   for (j=0; j<n; j++) {
138     ptr1 = (char*)(buff1 + j);
139     for (i=0; i<(int) sizeof(double); i++) {
140       ptr2[i] = ptr1[sizeof(double)-1-i];
141     }
142     buff1[j] = *tptr;
143   }
144   PetscFunctionReturn(0);
145 }
146 #endif
147 /* --------------------------------------------------------- */
148 #undef __FUNCT__
149 #define __FUNCT__ "PetscBinaryRead"
150 /*@
151    PetscBinaryRead - Reads from a binary file.
152 
153    Not Collective
154 
155    Input Parameters:
156 +  fd - the file
157 .  n  - the number of items to read
158 -  type - the type of items to read (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)
159 
160    Output Parameters:
161 .  p - the buffer
162 
163 
164 
165    Level: developer
166 
167    Notes:
168    PetscBinaryRead() uses byte swapping to work on all machines; the files
169    are written to file ALWAYS using big-endian ordering. On small-endian machines the numbers
170    are converted to the small-endian format when they are read in from the file.
171    Integers are stored on the file as 32 bits long, regardless of whether
172    they are stored in the machine as 32 bits or 64 bits, this means the same
173    binary file may be read on any machine.
174 
175    Concepts: files^reading binary
176    Concepts: binary files^reading
177 
178 .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscViewerBinaryGetDescriptor(), PetscBinarySynchronizedWrite(),
179           PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()
180 @*/
181 PetscErrorCode PETSC_DLLEXPORT PetscBinaryRead(int fd,void *p,PetscInt n,PetscDataType type)
182 {
183 #if (PETSC_SIZEOF_INT == 8) || defined(PETSC_USE_64BIT_INDICES) || !defined(PETSC_WORDS_BIGENDIAN)
184   PetscErrorCode    ierr;
185 #endif
186   int               wsize,err;
187   size_t            m = (size_t) n,maxblock = 65536;
188   char              *pp = (char*)p;
189 #if (PETSC_SIZEOF_INT == 8) || !defined(PETSC_WORDS_BIGENDIAN) || defined(PETSC_USE_64BIT_INDICES)
190   void              *ptmp = p;
191 #endif
192 
193   PetscFunctionBegin;
194   if (!n) PetscFunctionReturn(0);
195 
196   if (type == PETSC_INT){
197 #if defined(PETSC_USE_64BIT_INDICES_BINARY)
198     m   *= sizeof(PetscInt);
199 #else
200     m   *= sizeof(PetscInt32);
201 #endif
202 #if ((PETSC_SIZEOF_INT == 8) || defined(PETSC_USE_64BIT_INDICES)) && !defined(PETSC_USE_64BIT_INDICES_BINARY)
203     /* read them in as 32 bit ints, later stretch into ints */
204     ierr = PetscMalloc(m,&pp);CHKERRQ(ierr);
205     ptmp = (void*)pp;
206 #endif
207   }
208   else if (type == PETSC_SCALAR)  m *= sizeof(PetscScalar);
209   else if (type == PETSC_DOUBLE)  m *= sizeof(double);
210   else if (type == PETSC_SHORT)   m *= sizeof(short);
211   else if (type == PETSC_CHAR)    m *= sizeof(char);
212   else if (type == PETSC_ENUM)    m *= sizeof(PetscEnum);
213   else if (type == PETSC_TRUTH)   m *= sizeof(PetscTruth);
214   else if (type == PETSC_LOGICAL) m  = PetscBTLength(m)*sizeof(char);
215   else SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Unknown type");
216 
217   while (m) {
218     wsize = (m < maxblock) ? m : maxblock;
219     err = read(fd,pp,wsize);
220     if (err < 0 && errno == EINTR) continue;
221     if (!err && wsize > 0) SETERRQ(PETSC_ERR_FILE_READ,"Read past end of file");
222     if (err < 0) SETERRQ1(PETSC_ERR_FILE_READ,"Error reading from file, errno %d",errno);
223     m  -= err;
224     pp += err;
225   }
226 #if !defined(PETSC_WORDS_BIGENDIAN)
227 #if defined(PETSC_USE_64BIT_INDICES_BINARY)
228   if      (type == PETSC_INT)    {ierr = PetscByteSwapInt64((PetscInt*)ptmp,n);CHKERRQ(ierr);}
229 #else
230   if      (type == PETSC_INT)    {ierr = PetscByteSwapInt32((PetscInt32*)ptmp,n);CHKERRQ(ierr);}
231 #endif
232   else if (type == PETSC_ENUM)   {ierr = PetscByteSwapInt32((PetscInt32*)ptmp,n);CHKERRQ(ierr);}
233   else if (type == PETSC_TRUTH)  {ierr = PetscByteSwapInt32((PetscInt32*)ptmp,n);CHKERRQ(ierr);}
234   else if (type == PETSC_SCALAR) {ierr = PetscByteSwapScalar((PetscScalar*)ptmp,n);CHKERRQ(ierr);}
235   else if (type == PETSC_DOUBLE) {ierr = PetscByteSwapDouble((double*)ptmp,n);CHKERRQ(ierr);}
236   else if (type == PETSC_SHORT)  {ierr = PetscByteSwapShort((short*)ptmp,n);CHKERRQ(ierr);}
237 #endif
238 
239 #if ((PETSC_SIZEOF_INT == 8) || defined(PETSC_USE_64BIT_INDICES)) && !defined(PETSC_USE_64BIT_INDICES_BINARY)
240   if (type == PETSC_INT) {
241     PetscInt   *p_int = (PetscInt*)p,i;
242     PetscInt32 *p_short = (PetscInt32 *)ptmp;
243     for (i=0; i<n; i++) {
244       p_int[i] = (PetscInt)p_short[i];
245     }
246     ierr = PetscFree(ptmp);CHKERRQ(ierr);
247   }
248 #endif
249   PetscFunctionReturn(0);
250 }
251 /* --------------------------------------------------------- */
252 #undef __FUNCT__
253 #define __FUNCT__ "PetscBinaryWrite"
254 /*@
255    PetscBinaryWrite - Writes to a binary file.
256 
257    Not Collective
258 
259    Input Parameters:
260 +  fd     - the file
261 .  p      - the buffer
262 .  n      - the number of items to write
263 .  type   - the type of items to read (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)
264 -  istemp - PETSC_FALSE if buffer data should be preserved, PETSC_TRUE otherwise.
265 
266    Level: advanced
267 
268    Notes:
269    PetscBinaryWrite() uses byte swapping to work on all machines; the files
270    are written using big-endian ordering to the file. On small-endian machines the numbers
271    are converted to the big-endian format when they are written to disk.
272    Integers are stored on the file as 32 bits long, regardless of whether
273    they are stored in the machine as 32 bits or 64 bits, this means the same
274    binary file may be read on any machine. It also means that 64 bit integers larger than
275    roughly 2 billion are TRUNCATED/WRONG when written to the file.
276 
277    The Buffer p should be read-write buffer, and not static data.
278    This way, byte-swapping is done in-place, and then the buffer is
279    written to the file.
280 
281    This routine restores the original contents of the buffer, after
282    it is written to the file. This is done by byte-swapping in-place
283    the second time. If the flag istemp is set to PETSC_TRUE, the second
284    byte-swapping operation is not done, thus saving some computation,
285    but the buffer corrupted is corrupted.
286 
287    Concepts: files^writing binary
288    Concepts: binary files^writing
289 
290 .seealso: PetscBinaryRead(), PetscBinaryOpen(), PetscBinaryClose(), PetscViewerBinaryGetDescriptor(), PetscBinarySynchronizedWrite(),
291           PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()
292 @*/
293 PetscErrorCode PETSC_DLLEXPORT PetscBinaryWrite(int fd,void *p,PetscInt n,PetscDataType type,PetscTruth istemp)
294 {
295   char           *pp = (char*)p;
296   int            err,wsize;
297   size_t         m = (size_t)n,maxblock=65536;
298 #if !defined(PETSC_WORDS_BIGENDIAN) || (PETSC_SIZEOF_INT == 8) ||  defined(PETSC_USE_64BIT_INDICES)
299   PetscErrorCode ierr;
300   void           *ptmp = p;
301 #endif
302 
303   PetscFunctionBegin;
304   if (n < 0) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Trying to write a negative amount of data %D",n);
305   if (!n) PetscFunctionReturn(0);
306 
307   if (type == PETSC_INT){
308 #if defined(PETSC_USE_64BIT_INDICES_BINARY)
309     m   *= sizeof(PetscInt);
310 #else
311     m   *= sizeof(PetscInt32);
312 #endif
313 #if ((PETSC_SIZEOF_INT == 8) || defined(PETSC_USE_64BIT_INDICES)) && !defined(PETSC_USE_64BIT_INDICES_BINARY)
314     PetscInt   *p_int = (PetscInt*)p,i;
315     PetscInt32 *p_short;
316     ierr    = PetscMalloc(m,&pp);CHKERRQ(ierr);
317     ptmp    = (void*)pp;
318     p_short = (PetscInt32*)pp;
319 
320     for (i=0; i<n; i++) {
321       p_short[i] = (PetscInt32) p_int[i];
322     }
323     istemp = PETSC_TRUE;
324 #endif
325   }
326   else if (type == PETSC_SCALAR)  m *= sizeof(PetscScalar);
327   else if (type == PETSC_DOUBLE)  m *= sizeof(double);
328   else if (type == PETSC_SHORT)   m *= sizeof(short);
329   else if (type == PETSC_CHAR)    m *= sizeof(char);
330   else if (type == PETSC_ENUM)    m *= sizeof(PetscEnum);
331   else if (type == PETSC_TRUTH)   m *= sizeof(PetscTruth);
332   else if (type == PETSC_LOGICAL) m = PetscBTLength(m)*sizeof(char);
333   else SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Unknown type");
334 
335 #if !defined(PETSC_WORDS_BIGENDIAN)
336 #if defined(PETSC_USE_64BIT_INDICES_BINARY)
337   if      (type == PETSC_INT)    {ierr = PetscByteSwapInt64((PetscInt*)ptmp,n);CHKERRQ(ierr);}
338 #else
339   if      (type == PETSC_INT)    {ierr = PetscByteSwapInt32((PetscInt32*)ptmp,n);CHKERRQ(ierr);}
340 #endif
341   else if (type == PETSC_ENUM)   {ierr = PetscByteSwapInt32((PetscInt32*)ptmp,n);CHKERRQ(ierr);}
342   else if (type == PETSC_TRUTH)  {ierr = PetscByteSwapInt32((PetscInt32*)ptmp,n);CHKERRQ(ierr);}
343   else if (type == PETSC_SCALAR) {ierr = PetscByteSwapScalar((PetscScalar*)ptmp,n);CHKERRQ(ierr);}
344   else if (type == PETSC_DOUBLE) {ierr = PetscByteSwapDouble((double*)ptmp,n);CHKERRQ(ierr);}
345   else if (type == PETSC_SHORT)  {ierr = PetscByteSwapShort((short*)ptmp,n);CHKERRQ(ierr);}
346 #endif
347 
348   while (m) {
349     wsize = (m < maxblock) ? m : maxblock;
350     err = write(fd,pp,wsize);
351     if (err < 0 && errno == EINTR) continue;
352     if (err != wsize) SETERRQ(PETSC_ERR_FILE_WRITE,"Error writing to file.");
353     m -= wsize;
354     pp += wsize;
355   }
356 
357 #if !defined(PETSC_WORDS_BIGENDIAN)
358   if (!istemp) {
359 #if defined(PETSC_USE_64BIT_INDICES_BINARY)
360     if      (type == PETSC_INT)    {ierr = PetscByteSwapInt64((PetscInt*)ptmp,n);CHKERRQ(ierr);}
361 #else
362     if      (type == PETSC_INT)    {ierr = PetscByteSwapInt32((PetscInt32*)ptmp,n);CHKERRQ(ierr);}
363 #endif
364     if      (type == PETSC_SCALAR) {ierr = PetscByteSwapScalar((PetscScalar*)ptmp,n);CHKERRQ(ierr);}
365     else if (type == PETSC_DOUBLE) {ierr = PetscByteSwapDouble((double*)ptmp,n);CHKERRQ(ierr);}
366     else if (type == PETSC_SHORT)  {ierr = PetscByteSwapShort((short*)ptmp,n);CHKERRQ(ierr);}
367     else if (type == PETSC_INT)    {ierr = PetscByteSwapInt32((PetscInt32*)ptmp,n);CHKERRQ(ierr);}
368     else if (type == PETSC_ENUM)   {ierr = PetscByteSwapInt32((PetscInt32*)ptmp,n);CHKERRQ(ierr);}
369     else if (type == PETSC_TRUTH)  {ierr = PetscByteSwapInt32((PetscInt32*)ptmp,n);CHKERRQ(ierr);}
370   }
371 #endif
372 
373 #if (PETSC_SIZEOF_INT == 8) || defined(PETSC_USE_64BIT_INDICES) && !defined(PETSC_USE_64BIT_INDICES_BINARY)
374   if (type == PETSC_INT){
375     ierr = PetscFree(ptmp);CHKERRQ(ierr);
376   }
377 #endif
378   PetscFunctionReturn(0);
379 }
380 
381 #undef __FUNCT__
382 #define __FUNCT__ "PetscBinaryOpen"
383 /*@C
384    PetscBinaryOpen - Opens a PETSc binary file.
385 
386    Not Collective
387 
388    Input Parameters:
389 +  name - filename
390 -  type - type of binary file, one of FILE_MODE_READ, FILE_MODE_APPEND, FILE_MODE_WRITE
391 
392    Output Parameter:
393 .  fd - the file
394 
395    Level: advanced
396 
397   Concepts: files^opening binary
398   Concepts: binary files^opening
399 
400    Notes: Files access with PetscBinaryRead() and PetscBinaryWrite() are ALWAYS written in
401    big-endian format. This means the file can be accessed using PetscBinaryOpen() and
402    PetscBinaryRead() and PetscBinaryWrite() on any machine.
403 
404 .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscFileMode, PetscViewerFileSetMode(), PetscViewerBinaryGetDescriptor(),
405           PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()
406 
407 @*/
408 PetscErrorCode PETSC_DLLEXPORT PetscBinaryOpen(const char name[],PetscFileMode mode,int *fd)
409 {
410   PetscFunctionBegin;
411 #if defined(PETSC_HAVE_O_BINARY)
412   if (mode == FILE_MODE_WRITE) {
413     if ((*fd = open(name,O_WRONLY|O_CREAT|O_TRUNC|O_BINARY,0666)) == -1) {
414       SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot create file for writing: %s",name);
415     }
416   } else if (mode == FILE_MODE_READ) {
417     if ((*fd = open(name,O_RDONLY|O_BINARY,0)) == -1) {
418       SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open file for reading: %s",name);
419     }
420   } else if (mode == FILE_MODE_APPEND) {
421     if ((*fd = open(name,O_WRONLY|O_BINARY,0)) == -1) {
422       SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open file for writing: %s",name);
423     }
424 #else
425   if (mode == FILE_MODE_WRITE) {
426     if ((*fd = creat(name,0666)) == -1) {
427       SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot create file for writing: %s",name);
428     }
429   } else if (mode == FILE_MODE_READ) {
430     if ((*fd = open(name,O_RDONLY,0)) == -1) {
431       SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open file for reading: %s",name);
432     }
433   }
434   else if (mode == FILE_MODE_APPEND) {
435     if ((*fd = open(name,O_WRONLY,0)) == -1) {
436       SETERRQ1(PETSC_ERR_FILE_OPEN,"Cannot open file for writing: %s",name);
437     }
438 #endif
439   } else SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Unknown file mode");
440   PetscFunctionReturn(0);
441 }
442 
443 #undef __FUNCT__
444 #define __FUNCT__ "PetscBinaryClose"
445 /*@
446    PetscBinaryClose - Closes a PETSc binary file.
447 
448    Not Collective
449 
450    Output Parameter:
451 .  fd - the file
452 
453    Level: advanced
454 
455 .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
456           PetscBinarySynchronizedSeek()
457 @*/
458 PetscErrorCode PETSC_DLLEXPORT PetscBinaryClose(int fd)
459 {
460   PetscFunctionBegin;
461   close(fd);
462   PetscFunctionReturn(0);
463 }
464 
465 
466 #undef __FUNCT__
467 #define __FUNCT__ "PetscBinarySeek"
468 /*@
469    PetscBinarySeek - Moves the file pointer on a PETSc binary file.
470 
471    Not Collective
472 
473    Input Parameters:
474 +  fd - the file
475 .  off - number of bytes to move. Use PETSC_BINARY_INT_SIZE, PETSC_BINARY_SCALAR_SIZE,
476             etc. in your calculation rather than sizeof() to compute byte lengths.
477 -  whence - if PETSC_BINARY_SEEK_SET then off is an absolute location in the file
478             if PETSC_BINARY_SEEK_CUR then off is an offset from the current location
479             if PETSC_BINARY_SEEK_END then off is an offset from the end of file
480 
481    Output Parameter:
482 .   offset - new offset in file
483 
484    Level: developer
485 
486    Notes:
487    Integers are stored on the file as 32 long, regardless of whether
488    they are stored in the machine as 32 or 64, this means the same
489    binary file may be read on any machine. Hence you CANNOT use sizeof()
490    to determine the offset or location.
491 
492    Concepts: files^binary seeking
493    Concepts: binary files^seeking
494 
495 .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
496           PetscBinarySynchronizedSeek()
497 @*/
498 PetscErrorCode PETSC_DLLEXPORT PetscBinarySeek(int fd,off_t off,PetscBinarySeekType whence,off_t *offset)
499 {
500   int iwhence = 0;
501 
502   PetscFunctionBegin;
503   if (whence == PETSC_BINARY_SEEK_SET) {
504     iwhence = SEEK_SET;
505   } else if (whence == PETSC_BINARY_SEEK_CUR) {
506     iwhence = SEEK_CUR;
507   } else if (whence == PETSC_BINARY_SEEK_END) {
508     iwhence = SEEK_END;
509   } else {
510     SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Unknown seek location");
511   }
512 #if defined(PETSC_HAVE_LSEEK)
513   *offset = lseek(fd,off,iwhence);
514 #elif defined(PETSC_HAVE__LSEEK)
515   *offset = _lseek(fd,(long)off,iwhence);
516 #else
517   SETERRQ(PETSC_ERR_SUP_SYS,"System does not have a way of seeking on a file");
518 #endif
519   PetscFunctionReturn(0);
520 }
521 
522 #undef __FUNCT__
523 #define __FUNCT__ "PetscBinarySynchronizedRead"
524 /*@C
525    PetscBinarySynchronizedRead - Reads from a binary file.
526 
527    Collective on MPI_Comm
528 
529    Input Parameters:
530 +  comm - the MPI communicator
531 .  fd - the file
532 .  n  - the number of items to read
533 -  type - the type of items to read (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)
534 
535    Output Parameters:
536 .  p - the buffer
537 
538    Options Database Key:
539 .   -binary_longints - indicates the file was generated on a Cray vector
540          machine (not the T3E/D) and the ints are stored as 64 bit
541          quantities, otherwise they are stored as 32 bit
542 
543    Level: developer
544 
545    Notes:
546    Does a PetscBinaryRead() followed by an MPI_Bcast()
547 
548    PetscBinarySynchronizedRead() uses byte swapping to work on all machines.
549    Integers are stored on the file as 32 long, regardless of whether
550    they are stored in the machine as 32 or 64, this means the same
551    binary file may be read on any machine.
552 
553    Concepts: files^synchronized reading of binary files
554    Concepts: binary files^reading, synchronized
555 
556 .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscBinaryRead(), PetscBinarySynchronizedWrite(),
557           PetscBinarySynchronizedSeek()
558 @*/
559 PetscErrorCode PETSC_DLLEXPORT PetscBinarySynchronizedRead(MPI_Comm comm,int fd,void *p,PetscInt n,PetscDataType type)
560 {
561   PetscErrorCode ierr;
562   PetscMPIInt    rank;
563   MPI_Datatype   mtype;
564 
565   PetscFunctionBegin;
566   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
567   if (!rank) {
568     ierr = PetscBinaryRead(fd,p,n,type);CHKERRQ(ierr);
569   }
570   ierr = PetscDataTypeToMPIDataType(type,&mtype);CHKERRQ(ierr);
571   ierr = MPI_Bcast(p,n,mtype,0,comm);CHKERRQ(ierr);
572   PetscFunctionReturn(0);
573 }
574 
575 #undef __FUNCT__
576 #define __FUNCT__ "PetscBinarySynchronizedWrite"
577 /*@C
578    PetscBinarySynchronizedWrite - writes to a binary file.
579 
580    Collective on MPI_Comm
581 
582    Input Parameters:
583 +  comm - the MPI communicator
584 .  fd - the file
585 .  n  - the number of items to write
586 .  p - the buffer
587 .  istemp - the buffer may be changed
588 -  type - the type of items to write (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)
589 
590    Level: developer
591 
592    Notes:
593    Process 0 does a PetscBinaryWrite()
594 
595    PetscBinarySynchronizedWrite() uses byte swapping to work on all machines.
596    Integers are stored on the file as 32 long, regardless of whether
597    they are stored in the machine as 32 or 64, this means the same
598    binary file may be read on any machine.
599 
600    WARNING: This is NOT like PetscSynchronizedFPrintf()! This routine ignores calls on all but process 0,
601    while PetscSynchronizedFPrintf() has all processes print their strings in order.
602 
603    Concepts: files^synchronized writing of binary files
604    Concepts: binary files^reading, synchronized
605 
606 .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscBinaryRead(), PetscBinarySynchronizedRead(),
607           PetscBinarySynchronizedSeek()
608 @*/
609 PetscErrorCode PETSC_DLLEXPORT PetscBinarySynchronizedWrite(MPI_Comm comm,int fd,void *p,PetscInt n,PetscDataType type,PetscTruth istemp)
610 {
611   PetscErrorCode ierr;
612   PetscMPIInt    rank;
613 
614   PetscFunctionBegin;
615   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
616   if (!rank) {
617     ierr = PetscBinaryWrite(fd,p,n,type,istemp);CHKERRQ(ierr);
618   }
619   PetscFunctionReturn(0);
620 }
621 
622 #undef __FUNCT__
623 #define __FUNCT__ "PetscBinarySynchronizedSeek"
624 /*@C
625    PetscBinarySynchronizedSeek - Moves the file pointer on a PETSc binary file.
626 
627 
628    Input Parameters:
629 +  fd - the file
630 .  whence - if PETSC_BINARY_SEEK_SET then size is an absolute location in the file
631             if PETSC_BINARY_SEEK_CUR then size is offset from current location
632             if PETSC_BINARY_SEEK_END then size is offset from end of file
633 -  off    - number of bytes to move. Use PETSC_BINARY_INT_SIZE, PETSC_BINARY_SCALAR_SIZE,
634             etc. in your calculation rather than sizeof() to compute byte lengths.
635 
636    Output Parameter:
637 .   offset - new offset in file
638 
639    Level: developer
640 
641    Notes:
642    Integers are stored on the file as 32 long, regardless of whether
643    they are stored in the machine as 32 or 64, this means the same
644    binary file may be read on any machine. Hence you CANNOT use sizeof()
645    to determine the offset or location.
646 
647    Concepts: binary files^seeking
648    Concepts: files^seeking in binary
649 
650 .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
651           PetscBinarySynchronizedSeek()
652 @*/
653 PetscErrorCode PETSC_DLLEXPORT PetscBinarySynchronizedSeek(MPI_Comm comm,int fd,off_t off,PetscBinarySeekType whence,off_t *offset)
654 {
655   PetscErrorCode ierr;
656   PetscMPIInt    rank;
657 
658   PetscFunctionBegin;
659   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
660   if (!rank) {
661     ierr = PetscBinarySeek(fd,off,whence,offset);CHKERRQ(ierr);
662   }
663   PetscFunctionReturn(0);
664 }
665 
666