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