"Fossies" - the Fresh Open Source Software Archive

Member "atop-2.8.1/atopconvert.c" (7 Jan 2023, 40068 Bytes) of package /linux/misc/atop-2.8.1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "atopconvert.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.8.0_vs_2.8.1.

    1 /*
    2 ** ATOP - System & Process Monitor
    3 **
    4 ** The program 'atop' offers the possibility to view the activity of 
    5 ** the system on system-level as well as process-level.
    6 **
    7 ** This program converts a raw logfile created by a particular version
    8 ** of atop to (by default) the current version of atop.
    9 ** ==========================================================================
   10 ** Author:      Gerlof Langeveld
   11 ** E-mail:      gerlof.langeveld@atoptool.nl
   12 ** Initial:     July/August 2018
   13 ** --------------------------------------------------------------------------
   14 ** Copyright (C) 2018-2022 Gerlof Langeveld
   15 **
   16 ** This program is free software; you can redistribute it and/or modify it
   17 ** under the terms of the GNU General Public License as published by the
   18 ** Free Software Foundation; either version 2, or (at your option) any
   19 ** later version.
   20 **
   21 ** This program is distributed in the hope that it will be useful, but
   22 ** WITHOUT ANY WARRANTY; without even the implied warranty of
   23 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
   24 ** See the GNU General Public License for more details.
   25 **
   26 ** You should have received a copy of the GNU General Public License
   27 ** along with this program; if not, write to the Free Software
   28 ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   29 ** --------------------------------------------------------------------------
   30 */
   31 #include <sys/types.h>
   32 #include <sys/param.h>
   33 #include <sys/mman.h>
   34 #include <sys/stat.h>
   35 #include <time.h>
   36 #include <stdio.h>
   37 #include <errno.h>
   38 #include <fcntl.h>
   39 #include <stdlib.h>
   40 #include <signal.h>
   41 #include <ctype.h>
   42 #include <sys/utsname.h>
   43 #include <string.h>
   44 #include <regex.h>
   45 #include <zlib.h>
   46 #include <sys/time.h>
   47 #include <sys/resource.h>
   48 #include <unistd.h>
   49 #include <stdarg.h>
   50 
   51 #include "atop.h"
   52 #include "photosyst.h"
   53 #include "photoproc.h"
   54 #include "rawlog.h"
   55 
   56 #include "prev/netstats_wrong.h"
   57 
   58 #include "prev/photosyst_20.h"
   59 #include "prev/photoproc_20.h"
   60 
   61 #include "prev/photosyst_21.h"
   62 #include "prev/photoproc_21.h"
   63 
   64 #include "prev/photosyst_22.h"
   65 #include "prev/photoproc_22.h"
   66 
   67 #include "prev/photosyst_23.h"
   68 #include "prev/photoproc_23.h"
   69 
   70 #include "prev/photosyst_24.h"
   71 #include "prev/photoproc_24.h"
   72 
   73 #include "prev/photosyst_25.h"
   74 #include "prev/photoproc_25.h"
   75 
   76 #include "prev/photosyst_26.h"
   77 #include "prev/photoproc_26.h"
   78 
   79 #include "prev/photosyst_27.h"
   80 #include "prev/photoproc_27.h"
   81 
   82 #include "prev/photosyst_28.h"
   83 #include "prev/photoproc_28.h"
   84 
   85 
   86 ///////////////////////////////////////////////////////////////
   87 // Conversion functions
   88 // --------------------
   89 // The structures with system level and process level info
   90 // consists of sub-structures, generally for cpu, memory,
   91 // disk and network values. These sub-structures might have
   92 // changed from a specific version of atop to the next version.
   93 // For modified sub-structures, conversion functions have to be
   94 // written. These conversion functions will be called in a chained
   95 // way for one version increment at the time. Suppose that a
   96 // raw log is offered that has been created by atop 2.0 to be
   97 // converted to atop 2.3, every sub-structure will be converted
   98 // from 2.0 to 2.1, from 2.1 to 2.2 and finally from 2.2 to 2.3.
   99 // When a sub-structure has NOT been changed from one version to
  100 // another, it will just be copied by the generic conversion
  101 // function 'justcopy' to the proper location in the structure
  102 // of the next version.
  103 // All conversion steps are controlled by the convs[] table.
  104 ///////////////////////////////////////////////////////////////
  105 
  106 // Generic function that just copies an old structure byte-wise to
  107 // a new structure (new structure implicitly padded with binary zeroes)
  108 //
  109 void
  110 justcopy(void *old, void *new, count_t oldsize, count_t newsize)
  111 {
  112     if (oldsize)
  113         memcpy(new, old, newsize > oldsize ? oldsize : newsize);
  114 }
  115 
  116 // /////////////////////////////////////////////////////////////////
  117 // Specific functions that convert an old sstat sub-structure to
  118 // a new sub-structure (system level)
  119 // /////////////////////////////////////////////////////////////////
  120 void
  121 scpu_to_21(void *old, void *new, count_t oldsize, count_t newsize)
  122 {
  123     // cfuture[1] --> cfuture[4] in struct percpu
  124     //
  125     struct cpustat_20   *c20 = old;
  126     struct cpustat_21   *c21 = new;
  127     int         i;
  128 
  129     memcpy(c21, c20, (char *)&c20->all - (char *)c20);  // base values
  130     memcpy(&c21->all, &c20->all, sizeof(struct percpu_20));
  131 
  132     for (i=0; i < MAXCPU_20; i++)
  133         memcpy( &(c21->cpu[i]), &(c20->cpu[i]), sizeof(struct percpu_20));
  134 }
  135 
  136 void
  137 sdsk_to_21(void *old, void *new, count_t oldsize, count_t newsize)
  138 {
  139     // MAXDSK and MAXLVM have been enlarged
  140     //
  141     struct dskstat_20   *d20 = old;
  142     struct dskstat_21   *d21 = new;
  143 
  144     d21->ndsk   = d20->ndsk;
  145     d21->nmdd   = d20->nmdd;
  146     d21->nlvm   = d20->nlvm;
  147 
  148     memcpy(d21->dsk, d20->dsk, sizeof d20->dsk);
  149     memcpy(d21->mdd, d20->mdd, sizeof d20->mdd);
  150     memcpy(d21->lvm, d20->lvm, sizeof d20->lvm);
  151 }
  152 
  153 void
  154 sint_to_22(void *old, void *new, count_t oldsize, count_t newsize)
  155 {
  156     // members 'type' and 'speedp' added to struct perintf
  157     //
  158     struct intfstat_21  *i21 = old;
  159     struct intfstat_22  *i22 = new;
  160     int         i;
  161 
  162     i22->nrintf     = i21->nrintf;
  163 
  164     for (i=0; i < MAXINTF_21; i++)
  165     {
  166         memcpy(&(i22->intf[i]), &(i21->intf[i]),
  167                     sizeof(struct perintf_21));
  168 
  169         // correct last members by refilling
  170         // 
  171         i22->intf[i].type   = '?';
  172         i22->intf[i].speed  = i21->intf[i].speed;
  173         i22->intf[i].speedp = i21->intf[i].speed;
  174         i22->intf[i].duplex = i21->intf[i].duplex;
  175 
  176         memset(i22->intf[i].cfuture, 0, sizeof i22->intf[i].cfuture);
  177     }
  178 }
  179 
  180 void
  181 scpu_to_27(void *old, void *new, count_t oldsize, count_t newsize)
  182 {
  183     // cfuture[2] --> cfuture[4] in struct percpu
  184     //
  185     struct cpustat_26   *c26 = old;
  186     struct cpustat_27   *c27 = new;
  187     int         i;
  188 
  189     memcpy(c27, c26, (char *)&c26->all - (char *)c26);  // base values
  190     memcpy(&c27->all, &c26->all, sizeof(struct percpu_26));
  191 
  192     for (i=0; i < MAXCPU_26; i++)
  193         memcpy( &(c27->cpu[i]), &(c26->cpu[i]), sizeof(struct percpu_26));
  194 }
  195 
  196 void
  197 smem_to_27(void *old, void *new, count_t oldsize, count_t newsize)
  198 {
  199     struct memstat_26   *m26 = old;
  200     struct memstat_27   *m27 = new;
  201 
  202     memcpy(m27, m26, sizeof *m26);
  203 
  204     m27->oomkills = -1; // explicitly define 'unused'
  205 }
  206 
  207 void
  208 sdsk_to_27(void *old, void *new, count_t oldsize, count_t newsize)
  209 {
  210     struct dskstat_26   *d26 = old;
  211     struct dskstat_27   *d27 = new;
  212     int         i;
  213 
  214     memcpy(d27, d26, oldsize);
  215 
  216     for (i=0; i < d27->ndsk; i++)
  217         d27->dsk[i].ndisc = -1; // explicitly define 'unused'
  218 
  219     for (i=0; i < d27->nmdd; i++)
  220         d27->mdd[i].ndisc = -1; // explicitly define 'unused'
  221 
  222     for (i=0; i < d27->nlvm; i++)
  223         d27->lvm[i].ndisc = -1; // explicitly define 'unused'
  224 }
  225 
  226 void
  227 smem_to_28(void *old, void *new, count_t oldsize, count_t newsize)
  228 {
  229     struct memstat_27   *m27 = old;
  230     struct memstat_28   *m28 = new;
  231 
  232     memcpy(m28, m27, sizeof *m27);
  233 
  234     m28->tcpsock        = 0;    // new counter
  235     m28->udpsock        = 0;    // new counter
  236 
  237     m28->commitlim      = m27->commitlim;
  238     m28->committed      = m27->committed;
  239     m28->shmem      = m27->shmem;
  240     m28->shmrss     = m27->shmrss;
  241     m28->shmswp     = m27->shmswp;
  242     m28->slabreclaim    = m27->slabreclaim;
  243     m28->tothugepage    = m27->tothugepage;
  244     m28->freehugepage   = m27->freehugepage;
  245     m28->hugepagesz     = m27->hugepagesz;
  246     m28->vmwballoon     = m27->vmwballoon;
  247     m28->zfsarcsize     = m27->zfsarcsize;
  248     m28->swapcached     = m27->swapcached;
  249     m28->ksmsharing     = m27->ksmsharing;
  250     m28->ksmshared      = m27->ksmshared;
  251     m28->zswstored      = m27->zswstored;
  252     m28->zswtotpool     = m27->zswtotpool;
  253     m28->oomkills       = m27->oomkills;
  254     m28->compactstall   = m27->compactstall;
  255     m28->pgmigrate      = m27->pgmigrate;
  256     m28->numamigrate    = m27->numamigrate;
  257 
  258         m28->pgouts     = 0;    // new counter
  259         m28->pgins      = 0;    // new counter
  260         m28->pagetables     = 0;    // new counter
  261 
  262         memset(m28->cfuture, 0, sizeof m28->cfuture);
  263 }
  264 
  265 void
  266 sdsk_to_28(void *old, void *new, count_t oldsize, count_t newsize)
  267 {
  268     struct dskstat_27   *d27 = old;
  269     struct dskstat_28   *d28 = new;
  270     int         i;
  271 
  272     d28->ndsk   = d27->ndsk;
  273     d28->nmdd   = d27->nmdd;
  274     d28->nlvm   = d27->nlvm;
  275 
  276     for (i=0; i < d28->ndsk; i++)
  277         memcpy(&(d28->dsk[i]), &(d27->dsk[i]), sizeof d27->dsk[i]);
  278 
  279     for (i=0; i < d28->nmdd; i++)
  280         memcpy(&(d28->mdd[i]), &(d27->mdd[i]), sizeof d27->mdd[i]);
  281 
  282     for (i=0; i < d28->nlvm; i++)
  283         memcpy(&(d28->lvm[i]), &(d27->lvm[i]), sizeof d27->lvm[i]);
  284 }
  285 
  286 void
  287 smnu_to_28(void *old, void *new, count_t oldsize, count_t newsize)
  288 {
  289     struct memnuma_27   *n27 = old;
  290     struct memnuma_28   *n28 = new;
  291     int         i;
  292 
  293     n28->nrnuma = n27->nrnuma;
  294 
  295     for (i=0; i < n28->nrnuma; i++)
  296     {
  297         n28->numa[i].numanr         = i;
  298             n28->numa[i].frag       = n27->numa[i].frag;
  299             n28->numa[i].totmem     = n27->numa[i].totmem;
  300             n28->numa[i].freemem        = n27->numa[i].freemem;
  301             n28->numa[i].filepage       = n27->numa[i].filepage;
  302             n28->numa[i].dirtymem       = n27->numa[i].dirtymem;
  303             n28->numa[i].filepage       = n27->numa[i].filepage;
  304             n28->numa[i].slabmem        = n27->numa[i].slabmem;
  305             n28->numa[i].slabreclaim    = n27->numa[i].slabreclaim;
  306             n28->numa[i].active     = n27->numa[i].active;
  307             n28->numa[i].inactive       = n27->numa[i].inactive;
  308             n28->numa[i].shmem      = n27->numa[i].shmem;
  309             n28->numa[i].tothp      = n27->numa[i].tothp;
  310     } 
  311 }
  312 
  313 void
  314 scnu_to_28(void *old, void *new, count_t oldsize, count_t newsize)
  315 {
  316     struct cpunuma_27   *n27 = old;
  317     struct cpunuma_28   *n28 = new;
  318     int         i;
  319 
  320     n28->nrnuma = n27->nrnuma;
  321 
  322     for (i=0; i < n28->nrnuma; i++)
  323     {
  324         n28->numa[i].numanr     = i;
  325             n28->numa[i].nrcpu  = n27->numa[i].nrcpu;
  326             n28->numa[i].stime  = n27->numa[i].stime;
  327             n28->numa[i].utime  = n27->numa[i].utime;
  328             n28->numa[i].ntime  = n27->numa[i].ntime;
  329             n28->numa[i].itime  = n27->numa[i].itime;
  330             n28->numa[i].wtime  = n27->numa[i].wtime;
  331             n28->numa[i].Itime  = n27->numa[i].Itime;
  332             n28->numa[i].Stime  = n27->numa[i].Stime;
  333             n28->numa[i].steal  = n27->numa[i].steal;
  334             n28->numa[i].guest  = n27->numa[i].guest;
  335     } 
  336 }
  337 
  338 
  339 // /////////////////////////////////////////////////////////////////
  340 // Specific functions that convert an old tstat sub-structure to
  341 // a new sub-structure (process level)
  342 // /////////////////////////////////////////////////////////////////
  343 void
  344 tgen_to_21(void *old, void *new, count_t oldsize, count_t newsize)
  345 {
  346     // member 'envid' inserted in struct gen
  347     //
  348     struct gen_20   *g20 = old;
  349     struct gen_21   *g21 = new;
  350 
  351     memcpy(g21, g20, (char *)g20->ifuture - (char *)g20);   // base values
  352     g21->envid = 0;
  353 }
  354 
  355 void
  356 tmem_to_21(void *old, void *new, count_t oldsize, count_t newsize)
  357 {
  358     // members 'pmem' and 'cfuture[4]' inserted in struct mem
  359     //
  360     struct mem_20   *m20 = old;
  361     struct mem_21   *m21 = new;
  362 
  363     m21->minflt = m20->minflt;
  364     m21->majflt = m20->majflt;
  365     m21->vexec  = m20->vexec;
  366     m21->vmem   = m20->vmem;
  367     m21->rmem   = m20->rmem;
  368     m21->pmem   = 0;
  369     m21->vgrow  = m20->vgrow;
  370     m21->rgrow  = m20->rgrow;
  371     m21->vdata  = m20->vdata;
  372     m21->vstack = m20->vstack;
  373     m21->vlibs  = m20->vlibs;
  374     m21->vswap  = m20->vswap;
  375 }
  376 
  377 void
  378 tgen_to_22(void *old, void *new, count_t oldsize, count_t newsize)
  379 {
  380     // member 'envid' removed, members 'ctid' and 'vpid' inserted in struct gen
  381     //
  382     struct gen_21   *g21 = old;
  383     struct gen_22   *g22 = new;
  384 
  385     memcpy(g22, g21, (char *)&g21->envid - (char *)g21);    // copy base values
  386     g22->ctid = g21->envid;
  387     g22->vpid = 0;
  388 }
  389 
  390 void
  391 tcpu_to_26(void *old, void *new, count_t oldsize, count_t newsize)
  392 {
  393     // unused values appear not to be zeroed in version 2.5
  394     //
  395     struct cpu_25   *c25 = old;
  396     struct cpu_26   *c26 = new;
  397 
  398     memcpy(c26, c25, sizeof *c26);      // copy entire struct
  399 
  400         memset(&(c26->wchan), 0, sizeof c26->wchan);
  401     c26->rundelay = 0;
  402 }
  403 
  404 void
  405 tmem_to_26(void *old, void *new, count_t oldsize, count_t newsize)
  406 {
  407     // unused values appear not to be zeroed in version 2.5
  408     //
  409     struct mem_25   *m25 = old;
  410     struct mem_26   *m26 = new;
  411 
  412     memcpy(m26, m25, sizeof *m26);      // copy entire struct
  413 
  414     m26->vlock = 0;
  415 }
  416 
  417 void
  418 tcpu_to_28(void *old, void *new, count_t oldsize, count_t newsize)
  419 {
  420     // cgroup counters inserted
  421     //
  422     struct cpu_27   *c27 = old;
  423     struct cpu_28   *c28 = new;
  424 
  425         c28->utime  = c27->utime;
  426         c28->stime  = c27->stime;
  427         c28->nice   = c27->nice;
  428         c28->prio   = c27->prio;
  429         c28->rtprio = c27->rtprio;
  430         c28->policy = c27->policy;
  431         c28->curcpu = c27->curcpu;
  432         c28->sleepavg   = c27->sleepavg;
  433         c28->rundelay   = c27->rundelay;
  434 
  435     memcpy(c28->wchan, c27->wchan, sizeof c28->wchan);
  436 
  437         c28->blkdelay   = 0;
  438         c28->cgcpuweight= 0;
  439         c28->cgcpumax   = 0;
  440         c28->cgcpumaxr  = 0;
  441 
  442     memset(c28->ifuture, 0, sizeof c28->ifuture);
  443     memset(c28->cfuture, 0, sizeof c28->cfuture);
  444 }
  445 
  446 void
  447 tmem_to_28(void *old, void *new, count_t oldsize, count_t newsize)
  448 {
  449     struct mem_27   *m27 = old;
  450     struct mem_28   *m28 = new;
  451 
  452     memcpy(m28, m27, sizeof *m27);      // copy old struct
  453 
  454     m28->cgmemmax   = 0;
  455     m28->cgmemmaxr  = 0;
  456     m28->cgswpmax   = 0;
  457     m28->cgswpmaxr  = 0;
  458 
  459     memset(m28->cfuture, 0, sizeof m28->cfuture);
  460 }
  461 
  462 ///////////////////////////////////////////////////////////////
  463 // conversion definition for various structs in sstat and tstat
  464 //
  465 #define SETVERSION(major, minor)    ((major << 8) | minor)
  466 #define STROFFSET(str, begin)       ((long)((char *)str - (char *)begin))
  467 
  468 struct sconvstruct {
  469     count_t  structsize;
  470     void    *structptr;
  471     void    (*structconv)(void *, void *, count_t, count_t);
  472 };
  473 
  474 struct tconvstruct {
  475     count_t  structsize;
  476     long    structoffset;
  477     void    (*structconv)(void *, void *, count_t, count_t);
  478 };
  479 
  480 struct sstat_20     sstat_20;
  481 struct sstat_21     sstat_21;
  482 struct sstat_22     sstat_22;
  483 struct sstat_23     sstat_23;
  484 struct sstat_24     sstat_24;
  485 struct sstat_25     sstat_25;
  486 struct sstat_26     sstat_26;
  487 struct sstat_27     sstat_27;
  488 struct sstat_28     sstat_28;
  489 struct sstat        sstat;
  490 
  491 struct tstat_20     tstat_20;
  492 struct tstat_21     tstat_21;
  493 struct tstat_22     tstat_22;
  494 struct tstat_23     tstat_23;
  495 struct tstat_24     tstat_24;
  496 struct tstat_25     tstat_25;
  497 struct tstat_26     tstat_26;
  498 struct tstat_27     tstat_27;
  499 struct tstat_28     tstat_28;
  500 struct tstat        tstat;
  501 
  502 struct convertall {
  503     int         version;    // version of raw log
  504 
  505     unsigned int        sstatlen;   // length of struct sstat
  506     void            *sstat;     // pointer to sstat struct
  507 
  508     unsigned int        tstatlen;   // length of struct tstat
  509     void            *tstat;     // pointer to tstat structs
  510 
  511     // conversion definition for subparts within sstat
  512     struct sconvstruct  scpu;
  513     struct sconvstruct  smem;
  514     struct sconvstruct  snet;
  515     struct sconvstruct  sintf;
  516     struct sconvstruct  sdsk;   
  517     struct sconvstruct  snfs;
  518     struct sconvstruct  scfs;
  519     struct sconvstruct  swww;
  520     struct sconvstruct  spsi;
  521     struct sconvstruct  sgpu;
  522     struct sconvstruct  sifb;
  523         struct sconvstruct  smnum;
  524         struct sconvstruct  scnum;
  525         struct sconvstruct  sllc;
  526 
  527     // conversion definition for subparts within tstat
  528     struct tconvstruct  tgen;
  529     struct tconvstruct  tcpu;
  530     struct tconvstruct  tdsk;
  531     struct tconvstruct  tmem;
  532     struct tconvstruct  tnet;
  533     struct tconvstruct  tgpu;
  534 } convs[] = 
  535 {
  536     {SETVERSION(2,0),
  537          sizeof(struct sstat_20),   &sstat_20,
  538          sizeof(struct tstat_20),   NULL,
  539 
  540         {sizeof(struct cpustat_20),     &sstat_20.cpu,  NULL},
  541         {sizeof(struct memstat_20),     &sstat_20.mem,  NULL},
  542         {sizeof(struct netstat_20),     &sstat_20.net,  NULL},
  543         {sizeof(struct intfstat_20),    &sstat_20.intf, NULL},
  544         {sizeof(struct dskstat_20),     &sstat_20.dsk,  NULL},
  545         {0,                 NULL,       NULL},
  546         {0,                 NULL,       NULL},
  547         {sizeof(struct wwwstat_20),     &sstat_20.www,  NULL},
  548         {0,                 NULL,       NULL},
  549         {0,                 NULL,       NULL},
  550         {0,                 NULL,       NULL},
  551         {0,                 NULL,       NULL},
  552         {0,                 NULL,       NULL},
  553         {0,                 NULL,       NULL},
  554 
  555         {sizeof(struct gen_20),  
  556             STROFFSET(&tstat_20.gen, &tstat_20),    NULL},
  557         {sizeof(struct cpu_20),
  558             STROFFSET(&tstat_20.cpu, &tstat_20),    NULL},
  559         {sizeof(struct dsk_20), 
  560             STROFFSET(&tstat_20.dsk, &tstat_20),    NULL},
  561         {sizeof(struct mem_20),
  562             STROFFSET(&tstat_20.mem, &tstat_20),    NULL},
  563         {sizeof(struct net_20),
  564             STROFFSET(&tstat_20.net, &tstat_20),    NULL},
  565         {0,                 0,      NULL},
  566     },
  567 
  568     {SETVERSION(2,1), // 2.0 --> 2.1
  569          sizeof(struct sstat_21),   &sstat_21,
  570          sizeof(struct tstat_21),   NULL,
  571 
  572         {sizeof(struct cpustat_21),     &sstat_21.cpu,  scpu_to_21},
  573         {sizeof(struct memstat_21),     &sstat_21.mem,  justcopy},
  574         {sizeof(struct netstat_21),     &sstat_21.net,  justcopy},
  575         {sizeof(struct intfstat_21),    &sstat_21.intf, justcopy},
  576         {sizeof(struct dskstat_21),     &sstat_21.dsk,  sdsk_to_21},
  577         {0,                 NULL,       NULL},
  578         {0,                 NULL,       NULL},
  579         {sizeof(struct wwwstat_21),     &sstat_21.www,  justcopy},
  580         {0,                 NULL,       NULL},
  581         {0,                 NULL,       NULL},
  582         {0,                 NULL,       NULL},
  583         {0,                 NULL,       NULL},
  584         {0,                 NULL,       NULL},
  585         {0,                 NULL,       NULL},
  586 
  587         {sizeof(struct gen_21),
  588             STROFFSET(&tstat_21.gen, &tstat_21),    tgen_to_21},
  589         {sizeof(struct cpu_21),
  590             STROFFSET(&tstat_21.cpu, &tstat_21),    justcopy},
  591         {sizeof(struct dsk_21), 
  592             STROFFSET(&tstat_21.dsk, &tstat_21),    justcopy},
  593         {sizeof(struct mem_21),
  594             STROFFSET(&tstat_21.mem, &tstat_21),    tmem_to_21},
  595         {sizeof(struct net_21),
  596             STROFFSET(&tstat_21.net, &tstat_21),    justcopy},
  597         {0,                 0,      NULL},
  598     },
  599 
  600     {SETVERSION(2,2), // 2.1 --> 2.2
  601          sizeof(struct sstat_22),   &sstat_22,
  602          sizeof(struct tstat_22),   NULL,
  603 
  604         {sizeof(struct cpustat_22),     &sstat_22.cpu,  justcopy},
  605         {sizeof(struct memstat_22),     &sstat_22.mem,  justcopy},
  606         {sizeof(struct netstat_22),     &sstat_22.net,  justcopy},
  607         {sizeof(struct intfstat_22),    &sstat_22.intf, sint_to_22},
  608         {sizeof(struct dskstat_22),     &sstat_22.dsk,  justcopy},
  609         {sizeof(struct nfsstat_22),     &sstat_22.nfs,  NULL},
  610         {sizeof(struct contstat_22),    &sstat_22.cfs,  NULL},
  611         {sizeof(struct wwwstat_22),     &sstat_22.www,  justcopy},
  612         {0,                 NULL,       NULL},
  613         {0,                 NULL,       NULL},
  614         {0,                 NULL,       NULL},
  615         {0,                 NULL,       NULL},
  616         {0,                 NULL,       NULL},
  617         {0,                 NULL,       NULL},
  618 
  619         {sizeof(struct gen_22), 
  620             STROFFSET(&tstat_22.gen, &tstat_22),    tgen_to_22},
  621         {sizeof(struct cpu_22),
  622             STROFFSET(&tstat_22.cpu, &tstat_22),    justcopy},
  623         {sizeof(struct dsk_22),
  624             STROFFSET(&tstat_22.dsk, &tstat_22),    justcopy},
  625         {sizeof(struct mem_22),
  626             STROFFSET(&tstat_22.mem, &tstat_22),    justcopy},
  627         {sizeof(struct net_22),
  628             STROFFSET(&tstat_22.net, &tstat_22),    justcopy},
  629         {0,                 0,      NULL},
  630     },
  631 
  632     {SETVERSION(2,3), // 2.2 --> 2.3
  633          sizeof(struct sstat_23),   &sstat_23,
  634          sizeof(struct tstat_23),   NULL,
  635 
  636         {sizeof(struct cpustat_23),     &sstat_23.cpu,  justcopy},
  637         {sizeof(struct memstat_23),     &sstat_23.mem,  justcopy},
  638         {sizeof(struct netstat_23),     &sstat_23.net,  justcopy},
  639         {sizeof(struct intfstat_23),    &sstat_23.intf, justcopy},
  640         {sizeof(struct dskstat_23),     &sstat_23.dsk,  justcopy},
  641         {sizeof(struct nfsstat_23),     &sstat_23.nfs,  justcopy},
  642         {sizeof(struct contstat_23),    &sstat_23.cfs,  justcopy},
  643         {sizeof(struct wwwstat_23),     &sstat_23.www,  justcopy},
  644         {0,                 NULL,       NULL},
  645         {0,                 NULL,       NULL},
  646         {0,                 NULL,       NULL},
  647         {0,                 NULL,       NULL},
  648         {0,                 NULL,       NULL},
  649         {0,                 NULL,       NULL},
  650 
  651         {sizeof(struct gen_23),
  652             STROFFSET(&tstat_23.gen, &tstat_23),    justcopy},
  653         {sizeof(struct cpu_23),
  654             STROFFSET(&tstat_23.cpu, &tstat_23),    justcopy},
  655         {sizeof(struct dsk_23),
  656             STROFFSET(&tstat_23.dsk, &tstat_23),    justcopy},
  657         {sizeof(struct mem_23), 
  658             STROFFSET(&tstat_23.mem, &tstat_23),    justcopy},
  659         {sizeof(struct net_23),
  660             STROFFSET(&tstat_23.net, &tstat_23),    justcopy},
  661         {0,                 0,      NULL},
  662     },
  663 
  664     {SETVERSION(2,4), // 2.3 --> 2.4
  665          sizeof(struct sstat_24),   &sstat_24,
  666          sizeof(struct tstat_24),   NULL,
  667 
  668         {sizeof(struct cpustat_24),     &sstat_24.cpu,  justcopy},
  669         {sizeof(struct memstat_24),     &sstat_24.mem,  justcopy},
  670         {sizeof(struct netstat_24),     &sstat_24.net,  justcopy},
  671         {sizeof(struct intfstat_24),    &sstat_24.intf, justcopy},
  672         {sizeof(struct dskstat_24),     &sstat_24.dsk,  justcopy},
  673         {sizeof(struct nfsstat_24),     &sstat_24.nfs,  justcopy},
  674         {sizeof(struct contstat_24),    &sstat_24.cfs,  justcopy},
  675         {sizeof(struct wwwstat_24),     &sstat_24.www,  justcopy},
  676         {0,                 &sstat_24.psi,  NULL},
  677         {0,                 &sstat_24.gpu,  NULL},
  678         {0,                 &sstat_24.ifb,  NULL},
  679         {0,                 NULL,       NULL},
  680         {0,                 NULL,       NULL},
  681         {0,                 NULL,       NULL},
  682 
  683         {sizeof(struct gen_24),
  684             STROFFSET(&tstat_24.gen, &tstat_24),    justcopy},
  685         {sizeof(struct cpu_24),
  686             STROFFSET(&tstat_24.cpu, &tstat_24),    justcopy},
  687         {sizeof(struct dsk_24),
  688             STROFFSET(&tstat_24.dsk, &tstat_24),    justcopy},
  689         {sizeof(struct mem_24),
  690             STROFFSET(&tstat_24.mem, &tstat_24),    justcopy},
  691         {sizeof(struct net_24),
  692             STROFFSET(&tstat_24.net, &tstat_24),    justcopy},
  693         {sizeof(struct gpu_24),
  694             STROFFSET(&tstat_24.gpu, &tstat_24),    justcopy},
  695     },
  696 
  697     {SETVERSION(2,5), // 2.4 --> 2.5
  698          sizeof(struct sstat_25),   &sstat_25,
  699          sizeof(struct tstat_25),   NULL,
  700 
  701         {sizeof(struct cpustat_25),     &sstat_25.cpu,  justcopy},
  702         {sizeof(struct memstat_25),     &sstat_25.mem,  justcopy},
  703         {sizeof(struct netstat_25),     &sstat_25.net,  justcopy},
  704         {sizeof(struct intfstat_25),    &sstat_25.intf, justcopy},
  705         {sizeof(struct dskstat_25),     &sstat_25.dsk,  justcopy},
  706         {sizeof(struct nfsstat_25),     &sstat_25.nfs,  justcopy},
  707         {sizeof(struct contstat_25),    &sstat_25.cfs,  justcopy},
  708         {sizeof(struct wwwstat_25),     &sstat_25.www,  justcopy},
  709         {sizeof(struct pressure_25),    &sstat_25.psi,  justcopy},
  710         {sizeof(struct gpustat_25),     &sstat_25.gpu,  justcopy},
  711         {sizeof(struct ifbstat_25),     &sstat_25.ifb,  justcopy},
  712         {0,                 NULL,       NULL},
  713         {0,                 NULL,       NULL},
  714         {0,                 NULL,       NULL},
  715 
  716         {sizeof(struct gen_25),
  717             STROFFSET(&tstat_25.gen, &tstat_25),    justcopy},
  718         {sizeof(struct cpu_25),
  719             STROFFSET(&tstat_25.cpu, &tstat_25),    justcopy},
  720         {sizeof(struct dsk_25),
  721             STROFFSET(&tstat_25.dsk, &tstat_25),    justcopy},
  722         {sizeof(struct mem_25),
  723             STROFFSET(&tstat_25.mem, &tstat_25),    justcopy},
  724         {sizeof(struct net_25),
  725             STROFFSET(&tstat_25.net, &tstat_25),    justcopy},
  726         {sizeof(struct gpu_25),
  727             STROFFSET(&tstat_25.gpu, &tstat_25),    justcopy},
  728     },
  729 
  730     {SETVERSION(2,6), // 2.5 --> 2.6
  731          sizeof(struct sstat_26),   &sstat_26,
  732          sizeof(struct tstat_26),   NULL,
  733 
  734         {sizeof(struct cpustat_26),     &sstat_26.cpu,  justcopy},
  735         {sizeof(struct memstat_26),     &sstat_26.mem,  justcopy},
  736         {sizeof(struct netstat_26),     &sstat_26.net,  justcopy},
  737         {sizeof(struct intfstat_26),    &sstat_26.intf, justcopy},
  738         {sizeof(struct dskstat_26),     &sstat_26.dsk,  justcopy},
  739         {sizeof(struct nfsstat_26),     &sstat_26.nfs,  justcopy},
  740         {sizeof(struct contstat_26),    &sstat_26.cfs,  justcopy},
  741         {sizeof(struct wwwstat_26),     &sstat_26.www,  justcopy},
  742         {sizeof(struct pressure_26),    &sstat_26.psi,  justcopy},
  743         {sizeof(struct gpustat_26),     &sstat_26.gpu,  justcopy},
  744         {sizeof(struct ifbstat_26),     &sstat_26.ifb,  justcopy},
  745         {0,                 NULL,       NULL},
  746         {0,                 NULL,       NULL},
  747         {0,                 NULL,       NULL},
  748 
  749         {sizeof(struct gen_26),
  750             STROFFSET(&tstat_26.gen, &tstat_26),    justcopy},
  751         {sizeof(struct cpu_26),
  752             STROFFSET(&tstat_26.cpu, &tstat_26),    tcpu_to_26},
  753         {sizeof(struct dsk_26),
  754             STROFFSET(&tstat_26.dsk, &tstat_26),    justcopy},
  755         {sizeof(struct mem_26),
  756             STROFFSET(&tstat_26.mem, &tstat_26),    tmem_to_26},
  757         {sizeof(struct net_26),
  758             STROFFSET(&tstat_26.net, &tstat_26),    justcopy},
  759         {sizeof(struct gpu_26),
  760             STROFFSET(&tstat_26.gpu, &tstat_26),    justcopy},
  761     },
  762 
  763     {SETVERSION(2,7), // 2.6 --> 2.7
  764          sizeof(struct sstat_27),   &sstat_27,
  765          sizeof(struct tstat_27),   NULL,
  766 
  767         {sizeof(struct cpustat_27),     &sstat_27.cpu,  scpu_to_27},
  768         {sizeof(struct memstat_27),     &sstat_27.mem,  smem_to_27},
  769         {sizeof(struct netstat_27),     &sstat_27.net,  justcopy},
  770         {sizeof(struct intfstat_27),    &sstat_27.intf, justcopy},
  771         {sizeof(struct dskstat_27),     &sstat_27.dsk,  sdsk_to_27},
  772         {sizeof(struct nfsstat_27),     &sstat_27.nfs,  justcopy},
  773         {sizeof(struct contstat_27),    &sstat_27.cfs,  justcopy},
  774         {sizeof(struct wwwstat_27),     &sstat_27.www,  justcopy},
  775         {sizeof(struct pressure_27),    &sstat_27.psi,  justcopy},
  776         {sizeof(struct gpustat_27),     &sstat_27.gpu,  justcopy},
  777         {sizeof(struct ifbstat_27),     &sstat_27.ifb,  justcopy},
  778         {0,                 &sstat_27.memnuma,  NULL},
  779         {0,                 &sstat_27.cpunuma,  NULL},
  780         {0,                 NULL,       NULL},
  781 
  782         {sizeof(struct gen_27),
  783             STROFFSET(&tstat_27.gen, &tstat_27),    justcopy},
  784         {sizeof(struct cpu_27),
  785             STROFFSET(&tstat_27.cpu, &tstat_27),    justcopy},
  786         {sizeof(struct dsk_27),
  787             STROFFSET(&tstat_27.dsk, &tstat_27),    justcopy},
  788         {sizeof(struct mem_27),
  789             STROFFSET(&tstat_27.mem, &tstat_27),    justcopy},
  790         {sizeof(struct net_27),
  791             STROFFSET(&tstat_27.net, &tstat_27),    justcopy},
  792         {sizeof(struct gpu_27),
  793             STROFFSET(&tstat_27.gpu, &tstat_27),    justcopy},
  794     },
  795 
  796     {SETVERSION(2,8), // 2.7 --> 2.8
  797          sizeof(struct sstat_28),   &sstat_28,
  798          sizeof(struct tstat_28),   NULL,
  799 
  800         {sizeof(struct cpustat_28),     &sstat_28.cpu,     justcopy},
  801         {sizeof(struct memstat_28),     &sstat_28.mem,     smem_to_28},
  802         {sizeof(struct netstat_28),     &sstat_28.net,     justcopy},
  803         {sizeof(struct intfstat_28),    &sstat_28.intf,    justcopy},
  804         {sizeof(struct dskstat_28),     &sstat_28.dsk,     sdsk_to_28},
  805         {sizeof(struct nfsstat_28),     &sstat_28.nfs,     justcopy},
  806         {sizeof(struct contstat_28),    &sstat_28.cfs,     justcopy},
  807         {sizeof(struct wwwstat_28),     &sstat_28.www,     justcopy},
  808         {sizeof(struct pressure_28),    &sstat_28.psi,     justcopy},
  809         {sizeof(struct gpustat_28),     &sstat_28.gpu,     justcopy},
  810         {sizeof(struct ifbstat_28),     &sstat_28.ifb,     justcopy},
  811         {sizeof(struct memnuma_28),     &sstat_28.memnuma, smnu_to_28},
  812         {sizeof(struct cpunuma_28),     &sstat_28.cpunuma, scnu_to_28},
  813         {0,                 &sstat_28.llc,     NULL},
  814 
  815         {sizeof(struct gen_28),
  816             STROFFSET(&tstat_28.gen, &tstat_28),    justcopy},
  817         {sizeof(struct cpu_28),
  818             STROFFSET(&tstat_28.cpu, &tstat_28),    tcpu_to_28},
  819         {sizeof(struct dsk_28),
  820             STROFFSET(&tstat_28.dsk, &tstat_28),    justcopy},
  821         {sizeof(struct mem_28),
  822             STROFFSET(&tstat_28.mem, &tstat_28),    tmem_to_28},
  823         {sizeof(struct net_28),
  824             STROFFSET(&tstat_28.net, &tstat_28),    justcopy},
  825         {sizeof(struct gpu_28),
  826             STROFFSET(&tstat_28.gpu, &tstat_28),    justcopy},
  827     },
  828 };
  829 
  830 int numconvs = sizeof convs / sizeof(struct convertall);
  831 
  832 ///////////////////////////////////////////////////////////////
  833 // End of conversion functions
  834 ///////////////////////////////////////////////////////////////
  835 
  836 // function prototypes
  837 //
  838 static int  openin(char *);
  839 static void readin(int, void *, int);
  840 
  841 static int  openout(char *);
  842 static void writeout(int, void *, int);
  843 static void writesamp(int, struct rawrecord *, void *, int, void *,
  844                 int, int);
  845 
  846 static void copy_file(int, int);
  847 static void convert_samples(int, int, struct rawheader *, int,  int);
  848 static void do_sconvert(struct sconvstruct *, struct sconvstruct *);
  849 static void do_tconvert(void *, void *,
  850             struct tconvstruct *, struct tconvstruct *);
  851 
  852 static int  getrawsstat(int, struct sstat *, int);
  853 static int  getrawtstat(int, struct tstat *, int, int);
  854 static void testcompval(int, char *);
  855 
  856 int
  857 main(int argc, char *argv[])
  858 {
  859     int         ifd, ofd;
  860     struct rawheader    irh, orh;
  861     int         i, versionix, targetix = -1;
  862     int         c, major, minor, targetvers;
  863     char            *infile, *outfile;
  864 
  865     // verify the command line arguments:
  866     //  optional flags and mandatory input and output filename
  867     //
  868     if (argc < 2)
  869         prusage(argv[0]);
  870 
  871     while ((c = getopt(argc, argv, "?t:")) != EOF)
  872     {
  873         switch (c)
  874         {
  875            case '?':        // usage wanted ?
  876             prusage(argv[0]);
  877             break;
  878 
  879            case 't':        // target version
  880             if ( sscanf(optarg, "%d.%d", &major, &minor) != 2)
  881             {
  882                 fprintf(stderr,
  883                     "target version format: major.minor\n");
  884                 prusage(argv[0]);
  885             }
  886 
  887             targetvers = SETVERSION(major, minor);
  888 
  889             // search for target version in conversion table
  890             //
  891             for (i=0, targetix=-1; i < numconvs; i++)
  892             {
  893                 if (targetvers == convs[i].version)
  894                 {
  895                     targetix = i;
  896                     break;
  897                 }
  898             }
  899 
  900             if (targetix == -1) // incorrect target version?
  901             {
  902                 fprintf(stderr,
  903                     "target version incorrect!");
  904                 prusage(argv[0]);
  905             }
  906             break;
  907 
  908            default:
  909             prusage(argv[0]);
  910             break;
  911         }
  912     }
  913 
  914     if (optind >= argc)
  915         prusage(argv[0]);
  916 
  917     infile  = argv[optind++];
  918 
  919     // determine target version (default: latest version)
  920     //
  921     if (targetix == -1) // no specific target version requested?
  922         targetix = numconvs - 1;
  923 
  924     // open the input file and verify magic number
  925     //
  926     if ( (ifd = openin(infile)) == -1)
  927     {
  928         prusage(argv[0]);
  929         exit(2);
  930     }
  931 
  932     readin(ifd, &irh, sizeof irh);
  933 
  934     if (irh.magic != MYMAGIC)
  935     {
  936         fprintf(stderr,
  937             "File %s does not contain atop/atopsar data "
  938             "(wrong magic number)\n", infile);
  939         exit(3);
  940     }
  941 
  942     printf("Version of %s: %d.%d\n", infile,
  943             (irh.aversion >> 8) & 0x7f, irh.aversion & 0xff);
  944 
  945     if (irh.rawheadlen != sizeof(struct rawheader) ||
  946         irh.rawreclen  != sizeof(struct rawrecord)   )
  947     {
  948         fprintf(stderr,
  949             "File %s created with atop compiled "
  950             "for other CPU architecture\n", infile);
  951         exit(3);
  952     }
  953 
  954     // search for version of input file in conversion table
  955     //
  956     for (i=0, versionix=-1; i < numconvs; i++)
  957     {
  958         if (convs[i].version == (irh.aversion & 0x7fff))
  959         {
  960             versionix = i;
  961             break;
  962         }
  963     }
  964 
  965     if (versionix == -1)
  966     {
  967         fprintf(stderr,
  968             "This version is not supported for conversion!\n");
  969         exit(11);
  970     }
  971 
  972     if (versionix > targetix)
  973     {
  974         fprintf(stderr, "Downgrading of version is not supported!\n");
  975         exit(11);
  976     }
  977 
  978     if (irh.sstatlen != convs[versionix].sstatlen ||
  979         irh.tstatlen != convs[versionix].tstatlen   )
  980     {
  981         fprintf(stderr,
  982             "File %s contains unexpected internal structures\n",
  983             infile);
  984         fprintf(stderr, "sstat: %d/%d, tstat: %d/%d\n",
  985             irh.sstatlen, convs[versionix].sstatlen,
  986                 irh.tstatlen, convs[versionix].tstatlen);
  987                 
  988         exit(11);
  989     }
  990 
  991     // handle the output file 
  992     //
  993     if (optind >= argc)
  994         exit(0);
  995 
  996     outfile = argv[optind++];
  997 
  998     if (strcmp(infile, outfile) == 0)
  999     {
 1000         fprintf(stderr,
 1001             "input file and output file should not be identical!\n");
 1002         exit(12);
 1003     }
 1004 
 1005     // open the output file 
 1006     //
 1007     if ( (ofd = openout(outfile)) == -1)
 1008     {
 1009         prusage(argv[0]);
 1010         exit(4);
 1011     }
 1012 
 1013     // write raw header to output file
 1014     //
 1015     orh = irh;
 1016 
 1017     orh.aversion    = convs[targetix].version | 0x8000;
 1018     orh.sstatlen    = convs[targetix].sstatlen;
 1019     orh.tstatlen    = convs[targetix].tstatlen;
 1020 
 1021     writeout(ofd, &orh, sizeof orh);
 1022 
 1023     printf("Version of %s: %d.%d\n", outfile,
 1024             (orh.aversion >> 8) & 0x7f, orh.aversion & 0xff);
 1025 
 1026     // copy and convert every sample, unless the version of the
 1027     // input file is identical to the target version (then just copy)
 1028     //
 1029     if (versionix < targetix)
 1030         convert_samples(ifd, ofd, &irh, versionix, targetix);
 1031     else
 1032         copy_file(ifd, ofd);
 1033 
 1034     close(ifd);
 1035     close(ofd);
 1036 
 1037     return 0;
 1038 }
 1039 
 1040 //
 1041 // Function that reads the input file sample-by-sample,
 1042 // converts it to an output sample and writes that to the output file
 1043 //
 1044 static void
 1045 convert_samples(int ifd, int ofd, struct rawheader *irh, int ivix, int ovix)
 1046 {
 1047     struct rawrecord    irr, orr;
 1048     int         i, t;
 1049     count_t         count = 0;
 1050 
 1051     while ( read(ifd, &irr, irh->rawreclen) == irh->rawreclen)
 1052     {
 1053         count++;
 1054 
 1055         // read compressed system-level statistics and decompress
 1056         //
 1057         if ( !getrawsstat(ifd, convs[ivix].sstat, irr.scomplen) )
 1058             exit(7);
 1059 
 1060         // read compressed process-level statistics and decompress
 1061         //
 1062         convs[ivix].tstat = malloc(convs[ivix].tstatlen * irr.ndeviat);
 1063 
 1064         ptrverify(convs[ivix].tstat,
 1065             "Malloc failed for %d stored tasks\n", irr.ndeviat);
 1066 
 1067         if ( !getrawtstat(ifd, convs[ivix].tstat,
 1068                     irr.pcomplen, irr.ndeviat) )
 1069             exit(7);
 1070 
 1071         // STEP-BY-STEP CONVERSION FROM OLD VERSION TO NEW VERSION
 1072         // 
 1073         for (i=ivix; i < ovix; i++)
 1074         {
 1075             // convert system-level statistics to newer version
 1076             //
 1077             memset(convs[i+1].sstat, 0, convs[i+1].sstatlen);
 1078 
 1079             do_sconvert(&(convs[i].scpu),   &(convs[i+1].scpu));
 1080             do_sconvert(&(convs[i].smem),   &(convs[i+1].smem));
 1081             do_sconvert(&(convs[i].snet),   &(convs[i+1].snet));
 1082             do_sconvert(&(convs[i].sintf),  &(convs[i+1].sintf));
 1083             do_sconvert(&(convs[i].sdsk),   &(convs[i+1].sdsk));
 1084             do_sconvert(&(convs[i].snfs),   &(convs[i+1].snfs));
 1085             do_sconvert(&(convs[i].scfs),   &(convs[i+1].scfs));
 1086             do_sconvert(&(convs[i].spsi),   &(convs[i+1].spsi));
 1087             do_sconvert(&(convs[i].sgpu),   &(convs[i+1].sgpu));
 1088             do_sconvert(&(convs[i].sifb),   &(convs[i+1].sifb));
 1089             do_sconvert(&(convs[i].smnum),  &(convs[i+1].smnum));
 1090             do_sconvert(&(convs[i].scnum),  &(convs[i+1].scnum));
 1091             do_sconvert(&(convs[i].swww),   &(convs[i+1].swww));
 1092 
 1093             // convert process-level statistics to newer version
 1094             //
 1095             convs[i+1].tstat = malloc(convs[i+1].tstatlen *
 1096                                 irr.ndeviat);
 1097             ptrverify(convs[ivix].tstat,
 1098                "Malloc failed for %d stored tasks\n", irr.ndeviat);
 1099 
 1100             memset(convs[i+1].tstat, 0, convs[i+1].tstatlen *
 1101                                 irr.ndeviat);
 1102 
 1103             for (t=0; t < irr.ndeviat; t++) // for every task
 1104             {
 1105                 do_tconvert(
 1106                     convs[i].tstat  +(t*convs[i].tstatlen), 
 1107                     convs[i+1].tstat+(t*convs[i+1].tstatlen),
 1108                     &(convs[i].tgen), &(convs[i+1].tgen));
 1109 
 1110                 do_tconvert(
 1111                     convs[i].tstat  +(t*convs[i].tstatlen), 
 1112                     convs[i+1].tstat+(t*convs[i+1].tstatlen),
 1113                     &(convs[i].tcpu), &(convs[i+1].tcpu));
 1114 
 1115                 do_tconvert(
 1116                     convs[i].tstat  +(t*convs[i].tstatlen), 
 1117                     convs[i+1].tstat+(t*convs[i+1].tstatlen),
 1118                     &(convs[i].tdsk), &(convs[i+1].tdsk));
 1119 
 1120                 do_tconvert(
 1121                     convs[i].tstat  +(t*convs[i].tstatlen), 
 1122                     convs[i+1].tstat+(t*convs[i+1].tstatlen),
 1123                     &(convs[i].tmem), &(convs[i+1].tmem));
 1124 
 1125                 do_tconvert(
 1126                     convs[i].tstat  +(t*convs[i].tstatlen), 
 1127                     convs[i+1].tstat+(t*convs[i+1].tstatlen),
 1128                     &(convs[i].tnet), &(convs[i+1].tnet));
 1129 
 1130                 do_tconvert(
 1131                     convs[i].tstat  +(t*convs[i].tstatlen), 
 1132                     convs[i+1].tstat+(t*convs[i+1].tstatlen),
 1133                     &(convs[i].tgpu), &(convs[i+1].tgpu));
 1134             }
 1135 
 1136             free(convs[i].tstat);
 1137         }
 1138 
 1139         // write new sample to output file
 1140         //
 1141         orr = irr;
 1142 
 1143         writesamp(ofd, &orr, convs[ovix].sstat, convs[ovix].sstatlen,
 1144                              convs[ovix].tstat, convs[ovix].tstatlen,
 1145                              irr.ndeviat);
 1146 
 1147         // cleanup
 1148         // 
 1149         free(convs[ovix].tstat);
 1150     }
 1151 
 1152     printf("Samples converted: %llu\n", count);
 1153 }
 1154 
 1155 //
 1156 // Function that calls the appropriate function to convert a struct
 1157 // from the sstat structure
 1158 //
 1159 static void
 1160 do_sconvert(struct sconvstruct *cur, struct sconvstruct *next)
 1161 {
 1162     if (next->structconv)
 1163     {
 1164         (*(next->structconv))(cur->structptr,  next->structptr,
 1165                               cur->structsize, next->structsize);
 1166     }
 1167 }
 1168 
 1169 //
 1170 // Function that calls the appropriate function to convert a struct
 1171 // from one of the tstat structures
 1172 //
 1173 static void
 1174 do_tconvert(void *curtstat,          void *nexttstat,
 1175         struct tconvstruct *cur, struct tconvstruct *next)
 1176 {
 1177     if (next->structconv)
 1178     {
 1179         (*(next->structconv))(curtstat + cur->structoffset,
 1180                               nexttstat + next->structoffset,
 1181                               cur->structsize, next->structsize);
 1182     }
 1183 }
 1184 
 1185 
 1186 //
 1187 // Function to copy input file transparently to output file
 1188 //
 1189 static void
 1190 copy_file(int ifd, int ofd)
 1191 {
 1192     unsigned char   buf[64*1024];
 1193     int     nr, nw;
 1194 
 1195     (void) lseek(ifd, 0, SEEK_SET);
 1196     (void) lseek(ofd, 0, SEEK_SET);
 1197 
 1198     while ( (nr = read(ifd, buf, sizeof buf)) > 0)
 1199     {
 1200         if ( (nw = write(ofd, buf, nr)) < nr)
 1201         {
 1202             if (nw == -1)
 1203             {
 1204                 perror("write output file");
 1205                 exit(42);
 1206             }
 1207             else
 1208             {
 1209                 fprintf(stderr,
 1210                     "Output file saturated\n");
 1211                 exit(42);
 1212             }
 1213         }
 1214     }
 1215 
 1216     if (nr == -1)
 1217     {
 1218         perror("read input file");
 1219         exit(42);
 1220     }
 1221     else
 1222     {
 1223         printf("Raw file copied (version already up-to-date)\n");
 1224     }
 1225 }
 1226 
 1227 //
 1228 // Function that opens an existing raw file and
 1229 // verifies the magic number
 1230 //
 1231 static int
 1232 openin(char *infile)
 1233 {
 1234     int rawfd;
 1235 
 1236     /*
 1237     ** open raw file for reading
 1238     */
 1239     if ( (rawfd = open(infile, O_RDONLY)) == -1)
 1240     {
 1241         fprintf(stderr, "%s - ", infile);
 1242         perror("open for reading");
 1243         return -1;
 1244     }
 1245 
 1246     return rawfd;
 1247 }
 1248 
 1249 //
 1250 // Function that reads a chunk of bytes from
 1251 // the input raw file
 1252 //
 1253 static void
 1254 readin(int rawfd, void *buf, int size)
 1255 {
 1256     /*
 1257     ** read the requested chunk and verify
 1258     */
 1259     if ( read(rawfd, buf, size) < size)
 1260     {
 1261         fprintf(stderr, "can not read raw file\n");
 1262         close(rawfd);
 1263         exit(9);
 1264     }
 1265 }
 1266 
 1267 
 1268 //
 1269 // Function that creates a raw log for output
 1270 //
 1271 static int
 1272 openout(char *outfile)
 1273 {
 1274     int rawfd;
 1275 
 1276     /*
 1277     ** create new output file
 1278     */
 1279     if ( (rawfd = creat(outfile, 0666)) == -1)
 1280     {
 1281         fprintf(stderr, "%s - ", outfile);
 1282         perror("create raw output file");
 1283         return -1;
 1284     }
 1285 
 1286     return rawfd;
 1287 }
 1288 
 1289 //
 1290 // Function that reads a chunk of bytes from
 1291 // the input raw file
 1292 //
 1293 static void
 1294 writeout(int rawfd, void *buf, int size)
 1295 {
 1296     /*
 1297     ** write the provided chunk and verify
 1298     */
 1299     if ( write(rawfd, buf, size) < size)
 1300     {
 1301         fprintf(stderr, "can not write raw file\n");
 1302         close(rawfd);
 1303         exit(10);
 1304     }
 1305 }
 1306 
 1307 //
 1308 // Function that shows the usage message
 1309 //
 1310 void
 1311 prusage(char *name)
 1312 {
 1313     fprintf(stderr,
 1314         "Usage: %s [-t version] rawinput [rawoutput]\n", name);
 1315     fprintf(stderr,
 1316         "\t-t version      target version (default: %d.%d) for output\n",
 1317             (convs[numconvs-1].version >> 8) & 0x7f,
 1318              convs[numconvs-1].version  & 0x7f);
 1319 
 1320     exit(1);
 1321 }
 1322 
 1323 
 1324 //
 1325 // Function to read the system-level statistics from the current offset
 1326 //
 1327 static int
 1328 getrawsstat(int rawfd, struct sstat *sp, int complen)
 1329 {
 1330     Byte        *compbuf;
 1331     unsigned long   uncomplen = sizeof(struct sstat);
 1332     int     rv;
 1333 
 1334     compbuf = malloc(complen);
 1335 
 1336     ptrverify(compbuf, "Malloc failed for reading compressed sysstats\n");
 1337 
 1338     if ( read(rawfd, compbuf, complen) < complen)
 1339     {
 1340         free(compbuf);
 1341         fprintf(stderr,
 1342             "Failed to read %d bytes for system\n", complen);
 1343         return 0;
 1344     }
 1345 
 1346     rv = uncompress((Byte *)sp, &uncomplen, compbuf, complen);
 1347 
 1348     testcompval(rv, "uncompress");
 1349 
 1350     free(compbuf);
 1351 
 1352     return 1;
 1353 }
 1354 
 1355 //
 1356 // Function to read the process-level statistics from the current offset
 1357 //
 1358 static int
 1359 getrawtstat(int rawfd, struct tstat *pp, int complen, int ndeviat)
 1360 {
 1361     Byte        *compbuf;
 1362     unsigned long   uncomplen = sizeof(struct tstat) * ndeviat;
 1363     int     rv;
 1364 
 1365     compbuf = malloc(complen);
 1366 
 1367     ptrverify(compbuf, "Malloc failed for reading compressed procstats\n");
 1368 
 1369     if ( read(rawfd, compbuf, complen) < complen)
 1370     {
 1371         free(compbuf);
 1372         fprintf(stderr,
 1373             "Failed to read %d bytes for tasks\n", complen);
 1374         return 0;
 1375     }
 1376 
 1377     rv = uncompress((Byte *)pp, &uncomplen, compbuf, complen);
 1378 
 1379     testcompval(rv, "uncompress");
 1380 
 1381     free(compbuf);
 1382 
 1383     return 1;
 1384 }
 1385 
 1386 //
 1387 // Function that writes a new sample to the output file
 1388 //
 1389 static void
 1390 writesamp(int ofd, struct rawrecord *rr,
 1391      void *sstat, int sstatlen, void *tstat, int tstatlen, int ntask)
 1392 {
 1393     int         rv;
 1394     Byte            scompbuf[sstatlen], *pcompbuf;
 1395     unsigned long       scomplen = sizeof scompbuf;
 1396     unsigned long       pcomplen = tstatlen * ntask;
 1397 
 1398     /*
 1399     ** compress system- and process-level statistics
 1400     */
 1401     rv = compress(scompbuf, &scomplen,
 1402                 (Byte *)sstat, (unsigned long)sstatlen);
 1403 
 1404     testcompval(rv, "compress");
 1405 
 1406     pcompbuf = malloc(pcomplen);
 1407 
 1408     ptrverify(pcompbuf, "Malloc failed for compression buffer\n");
 1409 
 1410     rv = compress(pcompbuf, &pcomplen, (Byte *)tstat,
 1411                         (unsigned long)pcomplen);
 1412 
 1413     testcompval(rv, "compress");
 1414 
 1415     rr->scomplen    = scomplen;
 1416     rr->pcomplen    = pcomplen;
 1417 
 1418     if ( write(ofd, rr, sizeof *rr) == -1)
 1419     {
 1420         perror("write raw record");
 1421         exit(7);
 1422     }
 1423 
 1424     /*
 1425     ** write compressed system status structure to file
 1426     */
 1427     if ( write(ofd, scompbuf, scomplen) == -1)
 1428     {
 1429         perror("write raw status record");
 1430         exit(7);
 1431     }
 1432 
 1433     /*
 1434     ** write compressed list of process status structures to file
 1435     */
 1436     if ( write(ofd, pcompbuf, pcomplen) == -1)
 1437     {
 1438         perror("write raw process record");
 1439         exit(7);
 1440     }
 1441 
 1442     free(pcompbuf);
 1443 }
 1444 
 1445 
 1446 //
 1447 // check success of (de)compression
 1448 //
 1449 static void
 1450 testcompval(int rv, char *func)
 1451 {
 1452     switch (rv)
 1453     {
 1454        case Z_OK:
 1455        case Z_STREAM_END:
 1456        case Z_NEED_DICT:
 1457         break;
 1458 
 1459        case Z_MEM_ERROR:
 1460         fprintf(stderr, "%s: failed due to lack of memory\n", func);
 1461         exit(7);
 1462 
 1463        case Z_BUF_ERROR:
 1464         fprintf(stderr, "%s: failed due to lack of room in buffer\n",
 1465                                 func);
 1466         exit(7);
 1467 
 1468        case Z_DATA_ERROR:
 1469         fprintf(stderr, 
 1470                 "%s: failed due to corrupted/incomplete data\n", func);
 1471         exit(7);
 1472 
 1473        default:
 1474         fprintf(stderr,
 1475                 "%s: unexpected error %d\n", func, rv);
 1476         exit(7);
 1477     }
 1478 }
 1479 
 1480 //
 1481 // generic pointer verification after malloc
 1482 //
 1483 void
 1484 ptrverify(const void *ptr, const char *errormsg, ...)
 1485 {
 1486         if (!ptr)
 1487         {
 1488                 va_list args;
 1489                 va_start(args, errormsg);
 1490                 vfprintf(stderr, errormsg, args);
 1491                 va_end  (args);
 1492 
 1493                 exit(13);
 1494         }
 1495 }