//
// 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/ctype.h>

#include <libtardy/rcstring/accumulator.h>
#include <libtardy/tar/input/filter/ar_long_names2.h>


tar_input_filter_ar_long_names2::~tar_input_filter_ar_long_names2()
{
}


tar_input_filter_ar_long_names2::tar_input_filter_ar_long_names2(
    const pointer &a_deeper
) :
    tar_input_filter(a_deeper),
    do_header_padding(true)
{
}


tar_input_filter_ar_long_names2::pointer
tar_input_filter_ar_long_names2::create(const pointer &a_deeper)
{
    return pointer(new tar_input_filter_ar_long_names2(a_deeper));
}


static bool
special_file_name(const rcstring &name, int &namlen)
{
    const char *cp = name.c_str();
    if (*cp++ != '#')
        return false;
    if (*cp++ != '1')
        return false;
    if (*cp++ != '/')
        return false;
    namlen = 0;
    for (;;)
    {
        unsigned char c = *cp;
        if (!isdigit(c))
            return false;
        namlen = namlen * 10 + c - '0';
        ++cp;
        if (!*cp)
            return true;
    }
}


bool
tar_input_filter_ar_long_names2::read_header(tar_header &hdr)
{
    do_header_padding = true;
    if (!tar_input_filter::read_header(hdr))
        return false;
    int namlen = 0;
    if (!special_file_name(hdr.name, namlen))
        return true;
    do_header_padding = false;
    tar_input_filter::read_header_padding();
    if (namlen > hdr.size)
        fatal("member %s data size too short", hdr.name.quote_c().c_str());

    char *buf = new char [namlen];
    int nbytes = tar_input_filter::read_data(buf, namlen);
    if (nbytes != namlen)
        fatal("short data read (expected %d, got %d)", namlen, nbytes);

    // adjust the header, now that we have the name.
    hdr.name = rcstring(buf, namlen);
    delete [] buf;
    hdr.size -= namlen;
    return true;
}


void
tar_input_filter_ar_long_names2::read_header_padding(void)
{
    if (do_header_padding)
        tar_input_filter::read_header_padding();
    else
        do_header_padding = true;
}


size_t
tar_input_filter_ar_long_names2::get_maximum_name_length(void)
    const
{
    return 0;
}
