src/base/cs_file.h Source File

| programmer's documentation

- Main Page
- Related Pages
- Modules
- Data Structures
- Files

- File List
- Globals

All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
cs_file.h
Go to the documentation of this file.
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-2013 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 positionning methods */
96
97 typedef enum {
98
99 CS_FILE_MPI_EXPLICIT_OFFSETS,
100 CS_FILE_MPI_INDIVIDUAL_POINTERS
101
102 } cs_file_mpi_positionning_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 positionning */
121
122 extern const char *cs_file_mpi_positionning_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 acces 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 acces 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 * Destroy a file descriptor and close the associated file.
190 *
191 * parameters:
192 * f <-> file descriptor to destroy
193 *
194 * returns:
195 * NULL pointer
196 *----------------------------------------------------------------------------*/
197
198 cs_file_t *
199 cs_file_free(cs_file_t *f);
200
201 /*----------------------------------------------------------------------------
202 * Return a file's name.
203 *
204 * parameters:
205 * f <-- cs_file_t descriptor
206 *
207 * returns:
208 * pointer to the file's name.
209 *----------------------------------------------------------------------------*/
210
211 const char *
212 cs_file_get_name(const cs_file_t *f);
213
214 /*----------------------------------------------------------------------------
215 * Ensure that data is read or written in big-endian
216 * (network standard) format.
217 *
218 * parameters:
219 * f <-> cs_file_t descriptor
220 *----------------------------------------------------------------------------*/
221
222 void
223 cs_file_set_big_endian(cs_file_t *f);
224
225 /*----------------------------------------------------------------------------
226 * Return a file's byte-swapping behavior.
227 *
228 * parameters:
229 * f <-- cs_file_t descriptor
230 *
231 * returns:
232 * 0 if file's endianness is the same as the system's, 1 otherwise.
233 *----------------------------------------------------------------------------*/
234
235 int
236 cs_file_get_swap_endian(const cs_file_t *f);
237
238 /*----------------------------------------------------------------------------
239 * Set a file's byte-swapping behavior.
240 *
241 * Using this function assumes one is familiar with a file's coding
242 * or structure; use with caution.
243 *
244 * parameters:
245 * f <-> cs_file_t descriptor
246 * swap <-- 1 if bytes must be swapped, 0 otherwise
247 *----------------------------------------------------------------------------*/
248
249 void
250 cs_file_set_swap_endian(cs_file_t *f,
251 int swap);
252
253 /*----------------------------------------------------------------------------
254 * Read global data from a file, distributing it to all processes
255 * associated with that file.
256 *
257 * parameters:
258 * f <-- cs_file_t descriptor
259 * buf --> pointer to location receiving data
260 * size <-- size of each item of data in bytes
261 * ni <-- number of items to read
262 *
263 * returns:
264 * the number of items (not bytes) sucessfully read; currently,
265 * errors are fatal.
266 *----------------------------------------------------------------------------*/
267
268 size_t
269 cs_file_read_global(cs_file_t *f,
270 void *buf,
271 size_t size,
272 size_t ni);
273
274 /*----------------------------------------------------------------------------
275 * Write global data to a file.
276 *
277 * Under MPI, data is only written by the associated communicator's root
278 * rank. The buffers on other ranks are ignored, though the file offset
279 * is updated (i.e. the call to this function is collective).
280 *
281 * parameters:
282 * f <-- cs_file_t descriptor
283 * buf <-- pointer to location containing data
284 * size <-- size of each item of data in bytes
285 * ni <-- number of items to read
286 *
287 * returns:
288 * the number of items (not bytes) sucessfully written; currently,
289 * errors are fatal.
290 *----------------------------------------------------------------------------*/
291
292 size_t
293 cs_file_write_global(cs_file_t *f,
294 const void *buf,
295 size_t size,
296 size_t ni);
297
298 /*----------------------------------------------------------------------------
299 * Read data to a buffer, distributing a contiguous part of it to each
300 * process associated with a file.
301 *
302 * Each process should receive a (possibly empty) block of the data,
303 * and we should have:
304 * global_num_start at rank 0 = 1
305 * global_num_start at rank i+1 = global_num_end at rank i.
306 * Otherwise, behavior (especially positioning for future reads) is undefined.
307 *
308 * parameters:
309 * f <-- cs_file_t descriptor
310 * buf --> pointer to location receiving data
311 * size <-- size of each item of data in bytes
312 * stride <-- number of (interlaced) values per block item
313 * global_num_start <-- global number of first block item (1 to n numbering)
314 * global_num_end <-- global number of past-the end block item
315 * (1 to n numbering)
316 *
317 * returns:
318 * the (local) number of items (not bytes) sucessfully read; currently,
319 * errors are fatal.
320 *----------------------------------------------------------------------------*/
321
322 size_t
323 cs_file_read_block(cs_file_t *f,
324 void *buf,
325 size_t size,
326 size_t stride,
327 cs_gnum_t global_num_start,
328 cs_gnum_t global_num_end);
329
330 /*----------------------------------------------------------------------------
331 * Write data to a file, each associated process providing a contiguous part
332 * of this data.
333 *
334 * Each process should provide a (possibly empty) block of the data,
335 * and we should have:
336 * global_num_start at rank 0 = 1
337 * global_num_start at rank i+1 = global_num_end at rank i.
338 * Otherwise, behavior (especially positioning for future reads) is undefined.
339 *
340 * This function may require an internal copy of the data to ensure that
341 * the buffer contents are not modified, so if the buffer contents are
342 * temporary values, to be deleted after writing, using
343 * cs_file_write_block_buffer() instead may be used to avoid an unneeded
344 * memory allocation and copy.
345 *
346 * parameters:
347 * f <-- cs_file_t descriptor
348 * buf <-- pointer to location containing data
349 * size <-- size of each item of data in bytes
350 * stride <-- number of (interlaced) values per block item
351 * global_num_start <-- global number of first block item (1 to n numbering)
352 * global_num_end <-- global number of past-the end block item
353 * (1 to n numbering)
354 *
355 * returns:
356 * the (local) number of items (not bytes) sucessfully written; currently,
357 * errors are fatal.
358 *----------------------------------------------------------------------------*/
359
360 size_t
361 cs_file_write_block(cs_file_t *f,
362 const void *buf,
363 size_t size,
364 size_t stride,
365 cs_gnum_t global_num_start,
366 cs_gnum_t global_num_end);
367
368 /*----------------------------------------------------------------------------
369 * Write data to a file, each associated process providing a contiguous part
370 * of this data.
371 *
372 * Each process should provide a (possibly empty) block of the data,
373 * and we should have:
374 * global_num_start at rank 0 = 1
375 * global_num_start at rank i+1 = global_num_end at rank i.
376 * Otherwise, behavior (especially positioning for future reads) is undefined.
377 *
378 * This function is intended to be used mainly data that is already a
379 * copy of original data (such as data that has been redistributed across
380 * processors just for the sake of output), or that is to be deleted after
381 * writing, so it may modify the values in its input buffer (notably to
382 * convert from little-endian to big-endian of vice-versa if necessary).
383 *
384 * parameters:
385 * f <-- cs_file_t descriptor
386 * buf <-> pointer to location containing data
387 * size <-- size of each item of data in bytes
388 * stride <-- number of (interlaced) values per block item
389 * global_num_start <-- global number of first block item (1 to n numbering)
390 * global_num_end <-- global number of past-the end block item
391 * (1 to n numbering)
392 *
393 * returns:
394 * the (local) number of items (not bytes) sucessfully written; currently,
395 * errors are fatal.
396 *----------------------------------------------------------------------------*/
397
398 size_t
399 cs_file_write_block_buffer(cs_file_t *f,
400 void *buf,
401 size_t size,
402 size_t stride,
403 cs_gnum_t global_num_start,
404 cs_gnum_t global_num_end);
405
406 /*----------------------------------------------------------------------------
407 * Update the file pointer according to whence.
408 *
409 * parameters:
410 * f <-> cs_file_t descriptor.
411 * offset <-- add to position specified to whence to obtain new position,
412 * measured in characters from the beginning of the file.
413 * whence <-- beginning if CS_FILE_SEEK_SET, current if CS_FILE_SEEK_CUR,
414 * or end-of-file if CS_FILE_SEEK_END.
415 *
416 * returns:
417 * 0 upon success, nonzero otherwise; currently, errors are fatal.
418 *----------------------------------------------------------------------------*/
419
420 int
421 cs_file_seek(cs_file_t *f,
422 cs_file_off_t offset,
423 cs_file_seek_t whence);
424
425 /*----------------------------------------------------------------------------
426 * Return the position of the file pointer.
427 *
428 * In parallel, we consider the file pointer to be equal to the highest
429 * value of the individual file pointers.
430 *
431 * parameters:
432 * f <-- cs_file_t descriptor
433 *
434 * returns:
435 * current position of the file pointer
436 *----------------------------------------------------------------------------*/
437
438 cs_file_off_t
439 cs_file_tell(cs_file_t *f);
440
441 /*----------------------------------------------------------------------------
442 * Dump the metadata of a file structure in human readable form
443 *
444 * parameters:
445 * f <-- pointer to file
446 *----------------------------------------------------------------------------*/
447
448 void
449 cs_file_dump(const cs_file_t *f);
450
451 /*----------------------------------------------------------------------------
452 * Get the default options for file access.
453 *
454 * parameters:
455 * mode <-- file mode for which the default is queried (write and
456 * append use the same method, and are interchangeable here)
457 * access --> default file access method, or NULL
458 * hints --> MPI-IO hints, or NULL
459 *----------------------------------------------------------------------------*/
460
461 #if defined(HAVE_MPI)
462
463 void
464 cs_file_get_default_access(cs_file_mode_t mode,
465 cs_file_access_t *method,
466 MPI_Info *hints);
467
468 #else
469
470 void
471 cs_file_get_default_access(cs_file_mode_t mode,
472 cs_file_access_t *method);
473
474 #endif
475
476 /*----------------------------------------------------------------------------
477 * Set the default options for file access.
478 *
479 * If the method given contains incompatible values, such as when setting
480 * MPI-IO methods when MPI-IO is not available, a "reasonable" default
481 * is used instead.
482 *
483 * parameters:
484 * mode <-- file mode for which the default is to be set (write and
485 * append use the same method, and are interchangeable here)
486 * method <-- default access method to set
487 * hints <-- MPI-IO hints, or MPI_INFO_NULL
488 *----------------------------------------------------------------------------*/
489
490 #if defined(HAVE_MPI)
491
492 void
493 cs_file_set_default_access(cs_file_mode_t mode,
494 cs_file_access_t method,
495 MPI_Info hints);
496
497 #else
498
499 void
500 cs_file_set_default_access(cs_file_mode_t mode,
501 cs_file_access_t method);
502
503 #endif
504
505 #if defined(HAVE_MPI)
506
507 /*----------------------------------------------------------------------------
508 * Get default MPI communicator values for file access.
509 *
510 * A block rank stepping value may be used, allowing the use of a reduced
511 * communicator for distributed block reads and writes.
512 * If this value is greater than 1, ranks not a multiple of this step must be
513 * guaranteed to be empty for block reads and writes with files opened using
514 * this default.
515 *
516 * A minimum block size target may also be used, so as to limit the number
517 * of active blocks to a value proportional to the data size (limiting
518 * latency issues for small data sets, while not requiring too much local
519 * memory).
520 *
521 * parameters:
522 * block_rank_step --> MPI rank stepping between non-empty distributed blocks,
523 * or NULL
524 * block_min_size --> minimum block size target for non-empty distributed
525 * blocks, or NULL
526 * block_comm --> Handle to MPI communicator used for distributed
527 * file block access, or NULL
528 * comm --> Handle to main MPI communicator, or NULL
529 *----------------------------------------------------------------------------*/
530
531 void
532 cs_file_get_default_comm(int *block_rank_step,
533 int *block_min_size,
534 MPI_Comm *block_comm,
535 MPI_Comm *comm);
536
537 /*----------------------------------------------------------------------------
538 * Set default MPI communicator values for file access.
539 *
540 * A block rank stepping value may be used, allowing the use of a reduced
541 * communicator for distributed block reads and writes.
542 * If this value is greater than 1, ranks not a multiple of this step must be
543 * guaranteed to be empty for block reads and writes with files opened using
544 * this default.
545 *
546 * A minimum block size target may also be used, so as to limit the number
547 * of active blocks to a value proportional to the data size (limiting
548 * latency issues for small data sets, while not requiring too much local
549 * memory).
550 *
551 * For each argument, an "out of range" value may be used to avoid modifying
552 * the previous default for that argument.
553 *
554 * parameters:
555 * block_rank_step <-- MPI rank stepping between non-empty blocks for
556 * file block reads and writes (not set if <= 0)
557 * block_min_size <-- minimum block size target for non-empty distributed
558 * blocks (not set if < 1)
559 * comm <-- handle to main MPI communicator
560 * (not set if MPI_COMM_SELF)
561 *----------------------------------------------------------------------------*/
562
563 void
564 cs_file_set_default_comm(int block_rank_step,
565 int block_min_size,
566 MPI_Comm comm);
567
568 #endif /* defined(HAVE_MPI) */
569
570 /*----------------------------------------------------------------------------
571 * Get the positionning method for MPI-IO
572 *
573 * For details, see cs_file_set_mpi_io_positionning().
574 *
575 * returns:
576 * positionning method for MPI-IO
577 *----------------------------------------------------------------------------*/
578
579 cs_file_mpi_positionning_t
580 cs_file_get_mpi_io_positionning(void);
581
582 /*----------------------------------------------------------------------------
583 * Set the positionning method for MPI-IO
584 *
585 * It is not always known whether a performance or robustness difference is
586 * to be expected using explicit file offsets or individual file pointers.
587 * Perusal of a sampling of ROMIO code would seem to indicate that no
588 * difference is to be expected, but this might change with MPI IO variants
589 * or file systems, so this advanced setting is made possible.
590 *
591 * This setting is not available on a per-file basis, though this could be
592 * done in the future in the unexpected case of performance results
593 * showing this would be useful.
594 *
595 * parameters:
596 * positionning <-- chosen positionning method for MPI-IO
597 *----------------------------------------------------------------------------*/
598
599 void
600 cs_file_set_mpi_io_positionning(cs_file_mpi_positionning_t positionning);
601
602 /*----------------------------------------------------------------------------
603 * Print information on default options for file access.
604 *----------------------------------------------------------------------------*/
605
606 void
607 cs_file_defaults_info(void);
608
609 #if defined(HAVE_MPI)
610
611 /*----------------------------------------------------------------------------
612 * Create a cs_file_serializer_t structure.
613 *
614 * The buf_block_size argument is optional, and may be used when the buffer
615 * on rank 0 is larger than (global_num_end - global_num_start)*size*stride
616 * bytes. If zero, a block size of (global_num_end - global_num_start) on
617 * rank 0 is assumed; a buffer may not be smaller than this, as it must
618 * initially contain all data on rank 0's block.
619 *
620 * parameters:
621 * size <-- size of each item of data in bytes
622 * stride <-- number of (interlaced) values per block item
623 * global_num_start <-- global number of first block item (1 to n numbering)
624 * global_num_end <-- global number of past-the end block item
625 * (1 to n numbering)
626 * buf_block_size <-- Local data buffer block size, or 0 for default
627 * global_num_end - global_num_start
628 * (only useful on rank 0)
629 * buf <-- pointer to local block data buffer
630 * comm <-- associated MPI communicator
631 *
632 * returns:
633 * pointer to new serializer structure
634 *----------------------------------------------------------------------------*/
635
636 cs_file_serializer_t *
637 cs_file_serializer_create(size_t size,
638 size_t stride,
639 cs_gnum_t global_num_start,
640 cs_gnum_t global_num_end,
641 size_t buf_block_size,
642 void *buf,
643 MPI_Comm comm);
644
645 /*----------------------------------------------------------------------------
646 * Destroy a cs_file_serializer_t structure.
647 *
648 * parameters:
649 * s <-> pointer to pointer structure that should be destroyed
650 *----------------------------------------------------------------------------*/
651
652 void
653 cs_file_serializer_destroy(cs_file_serializer_t **s);
654
655 /*----------------------------------------------------------------------------
656 * Advance a cs_file_serializer_t structure.
657 *
658 * Data from the buffer of the next communicating rank is copied
659 * to rank 0 (this is a no-op the first time this function is called,
660 * as rank 0 already has its data).
661 *
662 * On rank 0, the return value may point to the buffer defined when
663 * initializing the serializer, or to an aditional buffer if the former is
664 * too small to receive data from all ranks.
665 *
666 * Note also that for ranks > 0, this function always returns NULL,
667 * as only one call is needed for those ranks.
668 *
669 * parameters:
670 * s <-- pointer to serializer structure
671 * cur_range --> optional start and past-the end global numbers for the
672 * current block (size: 2), or NULL; only on rank 0
673 *
674 * returns:
675 * a pointer to the buffer containing new data (first call counts as new),
676 * or NULL if we are finished; always NULL on ranks > 0
677 *----------------------------------------------------------------------------*/
678
679 void *
680 cs_file_serializer_advance(cs_file_serializer_t *s,
681 cs_gnum_t cur_range[2]);
682
683 #endif /* defined(HAVE_MPI) */
684
685 /*----------------------------------------------------------------------------
686 * Create a new directory using default permissions.
687 *
688 * This function is similar to the POSIX function mkdir(), except that
689 * it has no "mode" argument: by default, on a POSIX type system,
690 * permissions include read, write, and execute access for the user,
691 * group and others, modified by the users umask value (so with a
692 * typical configuration, the user will have read, write, and execute
693 * pemission, the group and others will only have read and execute
694 * permission, but this behavior may be modified).
695 *
696 * Also, contrary to the usual mkdir(), if the directory already
697 * exists (and is truly a directory), this is considered a success
698 * and not a failure, and 0 is returned: the aim of this function
699 * is to make a directory available, so if it already exists,
700 * this is considered acceptable.
701 *
702 * parameters:
703 * path: <-- name of new directory.
704 *
705 * returns:
706 * 0 on success, -1 if an error occured (in which case errno
707 * contains the appropriate error code). If the underlying
708 * system has no mkdir() function or it was not detected
709 * upon BFT configuration, 1 is returned.
710 *----------------------------------------------------------------------------*/
711
712 int
713 cs_file_mkdir_default(const char *path);
714
715 /*----------------------------------------------------------------------------
716 * Check if a file exists and is a regular file.
717 *
718 * parameters:
719 * path <-- file name.
720 *
721 * returns:
722 * 1 if file exists and is a regular file, 0 otherwise.
723 *----------------------------------------------------------------------------*/
724
725 int
726 cs_file_isreg(const char *path);
727
728 /*----------------------------------------------------------------------------
729 * Check if a directory exists.
730 *
731 * parameters:
732 * path <-- directory name.
733 *
734 * returns:
735 * 1 if directory exists, 0 otherwise.
736 *----------------------------------------------------------------------------*/
737
738 int
739 cs_file_isdir(const char *path);
740
741 /*----------------------------------------------------------------------------
742 * List files inside a directory.
743 *
744 * The array returned must be freed by the caller using BFT_FREE,
745 * as well as the individual entries in the array.
746 *
747 * parameters:
748 * path <-- name of directory.
749 *
750 * returns:
751 * an array of file names in a directory. The last entry is set to NULL.
752 * If no means to list the directory or an error occured, the return
753 * value is simply NULL.
754 *----------------------------------------------------------------------------*/
755
756 char **
757 cs_file_listdir(const char *path);
758
759 /*----------------------------------------------------------------------------
760 * Return the size of a file.
761 *
762 * If the file does not exit, 0 is returned.
763 *
764 * Note that for some special files, such as files in the Linux /proc
765 * directory, this may return 0.
766 *
767 * parameters
768 * path <-- file path.
769 *
770 * returns:
771 * size of file.
772 *----------------------------------------------------------------------------*/
773
774 cs_file_off_t
775 cs_file_size(const char *path);
776
777 /*----------------------------------------------------------------------------*/
778
779 END_C_DECLS
780
781 #endif /* __CS_FILE_H__ */