From 8c44b9df6ecd47dcd9ff28843d803397f7b80291 Mon Sep 17 00:00:00 2001 From: Chad Trabant Date: Wed, 4 Mar 2015 05:29:53 +0000 Subject: [PATCH] commit libmseed 2.14 updates --- libmseed/ChangeLog | 61 +++++++++++ libmseed/Makefile | 77 ++++++-------- libmseed/doc/ms_intro.3 | 7 +- libmseed/doc/ms_log.3 | 10 +- libmseed/doc/ms_readleapsecondfile.3 | 1 + libmseed/doc/ms_readleapseconds.3 | 48 +++++++++ libmseed/doc/msr_pack.3 | 9 +- libmseed/doc/msr_parse.3 | 6 +- libmseed/doc/msr_starttime.3 | 10 +- libmseed/doc/mst_addmsr.3 | 4 +- libmseed/doc/mst_convertsamples.3 | 48 +++++++++ libmseed/doc/mst_pack.3 | 13 +-- libmseed/doc/mstl_convertsamples.3 | 1 + libmseed/example/Makefile | 42 +------- libmseed/fileutils.c | 36 +++---- libmseed/genutils.c | 143 ++++++++++++++++++++++++- libmseed/gswap.c | 2 +- libmseed/libmseed.h | 116 ++++++++++++--------- libmseed/lmplatform.h | 4 +- libmseed/logging.c | 15 +-- libmseed/msrutils.c | 28 ++++- libmseed/pack.c | 7 +- libmseed/parseutils.c | 26 ++--- libmseed/selection.c | 4 +- libmseed/tracelist.c | 147 +++++++++++++++++++++++++- libmseed/traceutils.c | 149 ++++++++++++++++++++++++++- libmseed/unpack.c | 3 +- 27 files changed, 804 insertions(+), 213 deletions(-) create mode 120000 libmseed/doc/ms_readleapsecondfile.3 create mode 100644 libmseed/doc/ms_readleapseconds.3 create mode 100644 libmseed/doc/mst_convertsamples.3 create mode 120000 libmseed/doc/mstl_convertsamples.3 diff --git a/libmseed/ChangeLog b/libmseed/ChangeLog index d43d13c..cc3ae39 100644 --- a/libmseed/ChangeLog +++ b/libmseed/ChangeLog @@ -1,3 +1,64 @@ +2015.062: 2.14 + - Fix memory leak when msr_pack() returns after an error. Patch + contributed by Larry Baker and Eric Thomas. + - Change casting of values passed to isdigit() to int intead of + unsigned character. Apparently this was consufing on ARM archs. + +2015.061: + - Add ms_readleapseconds() and ms_readleapsecondfile() routines to + read a leap seconds file into an internal list. + - Modify msr_endtime() to check for an internal leap second list, + check for overlap with the record and adjust the end time as needed + when leap seconds are present. When a leap second list is present + any indication of positive leap seconds in the fixed section data + header are ignored. + +2014.248: + - Add casting to size_t and int to avoid build warnings on certain + build systems (e.g. older MS Visual Studio). + The effective maximum sample buffer and record buffer size is ~2GB. + +2014.234: 2.13 + - Clean up Makefile and example/Makefile, remove all GCC-specific and + debug targets. Makefiles are compatible with both GNU and BSD make. + As before, the shared target works only for GCC-compatible compilers. + Thanks to Elliott Sales de Andrade for pointing out that shared library + targets did not work with parallel builds, prompting this clean up. + +2014.197: 2.13rc + - Support 128-byte record length by changing MINRECLEN to 128 (was 256). + The current SEED specification is a minimum record length of 256-bytes, + but there are cases (e.g. low latency data flow) using 128-byte records. + - Add declarations, casting and string truncation to clear warnings + uncovered in ObsPy testing (thanks to Elliott Sales de Andrade). + +2014.074: + - Add __CYGWIN__ defined test to Linux section of lmplatform.h. + +2013.273: 2.12 + - Add mst_convertsamples() and mstl_convertsamples() to convert sample + types. When converting from float & double types to integer type + a simple rounding is employed to compensate for machine representation + of floating point numbers. + +2013.267: + - msr_endtime(): Check activity flags in fixed section of data header, + if bit 4 is set then a positive leap occurred during the record and + the end time should be reduced by one second to properly match the now + shifted UTC time. As long as the next record in the series is + properly marked with the correct UTC time no artificial time tear + will be generated when reconstructing the time series. + +2013.137: + - Update docs for transition to 64-bit sample counts done in 2011! + +2013.117: 2.11 + - Initialize internal counters in mst_pack() to avoid their use + in error conditions. Thanks to D. Ketchum and M. Potter for help. + - Add 'const' qualifier to the msfile argument of the file reading and + writing family of routines to stop compiler warnings resulting from + generated binding functions. Thanks to M. Bach for reporting. + 2013.056: 2.10 - Add more sanity checks to msr_unpack_data() to catch bad/corrupted data records and avoid crashes due to impossible pointer construction. diff --git a/libmseed/Makefile b/libmseed/Makefile index a4dd874..61697a2 100644 --- a/libmseed/Makefile +++ b/libmseed/Makefile @@ -4,19 +4,18 @@ # CC : Specify the C compiler to use # CFLAGS : Specify compiler options to use -# Options specific for GCC -GCC = gcc -GCCFLAGS = -O2 -Wall -fPIC - -LIB_OBJS = fileutils.o genutils.o gswap.o lmplatform.o lookup.o \ - msrutils.o pack.o packdata.o traceutils.o tracelist.o \ - parseutils.o unpack.o unpackdata.o selection.o logging.o - MAJOR_VER = 2 -MINOR_VER = 10 +MINOR_VER = 13 CURRENT_VER = $(MAJOR_VER).$(MINOR_VER) COMPAT_VER = $(MAJOR_VER).$(MINOR_VER) +LIB_SRCS = fileutils.c genutils.c gswap.c lmplatform.c lookup.c \ + msrutils.c pack.c packdata.c traceutils.c tracelist.c \ + parseutils.c unpack.c unpackdata.c selection.c logging.c + +LIB_OBJS = $(LIB_SRCS:.c=.o) +LIB_DOBJS = $(LIB_SRCS:.c=.lo) + LIB_A = libmseed.a LIB_SO_FILENAME = libmseed.so LIB_SO_ALIAS = $(LIB_SO_FILENAME).$(MAJOR_VER) @@ -28,59 +27,43 @@ all: static static: $(LIB_A) -shared: gcc $(LIB_SO) +shared: $(LIB_SO) -dynamic: gcc $(LIB_DYN) +dynamic: $(LIB_DYN) +# Build static library $(LIB_A): $(LIB_OBJS) rm -f $(LIB_A) - ar -csq $(LIB_A) $(LIB_OBJS) + ar -crs $(LIB_A) $(LIB_OBJS) -$(LIB_SO): $(LIB_OBJS) +# Build shared library using GCC-style options +$(LIB_SO): $(LIB_DOBJS) rm -f $(LIB_SO) $(LIB_SO_FILENAME) - $(GCC) $(GCCFLAGS) -shared -Wl,-soname -Wl,$(LIB_SO_ALIAS) -o $(LIB_SO) $(LIB_OBJS) + $(CC) $(CFLAGS) -shared -Wl,-soname -Wl,$(LIB_SO_ALIAS) -o $(LIB_SO) $(LIB_DOBJS) ln -s $(LIB_SO) $(LIB_SO_ALIAS) ln -s $(LIB_SO) $(LIB_SO_FILENAME) -$(LIB_DYN): $(LIB_OBJS) +# Build dynamic library (usually for Mac OSX) +$(LIB_DYN): $(LIB_DOBJS) rm -f $(LIB_DYN) $(LIB_DYN_ALIAS) - $(GCC) $(GCCFLAGS) -dynamiclib -compatibility_version $(COMPAT_VER) -current_version $(CURRENT_VER) -install_name $(LIB_DYN_ALIAS) -o $(LIB_DYN) $(LIB_OBJS) + $(CC) $(CFLAGS) -dynamiclib -compatibility_version $(COMPAT_VER) -current_version $(CURRENT_VER) -install_name $(LIB_DYN_ALIAS) -o $(LIB_DYN) $(LIB_DOBJS) ln -sf $(LIB_DYN) $(LIB_DYN_ALIAS) clean: - rm -f $(LIB_OBJS) $(LIB_A) $(LIB_SO) $(LIB_SO_ALIAS) $(LIB_DYN) $(LIB_DYN_ALIAS) - -cc: - @$(MAKE) "CC=$(CC)" "CFLAGS=$(CFLAGS)" - -gcc: - @$(MAKE) "CC=$(GCC)" "CFLAGS=$(GCCFLAGS)" - -gcc32: - @$(MAKE) "CC=$(GCC)" "CFLAGS=-m32 $(GCCFLAGS)" - -gcc64: - @$(MAKE) "CC=$(GCC)" "CFLAGS=-m64 $(GCCFLAGS)" + rm -f $(LIB_OBJS) $(LIB_DOBJS) $(LIB_A) $(LIB_SO_FILENAME) $(LIB_SO) $(LIB_SO_ALIAS) $(LIB_DYN) $(LIB_DYN_ALIAS) -debug: - $(MAKE) "CC=$(CC)" "CFLAGS=-g $(CFLAGS)" - -gccdebug: - $(MAKE) "CC=$(GCC)" "CFLAGS=-g $(GCCFLAGS)" - -gcc32debug: - $(MAKE) "CC=$(GCC)" "CFLAGS=-g -m32 $(GCCFLAGS)" +install: + @echo + @echo "No install target, copy the library and header as needed" + @echo -gcc64debug: - $(MAKE) "CC=$(GCC)" "CFLAGS=-g -m64 $(GCCFLAGS)" -gcc32gprof: - $(MAKE) "CC=$(GCC)" "CFLAGS=-pg -m32 $(GCCFLAGS)" +.SUFFIXES: .c .o .lo -gcc64gprof: - $(MAKE) "CC=$(GCC)" "CFLAGS=-pg -m64 $(GCCFLAGS)" +# Standard object building +.c.o: + $(CC) $(CFLAGS) -c $< -o $@ -install: - @echo - @echo "No install target, copy the library and header yourself" - @echo +# Standard object building for dynamic library components using -fPIC +.c.lo: + $(CC) $(CFLAGS) -fPIC -c $< -o $@ diff --git a/libmseed/doc/ms_intro.3 b/libmseed/doc/ms_intro.3 index 6e8c54e..0096ac0 100644 --- a/libmseed/doc/ms_intro.3 +++ b/libmseed/doc/ms_intro.3 @@ -1,4 +1,4 @@ -.TH MS_INTRO 3 2011/05/24 +.TH MS_INTRO 3 2013/07/17 .SH NAME Introduction to libmseed @@ -519,7 +519,7 @@ static void record_handler (char *record, int reclen, void *srcname) { } main() { - int psamples; + int64_t psamples; int precords; MSTrace *mst; char srcname[50]; @@ -546,7 +546,8 @@ main() { precords = mst_pack (mst, &record_handler, srcname, 4096, DE_STEIM2, 1, &psamples, 1, verbose, NULL); - ms_log (0, "Packed %d samples into %d records\n", psamples, precords); + ms_log (0, "Packed %lld samples into %d records\n", + (long long int)psamples, precords); /* Disconnect datasamples pointer, otherwise mst_free() will free it */ mst->datasamples = NULL; diff --git a/libmseed/doc/ms_log.3 b/libmseed/doc/ms_log.3 index 3d856de..f616e1b 100644 --- a/libmseed/doc/ms_log.3 +++ b/libmseed/doc/ms_log.3 @@ -1,4 +1,4 @@ -.TH MS_LOG 3 2006/11/21 +.TH MS_LOG 3 2014/07/16 .SH NAME ms_log and friends \- Central logging facility for libmseed @@ -10,12 +10,12 @@ ms_log and friends \- Central logging facility for libmseed .sp .BI "int \fBms_log_l\fP (MSLogParam *" logp ", int " level ", const char *" format ", ...); .sp -.BI "void \fBms_loginit\fP (void (*" log_print ")(const char*), const char *" logprefix ", -.BI " void (*" diag_print ")(const char*), const char *" errprefix "); +.BI "void \fBms_loginit\fP (void (*" log_print ")(char*), const char *" logprefix ", +.BI " void (*" diag_print ")(char*), const char *" errprefix "); .sp .BI "MSLogParam * \fBms_loginit_l\fP (MSLogParam *" logp ", -.BI " void (*" log_print ")(const char*), const char *" logprefix ", -.BI " void (*" diag_print ")(const char*), const char *" errprefix "); +.BI " void (*" log_print ")(char*), const char *" logprefix ", +.BI " void (*" diag_print ")(char*), const char *" errprefix "); .fi .SH DESCRIPTION The \fBms_log\fP functions are the central logging facility for diff --git a/libmseed/doc/ms_readleapsecondfile.3 b/libmseed/doc/ms_readleapsecondfile.3 new file mode 120000 index 0000000..c5fcda2 --- /dev/null +++ b/libmseed/doc/ms_readleapsecondfile.3 @@ -0,0 +1 @@ +ms_readleapseconds.3 \ No newline at end of file diff --git a/libmseed/doc/ms_readleapseconds.3 b/libmseed/doc/ms_readleapseconds.3 new file mode 100644 index 0000000..f4df8f7 --- /dev/null +++ b/libmseed/doc/ms_readleapseconds.3 @@ -0,0 +1,48 @@ +.TH MS_READLEAPSECONDS 3 2015/03/02 "Libmseed API" +.SH DESCRIPTION +Read a leap second file into a global buffer + +.SH SYNOPSIS +.nf +.B #include + +.BI "int \fBms_readleapseconds\fP ( char *" envvarname " );" + +.BI "int \fBms_readleapsecondfile\fP ( char *" filename " );" +.fi + +.SH DESCRIPTION +These functions read a leap seconds file and store a list of leap +seconds in an internal, global list. The leap seconds are used to +determine the proper end time of a record (and consquently a trace). +The use of this facility causes the leap second indication in the +fixed section data header to be ignored. + +The \fBms_readleapseconds\fP function takes and environment variable +name that is expected to contain the name of a leap seconds file. The +\fBms_readleapsecondfile\fP function takes the name of a leap second +file. + +.SH LEAP SECOND LIST FILE +The leap second list file is expected to contain a list of leap second +times and TAI-UTC difference values. The first column should be time +stamps as seconds since the NTP epoch (Jan. 1 1900). The second +column should be an integer number of seconds that specify the +difference between TAI and UTC. + +Usually the most recent version of this file is available here: +http://www.ietf.org/timezones/data/leap-seconds.list + +.SH RETURN VALUES +\fBms_readleapseconds\fP returns the number of leap seconds read on +success, -1 on file read errors and -2 when the environment variable +is not set. + +\fBms_readleapsecondfile\fP returns the number leap seconds read on +success and -1 on errors. + +.SH AUTHOR +.nf +Chad Trabant +IRIS Data Management Center +.fi diff --git a/libmseed/doc/msr_pack.3 b/libmseed/doc/msr_pack.3 index bfd6dac..da64271 100644 --- a/libmseed/doc/msr_pack.3 +++ b/libmseed/doc/msr_pack.3 @@ -1,4 +1,4 @@ -.TH MSR_PACK 3 2007/08/16 "Libmseed API" +.TH MSR_PACK 3 2013/05/17 "Libmseed API" .SH DESCRIPTION Packing of Mini-SEED records. @@ -8,7 +8,7 @@ Packing of Mini-SEED records. .BI "int \fBmsr_pack\fP ( MSRecord *" msr "," .BI " void (*" record_handler ") (char *, int, void *)," -.BI " void *" handlerdata ", int *" packedsamples "," +.BI " void *" handlerdata ", int64_t *" packedsamples "," .BI " flag " flush ", flag " verbose " );" .BI "int \fBmsr_pack_header\fP ( MSRecord *" msr ", flag " normalize "," @@ -151,7 +151,7 @@ static void record_handler (char *record, int reclen, void *srcname) { } main() { - int psamples; + int64_t psamples; int precords; MSRecord *msr; char srcname[50]; @@ -177,7 +177,8 @@ main() { /* Pack the record(s) */ precords = msr_pack (msr, &record_handler, srcname, &psamples, 1, verbose); - ms_log (0, "Packed %d samples into %d records\n", psamples, precords); + ms_log (0, "Packed %lld samples into %d records\n", + (long long int)psamples, precords); msr_free (&msr); } diff --git a/libmseed/doc/msr_parse.3 b/libmseed/doc/msr_parse.3 index f3fe60e..d4bd7fa 100644 --- a/libmseed/doc/msr_parse.3 +++ b/libmseed/doc/msr_parse.3 @@ -45,9 +45,9 @@ is found the record length is determined by: 1) Searching the buffer up to \fIrecbuflen\fP for a Blockette 1000. -2) If no Blockette 1000 is found search at 256-byte offsets for the -fixed section of the next header in the buffer, thereby implying the -record length. +2) If no Blockette 1000 is found search at MINRECLEN-byte offsets +for the fixed section of the next header in the buffer, thereby +implying the record length. .SH RETURN VALUES \fBmsr_parse\fP returns values: diff --git a/libmseed/doc/msr_starttime.3 b/libmseed/doc/msr_starttime.3 index f05658d..da4a58a 100644 --- a/libmseed/doc/msr_starttime.3 +++ b/libmseed/doc/msr_starttime.3 @@ -1,4 +1,4 @@ -.TH MSR_STARTTIME 3 2006/02/27 "Libmseed API" +.TH MSR_STARTTIME 3 2015/03/02 "Libmseed API" .SH DESCRIPTION Start and end time determination for MSRecord structures @@ -37,6 +37,14 @@ This function calculates the record start time with the record which is calculated from the number of samples and sample rate. +\fBmsr_endtime\fP will adjust the end time appropriately if the record +is known to contain a positive leap second. If the +\fBms_readleapseconds\fP or \fBms_readleapsecondfile\fP routines have +been called to read a leap second file into an internal list, it will +be checked to know when leap seconds occur. If a leap second list is +not available the fixed section data header is checked for a positive +leap second indicator. + .SH RETURN VALUES \fBmsr_starttime\fP, \fBmsr_starttime_uc\fP and \fBmsr_endtime\fP return a high precision epoch time on success and HPTERROR on error. diff --git a/libmseed/doc/mst_addmsr.3 b/libmseed/doc/mst_addmsr.3 index 7f00b43..08f5332 100644 --- a/libmseed/doc/mst_addmsr.3 +++ b/libmseed/doc/mst_addmsr.3 @@ -1,4 +1,4 @@ -.TH MST_ADDMSR 3 2006/02/27 "Libmseed API" +.TH MST_ADDMSR 3 2013/05/17 "Libmseed API" .SH DESCRIPTION Add time coverage and data samples to MSTrace structures @@ -9,7 +9,7 @@ Add time coverage and data samples to MSTrace structures .BI "int *\fBmst_addmsr\fP ( MSTrace *" mst ", MSRecord *" msr ", flag " whence " ); .BI "int \fBmst_addspan\fP ( MSTrace *" mst ", hptime_t " starttime ", hptime_t " endtime ", -.BI " void *" datasamples ", int " numsamples ", +.BI " void *" datasamples ", int64_t " numsamples ", .BI " char " sampletype ", flag " whence " ); .BI "MSTrace *\fBmst_addmsrtogroup\fP ( MSTraceGroup *" mstg ", MSRecord *" msr ", diff --git a/libmseed/doc/mst_convertsamples.3 b/libmseed/doc/mst_convertsamples.3 new file mode 100644 index 0000000..2c88e46 --- /dev/null +++ b/libmseed/doc/mst_convertsamples.3 @@ -0,0 +1,48 @@ +.TH MST_CONVERTSAMPLES 3 2013/10/01 "Libmseed API" +.SH DESCRIPTION +Convert data samples between numeric types + +.SH SYNOPSIS +.nf +.B #include + +.BI "int \fBmst_convertsamples\fP ( MSTrace *" mst ", char " type ", flag " truncate ");" + +.BI "int \fBmstl_convertsamples\fP ( MSTraceSeg *" seg ", char " type ", flag " truncate ");" + +.SH DESCRIPTION +\fBmst_convertsamples\fP and \fBmst_convertsamples\fP convert any data +samples associated with an \fIMSTrace\fP or \fIMSTraceSeg\fP to a +specified \fitype\fP. + +The routines can convert between 32-bit integers (type \fIi\fP), +32-bit floats (type \fIf\fP) and 64-bit doubles (type \fId\fP). + +When converting float and double sample types to integer type a simple +rouding is applied by adding 0.5 to the sample value before converting +(truncating) to integer. This compensates for common machine +representations of floating point values (e.g. "40.0" represented by +"39.99999999"). + +If the \fItruncate\fP flag is true data samples will be truncated to +integers even if loss of sample precision is detected. If the +\fItruncate\fP flag is false (0) and loss of precision is detected an +error is returned. Loss of precision is determined by testing that +the difference between the floating point value and the (truncated) +integer value is greater than 0.000001. + +ASCII data samples (type \fIa\fP) cannot be converted, if supplied or +requested an error will be returned. + +.SH RETURN VALUES +\fBmst_convertsamples\fP and \fBmstl_convertsamples\fP return 0 on +success and -1 on error. + +.SH SEE ALSO +\fBms_intro(3)\fP. + +.SH AUTHOR +.nf +Chad Trabant +IRIS Data Management Center +.fi diff --git a/libmseed/doc/mst_pack.3 b/libmseed/doc/mst_pack.3 index c5a5883..0386f7b 100644 --- a/libmseed/doc/mst_pack.3 +++ b/libmseed/doc/mst_pack.3 @@ -1,4 +1,4 @@ -.TH MST_PACK 3 2007/08/16 "Libmseed API" +.TH MST_PACK 3 2013/05/17 "Libmseed API" .SH DESCRIPTION Packing of Mini-SEED records from MSTrace segments. @@ -9,13 +9,13 @@ Packing of Mini-SEED records from MSTrace segments. .BI "int \fBmst_pack\fP ( MSTrace *" mst "," .BI " void (*" record_handler ") (char *, int, void *)," .BI " void *" handlerdata ", int " reclen ", flag " encoding "," -.BI " flag " byteorder ", int *" packedsamples ", flag " flush "," +.BI " flag " byteorder ", int64_t *" packedsamples ", flag " flush "," .BI " flag " verbose ", MSRecord *" mstemplate " );" .BI "int \fBmsr_packgroup\fP ( MSTraceGroup *" mstg "," .BI " void (*" record_handler ") (char *, int, void *)," .BI " void *" handlerdata ", int " reclen ", flag " encoding "," -.BI " flag " byteorder ", int *" packedsamples ", flag " flush "," +.BI " flag " byteorder ", int64_t *" packedsamples ", flag " flush "," .BI " flag " verbose ", MSRecord *" mstemplate " );" .fi @@ -127,7 +127,7 @@ static void record_handler (char *record, int reclen, void *srcname) { } main() { - int psamples; + int64_t psamples; int precords; MSTrace *mst; char srcname[50]; @@ -144,7 +144,7 @@ main() { /* The datasamples pointer and numsamples counter will be adjusted by the packing routine, the datasamples array must be dynamic memory allocated by the malloc() family of routines. */ - mst->datasamples = dataptr; /* pointer to 32-bit integer data samples */ + mst->datasamples = dataptr; /* pointer to 32-bit integer data samples */ mst->numsamples = 1234; mst->sampletype = 'i'; /* declare type to be 32-bit integers */ @@ -154,7 +154,8 @@ main() { precords = mst_pack (mst, &record_handler, srcname, 4096, DE_STEIM2, 1, &psamples, 1, verbose, NULL); - ms_log (0, "Packed %d samples into %d records\n", psamples, precords); + ms_log (0, "Packed %lld samples into %d records\n", + (long long int)psamples, precords); mst_free (&mst); } diff --git a/libmseed/doc/mstl_convertsamples.3 b/libmseed/doc/mstl_convertsamples.3 new file mode 120000 index 0000000..9650bf8 --- /dev/null +++ b/libmseed/doc/mstl_convertsamples.3 @@ -0,0 +1 @@ +mst_convertsamples.3 \ No newline at end of file diff --git a/libmseed/example/Makefile b/libmseed/example/Makefile index 1461f8e..6cc4532 100644 --- a/libmseed/example/Makefile +++ b/libmseed/example/Makefile @@ -4,10 +4,6 @@ # CC : Specify the C compiler to use # CFLAGS : Specify compiler options to use -# Options specific for GCC -GCC = gcc -GCCFLAGS = -O2 -Wall -fPIC -I.. - # Required compiler parameters CFLAGS += -I.. @@ -23,43 +19,9 @@ msrepack: msrepack.o $(CC) $(CFLAGS) -o $@ msrepack.o $(LDFLAGS) $(LDLIBS) clean: - rm -f msview.o msview msrepack.o msrepack mstest.o mstest - -cc: - @$(MAKE) "CC=$(CC)" "CFLAGS=$(CFLAGS)" - -gcc: - @$(MAKE) "CC=$(GCC)" "CFLAGS=$(GCCFLAGS)" - -gcc32: - @$(MAKE) "CC=$(GCC)" "CFLAGS=-m32 $(GCCFLAGS)" - -gcc64: - @$(MAKE) "CC=$(GCC)" "CFLAGS=-m64 $(GCCFLAGS)" - -debug: - $(MAKE) "CFLAGS=-g $(CFLAGS)" - -gccdebug: - $(MAKE) "CC=$(GCC)" "CFLAGS=-g $(GCCFLAGS)" - -gcc32debug: - $(MAKE) "CC=$(GCC)" "CFLAGS=-g -m32 $(GCCFLAGS)" - -gcc64debug: - $(MAKE) "CC=$(GCC)" "CFLAGS=-g -m64 $(GCCFLAGS)" - -gcc32gprof: - $(MAKE) "CC=$(GCC)" "CFLAGS=-pg -m32 $(GCCFLAGS)" - -gcc64gprof: - $(MAKE) "CC=$(GCC)" "CFLAGS=-pg -m64 $(GCCFLAGS)" - -# Implicit rule for building object files -%.o: %.c - $(CC) $(CFLAGS) -c $< + rm -f msview.o msview msrepack.o msrepack install: @echo - @echo "No install target, copy the executable(s) yourself" + @echo "No install target, copy the executable(s) as needed" @echo diff --git a/libmseed/fileutils.c b/libmseed/fileutils.c index 289dfd5..1802c9b 100644 --- a/libmseed/fileutils.c +++ b/libmseed/fileutils.c @@ -5,7 +5,7 @@ * Written by Chad Trabant * IRIS Data Management Center * - * modified: 2011.129 + * modified: 2013.117 ***************************************************************************/ #include @@ -98,7 +98,7 @@ MSFileParam gMSFileParam = {NULL, "", NULL, 0, 0, 0, 0, 0, 0, 0}; * further description of arguments. *********************************************************************/ int -ms_readmsr (MSRecord **ppmsr, char *msfile, int reclen, off_t *fpos, +ms_readmsr (MSRecord **ppmsr, const char *msfile, int reclen, off_t *fpos, int *last, flag skipnotdata, flag dataflag, flag verbose) { MSFileParam *msfp = &gMSFileParam; @@ -120,7 +120,7 @@ ms_readmsr (MSRecord **ppmsr, char *msfile, int reclen, off_t *fpos, * further description of arguments. *********************************************************************/ int -ms_readmsr_r (MSFileParam **ppmsfp, MSRecord **ppmsr, char *msfile, +ms_readmsr_r (MSFileParam **ppmsfp, MSRecord **ppmsr, const char *msfile, int reclen, off_t *fpos, int *last, flag skipnotdata, flag dataflag, flag verbose) { @@ -220,7 +220,7 @@ ms_shift_msfp (MSFileParam *msfp, int shift) * NULL. *********************************************************************/ int -ms_readmsr_main (MSFileParam **ppmsfp, MSRecord **ppmsr, char *msfile, +ms_readmsr_main (MSFileParam **ppmsfp, MSRecord **ppmsr, const char *msfile, int reclen, off_t *fpos, int *last, flag skipnotdata, flag dataflag, Selections *selections, flag verbose) { @@ -722,7 +722,7 @@ ms_readmsr_main (MSFileParam **ppmsfp, MSRecord **ppmsr, char *msfile, * and further description of arguments. *********************************************************************/ int -ms_readtraces (MSTraceGroup **ppmstg, char *msfile, int reclen, +ms_readtraces (MSTraceGroup **ppmstg, const char *msfile, int reclen, double timetol, double sampratetol, flag dataquality, flag skipnotdata, flag dataflag, flag verbose) { @@ -743,7 +743,7 @@ ms_readtraces (MSTraceGroup **ppmstg, char *msfile, int reclen, * and further description of arguments. *********************************************************************/ int -ms_readtraces_timewin (MSTraceGroup **ppmstg, char *msfile, int reclen, +ms_readtraces_timewin (MSTraceGroup **ppmstg, const char *msfile, int reclen, double timetol, double sampratetol, hptime_t starttime, hptime_t endtime, flag dataquality, flag skipnotdata, flag dataflag, flag verbose) @@ -784,8 +784,8 @@ ms_readtraces_timewin (MSTraceGroup **ppmstg, char *msfile, int reclen, * in libmseed.h). *********************************************************************/ int -ms_readtraces_selection (MSTraceGroup **ppmstg, char *msfile, int reclen, - double timetol, double sampratetol, +ms_readtraces_selection (MSTraceGroup **ppmstg, const char *msfile, + int reclen, double timetol, double sampratetol, Selections *selections, flag dataquality, flag skipnotdata, flag dataflag, flag verbose) { @@ -848,7 +848,7 @@ ms_readtraces_selection (MSTraceGroup **ppmstg, char *msfile, int reclen, * values and further description of arguments. *********************************************************************/ int -ms_readtracelist (MSTraceList **ppmstl, char *msfile, int reclen, +ms_readtracelist (MSTraceList **ppmstl, const char *msfile, int reclen, double timetol, double sampratetol, flag dataquality, flag skipnotdata, flag dataflag, flag verbose) { @@ -869,8 +869,8 @@ ms_readtracelist (MSTraceList **ppmstl, char *msfile, int reclen, * and further description of arguments. *********************************************************************/ int -ms_readtracelist_timewin (MSTraceList **ppmstl, char *msfile, int reclen, - double timetol, double sampratetol, +ms_readtracelist_timewin (MSTraceList **ppmstl, const char *msfile, + int reclen, double timetol, double sampratetol, hptime_t starttime, hptime_t endtime, flag dataquality, flag skipnotdata, flag dataflag, flag verbose) { @@ -910,8 +910,8 @@ ms_readtracelist_timewin (MSTraceList **ppmstl, char *msfile, int reclen, * in libmseed.h). *********************************************************************/ int -ms_readtracelist_selection (MSTraceList **ppmstl, char *msfile, int reclen, - double timetol, double sampratetol, +ms_readtracelist_selection (MSTraceList **ppmstl, const char *msfile, + int reclen, double timetol, double sampratetol, Selections *selections, flag dataquality, flag skipnotdata, flag dataflag, flag verbose) { @@ -1017,8 +1017,8 @@ ms_record_handler_int (char *record, int reclen, void *ofp) * Returns the number of records written on success and -1 on error. ***************************************************************************/ int -msr_writemseed ( MSRecord *msr, char *msfile, flag overwrite, int reclen, - flag encoding, flag byteorder, flag verbose ) +msr_writemseed ( MSRecord *msr, const char *msfile, flag overwrite, + int reclen, flag encoding, flag byteorder, flag verbose ) { FILE *ofp; char srcname[50]; @@ -1072,8 +1072,8 @@ msr_writemseed ( MSRecord *msr, char *msfile, flag overwrite, int reclen, * Returns the number of records written on success and -1 on error. ***************************************************************************/ int -mst_writemseed ( MSTrace *mst, char *msfile, flag overwrite, int reclen, - flag encoding, flag byteorder, flag verbose ) +mst_writemseed ( MSTrace *mst, const char *msfile, flag overwrite, + int reclen, flag encoding, flag byteorder, flag verbose ) { FILE *ofp; char srcname[50]; @@ -1124,7 +1124,7 @@ mst_writemseed ( MSTrace *mst, char *msfile, flag overwrite, int reclen, * Returns the number of records written on success and -1 on error. ***************************************************************************/ int -mst_writemseedgroup ( MSTraceGroup *mstg, char *msfile, flag overwrite, +mst_writemseedgroup ( MSTraceGroup *mstg, const char *msfile, flag overwrite, int reclen, flag encoding, flag byteorder, flag verbose ) { MSTrace *mst; diff --git a/libmseed/genutils.c b/libmseed/genutils.c index c8e438b..93a6edf 100644 --- a/libmseed/genutils.c +++ b/libmseed/genutils.c @@ -7,12 +7,13 @@ * ORFEUS/EC-Project MEREDIAN * IRIS Data Management Center * - * modified: 2013.053 + * modified: 2015.061 ***************************************************************************/ #include #include #include +#include #include #include "lmplatform.h" @@ -24,6 +25,10 @@ static hptime_t ms_time2hptime_int (int year, int day, int hour, static struct tm *ms_gmtime_r (int64_t *timep, struct tm *result); +/* Global variable to hold a leap second list */ +LeapSecond *leapsecondlist = NULL; + + /*************************************************************************** * ms_recsrcname: * @@ -1114,6 +1119,140 @@ ms_nomsamprate (int factor, int multiplier) } /* End of ms_nomsamprate() */ +/*************************************************************************** + * ms_readleapseconds: + * + * Read leap seconds from a file indicated by the specified + * environment variable and populate the global leapsecondlist. + * + * Returns positive number of leap seconds read, -1 on file read + * error, and -2 when the environment variable is not set. + ***************************************************************************/ +int +ms_readleapseconds (char *envvarname) +{ + char *filename; + + if ( (filename = getenv(envvarname)) ) + { + return ms_readleapsecondfile (filename); + } + + return -2; +} /* End of ms_readleapseconds() */ + + +/*************************************************************************** + * ms_readleapsecondfile: + * + * Read leap seconds from the specified file and populate the global + * leapsecondlist. The file is expected to be standard IETF leap + * second list format. The list is usually available from: + * http://www.ietf.org/timezones/data/leap-seconds.list + * + * Returns positive number of leap seconds read on success and -1 on error. + ***************************************************************************/ +int +ms_readleapsecondfile (char *filename) +{ + FILE *fp = NULL; + LeapSecond *ls = NULL; + LeapSecond *lastls = NULL; + long long int expires; + char readline[200]; + char *cp; + long long int leapsecond; + int TAIdelta; + int fields; + int count = 0; + + if ( ! filename ) + return -1; + + if ( ! (fp = fopen(filename, "rb")) ) + { + ms_log (2, "Cannot open file %s: %s\n", filename, strerror(errno)); + return -1; + } + + while ( fgets (readline, sizeof(readline)-1, fp) ) + { + /* Guarantee termination */ + readline[sizeof(readline)-1] = '\0'; + + /* Terminate string at first newline character if any */ + if ( (cp = strchr(readline, '\n')) ) + *cp = '\0'; + + /* Skip empty lines */ + if ( ! strlen (readline) ) + continue; + + /* Check for and parse expiration date */ + if ( ! strncmp (readline, "#@", 2) ) + { + expires = 0; + fields = sscanf (readline, "#@ %lld", &expires); + + if ( fields == 1 ) + { + /* Convert expires to Unix epoch */ + expires = expires - 2208988800; + + /* Compare expire time to current time */ + if ( time(NULL) > expires ) + { + char timestr[100]; + ms_hptime2mdtimestr (MS_EPOCH2HPTIME(expires), timestr, 0); + ms_log (1, "Warning: leap second file (%s) has expired as of %s\n", + filename, timestr); + } + } + + continue; + } + + /* Skip comment lines */ + if ( *readline == '#' ) + continue; + + fields = sscanf (readline, "%lld %d ", &leapsecond, &TAIdelta); + + if ( fields == 2 ) + { + if ( (ls = malloc (sizeof(LeapSecond))) == NULL ) + { + ms_log (2, "Cannot allocate LeapSecond, out of memory?\n"); + return -1; + } + + /* Convert NTP epoch time to Unix epoch time and then to HPT */ + ls->leapsecond = MS_EPOCH2HPTIME( (leapsecond - 2208988800) ); + ls->TAIdelta = TAIdelta; + ls->next = NULL; + + /* Add leap second to global list */ + if ( ! leapsecondlist ) + { + leapsecondlist = ls; + lastls = ls; + } + else + { + lastls->next = ls; + lastls = ls; + } + } + else + { + ms_log (1, "Unrecognized leap second file line: '%s'\n", readline); + } + } + + return count; +} /* End of ms_readleapsecondfile() */ + + /*************************************************************************** * ms_genfactmult: * @@ -1232,7 +1371,7 @@ ms_ratapprox (double real, int *num, int *den, int maxval, double precision) * Returns 0 if the host is little endian, otherwise 1. ***************************************************************************/ int -ms_bigendianhost () +ms_bigendianhost (void) { int16_t host = 1; return !(*((int8_t *)(&host))); diff --git a/libmseed/gswap.c b/libmseed/gswap.c index ecb6a3e..ddccfbc 100644 --- a/libmseed/gswap.c +++ b/libmseed/gswap.c @@ -1,7 +1,7 @@ /*************************************************************************** * gswap.c: * - * Functions for generalized, in-pace byte swapping between LSBF and + * Functions for generalized, in-place byte swapping between LSBF and * MSBF byte orders. * * Some standard integer types are needed, namely uint8_t and diff --git a/libmseed/libmseed.h b/libmseed/libmseed.h index 16b0a08..b28ca52 100644 --- a/libmseed/libmseed.h +++ b/libmseed/libmseed.h @@ -30,10 +30,11 @@ extern "C" { #include "lmplatform.h" -#define LIBMSEED_VERSION "2.10" -#define LIBMSEED_RELEASE "2013.056" +#define LIBMSEED_VERSION "2.14" +#define LIBMSEED_RELEASE "2015.062" -#define MINRECLEN 256 /* Minimum Mini-SEED record length, 2^8 bytes */ +#define MINRECLEN 128 /* Minimum Mini-SEED record length, 2^7 bytes */ + /* Note: the SEED specification minimum is 256 */ #define MAXRECLEN 1048576 /* Maximum Mini-SEED record length, 2^20 bytes */ /* SEED data encoding types */ @@ -106,18 +107,18 @@ extern "C" { * Usage: * MS_ISVALIDHEADER ((char *)X) X buffer must contain at least 27 bytes */ -#define MS_ISVALIDHEADER(X) ( \ - (isdigit ((unsigned char) *(X)) || *(X) == ' ' || !*(X) ) && \ - (isdigit ((unsigned char) *(X+1)) || *(X+1) == ' ' || !*(X+1) ) && \ - (isdigit ((unsigned char) *(X+2)) || *(X+2) == ' ' || !*(X+2) ) && \ - (isdigit ((unsigned char) *(X+3)) || *(X+3) == ' ' || !*(X+3) ) && \ - (isdigit ((unsigned char) *(X+4)) || *(X+4) == ' ' || !*(X+4) ) && \ - (isdigit ((unsigned char) *(X+5)) || *(X+5) == ' ' || !*(X+5) ) && \ - MS_ISDATAINDICATOR(*(X+6)) && \ - (*(X+7) == ' ' || *(X+7) == '\0') && \ - (int)(*(X+24)) >= 0 && (int)(*(X+24)) <= 23 && \ - (int)(*(X+25)) >= 0 && (int)(*(X+25)) <= 59 && \ - (int)(*(X+26)) >= 0 && (int)(*(X+26)) <= 60) +#define MS_ISVALIDHEADER(X) ( \ + (isdigit ((int) *(X)) || *(X) == ' ' || !*(X) ) && \ + (isdigit ((int) *(X+1)) || *(X+1) == ' ' || !*(X+1) ) && \ + (isdigit ((int) *(X+2)) || *(X+2) == ' ' || !*(X+2) ) && \ + (isdigit ((int) *(X+3)) || *(X+3) == ' ' || !*(X+3) ) && \ + (isdigit ((int) *(X+4)) || *(X+4) == ' ' || !*(X+4) ) && \ + (isdigit ((int) *(X+5)) || *(X+5) == ' ' || !*(X+5) ) && \ + MS_ISDATAINDICATOR(*(X+6)) && \ + (*(X+7) == ' ' || *(X+7) == '\0') && \ + (int)(*(X+24)) >= 0 && (int)(*(X+24)) <= 23 && \ + (int)(*(X+25)) >= 0 && (int)(*(X+25)) <= 59 && \ + (int)(*(X+26)) >= 0 && (int)(*(X+26)) <= 60 ) /* Macro to test memory for a blank/noise SEED data record signature * by checking for a valid SEED sequence number and padding characters @@ -130,26 +131,27 @@ extern "C" { * Usage: * MS_ISVALIDBLANK ((char *)X) X buffer must contain at least 27 bytes */ -#define MS_ISVALIDBLANK(X) ((isdigit ((unsigned char) *(X)) || !*(X) ) && \ - (isdigit ((unsigned char) *(X+1)) || !*(X+1) ) && \ - (isdigit ((unsigned char) *(X+2)) || !*(X+2) ) && \ - (isdigit ((unsigned char) *(X+3)) || !*(X+3) ) && \ - (isdigit ((unsigned char) *(X+4)) || !*(X+4) ) && \ - (isdigit ((unsigned char) *(X+5)) || !*(X+5) ) && \ - (*(X+6)==' ')&&(*(X+7)==' ')&&(*(X+8)==' ') && \ - (*(X+9)==' ')&&(*(X+10)==' ')&&(*(X+11)==' ') && \ - (*(X+12)==' ')&&(*(X+13)==' ')&&(*(X+14)==' ') && \ - (*(X+15)==' ')&&(*(X+16)==' ')&&(*(X+17)==' ') && \ - (*(X+18)==' ')&&(*(X+19)==' ')&&(*(X+20)==' ') && \ - (*(X+21)==' ')&&(*(X+22)==' ')&&(*(X+23)==' ') && \ - (*(X+24)==' ')&&(*(X+25)==' ')&&(*(X+26)==' ') && \ - (*(X+27)==' ')&&(*(X+28)==' ')&&(*(X+29)==' ') && \ - (*(X+30)==' ')&&(*(X+31)==' ')&&(*(X+32)==' ') && \ - (*(X+33)==' ')&&(*(X+34)==' ')&&(*(X+35)==' ') && \ - (*(X+36)==' ')&&(*(X+37)==' ')&&(*(X+38)==' ') && \ - (*(X+39)==' ')&&(*(X+40)==' ')&&(*(X+41)==' ') && \ - (*(X+42)==' ')&&(*(X+43)==' ')&&(*(X+44)==' ') && \ - (*(X+45)==' ')&&(*(X+46)==' ')&&(*(X+47)==' ') ) +#define MS_ISVALIDBLANK(X) ( \ + (isdigit ((int) *(X)) || !*(X) ) && \ + (isdigit ((int) *(X+1)) || !*(X+1) ) && \ + (isdigit ((int) *(X+2)) || !*(X+2) ) && \ + (isdigit ((int) *(X+3)) || !*(X+3) ) && \ + (isdigit ((int) *(X+4)) || !*(X+4) ) && \ + (isdigit ((int) *(X+5)) || !*(X+5) ) && \ + (*(X+6) ==' ') && (*(X+7) ==' ') && (*(X+8) ==' ') && \ + (*(X+9) ==' ') && (*(X+10)==' ') && (*(X+11)==' ') && \ + (*(X+12)==' ') && (*(X+13)==' ') && (*(X+14)==' ') && \ + (*(X+15)==' ') && (*(X+16)==' ') && (*(X+17)==' ') && \ + (*(X+18)==' ') && (*(X+19)==' ') && (*(X+20)==' ') && \ + (*(X+21)==' ') && (*(X+22)==' ') && (*(X+23)==' ') && \ + (*(X+24)==' ') && (*(X+25)==' ') && (*(X+26)==' ') && \ + (*(X+27)==' ') && (*(X+28)==' ') && (*(X+29)==' ') && \ + (*(X+30)==' ') && (*(X+31)==' ') && (*(X+32)==' ') && \ + (*(X+33)==' ') && (*(X+34)==' ') && (*(X+35)==' ') && \ + (*(X+36)==' ') && (*(X+37)==' ') && (*(X+38)==' ') && \ + (*(X+39)==' ') && (*(X+40)==' ') && (*(X+41)==' ') && \ + (*(X+42)==' ') && (*(X+43)==' ') && (*(X+44)==' ') && \ + (*(X+45)==' ') && (*(X+46)==' ') && (*(X+47)==' ') ) /* A simple bitwise AND test to return 0 or 1 */ #define bit(x,y) (x&y)?1:0 @@ -575,6 +577,7 @@ extern MSTrace* mst_addmsrtogroup (MSTraceGroup *mstg, MSRecord *msr, flag extern MSTrace* mst_addtracetogroup (MSTraceGroup *mstg, MSTrace *mst); extern int mst_groupheal (MSTraceGroup *mstg, double timetol, double sampratetol); extern int mst_groupsort (MSTraceGroup *mstg, flag quality); +extern int mst_convertsamples (MSTrace *mst, char type, flag truncate); extern char * mst_srcname (MSTrace *mst, char *srcname, flag quality); extern void mst_printtracelist (MSTraceGroup *mstg, flag timeformat, flag details, flag gaps); @@ -595,6 +598,7 @@ extern MSTraceList * mstl_init ( MSTraceList *mstl ); extern void mstl_free ( MSTraceList **ppmstl, flag freeprvtptr ); extern MSTraceSeg * mstl_addmsr ( MSTraceList *mstl, MSRecord *msr, flag dataquality, flag autoheal, double timetol, double sampratetol ); +extern int mstl_convertsamples ( MSTraceSeg *seg, char type, flag truncate ); extern void mstl_printtracelist ( MSTraceList *mstl, flag timeformat, flag details, flag gaps ); extern void mstl_printsynclist ( MSTraceList *mstl, char *dccid, flag subsecond ); @@ -616,30 +620,30 @@ typedef struct MSFileParam_s int recordcount; } MSFileParam; -extern int ms_readmsr (MSRecord **ppmsr, char *msfile, int reclen, off_t *fpos, int *last, +extern int ms_readmsr (MSRecord **ppmsr, const char *msfile, int reclen, off_t *fpos, int *last, flag skipnotdata, flag dataflag, flag verbose); -extern int ms_readmsr_r (MSFileParam **ppmsfp, MSRecord **ppmsr, char *msfile, int reclen, +extern int ms_readmsr_r (MSFileParam **ppmsfp, MSRecord **ppmsr, const char *msfile, int reclen, off_t *fpos, int *last, flag skipnotdata, flag dataflag, flag verbose); -extern int ms_readmsr_main (MSFileParam **ppmsfp, MSRecord **ppmsr, char *msfile, int reclen, +extern int ms_readmsr_main (MSFileParam **ppmsfp, MSRecord **ppmsr, const char *msfile, int reclen, off_t *fpos, int *last, flag skipnotdata, flag dataflag, Selections *selections, flag verbose); -extern int ms_readtraces (MSTraceGroup **ppmstg, char *msfile, int reclen, double timetol, double sampratetol, +extern int ms_readtraces (MSTraceGroup **ppmstg, const char *msfile, int reclen, double timetol, double sampratetol, flag dataquality, flag skipnotdata, flag dataflag, flag verbose); -extern int ms_readtraces_timewin (MSTraceGroup **ppmstg, char *msfile, int reclen, double timetol, double sampratetol, +extern int ms_readtraces_timewin (MSTraceGroup **ppmstg, const char *msfile, int reclen, double timetol, double sampratetol, hptime_t starttime, hptime_t endtime, flag dataquality, flag skipnotdata, flag dataflag, flag verbose); -extern int ms_readtraces_selection (MSTraceGroup **ppmstg, char *msfile, int reclen, double timetol, double sampratetol, +extern int ms_readtraces_selection (MSTraceGroup **ppmstg, const char *msfile, int reclen, double timetol, double sampratetol, Selections *selections, flag dataquality, flag skipnotdata, flag dataflag, flag verbose); -extern int ms_readtracelist (MSTraceList **ppmstl, char *msfile, int reclen, double timetol, double sampratetol, +extern int ms_readtracelist (MSTraceList **ppmstl, const char *msfile, int reclen, double timetol, double sampratetol, flag dataquality, flag skipnotdata, flag dataflag, flag verbose); -extern int ms_readtracelist_timewin (MSTraceList **ppmstl, char *msfile, int reclen, double timetol, double sampratetol, +extern int ms_readtracelist_timewin (MSTraceList **ppmstl, const char *msfile, int reclen, double timetol, double sampratetol, hptime_t starttime, hptime_t endtime, flag dataquality, flag skipnotdata, flag dataflag, flag verbose); -extern int ms_readtracelist_selection (MSTraceList **ppmstl, char *msfile, int reclen, double timetol, double sampratetol, +extern int ms_readtracelist_selection (MSTraceList **ppmstl, const char *msfile, int reclen, double timetol, double sampratetol, Selections *selections, flag dataquality, flag skipnotdata, flag dataflag, flag verbose); -extern int msr_writemseed ( MSRecord *msr, char *msfile, flag overwrite, int reclen, +extern int msr_writemseed ( MSRecord *msr, const char *msfile, flag overwrite, int reclen, flag encoding, flag byteorder, flag verbose ); -extern int mst_writemseed ( MSTrace *mst, char *msfile, flag overwrite, int reclen, +extern int mst_writemseed ( MSTrace *mst, const char *msfile, flag overwrite, int reclen, flag encoding, flag byteorder, flag verbose ); -extern int mst_writemseedgroup ( MSTraceGroup *mstg, char *msfile, flag overwrite, +extern int mst_writemseedgroup ( MSTraceGroup *mstg, const char *msfile, flag overwrite, int reclen, flag encoding, flag byteorder, flag verbose ); /* General use functions */ @@ -664,7 +668,7 @@ extern hptime_t ms_timestr2hptime (char *timestr); extern double ms_nomsamprate (int factor, int multiplier); extern int ms_genfactmult (double samprate, int16_t *factor, int16_t *multiplier); extern int ms_ratapprox (double real, int *num, int *den, int maxval, double precision); -extern int ms_bigendianhost (); +extern int ms_bigendianhost (void); extern double ms_dabs (double val); @@ -681,9 +685,9 @@ extern char * ms_errorstr (int errorcode); /* Logging parameters */ typedef struct MSLogParam_s { - void (*log_print)(); + void (*log_print)(char*); const char *logprefix; - void (*diag_print)(); + void (*diag_print)(char*); const char *errprefix; } MSLogParam; @@ -707,6 +711,18 @@ extern int ms_readselectionsfile (Selections **ppselections, char *filename extern void ms_freeselections (Selections *selections); extern void ms_printselections (Selections *selections); +/* Leap second declarations, implementation in gentutils.c */ +typedef struct LeapSecond_s +{ + hptime_t leapsecond; + int32_t TAIdelta; + struct LeapSecond_s *next; +} LeapSecond; + +extern LeapSecond *leapsecondlist; +extern int ms_readleapseconds (char *envvarname); +extern int ms_readleapsecondfile (char *filename); + /* Generic byte swapping routines */ extern void ms_gswap2 ( void *data2 ); extern void ms_gswap3 ( void *data3 ); diff --git a/libmseed/lmplatform.h b/libmseed/lmplatform.h index f61b6a9..fb4d5bc 100644 --- a/libmseed/lmplatform.h +++ b/libmseed/lmplatform.h @@ -18,7 +18,7 @@ * * Written by Chad Trabant, IRIS Data Management Center * - * modified: 2012.138 + * modified: 2014.074 ***************************************************************************/ #ifndef LMPLATFORM_H @@ -52,7 +52,7 @@ extern "C" { * WIN32 => WIN32 and Windows Sockets 2 (LMP_WIN32) */ -#if defined(__linux__) || defined(__linux) +#if defined(__linux__) || defined(__linux) || defined(__CYGWIN__) #define LMP_GLIBC2 1 #include diff --git a/libmseed/logging.c b/libmseed/logging.c index 60039d0..cfa14fa 100644 --- a/libmseed/logging.c +++ b/libmseed/logging.c @@ -6,7 +6,7 @@ * Chad Trabant * IRIS Data Management Center * - * modified: 2010.253 + * modified: 2014.197 ***************************************************************************/ #include @@ -95,7 +95,7 @@ ms_loginit_l (MSLogParam *logp, * This function modifies the logging parameters in the passed MSLogParam. * * Any log/error printing functions indicated must except a single - * argument, namely a string (const char *). The ms_log() and + * argument, namely a string (char *). The ms_log() and * ms_log_r() functions format each message and then pass the result * on to the log/error printing functions. * @@ -221,7 +221,7 @@ ms_log_l (MSLogParam *logp, int level, ...) * 2+ : Error messagess, printed using diag_print with errprefix * * This function builds the log/error message and passes to it as a - * string (const char *) to the functions defined with ms_loginit() or + * string (char *) to the functions defined with ms_loginit() or * ms_loginit_l(). If the log/error printing functions have not been * defined messages will be printed with fprintf, log messages to * stdout and error messages to stderr. @@ -258,6 +258,7 @@ ms_log_main (MSLogParam *logp, int level, va_list *varlist) if ( logp->errprefix != NULL ) { strncpy (message, logp->errprefix, MAX_LOG_MSG_LENGTH); + message[MAX_LOG_MSG_LENGTH - 1] = '\0'; } else { @@ -273,7 +274,7 @@ ms_log_main (MSLogParam *logp, int level, va_list *varlist) if ( logp->diag_print != NULL ) { - logp->diag_print ((const char *) message); + logp->diag_print (message); } else { @@ -285,6 +286,7 @@ ms_log_main (MSLogParam *logp, int level, va_list *varlist) if ( logp->logprefix != NULL ) { strncpy (message, logp->logprefix, MAX_LOG_MSG_LENGTH); + message[MAX_LOG_MSG_LENGTH - 1] = '\0'; } presize = strlen(message); @@ -296,7 +298,7 @@ ms_log_main (MSLogParam *logp, int level, va_list *varlist) if ( logp->diag_print != NULL ) { - logp->diag_print ((const char *) message); + logp->diag_print (message); } else { @@ -308,6 +310,7 @@ ms_log_main (MSLogParam *logp, int level, va_list *varlist) if ( logp->logprefix != NULL ) { strncpy (message, logp->logprefix, MAX_LOG_MSG_LENGTH); + message[MAX_LOG_MSG_LENGTH - 1] = '\0'; } presize = strlen(message); @@ -319,7 +322,7 @@ ms_log_main (MSLogParam *logp, int level, va_list *varlist) if ( logp->log_print != NULL ) { - logp->log_print ((const char *) message); + logp->log_print (message); } else { diff --git a/libmseed/msrutils.c b/libmseed/msrutils.c index 14ce72d..1865f67 100644 --- a/libmseed/msrutils.c +++ b/libmseed/msrutils.c @@ -597,13 +597,39 @@ hptime_t msr_endtime (MSRecord *msr) { hptime_t span = 0; + LeapSecond *lslist = leapsecondlist; if ( ! msr ) return HPTERROR; - + if ( msr->samprate > 0.0 && msr->samplecnt > 0 ) span = (hptime_t)(((double) (msr->samplecnt - 1) / msr->samprate * HPTMODULUS) + 0.5); + /* Check if the record contains a leap second, if list is available */ + if ( lslist ) + { + while ( lslist ) + { + if ( lslist->leapsecond > msr->starttime && + lslist->leapsecond < (msr->starttime + span) ) + { + span -= HPTMODULUS; + break; + } + + lslist = lslist->next; + } + } + else + { + /* If a positive leap second occurred during this record as denoted by + * bit 4 of the activity flags being set, reduce the end time to match + * the now shifted UTC time. */ + if ( msr->fsdh ) + if ( msr->fsdh->act_flags & 0x10 ) + span -= HPTMODULUS; + } + return (msr->starttime + span); } /* End of msr_endtime() */ diff --git a/libmseed/pack.c b/libmseed/pack.c index ee9c1df..a64e171 100644 --- a/libmseed/pack.c +++ b/libmseed/pack.c @@ -7,7 +7,7 @@ * Written by Chad Trabant, * IRIS Data Management Center * - * modified: 2012.090 + * modified: 2015.062 ***************************************************************************/ #include @@ -279,6 +279,7 @@ msr_pack ( MSRecord * msr, void (*record_handler) (char *, int, void *), if ( ! msr_addblockette (msr, (char *) &blkt1000, sizeof(struct blkt_1000_s), 1000, 0) ) { ms_log (2, "msr_pack(%s): Error adding 1000 Blockette\n", PACK_SRCNAME); + free (rawrec); return -1; } } @@ -288,6 +289,7 @@ msr_pack ( MSRecord * msr, void (*record_handler) (char *, int, void *), if ( headerlen == -1 ) { ms_log (2, "msr_pack(%s): Error packing header\n", PACK_SRCNAME); + free (rawrec); return -1; } @@ -342,6 +344,7 @@ msr_pack ( MSRecord * msr, void (*record_handler) (char *, int, void *), if ( packret ) { ms_log (2, "msr_pack(%s): Error packing record\n", PACK_SRCNAME); + free (rawrec); return -1; } @@ -553,7 +556,7 @@ msr_pack_header_raw ( MSRecord *msr, char *rawrec, int maxheaderlen, return -1; } - if ( maxheaderlen < sizeof(struct fsdh_s) ) + if ( maxheaderlen < (int)sizeof(struct fsdh_s) ) { ms_log (2, "msr_pack_header_raw(%s): maxheaderlen of %d is too small, must be >= %d\n", PACK_SRCNAME, maxheaderlen, sizeof(struct fsdh_s)); diff --git a/libmseed/parseutils.c b/libmseed/parseutils.c index b087c2a..0284169 100644 --- a/libmseed/parseutils.c +++ b/libmseed/parseutils.c @@ -5,7 +5,7 @@ * Written by Chad Trabant * IRIS Data Management Center * - * modified: 2013.050 + * modified: 2014.248 ***************************************************************************/ #include @@ -75,7 +75,7 @@ msr_parse ( char *record, int recbuflen, MSRecord **ppmsr, int reclen, /* Found record but could not determine length */ if ( detlen == 0 ) { - return 256; + return MINRECLEN; } if ( verbose > 2 ) @@ -164,14 +164,14 @@ msr_parse_selection ( char *recbuf, int recbuflen, int64_t *offset, while ( *offset < recbuflen ) { - retval = msr_parse (recbuf+*offset, recbuflen-*offset, ppmsr, reclen, 0, verbose); + retval = msr_parse (recbuf+*offset, (int)(recbuflen-*offset), ppmsr, reclen, 0, verbose); if ( retval ) { if ( verbose ) ms_log (2, "Error parsing record at offset %lld\n", *offset); - *offset += 256; + *offset += MINRECLEN; } else { @@ -218,9 +218,9 @@ msr_parse_selection ( char *recbuf, int recbuflen, int64_t *offset, * * 2) search the record up to recbuflen bytes for a 1000 blockette. * - * 3) If no blockette 1000 is found search at 256-byte offsets for the - * fixed section of the next header or blank/noise record, thereby - * implying the record length. + * 3) If no blockette 1000 is found search at MINRECLEN-byte offsets + * for the fixed section of the next header or blank/noise record, + * thereby implying the record length. * * Returns: * -1 : data record not detected or error @@ -303,9 +303,9 @@ ms_detect ( const char *record, int recbuflen ) * and search for the next record */ if ( reclen == -1 ) { - nextfsdh = record + 256; + nextfsdh = record + MINRECLEN; - /* Check for record header or blank/noise record at 256 byte offsets */ + /* Check for record header or blank/noise record at MINRECLEN byte offsets */ while ( ((nextfsdh - record) + 48) < recbuflen ) { if ( MS_ISVALIDHEADER(nextfsdh) || MS_ISVALIDBLANK(nextfsdh) ) @@ -315,7 +315,7 @@ ms_detect ( const char *record, int recbuflen ) break; } - nextfsdh += 256; + nextfsdh += MINRECLEN; } } @@ -411,9 +411,9 @@ ms_parse_raw ( char *record, int maxreclen, flag details, flag swapflag ) X = record; /* Pointer of convenience */ /* Check record sequence number, 6 ASCII digits */ - if ( ! isdigit((unsigned char) *(X)) || ! isdigit ((unsigned char) *(X+1)) || - ! isdigit((unsigned char) *(X+2)) || ! isdigit ((unsigned char) *(X+3)) || - ! isdigit((unsigned char) *(X+4)) || ! isdigit ((unsigned char) *(X+5)) ) + if ( ! isdigit((int) *(X)) || ! isdigit ((int) *(X+1)) || + ! isdigit((int) *(X+2)) || ! isdigit ((int) *(X+3)) || + ! isdigit((int) *(X+4)) || ! isdigit ((int) *(X+5)) ) { ms_log (2, "%s: Invalid sequence number: '%c%c%c%c%c%c'\n", srcname, X, X+1, X+2, X+3, X+4, X+5); retval++; diff --git a/libmseed/selection.c b/libmseed/selection.c index e5dc985..4f150f1 100644 --- a/libmseed/selection.c +++ b/libmseed/selection.c @@ -6,7 +6,7 @@ * Written by Chad Trabant unless otherwise noted * IRIS Data Management Center * - * modified: 2010.068 + * modified: 2014.197 ***************************************************************************/ #include @@ -140,6 +140,7 @@ ms_addselect (Selections **ppselections, char *srcname, } strncpy (newsl->srcname, srcname, sizeof(newsl->srcname)); + newsl->srcname[sizeof(newsl->srcname) - 1] = '\0'; /* Add new Selections struct as first in list */ *ppselections = newsl; @@ -178,6 +179,7 @@ ms_addselect (Selections **ppselections, char *srcname, } strncpy (newsl->srcname, srcname, sizeof(newsl->srcname)); + newsl->srcname[sizeof(newsl->srcname) - 1] = '\0'; /* Add new Selections to beginning of list */ newsl->next = *ppselections; diff --git a/libmseed/tracelist.c b/libmseed/tracelist.c index d99272c..735daaa 100644 --- a/libmseed/tracelist.c +++ b/libmseed/tracelist.c @@ -5,7 +5,7 @@ * * Written by Chad Trabant, IRIS Data Management Center * - * modified: 2012.105 + * modified: 2014.248 ***************************************************************************/ #include @@ -686,7 +686,7 @@ mstl_addmsrtoseg (MSTraceSeg *seg, MSRecord *msr, hptime_t endtime, flag whence) return 0; } - if ( ! (newdatasamples = realloc (seg->datasamples, (size_t)((seg->numsamples + msr->numsamples) * samplesize))) ) + if ( ! (newdatasamples = realloc (seg->datasamples, (size_t) ((seg->numsamples + msr->numsamples) * samplesize))) ) { ms_log (2, "mstl_addmsrtoseg(): Error allocating memory\n"); return 0; @@ -797,6 +797,149 @@ mstl_addsegtoseg (MSTraceSeg *seg1, MSTraceSeg *seg2) } /* End of mstl_addsegtoseg() */ +/*************************************************************************** + * mstl_convertsamples: + * + * Convert the data samples associated with an MSTraceSeg to another + * data type. ASCII data samples cannot be converted, if supplied or + * requested an error will be returned. + * + * When converting float & double sample types to integer type a + * simple rounding is applied by adding 0.5 to the sample value before + * converting (truncating) to integer. + * + * If the truncate flag is true data samples will be truncated to + * integers even if loss of sample precision is detected. If the + * truncate flag is false (0) and loss of precision is detected an + * error is returned. + * + * Returns 0 on success, and -1 on failure. + ***************************************************************************/ +int +mstl_convertsamples ( MSTraceSeg *seg, char type, flag truncate ) +{ + int32_t *idata; + float *fdata; + double *ddata; + int64_t idx; + + if ( ! seg ) + return -1; + + /* No conversion necessary, report success */ + if ( seg->sampletype == type ) + return 0; + + if ( seg->sampletype == 'a' || type == 'a' ) + { + ms_log (2, "mstl_convertsamples: cannot convert ASCII samples to/from numeric type\n"); + return -1; + } + + idata = (int32_t *) seg->datasamples; + fdata = (float *) seg->datasamples; + ddata = (double *) seg->datasamples; + + /* Convert to 32-bit integers */ + if ( type == 'i' ) + { + if ( seg->sampletype == 'f' ) /* Convert floats to integers with simple rounding */ + { + for (idx = 0; idx < seg->numsamples; idx++) + { + /* Check for loss of sub-integer */ + if ( ! truncate && (fdata[idx] - (int32_t)fdata[idx]) > 0.000001 ) + { + ms_log (1, "mstl_convertsamples: Warning, loss of precision when converting floats to integers, loss: %g\n", + (fdata[idx] - (int32_t)fdata[idx])); + return -1; + } + + idata[idx] = (int32_t) (fdata[idx] + 0.5); + } + } + else if ( seg->sampletype == 'd' ) /* Convert doubles to integers with simple rounding */ + { + for (idx = 0; idx < seg->numsamples; idx++) + { + /* Check for loss of sub-integer */ + if ( ! truncate && (ddata[idx] - (int32_t)ddata[idx]) > 0.000001 ) + { + ms_log (1, "mstl_convertsamples: Warning, loss of precision when converting doubles to integers, loss: %g\n", + (ddata[idx] - (int32_t)ddata[idx])); + return -1; + } + + idata[idx] = (int32_t) (ddata[idx] + 0.5); + } + + /* Reallocate buffer for reduced size needed */ + if ( ! (seg->datasamples = realloc (seg->datasamples, (size_t) (seg->numsamples * sizeof(int32_t)))) ) + { + ms_log (2, "mstl_convertsamples: cannot re-allocate buffer for sample conversion\n"); + return -1; + } + } + + seg->sampletype = 'i'; + } /* Done converting to 32-bit integers */ + + /* Convert to 32-bit floats */ + else if ( type == 'f' ) + { + if ( seg->sampletype == 'i' ) /* Convert integers to floats */ + { + for (idx = 0; idx < seg->numsamples; idx++) + fdata[idx] = (float) idata[idx]; + } + else if ( seg->sampletype == 'd' ) /* Convert doubles to floats */ + { + for (idx = 0; idx < seg->numsamples; idx++) + fdata[idx] = (float) ddata[idx]; + + /* Reallocate buffer for reduced size needed */ + if ( ! (seg->datasamples = realloc (seg->datasamples, (size_t) (seg->numsamples * sizeof(float)))) ) + { + ms_log (2, "mstl_convertsamples: cannot re-allocate buffer after sample conversion\n"); + return -1; + } + } + + seg->sampletype = 'f'; + } /* Done converting to 32-bit floats */ + + /* Convert to 64-bit doubles */ + else if ( type == 'd' ) + { + if ( ! (ddata = (double *) malloc ((size_t) (seg->numsamples * sizeof(double)))) ) + { + ms_log (2, "mstl_convertsamples: cannot allocate buffer for sample conversion to doubles\n"); + return -1; + } + + if ( seg->sampletype == 'i' ) /* Convert integers to doubles */ + { + for (idx = 0; idx < seg->numsamples; idx++) + ddata[idx] = (double) idata[idx]; + + free (idata); + } + else if ( seg->sampletype == 'f' ) /* Convert floats to doubles */ + { + for (idx = 0; idx < seg->numsamples; idx++) + ddata[idx] = (double) fdata[idx]; + + free (fdata); + } + + seg->datasamples = ddata; + seg->sampletype = 'd'; + } /* Done converting to 64-bit doubles */ + + return 0; +} /* End of mstl_convertsamples() */ + + /*************************************************************************** * mstl_printtracelist: * diff --git a/libmseed/traceutils.c b/libmseed/traceutils.c index b94d1ba..80c70ae 100644 --- a/libmseed/traceutils.c +++ b/libmseed/traceutils.c @@ -5,7 +5,7 @@ * * Written by Chad Trabant, IRIS Data Management Center * - * modified: 2012.105 + * modified: 2014.248 ***************************************************************************/ #include @@ -1090,6 +1090,149 @@ mst_groupsort_cmp ( MSTrace *mst1, MSTrace *mst2, flag quality ) } /* End of mst_groupsort_cmp() */ +/*************************************************************************** + * mst_convertsamples: + * + * Convert the data samples associated with an MSTrace to another data + * type. ASCII data samples cannot be converted, if supplied or + * requested an error will be returned. + * + * When converting float & double sample types to integer type a + * simple rounding is applied by adding 0.5 to the sample value before + * converting (truncating) to integer. + * + * If the truncate flag is true data samples will be truncated to + * integers even if loss of sample precision is detected. If the + * truncate flag is false (0) and loss of precision is detected an + * error is returned. + * + * Returns 0 on success, and -1 on failure. + ***************************************************************************/ +int +mst_convertsamples ( MSTrace *mst, char type, flag truncate ) +{ + int32_t *idata; + float *fdata; + double *ddata; + int64_t idx; + + if ( ! mst ) + return -1; + + /* No conversion necessary, report success */ + if ( mst->sampletype == type ) + return 0; + + if ( mst->sampletype == 'a' || type == 'a' ) + { + ms_log (2, "mst_convertsamples: cannot convert ASCII samples to/from numeric type\n"); + return -1; + } + + idata = (int32_t *) mst->datasamples; + fdata = (float *) mst->datasamples; + ddata = (double *) mst->datasamples; + + /* Convert to 32-bit integers */ + if ( type == 'i' ) + { + if ( mst->sampletype == 'f' ) /* Convert floats to integers with simple rounding */ + { + for (idx = 0; idx < mst->numsamples; idx++) + { + /* Check for loss of sub-integer */ + if ( ! truncate && (fdata[idx] - (int32_t)fdata[idx]) > 0.000001 ) + { + ms_log (1, "mst_convertsamples: Warning, loss of precision when converting floats to integers, loss: %g\n", + (fdata[idx] - (int32_t)fdata[idx])); + return -1; + } + + idata[idx] = (int32_t) (fdata[idx] + 0.5); + } + } + else if ( mst->sampletype == 'd' ) /* Convert doubles to integers with simple rounding */ + { + for (idx = 0; idx < mst->numsamples; idx++) + { + /* Check for loss of sub-integer */ + if ( ! truncate && (ddata[idx] - (int32_t)ddata[idx]) > 0.000001 ) + { + ms_log (1, "mst_convertsamples: Warning, loss of precision when converting doubles to integers, loss: %g\n", + (ddata[idx] - (int32_t)ddata[idx])); + return -1; + } + + idata[idx] = (int32_t) (ddata[idx] + 0.5); + } + + /* Reallocate buffer for reduced size needed */ + if ( ! (mst->datasamples = realloc (mst->datasamples, (size_t) (mst->numsamples * sizeof(int32_t)))) ) + { + ms_log (2, "mst_convertsamples: cannot re-allocate buffer for sample conversion\n"); + return -1; + } + } + + mst->sampletype = 'i'; + } /* Done converting to 32-bit integers */ + + /* Convert to 32-bit floats */ + else if ( type == 'f' ) + { + if ( mst->sampletype == 'i' ) /* Convert integers to floats */ + { + for (idx = 0; idx < mst->numsamples; idx++) + fdata[idx] = (float) idata[idx]; + } + else if ( mst->sampletype == 'd' ) /* Convert doubles to floats */ + { + for (idx = 0; idx < mst->numsamples; idx++) + fdata[idx] = (float) ddata[idx]; + + /* Reallocate buffer for reduced size needed */ + if ( ! (mst->datasamples = realloc (mst->datasamples, (size_t) (mst->numsamples * sizeof(float)))) ) + { + ms_log (2, "mst_convertsamples: cannot re-allocate buffer after sample conversion\n"); + return -1; + } + } + + mst->sampletype = 'f'; + } /* Done converting to 32-bit floats */ + + /* Convert to 64-bit doubles */ + else if ( type == 'd' ) + { + if ( ! (ddata = (double *) malloc ((size_t) (mst->numsamples * sizeof(double)))) ) + { + ms_log (2, "mst_convertsamples: cannot allocate buffer for sample conversion to doubles\n"); + return -1; + } + + if ( mst->sampletype == 'i' ) /* Convert integers to doubles */ + { + for (idx = 0; idx < mst->numsamples; idx++) + ddata[idx] = (double) idata[idx]; + + free (idata); + } + else if ( mst->sampletype == 'f' ) /* Convert floats to doubles */ + { + for (idx = 0; idx < mst->numsamples; idx++) + ddata[idx] = (double) fdata[idx]; + + free (fdata); + } + + mst->datasamples = ddata; + mst->sampletype = 'd'; + } /* Done converting to 64-bit doubles */ + + return 0; +} /* End of mst_convertsamples() */ + + /*************************************************************************** * mst_srcname: * @@ -1513,8 +1656,8 @@ mst_pack ( MSTrace *mst, void (*record_handler) (char *, int, void *), { MSRecord *msr; char srcname[50]; - int trpackedrecords; - int64_t trpackedsamples; + int trpackedrecords = 0; + int64_t trpackedsamples = 0; int samplesize; int64_t bufsize; diff --git a/libmseed/unpack.c b/libmseed/unpack.c index 8c8d757..9ac4ebe 100644 --- a/libmseed/unpack.c +++ b/libmseed/unpack.c @@ -13,7 +13,7 @@ * ORFEUS/EC-Project MEREDIAN * IRIS Data Management Center * - * modified: 2013.056 + * modified: 2014.197 ***************************************************************************/ #include #include @@ -172,6 +172,7 @@ msr_unpack ( char *record, int reclen, MSRecord **ppmsr, /* Populate some of the common header fields */ strncpy (sequence_number, msr->fsdh->sequence_number, 6); + sequence_number[6] = '\0'; msr->sequence_number = (int32_t) strtol (sequence_number, NULL, 10); msr->dataquality = msr->fsdh->dataquality; ms_strncpcleantail (msr->network, msr->fsdh->network, 2);