Commit message: Fix #196 and #199: Out of bound reads security issues

Check args before calling memmove() and memset() in remap_struct()
function to avoid out of bound reads which would possibly lead to
unknown code execution and/or sadf command crash.

Signed-off-by: Sebastien GODARD <sysstat@users.noreply.github.com>
CVE: CVE-2018-19416
CWE: CWE-125
Vulnerability description: An issue was discovered in sysstat 12.1.1. The remap_struct function in sa_common.c has an out-of-bounds read during a memmove call, as demonstrated by sadf.

Project: sysstat
File: sar.c

void print_read_error(int error_code)
{
	switch (error_code) {

		case END_OF_DATA_UNEXPECTED:
			/* Happens when the data collector doesn't send enough data */
			fprintf(stderr, _("End of data collecting unexpected\n"));
			break;

		default:
			/* Strange data sent by sadc...! */
			fprintf(stderr, _("Inconsistent input data\n"));
			break;
	}
	exit(3);
}

Project: sysstat
File: sa_common.c

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 *endian_mismatch, int *arch_64)
{
	int i, j, k, p;
	struct file_activity *fal;
	void *buffer = NULL;

	/* Open sa data file and read its magic structure */
	if (sa_open_read_magic(ifd, dfile, file_magic, ignore, endian_mismatch, TRUE) < 0)
		/*
		 * Not current sysstat's format.
		 * Return now so that sadf -H can display at least
		 * file's version and magic number.
		 */
		return;

	/*
	 * We know now that we have a *compatible* sysstat datafile format
	 * (correct FORMAT_MAGIC value), and in this case, we should have
	 * checked header_size value. Anyway, with a corrupted datafile,
	 * this may not be the case. So check again.
	 */
	if ((file_magic->header_size <= MIN_FILE_HEADER_SIZE) ||
	    (file_magic->header_size > MAX_FILE_HEADER_SIZE)) {
#ifdef DEBUG
		fprintf(stderr, "%s: header_size=%u\n",
			__FUNCTION__, file_magic->header_size);
#endif
		goto format_error;
	}

	/* Allocate buffer for file_header structure */
	SREALLOC(buffer, char, file_magic->header_size);

	/* Read sa data file standard header and allocate activity list */
	sa_fread(*ifd, buffer, (size_t) file_magic->header_size, HARD_SIZE, UEOF_STOP);
	/*
	 * Data file header size (file_magic->header_size) may be greater or
	 * smaller than FILE_HEADER_SIZE. Remap the fields of the file header
	 * then copy its contents to the expected  structure.
	 */
	remap_struct(hdr_types_nr, file_magic->hdr_types_nr, buffer,
		     file_magic->header_size, FILE_HEADER_SIZE, file_magic->header_size);
	memcpy(file_hdr, buffer, FILE_HEADER_SIZE);
	free(buffer);
	buffer = NULL;

	/* Tell that data come from a 64 bit machine */
	*arch_64 = (file_hdr->sa_sizeof_long == SIZEOF_LONG_64BIT);

	/* Normalize endianness for file_hdr structure */
	if (*endian_mismatch) {
		swap_struct(hdr_types_nr, file_hdr, *arch_64);
	}

	/*
	 * Sanity checks.
	 * NB: Compare against MAX_NR_ACT and not NR_ACT because
	 * we are maybe reading a datafile from a future sysstat version
	 * with more activities than known today.
	 */
	if ((file_hdr->sa_act_nr > MAX_NR_ACT) ||
	    (file_hdr->act_size > MAX_FILE_ACTIVITY_SIZE) ||
	    (file_hdr->rec_size > MAX_RECORD_HEADER_SIZE) ||
	    (MAP_SIZE(file_hdr->act_types_nr) > file_hdr->act_size) ||
	    (MAP_SIZE(file_hdr->rec_types_nr) > file_hdr->rec_size)) {
#ifdef DEBUG
		fprintf(stderr, "%s: sa_act_nr=%d act_size=%u rec_size=%u map_size(act)=%u map_size(rec)=%u\n",
			__FUNCTION__, file_hdr->sa_act_nr, file_hdr->act_size, file_hdr->rec_size,
			MAP_SIZE(file_hdr->act_types_nr), MAP_SIZE(file_hdr->rec_types_nr));
#endif
		/* Maybe a "false positive" sysstat datafile? */
		goto format_error;
	}

	SREALLOC(buffer, char, file_hdr->act_size);
	SREALLOC(*file_actlst, struct file_activity, FILE_ACTIVITY_SIZE * file_hdr->sa_act_nr);
	fal = *file_actlst;

	/* Read activity list */
	j = 0;
	for (i = 0; i < file_hdr->sa_act_nr; i++, fal++) {

		/* Read current file_activity structure from file */
		sa_fread(*ifd, buffer, (size_t) file_hdr->act_size, HARD_SIZE, UEOF_STOP);
		/*
		* Data file_activity size (file_hdr->act_size) may be greater or
		* smaller than FILE_ACTIVITY_SIZE. Remap the fields of the file's structure
		* then copy its contents to the expected structure.
		*/
		remap_struct(act_types_nr, file_hdr->act_types_nr, buffer,
			     file_hdr->act_size, FILE_ACTIVITY_SIZE, file_hdr->act_size);
		memcpy(fal, buffer, FILE_ACTIVITY_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.
		 * Also check that the number of items and sub-items
		 * doesn't exceed a max value. This is necessary
		 * because we will use @nr and @nr2 to
		 * allocate memory to read the file contents. So we
		 * must make sure the file is not corrupted.
		 * NB: Another check will be made below for known
		 * activities which have each a specific max value.
		 */
		if ((fal->nr < 1) || (fal->nr2 < 1) ||
		    (fal->nr > NR_MAX) || (fal->nr2 > NR2_MAX)) {
#ifdef DEBUG
			fprintf(stderr, "%s: id=%d nr=%d nr2=%d\n",
				__FUNCTION__, fal->id, fal->nr, fal->nr2);
#endif
			goto format_error;
		}

		if ((p = get_activity_position(act, fal->id, RESUME_IF_NOT_FOUND)) < 0)
			/* Unknown activity */
			continue;

		if (act[p]->magic != fal->magic) {
			/* Bad magical number */
			if (ignore) {
				/*
				 * This is how sadf -H knows that this
				 * activity has an unknown format.
				 */
				act[p]->magic = ACTIVITY_MAGIC_UNKNOWN;
			}
			else
				continue;
		}

		/* Check max value for known activities */
		if (fal->nr > act[p]->nr_max) {
#ifdef DEBUG
			fprintf(stderr, "%s: id=%d nr=%d nr_max=%d\n",
				__FUNCTION__, fal->id, fal->nr, act[p]->nr_max);
#endif
			goto format_error;
		}

		/*
		 * Number of fields of each type ("long long", or "long"
		 * or "int") composing the structure with statistics may
		 * only increase with new sysstat versions. Here, we may
		 * be reading a file created by current sysstat version,
		 * or by an older or a newer version.
		 */
		if (!(((fal->types_nr[0] >= act[p]->gtypes_nr[0]) &&
		     (fal->types_nr[1] >= act[p]->gtypes_nr[1]) &&
		     (fal->types_nr[2] >= act[p]->gtypes_nr[2]))
		     ||
		     ((fal->types_nr[0] <= act[p]->gtypes_nr[0]) &&
		     (fal->types_nr[1] <= act[p]->gtypes_nr[1]) &&
		     (fal->types_nr[2] <= act[p]->gtypes_nr[2]))) && !ignore) {
#ifdef DEBUG
			fprintf(stderr, "%s: id=%d file=%d,%d,%d activity=%d,%d,%d\n",
				__FUNCTION__, fal->id, fal->types_nr[0], fal->types_nr[1], fal->types_nr[2],
				act[p]->gtypes_nr[0], act[p]->gtypes_nr[1], act[p]->gtypes_nr[2]);
#endif
			goto format_error;
		}

		if (MAP_SIZE(fal->types_nr) > fal->size) {
#ifdef DEBUG
		fprintf(stderr, "%s: id=%d size=%u map_size=%u\n",
			__FUNCTION__, fal->id, fal->size, MAP_SIZE(fal->types_nr));
#endif
			goto format_error;
		}

		for (k = 0; k < 3; k++) {
			act[p]->ftypes_nr[k] = fal->types_nr[k];
		}

		if (fal->size > act[p]->msize) {
			act[p]->msize = fal->size;
		}

		act[p]->nr_ini = fal->nr;
		act[p]->nr2    = fal->nr2;
		act[p]->fsize  = fal->size;
		/*
		 * This is a known activity with a known format
		 * (magical number). Only such activities will be displayed.
		 * (Well, this may also be an unknown format if we have entered sadf -H.)
		 */
		id_seq[j++] = fal->id;
	}

	while (j < NR_ACT) {
		id_seq[j++] = 0;
	}

	free(buffer);

	/* Check that at least one activity selected by the user is available in file */
	for (i = 0; i < NR_ACT; i++) {

		if (!IS_SELECTED(act[i]->options))
			continue;

		/* Here is a selected activity: Does it exist in file? */
		fal = *file_actlst;
		for (j = 0; j < file_hdr->sa_act_nr; j++, fal++) {
			if (act[i]->id == fal->id)
				break;
		}
		if (j == file_hdr->sa_act_nr) {
			/* No: Unselect it */
			act[i]->options &= ~AO_SELECTED;
		}
	}

	/*
	 * None of selected activities exist in file: Abort.
	 * NB: Error is ignored if we only want to display
	 * datafile header (sadf -H).
	 */
	if (!get_activity_nr(act, AO_SELECTED, COUNT_ACTIVITIES) && !ignore) {
		fprintf(stderr, _("Requested activities not available in file %s\n"),
			dfile);
		close(*ifd);
		exit(1);
	}

	return;

format_error:
	if (buffer) {
		free(buffer);
	}
	handle_invalid_sa_file(*ifd, file_magic, dfile, 0);
}

Project: sysstat
File: sar.c

void write_stats_avg(int curr, int read_from_file, unsigned int act_id)
{
	int i;
	unsigned long long itv;

	/* Interval value in 1/100th of a second */
	itv = get_interval(record_hdr[2].uptime_cs, record_hdr[curr].uptime_cs);

	strncpy(timestamp[curr], _("Average:"), TIMESTAMP_LEN);
	timestamp[curr][TIMESTAMP_LEN - 1] = '\0';
	memcpy(timestamp[!curr], timestamp[curr], TIMESTAMP_LEN);

	/* Test stdout */
	TEST_STDOUT(STDOUT_FILENO);

	for (i = 0; i < NR_ACT; i++) {

		if ((act_id != ALL_ACTIVITIES) && (act[i]->id != act_id))
			continue;

		if (IS_SELECTED(act[i]->options) && (act[i]->nr[curr] > 0)) {
			/* Display current average activity statistics */
			(*act[i]->f_print_avg)(act[i], 2, curr, itv);
		}
	}

	if (read_from_file) {
		/*
		 * Reset number of lines printed only if we read stats
		 * from a system activity file.
		 */
		avg_count = 0;
	}
}

Project: sysstat
File: sa_common.c

void get_global_soft_statistics(struct activity *a, int prev, int curr,
				unsigned int flags, unsigned char offline_cpu_bitmap[])
{
	int i;
	struct stats_softnet *ssnc, *ssnp;
	struct stats_softnet *ssnc_all = (struct stats_softnet *) ((char *) a->buf[curr]);
	struct stats_softnet *ssnp_all = (struct stats_softnet *) ((char *) a->buf[prev]);

	/*
	 * Init structures that will contain values for CPU "all".
	 * CPU "all" doesn't exist in /proc/net/softnet_stat file, so
	 * we compute its values as the sum of the values of each CPU.
	 */
	memset(ssnc_all, 0, sizeof(struct stats_softnet));
	memset(ssnp_all, 0, sizeof(struct stats_softnet));

	for (i = 1; (i < a->nr_ini) && (i < a->bitmap->b_size + 1); i++) {

		/*
		 * The size of a->buf[...] CPU structure may be different from the default
		 * sizeof(struct stats_pwr_cpufreq) value if data have been read from a file!
		 * That's why we don't use a syntax like:
		 * ssnc = (struct stats_softnet *) a->buf[...] + i;
                 */
                ssnc = (struct stats_softnet *) ((char *) a->buf[curr] + i * a->msize);
                ssnp = (struct stats_softnet *) ((char *) a->buf[prev] + i * a->msize);

		if (ssnc->processed + ssnc->dropped + ssnc->time_squeeze +
		    ssnc->received_rps + ssnc->flow_limit == 0) {
			/* Assume current CPU is offline */
			*ssnc = *ssnp;
			offline_cpu_bitmap[i >> 3] |= 1 << (i & 0x07);
		}

		if ((ssnp->processed + ssnp->dropped + ssnp->time_squeeze +
		    ssnp->received_rps + ssnp->flow_limit == 0) && !WANT_SINCE_BOOT(flags)) {
			/* Current CPU back online but no previous sample for it */
			offline_cpu_bitmap[i >> 3] |= 1 << (i & 0x07);
			continue;
		}

		ssnc_all->processed += ssnc->processed;
		ssnc_all->dropped += ssnc->dropped;
		ssnc_all->time_squeeze += ssnc->time_squeeze;
		ssnc_all->received_rps += ssnc->received_rps;
		ssnc_all->flow_limit += ssnc->flow_limit;

		ssnp_all->processed += ssnp->processed;
		ssnp_all->dropped += ssnp->dropped;
		ssnp_all->time_squeeze += ssnp->time_squeeze;
		ssnp_all->received_rps += ssnp->received_rps;
		ssnp_all->flow_limit += ssnp->flow_limit;
	}
}

Project: sysstat
File: sadf.c

int generic_write_stats(int curr, int use_tm_start, int use_tm_end, int reset,
			long *cnt, void *parm, struct tm *rectime,
			struct tm *loctime, int reset_cd, unsigned int act_id)
{
	int i;
	unsigned long long dt, itv;
	char cur_date[TIMESTAMP_LEN], cur_time[TIMESTAMP_LEN], *pre = NULL;
	static int cross_day = FALSE;

	if (reset_cd) {
		/*
		 * See note in sar.c.
		 * NB: Reseting cross_day is needed only if datafile
		 * may be rewinded (eg. in db or ppc output formats).
		 */
		cross_day = 0;
	}

	/*
	 * Check time (1).
	 * For this first check, we use the time interval entered on
	 * the command line. This is equivalent to sar's option -i which
	 * selects records at seconds as close as possible to the number
	 * specified by the interval parameter.
	 */
	if (!next_slice(record_hdr[2].uptime_cs, record_hdr[curr].uptime_cs,
			reset, interval))
		/* Not close enough to desired interval */
		return 0;

	/* Check if we are beginning a new day */
	if (use_tm_start && record_hdr[!curr].ust_time &&
	    (record_hdr[curr].ust_time > record_hdr[!curr].ust_time) &&
	    (record_hdr[curr].hour < record_hdr[!curr].hour)) {
		cross_day = TRUE;
	}

	if (cross_day) {
		/*
		 * This is necessary if we want to properly handle something like:
		 * sar -s time_start -e time_end with
		 * time_start(day D) > time_end(day D+1)
		 */
		loctime->tm_hour += 24;
	}

	/* Check time (2) */
	if (use_tm_start && (datecmp(loctime, &tm_start) < 0))
		/* it's too soon... */
		return 0;

	/* Get interval values in 1/100th of a second */
	get_itv_value(&record_hdr[curr], &record_hdr[!curr], &itv);

	/* Check time (3) */
	if (use_tm_end && (datecmp(loctime, &tm_end) > 0)) {
		/* It's too late... */
		*cnt = 0;
		return 0;
	}

	dt = itv / 100;
	/* Correct rounding error for dt */
	if ((itv % 100) >= 50) {
		dt++;
	}

	/* Set date and time strings for current record */
	set_record_timestamp_string(flags, &record_hdr[curr],
				    cur_date, cur_time, TIMESTAMP_LEN, rectime);

	if (*fmt[f_position]->f_timestamp) {
		pre = (char *) (*fmt[f_position]->f_timestamp)(parm, F_BEGIN, cur_date, cur_time,
							       dt, &file_hdr, flags);
	}

	/* Display statistics */
	for (i = 0; i < NR_ACT; i++) {

		if ((act_id != ALL_ACTIVITIES) && (act[i]->id != act_id))
			continue;

		if ((TEST_MARKUP(fmt[f_position]->options) && CLOSE_MARKUP(act[i]->options)) ||
		    (IS_SELECTED(act[i]->options) && (act[i]->nr > 0))) {

			if (format == F_JSON_OUTPUT) {
				/* JSON output */
				int *tab = (int *) parm;

				if (IS_SELECTED(act[i]->options) && (act[i]->nr > 0)) {

					if (*fmt[f_position]->f_timestamp) {
						(*fmt[f_position]->f_timestamp)(tab, F_MAIN, cur_date, cur_time,
										dt, &file_hdr, flags);
					}
				}
				(*act[i]->f_json_print)(act[i], curr, *tab, itv);
			}

			else if (format == F_XML_OUTPUT) {
				/* XML output */
				int *tab = (int *) parm;

				(*act[i]->f_xml_print)(act[i], curr, *tab, itv);
			}

			else if (format == F_SVG_OUTPUT) {
				/* SVG output */
				struct svg_parm *svg_p = (struct svg_parm *) parm;

				svg_p->dt = (unsigned long) dt;
				(*act[i]->f_svg_print)(act[i], curr, F_MAIN, svg_p, itv, &record_hdr[curr]);
			}

			else if (format == F_RAW_OUTPUT) {
				/* Raw output */
				if (DISPLAY_DEBUG_MODE(flags)) {
					printf("# %s: %d/%d (%d)\n", act[i]->name,
					       act[i]->nr[curr], act[i]->nr_allocated, act[i]->nr_ini);
				}

				(*act[i]->f_raw_print)(act[i], pre, curr);
			}

			else {
				/* Other output formats: db, ppc */
				(*act[i]->f_render)(act[i], (format == F_DB_OUTPUT), pre, curr, itv);
			}
		}
	}

	if (*fmt[f_position]->f_timestamp) {
		(*fmt[f_position]->f_timestamp)(parm, F_END, cur_date, cur_time,
						dt, &file_hdr, flags);
	}

	return 1;
}

Project: sysstat
File: sadf.c

void list_fields(unsigned int act_id)
{
	int i, j;
	unsigned int msk;
	char *hl;
	char hline[HEADER_LINE_LEN] = "";

	printf("# hostname;interval;timestamp");

	for (i = 0; i < NR_ACT; i++) {

		if ((act_id != ALL_ACTIVITIES) && (act[i]->id != act_id))
			continue;

		if (IS_SELECTED(act[i]->options) && (act[i]->nr_ini > 0)) {
			if (!HAS_MULTIPLE_OUTPUTS(act[i]->options)) {
				printf(";%s", act[i]->hdr_line);
				if ((act[i]->nr_ini > 1) && DISPLAY_HORIZONTALLY(flags)) {
					printf("[...]");
				}
			}
			else {
				msk = 1;
				strncpy(hline, act[i]->hdr_line, HEADER_LINE_LEN - 1);
				hline[HEADER_LINE_LEN - 1] = '\0';
				for (hl = strtok(hline, "|"); hl; hl = strtok(NULL, "|"), msk <<= 1) {
					if ((hl != NULL) && ((act[i]->opt_flags & 0xff) & msk)) {
						if (strchr(hl, '&')) {
							j = strcspn(hl, "&");
							if ((act[i]->opt_flags & 0xff00) & (msk << 8)) {
								/* Display whole header line */
								*(hl + j) = ';';
								printf(";%s", hl);
							}
							else {
								/* Display only the first part of the header line */
								*(hl + j) = '\0';
								printf(";%s", hl);
							}
							*(hl + j) = '&';
						}
						else {
							printf(";%s", hl);
						}
						if ((act[i]->nr_ini > 1) && DISPLAY_HORIZONTALLY(flags)) {
							printf("[...]");
						}
					}
				}
			}
		}
	}
	printf("\n");
}

Project: sysstat
File: sadf.c

void init_structures(void)
{
	int i;

	for (i = 0; i < 3; i++) {
		memset(&record_hdr[i], 0, RECORD_HEADER_SIZE);
	}
}

Project: sysstat
File: sadf.c

int read_next_sample(int ifd, int action, int curr, char *file, int *rtype, int tab,
		     struct file_magic *file_magic, struct file_activity *file_actlst,
		     struct tm *rectime, struct tm *loctime, int oneof)
{
	int rc;
	char rec_hdr_tmp[MAX_RECORD_HEADER_SIZE];

	/* Read current record */
	if ((rc = read_record_hdr(ifd, rec_hdr_tmp, &record_hdr[curr], &file_hdr,
			    arch_64, endian_mismatch, oneof, sizeof(rec_hdr_tmp))) != 0)
		/* End of sa file */
		return rc;

	*rtype = record_hdr[curr].record_type;

	if (*rtype == R_COMMENT) {
		if (action & IGNORE_COMMENT) {
			/* Ignore COMMENT record */
			if (lseek(ifd, MAX_COMMENT_LEN, SEEK_CUR) < MAX_COMMENT_LEN) {
				perror("lseek");
				if (oneof == UEOF_CONT)
					return 2;
				close(ifd);
				exit(2);
			}
			if (action & SET_TIMESTAMPS) {
				sa_get_record_timestamp_struct(flags, &record_hdr[curr],
							       rectime, loctime);
			}
		}
		else {
			/* 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],
					     endian_mismatch, arch_64);
		}
	}
	else if (*rtype == R_RESTART) {
		if (action & IGNORE_RESTART) {
			/*
			 * Ignore RESTART record (don't display it)
			 * but anyway we have to read the CPU number that follows it
			 * (unless we don't want to do it now).
			 */
			if (!(action & DONT_READ_CPU_NR)) {
				file_hdr.sa_cpu_nr = read_nr_value(ifd, file, file_magic,
								   endian_mismatch, arch_64, TRUE);
			}
			if (action & SET_TIMESTAMPS) {
				sa_get_record_timestamp_struct(flags, &record_hdr[curr],
							       rectime, loctime);
			}
		}
		else {
			/* 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],
					     endian_mismatch, arch_64);
		}
	}
	else {
		/*
		 * OK: Previous record was not a special one.
		 * So read now the extra fields.
		 */
		if (read_file_stat_bunch(act, curr, ifd, file_hdr.sa_act_nr, file_actlst,
					 endian_mismatch, arch_64, file, file_magic, oneof) > 0)
			return 2;
		sa_get_record_timestamp_struct(flags, &record_hdr[curr], rectime, loctime);
	}

	return 0;
}

Project: sysstat
File: sar.c

void read_sadc_stat_bunch(int curr)
{
	int i, p;

	/* Read record header (type is always R_STATS since it is read from sadc) */
	if (sa_read(&record_hdr[curr], RECORD_HEADER_SIZE)) {
		/*
		 * SIGINT (sent by sadc) is likely to be received
		 * while we are stuck in sa_read().
		 * If this happens then no data have to be read.
		 */
		if (sigint_caught)
			return;

#ifdef DEBUG
		fprintf(stderr, "%s: Record header\n", __FUNCTION__);
#endif
		print_read_error(END_OF_DATA_UNEXPECTED);
	}

	for (i = 0; i < NR_ACT; i++) {

		if (!id_seq[i])
			continue;
		p = get_activity_position(act, id_seq[i], EXIT_IF_NOT_FOUND);

		if (HAS_COUNT_FUNCTION(act[p]->options)) {
			if (sa_read(&(act[p]->nr[curr]), sizeof(__nr_t))) {
#ifdef DEBUG
				fprintf(stderr, "%s: Nb of items\n", __FUNCTION__);
#endif
				print_read_error(END_OF_DATA_UNEXPECTED);
			}
			if ((act[p]->nr[curr] > act[p]->nr_max) || (act[p]->nr[curr] < 0)) {
#ifdef DEBUG
				fprintf(stderr, "%s: %s: nr=%d nr_max=%d\n",
					__FUNCTION__, act[p]->name, act[p]->nr[curr], act[p]->nr_max);
#endif
				print_read_error(INCONSISTENT_INPUT_DATA);
			}
			if (act[p]->nr[curr] > act[p]->nr_allocated) {
				reallocate_all_buffers(act[p], act[p]->nr[curr]);
			}


			/*
			 * For persistent activities, we must make sure that no statistics
                         * from a previous iteration remain, especially if the number
                         * of structures read is smaller than @nr_ini.
                         */
                        if (HAS_PERSISTENT_VALUES(act[p]->options)) {
                            memset(act[p]->buf[curr], 0,
                                   (size_t) act[p]->fsize * (size_t) act[p]->nr_ini * (size_t) act[p]->nr2);
                        }
                }
		if (sa_read(act[p]->buf[curr],
			    (size_t) act[p]->fsize * (size_t) act[p]->nr[curr] * (size_t) act[p]->nr2)) {
#ifdef DEBUG
			fprintf(stderr, "%s: Statistics\n", __FUNCTION__);
#endif
			print_read_error(END_OF_DATA_UNEXPECTED);
		}
	}
}

Project: sysstat
File: sa_common.c

int set_default_file(char *datafile, int d_off, int sa_name)
{
	char sa_dir[MAX_FILE_LEN];
	struct tm rectime = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL};
	int err = 0;

	/* Set directory where daily data files will be saved */
	if (datafile[0]) {
		strncpy(sa_dir, datafile, MAX_FILE_LEN);
	}
	else {
		strncpy(sa_dir, SA_DIR, MAX_FILE_LEN);
	}
	sa_dir[MAX_FILE_LEN - 1] = '\0';

	get_time(&rectime, d_off);
	if (sa_name < 0) {
		/*
		 * Look for the most recent of saDD and saYYYYMMDD
		 * and use it. If neither exists then use saDD.
		 * sa_name is set accordingly.
		 */
		guess_sa_name(sa_dir, &rectime, &sa_name);
	}
	if (sa_name) {
		/* Using saYYYYMMDD data files */
		err = snprintf(datafile, MAX_FILE_LEN,
			       "%s/sa%04d%02d%02d", sa_dir,
			       rectime.tm_year + 1900,
			       rectime.tm_mon + 1,
			       rectime.tm_mday);
	}
	else {
		/* Using saDD data files */
		err = snprintf(datafile, MAX_FILE_LEN,
			       "%s/sa%02d", sa_dir,
			       rectime.tm_mday);
	}
	datafile[MAX_FILE_LEN - 1] = '\0';
	default_file_used = TRUE;

	return ((err < 0) || (err >= MAX_FILE_LEN));
}

Project: sysstat
File: sa_common.c

int read_file_stat_bunch(struct activity *act[], int curr, int ifd, int act_nr,
			 struct file_activity *file_actlst, int endian_mismatch,
			 int arch_64, char *dfile, struct file_magic *file_magic,
			 int oneof)
{
	int i, j, p;
	struct file_activity *fal = file_actlst;
	off_t offset;
	__nr_t nr_value;

	for (i = 0; i < act_nr; i++, fal++) {

		/* Read __nr_t value preceding statistics structures if it exists */
		if (fal->has_nr) {
			nr_value = read_nr_value(ifd, dfile, file_magic,
						 endian_mismatch, arch_64, FALSE);
		}
		else {
			nr_value = fal->nr;
		}

		if (nr_value > NR_MAX) {
#ifdef DEBUG
			fprintf(stderr, "%s: Value=%d Max=%d\n", __FUNCTION__, nr_value, NR_MAX);
#endif
			handle_invalid_sa_file(ifd, file_magic, dfile, 0);
		}

		if (((p = get_activity_position(act, fal->id, RESUME_IF_NOT_FOUND)) < 0) ||
		    (act[p]->magic != fal->magic)) {
			/*
			 * Ignore current activity in file, which is unknown to
			 * current sysstat version or has an unknown format.
			 */
			if (nr_value) {
				offset = (off_t) fal->size * (off_t) nr_value * (off_t) fal->nr2;
				if (lseek(ifd, offset, SEEK_CUR) < offset) {
					close(ifd);
					perror("lseek");
					if (oneof == UEOF_CONT)
						return 2;
					exit(2);
				}
			}
			continue;
		}

		if (nr_value > act[p]->nr_max) {
#ifdef DEBUG
			fprintf(stderr, "%s: %s: Value=%d Max=%d\n",
				__FUNCTION__, act[p]->name, nr_value, act[p]->nr_max);
#endif
			handle_invalid_sa_file(ifd, file_magic, dfile, 0);
		}
		act[p]->nr[curr] = nr_value;

		/* Reallocate buffers if needed */
		if (nr_value > act[p]->nr_allocated) {
			reallocate_all_buffers(act[p], nr_value);
		}

		/*
                 * For persistent activities, we must make sure that no statistics
                 * from a previous iteration remain, especially if the number
                 * of structures read is smaller than @nr_ini.
                 */
		if (HAS_PERSISTENT_VALUES(act[p]->options)) {
                    memset(act[p]->buf[curr], 0,
                           (size_t) act[p]->msize * (size_t) act[p]->nr_ini * (size_t) act[p]->nr2);
                }

		/* OK, this is a known activity: Read the stats structures */
		if ((nr_value > 0) &&
		    ((nr_value > 1) || (act[p]->nr2 > 1)) &&
		    (act[p]->msize > act[p]->fsize)) {

			for (j = 0; j < (nr_value * act[p]->nr2); j++) {
				if (sa_fread(ifd, (char *) act[p]->buf[curr] + j * act[p]->msize,
					 (size_t) act[p]->fsize, HARD_SIZE, oneof) > 0)
					/* Unexpected EOF */
					return 2;
			}
		}
		else if (nr_value > 0) {
			/*
			 * Note: If msize was smaller than fsize,
			 * then it has been set to fsize in check_file_actlst().
			 */
			if (sa_fread(ifd, act[p]->buf[curr],
				 (size_t) act[p]->fsize * (size_t) nr_value * (size_t) act[p]->nr2,
				 HARD_SIZE, oneof) > 0)
				/* Unexpected EOF */
				return 2;
		}
		else {
			/* nr_value == 0: Nothing to read */
			continue;
		}

		/* Normalize endianness for current activity's structures */
		if (endian_mismatch) {
			for (j = 0; j < (nr_value * act[p]->nr2); j++) {
				swap_struct(act[p]->ftypes_nr, (char *) act[p]->buf[curr] + j * act[p]->msize,
					    arch_64);
			}
		}

		/* Remap structure's fields to those known by current sysstat version */
		for (j = 0; j < (nr_value * act[p]->nr2); j++) {
			remap_struct(act[p]->gtypes_nr, act[p]->ftypes_nr,
				     (char *) act[p]->buf[curr] + j * act[p]->msize,
				     act[p]->fsize, act[p]->msize, act[p]->msize);
		}
	}

	return 0;
}

Project: sysstat
File: sar.c

void read_stats_from_file(char from_file[])
{
	struct file_magic file_magic;
	struct file_activity *file_actlst = NULL;
	char rec_hdr_tmp[MAX_RECORD_HEADER_SIZE];
	int curr = 1, i, p;
	int ifd, rtype;
	int rows, eosaf = TRUE, reset = FALSE;
	long cnt = 1;
	off_t fpos;

	/* Get window size */
	rows = get_win_height();

	/* Read file headers and activity list */
	check_file_actlst(&ifd, from_file, act, &file_magic, &file_hdr,
			  &file_actlst, id_seq, FALSE, &endian_mismatch, &arch_64);

	/* Perform required allocations */
	allocate_structures(act);

	/* Print report header */
	print_report_hdr(flags, &rectime, &file_hdr);

	/* Read system statistics from file */
	do {
		/*
		 * If this record is a special (RESTART or COMMENT) one, print it and
		 * (try to) get another one.
		 */
		do {
			if (read_record_hdr(ifd, rec_hdr_tmp, &record_hdr[0], &file_hdr,
					    arch_64, endian_mismatch, UEOF_STOP, sizeof(rec_hdr_tmp))) {
				/* End of sa data file */
				return;
			}

			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, endian_mismatch, arch_64);
			}
			else {
				/*
				 * OK: Previous record was not a special one.
				 * So read now the extra fields.
				 */
				read_file_stat_bunch(act, 0, ifd, file_hdr.sa_act_nr,
						     file_actlst, endian_mismatch, arch_64,
						     from_file, &file_magic, UEOF_STOP);
				if (sa_get_record_timestamp_struct(flags + S_F_LOCAL_TIME,
								   &record_hdr[0],
								   &rectime, NULL))
					/*
					 * An error was detected.
					 * The timestamp hasn't been updated.
					 */
					continue;
			}
		}
		while ((rtype == R_RESTART) || (rtype == R_COMMENT) ||
		       (tm_start.use && (datecmp(&rectime, &tm_start) < 0)) ||
		       (tm_end.use && (datecmp(&rectime, &tm_end) >=0)));

		/* Save the first stats collected. Will be used to compute the average */
		copy_structures(act, id_seq, record_hdr, 2, 0);

		reset = TRUE;	/* Set flag to reset last_uptime variable */

		/* Save current file position */
		if ((fpos = lseek(ifd, 0, SEEK_CUR)) < 0) {
			perror("lseek");
			exit(2);
		}

		/*
		 * Read and write stats located between two possible Linux restarts.
		 * Activities that should be displayed are saved in id_seq[] array.
		 * Since we are reading from a file, we print all the stats for an
		 * activity before displaying the next activity.
		 * id_seq[] has been created in check_file_actlst(), retaining only
		 * activities known by current sysstat version.
		 */
		for (i = 0; i < NR_ACT; i++) {

			if (!id_seq[i])
				continue;

			p = get_activity_position(act, id_seq[i], EXIT_IF_NOT_FOUND);
			if (!IS_SELECTED(act[p]->options))
				continue;

			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, rec_hdr_tmp,
						      endian_mismatch, arch_64, sizeof(rec_hdr_tmp));
			}
			else {
				unsigned int optf, msk;

				optf = act[p]->opt_flags;

				for (msk = 1; msk < 0x100; msk <<= 1) {
					if ((act[p]->opt_flags & 0xff) & msk) {
						act[p]->opt_flags &= (0xffffff00 + msk);

						handle_curr_act_stats(ifd, fpos, &curr, &cnt, &eosaf,
								      rows, act[p]->id, &reset, file_actlst,
								      from_file, &file_magic, rec_hdr_tmp,
								      endian_mismatch, arch_64, sizeof(rec_hdr_tmp));
						act[p]->opt_flags = optf;
					}
				}
			}
		}

		if (!cnt) {
			/* Go to next Linux restart, if possible */
			do {
				/* Read next record header */
				eosaf = read_record_hdr(ifd, rec_hdr_tmp, &record_hdr[curr],
							&file_hdr, arch_64, endian_mismatch, UEOF_STOP, sizeof(rec_hdr_tmp));
				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, endian_mismatch, arch_64,
							     from_file, &file_magic, UEOF_STOP);
				}
				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,
							     endian_mismatch, arch_64);
				}
			}
			while (!eosaf && (rtype != R_RESTART));
		}

		/* The last record we read was a RESTART one: Print it */
		if (!eosaf && (record_hdr[curr].record_type == 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,
					     endian_mismatch, arch_64);
		}
	}
	while (!eosaf);

	close(ifd);

	free(file_actlst);
}

Project: sysstat
File: sadf.c

void read_stats_from_file(char dfile[])
{
	struct file_magic file_magic;
	struct file_activity *file_actlst = NULL;
	struct tm rectime, loctime;
	int ifd, ignore, tab = 0;

	/* 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, &endian_mismatch, &arch_64);

	if (DISPLAY_HDR_ONLY(flags)) {
		if (*fmt[f_position]->f_header) {
			/* Display only data file header then exit */
			(*fmt[f_position]->f_header)(&tab, F_BEGIN + F_END, dfile, &file_magic,
						     &file_hdr, act, id_seq, file_actlst);
		}
		exit(0);
	}

	/* Perform required allocations */
	allocate_structures(act);

	/* Call function corresponding to selected output format */
	if (format == F_SVG_OUTPUT) {
		logic3_display_loop(ifd, file_actlst,
				    &rectime, &loctime, dfile, &file_magic);
	}
	else if (DISPLAY_GROUPED_STATS(fmt[f_position]->options)) {
		logic2_display_loop(ifd, file_actlst,
				    &rectime, &loctime, dfile, &file_magic);
	}
	else {
		logic1_display_loop(ifd, file_actlst, dfile,
				    &file_magic, &rectime, &loctime);
	}

	close(ifd);

	free(file_actlst);
	free_structures(act);
}

Project: sysstat
File: sar.c

__printf_funct_t print_sar_restart(int *tab, int action, char *cur_date, char *cur_time,
				  int utc, struct file_header *file_hdr)
{
	char restart[64];

	printf("\n%-11s", cur_time);
	sprintf(restart, "  LINUX RESTART\t(%d CPU)\n",
		file_hdr->sa_cpu_nr > 1 ? file_hdr->sa_cpu_nr - 1 : 1);
	cprintf_s(IS_RESTART, "%s", restart);

}

Project: sysstat
File: sar.c

void read_header_data(void)
{
	struct file_magic file_magic;
	struct file_activity file_act;
	int rc, i, p;
	char version[16];

	/* Read magic header */
	rc = sa_read(&file_magic, FILE_MAGIC_SIZE);

	sprintf(version, "%d.%d.%d.%d",
		file_magic.sysstat_version,
		file_magic.sysstat_patchlevel,
		file_magic.sysstat_sublevel,
		file_magic.sysstat_extraversion);
	if (!file_magic.sysstat_extraversion) {
		version[strlen(version) - 2] = '\0';
	}

	if (rc || (file_magic.sysstat_magic != SYSSTAT_MAGIC) ||
	    (file_magic.format_magic != FORMAT_MAGIC) ||
	    strcmp(version, VERSION)) {

		/* sar and sadc commands are not consistent */
		if (!rc && (file_magic.sysstat_magic == SYSSTAT_MAGIC)) {
			fprintf(stderr,
				_("Using a wrong data collector from a different sysstat version\n"));
		}

#ifdef DEBUG
		fprintf(stderr, "%s: sysstat_magic=%x format_magic=%x version=%s\n",
			__FUNCTION__, file_magic.sysstat_magic, file_magic.format_magic, version);
#endif
		print_read_error(INCONSISTENT_INPUT_DATA);
	}

	/*
	 * Read header data.
	 * No need to take into account file_magic.header_size. We are sure that
	 * sadc and sar are from the same version (we have checked FORMAT_MAGIC
	 * but also VERSION above) and thus the size of file_header is FILE_HEADER_SIZE.
	 */
	if (sa_read(&file_hdr, FILE_HEADER_SIZE)) {
#ifdef DEBUG
		fprintf(stderr, "%s: File header\n", __FUNCTION__);
#endif
		print_read_error(END_OF_DATA_UNEXPECTED);
	}

	/* All activities are not necessarily selected, but NR_ACT is a max */
	if (file_hdr.sa_act_nr > NR_ACT) {
#ifdef DEBUG
		fprintf(stderr, "%s: sa_act_nr=%d\n", __FUNCTION__, file_hdr.sa_act_nr);
#endif
		print_read_error(INCONSISTENT_INPUT_DATA);
	}

	if ((file_hdr.act_size != FILE_ACTIVITY_SIZE) ||
	    (file_hdr.rec_size != RECORD_HEADER_SIZE)) {
#ifdef DEBUG
		fprintf(stderr, "%s: act_size=%u/%lu rec_size=%u/%lu\n", __FUNCTION__,
			file_hdr.act_size, FILE_ACTIVITY_SIZE, file_hdr.rec_size, RECORD_HEADER_SIZE);
#endif
		print_read_error(INCONSISTENT_INPUT_DATA);
	}

	/* Read activity list */
	for (i = 0; i < file_hdr.sa_act_nr; i++) {

		if (sa_read(&file_act, FILE_ACTIVITY_SIZE)) {
#ifdef DEBUG
			fprintf(stderr, "%s: File activity (%d)\n", __FUNCTION__, i);
#endif
			print_read_error(END_OF_DATA_UNEXPECTED);
		}

		p = get_activity_position(act, file_act.id, RESUME_IF_NOT_FOUND);

		if ((p < 0) || (act[p]->fsize != file_act.size)
			    || (act[p]->gtypes_nr[0] != file_act.types_nr[0])
			    || (act[p]->gtypes_nr[1] != file_act.types_nr[1])
			    || (act[p]->gtypes_nr[2] != file_act.types_nr[2])
			    || (file_act.nr <= 0)
			    || (file_act.nr2 <= 0)
			    || (act[p]->magic != file_act.magic)) {
#ifdef DEBUG
			if (p < 0) {
				fprintf(stderr, "%s: p=%d\n", __FUNCTION__, p);
			}
			else {
				fprintf(stderr, "%s: %s: size=%d/%d magic=%x/%x nr=%d nr2=%d types=%d,%d,%d/%d,%d,%d\n",
					__FUNCTION__, act[p]->name, act[p]->fsize, file_act.size,
					act[p]->magic, file_act.magic, file_act.nr, file_act.nr2,
					act[p]->gtypes_nr[0], act[p]->gtypes_nr[1], act[p]->gtypes_nr[2],
					file_act.types_nr[0], file_act.types_nr[1], file_act.types_nr[2]);
			}
#endif
			/* Remember that we are reading data from sadc and not from a file... */
			print_read_error(INCONSISTENT_INPUT_DATA);
		}

		id_seq[i]      = file_act.id;	/* We necessarily have "i < NR_ACT" */
		act[p]->nr_ini = file_act.nr;
		act[p]->nr2    = file_act.nr2;
	}

	while (i < NR_ACT) {
		id_seq[i++] = 0;
	}

	/* Check that all selected activties are actually sent by sadc */
	reverse_check_act(file_hdr.sa_act_nr);

	return;
}

Project: sysstat
File: sadf.c

void logic2_display_loop(int ifd, struct file_activity *file_actlst,
			 struct tm *rectime, struct tm *loctime, char *file,
			 struct file_magic *file_magic)
{
	int i, p;
	int curr = 1, rtype;
	int eosaf = TRUE, reset = FALSE;
	long cnt = 1;

	/* Read system statistics from file */
	do {
		/*
		 * If this record is a special (RESTART or COMMENT) one, print it and
		 * (try to) get another one.
		 */
		do {
			if (read_next_sample(ifd, IGNORE_NOTHING, 0,
					     file, &rtype, 0, file_magic, file_actlst,
					     rectime, loctime, UEOF_STOP))
				/* End of sa data file */
				return;
		}
		while ((rtype == R_RESTART) || (rtype == R_COMMENT) ||
		       (tm_start.use && (datecmp(loctime, &tm_start) < 0)) ||
		       (tm_end.use && (datecmp(loctime, &tm_end) >= 0)));

		/* Save the first stats collected. Used for example in next_slice() function */
		copy_structures(act, id_seq, record_hdr, 2, 0);

		/* Set flag to reset last_uptime variable. Should be done after a LINUX RESTART record */
		reset = TRUE;

		/* Save current file position */
		seek_file_position(ifd, DO_SAVE);

		/* Read and write stats located between two possible Linux restarts */

		if (DISPLAY_HORIZONTALLY(flags)) {
			/*
			 * If stats are displayed horizontally, then all activities
			 * are printed on the same line.
			 */
			rw_curr_act_stats(ifd, &curr, &cnt, &eosaf,
					  ALL_ACTIVITIES, &reset, file_actlst,
					  rectime, loctime, file, file_magic);
		}
		else {
			/* For each requested activity... */
			for (i = 0; i < NR_ACT; i++) {

				if (!id_seq[i])
					continue;

				p = get_activity_position(act, id_seq[i], EXIT_IF_NOT_FOUND);
				if (!IS_SELECTED(act[p]->options))
					continue;

				if (!HAS_MULTIPLE_OUTPUTS(act[p]->options)) {
					rw_curr_act_stats(ifd, &curr, &cnt, &eosaf,
							  act[p]->id, &reset, file_actlst,
							  rectime, loctime, file, file_magic);
				}
				else {
					unsigned int optf, msk;

					optf = act[p]->opt_flags;

					for (msk = 1; msk < 0x100; msk <<= 1) {
						if ((act[p]->opt_flags & 0xff) & msk) {
							act[p]->opt_flags &= (0xffffff00 + msk);

							rw_curr_act_stats(ifd, &curr, &cnt, &eosaf,
									  act[p]->id, &reset, file_actlst,
									  rectime, loctime, file,
									  file_magic);
							act[p]->opt_flags = optf;
						}
					}
				}
			}
		}

		if (!cnt) {
			/* Go to next Linux restart, if possible */
			do {
				eosaf = read_next_sample(ifd, IGNORE_RESTART | DONT_READ_CPU_NR,
							 curr, file, &rtype, 0, file_magic,
							 file_actlst, rectime, loctime, UEOF_STOP);
			}
			while (!eosaf && (rtype != R_RESTART));
		}

		/*
		 * The last record we read was a RESTART one: Print it.
		 * NB: Unlike COMMENTS records (which are displayed for each
		 * activity), RESTART ones are only displayed once.
		 */
		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],
					     endian_mismatch, arch_64);
		}
	}
	while (!eosaf);
}

Project: sysstat
File: sa_common.c

int parse_sar_opt(char *argv[], int *opt, struct activity *act[],
		  unsigned int *flags, int caller)
{
	int i, p;

	for (i = 1; *(argv[*opt] + i); i++) {
		/*
		 * Note: argv[*opt] contains something like "-BruW"
		 *     *(argv[*opt] + i) will contain 'B', 'r', etc.
		 */

		switch (*(argv[*opt] + i)) {

		case 'A':
			select_all_activities(act);

			/*
			 * Force '-P ALL -I ALL -r ALL -u ALL -F'.
			 * Setting -F is compulsory because corresponding activity
			 * has AO_MULTIPLE_OUTPUTS flag set.
			 */
			p = get_activity_position(act, A_MEMORY, EXIT_IF_NOT_FOUND);
			act[p]->opt_flags |= AO_F_MEMORY + AO_F_SWAP + AO_F_MEM_ALL;

			p = get_activity_position(act, A_IRQ, EXIT_IF_NOT_FOUND);
			memset(act[p]->bitmap->b_array, ~0,
			       BITMAP_SIZE(act[p]->bitmap->b_size));
			p = get_activity_position(act, A_CPU, EXIT_IF_NOT_FOUND);
			memset(act[p]->bitmap->b_array, ~0,
			       BITMAP_SIZE(act[p]->bitmap->b_size));
			act[p]->opt_flags = AO_F_CPU_ALL;

			p = get_activity_position(act, A_FS, EXIT_IF_NOT_FOUND);
			act[p]->opt_flags = AO_F_FILESYSTEM;
			break;

		case 'B':
			SELECT_ACTIVITY(A_PAGE);
			break;

		case 'b':
			SELECT_ACTIVITY(A_IO);
			break;

		case 'C':
			*flags |= S_F_COMMENT;
			break;

		case 'd':
			SELECT_ACTIVITY(A_DISK);
			break;

		case 'F':
			p = get_activity_position(act, A_FS, EXIT_IF_NOT_FOUND);
			act[p]->options |= AO_SELECTED;
			if (!*(argv[*opt] + i + 1) && argv[*opt + 1] && !strcmp(argv[*opt + 1], K_MOUNT)) {
				(*opt)++;
				act[p]->opt_flags |= AO_F_MOUNT;
				return 0;
			}
			else {
				act[p]->opt_flags |= AO_F_FILESYSTEM;
			}
			break;

		case 'H':
			SELECT_ACTIVITY(A_HUGE);
			break;

		case 'h':
			/*
			 * Make output easier to read by a human.
			 * Option -h implies --human and -p (pretty-print).
			 */
			*flags |= S_F_HUMAN_READ + S_F_UNIT + S_F_DEV_PRETTY;
			break;

		case 'j':
			if (!argv[*opt + 1]) {
				return 1;
			}
			(*opt)++;
			if (strnlen(argv[*opt], MAX_FILE_LEN) >= MAX_FILE_LEN - 1)
				return 1;

			strncpy(persistent_name_type, argv[*opt], MAX_FILE_LEN - 1);
			persistent_name_type[MAX_FILE_LEN - 1] = '\0';
			strtolower(persistent_name_type);
			if (!get_persistent_type_dir(persistent_name_type)) {
				fprintf(stderr, _("Invalid type of persistent device name\n"));
				return 2;
			}
			/*
			 * If persistent device name doesn't exist for device, use
			 * its pretty name.
			 */
			*flags |= S_F_PERSIST_NAME + S_F_DEV_PRETTY;
			return 0;
			break;

		case 'p':
			*flags |= S_F_DEV_PRETTY;
			break;

		case 'q':
			SELECT_ACTIVITY(A_QUEUE);
			break;

		case 'r':
			p = get_activity_position(act, A_MEMORY, EXIT_IF_NOT_FOUND);
			act[p]->options   |= AO_SELECTED;
			act[p]->opt_flags |= AO_F_MEMORY;
			if (!*(argv[*opt] + i + 1) && argv[*opt + 1] && !strcmp(argv[*opt + 1], K_ALL)) {
				(*opt)++;
				act[p]->opt_flags |= AO_F_MEM_ALL;
				return 0;
			}
			break;

		case 'S':
			p = get_activity_position(act, A_MEMORY, EXIT_IF_NOT_FOUND);
			act[p]->options   |= AO_SELECTED;
			act[p]->opt_flags |= AO_F_SWAP;
			break;

		case 't':
			/*
			 * Check sar option -t here (as it can be combined
			 * with other ones, eg. "sar -rtu ..."
			 * But sadf option -t is checked in sadf.c as it won't
			 * be entered as a sar option after "--".
			 */
			if (caller != C_SAR) {
				return 1;
			}
			*flags |= S_F_TRUE_TIME;
			break;

		case 'u':
			p = get_activity_position(act, A_CPU, EXIT_IF_NOT_FOUND);
			act[p]->options |= AO_SELECTED;
			if (!*(argv[*opt] + i + 1) && argv[*opt + 1] && !strcmp(argv[*opt + 1], K_ALL)) {
				(*opt)++;
				act[p]->opt_flags = AO_F_CPU_ALL;
				return 0;
			}
			else {
				act[p]->opt_flags = AO_F_CPU_DEF;
			}
			break;

		case 'v':
			SELECT_ACTIVITY(A_KTABLES);
			break;

		case 'w':
			SELECT_ACTIVITY(A_PCSW);
			break;

		case 'W':
			SELECT_ACTIVITY(A_SWAP);
			break;

		case 'y':
			SELECT_ACTIVITY(A_SERIAL);
			break;

		case 'z':
			*flags |= S_F_ZERO_OMIT;
			break;

		case 'V':
			print_version();
			break;

		default:
			return 1;
		}
	}
	return 0;
}

Project: sysstat
File: sa_common.c

int sa_open_read_magic(int *fd, char *dfile, struct file_magic *file_magic,
		       int ignore, int *endian_mismatch, int do_swap)
{
	int n;
	unsigned int fm_types_nr[] = {FILE_MAGIC_ULL_NR, FILE_MAGIC_UL_NR, FILE_MAGIC_U_NR};

	/* Open sa data file */
	if ((*fd = open(dfile, O_RDONLY)) < 0) {
		int saved_errno = errno;

		fprintf(stderr, _("Cannot open %s: %s\n"), dfile, strerror(errno));

		if ((saved_errno == ENOENT) && default_file_used) {
			fprintf(stderr, _("Please check if data collecting is enabled\n"));
		}
		exit(2);
	}

	/* Read file magic data */
	n = read(*fd, file_magic, FILE_MAGIC_SIZE);

	if ((n != FILE_MAGIC_SIZE) ||
	    ((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)) {
#ifdef DEBUG
		fprintf(stderr, "%s: Bytes read=%d sysstat_magic=%x format_magic=%x\n",
			__FUNCTION__, n, file_magic->sysstat_magic, file_magic->format_magic);
#endif
		/* 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) {
		if (do_swap) {
			/* Swap bytes for file_magic fields */
			file_magic->sysstat_magic = SYSSTAT_MAGIC;
			file_magic->format_magic  = __builtin_bswap16(file_magic->format_magic);
		}
		/*
		 * Start swapping at field "header_size" position.
		 * May not exist for older versions but in this case, it won't be used.
		 */
		swap_struct(fm_types_nr, &file_magic->header_size, 0);
	}

	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 */
		if ((file_magic->header_size <= MIN_FILE_HEADER_SIZE) ||
		    (file_magic->header_size > MAX_FILE_HEADER_SIZE) ||
		    ((file_magic->header_size < FILE_HEADER_SIZE) && !ignore)) {
#ifdef DEBUG
			fprintf(stderr, "%s: header_size=%u\n",
				__FUNCTION__, file_magic->header_size);
#endif
			/* Display error message and exit */
			handle_invalid_sa_file(*fd, file_magic, dfile, n);
		}
	}
	if ((file_magic->sysstat_version > 11) ||
	    ((file_magic->sysstat_version == 11) && (file_magic->sysstat_patchlevel >= 7))) {
		/* hdr_types_nr field exists only for sysstat versions 11.7.1 and later */
		if (MAP_SIZE(file_magic->hdr_types_nr) > file_magic->header_size) {
#ifdef DEBUG
			fprintf(stderr, "%s: map_size=%u header_size=%u\n",
				__FUNCTION__, MAP_SIZE(file_magic->hdr_types_nr), file_magic->header_size);
#endif
			handle_invalid_sa_file(*fd, file_magic, dfile, n);
		}
	}

	if ((file_magic->format_magic != FORMAT_MAGIC) &&
	    (file_magic->format_magic != FORMAT_MAGIC_SWAPPED))
		/*
		 * This is an old (or new) sa datafile format to
		 * be read by sadf (since @ignore was set to TRUE).
		 */
		return -1;

	return 0;
}

Project: sysstat
File: sar.c

int write_stats(int curr, int read_from_file, long *cnt, int use_tm_start,
		int use_tm_end, int reset, unsigned int act_id, int reset_cd)
{
	int i;
	unsigned long long itv;
	static int cross_day = 0;

	if (reset_cd) {
		/*
		 * cross_day is a static variable that is set to 1 when the first
		 * record of stats from a new day is read from a unique data file
		 * (in the case where the file contains data from two consecutive
		 * days). When set to 1, every following records timestamp will
		 * have its hour value increased by 24.
		 * Yet when a new activity (being read from the file) is going to
		 * be displayed, we start reading the file from the beginning
		 * again, and so cross_day should be reset in this case.
		 */
		cross_day = 0;
	}

	/* Check time (1) */
	if (read_from_file) {
		if (!next_slice(record_hdr[2].uptime_cs, record_hdr[curr].uptime_cs,
				reset, interval))
			/* Not close enough to desired interval */
			return 0;
	}

	/* Get then set previous timestamp */
	if (sa_get_record_timestamp_struct(flags + S_F_LOCAL_TIME, &record_hdr[!curr],
					   &rectime, NULL))
		return 0;
	set_record_timestamp_string(flags, &record_hdr[!curr],
				    NULL, timestamp[!curr], TIMESTAMP_LEN, &rectime);

	/* Get then set current timestamp */
	if (sa_get_record_timestamp_struct(flags + S_F_LOCAL_TIME, &record_hdr[curr],
					   &rectime, NULL))
		return 0;
	set_record_timestamp_string(flags, &record_hdr[curr],
				    NULL, timestamp[curr], TIMESTAMP_LEN, &rectime);

	/* Check if we are beginning a new day */
	if (use_tm_start && record_hdr[!curr].ust_time &&
	    (record_hdr[curr].ust_time > record_hdr[!curr].ust_time) &&
	    (record_hdr[curr].hour < record_hdr[!curr].hour)) {
		cross_day = 1;
	}

	if (cross_day) {
		/*
		 * This is necessary if we want to properly handle something like:
		 * sar -s time_start -e time_end with
		 * time_start(day D) > time_end(day D+1)
		 */
		rectime.tm_hour += 24;
	}

	/* Check time (2) */
	if (use_tm_start && (datecmp(&rectime, &tm_start) < 0))
		/* it's too soon... */
		return 0;

	/* Get interval value in 1/100th of a second */
	get_itv_value(&record_hdr[curr], &record_hdr[!curr], &itv);

	/* Check time (3) */
	if (use_tm_end && (datecmp(&rectime, &tm_end) > 0)) {
		/* It's too late... */
		*cnt = 0;
		return 0;
	}

	avg_count++;

	/* Test stdout */
	TEST_STDOUT(STDOUT_FILENO);

	for (i = 0; i < NR_ACT; i++) {

		if ((act_id != ALL_ACTIVITIES) && (act[i]->id != act_id))
			continue;

		if (IS_SELECTED(act[i]->options) && (act[i]->nr[curr] > 0)) {
			/* Display current activity statistics */
			(*act[i]->f_print)(act[i], !curr, curr, itv);
		}
	}

	return 1;
}

Project: sysstat
File: sadf.c

int get_svg_graph_nr(int ifd, char *file, struct file_magic *file_magic,
		     struct file_activity *file_actlst, struct tm *rectime,
		     struct tm *loctime, int *views_per_row, int *nr_act_dispd)
{
	int i, n, p, tot_g_nr = 0;

	*nr_act_dispd = 0;

	/* Count items in file */
	if (!count_file_items(ifd, file, file_magic, file_actlst, rectime, loctime))
		/* No record to display => No graph */
		return 0;

	for (i = 0; i < NR_ACT; i++) {
		if (!id_seq[i])
			continue;

		p = get_activity_position(act, id_seq[i], EXIT_IF_NOT_FOUND);
		if (!IS_SELECTED(act[p]->options) || !act[p]->g_nr)
			continue;

		(*nr_act_dispd)++;

		if (PACK_VIEWS(flags)) {
			/*
			 * One activity = one row with multiple views.
			 * Exception is A_MEMORY, for which one activity may be
			 * displayed in two rows if both memory *and* swap utilization
			 * have been selected.
			 */
			if ((act[p]->id == A_MEMORY) &&
			    (DISPLAY_MEMORY(act[p]->opt_flags) && DISPLAY_SWAP(act[p]->opt_flags))) {
				n = 2;
			}
			else {
				n = 1;
			}
		}
		else {
			/* One activity = multiple rows with only one view */
			n = act[p]->g_nr;
		}
		if (ONE_GRAPH_PER_ITEM(act[p]->options)) {
			 n = n * act[p]->item_list_sz;
		}
		if (act[p]->g_nr > *views_per_row) {
			*views_per_row = act[p]->g_nr;
		}

		tot_g_nr += n;
	}

	if (*views_per_row > MAX_VIEWS_ON_A_ROW) {
		*views_per_row = MAX_VIEWS_ON_A_ROW;
	}

	return tot_g_nr;
}

Project: sysstat
File: sadf.c

void logic1_display_loop(int ifd, struct file_activity *file_actlst, char *file,
			 struct file_magic *file_magic,
			 struct tm *rectime, struct tm *loctime)
{
	int curr, tab = 0, rtype;
	int eosaf, next, reset = FALSE;
	long cnt = 1;

	if (format == F_JSON_OUTPUT) {
		/* Use a decimal point to make JSON code compliant with RFC7159 */
		setlocale(LC_NUMERIC, "C");
	}

	/* Save current file position */
	seek_file_position(ifd, DO_SAVE);

	/* Print header (eg. XML file header) */
	if (*fmt[f_position]->f_header) {
		(*fmt[f_position]->f_header)(&tab, F_BEGIN, file, file_magic,
					     &file_hdr, act, id_seq, file_actlst);
	}

	/* Process activities */
	if (*fmt[f_position]->f_statistics) {
		(*fmt[f_position]->f_statistics)(&tab, F_BEGIN);
	}

	do {
		/*
		 * If this record is a special (RESTART or COMMENT) one,
		 * skip it and try to read the next record in file.
		 */
		do {
			eosaf = read_next_sample(ifd, IGNORE_COMMENT | IGNORE_RESTART, 0,
						 file, &rtype, tab, file_magic, file_actlst,
						 rectime, loctime, UEOF_STOP);
		}
		while (!eosaf && ((rtype == R_RESTART) || (rtype == R_COMMENT) ||
			(tm_start.use && (datecmp(loctime, &tm_start) < 0)) ||
			(tm_end.use && (datecmp(loctime, &tm_end) >= 0))));

		/* Save the first stats collected. Used for example in next_slice() function */
		copy_structures(act, id_seq, record_hdr, 2, 0);

		curr = 1;
		cnt = count;
		reset = TRUE;

		if (!eosaf) {
			do {
				eosaf = read_next_sample(ifd, IGNORE_COMMENT | IGNORE_RESTART, curr,
							 file, &rtype, tab, file_magic, file_actlst,
							 rectime, loctime, UEOF_CONT);

				if (!eosaf && (rtype != R_COMMENT) && (rtype != R_RESTART)) {
					if (*fmt[f_position]->f_statistics) {
						(*fmt[f_position]->f_statistics)(&tab, F_MAIN);
					}

					/* next is set to 1 when we were close enough to desired interval */
					next = generic_write_stats(curr, tm_start.use, tm_end.use, reset,
								  &cnt, &tab, rectime, loctime,
								  FALSE, ALL_ACTIVITIES);

					if (next) {
						curr ^= 1;
						if (cnt > 0) {
							cnt--;
						}
					}
					reset = FALSE;
				}
			}
			while (cnt && !eosaf && (rtype != R_RESTART));

			if (!cnt) {
				/* Go to next Linux restart, if possible */
				do {
					eosaf = read_next_sample(ifd, IGNORE_COMMENT | IGNORE_RESTART, curr,
								 file, &rtype, tab, file_magic, file_actlst,
								 rectime, loctime, UEOF_CONT);
				}
				while (!eosaf && (rtype != R_RESTART));
			}
			reset = TRUE;
		}
	}
	while (!eosaf);

	if (*fmt[f_position]->f_statistics) {
		(*fmt[f_position]->f_statistics)(&tab, F_END);
	}

	/* Rewind file */
	seek_file_position(ifd, DO_RESTORE);

	/* Process now RESTART entries to display restart messages */
	if (*fmt[f_position]->f_restart) {
		(*fmt[f_position]->f_restart)(&tab, F_BEGIN, NULL, NULL, FALSE,
					      &file_hdr);
	}

	do {
		eosaf = read_next_sample(ifd, IGNORE_COMMENT, 0,
					 file, &rtype, tab, file_magic, file_actlst,
					 rectime, loctime, UEOF_CONT);
	}
	while (!eosaf);

	if (*fmt[f_position]->f_restart) {
		(*fmt[f_position]->f_restart)(&tab, F_END, NULL, NULL, FALSE, &file_hdr);
	}

	/* Rewind file */
	seek_file_position(ifd, DO_RESTORE);

	/* Last, process COMMENT entries to display comments */
	if (DISPLAY_COMMENT(flags)) {
		if (*fmt[f_position]->f_comment) {
			(*fmt[f_position]->f_comment)(&tab, F_BEGIN, NULL, NULL, 0, NULL,
						      &file_hdr);
		}
		do {
			eosaf = read_next_sample(ifd, IGNORE_RESTART, 0,
						 file, &rtype, tab, file_magic, file_actlst,
						 rectime, loctime, UEOF_CONT);
		}
		while (!eosaf);

		if (*fmt[f_position]->f_comment) {
			(*fmt[f_position]->f_comment)(&tab, F_END, NULL, NULL, 0, NULL,
						      &file_hdr);
		}
	}

	/* Print header trailer */
	if (*fmt[f_position]->f_header) {
		(*fmt[f_position]->f_header)(&tab, F_END, file, file_magic,
					     &file_hdr, act, id_seq, file_actlst);
	}
}

Project: sysstat
File: sa_common.c

void set_record_timestamp_string(unsigned int l_flags, struct record_header *record_hdr,
				 char *cur_date, char *cur_time, int len, struct tm *rectime)
{
	/* Set cur_time date value */
	if (PRINT_SEC_EPOCH(l_flags) && cur_date) {
		sprintf(cur_time, "%llu", record_hdr->ust_time);
		strcpy(cur_date, "");
	}
	else {
		/*
		 * If options -T or -t have been used then cur_time is
		 * expressed in local time. Else it is expressed in UTC.
		 */
		if (cur_date) {
			strftime(cur_date, len, "%Y-%m-%d", rectime);
		}
		if (USE_PREFD_TIME_OUTPUT(l_flags)) {
			strftime(cur_time, len, "%X", rectime);
		}
		else {
			strftime(cur_time, len, "%H:%M:%S", rectime);
		}
	}
}

Project: sysstat
File: sadf.c

time_t get_time_ref(void)
{
	struct tm ltm;
	time_t t;

	if (DISPLAY_ONE_DAY(flags)) {
		localtime_r((time_t *) &(record_hdr[2].ust_time), &ltm);

		/* Move back to midnight */
		ltm.tm_sec = ltm.tm_min = ltm.tm_hour = 0;

		t = mktime(&ltm);
		if (t != -1)
			return t;
	}

	return (time_t) record_hdr[2].ust_time;
}

Project: sysstat
File: sa_common.c

int parse_sa_P_opt(char *argv[], int *opt, unsigned int *flags, struct activity *act[])
{
	int p;

	p = get_activity_position(act, A_CPU, EXIT_IF_NOT_FOUND);

	if (argv[++(*opt)]) {
		if (parse_values(argv[*opt], act[p]->bitmap->b_array,
			     act[p]->bitmap->b_size, K_LOWERALL))
			return 1;
		(*opt)++;
		return 0;
	}

	return 1;
}

Project: sysstat
File: sar.c

void init_structures(void)
{
	int i;

	for (i = 0; i < 3; i++)
		memset(&record_hdr[i], 0, RECORD_HEADER_SIZE);
}

Project: sysstat
File: sadf.c

int get_format_position(struct report_format *fmt[], unsigned int format)
{
        int i;

        for (i = 0; i < NR_FMT; i++) {
                if (fmt[i]->id == format)
                        break;
        }

        if (i == NR_FMT)
		/* Should never happen */
                return 0;

        return i;
}

Project: sysstat
File: sar.c

void reverse_check_act(unsigned int act_nr)
{
	int i, j;

	for (i = 0; i < NR_ACT; i++) {

		if (IS_SELECTED(act[i]->options)) {

			for (j = 0; j < act_nr; j++) {
				if (id_seq[j] == act[i]->id)
					break;
			}
			if (j == act_nr)
				act[i]->options &= ~AO_SELECTED;
		}
	}
}

Project: sysstat
File: sa_common.c

void get_file_timestamp_struct(unsigned int flags, struct tm *rectime,
			       struct file_header *file_hdr)
{
	if (PRINT_TRUE_TIME(flags)) {
		/* Get local time. This is just to fill fields with a default value. */
		get_time(rectime, 0);

		rectime->tm_mday = file_hdr->sa_day;
		rectime->tm_mon  = file_hdr->sa_month;
		rectime->tm_year = file_hdr->sa_year;
		/*
		 * Call mktime() to set DST (Daylight Saving Time) flag.
		 * Has anyone a better way to do it?
		 */
		rectime->tm_hour = rectime->tm_min = rectime->tm_sec = 0;
		mktime(rectime);
	}
	else {
		localtime_r((const time_t *) &file_hdr->sa_ust_time, rectime);
	}
}

Project: sysstat
File: sa_common.c

void remap_struct(unsigned int gtypes_nr[], unsigned int ftypes_nr[],
		  void *ps, unsigned int f_size, unsigned int g_size, size_t b_size)
{
	int d;
	size_t n;

	/* Sanity check */
	if (MAP_SIZE(ftypes_nr) > f_size)
		return;

	/* Remap [unsigned] long fields */
	d = gtypes_nr[0] - ftypes_nr[0];
	if (d) {
		n = MINIMUM(f_size - ftypes_nr[0] * ULL_ALIGNMENT_WIDTH,
			    g_size - gtypes_nr[0] * ULL_ALIGNMENT_WIDTH);
		if ((ftypes_nr[0] * ULL_ALIGNMENT_WIDTH >= b_size) ||
		    (gtypes_nr[0] * ULL_ALIGNMENT_WIDTH + n > b_size) ||
		    (ftypes_nr[0] * ULL_ALIGNMENT_WIDTH + n > b_size))
			return;
		memmove(((char *) ps) + gtypes_nr[0] * ULL_ALIGNMENT_WIDTH,
			((char *) ps) + ftypes_nr[0] * ULL_ALIGNMENT_WIDTH, n);
		if (d > 0) {
			memset(((char *) ps) + ftypes_nr[0] * ULL_ALIGNMENT_WIDTH,
			       0, d * ULL_ALIGNMENT_WIDTH);
		}
	}
	/* Remap [unsigned] int fields */
	d = gtypes_nr[1] - ftypes_nr[1];
	if (d) {
		n = MINIMUM(f_size - ftypes_nr[0] * ULL_ALIGNMENT_WIDTH
				   - ftypes_nr[1] * UL_ALIGNMENT_WIDTH,
			    g_size - gtypes_nr[0] * ULL_ALIGNMENT_WIDTH
				   - gtypes_nr[1] * UL_ALIGNMENT_WIDTH);
		if ((gtypes_nr[0] * ULL_ALIGNMENT_WIDTH +
		     ftypes_nr[1] * UL_ALIGNMENT_WIDTH >= b_size) ||
		    (gtypes_nr[0] * ULL_ALIGNMENT_WIDTH +
		     gtypes_nr[1] * UL_ALIGNMENT_WIDTH + n > b_size) ||
		    (gtypes_nr[0] * ULL_ALIGNMENT_WIDTH +
		     ftypes_nr[1] * UL_ALIGNMENT_WIDTH + n > b_size))
			return;
		memmove(((char *) ps) + gtypes_nr[0] * ULL_ALIGNMENT_WIDTH
				      + gtypes_nr[1] * UL_ALIGNMENT_WIDTH,
			((char *) ps) + gtypes_nr[0] * ULL_ALIGNMENT_WIDTH
				      + ftypes_nr[1] * UL_ALIGNMENT_WIDTH, n);
		if (d > 0) {
			memset(((char *) ps) + gtypes_nr[0] * ULL_ALIGNMENT_WIDTH
					     + ftypes_nr[1] * UL_ALIGNMENT_WIDTH,
			       0, d * UL_ALIGNMENT_WIDTH);
		}
	}
	/* Remap possible fields (like strings of chars) following int fields */
	d = gtypes_nr[2] - ftypes_nr[2];
	if (d) {
		n = MINIMUM(f_size - ftypes_nr[0] * ULL_ALIGNMENT_WIDTH
				   - ftypes_nr[1] * UL_ALIGNMENT_WIDTH
				   - ftypes_nr[2] * U_ALIGNMENT_WIDTH,
			    g_size - gtypes_nr[0] * ULL_ALIGNMENT_WIDTH
				   - gtypes_nr[1] * UL_ALIGNMENT_WIDTH
				   - gtypes_nr[2] * U_ALIGNMENT_WIDTH);
		if ((gtypes_nr[0] * ULL_ALIGNMENT_WIDTH +
		     gtypes_nr[1] * UL_ALIGNMENT_WIDTH +
		     ftypes_nr[2] * U_ALIGNMENT_WIDTH >= b_size) ||
		    (gtypes_nr[0] * ULL_ALIGNMENT_WIDTH +
		     gtypes_nr[1] * UL_ALIGNMENT_WIDTH +
		     gtypes_nr[2] * U_ALIGNMENT_WIDTH + n > b_size) ||
		    (gtypes_nr[0] * ULL_ALIGNMENT_WIDTH +
		     gtypes_nr[1] * UL_ALIGNMENT_WIDTH +
		     ftypes_nr[2] * U_ALIGNMENT_WIDTH + n > b_size))
			return;
		memmove(((char *) ps) + gtypes_nr[0] * ULL_ALIGNMENT_WIDTH
				      + gtypes_nr[1] * UL_ALIGNMENT_WIDTH
				      + gtypes_nr[2] * U_ALIGNMENT_WIDTH,
			((char *) ps) + gtypes_nr[0] * ULL_ALIGNMENT_WIDTH
				      + gtypes_nr[1] * UL_ALIGNMENT_WIDTH
				      + ftypes_nr[2] * U_ALIGNMENT_WIDTH, n);
		if (d > 0) {
			memset(((char *) ps) + gtypes_nr[0] * ULL_ALIGNMENT_WIDTH
					     + gtypes_nr[1] * UL_ALIGNMENT_WIDTH
					     + ftypes_nr[2] * U_ALIGNMENT_WIDTH,
			       0, d * U_ALIGNMENT_WIDTH);
		}
	}
}

Project: sysstat
File: sa_common.c

char *get_devname_from_sysfs(unsigned int major, unsigned int minor)
{
	static char link[32], target[PATH_MAX];
	char *devname;
	ssize_t r;

	snprintf(link, 32, "%s/%u:%u", SYSFS_DEV_BLOCK, major, minor);

	/* Get full path to device knowing its major and minor numbers */
	r = readlink(link, target, PATH_MAX);
	if (r <= 0 || r >= PATH_MAX) {
		return (NULL);
	}

	target[r] = '\0';

	/* Get device name */
	devname = basename(target);
	if (!devname || strnlen(devname, FILENAME_MAX) == 0) {
		return (NULL);
	}

	return (devname);
}

Project: sysstat
File: sa_common.c

int datecmp(struct tm *rectime, struct tstamp *tse)
{
	if (rectime->tm_hour == tse->tm_hour) {
		if (rectime->tm_min == tse->tm_min)
			return (rectime->tm_sec - tse->tm_sec);
		else
			return (rectime->tm_min - tse->tm_min);
	}
	else
		return (rectime->tm_hour - tse->tm_hour);
}

Project: sysstat
File: sar.c

void write_stats_startup(int curr)
{
	int i;

	/* Set to 0 previous structures corresponding to boot time */
	memset(&record_hdr[!curr], 0, RECORD_HEADER_SIZE);
	record_hdr[!curr].record_type = R_STATS;
	record_hdr[!curr].hour        = record_hdr[curr].hour;
	record_hdr[!curr].minute      = record_hdr[curr].minute;
	record_hdr[!curr].second      = record_hdr[curr].second;
	record_hdr[!curr].ust_time    = record_hdr[curr].ust_time;

	for (i = 0; i < NR_ACT; i++) {
		if (IS_SELECTED(act[i]->options) && (act[i]->nr[curr] > 0)) {
			/*
			 * Using nr[curr] and not nr[!curr] below because we initialize
			 * reference structures for each structure that has been
			 * currently read in memory.
			 * No problem with buffers allocation since they all have the
			 * same size.
			 */
			memset(act[i]->buf[!curr], 0,
			       (size_t) act[i]->msize * (size_t) act[i]->nr[curr] * (size_t) act[i]->nr2);
		}
	}

	flags |= S_F_SINCE_BOOT;
	dis = TRUE;

	write_stats(curr, USE_SADC, &count, NO_TM_START, NO_TM_END, NO_RESET,
		    ALL_ACTIVITIES, TRUE);

	exit(0);
}

Project: sysstat
File: sadf.c

int count_file_items(int ifd, char *file, struct file_magic *file_magic,
		      struct file_activity *file_actlst, struct tm *rectime,
		      struct tm *loctime)
{
	int i, eosaf, rtype;

	/* Save current file position */
	seek_file_position(ifd, DO_SAVE);

	/* Init maximum number of items for each activity */
	for (i = 0; i < NR_ACT; i++) {
		if (!HAS_LIST_ON_CMDLINE(act[i]->options)) {
			act[i]->item_list_sz = 0;
		}
	}

	/* Look for the first record that will be displayed */
	do {
		eosaf = read_next_sample(ifd, IGNORE_RESTART | IGNORE_COMMENT | SET_TIMESTAMPS,
					 0, file, &rtype, 0, file_magic, file_actlst,
					 rectime, loctime, UEOF_CONT);
		if (eosaf)
			/* No record to display */
			return 0;
	}
	while ((tm_start.use && (datecmp(loctime, &tm_start) < 0)) ||
	       (tm_end.use && (datecmp(loctime, &tm_end) >= 0)));

	/*
	 * Read all the file and determine the maximum number
	 * of items for each activity.
	 */
	do {
		for (i = 0; i < NR_ACT; i++) {
			if (!HAS_LIST_ON_CMDLINE(act[i]->options)) {
				if (act[i]->f_count_new) {
					act[i]->item_list_sz += (*act[i]->f_count_new)(act[i], 0);
				}
				else if (act[i]->nr[0] > act[i]->item_list_sz) {
					act[i]->item_list_sz = act[i]->nr[0];
				}
			}
		}

		do {
			eosaf = read_next_sample(ifd, IGNORE_RESTART | IGNORE_COMMENT | SET_TIMESTAMPS,
						 0, file, &rtype, 0, file_magic, file_actlst,
						 rectime, loctime, UEOF_CONT);
			if (eosaf ||
			    (tm_end.use && (datecmp(loctime, &tm_end) >= 0)))
				/* End of data file or end time exceeded */
				break;
		}
		while ((rtype == R_RESTART) || (rtype == R_COMMENT));
	}
	while (!eosaf && !(tm_end.use && (datecmp(loctime, &tm_end) >= 0)));

	/* Rewind file */
	seek_file_position(ifd, DO_RESTORE);

	return 1;
}

Project: sysstat
File: sar.c

int main(int argc, char **argv)
{
	int i, rc, opt = 1, args_idx = 1, p, q;
	int fd[2];
	int day_offset = 0;
	char from_file[MAX_FILE_LEN], to_file[MAX_FILE_LEN];
	char ltemp[1024];

	/* Compute page shift in kB */
	get_kb_shift();

	from_file[0] = to_file[0] = '\0';

#ifdef USE_NLS
	/* Init National Language Support */
	init_nls();
#endif

	/* Init color strings */
	init_colors();

	tm_start.use = tm_end.use = FALSE;

	/* Allocate and init activity bitmaps */
	allocate_bitmaps(act);

	init_structures();

	/* Process options */
	while (opt < argc) {

		if (!strcmp(argv[opt], "--sadc")) {
			/* Locate sadc */
			which_sadc();
		}

		else if (!strncmp(argv[opt], "--dev=", 6)) {
			/* Parse devices entered on the command line */
			p = get_activity_position(act, A_DISK, EXIT_IF_NOT_FOUND);
			parse_sa_devices(argv[opt], act[p], MAX_DEV_LEN, &opt, 6);
		}

		else if (!strncmp(argv[opt], "--fs=", 5)) {
			/* Parse devices entered on the command line */
			p = get_activity_position(act, A_FS, EXIT_IF_NOT_FOUND);
			parse_sa_devices(argv[opt], act[p], MAX_FS_LEN, &opt, 5);
		}

		else if (!strncmp(argv[opt], "--iface=", 8)) {
			/* Parse devices entered on the command line */
			p = get_activity_position(act, A_NET_DEV, EXIT_IF_NOT_FOUND);
			parse_sa_devices(argv[opt], act[p], MAX_IFACE_LEN, &opt, 8);
			q = get_activity_position(act, A_NET_EDEV, EXIT_IF_NOT_FOUND);
			act[q]->item_list = act[p]->item_list;
			act[q]->item_list_sz = act[p]->item_list_sz;
			act[q]->options |= AO_LIST_ON_CMDLINE;
		}

		else if (!strcmp(argv[opt], "--help")) {
			/* Display help message */
			display_help(argv[0]);
		}

		else if (!strcmp(argv[opt], "--human")) {
			/* Display sizes in a human readable format */
			flags |= S_F_UNIT;
			opt++;
		}

		else if (!strncmp(argv[opt], "--dec=", 6) && (strlen(argv[opt]) == 7)) {
			/* Get number of decimal places */
			dplaces_nr = atoi(argv[opt] + 6);
			if ((dplaces_nr < 0) || (dplaces_nr > 2)) {
				usage(argv[0]);
			}
			opt++;
		}

		else if (!strcmp(argv[opt], "-I")) {
			/* Parse -I option */
			if (parse_sar_I_opt(argv, &opt, act)) {
				usage(argv[0]);
			}
		}

		else if (!strcmp(argv[opt], "-D")) {
			/* Option to tell sar to write to saYYYYMMDD data files */
			flags |= S_F_SA_YYYYMMDD;
			opt++;
		}

		else if (!strcmp(argv[opt], "-P")) {
			/* Parse -P option */
			if (parse_sa_P_opt(argv, &opt, &flags, act)) {
				usage(argv[0]);
			}
		}

		else if (!strcmp(argv[opt], "-o")) {
			if (to_file[0]) {
				/* Output file already specified */
				usage(argv[0]);
			}
			/* Save stats to a file */
			if ((argv[++opt]) && strncmp(argv[opt], "-", 1) &&
			    (strspn(argv[opt], DIGITS) != strlen(argv[opt]))) {
				strncpy(to_file, argv[opt++], MAX_FILE_LEN);
				to_file[MAX_FILE_LEN - 1] = '\0';
			}
			else {
				strcpy(to_file, "-");
			}
		}

		else if (!strcmp(argv[opt], "-f")) {
			if (from_file[0] || day_offset) {
				/* Input file already specified */
				usage(argv[0]);
			}
			/* Read stats from a file */
			if ((argv[++opt]) && strncmp(argv[opt], "-", 1) &&
			    (strspn(argv[opt], DIGITS) != strlen(argv[opt]))) {
				strncpy(from_file, argv[opt++], MAX_FILE_LEN);
				from_file[MAX_FILE_LEN - 1] = '\0';
				/* Check if this is an alternate directory for sa files */
				check_alt_sa_dir(from_file, day_offset, -1);
			}
			else {
				set_default_file(from_file, day_offset, -1);
			}
		}

		else if (!strcmp(argv[opt], "-s")) {
			/* Get time start */
			if (parse_timestamp(argv, &opt, &tm_start, DEF_TMSTART)) {
				usage(argv[0]);
			}
		}

		else if (!strcmp(argv[opt], "-e")) {
			/* Get time end */
			if (parse_timestamp(argv, &opt, &tm_end, DEF_TMEND)) {
				usage(argv[0]);
			}
		}

		else if (!strcmp(argv[opt], "-i")) {
			if (!argv[++opt] || (strspn(argv[opt], DIGITS) != strlen(argv[opt]))) {
				usage(argv[0]);
			}
			interval = atol(argv[opt++]);
			if (interval < 1) {
				usage(argv[0]);
			}
			flags |= S_F_INTERVAL_SET;
		}

		else if (!strcmp(argv[opt], "-m")) {
			if (!argv[++opt]) {
				usage(argv[0]);
			}
			/* Parse option -m */
			if (parse_sar_m_opt(argv, &opt, act)) {
				usage(argv[0]);
			}
		}

		else if (!strcmp(argv[opt], "-n")) {
			if (!argv[++opt]) {
				usage(argv[0]);
			}
			/* Parse option -n */
			if (parse_sar_n_opt(argv, &opt, act)) {
				usage(argv[0]);
			}
		}

		else if ((strlen(argv[opt]) > 1) &&
			 (strlen(argv[opt]) < 4) &&
			 !strncmp(argv[opt], "-", 1) &&
			 (strspn(argv[opt] + 1, DIGITS) == (strlen(argv[opt]) - 1))) {
			if (from_file[0] || day_offset) {
				/* Input file already specified */
				usage(argv[0]);
			}
			day_offset = atoi(argv[opt++] + 1);
		}

		else if (!strncmp(argv[opt], "-", 1)) {
			/* Other options not previously tested */
			if ((rc = parse_sar_opt(argv, &opt, act, &flags, C_SAR)) != 0) {
				if (rc == 1) {
					usage(argv[0]);
				}
				exit(1);
			}
			opt++;
		}

		else if (interval < 0) {
			/* Get interval */
			if (strspn(argv[opt], DIGITS) != strlen(argv[opt])) {
				usage(argv[0]);
			}
			interval = atol(argv[opt++]);
			if (interval < 0) {
				usage(argv[0]);
			}
		}

		else {
			/* Get count value */
			if ((strspn(argv[opt], DIGITS) != strlen(argv[opt])) ||
			    !interval) {
				usage(argv[0]);
			}
			if (count) {
				/* Count parameter already set */
				usage(argv[0]);
			}
			count = atol(argv[opt++]);
			if (count < 1) {
				usage(argv[0]);
			}
		}
	}

	/* 'sar' is equivalent to 'sar -f' */
	if ((argc == 1) ||
	    ((interval < 0) && !from_file[0] && !to_file[0])) {
		set_default_file(from_file, day_offset, -1);
	}

	if (tm_start.use && tm_end.use && (tm_end.tm_hour < tm_start.tm_hour)) {
		tm_end.tm_hour += 24;
	}

	/*
	 * Check option dependencies.
	 */
	/* You read from a file OR you write to it... */
	if (from_file[0] && to_file[0]) {
		fprintf(stderr, _("-f and -o options are mutually exclusive\n"));
		exit(1);
	}
	/* Use time start or option -i only when reading stats from a file */
	if ((tm_start.use || INTERVAL_SET(flags)) && !from_file[0]) {
		fprintf(stderr,
			_("Not reading from a system activity file (use -f option)\n"));
		exit(1);
	}
	/* Don't print stats since boot time if -o or -f options are used */
	if (!interval && (from_file[0] || to_file[0])) {
		usage(argv[0]);
	}

	/* Cannot enter a day shift with -o option */
	if (to_file[0] && day_offset) {
		usage(argv[0]);
	}

	if (USE_PRETTY_OPTION(flags)) {
		dm_major = get_devmap_major();
	}

	if (!count) {
		/*
		 * count parameter not set: Display all the contents of the file
		 * or generate a report continuously.
		 */
		count = -1;
	}

	/* Default is CPU activity... */
	select_default_activity(act);

	/* Check S_TIME_FORMAT variable contents */
	if (!is_iso_time_fmt())
		flags |= S_F_PREFD_TIME_OUTPUT;

	/* Reading stats from file: */
	if (from_file[0]) {
		if (interval < 0) {
			interval = 1;
		}

		/* Read stats from file */
		read_stats_from_file(from_file);

		/* Free stuctures and activity bitmaps */
		free_bitmaps(act);
		free_structures(act);

		return 0;
	}

	/* Reading stats from sadc: */

	/* Create anonymous pipe */
	if (pipe(fd) == -1) {
		perror("pipe");
		exit(4);
	}

	switch (fork()) {

	case -1:
		perror("fork");
		exit(4);
		break;

	case 0: /* Child */
		if (dup2(fd[1], STDOUT_FILENO) < 0) {
			perror("dup2");
			exit(4);
		}
		CLOSE_ALL(fd);

		/*
		 * Prepare options for sadc.
		 */
		/* Program name */
		salloc(0, SADC);

		/* Interval value */
		if (interval < 0) {
			usage(argv[0]);
		}
		else if (!interval) {
			strcpy(ltemp, "1");
			/*
			 * Display stats since system startup: Set <interval> to 1.
			 * <count> arg will also be set to 1 below.
			 */
			salloc(args_idx++, ltemp);
		}
		else {
			sprintf(ltemp, "%ld", interval);
		}
		salloc(args_idx++, ltemp);

		/* Count number */
		if (count >= 0) {
			sprintf(ltemp, "%ld", count + 1);
			salloc(args_idx++, ltemp);
		}

		/* Flags to be passed to sadc */
		salloc(args_idx++, "-Z");

		/* Writing data to a file (option -o) */
		if (to_file[0]) {
			/* Set option -D if entered */
			if (USE_SA_YYYYMMDD(flags)) {
				salloc(args_idx++, "-D");
			}
			/* Collect all possible activities (option -S XALL for sadc) */
			salloc(args_idx++, "-S");
			salloc(args_idx++, K_XALL);
			/* Outfile arg */
			salloc(args_idx++, to_file);
		}
		else {
			/*
			 * If option -o hasn't been used, then tell sadc
			 * to collect only activities that will be displayed.
			 */
			salloc(args_idx++, "-S");
			strcpy(ltemp, K_A_NULL);
			for (i = 0; i < NR_ACT; i++) {
				if (IS_SELECTED(act[i]->options)) {
					strcat(ltemp, ",");
					strcat(ltemp, act[i]->name);
				}
			}
			salloc(args_idx++, ltemp);
		}

		/* Last arg is NULL */
		args[args_idx] = NULL;

		/* Call now the data collector */
#ifdef DEBUG
		fprintf(stderr, "%s: 1.sadc: %s\n", __FUNCTION__, SADC_PATH);
#endif

		execv(SADC_PATH, args);
#ifdef DEBUG
		fprintf(stderr, "%s: 2.sadc: %s\n", __FUNCTION__, SADC);
#endif
		execvp(SADC, args);
		/*
		 * Note: Don't use execl/execlp since we don't have a fixed number of
		 * args to give to sadc.
		 */
		fprintf(stderr, _("Cannot find the data collector (%s)\n"), SADC);
		perror("exec");
		exit(4);
		break;

	default: /* Parent */
		if (dup2(fd[0], STDIN_FILENO) < 0) {
			perror("dup2");
			exit(4);
		}
		CLOSE_ALL(fd);

		/* Get now the statistics */
		read_stats();

		break;
	}

	/* Free structures and activity bitmaps */
	free_bitmaps(act);
	free_structures(act);

	return 0;
}

Project: sysstat
File: sa_common.c

int parse_sar_I_opt(char *argv[], int *opt, struct activity *act[])
{
	int p;

	/* Select interrupt activity */
	p = get_activity_position(act, A_IRQ, EXIT_IF_NOT_FOUND);
	act[p]->options |= AO_SELECTED;

	if (argv[++(*opt)]) {
		if (parse_values(argv[*opt], act[p]->bitmap->b_array,
			     act[p]->bitmap->b_size, K_SUM))
			return 1;
		(*opt)++;
		return 0;
	}

	return 1;
}

Project: sysstat
File: sadf.c

void seek_file_position(int ifd, int action)
{
	static off_t fpos = -1;
	static unsigned int save_cpu_nr = 0;

	if (action == DO_SAVE) {
		/* Save current file position */
		if ((fpos = lseek(ifd, 0, SEEK_CUR)) < 0) {
			perror("lseek");
			exit(2);
		}
		save_cpu_nr = file_hdr.sa_cpu_nr;
	}
	else if (action == DO_RESTORE) {
		/* Rewind file */
		if ((fpos < 0) || (lseek(ifd, fpos, SEEK_SET) < fpos)) {
			perror("lseek");
			exit(2);
		}
		file_hdr.sa_cpu_nr = save_cpu_nr;
	}
}

Project: sysstat
File: sa_common.c

int sa_get_record_timestamp_struct(unsigned int l_flags, struct record_header *record_hdr,
				   struct tm *rectime, struct tm *loctime)
{
	struct tm *ltm = NULL;
	int rc = 0;

	/* Fill localtime structure if given */
	if (loctime) {
		ltm = localtime_r((const time_t *) &(record_hdr->ust_time), loctime);
		if (ltm) {
			/* Done so that we have some default values */
			*rectime = *loctime;
		}
		else {
			rc = 1;
		}
	}

	/* Fill generic rectime structure */
	if (PRINT_LOCAL_TIME(l_flags) && !ltm) {
		/* Get local time if not already done */
		ltm = localtime_r((const time_t *) &(record_hdr->ust_time), rectime);
	}

	if (!PRINT_LOCAL_TIME(l_flags) && !PRINT_TRUE_TIME(l_flags)) {
		/*
		 * Get time in UTC
		 * (the user doesn't want local time nor time of file's creator).
		 */
		ltm = gmtime_r((const time_t *) &(record_hdr->ust_time), rectime);
	}

	if (!ltm) {
		rc = 1;
	}

	if (PRINT_TRUE_TIME(l_flags)) {
		/* Time of file's creator */
		rectime->tm_hour = record_hdr->hour;
		rectime->tm_min  = record_hdr->minute;
		rectime->tm_sec  = record_hdr->second;
	}

	return rc;
}

Project: sysstat
File: sar.c

int sa_read(void *buffer, size_t size)
{
	ssize_t n;

	while (size) {

		if ((n = read(STDIN_FILENO, buffer, size)) < 0) {
			perror("read");
			exit(2);
		}

		if (!n)
			return 1;	/* EOF */

		size -= n;
		buffer = (char *) buffer + n;
	}

	return 0;
}

Project: sysstat
File: sa_common.c

void guess_sa_name(char *sa_dir, struct tm *rectime, int *sa_name)
{
	char filename[MAX_FILE_LEN];
	struct stat sb;
	time_t sa_mtime;

	/* Use saDD by default */
	*sa_name = 0;

	/* Look for saYYYYMMDD */
	snprintf(filename, MAX_FILE_LEN,
		 "%s/sa%04d%02d%02d", sa_dir,
		 rectime->tm_year + 1900,
		 rectime->tm_mon + 1,
		 rectime->tm_mday);
	filename[MAX_FILE_LEN - 1] = '\0';

	if (stat(filename, &sb) < 0)
		/* Cannot find or access saYYYYMMDD, so use saDD */
		return;
	sa_mtime = sb.st_mtime;

	/* Look for saDD */
	snprintf(filename, MAX_FILE_LEN,
		 "%s/sa%02d", sa_dir,
		 rectime->tm_mday);
	filename[MAX_FILE_LEN - 1] = '\0';

	if (stat(filename, &sb) < 0) {
		/* Cannot find or access saDD, so use saYYYYMMDD */
		*sa_name = 1;
		return;
	}

	if (sa_mtime > sb.st_mtime) {
		/* saYYYYMMDD is more recent than saDD, so use it */
		*sa_name = 1;
	}
}

Project: sysstat
File: sar.c

void int_handler(int sig)
{
	sigint_caught = 1;
	printf("\n");	/* Skip "^C" displayed on screen */

}

Project: sysstat
File: sa_common.c

int check_disk_reg(struct activity *a, int curr, int ref, int pos)
{
	struct stats_disk *sdc, *sdp;
	int j0, j = pos;

	if (!a->nr[ref])
		/*
		 * No items found in previous iteration:
		 * Current interface is necessarily new.
		 */
		return -1;

	if (j >= a->nr[ref]) {
		j = a->nr[ref] - 1;
	}
	j0 = j;

	sdc = (struct stats_disk *) ((char *) a->buf[curr] + pos * a->msize);

	do {
		sdp = (struct stats_disk *) ((char *) a->buf[ref] + j * a->msize);

		if ((sdc->major == sdp->major) &&
		    (sdc->minor == sdp->minor)) {
			/*
			 * Disk found.
			 * If all the counters have decreased then the likelyhood
			 * is that the disk has been unregistered and a new disk inserted.
			 * If only one or two have decreased then the likelyhood
			 * is that the counter has simply wrapped.
			 */
			if ((sdc->nr_ios < sdp->nr_ios) &&
			    (sdc->rd_sect < sdp->rd_sect) &&
			    (sdc->wr_sect < sdp->wr_sect))
				/* Same device registered again */
				return -2;

			return j;
		}
		if (++j >= a->nr[ref]) {
			j = 0;
		}
	}
	while (j != j0);

	/* This is a newly registered device */
	return -1;
}

Project: sysstat
File: sar.c

void salloc(int i, char *ltemp)
{
	if ((args[i] = (char *) malloc(strlen(ltemp) + 1)) == NULL) {
		perror("malloc");
		exit(4);
	}
	strcpy(args[i], ltemp);
}

Project: sysstat
File: sadf.c

void rw_curr_act_stats(int ifd, int *curr, long *cnt, int *eosaf,
		       unsigned int act_id, int *reset, struct file_activity *file_actlst,
		       struct tm *rectime, struct tm *loctime, char *file,
		       struct file_magic *file_magic)
{
	int rtype;
	int next, reset_cd;

	/* Rewind file */
	seek_file_position(ifd, DO_RESTORE);

	if (DISPLAY_FIELD_LIST(fmt[f_position]->options)) {
		/* Print field list */
		list_fields(act_id);
	}

	/*
	 * Restore the first stats collected.
	 * Used to compute the rate displayed on the first line.
	 */
	copy_structures(act, id_seq, record_hdr, !*curr, 2);

	*cnt  = count;
	reset_cd = 1;

	do {
		/* Display <count> lines of stats */
		*eosaf = read_next_sample(ifd, IGNORE_RESTART | DONT_READ_CPU_NR,
					  *curr, file, &rtype, 0, file_magic,
					  file_actlst, rectime, loctime, UEOF_STOP);

		if (!*eosaf && (rtype != R_RESTART) && (rtype != R_COMMENT)) {
			next = generic_write_stats(*curr, tm_start.use, tm_end.use, *reset, cnt,
						   NULL, rectime, loctime, reset_cd, act_id);
			reset_cd = 0;

			if (next) {
				/*
				 * next is set to 1 when we were close enough to desired interval.
				 * In this case, the call to generic_write_stats() has actually
				 * displayed a line of stats.
				 */
				*curr ^= 1;
				if (*cnt > 0) {
					(*cnt)--;
				}
			}
			*reset = FALSE;
		}
	}
	while (*cnt && !*eosaf && (rtype != R_RESTART));

	*reset = TRUE;
}

Project: sysstat
File: sar.c

void display_help(char *progname)
{
	print_usage_title(stdout, progname);
	printf(_("Main options and reports (report name between square brackets):\n"));
	printf(_("\t-B\tPaging statistics [A_PAGE]\n"));
	printf(_("\t-b\tI/O and transfer rate statistics [A_IO]\n"));
	printf(_("\t-d\tBlock devices statistics [A_DISK]\n"));
	printf(_("\t-F [ MOUNT ]\n"));
	printf(_("\t\tFilesystems statistics [A_FS]\n"));
	printf(_("\t-H\tHugepages utilization statistics [A_HUGE]\n"));
	printf(_("\t-I { <int_list> | SUM | ALL }\n"
		 "\t\tInterrupts statistics [A_IRQ]\n"));
	printf(_("\t-m { <keyword> [,...] | ALL }\n"
		 "\t\tPower management statistics [A_PWR_...]\n"
		 "\t\tKeywords are:\n"
		 "\t\tCPU\tCPU instantaneous clock frequency\n"
		 "\t\tFAN\tFans speed\n"
		 "\t\tFREQ\tCPU average clock frequency\n"
		 "\t\tIN\tVoltage inputs\n"
		 "\t\tTEMP\tDevices temperature\n"
		 "\t\tUSB\tUSB devices plugged into the system\n"));
	printf(_("\t-n { <keyword> [,...] | ALL }\n"
		 "\t\tNetwork statistics [A_NET_...]\n"
		 "\t\tKeywords are:\n"
		 "\t\tDEV\tNetwork interfaces\n"
		 "\t\tEDEV\tNetwork interfaces (errors)\n"
		 "\t\tNFS\tNFS client\n"
		 "\t\tNFSD\tNFS server\n"
		 "\t\tSOCK\tSockets\t(v4)\n"
		 "\t\tIP\tIP traffic\t(v4)\n"
		 "\t\tEIP\tIP traffic\t(v4) (errors)\n"
		 "\t\tICMP\tICMP traffic\t(v4)\n"
		 "\t\tEICMP\tICMP traffic\t(v4) (errors)\n"
		 "\t\tTCP\tTCP traffic\t(v4)\n"
		 "\t\tETCP\tTCP traffic\t(v4) (errors)\n"
		 "\t\tUDP\tUDP traffic\t(v4)\n"
		 "\t\tSOCK6\tSockets\t(v6)\n"
		 "\t\tIP6\tIP traffic\t(v6)\n"
		 "\t\tEIP6\tIP traffic\t(v6) (errors)\n"
		 "\t\tICMP6\tICMP traffic\t(v6)\n"
		 "\t\tEICMP6\tICMP traffic\t(v6) (errors)\n"
		 "\t\tUDP6\tUDP traffic\t(v6)\n"
		 "\t\tFC\tFibre channel HBAs\n"
		 "\t\tSOFT\tSoftware-based network processing\n"));
	printf(_("\t-q\tQueue length and load average statistics [A_QUEUE]\n"));
	printf(_("\t-r [ ALL ]\n"
		 "\t\tMemory utilization statistics [A_MEMORY]\n"));
	printf(_("\t-S\tSwap space utilization statistics [A_MEMORY]\n"));
	printf(_("\t-u [ ALL ]\n"
		 "\t\tCPU utilization statistics [A_CPU]\n"));
	printf(_("\t-v\tKernel tables statistics [A_KTABLES]\n"));
	printf(_("\t-W\tSwapping statistics [A_SWAP]\n"));
	printf(_("\t-w\tTask creation and system switching statistics [A_PCSW]\n"));
	printf(_("\t-y\tTTY devices statistics [A_SERIAL]\n"));
	exit(0);
}

Project: sysstat
File: sadf.c

int main(int argc, char **argv)
{
	int opt = 1, sar_options = 0;
	int day_offset = 0;
	int i, rc, p, q;
	char dfile[MAX_FILE_LEN];
	char *t, *v;

	/* Compute page shift in kB */
	get_kb_shift();

	dfile[0] = '\0';

#ifdef USE_NLS
	/* Init National Language Support */
	init_nls();
#endif

	tm_start.use = tm_end.use = FALSE;

	/* Allocate and init activity bitmaps */
	allocate_bitmaps(act);

	/* Init some structures */
	init_structures();

	/* Process options */
	while (opt < argc) {

		if (!strcmp(argv[opt], "-I")) {
			if (!sar_options) {
				usage(argv[0]);
			}
			if (parse_sar_I_opt(argv, &opt, act)) {
				usage(argv[0]);
			}
		}

		else if (!strcmp(argv[opt], "-P")) {
			if (parse_sa_P_opt(argv, &opt, &flags, act)) {
				usage(argv[0]);
			}
		}

		else if (!strncmp(argv[opt], "--dev=", 6)) {
			/* Parse devices entered on the command line */
			p = get_activity_position(act, A_DISK, EXIT_IF_NOT_FOUND);
			parse_sa_devices(argv[opt], act[p], MAX_DEV_LEN, &opt, 6);
		}

		else if (!strncmp(argv[opt], "--fs=", 5)) {
			/* Parse devices entered on the command line */
			p = get_activity_position(act, A_FS, EXIT_IF_NOT_FOUND);
			parse_sa_devices(argv[opt], act[p], MAX_FS_LEN, &opt, 5);
		}

		else if (!strncmp(argv[opt], "--iface=", 8)) {
			/* Parse devices entered on the command line */
			p = get_activity_position(act, A_NET_DEV, EXIT_IF_NOT_FOUND);
			parse_sa_devices(argv[opt], act[p], MAX_IFACE_LEN, &opt, 8);
			q = get_activity_position(act, A_NET_EDEV, EXIT_IF_NOT_FOUND);
			act[q]->item_list = act[p]->item_list;
			act[q]->item_list_sz = act[p]->item_list_sz;
			act[q]->options |= AO_LIST_ON_CMDLINE;
		}

		else if (!strcmp(argv[opt], "-s")) {
			/* Get time start */
			if (parse_timestamp(argv, &opt, &tm_start, DEF_TMSTART)) {
				usage(argv[0]);
			}
		}

		else if (!strcmp(argv[opt], "-e")) {
			/* Get time end */
			if (parse_timestamp(argv, &opt, &tm_end, DEF_TMEND)) {
				usage(argv[0]);
			}
		}

		else if (!strcmp(argv[opt], "-O")) {
			/* Parse output options */
			if (!argv[++opt] || sar_options) {
				usage(argv[0]);
			}
			for (t = strtok(argv[opt], ","); t; t = strtok(NULL, ",")) {
				if (!strcmp(t, K_SKIP_EMPTY)) {
					flags |= S_F_SVG_SKIP;
				}
				else if (!strcmp(t, K_AUTOSCALE)) {
					flags |= S_F_SVG_AUTOSCALE;
				}
				else if (!strcmp(t, K_ONEDAY)) {
					flags |= S_F_SVG_ONE_DAY;
				}
				else if (!strcmp(t, K_SHOWIDLE)) {
					flags |= S_F_SVG_SHOW_IDLE;
				}
				else if (!strcmp(t, K_SHOWINFO)) {
					flags |= S_F_SVG_SHOW_INFO;
				}
				else if (!strcmp(t, K_DEBUG)) {
					flags |= S_F_RAW_DEBUG_MODE;
				}
				else if (!strncmp(t, K_HEIGHT, strlen(K_HEIGHT))) {
					v = t + strlen(K_HEIGHT);
					if (!strlen(v) || (strspn(v, DIGITS) != strlen(v))) {
						usage(argv[0]);
					}
					canvas_height = atoi(v);
					flags |= S_F_SVG_HEIGHT;
				}
				else if (!strcmp(t, K_PACKED)) {
					flags |= S_F_SVG_PACKED;
				}
				else if (!strcmp(t, K_SHOWTOC)) {
					flags |= S_F_SVG_SHOW_TOC;
				}
				else {
					usage(argv[0]);
				}
			}
			opt++;
		}

		else if ((strlen(argv[opt]) > 1) &&
			 (strlen(argv[opt]) < 4) &&
			 !strncmp(argv[opt], "-", 1) &&
			 (strspn(argv[opt] + 1, DIGITS) == (strlen(argv[opt]) - 1))) {
			if (dfile[0] || day_offset) {
				/* File already specified */
				usage(argv[0]);
			}
			day_offset = atoi(argv[opt++] + 1);
		}

		else if (!strcmp(argv[opt], "--")) {
			sar_options = 1;
			opt++;
		}

		else if (!strcmp(argv[opt], "-m")) {
			if (!argv[++opt] || !sar_options) {
				usage(argv[0]);
			}
			/* Parse sar's option -m */
			if (parse_sar_m_opt(argv, &opt, act)) {
				usage(argv[0]);
			}
		}

		else if (!strcmp(argv[opt], "-n")) {
			if (!argv[++opt] || !sar_options) {
				usage(argv[0]);
			}
			/* Parse sar's option -n */
			if (parse_sar_n_opt(argv, &opt, act)) {
				usage(argv[0]);
			}
		}

		else if (!strncmp(argv[opt], "-", 1)) {
			/* Other options not previously tested */
			if (sar_options) {
				if ((rc = parse_sar_opt(argv, &opt, act, &flags, C_SADF)) != 0) {
					if (rc == 1) {
						usage(argv[0]);
					}
					exit(1);
				}
			}
			else {

				for (i = 1; *(argv[opt] + i); i++) {

					switch (*(argv[opt] + i)) {

					case 'C':
						flags |= S_F_COMMENT;
						break;

					case 'c':
						if (format) {
							usage(argv[0]);
						}
						format = F_CONV_OUTPUT;
						break;

					case 'd':
						if (format) {
							usage(argv[0]);
						}
						format = F_DB_OUTPUT;
						break;

					case 'g':
						if (format) {
							usage(argv[0]);
						}
						format = F_SVG_OUTPUT;
						break;

					case 'h':
						flags |= S_F_HORIZONTALLY;
						break;

					case 'H':
						flags |= S_F_HDR_ONLY;
						break;

					case 'j':
						if (format) {
							usage(argv[0]);
						}
						format = F_JSON_OUTPUT;
						break;

					case 'p':
						if (format) {
							usage(argv[0]);
						}
						format = F_PPC_OUTPUT;
						break;

					case 'r':
						if (format) {
							usage(argv[0]);
						}
						format = F_RAW_OUTPUT;
						break;

					case 'T':
						flags |= S_F_LOCAL_TIME;
						break;

					case 't':
						flags |= S_F_TRUE_TIME;
						break;

					case 'U':
						flags |= S_F_SEC_EPOCH;
						break;

					case 'x':
						if (format) {
							usage(argv[0]);
						}
						format = F_XML_OUTPUT;
						break;

					case 'V':
						print_version();
						break;

					default:
						usage(argv[0]);
					}
				}
			}
			opt++;
		}

		/* Get data file name */
		else if (strspn(argv[opt], DIGITS) != strlen(argv[opt])) {
			if (dfile[0] || day_offset) {
				/* File already specified */
				usage(argv[0]);
			}
			/* Write data to file */
			strncpy(dfile, argv[opt++], MAX_FILE_LEN);
			dfile[MAX_FILE_LEN - 1] = '\0';
			/* Check if this is an alternate directory for sa files */
			check_alt_sa_dir(dfile, 0, -1);
		}

		else if (interval < 0) {
			/* Get interval */
			if (strspn(argv[opt], DIGITS) != strlen(argv[opt])) {
				usage(argv[0]);
			}
			interval = atol(argv[opt++]);
			if (interval <= 0) {
				usage(argv[0]);
			}
		}

		else {
			/* Get count value */
			if (strspn(argv[opt], DIGITS) != strlen(argv[opt])) {
				usage(argv[0]);
			}
			if (count) {
				/* Count parameter already set */
				usage(argv[0]);
			}
			count = atol(argv[opt++]);
			if (count < 0) {
				usage(argv[0]);
			}
			else if (!count) {
				count = -1;	/* To generate a report continuously */
			}
		}
	}

	/* sadf reads current daily data file by default */
	if (!dfile[0]) {
		set_default_file(dfile, day_offset, -1);
	}

	if (tm_start.use && tm_end.use && (tm_end.tm_hour < tm_start.tm_hour)) {
		tm_end.tm_hour += 24;
	}

	if (USE_PRETTY_OPTION(flags)) {
		dm_major = get_devmap_major();
	}

	/* Options -T, -t and -U are mutually exclusive */
	if ((PRINT_LOCAL_TIME(flags) + PRINT_TRUE_TIME(flags) +
	    PRINT_SEC_EPOCH(flags)) > 1) {
		usage(argv[0]);
	}

	/*
	 * Display all the contents of the daily data file if the count parameter
	 * was not set on the command line.
	 */
	if (!count) {
		count = -1;
	}

	/* Default is CPU activity */
	select_default_activity(act);

	/* Check options consistency with selected output format. Default is PPC display */
	check_format_options();

	if (interval < 0) {
		interval = 1;
	}

	if (format == F_CONV_OUTPUT) {
		/* Convert file to current format */
		convert_file(dfile, act);
	}
	else {
		/* Read stats from file */
		read_stats_from_file(dfile);
	}

	/* Free bitmaps */
	free_bitmaps(act);

	return 0;
}

Project: sysstat
File: sar.c

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, void *rec_hdr_tmp,
			   int endian_mismatch, int arch_64, size_t b_size)
{
	int p, reset_cd;
	unsigned long lines = 0;
	unsigned char rtype;
	int davg = 0, next, inc = 0;

	if (lseek(ifd, fpos, SEEK_SET) < fpos) {
		perror("lseek");
		exit(2);
	}

	/*
	 * Restore the first stats collected.
	 * Used to compute the rate displayed on the first line.
	 */
	copy_structures(act, id_seq, record_hdr, !*curr, 2);

	*cnt  = count;

	/* Assess number of lines printed when a bitmap is used */
	p = get_activity_position(act, act_id, EXIT_IF_NOT_FOUND);
	if (act[p]->bitmap) {
		inc = count_bits(act[p]->bitmap->b_array,
				 BITMAP_SIZE(act[p]->bitmap->b_size));
	}
	reset_cd = 1;

	do {
		/*
		 * Display <count> lines of stats.
		 * Start with reading current sample's record header.
		 */
		*eosaf = read_record_hdr(ifd, rec_hdr_tmp, &record_hdr[*curr],
					 &file_hdr, arch_64, endian_mismatch, UEOF_STOP, b_size);
		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,
					     endian_mismatch, arch_64, file, file_magic, UEOF_STOP);
		}

		if ((lines >= rows) || !lines) {
			lines = 0;
			dis = 1;
		}
		else
			dis = 0;

		if (!*eosaf && (rtype != R_RESTART)) {

			if (rtype == R_COMMENT) {
				/* Display comment */
				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,
							    endian_mismatch, arch_64);
				if (next && lines) {
					/*
					 * A line of comment was actually displayed: Count it in the
					 * total number of displayed lines.
					 * If no lines of stats had been previously displayed, ignore it
					 * to make sure the header line will be displayed.
					 */
					lines++;
				}
				continue;
			}

			/* next is set to 1 when we were close enough to desired interval */
			next = write_stats(*curr, USE_SA_FILE, cnt, tm_start.use, tm_end.use,
					   *reset, act_id, reset_cd);
			reset_cd = 0;
			if (next && (*cnt > 0)) {
				(*cnt)--;
			}

			if (next) {
				davg++;
				*curr ^= 1;

				if (inc) {
					lines += inc;
				}
				else {
					lines += act[p]->nr[*curr];
				}
			}
			*reset = FALSE;
		}
	}
	while (*cnt && !*eosaf && (rtype != R_RESTART));

	if (davg) {
		write_stats_avg(!*curr, USE_SA_FILE, act_id);
	}

	*reset = TRUE;
}

Project: sysstat
File: sar.c

int check_line_hdr(void)
{
	int i, rc = FALSE;

	/* Get number of options entered on the command line */
	if (get_activity_nr(act, AO_SELECTED, COUNT_OUTPUTS) > 1)
		return TRUE;

	for (i = 0; i < NR_ACT; i++) {
		if (IS_SELECTED(act[i]->options)) {
			/* Special processing for activities using a bitmap */
			if (act[i]->bitmap) {
				if (count_bits(act[i]->bitmap->b_array,
					       BITMAP_SIZE(act[i]->bitmap->b_size)) > 1) {
					rc = TRUE;
				}
			}
			else if (act[i]->nr_ini > 1) {
				rc = TRUE;
			}
			/* Stop now since we have only one selected activity */
			break;
		}
	}

	return rc;
}

Project: sysstat
File: sar.c

__print_funct_t print_sar_comment(int *tab, int action, char *cur_date, char *cur_time, int utc,
				  char *comment, struct file_header *file_hdr)
{
	printf("%-11s", cur_time);
	cprintf_s(IS_COMMENT, "  COM %s\n", comment);
}

Project: sysstat
File: sadf.c

void usage(char *progname)
{
	fprintf(stderr,
		_("Usage: %s [ options ] [ <interval> [ <count> ] ] [ <datafile> | -[0-9]+ ]\n"),
		progname);

	fprintf(stderr, _("Options are:\n"
			  "[ -C ] [ -c | -d | -g | -j | -p | -r | -x ] [ -H ] [ -h ] [ -T | -t | -U ] [ -V ]\n"
			  "[ -O <opts> [,...] ] [ -P { <cpu> [,...] | ALL } ]\n"
			  "[ --dev=<dev_list> ] [ --fs=<fs_list> ] [ --iface=<iface_list> ]\n"
			  "[ -s [ <hh:mm[:ss]> ] ] [ -e [ <hh:mm[:ss]> ] ]\n"
			  "[ -- <sar_options> ]\n"));
	exit(1);
}

Project: sysstat
File: sadf.c

void display_curr_act_graphs(int ifd, int *curr, long *cnt, int *eosaf,
			     int p, int *reset, struct file_activity *file_actlst,
			     struct tm *rectime, struct tm *loctime,
			     char *file, struct file_magic *file_magic, int *g_nr,
			     int nr_act_dispd)
{
	struct svg_parm parm;
	int rtype;
	int next, reset_cd;

	/* Rewind file */
	seek_file_position(ifd, DO_RESTORE);

	/*
	 * Restore the first stats collected.
	 * Used to compute the rate displayed on the first line.
	 */
	copy_structures(act, id_seq, record_hdr, !*curr, 2);

	parm.graph_no = *g_nr;
	parm.ust_time_ref = (unsigned long long) get_time_ref();
	parm.ust_time_first = record_hdr[2].ust_time;
	parm.restart = TRUE;
	parm.file_hdr = &file_hdr;
	parm.nr_act_dispd = nr_act_dispd;

	*cnt  = count;
	reset_cd = 1;

	/* Allocate graphs arrays */
	(*act[p]->f_svg_print)(act[p], !*curr, F_BEGIN, &parm, 0, &record_hdr[!*curr]);

	do {
		*eosaf = read_next_sample(ifd, IGNORE_RESTART | IGNORE_COMMENT | SET_TIMESTAMPS,
					  *curr, file, &rtype, 0, file_magic,
					  file_actlst, rectime, loctime, UEOF_CONT);

		if (!*eosaf && (rtype != R_COMMENT) && (rtype != R_RESTART)) {

			next = generic_write_stats(*curr, tm_start.use, tm_end.use, *reset, cnt,
						   &parm, rectime, loctime, reset_cd, act[p]->id);
			reset_cd = 0;
			if (next) {
				/*
				 * next is set to 1 when we were close enough to desired interval.
				 * In this case, the call to generic_write_stats() has actually
				 * displayed a line of stats.
				 */
				parm.restart = FALSE;
				parm.ust_time_end = record_hdr[*curr].ust_time;
				*curr ^= 1;
				if (*cnt > 0) {
					(*cnt)--;
				}
			}
			*reset = FALSE;
		}
		if (!*eosaf && (rtype == R_RESTART)) {
			parm.restart = TRUE;
			*reset = TRUE;
			/* Go to next statistics record, if possible */
			do {
				*eosaf = read_next_sample(ifd, IGNORE_RESTART | IGNORE_COMMENT | SET_TIMESTAMPS,
							  *curr, file, &rtype, 0, file_magic,
							  file_actlst, rectime, loctime, UEOF_CONT);
			}
			while (!*eosaf && ((rtype == R_RESTART) || (rtype == R_COMMENT)));

			*curr ^= 1;
		}
	}
	while (!*eosaf);

	*reset = TRUE;

	/* Determine X axis end value */
	if (DISPLAY_ONE_DAY(flags) &&
	    (parm.ust_time_ref + (3600 * 24) > parm.ust_time_end)) {
		parm.ust_time_end = parm.ust_time_ref + (3600 * 24);
	}

	/* Actually display graphs for current activity */
	(*act[p]->f_svg_print)(act[p], *curr, F_END, &parm, 0, &record_hdr[!*curr]);

	/* Update total number of graphs already displayed */
	*g_nr = parm.graph_no;
}

Project: sysstat
File: sar.c

void which_sadc(void)
{
	struct stat buf;

	if (stat(SADC_PATH, &buf) < 0) {
		printf(_("Data collector will be sought in PATH\n"));
	}
	else {
		printf(_("Data collector found: %s\n"), SADC_PATH);
	}
	exit(0);
}

Project: sysstat
File: sa_common.c

int print_special_record(struct record_header *record_hdr, unsigned int l_flags,
			 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,
			 int endian_mismatch, int arch_64)
{
	char cur_date[TIMESTAMP_LEN], cur_time[TIMESTAMP_LEN];
	int dp = 1;
	int p;

	/* Fill timestamp structure (rectime) for current record */
	if (sa_get_record_timestamp_struct(l_flags, record_hdr, rectime, loctime))
		return 0;

	/* If loctime is NULL, then use rectime for comparison */
	if (!loctime) {
		loctime = rectime;
	}

	/* The record must be in the interval specified by -s/-e options */
	if ((tm_start->use && (datecmp(loctime, tm_start) < 0)) ||
	    (tm_end->use && (datecmp(loctime, tm_end) > 0))) {
		/* Will not display the special record */
		dp = 0;
	}
	else {
		/* Set date and time strings to be displayed for current record */
		set_record_timestamp_string(l_flags, record_hdr,
					    cur_date, cur_time, TIMESTAMP_LEN, rectime);
	}

	if (rtype == R_RESTART) {
		/* Read new cpu number following RESTART record */
		file_hdr->sa_cpu_nr = read_nr_value(ifd, file, file_magic,
						    endian_mismatch, arch_64, TRUE);

		/*
		 * We don't know if CPU related activities will be displayed or not.
		 * But if it is the case, @nr_ini will be used in the loop
		 * to process all CPUs. So update their value here and
		 * reallocate buffers if needed.
		 * NB: We may have nr_allocated=0 here if the activity has
		 * not been collected in file (or if it has an unknown format).
		 */
		for (p = 0; p < NR_ACT; p++) {
			if (HAS_PERSISTENT_VALUES(act[p]->options)) {
				act[p]->nr_ini = file_hdr->sa_cpu_nr;
				if (act[p]->nr_ini > act[p]->nr_allocated) {
					reallocate_all_buffers(act[p], act[p]->nr_ini);
				}
			}
		}

		if (!dp)
			return 0;

		if (*ofmt->f_restart) {
			(*ofmt->f_restart)(&tab, F_MAIN, cur_date, cur_time,
					   !PRINT_LOCAL_TIME(l_flags) &&
					   !PRINT_TRUE_TIME(l_flags), file_hdr);
		}
	}
	else if (rtype == R_COMMENT) {
		char file_comment[MAX_COMMENT_LEN];

		/* Read and replace non printable chars in comment */
		replace_nonprintable_char(ifd, file_comment);

		if (!dp || !DISPLAY_COMMENT(l_flags))
			return 0;

		if (*ofmt->f_comment) {
			(*ofmt->f_comment)(&tab, F_MAIN, cur_date, cur_time,
					   !PRINT_LOCAL_TIME(l_flags) &&
					   !PRINT_TRUE_TIME(l_flags), file_comment,
					   file_hdr);
		}
	}

	return 1;
}

Project: sysstat
File: sa_common.c

unsigned long long get_global_cpu_statistics(struct activity *a, int prev, int curr,
					     unsigned int flags, unsigned char offline_cpu_bitmap[])
{
	int i;
	unsigned long long tot_jiffies_c, tot_jiffies_p;
	unsigned long long deltot_jiffies = 0;
	struct stats_cpu *scc, *scp;
	struct stats_cpu *scc_all = (struct stats_cpu *) ((char *) a->buf[curr]);
	struct stats_cpu *scp_all = (struct stats_cpu *) ((char *) a->buf[prev]);

	/*
	 * Initial processing.
	 * Compute CPU "all" as sum of all individual CPU. Done only on SMP machines (a->nr_ini > 1).
	 * For UP machines we keep the values read from global CPU line in /proc/stat.
	 * Also look for offline CPU: They won't be displayed, and some of their values may
	 * have to be modified.
	 */
	if (a->nr_ini > 1) {
		memset(scc_all, 0, sizeof(struct stats_cpu));
		memset(scp_all, 0, sizeof(struct stats_cpu));
	}

	for (i = 1; (i < a->nr_ini) && (i < a->bitmap->b_size + 1); i++) {

		/*
		 * The size of a->buf[...] CPU structure may be different from the default
		 * sizeof(struct stats_cpu) value if data have been read from a file!
		 * That's why we don't use a syntax like:
		 * scc = (struct stats_cpu *) a->buf[...] + i;
		 */
		scc = (struct stats_cpu *) ((char *) a->buf[curr] + i * a->msize);
		scp = (struct stats_cpu *) ((char *) a->buf[prev] + i * a->msize);

		/*
		 * Compute the total number of jiffies spent by current processor.
		 * NB: Don't add cpu_guest/cpu_guest_nice because cpu_user/cpu_nice
		 * already include them.
		 */
		tot_jiffies_c = scc->cpu_user + scc->cpu_nice +
				scc->cpu_sys + scc->cpu_idle +
				scc->cpu_iowait + scc->cpu_hardirq +
				scc->cpu_steal + scc->cpu_softirq;
		tot_jiffies_p = scp->cpu_user + scp->cpu_nice +
				scp->cpu_sys + scp->cpu_idle +
				scp->cpu_iowait + scp->cpu_hardirq +
				scp->cpu_steal + scp->cpu_softirq;

		/*
		 * If the CPU is offline then it is omited from /proc/stat:
		 * All the fields couldn't have been read and the sum of them is zero.
		 */
		if (tot_jiffies_c == 0) {
			/*
			 * CPU is currently offline.
			 * Set current struct fields (which have been set to zero)
			 * to values from previous iteration. Hence their values won't
			 * jump from zero when the CPU comes back online.
			 * Note that this workaround no longer fully applies with recent kernels,
			 * as I have noticed that when a CPU comes back online, some fields
			 * restart from their previous value (e.g. user, nice, system)
			 * whereas others restart from zero (idle, iowait)! To deal with this,
			 * the get_per_cpu_interval() function will set these previous values
			 * to zero if necessary.
			 */
			*scc = *scp;

			/*
			 * Mark CPU as offline to not display it
			 * (and thus it will not be confused with a tickless CPU).
			 */
			offline_cpu_bitmap[i >> 3] |= 1 << (i & 0x07);
		}

		if ((tot_jiffies_p == 0) && !WANT_SINCE_BOOT(flags)) {
			/*
			 * CPU has just come back online.
			 * Unfortunately, no reference values are available
			 * from a previous iteration, probably because it was
			 * already offline when the first sample has been taken.
			 * So don't display that CPU to prevent "jump-from-zero"
			 * output syndrome, and don't take it into account for CPU "all".
			 */
			offline_cpu_bitmap[i >> 3] |= 1 << (i & 0x07);
			continue;
		}

		/*
		 * Get interval for current CPU and add it to global CPU.
		 * Note: Previous idle and iowait values (saved in scp) may be modified here.
		 */
		deltot_jiffies += get_per_cpu_interval(scc, scp);

		scc_all->cpu_user += scc->cpu_user;
		scp_all->cpu_user += scp->cpu_user;

		scc_all->cpu_nice += scc->cpu_nice;
		scp_all->cpu_nice += scp->cpu_nice;

		scc_all->cpu_sys += scc->cpu_sys;
		scp_all->cpu_sys += scp->cpu_sys;

		scc_all->cpu_idle += scc->cpu_idle;
		scp_all->cpu_idle += scp->cpu_idle;

		scc_all->cpu_iowait += scc->cpu_iowait;
		scp_all->cpu_iowait += scp->cpu_iowait;

		scc_all->cpu_hardirq += scc->cpu_hardirq;
		scp_all->cpu_hardirq += scp->cpu_hardirq;

		scc_all->cpu_steal += scc->cpu_steal;
		scp_all->cpu_steal += scp->cpu_steal;

		scc_all->cpu_softirq += scc->cpu_softirq;
		scp_all->cpu_softirq += scp->cpu_softirq;

		scc_all->cpu_guest += scc->cpu_guest;
		scp_all->cpu_guest += scp->cpu_guest;

		scc_all->cpu_guest_nice += scc->cpu_guest_nice;
		scp_all->cpu_guest_nice += scp->cpu_guest_nice;
	}

	return deltot_jiffies;
}

Project: sysstat
File: sa_common.c

char *get_sa_devname(unsigned int major, unsigned int minor, unsigned int flags)
{
	char *dev_name = NULL, *persist_dev_name = NULL;

	if (DISPLAY_PERSIST_NAME_S(flags)) {
		persist_dev_name = get_persistent_name_from_pretty(get_devname(major, minor, TRUE));
	}

	if (persist_dev_name) {
		dev_name = persist_dev_name;
	}
	else {
		if ((USE_PRETTY_OPTION(flags)) && (major == dm_major)) {
			dev_name = transform_devmapname(major, minor);
		}

		if (!dev_name) {
			dev_name = get_devname(major, minor,
					       USE_PRETTY_OPTION(flags));
		}
	}

	return dev_name;
}

Project: sysstat
File: sa_common.c

void print_report_hdr(unsigned int flags, struct tm *rectime,
		      struct file_header *file_hdr)
{

	/* Get date of file creation */
	get_file_timestamp_struct(flags, rectime, file_hdr);

	/*
	 * Display the header.
	 * NB: Number of CPU (value in [1, NR_CPUS + 1]).
	 * 	1 means that there is only one proc and non SMP kernel.
	 *	2 means one proc and SMP kernel. Etc.
	 */
	print_gal_header(rectime, file_hdr->sa_sysname, file_hdr->sa_release,
			 file_hdr->sa_nodename, file_hdr->sa_machine,
			 file_hdr->sa_cpu_nr > 1 ? file_hdr->sa_cpu_nr - 1 : 1,
			 PLAIN_OUTPUT);
}

Project: sysstat
File: sar.c

void read_stats(void)
{
	int curr = 1;
	unsigned long lines;
	unsigned int rows;
	int dis_hdr = 0;

	/* Don't buffer data if redirected to a pipe... */
	setbuf(stdout, NULL);

	/* Read stats header */
	read_header_data();

	if (!get_activity_nr(act, AO_SELECTED, COUNT_ACTIVITIES)) {
		/* Requested activities not available: Exit */
		print_collect_error();
	}

	/* Determine if a stat line header has to be displayed */
	dis_hdr = check_line_hdr();

	lines = rows = get_win_height();

	/* Perform required allocations */
	allocate_structures(act);

	/* Print report header */
	print_report_hdr(flags, &rectime, &file_hdr);

	/* Read system statistics sent by the data collector */
	read_sadc_stat_bunch(0);

	if (!interval) {
		/* Display stats since boot time and exit */
		write_stats_startup(0);
	}

	/* Save the first stats collected. Will be used to compute the average */
	copy_structures(act, id_seq, record_hdr, 2, 0);

	/* Set a handler for SIGINT */
	memset(&int_act, 0, sizeof(int_act));
	int_act.sa_handler = int_handler;
	int_act.sa_flags = SA_RESTART;
	sigaction(SIGINT, &int_act, NULL);

	/* Main loop */
	do {

		/* Get stats */
		read_sadc_stat_bunch(curr);
		if (sigint_caught) {
			/*
			 * SIGINT signal caught (it is sent by sadc).
			 * => Display average stats.
			 */
			curr ^= 1; /* No data retrieved from last read */
			break;
		}

		/* Print results */
		if (!dis_hdr) {
			dis = lines / rows;
			if (dis) {
				lines %= rows;
			}
			lines++;
		}
		write_stats(curr, USE_SADC, &count, NO_TM_START, tm_end.use,
			    NO_RESET, ALL_ACTIVITIES, TRUE);

		if (record_hdr[curr].record_type == R_LAST_STATS) {
			/* File rotation is happening: Re-read header data sent by sadc */
			read_header_data();
			allocate_structures(act);
		}

		if (count > 0) {
			count--;
		}
		if (count) {
			curr ^= 1;
		}
	}
	while (count);

	/*
	 * Print statistics average.
	 * At least one line of stats must have been displayed for this.
	 * (There may be no lines at all if we press Ctrl/C immediately).
	 */
	dis = dis_hdr;
	if (avg_count) {
		write_stats_avg(curr, USE_SADC, ALL_ACTIVITIES);
	}
}

Project: sysstat
File: sa_common.c

int read_record_hdr(int ifd, void *buffer, struct record_header *record_hdr,
		    struct file_header *file_hdr, int arch_64, int endian_mismatch,
		    int oneof, size_t b_size)
{
	int rc;

	if ((rc = sa_fread(ifd, buffer, (size_t) file_hdr->rec_size, SOFT_SIZE, oneof)) != 0)
		/* End of sa data file */
		return rc;

	/* Remap record header structure to that expected by current version */
	remap_struct(rec_types_nr, file_hdr->rec_types_nr, buffer,
		     file_hdr->rec_size, RECORD_HEADER_SIZE, b_size);
	memcpy(record_hdr, buffer, RECORD_HEADER_SIZE);

	/* Normalize endianness */
	if (endian_mismatch) {
		swap_struct(rec_types_nr, record_hdr, arch_64);
	}

	return 0;
}

Project: sysstat
File: sadf.c

void check_format_options(void)
{
	if (!format) {
		/* Select output format if none has been selected */
		if (DISPLAY_HDR_ONLY(flags)) {
			format = F_HEADER_OUTPUT;
		}
		else {
			format = F_PPC_OUTPUT;
		}
	}

	/* Get format position in array */
	f_position = get_format_position(fmt, format);

	/* Check options consistency wrt output format */
	if (!ACCEPT_HEADER_ONLY(fmt[f_position]->options)) {
		/* Remove option -H */
		flags &= ~S_F_HDR_ONLY;
	}
	if (!ACCEPT_HORIZONTALLY(fmt[f_position]->options)) {
		/* Remove option -h */
		flags &= ~S_F_HORIZONTALLY;
	}
	if (!ACCEPT_LOCAL_TIME(fmt[f_position]->options)) {
		/* Remove options -T and -t */
		flags &= ~(S_F_LOCAL_TIME + S_F_TRUE_TIME);
	}
	if (!ACCEPT_SEC_EPOCH(fmt[f_position]->options)) {
		/* Remove option -U */
		flags &= ~S_F_SEC_EPOCH;
	}
	if (REJECT_TRUE_TIME(fmt[f_position]->options)) {
		/* Remove option -t */
		flags &= ~S_F_TRUE_TIME;
	}
}

Project: sysstat
File: sar.c

void print_usage_title(FILE *fp, char *progname)
{
	fprintf(fp, _("Usage: %s [ options ] [ <interval> [ <count> ] ]\n"),
		progname);
}

Project: sysstat
File: sadf.c

void logic3_display_loop(int ifd, struct file_activity *file_actlst,
			 struct tm *rectime, struct tm *loctime, char *file,
			 struct file_magic *file_magic)
{
	struct svg_hdr_parm parm;
	int i, p;
	int curr = 1, rtype, g_nr = 0, views_per_row = 1, nr_act_dispd;
	int eosaf = TRUE, reset = TRUE;
	long cnt = 1;
	int graph_nr = 0;

	/* Use a decimal point to make SVG code locale independent */
	setlocale(LC_NUMERIC, "C");

	/*
	 * Calculate the number of rows and the max number of views per row to display.
	 * Result may be 0. In this case, "No data" will be displayed instead of the graphs.
	 */
	graph_nr = get_svg_graph_nr(ifd, file, file_magic,
				    file_actlst, rectime, loctime, &views_per_row,
				    &nr_act_dispd);

	if (SET_CANVAS_HEIGHT(flags)) {
		/*
		 * Option "-O height=..." used: @graph_nr is NO LONGER a number
		 * of graphs but the SVG canvas height set on the command line.
		 */
		graph_nr = canvas_height;
	}


	parm.graph_nr = graph_nr;
	parm.views_per_row = PACK_VIEWS(flags) ? views_per_row : 1;
	parm.nr_act_dispd = nr_act_dispd;

	/* Print SVG header */
	if (*fmt[f_position]->f_header) {
		(*fmt[f_position]->f_header)(&parm, F_BEGIN + F_MAIN, file, file_magic,
					     &file_hdr, act, id_seq, file_actlst);
	}

	/*
	* If this record is a special (RESTART or COMMENT) one, ignore it and
	* (try to) get another one.
	*/
	do {
		if (read_next_sample(ifd, IGNORE_RESTART | IGNORE_COMMENT, 0,
				     file, &rtype, 0, file_magic, file_actlst,
				     rectime, loctime, UEOF_CONT))
		{
			/* End of sa data file: No views displayed */
			parm.graph_nr = 0;
			goto close_svg;
		}
	}
	while ((rtype == R_RESTART) || (rtype == R_COMMENT) ||
	       (tm_start.use && (datecmp(loctime, &tm_start) < 0)) ||
	       (tm_end.use && (datecmp(loctime, &tm_end) >= 0)));

	/* Save the first stats collected. Used for example in next_slice() function */
	copy_structures(act, id_seq, record_hdr, 2, 0);

	/* Save current file position */
	seek_file_position(ifd, DO_SAVE);

	/* For each requested activity, display graphs */
	for (i = 0; i < NR_ACT; i++) {

		if (!id_seq[i])
			continue;

		p = get_activity_position(act, id_seq[i], EXIT_IF_NOT_FOUND);
		if (!IS_SELECTED(act[p]->options) || !act[p]->g_nr)
			continue;

		if (!HAS_MULTIPLE_OUTPUTS(act[p]->options)) {
			display_curr_act_graphs(ifd, &curr, &cnt, &eosaf,
						p, &reset, file_actlst,
						rectime, loctime, file,
						file_magic, &g_nr, nr_act_dispd);
		}
		else {
			unsigned int optf, msk;

			optf = act[p]->opt_flags;

			for (msk = 1; msk < 0x100; msk <<= 1) {
				if ((act[p]->opt_flags & 0xff) & msk) {
					act[p]->opt_flags &= (0xffffff00 + msk);
					display_curr_act_graphs(ifd, &curr, &cnt, &eosaf,
								p, &reset, file_actlst,
								rectime, loctime, file,
								file_magic, &g_nr, nr_act_dispd);
					act[p]->opt_flags = optf;
				}
			}
		}
	}

	/* Real number of graphs that have been displayed */
	parm.graph_nr = g_nr;

close_svg:
	/* Print SVG trailer */
	if (*fmt[f_position]->f_header) {
		(*fmt[f_position]->f_header)(&parm, F_END, file, file_magic,
					     &file_hdr, act, id_seq, file_actlst);
	}
}

Project: sysstat
File: sar.c

void usage(char *progname)
{
	print_usage_title(stderr, progname);
	fprintf(stderr, _("Options are:\n"
			  "[ -A ] [ -B ] [ -b ] [ -C ] [ -D ] [ -d ] [ -F [ MOUNT ] ] [ -H ] [ -h ]\n"
			  "[ -p ] [ -q ] [ -r [ ALL ] ] [ -S ] [ -t ] [ -u [ ALL ] ] [ -V ]\n"
			  "[ -v ] [ -W ] [ -w ] [ -y ] [ -z ]\n"
			  "[ -I { <int_list> | SUM | ALL } ] [ -P { <cpu_list> | ALL } ]\n"
			  "[ -m { <keyword> [,...] | ALL } ] [ -n { <keyword> [,...] | ALL } ]\n"
			  "[ --dev=<dev_list> ] [ --fs=<fs_list> ] [ --iface=<iface_list> ]\n"
			  "[ --dec={ 0 | 1 | 2 } ] [ --help ] [ --human ] [ --sadc ]\n"
			  "[ -j { ID | LABEL | PATH | UUID | ... } ]\n"
			  "[ -f [ <filename> ] | -o [ <filename> ] | -[0-9]+ ]\n"
			  "[ -i <interval> ] [ -s [ <hh:mm[:ss]> ] ] [ -e [ <hh:mm[:ss]> ] ]\n"));
	exit(1);
}

Project: sysstat
File: sadf.c

char *sccsid(void) { return (SCCSID); }