//
// tardy - a tar post-processor
// Copyright (C) 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/input/cpio.h>


tar_input_cpio::~tar_input_cpio()
{
}


tar_input_cpio::tar_input_cpio(
    const file_input::pointer &a_ifp,
    int a_padding
) :
    ifp(a_ifp),
    padding(a_padding >= 2 ? a_padding : 0)
{
    assert(ifp);
}


rcstring
tar_input_cpio::filename(void)
    const
{
    return ifp->filename();
}


format_family_t
tar_input_cpio::get_format_family(void)
    const
{
    return format_family_cpio;
}


int
tar_input_cpio::read_data(void *data, int data_size)
{
    return read_deeper(data, data_size);
}


void
tar_input_cpio::read_header_padding(void)
{
    read_padding();
}


void
tar_input_cpio::read_data_padding(void)
{
    read_padding();
}


void
tar_input_cpio::read_padding(void)
{
    if (padding <= 0)
        return;
    unsigned n = ifp->get_position() % padding;
    if (!n)
        return;
    ifp->skip(padding - n);
}


rcstring
tar_input_cpio::read_name(unsigned namsiz)
{
    if (namsiz < 2)
        fatal("invalid name size field (%d)", namsiz);
    static size_t name_buf_max = 0;
    static char *name_buf = 0;
    if (namsiz > name_buf_max)
    {
        delete [] name_buf;
        name_buf_max = name_buf_max * 2 + 32;
        name_buf = new char [name_buf_max];
    }
    unsigned nbytes = read_deeper(name_buf, namsiz);
    if (nbytes != namsiz)
        fatal("short header name read (expected %d, read %d)", namsiz, nbytes);
    if (name_buf[namsiz - 1] != '\0' || memchr(name_buf, '\0', namsiz - 1))
        fatal("badly formatted name");
    return rcstring(name_buf, namsiz - 1);
}


bool
tar_input_cpio::is_end(const tar_header &hdr)
{
    return (hdr.inode_number == 0 && hdr.name == "TRAILER!!!");
}


size_t
tar_input_cpio::read_deeper(void *data, size_t data_size)
{
    return ifp->read(data, data_size);
}
