1 /***************************************************************************
4 * Generic routines to manage selection lists.
6 * Written by Chad Trabant unless otherwise noted
7 * IRIS Data Management Center
10 ***************************************************************************/
20 static int ms_globmatch (char *string
, char *pattern
);
23 /***************************************************************************
26 * Test the specified parameters for a matching selection entry. The
27 * srcname parameter may contain globbing characters. The NULL value
28 * (matching any times) for the start and end times is HPTERROR.
30 * Return Selections pointer to matching entry on successful match and
31 * NULL for no match or error.
32 ***************************************************************************/
34 ms_matchselect (Selections
*selections
, char *srcname
, hptime_t starttime
,
35 hptime_t endtime
, SelectTime
**ppselecttime
)
37 Selections
*findsl
= NULL
;
38 SelectTime
*findst
= NULL
;
39 SelectTime
*matchst
= NULL
;
46 if ( ms_globmatch (srcname
, findsl
->srcname
) )
48 findst
= findsl
->timewindows
;
51 if ( starttime
!= HPTERROR
&& findst
->starttime
!= HPTERROR
&&
52 (starttime
< findst
->starttime
&& ! (starttime
<= findst
->starttime
&& endtime
>= findst
->starttime
)) )
53 { findst
= findst
->next
; continue; }
54 else if ( endtime
!= HPTERROR
&& findst
->endtime
!= HPTERROR
&&
55 (endtime
> findst
->endtime
&& ! (starttime
<= findst
->endtime
&& endtime
>= findst
->endtime
)) )
56 { findst
= findst
->next
; continue; }
66 findsl
= findsl
->next
;
71 *ppselecttime
= matchst
;
73 return ( matchst
) ? findsl
: NULL
;
74 } /* End of ms_matchselect() */
77 /***************************************************************************
80 * A simple wrapper for calling ms_matchselect() using details from a
83 * Return Selections pointer to matching entry on successful match and
84 * NULL for no match or error.
85 ***************************************************************************/
87 msr_matchselect (Selections
*selections
, MSRecord
*msr
, SelectTime
**ppselecttime
)
92 if ( ! selections
|| ! msr
)
95 msr_srcname (msr
, srcname
, 1);
96 endtime
= msr_endtime (msr
);
98 return ms_matchselect (selections
, srcname
, msr
->starttime
, endtime
,
100 } /* End of msr_matchselect() */
103 /***************************************************************************
106 * Add select parameters to a specified selection list. The srcname
107 * argument may contain globbing parameters. The NULL value (matching
108 * any value) for the start and end times is HPTERROR.
110 * Return 0 on success and -1 on error.
111 ***************************************************************************/
113 ms_addselect (Selections
**ppselections
, char *srcname
,
114 hptime_t starttime
, hptime_t endtime
)
116 Selections
*newsl
= NULL
;
117 SelectTime
*newst
= NULL
;
119 if ( ! ppselections
|| ! srcname
)
122 /* Allocate new SelectTime and populate */
123 if ( ! (newst
= (SelectTime
*) calloc (1, sizeof(SelectTime
))) )
125 ms_log (2, "Cannot allocate memory\n");
129 newst
->starttime
= starttime
;
130 newst
->endtime
= endtime
;
132 /* Add new Selections struct to begining of list */
133 if ( ! *ppselections
)
135 /* Allocate new Selections and populate */
136 if ( ! (newsl
= (Selections
*) calloc (1, sizeof(Selections
))) )
138 ms_log (2, "Cannot allocate memory\n");
142 strncpy (newsl
->srcname
, srcname
, sizeof(newsl
->srcname
));
143 newsl
->srcname
[sizeof(newsl
->srcname
) - 1] = '\0';
145 /* Add new Selections struct as first in list */
146 *ppselections
= newsl
;
147 newsl
->timewindows
= newst
;
151 Selections
*findsl
= *ppselections
;
152 Selections
*matchsl
= 0;
154 /* Search for matching Selectlink entry */
157 if ( ! strcmp (findsl
->srcname
, srcname
) )
163 findsl
= findsl
->next
;
168 /* Add time window selection to beginning of window list */
169 newst
->next
= matchsl
->timewindows
;
170 matchsl
->timewindows
= newst
;
174 /* Allocate new Selections and populate */
175 if ( ! (newsl
= (Selections
*) calloc (1, sizeof(Selections
))) )
177 ms_log (2, "Cannot allocate memory\n");
181 strncpy (newsl
->srcname
, srcname
, sizeof(newsl
->srcname
));
182 newsl
->srcname
[sizeof(newsl
->srcname
) - 1] = '\0';
184 /* Add new Selections to beginning of list */
185 newsl
->next
= *ppselections
;
186 *ppselections
= newsl
;
187 newsl
->timewindows
= newst
;
192 } /* End of ms_addselect() */
195 /***************************************************************************
198 * Add select parameters to a specified selection list based on
199 * separate name components. The network, station, location, channel
200 * and quality arguments may contain globbing parameters. The NULL
201 * value (matching any value) for the start and end times is HPTERROR.
203 * If any of the naming parameters are not supplied (pointer is NULL)
204 * a wildcard for all matches is substituted. As a special case, if
205 * the location ID (loc) is set to "--" to match a space-space/blank
206 * ID it will be translated to an empty string to match libmseed's
209 * Return 0 on success and -1 on error.
210 ***************************************************************************/
212 ms_addselect_comp (Selections
**ppselections
, char *net
, char* sta
, char *loc
,
213 char *chan
, char *qual
, hptime_t starttime
, hptime_t endtime
)
222 if ( ! ppselections
)
227 strncpy (selnet
, net
, sizeof(selnet
));
228 selnet
[sizeof(selnet
)-1] = '\0';
231 strcpy (selnet
, "*");
235 strncpy (selsta
, sta
, sizeof(selsta
));
236 selsta
[sizeof(selsta
)-1] = '\0';
239 strcpy (selsta
, "*");
243 /* Test for special case blank location ID */
244 if ( ! strcmp (loc
, "--") )
248 strncpy (selloc
, loc
, sizeof(selloc
));
249 selloc
[sizeof(selloc
)-1] = '\0';
253 strcpy (selloc
, "*");
257 strncpy (selchan
, chan
, sizeof(selchan
));
258 selchan
[sizeof(selchan
)-1] = '\0';
261 strcpy (selchan
, "*");
265 strncpy (selqual
, qual
, sizeof(selqual
));
266 selqual
[sizeof(selqual
)-1] = '\0';
269 strcpy (selqual
, "?");
271 /* Create the srcname globbing match for this entry */
272 snprintf (srcname
, sizeof(srcname
), "%s_%s_%s_%s_%s",
273 selnet
, selsta
, selloc
, selchan
, selqual
);
275 /* Add selection to list */
276 if ( ms_addselect (ppselections
, srcname
, starttime
, endtime
) )
280 } /* End of ms_addselect_comp() */
283 /***************************************************************************
284 * ms_readselectionsfile:
286 * Read a list of data selections from a file and them to the
287 * specified selections list. On errors this routine will leave
288 * allocated memory unreachable (leaked), it is expected that this is
289 * a program failing condition.
291 * As a special case if the filename is "-", selection lines will be
294 * Returns count of selections added on success and -1 on error.
295 ***************************************************************************/
297 ms_readselectionsfile (Selections
**ppselections
, char *filename
)
302 char selectline
[200];
315 if ( ! ppselections
|| ! filename
)
318 if ( strcmp (filename
, "-" ) )
320 if ( ! (fp
= fopen(filename
, "rb")) )
322 ms_log (2, "Cannot open file %s: %s\n", filename
, strerror(errno
));
328 /* Use stdin as special case */
332 while ( fgets (selectline
, sizeof(selectline
)-1, fp
) )
344 /* Guarantee termination */
345 selectline
[sizeof(selectline
)-1] = '\0';
347 /* End string at first newline character if any */
348 if ( (cp
= strchr(selectline
, '\n')) )
351 /* Skip empty lines */
352 if ( ! strlen (selectline
) )
355 /* Skip comment lines */
356 if ( *selectline
== '#' )
359 /* Parse: identify components of selection and terminate */
364 if ( *cp
== ' ' || *cp
== '\t' ) { *cp
= '\0'; next
= 1; }
365 else if ( *cp
== '#' ) { *cp
= '\0'; break; }
366 else if ( next
&& ! selnet
) { selnet
= cp
; next
= 0; }
367 else if ( next
&& ! selsta
) { selsta
= cp
; next
= 0; }
368 else if ( next
&& ! selloc
) { selloc
= cp
; next
= 0; }
369 else if ( next
&& ! selchan
) { selchan
= cp
; next
= 0; }
370 else if ( next
&& ! selqual
) { selqual
= cp
; next
= 0; }
371 else if ( next
&& ! selstart
) { selstart
= cp
; next
= 0; }
372 else if ( next
&& ! selend
) { selend
= cp
; next
= 0; }
373 else if ( next
) { *cp
= '\0'; break; }
377 /* Skip line if network, station, location and channel are not defined */
378 if ( ! selnet
|| ! selsta
|| ! selloc
|| ! selchan
)
380 ms_log (2, "[%s] Skipping data selection line number %d\n", filename
, linecount
);
386 starttime
= ms_seedtimestr2hptime (selstart
);
387 if ( starttime
== HPTERROR
)
389 ms_log (2, "Cannot convert data selection start time (line %d): %s\n", linecount
, selstart
);
395 starttime
= HPTERROR
;
400 endtime
= ms_seedtimestr2hptime (selend
);
401 if ( endtime
== HPTERROR
)
403 ms_log (2, "Cannot convert data selection end time (line %d): %s\n", linecount
, selend
);
412 /* Add selection to list */
413 if ( ms_addselect_comp (ppselections
, selnet
, selsta
, selloc
, selchan
, selqual
, starttime
, endtime
) )
415 ms_log (2, "[%s] Error adding selection on line %d\n", filename
, linecount
);
426 } /* End of ms_readselectionsfile() */
429 /***************************************************************************
432 * Free all memory associated with a Selections struct.
433 ***************************************************************************/
435 ms_freeselections ( Selections
*selections
)
438 Selections
*selectnext
;
439 SelectTime
*selecttime
;
440 SelectTime
*selecttimenext
;
448 selectnext
= select
->next
;
450 selecttime
= select
->timewindows
;
454 selecttimenext
= selecttime
->next
;
458 selecttime
= selecttimenext
;
467 } /* End of ms_freeselections() */
470 /***************************************************************************
471 * ms_printselections:
473 * Print the selections list using the ms_log() facility.
474 ***************************************************************************/
476 ms_printselections ( Selections
*selections
)
479 SelectTime
*selecttime
;
489 ms_log (0, "Selection: %s\n", select
->srcname
);
491 selecttime
= select
->timewindows
;
494 if ( selecttime
->starttime
!= HPTERROR
)
495 ms_hptime2seedtimestr (selecttime
->starttime
, starttime
, 1);
497 strncpy (starttime
, "No start time", sizeof(starttime
)-1);
499 if ( selecttime
->endtime
!= HPTERROR
)
500 ms_hptime2seedtimestr (selecttime
->endtime
, endtime
, 1);
502 strncpy (endtime
, "No end time", sizeof(endtime
)-1);
504 ms_log (0, " %30s %30s\n", starttime
, endtime
);
506 selecttime
= selecttime
->next
;
509 select
= select
->next
;
511 } /* End of ms_printselections() */
514 /***********************************************************************
515 * robust glob pattern matcher
516 * ozan s. yigit/dec 1994
520 * * matches zero or more characters
521 * ? matches any single character
522 * [set] matches any character in the set
523 * [^set] matches any character NOT in the set
524 * where a set is a group of characters or ranges. a range
525 * is written as two characters seperated with a hyphen: a-z denotes
526 * all characters between a to z inclusive.
527 * [-set] set matches a literal hypen and any character in the set
528 * []set] matches a literal close bracket and any character in the set
530 * char matches itself except where char is '*' or '?' or '['
531 * \char matches char, including any pattern character
534 * a*c ac abc abbc ...
535 * a?c acc abc aXc ...
536 * a[a-z]c aac abc acc ...
537 * a[-a-z]c a-c aac abc ...
539 * Revision 1.4 2004/12/26 12:38:00 ct
540 * Changed function name (amatch -> globmatch), variables and
541 * formatting for clarity. Also add matching header globmatch.h.
543 * Revision 1.3 1995/09/14 23:24:23 oz
544 * removed boring test/main code.
546 * Revision 1.2 94/12/11 10:38:15 oz
547 * charset code fixed. it is now robust and interprets all
548 * variations of charset [i think] correctly, including [z-a] etc.
550 * Revision 1.1 94/12/08 12:45:23 oz
552 ***********************************************************************/
554 #define GLOBMATCH_TRUE 1
555 #define GLOBMATCH_FALSE 0
556 #define GLOBMATCH_NEGATE '^' /* std char set negation char */
558 /***********************************************************************
561 * Check if a string matches a globbing pattern.
563 * Return 0 if string does not match pattern and non-zero otherwise.
564 **********************************************************************/
566 ms_globmatch (char *string
, char *pattern
)
574 if ( !*string
&& *pattern
!= '*' )
575 return GLOBMATCH_FALSE
;
577 switch ( c
= *pattern
++ )
581 while ( *pattern
== '*' )
585 return GLOBMATCH_TRUE
;
587 if ( *pattern
!= '?' && *pattern
!= '[' && *pattern
!= '\\' )
588 while ( *string
&& *pattern
!= *string
)
593 if ( ms_globmatch(string
, pattern
) )
594 return GLOBMATCH_TRUE
;
597 return GLOBMATCH_FALSE
;
602 return GLOBMATCH_FALSE
;
604 /* set specification is inclusive, that is [a-z] is a, z and
605 * everything in between. this means [z-a] may be interpreted
606 * as a set that contains z, a and nothing in between.
609 if ( *pattern
!= GLOBMATCH_NEGATE
)
610 negate
= GLOBMATCH_FALSE
;
613 negate
= GLOBMATCH_TRUE
;
617 match
= GLOBMATCH_FALSE
;
619 while ( !match
&& (c
= *pattern
++) )
622 return GLOBMATCH_FALSE
;
624 if ( *pattern
== '-' ) /* c-c */
627 return GLOBMATCH_FALSE
;
628 if ( *pattern
!= ']' )
630 if ( *string
== c
|| *string
== *pattern
||
631 ( *string
> c
&& *string
< *pattern
) )
632 match
= GLOBMATCH_TRUE
;
637 match
= GLOBMATCH_TRUE
;
644 match
= GLOBMATCH_TRUE
;
645 if ( *pattern
!= ']' )
647 if ( *pattern
== *string
)
648 match
= GLOBMATCH_TRUE
;
655 if ( negate
== match
)
656 return GLOBMATCH_FALSE
;
659 * if there is a match, skip past the charset and continue on
661 while ( *pattern
&& *pattern
!= ']' )
663 if ( !*pattern
++ ) /* oops! */
664 return GLOBMATCH_FALSE
;
672 return GLOBMATCH_FALSE
;
680 } /* End of ms_globmatch() */