xref: /petsc/src/sys/fileio/sysio.c (revision d12f57a093ab968f9389e2bae430a26a0ef8b3c9)
1 
2 /*
3    This file contains simple binary read/write routines.
4  */
5 
6 #include <petscsys.h>
7 #include <errno.h>
8 #include <fcntl.h>
9 #if defined(PETSC_HAVE_UNISTD_H)
10 #include <unistd.h>
11 #endif
12 #if defined(PETSC_HAVE_IO_H)
13 #include <io.h>
14 #endif
15 #include <petscbt.h>
16 
17 const char *const PetscFileModes[] = {"READ","WRITE","APPEND","UPDATE","APPEND_UPDATE","PetscFileMode","PETSC_FILE_",0};
18 
19 /* --------------------------------------------------------- */
20 #undef __FUNCT__
21 #define __FUNCT__ "PetscByteSwapEnum"
22 /*
23   PetscByteSwapEnum - Swap bytes in a  PETSc Enum
24 
25 */
26 PetscErrorCode  PetscByteSwapEnum(PetscEnum *buff,PetscInt n)
27 {
28   PetscInt  i,j;
29   PetscEnum tmp = ENUM_DUMMY;
30   char      *ptr1,*ptr2 = (char*)&tmp;
31 
32   PetscFunctionBegin;
33   for (j=0; j<n; j++) {
34     ptr1 = (char*)(buff + j);
35     for (i=0; i<(PetscInt)sizeof(PetscEnum); i++) ptr2[i] = ptr1[sizeof(PetscEnum)-1-i];
36     for (i=0; i<(PetscInt)sizeof(PetscEnum); i++) ptr1[i] = ptr2[i];
37   }
38   PetscFunctionReturn(0);
39 }
40 
41 #undef __FUNCT__
42 #define __FUNCT__ "PetscByteSwapBool"
43 /*
44   PetscByteSwapBool - Swap bytes in a  PETSc Bool
45 
46 */
47 PetscErrorCode  PetscByteSwapBool(PetscBool *buff,PetscInt n)
48 {
49   PetscInt  i,j;
50   PetscBool tmp = PETSC_FALSE;
51   char      *ptr1,*ptr2 = (char*)&tmp;
52 
53   PetscFunctionBegin;
54   for (j=0; j<n; j++) {
55     ptr1 = (char*)(buff + j);
56     for (i=0; i<(PetscInt)sizeof(PetscBool); i++) ptr2[i] = ptr1[sizeof(PetscBool)-1-i];
57     for (i=0; i<(PetscInt)sizeof(PetscBool); i++) ptr1[i] = ptr2[i];
58   }
59   PetscFunctionReturn(0);
60 }
61 
62 #undef __FUNCT__
63 #define __FUNCT__ "PetscByteSwapInt"
64 /*
65   PetscByteSwapInt - Swap bytes in a  PETSc integer (which may be 32 or 64 bits)
66 
67 */
68 PetscErrorCode  PetscByteSwapInt(PetscInt *buff,PetscInt n)
69 {
70   PetscInt i,j,tmp = 0;
71   char     *ptr1,*ptr2 = (char*)&tmp;
72 
73   PetscFunctionBegin;
74   for (j=0; j<n; j++) {
75     ptr1 = (char*)(buff + j);
76     for (i=0; i<(PetscInt)sizeof(PetscInt); i++) ptr2[i] = ptr1[sizeof(PetscInt)-1-i];
77     for (i=0; i<(PetscInt)sizeof(PetscInt); i++) ptr1[i] = ptr2[i];
78   }
79   PetscFunctionReturn(0);
80 }
81 /* --------------------------------------------------------- */
82 #undef __FUNCT__
83 #define __FUNCT__ "PetscByteSwapShort"
84 /*
85   PetscByteSwapShort - Swap bytes in a short
86 */
87 PetscErrorCode  PetscByteSwapShort(short *buff,PetscInt n)
88 {
89   PetscInt i,j;
90   short    tmp;
91   char     *ptr1,*ptr2 = (char*)&tmp;
92 
93   PetscFunctionBegin;
94   for (j=0; j<n; j++) {
95     ptr1 = (char*)(buff + j);
96     for (i=0; i<(PetscInt) sizeof(short); i++) ptr2[i] = ptr1[sizeof(short)-1-i];
97     for (i=0; i<(PetscInt) sizeof(short); i++) ptr1[i] = ptr2[i];
98   }
99   PetscFunctionReturn(0);
100 }
101 /* --------------------------------------------------------- */
102 #undef __FUNCT__
103 #define __FUNCT__ "PetscByteSwapScalar"
104 /*
105   PetscByteSwapScalar - Swap bytes in a double
106   Complex is dealt with as if array of double twice as long.
107 */
108 PetscErrorCode  PetscByteSwapScalar(PetscScalar *buff,PetscInt n)
109 {
110   PetscInt  i,j;
111   PetscReal tmp,*buff1 = (PetscReal*)buff;
112   char      *ptr1,*ptr2 = (char*)&tmp;
113 
114   PetscFunctionBegin;
115 #if defined(PETSC_USE_COMPLEX)
116   n *= 2;
117 #endif
118   for (j=0; j<n; j++) {
119     ptr1 = (char*)(buff1 + j);
120     for (i=0; i<(PetscInt) sizeof(PetscReal); i++) ptr2[i] = ptr1[sizeof(PetscReal)-1-i];
121     for (i=0; i<(PetscInt) sizeof(PetscReal); i++) ptr1[i] = ptr2[i];
122   }
123   PetscFunctionReturn(0);
124 }
125 /* --------------------------------------------------------- */
126 #undef __FUNCT__
127 #define __FUNCT__ "PetscByteSwapDouble"
128 /*
129   PetscByteSwapDouble - Swap bytes in a double
130 */
131 PetscErrorCode  PetscByteSwapDouble(double *buff,PetscInt n)
132 {
133   PetscInt i,j;
134   double   tmp,*buff1 = (double*)buff;
135   char     *ptr1,*ptr2 = (char*)&tmp;
136 
137   PetscFunctionBegin;
138   for (j=0; j<n; j++) {
139     ptr1 = (char*)(buff1 + j);
140     for (i=0; i<(PetscInt) sizeof(double); i++) ptr2[i] = ptr1[sizeof(double)-1-i];
141     for (i=0; i<(PetscInt) sizeof(double); i++) ptr1[i] = ptr2[i];
142   }
143   PetscFunctionReturn(0);
144 }
145 
146 #undef __FUNCT__
147 #define __FUNCT__ "PetscByteSwapFloat"
148 /*
149   PetscByteSwapFloat - Swap bytes in a float
150 */
151 PetscErrorCode PetscByteSwapFloat(float *buff,PetscInt n)
152 {
153   PetscInt i,j;
154   float    tmp,*buff1 = (float*)buff;
155   char     *ptr1,*ptr2 = (char*)&tmp;
156 
157   PetscFunctionBegin;
158   for (j=0; j<n; j++) {
159     ptr1 = (char*)(buff1 + j);
160     for (i=0; i<(PetscInt) sizeof(float); i++) ptr2[i] = ptr1[sizeof(float)-1-i];
161     for (i=0; i<(PetscInt) sizeof(float); i++) ptr1[i] = ptr2[i];
162   }
163   PetscFunctionReturn(0);
164 }
165 
166 #undef __FUNCT__
167 #define __FUNCT__ "PetscByteSwap"
168 PetscErrorCode PetscByteSwap(void *data,PetscDataType pdtype,PetscInt count)
169 {
170   PetscErrorCode ierr;
171 
172   PetscFunctionBegin;
173   if      (pdtype == PETSC_INT)    {ierr = PetscByteSwapInt((PetscInt*)data,count);CHKERRQ(ierr);}
174   else if (pdtype == PETSC_ENUM)   {ierr = PetscByteSwapEnum((PetscEnum*)data,count);CHKERRQ(ierr);}
175   else if (pdtype == PETSC_BOOL)   {ierr = PetscByteSwapBool((PetscBool*)data,count);CHKERRQ(ierr);}
176   else if (pdtype == PETSC_SCALAR) {ierr = PetscByteSwapScalar((PetscScalar*)data,count);CHKERRQ(ierr);}
177   else if (pdtype == PETSC_DOUBLE) {ierr = PetscByteSwapDouble((double*)data,count);CHKERRQ(ierr);}
178   else if (pdtype == PETSC_FLOAT)  {ierr = PetscByteSwapFloat((float*)data,count);CHKERRQ(ierr);}
179   else if (pdtype == PETSC_SHORT)  {ierr = PetscByteSwapShort((short*)data,count);CHKERRQ(ierr);}
180   PetscFunctionReturn(0);
181 }
182 
183 /* --------------------------------------------------------- */
184 #undef __FUNCT__
185 #define __FUNCT__ "PetscBinaryRead"
186 /*@
187    PetscBinaryRead - Reads from a binary file.
188 
189    Not Collective
190 
191    Input Parameters:
192 +  fd - the file
193 .  n  - the number of items to read
194 -  type - the type of items to read (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)
195 
196    Output Parameters:
197 .  p - the buffer
198 
199 
200 
201    Level: developer
202 
203    Notes:
204    PetscBinaryRead() uses byte swapping to work on all machines; the files
205    are written to file ALWAYS using big-endian ordering. On small-endian machines the numbers
206    are converted to the small-endian format when they are read in from the file.
207    When PETSc is ./configure with --with-64bit-indices the integers are written to the
208    file as 64 bit integers, this means they can only be read back in when the option --with-64bit-indices
209    is used.
210 
211    Concepts: files^reading binary
212    Concepts: binary files^reading
213 
214 .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscViewerBinaryGetDescriptor(), PetscBinarySynchronizedWrite(),
215           PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()
216 @*/
217 PetscErrorCode  PetscBinaryRead(int fd,void *p,PetscInt n,PetscDataType type)
218 {
219   int               wsize,err;
220   size_t            m = (size_t) n,maxblock = 65536;
221   char              *pp = (char*)p;
222 #if defined(PETSC_USE_REAL___FLOAT128)
223   PetscBool         readdouble = PETSC_FALSE;
224   double            *ppp;
225 #endif
226 #if !defined(PETSC_WORDS_BIGENDIAN) || defined(PETSC_USE_REAL___FLOAT128)
227   PetscErrorCode    ierr;
228 #endif
229 #if !defined(PETSC_WORDS_BIGENDIAN)
230   void              *ptmp = p;
231 #endif
232   char              fname[64];
233   PetscBool         functionload = PETSC_FALSE;
234 
235   PetscFunctionBegin;
236   if (n < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Trying to write a negative amount of data %D",n);
237   if (!n) PetscFunctionReturn(0);
238 
239   if (type == PETSC_FUNCTION) {
240     functionload = PETSC_TRUE;
241     m            = 64;
242     type         = PETSC_CHAR;
243     pp           = (char*)fname;
244 #if !defined(PETSC_WORDS_BIGENDIAN)
245     ptmp         = (void*)fname;
246 #endif
247   }
248 
249   if (type == PETSC_INT)          m *= sizeof(PetscInt);
250   else if (type == PETSC_SCALAR)  m *= sizeof(PetscScalar);
251   else if (type == PETSC_DOUBLE)  m *= sizeof(double);
252   else if (type == PETSC_FLOAT)   m *= sizeof(float);
253   else if (type == PETSC_SHORT)   m *= sizeof(short);
254   else if (type == PETSC_CHAR)    m *= sizeof(char);
255   else if (type == PETSC_ENUM)    m *= sizeof(PetscEnum);
256   else if (type == PETSC_BOOL)   m *= sizeof(PetscBool);
257   else if (type == PETSC_BIT_LOGICAL) m  = PetscBTLength(m)*sizeof(char);
258   else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown type");
259 
260 #if defined(PETSC_USE_REAL___FLOAT128)
261   ierr = PetscOptionsGetBool(NULL,"-binary_read_double",&readdouble,NULL);CHKERRQ(ierr);
262   /* If using __float128 precision we still read in doubles from file */
263   if (type == PETSC_SCALAR && readdouble) {
264     m    = m/2;
265     ierr = PetscMalloc1(n,&ppp);CHKERRQ(ierr);
266     pp   = (char*)ppp;
267   }
268 #endif
269 
270   while (m) {
271     wsize = (m < maxblock) ? m : maxblock;
272     err   = read(fd,pp,wsize);
273     if (err < 0 && errno == EINTR) continue;
274     if (!err && wsize > 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_READ,"Read past end of file");
275     if (err < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_READ,"Error reading from file, errno %d",errno);
276     m  -= err;
277     pp += err;
278   }
279 
280 #if defined(PETSC_USE_REAL___FLOAT128)
281   if (type == PETSC_SCALAR && readdouble) {
282     PetscScalar *pv = (PetscScalar*) p;
283     PetscInt    i;
284 #if !defined(PETSC_WORDS_BIGENDIAN)
285     ierr = PetscByteSwapDouble(ppp,n);CHKERRQ(ierr);
286 #endif
287     for (i=0; i<n; i++) pv[i] = ppp[i];
288     ierr = PetscFree(ppp);CHKERRQ(ierr);
289     PetscFunctionReturn(0);
290   }
291 #endif
292 
293 #if !defined(PETSC_WORDS_BIGENDIAN)
294   ierr = PetscByteSwap(ptmp,type,n);CHKERRQ(ierr);
295 #endif
296 
297   if (functionload) {
298 #if defined(PETSC_SERIALIZE_FUNCTIONS)
299     ierr = PetscDLSym(NULL,fname,(void**)p);CHKERRQ(ierr);
300 #else
301     *(void**)p = NULL;
302 #endif
303   }
304   PetscFunctionReturn(0);
305 }
306 /* --------------------------------------------------------- */
307 #undef __FUNCT__
308 #define __FUNCT__ "PetscBinaryWrite"
309 /*@
310    PetscBinaryWrite - Writes to a binary file.
311 
312    Not Collective
313 
314    Input Parameters:
315 +  fd     - the file
316 .  p      - the buffer
317 .  n      - the number of items to write
318 .  type   - the type of items to read (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)
319 -  istemp - PETSC_FALSE if buffer data should be preserved, PETSC_TRUE otherwise.
320 
321    Level: advanced
322 
323    Notes:
324    PetscBinaryWrite() uses byte swapping to work on all machines; the files
325    are written using big-endian ordering to the file. On small-endian machines the numbers
326    are converted to the big-endian format when they are written to disk.
327    When PETSc is ./configure with --with-64bit-indices the integers are written to the
328    file as 64 bit integers, this means they can only be read back in when the option --with-64bit-indices
329    is used.
330 
331    The Buffer p should be read-write buffer, and not static data.
332    This way, byte-swapping is done in-place, and then the buffer is
333    written to the file.
334 
335    This routine restores the original contents of the buffer, after
336    it is written to the file. This is done by byte-swapping in-place
337    the second time. If the flag istemp is set to PETSC_TRUE, the second
338    byte-swapping operation is not done, thus saving some computation,
339    but the buffer is left corrupted.
340 
341    Because byte-swapping may be done on the values in data it cannot be declared const
342 
343    Concepts: files^writing binary
344    Concepts: binary files^writing
345 
346 .seealso: PetscBinaryRead(), PetscBinaryOpen(), PetscBinaryClose(), PetscViewerBinaryGetDescriptor(), PetscBinarySynchronizedWrite(),
347           PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()
348 @*/
349 PetscErrorCode  PetscBinaryWrite(int fd,void *p,PetscInt n,PetscDataType type,PetscBool  istemp)
350 {
351   char           *pp = (char*)p;
352   int            err,wsize;
353   size_t         m = (size_t)n,maxblock=65536;
354   PetscErrorCode ierr;
355 #if !defined(PETSC_WORDS_BIGENDIAN)
356   void           *ptmp = p;
357 #endif
358   char           fname[64];
359 
360   PetscFunctionBegin;
361   if (n < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Trying to write a negative amount of data %D",n);
362   if (!n) PetscFunctionReturn(0);
363 
364   if (type == PETSC_FUNCTION) {
365 #if defined(PETSC_SERIALIZE_FUNCTIONS)
366     const char *fnametmp;
367 
368     if (n > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Can only binary view a single function at a time");
369     ierr = PetscFPTFind(*(void**)p,&fnametmp);CHKERRQ(ierr);
370     ierr = PetscStrncpy(fname,fnametmp,64);CHKERRQ(ierr);
371 #else
372     ierr = PetscStrncpy(fname,"",64);CHKERRQ(ierr);
373 #endif
374     m    = 64;
375     type = PETSC_CHAR;
376     pp   = (char*)fname;
377 #if !defined(PETSC_WORDS_BIGENDIAN)
378     ptmp = (void*)fname;
379 #endif
380   }
381 
382   if (type == PETSC_INT)          m *= sizeof(PetscInt);
383   else if (type == PETSC_SCALAR)  m *= sizeof(PetscScalar);
384   else if (type == PETSC_DOUBLE)  m *= sizeof(double);
385   else if (type == PETSC_FLOAT)   m *= sizeof(float);
386   else if (type == PETSC_SHORT)   m *= sizeof(short);
387   else if (type == PETSC_CHAR)    m *= sizeof(char);
388   else if (type == PETSC_ENUM)    m *= sizeof(PetscEnum);
389   else if (type == PETSC_BOOL)   m *= sizeof(PetscBool);
390   else if (type == PETSC_BIT_LOGICAL) m = PetscBTLength(m)*sizeof(char);
391   else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown type");
392 
393 #if !defined(PETSC_WORDS_BIGENDIAN)
394   ierr = PetscByteSwap(ptmp,type,n);CHKERRQ(ierr);
395 #endif
396 
397   while (m) {
398     wsize = (m < maxblock) ? m : maxblock;
399     err   = write(fd,pp,wsize);
400     if (err < 0 && errno == EINTR) continue;
401     if (err != wsize) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_FILE_WRITE,"Error writing to file total size %d err %d wsize %d",(int)n,(int)err,(int)wsize);
402     m  -= wsize;
403     pp += wsize;
404   }
405 
406 #if !defined(PETSC_WORDS_BIGENDIAN)
407   if (!istemp) {
408     ierr = PetscByteSwap(ptmp,type,n);CHKERRQ(ierr);
409   }
410 #endif
411   PetscFunctionReturn(0);
412 }
413 
414 #undef __FUNCT__
415 #define __FUNCT__ "PetscBinaryOpen"
416 /*@C
417    PetscBinaryOpen - Opens a PETSc binary file.
418 
419    Not Collective
420 
421    Input Parameters:
422 +  name - filename
423 -  type - type of binary file, one of FILE_MODE_READ, FILE_MODE_APPEND, FILE_MODE_WRITE
424 
425    Output Parameter:
426 .  fd - the file
427 
428    Level: advanced
429 
430   Concepts: files^opening binary
431   Concepts: binary files^opening
432 
433    Notes: Files access with PetscBinaryRead() and PetscBinaryWrite() are ALWAYS written in
434    big-endian format. This means the file can be accessed using PetscBinaryOpen() and
435    PetscBinaryRead() and PetscBinaryWrite() on any machine.
436 
437 .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscFileMode, PetscViewerFileSetMode(), PetscViewerBinaryGetDescriptor(),
438           PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()
439 
440 @*/
441 PetscErrorCode  PetscBinaryOpen(const char name[],PetscFileMode mode,int *fd)
442 {
443   PetscFunctionBegin;
444 #if defined(PETSC_HAVE_O_BINARY)
445   if (mode == FILE_MODE_WRITE) {
446     if ((*fd = open(name,O_WRONLY|O_CREAT|O_TRUNC|O_BINARY,0666)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot create file for writing: %s",name);
447   } else if (mode == FILE_MODE_READ) {
448     if ((*fd = open(name,O_RDONLY|O_BINARY,0)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file for reading: %s",name);
449   } else if (mode == FILE_MODE_APPEND) {
450     if ((*fd = open(name,O_WRONLY|O_BINARY,0)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file for writing: %s",name);
451 #else
452   if (mode == FILE_MODE_WRITE) {
453     if ((*fd = creat(name,0666)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot create file for writing: %s",name);
454   } else if (mode == FILE_MODE_READ) {
455     if ((*fd = open(name,O_RDONLY,0)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file for reading: %s",name);
456   }
457   else if (mode == FILE_MODE_APPEND) {
458     if ((*fd = open(name,O_WRONLY,0)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file for writing: %s",name);
459 #endif
460   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown file mode");
461   PetscFunctionReturn(0);
462 }
463 
464 #undef __FUNCT__
465 #define __FUNCT__ "PetscBinaryClose"
466 /*@
467    PetscBinaryClose - Closes a PETSc binary file.
468 
469    Not Collective
470 
471    Output Parameter:
472 .  fd - the file
473 
474    Level: advanced
475 
476 .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
477           PetscBinarySynchronizedSeek()
478 @*/
479 PetscErrorCode  PetscBinaryClose(int fd)
480 {
481   PetscFunctionBegin;
482   close(fd);
483   PetscFunctionReturn(0);
484 }
485 
486 
487 #undef __FUNCT__
488 #define __FUNCT__ "PetscBinarySeek"
489 /*@
490    PetscBinarySeek - Moves the file pointer on a PETSc binary file.
491 
492    Not Collective
493 
494    Input Parameters:
495 +  fd - the file
496 .  off - number of bytes to move. Use PETSC_BINARY_INT_SIZE, PETSC_BINARY_SCALAR_SIZE,
497             etc. in your calculation rather than sizeof() to compute byte lengths.
498 -  whence - if PETSC_BINARY_SEEK_SET then off is an absolute location in the file
499             if PETSC_BINARY_SEEK_CUR then off is an offset from the current location
500             if PETSC_BINARY_SEEK_END then off is an offset from the end of file
501 
502    Output Parameter:
503 .   offset - new offset in file
504 
505    Level: developer
506 
507    Notes:
508    Integers are stored on the file as 32 long, regardless of whether
509    they are stored in the machine as 32 or 64, this means the same
510    binary file may be read on any machine. Hence you CANNOT use sizeof()
511    to determine the offset or location.
512 
513    Concepts: files^binary seeking
514    Concepts: binary files^seeking
515 
516 .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
517           PetscBinarySynchronizedSeek()
518 @*/
519 PetscErrorCode  PetscBinarySeek(int fd,off_t off,PetscBinarySeekType whence,off_t *offset)
520 {
521   int iwhence = 0;
522 
523   PetscFunctionBegin;
524   if (whence == PETSC_BINARY_SEEK_SET) iwhence = SEEK_SET;
525   else if (whence == PETSC_BINARY_SEEK_CUR) iwhence = SEEK_CUR;
526   else if (whence == PETSC_BINARY_SEEK_END) iwhence = SEEK_END;
527   else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown seek location");
528 #if defined(PETSC_HAVE_LSEEK)
529   *offset = lseek(fd,off,iwhence);
530 #elif defined(PETSC_HAVE__LSEEK)
531   *offset = _lseek(fd,(long)off,iwhence);
532 #else
533   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS,"System does not have a way of seeking on a file");
534 #endif
535   PetscFunctionReturn(0);
536 }
537 
538 #undef __FUNCT__
539 #define __FUNCT__ "PetscBinarySynchronizedRead"
540 /*@C
541    PetscBinarySynchronizedRead - Reads from a binary file.
542 
543    Collective on MPI_Comm
544 
545    Input Parameters:
546 +  comm - the MPI communicator
547 .  fd - the file
548 .  n  - the number of items to read
549 -  type - the type of items to read (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)
550 
551    Output Parameters:
552 .  p - the buffer
553 
554    Options Database Key:
555 .   -binary_longints - indicates the file was generated on a Cray vector
556          machine (not the T3E/D) and the ints are stored as 64 bit
557          quantities, otherwise they are stored as 32 bit
558 
559    Level: developer
560 
561    Notes:
562    Does a PetscBinaryRead() followed by an MPI_Bcast()
563 
564    PetscBinarySynchronizedRead() uses byte swapping to work on all machines.
565    Integers are stored on the file as 32 long, regardless of whether
566    they are stored in the machine as 32 or 64, this means the same
567    binary file may be read on any machine.
568 
569    Concepts: files^synchronized reading of binary files
570    Concepts: binary files^reading, synchronized
571 
572 .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscBinaryRead(), PetscBinarySynchronizedWrite(),
573           PetscBinarySynchronizedSeek()
574 @*/
575 PetscErrorCode  PetscBinarySynchronizedRead(MPI_Comm comm,int fd,void *p,PetscInt n,PetscDataType type)
576 {
577   PetscErrorCode ierr;
578   PetscMPIInt    rank;
579   MPI_Datatype   mtype;
580   char           *fname;
581   void           *ptmp = NULL;
582 
583   PetscFunctionBegin;
584   if (type == PETSC_FUNCTION) {
585     n            = 64;
586     type         = PETSC_CHAR;
587     ptmp         = p;
588     fname        = (char*)malloc(n*sizeof(char));
589     p            = (void*)fname;
590   }
591 
592   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
593   if (!rank) {
594     ierr = PetscBinaryRead(fd,p,n,type);CHKERRQ(ierr);
595   }
596   ierr = PetscDataTypeToMPIDataType(type,&mtype);CHKERRQ(ierr);
597   ierr = MPI_Bcast(p,n,mtype,0,comm);CHKERRQ(ierr);
598 
599   if (type == PETSC_FUNCTION) {
600 #if defined(PETSC_SERIALIZE_FUNCTIONS)
601     ierr = PetscDLLibrarySym(PETSC_COMM_SELF,&PetscDLLibrariesLoaded,NULL,fname,(void**)ptmp);CHKERRQ(ierr);
602 #else
603     *(void**)ptmp = NULL;
604 #endif
605     free(fname);
606   }
607   PetscFunctionReturn(0);
608 }
609 
610 #undef __FUNCT__
611 #define __FUNCT__ "PetscBinarySynchronizedWrite"
612 /*@C
613    PetscBinarySynchronizedWrite - writes to a binary file.
614 
615    Collective on MPI_Comm
616 
617    Input Parameters:
618 +  comm - the MPI communicator
619 .  fd - the file
620 .  n  - the number of items to write
621 .  p - the buffer
622 .  istemp - the buffer may be changed
623 -  type - the type of items to write (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)
624 
625    Level: developer
626 
627    Notes:
628    Process 0 does a PetscBinaryWrite()
629 
630    PetscBinarySynchronizedWrite() uses byte swapping to work on all machines.
631    Integers are stored on the file as 32 long, regardless of whether
632    they are stored in the machine as 32 or 64, this means the same
633    binary file may be read on any machine.
634 
635    Notes: because byte-swapping may be done on the values in data it cannot be declared const
636 
637    WARNING: This is NOT like PetscSynchronizedFPrintf()! This routine ignores calls on all but process 0,
638    while PetscSynchronizedFPrintf() has all processes print their strings in order.
639 
640    Concepts: files^synchronized writing of binary files
641    Concepts: binary files^reading, synchronized
642 
643 .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscBinaryRead(), PetscBinarySynchronizedRead(),
644           PetscBinarySynchronizedSeek()
645 @*/
646 PetscErrorCode  PetscBinarySynchronizedWrite(MPI_Comm comm,int fd,void *p,PetscInt n,PetscDataType type,PetscBool istemp)
647 {
648   PetscErrorCode ierr;
649   PetscMPIInt    rank;
650 
651   PetscFunctionBegin;
652   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
653   if (!rank) {
654     ierr = PetscBinaryWrite(fd,p,n,type,istemp);CHKERRQ(ierr);
655   }
656   PetscFunctionReturn(0);
657 }
658 
659 #undef __FUNCT__
660 #define __FUNCT__ "PetscBinarySynchronizedSeek"
661 /*@C
662    PetscBinarySynchronizedSeek - Moves the file pointer on a PETSc binary file.
663 
664 
665    Input Parameters:
666 +  fd - the file
667 .  whence - if PETSC_BINARY_SEEK_SET then size is an absolute location in the file
668             if PETSC_BINARY_SEEK_CUR then size is offset from current location
669             if PETSC_BINARY_SEEK_END then size is offset from end of file
670 -  off    - number of bytes to move. Use PETSC_BINARY_INT_SIZE, PETSC_BINARY_SCALAR_SIZE,
671             etc. in your calculation rather than sizeof() to compute byte lengths.
672 
673    Output Parameter:
674 .   offset - new offset in file
675 
676    Level: developer
677 
678    Notes:
679    Integers are stored on the file as 32 long, regardless of whether
680    they are stored in the machine as 32 or 64, this means the same
681    binary file may be read on any machine. Hence you CANNOT use sizeof()
682    to determine the offset or location.
683 
684    Concepts: binary files^seeking
685    Concepts: files^seeking in binary
686 
687 .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
688           PetscBinarySynchronizedSeek()
689 @*/
690 PetscErrorCode  PetscBinarySynchronizedSeek(MPI_Comm comm,int fd,off_t off,PetscBinarySeekType whence,off_t *offset)
691 {
692   PetscErrorCode ierr;
693   PetscMPIInt    rank;
694 
695   PetscFunctionBegin;
696   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
697   if (!rank) {
698     ierr = PetscBinarySeek(fd,off,whence,offset);CHKERRQ(ierr);
699   }
700   PetscFunctionReturn(0);
701 }
702 
703 #if defined(PETSC_HAVE_MPIIO)
704 #if !defined(PETSC_WORDS_BIGENDIAN)
705 
706 #if defined(PETSC_USE_PETSC_MPI_EXTERNAL32)
707 /*
708       MPICH does not provide the external32 representation for MPI_File_set_view() so we need to provide the functions.
709     These are set into MPI in PetscInitialize() via MPI_Register_datarep()
710 
711     Note I use PetscMPIInt for the MPI error codes since that is what MPI uses (instead of the standard PetscErrorCode)
712 
713     The next three routines are not used because MPICH does not support their use
714 
715 */
716 PETSC_EXTERN PetscMPIInt PetscDataRep_extent_fn(MPI_Datatype datatype,MPI_Aint *file_extent,void *extra_state)
717 {
718   MPI_Aint    ub;
719   PetscMPIInt ierr;
720 
721   ierr = MPI_Type_get_extent(datatype,&ub,file_extent);
722   return ierr;
723 }
724 
725 PETSC_EXTERN PetscMPIInt PetscDataRep_read_conv_fn(void *userbuf, MPI_Datatype datatype,PetscMPIInt count,void *filebuf, MPI_Offset position,void *extra_state)
726 {
727   PetscDataType pdtype;
728   PetscMPIInt   ierr;
729   size_t        dsize;
730 
731   ierr = PetscMPIDataTypeToPetscDataType(datatype,&pdtype);CHKERRQ(ierr);
732   ierr = PetscDataTypeGetSize(pdtype,&dsize);CHKERRQ(ierr);
733 
734   /* offset is given in units of MPI_Datatype */
735   userbuf = ((char*)userbuf) + dsize*position;
736 
737   ierr = PetscMemcpy(userbuf,filebuf,count*dsize);CHKERRQ(ierr);
738   ierr = PetscByteSwap(userbuf,pdtype,count);CHKERRQ(ierr);
739   return ierr;
740 }
741 
742 PetscMPIInt PetscDataRep_write_conv_fn(void *userbuf, MPI_Datatype datatype,PetscMPIInt count,void *filebuf, MPI_Offset position,void *extra_state)
743 {
744   PetscDataType pdtype;
745   PetscMPIInt   ierr;
746   size_t        dsize;
747 
748   ierr = PetscMPIDataTypeToPetscDataType(datatype,&pdtype);CHKERRQ(ierr);
749   ierr = PetscDataTypeGetSize(pdtype,&dsize);CHKERRQ(ierr);
750 
751   /* offset is given in units of MPI_Datatype */
752   userbuf = ((char*)userbuf) + dsize*position;
753 
754   ierr = PetscMemcpy(filebuf,userbuf,count*dsize);CHKERRQ(ierr);
755   ierr = PetscByteSwap(filebuf,pdtype,count);CHKERRQ(ierr);
756   return ierr;
757 }
758 #endif
759 
760 #undef __FUNCT__
761 #define __FUNCT__ "MPIU_File_write_all"
762 PetscErrorCode MPIU_File_write_all(MPI_File fd,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status)
763 {
764   PetscErrorCode ierr;
765   PetscDataType  pdtype;
766 
767   PetscFunctionBegin;
768   ierr = PetscMPIDataTypeToPetscDataType(dtype,&pdtype);CHKERRQ(ierr);
769   ierr = PetscByteSwap(data,pdtype,cnt);CHKERRQ(ierr);
770   ierr = MPI_File_write_all(fd,data,cnt,dtype,status);CHKERRQ(ierr);
771   ierr = PetscByteSwap(data,pdtype,cnt);CHKERRQ(ierr);
772   PetscFunctionReturn(0);
773 }
774 
775 #undef __FUNCT__
776 #define __FUNCT__ "MPIU_File_read_all"
777 PetscErrorCode MPIU_File_read_all(MPI_File fd,void *data,PetscMPIInt cnt,MPI_Datatype dtype,MPI_Status *status)
778 {
779   PetscErrorCode ierr;
780   PetscDataType  pdtype;
781 
782   PetscFunctionBegin;
783   ierr = PetscMPIDataTypeToPetscDataType(dtype,&pdtype);CHKERRQ(ierr);
784   ierr = MPI_File_read_all(fd,data,cnt,dtype,status);CHKERRQ(ierr);
785   ierr = PetscByteSwap(data,pdtype,cnt);CHKERRQ(ierr);
786   PetscFunctionReturn(0);
787 }
788 #endif
789 #endif
790