OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2009, Google Inc. | 2 * Copyright 2009, Google Inc. |
3 * All rights reserved. | 3 * All rights reserved. |
4 * | 4 * |
5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
6 * modification, are permitted provided that the following conditions are | 6 * modification, are permitted provided that the following conditions are |
7 * met: | 7 * met: |
8 * | 8 * |
9 * * Redistributions of source code must retain the above copyright | 9 * * Redistributions of source code must retain the above copyright |
10 * notice, this list of conditions and the following disclaimer. | 10 * notice, this list of conditions and the following disclaimer. |
(...skipping 23 matching lines...) Expand all Loading... | |
34 #include "import/cross/tar_generator.h" | 34 #include "import/cross/tar_generator.h" |
35 | 35 |
36 using std::string; | 36 using std::string; |
37 | 37 |
38 #if defined(OS_WIN) | 38 #if defined(OS_WIN) |
39 #define snprintf _snprintf | 39 #define snprintf _snprintf |
40 #endif | 40 #endif |
41 | 41 |
42 namespace o3d { | 42 namespace o3d { |
43 | 43 |
44 const int kMaxFilenameSize = 100; | 44 const int kMaxFilenameSizeOldFormat = 100; |
45 | 45 |
46 const int kFileNameOffset = 0; | 46 const int kFileNameOffset = 0; |
47 const int kFileModeOffset = 100; | 47 const int kFileModeOffset = 100; |
48 const int kUserIDOffset = 108; | 48 const int kUserIDOffset = 108; |
49 const int kGroupIDOffset = 116; | 49 const int kGroupIDOffset = 116; |
50 const int kFileSizeOffset = 124; | 50 const int kFileSizeOffset = 124; |
51 const int kModifyTimeOffset = 136; | 51 const int kModifyTimeOffset = 136; |
52 const int kHeaderCheckSumOffset = 148; | 52 const int kHeaderCheckSumOffset = 148; |
53 const int kLinkFlagOffset = 156; | 53 const int kLinkFlagOffset = 156; |
54 const int kMagicOffset = 257; | 54 const int kMagicOffset = 257; |
55 const int kUserNameOffset = 265; | 55 const int kUserNameOffset = 265; |
56 const int kGroupNameOffset = 297; | 56 const int kGroupNameOffset = 297; |
57 static const char* kLongLink = "././@LongLink"; | |
Chris Rogers
2009/07/21 19:14:28
comment explaining what kLongLink is
| |
57 | 58 |
58 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 59 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
59 void TarGenerator::AddFile(const String &file_name, size_t file_size) { | 60 bool TarGenerator::AddFile(const String &file_name, size_t file_size) { |
60 AddDirectoryEntryIfNeeded(file_name); | 61 if (!AddDirectoryEntryIfNeeded(file_name)) { |
61 AddEntry(file_name, file_size, false); | 62 return false; |
63 } | |
64 return AddEntry(file_name, file_size, false); | |
62 } | 65 } |
63 | 66 |
64 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 67 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
65 void TarGenerator::AddDirectory(const String &file_name) { | 68 bool TarGenerator::AddDirectory(const String &file_name) { |
66 AddEntry(file_name, 0, true); | 69 return AddEntry(file_name, 0, true); |
67 } | 70 } |
68 | 71 |
69 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 72 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
70 // We keep a map so we add a particular directory entry only once | 73 // We keep a map so we add a particular directory entry only once |
71 void TarGenerator::AddDirectoryEntryIfNeeded(const String &file_name) { | 74 bool TarGenerator::AddDirectoryEntryIfNeeded(const String &file_name) { |
72 string::size_type index = file_name.find_last_of('/'); | 75 string::size_type index = file_name.find_last_of('/'); |
73 | 76 |
74 if (index != string::npos) { | 77 if (index != string::npos) { |
75 String dir_name = file_name.substr(0, index + 1); // keep the '/' at end | 78 String dir_name = file_name.substr(0, index + 1); // keep the '/' at end |
76 if (!directory_map_[dir_name]) { | 79 if (!directory_map_[dir_name]) { |
77 directory_map_[dir_name] = true; | 80 directory_map_[dir_name] = true; |
78 AddDirectory(dir_name); | 81 return AddDirectory(dir_name); |
79 } | 82 } |
80 } | 83 } |
84 return true; | |
81 } | 85 } |
82 | 86 |
83 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 87 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
84 void TarGenerator::AddEntry(const String &file_name, | 88 |
85 size_t file_size, | 89 |
86 bool is_directory) { | 90 void TarGenerator::WriteHeader(const String& file_name, |
91 size_t file_size, | |
92 char type, | |
93 int mode, | |
94 int user_id, | |
95 int group_id, | |
96 int mod_time) { | |
87 // first write out last data block from last file (if any) | 97 // first write out last data block from last file (if any) |
88 FlushDataBuffer(true); | 98 FlushDataBuffer(true); |
89 | 99 |
90 // next fill out a tar header | 100 // next fill out a tar header |
91 MemoryBuffer<uint8> header(TAR_HEADER_SIZE); // initializes header to zeroes | 101 MemoryBuffer<uint8> header(TAR_HEADER_SIZE); // initializes header to zeroes |
92 | 102 |
93 // leave room for NULL-termination | 103 // leave room for NULL-termination |
94 uint8 *h = header; | 104 uint8 *h = header; |
95 char *p = reinterpret_cast<char*>(h); | 105 char *p = reinterpret_cast<char*>(h); |
96 | 106 |
97 // File name | 107 // File name |
98 strncpy(p, file_name.c_str(), kMaxFilenameSize - 1); | 108 strncpy(p, file_name.c_str(), kMaxFilenameSizeOldFormat - 1); |
99 | 109 |
100 // File mode | 110 // File mode |
101 ::snprintf(p + kFileModeOffset, 8, "%07o", is_directory ? 0755 : 0644); | 111 ::snprintf(p + kFileModeOffset, 8, "%07o", mode); |
102 | 112 |
103 // UserID | 113 // UserID |
104 ::snprintf(p + kUserIDOffset, 8, "%07o", 0765); | 114 ::snprintf(p + kUserIDOffset, 8, "%07o", user_id); |
105 | 115 |
106 // GroupID | 116 // GroupID |
107 ::snprintf(p + kGroupIDOffset, 8, "%07o", 0204); | 117 ::snprintf(p + kGroupIDOffset, 8, "%07o", group_id); |
108 | 118 |
109 // File size | 119 // File size |
110 ::snprintf(p + kFileSizeOffset, 12, "%011o", file_size); | 120 ::snprintf(p + kFileSizeOffset, 12, "%011o", file_size); |
111 | 121 |
112 // Modification time | 122 // Modification time |
113 // TODO: write the correct current time here... | 123 // TODO: write the correct current time here... |
114 ::snprintf(p + kModifyTimeOffset, 12, "%07o", 011131753141); | 124 ::snprintf(p + kModifyTimeOffset, 12, "%07o", mod_time); |
115 | 125 |
116 // Initialize Header checksum so check sum can be computed | 126 // Initialize Header checksum so check sum can be computed |
117 // by ComputeCheckSum() which will fill in the value here | 127 // by ComputeCheckSum() which will fill in the value here |
118 ::memset(p + kHeaderCheckSumOffset, 32, 8); | 128 ::memset(p + kHeaderCheckSumOffset, 32, 8); |
119 | 129 |
120 // We only support ordinary files and directories, which is fine | 130 // We only support ordinary files and directories, which is fine |
121 // for our use case | 131 // for our use case |
Chris Rogers
2009/07/21 19:14:28
maybe should adjust comment to say this can indica
| |
122 int link_flag = is_directory ? '5' : '0'; | 132 p[kLinkFlagOffset] = type; |
123 p[kLinkFlagOffset] = link_flag; | |
124 | 133 |
125 // Magic offset | 134 // Magic offset |
126 ::snprintf(p + kMagicOffset, 8, "ustar "); | 135 ::snprintf(p + kMagicOffset, 8, "ustar "); |
127 | 136 |
128 // User name | 137 // User name |
129 ::snprintf(p + kUserNameOffset, 32, "guest"); | 138 ::snprintf(p + kUserNameOffset, 32, "guest"); |
130 | 139 |
131 // Group name | 140 // Group name |
132 ::snprintf(p + kGroupNameOffset, 32, "staff"); | 141 ::snprintf(p + kGroupNameOffset, 32, "staff"); |
133 | 142 |
134 | |
135 // This has to be done at the end | 143 // This has to be done at the end |
136 ComputeCheckSum(header); | 144 ComputeCheckSum(header); |
137 | 145 |
138 if (callback_client_) { | 146 if (callback_client_) { |
139 MemoryReadStream stream(header, TAR_HEADER_SIZE); | 147 MemoryReadStream stream(header, TAR_HEADER_SIZE); |
140 callback_client_->ProcessBytes(&stream, TAR_HEADER_SIZE); | 148 callback_client_->ProcessBytes(&stream, TAR_HEADER_SIZE); |
141 } | 149 } |
142 } | 150 } |
143 | 151 |
152 | |
153 bool TarGenerator::AddEntry(const String &file_name, | |
154 size_t file_size, | |
155 bool is_directory) { | |
156 // If filename is longer 99 chars, use the GNU format to write out a longer | |
157 // filename. | |
158 if (file_name.size() >= kMaxFilenameSizeOldFormat) { | |
159 WriteHeader(kLongLink, | |
160 file_name.size(), | |
161 'L', | |
162 0, | |
163 0, | |
164 0, | |
165 0); | |
166 | |
167 MemoryReadStream stream( | |
168 reinterpret_cast<const uint8*>(file_name.c_str()), file_name.size()); | |
169 AddFileBytes(&stream, file_name.size()); | |
170 } | |
171 | |
172 WriteHeader(file_name, | |
173 file_size, | |
174 is_directory ? '5' : '0', | |
175 is_directory ? 0755 : 0644, | |
176 0765, | |
177 0204, | |
178 011131753141); | |
179 | |
180 return true; | |
181 } | |
182 | |
144 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 183 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
145 void TarGenerator::ComputeCheckSum(uint8 *header) { | 184 void TarGenerator::ComputeCheckSum(uint8 *header) { |
146 unsigned int checksum = 0; | 185 unsigned int checksum = 0; |
147 for (int i = 0; i < TAR_HEADER_SIZE; ++i) { | 186 for (int i = 0; i < TAR_HEADER_SIZE; ++i) { |
148 checksum += header[i]; | 187 checksum += header[i]; |
149 } | 188 } |
150 snprintf(reinterpret_cast<char*>(header + kHeaderCheckSumOffset), | 189 snprintf(reinterpret_cast<char*>(header + kHeaderCheckSumOffset), |
151 8, "%06o\0\0", checksum); | 190 8, "%06o\0\0", checksum); |
152 } | 191 } |
153 | 192 |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
190 data_buffer_stream_.Seek(0); | 229 data_buffer_stream_.Seek(0); |
191 } | 230 } |
192 } | 231 } |
193 | 232 |
194 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 233 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
195 void TarGenerator::Finalize() { | 234 void TarGenerator::Finalize() { |
196 FlushDataBuffer(true); | 235 FlushDataBuffer(true); |
197 } | 236 } |
198 | 237 |
199 } // namespace o3d | 238 } // namespace o3d |
OLD | NEW |