***************************************************************************
*/
-#define ULL_ALIGNMENT_WIDTH 8
-#define UL_ALIGNMENT_WIDTH 8
-#define U_ALIGNMENT_WIDTH 4
+#define SIZEOF_LONG_64BIT 8
+#define ULL_ALIGNMENT_WIDTH 8
+#define UL_ALIGNMENT_WIDTH SIZEOF_LONG_64BIT
+#define U_ALIGNMENT_WIDTH 4
/*
* Structure for CPU statistics.
* Indicate that the file was created by sysstat.
*/
#define SYSSTAT_MAGIC 0xd596
+#define SYSSTAT_MAGIC_SWAPPED (((SYSSTAT_MAGIC << 8) | (SYSSTAT_MAGIC >> 8)) & 0xffff)
/*
* Datafile format magic number.
* no longer compatible with that of previous sysstat versions.
*/
#define FORMAT_MAGIC 0x2175
+#define FORMAT_MAGIC_SWAPPED (((FORMAT_MAGIC << 8) | (FORMAT_MAGIC >> 8)) & 0xffff)
/* Previous datafile format magic number used by older sysstat versions */
#define PREVIOUS_FORMAT_MAGIC 0x2173
};
#define FILE_HEADER_SIZE (sizeof(struct file_header))
+#define FILE_HEADER_ULL_NR 0 /* Nr of unsigned long long in file_header structure */
+#define FILE_HEADER_UL_NR 1 /* Nr of unsigned long in file_header structure */
+#define FILE_HEADER_U_NR 3 /* Nr of unsigned int in file_header structure */
/* The values below are used for sanity check */
#define MIN_FILE_HEADER_SIZE 0
#define MAX_FILE_HEADER_SIZE 8192
};
#define FILE_ACTIVITY_SIZE (sizeof(struct file_activity))
+#define FILE_ACTIVITY_ULL_NR 0 /* Nr of unsigned long long in file_activity structure */
+#define FILE_ACTIVITY_UL_NR 0 /* Nr of unsigned long in file_activity structure */
+#define FILE_ACTIVITY_U_NR 5 /* Nr of [unsigned] int in file_activity structure */
/* Record type */
};
#define RECORD_HEADER_SIZE (sizeof(struct record_header))
+#define RECORD_HEADER_ULL_NR 2 /* Nr of unsigned long long in record_header structure */
+#define RECORD_HEADER_UL_NR 1 /* Nr of unsigned long in record_header structure */
+#define RECORD_HEADER_U_NR 0 /* Nr of unsigned int in record_header structure */
/*
(struct activity *, int, int, int);
void check_file_actlst
(int *, char *, struct activity * [], struct file_magic *, struct file_header *,
- struct file_activity **, unsigned int [], int);
+ struct file_activity **, unsigned int [], int, int *, int *);
int check_net_dev_reg
(struct activity *, int, int, int);
int check_net_edev_reg
int print_special_record
(struct record_header *, unsigned int, struct tstamp *, struct tstamp *,
int, int, struct tm *, struct tm *, char *, int, struct file_magic *,
- struct file_header *, struct activity * [], struct report_format *);
+ struct file_header *, struct activity * [], struct report_format *, int, int);
void read_file_stat_bunch
- (struct activity * [], int, int, int, struct file_activity *);
+ (struct activity * [], int, int, int, struct file_activity *, int, int);
__nr_t read_vol_act_structures
- (int, struct activity * [], char *, struct file_magic *, unsigned int);
+ (int, struct activity * [], char *, struct file_magic *, unsigned int, int, int);
int reallocate_vol_act_structures
(struct activity * [], unsigned int, unsigned int);
void replace_nonprintable_char
int sa_get_record_timestamp_struct
(unsigned int, struct record_header *, struct tm *, struct tm *);
int sa_open_read_magic
- (int *, char *, struct file_magic *, int);
+ (int *, char *, struct file_magic *, int, int *);
void select_all_activities
(struct activity * []);
void select_default_activity
int default_file_used = FALSE;
extern struct act_bitmap cpu_bitmap;
+int hdr_types_nr[] = {FILE_HEADER_ULL_NR, FILE_HEADER_UL_NR, FILE_HEADER_U_NR};
+int act_types_nr[] = {FILE_ACTIVITY_ULL_NR, FILE_ACTIVITY_UL_NR, FILE_ACTIVITY_U_NR};
+
/*
***************************************************************************
* Allocate structures.
void handle_invalid_sa_file(int *fd, struct file_magic *file_magic, char *file,
int n)
{
- unsigned short sm;
-
fprintf(stderr, _("Invalid system activity file: %s\n"), file);
if (n == FILE_MAGIC_SIZE) {
- sm = (file_magic->sysstat_magic << 8) | (file_magic->sysstat_magic >> 8);
- if ((file_magic->sysstat_magic == SYSSTAT_MAGIC) || (sm == SYSSTAT_MAGIC)) {
- /*
- * This is a sysstat file, but this file has an old format
- * or its internal endian format doesn't match.
- */
+ if ((file_magic->sysstat_magic == SYSSTAT_MAGIC) || (file_magic->sysstat_magic == SYSSTAT_MAGIC_SWAPPED)) {
+ /* This is a sysstat file, but this file has an old format */
display_sa_file_version(stderr, file_magic);
- if (sm == SYSSTAT_MAGIC) {
- fprintf(stderr, _("Endian format mismatch\n"));
- }
- else {
- fprintf(stderr,
- _("Current sysstat version cannot read the format of this file (%#x)\n"),
- file_magic->format_magic);
- }
+ fprintf(stderr,
+ _("Current sysstat version cannot read the format of this file (%#x)\n"),
+ file_magic->sysstat_magic == SYSSTAT_MAGIC ?
+ file_magic->format_magic : __builtin_bswap16(file_magic->format_magic));
}
}
* @ifd Input file descriptor.
* @act_nr Number of activities in file.
* @file_actlst Activity list in file.
+ * @endian_mismatch
+ * TRUE if file's data don't match current machine's endianness.
+ * @arch_64 TRUE if file's data come from a 64 bit machine.
***************************************************************************
*/
void read_file_stat_bunch(struct activity *act[], int curr, int ifd, int act_nr,
- struct file_activity *file_actlst)
+ struct file_activity *file_actlst, int endian_mismatch,
+ int arch_64)
{
int i, j, p;
struct file_activity *fal = file_actlst;
else {
PANIC(p);
}
+
+ /* Normalize endianness for current activity's structures */
+ if (endian_mismatch) {
+ for (j = 0; j < (act[p]->nr * act[p]->nr2); j++) {
+ swap_struct(act[p]->gtypes_nr, (char *) act[p]->buf[curr] + j * act[p]->msize,
+ arch_64);
+ }
+ }
}
}
* IN:
* @dfile Name of system activity data file.
* @ignore Set to 1 if a true sysstat activity file but with a bad
- * format should not yield an error message. Useful with
- * sadf -H and sadf -c.
+ * format should not yield an error message. Useful with
+ * sadf -H and sadf -c.
*
* OUT:
* @fd System activity data file descriptor.
* @file_magic file_magic structure containing data read from file magic
* header.
+ * @endian_mismatch
+ * TRUE if file's data don't match current machine's endianness.
*
* RETURNS:
* -1 if data file is a sysstat file with an old format, 0 otherwise.
***************************************************************************
*/
int sa_open_read_magic(int *fd, char *dfile, struct file_magic *file_magic,
- int ignore)
+ int ignore, int *endian_mismatch)
{
int n;
n = read(*fd, file_magic, FILE_MAGIC_SIZE);
if ((n != FILE_MAGIC_SIZE) ||
- (file_magic->sysstat_magic != SYSSTAT_MAGIC) ||
- ((file_magic->format_magic != FORMAT_MAGIC) && !ignore)) {
+ ((file_magic->sysstat_magic != SYSSTAT_MAGIC) && (file_magic->sysstat_magic != SYSSTAT_MAGIC_SWAPPED)) ||
+ ((file_magic->format_magic != FORMAT_MAGIC) && (file_magic->format_magic != FORMAT_MAGIC_SWAPPED) && !ignore)) {
/* Display error message and exit */
handle_invalid_sa_file(fd, file_magic, dfile, n);
}
+
+ *endian_mismatch = (file_magic->sysstat_magic != SYSSTAT_MAGIC);
+ if (*endian_mismatch) {
+ /* Swap bytes for file_magic fields */
+ file_magic->sysstat_magic = __builtin_bswap16(file_magic->sysstat_magic);
+ file_magic->format_magic = __builtin_bswap16(file_magic->format_magic);
+ file_magic->header_size = __builtin_bswap32(file_magic->header_size);
+ }
+
if ((file_magic->sysstat_version > 10) ||
((file_magic->sysstat_version == 10) && (file_magic->sysstat_patchlevel >= 3))) {
/* header_size field exists only for sysstat versions 10.3.1 and later */
* @dfile Name of system activity data file.
* @act Array of activities.
* @ignore Set to 1 if a true sysstat activity file but with a bad
- * format should not yield an error message. Useful with
- * sadf -H and sadf -c.
+ * format should not yield an error message. Useful with
+ * sadf -H and sadf -c.
*
* OUT:
* @ifd System activity data file descriptor.
* @file_magic file_magic structure containing data read from file magic
* header.
* @file_hdr file_hdr structure containing data read from file standard
- * header.
+ * header.
* @file_actlst Acvtivity list in file.
* @id_seq Activity sequence.
+ * @endian_mismatch
+ * TRUE if file's data don't match current machine's endianness.
+ * @arch_64 TRUE if file's data come from a 64 bit machine.
***************************************************************************
*/
void check_file_actlst(int *ifd, char *dfile, struct activity *act[],
struct file_magic *file_magic, struct file_header *file_hdr,
struct file_activity **file_actlst, unsigned int id_seq[],
- int ignore)
+ int ignore, int *endian_mismatch, int *arch_64)
{
int i, j, p;
unsigned int a_cpu = FALSE;
void *buffer = NULL;
/* Open sa data file and read its magic structure */
- if (sa_open_read_magic(ifd, dfile, file_magic, ignore) < 0)
+ if (sa_open_read_magic(ifd, dfile, file_magic, ignore, endian_mismatch) < 0)
return;
SREALLOC(buffer, char, file_magic->header_size);
memcpy(file_hdr, buffer, FILE_HEADER_SIZE);
free(buffer);
+ /* Normalize endianness for file_hdr structure */
+ *arch_64 = (file_hdr->sa_sizeof_long == SIZEOF_LONG_64BIT);
+ if (*endian_mismatch) {
+ swap_struct(hdr_types_nr, file_hdr, *arch_64);
+ }
+
/*
* Sanity check.
* Compare against MAX_NR_ACT and not NR_ACT because
sa_fread(*ifd, fal, FILE_ACTIVITY_SIZE, HARD_SIZE);
+ /* Normalize endianness for file_activity structures */
+ if (*endian_mismatch) {
+ swap_struct(act_types_nr, fal, *arch_64);
+ }
+
/*
* Every activity, known or unknown, should have
* at least one item and sub-item.
* @file Name of file being read.
* @file_magic file_magic structure filled with file magic header data.
* @vol_act_nr Number of volatile activities structures to read.
+ * @endian_mismatch
+ * TRUE if file's data don't match current machine's endianness.
+ * @arch_64 TRUE if file's data come from a 64 bit machine.
*
* RETURNS:
* New number of items.
*/
__nr_t read_vol_act_structures(int ifd, struct activity *act[], char *file,
struct file_magic *file_magic,
- unsigned int vol_act_nr)
+ unsigned int vol_act_nr, int endian_mismatch,
+ int arch_64)
{
struct file_activity file_act;
int item_nr = 0;
sa_fread(ifd, &file_act, FILE_ACTIVITY_SIZE, HARD_SIZE);
+ /* Normalize endianness for file_activity structures */
+ if (endian_mismatch) {
+ swap_struct(act_types_nr, &file_act, arch_64);
+ }
+
if (file_act.id) {
rc = reallocate_vol_act_structures(act, file_act.nr, file_act.id);
if ((rc == 0) && !item_nr) {
* @rtype Record type (R_RESTART or R_COMMENT).
* @ifd Input file descriptor.
* @rectime Structure where timestamp (expressed in local time or in UTC
- * depending on whether options -T/-t have been used or not) can
+ * depending on whether options -T/-t have been used or not) can
* be saved for current record.
* @loctime Structure where timestamp (expressed in local time) can be
* saved for current record. May be NULL.
* @file_magic file_magic structure filled with file magic header data.
* @file_hdr System activity file standard header.
* @act Array of activities.
- * @ofmt Pointer on report output format structure.
+ * @ofmt Pointer on report output format structure.
+ * @endian_mismatch
+ * TRUE if file's data don't match current machine's endianness.
+ * @arch_64 TRUE if file's data come from a 64 bit machine.
*
* OUT:
- * @rectime Structure where timestamp (expressed in local time
- * or in UTC) has been saved.
- * @loctime Structure where timestamp (expressed in local time)
- * has been saved (if requested).
+ * @rectime Structure where timestamp (expressed in local time or in UTC)
+ * has been saved.
+ * @loctime Structure where timestamp (expressed in local time) has been
+ * saved (if requested).
*
* RETURNS:
* 1 if the record has been successfully displayed, and 0 otherwise.
struct tstamp *tm_start, struct tstamp *tm_end, int rtype, int ifd,
struct tm *rectime, struct tm *loctime, char *file, int tab,
struct file_magic *file_magic, struct file_header *file_hdr,
- struct activity *act[], struct report_format *ofmt)
+ struct activity *act[], struct report_format *ofmt,
+ int endian_mismatch, int arch_64)
{
char cur_date[TIMESTAMP_LEN], cur_time[TIMESTAMP_LEN];
int dp = 1;
if (rtype == R_RESTART) {
/* Don't forget to read the volatile activities structures */
new_cpu_nr = read_vol_act_structures(ifd, act, file, file_magic,
- file_hdr->sa_vol_act_nr);
+ file_hdr->sa_vol_act_nr,
+ endian_mismatch, arch_64);
if (!dp)
return 0;
# define _(string) (string)
#endif
+extern int endian_mismatch;
+
/*
***************************************************************************
* Read and upgrade file's magic data section.
struct file_magic fm;
/* Open and read sa magic structure */
- sa_open_read_magic(fd, dfile, file_magic, TRUE);
+ sa_open_read_magic(fd, dfile, file_magic, TRUE, &endian_mismatch);
if ((file_magic->format_magic != FORMAT_MAGIC) &&
(file_magic->format_magic != PREVIOUS_FORMAT_MAGIC)) {
long interval = -1, count = 0;
+/* TRUE if data read from file don't match current machine's endianness */
+int endian_mismatch = FALSE;
+/* TRUE if file's data come from a 64 bit machine */
+int arch_64 = FALSE;
+
+int rec_types_nr[] = {RECORD_HEADER_ULL_NR, RECORD_HEADER_UL_NR, RECORD_HEADER_U_NR};
+
unsigned int flags = 0;
unsigned int dm_major; /* Device-mapper major number */
unsigned int format = 0; /* Output format */
*rtype = record_hdr[curr].record_type;
if (!eosaf) {
+ /* Normalize endianness for file_hdr structure */
+ if (endian_mismatch) {
+ swap_struct(rec_types_nr, &record_hdr[curr], arch_64);
+ }
+
if (*rtype == R_COMMENT) {
if (action & IGNORE_COMMENT) {
/* Ignore COMMENT record */
/* Display COMMENT record */
print_special_record(&record_hdr[curr], flags, &tm_start, &tm_end,
*rtype, ifd, rectime, loctime, file, tab,
- file_magic, &file_hdr, act, fmt[f_position]);
+ file_magic, &file_hdr, act, fmt[f_position],
+ endian_mismatch, arch_64);
}
}
else if (*rtype == R_RESTART) {
*/
if (!(action & DONT_READ_VOLATILE)) {
read_vol_act_structures(ifd, act, file, file_magic,
- file_hdr.sa_vol_act_nr);
+ file_hdr.sa_vol_act_nr,
+ endian_mismatch, arch_64);
}
if (action & SET_TIMESTAMPS) {
sa_get_record_timestamp_struct(flags, &record_hdr[curr],
/* Display RESTART record */
print_special_record(&record_hdr[curr], flags, &tm_start, &tm_end,
*rtype, ifd, rectime, loctime, file, tab,
- file_magic, &file_hdr, act, fmt[f_position]);
+ file_magic, &file_hdr, act, fmt[f_position],
+ endian_mismatch, arch_64);
}
}
else {
* So read now the extra fields.
*/
read_file_stat_bunch(act, curr, ifd, file_hdr.sa_act_nr,
- file_actlst);
+ file_actlst, endian_mismatch, arch_64);
sa_get_record_timestamp_struct(flags, &record_hdr[curr], rectime, loctime);
}
}
if (!eosaf && (record_hdr[curr].record_type == R_RESTART)) {
print_special_record(&record_hdr[curr], flags, &tm_start, &tm_end,
R_RESTART, ifd, rectime, loctime, file, 0,
- file_magic, &file_hdr, act, fmt[f_position]);
+ file_magic, &file_hdr, act, fmt[f_position],
+ endian_mismatch, arch_64);
}
}
while (!eosaf);
/* Prepare file for reading and read its headers */
ignore = ACCEPT_BAD_FILE_FORMAT(fmt[f_position]->options);
check_file_actlst(&ifd, dfile, act, &file_magic, &file_hdr,
- &file_actlst, id_seq, ignore);
+ &file_actlst, id_seq, ignore, &endian_mismatch, &arch_64);
/* Now pick up number of proc for this file */
cpu_nr = act[get_activity_position(act, A_CPU, EXIT_IF_NOT_FOUND)]->nr;
/* TRUE if a header line must be printed */
int dis = TRUE;
+/* TRUE if data read from file don't match current machine's endianness */
+int endian_mismatch = FALSE;
+/* TRUE if file's data come from a 64 bit machine */
+int arch_64 = FALSE;
unsigned int flags = 0;
unsigned int dm_major; /* Device-mapper major number */
char timestamp[2][TIMESTAMP_LEN];
+int rec_types_nr[] = {RECORD_HEADER_ULL_NR, RECORD_HEADER_UL_NR, RECORD_HEADER_U_NR};
unsigned long avg_count = 0;
* @file_actlst List of activities in file.
* @file Name of file being read.
* @file_magic file_magic structure filled with file magic header data.
+ * @endian_mismatch
+ * TRUE if file's data don't match current machine's endianness.
+ * @arch_64 TRUE if file's data come from a 64 bit machine.
*
* OUT:
* @curr Index in array for next sample statistics.
* @cnt Number of remaining lines of stats to write.
* @eosaf Set to TRUE if EOF (end of file) has been reached.
- * @reset Set to TRUE if last_uptime variable should be
- * reinitialized (used in next_slice() function).
+ * @reset Set to TRUE if last_uptime variable should be reinitialized
+ * (used in next_slice() function).
***************************************************************************
*/
void handle_curr_act_stats(int ifd, off_t fpos, int *curr, long *cnt, int *eosaf,
int rows, unsigned int act_id, int *reset,
struct file_activity *file_actlst, char *file,
- struct file_magic *file_magic)
+ struct file_magic *file_magic, int endian_mismatch,
+ int arch_64)
{
int p, reset_cd;
unsigned long lines = 0;
/* Display count lines of stats */
*eosaf = sa_fread(ifd, &record_hdr[*curr],
RECORD_HEADER_SIZE, SOFT_SIZE);
+
+ /* Normalize endianness for record_hdr structure */
+ if (endian_mismatch) {
+ swap_struct(rec_types_nr, &record_hdr[*curr], arch_64);
+ }
rtype = record_hdr[*curr].record_type;
if (!*eosaf && (rtype != R_RESTART) && (rtype != R_COMMENT)) {
/* Read the extra fields since it's not a special record */
- read_file_stat_bunch(act, *curr, ifd, file_hdr.sa_act_nr, file_actlst);
+ read_file_stat_bunch(act, *curr, ifd, file_hdr.sa_act_nr, file_actlst,
+ endian_mismatch, arch_64);
}
if ((lines >= rows) || !lines) {
next = print_special_record(&record_hdr[*curr], flags + S_F_LOCAL_TIME,
&tm_start, &tm_end, R_COMMENT, ifd,
&rectime, NULL, file, 0,
- file_magic, &file_hdr, act, &sar_fmt);
+ file_magic, &file_hdr, act, &sar_fmt,
+ endian_mismatch, arch_64);
if (next) {
/* A line of comment was actually displayed */
lines++;
/* Read file headers and activity list */
check_file_actlst(&ifd, from_file, act, &file_magic, &file_hdr,
- &file_actlst, id_seq, FALSE);
+ &file_actlst, id_seq, FALSE, &endian_mismatch, &arch_64);
/* Perform required allocations */
allocate_structures(act);
/* End of sa data file */
return;
+ /* Normalize endianness for file_hdr structure */
+ if (endian_mismatch) {
+ swap_struct(rec_types_nr, &record_hdr[0], arch_64);
+ }
+
rtype = record_hdr[0].record_type;
if ((rtype == R_RESTART) || (rtype == R_COMMENT)) {
print_special_record(&record_hdr[0], flags + S_F_LOCAL_TIME,
&tm_start, &tm_end, rtype, ifd,
&rectime, NULL, from_file, 0, &file_magic,
- &file_hdr, act, &sar_fmt);
+ &file_hdr, act, &sar_fmt, endian_mismatch, arch_64);
}
else {
/*
* So read now the extra fields.
*/
read_file_stat_bunch(act, 0, ifd, file_hdr.sa_act_nr,
- file_actlst);
+ file_actlst, endian_mismatch, arch_64);
if (sa_get_record_timestamp_struct(flags + S_F_LOCAL_TIME,
&record_hdr[0],
&rectime, NULL))
if (!HAS_MULTIPLE_OUTPUTS(act[p]->options)) {
handle_curr_act_stats(ifd, fpos, &curr, &cnt, &eosaf, rows,
act[p]->id, &reset, file_actlst,
- from_file, &file_magic);
+ from_file, &file_magic, endian_mismatch, arch_64);
}
else {
unsigned int optf, msk;
handle_curr_act_stats(ifd, fpos, &curr, &cnt,
&eosaf, rows, act[p]->id,
&reset, file_actlst,
- from_file, &file_magic);
+ from_file, &file_magic,
+ endian_mismatch, arch_64);
act[p]->opt_flags = optf;
}
}
do {
eosaf = sa_fread(ifd, &record_hdr[curr], RECORD_HEADER_SIZE,
SOFT_SIZE);
+
+ /* Normalize endianness for file_hdr structure */
+ if (endian_mismatch) {
+ swap_struct(rec_types_nr, &record_hdr[curr], arch_64);
+ }
rtype = record_hdr[curr].record_type;
+
if (!eosaf && (rtype != R_RESTART) && (rtype != R_COMMENT)) {
read_file_stat_bunch(act, curr, ifd, file_hdr.sa_act_nr,
- file_actlst);
+ file_actlst, endian_mismatch, arch_64);
}
else if (!eosaf && (rtype == R_COMMENT)) {
/* This was a COMMENT record: print it */
print_special_record(&record_hdr[curr], flags + S_F_LOCAL_TIME,
&tm_start, &tm_end, R_COMMENT, ifd,
&rectime, NULL, from_file, 0,
- &file_magic, &file_hdr, act, &sar_fmt);
+ &file_magic, &file_hdr, act, &sar_fmt,
+ endian_mismatch, arch_64);
}
}
while (!eosaf && (rtype != R_RESTART));
print_special_record(&record_hdr[curr], flags + S_F_LOCAL_TIME,
&tm_start, &tm_end, R_RESTART, ifd,
&rectime, NULL, from_file, 0,
- &file_magic, &file_hdr, act, &sar_fmt);
+ &file_magic, &file_hdr, act, &sar_fmt,
+ endian_mismatch, arch_64);
}
}
while (!eosaf);