// // aegis - project change supervisor // Copyright (C) 2002-2006, 2008 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 // . // #include #include #include #include #include #include #include output_tar_child::~output_tar_child() { trace(("output_tar_child::~output_tar_child(this = %08lX)\n{\n", (long)this)); // // Make sure all buffered data has been passed to our write_inner // method. // flush(); // // It is a bug if the size changed. // if (pos != length) { changed_size(); } // // Pad the data so that we are a multiple of 512 bytes. // padding(); // // DO NOT delete deeper; // this is output_tar::destructor's job. // trace(("}\n")); } output_tar_child::output_tar_child(const output::pointer &arg1, const nstring &arg2, long arg3, bool arg4) : deeper(arg1), name(arg2), length(arg3), executable(arg4), pos(0), bol(true) { trace(("output_tar_child::output_tar_child(this = %08lX)\n{\n", (long)this)); // assert(length >= 0); trace(("deeper pos = %ld\n", deeper->ftell())); header(); trace(("}\n")); } output::pointer output_tar_child::create(const output::pointer &a_deeper, const nstring &a_name, long a_length, bool a_exec) { return pointer(new output_tar_child(a_deeper, a_name, a_length, a_exec)); } void output_tar_child::changed_size() { sub_context_ty sc; sc.var_set_format ( "File_Name", "%s(%s)", deeper->filename().c_str(), name.c_str() ); sc.fatal_intl(i18n("archive member $filename changed size")); } void output_tar_child::padding() { trace(("output_tar_child::padding(this = %08lX)\n{\n", (long)this)); int n = deeper->ftell(); trace(("n = %d\n", n)); for (;;) { if ((n & (TBLOCK - 1)) == 0) { trace(("deeper pos = %ld\n", deeper->ftell())); trace(("}\n")); return; } deeper->fputc('\n'); ++n; } } void output_tar_child::header() { trace(("output_tar_child::header(this = %08lX)\n{\n", (long)this)); char tblock[TBLOCK]; header_ty *hp = (header_ty *)tblock; nstring root("root"); // // Long names get special treatment. // if (name.length() >= sizeof(hp->name)) { memset(tblock, 0, sizeof(tblock)); strendcpy(hp->name, "././@LongLink", hp->name + sizeof(hp->name)); header_size_set(hp, name.length() + 1); header_mode_set(hp, 0); header_uid_set(hp, 0); header_uname_set(hp, root); header_gid_set(hp, 0); header_gname_set(hp, root); header_mtime_set(hp, 0); header_linkflag_set(hp, LF_LONGNAME); header_checksum_set(hp, header_checksum_calculate(hp)); deeper->write(tblock, TBLOCK); // // This write, and the length in the header, include the // terminating NUL on the end of the file name. // deeper->write(name.c_str(), name.length() + 1); trace(("deeper pos = %ld\n", deeper->ftell())); padding(); } memset(tblock, 0, sizeof(tblock)); header_name_set(hp, name); header_size_set(hp, length); header_mode_set(hp, 0100644 | (executable ? 0111 : 0)); header_uid_set(hp, 0); header_uname_set(hp, root); header_gid_set(hp, 0); header_gname_set(hp, root); header_mtime_set(hp, now()); header_linkflag_set(hp, LF_NORMAL); header_checksum_set(hp, header_checksum_calculate(hp)); deeper->write(tblock, TBLOCK); trace(("deeper pos = %ld\n", deeper->ftell())); trace(("}\n")); } nstring output_tar_child::filename() const { return deeper->filename(); } long output_tar_child::ftell_inner() const { return pos; } void output_tar_child::write_inner(const void *data, size_t len) { trace(("output_tar_child::write_inner(this = %08lX, data = %08lX, " "len = %ld)\n{\n", (long)this, (long)data, (long)len)); deeper->write(data, len); pos += len; if (len > 0) bol = (((const char *)data)[len - 1] == '\n'); trace(("deeper pos = %ld\n", deeper->ftell())); trace(("}\n")); } void output_tar_child::end_of_line_inner() { trace(("output_tar_child::end_of_line_inner(this = %08lX)\n{\n", (long)this)); if (!bol) fputc('\n'); trace(("deeper pos = %ld\n", deeper->ftell())); trace(("}\n")); } const char * output_tar_child::type_name() const { return "tar child"; }