4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
27 * Main processor for auditreduce.
28 * Mproc() is the entry point for this module. It is the only visible
29 * function in this module.
32 #include <sys/types.h>
34 #include <bsm/libbsm.h>
35 #include <bsm/audit.h>
38 extern int write_header();
39 extern int token_processing();
42 static audit_pcb_t
*aget();
43 static int get_file();
44 static int write_recs();
45 static int get_recs();
46 static int check_rec();
47 static void check_order();
48 static int check_header();
49 static int get_record();
51 static char empty_file_token
[] = {
53 AUT_OTHER_FILE64
, /* token id */
54 0, 0, 0, 0, 0, 0, 0, 0, /* seconds of time */
55 0, 0, 0, 0, 0, 0, 0, 0, /* microseconds of time */
57 AUT_OTHER_FILE32
, /* token id */
58 0, 0, 0, 0, /* seconds of time */
59 0, 0, 0, 0, /* microseconds of time */
61 0, 0, /* length of path name */
66 * .func mproc - main processor.
67 * .desc Mproc controls a single process's actions.
68 * First one record is retreived from each pcb. As they are retreived
69 * they are placed into a linked list sorted with oldest first. Then
70 * the first one from the list is written out and another record
71 * read in to replace it. The new record is placed into the list.
72 * This continues until the list is empty.
73 * .call ret = mproc(pcbr).
74 * .arg pcbr - ptr to pcb for this process.
75 * .ret 0 - no errors in processing.
76 * .ret -1 - errors in processing (message already printed).
80 register audit_pcb_t
*pcbr
;
83 int nrecs
= 0; /* number of records read from stream */
84 int nprecs
= 0; /* number of records put to stream */
85 register audit_pcb_t
*pcb
;
90 (void) fprintf(stderr
, "mproc: count %d lo %d hi %d\n",
91 pcbr
->pcb_count
, pcbr
->pcb_lo
, pcbr
->pcb_hi
);
95 * First load up a record from each input group.
97 for (i
= pcbr
->pcb_lo
; i
<= pcbr
->pcb_hi
; i
++) {
98 pcb
= &(pcbr
->pcb_below
[i
]); /* get next PCB */
99 while (pcb
->pcb_time
< 0) { /* while no active record ... */
100 if ((ret
= get_file(pcb
)) == -1)
101 break; /* no files - finished PCB */
103 return (-1); /* quit processing - failed */
104 if (get_recs(pcb
, &nrecs
) == 0)
105 asort(pcb
); /* got a rec - put in list */
109 * Now process all of the records.
111 while ((pcb
= aget()) != NULL
) { /* get oldest record */
112 if (write_recs(pcbr
, pcb
, &nprecs
))
114 while (pcb
->pcb_time
< 0) { /* while we don't have a rec */
115 if (pcb
->pcb_fpr
== NULL
) { /* no active file ... */
116 if ((ret
= get_file(pcb
)) == -1)
117 break; /* no files - finished pcb */
119 return (-1); /* quit - failed */
121 if (get_recs(pcb
, &nrecs
) == 0)
122 asort(pcb
); /* put record in list */
126 * For root: write outfile header if no records were encountered.
127 * For non-root: write trailer to pipe and close pipe.
129 if (pcbr
->pcb_flags
& PF_ROOT
) {
131 if (write_header()) /* write header if no records */
135 pcb
= &(pcbr
->pcb_below
[0]); /* any old PCB will do */
136 pcb
->pcb_rec
= empty_file_token
;
137 if (write_recs(pcbr
, pcb
, &junk
))
139 if (fclose(pcbr
->pcb_fpw
) == EOF
) {
141 (void) fprintf(stderr
,
142 gettext("%s couldn't close pipe.\n"), ar
);
146 * For root process tell how many records were written.
148 if (f_verbose
&& (pcbr
->pcb_flags
& PF_ROOT
)) {
149 (void) fprintf(stderr
,
150 gettext("%s %d record(s) total were written out.\n"),
158 * Head of linked-list of pcbs - sorted by time - oldest first.
160 static audit_pcb_t
*pcbls
= NULL
;
163 * .func asort - audit sort.
164 * .desc Place a pcb in the list sorted by time - oldest first.
166 * .arg pcb - ptr to pcb to install in list.
171 register audit_pcb_t
*pcb
;
173 register audit_pcb_t
*pcbc
, *pcbp
;
174 extern audit_pcb_t
*pcbls
; /* ptr to start of list */
176 pcb
->pcb_next
= NULL
;
178 pcbls
= pcb
; /* empty list */
181 pcbc
= pcbls
; /* current pcb */
182 pcbp
= pcbls
; /* previous pcb */
183 while (pcbc
!= NULL
) {
184 if (pcb
->pcb_time
< pcbc
->pcb_time
) {
186 pcb
->pcb_next
= pcbls
; /* new -> 1st in list */
190 pcbp
->pcb_next
= pcb
;
191 pcb
->pcb_next
= pcbc
; /* new in the inside */
195 pcbc
= pcbc
->pcb_next
;
197 pcbp
->pcb_next
= pcb
; /* new -> last */
202 * .func aget - audit get.
203 * .desc Get the first pcb from the list. Pcb is removed from list, too.
204 * .call pcb = aget().
206 * .ret pcb - ptr to pcb that was the first.
212 extern audit_pcb_t
*pcbls
; /* ptr to start of list */
215 return (pcbls
); /* empty list */
217 pcbls
= pcbls
->pcb_next
; /* 2nd becomes 1st */
223 * .func get_file - get a new file.
224 * .desc Get the next file from the pcb's list. Check the header to see
225 * if the file really is an audit file. If there are no more then
226 * quit. If a file open (fopen) fails because the system file table
227 * is full or the process file table is full then quit processing
229 * .call ret = get_file(pcb).
230 * .arg pcb - pcb holding the fcb's (files).
231 * .ret 0 - new file opened for processing.
232 * .ret -1 - no more files - pcb finished.
233 * .ret -2 - fatal error - quit processing.
237 register audit_pcb_t
*pcb
;
243 * Process file list until a good one if found or empty.
245 while (pcb
->pcb_fpr
== NULL
) {
246 if ((fcb
= pcb
->pcb_first
) == NULL
) {
248 return (-1); /* pcb is all done */
251 * If we are reading from files then open the next one.
254 if ((fp
= fopen(fcb
->fcb_file
, "r")) == NULL
) {
256 (void) sprintf(errbuf
, gettext(
257 "%s couldn't open:\n %s"),
262 * See if file space is depleted.
263 * If it is then we quit.
265 if (errno
== ENFILE
|| errno
== EMFILE
)
269 pcb
->pcb_first
= fcb
->fcb_next
;
270 continue; /* try another file */
274 * Read from standard input.
279 * Check header of audit file.
281 if (check_header(fp
, fcb
->fcb_name
)) {
283 (void) fprintf(stderr
,
285 ar
, error_str
, fcb
->fcb_file
);
287 if (fclose(fp
) == EOF
) {
289 (void) fprintf(stderr
, gettext(
290 "%s couldn't close %s.\n"),
294 pcb
->pcb_first
= fcb
->fcb_next
;
295 continue; /* try another file */
298 * Found a good audit file.
299 * Initalize pcb for processing.
301 pcb
->pcb_first
= fcb
->fcb_next
;
314 * .func write_recs - write records.
315 * .desc Write record from a buffer to output stream. Keep an eye out
316 * for the first and last records of the root's output stream.
317 * .call ret = write_recs(pcbr, pcb, nprecs).
318 * .arg pcbr - ptr to node pcb.
319 * .arg pcb - ptr to pcb holding the stream.
320 * .arg nprecs - ptr to the number of put records. Updated here.
321 * .ret 0 - no errors detected.
322 * .ret -1 - error in writing. Quit processing.
325 write_recs(pcbr
, pcb
, nprecs
)
326 register audit_pcb_t
*pcbr
, *pcb
;
333 adrm_start(&adr
, pcb
->pcb_rec
);
334 (void) adrm_char(&adr
, &id
, 1);
335 (void) adrm_int32(&adr
, &size
, 1);
338 * Scan for first record to be written to outfile.
339 * When we find it then write the header and
340 * save the time for the outfile name.
342 if ((*nprecs
)++ == 0) {
343 if (pcbr
->pcb_flags
& PF_ROOT
) {
344 f_start
= pcb
->pcb_time
; /* save start time */
349 f_end
= pcb
->pcb_time
; /* find last record's time */
350 pcb
->pcb_time
= -1; /* disable just written rec */
352 if ((fwrite(pcb
->pcb_rec
, sizeof (char), size
, pcbr
->pcb_fpw
)) !=
354 if (pcbr
->pcb_flags
& PF_ROOT
) {
355 (void) sprintf(errbuf
, gettext(
356 "%s write failed to %s"),
357 ar
, f_outfile
? f_outfile
: gettext("stdout"));
360 perror(gettext("auditreduce: write failed to pipe"));
369 * .func get_recs - get records.
370 * .desc Get records from a stream until one passing the current selection
371 * criteria is found or the stream is emptied.
372 * .call ret = get_recs(pcb, nr).
373 * .arg pcb - ptr to pcb that holds this stream.
374 * .arg nr - ptr to number of records read. Updated by this routine.
375 * .ret 0 - got a record.
376 * .ret -1 - stream is finished.
380 register audit_pcb_t
*pcb
;
387 int nrecs
= 0; /* count how many records read this call */
394 static void get_trace();
398 ret
= get_record(pcb
->pcb_fpr
, &pcb
->pcb_rec
,
399 pcb
->pcb_cur
->fcb_name
);
401 adrm_start(&adr
, pcb
->pcb_rec
);
404 (void) adrm_char(&adr
, (char *)&header_type
, 1);
405 /* skip over byte count */
406 (void) adrm_int32(&adr
, (int32_t *)&tmp
, 1);
407 /* skip over version # */
408 (void) adrm_char(&adr
, (char *)&tmp
, 1);
409 /* skip over event id */
410 (void) adrm_short(&adr
, (short *)&e
, 1);
411 /* skip over event id modifier */
412 (void) adrm_short(&adr
, (short *)&tmp
, 1);
414 if (header_type
== AUT_HEADER32
) {
418 (void) adrm_int32(&adr
, (int32_t *)&s
, 1);
419 /* get microseconds */
420 (void) adrm_int32(&adr
, (int32_t *)&m
, 1);
422 } else if (header_type
== AUT_HEADER32_EX
) {
424 int32_t t
, junk
[4]; /* at_type + at_addr[4] */
426 /* skip type and ip address field */
427 (void) adrm_int32(&adr
, (int32_t *)&t
, 1);
428 (void) adrm_int32(&adr
, (int32_t *)&junk
[0], t
/4);
431 (void) adrm_int32(&adr
, (int32_t *)&s
, 1);
432 /* get microseconds */
433 (void) adrm_int32(&adr
, (int32_t *)&m
, 1);
435 } else if (header_type
== AUT_HEADER64
) {
439 (void) adrm_int64(&adr
, (int64_t *)&s
, 1);
440 /* get microseconds */
441 (void) adrm_int64(&adr
, (int64_t *)&m
, 1);
442 #if ((!defined(_LP64)) || defined(_SYSCALL32))
443 if (s
< (time_t)INT32_MIN
||
444 s
> (time_t)INT32_MAX
)
451 } else if (header_type
== AUT_HEADER64_EX
) {
455 /* skip type and ip address field */
456 (void) adrm_int32(&adr
, (int32_t *)&t
, 1);
457 (void) adrm_int32(&adr
, (int32_t *)&junk
[0], t
/4);
460 (void) adrm_int64(&adr
, (int64_t *)&s
, 1);
461 /* get microseconds */
462 (void) adrm_int64(&adr
, (int64_t *)&m
, 1);
463 #if ((!defined(_LP64)) || defined(_SYSCALL32))
464 if (s
< (time_t)INT32_MIN
||
465 s
> (time_t)INT32_MAX
)
476 (void) fprintf(stderr
, "get_recs: %d ret %d recno %d\n",
477 pcb
->pcb_procno
, ret
, pcb
->pcb_nrecs
+ 1);
480 * See if entire file is after the time window specified.
481 * Must be check here because the start time of the file name
482 * may be after the first record(s).
484 if (pcb
->pcb_nrecs
== 0 && (pcb
->pcb_flags
& PF_USEFILE
)) {
486 * If the first record read failed then use the time
487 * that was in the filename to judge.
490 (pcb
->pcb_cur
)->fcb_start
= secs
;
491 if (!f_all
&& (m_before
<= (pcb
->pcb_cur
)->fcb_start
)) {
492 (void) fclose(pcb
->pcb_fpr
); /* ignore file */
497 /* Give belated announcement of file opening. */
499 (void) fprintf(stderr
,
500 gettext("%s opened:\n %s.\n"),
501 ar
, (pcb
->pcb_cur
)->fcb_file
);
505 /* Succesful acquisition of a record. */
507 pcb
->pcb_time
= secs
; /* time of record */
508 pcb
->pcb_nrecs
++; /* # of read recs from stream */
509 nrecs
++; /* # of recs read this call */
510 /* Only check record if at bottom of process tree. */
511 if (pcb
->pcb_flags
& PF_USEFILE
) {
512 check_order(pcb
); /* check time sequence */
513 if ((ret2
= check_rec(pcb
)) == 0) {
516 } else if (ret2
== -2) {
518 getrec
= FALSE
; /* get no more recs */
519 alldone
= TRUE
; /* quit this file */
522 /* -1: record not interesting */
530 /* Error with record read or all done with stream. */
535 if (alldone
== TRUE
) {
539 /* Error in record read. Display messages. */
540 if (ret
< 0 || ret2
== -2) {
541 pcb
->pcb_nrecs
++; /* # of read records */
543 if (pcb
->pcb_flags
& PF_USEFILE
) {
544 /* Ignore if this is not_terminated. */
545 if (!strstr((pcb
->pcb_cur
)->fcb_file
,
547 (void) fprintf(stderr
, gettext("%s read error in %s at record %d.\n"), ar
,
548 (pcb
->pcb_cur
)->fcb_file
, pcb
->pcb_nrecs
);
551 (void) fprintf(stderr
, gettext("%s read error in pipe at record %d.\n"), ar
,
557 * Only mark infile for deleting if we have succesfully
558 * processed all of it.
560 if (pcb
->pcb_flags
& PF_USEFILE
)
561 (pcb
->pcb_cur
)->fcb_flags
|= FF_DELETE
;
563 if (fclose(pcb
->pcb_fpr
) == EOF
) {
565 if (pcb
->pcb_flags
& PF_USEFILE
) {
566 str
= (pcb
->pcb_cur
)->fcb_file
;
570 (void) fprintf(stderr
,
571 gettext("%s couldn't close %s.\n"),
587 * .func get_trace - get trace.
588 * .desc If we are tracing file action (AUDIT_FILE is on) then print out
589 * a message when the file is closed regarding how many records
591 * .call get_trace(pcb).
592 * .arg pcb - ptr to pcb holding file/pipe.
600 * For file give filename, too.
602 if (pcb
->pcb_flags
& PF_USEFILE
) {
603 (void) fprintf(stderr
, "%s closed %s: %d records read recs: \
604 %d record written.\n", ar
, (pcb
->pcb_cur
)->fcb_file
,
605 pcb
->pcb_nrecs
, pcb
->pcb_nprecs
);
607 (void) fprintf(stderr
, "%s closed pipe: %d records read: \
608 %d records written .\n", ar
, pcb
->pcb_nrecs
,
616 * .func check_rec - check a record.
617 * .desc Check a record against the user's selection criteria.
618 * .call ret = check_rec(pcb).
619 * .arg pcb - ptr to pcb holding the record.
620 * .ret 0 - record accepted.
621 * .ret -1 - record rejected - continue processing file.
622 * .ret -2 - record rejected - quit processing file.
626 register audit_pcb_t
*pcb
;
631 au_emod_t id_modifier
;
633 au_event_t event_type
;
635 int rc
; /* return code */
637 adrm_start(&adr
, pcb
->pcb_rec
);
638 (void) adrm_char(&adr
, &tokenid
, 1);
641 * checkflags will be my data structure for determining if
642 * a record has met ALL the selection criteria. Once
643 * checkflags == flags, we have seen all we need to of the
644 * record, and can go to the next one. If when we finish
645 * processing the record we still have stuff to see,
646 * checkflags != flags, and thus we should return a -1
647 * from this function meaning reject this record.
652 /* must be header token -- sanity check */
653 if (tokenid
!= AUT_HEADER32
&& tokenid
!= AUT_HEADER64
&&
654 tokenid
!= AUT_HEADER32_EX
&& tokenid
!= AUT_HEADER64_EX
) {
656 (void) fprintf(stderr
,
657 "check_rec: %d recno %d no header %d found\n",
658 pcb
->pcb_procno
, pcb
->pcb_nrecs
, tokenid
);
664 * The header token is:
670 * seconds (date): int
671 * time (microsecs): int
673 (void) adrm_u_int32(&adr
, (uint32_t *)&bytes
, 1);
674 (void) adrm_char(&adr
, &version
, 1);
675 (void) adrm_u_short(&adr
, &event_type
, 1);
678 * Used by s5_IPC_token to set the ipc_type so
679 * s5_IPC_perm_token can test.
683 if (flags
& M_TYPE
) {
684 checkflags
|= M_TYPE
;
685 if (m_type
!= event_type
)
688 if (flags
& M_CLASS
) {
689 au_event_ent_t
*ev
= NULL
;
691 checkflags
|= M_CLASS
;
692 if (cacheauevent(&ev
, event_type
) <= 0) {
693 (void) fprintf(stderr
, gettext(
694 "Warning: invalid event no %d in audit trail."),
698 global_class
= ev
->ae_class
;
699 if (!(flags
& M_SORF
) && !(mask
.am_success
& global_class
))
703 (void) adrm_u_short(&adr
, &id_modifier
, 1);
706 * Check record against time criteria.
707 * If the 'A' option was used then no time checking is done.
708 * The 'a' parameter is inclusive and the 'b' exclusive.
710 if (tokenid
== AUT_HEADER32
) {
712 (void) adrm_int32(&adr
, (int32_t *)&secs
, 1);
713 (void) adrm_int32(&adr
, (int32_t *)&msecs
, 1);
714 tv
.tv_sec
= (time_t)secs
;
715 tv
.tv_usec
= (suseconds_t
)msecs
;
716 } else if (tokenid
== AUT_HEADER32_EX
) {
718 int32_t t
, junk
[5]; /* at_type + at_addr[4] */
719 /* skip type and ip address field */
720 (void) adrm_int32(&adr
, (int32_t *)&t
, 1);
721 (void) adrm_int32(&adr
, (int32_t *)&junk
[0], t
/4);
723 (void) adrm_int32(&adr
, (int32_t *)&secs
, 1);
724 (void) adrm_int32(&adr
, (int32_t *)&msecs
, 1);
725 tv
.tv_sec
= (time_t)secs
;
726 tv
.tv_usec
= (suseconds_t
)msecs
;
727 } else if (tokenid
== AUT_HEADER64
) {
729 (void) adrm_int64(&adr
, (int64_t *)&secs
, 1);
730 (void) adrm_int64(&adr
, (int64_t *)&msecs
, 1);
731 #if ((!defined(_LP64)) || defined(_SYSCALL32))
732 if (secs
< (time_t)INT32_MIN
||
733 secs
> (time_t)INT32_MAX
)
736 tv
.tv_sec
= (time_t)secs
;
737 if (msecs
< (suseconds_t
)INT32_MIN
||
738 msecs
> (suseconds_t
)INT32_MAX
)
741 tv
.tv_usec
= (suseconds_t
)msecs
;
743 tv
.tv_sec
= (time_t)secs
;
744 tv
.tv_usec
= (suseconds_t
)msecs
;
746 } else if (tokenid
== AUT_HEADER64_EX
) {
748 int32_t t
, junk
[4]; /* at_type + at_addr[4] */
749 /* skip type and ip address field */
750 (void) adrm_int32(&adr
, (int32_t *)&t
, 1);
751 (void) adrm_int32(&adr
, (int32_t *)&junk
[0], t
/4);
753 (void) adrm_int64(&adr
, (int64_t *)&secs
, 1);
754 (void) adrm_int64(&adr
, (int64_t *)&msecs
, 1);
755 #if ((!defined(_LP64)) || defined(_SYSCALL32))
756 if (secs
< (time_t)INT32_MIN
||
757 secs
> (time_t)INT32_MAX
)
760 tv
.tv_sec
= (time_t)secs
;
761 if (msecs
< (suseconds_t
)INT32_MIN
||
762 msecs
> (suseconds_t
)INT32_MAX
)
765 tv
.tv_usec
= (suseconds_t
)msecs
;
767 tv
.tv_sec
= (time_t)secs
;
768 tv
.tv_usec
= (suseconds_t
)msecs
;
771 pcb
->pcb_otime
= pcb
->pcb_time
;
773 if (m_after
> tv
.tv_sec
)
775 if (m_before
<= tv
.tv_sec
)
779 /* if no selection flags were passed, select everything */
784 * If all information can be found in header,
785 * there is no need to continue processing the tokens.
787 if (flags
== checkflags
)
791 * Process tokens until we hit the end of the record
793 while ((uint_t
)(adr
.adr_now
- adr
.adr_stream
) < bytes
) {
794 adrm_char(&adr
, &tokenid
, 1);
795 rc
= token_processing(&adr
, tokenid
);
799 (void) fprintf(stderr
,
800 gettext("auditreduce: bad token %u, terminating "
801 "file %s\n"), tokenid
, (pcb
->pcb_cur
)->fcb_file
);
805 /* Are we finished? */
806 if (flags
== checkflags
)
811 * So, we haven't seen all that we need to see. Reject record.
819 * .func check_order - Check temporal sequence.
820 * .call check_order(pcb).
821 * .arg pcb - ptr to audit_pcb_t.
822 * .desc Check to see if the records are out of temporal sequence, ie,
823 * a record has a time stamp older than its predecessor.
824 * Also check to see if the current record is within the bounds of
826 * This routine prints a diagnostic message, unless the QUIET
827 * option was selected.
828 * .call check_order(pcb).
829 * .arg pcb - ptr to pcb holding the records.
834 register audit_pcb_t
*pcb
;
836 char cptr1
[28], cptr2
[28]; /* for error reporting */
839 * If the record-past is not the oldest then say so.
841 if (pcb
->pcb_otime
> pcb
->pcb_time
) {
843 (void) memcpy((void *)cptr1
,
844 (void *)ctime(&pcb
->pcb_otime
), 26);
846 (void) memcpy((void *)cptr2
,
847 (void *)ctime(&pcb
->pcb_time
), 26);
849 (void) fprintf(stderr
,
850 gettext("%s %s had records out of order: %s was followed by %s.\n"),
851 ar
, (pcb
->pcb_cur
)->fcb_file
, cptr1
, cptr2
);
858 * .func check_header.
859 * .desc Read in and check the header for an audit file.
860 * The header must read-in properly and have the magic #.
861 * .call err = check_header(fp).
862 * .arg fp - file stream.
863 * .ret 0 no problems.
877 adrf_start(&adrf
, &adr
, fp
);
879 if (adrf_char(&adrf
, &id
, 1)) {
880 (void) sprintf(errbuf
, gettext("%s is empty"), fn
);
884 if (!(id
== AUT_OTHER_FILE32
|| id
== AUT_OTHER_FILE64
)) {
885 (void) sprintf(errbuf
, gettext("%s not an audit file "), fn
);
890 if (id
== AUT_OTHER_FILE32
) {
892 (void) adrf_int32(&adrf
, (int32_t *)&secs
, 1);
893 (void) adrf_int32(&adrf
, (int32_t *)&msecs
, 1);
896 (void) adrf_int64(&adrf
, (int64_t *)&secs
, 1);
897 (void) adrf_int64(&adrf
, (int64_t *)&msecs
, 1);
898 #if ((!defined(_LP64)) || defined(_SYSCALL32))
899 if (secs
< (time_t)INT32_MIN
||
900 secs
> (time_t)INT32_MAX
) {
901 error_str
= gettext("bad time stamp in file header");
904 if (msecs
< (suseconds_t
)INT32_MIN
||
905 msecs
> (suseconds_t
)INT32_MAX
) {
906 error_str
= gettext("bad time stamp in file header");
912 if (adrf_short(&adrf
, &pathlength
, 1)) {
913 error_str
= gettext("incomplete file header");
917 if (pathlength
!= 0) {
918 fname
= (char *)a_calloc(1, (size_t)pathlength
);
919 if ((fread(fname
, sizeof (char), pathlength
, fp
)) !=
921 (void) sprintf(errbuf
,
922 gettext("error in header/filename read in %s"),
934 * .func get_record - get a single record.
935 * .desc Read a single record from stream fp. If the record to be read
936 * is larger than the buffer given to hold it (as determined by
937 * cur_size) then free that buffer and allocate a new and bigger
938 * one, making sure to store its size.
939 * .call ret = get_record(fp, buf, cur_size, flags).
940 * .arg fp - stream to read from.
941 * .arg buf - ptr to ptr to buffer to place record in.
942 * .arg cur_size- ptr to the size of the buffer that *buf points to.
943 * .arg flags - flags from fcb (to get FF_NOTTERM).
944 * .ret +number - number of chars in the record.
945 * .ret 0 - trailer seen - file done.
946 * .ret -1 - read error (error_str know what type).
949 get_record(fp
, buf
, fn
)
962 * Get the token type. It will be either a header or a file
965 (void) adrf_start(&adrf
, &adr
, fp
);
966 if (adrf_char(&adrf
, &id
, 1)) {
967 (void) sprintf(errbuf
, gettext(
968 "record expected but not found in %s"),
975 case AUT_HEADER32_EX
:
977 case AUT_HEADER64_EX
:
979 * The header token is:
985 * IP address type int (_EX only)
986 * IP address 1/4*int (_EX only)
987 * seconds (date): long
988 * time (microsecs): long
990 leadin
= sizeof (int32_t) + sizeof (char);
991 (void) adrf_int32(&adrf
, &lsize
, 1);
992 *buf
= (char *)a_calloc(1, (size_t)(lsize
+ leadin
));
993 adr_start(&adr
, *buf
);
994 adr_char(&adr
, &id
, 1);
995 adr_int32(&adr
, (int32_t *)&lsize
, 1);
996 if (fread(*buf
+ leadin
, sizeof (char), lsize
- leadin
, fp
) !=
998 (void) sprintf(errbuf
,
999 gettext("header token read failure in %s"), fn
);
1003 return (lsize
+ leadin
);
1004 case AUT_OTHER_FILE32
: {
1005 int32_t secs
, msecs
;
1006 leadin
= 2 * sizeof (int32_t) +
1007 sizeof (short) + sizeof (char);
1008 (void) adrf_int32(&adrf
, (int32_t *)&secs
, 1);
1009 (void) adrf_int32(&adrf
, (int32_t *)&msecs
, 1);
1010 (void) adrf_short(&adrf
, &ssize
, 1);
1011 *buf
= (char *)a_calloc(1, (size_t)(ssize
+ leadin
));
1012 adr_start(&adr
, *buf
);
1013 adr_char(&adr
, &id
, 1);
1014 adr_int32(&adr
, (int32_t *)&secs
, 1);
1015 adr_int32(&adr
, (int32_t *)&msecs
, 1);
1016 adr_short(&adr
, &ssize
, 1);
1017 if (fread(*buf
+ leadin
, sizeof (char), ssize
, fp
) != ssize
) {
1018 error_str
= gettext("file token read failure");
1021 return (0); /* done! */
1023 case AUT_OTHER_FILE64
: {
1024 int64_t secs
, msecs
;
1025 leadin
= 2 * sizeof (int64_t) +
1026 sizeof (short) + sizeof (char);
1027 (void) adrf_int64(&adrf
, (int64_t *)&secs
, 1);
1028 (void) adrf_int64(&adrf
, (int64_t *)&msecs
, 1);
1029 (void) adrf_short(&adrf
, &ssize
, 1);
1030 *buf
= (char *)a_calloc(1, (size_t)(ssize
+ leadin
));
1031 adr_start(&adr
, *buf
);
1032 adr_char(&adr
, &id
, 1);
1033 adr_int64(&adr
, (int64_t *)&secs
, 1);
1034 adr_int64(&adr
, (int64_t *)&msecs
, 1);
1035 adr_short(&adr
, &ssize
, 1);
1036 if (fread(*buf
+ leadin
, sizeof (char), ssize
, fp
) != ssize
) {
1037 error_str
= gettext("file token read failure");
1040 return (0); /* done! */
1045 error_str
= gettext("record begins without proper token");