Loading [MathJax]/extensions/TeX/AMSsymbols.js
LAL 7.7.0.1-00ddc7f
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
FileIO.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2007 Bernd Machenschalk, Jolien Creighton, Reinhard Prix
3 * Copyright (C) 2012--2015, 2021 Karl Wette
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with with program; see the file COPYING. If not, write to the
17 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 * MA 02110-1301 USA
19 */
20
21/* for realpath() for whereami.c on Linux */
22#define _GNU_SOURCE
23
24#include <config.h>
25
26#include <stdarg.h>
27#include <stdlib.h>
28#include <string.h>
29#include <errno.h>
30
31#ifdef HAVE_SYS_STAT_H
32#include <sys/stat.h>
33#endif
34#ifdef HAVE_SYS_TYPES_H
35#include <sys/types.h>
36#endif
37#ifdef HAVE_GLOB_H
38#include <glob.h>
39#endif
40
41#include <zlib.h>
42#define ZLIB_ENABLED
43
44#include <lal/LALStdlib.h>
45#include <lal/LALStdio.h>
46#include <lal/LALString.h>
47#include <lal/StringInput.h>
48#include <lal/FileIO.h>
49
50#ifdef __GNUC__
51#define UNUSED __attribute__ ((unused))
52#else
53#define UNUSED
54#endif
55
56/* do not export functions from whereami.c */
57#define WAI_FUNCSPEC static UNUSED
58
59#include "whereami.c"
60
61struct tagLALFILE {
63 void *fp;
64};
65
66LALFILE *lalstdin( void )
67{
68 static LALFILE _lalstdin;
69 _lalstdin.fp = (void*)stdin;
70 return &_lalstdin;
71}
72LALFILE *lalstdout( void )
73{
74 static LALFILE _lalstdout;
75 _lalstdout.fp = (void*)stdout;
76 return &_lalstdout;
77}
78LALFILE *lalstderr( void )
79{
80 static LALFILE _lalstderr;
81 _lalstderr.fp = (void*)stderr;
82 return &_lalstderr;
83}
84
85
86/** \cond DONT_DOXYGEN */
87/* should be only called from XLAL_FILE_RESOLVE_PATH() */
88char *
89XLALFileResolvePathLong ( const char *fname, const char *fallbackpath )
90{
91 XLAL_CHECK_NULL ( fname != NULL, XLAL_EINVAL );
92
93 const UINT4 fname_len = strlen ( fname );
94
95 XLALPrintInfo ( "%s(): trying to resolve fname='%s' ...\n", __func__, fname );
96
97 if ( strchr ( fname, '/' ) != NULL ) // any kind of (absolute or relative) path is given -> use only that
98 {
99 FILE *tmp;
100 XLALPrintInfo ( "%s(): strategy: absolute/relative path\n", __func__ );
101 XLALPrintInfo ( "%s(): trying '%s' -> '%s' ...\n", __func__, fname, fname );
102 if ( (tmp = LALFopen ( fname, "rb" )) != NULL ) {
103 LALFclose ( tmp );
104 XLALPrintInfo ( "%s(): success '%s' -> '%s'\n", __func__, fname, fname );
105 return XLALStringDuplicate ( fname );
106 } // if found
107 else {
108 XLALPrintInfo ( "%s(): failed '%s'\n", __func__, fname );
109 return NULL;
110 } // if not found
111
112 } // end: if path given
113 else // if pure filename given: try 1) local directory, then 2) scan LAL_DATA_PATH, then 3) scan 'fallbackpath' (if given)
114 {
115 FILE *tmp;
116 char *resolveFname = NULL;
117
118 // ----- Strategy 1: try local directory explicitly
119 XLALPrintInfo ( "%s(): strategy: local directory\n", __func__ );
120 XLAL_CHECK_NULL ( (resolveFname = XLALMalloc ( fname_len + 2 + 1 )) != NULL, XLAL_ENOMEM );
121 sprintf ( resolveFname, "./%s", fname );
122 XLALPrintInfo ( "%s(): trying '%s' -> '%s' ...\n", __func__, fname, resolveFname );
123 if ( (tmp = LALFopen ( resolveFname, "rb" )) != NULL ) {
124 LALFclose ( tmp );
125 XLALPrintInfo ( "%s(): success '%s' -> '%s'\n", __func__, fname, resolveFname );
126 return resolveFname;
127 } // if found
128
129 // ----- Strategy 2: scan LAL_DATA_PATH
130 const char *lal_data_path = getenv( "LAL_DATA_PATH" );
131 if ( ! ( lal_data_path && (strlen (lal_data_path ) > 0 ) ) )
132 {
133 XLALPrintInfo ( "%s(): skip strategy LAL_DATA_PATH: environment variable not set\n", __func__ );
134 }
135 else
136 {
137 XLALPrintInfo ( "%s(): strategy: LAL_DATA_PATH='%s'\n", __func__, lal_data_path );
138 TokenList *subPaths = NULL;
139 XLAL_CHECK_NULL ( XLALCreateTokenList ( &subPaths, lal_data_path, ":" ) == XLAL_SUCCESS, XLAL_EFUNC );
140 for ( UINT4 i = 0; i < subPaths->nTokens; i ++ )
141 {
142 const char *subPath_i = subPaths->tokens[i];
143 XLAL_CHECK_NULL ( (resolveFname = XLALRealloc ( resolveFname, strlen(subPath_i) + 1 + fname_len + 1 )) != NULL, XLAL_ENOMEM );
144 sprintf ( resolveFname, "%s/%s", subPath_i, fname );
145 XLALPrintInfo ( "%s(): trying '%s' -> '%s' ...\n", __func__, fname, resolveFname );
146 if ( (tmp = LALFopen ( resolveFname, "rb" )) != NULL ) {
147 LALFclose ( tmp );
148 XLALDestroyTokenList ( subPaths );
149 XLALPrintInfo ( "%s(): success '%s' -> '%s'\n", __func__, fname, resolveFname );
150 return resolveFname;
151 } // if found
152
153 } // for i < nTokens
154
155 XLALDestroyTokenList ( subPaths );
156
157 } // if LAL_DATA_PATH given
158
159 // ----- Strategy 3: scan 'fallbackpath', if given
160 if ( ! fallbackpath ) {
161 XLALPrintInfo ( "%s(): skip strategy: fallbackpath=NULL\n", __func__ );
162 } else {
163 XLALPrintInfo ( "%s(): strategy: fallbackpath='%s'\n", __func__, fallbackpath );
164
165 // get location of liblalsupport.so
166 char *module_path = NULL;
167 int module_path_length = wai_getModulePath ( NULL, 0, NULL );
168 int module_dirname_length = 0;
169 if ( module_path_length > 0 ) {
170 module_path = XLALMalloc ( module_path_length + 1 );
171 XLAL_CHECK_NULL ( module_path != NULL, XLAL_ENOMEM );
172 XLAL_CHECK_NULL ( wai_getModulePath ( module_path, module_path_length, &module_dirname_length ) > 0, XLAL_EERR );
173 module_path[module_path_length] = '\0';
174 XLAL_CHECK_NULL ( module_dirname_length >= 0, XLAL_EERR );
175 XLAL_CHECK_NULL ( module_dirname_length < module_path_length, XLAL_EERR );
176 module_path[module_dirname_length] = '\0';
177 }
178
179 // search 'fallbackpath'; relative paths are considered relative to location of liblalsupport.so (if known)
180 TokenList *subPaths = NULL;
181 XLAL_CHECK_NULL ( XLALCreateTokenList ( &subPaths, fallbackpath, ":" ) == XLAL_SUCCESS, XLAL_EFUNC );
182 for ( UINT4 i = 0; i < subPaths->nTokens; i ++ )
183 {
184 const char *subPath_i = subPaths->tokens[i];
185 const UINT4 subPath_i_len = strlen ( subPath_i );
186 if ( subPath_i_len == 0 ) {
187 XLALPrintInfo ( "%s(): skip empty fallbackpath element\n", __func__ );
188 continue;
189 }
190 if ( subPath_i[0] == '.' ) {
191 if ( ! module_path ) {
192 XLALPrintInfo ( "%s(): skip relative fallbackpath element '%s': location of liblalsupport.so unknown\n", __func__, subPath_i );
193 continue;
194 }
195 XLAL_CHECK_NULL ( (resolveFname = XLALRealloc ( resolveFname, module_dirname_length + 1 + subPath_i_len + 1 + fname_len + 1 )) != NULL, XLAL_ENOMEM );
196 sprintf ( resolveFname, "%s/%s/%s", module_path, subPath_i, fname );
197 } else {
198 XLAL_CHECK_NULL ( (resolveFname = XLALRealloc ( resolveFname, subPath_i_len + 1 + fname_len + 1 )) != NULL, XLAL_ENOMEM );
199 sprintf ( resolveFname, "%s/%s", subPath_i, fname );
200 }
201 XLALPrintInfo ( "%s(): trying '%s' -> '%s' ...\n", __func__, fname, resolveFname );
202#ifdef HAVE_GLOB_H
203 glob_t glob_buf;
204 int glob_retn = glob( resolveFname, 0, NULL, &glob_buf );
205 if ( glob_retn == 0 ) {
206 XLAL_CHECK_NULL ( glob_buf.gl_pathc > 0, XLAL_EERR );
207 XLAL_CHECK_NULL ( (resolveFname = XLALRealloc ( resolveFname, strlen( glob_buf.gl_pathv[0] ) + 1 )) != NULL, XLAL_ENOMEM );
208 strcpy( resolveFname, glob_buf.gl_pathv[0] );
209 globfree( &glob_buf );
210 XLALFree ( module_path );
211 XLALDestroyTokenList ( subPaths );
212 XLALPrintInfo ( "%s(): success '%s' -> '%s'\n", __func__, fname, resolveFname );
213 return resolveFname;
214 } // if found
215 char glob_errmsg[256];
216 switch (glob_retn) {
217 case GLOB_NOSPACE:
218 snprintf( glob_errmsg, sizeof( glob_errmsg ), "out of memory" );
219 break;
220 case GLOB_ABORTED:
221 snprintf( glob_errmsg, sizeof( glob_errmsg ), "read error" );
222 break;
223 case GLOB_NOMATCH:
224 snprintf( glob_errmsg, sizeof( glob_errmsg ), "no matches" );
225 break;
226 default:
227 snprintf( glob_errmsg, sizeof( glob_errmsg ), "unknown error %i", glob_retn );
228 }
229 XLALPrintInfo ( "%s(): trying '%s' -> '%s' ... glob failed (%s)\n", __func__, fname, resolveFname, glob_errmsg );
230 globfree( &glob_buf );
231#else
232 if ( (tmp = LALFopen ( resolveFname, "rb" )) != NULL ) {
233 LALFclose ( tmp );
234 XLALFree ( module_path );
235 XLALDestroyTokenList ( subPaths );
236 XLALPrintInfo ( "%s(): success '%s' -> '%s'\n", __func__, fname, resolveFname );
237 return resolveFname;
238 } // if found
239#endif
240 }
241
242 XLALFree ( module_path );
243 XLALDestroyTokenList ( subPaths );
244
245 }
246
247 XLALFree ( resolveFname );
248
249 } // end: if pure filename given
250
251 // nothing worked? that's ok: return NULL without failure!
252 XLALPrintInfo ( "%s(): failed '%s'\n", __func__, fname);
253 return NULL;
254
255} // XLALFileResolvePathLong()
256
257/* Simple wrapper to XLAL_FILE_RESOLVE_PATH(), using hardcoded fallbackdir for LAL
258 Use of XLAL_FILE_RESOLVE_PATH() directly is preferred; kept for ABI backward compatibility */
259char *
260XLALFileResolvePath ( const char *fname )
261{
262 return XLAL_FILE_RESOLVE_PATH( fname );
263} // XLALFileResolvePath()
264/** \endcond */ // DONT_DOXYGEN
265
266/** Read a complete data-file into memory as a string
267 */
268char *
269XLALFileLoad ( const char *path //!< [in] input filepath
270 )
271{
272 XLAL_CHECK_NULL ( path != NULL, XLAL_EINVAL );
273
274 // check that this is actually a regular file, rather than sth else (eg a directory)
275 size_t blobLen;
276 XLAL_CHECK_NULL ( XLALFileIsRegularAndGetSize ( path, &blobLen ) == 1, XLAL_EINVAL, "Path '%s' does not point to a regular file!\n", path );
277
278 char *dataBuffer = NULL;
279 size_t dataBufferLen = 0;
280 size_t numReadTotal = 0;
281 LALFILE *fp;
283
284 // read file in blobs the size of the (possibly compressed) file
285 int blobCounter = 0;
286 while ( ! XLALFileEOF( fp ) )
287 {
288 dataBufferLen += blobLen;
289 if ( (dataBuffer = XLALRealloc ( dataBuffer, dataBufferLen + 1)) == NULL ) {
291 XLAL_ERROR_NULL ( XLAL_ENOMEM, "Failed to XLALRealloc(%zu)\n", dataBufferLen+1 );
292 }
293 size_t numRead = XLALFileRead ( dataBuffer + blobCounter*blobLen, sizeof(char), blobLen, fp );
294 if ( xlalErrno != XLAL_SUCCESS ) {
295 XLALFree ( dataBuffer );
298 }
299
300 numReadTotal += numRead;
301
302 if ( numRead < blobLen ) {
303 break;
304 }
305 blobCounter ++;
306
307 } // while !eof
308
310
311 // adjust buffer to final size of data read
312 XLAL_CHECK_NULL ( (dataBuffer = XLALRealloc ( dataBuffer, numReadTotal + 1)) != NULL, XLAL_ENOMEM, "Failed to XLALRealloc(%zu)\n", numReadTotal+1 );
313 dataBuffer[numReadTotal] = 0;
314
315 return dataBuffer;
316
317} // XLALFileLoad()
318
319int XLALFileIsCompressed( const char *path )
320{
321 FILE *fp;
322 unsigned char magic[2] = { 0, 0 };
323 size_t c;
324 if ( ! ( fp = LALFopen( path, "rb" ) ) )
326 c = fread( magic, sizeof(*magic), XLAL_NUM_ELEM(magic), fp );
327 if (c == 0)
329 fclose( fp );
330 return magic[0] == 0x1f && magic[1] == 0x8b;
331}
332
333LALFILE *XLALFileOpenRead( const char *path )
334{
335 int compression;
336 LALFILE *file;
337 if ( 0 > (compression = XLALFileIsCompressed(path) ) )
339#ifndef ZLIB_ENABLED
340 if ( compression ) {
341 XLALPrintError( "XLAL Error - %s: Cannot read compressed file\n", __func__ );
343 }
344#endif
345 if ( ! ( file = XLALMalloc( sizeof(*file ) ) ) )
347 file->compression = compression;
348#ifdef ZLIB_ENABLED
349 file->fp = compression ? (void*)gzopen( path, "rb" ) : (void*)LALFopen( path, "rb" );
350#else
351 file->fp = (void*)LALFopen( path, "rb" );
352#endif
353 if ( ! file->fp ) {
354 XLALFree( file );
356 }
357 return file;
358}
359
360LALFILE *XLALFileOpenAppend( const char *path, int compression )
361{
362 LALFILE *file;
363 if ( ! ( file = XLALMalloc( sizeof(*file ) ) ) )
365#ifdef ZLIB_ENABLED
366 file->fp = compression ? (void*)gzopen( path, "a+" ) : (void*)LALFopen( path, "a+" );
367#else
368 if ( compression ) {
369 XLALPrintWarning( "XLAL Warning - %s: Compression not supported\n", __func__ );
370 compression = 0;
371 }
372 file->fp = (void*)LALFopen( path, "a+" );
373#endif
374 file->compression = compression;
375 if ( ! file->fp ) {
376 XLALFree( file );
378 }
379 return file;
380}
381
382LALFILE *XLALFileOpenWrite( const char *path, int compression )
383{
384 LALFILE *file;
385 if ( ! ( file = XLALMalloc( sizeof(*file ) ) ) )
387#ifdef ZLIB_ENABLED
388 file->fp = compression ? (void*)gzopen( path, "wb" ) : (void*)LALFopen( path, "wb" );
389#else
390 if ( compression ) {
391 XLALPrintWarning( "XLAL Warning - %s: Compression not supported\n", __func__ );
392 compression = 0;
393 }
394 file->fp = (void*)LALFopen( path, "wb" );
395#endif
396 file->compression = compression;
397 if ( ! file->fp ) {
398 XLALFree( file );
400 }
401 return file;
402}
403
404LALFILE *XLALFileOpen( const char *path, const char *mode )
405{
406 int compression;
407 char *ext;
408 switch ( *mode ) {
409 case 'r':
410 return XLALFileOpenRead( path );
411 case 'w':
412 /* check if filename ends in .gz */
413 ext = strrchr( path, '.' );
414 compression = ext ? ! strcmp( ext, ".gz" ) : 0;
415 return XLALFileOpenWrite( path, compression );
416 default:
417 break; /* fall-out */
418 }
419 /* error if code gets here */
421}
422
423int XLALFileClose( LALFILE *file )
424{
425 /* this routine acts as a no-op if the file is NULL */
426 /* this behavior is different from BSD fclose */
427 if ( file ) {
428 int c;
429 if ( ! file->fp )
431#ifdef ZLIB_ENABLED
432 c = file->compression ? gzclose(((gzFile)file->fp)) : fclose(((FILE*)file->fp));
433#else
434 c = fclose(((FILE*)file->fp));
435#endif
436 if ( c == EOF )
438 XLALFree( file );
439 }
440 return 0;
441}
442
443size_t XLALFileRead( void *ptr, size_t size, size_t nobj, LALFILE *file )
444{
445 size_t c;
446 if ( ! file )
448#ifdef ZLIB_ENABLED
449 c = file->compression ? (size_t)gzread( ((gzFile)file->fp), ptr, size * nobj ) : fread( ptr, size, nobj, ((FILE*)file->fp) );
450#else
451 c = fread( ptr, size, nobj, ((FILE*)file->fp) );
452#endif
453 if ( c == (size_t)(-1) || (file->compression == 0 && ferror((FILE*)(file->fp))) )
455 return c;
456}
457
458size_t XLALFileWrite( const void *ptr, size_t size, size_t nobj, LALFILE *file )
459{
460 size_t c;
461 if ( ! file )
463#ifdef ZLIB_ENABLED
464 c = file->compression ? (size_t)gzwrite( ((gzFile)file->fp), ptr, size * nobj ) : fwrite( ptr, size, nobj, ((FILE*)file->fp) );
465#else
466 c = fwrite( ptr, size, nobj, (FILE*)(file->fp) );
467#endif
468 if ( c == 0 || (file->compression == 0 && ferror((FILE*)(file->fp))) )
470 return c;
471}
472
473int XLALFileGetc( LALFILE *file )
474{
475 int c;
476 if ( ! file )
478#ifdef ZLIB_ENABLED
479 c = file->compression ? gzgetc(((gzFile)file->fp)) : fgetc(((FILE*)file->fp));
480#else
481 c = fgetc(((FILE*)file->fp));
482#endif
483 return c;
484}
485
486int XLALFilePutc( int c, LALFILE *file )
487{
488 int result;
489 if ( ! file )
491#ifdef ZLIB_ENABLED
492 result = file->compression ? gzputc(((gzFile)file->fp), c) : fputc(c, ((FILE*)file->fp));
493#else
494 result = fputc(c, (FILE*)(file->fp));
495#endif
496 if ( result == -1 )
498 return result;
499}
500
501char * XLALFileGets( char * s, int size, LALFILE *file )
502{
503 char *c;
504 if ( ! file )
506#ifdef ZLIB_ENABLED
507 c = file->compression ? gzgets( ((gzFile)file->fp), s, size ) : fgets( s, size, ((FILE*)file->fp) );
508#else
509 c = fgets( s, size, ((FILE*)file->fp) );
510#endif
511 return c;
512}
513
514int XLALFilePuts( const char * s, LALFILE *file )
515{
516 if ( ! file )
518 if ( 0 > (int)XLALFileWrite( s, sizeof(*s), strlen(s), file ) )
520 return 0;
521}
522
523int XLALFileVPrintf( LALFILE *file, const char *fmt, va_list ap )
524{
525 char buf[32768];
526 int len;
527 int c;
528 if ( ! file )
530 len = vsnprintf( buf, sizeof(buf), fmt, ap );
531 if ( len < 0 )
533 if ( len >= (int)sizeof(buf) ) { /* buffer is too small */
534 char *s;
535 s = XLALMalloc( len + 1 );
536 if ( !s )
538 len = vsnprintf( s, len + 1, fmt, ap );
539 c = XLALFilePuts( s, file );
540 XLALFree( s );
541 } else {
542 c = XLALFilePuts( buf, file );
543 }
544 if ( c < 0 )
546 return len;
547}
548
549int XLALFilePrintf( LALFILE *file, const char *fmt, ... )
550{
551 int c;
552 va_list ap;
553 va_start( ap, fmt );
554 c = XLALFileVPrintf( file, fmt, ap );
555 va_end( ap );
556 if ( c < 0 )
558 return c;
559}
560
561
562int XLALFileFlush( LALFILE *file )
563{
564 int c;
565 if ( ! file )
567#ifdef ZLIB_ENABLED
568 c = file->compression ? gzflush(((gzFile)file->fp), Z_FULL_FLUSH) : fflush(((FILE*)file->fp));
569#else
570 c = fflush(((FILE*)file->fp));
571#endif
572 if ( c == -1 )
574 return c;
575}
576
577int XLALFileSeek( LALFILE *file, long offset, int whence )
578{
579 int c;
580 if ( ! file )
582#ifdef ZLIB_ENABLED
583 if ( file->compression && whence == SEEK_END ) {
584 XLALPrintError( "XLAL Error - %s: SEEK_END not supported with compressed files\n", __func__ );
586 }
587 c = file->compression ? gzseek(((gzFile)file->fp), offset, whence) : fseek(((FILE*)file->fp), offset, whence);
588#else
589 c = fseek(((FILE*)file->fp), offset, whence);
590#endif
591 if ( c == -1 )
593 return 0;
594}
595
596long XLALFileTell( LALFILE *file )
597{
598 long c;
599 if ( ! file )
601#ifdef ZLIB_ENABLED
602 c = file->compression ? (long)gztell(((gzFile)file->fp)) : ftell(((FILE*)file->fp));
603#else
604 c = ftell(((FILE*)file->fp));
605#endif
606 if ( c == -1 )
608 return c;
609}
610
611void XLALFileRewind( LALFILE *file )
612{
613 if ( ! file )
615#ifdef ZLIB_ENABLED
616 file->compression ? (void)gzrewind(((gzFile)file->fp)) : rewind(((FILE*)file->fp));
617#else
618 rewind(((FILE*)file->fp));
619#endif
620 return;
621}
622
623/** \brief Set buffering for file I/O
624 *
625 * For a regular file buffering will be set using \c setvbuf. If \c buf is \c NULL then a buffer of \c size will be
626 * automatically allocated. The \c mode can be \c _IONBF, \c _IOLBF or \c _IOFBF for no buffering, line buffering
627 * or full buffering respectively.
628 *
629 * For a compressed file the buffering will be set with \c gzbuffer. The \c buf and \c mode inputs are ignored and a
630 * buffer of \c size is set.
631 */
632int XLALFileSetBuffer( LALFILE *file, char *buf, int mode, size_t size )
633{
634 int c = 0;
635 if ( ! file )
637#ifdef ZLIB_ENABLED
638 if ( !file->compression ){
639 c = setvbuf(((FILE*)file->fp), buf, mode, size);
640 }
641 else{
642#if defined ZLIB_VER_MAJOR && ZLIB_VER_MAJOR >= 1 && ZLIB_VER_MINOR >= 2 && ZLIB_VER_REVISION >= 4
643 c = (int)gzbuffer(((gzFile)file->fp), size);
644#else
645 XLAL_PRINT_WARNING("Ignored buffering: unsupported in zlib version %s", ZLIB_VERSION);
646#endif
647 }
648#else
649 c = setvbuf(((FILE*)file->fp), buf, mode, size);
650#endif
651 if ( c != 0 )
653 return c;
654}
655
656
657int XLALFileEOF( LALFILE *file )
658{
659 int c;
660 if ( ! file )
662#ifdef ZLIB_ENABLED
663 c = file->compression ? gzeof(((gzFile)file->fp)) : feof((FILE*)(file->fp));
664#else
665 c = feof((FILE*)(file->fp));
666#endif
667 return c;
668}
669
670/** Check if path points to a 'regular file', rather than a directory or sth else.
671 * and also return the size of the given file.
672 *
673 * This is simply a wrapper to stat(), and S_ISREG()
674 * and could be easily generalized along those lines to test for directories etc.
675 *
676 * return an error if stat() was unavailable
677 * return 1 for true, 0 for false, -1 on error
678 */
679int
680XLALFileIsRegularAndGetSize ( const char *path, //!< [in] path to file
681 size_t *fileLen //!< [out] size in bytes of file
682 )
683{
684#ifndef HAVE_STAT
685 XLAL_ERROR ( XLAL_EFAILED, "No implementation of function stat() available, which is required here!\n");
686#else
687 XLAL_CHECK ( path != NULL, XLAL_EINVAL );
688
689 struct stat sb;
690 XLAL_CHECK ( stat( path, &sb) != -1, XLAL_EIO, "stat() failed: perror = '%s'\n", strerror(errno) );
691
692 if ( fileLen ) { // optional output argument
693 (*fileLen) = (size_t)sb.st_size;
694 }
695
696 return (S_ISREG(sb.st_mode));
697#endif
698
699} // XLALFileIsRegularAndGetSize()
700
701
702/** Check if given file is 'regular' (rather than a directory or sth else)
703 *
704 * This is a simple wrapper to XLALFileIsRegularAndGetSize().
705 *
706 * Return 1 for true, 0 for false, -1 on error
707 */
708int
709XLALFileIsRegular ( const char *path //!< [in] path to file
710 )
711{
712 return XLALFileIsRegularAndGetSize ( path, NULL );
713} // XLALFileIsRegular()
714
715
716/** Return the size of given file in bytes.
717 *
718 * This is simply a wrapper to XLALFileIsRegularAndGetSize()
719 *
720 * Returns (size_t)-1 on error
721 */
722size_t
723XLALFileSize ( const char *path //!< [in] path to file
724 )
725{
726 size_t size;
727
729
730 return size;
731
732} // XLALFileSize()
733
734/**
735 * \brief Use gzip to compress a text file
736 * This function will use the gzip compression routines in \c zlib to compress a text file. The compressed file will
737 * have the extension ".gz" and the original uncompressed file will be removed.
738 *
739 * \param filename [in] The input text file.
740 */
741int XLALGzipTextFile( const char *filename ){
742 char *memblock = NULL; /* memory block to read data into */
743 long pos;
744 char *outname = NULL;
745
746 LALFILE *fp = NULL; /* input file pointer */
747 LALFILE *fg = NULL; /* output gzipped file pointer */
748
749 /* open file for reading and work out its size */
750 if( (fp = XLALFileOpen( filename, "rb" )) == NULL ){
751 XLALPrintError ("%s: Unable to open file %s.\n", __func__, filename );
753 }
754
755 XLALFileSeek( fp, 0, SEEK_END ); /* go to end of the file */
756 pos = XLALFileTell( fp ); /* get the position of the file pointer */
757 XLALFileRewind( fp ); /* return the file pointer to the start of the file */
758
759 /* allocate memory to read in data */
760 memblock = XLALMalloc( pos + 1);
761
762 if ( !memblock ){
763 XLALPrintError ("%s: Unable to allocate memory for reading file.\n", __func__ );
765 }
766
767 /* read in data */
768 if ( XLALFileRead( memblock, pos, 1, fp ) == 0 ){
769 XLALPrintError ("%s: Unable to read in file.\n", __func__ );
771 }
772 memblock[pos] = 0; // properly 0-terminate string
773
774 XLALFileClose( fp );
775
776 /* create output name with .gz appended */
777 if ( (outname = XLALCalloc(strlen(filename)+4, 1)) == NULL) /* we need local copy */{
779 }
780
781 strcpy(outname, filename);
782 strcat(outname, ".gz"); /* add the extension */
783
784 if ( !outname ){
785 XLALPrintError("%s: Unable to create output filename.\n", __func__ );
787 }
788
789 /* open output gzip file */
790 if ( (fg = XLALFileOpen( outname, "wb" )) == NULL ){
791 XLALPrintError ("%s: Unable to open output file %s.\n", __func__, outname );
793 }
794
795 if ( XLALFilePuts( memblock, fg ) != 0 ){
796 XLALPrintError ("%s: Unable to output gzipped data.\n", __func__ );
798 }
799
800 XLALFileClose( fg );
801
802 /* remove original file */
803 if ( remove( filename ) == -1 ){
804 XLALPrintError ("%s: Unable to remove original text file.\n", __func__ );
806 }
807
808 return XLAL_SUCCESS;
809}
810
811
812/**
813 * \brief Use gzip to uncompress a compressed text file
814 *
815 * This function will use the gzip compression routines in \c zlib to uncompress a gzipped text file. The compressed
816 * file should have the ".gz" extension otherwise it will be rejected. The output will have the same filename with the
817 * ".gz" extension removed. The compressed file will be removed.
818 *
819 * Note: \c gzopen will check the file's "magic number" to see if it is a gzipped file. If it's not a gzipped file it
820 * will still open the file for reading as a standard file.
821 *
822 * \param filename [in] The input gzipped text file.
823 */
824int XLALGunzipTextFile( const char *filename ){
825 CHAR *memblock = NULL; /* memory block to read data into */
826 CHAR *outname = NULL;
827 CHAR *gzpos = NULL;
828
829 LALFILE *fp = NULL; /* output file pointer */
830 LALFILE *fg = NULL; /* input gzipped file pointer */
831 size_t n;
832
833 /* create output file name by striping .gz from the input file name */
834 if ( (gzpos = strstr(filename, ".gz")) == NULL ){
835 XLALPrintError ("%s: File %s does not contain the .gz extension.\n", __func__, filename );
837 }
838
839 n = gzpos-filename;
840 outname = XLALMalloc( sizeof(CHAR)*(n+1) );
841
842 if ( ( outname = strncpy(outname, filename, n) ) == NULL ){
843 XLALPrintError ("%s: Unable to strip extension from file string.\n", __func__ );
845 }
846 outname[n] = 0;
847
848 /* open gzipped file for reading */
849 if ( (fg = XLALFileOpen(filename, "rb")) == NULL ){
850 XLALPrintError ("%s: Unable to open gzipped file %s.\n", __func__, filename );
852 }
853
854 /* open output text file */
855 if ( (fp = XLALFileOpen(outname, "w")) == NULL ){
856 XLALPrintError ("%s: Unable to open output file %s.\n", __func__, outname );
858 }
859
860 /* allocate memory for a single char */
861 memblock = XLALMalloc( sizeof(CHAR) );
862
863 /* read in gzipped data one byte at a time and output to text file */
864 while( ( memblock = XLALFileGets(memblock, 2, fg) ) != NULL ){ XLALFilePrintf(fp, "%s", memblock); }
865
866 /* close files */
867 XLALFileClose( fg );
868 XLALFileClose( fp );
869
870 /* remove original file */
871 if ( remove( filename ) == -1 ){
872 XLALPrintError ("%s: Unable to remove original gzipped file.\n", __func__ );
874 }
875
876 return XLAL_SUCCESS;
877}
static const size_t magic
Definition: LALMalloc.c:260
void XLALDestroyTokenList(TokenList *list)
See StringToken.c for documentation.
Definition: StringToken.c:262
int XLALCreateTokenList(TokenList **list, const CHAR *string, const CHAR *delimiters)
Split given input string into a list of 'tokens' separated by any of the characters given in 'delimit...
Definition: StringToken.c:168
int XLALPrintWarning(const char *fmt,...)
Definition: XLALError.c:79
int XLALPrintInfo(const char *fmt,...)
Definition: XLALError.c:90
int XLALPrintError(const char *fmt,...)
Definition: XLALError.c:68
LALFILE * XLALFileOpenWrite(const char *path, int compression)
Definition: FileIO.c:382
int XLALFileVPrintf(LALFILE *file, const char *fmt, va_list ap)
Definition: FileIO.c:523
int XLALGunzipTextFile(const char *filename)
Use gzip to uncompress a compressed text file.
Definition: FileIO.c:824
int XLALFileClose(LALFILE *file)
Definition: FileIO.c:423
int XLALFilePutc(int c, LALFILE *file)
Definition: FileIO.c:486
LALFILE * XLALFileOpenAppend(const char *path, int compression)
Definition: FileIO.c:360
int XLALFileEOF(LALFILE *file)
Definition: FileIO.c:657
LALFILE * XLALFileOpenRead(const char *path)
Definition: FileIO.c:333
LALFILE * lalstdin(void)
Definition: FileIO.c:66
size_t XLALFileSize(const char *path)
Return the size of given file in bytes.
Definition: FileIO.c:723
LALFILE * XLALFileOpen(const char *path, const char *mode)
Definition: FileIO.c:404
int XLALFilePuts(const char *s, LALFILE *file)
Definition: FileIO.c:514
int XLALFileIsRegular(const char *path)
Check if given file is 'regular' (rather than a directory or sth else)
Definition: FileIO.c:709
size_t XLALFileRead(void *ptr, size_t size, size_t nobj, LALFILE *file)
Definition: FileIO.c:443
int XLALFileSetBuffer(LALFILE *file, char *buf, int mode, size_t size)
Set buffering for file I/O.
Definition: FileIO.c:632
int XLALFileIsRegularAndGetSize(const char *path, size_t *fileLen)
Check if path points to a 'regular file', rather than a directory or sth else.
Definition: FileIO.c:680
int XLALFileSeek(LALFILE *file, long offset, int whence)
Definition: FileIO.c:577
int XLALFileIsCompressed(const char *path)
Definition: FileIO.c:319
size_t XLALFileWrite(const void *ptr, size_t size, size_t nobj, LALFILE *file)
Definition: FileIO.c:458
int XLALFilePrintf(LALFILE *file, const char *fmt,...)
Definition: FileIO.c:549
void XLALFileRewind(LALFILE *file)
Definition: FileIO.c:611
int XLALGzipTextFile(const char *filename)
Use gzip to compress a text file This function will use the gzip compression routines in zlib to comp...
Definition: FileIO.c:741
int XLALFileGetc(LALFILE *file)
Definition: FileIO.c:473
#define XLAL_FILE_RESOLVE_PATH(fname)
'Resolve' a given filename 'fname', returning a file path where the file can successfully be opened b...
Definition: FileIO.h:116
long XLALFileTell(LALFILE *file)
Definition: FileIO.c:596
char * XLALFileGets(char *s, int size, LALFILE *file)
Definition: FileIO.c:501
LALFILE * lalstderr(void)
Definition: FileIO.c:78
char * XLALFileLoad(const char *path)
Read a complete data-file into memory as a string.
Definition: FileIO.c:269
LALFILE * lalstdout(void)
Definition: FileIO.c:72
int XLALFileFlush(LALFILE *file)
Definition: FileIO.c:562
#define XLAL_NUM_ELEM(x)
MACRO which gives the number of elements in a fixed-size array.
char CHAR
One-byte signed integer, see Headers LAL(Atomic)Datatypes.h for more details.
uint32_t UINT4
Four-byte unsigned integer.
#define XLALMalloc(n)
Definition: LALMalloc.h:44
#define XLALCalloc(m, n)
Definition: LALMalloc.h:45
#define XLALFree(p)
Definition: LALMalloc.h:47
#define XLALRealloc(p, n)
Definition: LALMalloc.h:46
#define LALFclose
Definition: LALStdio.h:51
#define LALFopen
Definition: LALStdio.h:50
char * XLALStringDuplicate(const char *s)
Like strdup but uses LAL allocation routines (free with LALFree).
Definition: LALString.c:89
#define XLAL_ERROR_VOID(...)
Macro to invoke a failure from a XLAL routine returning void.
Definition: XLALError.h:726
#define XLAL_ERROR_NULL(...)
Macro to invoke a failure from a XLAL routine returning a pointer.
Definition: XLALError.h:713
#define xlalErrno
Modifiable lvalue containing the XLAL error number.
Definition: XLALError.h:571
#define XLAL_ERROR(...)
Macro to invoke a failure from a XLAL routine returning an integer.
Definition: XLALError.h:700
#define XLAL_CHECK(assertion,...)
Macro to test an assertion and invoke a failure if it is not true in a function that returns an integ...
Definition: XLALError.h:810
#define XLAL_PRINT_WARNING(...)
Macro that will print a warning message with a standard format.
Definition: XLALError.h:270
#define XLAL_CHECK_NULL(assertion,...)
Macro to test an assertion and invoke a failure if it is not true in a function that returns a pointe...
Definition: XLALError.h:825
@ XLAL_ENOMEM
Memory allocation error.
Definition: XLALError.h:407
@ XLAL_SUCCESS
Success return value (not an error number)
Definition: XLALError.h:401
@ XLAL_EFAULT
Invalid pointer.
Definition: XLALError.h:408
@ XLAL_EFUNC
Internal function call failed bit: "or" this with existing error number.
Definition: XLALError.h:462
@ XLAL_EERR
Internal error.
Definition: XLALError.h:443
@ XLAL_EIO
I/O error.
Definition: XLALError.h:406
@ XLAL_EINVAL
Invalid argument.
Definition: XLALError.h:409
@ XLAL_EFAILED
Generic failure.
Definition: XLALError.h:418
This structure stores a number of null-terminated strings of arbitrary length.
Definition: StringInput.h:135
CHAR ** tokens
A list of pointers to the individual tokens; the elements tokens[0..nTokens-1] point to tokens,...
Definition: StringInput.h:137
UINT4 nTokens
The number of tokens in the list.
Definition: StringInput.h:136
void * fp
Definition: FileIO.c:63
int compression
Definition: FileIO.c:62
FILE * fp
Definition: tconvert.c:105