diff options
author | Erik Andersen <andersen@codepoet.org> | 2000-02-08 19:58:47 +0000 |
---|---|---|
committer | Erik Andersen <andersen@codepoet.org> | 2000-02-08 19:58:47 +0000 |
commit | e49d5ecbbe51718fa925b6890a735e5937cc2aa2 (patch) | |
tree | c90bda10731ad9333ce3b404f993354c9fc104b8 /tar.c | |
parent | c0bf817bbc5c7867fbe8fb76d5c39f8ee802692f (diff) | |
download | busybox-w32-e49d5ecbbe51718fa925b6890a735e5937cc2aa2.tar.gz busybox-w32-e49d5ecbbe51718fa925b6890a735e5937cc2aa2.tar.bz2 busybox-w32-e49d5ecbbe51718fa925b6890a735e5937cc2aa2.zip |
Some formatting updates (ran the code through indent)
-Erik
Diffstat (limited to 'tar.c')
-rw-r--r-- | tar.c | 1857 |
1 files changed, 932 insertions, 925 deletions
@@ -1,3 +1,4 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | ||
1 | /* | 2 | /* |
2 | * Mini tar implementation for busybox based on code taken from sash. | 3 | * Mini tar implementation for busybox based on code taken from sash. |
3 | * | 4 | * |
@@ -40,27 +41,29 @@ | |||
40 | #include <utime.h> | 41 | #include <utime.h> |
41 | #include <sys/types.h> | 42 | #include <sys/types.h> |
42 | #include <sys/sysmacros.h> | 43 | #include <sys/sysmacros.h> |
43 | #include <sys/param.h> /* for PATH_MAX */ | 44 | #include <sys/param.h> /* for PATH_MAX */ |
44 | 45 | ||
45 | 46 | ||
46 | #ifdef BB_FEATURE_TAR_CREATE | 47 | #ifdef BB_FEATURE_TAR_CREATE |
47 | 48 | ||
48 | static const char tar_usage[] = | 49 | static const char tar_usage[] = |
49 | "tar -[cxtvOf] [tarFileName] [FILE] ...\n\n" | 50 | "tar -[cxtvOf] [tarFileName] [FILE] ...\n\n" |
50 | "Create, extract, or list files from a tar file.\n\n" | 51 | "Create, extract, or list files from a tar file.\n\n" |
51 | "Options:\n" | 52 | "Options:\n" |
52 | "\tc=create, x=extract, t=list contents, v=verbose,\n" | 53 | |
53 | "\tO=extract to stdout, f=tarfile or \"-\" for stdin\n"; | 54 | "\tc=create, x=extract, t=list contents, v=verbose,\n" |
55 | "\tO=extract to stdout, f=tarfile or \"-\" for stdin\n"; | ||
54 | 56 | ||
55 | #else | 57 | #else |
56 | 58 | ||
57 | static const char tar_usage[] = | 59 | static const char tar_usage[] = |
58 | "tar -[xtvOf] [tarFileName] [FILE] ...\n\n" | 60 | "tar -[xtvOf] [tarFileName] [FILE] ...\n\n" |
59 | "Extract, or list files stored in a tar file. This\n" | 61 | "Extract, or list files stored in a tar file. This\n" |
60 | "version of tar does not support creation of tar files.\n\n" | 62 | "version of tar does not support creation of tar files.\n\n" |
61 | "Options:\n" | 63 | "Options:\n" |
62 | "\tx=extract, t=list contents, v=verbose,\n" | 64 | |
63 | "\tO=extract to stdout, f=tarfile or \"-\" for stdin\n"; | 65 | "\tx=extract, t=list contents, v=verbose,\n" |
66 | "\tO=extract to stdout, f=tarfile or \"-\" for stdin\n"; | ||
64 | 67 | ||
65 | #endif | 68 | #endif |
66 | 69 | ||
@@ -78,22 +81,22 @@ static const char tar_usage[] = | |||
78 | * with zero padding. We only process this information minimally. | 81 | * with zero padding. We only process this information minimally. |
79 | */ | 82 | */ |
80 | typedef struct { | 83 | typedef struct { |
81 | char name[TAR_NAME_SIZE]; | 84 | char name[TAR_NAME_SIZE]; |
82 | char mode[8]; | 85 | char mode[8]; |
83 | char uid[8]; | 86 | char uid[8]; |
84 | char gid[8]; | 87 | char gid[8]; |
85 | char size[12]; | 88 | char size[12]; |
86 | char mtime[12]; | 89 | char mtime[12]; |
87 | char checkSum[8]; | 90 | char checkSum[8]; |
88 | char typeFlag; | 91 | char typeFlag; |
89 | char linkName[TAR_NAME_SIZE]; | 92 | char linkName[TAR_NAME_SIZE]; |
90 | char magic[6]; | 93 | char magic[6]; |
91 | char version[2]; | 94 | char version[2]; |
92 | char uname[32]; | 95 | char uname[32]; |
93 | char gname[32]; | 96 | char gname[32]; |
94 | char devMajor[8]; | 97 | char devMajor[8]; |
95 | char devMinor[8]; | 98 | char devMinor[8]; |
96 | char prefix[155]; | 99 | char prefix[155]; |
97 | } TarHeader; | 100 | } TarHeader; |
98 | 101 | ||
99 | #define TAR_MAGIC "ustar" | 102 | #define TAR_MAGIC "ustar" |
@@ -113,7 +116,7 @@ static int createFlag; | |||
113 | static int verboseFlag; | 116 | static int verboseFlag; |
114 | static int tostdoutFlag; | 117 | static int tostdoutFlag; |
115 | 118 | ||
116 | static int inHeader; // <- check me | 119 | static int inHeader; // <- check me |
117 | static int badHeader; | 120 | static int badHeader; |
118 | static int errorFlag; | 121 | static int errorFlag; |
119 | static int skipFileFlag; | 122 | static int skipFileFlag; |
@@ -140,141 +143,145 @@ static ino_t tarInode; | |||
140 | /* | 143 | /* |
141 | * Local procedures to restore files from a tar file. | 144 | * Local procedures to restore files from a tar file. |
142 | */ | 145 | */ |
143 | static void readTarFile (int fileCount, char **fileTable); | 146 | static void readTarFile(int fileCount, char **fileTable); |
144 | static void readData (const char *cp, int count); | 147 | static void readData(const char *cp, int count); |
145 | static long getOctal (const char *cp, int len); | 148 | static long getOctal(const char *cp, int len); |
149 | |||
150 | static void readHeader(const TarHeader * hp, | ||
146 | 151 | ||
147 | static void readHeader (const TarHeader * hp, | 152 | int fileCount, char **fileTable); |
148 | int fileCount, char **fileTable); | ||
149 | 153 | ||
150 | static int wantFileName (const char *fileName, | 154 | static int wantFileName(const char *fileName, |
151 | int fileCount, char **fileTable); | 155 | |
156 | int fileCount, char **fileTable); | ||
152 | 157 | ||
153 | #ifdef BB_FEATURE_TAR_CREATE | 158 | #ifdef BB_FEATURE_TAR_CREATE |
154 | /* | 159 | /* |
155 | * Local procedures to save files into a tar file. | 160 | * Local procedures to save files into a tar file. |
156 | */ | 161 | */ |
157 | static void saveFile (const char *fileName, int seeLinks); | 162 | static void saveFile(const char *fileName, int seeLinks); |
163 | |||
164 | static void saveRegularFile(const char *fileName, | ||
158 | 165 | ||
159 | static void saveRegularFile (const char *fileName, | 166 | const struct stat *statbuf); |
160 | const struct stat *statbuf); | ||
161 | 167 | ||
162 | static void saveDirectory (const char *fileName, | 168 | static void saveDirectory(const char *fileName, |
163 | const struct stat *statbuf); | ||
164 | 169 | ||
165 | static void writeHeader (const char *fileName, const struct stat *statbuf); | 170 | const struct stat *statbuf); |
166 | 171 | ||
167 | static void writeTarFile (int fileCount, char **fileTable); | 172 | static void writeHeader(const char *fileName, const struct stat *statbuf); |
168 | static void writeTarBlock (const char *buf, int len); | 173 | |
169 | static int putOctal (char *cp, int len, long value); | 174 | static void writeTarFile(int fileCount, char **fileTable); |
175 | static void writeTarBlock(const char *buf, int len); | ||
176 | static int putOctal(char *cp, int len, long value); | ||
170 | 177 | ||
171 | #endif | 178 | #endif |
172 | 179 | ||
173 | 180 | ||
174 | extern int tar_main (int argc, char **argv) | 181 | extern int tar_main(int argc, char **argv) |
175 | { | 182 | { |
176 | const char *options; | 183 | const char *options; |
177 | 184 | ||
178 | argc--; | 185 | argc--; |
179 | argv++; | 186 | argv++; |
180 | 187 | ||
181 | if (argc < 1) | 188 | if (argc < 1) |
182 | usage( tar_usage); | 189 | usage(tar_usage); |
183 | 190 | ||
184 | 191 | ||
185 | errorFlag = FALSE; | 192 | errorFlag = FALSE; |
186 | extractFlag = FALSE; | 193 | extractFlag = FALSE; |
187 | createFlag = FALSE; | 194 | createFlag = FALSE; |
188 | listFlag = FALSE; | 195 | listFlag = FALSE; |
189 | verboseFlag = FALSE; | 196 | verboseFlag = FALSE; |
190 | tostdoutFlag = FALSE; | 197 | tostdoutFlag = FALSE; |
191 | tarName = NULL; | 198 | tarName = NULL; |
192 | tarDev = 0; | 199 | tarDev = 0; |
193 | tarInode = 0; | 200 | tarInode = 0; |
194 | tarFd = -1; | 201 | tarFd = -1; |
195 | 202 | ||
196 | /* | 203 | /* |
197 | * Parse the options. | 204 | * Parse the options. |
198 | */ | 205 | */ |
199 | if (**argv == '-') | 206 | if (**argv == '-') |
200 | options = (*argv++) + 1; | 207 | options = (*argv++) + 1; |
201 | else | 208 | else |
202 | options = (*argv++); | 209 | options = (*argv++); |
203 | argc--; | 210 | argc--; |
204 | 211 | ||
205 | for (; *options; options++) { | 212 | for (; *options; options++) { |
206 | switch (*options) { | 213 | switch (*options) { |
207 | case 'f': | 214 | case 'f': |
208 | if (tarName != NULL) { | 215 | if (tarName != NULL) { |
209 | fprintf (stderr, "Only one 'f' option allowed\n"); | 216 | fprintf(stderr, "Only one 'f' option allowed\n"); |
210 | 217 | ||
211 | exit (FALSE); | 218 | exit(FALSE); |
212 | } | 219 | } |
213 | 220 | ||
214 | tarName = *argv++; | 221 | tarName = *argv++; |
215 | argc--; | 222 | argc--; |
216 | 223 | ||
217 | break; | 224 | break; |
218 | 225 | ||
219 | case 't': | 226 | case 't': |
220 | if (extractFlag == TRUE || createFlag == TRUE ) | 227 | if (extractFlag == TRUE || createFlag == TRUE) |
221 | goto flagError; | 228 | goto flagError; |
222 | listFlag = TRUE; | 229 | listFlag = TRUE; |
223 | break; | 230 | break; |
224 | 231 | ||
225 | case 'x': | 232 | case 'x': |
226 | if (listFlag == TRUE || createFlag == TRUE ) | 233 | if (listFlag == TRUE || createFlag == TRUE) |
227 | goto flagError; | 234 | goto flagError; |
228 | extractFlag = TRUE; | 235 | extractFlag = TRUE; |
229 | break; | 236 | break; |
230 | case 'c': | 237 | case 'c': |
231 | if (extractFlag == TRUE || listFlag == TRUE) | 238 | if (extractFlag == TRUE || listFlag == TRUE) |
232 | goto flagError; | 239 | goto flagError; |
233 | createFlag = TRUE; | 240 | createFlag = TRUE; |
234 | break; | 241 | break; |
235 | 242 | ||
236 | case 'v': | 243 | case 'v': |
237 | verboseFlag = TRUE; | 244 | verboseFlag = TRUE; |
238 | break; | 245 | break; |
239 | 246 | ||
240 | case 'O': | 247 | case 'O': |
241 | tostdoutFlag = TRUE; | 248 | tostdoutFlag = TRUE; |
242 | break; | 249 | break; |
243 | 250 | ||
244 | case '-': | 251 | case '-': |
245 | usage( tar_usage); | 252 | usage(tar_usage); |
246 | break; | 253 | break; |
247 | 254 | ||
248 | default: | 255 | default: |
249 | fprintf (stderr, "Unknown tar flag '%c'\n" | 256 | fprintf(stderr, "Unknown tar flag '%c'\n" |
250 | "Try `tar --help' for more information\n", | 257 | "Try `tar --help' for more information\n", *options); |
251 | *options); | 258 | exit(FALSE); |
252 | exit (FALSE); | 259 | } |
253 | } | 260 | } |
254 | } | ||
255 | 261 | ||
256 | /* | 262 | /* |
257 | * Do the correct type of action supplying the rest of the | 263 | * Do the correct type of action supplying the rest of the |
258 | * command line arguments as the list of files to process. | 264 | * command line arguments as the list of files to process. |
259 | */ | 265 | */ |
260 | if (createFlag==TRUE) { | 266 | if (createFlag == TRUE) { |
261 | #ifndef BB_FEATURE_TAR_CREATE | 267 | #ifndef BB_FEATURE_TAR_CREATE |
262 | fprintf (stderr, "This version of tar was not compiled with tar creation support.\n" ); | 268 | fprintf(stderr, |
263 | exit (FALSE); | 269 | "This version of tar was not compiled with tar creation support.\n"); |
270 | exit(FALSE); | ||
264 | #else | 271 | #else |
265 | writeTarFile (argc, argv); | 272 | writeTarFile(argc, argv); |
266 | #endif | 273 | #endif |
267 | } else { | 274 | } else { |
268 | readTarFile (argc, argv); | 275 | readTarFile(argc, argv); |
269 | } | 276 | } |
270 | if (errorFlag==TRUE) { | 277 | if (errorFlag == TRUE) { |
271 | fprintf (stderr, "\n"); | 278 | fprintf(stderr, "\n"); |
272 | } | 279 | } |
273 | exit (!errorFlag); | 280 | exit(!errorFlag); |
274 | 281 | ||
275 | flagError: | 282 | flagError: |
276 | fprintf (stderr, "Exactly one of 'c', 'x' or 't' must be specified\n"); | 283 | fprintf(stderr, "Exactly one of 'c', 'x' or 't' must be specified\n"); |
277 | exit (FALSE); | 284 | exit(FALSE); |
278 | } | 285 | } |
279 | 286 | ||
280 | 287 | ||
@@ -282,120 +289,120 @@ flagError: | |||
282 | * Read a tar file and extract or list the specified files within it. | 289 | * Read a tar file and extract or list the specified files within it. |
283 | * If the list is empty than all files are extracted or listed. | 290 | * If the list is empty than all files are extracted or listed. |
284 | */ | 291 | */ |
285 | static void readTarFile (int fileCount, char **fileTable) | 292 | static void readTarFile(int fileCount, char **fileTable) |
286 | { | 293 | { |
287 | const char *cp; | 294 | const char *cp; |
288 | int cc; | 295 | int cc; |
289 | int inCc; | 296 | int inCc; |
290 | int blockSize; | 297 | int blockSize; |
291 | char buf[BUF_SIZE]; | 298 | char buf[BUF_SIZE]; |
292 | 299 | ||
293 | skipFileFlag = FALSE; | 300 | skipFileFlag = FALSE; |
294 | badHeader = FALSE; | 301 | badHeader = FALSE; |
295 | warnedRoot = FALSE; | 302 | warnedRoot = FALSE; |
296 | eofFlag = FALSE; | 303 | eofFlag = FALSE; |
297 | inHeader = TRUE; | 304 | inHeader = TRUE; |
298 | inCc = 0; | 305 | inCc = 0; |
299 | dataCc = 0; | 306 | dataCc = 0; |
300 | outFd = -1; | 307 | outFd = -1; |
301 | blockSize = sizeof (buf); | 308 | blockSize = sizeof(buf); |
302 | cp = buf; | 309 | cp = buf; |
303 | 310 | ||
304 | /* | ||
305 | * Open the tar file for reading. | ||
306 | */ | ||
307 | if ((tarName == NULL) || !strcmp (tarName, "-")) { | ||
308 | tarFd = fileno(stdin); | ||
309 | } else | ||
310 | tarFd = open (tarName, O_RDONLY); | ||
311 | |||
312 | if (tarFd < 0) { | ||
313 | perror (tarName); | ||
314 | errorFlag = TRUE; | ||
315 | return; | ||
316 | } | ||
317 | |||
318 | /* | ||
319 | * Read blocks from the file until an end of file header block | ||
320 | * has been seen. (A real end of file from a read is an error.) | ||
321 | */ | ||
322 | while (eofFlag==FALSE) { | ||
323 | /* | 311 | /* |
324 | * Read the next block of data if necessary. | 312 | * Open the tar file for reading. |
325 | * This will be a large block if possible, which we will | ||
326 | * then process in the small tar blocks. | ||
327 | */ | 313 | */ |
328 | if (inCc <= 0) { | 314 | if ((tarName == NULL) || !strcmp(tarName, "-")) { |
329 | cp = buf; | 315 | tarFd = fileno(stdin); |
330 | inCc = fullRead (tarFd, buf, blockSize); | 316 | } else |
331 | 317 | tarFd = open(tarName, O_RDONLY); | |
332 | if (inCc < 0) { | ||
333 | perror (tarName); | ||
334 | errorFlag = TRUE; | ||
335 | goto done; | ||
336 | } | ||
337 | 318 | ||
338 | if (inCc == 0) { | 319 | if (tarFd < 0) { |
339 | fprintf (stderr, | 320 | perror(tarName); |
340 | "Unexpected end of file from \"%s\"", tarName); | ||
341 | errorFlag = TRUE; | 321 | errorFlag = TRUE; |
342 | goto done; | 322 | return; |
343 | } | ||
344 | } | 323 | } |
345 | 324 | ||
346 | /* | 325 | /* |
347 | * If we are expecting a header block then examine it. | 326 | * Read blocks from the file until an end of file header block |
327 | * has been seen. (A real end of file from a read is an error.) | ||
348 | */ | 328 | */ |
349 | if (inHeader==TRUE) { | 329 | while (eofFlag == FALSE) { |
350 | readHeader ((const TarHeader *) cp, fileCount, fileTable); | 330 | /* |
351 | 331 | * Read the next block of data if necessary. | |
352 | cp += TAR_BLOCK_SIZE; | 332 | * This will be a large block if possible, which we will |
353 | inCc -= TAR_BLOCK_SIZE; | 333 | * then process in the small tar blocks. |
354 | 334 | */ | |
355 | continue; | 335 | if (inCc <= 0) { |
336 | cp = buf; | ||
337 | inCc = fullRead(tarFd, buf, blockSize); | ||
338 | |||
339 | if (inCc < 0) { | ||
340 | perror(tarName); | ||
341 | errorFlag = TRUE; | ||
342 | goto done; | ||
343 | } | ||
344 | |||
345 | if (inCc == 0) { | ||
346 | fprintf(stderr, | ||
347 | "Unexpected end of file from \"%s\"", tarName); | ||
348 | errorFlag = TRUE; | ||
349 | goto done; | ||
350 | } | ||
351 | } | ||
352 | |||
353 | /* | ||
354 | * If we are expecting a header block then examine it. | ||
355 | */ | ||
356 | if (inHeader == TRUE) { | ||
357 | readHeader((const TarHeader *) cp, fileCount, fileTable); | ||
358 | |||
359 | cp += TAR_BLOCK_SIZE; | ||
360 | inCc -= TAR_BLOCK_SIZE; | ||
361 | |||
362 | continue; | ||
363 | } | ||
364 | |||
365 | /* | ||
366 | * We are currently handling the data for a file. | ||
367 | * Process the minimum of the amount of data we have available | ||
368 | * and the amount left to be processed for the file. | ||
369 | */ | ||
370 | cc = inCc; | ||
371 | |||
372 | if (cc > dataCc) | ||
373 | cc = dataCc; | ||
374 | |||
375 | readData(cp, cc); | ||
376 | |||
377 | /* | ||
378 | * If the amount left isn't an exact multiple of the tar block | ||
379 | * size then round it up to the next block boundary since there | ||
380 | * is padding at the end of the file. | ||
381 | */ | ||
382 | if (cc % TAR_BLOCK_SIZE) | ||
383 | cc += TAR_BLOCK_SIZE - (cc % TAR_BLOCK_SIZE); | ||
384 | |||
385 | cp += cc; | ||
386 | inCc -= cc; | ||
356 | } | 387 | } |
357 | 388 | ||
389 | done: | ||
358 | /* | 390 | /* |
359 | * We are currently handling the data for a file. | 391 | * Close the tar file if needed. |
360 | * Process the minimum of the amount of data we have available | ||
361 | * and the amount left to be processed for the file. | ||
362 | */ | 392 | */ |
363 | cc = inCc; | 393 | if ((tarFd >= 0) && (close(tarFd) < 0)) |
364 | 394 | perror(tarName); | |
365 | if (cc > dataCc) | ||
366 | cc = dataCc; | ||
367 | |||
368 | readData (cp, cc); | ||
369 | 395 | ||
370 | /* | 396 | /* |
371 | * If the amount left isn't an exact multiple of the tar block | 397 | * Close the output file if needed. |
372 | * size then round it up to the next block boundary since there | 398 | * This is only done here on a previous error and so no |
373 | * is padding at the end of the file. | 399 | * message is required on errors. |
374 | */ | 400 | */ |
375 | if (cc % TAR_BLOCK_SIZE) | 401 | if (tostdoutFlag == FALSE) { |
376 | cc += TAR_BLOCK_SIZE - (cc % TAR_BLOCK_SIZE); | 402 | if (outFd >= 0) { |
377 | 403 | close(outFd); | |
378 | cp += cc; | 404 | } |
379 | inCc -= cc; | ||
380 | } | ||
381 | |||
382 | done: | ||
383 | /* | ||
384 | * Close the tar file if needed. | ||
385 | */ | ||
386 | if ((tarFd >= 0) && (close (tarFd) < 0)) | ||
387 | perror (tarName); | ||
388 | |||
389 | /* | ||
390 | * Close the output file if needed. | ||
391 | * This is only done here on a previous error and so no | ||
392 | * message is required on errors. | ||
393 | */ | ||
394 | if (tostdoutFlag == FALSE) { | ||
395 | if (outFd >= 0) { | ||
396 | close (outFd); | ||
397 | } | 405 | } |
398 | } | ||
399 | } | 406 | } |
400 | 407 | ||
401 | 408 | ||
@@ -405,304 +412,305 @@ static void readTarFile (int fileCount, char **fileTable) | |||
405 | * the end of the tar file. | 412 | * the end of the tar file. |
406 | */ | 413 | */ |
407 | static void | 414 | static void |
408 | readHeader (const TarHeader * hp, int fileCount, char **fileTable) | 415 | readHeader(const TarHeader * hp, int fileCount, char **fileTable) |
409 | { | 416 | { |
410 | int checkSum; | 417 | int checkSum; |
411 | int cc; | 418 | int cc; |
412 | int hardLink; | 419 | int hardLink; |
413 | int softLink; | 420 | int softLink; |
414 | int devFileFlag; | 421 | int devFileFlag; |
415 | unsigned int major; | 422 | unsigned int major; |
416 | unsigned int minor; | 423 | unsigned int minor; |
417 | long size; | 424 | long size; |
418 | struct utimbuf utb; | 425 | struct utimbuf utb; |
419 | 426 | ||
420 | /* | 427 | /* |
421 | * If the block is completely empty, then this is the end of the | 428 | * If the block is completely empty, then this is the end of the |
422 | * archive file. If the name is null, then just skip this header. | 429 | * archive file. If the name is null, then just skip this header. |
423 | */ | 430 | */ |
424 | outName = hp->name; | 431 | outName = hp->name; |
425 | 432 | ||
426 | if (*outName == '\0') { | 433 | if (*outName == '\0') { |
427 | for (cc = TAR_BLOCK_SIZE; cc > 0; cc--) { | 434 | for (cc = TAR_BLOCK_SIZE; cc > 0; cc--) { |
428 | if (*outName++) | 435 | if (*outName++) |
436 | return; | ||
437 | } | ||
438 | |||
439 | eofFlag = TRUE; | ||
440 | |||
429 | return; | 441 | return; |
430 | } | 442 | } |
431 | 443 | ||
432 | eofFlag = TRUE; | 444 | /* |
433 | 445 | * There is another file in the archive to examine. | |
434 | return; | 446 | * Extract the encoded information and check it. |
435 | } | 447 | */ |
436 | 448 | mode = getOctal(hp->mode, sizeof(hp->mode)); | |
437 | /* | 449 | uid = getOctal(hp->uid, sizeof(hp->uid)); |
438 | * There is another file in the archive to examine. | 450 | gid = getOctal(hp->gid, sizeof(hp->gid)); |
439 | * Extract the encoded information and check it. | 451 | size = getOctal(hp->size, sizeof(hp->size)); |
440 | */ | 452 | mtime = getOctal(hp->mtime, sizeof(hp->mtime)); |
441 | mode = getOctal (hp->mode, sizeof (hp->mode)); | 453 | checkSum = getOctal(hp->checkSum, sizeof(hp->checkSum)); |
442 | uid = getOctal (hp->uid, sizeof (hp->uid)); | 454 | major = getOctal(hp->devMajor, sizeof(hp->devMajor)); |
443 | gid = getOctal (hp->gid, sizeof (hp->gid)); | 455 | minor = getOctal(hp->devMinor, sizeof(hp->devMinor)); |
444 | size = getOctal (hp->size, sizeof (hp->size)); | ||
445 | mtime = getOctal (hp->mtime, sizeof (hp->mtime)); | ||
446 | checkSum = getOctal (hp->checkSum, sizeof (hp->checkSum)); | ||
447 | major = getOctal (hp->devMajor, sizeof (hp->devMajor)); | ||
448 | minor = getOctal (hp->devMinor, sizeof (hp->devMinor)); | ||
449 | |||
450 | if ((mode < 0) || (uid < 0) || (gid < 0) || (size < 0)) { | ||
451 | if (badHeader==FALSE) | ||
452 | fprintf (stderr, "Bad tar header, skipping\n"); | ||
453 | |||
454 | badHeader = TRUE; | ||
455 | |||
456 | return; | ||
457 | } | ||
458 | |||
459 | badHeader = FALSE; | ||
460 | skipFileFlag = FALSE; | ||
461 | devFileFlag = FALSE; | ||
462 | |||
463 | /* | ||
464 | * Check for the file modes. | ||
465 | */ | ||
466 | hardLink = ((hp->typeFlag == TAR_TYPE_HARD_LINK) || | ||
467 | (hp->typeFlag == TAR_TYPE_HARD_LINK - '0')); | ||
468 | |||
469 | softLink = ((hp->typeFlag == TAR_TYPE_SOFT_LINK) || | ||
470 | (hp->typeFlag == TAR_TYPE_SOFT_LINK - '0')); | ||
471 | |||
472 | /* | ||
473 | * Check for a directory. | ||
474 | */ | ||
475 | if (outName[strlen (outName) - 1] == '/') | ||
476 | mode |= S_IFDIR; | ||
477 | |||
478 | /* | ||
479 | * Check for absolute paths in the file. | ||
480 | * If we find any, then warn the user and make them relative. | ||
481 | */ | ||
482 | if (*outName == '/') { | ||
483 | while (*outName == '/') | ||
484 | outName++; | ||
485 | |||
486 | if (warnedRoot==FALSE) { | ||
487 | fprintf (stderr, | ||
488 | "Absolute path detected, removing leading slashes\n"); | ||
489 | } | ||
490 | 456 | ||
491 | warnedRoot = TRUE; | 457 | if ((mode < 0) || (uid < 0) || (gid < 0) || (size < 0)) { |
492 | } | 458 | if (badHeader == FALSE) |
493 | 459 | fprintf(stderr, "Bad tar header, skipping\n"); | |
494 | /* | ||
495 | * See if we want this file to be restored. | ||
496 | * If not, then set up to skip it. | ||
497 | */ | ||
498 | if (wantFileName (outName, fileCount, fileTable) == FALSE) { | ||
499 | if ( !hardLink && !softLink && (S_ISREG (mode) || S_ISCHR (mode) | ||
500 | || S_ISBLK (mode) || S_ISSOCK(mode) || S_ISFIFO(mode) ) ) { | ||
501 | inHeader = (size == 0)? TRUE : FALSE; | ||
502 | dataCc = size; | ||
503 | } | ||
504 | 460 | ||
505 | skipFileFlag = TRUE; | 461 | badHeader = TRUE; |
506 | 462 | ||
507 | return; | 463 | return; |
508 | } | ||
509 | |||
510 | /* | ||
511 | * This file is to be handled. | ||
512 | * If we aren't extracting then just list information about the file. | ||
513 | */ | ||
514 | if (extractFlag==FALSE) { | ||
515 | if (verboseFlag==TRUE) { | ||
516 | printf ("%s %3d/%-d ", modeString (mode), uid, gid); | ||
517 | if( S_ISCHR (mode) || S_ISBLK (mode) ) | ||
518 | printf ("%4d,%4d %s ", major,minor, timeString (mtime)); | ||
519 | else | ||
520 | printf ("%9ld %s ", size, timeString (mtime)); | ||
521 | } | ||
522 | printf ("%s", outName); | ||
523 | |||
524 | if (hardLink) | ||
525 | printf (" (link to \"%s\")", hp->linkName); | ||
526 | else if (softLink) | ||
527 | printf (" (symlink to \"%s\")", hp->linkName); | ||
528 | else if (S_ISREG (mode) || S_ISCHR (mode) || S_ISBLK (mode) || | ||
529 | S_ISSOCK(mode) || S_ISFIFO(mode) ) { | ||
530 | inHeader = (size == 0)? TRUE : FALSE; | ||
531 | dataCc = size; | ||
532 | } | 464 | } |
533 | 465 | ||
534 | printf ("\n"); | 466 | badHeader = FALSE; |
467 | skipFileFlag = FALSE; | ||
468 | devFileFlag = FALSE; | ||
535 | 469 | ||
536 | return; | 470 | /* |
537 | } | 471 | * Check for the file modes. |
472 | */ | ||
473 | hardLink = ((hp->typeFlag == TAR_TYPE_HARD_LINK) || | ||
474 | (hp->typeFlag == TAR_TYPE_HARD_LINK - '0')); | ||
475 | |||
476 | softLink = ((hp->typeFlag == TAR_TYPE_SOFT_LINK) || | ||
477 | (hp->typeFlag == TAR_TYPE_SOFT_LINK - '0')); | ||
478 | |||
479 | /* | ||
480 | * Check for a directory. | ||
481 | */ | ||
482 | if (outName[strlen(outName) - 1] == '/') | ||
483 | mode |= S_IFDIR; | ||
484 | |||
485 | /* | ||
486 | * Check for absolute paths in the file. | ||
487 | * If we find any, then warn the user and make them relative. | ||
488 | */ | ||
489 | if (*outName == '/') { | ||
490 | while (*outName == '/') | ||
491 | outName++; | ||
538 | 492 | ||
539 | /* | 493 | if (warnedRoot == FALSE) { |
540 | * We really want to extract the file. | 494 | fprintf(stderr, |
541 | */ | 495 | "Absolute path detected, removing leading slashes\n"); |
542 | if (verboseFlag==TRUE) | 496 | } |
543 | printf ("x %s\n", outName); | ||
544 | 497 | ||
545 | if (hardLink) { | 498 | warnedRoot = TRUE; |
546 | if (link (hp->linkName, outName) < 0) { | ||
547 | perror (outName); | ||
548 | return; | ||
549 | } | 499 | } |
550 | /* Set the file time */ | 500 | |
551 | utb.actime = mtime; | 501 | /* |
552 | utb.modtime = mtime; | 502 | * See if we want this file to be restored. |
553 | utime (outName, &utb); | 503 | * If not, then set up to skip it. |
554 | /* Set the file permissions */ | 504 | */ |
555 | chown(outName, uid, gid); | 505 | if (wantFileName(outName, fileCount, fileTable) == FALSE) { |
556 | chmod(outName, mode); | 506 | if (!hardLink && !softLink && (S_ISREG(mode) || S_ISCHR(mode) |
557 | return; | 507 | || S_ISBLK(mode) || S_ISSOCK(mode) |
558 | } | 508 | || S_ISFIFO(mode))) { |
559 | 509 | inHeader = (size == 0) ? TRUE : FALSE; | |
560 | if (softLink) { | 510 | dataCc = size; |
561 | #ifdef S_ISLNK | 511 | } |
562 | if (symlink (hp->linkName, outName) < 0) { | 512 | |
563 | perror (outName); | 513 | skipFileFlag = TRUE; |
564 | return; | 514 | |
515 | return; | ||
565 | } | 516 | } |
566 | /* Try to change ownership of the symlink. | 517 | |
567 | * If libs doesn't support that, don't bother. | 518 | /* |
568 | * Changing the pointed-to file is the Wrong Thing(tm). | 519 | * This file is to be handled. |
520 | * If we aren't extracting then just list information about the file. | ||
569 | */ | 521 | */ |
522 | if (extractFlag == FALSE) { | ||
523 | if (verboseFlag == TRUE) { | ||
524 | printf("%s %3d/%-d ", modeString(mode), uid, gid); | ||
525 | if (S_ISCHR(mode) || S_ISBLK(mode)) | ||
526 | printf("%4d,%4d %s ", major, minor, timeString(mtime)); | ||
527 | else | ||
528 | printf("%9ld %s ", size, timeString(mtime)); | ||
529 | } | ||
530 | printf("%s", outName); | ||
531 | |||
532 | if (hardLink) | ||
533 | printf(" (link to \"%s\")", hp->linkName); | ||
534 | else if (softLink) | ||
535 | printf(" (symlink to \"%s\")", hp->linkName); | ||
536 | else if (S_ISREG(mode) || S_ISCHR(mode) || S_ISBLK(mode) || | ||
537 | S_ISSOCK(mode) || S_ISFIFO(mode)) { | ||
538 | inHeader = (size == 0) ? TRUE : FALSE; | ||
539 | dataCc = size; | ||
540 | } | ||
541 | |||
542 | printf("\n"); | ||
543 | |||
544 | return; | ||
545 | } | ||
546 | |||
547 | /* | ||
548 | * We really want to extract the file. | ||
549 | */ | ||
550 | if (verboseFlag == TRUE) | ||
551 | printf("x %s\n", outName); | ||
552 | |||
553 | if (hardLink) { | ||
554 | if (link(hp->linkName, outName) < 0) { | ||
555 | perror(outName); | ||
556 | return; | ||
557 | } | ||
558 | /* Set the file time */ | ||
559 | utb.actime = mtime; | ||
560 | utb.modtime = mtime; | ||
561 | utime(outName, &utb); | ||
562 | /* Set the file permissions */ | ||
563 | chown(outName, uid, gid); | ||
564 | chmod(outName, mode); | ||
565 | return; | ||
566 | } | ||
567 | |||
568 | if (softLink) { | ||
569 | #ifdef S_ISLNK | ||
570 | if (symlink(hp->linkName, outName) < 0) { | ||
571 | perror(outName); | ||
572 | return; | ||
573 | } | ||
574 | /* Try to change ownership of the symlink. | ||
575 | * If libs doesn't support that, don't bother. | ||
576 | * Changing the pointed-to file is the Wrong Thing(tm). | ||
577 | */ | ||
570 | #if (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1) | 578 | #if (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1) |
571 | lchown(outName, uid, gid); | 579 | lchown(outName, uid, gid); |
572 | #endif | 580 | #endif |
573 | 581 | ||
574 | /* Do not change permissions or date on symlink, | 582 | /* Do not change permissions or date on symlink, |
575 | * since it changes the pointed to file instead. duh. */ | 583 | * since it changes the pointed to file instead. duh. */ |
576 | #else | 584 | #else |
577 | fprintf (stderr, "Cannot create symbolic links\n"); | 585 | fprintf(stderr, "Cannot create symbolic links\n"); |
578 | #endif | 586 | #endif |
579 | return; | 587 | return; |
580 | } | ||
581 | |||
582 | /* Set the umask for this process so it doesn't | ||
583 | * screw things up. */ | ||
584 | umask(0); | ||
585 | |||
586 | /* | ||
587 | * If the file is a directory, then just create the path. | ||
588 | */ | ||
589 | if (S_ISDIR (mode)) { | ||
590 | if (createPath (outName, mode)==TRUE) { | ||
591 | /* Set the file time */ | ||
592 | utb.actime = mtime; | ||
593 | utb.modtime = mtime; | ||
594 | utime (outName, &utb); | ||
595 | /* Set the file permissions */ | ||
596 | chown(outName, uid, gid); | ||
597 | chmod(outName, mode); | ||
598 | return; | ||
599 | } | 588 | } |
600 | return; | 589 | |
601 | } | 590 | /* Set the umask for this process so it doesn't |
602 | 591 | * screw things up. */ | |
603 | /* | 592 | umask(0); |
604 | * There is a file to write. | 593 | |
605 | * First create the path to it if necessary with default permissions. | 594 | /* |
606 | */ | 595 | * If the file is a directory, then just create the path. |
607 | createPath (outName, 0777); | 596 | */ |
608 | 597 | if (S_ISDIR(mode)) { | |
609 | inHeader = (size == 0)? TRUE : FALSE; | 598 | if (createPath(outName, mode) == TRUE) { |
610 | dataCc = size; | 599 | /* Set the file time */ |
611 | 600 | utb.actime = mtime; | |
612 | /* | 601 | utb.modtime = mtime; |
613 | * Start the output file. | 602 | utime(outName, &utb); |
614 | */ | 603 | /* Set the file permissions */ |
615 | if (tostdoutFlag == TRUE) | 604 | chown(outName, uid, gid); |
616 | outFd = fileno(stdout); | 605 | chmod(outName, mode); |
617 | else { | 606 | return; |
618 | if ( S_ISCHR(mode) || S_ISBLK(mode) || S_ISSOCK(mode) ) { | 607 | } |
619 | devFileFlag = TRUE; | 608 | return; |
620 | outFd = mknod (outName, mode, makedev(major, minor) ); | ||
621 | } | 609 | } |
622 | else if (S_ISFIFO(mode) ) { | 610 | |
623 | devFileFlag = TRUE; | 611 | /* |
624 | outFd = mkfifo(outName, mode); | 612 | * There is a file to write. |
625 | } else { | 613 | * First create the path to it if necessary with default permissions. |
626 | outFd = open (outName, O_WRONLY | O_CREAT | O_TRUNC, mode); | 614 | */ |
615 | createPath(outName, 0777); | ||
616 | |||
617 | inHeader = (size == 0) ? TRUE : FALSE; | ||
618 | dataCc = size; | ||
619 | |||
620 | /* | ||
621 | * Start the output file. | ||
622 | */ | ||
623 | if (tostdoutFlag == TRUE) | ||
624 | outFd = fileno(stdout); | ||
625 | else { | ||
626 | if (S_ISCHR(mode) || S_ISBLK(mode) || S_ISSOCK(mode)) { | ||
627 | devFileFlag = TRUE; | ||
628 | outFd = mknod(outName, mode, makedev(major, minor)); | ||
629 | } else if (S_ISFIFO(mode)) { | ||
630 | devFileFlag = TRUE; | ||
631 | outFd = mkfifo(outName, mode); | ||
632 | } else { | ||
633 | outFd = open(outName, O_WRONLY | O_CREAT | O_TRUNC, mode); | ||
634 | } | ||
635 | if (outFd < 0) { | ||
636 | perror(outName); | ||
637 | skipFileFlag = TRUE; | ||
638 | return; | ||
639 | } | ||
640 | /* Set the file time */ | ||
641 | utb.actime = mtime; | ||
642 | utb.modtime = mtime; | ||
643 | utime(outName, &utb); | ||
644 | /* Set the file permissions */ | ||
645 | chown(outName, uid, gid); | ||
646 | chmod(outName, mode); | ||
627 | } | 647 | } |
628 | if (outFd < 0) { | 648 | |
629 | perror (outName); | 649 | |
630 | skipFileFlag = TRUE; | 650 | /* |
631 | return; | 651 | * If the file is empty, then that's all we need to do. |
652 | */ | ||
653 | if (size == 0 && (tostdoutFlag == FALSE) && (devFileFlag == FALSE)) { | ||
654 | close(outFd); | ||
655 | outFd = -1; | ||
632 | } | 656 | } |
633 | /* Set the file time */ | ||
634 | utb.actime = mtime; | ||
635 | utb.modtime = mtime; | ||
636 | utime (outName, &utb); | ||
637 | /* Set the file permissions */ | ||
638 | chown(outName, uid, gid); | ||
639 | chmod(outName, mode); | ||
640 | } | ||
641 | |||
642 | |||
643 | /* | ||
644 | * If the file is empty, then that's all we need to do. | ||
645 | */ | ||
646 | if (size == 0 && (tostdoutFlag == FALSE) && (devFileFlag == FALSE)) { | ||
647 | close (outFd); | ||
648 | outFd = -1; | ||
649 | } | ||
650 | } | 657 | } |
651 | 658 | ||
652 | 659 | ||
653 | /* | 660 | /* |
654 | * Handle a data block of some specified size that was read. | 661 | * Handle a data block of some specified size that was read. |
655 | */ | 662 | */ |
656 | static void readData (const char *cp, int count) | 663 | static void readData(const char *cp, int count) |
657 | { | 664 | { |
658 | /* | 665 | /* |
659 | * Reduce the amount of data left in this file. | 666 | * Reduce the amount of data left in this file. |
660 | * If there is no more data left, then we need to read | 667 | * If there is no more data left, then we need to read |
661 | * the header again. | 668 | * the header again. |
662 | */ | 669 | */ |
663 | dataCc -= count; | 670 | dataCc -= count; |
664 | |||
665 | if (dataCc <= 0) | ||
666 | inHeader = TRUE; | ||
667 | 671 | ||
668 | /* | 672 | if (dataCc <= 0) |
669 | * If we aren't extracting files or this file is being | 673 | inHeader = TRUE; |
670 | * skipped then do nothing more. | 674 | |
671 | */ | 675 | /* |
672 | if (extractFlag==FALSE || skipFileFlag==TRUE) | 676 | * If we aren't extracting files or this file is being |
673 | return; | 677 | * skipped then do nothing more. |
674 | 678 | */ | |
675 | /* | 679 | if (extractFlag == FALSE || skipFileFlag == TRUE) |
676 | * Write the data to the output file. | 680 | return; |
677 | */ | 681 | |
678 | if (fullWrite (outFd, cp, count) < 0) { | 682 | /* |
679 | perror (outName); | 683 | * Write the data to the output file. |
680 | if (tostdoutFlag == FALSE) { | 684 | */ |
681 | close (outFd); | 685 | if (fullWrite(outFd, cp, count) < 0) { |
682 | outFd = -1; | 686 | perror(outName); |
687 | if (tostdoutFlag == FALSE) { | ||
688 | close(outFd); | ||
689 | outFd = -1; | ||
690 | } | ||
691 | skipFileFlag = TRUE; | ||
692 | return; | ||
683 | } | 693 | } |
684 | skipFileFlag = TRUE; | ||
685 | return; | ||
686 | } | ||
687 | |||
688 | /* | ||
689 | * Check if we are done writing to the file now. | ||
690 | */ | ||
691 | if (dataCc <= 0 && tostdoutFlag == FALSE) { | ||
692 | struct utimbuf utb; | ||
693 | if (close (outFd)) | ||
694 | perror (outName); | ||
695 | 694 | ||
696 | /* Set the file time */ | 695 | /* |
697 | utb.actime = mtime; | 696 | * Check if we are done writing to the file now. |
698 | utb.modtime = mtime; | 697 | */ |
699 | utime (outName, &utb); | 698 | if (dataCc <= 0 && tostdoutFlag == FALSE) { |
700 | /* Set the file permissions */ | 699 | struct utimbuf utb; |
701 | chown(outName, uid, gid); | 700 | |
702 | chmod(outName, mode); | 701 | if (close(outFd)) |
702 | perror(outName); | ||
703 | 703 | ||
704 | outFd = -1; | 704 | /* Set the file time */ |
705 | } | 705 | utb.actime = mtime; |
706 | utb.modtime = mtime; | ||
707 | utime(outName, &utb); | ||
708 | /* Set the file permissions */ | ||
709 | chown(outName, uid, gid); | ||
710 | chmod(outName, mode); | ||
711 | |||
712 | outFd = -1; | ||
713 | } | ||
706 | } | 714 | } |
707 | 715 | ||
708 | 716 | ||
@@ -712,40 +720,40 @@ static void readData (const char *cp, int count) | |||
712 | * Returns TRUE if the file is selected. | 720 | * Returns TRUE if the file is selected. |
713 | */ | 721 | */ |
714 | static int | 722 | static int |
715 | wantFileName (const char *fileName, int fileCount, char **fileTable) | 723 | wantFileName(const char *fileName, int fileCount, char **fileTable) |
716 | { | 724 | { |
717 | const char *pathName; | 725 | const char *pathName; |
718 | int fileLength; | 726 | int fileLength; |
719 | int pathLength; | 727 | int pathLength; |
720 | 728 | ||
721 | /* | 729 | /* |
722 | * If there are no files in the list, then the file is wanted. | 730 | * If there are no files in the list, then the file is wanted. |
723 | */ | 731 | */ |
724 | if (fileCount == 0) | 732 | if (fileCount == 0) |
725 | return TRUE; | 733 | return TRUE; |
726 | 734 | ||
727 | fileLength = strlen (fileName); | 735 | fileLength = strlen(fileName); |
728 | 736 | ||
729 | /* | 737 | /* |
730 | * Check each of the test paths. | 738 | * Check each of the test paths. |
731 | */ | 739 | */ |
732 | while (fileCount-- > 0) { | 740 | while (fileCount-- > 0) { |
733 | pathName = *fileTable++; | 741 | pathName = *fileTable++; |
734 | 742 | ||
735 | pathLength = strlen (pathName); | 743 | pathLength = strlen(pathName); |
736 | 744 | ||
737 | if (fileLength < pathLength) | 745 | if (fileLength < pathLength) |
738 | continue; | 746 | continue; |
739 | 747 | ||
740 | if (memcmp (fileName, pathName, pathLength) != 0) | 748 | if (memcmp(fileName, pathName, pathLength) != 0) |
741 | continue; | 749 | continue; |
742 | 750 | ||
743 | if ((fileLength == pathLength) || (fileName[pathLength] == '/')) { | 751 | if ((fileLength == pathLength) || (fileName[pathLength] == '/')) { |
744 | return TRUE; | 752 | return TRUE; |
753 | } | ||
745 | } | 754 | } |
746 | } | ||
747 | 755 | ||
748 | return FALSE; | 756 | return FALSE; |
749 | } | 757 | } |
750 | 758 | ||
751 | /* | 759 | /* |
@@ -753,34 +761,34 @@ wantFileName (const char *fileName, int fileCount, char **fileTable) | |||
753 | * spaces on both sides of the number and with an optional null character | 761 | * spaces on both sides of the number and with an optional null character |
754 | * at the end. Returns -1 on an illegal format. | 762 | * at the end. Returns -1 on an illegal format. |
755 | */ | 763 | */ |
756 | static long getOctal (const char *cp, int len) | 764 | static long getOctal(const char *cp, int len) |
757 | { | 765 | { |
758 | long val; | 766 | long val; |
759 | 767 | ||
760 | while ((len > 0) && (*cp == ' ')) { | 768 | while ((len > 0) && (*cp == ' ')) { |
761 | cp++; | 769 | cp++; |
762 | len--; | 770 | len--; |
763 | } | 771 | } |
764 | 772 | ||
765 | if ((len == 0) || !isOctal (*cp)) | 773 | if ((len == 0) || !isOctal(*cp)) |
766 | return -1; | 774 | return -1; |
767 | 775 | ||
768 | val = 0; | 776 | val = 0; |
769 | 777 | ||
770 | while ((len > 0) && isOctal (*cp)) { | 778 | while ((len > 0) && isOctal(*cp)) { |
771 | val = val * 8 + *cp++ - '0'; | 779 | val = val * 8 + *cp++ - '0'; |
772 | len--; | 780 | len--; |
773 | } | 781 | } |
774 | 782 | ||
775 | while ((len > 0) && (*cp == ' ')) { | 783 | while ((len > 0) && (*cp == ' ')) { |
776 | cp++; | 784 | cp++; |
777 | len--; | 785 | len--; |
778 | } | 786 | } |
779 | 787 | ||
780 | if ((len > 0) && *cp) | 788 | if ((len > 0) && *cp) |
781 | return -1; | 789 | return -1; |
782 | 790 | ||
783 | return val; | 791 | return val; |
784 | } | 792 | } |
785 | 793 | ||
786 | 794 | ||
@@ -795,65 +803,65 @@ static long getOctal (const char *cp, int len) | |||
795 | /* | 803 | /* |
796 | * Write a tar file containing the specified files. | 804 | * Write a tar file containing the specified files. |
797 | */ | 805 | */ |
798 | static void writeTarFile (int fileCount, char **fileTable) | 806 | static void writeTarFile(int fileCount, char **fileTable) |
799 | { | 807 | { |
800 | struct stat statbuf; | 808 | struct stat statbuf; |
801 | 809 | ||
802 | /* | 810 | /* |
803 | * Make sure there is at least one file specified. | 811 | * Make sure there is at least one file specified. |
804 | */ | 812 | */ |
805 | if (fileCount <= 0) { | 813 | if (fileCount <= 0) { |
806 | fprintf (stderr, "No files specified to be saved\n"); | 814 | fprintf(stderr, "No files specified to be saved\n"); |
807 | errorFlag = TRUE; | 815 | errorFlag = TRUE; |
808 | } | 816 | } |
809 | 817 | ||
810 | /* | 818 | /* |
811 | * Create the tar file for writing. | 819 | * Create the tar file for writing. |
812 | */ | 820 | */ |
813 | if ((tarName == NULL) || !strcmp (tarName, "-")) { | 821 | if ((tarName == NULL) || !strcmp(tarName, "-")) { |
814 | tostdoutFlag = TRUE; | 822 | tostdoutFlag = TRUE; |
815 | tarFd = fileno(stdout); | 823 | tarFd = fileno(stdout); |
816 | } else | 824 | } else |
817 | tarFd = open (tarName, O_WRONLY | O_CREAT | O_TRUNC, 0666); | 825 | tarFd = open(tarName, O_WRONLY | O_CREAT | O_TRUNC, 0666); |
818 | 826 | ||
819 | if (tarFd < 0) { | 827 | if (tarFd < 0) { |
820 | perror (tarName); | 828 | perror(tarName); |
821 | errorFlag = TRUE; | 829 | errorFlag = TRUE; |
822 | return; | 830 | return; |
823 | } | 831 | } |
824 | 832 | ||
825 | /* | 833 | /* |
826 | * Get the device and inode of the tar file for checking later. | 834 | * Get the device and inode of the tar file for checking later. |
827 | */ | 835 | */ |
828 | if (fstat (tarFd, &statbuf) < 0) { | 836 | if (fstat(tarFd, &statbuf) < 0) { |
829 | perror (tarName); | 837 | perror(tarName); |
830 | errorFlag = TRUE; | 838 | errorFlag = TRUE; |
831 | goto done; | 839 | goto done; |
832 | } | 840 | } |
833 | 841 | ||
834 | tarDev = statbuf.st_dev; | 842 | tarDev = statbuf.st_dev; |
835 | tarInode = statbuf.st_ino; | 843 | tarInode = statbuf.st_ino; |
836 | 844 | ||
837 | /* | 845 | /* |
838 | * Append each file name into the archive file. | 846 | * Append each file name into the archive file. |
839 | * Follow symbolic links for these top level file names. | 847 | * Follow symbolic links for these top level file names. |
840 | */ | 848 | */ |
841 | while (errorFlag==FALSE && (fileCount-- > 0)) { | 849 | while (errorFlag == FALSE && (fileCount-- > 0)) { |
842 | saveFile (*fileTable++, FALSE); | 850 | saveFile(*fileTable++, FALSE); |
843 | } | 851 | } |
844 | 852 | ||
845 | /* | 853 | /* |
846 | * Now write an empty block of zeroes to end the archive. | 854 | * Now write an empty block of zeroes to end the archive. |
847 | */ | 855 | */ |
848 | writeTarBlock ("", 1); | 856 | writeTarBlock("", 1); |
849 | 857 | ||
850 | 858 | ||
851 | done: | 859 | done: |
852 | /* | 860 | /* |
853 | * Close the tar file and check for errors if it was opened. | 861 | * Close the tar file and check for errors if it was opened. |
854 | */ | 862 | */ |
855 | if ((tostdoutFlag == FALSE) && (tarFd >= 0) && (close (tarFd) < 0)) | 863 | if ((tostdoutFlag == FALSE) && (tarFd >= 0) && (close(tarFd) < 0)) |
856 | perror (tarName); | 864 | perror(tarName); |
857 | } | 865 | } |
858 | 866 | ||
859 | /* | 867 | /* |
@@ -863,73 +871,73 @@ static void writeTarFile (int fileCount, char **fileTable) | |||
863 | * flag indicates whether or not we want to see symbolic links as | 871 | * flag indicates whether or not we want to see symbolic links as |
864 | * they really are, instead of blindly following them. | 872 | * they really are, instead of blindly following them. |
865 | */ | 873 | */ |
866 | static void saveFile (const char *fileName, int seeLinks) | 874 | static void saveFile(const char *fileName, int seeLinks) |
867 | { | 875 | { |
868 | int status; | 876 | int status; |
869 | struct stat statbuf; | 877 | struct stat statbuf; |
870 | 878 | ||
871 | if (verboseFlag==TRUE) | 879 | if (verboseFlag == TRUE) |
872 | printf ("a %s\n", fileName); | 880 | printf("a %s\n", fileName); |
873 | 881 | ||
874 | /* | 882 | /* |
875 | * Check that the file name will fit in the header. | 883 | * Check that the file name will fit in the header. |
876 | */ | 884 | */ |
877 | if (strlen (fileName) >= TAR_NAME_SIZE) { | 885 | if (strlen(fileName) >= TAR_NAME_SIZE) { |
878 | fprintf (stderr, "%s: File name is too long\n", fileName); | 886 | fprintf(stderr, "%s: File name is too long\n", fileName); |
879 | 887 | ||
880 | return; | 888 | return; |
881 | } | 889 | } |
882 | 890 | ||
883 | /* | 891 | /* |
884 | * Find out about the file. | 892 | * Find out about the file. |
885 | */ | 893 | */ |
886 | #ifdef S_ISLNK | 894 | #ifdef S_ISLNK |
887 | if (seeLinks==TRUE) | 895 | if (seeLinks == TRUE) |
888 | status = lstat (fileName, &statbuf); | 896 | status = lstat(fileName, &statbuf); |
889 | else | 897 | else |
890 | #endif | 898 | #endif |
891 | status = stat (fileName, &statbuf); | 899 | status = stat(fileName, &statbuf); |
892 | 900 | ||
893 | if (status < 0) { | 901 | if (status < 0) { |
894 | perror (fileName); | 902 | perror(fileName); |
903 | |||
904 | return; | ||
905 | } | ||
895 | 906 | ||
896 | return; | 907 | /* |
897 | } | 908 | * Make sure we aren't trying to save our file into itself. |
909 | */ | ||
910 | if ((statbuf.st_dev == tarDev) && (statbuf.st_ino == tarInode)) { | ||
911 | fprintf(stderr, "Skipping saving of archive file itself\n"); | ||
898 | 912 | ||
899 | /* | 913 | return; |
900 | * Make sure we aren't trying to save our file into itself. | 914 | } |
901 | */ | ||
902 | if ((statbuf.st_dev == tarDev) && (statbuf.st_ino == tarInode)) { | ||
903 | fprintf (stderr, "Skipping saving of archive file itself\n"); | ||
904 | 915 | ||
905 | return; | 916 | /* |
906 | } | 917 | * Check the type of file. |
918 | */ | ||
919 | mode = statbuf.st_mode; | ||
907 | 920 | ||
908 | /* | 921 | if (S_ISDIR(mode)) { |
909 | * Check the type of file. | 922 | saveDirectory(fileName, &statbuf); |
910 | */ | ||
911 | mode = statbuf.st_mode; | ||
912 | 923 | ||
913 | if (S_ISDIR (mode)) { | 924 | return; |
914 | saveDirectory (fileName, &statbuf); | 925 | } |
926 | if (S_ISREG(mode)) { | ||
927 | saveRegularFile(fileName, &statbuf); | ||
915 | 928 | ||
916 | return; | 929 | return; |
917 | } | 930 | } |
918 | if (S_ISREG (mode)) { | ||
919 | saveRegularFile (fileName, &statbuf); | ||
920 | 931 | ||
921 | return; | 932 | /* Some day add support for tarring these up... but not today. :) */ |
922 | } | ||
923 | |||
924 | /* Some day add support for tarring these up... but not today. :) */ | ||
925 | // if (S_ISLNK(mode) || S_ISFIFO(mode) || S_ISBLK(mode) || S_ISCHR (mode) ) { | 933 | // if (S_ISLNK(mode) || S_ISFIFO(mode) || S_ISBLK(mode) || S_ISCHR (mode) ) { |
926 | // fprintf (stderr, "%s: This version of tar can't store this type of file\n", fileName); | 934 | // fprintf (stderr, "%s: This version of tar can't store this type of file\n", fileName); |
927 | // } | 935 | // } |
928 | 936 | ||
929 | /* | 937 | /* |
930 | * The file is a strange type of file, ignore it. | 938 | * The file is a strange type of file, ignore it. |
931 | */ | 939 | */ |
932 | fprintf (stderr, "%s: not a directory or regular file\n", fileName); | 940 | fprintf(stderr, "%s: not a directory or regular file\n", fileName); |
933 | } | 941 | } |
934 | 942 | ||
935 | 943 | ||
@@ -937,173 +945,172 @@ static void saveFile (const char *fileName, int seeLinks) | |||
937 | * Save a regular file to the tar file. | 945 | * Save a regular file to the tar file. |
938 | */ | 946 | */ |
939 | static void | 947 | static void |
940 | saveRegularFile (const char *fileName, const struct stat *statbuf) | 948 | saveRegularFile(const char *fileName, const struct stat *statbuf) |
941 | { | 949 | { |
942 | int sawEof; | 950 | int sawEof; |
943 | int fileFd; | 951 | int fileFd; |
944 | int cc; | 952 | int cc; |
945 | int dataCount; | 953 | int dataCount; |
946 | long fullDataCount; | 954 | long fullDataCount; |
947 | char data[TAR_BLOCK_SIZE * 16]; | 955 | char data[TAR_BLOCK_SIZE * 16]; |
948 | |||
949 | /* | ||
950 | * Open the file for reading. | ||
951 | */ | ||
952 | fileFd = open (fileName, O_RDONLY); | ||
953 | |||
954 | if (fileFd < 0) { | ||
955 | perror (fileName); | ||
956 | |||
957 | return; | ||
958 | } | ||
959 | |||
960 | /* | ||
961 | * Write out the header for the file. | ||
962 | */ | ||
963 | writeHeader (fileName, statbuf); | ||
964 | |||
965 | /* | ||
966 | * Write the data blocks of the file. | ||
967 | * We must be careful to write the amount of data that the stat | ||
968 | * buffer indicated, even if the file has changed size. Otherwise | ||
969 | * the tar file will be incorrect. | ||
970 | */ | ||
971 | fullDataCount = statbuf->st_size; | ||
972 | sawEof = FALSE; | ||
973 | |||
974 | while (fullDataCount > 0) { | ||
975 | /* | ||
976 | * Get the amount to write this iteration which is | ||
977 | * the minumum of the amount left to write and the | ||
978 | * buffer size. | ||
979 | */ | ||
980 | dataCount = sizeof (data); | ||
981 | |||
982 | if (dataCount > fullDataCount) | ||
983 | dataCount = (int) fullDataCount; | ||
984 | 956 | ||
985 | /* | 957 | /* |
986 | * Read the data from the file if we haven't seen the | 958 | * Open the file for reading. |
987 | * end of file yet. | ||
988 | */ | 959 | */ |
989 | cc = 0; | 960 | fileFd = open(fileName, O_RDONLY); |
990 | |||
991 | if (sawEof==FALSE) { | ||
992 | cc = fullRead (fileFd, data, dataCount); | ||
993 | 961 | ||
994 | if (cc < 0) { | 962 | if (fileFd < 0) { |
995 | perror (fileName); | 963 | perror(fileName); |
996 | |||
997 | (void) close (fileFd); | ||
998 | errorFlag = TRUE; | ||
999 | 964 | ||
1000 | return; | 965 | return; |
1001 | } | ||
1002 | |||
1003 | /* | ||
1004 | * If the file ended too soon, complain and set | ||
1005 | * a flag so we will zero fill the rest of it. | ||
1006 | */ | ||
1007 | if (cc < dataCount) { | ||
1008 | fprintf (stderr, | ||
1009 | "%s: Short read - zero filling", fileName); | ||
1010 | |||
1011 | sawEof = TRUE; | ||
1012 | } | ||
1013 | } | 966 | } |
1014 | 967 | ||
1015 | /* | 968 | /* |
1016 | * Zero fill the rest of the data if necessary. | 969 | * Write out the header for the file. |
1017 | */ | 970 | */ |
1018 | if (cc < dataCount) | 971 | writeHeader(fileName, statbuf); |
1019 | memset (data + cc, 0, dataCount - cc); | ||
1020 | 972 | ||
1021 | /* | 973 | /* |
1022 | * Write the buffer to the TAR file. | 974 | * Write the data blocks of the file. |
975 | * We must be careful to write the amount of data that the stat | ||
976 | * buffer indicated, even if the file has changed size. Otherwise | ||
977 | * the tar file will be incorrect. | ||
1023 | */ | 978 | */ |
1024 | writeTarBlock (data, dataCount); | 979 | fullDataCount = statbuf->st_size; |
1025 | 980 | sawEof = FALSE; | |
1026 | fullDataCount -= dataCount; | 981 | |
1027 | } | 982 | while (fullDataCount > 0) { |
983 | /* | ||
984 | * Get the amount to write this iteration which is | ||
985 | * the minumum of the amount left to write and the | ||
986 | * buffer size. | ||
987 | */ | ||
988 | dataCount = sizeof(data); | ||
989 | |||
990 | if (dataCount > fullDataCount) | ||
991 | dataCount = (int) fullDataCount; | ||
992 | |||
993 | /* | ||
994 | * Read the data from the file if we haven't seen the | ||
995 | * end of file yet. | ||
996 | */ | ||
997 | cc = 0; | ||
998 | |||
999 | if (sawEof == FALSE) { | ||
1000 | cc = fullRead(fileFd, data, dataCount); | ||
1001 | |||
1002 | if (cc < 0) { | ||
1003 | perror(fileName); | ||
1004 | |||
1005 | (void) close(fileFd); | ||
1006 | errorFlag = TRUE; | ||
1007 | |||
1008 | return; | ||
1009 | } | ||
1010 | |||
1011 | /* | ||
1012 | * If the file ended too soon, complain and set | ||
1013 | * a flag so we will zero fill the rest of it. | ||
1014 | */ | ||
1015 | if (cc < dataCount) { | ||
1016 | fprintf(stderr, "%s: Short read - zero filling", fileName); | ||
1017 | |||
1018 | sawEof = TRUE; | ||
1019 | } | ||
1020 | } | ||
1021 | |||
1022 | /* | ||
1023 | * Zero fill the rest of the data if necessary. | ||
1024 | */ | ||
1025 | if (cc < dataCount) | ||
1026 | memset(data + cc, 0, dataCount - cc); | ||
1027 | |||
1028 | /* | ||
1029 | * Write the buffer to the TAR file. | ||
1030 | */ | ||
1031 | writeTarBlock(data, dataCount); | ||
1032 | |||
1033 | fullDataCount -= dataCount; | ||
1034 | } | ||
1028 | 1035 | ||
1029 | /* | 1036 | /* |
1030 | * Close the file. | 1037 | * Close the file. |
1031 | */ | 1038 | */ |
1032 | if ((tostdoutFlag == FALSE) && close (fileFd) < 0) | 1039 | if ((tostdoutFlag == FALSE) && close(fileFd) < 0) |
1033 | fprintf (stderr, "%s: close: %s\n", fileName, strerror (errno)); | 1040 | fprintf(stderr, "%s: close: %s\n", fileName, strerror(errno)); |
1034 | } | 1041 | } |
1035 | 1042 | ||
1036 | 1043 | ||
1037 | /* | 1044 | /* |
1038 | * Save a directory and all of its files to the tar file. | 1045 | * Save a directory and all of its files to the tar file. |
1039 | */ | 1046 | */ |
1040 | static void saveDirectory (const char *dirName, const struct stat *statbuf) | 1047 | static void saveDirectory(const char *dirName, const struct stat *statbuf) |
1041 | { | 1048 | { |
1042 | DIR *dir; | 1049 | DIR *dir; |
1043 | struct dirent *entry; | 1050 | struct dirent *entry; |
1044 | int needSlash; | 1051 | int needSlash; |
1045 | char fullName[PATH_MAX + 1]; | 1052 | char fullName[PATH_MAX + 1]; |
1046 | 1053 | ||
1047 | /* | 1054 | /* |
1048 | * Construct the directory name as used in the tar file by appending | 1055 | * Construct the directory name as used in the tar file by appending |
1049 | * a slash character to it. | 1056 | * a slash character to it. |
1050 | */ | 1057 | */ |
1051 | strcpy (fullName, dirName); | 1058 | strcpy(fullName, dirName); |
1052 | strcat (fullName, "/"); | 1059 | strcat(fullName, "/"); |
1053 | 1060 | ||
1054 | /* | 1061 | /* |
1055 | * Write out the header for the directory entry. | 1062 | * Write out the header for the directory entry. |
1056 | */ | 1063 | */ |
1057 | writeHeader (fullName, statbuf); | 1064 | writeHeader(fullName, statbuf); |
1058 | |||
1059 | /* | ||
1060 | * Open the directory. | ||
1061 | */ | ||
1062 | dir = opendir (dirName); | ||
1063 | |||
1064 | if (dir == NULL) { | ||
1065 | fprintf (stderr, "Cannot read directory \"%s\": %s\n", | ||
1066 | dirName, strerror (errno)); | ||
1067 | |||
1068 | return; | ||
1069 | } | ||
1070 | |||
1071 | /* | ||
1072 | * See if a slash is needed. | ||
1073 | */ | ||
1074 | needSlash = (*dirName && (dirName[strlen (dirName) - 1] != '/')); | ||
1075 | |||
1076 | /* | ||
1077 | * Read all of the directory entries and check them, | ||
1078 | * except for the current and parent directory entries. | ||
1079 | */ | ||
1080 | while (errorFlag==FALSE && ((entry = readdir (dir)) != NULL)) { | ||
1081 | if ((strcmp (entry->d_name, ".") == 0) || | ||
1082 | (strcmp (entry->d_name, "..") == 0)) { | ||
1083 | continue; | ||
1084 | } | ||
1085 | 1065 | ||
1086 | /* | 1066 | /* |
1087 | * Build the full path name to the file. | 1067 | * Open the directory. |
1088 | */ | 1068 | */ |
1089 | strcpy (fullName, dirName); | 1069 | dir = opendir(dirName); |
1070 | |||
1071 | if (dir == NULL) { | ||
1072 | fprintf(stderr, "Cannot read directory \"%s\": %s\n", | ||
1073 | dirName, strerror(errno)); | ||
1090 | 1074 | ||
1091 | if (needSlash) | 1075 | return; |
1092 | strcat (fullName, "/"); | 1076 | } |
1093 | 1077 | ||
1094 | strcat (fullName, entry->d_name); | 1078 | /* |
1079 | * See if a slash is needed. | ||
1080 | */ | ||
1081 | needSlash = (*dirName && (dirName[strlen(dirName) - 1] != '/')); | ||
1095 | 1082 | ||
1096 | /* | 1083 | /* |
1097 | * Write this file to the tar file, noticing whether or not | 1084 | * Read all of the directory entries and check them, |
1098 | * the file is a symbolic link. | 1085 | * except for the current and parent directory entries. |
1099 | */ | 1086 | */ |
1100 | saveFile (fullName, TRUE); | 1087 | while (errorFlag == FALSE && ((entry = readdir(dir)) != NULL)) { |
1101 | } | 1088 | if ((strcmp(entry->d_name, ".") == 0) || |
1089 | (strcmp(entry->d_name, "..") == 0)) { | ||
1090 | continue; | ||
1091 | } | ||
1092 | |||
1093 | /* | ||
1094 | * Build the full path name to the file. | ||
1095 | */ | ||
1096 | strcpy(fullName, dirName); | ||
1097 | |||
1098 | if (needSlash) | ||
1099 | strcat(fullName, "/"); | ||
1100 | |||
1101 | strcat(fullName, entry->d_name); | ||
1102 | |||
1103 | /* | ||
1104 | * Write this file to the tar file, noticing whether or not | ||
1105 | * the file is a symbolic link. | ||
1106 | */ | ||
1107 | saveFile(fullName, TRUE); | ||
1108 | } | ||
1102 | 1109 | ||
1103 | /* | 1110 | /* |
1104 | * All done, close the directory. | 1111 | * All done, close the directory. |
1105 | */ | 1112 | */ |
1106 | closedir (dir); | 1113 | closedir(dir); |
1107 | } | 1114 | } |
1108 | 1115 | ||
1109 | 1116 | ||
@@ -1111,54 +1118,54 @@ static void saveDirectory (const char *dirName, const struct stat *statbuf) | |||
1111 | * Write a tar header for the specified file name and status. | 1118 | * Write a tar header for the specified file name and status. |
1112 | * It is assumed that the file name fits. | 1119 | * It is assumed that the file name fits. |
1113 | */ | 1120 | */ |
1114 | static void writeHeader (const char *fileName, const struct stat *statbuf) | 1121 | static void writeHeader(const char *fileName, const struct stat *statbuf) |
1115 | { | 1122 | { |
1116 | long checkSum; | 1123 | long checkSum; |
1117 | const unsigned char *cp; | 1124 | const unsigned char *cp; |
1118 | int len; | 1125 | int len; |
1119 | TarHeader header; | 1126 | TarHeader header; |
1120 | 1127 | ||
1121 | /* | 1128 | /* |
1122 | * Zero the header block in preparation for filling it in. | 1129 | * Zero the header block in preparation for filling it in. |
1123 | */ | 1130 | */ |
1124 | memset ((char *) &header, 0, sizeof (header)); | 1131 | memset((char *) &header, 0, sizeof(header)); |
1125 | 1132 | ||
1126 | /* | 1133 | /* |
1127 | * Fill in the header. | 1134 | * Fill in the header. |
1128 | */ | 1135 | */ |
1129 | strcpy (header.name, fileName); | 1136 | strcpy(header.name, fileName); |
1130 | 1137 | ||
1131 | strncpy (header.magic, TAR_MAGIC, sizeof (header.magic)); | 1138 | strncpy(header.magic, TAR_MAGIC, sizeof(header.magic)); |
1132 | strncpy (header.version, TAR_VERSION, sizeof (header.version)); | 1139 | strncpy(header.version, TAR_VERSION, sizeof(header.version)); |
1133 | 1140 | ||
1134 | putOctal (header.mode, sizeof (header.mode), statbuf->st_mode & 0777); | 1141 | putOctal(header.mode, sizeof(header.mode), statbuf->st_mode & 0777); |
1135 | putOctal (header.uid, sizeof (header.uid), statbuf->st_uid); | 1142 | putOctal(header.uid, sizeof(header.uid), statbuf->st_uid); |
1136 | putOctal (header.gid, sizeof (header.gid), statbuf->st_gid); | 1143 | putOctal(header.gid, sizeof(header.gid), statbuf->st_gid); |
1137 | putOctal (header.size, sizeof (header.size), statbuf->st_size); | 1144 | putOctal(header.size, sizeof(header.size), statbuf->st_size); |
1138 | putOctal (header.mtime, sizeof (header.mtime), statbuf->st_mtime); | 1145 | putOctal(header.mtime, sizeof(header.mtime), statbuf->st_mtime); |
1139 | 1146 | ||
1140 | header.typeFlag = TAR_TYPE_REGULAR; | 1147 | header.typeFlag = TAR_TYPE_REGULAR; |
1141 | 1148 | ||
1142 | /* | 1149 | /* |
1143 | * Calculate and store the checksum. | 1150 | * Calculate and store the checksum. |
1144 | * This is the sum of all of the bytes of the header, | 1151 | * This is the sum of all of the bytes of the header, |
1145 | * with the checksum field itself treated as blanks. | 1152 | * with the checksum field itself treated as blanks. |
1146 | */ | 1153 | */ |
1147 | memset (header.checkSum, ' ', sizeof (header.checkSum)); | 1154 | memset(header.checkSum, ' ', sizeof(header.checkSum)); |
1148 | 1155 | ||
1149 | cp = (const unsigned char *) &header; | 1156 | cp = (const unsigned char *) &header; |
1150 | len = sizeof (header); | 1157 | len = sizeof(header); |
1151 | checkSum = 0; | 1158 | checkSum = 0; |
1152 | 1159 | ||
1153 | while (len-- > 0) | 1160 | while (len-- > 0) |
1154 | checkSum += *cp++; | 1161 | checkSum += *cp++; |
1155 | 1162 | ||
1156 | putOctal (header.checkSum, sizeof (header.checkSum), checkSum); | 1163 | putOctal(header.checkSum, sizeof(header.checkSum), checkSum); |
1157 | 1164 | ||
1158 | /* | 1165 | /* |
1159 | * Write the tar header. | 1166 | * Write the tar header. |
1160 | */ | 1167 | */ |
1161 | writeTarBlock ((const char *) &header, sizeof (header)); | 1168 | writeTarBlock((const char *) &header, sizeof(header)); |
1162 | } | 1169 | } |
1163 | 1170 | ||
1164 | 1171 | ||
@@ -1167,56 +1174,56 @@ static void writeHeader (const char *fileName, const struct stat *statbuf) | |||
1167 | * The data is always padded out to a multiple of TAR_BLOCK_SIZE. | 1174 | * The data is always padded out to a multiple of TAR_BLOCK_SIZE. |
1168 | * The errorFlag static variable is set on an error. | 1175 | * The errorFlag static variable is set on an error. |
1169 | */ | 1176 | */ |
1170 | static void writeTarBlock (const char *buf, int len) | 1177 | static void writeTarBlock(const char *buf, int len) |
1171 | { | 1178 | { |
1172 | int partialLength; | 1179 | int partialLength; |
1173 | int completeLength; | 1180 | int completeLength; |
1174 | char fullBlock[TAR_BLOCK_SIZE]; | 1181 | char fullBlock[TAR_BLOCK_SIZE]; |
1175 | 1182 | ||
1176 | /* | 1183 | /* |
1177 | * If we had a write error before, then do nothing more. | 1184 | * If we had a write error before, then do nothing more. |
1178 | */ | 1185 | */ |
1179 | if (errorFlag==TRUE) | 1186 | if (errorFlag == TRUE) |
1180 | return; | 1187 | return; |
1181 | 1188 | ||
1182 | /* | 1189 | /* |
1183 | * Get the amount of complete and partial blocks. | 1190 | * Get the amount of complete and partial blocks. |
1184 | */ | 1191 | */ |
1185 | partialLength = len % TAR_BLOCK_SIZE; | 1192 | partialLength = len % TAR_BLOCK_SIZE; |
1186 | completeLength = len - partialLength; | 1193 | completeLength = len - partialLength; |
1187 | 1194 | ||
1188 | /* | 1195 | /* |
1189 | * Write all of the complete blocks. | 1196 | * Write all of the complete blocks. |
1190 | */ | 1197 | */ |
1191 | if ((completeLength > 0) && !fullWrite (tarFd, buf, completeLength)) { | 1198 | if ((completeLength > 0) && !fullWrite(tarFd, buf, completeLength)) { |
1192 | perror (tarName); | 1199 | perror(tarName); |
1193 | 1200 | ||
1194 | errorFlag = TRUE; | 1201 | errorFlag = TRUE; |
1195 | 1202 | ||
1196 | return; | 1203 | return; |
1197 | } | 1204 | } |
1198 | 1205 | ||
1199 | /* | 1206 | /* |
1200 | * If there are no partial blocks left, we are done. | 1207 | * If there are no partial blocks left, we are done. |
1201 | */ | 1208 | */ |
1202 | if (partialLength == 0) | 1209 | if (partialLength == 0) |
1203 | return; | 1210 | return; |
1204 | 1211 | ||
1205 | /* | 1212 | /* |
1206 | * Copy the partial data into a complete block, and pad the rest | 1213 | * Copy the partial data into a complete block, and pad the rest |
1207 | * of it with zeroes. | 1214 | * of it with zeroes. |
1208 | */ | 1215 | */ |
1209 | memcpy (fullBlock, buf + completeLength, partialLength); | 1216 | memcpy(fullBlock, buf + completeLength, partialLength); |
1210 | memset (fullBlock + partialLength, 0, TAR_BLOCK_SIZE - partialLength); | 1217 | memset(fullBlock + partialLength, 0, TAR_BLOCK_SIZE - partialLength); |
1211 | 1218 | ||
1212 | /* | 1219 | /* |
1213 | * Write the last complete block. | 1220 | * Write the last complete block. |
1214 | */ | 1221 | */ |
1215 | if (!fullWrite (tarFd, fullBlock, TAR_BLOCK_SIZE)) { | 1222 | if (!fullWrite(tarFd, fullBlock, TAR_BLOCK_SIZE)) { |
1216 | perror (tarName); | 1223 | perror(tarName); |
1217 | 1224 | ||
1218 | errorFlag = TRUE; | 1225 | errorFlag = TRUE; |
1219 | } | 1226 | } |
1220 | } | 1227 | } |
1221 | 1228 | ||
1222 | 1229 | ||
@@ -1225,48 +1232,48 @@ static void writeTarBlock (const char *buf, int len) | |||
1225 | * The number is zero and space padded and possibly null padded. | 1232 | * The number is zero and space padded and possibly null padded. |
1226 | * Returns TRUE if successful. | 1233 | * Returns TRUE if successful. |
1227 | */ | 1234 | */ |
1228 | static int putOctal (char *cp, int len, long value) | 1235 | static int putOctal(char *cp, int len, long value) |
1229 | { | 1236 | { |
1230 | int tempLength; | 1237 | int tempLength; |
1231 | char *tempString; | 1238 | char *tempString; |
1232 | char tempBuffer[32]; | 1239 | char tempBuffer[32]; |
1233 | |||
1234 | /* | ||
1235 | * Create a string of the specified length with an initial space, | ||
1236 | * leading zeroes and the octal number, and a trailing null. | ||
1237 | */ | ||
1238 | tempString = tempBuffer; | ||
1239 | |||
1240 | sprintf (tempString, " %0*lo", len - 2, value); | ||
1241 | |||
1242 | tempLength = strlen (tempString) + 1; | ||
1243 | |||
1244 | /* | ||
1245 | * If the string is too large, suppress the leading space. | ||
1246 | */ | ||
1247 | if (tempLength > len) { | ||
1248 | tempLength--; | ||
1249 | tempString++; | ||
1250 | } | ||
1251 | |||
1252 | /* | ||
1253 | * If the string is still too large, suppress the trailing null. | ||
1254 | */ | ||
1255 | if (tempLength > len) | ||
1256 | tempLength--; | ||
1257 | |||
1258 | /* | ||
1259 | * If the string is still too large, fail. | ||
1260 | */ | ||
1261 | if (tempLength > len) | ||
1262 | return FALSE; | ||
1263 | 1240 | ||
1264 | /* | 1241 | /* |
1265 | * Copy the string to the field. | 1242 | * Create a string of the specified length with an initial space, |
1266 | */ | 1243 | * leading zeroes and the octal number, and a trailing null. |
1267 | memcpy (cp, tempString, len); | 1244 | */ |
1245 | tempString = tempBuffer; | ||
1268 | 1246 | ||
1269 | return TRUE; | 1247 | sprintf(tempString, " %0*lo", len - 2, value); |
1248 | |||
1249 | tempLength = strlen(tempString) + 1; | ||
1250 | |||
1251 | /* | ||
1252 | * If the string is too large, suppress the leading space. | ||
1253 | */ | ||
1254 | if (tempLength > len) { | ||
1255 | tempLength--; | ||
1256 | tempString++; | ||
1257 | } | ||
1258 | |||
1259 | /* | ||
1260 | * If the string is still too large, suppress the trailing null. | ||
1261 | */ | ||
1262 | if (tempLength > len) | ||
1263 | tempLength--; | ||
1264 | |||
1265 | /* | ||
1266 | * If the string is still too large, fail. | ||
1267 | */ | ||
1268 | if (tempLength > len) | ||
1269 | return FALSE; | ||
1270 | |||
1271 | /* | ||
1272 | * Copy the string to the field. | ||
1273 | */ | ||
1274 | memcpy(cp, tempString, len); | ||
1275 | |||
1276 | return TRUE; | ||
1270 | } | 1277 | } |
1271 | #endif | 1278 | #endif |
1272 | 1279 | ||