2 * Read/write files in the oncoming Standard AMANDA format - "format 2000"
4 #if 0 /******* TODO *********/
5 /* skip event gets array as parameter */
6 /* level 4 event types in mevt */
7 /* end of file, tend */
8 /******************************/
12 char *amanda_rdmc_cvsid =
13 "$Header: /net/local/cvsroot/siegmund/rdmc/amanda.c,v 1.81 2004/02/19 17:10:08 wiebusch Exp $";
21 #include "rdmc_local.h"
26 /****************************************************************************/
27 /* rdmc_nint(double a) */
28 /* converts a to the nearest integer */
29 /* but also takes care on the sign */
30 /****************************************************************************/
31 long rdmc_nint(double a)
33 i = (a >= 0.) ? (long) (a + 0.5 ) : (long) (a - 0.5);
37 /*******************************/
38 /* Work around missing isnan() */
39 /*******************************/
45 /******************************************************/
46 /*** Definitions of f2k blocks struture in memory ***/
47 /******************************************************/
50 /* check if line is in buffer or read a new one */
52 static int amanda_readline(mcfile *fp);
54 /* dump a line back into the buffer if it is empty */
56 static int amanda_unreadline(mcfile *fp);
58 /* read the next block according to a list of allowed lines into the buffer */
60 static int amanda_read_block(mcfile *fp ,const f2000_event_t *def);
62 /* try to decode a given line according to line_def */
64 /* returns RDMC_IO_OK or RDMC_LINE_EMPTY or RDMC_EVENT_NOT_RECOGNIZED */
65 static int amanda_lex_line(mcfile *fp, const f2000_line_t * const line_def[F2K_MAX_LINETYPES] );
67 /* compares each byte of key to the first no white exam until lngth of key*/
68 /* -1 if line is empty, 0 on no and 1 on succes */
69 static int tokencmp(const char *key, char *exam);
71 /* same with no trailing chars */
72 static int tokencmp_notrail(const char *key, char *exam);
74 /* checks if the first non-white char in exam is in keys */
75 /* if a line is only whitespace ot empty -1 is returned */
76 /* 0: if the char is not found */
77 /* 1: if the char is not found */
78 static int tokenchr(const char *keys, char *exam);
79 /* same as above but chars are not alnum (ispunct()) */
80 static int tokenchrpunct(const char *keys, char *exam);
82 /***************************************************************************/
83 /***************************************************************************/
85 /*** Read functions follow ***/
87 /***************************************************************************/
90 /****************************************************************************
91 * read the F2000 "V" line (the first one) and put it into fp
92 ****************************************************************************/
93 /******* This is the only parswer routine, which is different !!! */
94 /* it reads directly from fp, instead of the readline mode */
95 int rdmc_amanda_V(const char *s, mcfile *fp)
97 int major = 0, minor = 0;
98 if(sscanf(s,"V 2000.%i.%i",&major, &minor) != 2)
99 return RDMC_LINE_NOT_PARSED;
100 if (rdmc_is_f2000_supported(major, minor) == 0)
101 return RDMC_UNKNOWN_FORMAT_VERSION;
106 } /* amanda_rdmc_V() */
108 int rdmc_rhd_amanda(mcfile *fp){
109 const f2000_event_t *ev_def;
112 /* get the config def for the right format*/
113 switch( 100*fp->fmajor + fp->fminor ){
117 ev_def=&f2000_preamble_1x1;
120 return RDMC_UNKNOWN_FORMAT_VERSION;
123 /* read the block acordng to the def */
124 if ((ret = amanda_read_block(fp, ev_def)) != RDMC_IO_OK)
127 /* use the pointer from the event definition and scan*/
128 return ev_def->reader(fp, NULL, NULL);
132 int rdmc_rarr_amanda(mcfile *fp, array *ar)
134 const f2000_event_t *ev_def;
137 /* get the config def for the right format*/
138 switch( 100*fp->fmajor + fp->fminor ){
142 ev_def=&f2000_mhead_1x1;
145 return RDMC_UNKNOWN_FORMAT_VERSION;
148 /* read the block acordng to the def */
149 if ((ret = amanda_read_block(fp, ev_def)) != RDMC_IO_OK)
152 /* use the pointer from the event definition and scan*/
153 return ev_def->reader(fp, ar, NULL);
157 int rdmc_revt_amanda(mcfile *fp, mevt *ev, array *ar){
158 const f2000_event_t **ev_def,*foot_def;
163 /* get the config def for the right format*/
164 /* get the config def for the right format*/
165 switch( 100*fp->fmajor + fp->fminor ){
167 ev_def = f2000_events_1x1;
168 foot_def = &f2000_mfoot_1x1 ;
171 ev_def =f2000_events_1x2;
172 foot_def = &f2000_mfoot_1x1 ;
175 ev_def =f2000_events_2004x1;
176 foot_def = &f2000_mfoot_1x1 ;
179 return RDMC_UNKNOWN_FORMAT_VERSION;
182 while( *ev_def !=NULL ){
183 /* read the block acordng to the def */
184 ret = amanda_read_block(fp, *ev_def);
185 if ( ret == RDMC_IO_OK)
189 if ( ret == RDMC_IO_OK){
190 rdmc_clear_mevt(ev); /* reset the event */
191 /* use the pointer from the event definition and scan*/
192 if (fp->info.f2000.nolex)
195 return (*ev_def)->reader(fp, ar, ev);
196 }else{ /* test footer */
197 if ( ret == RDMC_EVENT_NOT_RECOGNIZED) {
198 ret2 = amanda_read_block(fp, foot_def);
199 if (ret2 == RDMC_IO_OK)
209 int rdmc_skipevt_amanda(mcfile *fp)
216 #if 0 /* this is the proper, presently slow version */
217 rdmc_init_array(&ar);
219 fp->info.f2000.nolex=1;
220 ret = rdmc_revt_amanda(fp, &ev, &ar);
221 fp->info.f2000.nolex=0;
222 rdmc_clear_array(&ar);
223 rdmc_clear_mevt(&ev);
224 #else /* presently no array is needed -> dirty patch ! */
226 fp->info.f2000.nolex=1;
227 ret = rdmc_revt_amanda(fp, &ev, NULL);
228 fp->info.f2000.nolex=0;
229 rdmc_clear_mevt(&ev);
236 /****************************************************************************
237 * Reads a nonempty line
238 ****************************************************************************/
239 static int amanda_readline(mcfile *fp){
241 char *s = fp->last_line;
243 if (fp->info.f2000.unread != 0 ) { /* line in buffer */
244 fp->info.f2000.unread = 0;
245 } else{ /* no line in buffer - read from file */
246 if (fgets(s, RDMC_MAXLINE-1, fp->fp) == NULL)/*fgets includes the '\n'*/
249 } while (*s == '\0'); /* look for a not-empty line */
250 /* increment the counter line */
254 } /* amanda_readline() */
256 /****************************************************************************
257 * "unread" an amanda F2000 format line
258 ****************************************************************************/
260 static int amanda_unreadline(mcfile *fp){
261 if (fp->info.f2000.unread != 0)
262 return EOF; /* only one line allowed */
264 fp->info.f2000.unread = 1;
267 } /* amanda_unreadline() */
270 static int amanda_read_block(mcfile *fp ,const f2000_event_t *def){
274 rdmc_clear_f2k_buffer(fp->info.f2000.f2k_buffer);
277 /* test if the block starts with the right line */
280 if (def->opener[0]){ /* yes there is one needed ! */
281 if ( (r=amanda_readline(fp)) != RDMC_IO_OK)
283 else /* analyse if this line matches and store it then */
284 ret = amanda_lex_line(fp, def->opener);
285 } else{ /* no opener needed -> OK */
289 if( ret != RDMC_LINE_EMPTY ){ /* something happende */
291 if ( ret == RDMC_EVENT_NOT_RECOGNIZED){
292 amanda_unreadline(fp); /* we have read one line to much */
298 /* keep on reading body lines */
301 /* analyse if this line matches and store it then */
302 if (def->inner[0]){ /* yes there are some ! */
303 if ( (r=amanda_readline(fp)) != RDMC_IO_OK)
306 ret = amanda_lex_line(fp, def->inner);
313 if( ret != RDMC_LINE_EMPTY ){ /* something happend */
314 if (ret == RDMC_IO_OK) /* line OK -> next one */
316 else{ /* line is not parsed -> check if an end marker appeared */
317 amanda_unreadline(fp); /* we have read one line to much */
318 do_reading = 0; /* this is no error since the body may be empty */
319 ret = RDMC_IO_OK; /* this is no error but maybe the next event */
320 break; /* ok we end here */
325 /* check the end marker */
328 /* analyse if this line matches and store it then */
329 if (def->closer[0]){ /* yes there are some needed ! */
330 if ( (r=amanda_readline(fp)) != RDMC_IO_OK)
333 ret = amanda_lex_line(fp, def->closer);
340 if( ret != RDMC_LINE_EMPTY ){ /* something happend */
341 if (ret == RDMC_IO_OK){ /* line OK -> finish */
345 else{ /* line is not parsed */
346 amanda_unreadline(fp); /* we have read one line to much */
347 do_reading = 0; /* this is no error since the body may be empty */
348 break; /* ok we end here */
357 static int amanda_lex_line(mcfile *fp, const f2000_line_t * const line_def[F2K_MAX_LINETYPES] ){
358 int ptindex , cres = 0;
359 const f2000_line_t *opt;
361 if ( !(line_def[0]) ) /* no match actually needed */
362 return RDMC_EVENT_NOT_RECOGNIZED;
364 for(ptindex=0 , cres=0, opt = line_def[0]
366 ; opt = line_def[++ptindex]
369 switch (opt->searchtype){
370 case COMP_STRINGWISE:
371 cres = tokencmp(opt->tag,fp->last_line);
373 case COMP_STRINGWISE_NOTRAIL:
374 cres = tokencmp_notrail(opt->tag,fp->last_line);
377 cres = tokenchr(opt->tag,fp->last_line);
380 cres = tokenchrpunct(opt->tag,fp->last_line);
383 case COMP_DUMMY: /* no token is needed so stop parsing */
384 /* trap to finish here */
385 return RDMC_EVENT_NOT_RECOGNIZED;
389 return RDMC_LIBRARY_ERROR;
391 if (cres < 0){ /* empty line */
392 return RDMC_LINE_EMPTY;
393 } else if(cres == 0){ /* no match found */
394 /* needed but not found -> try the next */
396 }else{ /* ok tag is found */
397 rdmc_push_f2k_buffer(fp->info.f2000.f2k_buffer, fp->last_line,line_def[ptindex]);
401 return RDMC_EVENT_NOT_RECOGNIZED;
404 /* compares each byte of key to exam until th lngth of key */
405 /* leading whitespaces are ignored */
406 static int tokencmp(const char *key, char *exam){
409 const char *e = exam;
413 else { /* this is the first non white */
415 while (*k){ /* now check key */
416 if (!(*e)) /* if e ends before key */
418 if( *e == *k ) /* stil agreement ? */
421 return r=0; /* break if not */
425 return r; /* exit here likely with r==1 */
431 /* compares each byte of key to exam until the lngth of key */
432 /* trailing chars are ignored */
433 static int tokencmp_notrail(const char *key, char *exam){
436 const char *e = exam;
440 else { /* this is the first non white */
442 while (*k){ /* now check key */
443 if (!(*e)) /* if e ends before key */
445 if( *e == *k ) /* stil agreement ? */
448 return r=0; /* break if not */
452 return r; /* exit here likely with r==1 */
458 /* checks if the first non-white char in exam is in keys */
459 /* if a line is only whitespace ot empty -1 is returned */
460 /* 0: if the char is not found */
461 /* 1: if the char is found */
462 static int tokenchr(const char *keys, char *exam){
469 else { /* this is the first non white */
471 while (*k){ /* now check key */
472 if( *e == *k ) /* agreement ? */
477 return r=0; /* exit here likely with r==1 */
483 static int tokenchrpunct(const char *keys, char *exam){
490 else if (!ispunct(*e))
492 else { /* this is the first non white */
494 while (*k){ /* now check key */
495 if( *e == *k ) /* agreement ? */
500 return r=0; /* exit here likely */
507 /***************************************************************************/
509 /*** Write functions follow ***/
511 /***************************************************************************/
512 /***************************************************************************/
517 /***************************************************************************/
518 /* write end of file (F2000 format) */
519 int rdmc_wrend_amanda(const mcfile *fp)
521 const f2000_event_t *ev_def;
523 /* get the config def for the right format*/
524 switch( 100*fp->fmajor + fp->fminor ){
528 ev_def=&f2000_mfoot_1x1;
531 return RDMC_UNKNOWN_FORMAT_VERSION;
534 /* use the pointer from the event definition and scan*/
535 return ev_def->writer(fp, NULL, NULL);
536 } /* wrend_amanda() */
538 /****************************************************************************
539 * function warr_amanda() writes the array info to a amanda-like file
540 * This function writes out the head of a AMANDA ascii file
541 * opposite to reading the input file it writes not only
542 * the Geometry banks ('G', 'P') , but also the ('V' and 'M' flags)
543 * so the function whd_amanda does not exist
544 ****************************************************************************/
546 int rdmc_warr_amanda(const mcfile *fp,const array *geo)
548 const f2000_event_t *ev_def;
550 /* get the config def for the right format*/
551 switch( 100*fp->fmajor + fp->fminor ){
553 ev_def=&f2000_mhead_1x1;
557 /* use the pointer from the event definition and scan*/
558 return ev_def->writer(fp, geo, NULL);
561 /****************************************************************************
562 * function wevt_amanda() writes an event to a amanda-like file
563 ****************************************************************************/
565 int rdmc_wevt_amanda(const mcfile *fp,const mevt *event, const array *ar)
567 const f2000_event_t *ev_def;
569 /* get the config def for the right format*/
570 switch( 100*fp->fmajor + fp->fminor ){
572 ev_def=f2000_events_1x1[0]; /* take first array element */
575 ev_def=f2000_events_1x2[0]; /* take first array element */
578 ev_def=f2000_events_2004x1[0]; /* take first array element */
581 return RDMC_UNKNOWN_FORMAT_VERSION;
584 /* use the pointer from the event definition and scan*/
585 return ev_def->writer(fp, ar, event);
590 /****************************************************************************
591 * wrhist_amanda() writes history lines to an ASCII file
592 ****************************************************************************/
594 int rdmc_wrhist_amanda(const mcfile *fp, const char *s, const char *pre)
596 return rdmc_wrhist_f2k_1x1(fp, s, pre);
599 /****************************************************************************
600 * wrcomment_amanda() writes a comment line to an ASCII file
601 ****************************************************************************/
603 int rdmc_wrcomment_amanda(const mcfile *fp, const char *s)
605 return rdmc_wrcomment_f2k_1x1(fp, s);
609 #endif /* AMANDA_ASCII_F */
611 /****************************************************************************
612 ********************************** E O F ***********************************
613 ****************************************************************************/
615 This is just for EMACS:
617 compile-command: "cd .. ; make -k rdmc"