1717 */
1818
1919#include " Tar.h"
20+ #include " Utils.h"
2021
2122#include < array>
22- #include < sstream >
23+ #include < cstring >
2324
24- std::vector<std::string>
25- split (const std::string &s, char delim) {
26- std::vector<std::string> result;
27- std::stringstream ss (s);
28- std::string item;
29-
30- while (getline (ss, item, delim)) {
31- result.push_back (item);
32- }
33-
34- return result;
35- }
25+ using namespace libcdoc ;
3626
3727template <std::size_t SIZE>
3828static int64_t fromOctal (const std::array<char ,SIZE> &data)
@@ -59,7 +49,7 @@ static void toOctal(std::array<char,SIZE> &data, int64_t value)
5949 }
6050}
6151
62- struct Header {
52+ struct libcdoc :: Header {
6353 std::array<char ,100 > name;
6454 std::array<char , 8 > mode;
6555 std::array<char , 8 > uid;
@@ -103,42 +93,13 @@ struct Header {
10393 return referenceChecksum == checkSum.first ||
10494 referenceChecksum == checkSum.second ;
10595 }
106-
107- static const Header Empty;
108- static const int Size;
10996};
11097
11198static int padding (int64_t size)
11299{
113100 return sizeof (Header) - size % sizeof (Header);
114101}
115102
116- bool
117- libcdoc::TAR::files (libcdoc::DataSource *src, bool &warning, libcdoc::MultiDataConsumer *dst)
118- {
119- TarSource tar (src, false );
120- std::string name;
121- int64_t size;
122- while (tar.next (name, size) == OK) {
123- dst->open (name, size);
124- dst->writeAll (tar);
125- }
126- warning = !src->isEof ();
127- return true ;
128- }
129-
130- int64_t writePadding (libcdoc::DataConsumer *dst, uint64_t size) {
131- std::vector<char > pad (padding (size), 0 );
132- return dst->write ((const uint8_t *) pad.data (), pad.size ()) == pad.size ();
133- };
134-
135- int64_t writeHeader (libcdoc::DataConsumer *dst, Header &h, uint64_t size) {
136- h.chksum .fill (' ' );
137- toOctal (h.size , size);
138- toOctal (h.chksum , h.checksum ().first );
139- return dst->write ((const uint8_t *)&h, sizeof (Header)) == sizeof (Header);
140- };
141-
142103std::string toPaxRecord (const std::string &keyword, const std::string &value) {
143104 std::string record = ' ' + keyword + ' =' + value + ' \n ' ;
144105 std::string result;
@@ -147,51 +108,6 @@ std::string toPaxRecord (const std::string &keyword, const std::string &value) {
147108 return result;
148109};
149110
150- bool
151- libcdoc::TAR::save (libcdoc::DataConsumer& dst, libcdoc::MultiDataSource& src)
152- {
153- std::string name;
154- int64_t size;
155- while (src.next (name, size)) {
156- Header h {};
157- std::string filename (name);
158- std::string filenameTruncated (filename.begin (), filename.begin () + h.name .size ());
159- std::copy (filenameTruncated.cbegin (), filenameTruncated.cend (), h.name .begin ());
160-
161- // TODO:
162- // write pax record if name contains special symbols
163- if (filename.size () > 100 || size > 07777777 ) {
164- h.typeflag = ' x' ;
165- std::string paxData;
166- if (filename.size () > 100 )
167- paxData += toPaxRecord (" path" , filename);
168- if (size > 07777777 )
169- paxData += toPaxRecord (" size" , std::to_string (size));
170- if (!writeHeader (&dst, h, paxData.size ()) ||
171- dst.write ((const uint8_t *) paxData.data (), paxData.size ()) != paxData.size () ||
172- !writePadding (&dst, paxData.size ()))
173- return false ;
174- }
175-
176- h.typeflag = ' 0' ;
177- if (!writeHeader (&dst, h, size))
178- return false ;
179- size_t total_written = 0 ;
180- while (!src.isEof ()) {
181- uint8_t buf[256 ];
182- auto n_read = src.read (buf, 256 );
183- if (n_read < 0 ) return false ;
184- dst.write (buf, n_read);
185- total_written += n_read;
186- }
187- writePadding (&dst, total_written);
188-
189- }
190- Header empty = {};
191- return dst.write ((const uint8_t *)&empty, sizeof (Header)) == sizeof (Header) &&
192- dst.write ((const uint8_t *)&empty, sizeof (Header)) == sizeof (Header);
193- }
194-
195111libcdoc::TarConsumer::TarConsumer (DataConsumer *dst, bool take_ownership)
196112 : _dst(dst), _owned(take_ownership)
197113{
@@ -211,17 +127,44 @@ libcdoc::TarConsumer::write(const uint8_t *src, size_t size)
211127 return _dst->write (src, size);
212128}
213129
130+ libcdoc::result_t
131+ libcdoc::TarConsumer::writeHeader (const Header &h) {
132+ if (auto rv = _dst->write ((const uint8_t *)&h, sizeof (Header)); rv != sizeof (Header))
133+ return rv < OK ? rv : OUTPUT_ERROR;
134+ return OK;
135+ }
136+
137+ libcdoc::result_t
138+ libcdoc::TarConsumer::writeHeader (Header &h, int64_t size) {
139+ h.chksum .fill (' ' );
140+ toOctal (h.size , size);
141+ toOctal (h.chksum , h.checksum ().first );
142+ return writeHeader (h);
143+ }
144+
145+ libcdoc::result_t
146+ libcdoc::TarConsumer::writePadding (int64_t size) {
147+ std::array<uint8_t ,sizeof (libcdoc::Header)> pad {};
148+ auto padSize = padding (size);
149+ if (auto rv = _dst->write (pad.data (), padSize); rv != padSize)
150+ return rv < OK ? rv : OUTPUT_ERROR;
151+ return OK;
152+ }
153+
214154libcdoc::result_t
215155libcdoc::TarConsumer::close ()
216156{
217- if (_current_size) {
218- writePadding (_dst, _current_size);
219- }
220- Header empty = {};
221- _dst->write ((const uint8_t *)&empty, sizeof (Header));
222- _dst->write ((const uint8_t *)&empty, sizeof (Header));
157+ if (_current_size > 0 ) {
158+ if (auto rv = writePadding (_current_size); rv != OK)
159+ return rv;
160+ }
161+ Header empty = {};
162+ if (auto rv = writeHeader (empty); rv != OK)
163+ return rv;
164+ if (auto rv = writeHeader (empty); rv != OK)
165+ return rv;
223166 if (_owned) {
224- _dst->close ();
167+ return _dst->close ();
225168 }
226169 return OK;
227170}
@@ -235,32 +178,33 @@ libcdoc::TarConsumer::isError()
235178libcdoc::result_t
236179libcdoc::TarConsumer::open (const std::string& name, int64_t size)
237180{
238- if (_current_size) {
239- writePadding (_dst, _current_size);
240- }
241- _current_size = size;
181+ if (_current_size > 0 ) {
182+ if (auto rv = writePadding (_current_size); rv != OK)
183+ return rv;
184+ }
185+
186+ _current_size = size;
242187 Header h {};
243- std::string filename (name);
244- size_t len = name.size ();
245- if (len > h.name .size ()) len = h.name .size ();
246- std::copy (name.cbegin (), name.cbegin () + len, h.name .begin ());
188+ size_t len = std::min (name.size (), h.name .size ());
189+ std::copy_n (name.cbegin (), len, h.name .begin ());
247190
248191 // TODO: Create pax record if name contains special symbols
249- if (filename .size () > 100 || size > 07777777 ) {
192+ if (name .size () > 100 || size > 07777777 ) {
250193 h.typeflag = ' x' ;
251194 std::string paxData;
252- if (filename .size () > 100 )
253- paxData += toPaxRecord (" path" , filename );
195+ if (name .size () > 100 )
196+ paxData += toPaxRecord (" path" , name );
254197 if (size > 07777777 )
255198 paxData += toPaxRecord (" size" , std::to_string (size));
256- return writeHeader (_dst, h, paxData.size ()) &&
257- _dst->write ((const uint8_t *) paxData.data (), paxData.size ()) == paxData.size () &&
258- writePadding (_dst, paxData.size ()) ? OK : OUTPUT_ERROR;
259- }
260-
199+ if (auto rv = writeHeader (h, paxData.size ()); rv != OK)
200+ return rv;
201+ if (auto rv = _dst->write ((const uint8_t *) paxData.data (), paxData.size ()); rv != paxData.size ())
202+ return rv < OK ? rv : OUTPUT_ERROR;
203+ if (auto rv = writePadding (paxData.size ()); rv != OK)
204+ return rv;
205+ }
261206 h.typeflag = ' 0' ;
262- if (writeHeader (_dst, h, size) < 0 ) return OUTPUT_ERROR;
263- return OK;
207+ return writeHeader (h, size);
264208}
265209
266210libcdoc::TarSource::TarSource (DataSource *src, bool take_ownership)
0 commit comments