Index: import/cross/tar_generator.cc |
=================================================================== |
--- import/cross/tar_generator.cc (revision 21085) |
+++ import/cross/tar_generator.cc (working copy) |
@@ -41,7 +41,7 @@ |
namespace o3d { |
-const int kMaxFilenameSize = 100; |
+const int kMaxFilenameSizeOldFormat = 100; |
const int kFileNameOffset = 0; |
const int kFileModeOffset = 100; |
@@ -54,36 +54,46 @@ |
const int kMagicOffset = 257; |
const int kUserNameOffset = 265; |
const int kGroupNameOffset = 297; |
+static const char* kLongLink = "././@LongLink"; |
Chris Rogers
2009/07/21 19:14:28
comment explaining what kLongLink is
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
-void TarGenerator::AddFile(const String &file_name, size_t file_size) { |
- AddDirectoryEntryIfNeeded(file_name); |
- AddEntry(file_name, file_size, false); |
+bool TarGenerator::AddFile(const String &file_name, size_t file_size) { |
+ if (!AddDirectoryEntryIfNeeded(file_name)) { |
+ return false; |
+ } |
+ return AddEntry(file_name, file_size, false); |
} |
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
-void TarGenerator::AddDirectory(const String &file_name) { |
- AddEntry(file_name, 0, true); |
+bool TarGenerator::AddDirectory(const String &file_name) { |
+ return AddEntry(file_name, 0, true); |
} |
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
// We keep a map so we add a particular directory entry only once |
-void TarGenerator::AddDirectoryEntryIfNeeded(const String &file_name) { |
+bool TarGenerator::AddDirectoryEntryIfNeeded(const String &file_name) { |
string::size_type index = file_name.find_last_of('/'); |
if (index != string::npos) { |
String dir_name = file_name.substr(0, index + 1); // keep the '/' at end |
if (!directory_map_[dir_name]) { |
directory_map_[dir_name] = true; |
- AddDirectory(dir_name); |
+ return AddDirectory(dir_name); |
} |
} |
+ return true; |
} |
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
-void TarGenerator::AddEntry(const String &file_name, |
- size_t file_size, |
- bool is_directory) { |
+ |
+ |
+void TarGenerator::WriteHeader(const String& file_name, |
+ size_t file_size, |
+ char type, |
+ int mode, |
+ int user_id, |
+ int group_id, |
+ int mod_time) { |
// first write out last data block from last file (if any) |
FlushDataBuffer(true); |
@@ -95,23 +105,23 @@ |
char *p = reinterpret_cast<char*>(h); |
// File name |
- strncpy(p, file_name.c_str(), kMaxFilenameSize - 1); |
+ strncpy(p, file_name.c_str(), kMaxFilenameSizeOldFormat - 1); |
// File mode |
- ::snprintf(p + kFileModeOffset, 8, "%07o", is_directory ? 0755 : 0644); |
+ ::snprintf(p + kFileModeOffset, 8, "%07o", mode); |
// UserID |
- ::snprintf(p + kUserIDOffset, 8, "%07o", 0765); |
+ ::snprintf(p + kUserIDOffset, 8, "%07o", user_id); |
// GroupID |
- ::snprintf(p + kGroupIDOffset, 8, "%07o", 0204); |
+ ::snprintf(p + kGroupIDOffset, 8, "%07o", group_id); |
// File size |
::snprintf(p + kFileSizeOffset, 12, "%011o", file_size); |
// Modification time |
// TODO: write the correct current time here... |
- ::snprintf(p + kModifyTimeOffset, 12, "%07o", 011131753141); |
+ ::snprintf(p + kModifyTimeOffset, 12, "%07o", mod_time); |
// Initialize Header checksum so check sum can be computed |
// by ComputeCheckSum() which will fill in the value here |
@@ -119,8 +129,7 @@ |
// We only support ordinary files and directories, which is fine |
// for our use case |
Chris Rogers
2009/07/21 19:14:28
maybe should adjust comment to say this can indica
|
- int link_flag = is_directory ? '5' : '0'; |
- p[kLinkFlagOffset] = link_flag; |
+ p[kLinkFlagOffset] = type; |
// Magic offset |
::snprintf(p + kMagicOffset, 8, "ustar "); |
@@ -131,7 +140,6 @@ |
// Group name |
::snprintf(p + kGroupNameOffset, 32, "staff"); |
- |
// This has to be done at the end |
ComputeCheckSum(header); |
@@ -141,6 +149,37 @@ |
} |
} |
+ |
+bool TarGenerator::AddEntry(const String &file_name, |
+ size_t file_size, |
+ bool is_directory) { |
+ // If filename is longer 99 chars, use the GNU format to write out a longer |
+ // filename. |
+ if (file_name.size() >= kMaxFilenameSizeOldFormat) { |
+ WriteHeader(kLongLink, |
+ file_name.size(), |
+ 'L', |
+ 0, |
+ 0, |
+ 0, |
+ 0); |
+ |
+ MemoryReadStream stream( |
+ reinterpret_cast<const uint8*>(file_name.c_str()), file_name.size()); |
+ AddFileBytes(&stream, file_name.size()); |
+ } |
+ |
+ WriteHeader(file_name, |
+ file_size, |
+ is_directory ? '5' : '0', |
+ is_directory ? 0755 : 0644, |
+ 0765, |
+ 0204, |
+ 011131753141); |
+ |
+ return true; |
+} |
+ |
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
void TarGenerator::ComputeCheckSum(uint8 *header) { |
unsigned int checksum = 0; |