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