]> granicus.if.org Git - sysstat/blob - sa_conv.c
sysstat 11.1.4
[sysstat] / sa_conv.c
1 /*
2  * sa_conv.c: Convert an old format sa file to the up-to-date format.
3  * (C) 1999-2015 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  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 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         /* Read file activity list */
474         SREALLOC(*file_actlst, struct file_activity, FILE_ACTIVITY_SIZE * file_hdr->sa_act_nr);
475         fal = *file_actlst;
476
477         j = 0;
478         for (i = 0; i < file_hdr->sa_act_nr; i++, fal++) {
479
480                 sa_fread(fd, fal, FILE_ACTIVITY_SIZE, HARD_SIZE);
481
482                 if ((fal->nr < 1) || (fal->nr2 < 1)) {
483                         /*
484                          * Every activity, known or unknown,
485                          * should have at least one item and sub-item.
486                          */
487                         fprintf(stderr, _("\nInvalid data found. Aborting...\n"));
488                         return -1;
489                 }
490
491                 if ((p = get_activity_position(act, fal->id, RESUME_IF_NOT_FOUND)) >= 0) {
492                         /* This is a known activity, maybe with an unknown format */
493
494                         if (IS_VOLATILE(act[p]->options) && previous_format) {
495                                 /*
496                                  * Current activity is known by current version
497                                  * as a volatile one: So increment the number of
498                                  * volatile activities in file's header (but only
499                                  * for old format data files, since up-to-date
500                                  * format data files already have the right value here).
501                                  */
502                                 file_hdr->sa_vol_act_nr += 1;
503
504                                 /*
505                                  * Create the sequence of volatile activities.
506                                  * Used only for old format datafiles.
507                                  * For new format datafiles, this is not necessary
508                                  * since this sequence already exists following
509                                  * the RESTART record.
510                                  */
511                                 vol_id_seq[j++] = act[p]->id;
512                         }
513
514                         if (fal->id == A_CPU) {
515                                 /*
516                                  * Old format data files don't know volatile
517                                  * activities. The number of CPU is a constant
518                                  * all along the file.
519                                  */
520                                 if (previous_format) {
521                                         file_hdr->sa_last_cpu_nr = fal->nr;
522                                 }
523                                 a_cpu = TRUE;
524                         }
525
526                         /* Size of activity in file is larger than up-to-date activity size */
527                         if (fal->size > act[p]->msize) {
528                                 act[p]->msize = fal->size;
529                         }
530
531                         /*
532                          * When upgrading a file:
533                          * fal->size    : Size of an item for current activity, as
534                          *                read from the file.
535                          * act[p]->msize: Size of the buffer in memory where an item
536                          *                for current activity, as read from the file,
537                          *                will be saved. We have:
538                          *                act[p]->msize >= {fal->size ; act[p]->fsize}
539                          * act[p]->fsize: Size of an item for current activity with
540                          *                up-to-date format.
541                          */
542                         act[p]->nr    = fal->nr;
543                         act[p]->nr2   = fal->nr2;
544                         /*
545                          * Don't set act[p]->fsize! Should retain the size of an item
546                          * for up-to-date format!
547                          */
548                 }
549         }
550
551         if (!a_cpu) {
552                 /*
553                  * CPU activity should always be in file
554                  * and have a known format (expected magical number).
555                  */
556                 fprintf(stderr, _("\nCPU activity not found in file. Aborting...\n"));
557                 return -1;
558         }
559
560         /* Write file_header structure */
561         if ((n = write(stdfd, file_hdr, FILE_HEADER_SIZE)) != FILE_HEADER_SIZE) {
562                 fprintf(stderr, "\nwrite: %s\n", strerror(errno));
563                 return -1;
564         }
565
566         fprintf(stderr, "OK\n");
567
568         return 0;
569 }
570
571 /*
572  ***************************************************************************
573  * Upgrade file's activity list section.
574  *
575  * IN:
576  * @stdfd               File descriptor for STDOUT.
577  * @act                 Array of activities.
578  * @file_hdr            Pointer on file_header structure.
579  * @file_actlst         Activity list in file.
580  *
581  * RETURNS:
582  * -1 on error, 0 otherwise.
583 ***************************************************************************
584  */
585 int upgrade_activity_section(int stdfd, struct activity *act[],
586                              struct file_header *file_hdr,
587                              struct file_activity *file_actlst)
588 {
589         int i, p;
590         struct file_activity file_act;
591         struct file_activity *fal;
592
593         fprintf(stderr, "file_activity: ");
594
595         fal = file_actlst;
596
597         for (i = 0; i < file_hdr->sa_act_nr; i++, fal++) {
598
599                 file_act = *fal;
600                 if ((p = get_activity_position(act, fal->id, RESUME_IF_NOT_FOUND)) >= 0) {
601                         /* Update activity magic number */
602                         file_act.magic = act[p]->magic;
603                         /* Also update its size, which may have changed with recent versions */
604                         file_act.size = act[p]->fsize;
605                 }
606
607                 /*
608                  * Even unknown activities must be written
609                  * (they are counted in sa_act_nr).
610                  */
611                 if (write(stdfd, &file_act, FILE_ACTIVITY_SIZE) != FILE_ACTIVITY_SIZE) {
612                         fprintf(stderr, "\nwrite: %s\n", strerror(errno));
613                         return -1;
614                 }
615
616                 fprintf(stderr, "%s ", act[p]->name);
617         }
618
619         fprintf(stderr, "OK\n");
620
621         return 0;
622 }
623
624 /*
625  ***************************************************************************
626  * Upgrade a COMMENT record.
627  *
628  * IN:
629  * @fd          File descriptor for sa datafile to convert.
630  * @stdfd       File descriptor for STDOUT.
631  *
632  * RETURNS:
633  * -1 on error, 0 otherwise.
634 ***************************************************************************
635  */
636 int upgrade_comment_record(int fd, int stdfd)
637 {
638         char file_comment[MAX_COMMENT_LEN];
639
640         /* Read the COMMENT record */
641         sa_fread(fd, file_comment, MAX_COMMENT_LEN, HARD_SIZE);
642         file_comment[MAX_COMMENT_LEN - 1] = '\0';
643
644         /* Then write it. No changes at this time */
645         if (write(stdfd, file_comment, MAX_COMMENT_LEN) != MAX_COMMENT_LEN) {
646                 fprintf(stderr, "\nwrite: %s\n", strerror(errno));
647                 return -1;
648         }
649
650         fprintf(stderr, "C");
651
652         return 0;
653 }
654
655 /*
656  ***************************************************************************
657  * Upgrade a RESTART record.
658  *
659  * IN:
660  * @fd                  File descriptor for sa datafile to convert.
661  * @stdfd               File descriptor for STDOUT.
662  * @act                 Array of activities.
663  * @file_hdr            Pointer on file_header structure.
664  * @previous_format     TRUE is sa datafile has an old format which is no
665  *                      longer compatible with current one.
666  * @vol_id_seq          Sequence of volatile activities.
667  *
668  * RETURNS:
669  * -1 on error, 0 otherwise.
670 ***************************************************************************
671  */
672 int upgrade_restart_record(int fd, int stdfd, struct activity *act[],
673                            struct file_header *file_hdr, int previous_format,
674                            unsigned int vol_id_seq[])
675 {
676         int i, p;
677         struct file_activity file_act;
678
679         /*
680          * This is a RESTART record.
681          * Only new format data file have additional structures
682          * to read here for volatile activities.
683          */
684         for (i = 0; i < file_hdr->sa_vol_act_nr; i++) {
685
686                 if (!previous_format) {
687                         sa_fread(fd, &file_act, FILE_ACTIVITY_SIZE, HARD_SIZE);
688                         if (file_act.id) {
689                                 reallocate_vol_act_structures(act, file_act.nr, file_act.id);
690                         }
691                 }
692                 else {
693                         memset(&file_act, 0, FILE_ACTIVITY_SIZE);
694
695                         /* Old format: Sequence of volatile activities is in vol_id_seq */
696                         p = get_activity_position(act, vol_id_seq[i], EXIT_IF_NOT_FOUND);
697
698                         /* Set only the necessary fields */
699                         file_act.id = act[p]->id;
700                         file_act.nr = act[p]->nr;
701                 }
702
703                 if (write(stdfd, &file_act, FILE_ACTIVITY_SIZE) != FILE_ACTIVITY_SIZE) {
704                         fprintf(stderr, "\nwrite: %s\n", strerror(errno));
705                         return -1;
706                 }
707         }
708
709         fprintf(stderr, "R");
710
711         return 0;
712 }
713
714 /*
715  ***************************************************************************
716  * Upgrade a record which is not a COMMENT or a RESTART one.
717  *
718  * IN:
719  * @fd                  File descriptor for sa datafile to convert.
720  * @stdfd               File descriptor for STDOUT.
721  * @act                 Array of activities.
722  * @file_hdr            Pointer on file_header structure.
723  * @file_actlst         Activity list in file.
724  *
725  * RETURNS:
726  * -1 on error, 0 otherwise.
727 ***************************************************************************
728  */
729 int upgrade_common_record(int fd, int stdfd, struct activity *act[],
730                            struct file_header *file_hdr,
731                            struct file_activity *file_actlst)
732 {
733         int i, j, k, p;
734         struct file_activity *fal;
735         void *buffer = NULL;
736         size_t size;
737
738         /*
739          * This is not a special record, so read the extra fields,
740          * even if the format of the activity is unknown.
741          */
742         fal = file_actlst;
743         for (i = 0; i < file_hdr->sa_act_nr; i++, fal++) {
744
745                 if ((p = get_activity_position(act, fal->id, RESUME_IF_NOT_FOUND)) < 0) {
746                         /* An unknown activity should still be read and written */
747                         size = (size_t) fal->size * (size_t) fal->nr * (size_t) fal->nr2;
748                         SREALLOC(buffer, void, size);
749                         sa_fread(fd, buffer, fal->size * fal->nr * fal->nr2, HARD_SIZE);
750                         if (write(stdfd, (char *) buffer, size) != size) {
751                                 fprintf(stderr, "\nwrite: %s\n", strerror(errno));
752                                 free(buffer);
753                                 return -1;
754                         }
755                         continue;
756                 }
757
758                 if ((act[p]->nr > 0) &&
759                     ((act[p]->nr > 1) || (act[p]->nr2 > 1)) &&
760                     (act[p]->msize > fal->size)) {
761
762                         for (j = 0; j < act[p]->nr; j++) {
763                                 for (k = 0; k < act[p]->nr2; k++) {
764                                         sa_fread(fd,
765                                                  (char *) act[p]->buf[0] + (j * act[p]->nr2 + k) * act[p]->msize,
766                                                  fal->size, HARD_SIZE);
767                                 }
768                         }
769                 }
770
771                 else if (act[p]->nr > 0) {
772                         sa_fread(fd, act[p]->buf[0], fal->size * act[p]->nr * act[p]->nr2, HARD_SIZE);
773                 }
774
775                 if (act[p]->magic != fal->magic) {
776
777                         /* Known activity but old format */
778                         switch (fal->id) {
779
780                                 case A_IO:
781                                         upgrade_stats_io(act, p);
782                                         break;
783
784                                 case A_QUEUE:
785                                         upgrade_stats_queue(act, p);
786                                         break;
787
788                                 case A_DISK:
789                                         upgrade_stats_disk(act, p);
790                                         break;
791
792                                 case A_NET_DEV:
793                                         upgrade_stats_net_dev(act, p, fal->magic);
794                                         break;
795
796                                 case A_NET_EDEV:
797                                         upgrade_stats_net_edev(act, p);
798                                         break;
799
800                                 case A_NET_IP:
801                                         upgrade_stats_net_ip(act, p);
802                                         break;
803
804                                 case A_NET_EIP:
805                                         upgrade_stats_net_eip(act, p);
806                                         break;
807
808                                 case A_NET_IP6:
809                                         upgrade_stats_net_ip6(act, p);
810                                         break;
811
812                                 case A_NET_EIP6:
813                                         upgrade_stats_net_eip6(act, p);
814                                         break;
815                                 }
816                 }
817                 else {
818                         /* Known activity with current up-to-date format */
819                         for (j = 0; j < act[p]->nr; j++) {
820                                 for (k = 0; k < act[p]->nr2; k++) {
821                                         memcpy((char *) act[p]->buf[1] + (j * act[p]->nr2 + k) * act[p]->msize,
822                                                (char *) act[p]->buf[0] + (j * act[p]->nr2 + k) * act[p]->msize,
823                                                fal->size);
824                                 }
825                         }
826                 }
827
828                 for (j = 0; j < act[p]->nr; j++) {
829                         for (k = 0; k < act[p]->nr2; k++) {
830                                 if (write(stdfd,
831                                                (char *) act[p]->buf[1] + (j * act[p]->nr2 + k) * act[p]->msize,
832                                                act[p]->fsize) !=
833                                                act[p]->fsize) {
834                                         fprintf(stderr, "\nwrite: %s\n", strerror(errno));
835                                         free(buffer);
836                                         return -1;
837                                 }
838                         }
839                 }
840         }
841
842         fprintf(stderr, ".");
843
844         if (buffer) {
845                 free(buffer);
846         }
847
848         return 0;
849 }
850
851 /*
852  ***************************************************************************
853  * Upgrade statistics records.
854  *
855  * IN:
856  * @fd                  File descriptor for sa datafile to convert.
857  * @stdfd               File descriptor for STDOUT.
858  * @act                 Array of activities.
859  * @file_hdr            Pointer on file_header structure.
860  * @previous_format     TRUE is sa datafile has an old format which is no
861  *                      longer compatible with current one.
862  * @file_actlst         Activity list in file.
863  * @vol_id_seq          Sequence of volatile activities.
864  *
865  * RETURNS:
866  * -1 on error, 0 otherwise.
867 ***************************************************************************
868  */
869 int upgrade_stat_records(int fd, int stdfd, struct activity *act[],
870                          struct file_header *file_hdr, int previous_format,
871                          struct file_activity *file_actlst, unsigned int vol_id_seq[])
872 {
873         int rtype;
874         int eosaf;
875         struct record_header record_hdr;
876
877         fprintf(stderr, _("Statistics: "));
878
879         do {
880                 eosaf = sa_fread(fd, &record_hdr, RECORD_HEADER_SIZE, SOFT_SIZE);
881                 rtype = record_hdr.record_type;
882
883                 if (!eosaf) {
884
885                         if (write(stdfd, &record_hdr, RECORD_HEADER_SIZE)
886                                 != RECORD_HEADER_SIZE) {
887                                 fprintf(stderr, "\nwrite: %s\n", strerror(errno));
888                                 return -1;
889                         }
890
891                         if (rtype == R_COMMENT) {
892                                 /* Upgrade the COMMENT record */
893                                 if (upgrade_comment_record(fd, stdfd) < 0)
894                                         return -1;
895                         }
896
897                         else if (rtype == R_RESTART) {
898                                 /* Upgrade the RESTART record */
899                                 if (upgrade_restart_record(fd, stdfd, act, file_hdr,
900                                                            previous_format, vol_id_seq) < 0)
901                                         return -1;
902                         }
903
904                         else {
905                                 /* Upgrade current statistics record */
906                                 if (upgrade_common_record(fd, stdfd, act, file_hdr,
907                                                           file_actlst) < 0)
908                                         return -1;
909                         }
910                 }
911         }
912         while (!eosaf);
913
914         return 0;
915 }
916
917 /*
918  ***************************************************************************
919  * Close file descriptors and exit.
920  *
921  * IN:
922  * @fd          File descriptor for sa datafile to convert.
923  * @stdfd       File descriptor for STDOUT.
924  * @exit_code   Exit code.
925  ***************************************************************************
926  */
927 void upgrade_exit(int fd, int stdfd, int exit_code)
928 {
929         if (fd) {
930                 close(fd);
931         }
932         if (stdfd) {
933                 close(stdfd);
934         }
935
936         exit(exit_code);
937 }
938
939 /*
940  ***************************************************************************
941  * Convert a sysstat activity data file from a previous version to the
942  * up-to-date format. Presently data files from sysstat version 9.1.6 and
943  * later are converted to current sysstat version format.
944  *
945  * IN:
946  * @dfile       System activity data file name.
947  * @act         Array of activities.
948  ***************************************************************************
949  */
950 void convert_file(char dfile[], struct activity *act[])
951 {
952         int fd = 0, stdfd = 0;
953         int previous_format = FALSE;
954         struct file_magic file_magic;
955         struct file_header file_hdr;
956         struct file_activity *file_actlst = NULL;
957         unsigned int vol_id_seq[NR_ACT];
958
959         /* Open stdout */
960         if ((stdfd = dup(STDOUT_FILENO)) < 0) {
961                 perror("dup");
962                 upgrade_exit(0, 0, 2);
963         }
964
965         /* Upgrade file's magic section */
966         if (upgrade_magic_section(dfile, &fd, stdfd, &file_magic,
967                                   &previous_format) < 0) {
968                 upgrade_exit(fd, stdfd, 2);
969         }
970
971         /* Upgrade file's header section */
972         if (upgrade_header_section(dfile, fd, stdfd, act,
973                                    &file_magic, &file_hdr,
974                                    previous_format, &file_actlst,
975                                    vol_id_seq) < 0) {
976                 upgrade_exit(fd, stdfd, 2);
977         }
978
979         /* Upgrade file's activity list section */
980         if (upgrade_activity_section(stdfd, act, &file_hdr,
981                                      file_actlst) < 0) {
982                 upgrade_exit(fd, stdfd, 2);
983         }
984
985         /* Perform required allocations */
986         allocate_structures(act);
987
988         /* Upgrade statistics records */
989         if (upgrade_stat_records(fd, stdfd, act, &file_hdr,
990                                  previous_format, file_actlst,
991                                  vol_id_seq) <0) {
992                 upgrade_exit(fd, stdfd, 2);
993         }
994
995         fprintf(stderr,
996                 _("\nFile successfully converted to sysstat format version %s\n"),
997                 VERSION);
998
999         free(file_actlst);
1000         free_structures(act);
1001         close(fd);
1002         close(stdfd);
1003 }