/*
 * sar/sadc: Report system activity
 * (C) 1999-2015 by Sebastien Godard (sysstat <at> orange.fr)
 */

#ifndef _SA_H
#define _SA_H

#include <stdio.h>

#include "common.h"
#include "prealloc.h"
#include "rd_stats.h"
#include "rd_sensors.h"

/*
 ***************************************************************************
 * Activity identification values.
 ***************************************************************************
 */

/* Number of activities */
#define NR_ACT		38
/* The value below is used for sanity check */
#define MAX_NR_ACT	256

/* Number of functions used to count items */
#define NR_F_COUNT	11

/* Activities */
#define A_CPU		1
#define A_PCSW		2
#define A_IRQ		3
#define A_SWAP		4
#define A_PAGE		5
#define A_IO		6
#define A_MEMORY	7
#define A_KTABLES	8
#define A_QUEUE		9
#define A_SERIAL	10
#define A_DISK		11
#define A_NET_DEV	12
#define A_NET_EDEV	13
#define A_NET_NFS	14
#define A_NET_NFSD	15
#define A_NET_SOCK	16
#define A_NET_IP	17
#define A_NET_EIP	18
#define A_NET_ICMP	19
#define A_NET_EICMP	20
#define A_NET_TCP	21
#define A_NET_ETCP	22
#define A_NET_UDP	23
#define A_NET_SOCK6	24
#define A_NET_IP6	25
#define A_NET_EIP6	26
#define A_NET_ICMP6	27
#define A_NET_EICMP6	28
#define A_NET_UDP6	29
#define A_PWR_CPUFREQ	30
#define A_PWR_FAN	31
#define A_PWR_TEMP	32
#define A_PWR_IN	33
#define A_HUGE		34
#define A_PWR_WGHFREQ	35
#define A_PWR_USB	36
#define A_FILESYSTEM	37
#define A_NET_FC	38


/* Macro used to flag an activity that should be collected */
#define COLLECT_ACTIVITY(m)	act[get_activity_position(act, m, EXIT_IF_NOT_FOUND)]->options |= AO_COLLECTED

/* Macro used to flag an activity that should be selected */
#define SELECT_ACTIVITY(m)	act[get_activity_position(act, m, EXIT_IF_NOT_FOUND)]->options |= AO_SELECTED


/*
 ***************************************************************************
 * Flags.
 ***************************************************************************
 */

#define S_F_SINCE_BOOT		0x00000001
#define S_F_SA_ROTAT      	0x00000002
#define S_F_DEV_PRETTY		0x00000004
#define S_F_FORCE_FILE		0x00000008
#define S_F_INTERVAL_SET	0x00000010
#define S_F_TRUE_TIME		0x00000020
#define S_F_LOCK_FILE		0x00000040
#define S_F_SEC_EPOCH		0x00000080
#define S_F_HDR_ONLY		0x00000100
#define S_F_FILE_LOCKED		0x00000200
#define S_F_SA_YYYYMMDD		0x00000400
#define S_F_HORIZONTALLY	0x00000800
#define S_F_COMMENT		0x00001000
#define S_F_PERSIST_NAME	0x00002000
#define S_F_LOCAL_TIME		0x00004000

#define WANT_SINCE_BOOT(m)		(((m) & S_F_SINCE_BOOT)   == S_F_SINCE_BOOT)
#define WANT_SA_ROTAT(m)		(((m) & S_F_SA_ROTAT)     == S_F_SA_ROTAT)
#define USE_PRETTY_OPTION(m)		(((m) & S_F_DEV_PRETTY)   == S_F_DEV_PRETTY)
#define FORCE_FILE(m)			(((m) & S_F_FORCE_FILE)   == S_F_FORCE_FILE)
#define INTERVAL_SET(m)			(((m) & S_F_INTERVAL_SET) == S_F_INTERVAL_SET)
#define PRINT_TRUE_TIME(m)		(((m) & S_F_TRUE_TIME)    == S_F_TRUE_TIME)
#define LOCK_FILE(m)			(((m) & S_F_LOCK_FILE)    == S_F_LOCK_FILE)
#define PRINT_SEC_EPOCH(m)		(((m) & S_F_SEC_EPOCH)    == S_F_SEC_EPOCH)
#define DISPLAY_HDR_ONLY(m)		(((m) & S_F_HDR_ONLY)     == S_F_HDR_ONLY)
#define FILE_LOCKED(m)			(((m) & S_F_FILE_LOCKED)  == S_F_FILE_LOCKED)
#define USE_SA_YYYYMMDD(m)		(((m) & S_F_SA_YYYYMMDD)  == S_F_SA_YYYYMMDD)
#define DISPLAY_HORIZONTALLY(m)		(((m) & S_F_HORIZONTALLY) == S_F_HORIZONTALLY)
#define DISPLAY_COMMENT(m)		(((m) & S_F_COMMENT)      == S_F_COMMENT)
#define DISPLAY_PERSIST_NAME_S(m)	(((m) & S_F_PERSIST_NAME) == S_F_PERSIST_NAME)
#define PRINT_LOCAL_TIME(m)		(((m) & S_F_LOCAL_TIME)   == S_F_LOCAL_TIME)

#define AO_F_NULL		0x00000000

/* Output flags for options -R / -r / -S */
#define AO_F_MEM_DIA		0x00000001
#define AO_F_MEM_AMT		0x00000002
#define AO_F_MEM_SWAP		0x00000004
/* AO_F_MEM_ALL: See opt_flags in struct activity below */
#define AO_F_MEM_ALL		(AO_F_MEM_AMT << 8)

#define DISPLAY_MEMORY(m)	(((m) & AO_F_MEM_DIA)     == AO_F_MEM_DIA)
#define DISPLAY_MEM_AMT(m)	(((m) & AO_F_MEM_AMT)     == AO_F_MEM_AMT)
#define DISPLAY_SWAP(m)		(((m) & AO_F_MEM_SWAP)    == AO_F_MEM_SWAP)
#define DISPLAY_MEM_ALL(m)	(((m) & AO_F_MEM_ALL)     == AO_F_MEM_ALL)

/* Output flags for option -u [ ALL ] */
#define AO_F_CPU_DEF		0x00000001
#define AO_F_CPU_ALL		0x00000002

#define DISPLAY_CPU_DEF(m)	(((m) & AO_F_CPU_DEF)     == AO_F_CPU_DEF)
#define DISPLAY_CPU_ALL(m)	(((m) & AO_F_CPU_ALL)     == AO_F_CPU_ALL)

/* Output flags for option -d */
#define AO_F_DISK_PART		0x00000001

#define COLLECT_PARTITIONS(m)	(((m) & AO_F_DISK_PART)   == AO_F_DISK_PART)

/* Output flags for option -F */
#define AO_F_MOUNT		0x00000001

#define DISPLAY_MOUNT(m)	(((m) & AO_F_MOUNT)       == AO_F_MOUNT)

/*
 ***************************************************************************
 * Various keywords and constants.
 ***************************************************************************
 */

/* Keywords */
#define K_XALL		"XALL"
#define K_SUM		"SUM"
#define K_DEV		"DEV"
#define K_EDEV		"EDEV"
#define K_NFS		"NFS"
#define K_NFSD		"NFSD"
#define K_SOCK		"SOCK"
#define K_IP		"IP"
#define K_EIP		"EIP"
#define K_ICMP		"ICMP"
#define K_EICMP		"EICMP"
#define K_TCP		"TCP"
#define K_ETCP		"ETCP"
#define K_UDP		"UDP"
#define K_SOCK6		"SOCK6"
#define K_IP6		"IP6"
#define K_EIP6		"EIP6"
#define K_ICMP6		"ICMP6"
#define K_EICMP6	"EICMP6"
#define K_UDP6		"UDP6"
#define K_CPU		"CPU"
#define K_FAN		"FAN"
#define K_TEMP		"TEMP"
#define K_IN		"IN"
#define K_FREQ		"FREQ"
#define K_MOUNT		"MOUNT"
#define K_FC		"FC"

#define K_INT		"INT"
#define K_DISK		"DISK"
#define K_XDISK		"XDISK"
#define K_SNMP		"SNMP"
#define K_IPV6		"IPV6"
#define K_POWER		"POWER"
#define K_USB		"USB"

/* Groups of activities */
#define G_DEFAULT	0x00
#define G_INT		0x01
#define G_DISK		0x02
#define G_SNMP		0x04
#define G_IPV6		0x08
#define G_POWER		0x10
#define G_XDISK		0x20

/* sadc program */
#define SADC		"sadc"

/* Time must have the format HH:MM:SS with HH in 24-hour format */
#define DEF_TMSTART	"08:00:00"
#define DEF_TMEND	"18:00:00"

/*
 * Macro used to define activity bitmap size.
 * All those bitmaps have an additional bit used for global activity
 * (eg. CPU "all" or total number of interrupts). That's why we do "(m) + 1".
 */
#define BITMAP_SIZE(m)	((((m) + 1) / 8) + 1)

#define UTSNAME_LEN	65
#define TIMESTAMP_LEN	16
#define HEADER_LINE_LEN	512

/*
 * Define upper limit for various items.
 * Made necessary because we have to check the number of
 * items for each activity when we read a (possibly tainted)
 * sa data file.
 */
#define MAX_NR_SERIAL_LINES	512
#define MAX_NR_DISKS		8192
#define MAX_NR_IFACES		512
#define MAX_NR_FANS		128
#define MAX_NR_TEMP_SENSORS	128
#define MAX_NR_IN_SENSORS	128
#define MAX_NR_USB		1024
#define MAX_NR_FS		8192
#define MAX_NR_FCHOSTS		8192

/* NR_MAX is the upper limit used for unknown activities */
#define NR_MAX		65536
#define NR2_MAX		128

/* Maximum number of args that can be passed to sadc */
#define MAX_ARGV_NR	32

/* Miscellaneous constants */
#define USE_SADC		0
#define USE_SA_FILE		1
#define NO_TM_START		0
#define NO_TM_END		0
#define NO_RESET		0
#define NON_FATAL		0
#define FATAL			1
#define C_SAR			0
#define C_SADF			1
#define ALL_ACTIVITIES		~0U
#define EXIT_IF_NOT_FOUND	1
#define RESUME_IF_NOT_FOUND	0

#define SOFT_SIZE	0
#define HARD_SIZE	1

#define CLOSE_XML_MARKUP	0
#define OPEN_XML_MARKUP		1

#define CLOSE_JSON_MARKUP	0
#define OPEN_JSON_MARKUP	1

#define COUNT_ACTIVITIES	0
#define COUNT_OUTPUTS		1


/*
 ***************************************************************************
 * Generic description of an activity.
 ***************************************************************************
 */

/* Activity options */
#define AO_NULL			0x00
/*
 * Indicate that corresponding activity should be collected by sadc.
 */
#define AO_COLLECTED		0x01
/*
 * Indicate that corresponding activity should be displayed by sar.
 */
#define AO_SELECTED		0x02
/*
 * When appending data to a file, the number of items (for every activity)
 * is forced to that of the file (number of network interfaces, serial lines,
 * etc.) Exceptions are volatile activities (like A_CPU) whose number of items
 * is related to the number of CPUs: If current machine has a different number
 * of CPU than that of the file (but is equal to sa_last_cpu_nr) then data
 * will be appended with a number of items equal to that of the machine.
 */
#define AO_VOLATILE		0x04
/*
 * Indicate that the interval of time, given to f_print() function
 * displaying statistics, should be the interval of time in jiffies
 * multiplied by the number of processors.
 */
#define AO_GLOBAL_ITV		0x08
/*
 * This flag should be set for every activity closing a markup used
 * by several activities. Used by sadf f_xml_print() functions to
 * display XML output.
 */
#define AO_CLOSE_MARKUP		0x10
/*
 * Indicate that corresponding activity has multiple different
 * output formats. This is the case for example for memory activity
 * with options -r and -R.
 */
#define AO_MULTIPLE_OUTPUTS	0x20

#define IS_COLLECTED(m)		(((m) & AO_COLLECTED)        == AO_COLLECTED)
#define IS_SELECTED(m)		(((m) & AO_SELECTED)         == AO_SELECTED)
#define IS_VOLATILE(m)		(((m) & AO_VOLATILE)         == AO_VOLATILE)
#define NEED_GLOBAL_ITV(m)	(((m) & AO_GLOBAL_ITV)       == AO_GLOBAL_ITV)
#define CLOSE_MARKUP(m)		(((m) & AO_CLOSE_MARKUP)     == AO_CLOSE_MARKUP)
#define HAS_MULTIPLE_OUTPUTS(m)	(((m) & AO_MULTIPLE_OUTPUTS) == AO_MULTIPLE_OUTPUTS)

/* Type for all functions counting items */
#define __nr_t		int
/* Type for all functions reading statistics */
#define __read_funct_t	void
/* Type for all functions displaying statistics */
#define __print_funct_t void

#define _buf0	buf[0]

/* Structure used to define a bitmap needed by an activity */
struct act_bitmap {
	/*
	 * Bitmap for activities that need one. Remember to allocate it
	 * before use!
	 */
	unsigned char *b_array;
	/*
	 * Size of the bitmap in bits. In fact, bitmap is sized to b_size + 1
	 * to take into account CPU "all"
	 */
	int b_size;
};

/*
 * Structure used to define an activity.
 * Note: This structure can be modified without changing the format of data files.
 */
struct activity {
	/*
	 * This variable contains the identification value (A_...) for this activity.
	 */
	unsigned int id;
	/*
	 * Activity options (AO_...)
	 */
	unsigned int options;
	/*
	 * Activity magical number. This number changes when activity format in file
	 * is no longer compatible with the format of that same activity from
	 * previous versions.
	 */
	unsigned int magic;
	/*
	 * An activity belongs to a group (and only one).
	 * Groups are those selected with option -S of sadc.
	 */
	unsigned int group;
	/*
	 * Index in f_count[] array to determine function used to count
	 * the number of items (serial lines, network interfaces, etc.) -> @nr
	 * Such a function should _always_ return a value greater than
	 * or equal to 0.
	 *
	 * A value of -1 indicates that the number of items
	 * is a constant (and @nr is set to this value).
	 *
	 * These functions are called even if corresponding activities have not
	 * been selected, to make sure that all items have been calculated
	 * (including #CPU, etc.)
	 */
	int f_count_index;
	/*
	 * The f_count2() function is used to count the number of
	 * sub-items -> @nr2
	 * Such a function should _always_ return a value greater than
	 * or equal to 0.
	 *
	 * A NULL value for this function pointer indicates that the number of items
	 * is a constant (and @nr2 is set to this value).
	 */
	__nr_t (*f_count2) (struct activity *);
	/*
	 * This function reads the relevant file and fill the buffer
	 * with statistics corresponding to given activity.
	 */
	__read_funct_t (*f_read) (struct activity *);
	/*
	 * This function displays activity statistics onto the screen.
	 */
	__print_funct_t (*f_print) (struct activity *, int, int, unsigned long long);
	/*
	 * This function displays average activity statistics onto the screen.
	 */
	__print_funct_t (*f_print_avg) (struct activity *, int, int, unsigned long long);
	/*
	 * This function is used by sadf to display activity in a format that can
	 * easily be ingested by a relational database, or a format that can be
	 * handled by pattern processing commands like "awk".
	 */
	__print_funct_t (*f_render) (struct activity *, int, char *, int, unsigned long long);
	/*
	 * This function is used by sadf to display activity statistics in XML.
	 */
	__print_funct_t (*f_xml_print) (struct activity *, int, int, unsigned long long);
	/*
	 * This function is used by sadf to display activity statistics in JSON.
	 */
	__print_funct_t (*f_json_print) (struct activity *, int, int, unsigned long long);
	/*
	 * Header string displayed by sadf -d.
	 * Header lines for each output (for activities with multiple outputs) are
	 * separated with a '|' character.
	 * For a given output, the first field corresponding to extended statistics
	 * (eg. -r ALL) begins with a '&' character.
	 */
	char *hdr_line;
	/*
	 * Name of activity.
	 */
	char *name;
	/*
	 * Number of items on the system.
	 * A negative value (-1) is the default value and indicates that this number
	 * has still not been calculated by the f_count() function.
	 * A value of 0 means that this number has been calculated, but no items have
	 * been found.
	 * A positive value (>0) has either been calculated or is a constant.
	 */
	__nr_t nr;
	/*
	 * Number of sub-items on the system.
	 * @nr2 is in fact the second dimension of a matrix of items, the first
	 * one being @nr. @nr is the number of lines, and @nr2 the number of columns.
	 * A negative value (-1) is the default value and indicates that this number
	 * has still not been calculated by the f_count2() function.
	 * A value of 0 means that this number has been calculated, but no sub-items have
	 * been found.
	 * A positive value (>0) has either been calculated or is a constant.
	 * Rules:
	 * 1) IF @nr2 = 0 THEN @nr = 0
	 *    Note: If @nr = 0, then @nr2 is undetermined (may be -1, 0 or >0).
	 * 2) IF @nr > 0 THEN @nr2 > 0.
	 *    Note: If @nr2 > 0 then @nr is undetermined (may be -1, 0 or >0).
	 * 3) IF @nr <= 0 THEN @nr2 = -1 (this is the default value for @nr2,
	 * meaning that it has not been calculated).
	 */
	__nr_t nr2;
	/*
	 * Maximum number of elements that sar can handle for this item.
	 * NB: The maximum number of elements that sar can handle for sub-items
	 * is NR2_MAX.
	 */
	__nr_t nr_max;
	/*
	 * Size of an item.
	 * This is the size of the corresponding structure, as read from or written
	 * to a file, or read from or written by the data collector.
	 */
	int fsize;
	/*
	 * Size of an item.
	 * This is the size of the corresponding structure as mapped into memory.
	 * @msize can be different from @fsize when data are read from or written to
	 * a data file from a different sysstat version.
	 */
	int msize;
	/*
	 * Optional flags for activity. This is eg. used when AO_MULTIPLE_OUTPUTS
	 * option is set.
	 * 0x0001 - 0x0080 : Multiple outputs (eg. AO_F_MEM_AMT, AO_F_MEM_SWAP...)
	 * 0x0100 - 0x8000 : If bit set then display complete header (hdr_line) for
	 *                   corresponding output
	 * 0x010000+       : Optional flags
	 */
	unsigned int opt_flags;
	/*
	 * Buffers that will contain the statistics read. Its size is @nr * @nr2 * @size each.
	 * [0]: used by sadc.
	 * [0] and [1]: current/previous statistics values (used by sar).
	 * [2]: Used by sar to save first collected stats (used later to
	 * compute average).
	 */
	void *buf[3];
	/*
	 * Bitmap for activities that need one. Such a bitmap is needed by activity
	 * if @bitmap is not NULL.
	 */
	struct act_bitmap *bitmap;
};

/*
 ***************************************************************************
 * Definitions of header structures.
 *
 * Format of system activity data files:
 *	 __
 *	|
 *	| file_magic structure
 *	|
 * 	|--
 *	|
 * 	| file_header structure
 * 	|
 * 	|--                         --|
 * 	|                             |
 * 	| file_activity structure     | * sa_act_nr
 * 	|                             |
 * 	|--                         --|
 * 	|                             |
 * 	| record_header structure     |
 * 	|                             |
 * 	|--                           | * <count>
 * 	|                             |
 * 	| Statistics structures...(*) |
 * 	|                             |
 * 	|--                         --|
 *
 * (*)Note: If it's a special record, we may find a comment instead of
 * statistics (R_COMMENT record type) or, if it's a R_RESTART record type,
 * <sa_nr_vol_act> structures (of type file_activity) for the volatile
 * activities.
 ***************************************************************************
 */

/*
 * Sysstat magic number. Should never be modified.
 * Indicate that the file was created by sysstat.
 */
#define SYSSTAT_MAGIC	0xd596

/*
 * Datafile format magic number.
 * Modified to indicate that the format of the file is
 * no longer compatible with that of previous sysstat versions.
 */
#define FORMAT_MAGIC	0x2173

/* Previous datafile format magic number used by older sysstat versions */
#define PREVIOUS_FORMAT_MAGIC	0x2171

/* Padding in file_magic structure. See below. */
#define FILE_MAGIC_PADDING	63

/* Structure for file magic header data */
struct file_magic {
	/*
	 * This field identifies the file as a file created by sysstat.
	 */
	unsigned short sysstat_magic;
	/*
	 * The value of this field varies whenever datafile format changes.
	 */
	unsigned short format_magic;
	/*
	 * Sysstat version used to create the file.
	 */
	unsigned char sysstat_version;
	unsigned char sysstat_patchlevel;
	unsigned char sysstat_sublevel;
	unsigned char sysstat_extraversion;
	/*
	 * Size of file's header (size of file_header structure used by file).
	 */
	unsigned int header_size;
	/*
	 * Set to non zero if data file has been converted with "sadf -c" from
	 * an old format (version x.y.z) to a newest format (version X.Y.Z).
	 * In this case, the value is: Y*16 + Z + 1.
	 * The FORMAT_MAGIC value of the file can be used to determine X.
	 */
	unsigned char upgraded;
	/*
	 * Padding. Reserved for future use while avoiding a format change.
	 */
	unsigned char pad[FILE_MAGIC_PADDING];
};

#define FILE_MAGIC_SIZE	(sizeof(struct file_magic))


/* Header structure for system activity data file */
struct file_header {
	/*
	 * Timestamp in seconds since the epoch.
	 */
	unsigned long sa_ust_time	__attribute__ ((aligned (8)));
	/*
	 * Number of CPU items (1 .. CPU_NR + 1) for the last sample in file.
	 */
	unsigned int sa_last_cpu_nr	__attribute__ ((aligned (8)));
	/*
	 * Number of activities saved in file.
	 */
	unsigned int sa_act_nr;
	/*
	 * Number of volatile activities in file. This is the number of
	 * file_activity structures saved after each restart mark in file.
	 */
	unsigned int sa_vol_act_nr;
	/*
	 * Current day, month and year.
	 * No need to save DST (Daylight Saving Time) flag, since it is not taken
	 * into account by the strftime() function used to print the timestamp.
	 */
	unsigned char sa_day;
	unsigned char sa_month;
	unsigned char sa_year;
	/*
	 * Size of a long integer. Useful to know the architecture on which
	 * the datafile was created.
	 */
	char sa_sizeof_long;
	/*
	 * Operating system name.
	 */
	char sa_sysname[UTSNAME_LEN];
	/*
	 * Machine hostname.
	 */
	char sa_nodename[UTSNAME_LEN];
	/*
	 * Operating system release number.
	 */
	char sa_release[UTSNAME_LEN];
	/*
	 * Machine architecture.
	 */
	char sa_machine[UTSNAME_LEN];
};

#define FILE_HEADER_SIZE	(sizeof(struct file_header))
/* The value below is used for sanity check */
#define MAX_FILE_HEADER_SIZE	8192


/*
 * Base magical number for activities.
 */
#define ACTIVITY_MAGIC_BASE	0x8a
/*
 * Magical value used for activities with
 * unknown format (used for sadf -H only).
 */
#define ACTIVITY_MAGIC_UNKNOWN	0x89

/* List of activities saved in file */
struct file_activity {
	/*
	 * Identification value of activity.
	 */
	unsigned int id		__attribute__ ((aligned (4)));
	/*
	 * Activity magical number.
	 */
	unsigned int magic	__attribute__ ((packed));
	/*
	 * Number of items for this activity.
	 */
	__nr_t nr		__attribute__ ((packed));
	/*
	 * Number of sub-items for this activity.
	 */
	__nr_t nr2		__attribute__ ((packed));
	/*
	 * Size of an item structure.
	 */
	int size		__attribute__ ((packed));
};

#define FILE_ACTIVITY_SIZE	(sizeof(struct file_activity))


/* Record type */
/*
 * R_STATS means that this is a record of statistics.
 */
#define R_STATS		1
/*
 * R_RESTART means that this is a special record containing
 * a LINUX RESTART message.
 */
#define R_RESTART	2
/*
 * R_LAST_STATS warns sar that this is the last record to be written
 * to file before a file rotation, and that the next data to come will
 * be a header file.
 * Such a record is tagged R_STATS anyway before being written to file.
 */
#define R_LAST_STATS	3
/*
 * R_COMMENT means that this is a special record containing
 * a comment.
 */
#define R_COMMENT	4

/* Maximum length of a comment */
#define MAX_COMMENT_LEN	64

/* Header structure for every record */
struct record_header {
	/*
	 * Machine uptime (multiplied by the # of proc).
	 */
	unsigned long long uptime	__attribute__ ((aligned (16)));
	/*
	 * Uptime reduced to one processor. Always set, even on UP machines.
	 */
	unsigned long long uptime0	__attribute__ ((aligned (16)));
	/*
	 * Timestamp (number of seconds since the epoch).
	 */
	unsigned long ust_time		__attribute__ ((aligned (16)));
	/*
	 * Record type: R_STATS, R_RESTART,...
	 */
	unsigned char record_type	__attribute__ ((aligned (8)));
	/*
	 * Timestamp: Hour (0-23), minute (0-59) and second (0-59).
	 * Used to determine TRUE time (immutable, non locale dependent time).
	 */
	unsigned char hour;
	unsigned char minute;
	unsigned char second;
};

#define RECORD_HEADER_SIZE	(sizeof(struct record_header))


/*
 ***************************************************************************
 * Macro functions definitions.
 *
 * Note: Using 'do ... while' makes the macros safer to use
 * (remember that macro use is followed by a semicolon).
 ***************************************************************************
 */

/* Close file descriptors */
#define CLOSE_ALL(_fd_)		do {			\
					close(_fd_[0]); \
					close(_fd_[1]); \
				} while (0)

#define CLOSE(_fd_)		if (_fd_ >= 0)		\
					close(_fd_)


/*
 ***************************************************************************
 * Various structure definitions.
 ***************************************************************************
 */

/* Structure for timestamps */
struct tstamp {
	int tm_sec;
	int tm_min;
	int tm_hour;
	int use;
};


/*
 ***************************************************************************
 * Functions prototypes.
 ***************************************************************************
 */

/* Functions used to count number of items */
extern __nr_t
	wrap_get_cpu_nr(struct activity *);
extern __nr_t
	wrap_get_irq_nr(struct activity *);
extern __nr_t
	wrap_get_serial_nr(struct activity *);
extern __nr_t
	wrap_get_disk_nr(struct activity *);
extern __nr_t
	wrap_get_iface_nr(struct activity *);
extern __nr_t
	wrap_get_fan_nr(struct activity *);
extern __nr_t
	wrap_get_temp_nr(struct activity *);
extern __nr_t
	wrap_get_in_nr(struct activity *);
extern __nr_t
	wrap_get_freq_nr(struct activity *);
extern __nr_t
	wrap_get_usb_nr(struct activity *);
extern __nr_t
	wrap_get_filesystem_nr(struct activity *);
extern __nr_t
	wrap_get_fchost_nr(struct activity *);

/* Functions used to read activities statistics */
extern __read_funct_t
	wrap_read_stat_cpu(struct activity *);
extern __read_funct_t
	wrap_read_stat_pcsw(struct activity *);
extern __read_funct_t
	wrap_read_stat_irq(struct activity *);
extern __read_funct_t
	wrap_read_swap(struct activity *);
extern __read_funct_t
	wrap_read_paging(struct activity *);
extern __read_funct_t
	wrap_read_io(struct activity *);
extern __read_funct_t
	wrap_read_meminfo(struct activity *);
extern __read_funct_t
	wrap_read_kernel_tables(struct activity *);
extern __read_funct_t
	wrap_read_loadavg(struct activity *);
extern __read_funct_t
	wrap_read_tty_driver_serial(struct activity *);
extern __read_funct_t
	wrap_read_disk(struct activity *);
extern __read_funct_t
	wrap_read_net_dev(struct activity *);
extern __read_funct_t
	wrap_read_net_edev(struct activity *);
extern __read_funct_t
	wrap_read_net_nfs(struct activity *);
extern __read_funct_t
	wrap_read_net_nfsd(struct activity *);
extern __read_funct_t
	wrap_read_net_sock(struct activity *);
extern __read_funct_t
	wrap_read_net_ip(struct activity *);
extern __read_funct_t
	wrap_read_net_eip(struct activity *);
extern __read_funct_t
	wrap_read_net_icmp(struct activity *);
extern __read_funct_t
	wrap_read_net_eicmp(struct activity *);
extern __read_funct_t
	wrap_read_net_tcp(struct activity *);
extern __read_funct_t
	wrap_read_net_etcp(struct activity *);
extern __read_funct_t
	wrap_read_net_udp(struct activity *);
extern __read_funct_t
	wrap_read_net_sock6(struct activity *);
extern __read_funct_t
	wrap_read_net_ip6(struct activity *);
extern __read_funct_t
	wrap_read_net_eip6(struct activity *);
extern __read_funct_t
	wrap_read_net_icmp6(struct activity *);
extern __read_funct_t
	wrap_read_net_eicmp6(struct activity *);
extern __read_funct_t
	wrap_read_net_udp6(struct activity *);
extern __read_funct_t
	wrap_read_cpuinfo(struct activity *);
extern __read_funct_t
	wrap_read_fan(struct activity *);
extern __read_funct_t
	wrap_read_temp(struct activity *);
extern __read_funct_t
	wrap_read_in(struct activity *);
extern __read_funct_t
	wrap_read_meminfo_huge(struct activity *);
extern __read_funct_t
	wrap_read_time_in_state(struct activity *);
extern __read_funct_t
	wrap_read_bus_usb_dev(struct activity *);
extern __read_funct_t
	wrap_read_filesystem(struct activity *);
extern __read_funct_t
	wrap_read_fchost(struct activity *);

/* Other functions */
extern void
	allocate_bitmaps(struct activity * []);
extern void
	allocate_structures(struct activity * []);
extern int
	check_alt_sa_dir(char *, int, int);
extern int
	check_disk_reg(struct activity *, int, int, int);
extern void
	check_file_actlst(int *, char *, struct activity * [], struct file_magic *,
			  struct file_header *, struct file_activity **,
			  unsigned int [], int);
extern unsigned int
	check_net_dev_reg(struct activity *, int, int, unsigned int);
extern unsigned int
	check_net_edev_reg(struct activity *, int, int, unsigned int);
extern double
	compute_ifutil(struct stats_net_dev *, double, double);
extern void
	copy_structures(struct activity * [], unsigned int [],
			struct record_header [], int, int);
extern int
	datecmp(struct tm *, struct tstamp *);
extern void
	display_sa_file_version(FILE *, struct file_magic *);
extern void
	enum_version_nr(struct file_magic *);
extern void
	free_bitmaps(struct activity * []);
extern void
	free_structures(struct activity * []);
extern int
	get_activity_nr(struct activity * [], unsigned int, int);
extern int
	get_activity_position(struct activity * [], unsigned int, int);
extern char *
	get_devname(unsigned int, unsigned int, int);
extern void
	get_file_timestamp_struct(unsigned int, struct tm *, struct file_header *);
extern void
	get_itv_value(struct record_header *, struct record_header *,
		      unsigned int, unsigned long long *, unsigned long long *);
extern void
	handle_invalid_sa_file(int *, struct file_magic *, char *, int);
extern int
	next_slice(unsigned long long, unsigned long long, int, long);
extern int
	parse_sar_opt(char * [], int *, struct activity * [], unsigned int *, int);
extern int
	parse_sar_I_opt(char * [], int *, struct activity * []);
extern int
	parse_sa_P_opt(char * [], int *, unsigned int *, struct activity * []);
extern int
	parse_sar_m_opt(char * [], int *, struct activity * []);
extern int
	parse_sar_n_opt(char * [], int *, struct activity * []);
extern int
	parse_timestamp(char * [], int *, struct tstamp *, const char *);
extern void
	print_report_hdr(unsigned int, struct tm *, struct file_header *, int);
extern void
	read_file_stat_bunch(struct activity * [], int, int, int, struct file_activity *);
extern __nr_t
	read_vol_act_structures(int, struct activity * [], char *, struct file_magic *,
			        unsigned int);
extern int
	reallocate_vol_act_structures(struct activity * [], unsigned int, unsigned int);
extern void
	replace_nonprintable_char(int, char *);
extern int
	sa_fread(int, void *, int, int);
extern int
	sa_open_read_magic(int *, char *, struct file_magic *, int);
extern void
	select_all_activities(struct activity * []);
extern void
	select_default_activity(struct activity * []);
extern void
	set_bitmap(unsigned char [], unsigned char, unsigned int);
extern void
	set_default_file(char *, int, int);
extern void
	set_hdr_rectime(unsigned int, struct tm *, struct file_header *);

#endif  /* _SA_H */
