diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2006-11-25 14:48:09 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2006-11-25 14:48:09 +0000 |
commit | f2408e6c3ff5f9f798bb5553346d9e1657dc9833 (patch) | |
tree | 29a7144d66c91086fb53278c40ee1b27f4006cd7 /archival/tar.c | |
parent | 5dd27b1ee0518f4f886e6140adc5d1f20fb770e2 (diff) | |
download | busybox-w32-f2408e6c3ff5f9f798bb5553346d9e1657dc9833.tar.gz busybox-w32-f2408e6c3ff5f9f798bb5553346d9e1657dc9833.tar.bz2 busybox-w32-f2408e6c3ff5f9f798bb5553346d9e1657dc9833.zip |
tar: abort if tarring up file larger that 64Gb
(otherwise we will produce garbled tarfile)
Diffstat (limited to 'archival/tar.c')
-rw-r--r-- | archival/tar.c | 77 |
1 files changed, 35 insertions, 42 deletions
diff --git a/archival/tar.c b/archival/tar.c index b326d1e88..d875805b0 100644 --- a/archival/tar.c +++ b/archival/tar.c | |||
@@ -150,40 +150,29 @@ static HardLinkInfo *findHardLinkInfo(HardLinkInfo * hlInfo, struct stat *statbu | |||
150 | 150 | ||
151 | /* Put an octal string into the specified buffer. | 151 | /* Put an octal string into the specified buffer. |
152 | * The number is zero padded and possibly null terminated. | 152 | * The number is zero padded and possibly null terminated. |
153 | * Returns TRUE if successful. - DISABLED (no caller ever checked) */ | 153 | * Stores low-order bits only if whole value does not fit. |
154 | /* FIXME: we leave field untouched if value doesn't fit. */ | 154 | * Returns FALSE if that happens. */ |
155 | /* This is not good - what will happen at untar time?? */ | 155 | static int putOctal(char *cp, int len, off_t value) |
156 | static void putOctal(char *cp, int len, long long value) | ||
157 | { | 156 | { |
158 | int tempLength; | 157 | char tempBuffer[sizeof(off_t)*3+1]; |
159 | /* long long for the sake of storing lengths of 4Gb+ files */ | ||
160 | /* (we are bust anyway after 64Gb: it doesn't fit into the field) */ | ||
161 | char tempBuffer[sizeof(long long)*3+1]; | ||
162 | char *tempString = tempBuffer; | 158 | char *tempString = tempBuffer; |
159 | int width; | ||
163 | 160 | ||
164 | /* Create a string of the specified length with | 161 | width = sprintf(tempBuffer, "%0*"OFF_FMT"o", len, value); |
165 | * leading zeroes and the octal number, and a trailing null. */ | 162 | tempString += (width - len); |
166 | tempLength = sprintf(tempBuffer, "%0*llo", len - 1, value); | ||
167 | |||
168 | /* If the string is too large, suppress leading 0's. */ | ||
169 | /* If that is not enough, drop trailing null. */ | ||
170 | tempLength -= len; /* easier to do checks */ | ||
171 | while (tempLength >= 0) { | ||
172 | if (tempString[0] != '0') { | ||
173 | if (!tempLength) { | ||
174 | /* 1234 barely fits in 4 chars (w/o EOL '\0') */ | ||
175 | break; | ||
176 | } | ||
177 | /* 12345 doesn't fit into 4 chars */ | ||
178 | return /*FALSE*/; | ||
179 | } | ||
180 | tempLength--; /* still have leading '0', */ | ||
181 | tempString++; /* can afford to drop it but retain EOL '\0' */ | ||
182 | } | ||
183 | 163 | ||
184 | /* Copy the string to the field. */ | 164 | /* If string has leading zeroes, we can drop one */ |
165 | /* and field will have trailing '\0' */ | ||
166 | /* (increases chances of compat with other tars) */ | ||
167 | if (tempString[0] == '0') | ||
168 | tempString++; | ||
169 | |||
170 | /* Copy the string to the field */ | ||
185 | memcpy(cp, tempString, len); | 171 | memcpy(cp, tempString, len); |
186 | /*return TRUE;*/ | 172 | |
173 | /* If after shift we have zero - value did not overflow, */ | ||
174 | /* return 1 (TRUE) then */ | ||
175 | return (value >> (len*3)) == 0; | ||
187 | } | 176 | } |
188 | 177 | ||
189 | /* Write out a tar header for the specified file/directory/whatever */ | 178 | /* Write out a tar header for the specified file/directory/whatever */ |
@@ -203,12 +192,13 @@ static int writeTarHeader(struct TarBallInfo *tbInfo, | |||
203 | 192 | ||
204 | safe_strncpy(header.name, header_name, sizeof(header.name)); | 193 | safe_strncpy(header.name, header_name, sizeof(header.name)); |
205 | 194 | ||
195 | #define PUT_OCTAL(a, b) putOctal((a), sizeof(a), (b)) | ||
206 | /* POSIX says to mask mode with 07777. */ | 196 | /* POSIX says to mask mode with 07777. */ |
207 | putOctal(header.mode, sizeof(header.mode), statbuf->st_mode & 07777); | 197 | PUT_OCTAL(header.mode, statbuf->st_mode & 07777); |
208 | putOctal(header.uid, sizeof(header.uid), statbuf->st_uid); | 198 | PUT_OCTAL(header.uid, statbuf->st_uid); |
209 | putOctal(header.gid, sizeof(header.gid), statbuf->st_gid); | 199 | PUT_OCTAL(header.gid, statbuf->st_gid); |
210 | memset(header.size, '0', sizeof(header.size)-1); /* Regular file size is handled later */ | 200 | memset(header.size, '0', sizeof(header.size)-1); /* Regular file size is handled later */ |
211 | putOctal(header.mtime, sizeof(header.mtime), statbuf->st_mtime); | 201 | PUT_OCTAL(header.mtime, statbuf->st_mtime); |
212 | strcpy(header.magic, "ustar "); | 202 | strcpy(header.magic, "ustar "); |
213 | 203 | ||
214 | /* Enter the user and group names */ | 204 | /* Enter the user and group names */ |
@@ -240,25 +230,28 @@ static int writeTarHeader(struct TarBallInfo *tbInfo, | |||
240 | strncat(header.name, "/", sizeof(header.name)); | 230 | strncat(header.name, "/", sizeof(header.name)); |
241 | } else if (S_ISCHR(statbuf->st_mode)) { | 231 | } else if (S_ISCHR(statbuf->st_mode)) { |
242 | header.typeflag = CHRTYPE; | 232 | header.typeflag = CHRTYPE; |
243 | putOctal(header.devmajor, sizeof(header.devmajor), | 233 | PUT_OCTAL(header.devmajor, major(statbuf->st_rdev)); |
244 | major(statbuf->st_rdev)); | 234 | PUT_OCTAL(header.devminor, minor(statbuf->st_rdev)); |
245 | putOctal(header.devminor, sizeof(header.devminor), | ||
246 | minor(statbuf->st_rdev)); | ||
247 | } else if (S_ISBLK(statbuf->st_mode)) { | 235 | } else if (S_ISBLK(statbuf->st_mode)) { |
248 | header.typeflag = BLKTYPE; | 236 | header.typeflag = BLKTYPE; |
249 | putOctal(header.devmajor, sizeof(header.devmajor), | 237 | PUT_OCTAL(header.devmajor, major(statbuf->st_rdev)); |
250 | major(statbuf->st_rdev)); | 238 | PUT_OCTAL(header.devminor, minor(statbuf->st_rdev)); |
251 | putOctal(header.devminor, sizeof(header.devminor), | ||
252 | minor(statbuf->st_rdev)); | ||
253 | } else if (S_ISFIFO(statbuf->st_mode)) { | 239 | } else if (S_ISFIFO(statbuf->st_mode)) { |
254 | header.typeflag = FIFOTYPE; | 240 | header.typeflag = FIFOTYPE; |
255 | } else if (S_ISREG(statbuf->st_mode)) { | 241 | } else if (S_ISREG(statbuf->st_mode)) { |
256 | header.typeflag = REGTYPE; | 242 | header.typeflag = REGTYPE; |
257 | putOctal(header.size, sizeof(header.size), statbuf->st_size); | 243 | if ((PUT_OCTAL(header.size, statbuf->st_size) == FALSE) |
244 | && sizeof(statbuf->st_size) > 4 | ||
245 | ) { | ||
246 | bb_error_msg_and_die("cannot store file '%s' " | ||
247 | "of size %"OFF_FMT"d, aborting", | ||
248 | fileName, statbuf->st_size); | ||
249 | } | ||
258 | } else { | 250 | } else { |
259 | bb_error_msg("%s: unknown file type", fileName); | 251 | bb_error_msg("%s: unknown file type", fileName); |
260 | return FALSE; | 252 | return FALSE; |
261 | } | 253 | } |
254 | #undef PUT_OCTAL | ||
262 | 255 | ||
263 | /* Calculate and store the checksum (i.e., the sum of all of the bytes of | 256 | /* Calculate and store the checksum (i.e., the sum of all of the bytes of |
264 | * the header). The checksum field must be filled with blanks for the | 257 | * the header). The checksum field must be filled with blanks for the |