1 #ifndef __CS_FILE_H__
2 #define __CS_FILE_H__
3 
4 /*============================================================================
5  * File and directory operations, with parallel file I/O
6  *============================================================================*/
7 
8 /*
9   This file is part of Code_Saturne, a general-purpose CFD tool.
10 
11   Copyright (C) 1998-2021 EDF S.A.
12 
13   This program is free software; you can redistribute it and/or modify it under
14   the terms of the GNU General Public License as published by the Free Software
15   Foundation; either version 2 of the License, or (at your option) any later
16   version.
17 
18   This program is distributed in the hope that it will be useful, but WITHOUT
19   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
20   FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
21   details.
22 
23   You should have received a copy of the GNU General Public License along with
24   this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
25   Street, Fifth Floor, Boston, MA 02110-1301, USA.
26 */
27 
28 /*----------------------------------------------------------------------------*/
29 
30 #if defined(HAVE_MPI)
31 #include <mpi.h>
32 #endif
33 
34 /*----------------------------------------------------------------------------
35  *  Local headers
36  *----------------------------------------------------------------------------*/
37 
38 #include "cs_defs.h"
39 
40 /*----------------------------------------------------------------------------*/
41 
42 BEGIN_C_DECLS
43 
44 /*=============================================================================
45  * Macro definitions
46  *============================================================================*/
47 
48 /*============================================================================
49  * Type definitions
50  *============================================================================*/
51 
52 /* File descriptor */
53 
54 typedef struct _cs_file_t  cs_file_t;
55 
56 /* Helper structure for IO serialization */
57 
58 #if defined(HAVE_MPI)
59 typedef struct _cs_file_serializer_t cs_file_serializer_t;
60 #endif
61 
62 /* File modes */
63 
64 typedef enum {
65 
66   CS_FILE_MODE_READ,   /* Read mode */
67   CS_FILE_MODE_WRITE,  /* Write mode */
68   CS_FILE_MODE_APPEND  /* Append mode */
69 
70 } cs_file_mode_t;
71 
72 /* Possibilities for the third argument of cs_file_seek() */
73 
74 typedef enum {
75 
76   CS_FILE_SEEK_SET,   /* Seek from beginning of file */
77   CS_FILE_SEEK_CUR,   /* Seek from current position */
78   CS_FILE_SEEK_END    /* Seek from end of file */
79 
80 } cs_file_seek_t;
81 
82 /* File access methods */
83 
84 typedef enum {
85 
86   CS_FILE_DEFAULT,
87   CS_FILE_STDIO_SERIAL,
88   CS_FILE_STDIO_PARALLEL,
89   CS_FILE_MPI_INDEPENDENT,
90   CS_FILE_MPI_NON_COLLECTIVE,
91   CS_FILE_MPI_COLLECTIVE
92 
93 } cs_file_access_t;
94 
95 /* MPI-IO file positioning methods */
96 
97 typedef enum {
98 
99   CS_FILE_MPI_EXPLICIT_OFFSETS,
100   CS_FILE_MPI_INDIVIDUAL_POINTERS
101 
102 } cs_file_mpi_positioning_t;
103 
104 /* Offset for file position indicator (int64_t in C99) */
105 
106 #if defined(SIZEOF_LONG_LONG)
107 typedef long long cs_file_off_t;
108 #else
109 typedef long cs_file_off_t;
110 #endif
111 
112 /*=============================================================================
113  * Global variables
114  *============================================================================*/
115 
116 /* names associated with file access methods */
117 
118 extern const char  *cs_file_access_name[];
119 
120 /* names associated with MPI-IO positioning */
121 
122 extern const char  *cs_file_mpi_positioning_name[];
123 
124 /*=============================================================================
125  * Public function prototypes
126  *============================================================================*/
127 
128 /*----------------------------------------------------------------------------
129  * Create a file descriptor and open the associated file.
130  *
131  * By default, data is written or read as native data. This behavior may be
132  * modified by cs_file_set_swap_endian().
133  *
134  * parameters:
135  *   name       <-- file name
136  *   mode       <-- file access mode: read, write, or append
137  *   method     <-- file access method
138  *   hints      <-- associated hints for MPI-IO, or MPI_INFO_NULL
139  *   block_comm <-- handle to MPI communicator used for distributed file
140  *                  block access (may be a subset of comm if some ranks do
141  *                  not directly access distributed data blocks)
142  *   comm       <-- handle to main MPI communicator
143  *
144  * returns:
145  *   pointer to cs_file_t file descriptor (NULL in case of failure);
146  *   currently, errors are fatal.
147  *----------------------------------------------------------------------------*/
148 
149 #if defined(HAVE_MPI)
150 
151 cs_file_t *
152 cs_file_open(const char        *name,
153              cs_file_mode_t     mode,
154              cs_file_access_t   method,
155              MPI_Info           hints,
156              MPI_Comm           block_comm,
157              MPI_Comm           comm);
158 
159 #else
160 
161 cs_file_t *
162 cs_file_open(const char        *name,
163              cs_file_mode_t     mode,
164              cs_file_access_t   method);
165 
166 #endif
167 
168 /*----------------------------------------------------------------------------
169  * Create a file descriptor and open the associated file, using the default
170  * file communicator and access method.
171  *
172  * By default, data is written or read as native data. This behavior may be
173  * modified by cs_file_set_swap_endian().
174  *
175  * parameters:
176  *   name    <-- file name
177  *   mode    <-- file access mode: read, write, or append
178  *
179  * returns:
180  *   pointer to cs_file_t file descriptor (NULL in case of failure);
181  *   currently, errors are fatal.
182  *----------------------------------------------------------------------------*/
183 
184 cs_file_t *
185 cs_file_open_default(const char        *name,
186                      cs_file_mode_t     mode);
187 
188 /*----------------------------------------------------------------------------*/
189 /*!
190  * \brief Create a file descriptor and open the associated file, using the
191  *        serial IO on the root rank.
192  *
193  * By default, data is written or read as native data. This behavior may be
194  * modified by cs_file_set_swap_endian().
195  *
196  * \param[in]  name   file name
197  * \param[in]  mode   file access mode: read, write, or append
198  *
199  * \return pointer to cs_file_t file descriptor (NULL in case of failure);
200  *   currently, errors are fatal.
201  */
202 /*----------------------------------------------------------------------------*/
203 
204 cs_file_t *
205 cs_file_open_serial(const char      *name,
206                     cs_file_mode_t   mode);
207 
208 /*----------------------------------------------------------------------------
209  * Destroy a file descriptor and close the associated file.
210  *
211  * parameters:
212  *   f <-> file descriptor to destroy
213  *
214  * returns:
215  *   NULL pointer
216  *----------------------------------------------------------------------------*/
217 
218 cs_file_t *
219 cs_file_free(cs_file_t  *f);
220 
221 /*----------------------------------------------------------------------------
222  * Return a file's name.
223  *
224  * parameters:
225  *   f <-- cs_file_t descriptor
226  *
227  * returns:
228  *   pointer to the file's name.
229  *----------------------------------------------------------------------------*/
230 
231 const char *
232 cs_file_get_name(const cs_file_t  *f);
233 
234 /*----------------------------------------------------------------------------
235  * Ensure that data is read or written in big-endian
236  * (network standard) format.
237  *
238  * parameters:
239  *   f <-> cs_file_t descriptor
240  *----------------------------------------------------------------------------*/
241 
242 void
243 cs_file_set_big_endian(cs_file_t  *f);
244 
245 /*----------------------------------------------------------------------------
246  * Return a file's byte-swapping behavior.
247  *
248  * parameters:
249  *   f <-- cs_file_t descriptor
250  *
251  * returns:
252  *   0 if file's endianness is the same as the system's, 1 otherwise.
253  *----------------------------------------------------------------------------*/
254 
255 int
256 cs_file_get_swap_endian(const cs_file_t  *f);
257 
258 /*----------------------------------------------------------------------------
259  * Set a file's byte-swapping behavior.
260  *
261  * Using this function assumes one is familiar with a file's coding
262  * or structure; use with caution.
263  *
264  * parameters:
265  *   f    <-> cs_file_t descriptor
266  *   swap <-- 1 if bytes must be swapped, 0 otherwise
267  *----------------------------------------------------------------------------*/
268 
269 void
270 cs_file_set_swap_endian(cs_file_t  *f,
271                         int         swap);
272 
273 /*----------------------------------------------------------------------------
274  * Read global data from a file, distributing it to all processes
275  * associated with that file.
276  *
277  * parameters:
278  *   f    <-- cs_file_t descriptor
279  *   buf  --> pointer to location receiving data
280  *   size <-- size of each item of data in bytes
281  *   ni   <-- number of items to read
282  *
283  * returns:
284  *   the number of items (not bytes) sucessfully read; currently,
285  *   errors are fatal.
286  *----------------------------------------------------------------------------*/
287 
288 size_t
289 cs_file_read_global(cs_file_t  *f,
290                     void       *buf,
291                     size_t      size,
292                     size_t      ni);
293 
294 /*----------------------------------------------------------------------------
295  * Write global data to a file.
296  *
297  * Under MPI, data is only written by the associated communicator's root
298  * rank. The buffers on other ranks are ignored, though the file offset
299  * is updated (i.e. the call to this function is collective).
300  *
301  * parameters:
302  *   f    <-- cs_file_t descriptor
303  *   buf  <-- pointer to location containing data
304  *   size <-- size of each item of data in bytes
305  *   ni   <-- number of items to read
306  *
307  * returns:
308  *   the number of items (not bytes) sucessfully written; currently,
309  *   errors are fatal.
310  *----------------------------------------------------------------------------*/
311 
312 size_t
313 cs_file_write_global(cs_file_t   *f,
314                      const void  *buf,
315                      size_t       size,
316                      size_t       ni);
317 
318 /*----------------------------------------------------------------------------
319  * Read data to a buffer, distributing a contiguous part of it to each
320  * process associated with a file.
321  *
322  * Each process should receive a (possibly empty) block of the data,
323  * and we should have:
324  *   global_num_start at rank 0 = 1
325  *   global_num_start at rank i+1 = global_num_end at rank i.
326  * Otherwise, behavior (especially positioning for future reads) is undefined.
327  *
328  * parameters:
329  *   f                <-- cs_file_t descriptor
330  *   buf              --> pointer to location receiving data
331  *   size             <-- size of each item of data in bytes
332  *   stride           <-- number of (interlaced) values per block item
333  *   global_num_start <-- global number of first block item (1 to n numbering)
334  *   global_num_end   <-- global number of past-the end block item
335  *                        (1 to n numbering)
336  *
337  * returns:
338  *   the (local) number of items (not bytes) sucessfully read; currently,
339  *   errors are fatal.
340  *----------------------------------------------------------------------------*/
341 
342 size_t
343 cs_file_read_block(cs_file_t  *f,
344                    void       *buf,
345                    size_t      size,
346                    size_t      stride,
347                    cs_gnum_t   global_num_start,
348                    cs_gnum_t   global_num_end);
349 
350 /*----------------------------------------------------------------------------
351  * Write data to a file, each associated process providing a contiguous part
352  * of this data.
353  *
354  * Each process should provide a (possibly empty) block of the data,
355  * and we should have:
356  *   global_num_start at rank 0 = 1
357  *   global_num_start at rank i+1 = global_num_end at rank i.
358  * Otherwise, behavior (especially positioning for future reads) is undefined.
359  *
360  * This function may require an internal copy of the data to ensure that
361  * the buffer contents are not modified, so if the buffer contents are
362  * temporary values, to be deleted after writing, using
363  * cs_file_write_block_buffer() instead may be used to avoid an unneeded
364  * memory allocation and copy.
365  *
366  * parameters:
367  *   f                <-- cs_file_t descriptor
368  *   buf              <-- pointer to location containing data
369  *   size             <-- size of each item of data in bytes
370  *   stride           <-- number of (interlaced) values per block item
371  *   global_num_start <-- global number of first block item (1 to n numbering)
372  *   global_num_end   <-- global number of past-the end block item
373  *                        (1 to n numbering)
374  *
375  * returns:
376  *   the (local) number of items (not bytes) sucessfully written; currently,
377  *   errors are fatal.
378  *----------------------------------------------------------------------------*/
379 
380 size_t
381 cs_file_write_block(cs_file_t   *f,
382                     const void  *buf,
383                     size_t       size,
384                     size_t       stride,
385                     cs_gnum_t    global_num_start,
386                     cs_gnum_t    global_num_end);
387 
388 /*----------------------------------------------------------------------------
389  * Write data to a file, each associated process providing a contiguous part
390  * of this data.
391  *
392  * Each process should provide a (possibly empty) block of the data,
393  * and we should have:
394  *   global_num_start at rank 0 = 1
395  *   global_num_start at rank i+1 = global_num_end at rank i.
396  * Otherwise, behavior (especially positioning for future reads) is undefined.
397  *
398  * This function is intended to be used mainly data that is already a
399  * copy of original data (such as data that has been redistributed across
400  * processors just for the sake of output), or that is to be deleted after
401  * writing, so it may modify the values in its input buffer (notably to
402  * convert from little-endian to big-endian of vice-versa if necessary).
403  *
404  * parameters:
405  *   f                <-- cs_file_t descriptor
406  *   buf              <-> pointer to location containing data
407  *   size             <-- size of each item of data in bytes
408  *   stride           <-- number of (interlaced) values per block item
409  *   global_num_start <-- global number of first block item (1 to n numbering)
410  *   global_num_end   <-- global number of past-the end block item
411  *                        (1 to n numbering)
412  *
413  * returns:
414  *   the (local) number of items (not bytes) sucessfully written; currently,
415  *   errors are fatal.
416  *----------------------------------------------------------------------------*/
417 
418 size_t
419 cs_file_write_block_buffer(cs_file_t  *f,
420                            void       *buf,
421                            size_t      size,
422                            size_t      stride,
423                            cs_gnum_t   global_num_start,
424                            cs_gnum_t   global_num_end);
425 
426 /*----------------------------------------------------------------------------
427  * Update the file pointer according to whence.
428  *
429  * parameters:
430  *   f      <-> cs_file_t descriptor.
431  *   offset <-- add to position specified to whence to obtain new position,
432  *              measured in characters from the beginning of the file.
433  *   whence <-- beginning if CS_FILE_SEEK_SET, current if CS_FILE_SEEK_CUR,
434  *               or end-of-file if CS_FILE_SEEK_END.
435  *
436  * returns:
437  *   0 upon success, nonzero otherwise; currently, errors are fatal.
438  *----------------------------------------------------------------------------*/
439 
440 int
441 cs_file_seek(cs_file_t       *f,
442              cs_file_off_t    offset,
443              cs_file_seek_t   whence);
444 
445 /*----------------------------------------------------------------------------
446  * Return the position of the file pointer.
447  *
448  * In parallel, we consider the file pointer to be equal to the highest
449  * value of the individual file pointers.
450  *
451  * parameters:
452  *   f <-- cs_file_t descriptor
453  *
454  * returns:
455  *   current position of the file pointer
456  *----------------------------------------------------------------------------*/
457 
458 cs_file_off_t
459 cs_file_tell(cs_file_t  *f);
460 
461 /*----------------------------------------------------------------------------*/
462 /*!
463  * \brief Formatted input from a text file (as fgets()).
464  *
465  * \param [out]      s     buffer to which string is to be read.
466  * \param [in]       size  maximum number of characters to be read plus one.
467  * \param [in]       f     ecs_file_t descriptor.
468  * \param [in, out]  line  file line number if available, or NULL.
469  *
470  * \return s on success, NULL on error or when end of file occurs and
471  *         no characters have been read.
472  */
473 /*----------------------------------------------------------------------------*/
474 
475 char *
476 cs_file_gets(char             *s,
477              const int         size,
478              const cs_file_t  *f,
479              int              *line);
480 
481 /*----------------------------------------------------------------------------*/
482 /*!
483  * \brief Formatted input from a text file if possible (as fgets()).
484  *
485  * This function is similar to cs_file_gets(), but failure to read
486  * a line due to an end-of-file condition is not considered an error with
487  * this variant, which may be used to read text files or sections thereof
488  * of unknown length.
489  *
490  * \param [out]      s     buffer to which string is to be read.
491  * \param [in]       size  maximum number of characters to be read plus one.
492  * \param [in]       f     cs_file_t descriptor.
493  * \param [in, out]  line  file line number if available, or NULL.
494  *
495  * \return s on success, NULL on error or when end of file occurs and
496  *         no characters have been read.
497  */
498 /*----------------------------------------------------------------------------*/
499 
500 char *
501 cs_file_gets_try(char              *s,
502                  const int          size,
503                  const cs_file_t   *f,
504                  int               *line);
505 
506 /*----------------------------------------------------------------------------
507  * Dump the metadata of a file structure in human readable form
508  *
509  * parameters:
510  *   f <-- pointer to file
511  *----------------------------------------------------------------------------*/
512 
513 void
514 cs_file_dump(const cs_file_t  *f);
515 
516 /*----------------------------------------------------------------------------
517  * Free the default options for file access.
518  *----------------------------------------------------------------------------*/
519 
520 void
521 cs_file_free_defaults(void);
522 
523 /*----------------------------------------------------------------------------
524  * Get the default options for file access.
525  *
526  * parameters:
527  *   mode   <-- file mode for which the default is queried (write and
528  *              append use the same method, and are interchangeable here)
529  *   access --> default file access method, or NULL
530  *   hints  --> MPI-IO hints, or NULL
531  *----------------------------------------------------------------------------*/
532 
533 #if defined(HAVE_MPI)
534 
535 void
536 cs_file_get_default_access(cs_file_mode_t     mode,
537                            cs_file_access_t  *method,
538                            MPI_Info          *hints);
539 
540 #else
541 
542 void
543 cs_file_get_default_access(cs_file_mode_t     mode,
544                            cs_file_access_t  *method);
545 
546 #endif
547 
548 /*----------------------------------------------------------------------------
549  * Set the default options for file access.
550  *
551  * If the method given contains incompatible values, such as when setting
552  * MPI-IO methods when MPI-IO is not available, a "reasonable" default
553  * is used instead.
554  *
555  * parameters:
556  *   mode      <-- file mode for which the default is to be set (write and
557  *                 append use the same method, and are interchangeable here)
558  *   method    <-- default access method to set
559  *   hints     <-- MPI-IO hints, or MPI_INFO_NULL
560  *----------------------------------------------------------------------------*/
561 
562 #if defined(HAVE_MPI)
563 
564 void
565 cs_file_set_default_access(cs_file_mode_t    mode,
566                            cs_file_access_t  method,
567                            MPI_Info          hints);
568 
569 #else
570 
571 void
572 cs_file_set_default_access(cs_file_mode_t    mode,
573                            cs_file_access_t  method);
574 
575 #endif
576 
577 #if defined(HAVE_MPI)
578 
579 /*----------------------------------------------------------------------------
580  * Get default MPI communicator values for file access.
581  *
582  * A block rank stepping value may be used, allowing the use of a reduced
583  * communicator for distributed block reads and writes.
584  * If this value is greater than 1, ranks not a multiple of this step must be
585  * guaranteed to be empty for block reads and writes with files opened using
586  * this default.
587  *
588  * parameters:
589  *   block_rank_step --> MPI rank stepping between non-empty distributed blocks,
590  *                       or NULL
591  *   block_comm      --> Handle to MPI communicator used for distributed
592  *                       file block access, or NULL
593  *   comm            --> Handle to main MPI communicator, or NULL
594  *----------------------------------------------------------------------------*/
595 
596 void
597 cs_file_get_default_comm(int       *block_rank_step,
598                          MPI_Comm  *block_comm,
599                          MPI_Comm  *comm);
600 
601 /*----------------------------------------------------------------------------
602  * Set default MPI communicator values for file access.
603  *
604  * A block rank stepping value may be used, allowing the use of a reduced
605  * communicator for distributed block reads and writes.
606  * If this value is greater than 1, ranks not a multiple of this step must be
607  * guaranteed to be empty for block reads and writes with files opened using
608  * this default.
609  *
610  * For each argument, an "out of range" value may be used to avoid modifying
611  * the previous default for that argument.
612  *
613  * parameters:
614  *   block_rank_step <-- MPI rank stepping between non-empty blocks for
615  *                       file block reads and writes (not set if <= 0)
616  *   comm            <-- handle to main MPI communicator
617  *                       (not set if MPI_COMM_SELF)
618  *----------------------------------------------------------------------------*/
619 
620 void
621 cs_file_set_default_comm(int       block_rank_step,
622                          MPI_Comm  comm);
623 
624 /*----------------------------------------------------------------------------
625  * Create an MPI communicator for distributed block parallel IO.
626  *
627  * parameters:
628  *   block_rank_step <-- MPI rank stepping between non-empty blocks
629  *   comm            <-- Handle to main MPI communicator
630  *
631  * returns:
632  *   communicator associated with IO, MPI_COMM_NULL for ranks not
633  *   participating in parallel IO (including ranks participating in IO
634  *   where communicator size would be 1)
635  *----------------------------------------------------------------------------*/
636 
637 MPI_Comm
638 cs_file_block_comm(int       block_rank_step,
639                    MPI_Comm  comm);
640 
641 #endif /* defined(HAVE_MPI) */
642 
643 /*----------------------------------------------------------------------------
644  * Get the positioning method for MPI-IO
645  *
646  * For details, see cs_file_set_mpi_io_positioning().
647  *
648  * returns:
649  *   positioning method for MPI-IO
650  *----------------------------------------------------------------------------*/
651 
652 cs_file_mpi_positioning_t
653 cs_file_get_mpi_io_positioning(void);
654 
655 /*----------------------------------------------------------------------------
656  * Set the positioning method for MPI-IO
657  *
658  * It is not always known whether a performance or robustness difference is
659  * to be expected using explicit file offsets or individual file pointers.
660  * Perusal of a sampling of ROMIO code would seem to indicate that no
661  * difference is to be expected, but this might change with MPI IO variants
662  * or file systems, so this advanced setting is made possible.
663  *
664  * This setting is not available on a per-file basis, though this could be
665  * done in the future in the unexpected case of performance results
666  * showing this would be useful.
667  *
668  * parameters:
669  *   positioning <-- chosen positioning method for MPI-IO
670  *----------------------------------------------------------------------------*/
671 
672 void
673 cs_file_set_mpi_io_positioning(cs_file_mpi_positioning_t  positioning);
674 
675 /*----------------------------------------------------------------------------
676  * Print information on default options for file access.
677  *----------------------------------------------------------------------------*/
678 
679 void
680 cs_file_defaults_info(void);
681 
682 #if defined(HAVE_MPI)
683 
684 /*----------------------------------------------------------------------------
685  * Create a cs_file_serializer_t structure.
686  *
687  * The buf_block_size argument is optional, and may be used when the buffer
688  * on rank 0 is larger than (global_num_end - global_num_start)*size*stride
689  * bytes. If zero, a block size of (global_num_end - global_num_start) on
690  * rank 0 is assumed; a buffer may not be smaller than this, as it must
691  * initially contain all data on rank 0's block.
692  *
693  * parameters:
694  *   size             <-- size of each item of data in bytes
695  *   stride           <-- number of (interlaced) values per block item
696  *   global_num_start <-- global number of first block item (1 to n numbering)
697  *   global_num_end   <-- global number of past-the end block item
698  *                        (1 to n numbering)
699  *   buf_block_size   <-- Local data buffer block size, or 0 for default
700  *                        global_num_end - global_num_start
701  *                        (only useful on rank 0)
702  *   buf              <-- pointer to local block data buffer
703  *   comm             <-- associated MPI communicator
704  *
705  * returns:
706  *   pointer to new serializer structure
707  *----------------------------------------------------------------------------*/
708 
709 cs_file_serializer_t *
710 cs_file_serializer_create(size_t      size,
711                           size_t      stride,
712                           cs_gnum_t   global_num_start,
713                           cs_gnum_t   global_num_end,
714                           size_t      buf_block_size,
715                           void       *buf,
716                           MPI_Comm    comm);
717 
718 /*----------------------------------------------------------------------------
719  * Destroy a cs_file_serializer_t structure.
720  *
721  * parameters:
722  *   s <-> pointer to pointer structure that should be destroyed
723  *----------------------------------------------------------------------------*/
724 
725 void
726 cs_file_serializer_destroy(cs_file_serializer_t  **s);
727 
728 /*----------------------------------------------------------------------------
729  * Advance a cs_file_serializer_t structure.
730  *
731  * Data from the buffer of the next communicating rank is copied
732  * to rank 0 (this is a no-op the first time this function is called,
733  * as rank 0 already has its data).
734  *
735  * On rank 0, the return value may point to the buffer defined when
736  * initializing the serializer, or to an aditional buffer if the former is
737  * too small to receive data from all ranks.
738  *
739  * Note also that for ranks > 0, this function always returns NULL,
740  * as only one call is needed for those ranks.
741  *
742  * parameters:
743  *   s         <-- pointer to serializer structure
744  *   cur_range --> optional start and past-the end global numbers for the
745  *                 current block (size: 2), or NULL; only on rank 0
746  *
747  * returns:
748  *   a pointer to the buffer containing new data (first call counts as new),
749  *   or NULL if we are finished; always NULL on ranks > 0
750  *----------------------------------------------------------------------------*/
751 
752 void *
753 cs_file_serializer_advance(cs_file_serializer_t  *s,
754                            cs_gnum_t              cur_range[2]);
755 
756 #endif /* defined(HAVE_MPI) */
757 
758 /*----------------------------------------------------------------------------
759  * Create a new directory using default permissions.
760  *
761  * This function is similar to the POSIX function mkdir(), except that
762  * it has no "mode" argument: by default, on a POSIX type system,
763  * permissions include read, write, and execute access for the user,
764  * group and others, modified by the users umask value (so with a
765  * typical configuration, the user will have read, write, and execute
766  * pemission, the group and others will only have read and execute
767  * permission, but this behavior may be modified).
768  *
769  * Also, contrary to the usual mkdir(), if the directory already
770  * exists (and is truly a directory), this is considered a success
771  * and not a failure, and 0 is returned: the aim of this function
772  * is to make a directory available, so if it already exists,
773  * this is considered acceptable.
774  *
775  * parameters:
776  *   path: <-- name of new directory.
777  *
778  * returns:
779  *   0 on success, -1 if an error occured (in which case errno
780  *   contains the appropriate error code). If the underlying
781  *   system has no mkdir() function or it was not detected
782  *   upon BFT configuration, 1 is returned.
783  *----------------------------------------------------------------------------*/
784 
785 int
786 cs_file_mkdir_default(const char  *path);
787 
788 /*----------------------------------------------------------------------------
789  * Check if a file exists and is a regular file.
790  *
791  * parameters:
792  *   path <-- file name.
793  *
794  * returns:
795  *   1 if file exists and is a regular file, 0 otherwise.
796  *----------------------------------------------------------------------------*/
797 
798 int
799 cs_file_isreg(const char  *path);
800 
801 /*----------------------------------------------------------------------------
802  * Check if a directory exists.
803  *
804  * parameters:
805  *   path <-- directory name.
806  *
807  * returns:
808  *   1 if directory exists, 0 otherwise.
809  *----------------------------------------------------------------------------*/
810 
811 int
812 cs_file_isdir(const char  *path);
813 
814 /*----------------------------------------------------------------------------
815  * List files inside a directory.
816  *
817  * The array returned must be freed by the caller using BFT_FREE,
818  * as well as the individual entries in the array.
819  *
820  * parameters:
821  *   path <-- name of directory.
822  *
823  * returns:
824  *   an array of file names in a directory. The last entry is set to NULL.
825  *   If no means to list the directory or an error occured, the return
826  *    value is simply NULL.
827  *----------------------------------------------------------------------------*/
828 
829 char **
830 cs_file_listdir(const char *path);
831 
832 /*----------------------------------------------------------------------------
833  * Return the size of a file.
834  *
835  * If the file does not exist, 0 is returned.
836  *
837  * Note that for some special files, such as files in the Linux /proc
838  * directory, this may return 0.
839  *
840  * parameters
841  *   path <-- file path.
842  *
843  * returns:
844  *   size of file.
845  *----------------------------------------------------------------------------*/
846 
847 cs_file_off_t
848 cs_file_size(const char  *path);
849 
850 /*----------------------------------------------------------------------------
851  * Remove a file if it exists and is a regular file or an empty directory.
852  *
853  * parameters
854  *   path <-- file path.
855  *
856  * returns:
857  *   0 in case of success or if file does not exist, not 0 otherwise.
858  *----------------------------------------------------------------------------*/
859 
860 int
861 cs_file_remove(const char  *path);
862 
863 /*----------------------------------------------------------------------------
864  * Check if a file name ends with a specific string (extension)
865  *
866  * parameters
867  *   path <-- file path.
868  *   end  <-- string to compare
869  *
870  * returns:
871  *   1 if the path ends with the given string, 0 otherwise.
872  *----------------------------------------------------------------------------*/
873 
874 int
875 cs_file_endswith(const char  *path,
876                  const char  *end);
877 
878 /*----------------------------------------------------------------------------*/
879 
880 END_C_DECLS
881 
882 #endif /* __CS_FILE_H__ */
883