Index: import/cross/tar_processor.cc |
=================================================================== |
--- import/cross/tar_processor.cc (revision 21085) |
+++ import/cross/tar_processor.cc (working copy) |
@@ -37,6 +37,9 @@ |
namespace o3d { |
+static const int kFileSizeOffset = 124; |
+static const int kLinkFlagOffset = 156; |
+ |
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
int TarProcessor::ProcessBytes(MemoryReadStream *stream, size_t n) { |
// Keep processing the byte-stream until we've consumed all we're given |
@@ -60,26 +63,41 @@ |
bytes_to_consume -= bytes_to_read; |
if (header_bytes_read_ == TAR_HEADER_SIZE) { |
- const char *filename = (const char *)header_; |
- |
// The tar format stupidly represents size_teger values as |
Chris Rogers
2009/07/21 19:14:28
might as well fix this comment now "size_teger"
|
// octal strings!! |
size_t file_size = 0; |
- sscanf(header_ + 124, "%o", &file_size); |
+ sscanf(header_ + kFileSizeOffset, "%o", &file_size); |
- // Only callback client if this is a "real" header |
- // (filename is not NULL) |
- // Extra zero-padding can be added by the gzip compression |
- // (at end of archive), so ignore these ones. |
- // |
- // Also, ignore entries for directories (which have zero size) |
- if (header_[0] != 0 && file_size > 0) { |
- ArchiveFileInfo info(filename, file_size); |
- callback_client_->ReceiveFileHeader(info); |
- } else if (header_[0] == 0) { |
- // If filename is NULL due to zero-padding then file size |
- // should also be NULL |
- assert(file_size == 0); |
+ // Check if it's a long filename |
+ char type = header_[kLinkFlagOffset]; |
+ if (type == 'L') { |
+ getting_filename_ = true; |
+ // We should pick some size that's too large. |
+ if (file_size > 1024) { |
+ return -1; |
+ } |
+ } else { |
+ getting_filename_ = false; |
+ const char *filename = (const char *)header_; |
+ if (!file_name_.empty()) { |
+ filename = file_name_.c_str(); |
+ } |
+ |
+ // Only callback client if this is a "real" header |
+ // (filename is not NULL) |
+ // Extra zero-padding can be added by the gzip compression |
+ // (at end of archive), so ignore these ones. |
+ // |
+ // Also, ignore entries for directories (which have zero size) |
+ if (header_[0] != 0 && file_size > 0) { |
+ ArchiveFileInfo info(filename, file_size); |
+ callback_client_->ReceiveFileHeader(info); |
+ } else if (header_[0] == 0) { |
+ // If filename is NULL due to zero-padding then file size |
+ // should also be NULL |
+ // TODO(gman): Won't this crash the plugin if I make a bad tar? |
+ assert(file_size == 0); |
+ } |
} |
// Round filesize up to nearest block size |
@@ -89,6 +107,9 @@ |
// Our client doesn't want to be bothered with the block padding, |
// so only send him the actual file bytes |
client_file_bytes_to_read_ = file_size; |
+ |
+ // Clear the file_name_ so we don't use it next time. |
+ file_name_.clear(); |
} |
} |
@@ -105,9 +126,17 @@ |
size_t client_bytes_this_time = |
std::min(bytes_to_consume, client_file_bytes_to_read_); |
- if (!callback_client_->ReceiveFileData(&client_read_stream, |
- client_bytes_this_time)) { |
- return -1; |
+ if (getting_filename_) { |
+ String name_piece( |
+ client_read_stream.GetDirectMemoryPointerAs<const char>(), |
+ client_bytes_this_time); |
+ client_read_stream.Skip(client_bytes_this_time); |
+ file_name_ += name_piece; |
+ } else { |
+ if (!callback_client_->ReceiveFileData(&client_read_stream, |
+ client_bytes_this_time)) { |
+ return -1; |
+ } |
} |
client_file_bytes_to_read_ -= client_bytes_this_time; |