LAL  7.5.0.1-b72065a
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 
38 #include <zlib.h>
39 #define ZLIB_ENABLED
40 
41 #include <lal/LALStdlib.h>
42 #include <lal/LALStdio.h>
43 #include <lal/LALString.h>
44 #include <lal/StringInput.h>
45 #include <lal/FileIO.h>
46 
47 #ifdef __GNUC__
48 #define UNUSED __attribute__ ((unused))
49 #else
50 #define UNUSED
51 #endif
52 
53 /* do not export functions from whereami.c */
54 #define WAI_FUNCSPEC static UNUSED
55 
56 #include "whereami.c"
57 
58 struct tagLALFILE {
60  void *fp;
61 };
62 
63 LALFILE *lalstdin( void )
64 {
65  static LALFILE _lalstdin;
66  _lalstdin.fp = (void*)stdin;
67  return &_lalstdin;
68 }
69 LALFILE *lalstdout( void )
70 {
71  static LALFILE _lalstdout;
72  _lalstdout.fp = (void*)stdout;
73  return &_lalstdout;
74 }
75 LALFILE *lalstderr( void )
76 {
77  static LALFILE _lalstderr;
78  _lalstderr.fp = (void*)stderr;
79  return &_lalstderr;
80 }
81 
82 
83 /** \cond DONT_DOXYGEN */
84 /* should be only called from XLAL_FILE_RESOLVE_PATH() */
85 char *
86 XLALFileResolvePathLong ( const char *fname, const char *fallbackpath )
87 {
88  XLAL_CHECK_NULL ( fname != NULL, XLAL_EINVAL );
89 
90  const UINT4 fname_len = strlen ( fname );
91 
92  XLALPrintInfo ( "%s(): trying to resolve fname='%s' ...\n", __func__, fname );
93 
94  if ( strchr ( fname, '/' ) != NULL ) // any kind of (absolute or relative) path is given -> use only that
95  {
96  FILE *tmp;
97  XLALPrintInfo ( "%s(): strategy: absolute/relative path\n", __func__ );
98  XLALPrintInfo ( "%s(): trying '%s' -> '%s' ...\n", __func__, fname, fname );
99  if ( (tmp = LALFopen ( fname, "rb" )) != NULL ) {
100  LALFclose ( tmp );
101  XLALPrintInfo ( "%s(): success '%s' -> '%s'\n", __func__, fname, fname );
102  return XLALStringDuplicate ( fname );
103  } // if found
104  else {
105  XLALPrintInfo ( "%s(): failed '%s'\n", __func__, fname );
106  return NULL;
107  } // if not found
108 
109  } // end: if path given
110  else // if pure filename given: try 1) local directory, then 2) scan LAL_DATA_PATH, then 3) scan 'fallbackpath' (if given)
111  {
112  FILE *tmp;
113  char *resolveFname = NULL;
114 
115  // ----- Strategy 1: try local directory explicitly
116  XLALPrintInfo ( "%s(): strategy: local directory\n", __func__ );
117  XLAL_CHECK_NULL ( (resolveFname = XLALMalloc ( fname_len + 2 + 1 )) != NULL, XLAL_ENOMEM );
118  sprintf ( resolveFname, "./%s", fname );
119  XLALPrintInfo ( "%s(): trying '%s' -> '%s' ...\n", __func__, fname, resolveFname );
120  if ( (tmp = LALFopen ( resolveFname, "rb" )) != NULL ) {
121  LALFclose ( tmp );
122  XLALPrintInfo ( "%s(): success '%s' -> '%s'\n", __func__, fname, resolveFname );
123  return resolveFname;
124  } // if found
125 
126  // ----- Strategy 2: scan LAL_DATA_PATH
127  const char *lal_data_path = getenv( "LAL_DATA_PATH" );
128  if ( ! ( lal_data_path && (strlen (lal_data_path ) > 0 ) ) )
129  {
130  XLALPrintInfo ( "%s(): skip strategy LAL_DATA_PATH: environment variable not set\n", __func__ );
131  }
132  else
133  {
134  XLALPrintInfo ( "%s(): strategy: LAL_DATA_PATH='%s'\n", __func__, lal_data_path );
135  TokenList *subPaths = NULL;
136  XLAL_CHECK_NULL ( XLALCreateTokenList ( &subPaths, lal_data_path, ":" ) == XLAL_SUCCESS, XLAL_EFUNC );
137  for ( UINT4 i = 0; i < subPaths->nTokens; i ++ )
138  {
139  const char *subPath_i = subPaths->tokens[i];
140  XLAL_CHECK_NULL ( (resolveFname = XLALRealloc ( resolveFname, strlen(subPath_i) + 1 + fname_len + 1 )) != NULL, XLAL_ENOMEM );
141  sprintf ( resolveFname, "%s/%s", subPath_i, fname );
142  XLALPrintInfo ( "%s(): trying '%s' -> '%s' ...\n", __func__, fname, resolveFname );
143  if ( (tmp = LALFopen ( resolveFname, "rb" )) != NULL ) {
144  LALFclose ( tmp );
145  XLALDestroyTokenList ( subPaths );
146  XLALPrintInfo ( "%s(): success '%s' -> '%s'\n", __func__, fname, resolveFname );
147  return resolveFname;
148  } // if found
149 
150  } // for i < nTokens
151 
152  XLALDestroyTokenList ( subPaths );
153 
154  } // if LAL_DATA_PATH given
155 
156  // ----- Strategy 3: scan 'fallbackpath', if given
157  if ( ! fallbackpath ) {
158  XLALPrintInfo ( "%s(): skip strategy: fallbackpath=NULL\n", __func__ );
159  } else {
160  XLALPrintInfo ( "%s(): strategy: fallbackpath='%s'\n", __func__, fallbackpath );
161 
162  // get location of liblalsupport.so
163  char *module_path = NULL;
164  int module_path_length = wai_getModulePath ( NULL, 0, NULL );
165  int module_dirname_length = 0;
166  if ( module_path_length > 0 ) {
167  module_path = XLALMalloc ( module_path_length + 1 );
168  XLAL_CHECK_NULL ( module_path != NULL, XLAL_ENOMEM );
169  XLAL_CHECK_NULL ( wai_getModulePath ( module_path, module_path_length, &module_dirname_length ) > 0, XLAL_EERR );
170  module_path[module_path_length] = '\0';
171  XLAL_CHECK_NULL ( module_dirname_length >= 0, XLAL_EERR );
172  XLAL_CHECK_NULL ( module_dirname_length < module_path_length, XLAL_EERR );
173  module_path[module_dirname_length] = '\0';
174  }
175 
176  // search 'fallbackpath'; relative paths are considered relative to location of liblalsupport.so (if known)
177  TokenList *subPaths = NULL;
178  XLAL_CHECK_NULL ( XLALCreateTokenList ( &subPaths, fallbackpath, ":" ) == XLAL_SUCCESS, XLAL_EFUNC );
179  for ( UINT4 i = 0; i < subPaths->nTokens; i ++ )
180  {
181  const char *subPath_i = subPaths->tokens[i];
182  const UINT4 subPath_i_len = strlen ( subPath_i );
183  if ( subPath_i_len == 0 ) {
184  XLALPrintInfo ( "%s(): skip empty fallbackpath element\n", __func__ );
185  continue;
186  }
187  if ( subPath_i[0] == '.' ) {
188  if ( ! module_path ) {
189  XLALPrintInfo ( "%s(): skip relative fallbackpath element '%s': location of liblalsupport.so unknown\n", __func__, subPath_i );
190  continue;
191  }
192  XLAL_CHECK_NULL ( (resolveFname = XLALRealloc ( resolveFname, module_dirname_length + 1 + subPath_i_len + 1 + fname_len + 1 )) != NULL, XLAL_ENOMEM );
193  sprintf ( resolveFname, "%s/%s/%s", module_path, subPath_i, fname );
194  } else {
195  XLAL_CHECK_NULL ( (resolveFname = XLALRealloc ( resolveFname, subPath_i_len + 1 + fname_len + 1 )) != NULL, XLAL_ENOMEM );
196  sprintf ( resolveFname, "%s/%s", subPath_i, fname );
197  }
198  XLALPrintInfo ( "%s(): trying '%s' -> '%s' ...\n", __func__, fname, resolveFname );
199  if ( (tmp = LALFopen ( resolveFname, "rb" )) != NULL ) {
200  LALFclose ( tmp );
201  XLALFree ( module_path );
202  XLALDestroyTokenList ( subPaths );
203  XLALPrintInfo ( "%s(): success '%s' -> '%s'\n", __func__, fname, resolveFname );
204  return resolveFname;
205  } // if found
206  }
207 
208  XLALFree ( module_path );
209  XLALDestroyTokenList ( subPaths );
210 
211  }
212 
213  XLALFree ( resolveFname );
214 
215  } // end: if pure filename given
216 
217  // nothing worked? that's ok: return NULL without failure!
218  XLALPrintInfo ( "%s(): failed '%s'\n", __func__, fname);
219  return NULL;
220 
221 } // XLALFileResolvePathLong()
222 
223 /* Simple wrapper to XLAL_FILE_RESOLVE_PATH(), using hardcoded fallbackdir for LAL
224  Use of XLAL_FILE_RESOLVE_PATH() directly is preferred; kept for ABI backward compatibility */
225 char *
226 XLALFileResolvePath ( const char *fname )
227 {
228  return XLAL_FILE_RESOLVE_PATH( fname );
229 } // XLALFileResolvePath()
230 /** \endcond */ // DONT_DOXYGEN
231 
232 /** Read a complete data-file into memory as a string
233  */
234 char *
235 XLALFileLoad ( const char *path //!< [in] input filepath
236  )
237 {
238  XLAL_CHECK_NULL ( path != NULL, XLAL_EINVAL );
239 
240  // check that this is actually a regular file, rather than sth else (eg a directory)
241  size_t blobLen;
242  XLAL_CHECK_NULL ( XLALFileIsRegularAndGetSize ( path, &blobLen ) == 1, XLAL_EINVAL, "Path '%s' does not point to a regular file!\n", path );
243 
244  char *dataBuffer = NULL;
245  size_t dataBufferLen = 0;
246  size_t numReadTotal = 0;
247  LALFILE *fp;
249 
250  // read file in blobs the size of the (possibly compressed) file
251  int blobCounter = 0;
252  while ( ! XLALFileEOF( fp ) )
253  {
254  dataBufferLen += blobLen;
255  if ( (dataBuffer = XLALRealloc ( dataBuffer, dataBufferLen + 1)) == NULL ) {
256  XLALFileClose(fp);
257  XLAL_ERROR_NULL ( XLAL_ENOMEM, "Failed to XLALRealloc(%zu)\n", dataBufferLen+1 );
258  }
259  size_t numRead = XLALFileRead ( dataBuffer + blobCounter*blobLen, sizeof(char), blobLen, fp );
260  if ( xlalErrno != XLAL_SUCCESS ) {
261  XLALFree ( dataBuffer );
262  XLALFileClose(fp);
264  }
265 
266  numReadTotal += numRead;
267 
268  if ( numRead < blobLen ) {
269  break;
270  }
271  blobCounter ++;
272 
273  } // while !eof
274 
275  XLALFileClose(fp);
276 
277  // adjust buffer to final size of data read
278  XLAL_CHECK_NULL ( (dataBuffer = XLALRealloc ( dataBuffer, numReadTotal + 1)) != NULL, XLAL_ENOMEM, "Failed to XLALRealloc(%zu)\n", numReadTotal+1 );
279  dataBuffer[numReadTotal] = 0;
280 
281  return dataBuffer;
282 
283 } // XLALFileLoad()
284 
285 int XLALFileIsCompressed( const char *path )
286 {
287  FILE *fp;
288  unsigned char magic[2] = { 0, 0 };
289  size_t c;
290  if ( ! ( fp = LALFopen( path, "rb" ) ) )
291  XLAL_ERROR( XLAL_EIO );
292  c = fread( magic, sizeof(*magic), XLAL_NUM_ELEM(magic), fp );
293  if (c == 0)
294  XLAL_ERROR( XLAL_EIO );
295  fclose( fp );
296  return magic[0] == 0x1f && magic[1] == 0x8b;
297 }
298 
299 LALFILE *XLALFileOpenRead( const char *path )
300 {
301  int compression;
302  LALFILE *file;
303  if ( 0 > (compression = XLALFileIsCompressed(path) ) )
305 #ifndef ZLIB_ENABLED
306  if ( compression ) {
307  XLALPrintError( "XLAL Error - %s: Cannot read compressed file\n", __func__ );
309  }
310 #endif
311  if ( ! ( file = XLALMalloc( sizeof(*file ) ) ) )
313  file->compression = compression;
314 #ifdef ZLIB_ENABLED
315  file->fp = compression ? (void*)gzopen( path, "rb" ) : (void*)LALFopen( path, "rb" );
316 #else
317  file->fp = (void*)LALFopen( path, "rb" );
318 #endif
319  if ( ! file->fp ) {
320  XLALFree( file );
322  }
323  return file;
324 }
325 
326 LALFILE *XLALFileOpenAppend( const char *path, int compression )
327 {
328  LALFILE *file;
329  if ( ! ( file = XLALMalloc( sizeof(*file ) ) ) )
331 #ifdef ZLIB_ENABLED
332  file->fp = compression ? (void*)gzopen( path, "a+" ) : (void*)LALFopen( path, "a+" );
333 #else
334  if ( compression ) {
335  XLALPrintWarning( "XLAL Warning - %s: Compression not supported\n", __func__ );
336  compression = 0;
337  }
338  file->fp = (void*)LALFopen( path, "a+" );
339 #endif
340  file->compression = compression;
341  if ( ! file->fp ) {
342  XLALFree( file );
344  }
345  return file;
346 }
347 
348 LALFILE *XLALFileOpenWrite( const char *path, int compression )
349 {
350  LALFILE *file;
351  if ( ! ( file = XLALMalloc( sizeof(*file ) ) ) )
353 #ifdef ZLIB_ENABLED
354  file->fp = compression ? (void*)gzopen( path, "wb" ) : (void*)LALFopen( path, "wb" );
355 #else
356  if ( compression ) {
357  XLALPrintWarning( "XLAL Warning - %s: Compression not supported\n", __func__ );
358  compression = 0;
359  }
360  file->fp = (void*)LALFopen( path, "wb" );
361 #endif
362  file->compression = compression;
363  if ( ! file->fp ) {
364  XLALFree( file );
366  }
367  return file;
368 }
369 
370 LALFILE *XLALFileOpen( const char *path, const char *mode )
371 {
372  int compression;
373  char *ext;
374  switch ( *mode ) {
375  case 'r':
376  return XLALFileOpenRead( path );
377  case 'w':
378  /* check if filename ends in .gz */
379  ext = strrchr( path, '.' );
380  compression = ext ? ! strcmp( ext, ".gz" ) : 0;
381  return XLALFileOpenWrite( path, compression );
382  default:
383  break; /* fall-out */
384  }
385  /* error if code gets here */
387 }
388 
389 int XLALFileClose( LALFILE *file )
390 {
391  /* this routine acts as a no-op if the file is NULL */
392  /* this behavior is different from BSD fclose */
393  if ( file ) {
394  int c;
395  if ( ! file->fp )
397 #ifdef ZLIB_ENABLED
398  c = file->compression ? gzclose(((gzFile)file->fp)) : fclose(((FILE*)file->fp));
399 #else
400  c = fclose(((FILE*)file->fp));
401 #endif
402  if ( c == EOF )
403  XLAL_ERROR( XLAL_EIO );
404  XLALFree( file );
405  }
406  return 0;
407 }
408 
409 size_t XLALFileRead( void *ptr, size_t size, size_t nobj, LALFILE *file )
410 {
411  size_t c;
412  if ( ! file )
414 #ifdef ZLIB_ENABLED
415  c = file->compression ? (size_t)gzread( ((gzFile)file->fp), ptr, size * nobj ) : fread( ptr, size, nobj, ((FILE*)file->fp) );
416 #else
417  c = fread( ptr, size, nobj, ((FILE*)file->fp) );
418 #endif
419  if ( c == (size_t)(-1) || (file->compression == 0 && ferror((FILE*)(file->fp))) )
420  XLAL_ERROR( XLAL_EIO );
421  return c;
422 }
423 
424 size_t XLALFileWrite( const void *ptr, size_t size, size_t nobj, LALFILE *file )
425 {
426  size_t c;
427  if ( ! file )
429 #ifdef ZLIB_ENABLED
430  c = file->compression ? (size_t)gzwrite( ((gzFile)file->fp), ptr, size * nobj ) : fwrite( ptr, size, nobj, ((FILE*)file->fp) );
431 #else
432  c = fwrite( ptr, size, nobj, (FILE*)(file->fp) );
433 #endif
434  if ( c == 0 || (file->compression == 0 && ferror((FILE*)(file->fp))) )
435  XLAL_ERROR( XLAL_EIO );
436  return c;
437 }
438 
439 int XLALFileGetc( LALFILE *file )
440 {
441  int c;
442  if ( ! file )
444 #ifdef ZLIB_ENABLED
445  c = file->compression ? gzgetc(((gzFile)file->fp)) : fgetc(((FILE*)file->fp));
446 #else
447  c = fgetc(((FILE*)file->fp));
448 #endif
449  return c;
450 }
451 
452 int XLALFilePutc( int c, LALFILE *file )
453 {
454  int result;
455  if ( ! file )
457 #ifdef ZLIB_ENABLED
458  result = file->compression ? gzputc(((gzFile)file->fp), c) : fputc(c, ((FILE*)file->fp));
459 #else
460  result = fputc(c, (FILE*)(file->fp));
461 #endif
462  if ( result == -1 )
463  XLAL_ERROR( XLAL_EIO );
464  return result;
465 }
466 
467 char * XLALFileGets( char * s, int size, LALFILE *file )
468 {
469  char *c;
470  if ( ! file )
472 #ifdef ZLIB_ENABLED
473  c = file->compression ? gzgets( ((gzFile)file->fp), s, size ) : fgets( s, size, ((FILE*)file->fp) );
474 #else
475  c = fgets( s, size, ((FILE*)file->fp) );
476 #endif
477  return c;
478 }
479 
480 int XLALFilePuts( const char * s, LALFILE *file )
481 {
482  if ( ! file )
484  if ( 0 > (int)XLALFileWrite( s, sizeof(*s), strlen(s), file ) )
486  return 0;
487 }
488 
489 int XLALFileVPrintf( LALFILE *file, const char *fmt, va_list ap )
490 {
491  char buf[32768];
492  int len;
493  int c;
494  if ( ! file )
496  len = vsnprintf( buf, sizeof(buf), fmt, ap );
497  if ( len < 0 )
499  if ( len >= (int)sizeof(buf) ) { /* buffer is too small */
500  char *s;
501  s = XLALMalloc( len + 1 );
502  if ( !s )
504  len = vsnprintf( s, len + 1, fmt, ap );
505  c = XLALFilePuts( s, file );
506  XLALFree( s );
507  } else {
508  c = XLALFilePuts( buf, file );
509  }
510  if ( c < 0 )
512  return len;
513 }
514 
515 int XLALFilePrintf( LALFILE *file, const char *fmt, ... )
516 {
517  int c;
518  va_list ap;
519  va_start( ap, fmt );
520  c = XLALFileVPrintf( file, fmt, ap );
521  va_end( ap );
522  if ( c < 0 )
524  return c;
525 }
526 
527 
528 int XLALFileFlush( LALFILE *file )
529 {
530  int c;
531  if ( ! file )
533 #ifdef ZLIB_ENABLED
534  c = file->compression ? gzflush(((gzFile)file->fp), Z_FULL_FLUSH) : fflush(((FILE*)file->fp));
535 #else
536  c = fflush(((FILE*)file->fp));
537 #endif
538  if ( c == -1 )
539  XLAL_ERROR( XLAL_EIO );
540  return c;
541 }
542 
543 int XLALFileSeek( LALFILE *file, long offset, int whence )
544 {
545  int c;
546  if ( ! file )
548 #ifdef ZLIB_ENABLED
549  if ( file->compression && whence == SEEK_END ) {
550  XLALPrintError( "XLAL Error - %s: SEEK_END not supported with compressed files\n", __func__ );
552  }
553  c = file->compression ? gzseek(((gzFile)file->fp), offset, whence) : fseek(((FILE*)file->fp), offset, whence);
554 #else
555  c = fseek(((FILE*)file->fp), offset, whence);
556 #endif
557  if ( c == -1 )
558  XLAL_ERROR( XLAL_EIO );
559  return 0;
560 }
561 
562 long XLALFileTell( LALFILE *file )
563 {
564  long c;
565  if ( ! file )
567 #ifdef ZLIB_ENABLED
568  c = file->compression ? (long)gztell(((gzFile)file->fp)) : ftell(((FILE*)file->fp));
569 #else
570  c = ftell(((FILE*)file->fp));
571 #endif
572  if ( c == -1 )
573  XLAL_ERROR( XLAL_EIO );
574  return c;
575 }
576 
577 void XLALFileRewind( LALFILE *file )
578 {
579  if ( ! file )
581 #ifdef ZLIB_ENABLED
582  file->compression ? (void)gzrewind(((gzFile)file->fp)) : rewind(((FILE*)file->fp));
583 #else
584  rewind(((FILE*)file->fp));
585 #endif
586  return;
587 }
588 
589 /** \brief Set buffering for file I/O
590  *
591  * 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
592  * automatically allocated. The \c mode can be \c _IONBF, \c _IOLBF or \c _IOFBF for no buffering, line buffering
593  * or full buffering respectively.
594  *
595  * For a compressed file the buffering will be set with \c gzbuffer. The \c buf and \c mode inputs are ignored and a
596  * buffer of \c size is set.
597  */
598 int XLALFileSetBuffer( LALFILE *file, char *buf, int mode, size_t size )
599 {
600  int c = 0;
601  if ( ! file )
603 #ifdef ZLIB_ENABLED
604  if ( !file->compression ){
605  c = setvbuf(((FILE*)file->fp), buf, mode, size);
606  }
607  else{
608 #if defined ZLIB_VER_MAJOR && ZLIB_VER_MAJOR >= 1 && ZLIB_VER_MINOR >= 2 && ZLIB_VER_REVISION >= 4
609  c = (int)gzbuffer(((gzFile)file->fp), size);
610 #else
611  XLAL_PRINT_WARNING("Ignored buffering: unsupported in zlib version %s", ZLIB_VERSION);
612 #endif
613  }
614 #else
615  c = setvbuf(((FILE*)file->fp), buf, mode, size);
616 #endif
617  if ( c != 0 )
618  XLAL_ERROR( XLAL_EIO );
619  return c;
620 }
621 
622 
623 int XLALFileEOF( LALFILE *file )
624 {
625  int c;
626  if ( ! file )
628 #ifdef ZLIB_ENABLED
629  c = file->compression ? gzeof(((gzFile)file->fp)) : feof((FILE*)(file->fp));
630 #else
631  c = feof((FILE*)(file->fp));
632 #endif
633  return c;
634 }
635 
636 /** Check if path points to a 'regular file', rather than a directory or sth else.
637  * and also return the size of the given file.
638  *
639  * This is simply a wrapper to stat(), and S_ISREG()
640  * and could be easily generalized along those lines to test for directories etc.
641  *
642  * return an error if stat() was unavailable
643  * return 1 for true, 0 for false, -1 on error
644  */
645 int
646 XLALFileIsRegularAndGetSize ( const char *path, //!< [in] path to file
647  size_t *fileLen //!< [out] size in bytes of file
648  )
649 {
650 #ifndef HAVE_STAT
651  XLAL_ERROR ( XLAL_EFAILED, "No implementation of function stat() available, which is required here!\n");
652 #else
653  XLAL_CHECK ( path != NULL, XLAL_EINVAL );
654 
655  struct stat sb;
656  XLAL_CHECK ( stat( path, &sb) != -1, XLAL_EIO, "stat() failed: perror = '%s'\n", strerror(errno) );
657 
658  if ( fileLen ) { // optional output argument
659  (*fileLen) = (size_t)sb.st_size;
660  }
661 
662  return (S_ISREG(sb.st_mode));
663 #endif
664 
665 } // XLALFileIsRegularAndGetSize()
666 
667 
668 /** Check if given file is 'regular' (rather than a directory or sth else)
669  *
670  * This is a simple wrapper to XLALFileIsRegularAndGetSize().
671  *
672  * Return 1 for true, 0 for false, -1 on error
673  */
674 int
675 XLALFileIsRegular ( const char *path //!< [in] path to file
676  )
677 {
678  return XLALFileIsRegularAndGetSize ( path, NULL );
679 } // XLALFileIsRegular()
680 
681 
682 /** Return the size of given file in bytes.
683  *
684  * This is simply a wrapper to XLALFileIsRegularAndGetSize()
685  *
686  * Returns (size_t)-1 on error
687  */
688 size_t
689 XLALFileSize ( const char *path //!< [in] path to file
690  )
691 {
692  size_t size;
693 
695 
696  return size;
697 
698 } // XLALFileSize()
699 
700 /**
701  * \brief Use gzip to compress a text file
702  * This function will use the gzip compression routines in \c zlib to compress a text file. The compressed file will
703  * have the extension ".gz" and the original uncompressed file will be removed.
704  *
705  * \param filename [in] The input text file.
706  */
707 int XLALGzipTextFile( const char *filename ){
708  char *memblock = NULL; /* memory block to read data into */
709  long pos;
710  char *outname = NULL;
711 
712  LALFILE *fp = NULL; /* input file pointer */
713  LALFILE *fg = NULL; /* output gzipped file pointer */
714 
715  /* open file for reading and work out its size */
716  if( (fp = XLALFileOpen( filename, "rb" )) == NULL ){
717  XLALPrintError ("%s: Unable to open file %s.\n", __func__, filename );
718  XLAL_ERROR( XLAL_EIO );
719  }
720 
721  XLALFileSeek( fp, 0, SEEK_END ); /* go to end of the file */
722  pos = XLALFileTell( fp ); /* get the position of the file pointer */
723  XLALFileRewind( fp ); /* return the file pointer to the start of the file */
724 
725  /* allocate memory to read in data */
726  memblock = XLALMalloc( pos + 1);
727 
728  if ( !memblock ){
729  XLALPrintError ("%s: Unable to allocate memory for reading file.\n", __func__ );
731  }
732 
733  /* read in data */
734  if ( XLALFileRead( memblock, pos, 1, fp ) == 0 ){
735  XLALPrintError ("%s: Unable to read in file.\n", __func__ );
736  XLAL_ERROR( XLAL_EIO );
737  }
738  memblock[pos] = 0; // properly 0-terminate string
739 
740  XLALFileClose( fp );
741 
742  /* create output name with .gz appended */
743  if ( (outname = XLALCalloc(strlen(filename)+4, 1)) == NULL) /* we need local copy */{
745  }
746 
747  strcpy(outname, filename);
748  strcat(outname, ".gz"); /* add the extension */
749 
750  if ( !outname ){
751  XLALPrintError("%s: Unable to create output filename.\n", __func__ );
753  }
754 
755  /* open output gzip file */
756  if ( (fg = XLALFileOpen( outname, "wb" )) == NULL ){
757  XLALPrintError ("%s: Unable to open output file %s.\n", __func__, outname );
758  XLAL_ERROR( XLAL_EIO );
759  }
760 
761  if ( XLALFilePuts( memblock, fg ) != 0 ){
762  XLALPrintError ("%s: Unable to output gzipped data.\n", __func__ );
763  XLAL_ERROR( XLAL_EIO );
764  }
765 
766  XLALFileClose( fg );
767 
768  /* remove original file */
769  if ( remove( filename ) == -1 ){
770  XLALPrintError ("%s: Unable to remove original text file.\n", __func__ );
772  }
773 
774  return XLAL_SUCCESS;
775 }
776 
777 
778 /**
779  * \brief Use gzip to uncompress a compressed text file
780  *
781  * This function will use the gzip compression routines in \c zlib to uncompress a gzipped text file. The compressed
782  * file should have the ".gz" extension otherwise it will be rejected. The output will have the same filename with the
783  * ".gz" extension removed. The compressed file will be removed.
784  *
785  * 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
786  * will still open the file for reading as a standard file.
787  *
788  * \param filename [in] The input gzipped text file.
789  */
790 int XLALGunzipTextFile( const char *filename ){
791  CHAR *memblock = NULL; /* memory block to read data into */
792  CHAR *outname = NULL;
793  CHAR *gzpos = NULL;
794 
795  LALFILE *fp = NULL; /* output file pointer */
796  LALFILE *fg = NULL; /* input gzipped file pointer */
797  size_t n;
798 
799  /* create output file name by striping .gz from the input file name */
800  if ( (gzpos = strstr(filename, ".gz")) == NULL ){
801  XLALPrintError ("%s: File %s does not contain the .gz extension.\n", __func__, filename );
802  XLAL_ERROR ( XLAL_EIO );
803  }
804 
805  n = gzpos-filename;
806  outname = XLALMalloc( sizeof(CHAR)*(n+1) );
807 
808  if ( ( outname = strncpy(outname, filename, n) ) == NULL ){
809  XLALPrintError ("%s: Unable to strip extension from file string.\n", __func__ );
810  XLAL_ERROR ( XLAL_EIO );
811  }
812  outname[n] = 0;
813 
814  /* open gzipped file for reading */
815  if ( (fg = XLALFileOpen(filename, "rb")) == NULL ){
816  XLALPrintError ("%s: Unable to open gzipped file %s.\n", __func__, filename );
817  XLAL_ERROR ( XLAL_EIO );
818  }
819 
820  /* open output text file */
821  if ( (fp = XLALFileOpen(outname, "w")) == NULL ){
822  XLALPrintError ("%s: Unable to open output file %s.\n", __func__, outname );
823  XLAL_ERROR ( XLAL_EIO );
824  }
825 
826  /* allocate memory for a single char */
827  memblock = XLALMalloc( sizeof(CHAR) );
828 
829  /* read in gzipped data one byte at a time and output to text file */
830  while( ( memblock = XLALFileGets(memblock, 2, fg) ) != NULL ){ XLALFilePrintf(fp, "%s", memblock); }
831 
832  /* close files */
833  XLALFileClose( fg );
834  XLALFileClose( fp );
835 
836  /* remove original file */
837  if ( remove( filename ) == -1 ){
838  XLALPrintError ("%s: Unable to remove original gzipped file.\n", __func__ );
840  }
841 
842  return XLAL_SUCCESS;
843 }
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 * lalstdin(void)
Definition: FileIO.c:63
int XLALFileVPrintf(LALFILE *file, const char *fmt, va_list ap)
Definition: FileIO.c:489
int XLALGunzipTextFile(const char *filename)
Use gzip to uncompress a compressed text file.
Definition: FileIO.c:790
int XLALFileClose(LALFILE *file)
Definition: FileIO.c:389
int XLALFilePutc(int c, LALFILE *file)
Definition: FileIO.c:452
char * XLALFileLoad(const char *path)
Read a complete data-file into memory as a string.
Definition: FileIO.c:235
int XLALFileEOF(LALFILE *file)
Definition: FileIO.c:623
LALFILE * XLALFileOpenAppend(const char *path, int compression)
Definition: FileIO.c:326
LALFILE * lalstdout(void)
Definition: FileIO.c:69
size_t XLALFileSize(const char *path)
Return the size of given file in bytes.
Definition: FileIO.c:689
int XLALFilePuts(const char *s, LALFILE *file)
Definition: FileIO.c:480
int XLALFileIsRegular(const char *path)
Check if given file is 'regular' (rather than a directory or sth else)
Definition: FileIO.c:675
LALFILE * lalstderr(void)
Definition: FileIO.c:75
size_t XLALFileRead(void *ptr, size_t size, size_t nobj, LALFILE *file)
Definition: FileIO.c:409
int XLALFileSetBuffer(LALFILE *file, char *buf, int mode, size_t size)
Set buffering for file I/O.
Definition: FileIO.c:598
char * XLALFileGets(char *s, int size, LALFILE *file)
Definition: FileIO.c:467
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:646
int XLALFileSeek(LALFILE *file, long offset, int whence)
Definition: FileIO.c:543
int XLALFileIsCompressed(const char *path)
Definition: FileIO.c:285
size_t XLALFileWrite(const void *ptr, size_t size, size_t nobj, LALFILE *file)
Definition: FileIO.c:424
LALFILE * XLALFileOpenRead(const char *path)
Definition: FileIO.c:299
int XLALFilePrintf(LALFILE *file, const char *fmt,...)
Definition: FileIO.c:515
void XLALFileRewind(LALFILE *file)
Definition: FileIO.c:577
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:707
int XLALFileGetc(LALFILE *file)
Definition: FileIO.c:439
LALFILE * XLALFileOpen(const char *path, const char *mode)
Definition: FileIO.c:370
#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:562
LALFILE * XLALFileOpenWrite(const char *path, int compression)
Definition: FileIO.c:348
int XLALFileFlush(LALFILE *file)
Definition: FileIO.c:528
#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:60
int compression
Definition: FileIO.c:59
FILE * fp
Definition: tconvert.c:105