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