//
// tardy - a tar post-processor
// Copyright (C) 1998, 1999, 2003, 2008, 2009, 2011 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 <http://www.gnu.org/licenses/>.
//

#include <libtardy/ac/string.h>

#include <libtardy/tar/output/cpio.h>


tar_output_cpio::~tar_output_cpio()
{
}


tar_output_cpio::tar_output_cpio(
    const file_output::pointer &a_fp,
    int a_padding
) :
    fp(a_fp),
    padding(a_padding),
    pos(0)
{
}


void
tar_output_cpio::write_header_padding(void)
{
    write_padding();
}


void
tar_output_cpio::write_data(const void *data, int data_size)
{
    write_deeper(data, data_size);
}


void
tar_output_cpio::write_data_padding(void)
{
    write_padding();
}


void
tar_output_cpio::write_padding(void)
{
    if (padding <= 0)
        return;
    unsigned n = pos % padding;
    if (!n)
        return;

    //
    // This serves all class instances, even though the chances
    // of more than one are unlikely.  Each instance could
    // have a different padding multiple.
    //
    static char *dummy;
    static size_t dummy_size;
    if (dummy_size < padding)
    {
        delete [] dummy;
        dummy_size = 16;
        while (dummy_size < padding)
            dummy_size <<= 1;
        dummy = new char [dummy_size];
        memset(dummy, 0, dummy_size);
    }
    write_deeper(dummy, padding - n);
}


void
tar_output_cpio::write_deeper(const void *data, size_t data_size)
{
    fp->write(data, data_size);
    pos += data_size;
}


void
tar_output_cpio::write_archive_end(void)
{
    tar_header h;
    h.name = "TRAILER!!!";
    h.inode_number = 0;
    write_header(h);
    write_header_padding();
    write_data_padding();
}


rcstring
tar_output_cpio::filename(void)
    const
{
    return fp->filename();
}
