summaryrefslogtreecommitdiff
path: root/archival/tar.c
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2006-11-25 14:48:09 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2006-11-25 14:48:09 +0000
commitf2408e6c3ff5f9f798bb5553346d9e1657dc9833 (patch)
tree29a7144d66c91086fb53278c40ee1b27f4006cd7 /archival/tar.c
parent5dd27b1ee0518f4f886e6140adc5d1f20fb770e2 (diff)
downloadbusybox-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.c77
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?? */ 155static int putOctal(char *cp, int len, off_t value)
156static 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