/* * sa_conv.c: Convert an old format sa file to the up-to-date format. * (C) 1999-2017 by Sebastien GODARD (sysstat orange.fr) * *************************************************************************** * This program is free software; you can redistribute it and/or modify it * * under the terms of the GNU General Public License as published by the * * Free Software Foundation; either version 2 of the License, or (at your * * option) any later version. * * * * This program is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without the implied warranty of MERCHANTABILITY * * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * * for more details. * * * * You should have received a copy of the GNU General Public License along * * with this program; if not, write to the Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA * *************************************************************************** */ #include #include #include #include #include #include "version.h" #include "sadf.h" #include "sa.h" #include "sa_conv.h" #ifdef USE_NLS # include # include # define _(string) gettext(string) #else # define _(string) (string) #endif extern int endian_mismatch; /* *************************************************************************** * Read and upgrade file's magic data section. * * IN: * @dfile System activity data file name. * @stdfd File descriptor for STDOUT. * * OUT: * @fd File descriptor for sa datafile to convert. * @file_magic Pointer on file_magic structure. * @previous_format TRUE is sa datafile has an old format which is no * longer compatible with current one. * * RETURNS: * -1 on error, 0 otherwise. *************************************************************************** */ int upgrade_magic_section(char dfile[], int *fd, int stdfd, struct file_magic *file_magic, int *previous_format) { struct file_magic fm; /* Open and read sa magic structure */ sa_open_read_magic(fd, dfile, file_magic, TRUE, &endian_mismatch); if ((file_magic->format_magic != FORMAT_MAGIC) && (file_magic->format_magic != PREVIOUS_FORMAT_MAGIC)) { fprintf(stderr, _("Cannot convert the format of this file\n")); return -1; } fprintf(stderr, "file_magic: "); if (file_magic->format_magic == PREVIOUS_FORMAT_MAGIC) { /* * We have read too many bytes: file_magic structure * was smaller with previous sysstat versions. * Go back 4 (unsigned int header_size) + 64 (char pad[64]) bytes. */ if (lseek(*fd, -68, SEEK_CUR) < 0) { fprintf(stderr, "\nlseek: %s\n", strerror(errno)); return -1; } /* Set format magic number to that of current version */ *previous_format = TRUE; file_magic->format_magic = FORMAT_MAGIC; /* Fill new structure members */ file_magic->header_size = FILE_HEADER_SIZE; memset(file_magic->pad, 0, sizeof(unsigned char) * FILE_MAGIC_PADDING); } /* Indicate that file has been upgraded */ enum_version_nr(&fm); file_magic->upgraded = (fm.sysstat_patchlevel << 4) + fm.sysstat_sublevel + 1; /* Write file_magic structure */ if (write(stdfd, file_magic, FILE_MAGIC_SIZE) != FILE_MAGIC_SIZE) { fprintf(stderr, "\nwrite: %s\n", strerror(errno)); return -1; } fprintf(stderr, "OK\n"); return 0; } /* *************************************************************************** * Upgrade file_header structure (from 0x2171 format to current format). * * IN: * @buffer Pointer on file's header structure (as read from file). * * OUT: * @file_hdr Pointer on file_header structure (up-to-date format). *************************************************************************** */ void upgrade_file_header(void *buffer, struct file_header *file_hdr) { struct file_header_2171 *f_hdr = (struct file_header_2171 *) buffer; file_hdr->sa_ust_time = f_hdr->sa_ust_time; file_hdr->sa_act_nr = f_hdr->sa_act_nr; file_hdr->sa_day = f_hdr->sa_day; file_hdr->sa_month = f_hdr->sa_month; file_hdr->sa_year = f_hdr->sa_year; file_hdr->sa_sizeof_long = f_hdr->sa_sizeof_long; strncpy(file_hdr->sa_sysname, f_hdr->sa_sysname, UTSNAME_LEN); file_hdr->sa_sysname[UTSNAME_LEN - 1] = '\0'; strncpy(file_hdr->sa_nodename, f_hdr->sa_nodename, UTSNAME_LEN); file_hdr->sa_nodename[UTSNAME_LEN - 1] = '\0'; strncpy(file_hdr->sa_release, f_hdr->sa_release, UTSNAME_LEN); file_hdr->sa_release[UTSNAME_LEN - 1] = '\0'; strncpy(file_hdr->sa_machine, f_hdr->sa_machine, UTSNAME_LEN); file_hdr->sa_machine[UTSNAME_LEN - 1] = '\0'; /* The last two values below will be updated later */ file_hdr->sa_vol_act_nr = 0; file_hdr->sa_last_cpu_nr = 0; } /* *************************************************************************** * Upgrade stats_io structure (from ACTIVITY_MAGIC_BASE format to * ACTIVITY_MAGIC_BASE + 1 format). * * IN: * @act Array of activities. * @p Position of activity in array. *************************************************************************** */ void upgrade_stats_io(struct activity *act[], int p) { struct stats_io *sic = (struct stats_io *) act[p]->buf[1]; struct stats_io_8a *sip = (struct stats_io_8a *) act[p]->buf[0]; sic->dk_drive = (unsigned long long) sip->dk_drive; sic->dk_drive_rio = (unsigned long long) sip->dk_drive_rio; sic->dk_drive_wio = (unsigned long long) sip->dk_drive_wio; sic->dk_drive_rblk = (unsigned long long) sip->dk_drive_rblk; sic->dk_drive_wblk = (unsigned long long) sip->dk_drive_wblk; } /* *************************************************************************** * Upgrade stats_queue structure (from ACTIVITY_MAGIC_BASE format to * ACTIVITY_MAGIC_BASE + 1 format). * * IN: * @act Array of activities. * @p Position of activity in array. *************************************************************************** */ void upgrade_stats_queue(struct activity *act[], int p) { struct stats_queue *sqc = (struct stats_queue *) act[p]->buf[1]; struct stats_queue_8a *sqp = (struct stats_queue_8a *) act[p]->buf[0]; sqc->nr_running = sqp->nr_running; sqc->procs_blocked = 0; /* New field */ sqc->load_avg_1 = sqp->load_avg_1; sqc->load_avg_5 = sqp->load_avg_5; sqc->load_avg_15 = sqp->load_avg_15; sqc->nr_threads = sqp->nr_threads; } /* *************************************************************************** * Upgrade stats_disk structure (from ACTIVITY_MAGIC_BASE format to * ACTIVITY_MAGIC_BASE + 1 format). * * IN: * @act Array of activities. * @p Position of activity in array. *************************************************************************** */ void upgrade_stats_disk(struct activity *act[], int p) { int i; struct stats_disk *sdc; struct stats_disk_8a *sdp; for (i = 0; i < act[p]->nr; i++) { sdp = (struct stats_disk_8a *) ((char *) act[p]->buf[0] + i * act[p]->msize); sdc = (struct stats_disk *) ((char *) act[p]->buf[1] + i * act[p]->fsize); sdc->nr_ios = (unsigned long long) sdp->nr_ios; sdc->rd_sect = (unsigned long) sdp->rd_sect; sdc->wr_sect = (unsigned long) sdp->wr_sect; sdc->rd_ticks = (unsigned int) sdp->rd_ticks; sdc->wr_ticks = (unsigned int) sdp->wr_ticks; sdc->tot_ticks = (unsigned int) sdp->tot_ticks; sdc->rq_ticks = (unsigned int) sdp->rq_ticks; sdc->major = sdp->major; sdc->minor = sdp->minor; } } /* *************************************************************************** * Upgrade stats_net_dev structure (from ACTIVITY_MAGIC_BASE or * ACTIVITY_MAGIC_BASE + 1 format to ACTIVITY_MAGIC_BASE + 2 format). * * IN: * @act Array of activities. * @p Position of activity in array. * @m_format Structure format magic value. *************************************************************************** */ void upgrade_stats_net_dev(struct activity *act[], int p, unsigned int m_format) { int i; struct stats_net_dev *sndc; if (m_format == ACTIVITY_MAGIC_BASE) { struct stats_net_dev_8a *sndp_a; for (i = 0; i < act[p]->nr; i++) { sndp_a = (struct stats_net_dev_8a *) ((char *) act[p]->buf[0] + i * act[p]->msize); sndc = (struct stats_net_dev *) ((char *) act[p]->buf[1] + i * act[p]->fsize); sndc->rx_packets = (unsigned long long) sndp_a->rx_packets; sndc->tx_packets = (unsigned long long) sndp_a->tx_packets; sndc->rx_bytes = (unsigned long long) sndp_a->rx_bytes; sndc->tx_bytes = (unsigned long long) sndp_a->tx_bytes; sndc->rx_compressed = (unsigned long long) sndp_a->rx_compressed; sndc->tx_compressed = (unsigned long long) sndp_a->tx_compressed; sndc->multicast = (unsigned long long) sndp_a->multicast; sndc->speed = 0; /* New field */ strncpy(sndc->interface, sndp_a->interface, MAX_IFACE_LEN); sndc->interface[MAX_IFACE_LEN - 1] = '\0'; sndc->duplex = '\0'; /* New field */ } } else { struct stats_net_dev_8b *sndp_b; for (i = 0; i < act[p]->nr; i++) { sndp_b = (struct stats_net_dev_8b *) ((char *) act[p]->buf[0] + i * act[p]->msize); sndc = (struct stats_net_dev *) ((char *) act[p]->buf[1] + i * act[p]->fsize); sndc->rx_packets = sndp_b->rx_packets; sndc->tx_packets = sndp_b->tx_packets; sndc->rx_bytes = sndp_b->rx_bytes; sndc->tx_bytes = sndp_b->tx_bytes; sndc->rx_compressed = sndp_b->rx_compressed; sndc->tx_compressed = sndp_b->tx_compressed; sndc->multicast = sndp_b->multicast; sndc->speed = 0; /* New field */ strncpy(sndc->interface, sndp_b->interface, MAX_IFACE_LEN); sndc->interface[MAX_IFACE_LEN - 1] = '\0'; sndc->duplex = '\0'; /* New field */ } } } /* *************************************************************************** * Upgrade stats_net_edev structure (from ACTIVITY_MAGIC_BASE format to * ACTIVITY_MAGIC_BASE + 1 format). * * IN: * @act Array of activities. * @p Position of activity in array. *************************************************************************** */ void upgrade_stats_net_edev(struct activity *act[], int p) { int i; struct stats_net_edev *snedc; struct stats_net_edev_8a *snedp; for (i = 0; i < act[p]->nr; i++) { snedp = (struct stats_net_edev_8a *) ((char *) act[p]->buf[0] + i * act[p]->msize); snedc = (struct stats_net_edev *) ((char *) act[p]->buf[1] + i * act[p]->fsize); snedc->collisions = (unsigned long long) snedp->collisions; snedc->rx_errors = (unsigned long long) snedp->rx_errors; snedc->tx_errors = (unsigned long long) snedp->tx_errors; snedc->rx_dropped = (unsigned long long) snedp->rx_dropped; snedc->tx_dropped = (unsigned long long) snedp->tx_dropped; snedc->rx_fifo_errors = (unsigned long long) snedp->rx_fifo_errors; snedc->tx_fifo_errors = (unsigned long long) snedp->tx_fifo_errors; snedc->rx_frame_errors = (unsigned long long) snedp->rx_frame_errors; snedc->tx_carrier_errors = (unsigned long long) snedp->tx_carrier_errors; strncpy(snedc->interface, snedp->interface, MAX_IFACE_LEN); snedc->interface[MAX_IFACE_LEN - 1] = '\0'; } } /* *************************************************************************** * Upgrade stats_net_ip structure (from ACTIVITY_MAGIC_BASE format to * ACTIVITY_MAGIC_BASE + 1 format). * * IN: * @act Array of activities. * @p Position of activity in array. *************************************************************************** */ void upgrade_stats_net_ip(struct activity *act[], int p) { struct stats_net_ip *snic = (struct stats_net_ip *) act[p]->buf[1]; struct stats_net_ip_8a *snip = (struct stats_net_ip_8a *) act[p]->buf[0]; snic->InReceives = (unsigned long long) snip->InReceives; snic->ForwDatagrams = (unsigned long long) snip->ForwDatagrams; snic->InDelivers = (unsigned long long) snip->InDelivers; snic->OutRequests = (unsigned long long) snip->OutRequests; snic->ReasmReqds = (unsigned long long) snip->ReasmReqds; snic->ReasmOKs = (unsigned long long) snip->ReasmOKs; snic->FragOKs = (unsigned long long) snip->FragOKs; snic->FragCreates = (unsigned long long) snip->FragCreates; } /* *************************************************************************** * Upgrade stats_net_eip structure (from ACTIVITY_MAGIC_BASE format to * ACTIVITY_MAGIC_BASE + 1 format). * * IN: * @act Array of activities. * @p Position of activity in array. *************************************************************************** */ void upgrade_stats_net_eip(struct activity *act[], int p) { struct stats_net_eip *sneic = (struct stats_net_eip *) act[p]->buf[1]; struct stats_net_eip_8a *sneip = (struct stats_net_eip_8a *) act[p]->buf[0]; sneic->InHdrErrors = (unsigned long long) sneip->InHdrErrors; sneic->InAddrErrors = (unsigned long long) sneip->InAddrErrors; sneic->InUnknownProtos = (unsigned long long) sneip->InUnknownProtos; sneic->InDiscards = (unsigned long long) sneip->InDiscards; sneic->OutDiscards = (unsigned long long) sneip->OutDiscards; sneic->OutNoRoutes = (unsigned long long) sneip->OutNoRoutes; sneic->ReasmFails = (unsigned long long) sneip->ReasmFails; sneic->FragFails = (unsigned long long) sneip->FragFails; } /* *************************************************************************** * Upgrade stats_net_ip6 structure (from ACTIVITY_MAGIC_BASE format to * ACTIVITY_MAGIC_BASE + 1 format). * * IN: * @act Array of activities. * @p Position of activity in array. *************************************************************************** */ void upgrade_stats_net_ip6(struct activity *act[], int p) { struct stats_net_ip6 *snic6 = (struct stats_net_ip6 *) act[p]->buf[1]; struct stats_net_ip6_8a *snip6 = (struct stats_net_ip6_8a *) act[p]->buf[0]; snic6->InReceives6 = (unsigned long long) snip6->InReceives6; snic6->OutForwDatagrams6 = (unsigned long long) snip6->OutForwDatagrams6; snic6->InDelivers6 = (unsigned long long) snip6->InDelivers6; snic6->OutRequests6 = (unsigned long long) snip6->OutRequests6; snic6->ReasmReqds6 = (unsigned long long) snip6->ReasmReqds6; snic6->ReasmOKs6 = (unsigned long long) snip6->ReasmOKs6; snic6->InMcastPkts6 = (unsigned long long) snip6->InMcastPkts6; snic6->OutMcastPkts6 = (unsigned long long) snip6->OutMcastPkts6; snic6->FragOKs6 = (unsigned long long) snip6->FragOKs6; snic6->FragCreates6 = (unsigned long long) snip6->FragCreates6; } /* *************************************************************************** * Upgrade stats_net_eip6 structure (from ACTIVITY_MAGIC_BASE format to * ACTIVITY_MAGIC_BASE + 1 format). * * IN: * @act Array of activities. * @p Position of activity in array. *************************************************************************** */ void upgrade_stats_net_eip6(struct activity *act[], int p) { struct stats_net_eip6 *sneic6 = (struct stats_net_eip6 *) act[p]->buf[1]; struct stats_net_eip6_8a *sneip6 = (struct stats_net_eip6_8a *) act[p]->buf[0]; sneic6->InHdrErrors6 = (unsigned long long) sneip6->InHdrErrors6; sneic6->InAddrErrors6 = (unsigned long long) sneip6->InAddrErrors6; sneic6->InUnknownProtos6 = (unsigned long long) sneip6->InUnknownProtos6; sneic6->InTooBigErrors6 = (unsigned long long) sneip6->InTooBigErrors6; sneic6->InDiscards6 = (unsigned long long) sneip6->InDiscards6; sneic6->OutDiscards6 = (unsigned long long) sneip6->OutDiscards6; sneic6->InNoRoutes6 = (unsigned long long) sneip6->InNoRoutes6; sneic6->OutNoRoutes6 = (unsigned long long) sneip6->OutNoRoutes6; sneic6->ReasmFails6 = (unsigned long long) sneip6->ReasmFails6; sneic6->FragFails6 = (unsigned long long) sneip6->FragFails6; sneic6->InTruncatedPkts6 = (unsigned long long) sneip6->InTruncatedPkts6; } /* *************************************************************************** * Read and upgrade file's header section. * * IN: * @dfile System activity data file name. * @fd File descriptor for sa datafile to convert. * @stdfd File descriptor for STDOUT. * @act Array of activities. * @file_magic Pointer on file_magic structure. * @previous_format TRUE is sa datafile has an old format which is no * longer compatible with current one. * * OUT: * @file_hdr Pointer on file_header structure. * @file_actlst Activity list in file. * @vol_id_seq Sequence of volatile activities. * * RETURNS: * -1 on error, 0 otherwise. *************************************************************************** */ int upgrade_header_section(char dfile[], int fd, int stdfd, struct activity *act[], struct file_magic *file_magic, struct file_header *file_hdr, int previous_format, struct file_activity **file_actlst, unsigned int vol_id_seq[]) { int i, j, n, p; unsigned int a_cpu = FALSE; void *buffer = NULL; struct file_activity *fal; /* Read file header structure */ fprintf(stderr, "file_header: "); if (previous_format) { /* Previous format had 2 unsigned int less */ n = FILE_HEADER_SIZE - 8; } else { n = file_magic->header_size; } SREALLOC(buffer, char, n); sa_fread(fd, buffer, n, HARD_SIZE); if (previous_format) { /* Upgrade file_header structure */ upgrade_file_header(buffer, file_hdr); } else { memcpy(file_hdr, buffer, MINIMUM(n, FILE_HEADER_SIZE)); } free(buffer); /* Sanity check */ if (file_hdr->sa_act_nr > MAX_NR_ACT) goto invalid_header; /* Read file activity list */ SREALLOC(*file_actlst, struct file_activity, FILE_ACTIVITY_SIZE * file_hdr->sa_act_nr); fal = *file_actlst; j = 0; for (i = 0; i < file_hdr->sa_act_nr; i++, fal++) { sa_fread(fd, fal, FILE_ACTIVITY_SIZE, HARD_SIZE); if ((fal->nr < 1) || (fal->nr2 < 1)) /* * Every activity, known or unknown, * should have at least one item and sub-item. */ goto invalid_header; if ((p = get_activity_position(act, fal->id, RESUME_IF_NOT_FOUND)) >= 0) { /* This is a known activity, maybe with an unknown format */ if (IS_VOLATILE(act[p]->options) && previous_format) { /* * Current activity is known by current version * as a volatile one: So increment the number of * volatile activities in file's header (but only * for old format data files, since up-to-date * format data files already have the right value here). */ file_hdr->sa_vol_act_nr += 1; /* * Create the sequence of volatile activities. * Used only for old format datafiles. * For new format datafiles, this is not necessary * since this sequence already exists following * the RESTART record. */ vol_id_seq[j++] = act[p]->id; } if (fal->id == A_CPU) { /* * Old format data files don't know volatile * activities. The number of CPU is a constant * all along the file. */ if (previous_format) { file_hdr->sa_last_cpu_nr = fal->nr; } a_cpu = TRUE; } /* Size of an activity cannot be zero */ if (!fal->size) goto invalid_header; /* Size of activity in file is larger than up-to-date activity size */ if (fal->size > act[p]->msize) { act[p]->msize = fal->size; } /* * When upgrading a file: * fal->size : Size of an item for current activity, as * read from the file. * act[p]->msize: Size of the buffer in memory where an item * for current activity, as read from the file, * will be saved. We have: * act[p]->msize >= {fal->size ; act[p]->fsize} * act[p]->fsize: Size of an item for current activity with * up-to-date format. */ act[p]->nr = fal->nr; act[p]->nr2 = fal->nr2; /* * Don't set act[p]->fsize! Should retain the size of an item * for up-to-date format! */ } } if (!a_cpu) { /* * CPU activity should always be in file * and have a known format (expected magical number). */ fprintf(stderr, _("\nCPU activity not found in file. Aborting...\n")); return -1; } /* Write file_header structure */ if ((n = write(stdfd, file_hdr, FILE_HEADER_SIZE)) != FILE_HEADER_SIZE) { fprintf(stderr, "\nwrite: %s\n", strerror(errno)); return -1; } fprintf(stderr, "OK\n"); return 0; invalid_header: fprintf(stderr, _("\nInvalid data found. Aborting...\n")); return -1; } /* *************************************************************************** * Upgrade file's activity list section. * * IN: * @stdfd File descriptor for STDOUT. * @act Array of activities. * @file_hdr Pointer on file_header structure. * @file_actlst Activity list in file. * * RETURNS: * -1 on error, 0 otherwise. *************************************************************************** */ int upgrade_activity_section(int stdfd, struct activity *act[], struct file_header *file_hdr, struct file_activity *file_actlst) { int i, p; struct file_activity file_act; struct file_activity *fal; fprintf(stderr, "file_activity: "); fal = file_actlst; for (i = 0; i < file_hdr->sa_act_nr; i++, fal++) { file_act = *fal; if ((p = get_activity_position(act, fal->id, RESUME_IF_NOT_FOUND)) >= 0) { /* Update activity magic number */ file_act.magic = act[p]->magic; /* Also update its size, which may have changed with recent versions */ file_act.size = act[p]->fsize; } /* * Even unknown activities must be written * (they are counted in sa_act_nr). */ if (write(stdfd, &file_act, FILE_ACTIVITY_SIZE) != FILE_ACTIVITY_SIZE) { fprintf(stderr, "\nwrite: %s\n", strerror(errno)); return -1; } fprintf(stderr, "%s ", act[p]->name); } fprintf(stderr, "OK\n"); return 0; } /* *************************************************************************** * Upgrade a COMMENT record. * * IN: * @fd File descriptor for sa datafile to convert. * @stdfd File descriptor for STDOUT. * * RETURNS: * -1 on error, 0 otherwise. *************************************************************************** */ int upgrade_comment_record(int fd, int stdfd) { char file_comment[MAX_COMMENT_LEN]; /* Read the COMMENT record */ sa_fread(fd, file_comment, MAX_COMMENT_LEN, HARD_SIZE); file_comment[MAX_COMMENT_LEN - 1] = '\0'; /* Then write it. No changes at this time */ if (write(stdfd, file_comment, MAX_COMMENT_LEN) != MAX_COMMENT_LEN) { fprintf(stderr, "\nwrite: %s\n", strerror(errno)); return -1; } fprintf(stderr, "C"); return 0; } /* *************************************************************************** * Upgrade a RESTART record. * * IN: * @fd File descriptor for sa datafile to convert. * @stdfd File descriptor for STDOUT. * @act Array of activities. * @file_hdr Pointer on file_header structure. * @previous_format TRUE is sa datafile has an old format which is no * longer compatible with current one. * @vol_id_seq Sequence of volatile activities. * * RETURNS: * -1 on error, 0 otherwise. *************************************************************************** */ int upgrade_restart_record(int fd, int stdfd, struct activity *act[], struct file_header *file_hdr, int previous_format, unsigned int vol_id_seq[]) { int i, p; struct file_activity file_act; /* * This is a RESTART record. * Only new format data file have additional structures * to read here for volatile activities. */ for (i = 0; i < file_hdr->sa_vol_act_nr; i++) { if (!previous_format) { sa_fread(fd, &file_act, FILE_ACTIVITY_SIZE, HARD_SIZE); if (file_act.id) { reallocate_vol_act_structures(act, file_act.nr, file_act.id); } } else { memset(&file_act, 0, FILE_ACTIVITY_SIZE); /* Old format: Sequence of volatile activities is in vol_id_seq */ p = get_activity_position(act, vol_id_seq[i], EXIT_IF_NOT_FOUND); /* Set only the necessary fields */ file_act.id = act[p]->id; file_act.nr = act[p]->nr; } if (write(stdfd, &file_act, FILE_ACTIVITY_SIZE) != FILE_ACTIVITY_SIZE) { fprintf(stderr, "\nwrite: %s\n", strerror(errno)); return -1; } } fprintf(stderr, "R"); return 0; } /* *************************************************************************** * Upgrade a record which is not a COMMENT or a RESTART one. * * IN: * @fd File descriptor for sa datafile to convert. * @stdfd File descriptor for STDOUT. * @act Array of activities. * @file_hdr Pointer on file_header structure. * @file_actlst Activity list in file. * * RETURNS: * -1 on error, 0 otherwise. *************************************************************************** */ int upgrade_common_record(int fd, int stdfd, struct activity *act[], struct file_header *file_hdr, struct file_activity *file_actlst) { int i, j, k, p; struct file_activity *fal; void *buffer = NULL; size_t size; /* * This is not a special record, so read the extra fields, * even if the format of the activity is unknown. */ fal = file_actlst; for (i = 0; i < file_hdr->sa_act_nr; i++, fal++) { if ((p = get_activity_position(act, fal->id, RESUME_IF_NOT_FOUND)) < 0) { /* An unknown activity should still be read and written */ size = (size_t) fal->size * (size_t) fal->nr * (size_t) fal->nr2; if (!size) { /* Buffer may have been allocated from a previous iteration in the loop */ if (buffer) { free (buffer); } return -1; } SREALLOC(buffer, void, size); sa_fread(fd, buffer, fal->size * fal->nr * fal->nr2, HARD_SIZE); if (write(stdfd, (char *) buffer, size) != size) { fprintf(stderr, "\nwrite: %s\n", strerror(errno)); free(buffer); return -1; } continue; } if ((act[p]->nr > 0) && ((act[p]->nr > 1) || (act[p]->nr2 > 1)) && (act[p]->msize > fal->size)) { for (j = 0; j < act[p]->nr; j++) { for (k = 0; k < act[p]->nr2; k++) { sa_fread(fd, (char *) act[p]->buf[0] + (j * act[p]->nr2 + k) * act[p]->msize, fal->size, HARD_SIZE); } } } else if (act[p]->nr > 0) { sa_fread(fd, act[p]->buf[0], fal->size * act[p]->nr * act[p]->nr2, HARD_SIZE); } if (act[p]->magic != fal->magic) { /* Known activity but old format */ switch (fal->id) { case A_IO: upgrade_stats_io(act, p); break; case A_QUEUE: upgrade_stats_queue(act, p); break; case A_DISK: upgrade_stats_disk(act, p); break; case A_NET_DEV: upgrade_stats_net_dev(act, p, fal->magic); break; case A_NET_EDEV: upgrade_stats_net_edev(act, p); break; case A_NET_IP: upgrade_stats_net_ip(act, p); break; case A_NET_EIP: upgrade_stats_net_eip(act, p); break; case A_NET_IP6: upgrade_stats_net_ip6(act, p); break; case A_NET_EIP6: upgrade_stats_net_eip6(act, p); break; } } else { /* Known activity with current up-to-date format */ for (j = 0; j < act[p]->nr; j++) { for (k = 0; k < act[p]->nr2; k++) { memcpy((char *) act[p]->buf[1] + (j * act[p]->nr2 + k) * act[p]->msize, (char *) act[p]->buf[0] + (j * act[p]->nr2 + k) * act[p]->msize, fal->size); } } } for (j = 0; j < act[p]->nr; j++) { for (k = 0; k < act[p]->nr2; k++) { if (write(stdfd, (char *) act[p]->buf[1] + (j * act[p]->nr2 + k) * act[p]->msize, act[p]->fsize) != act[p]->fsize) { fprintf(stderr, "\nwrite: %s\n", strerror(errno)); free(buffer); return -1; } } } } fprintf(stderr, "."); if (buffer) { free(buffer); } return 0; } /* *************************************************************************** * Upgrade statistics records. * * IN: * @fd File descriptor for sa datafile to convert. * @stdfd File descriptor for STDOUT. * @act Array of activities. * @file_hdr Pointer on file_header structure. * @previous_format TRUE is sa datafile has an old format which is no * longer compatible with current one. * @file_actlst Activity list in file. * @vol_id_seq Sequence of volatile activities. * * RETURNS: * -1 on error, 0 otherwise. *************************************************************************** */ int upgrade_stat_records(int fd, int stdfd, struct activity *act[], struct file_header *file_hdr, int previous_format, struct file_activity *file_actlst, unsigned int vol_id_seq[]) { int rtype; int eosaf; struct record_header record_hdr; fprintf(stderr, _("Statistics: ")); do { eosaf = sa_fread(fd, &record_hdr, RECORD_HEADER_SIZE, SOFT_SIZE); rtype = record_hdr.record_type; if (!eosaf) { if (write(stdfd, &record_hdr, RECORD_HEADER_SIZE) != RECORD_HEADER_SIZE) { fprintf(stderr, "\nwrite: %s\n", strerror(errno)); return -1; } if (rtype == R_COMMENT) { /* Upgrade the COMMENT record */ if (upgrade_comment_record(fd, stdfd) < 0) return -1; } else if (rtype == R_RESTART) { /* Upgrade the RESTART record */ if (upgrade_restart_record(fd, stdfd, act, file_hdr, previous_format, vol_id_seq) < 0) return -1; } else { /* Upgrade current statistics record */ if (upgrade_common_record(fd, stdfd, act, file_hdr, file_actlst) < 0) return -1; } } } while (!eosaf); return 0; } /* *************************************************************************** * Close file descriptors and exit. * * IN: * @fd File descriptor for sa datafile to convert. * @stdfd File descriptor for STDOUT. * @exit_code Exit code. *************************************************************************** */ void upgrade_exit(int fd, int stdfd, int exit_code) { if (fd) { close(fd); } if (stdfd) { close(stdfd); } exit(exit_code); } /* *************************************************************************** * Convert a sysstat activity data file from a previous version to the * up-to-date format. Presently data files from sysstat version 9.1.6 and * later are converted to current sysstat version format. * * IN: * @dfile System activity data file name. * @act Array of activities. *************************************************************************** */ void convert_file(char dfile[], struct activity *act[]) { int fd = 0, stdfd = 0; int previous_format = FALSE; struct file_magic file_magic; struct file_header file_hdr; struct file_activity *file_actlst = NULL; unsigned int vol_id_seq[NR_ACT]; /* Open stdout */ if ((stdfd = dup(STDOUT_FILENO)) < 0) { perror("dup"); upgrade_exit(0, 0, 2); } /* Upgrade file's magic section */ if (upgrade_magic_section(dfile, &fd, stdfd, &file_magic, &previous_format) < 0) { upgrade_exit(fd, stdfd, 2); } /* Upgrade file's header section */ if (upgrade_header_section(dfile, fd, stdfd, act, &file_magic, &file_hdr, previous_format, &file_actlst, vol_id_seq) < 0) { upgrade_exit(fd, stdfd, 2); } /* Upgrade file's activity list section */ if (upgrade_activity_section(stdfd, act, &file_hdr, file_actlst) < 0) { upgrade_exit(fd, stdfd, 2); } /* Perform required allocations */ allocate_structures(act); /* Upgrade statistics records */ if (upgrade_stat_records(fd, stdfd, act, &file_hdr, previous_format, file_actlst, vol_id_seq) <0) { upgrade_exit(fd, stdfd, 2); } fprintf(stderr, _("\nFile successfully converted to sysstat format version %s\n"), VERSION); free(file_actlst); free_structures(act); close(fd); close(stdfd); }