//
// tardy - a tar post-processor
// Copyright (C) 1998, 1999, 2002, 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/sys/stat.h>
#include <libexplain/close.h>
#include <libexplain/fstat.h>
#include <libexplain/lseek.h>
#include <libexplain/open.h>
#include <libexplain/read.h>

#include <libtardy/ac/unistd.h>
#include <libtardy/ac/fcntl.h>
#include <libtardy/file/input/normal.h>
#include <libtardy/file/input/position.h>


file_input_normal::~file_input_normal()
{
    if (fd >= 0)
        explain_close_or_die(fd);
}


file_input_normal::file_input_normal(const rcstring &a_fn) :
    fn(a_fn),
    fd(-1)
{
    fd = explain_open_or_die(fn.c_str(), O_RDONLY, 0);
}


file_input::pointer
file_input_normal::create(const rcstring &a_fn)
{
    typedef boost::shared_ptr<file_input_normal> ptr;

    ptr p = ptr(new file_input_normal(a_fn));
    if (p->needs_position_filter())
        return file_input_position::create(p);
    return p;
}


bool
file_input_normal::needs_position_filter(void)
    const
{
    struct stat st;
    explain_fstat_or_die(fd, &st);
    return !S_ISREG(st.st_mode);
}


int
file_input_normal::read_inner(void *data, size_t data_size)
{
    return explain_read_or_die(fd, data, data_size);
}


rcstring
file_input_normal::filename(void)
    const
{
    return fn;
}


unsigned long
file_input_normal::get_position_inner(void)
    const
{
    // This is why we sometimes need the position filter: pipes report
    // an EINVAL error for this system call.
    return explain_lseek_or_die(fd, 0, SEEK_CUR);
}
