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