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