//
// 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/sys/param.h>
#include <libtardy/ac/sys/stat.h>
#include <libexplain/lstat.h>

#include <libtardy/filenamelist/file.h>
#include <libtardy/read_whole_directory.h>
#include <libtardy/tar/input/directory.h>
#include <libtardy/tar/input/filename.h>


tar_input_directory::~tar_input_directory()
{
}


tar_input_directory::tar_input_directory(const filenamelist::pointer &a_fnl) :
    fnl(a_fnl)
{
}


tar_input::pointer
tar_input_directory::create(const file_input::pointer &ifp)
{
    filenamelist::pointer names = filenamelist_file::create(ifp);
    return pointer(new tar_input_directory(names));
}


bool
tar_input_directory::read_header(tar_header &hdr)
{
    if (current)
        current.reset();
    if (queue.empty())
    {
        rcstring line;
        if (!fnl->read_one_line(line))
            return false;
        queue.push_back(line);
    }

    rcstring path = queue.front();
    queue.pop_front();

    struct stat st;
    explain_lstat_or_die(path.c_str(), &st);
    if (S_ISDIR(st.st_mode))
    {
        rcstring_list names;
        read_whole_directory(path, names);
        names.sort();
        while (!names.empty())
        {
            rcstring fn = names.back();
            names.pop_back();
            queue.push_front(path + "/" + fn);
        }
    }

    current = tar_input_filename::create(path);
    return current->read_header(hdr);
}


void
tar_input_directory::read_header_padding(void)
{
    if (current)
        current->read_header_padding();
}


int
tar_input_directory::read_data(void *buffer, int buflen)
{
    if (!current)
        return 0;
    return current->read_data(buffer, buflen);
}


void
tar_input_directory::read_data_padding(void)
{
    if (current)
    {
        current->read_data_padding();
        current.reset();
    }
}


rcstring
tar_input_directory::filename(void)
    const
{
    return fnl->filename();
}


const char *
tar_input_directory::get_format_name(void)
    const
{
    return "recursive-list";
}


format_family_t
tar_input_directory::get_format_family(void)
    const
{
    return format_family_other;
}


size_t
tar_input_directory::get_maximum_name_length(void)
    const
{
    return PATH_MAX;
}
