Beispiel #1
0
 size_node_ptr size_tree_of(T& val, const char* friendly_name = "<TOP>")
 {
     detail::sizeof_visitor sizer(true);
     sizer(val, friendly_name);
     assert(sizer.size_tree()->children.size());
     return sizer.size_tree()->children[0];
 }
void Raw::sizer(Raw* src) {
	long long ix, iy,iz;

	ix = src->getXsize();
	iy = src->getYsize();
	iz = src->getZsize();
	sizer(ix,iy,iz);
}
Beispiel #3
0
int printBasicMachine(FILE *out, int indent, const char* tag,
                      const void* data) {
    /* purpose: format the machine information into the given stream as XML.
     * paramtr: out (IO): The stream
     *          indent (IN): indentation level
     *          tag (IN): name to use for element tags.
     *          data (IN): MachineBasicInfo info to print.
     */
    const MachineBasicInfo* ptr = (const MachineBasicInfo*) data;

    if (ptr) {
        char b[32];
        startBasicMachine(out, indent+2, tag, ptr);

#if defined(_SC_PHYS_PAGES) || defined(_SC_AVPHYS_PAGES)
        fprintf(out, "%*s<ram", indent, "");
#ifdef _SC_PHYS_PAGES
        fprintf(out, " total=\"%s\"",
                sizer(b, 32, sizeof(ptr->ram_total), &(ptr->ram_total)));
#endif /* _SC_PHYS_PAGES */
#ifdef _SC_AVPHYS_PAGES
        fprintf(out, " avail=\"%s\"",
                sizer(b, 32, sizeof(ptr->ram_avail), &(ptr->ram_avail)));
#endif /* _SC_AVPHYS_PAGES */
        fprintf(out, "/>\n");
#endif /* _SC_PHYS_PAGES || _SC_AVPHYS_PAGES */

#if defined(_SC_NPROCESSORS_CONF) || defined(_SC_NPROCESSORS_ONLN)
        fprintf(out, "%*s<cpu", indent, "");
#ifdef _SC_NPROCESSORS_CONF
        fprintf(out, " total=\"%s\"",
                sizer(b, 32, sizeof(ptr->cpu_total), &(ptr->cpu_total)));
#endif /* _SCN_PROCESSORS_CONF */
#ifdef _SC_NPROCESSORS_ONLN
        fprintf(out, " online=\"%s\"",
                sizer(b, 32, sizeof(ptr->cpu_online), &(ptr->cpu_online)));
#endif /* _SC_NPROCESSORS_ONLN */
        fprintf(out, "/>\n");
#endif /* _SC_NPROCESSORS_CONF || _SC_NPROCESSORS_ONLN */

        finalBasicMachine(out, indent+2, tag, ptr);
    }

    return 0;
}
Beispiel #4
0
int printXMLUseInfo(FILE *out, int indent, const char* id,
                    const struct rusage* use) {
    /* purpose: format the rusage record into the given stream as XML.
     * paramtr: out (IO): the stream
     *          indent (IN): indentation level
     *          id (IN): object identifier to use as element tag name.
     *          use (IN): struct rusage info
     * returns: number of characters put into buffer (buffer length)
     */
    char b[4][32];

    /* <usage> */
    fprintf(out, "%*s<%s utime=\"%.3f\" stime=\"%.3f\"", indent, "",
            id, doubletime(use->ru_utime), doubletime(use->ru_stime));

    fprintf(out, " maxrss=\"%lu\"", 
#ifdef DARWIN
            /* On Mac OS X this is in bytes */
            use->ru_maxrss / 1024
#else
            /* On linux it is in KB */
            use->ru_maxrss
#endif
    );

    fprintf(out, " minflt=\"%s\" majflt=\"%s\" nswap=\"%s\"",
            sizer(b[0], 32, sizeof(use->ru_minflt), &(use->ru_minflt)),
            sizer(b[1], 32, sizeof(use->ru_majflt), &(use->ru_majflt)),
            sizer(b[2], 32, sizeof(use->ru_nswap), &(use->ru_nswap)));

    fprintf(out, " inblock=\"%s\" outblock=\"%s\"",
            sizer(b[0], 32, sizeof(use->ru_inblock), &(use->ru_inblock)),
            sizer(b[1], 32, sizeof(use->ru_oublock), &(use->ru_oublock)));

    fprintf(out, " msgsnd=\"%s\" msgrcv=\"%s\"",
            sizer(b[2], 32, sizeof(use->ru_msgsnd), &(use->ru_msgsnd)),
            sizer(b[3], 32, sizeof(use->ru_msgrcv), &(use->ru_msgrcv)));

    fprintf(out, " nsignals=\"%s\" nvcsw=\"%s\" nivcsw=\"%s\"/>\n",
            sizer(b[0], 32, sizeof(use->ru_nsignals), &(use->ru_nsignals)),
            sizer(b[1], 32, sizeof(use->ru_nvcsw), &(use->ru_nvcsw)),
            sizer(b[2], 32, sizeof(use->ru_nivcsw), &(use->ru_nivcsw)));

    return 0;
}
Beispiel #5
0
void factor_vm::fixup_data(cell data_offset, cell code_offset)
{
	slot_visitor<data_fixupper> data_workhorse(this,data_fixupper(data_offset));
	data_workhorse.visit_roots();

	object_fixupper fixupper(this,data_offset,code_offset);
	fixup_sizer sizer(data_offset);
	data->tenured->iterate(fixupper,sizer);
}
// ---------------------------------------------------------------------------
// CMMCScBkupStateRequestListOfPublicFiles::PerformLastRightsL()
// 
// 
// ---------------------------------------------------------------------------
void CMMCScBkupStateRequestListOfPublicFiles::PerformLastRightsL()
    {
    // Now we can calculate the progress        
    TInt64 totalProgressAmount = 0;

    // Calculate the total progress required for the entire backup operation
    CMMCScBkupDataOwnerCollection& dataOwners = Driver().DrvDataOwners();
    const TInt count = dataOwners.Count();
    //
    RMMCScBkupProgressSizer sizer( Driver().DrvParamsBase().DriveAndOperations() );
    for(TInt i=0; i<count; i++)
        {
        CMMCScBkupDataOwnerInfo& owner = dataOwners.Owner( i );
        //
        totalProgressAmount += sizer.BackupTotalProgressValueL( owner );
        }

    // Check whether all categories have been processed and either store current 
    // progress information in driver or inform progress handler about cumulative progress.
    // If size is getting beyond file system limitation (2GB), leave with KErrxxx.
    if(Driver().DrvLastCategory())
        {
        __LOG2("CMMCScBkupStateRequestListOfPublicFiles::PerformLastRightsL() - report progress understood (%Ld + %Ld)", 
            totalProgressAmount, Driver().DrvTotalProgress());
        
        Driver().DrvStoreTotalProgress( totalProgressAmount );

        if( Driver().DrvTotalProgress() > KMaxTInt )
            {
            __LOG1("CMMCScBkupStateRequestListOfPublicFiles::PerformLastRightsL() - leaving with KErrNotSupported due amount of data (%Ld)", 
                Driver().DrvTotalProgress());
            Driver().DrvProgressHandler().MMCScBkupStartBackuping( EFalse );
            User::Leave( KErrNotSupported );
            }
        else
            {
            Driver().DrvProgressHandler().MMCScBkupHandleProgressDomainUnderstood( Driver().DrvTotalProgress() );
            }
        }
    else
        {
        __LOG2("CMMCScBkupStateRequestListOfPublicFiles::PerformLastRightsL() - adding progress amount %Ld to existing %Ld)", 
            totalProgressAmount, Driver().DrvTotalProgress());
            
        if( (totalProgressAmount + Driver().DrvTotalProgress()) > KMaxTInt )
            {
            __LOG1("CMMCScBkupStateRequestListOfPublicFiles::PerformLastRightsL() - leaving due amount of data (%Ld)", 
                totalProgressAmount + Driver().DrvTotalProgress());
            User::Leave(KErrNotSupported);
            }
        else
            {
            Driver().DrvStoreTotalProgress( totalProgressAmount );
            }
        }
    }
void RawArray::wipecopy(RawArray& src) {
	long long k,kmax;

	if(&src==NULL)return;
	if(src.rawNum==0) return;		// ignore empty inputs.
	if(src.getrawNum()!=rawNum || src.getZsize() != z[0].getZsize() || src.getYsize() != z[0].getYsize() ||
		src.getXsize() != getXsize()) {
			sizer(&src);
	}
	kmax = getrawNum();
	for(k=0; k< kmax; k++) {		// copy each field;
		z[k].wipecopy(&(src.z[k]));
	}
}
long long Raw::wipecopy(Raw* src) {
	long long out=1;
	long long i,imax;	

	if(getYsize() != src->getYsize() || getXsize()!=src->getXsize()) { // resize to fit 'src'.
		sizer(src);
		out=0;
	}
	imax = getXsize()*getYsize();
	for(i=0; i<imax; i++) {
		putXYZ(i,src->getXYZ(i));
	}

	return(out);
}
Beispiel #9
0
bool DoLRSizingIfRequired(HDPGrid& grid, const char* cfgOptName)
{
    if (grid.Design().cfg.ValueOf(cfgOptName, false))
    {
        //DetailedPlacement(grid);

        WRITELINE("LRSizing started");
        //if (grid.Design().CanDoTiming()) ALERT("STA after detailed placement:");
        //STA(grid.Design());
        //LambdaMatrix lm (grid,grid.Design());
        LRSizer sizer(grid.Design());

        sizer.DoLRSizing();
        WRITELINE("LRSizing finished");
        return true;
    }
    return false;
}
Beispiel #10
0
//---------------------------------------------------------------------------------------
void TableRowLayouter::layout_in_box()
{
    LOMSE_LOG_DEBUG(Logger::k_layout, string(""));

    set_cursor_and_available_space();
    LUnits yPos = m_pageCursor.y;

    //loop to layout the cells in this rows group range
    vector<LUnits> cellHeights;
    cellHeights.assign(m_cellLayouters.size(), 0.0f);

    int iRow = m_iFirstRow;
    for (int i=0; i < m_numRows; ++i, ++iRow)
    {
        LUnits xPos = m_pItemMainBox->get_content_left();
        for (int iCol=0; iCol < m_numColumns; ++iCol)
        {
            int iCell = iRow * m_numColumns + iCol;
            if (m_cellLayouters[iCell] != nullptr)
            {
                LUnits height = layout_cell(m_cellLayouters[iCell], m_pItemMainBox,
                                            UPoint(xPos, m_pageCursor.y));
                cellHeights[iCell] = height;
            }
            xPos += m_columnsWidth[iCol];
        }
    }

    //set height and final position of cells
    TableCellSizer sizer(m_cellLayouters, cellHeights, m_iFirstRow,
                         m_numRows, m_numColumns);
    sizer.assign_height_and_reposition_cells();
    yPos += sizer.get_total_height();

    //update cursor and available space
    LUnits height = yPos - m_pageCursor.y;
    m_pageCursor.y = yPos;
    m_availableHeight -= height;

    set_layout_is_finished(true);
}
Beispiel #11
0
int printLinuxInfo(FILE *out, int indent, const MachineLinuxInfo *ptr) {
    static const char* state_names[MAX_STATE] = {
        "running",
        "sleeping",
        "waiting",
        "stopped",
        "zombie",
        "other"
    };

    char b[4][32];

    /* <ram .../> tag */
    fprintf(out, "%*s<ram total=\"%s\" free=\"%s\" shared=\"%s\" buffer=\"%s\"/>\n",
            indent, "",
            sizer(b[0], 32, sizeof(ptr->ram_total), &(ptr->ram_total)),
            sizer(b[1], 32, sizeof(ptr->ram_free), &(ptr->ram_free)),
            sizer(b[2], 32, sizeof(ptr->ram_total), &(ptr->ram_shared)),
            sizer(b[3], 32, sizeof(ptr->ram_free), &(ptr->ram_buffer)));

    /* <swap .../> tag */
    fprintf(out, "%*s<swap total=\"%s\" free=\"%s\"/>\n", indent, "",
            sizer(b[0], 32, sizeof(ptr->swap_total), &(ptr->swap_total)),
            sizer(b[1], 32, sizeof(ptr->swap_free), &(ptr->swap_free)));

    /* <boot> element */
    fprintf(out, "%*s<boot idle=\"%.3f\">%s</boot>\n", indent, "",
            ptr->idletime,
            fmtisodate(ptr->boottime.tv_sec, ptr->boottime.tv_usec));

    /* <cpu> element */
    fprintf(out, "%*s<cpu count=\"%hu\" speed=\"%lu\" vendor=\"%s\">%s</cpu>\n",
            indent, "", ptr->cpu_count, ptr->megahertz, ptr->vendor_id,
            ptr->model_name);

    /* <load> element */
    fprintf(out, "%*s<load min1=\"%.2f\" min5=\"%.2f\" min15=\"%.2f\"/>\n",
            indent, "", ptr->load[0], ptr->load[1], ptr->load[2]);

    if (ptr->procs.total && ptr->tasks.total) {
        /* <procs> element */
        fprintf(out, "%*s<procs total=\"%u\"", indent, "", ptr->procs.total);
        for (LinuxState s=S_RUNNING; s<=S_OTHER; ++s) {
            if (ptr->procs.state[s]) {
                fprintf(out, " %s=\"%hu\"", state_names[s], ptr->procs.state[s]);
            }
        }
        fprintf(out, " vmsize=\"%s\" rss=\"%s\"/>\n",
                sizer(b[0], 32, sizeof(ptr->procs.size), &ptr->procs.size),
                sizer(b[1], 32, sizeof(ptr->procs.rss), &ptr->procs.rss));

        /* <task> element */
        fprintf(out, "%*s<task total=\"%u\"", indent, "", ptr->tasks.total);
        for (LinuxState s=S_RUNNING; s<=S_OTHER; ++s) {
            if (ptr->tasks.state[s]) {
                fprintf(out, " %s=\"%hu\"", state_names[s], ptr->tasks.state[s]);
            }
        }

        /* vmsize and rss do not make sense for threads b/c they share memory */

        fprintf(out, "/>\n");
    }

    return 0;
}
Beispiel #12
0
 size_t size_of(T& val)
 {
     detail::sizeof_visitor sizer;
     sizer(val, "");
     return sizer.size();
 }
Beispiel #13
0
size_t printXMLStatInfo(FILE *out, int indent, const char* tag, const char* id,
                        const StatInfo* info, int includeData, int useCDATA) {
    char *real = NULL;

    /* sanity check */
    if (info->source == IS_INVALID) {
        return 0;
    }

    /* start main tag */
    fprintf(out, "%*s<%s error=\"%d\"", indent, "", tag, info->error);
    if (id != NULL) {
        fprintf(out, " id=\"%s\"", id);
    }
    if (info->lfn != NULL) {
        fprintf(out, " lfn=\"%s\"", info->lfn);
    }
    fprintf(out, ">\n");

    /* NEW: ignore "file not found" error for "kickstart" */
    if (id != NULL && info->error == 2 && strcmp(id, "kickstart") == 0) {
        fprintf(out, "%*s<!-- ignore above error -->\n", indent+2, "");
    }

    /* either a <name> or <descriptor> sub element */
    switch (info->source) {
        case IS_TEMP:   /* preparation for <temporary> element */
            /* late update for temp files */
            errno = 0;
            if (fstat(info->file.descriptor, (struct stat*) &info->info) != -1 &&
                (((StatInfo*) info)->error = errno) == 0) {

                /* obtain header of file */
                int fd = dup(info->file.descriptor);
                if (fd != -1) {
                    if (lseek(fd, 0, SEEK_SET) != -1) {
                        read(fd, (char*) info->client.header, sizeof(info->client.header));
                    }
                    close(fd);
                }
            }

            fprintf(out, "%*s<temporary name=\"%s\" descriptor=\"%d\"/>\n",
                    indent+2, "", info->file.name, info->file.descriptor);
            break;

        case IS_FIFO: /* <fifo> element */
            fprintf(out, "%*s<fifo name=\"%s\" descriptor=\"%d\" count=\"%zu\" rsize=\"%zu\" wsize=\"%zu\"/>\n",
                    indent+2, "", info->file.name, info->file.descriptor,
                    info->client.fifo.count, info->client.fifo.rsize,
                    info->client.fifo.wsize);
            break;

        case IS_FILE: /* <file> element */
            real = realpath(info->file.name, NULL);
            fprintf(out, "%*s<file name=\"%s\"", indent+2, "", real ? real : info->file.name);
            if (real) {
                free((void*) real);
            }

            if (info->error == 0 &&
                S_ISREG(info->info.st_mode) &&
                info->info.st_size > 0) {

                /* optional hex information */
                size_t i, end = sizeof(info->client.header);
                if (info->info.st_size < end) end = info->info.st_size;

                fprintf(out, ">");
                for (i=0; i<end; ++i) {
                    fprintf(out, "%02X", info->client.header[i]);
                }
                fprintf(out, "</file>\n");
            } else {
                fprintf(out, "/>\n");
            }
            break;

        case IS_HANDLE: /* <descriptor> element */
            fprintf(out, "%*s<descriptor number=\"%u\"/>\n", indent+2, "",
                    info->file.descriptor);
            break;

        default: /* this must not happen! */
            fprintf(out, "%*s<!-- ERROR: No valid file info available -->\n",
                    indent+2, "");
            break;
    }

    if (info->error == 0 && info->source != IS_INVALID) {
        /* <stat> subrecord */
        char my[32];
        struct passwd* user = getpwuid(info->info.st_uid);
        struct group* group = getgrgid(info->info.st_gid);

        fprintf(out, "%*s<statinfo mode=\"0%o\"", indent+2, "",
                info->info.st_mode);

        /* Grmblftz, are we in 32bit, 64bit LFS on 32bit, or 64bit on 64 */
        sizer(my, sizeof(my), sizeof(info->info.st_size), &info->info.st_size);
        fprintf(out, " size=\"%s\"", my);

        sizer(my, sizeof(my), sizeof(info->info.st_ino), &info->info.st_ino);
        fprintf(out, " inode=\"%s\"", my);

        sizer(my, sizeof(my), sizeof(info->info.st_nlink), &info->info.st_nlink);
        fprintf(out, " nlink=\"%s\"", my);

        sizer(my, sizeof(my), sizeof(info->info.st_blksize), &info->info.st_blksize);
        fprintf(out, " blksize=\"%s\"", my);

        /* st_blocks is new in iv-1.8 */
        sizer(my, sizeof(my), sizeof(info->info.st_blocks), &info->info.st_blocks);
        fprintf(out, " blocks=\"%s\"", my);

        fprintf(out, " mtime=\"%s\"", fmtisodate(info->info.st_mtime, -1));
        fprintf(out, " atime=\"%s\"", fmtisodate(info->info.st_atime, -1));
        fprintf(out, " ctime=\"%s\"", fmtisodate(info->info.st_ctime, -1));

        fprintf(out, " uid=\"%d\"", info->info.st_uid);
        if (user) {
            fprintf(out, " user=\"%s\"", user->pw_name);
        }
        fprintf(out, " gid=\"%d\"", info->info.st_gid);
        if (group) {
            fprintf(out, " group=\"%s\"", group->gr_name);
        }

        fprintf(out, "/>\n");
    }

    /* data section from stdout and stderr of application */
    if (includeData &&
        info->source == IS_TEMP &&
        info->error == 0 &&
        info->info.st_size && data_section_size > 0) {

        size_t dsize = data_section_size;
        size_t fsize = info->info.st_size;
        fprintf(out, "%*s<data%s", indent+2, "",
                (fsize > dsize ? " truncated=\"true\"" : ""));
        if (fsize > 0) {
            char buf [BUFSIZ];
            int fd = dup(info->file.descriptor);

            fprintf(out, ">");
            if (fd != -1) {

                if (useCDATA) {
                    fprintf(out, "<![CDATA[");
                }

                /* Get the last dsize bytes of the file */
                size_t offset = 0;
                if (fsize > dsize) {
                    offset = fsize - dsize;
                }
                if (lseek(fd, offset, SEEK_SET) != -1) {
                    ssize_t total = 0;
                    while (total < dsize) {
                        ssize_t rsize = read(fd, buf, BUFSIZ);
                        if (rsize == 0) {
                            break;
                        } else if (rsize < 0) {
                            printerr("ERROR reading %s: %s",
                                    info->file.name, strerror(errno));
                            break;
                        }
                        if (useCDATA) {
                            fwrite(buf, rsize, 1, out);
                        } else {
                            xmlquote(out, buf, rsize);
                        }
                        total += rsize;
                    }
                }
                close(fd);

                if (useCDATA) {
                    fprintf(out, "]]>");
                }
            }

            fprintf(out, "</data>\n");
        } else {
            fprintf(out, "/>\n");
        }
    }

    fprintf(out, "%*s</%s>\n", indent, "", tag);

    return 0;
}
Beispiel #14
0
size_t
printXMLStatInfo(FILE *out, int indent, const char* tag, const char* id,
                 const StatInfo* info)
/* purpose: XML format a stat info record into a given stream
 * paramtr: out (IO): the stream
 *          tag (IN): name of element to generate
 *          id (IN): id attribute, use NULL to not generate
 *          info (IN): stat info to print.
 * returns: number of characters put into buffer (buffer length)
 */
{
  char* real = NULL;

  /* sanity check */
  if (info->source == IS_INVALID) return 0;

  /* start main tag */
  fprintf(out, "%*s<%s error=\"%d\"", indent, "", tag, info->error);
  if (id != NULL) fprintf(out, " id=\"%s\"", id);
  if (info->lfn != NULL) fprintf(out, " lfn=\"%s\"", info->lfn);
  fprintf(out, ">\n");

  /* NEW: ignore "file not found" error for "gridstart" */
  if (id != NULL && info->error == 2 && strcmp(id, "gridstart") == 0)
    fprintf(out, "%*s<!-- ignore above error -->\n", indent+2, "");

  /* either a <name> or <descriptor> sub element */
  switch (info->source) {
  case IS_TEMP:   /* preparation for <temporary> element */
    /* late update for temp files */
    errno = 0;
    if (fstat(info->file.descriptor, (struct stat*) &info->info) != -1 &&
         (((StatInfo*) info)->error = errno) == 0) {
      /* obtain header of file */

#if 0
      /* implementation alternative 1: use a new filetable kernel structure */
      int fd = open(info->file.name, O_RDONLY);
      if (fd != -1) {
        read(fd, (char*) info->client.header, sizeof(info->client.header));
        close(fd);
      }
#else
      /* implementation alternative 2: share the kernel filetable structure */
      int fd = dup(info->file.descriptor);
      if (fd != -1) {
        if (lseek(fd, 0, SEEK_SET) != -1)
          read(fd, (char*) info->client.header, sizeof(info->client.header));
        close(fd);
      }
#endif
    }

    fprintf(out, "%*s<temporary name=\"%s\" descriptor=\"%d\"/>\n",
            indent+2, "", info->file.name, info->file.descriptor);
    break;

  case IS_FIFO: /* <fifo> element */
    fprintf(out, "%*s<fifo name=\"%s\" descriptor=\"%d\" count=\"%zu\" rsize=\"%zu\" wsize=\"%zu\"/>\n",
            indent+2, "", info->file.name, info->file.descriptor,
            info->client.fifo.count, info->client.fifo.rsize, 
            info->client.fifo.wsize);
    break;

  case IS_FILE: /* <file> element */
#if 0
    /* some debug info - for now */
    fprintf(out, "%*s<!-- deferred flag: %d -->\n",
            indent+2, "", info->deferred);
#endif

#ifdef HAS_REALPATH_EXT
    real = realpath(info->file.name, NULL); 
#endif /* HAS_REALPATH_EXT */
    fprintf(out, "%*s<file name=\"%s\"", indent+2, "",
            real ? real : info->file.name);
#ifdef HAS_REALPATH_EXT
    if (real) free((void*) real);
#endif /* HAS_REALPATH_EXT */

    if (info->error == 0 && S_ISREG(info->info.st_mode) &&
        info->info.st_size > 0) {
      /* optional hex information */
      size_t i, end = sizeof(info->client.header);
      if (info->info.st_size < end) end = info->info.st_size;

      fprintf(out, ">");
      for (i=0; i<end; ++i)
        fprintf(out, "%02X", info->client.header[i]);
      fprintf(out, "</file>\n");
    } else {
      fprintf(out, "/>\n");
    }
    break;

  case IS_HANDLE: /* <descriptor> element */
    fprintf(out, "%*s<descriptor number=\"%u\"/>\n", indent+2, "",
            info->file.descriptor);
    break;

  default: /* this must not happen! */
    fprintf(out, "%*s<!-- ERROR: No valid file info available -->\n",
            indent+2, "");
    break;
  }

  if (info->error == 0 && info->source != IS_INVALID) {
    /* <stat> subrecord */
    char my[32];
    struct passwd* user = wrap_getpwuid(info->info.st_uid);
    struct group* group = wrap_getgrgid(info->info.st_gid);

    fprintf(out, "%*s<statinfo mode=\"0%o\"", indent+2, "",
            info->info.st_mode);

    /* Grmblftz, are we in 32bit, 64bit LFS on 32bit, or 64bit on 64 */
    sizer(my, sizeof(my), sizeof(info->info.st_size), &info->info.st_size);
    fprintf(out, " size=\"%s\"", my);

    sizer(my, sizeof(my), sizeof(info->info.st_ino), &info->info.st_ino);
    fprintf(out, " inode=\"%s\"", my);

    sizer(my, sizeof(my), sizeof(info->info.st_nlink), &info->info.st_nlink);
    fprintf(out, " nlink=\"%s\"", my);

    sizer(my, sizeof(my), sizeof(info->info.st_blksize), &info->info.st_blksize);
    fprintf(out, " blksize=\"%s\"", my);

    /* st_blocks is new in iv-1.8 */
    sizer(my, sizeof(my), sizeof(info->info.st_blocks), &info->info.st_blocks);
    fprintf(out, " blocks=\"%s\"", my);

    fprintf(out, " mtime=\"%s\"",
            fmtisodate(isLocal, isExtended, info->info.st_mtime, -1));
    fprintf(out, " atime=\"%s\"",
            fmtisodate(isLocal, isExtended, info->info.st_atime, -1));
    fprintf(out, " ctime=\"%s\"",
            fmtisodate(isLocal, isExtended, info->info.st_ctime, -1));

    fprintf(out, " uid=\"%d\"", info->info.st_uid);
    if (user) fprintf(out, " user=\"%s\"", user->pw_name);
    fprintf(out, " gid=\"%d\"", info->info.st_gid);
    if (group) fprintf(out, " group=\"%s\"", group->gr_name);

    fprintf(out, "/>\n");
  }

  /* data section from stdout and stderr of application */
  if (info->source == IS_TEMP && info->error == 0 && info->info.st_size &&
      data_section_size > 0) {
    size_t dsize = data_section_size;
    size_t fsize = info->info.st_size;
    fprintf(out, "%*s<data%s", indent+2, "",
            (fsize > dsize ? " truncated=\"true\"" : ""));
    if (fsize > 0) {
      char* data = (char*) malloc(dsize+1);
      int fd = dup(info->file.descriptor);

      fprintf(out, ">");
      if (fd != -1) {
        /* Get the last dsize bytes of the file */
        size_t offset = 0;
        if (fsize > dsize) {
          offset = fsize - dsize;
        }
        if (lseek(fd, offset, SEEK_SET) != -1) {
          ssize_t rsize = read(fd, data, dsize);
          xmlquote(out, data, rsize);
        }
        close(fd);
      }

      fprintf(out, "</data>\n");
      free((void*) data);
    } else {
      fprintf(out, "/>\n");
    }
  }

  fprintf(out, "%*s</%s>\n", indent, "", tag);

  return 0;
}