xref: /petsc/src/sys/fileio/sysio.c (revision a3afe2d1ed14aa25e6e8bcdd861505b3816b69e5)
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   double            *ppp;
224 #endif
225 #if !defined(PETSC_WORDS_BIGENDIAN) || defined(PETSC_USE_REAL___FLOAT128)
226   PetscErrorCode    ierr;
227 #endif
228 #if !defined(PETSC_WORDS_BIGENDIAN)
229   void              *ptmp = p;
230 #endif
231   char              fname[64];
232   PetscBool         functionload = PETSC_FALSE;
233 
234   PetscFunctionBegin;
235   if (n < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Trying to write a negative amount of data %D",n);
236   if (!n) PetscFunctionReturn(0);
237 
238   if (type == PETSC_FUNCTION) {
239     functionload = PETSC_TRUE;
240     m            = 64;
241     type         = PETSC_CHAR;
242     pp           = (char*)fname;
243 #if !defined(PETSC_WORDS_BIGENDIAN)
244     ptmp         = (void*)fname;
245 #endif
246   }
247 
248   if (type == PETSC_INT)          m *= sizeof(PetscInt);
249   else if (type == PETSC_SCALAR)  m *= sizeof(PetscScalar);
250   else if (type == PETSC_DOUBLE)  m *= sizeof(double);
251   else if (type == PETSC_FLOAT)   m *= sizeof(float);
252   else if (type == PETSC_SHORT)   m *= sizeof(short);
253   else if (type == PETSC_CHAR)    m *= sizeof(char);
254   else if (type == PETSC_ENUM)    m *= sizeof(PetscEnum);
255   else if (type == PETSC_BOOL)   m *= sizeof(PetscBool);
256   else if (type == PETSC_BIT_LOGICAL) m  = PetscBTLength(m)*sizeof(char);
257   else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown type");
258 
259 #if defined(PETSC_USE_REAL___FLOAT128)
260   /* If using __float128 precision we still read in doubles from file */
261   if (type == PETSC_SCALAR) {
262     m    = m/2;
263     ierr = PetscMalloc(n*sizeof(double),&ppp);CHKERRQ(ierr);
264     pp   = (char*)ppp;
265   }
266 #endif
267 
268   while (m) {
269     wsize = (m < maxblock) ? m : maxblock;
270     err   = read(fd,pp,wsize);
271     if (err < 0 && errno == EINTR) continue;
272     if (!err && wsize > 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_READ,"Read past end of file");
273     if (err < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_READ,"Error reading from file, errno %d",errno);
274     m  -= err;
275     pp += err;
276   }
277 
278 #if defined(PETSC_USE_REAL___FLOAT128)
279   if (type == PETSC_SCALAR) {
280     PetscScalar *pv = (PetscScalar*) p;
281     PetscInt    i;
282 #if !defined(PETSC_WORDS_BIGENDIAN)
283     ierr = PetscByteSwapDouble(ppp,n);CHKERRQ(ierr);
284 #endif
285     for (i=0; i<n; i++) pv[i] = ppp[i];
286     ierr = PetscFree(ppp);CHKERRQ(ierr);
287     PetscFunctionReturn(0);
288   }
289 #endif
290 
291 #if !defined(PETSC_WORDS_BIGENDIAN)
292   ierr = PetscByteSwap(ptmp,type,n);CHKERRQ(ierr);
293 #endif
294 
295   if (functionload) {
296 #if defined(PETSC_SERIALIZE_FUNCTIONS)
297     ierr = PetscDLSym(NULL,fname,(void**)p);CHKERRQ(ierr);
298 #else
299     *(void**)p = NULL;
300 #endif
301   }
302   PetscFunctionReturn(0);
303 }
304 /* --------------------------------------------------------- */
305 #undef __FUNCT__
306 #define __FUNCT__ "PetscBinaryWrite"
307 /*@
308    PetscBinaryWrite - Writes to a binary file.
309 
310    Not Collective
311 
312    Input Parameters:
313 +  fd     - the file
314 .  p      - the buffer
315 .  n      - the number of items to write
316 .  type   - the type of items to read (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)
317 -  istemp - PETSC_FALSE if buffer data should be preserved, PETSC_TRUE otherwise.
318 
319    Level: advanced
320 
321    Notes:
322    PetscBinaryWrite() uses byte swapping to work on all machines; the files
323    are written using big-endian ordering to the file. On small-endian machines the numbers
324    are converted to the big-endian format when they are written to disk.
325    When PETSc is ./configure with --with-64bit-indices the integers are written to the
326    file as 64 bit integers, this means they can only be read back in when the option --with-64bit-indices
327    is used.
328 
329    The Buffer p should be read-write buffer, and not static data.
330    This way, byte-swapping is done in-place, and then the buffer is
331    written to the file.
332 
333    This routine restores the original contents of the buffer, after
334    it is written to the file. This is done by byte-swapping in-place
335    the second time. If the flag istemp is set to PETSC_TRUE, the second
336    byte-swapping operation is not done, thus saving some computation,
337    but the buffer is left corrupted.
338 
339    Because byte-swapping may be done on the values in data it cannot be declared const
340 
341    Concepts: files^writing binary
342    Concepts: binary files^writing
343 
344 .seealso: PetscBinaryRead(), PetscBinaryOpen(), PetscBinaryClose(), PetscViewerBinaryGetDescriptor(), PetscBinarySynchronizedWrite(),
345           PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()
346 @*/
347 PetscErrorCode  PetscBinaryWrite(int fd,void *p,PetscInt n,PetscDataType type,PetscBool  istemp)
348 {
349   char           *pp = (char*)p;
350   int            err,wsize;
351   size_t         m = (size_t)n,maxblock=65536;
352   PetscErrorCode ierr;
353 #if !defined(PETSC_WORDS_BIGENDIAN)
354   void           *ptmp = p;
355 #endif
356   char           fname[64];
357 
358   PetscFunctionBegin;
359   if (n < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Trying to write a negative amount of data %D",n);
360   if (!n) PetscFunctionReturn(0);
361 
362   if (type == PETSC_FUNCTION) {
363 #if defined(PETSC_SERIALIZE_FUNCTIONS)
364     const char *fnametmp;
365 
366     if (n > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Can only binary view a single function at a time");
367     ierr = PetscFPTFind(p,&fnametmp);CHKERRQ(ierr);
368     ierr = PetscStrncpy(fname,fnametmp,64);CHKERRQ(ierr);
369 #else
370     ierr = PetscStrncpy(fname,"",64);CHKERRQ(ierr);
371 #endif
372     m    = 64;
373     type = PETSC_CHAR;
374     pp   = (char*)fname;
375 #if !defined(PETSC_WORDS_BIGENDIAN)
376     ptmp = (void*)fname;
377 #endif
378   }
379 
380   if (type == PETSC_INT)          m *= sizeof(PetscInt);
381   else if (type == PETSC_SCALAR)  m *= sizeof(PetscScalar);
382   else if (type == PETSC_DOUBLE)  m *= sizeof(double);
383   else if (type == PETSC_FLOAT)   m *= sizeof(float);
384   else if (type == PETSC_SHORT)   m *= sizeof(short);
385   else if (type == PETSC_CHAR)    m *= sizeof(char);
386   else if (type == PETSC_ENUM)    m *= sizeof(PetscEnum);
387   else if (type == PETSC_BOOL)   m *= sizeof(PetscBool);
388   else if (type == PETSC_BIT_LOGICAL) m = PetscBTLength(m)*sizeof(char);
389   else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown type");
390 
391 #if !defined(PETSC_WORDS_BIGENDIAN)
392   ierr = PetscByteSwap(ptmp,type,n);CHKERRQ(ierr);
393 #endif
394 
395   while (m) {
396     wsize = (m < maxblock) ? m : maxblock;
397     err   = write(fd,pp,wsize);
398     if (err < 0 && errno == EINTR) continue;
399     if (err != wsize) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_WRITE,"Error writing to file.");
400     m  -= wsize;
401     pp += wsize;
402   }
403 
404 #if !defined(PETSC_WORDS_BIGENDIAN)
405   if (!istemp) {
406     ierr = PetscByteSwap(ptmp,type,n);CHKERRQ(ierr);
407   }
408 #endif
409   PetscFunctionReturn(0);
410 }
411 
412 #undef __FUNCT__
413 #define __FUNCT__ "PetscBinaryOpen"
414 /*@C
415    PetscBinaryOpen - Opens a PETSc binary file.
416 
417    Not Collective
418 
419    Input Parameters:
420 +  name - filename
421 -  type - type of binary file, one of FILE_MODE_READ, FILE_MODE_APPEND, FILE_MODE_WRITE
422 
423    Output Parameter:
424 .  fd - the file
425 
426    Level: advanced
427 
428   Concepts: files^opening binary
429   Concepts: binary files^opening
430 
431    Notes: Files access with PetscBinaryRead() and PetscBinaryWrite() are ALWAYS written in
432    big-endian format. This means the file can be accessed using PetscBinaryOpen() and
433    PetscBinaryRead() and PetscBinaryWrite() on any machine.
434 
435 .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscFileMode, PetscViewerFileSetMode(), PetscViewerBinaryGetDescriptor(),
436           PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(), PetscBinarySynchronizedSeek()
437 
438 @*/
439 PetscErrorCode  PetscBinaryOpen(const char name[],PetscFileMode mode,int *fd)
440 {
441   PetscFunctionBegin;
442 #if defined(PETSC_HAVE_O_BINARY)
443   if (mode == FILE_MODE_WRITE) {
444     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);
445   } else if (mode == FILE_MODE_READ) {
446     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);
447   } else if (mode == FILE_MODE_APPEND) {
448     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);
449 #else
450   if (mode == FILE_MODE_WRITE) {
451     if ((*fd = creat(name,0666)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot create file for writing: %s",name);
452   } else if (mode == FILE_MODE_READ) {
453     if ((*fd = open(name,O_RDONLY,0)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file for reading: %s",name);
454   }
455   else if (mode == FILE_MODE_APPEND) {
456     if ((*fd = open(name,O_WRONLY,0)) == -1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Cannot open file for writing: %s",name);
457 #endif
458   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown file mode");
459   PetscFunctionReturn(0);
460 }
461 
462 #undef __FUNCT__
463 #define __FUNCT__ "PetscBinaryClose"
464 /*@
465    PetscBinaryClose - Closes a PETSc binary file.
466 
467    Not Collective
468 
469    Output Parameter:
470 .  fd - the file
471 
472    Level: advanced
473 
474 .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
475           PetscBinarySynchronizedSeek()
476 @*/
477 PetscErrorCode  PetscBinaryClose(int fd)
478 {
479   PetscFunctionBegin;
480   close(fd);
481   PetscFunctionReturn(0);
482 }
483 
484 
485 #undef __FUNCT__
486 #define __FUNCT__ "PetscBinarySeek"
487 /*@
488    PetscBinarySeek - Moves the file pointer on a PETSc binary file.
489 
490    Not Collective
491 
492    Input Parameters:
493 +  fd - the file
494 .  off - number of bytes to move. Use PETSC_BINARY_INT_SIZE, PETSC_BINARY_SCALAR_SIZE,
495             etc. in your calculation rather than sizeof() to compute byte lengths.
496 -  whence - if PETSC_BINARY_SEEK_SET then off is an absolute location in the file
497             if PETSC_BINARY_SEEK_CUR then off is an offset from the current location
498             if PETSC_BINARY_SEEK_END then off is an offset from the end of file
499 
500    Output Parameter:
501 .   offset - new offset in file
502 
503    Level: developer
504 
505    Notes:
506    Integers are stored on the file as 32 long, regardless of whether
507    they are stored in the machine as 32 or 64, this means the same
508    binary file may be read on any machine. Hence you CANNOT use sizeof()
509    to determine the offset or location.
510 
511    Concepts: files^binary seeking
512    Concepts: binary files^seeking
513 
514 .seealso: PetscBinaryRead(), PetscBinaryWrite(), PetscBinaryOpen(), PetscBinarySynchronizedWrite(), PetscBinarySynchronizedRead(),
515           PetscBinarySynchronizedSeek()
516 @*/
517 PetscErrorCode  PetscBinarySeek(int fd,off_t off,PetscBinarySeekType whence,off_t *offset)
518 {
519   int iwhence = 0;
520 
521   PetscFunctionBegin;
522   if (whence == PETSC_BINARY_SEEK_SET) iwhence = SEEK_SET;
523   else if (whence == PETSC_BINARY_SEEK_CUR) iwhence = SEEK_CUR;
524   else if (whence == PETSC_BINARY_SEEK_END) iwhence = SEEK_END;
525   else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Unknown seek location");
526 #if defined(PETSC_HAVE_LSEEK)
527   *offset = lseek(fd,off,iwhence);
528 #elif defined(PETSC_HAVE__LSEEK)
529   *offset = _lseek(fd,(long)off,iwhence);
530 #else
531   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS,"System does not have a way of seeking on a file");
532 #endif
533   PetscFunctionReturn(0);
534 }
535 
536 #undef __FUNCT__
537 #define __FUNCT__ "PetscBinarySynchronizedRead"
538 /*@C
539    PetscBinarySynchronizedRead - Reads from a binary file.
540 
541    Collective on MPI_Comm
542 
543    Input Parameters:
544 +  comm - the MPI communicator
545 .  fd - the file
546 .  n  - the number of items to read
547 -  type - the type of items to read (PETSC_INT, PETSC_DOUBLE or PETSC_SCALAR)
548 
549    Output Parameters:
550 .  p - the buffer
551 
552    Options Database Key:
553 .   -binary_longints - indicates the file was generated on a Cray vector
554          machine (not the T3E/D) and the ints are stored as 64 bit
555          quantities, otherwise they are stored as 32 bit
556 
557    Level: developer
558 
559    Notes:
560    Does a PetscBinaryRead() followed by an MPI_Bcast()
561 
562    PetscBinarySynchronizedRead() uses byte swapping to work on all machines.
563    Integers are stored on the file as 32 long, regardless of whether
564    they are stored in the machine as 32 or 64, this means the same
565    binary file may be read on any machine.
566 
567    Concepts: files^synchronized reading of binary files
568    Concepts: binary files^reading, synchronized
569 
570 .seealso: PetscBinaryWrite(), PetscBinaryOpen(), PetscBinaryClose(), PetscBinaryRead(), PetscBinarySynchronizedWrite(),
571           PetscBinarySynchronizedSeek()
572 @*/
573 PetscErrorCode  PetscBinarySynchronizedRead(MPI_Comm comm,int fd,void *p,PetscInt n,PetscDataType type)
574 {
575   PetscErrorCode ierr;
576   PetscMPIInt    rank;
577   MPI_Datatype   mtype;
578   char           *fname;
579   PetscBool      functionload = PETSC_FALSE;
580   void           *ptmp        = NULL;
581 
582   PetscFunctionBegin;
583   if (type == PETSC_FUNCTION) {
584     functionload = PETSC_TRUE;
585     n            = 64;
586     type         = PETSC_CHAR;
587     ptmp         = p;
588     /* warning memory leak */
589     fname        = (char*)malloc(64*sizeof(char));
590     p            = (void*)fname;
591   }
592 
593   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
594   if (!rank) {
595     ierr = PetscBinaryRead(fd,p,n,type);CHKERRQ(ierr);
596   }
597   ierr = PetscDataTypeToMPIDataType(type,&mtype);CHKERRQ(ierr);
598   ierr = MPI_Bcast(p,n,mtype,0,comm);CHKERRQ(ierr);
599 
600   if (functionload) {
601 #if defined(PETSC_SERIALIZE_FUNCTIONS)
602     ierr = PetscDLLibrarySym(PETSC_COMM_SELF,&PetscDLLibrariesLoaded,NULL,fname,(void**)ptmp);CHKERRQ(ierr);
603 #else
604     *(void**)ptmp = NULL;
605 #endif
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