Changeset View
Changeset View
Standalone View
Standalone View
head/usr.bin/lastcomm/readrec.c
Show All 32 Lines | |||||
#include <sys/types.h> | #include <sys/types.h> | ||||
#include <sys/acct.h> | #include <sys/acct.h> | ||||
#include <errno.h> | #include <errno.h> | ||||
#include <stddef.h> | #include <stddef.h> | ||||
#include <stdio.h> | #include <stdio.h> | ||||
#include <string.h> | #include <string.h> | ||||
int readrec_forward(FILE *f, struct acctv2 *av2); | int readrec_forward(FILE *f, struct acctv3 *av2); | ||||
int readrec_backward(FILE *f, struct acctv2 *av2); | int readrec_backward(FILE *f, struct acctv3 *av2); | ||||
/* | /* | ||||
* Reverse offsetof: return the offset of field f | * Reverse offsetof: return the offset of field f | ||||
* from the end of the structure s. | * from the end of the structure s. | ||||
*/ | */ | ||||
#define roffsetof(s, f) (sizeof(s) - offsetof(s, f)) | #define roffsetof(s, f) (sizeof(s) - offsetof(s, f)) | ||||
/* | /* | ||||
Show All 34 Lines | |||||
/* | /* | ||||
* Read a v1 accounting record stored at the current | * Read a v1 accounting record stored at the current | ||||
* position of stream f. | * position of stream f. | ||||
* Convert the data to the current record format. | * Convert the data to the current record format. | ||||
* Return EOF on error or end-of-file. | * Return EOF on error or end-of-file. | ||||
*/ | */ | ||||
static int | static int | ||||
readrec_v1(FILE *f, struct acctv2 *av2) | readrec_v1(FILE *f, struct acctv3 *av3) | ||||
{ | { | ||||
struct acctv1 av1; | struct acctv1 av1; | ||||
int rv; | int rv; | ||||
if ((rv = fread_record(&av1, sizeof(av1), f)) == EOF) | if ((rv = fread_record(&av1, sizeof(av1), f)) == EOF) | ||||
return (EOF); | return (EOF); | ||||
av2->ac_zero = 0; | av3->ac_zero = 0; | ||||
av2->ac_version = 2; | av3->ac_version = 3; | ||||
av2->ac_len = av2->ac_len2 = sizeof(*av2); | av3->ac_len = av3->ac_len2 = sizeof(*av3); | ||||
memcpy(av2->ac_comm, av1.ac_comm, AC_COMM_LEN); | memcpy(av3->ac_comm, av1.ac_comm, AC_COMM_LEN); | ||||
av2->ac_utime = decode_comp(av1.ac_utime) * 1000000; | av3->ac_utime = decode_comp(av1.ac_utime) * 1000000; | ||||
av2->ac_stime = decode_comp(av1.ac_stime) * 1000000; | av3->ac_stime = decode_comp(av1.ac_stime) * 1000000; | ||||
av2->ac_etime = decode_comp(av1.ac_etime) * 1000000; | av3->ac_etime = decode_comp(av1.ac_etime) * 1000000; | ||||
av2->ac_btime = av1.ac_btime; | av3->ac_btime = av1.ac_btime; | ||||
av2->ac_uid = av1.ac_uid; | av3->ac_uid = av1.ac_uid; | ||||
av2->ac_gid = av1.ac_gid; | av3->ac_gid = av1.ac_gid; | ||||
av2->ac_mem = av1.ac_mem; | av3->ac_mem = av1.ac_mem; | ||||
av2->ac_io = decode_comp(av1.ac_io); | av3->ac_io = decode_comp(av1.ac_io); | ||||
av2->ac_tty = av1.ac_tty; | av3->ac_tty = av1.ac_tty; | ||||
av2->ac_flagx = av1.ac_flag | ANVER; | av3->ac_flagx = av1.ac_flag | ANVER; | ||||
return (0); | return (0); | ||||
} | } | ||||
/* | /* | ||||
* Read an v2 accounting record stored at the current | * Read an v2 accounting record stored at the current | ||||
* position of stream f. | * position of stream f. | ||||
* Return EOF on error or end-of-file. | * Return EOF on error or end-of-file. | ||||
*/ | */ | ||||
static int | static int | ||||
readrec_v2(FILE *f, struct acctv2 *av2) | readrec_v2(FILE *f, struct acctv3 *av3) | ||||
{ | { | ||||
return (fread_record(av2, sizeof(*av2), f)); | struct acctv2 av2; | ||||
int rv; | |||||
if ((rv = fread_record(&av2, sizeof(av2), f)) == EOF) | |||||
return (EOF); | |||||
av3->ac_zero = 0; | |||||
av3->ac_version = 3; | |||||
av3->ac_len = av3->ac_len2 = sizeof(*av3); | |||||
memcpy(av3->ac_comm, av2.ac_comm, AC_COMM_LEN); | |||||
av3->ac_utime = av2.ac_utime; | |||||
av3->ac_stime = av2.ac_stime; | |||||
av3->ac_etime = av2.ac_etime; | |||||
av3->ac_btime = av2.ac_btime; | |||||
av3->ac_uid = av2.ac_uid; | |||||
av3->ac_gid = av2.ac_gid; | |||||
av3->ac_mem = av2.ac_mem; | |||||
av3->ac_io = av2.ac_io; | |||||
av3->ac_tty = av2.ac_tty; | |||||
av3->ac_flagx = av2.ac_flagx; | |||||
return (0); | |||||
} | } | ||||
/* | /* | ||||
* Read an v2 accounting record stored at the current | |||||
* position of stream f. | |||||
* Return EOF on error or end-of-file. | |||||
*/ | |||||
static int | |||||
readrec_v3(FILE *f, struct acctv3 *av3) | |||||
{ | |||||
return (fread_record(av3, sizeof(*av3), f)); | |||||
} | |||||
/* | |||||
* Read a new-style (post-v1) accounting record stored at | * Read a new-style (post-v1) accounting record stored at | ||||
* the current position of stream f. | * the current position of stream f. | ||||
* Convert the data to the current record format. | * Convert the data to the current record format. | ||||
* Return EOF on error or end-of-file. | * Return EOF on error or end-of-file. | ||||
*/ | */ | ||||
static int | static int | ||||
readrec_vx(FILE *f, struct acctv2 *av2) | readrec_vx(FILE *f, struct acctv3 *av3) | ||||
{ | { | ||||
uint8_t magic, version; | uint8_t magic, version; | ||||
if (fread_record(&magic, sizeof(magic), f) == EOF || | if (fread_record(&magic, sizeof(magic), f) == EOF || | ||||
fread_record(&version, sizeof(version), f) == EOF || | fread_record(&version, sizeof(version), f) == EOF || | ||||
ungetc(version, f) == EOF || | ungetc(version, f) == EOF || | ||||
ungetc(magic, f) == EOF) | ungetc(magic, f) == EOF) | ||||
return (EOF); | return (EOF); | ||||
switch (version) { | switch (version) { | ||||
case 2: | case 2: | ||||
return (readrec_v2(f, av2)); | return (readrec_v2(f, av3)); | ||||
case 3: | |||||
return (readrec_v3(f, av3)); | |||||
/* Add handling for more versions here. */ | /* Add handling for more versions here. */ | ||||
default: | default: | ||||
errno = EFTYPE; | errno = EFTYPE; | ||||
return (EOF); | return (EOF); | ||||
} | } | ||||
} | } | ||||
/* | /* | ||||
* Read an accounting record stored at the current | * Read an accounting record stored at the current | ||||
* position of stream f. | * position of stream f. | ||||
* Old-format records are converted to the current record | * Old-format records are converted to the current record | ||||
* format. | * format. | ||||
* Return the number of records read (1 or 0 at the end-of-file), | * Return the number of records read (1 or 0 at the end-of-file), | ||||
* or EOF on error. | * or EOF on error. | ||||
*/ | */ | ||||
int | int | ||||
readrec_forward(FILE *f, struct acctv2 *av2) | readrec_forward(FILE *f, struct acctv3 *av3) | ||||
{ | { | ||||
int magic, rv; | int magic, rv; | ||||
if ((magic = getc(f)) == EOF) | if ((magic = getc(f)) == EOF) | ||||
return (ferror(f) ? EOF : 0); | return (ferror(f) ? EOF : 0); | ||||
if (ungetc(magic, f) == EOF) | if (ungetc(magic, f) == EOF) | ||||
return (EOF); | return (EOF); | ||||
if (magic != 0) | if (magic != 0) | ||||
/* Old record format. */ | /* Old record format. */ | ||||
rv = readrec_v1(f, av2); | rv = readrec_v1(f, av3); | ||||
else | else | ||||
/* New record formats. */ | /* New record formats. */ | ||||
rv = readrec_vx(f, av2); | rv = readrec_vx(f, av3); | ||||
return (rv == EOF ? EOF : 1); | return (rv == EOF ? EOF : 1); | ||||
} | } | ||||
/* | /* | ||||
* Read an accounting record ending at the current | * Read an accounting record ending at the current | ||||
* position of stream f. | * position of stream f. | ||||
* Old-format records are converted to the current record | * Old-format records are converted to the current record | ||||
* format. | * format. | ||||
* The file pointer is positioned at the beginning of the | * The file pointer is positioned at the beginning of the | ||||
* record read. | * record read. | ||||
* Return the number of records read (1 or 0 at the end-of-file), | * Return the number of records read (1 or 0 at the end-of-file), | ||||
* or EOF on error. | * or EOF on error. | ||||
*/ | */ | ||||
int | int | ||||
readrec_backward(FILE *f, struct acctv2 *av2) | readrec_backward(FILE *f, struct acctv3 *av3) | ||||
{ | { | ||||
off_t pos; | off_t pos; | ||||
int c; | int c; | ||||
uint16_t len; | uint16_t len; | ||||
if ((pos = ftell(f)) == -1) | if ((pos = ftell(f)) == -1) | ||||
return (EOF); | return (EOF); | ||||
if (pos == 0) | if (pos == 0) | ||||
return (0); | return (0); | ||||
if (fseek(f, -roffsetof(struct acctv2, ac_trailer), | if (fseek(f, -roffsetof(struct acctv3, ac_trailer), | ||||
SEEK_CUR) == EOF || | SEEK_CUR) == EOF || | ||||
(c = getc(f)) == EOF) | (c = getc(f)) == EOF) | ||||
return (EOF); | return (EOF); | ||||
if (c & ANVER) { | if (c & ANVER) { | ||||
/* New record formats. */ | /* | ||||
* New record formats. For v2 and v3 offset from the | |||||
* end for ac_len2 should be same. | |||||
*/ | |||||
if (fseeko(f, pos - roffsetof(struct acctv2, ac_len2), | if (fseeko(f, pos - roffsetof(struct acctv2, ac_len2), | ||||
SEEK_SET) == EOF || | SEEK_SET) == EOF || | ||||
fread_record(&len, sizeof(len), f) == EOF || | fread_record(&len, sizeof(len), f) == EOF || | ||||
fseeko(f, pos - len, SEEK_SET) == EOF || | fseeko(f, pos - len, SEEK_SET) == EOF || | ||||
readrec_vx(f, av2) == EOF || | readrec_vx(f, av3) == EOF || | ||||
fseeko(f, pos - len, SEEK_SET) == EOF) | fseeko(f, pos - len, SEEK_SET) == EOF) | ||||
return (EOF); | return (EOF); | ||||
else | else | ||||
return (1); | return (1); | ||||
} else { | } else { | ||||
/* Old record format. */ | /* Old record format. */ | ||||
if (fseeko(f, pos - sizeof(struct acctv1), SEEK_SET) == EOF || | if (fseeko(f, pos - sizeof(struct acctv1), SEEK_SET) == EOF || | ||||
readrec_v1(f, av2) == EOF || | readrec_v1(f, av3) == EOF || | ||||
fseeko(f, pos - sizeof(struct acctv1), SEEK_SET) == EOF) | fseeko(f, pos - sizeof(struct acctv1), SEEK_SET) == EOF) | ||||
return (EOF); | return (EOF); | ||||
else | else | ||||
return (1); | return (1); | ||||
} | } | ||||
} | } |