]> granicus.if.org Git - sysstat/blob - sa_conv.c
SVG: Fix how bar graphs are displayed for fs statistics
[sysstat] / sa_conv.c
1 /*
2  * sa_conv.c: Convert an old format sa file to the up-to-date format.
3  * (C) 1999-2016 by Sebastien GODARD (sysstat <at> orange.fr)
4  *
5  ***************************************************************************
6  * This program is free software; you can redistribute it and/or modify it *
7  * under the terms of the GNU General Public License as published  by  the *
8  * Free Software Foundation; either version 2 of the License, or (at  your *
9  * option) any later version.                                              *
10  *                                                                         *
11  * This program is distributed in the hope that it  will  be  useful,  but *
12  * WITHOUT ANY WARRANTY; without the implied warranty  of  MERCHANTABILITY *
13  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
14  * for more details.                                                       *
15  *                                                                         *
16  * You should have received a copy of the GNU General Public License along *
17  * with this program; if not, write to the Free Software Foundation, Inc., *
18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA              *
19  ***************************************************************************
20  */
21
22 #include <stdio.h>
23 #include <string.h>
24 #include <stdlib.h>
25 #include <unistd.h>
26 #include <errno.h>
27
28 #include "version.h"
29 #include "sadf.h"
30 #include "sa.h"
31 #include "sa_conv.h"
32
33 #ifdef USE_NLS
34 # include <locale.h>
35 # include <libintl.h>
36 # define _(string) gettext(string)
37 #else
38 # define _(string) (string)
39 #endif
40
41 /*
42  ***************************************************************************
43  * Read and upgrade file's magic data section.
44  *
45  * IN:
46  * @dfile               System activity data file name.
47  * @stdfd               File descriptor for STDOUT.
48  *
49  * OUT:
50  * @fd                  File descriptor for sa datafile to convert.
51  * @file_magic          Pointer on file_magic structure.
52  * @previous_format     TRUE is sa datafile has an old format which is no
53  *                      longer compatible with current one.
54  *
55  * RETURNS:
56  * -1 on error, 0 otherwise.
57  ***************************************************************************
58  */
59 int upgrade_magic_section(char dfile[], int *fd, int stdfd,
60                           struct file_magic *file_magic, int *previous_format)
61 {
62         struct file_magic fm;
63
64         /* Open and read sa magic structure */
65         sa_open_read_magic(fd, dfile, file_magic, TRUE);
66
67         if ((file_magic->format_magic != FORMAT_MAGIC) &&
68             (file_magic->format_magic != PREVIOUS_FORMAT_MAGIC)) {
69                 fprintf(stderr, _("Cannot convert the format of this file\n"));
70                 return -1;
71         }
72
73         fprintf(stderr, "file_magic: ");
74         if (file_magic->format_magic == PREVIOUS_FORMAT_MAGIC) {
75                 /*
76                  * We have read too many bytes: file_magic structure
77                  * was smaller with previous sysstat versions.
78                  * Go back 4 (unsigned int header_size) + 64 (char pad[64]) bytes.
79                  */
80                 if (lseek(*fd, -68, SEEK_CUR) < 0) {
81                         fprintf(stderr, "\nlseek: %s\n", strerror(errno));
82                         return -1;
83                 }
84                 /* Set format magic number to that of current version */
85                 *previous_format = TRUE;
86                 file_magic->format_magic = FORMAT_MAGIC;
87
88                 /* Fill new structure members */
89                 file_magic->header_size = FILE_HEADER_SIZE;
90                 memset(file_magic->pad, 0, sizeof(unsigned char) * FILE_MAGIC_PADDING);
91         }
92
93         /* Indicate that file has been upgraded */
94         enum_version_nr(&fm);
95         file_magic->upgraded = (fm.sysstat_patchlevel << 4) +
96                                fm.sysstat_sublevel + 1;
97
98         /* Write file_magic structure */
99         if (write(stdfd, file_magic, FILE_MAGIC_SIZE) != FILE_MAGIC_SIZE) {
100                 fprintf(stderr, "\nwrite: %s\n", strerror(errno));
101                 return -1;
102         }
103         fprintf(stderr, "OK\n");
104
105         return 0;
106 }
107
108 /*
109  ***************************************************************************
110  * Upgrade file_header structure (from 0x2171 format to current format).
111  *
112  * IN:
113  * @buffer      Pointer on file's header structure (as read from file).
114  *
115  * OUT:
116  * @file_hdr    Pointer on file_header structure (up-to-date format).
117  ***************************************************************************
118  */
119 void upgrade_file_header(void *buffer, struct file_header *file_hdr)
120 {
121         struct file_header_2171 *f_hdr = (struct file_header_2171 *) buffer;
122
123         file_hdr->sa_ust_time = f_hdr->sa_ust_time;
124         file_hdr->sa_act_nr = f_hdr->sa_act_nr;
125         file_hdr->sa_day = f_hdr->sa_day;
126         file_hdr->sa_month = f_hdr->sa_month;
127         file_hdr->sa_year = f_hdr->sa_year;
128         file_hdr->sa_sizeof_long = f_hdr->sa_sizeof_long;
129         strncpy(file_hdr->sa_sysname, f_hdr->sa_sysname, UTSNAME_LEN);
130         file_hdr->sa_sysname[UTSNAME_LEN - 1] = '\0';
131         strncpy(file_hdr->sa_nodename, f_hdr->sa_nodename, UTSNAME_LEN);
132         file_hdr->sa_nodename[UTSNAME_LEN - 1] = '\0';
133         strncpy(file_hdr->sa_release, f_hdr->sa_release, UTSNAME_LEN);
134         file_hdr->sa_release[UTSNAME_LEN - 1] = '\0';
135         strncpy(file_hdr->sa_machine, f_hdr->sa_machine, UTSNAME_LEN);
136         file_hdr->sa_machine[UTSNAME_LEN - 1] = '\0';
137         /* The last two values below will be updated later */
138         file_hdr->sa_vol_act_nr = 0;
139         file_hdr->sa_last_cpu_nr = 0;
140 }
141
142 /*
143  ***************************************************************************
144  * Upgrade stats_io structure (from ACTIVITY_MAGIC_BASE format to
145  * ACTIVITY_MAGIC_BASE + 1 format).
146  *
147  * IN:
148  * @act         Array of activities.
149  * @p           Position of activity in array.
150  ***************************************************************************
151  */
152 void upgrade_stats_io(struct activity *act[], int p)
153 {
154         struct stats_io *sic = (struct stats_io *) act[p]->buf[1];
155         struct stats_io_8a *sip = (struct stats_io_8a *) act[p]->buf[0];
156
157         sic->dk_drive = (unsigned long long) sip->dk_drive;
158         sic->dk_drive_rio = (unsigned long long) sip->dk_drive_rio;
159         sic->dk_drive_wio = (unsigned long long) sip->dk_drive_wio;
160         sic->dk_drive_rblk = (unsigned long long) sip->dk_drive_rblk;
161         sic->dk_drive_wblk = (unsigned long long) sip->dk_drive_wblk;
162 }
163
164 /*
165  ***************************************************************************
166  * Upgrade stats_queue structure (from ACTIVITY_MAGIC_BASE format to
167  * ACTIVITY_MAGIC_BASE + 1 format).
168  *
169  * IN:
170  * @act         Array of activities.
171  * @p           Position of activity in array.
172  ***************************************************************************
173  */
174 void upgrade_stats_queue(struct activity *act[], int p)
175 {
176         struct stats_queue *sqc = (struct stats_queue *) act[p]->buf[1];
177         struct stats_queue_8a *sqp = (struct stats_queue_8a *) act[p]->buf[0];
178
179         sqc->nr_running = sqp->nr_running;
180         sqc->procs_blocked = 0; /* New field */
181         sqc->load_avg_1 = sqp->load_avg_1;
182         sqc->load_avg_5 = sqp->load_avg_5;
183         sqc->load_avg_15 = sqp->load_avg_15;
184         sqc->nr_threads = sqp->nr_threads;
185 }
186
187 /*
188  ***************************************************************************
189  * Upgrade stats_disk structure (from ACTIVITY_MAGIC_BASE format to
190  * ACTIVITY_MAGIC_BASE + 1 format).
191  *
192  * IN:
193  * @act         Array of activities.
194  * @p           Position of activity in array.
195  ***************************************************************************
196  */
197 void upgrade_stats_disk(struct activity *act[], int p)
198 {
199         int i;
200         struct stats_disk *sdc;
201         struct stats_disk_8a *sdp;
202
203         for (i = 0; i < act[p]->nr; i++) {
204                 sdp = (struct stats_disk_8a *) ((char *) act[p]->buf[0] + i * act[p]->msize);
205                 sdc = (struct stats_disk *)    ((char *) act[p]->buf[1] + i * act[p]->fsize);
206
207                 sdc->nr_ios = (unsigned long long) sdp->nr_ios;
208                 sdc->rd_sect = (unsigned long) sdp->rd_sect;
209                 sdc->wr_sect = (unsigned long) sdp->wr_sect;
210                 sdc->rd_ticks = (unsigned int) sdp->rd_ticks;
211                 sdc->wr_ticks = (unsigned int) sdp->wr_ticks;
212                 sdc->tot_ticks = (unsigned int) sdp->tot_ticks;
213                 sdc->rq_ticks = (unsigned int) sdp->rq_ticks;
214                 sdc->major = sdp->major;
215                 sdc->minor = sdp->minor;
216         }
217 }
218
219 /*
220  ***************************************************************************
221  * Upgrade stats_net_dev structure (from ACTIVITY_MAGIC_BASE or
222  * ACTIVITY_MAGIC_BASE + 1 format to ACTIVITY_MAGIC_BASE + 2 format).
223  *
224  * IN:
225  * @act         Array of activities.
226  * @p           Position of activity in array.
227  * @m_format    Structure format magic value.
228  ***************************************************************************
229  */
230 void upgrade_stats_net_dev(struct activity *act[], int p, unsigned int m_format)
231 {
232         int i;
233         struct stats_net_dev *sndc;
234
235         if (m_format == ACTIVITY_MAGIC_BASE) {
236                 struct stats_net_dev_8a *sndp_a;
237
238                 for (i = 0; i < act[p]->nr; i++) {
239                         sndp_a = (struct stats_net_dev_8a *) ((char *) act[p]->buf[0] + i * act[p]->msize);
240                         sndc = (struct stats_net_dev *) ((char *) act[p]->buf[1] + i * act[p]->fsize);
241
242                         sndc->rx_packets = (unsigned long long) sndp_a->rx_packets;
243                         sndc->tx_packets = (unsigned long long) sndp_a->tx_packets;
244                         sndc->rx_bytes = (unsigned long long) sndp_a->rx_bytes;
245                         sndc->tx_bytes = (unsigned long long) sndp_a->tx_bytes;
246                         sndc->rx_compressed = (unsigned long long) sndp_a->rx_compressed;
247                         sndc->tx_compressed = (unsigned long long) sndp_a->tx_compressed;
248                         sndc->multicast = (unsigned long long) sndp_a->multicast;
249                         sndc->speed = 0; /* New field */
250                         strncpy(sndc->interface, sndp_a->interface, MAX_IFACE_LEN);
251                         sndc->interface[MAX_IFACE_LEN - 1] = '\0';
252                         sndc->duplex = '\0'; /* New field */
253                 }
254         }
255         else {
256                 struct stats_net_dev_8b *sndp_b;
257
258                 for (i = 0; i < act[p]->nr; i++) {
259                         sndp_b = (struct stats_net_dev_8b *) ((char *) act[p]->buf[0] + i * act[p]->msize);
260                         sndc = (struct stats_net_dev *) ((char *) act[p]->buf[1] + i * act[p]->fsize);
261
262                         sndc->rx_packets = sndp_b->rx_packets;
263                         sndc->tx_packets = sndp_b->tx_packets;
264                         sndc->rx_bytes = sndp_b->rx_bytes;
265                         sndc->tx_bytes = sndp_b->tx_bytes;
266                         sndc->rx_compressed = sndp_b->rx_compressed;
267                         sndc->tx_compressed = sndp_b->tx_compressed;
268                         sndc->multicast = sndp_b->multicast;
269                         sndc->speed = 0; /* New field */
270                         strncpy(sndc->interface, sndp_b->interface, MAX_IFACE_LEN);
271                         sndc->interface[MAX_IFACE_LEN - 1] = '\0';
272                         sndc->duplex = '\0'; /* New field */
273                 }
274         }
275 }
276
277 /*
278  ***************************************************************************
279  * Upgrade stats_net_edev structure (from ACTIVITY_MAGIC_BASE format to
280  * ACTIVITY_MAGIC_BASE + 1 format).
281  *
282  * IN:
283  * @act         Array of activities.
284  * @p           Position of activity in array.
285  ***************************************************************************
286  */
287 void upgrade_stats_net_edev(struct activity *act[], int p)
288 {
289         int i;
290         struct stats_net_edev *snedc;
291         struct stats_net_edev_8a *snedp;
292
293         for (i = 0; i < act[p]->nr; i++) {
294                 snedp = (struct stats_net_edev_8a *) ((char *) act[p]->buf[0] + i * act[p]->msize);
295                 snedc = (struct stats_net_edev *) ((char *) act[p]->buf[1] + i * act[p]->fsize);
296
297                 snedc->collisions = (unsigned long long) snedp->collisions;
298                 snedc->rx_errors = (unsigned long long) snedp->rx_errors;
299                 snedc->tx_errors = (unsigned long long) snedp->tx_errors;
300                 snedc->rx_dropped = (unsigned long long) snedp->rx_dropped;
301                 snedc->tx_dropped = (unsigned long long) snedp->tx_dropped;
302                 snedc->rx_fifo_errors = (unsigned long long) snedp->rx_fifo_errors;
303                 snedc->tx_fifo_errors = (unsigned long long) snedp->tx_fifo_errors;
304                 snedc->rx_frame_errors = (unsigned long long) snedp->rx_frame_errors;
305                 snedc->tx_carrier_errors = (unsigned long long) snedp->tx_carrier_errors;
306                 strncpy(snedc->interface, snedp->interface, MAX_IFACE_LEN);
307                 snedc->interface[MAX_IFACE_LEN - 1] = '\0';
308         }
309 }
310
311 /*
312  ***************************************************************************
313  * Upgrade stats_net_ip structure (from ACTIVITY_MAGIC_BASE format to
314  * ACTIVITY_MAGIC_BASE + 1 format).
315  *
316  * IN:
317  * @act         Array of activities.
318  * @p           Position of activity in array.
319  ***************************************************************************
320  */
321 void upgrade_stats_net_ip(struct activity *act[], int p)
322 {
323         struct stats_net_ip *snic = (struct stats_net_ip *) act[p]->buf[1];
324         struct stats_net_ip_8a *snip = (struct stats_net_ip_8a *) act[p]->buf[0];
325
326         snic->InReceives = (unsigned long long) snip->InReceives;
327         snic->ForwDatagrams = (unsigned long long) snip->ForwDatagrams;
328         snic->InDelivers = (unsigned long long) snip->InDelivers;
329         snic->OutRequests = (unsigned long long) snip->OutRequests;
330         snic->ReasmReqds = (unsigned long long) snip->ReasmReqds;
331         snic->ReasmOKs = (unsigned long long) snip->ReasmOKs;
332         snic->FragOKs = (unsigned long long) snip->FragOKs;
333         snic->FragCreates = (unsigned long long) snip->FragCreates;
334 }
335
336 /*
337  ***************************************************************************
338  * Upgrade stats_net_eip structure (from ACTIVITY_MAGIC_BASE format to
339  * ACTIVITY_MAGIC_BASE + 1 format).
340  *
341  * IN:
342  * @act         Array of activities.
343  * @p           Position of activity in array.
344  ***************************************************************************
345  */
346 void upgrade_stats_net_eip(struct activity *act[], int p)
347 {
348         struct stats_net_eip *sneic = (struct stats_net_eip *) act[p]->buf[1];
349         struct stats_net_eip_8a *sneip = (struct stats_net_eip_8a *) act[p]->buf[0];
350
351         sneic->InHdrErrors = (unsigned long long) sneip->InHdrErrors;
352         sneic->InAddrErrors = (unsigned long long) sneip->InAddrErrors;
353         sneic->InUnknownProtos = (unsigned long long) sneip->InUnknownProtos;
354         sneic->InDiscards = (unsigned long long) sneip->InDiscards;
355         sneic->OutDiscards = (unsigned long long) sneip->OutDiscards;
356         sneic->OutNoRoutes = (unsigned long long) sneip->OutNoRoutes;
357         sneic->ReasmFails = (unsigned long long) sneip->ReasmFails;
358         sneic->FragFails = (unsigned long long) sneip->FragFails;
359 }
360
361 /*
362  ***************************************************************************
363  * Upgrade stats_net_ip6 structure (from ACTIVITY_MAGIC_BASE format to
364  * ACTIVITY_MAGIC_BASE + 1 format).
365  *
366  * IN:
367  * @act         Array of activities.
368  * @p           Position of activity in array.
369  ***************************************************************************
370  */
371 void upgrade_stats_net_ip6(struct activity *act[], int p)
372 {
373         struct stats_net_ip6 *snic6 = (struct stats_net_ip6 *) act[p]->buf[1];
374         struct stats_net_ip6_8a *snip6 = (struct stats_net_ip6_8a *) act[p]->buf[0];
375
376         snic6->InReceives6 = (unsigned long long) snip6->InReceives6;
377         snic6->OutForwDatagrams6 = (unsigned long long) snip6->OutForwDatagrams6;
378         snic6->InDelivers6 = (unsigned long long) snip6->InDelivers6;
379         snic6->OutRequests6 = (unsigned long long) snip6->OutRequests6;
380         snic6->ReasmReqds6 = (unsigned long long) snip6->ReasmReqds6;
381         snic6->ReasmOKs6 = (unsigned long long) snip6->ReasmOKs6;
382         snic6->InMcastPkts6 = (unsigned long long) snip6->InMcastPkts6;
383         snic6->OutMcastPkts6 = (unsigned long long) snip6->OutMcastPkts6;
384         snic6->FragOKs6 = (unsigned long long) snip6->FragOKs6;
385         snic6->FragCreates6 = (unsigned long long) snip6->FragCreates6;
386 }
387
388 /*
389  ***************************************************************************
390  * Upgrade stats_net_eip6 structure (from ACTIVITY_MAGIC_BASE format to
391  * ACTIVITY_MAGIC_BASE + 1 format).
392  *
393  * IN:
394  * @act         Array of activities.
395  * @p           Position of activity in array.
396  ***************************************************************************
397  */
398 void upgrade_stats_net_eip6(struct activity *act[], int p)
399 {
400         struct stats_net_eip6 *sneic6 = (struct stats_net_eip6 *) act[p]->buf[1];
401         struct stats_net_eip6_8a *sneip6 = (struct stats_net_eip6_8a *) act[p]->buf[0];
402
403         sneic6->InHdrErrors6 = (unsigned long long) sneip6->InHdrErrors6;
404         sneic6->InAddrErrors6 = (unsigned long long) sneip6->InAddrErrors6;
405         sneic6->InUnknownProtos6 = (unsigned long long) sneip6->InUnknownProtos6;
406         sneic6->InTooBigErrors6 = (unsigned long long) sneip6->InTooBigErrors6;
407         sneic6->InDiscards6 = (unsigned long long) sneip6->InDiscards6;
408         sneic6->OutDiscards6 = (unsigned long long) sneip6->OutDiscards6;
409         sneic6->InNoRoutes6 = (unsigned long long) sneip6->InNoRoutes6;
410         sneic6->OutNoRoutes6 = (unsigned long long) sneip6->OutNoRoutes6;
411         sneic6->ReasmFails6 = (unsigned long long) sneip6->ReasmFails6;
412         sneic6->FragFails6 = (unsigned long long) sneip6->FragFails6;
413         sneic6->InTruncatedPkts6 = (unsigned long long) sneip6->InTruncatedPkts6;
414 }
415
416 /*
417  ***************************************************************************
418  * Read and upgrade file's header section.
419  *
420  * IN:
421  * @dfile               System activity data file name.
422  * @fd                  File descriptor for sa datafile to convert.
423  * @stdfd               File descriptor for STDOUT.
424  * @act                 Array of activities.
425  * @file_magic          Pointer on file_magic structure.
426  * @previous_format     TRUE is sa datafile has an old format which is no
427  *                      longer compatible with current one.
428  *
429  * OUT:
430  * @file_hdr            Pointer on file_header structure.
431  * @file_actlst         Activity list in file.
432  * @vol_id_seq          Sequence of volatile activities.
433  *
434  * RETURNS:
435  * -1 on error, 0 otherwise.
436 ***************************************************************************
437  */
438 int upgrade_header_section(char dfile[], int fd, int stdfd,
439                            struct activity *act[], struct file_magic *file_magic,
440                            struct file_header *file_hdr, int previous_format,
441                            struct file_activity **file_actlst, unsigned int vol_id_seq[])
442 {
443         int i, j, n, p;
444         unsigned int a_cpu = FALSE;
445         void *buffer = NULL;
446         struct file_activity *fal;
447
448         /* Read file header structure */
449         fprintf(stderr, "file_header: ");
450
451         if (previous_format) {
452                 /* Previous format had 2 unsigned int less */
453                 n = FILE_HEADER_SIZE - 8;
454         }
455         else {
456                 n = file_magic->header_size;
457         }
458
459         SREALLOC(buffer, char, n);
460
461         sa_fread(fd, buffer, n, HARD_SIZE);
462
463         if (previous_format) {
464                 /* Upgrade file_header structure */
465                 upgrade_file_header(buffer, file_hdr);
466         }
467         else {
468                 memcpy(file_hdr, buffer, MINIMUM(n, FILE_HEADER_SIZE));
469         }
470
471         free(buffer);
472
473         /* Sanity check */
474         if (file_hdr->sa_act_nr > MAX_NR_ACT)
475                 goto invalid_header;
476
477         /* Read file activity list */
478         SREALLOC(*file_actlst, struct file_activity, FILE_ACTIVITY_SIZE * file_hdr->sa_act_nr);
479         fal = *file_actlst;
480
481         j = 0;
482         for (i = 0; i < file_hdr->sa_act_nr; i++, fal++) {
483
484                 sa_fread(fd, fal, FILE_ACTIVITY_SIZE, HARD_SIZE);
485
486                 if ((fal->nr < 1) || (fal->nr2 < 1))
487                         /*
488                          * Every activity, known or unknown,
489                          * should have at least one item and sub-item.
490                          */
491                         goto invalid_header;
492
493                 if ((p = get_activity_position(act, fal->id, RESUME_IF_NOT_FOUND)) >= 0) {
494                         /* This is a known activity, maybe with an unknown format */
495
496                         if (IS_VOLATILE(act[p]->options) && previous_format) {
497                                 /*
498                                  * Current activity is known by current version
499                                  * as a volatile one: So increment the number of
500                                  * volatile activities in file's header (but only
501                                  * for old format data files, since up-to-date
502                                  * format data files already have the right value here).
503                                  */
504                                 file_hdr->sa_vol_act_nr += 1;
505
506                                 /*
507                                  * Create the sequence of volatile activities.
508                                  * Used only for old format datafiles.
509                                  * For new format datafiles, this is not necessary
510                                  * since this sequence already exists following
511                                  * the RESTART record.
512                                  */
513                                 vol_id_seq[j++] = act[p]->id;
514                         }
515
516                         if (fal->id == A_CPU) {
517                                 /*
518                                  * Old format data files don't know volatile
519                                  * activities. The number of CPU is a constant
520                                  * all along the file.
521                                  */
522                                 if (previous_format) {
523                                         file_hdr->sa_last_cpu_nr = fal->nr;
524                                 }
525                                 a_cpu = TRUE;
526                         }
527
528                         /* Size of an activity cannot be zero */
529                         if (!fal->size)
530                                 goto invalid_header;
531
532                         /* Size of activity in file is larger than up-to-date activity size */
533                         if (fal->size > act[p]->msize) {
534                                 act[p]->msize = fal->size;
535                         }
536
537                         /*
538                          * When upgrading a file:
539                          * fal->size    : Size of an item for current activity, as
540                          *                read from the file.
541                          * act[p]->msize: Size of the buffer in memory where an item
542                          *                for current activity, as read from the file,
543                          *                will be saved. We have:
544                          *                act[p]->msize >= {fal->size ; act[p]->fsize}
545                          * act[p]->fsize: Size of an item for current activity with
546                          *                up-to-date format.
547                          */
548                         act[p]->nr    = fal->nr;
549                         act[p]->nr2   = fal->nr2;
550                         /*
551                          * Don't set act[p]->fsize! Should retain the size of an item
552                          * for up-to-date format!
553                          */
554                 }
555         }
556
557         if (!a_cpu) {
558                 /*
559                  * CPU activity should always be in file
560                  * and have a known format (expected magical number).
561                  */
562                 fprintf(stderr, _("\nCPU activity not found in file. Aborting...\n"));
563                 return -1;
564         }
565
566         /* Write file_header structure */
567         if ((n = write(stdfd, file_hdr, FILE_HEADER_SIZE)) != FILE_HEADER_SIZE) {
568                 fprintf(stderr, "\nwrite: %s\n", strerror(errno));
569                 return -1;
570         }
571
572         fprintf(stderr, "OK\n");
573
574         return 0;
575
576 invalid_header:
577
578         fprintf(stderr, _("\nInvalid data found. Aborting...\n"));
579
580         return -1;
581
582 }
583
584 /*
585  ***************************************************************************
586  * Upgrade file's activity list section.
587  *
588  * IN:
589  * @stdfd               File descriptor for STDOUT.
590  * @act                 Array of activities.
591  * @file_hdr            Pointer on file_header structure.
592  * @file_actlst         Activity list in file.
593  *
594  * RETURNS:
595  * -1 on error, 0 otherwise.
596 ***************************************************************************
597  */
598 int upgrade_activity_section(int stdfd, struct activity *act[],
599                              struct file_header *file_hdr,
600                              struct file_activity *file_actlst)
601 {
602         int i, p;
603         struct file_activity file_act;
604         struct file_activity *fal;
605
606         fprintf(stderr, "file_activity: ");
607
608         fal = file_actlst;
609
610         for (i = 0; i < file_hdr->sa_act_nr; i++, fal++) {
611
612                 file_act = *fal;
613                 if ((p = get_activity_position(act, fal->id, RESUME_IF_NOT_FOUND)) >= 0) {
614                         /* Update activity magic number */
615                         file_act.magic = act[p]->magic;
616                         /* Also update its size, which may have changed with recent versions */
617                         file_act.size = act[p]->fsize;
618                 }
619
620                 /*
621                  * Even unknown activities must be written
622                  * (they are counted in sa_act_nr).
623                  */
624                 if (write(stdfd, &file_act, FILE_ACTIVITY_SIZE) != FILE_ACTIVITY_SIZE) {
625                         fprintf(stderr, "\nwrite: %s\n", strerror(errno));
626                         return -1;
627                 }
628
629                 fprintf(stderr, "%s ", act[p]->name);
630         }
631
632         fprintf(stderr, "OK\n");
633
634         return 0;
635 }
636
637 /*
638  ***************************************************************************
639  * Upgrade a COMMENT record.
640  *
641  * IN:
642  * @fd          File descriptor for sa datafile to convert.
643  * @stdfd       File descriptor for STDOUT.
644  *
645  * RETURNS:
646  * -1 on error, 0 otherwise.
647 ***************************************************************************
648  */
649 int upgrade_comment_record(int fd, int stdfd)
650 {
651         char file_comment[MAX_COMMENT_LEN];
652
653         /* Read the COMMENT record */
654         sa_fread(fd, file_comment, MAX_COMMENT_LEN, HARD_SIZE);
655         file_comment[MAX_COMMENT_LEN - 1] = '\0';
656
657         /* Then write it. No changes at this time */
658         if (write(stdfd, file_comment, MAX_COMMENT_LEN) != MAX_COMMENT_LEN) {
659                 fprintf(stderr, "\nwrite: %s\n", strerror(errno));
660                 return -1;
661         }
662
663         fprintf(stderr, "C");
664
665         return 0;
666 }
667
668 /*
669  ***************************************************************************
670  * Upgrade a RESTART record.
671  *
672  * IN:
673  * @fd                  File descriptor for sa datafile to convert.
674  * @stdfd               File descriptor for STDOUT.
675  * @act                 Array of activities.
676  * @file_hdr            Pointer on file_header structure.
677  * @previous_format     TRUE is sa datafile has an old format which is no
678  *                      longer compatible with current one.
679  * @vol_id_seq          Sequence of volatile activities.
680  *
681  * RETURNS:
682  * -1 on error, 0 otherwise.
683 ***************************************************************************
684  */
685 int upgrade_restart_record(int fd, int stdfd, struct activity *act[],
686                            struct file_header *file_hdr, int previous_format,
687                            unsigned int vol_id_seq[])
688 {
689         int i, p;
690         struct file_activity file_act;
691
692         /*
693          * This is a RESTART record.
694          * Only new format data file have additional structures
695          * to read here for volatile activities.
696          */
697         for (i = 0; i < file_hdr->sa_vol_act_nr; i++) {
698
699                 if (!previous_format) {
700                         sa_fread(fd, &file_act, FILE_ACTIVITY_SIZE, HARD_SIZE);
701                         if (file_act.id) {
702                                 reallocate_vol_act_structures(act, file_act.nr, file_act.id);
703                         }
704                 }
705                 else {
706                         memset(&file_act, 0, FILE_ACTIVITY_SIZE);
707
708                         /* Old format: Sequence of volatile activities is in vol_id_seq */
709                         p = get_activity_position(act, vol_id_seq[i], EXIT_IF_NOT_FOUND);
710
711                         /* Set only the necessary fields */
712                         file_act.id = act[p]->id;
713                         file_act.nr = act[p]->nr;
714                 }
715
716                 if (write(stdfd, &file_act, FILE_ACTIVITY_SIZE) != FILE_ACTIVITY_SIZE) {
717                         fprintf(stderr, "\nwrite: %s\n", strerror(errno));
718                         return -1;
719                 }
720         }
721
722         fprintf(stderr, "R");
723
724         return 0;
725 }
726
727 /*
728  ***************************************************************************
729  * Upgrade a record which is not a COMMENT or a RESTART one.
730  *
731  * IN:
732  * @fd                  File descriptor for sa datafile to convert.
733  * @stdfd               File descriptor for STDOUT.
734  * @act                 Array of activities.
735  * @file_hdr            Pointer on file_header structure.
736  * @file_actlst         Activity list in file.
737  *
738  * RETURNS:
739  * -1 on error, 0 otherwise.
740 ***************************************************************************
741  */
742 int upgrade_common_record(int fd, int stdfd, struct activity *act[],
743                            struct file_header *file_hdr,
744                            struct file_activity *file_actlst)
745 {
746         int i, j, k, p;
747         struct file_activity *fal;
748         void *buffer = NULL;
749         size_t size;
750
751         /*
752          * This is not a special record, so read the extra fields,
753          * even if the format of the activity is unknown.
754          */
755         fal = file_actlst;
756         for (i = 0; i < file_hdr->sa_act_nr; i++, fal++) {
757
758                 if ((p = get_activity_position(act, fal->id, RESUME_IF_NOT_FOUND)) < 0) {
759                         /* An unknown activity should still be read and written */
760                         size = (size_t) fal->size * (size_t) fal->nr * (size_t) fal->nr2;
761                         if (!size) {
762                                 /* Buffer may have been allocated from a previous iteration in the loop */
763                                 if (buffer) {
764                                         free (buffer);
765                                 }
766                                 return -1;
767                         }
768                         SREALLOC(buffer, void, size);
769                         sa_fread(fd, buffer, fal->size * fal->nr * fal->nr2, HARD_SIZE);
770                         if (write(stdfd, (char *) buffer, size) != size) {
771                                 fprintf(stderr, "\nwrite: %s\n", strerror(errno));
772                                 free(buffer);
773                                 return -1;
774                         }
775                         continue;
776                 }
777
778                 if ((act[p]->nr > 0) &&
779                     ((act[p]->nr > 1) || (act[p]->nr2 > 1)) &&
780                     (act[p]->msize > fal->size)) {
781
782                         for (j = 0; j < act[p]->nr; j++) {
783                                 for (k = 0; k < act[p]->nr2; k++) {
784                                         sa_fread(fd,
785                                                  (char *) act[p]->buf[0] + (j * act[p]->nr2 + k) * act[p]->msize,
786                                                  fal->size, HARD_SIZE);
787                                 }
788                         }
789                 }
790
791                 else if (act[p]->nr > 0) {
792                         sa_fread(fd, act[p]->buf[0], fal->size * act[p]->nr * act[p]->nr2, HARD_SIZE);
793                 }
794
795                 if (act[p]->magic != fal->magic) {
796
797                         /* Known activity but old format */
798                         switch (fal->id) {
799
800                                 case A_IO:
801                                         upgrade_stats_io(act, p);
802                                         break;
803
804                                 case A_QUEUE:
805                                         upgrade_stats_queue(act, p);
806                                         break;
807
808                                 case A_DISK:
809                                         upgrade_stats_disk(act, p);
810                                         break;
811
812                                 case A_NET_DEV:
813                                         upgrade_stats_net_dev(act, p, fal->magic);
814                                         break;
815
816                                 case A_NET_EDEV:
817                                         upgrade_stats_net_edev(act, p);
818                                         break;
819
820                                 case A_NET_IP:
821                                         upgrade_stats_net_ip(act, p);
822                                         break;
823
824                                 case A_NET_EIP:
825                                         upgrade_stats_net_eip(act, p);
826                                         break;
827
828                                 case A_NET_IP6:
829                                         upgrade_stats_net_ip6(act, p);
830                                         break;
831
832                                 case A_NET_EIP6:
833                                         upgrade_stats_net_eip6(act, p);
834                                         break;
835                                 }
836                 }
837                 else {
838                         /* Known activity with current up-to-date format */
839                         for (j = 0; j < act[p]->nr; j++) {
840                                 for (k = 0; k < act[p]->nr2; k++) {
841                                         memcpy((char *) act[p]->buf[1] + (j * act[p]->nr2 + k) * act[p]->msize,
842                                                (char *) act[p]->buf[0] + (j * act[p]->nr2 + k) * act[p]->msize,
843                                                fal->size);
844                                 }
845                         }
846                 }
847
848                 for (j = 0; j < act[p]->nr; j++) {
849                         for (k = 0; k < act[p]->nr2; k++) {
850                                 if (write(stdfd,
851                                                (char *) act[p]->buf[1] + (j * act[p]->nr2 + k) * act[p]->msize,
852                                                act[p]->fsize) !=
853                                                act[p]->fsize) {
854                                         fprintf(stderr, "\nwrite: %s\n", strerror(errno));
855                                         free(buffer);
856                                         return -1;
857                                 }
858                         }
859                 }
860         }
861
862         fprintf(stderr, ".");
863
864         if (buffer) {
865                 free(buffer);
866         }
867
868         return 0;
869 }
870
871 /*
872  ***************************************************************************
873  * Upgrade statistics records.
874  *
875  * IN:
876  * @fd                  File descriptor for sa datafile to convert.
877  * @stdfd               File descriptor for STDOUT.
878  * @act                 Array of activities.
879  * @file_hdr            Pointer on file_header structure.
880  * @previous_format     TRUE is sa datafile has an old format which is no
881  *                      longer compatible with current one.
882  * @file_actlst         Activity list in file.
883  * @vol_id_seq          Sequence of volatile activities.
884  *
885  * RETURNS:
886  * -1 on error, 0 otherwise.
887 ***************************************************************************
888  */
889 int upgrade_stat_records(int fd, int stdfd, struct activity *act[],
890                          struct file_header *file_hdr, int previous_format,
891                          struct file_activity *file_actlst, unsigned int vol_id_seq[])
892 {
893         int rtype;
894         int eosaf;
895         struct record_header record_hdr;
896
897         fprintf(stderr, _("Statistics: "));
898
899         do {
900                 eosaf = sa_fread(fd, &record_hdr, RECORD_HEADER_SIZE, SOFT_SIZE);
901                 rtype = record_hdr.record_type;
902
903                 if (!eosaf) {
904
905                         if (write(stdfd, &record_hdr, RECORD_HEADER_SIZE)
906                                 != RECORD_HEADER_SIZE) {
907                                 fprintf(stderr, "\nwrite: %s\n", strerror(errno));
908                                 return -1;
909                         }
910
911                         if (rtype == R_COMMENT) {
912                                 /* Upgrade the COMMENT record */
913                                 if (upgrade_comment_record(fd, stdfd) < 0)
914                                         return -1;
915                         }
916
917                         else if (rtype == R_RESTART) {
918                                 /* Upgrade the RESTART record */
919                                 if (upgrade_restart_record(fd, stdfd, act, file_hdr,
920                                                            previous_format, vol_id_seq) < 0)
921                                         return -1;
922                         }
923
924                         else {
925                                 /* Upgrade current statistics record */
926                                 if (upgrade_common_record(fd, stdfd, act, file_hdr,
927                                                           file_actlst) < 0)
928                                         return -1;
929                         }
930                 }
931         }
932         while (!eosaf);
933
934         return 0;
935 }
936
937 /*
938  ***************************************************************************
939  * Close file descriptors and exit.
940  *
941  * IN:
942  * @fd          File descriptor for sa datafile to convert.
943  * @stdfd       File descriptor for STDOUT.
944  * @exit_code   Exit code.
945  ***************************************************************************
946  */
947 void upgrade_exit(int fd, int stdfd, int exit_code)
948 {
949         if (fd) {
950                 close(fd);
951         }
952         if (stdfd) {
953                 close(stdfd);
954         }
955
956         exit(exit_code);
957 }
958
959 /*
960  ***************************************************************************
961  * Convert a sysstat activity data file from a previous version to the
962  * up-to-date format. Presently data files from sysstat version 9.1.6 and
963  * later are converted to current sysstat version format.
964  *
965  * IN:
966  * @dfile       System activity data file name.
967  * @act         Array of activities.
968  ***************************************************************************
969  */
970 void convert_file(char dfile[], struct activity *act[])
971 {
972         int fd = 0, stdfd = 0;
973         int previous_format = FALSE;
974         struct file_magic file_magic;
975         struct file_header file_hdr;
976         struct file_activity *file_actlst = NULL;
977         unsigned int vol_id_seq[NR_ACT];
978
979         /* Open stdout */
980         if ((stdfd = dup(STDOUT_FILENO)) < 0) {
981                 perror("dup");
982                 upgrade_exit(0, 0, 2);
983         }
984
985         /* Upgrade file's magic section */
986         if (upgrade_magic_section(dfile, &fd, stdfd, &file_magic,
987                                   &previous_format) < 0) {
988                 upgrade_exit(fd, stdfd, 2);
989         }
990
991         /* Upgrade file's header section */
992         if (upgrade_header_section(dfile, fd, stdfd, act,
993                                    &file_magic, &file_hdr,
994                                    previous_format, &file_actlst,
995                                    vol_id_seq) < 0) {
996                 upgrade_exit(fd, stdfd, 2);
997         }
998
999         /* Upgrade file's activity list section */
1000         if (upgrade_activity_section(stdfd, act, &file_hdr,
1001                                      file_actlst) < 0) {
1002                 upgrade_exit(fd, stdfd, 2);
1003         }
1004
1005         /* Perform required allocations */
1006         allocate_structures(act);
1007
1008         /* Upgrade statistics records */
1009         if (upgrade_stat_records(fd, stdfd, act, &file_hdr,
1010                                  previous_format, file_actlst,
1011                                  vol_id_seq) <0) {
1012                 upgrade_exit(fd, stdfd, 2);
1013         }
1014
1015         fprintf(stderr,
1016                 _("\nFile successfully converted to sysstat format version %s\n"),
1017                 VERSION);
1018
1019         free(file_actlst);
1020         free_structures(act);
1021         close(fd);
1022         close(stdfd);
1023 }