Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(393)

Side by Side Diff: import/cross/tar_generator.cc

Issue 159129: Refactor tar code to support long names.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/o3d/
Patch Set: Created 11 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698