//
// aegis - project change supervisor
// Copyright (C) 1999, 2002-2006, 2008 Peter Miller
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see
// .
//
#include
#include
#include
output_cpio_child::~output_cpio_child()
{
//
// Make sure all buffered data has been passed to our write_inner
// method.
//
flush();
//
// It is a fatal error if they got the length wrong.
//
if (pos != length)
changed_size();
//
// Add padding to brings us up to the correct multiple of bytes.
//
padding();
//
// DO NOT delete deeper;
// this is output_cpio::destructor's job.
//
}
output_cpio_child::output_cpio_child(const output::pointer &a_deeper,
const nstring &a_name, long a_length, time_t a_mtime) :
deeper(a_deeper),
name(a_name),
length(a_length),
pos(0),
bol(true),
mtime(a_mtime)
{
assert(length >= 0);
header();
}
output::pointer
output_cpio_child::create(const output::pointer &a_deeper,
const nstring &a_name, long a_length, time_t a_mtime)
{
return pointer(new output_cpio_child(a_deeper, a_name, a_length, a_mtime));
}
void
output_cpio_child::changed_size()
{
sub_context_ty sc;
sc.var_set_format
(
"File_Name",
"%s(%s)",
deeper->filename().c_str(),
name.c_str()
);
sc.fatal_intl(i18n("archive member $filename changed size"));
}
void
output_cpio_child::padding()
{
long n = deeper->ftell();
assert(n >= 0);
for (;;)
{
if ((n & 3) == 0)
break;
deeper->fputc('\n');
++n;
}
}
void
output_cpio_child::hex8(long n)
{
deeper->fprintf("%8.8lx", n);
}
void
output_cpio_child::header()
{
static int ino;
int inode = ++ino;
if (name == "TRAILER!!!")
inode = 0;
deeper->fputs("070701"); // magic number
hex8(inode); // inode
hex8(0100644); // mode
hex8(0); // uid
hex8(0); // gid
hex8(1); // nlinks
hex8(mtime); // mtime
hex8(length); // size
hex8(0); // dev_major
hex8(0); // dev_minor
hex8(0); // rdev_major
hex8(0); // rdev_minor
hex8(name.length() + 1);
hex8(0); // no checksum
deeper->write(name.c_str(), name.length() + 1);
padding();
}
nstring
output_cpio_child::filename()
const
{
return deeper->filename();
}
long
output_cpio_child::ftell_inner()
const
{
return pos;
}
void
output_cpio_child::write_inner(const void *data, size_t len)
{
deeper->write(data, len);
pos += len;
if (len > 0)
bol = (((const char *)data)[len - 1] == '\n');
}
void
output_cpio_child::end_of_line_inner()
{
if (!bol)
fputc('\n');
}
const char *
output_cpio_child::type_name()
const
{
return "cpio child";
}