]> Dogcows Code - chaz/tar/blob - src/create.c
*** empty log message ***
[chaz/tar] / src / create.c
1 /* Create a tar archive.
2 Copyright (C) 1985, 1992 Free Software Foundation
3
4 This file is part of GNU Tar.
5
6 GNU Tar is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU Tar is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Tar; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20 /*
21 * Create a tar archive.
22 *
23 * Written 25 Aug 1985 by John Gilmore, ihnp4!hoptoad!gnu.
24 */
25
26 #ifdef _AIX
27 #pragma alloca
28 #endif
29 #include <sys/types.h>
30 #include <stdio.h>
31 #include <errno.h>
32 #ifndef STDC_HEADERS
33 extern int errno;
34 #endif
35
36 #ifdef BSD42
37 #include <sys/file.h>
38 #else
39 #ifndef V7
40 #include <fcntl.h>
41 #endif
42 #endif
43
44 #include "tar.h"
45 #include "port.h"
46
47 #ifndef __MSDOS__
48 #include <pwd.h>
49 #include <grp.h>
50 #endif
51
52 #if defined (_POSIX_VERSION)
53 #include <utime.h>
54 #else
55 struct utimbuf
56 {
57 long actime;
58 long modtime;
59 };
60 #endif
61
62 #if defined(_POSIX_VERSION) || defined(DIRENT)
63 #include <dirent.h>
64 #ifdef direct
65 #undef direct
66 #endif /* direct */
67 #define direct dirent
68 #define DP_NAMELEN(x) strlen((x)->d_name)
69 #endif /* _POSIX_VERSION or DIRENT */
70 #if !defined(_POSIX_VERSION) && !defined(DIRENT) && defined(BSD42)
71 #include <sys/dir.h>
72 #define DP_NAMELEN(x) (x)->d_namlen
73 #endif /* not _POSIX_VERSION and BSD42 */
74 #ifdef __MSDOS__
75 #include "msd_dir.h"
76 #define DP_NAMELEN(x) (x)->d_namlen
77 #define direct dirent
78 #endif
79 #if defined(USG) && !defined(_POSIX_VERSION) && !defined(DIRENT)
80 #include <ndir.h>
81 #define DP_NAMELEN(x) strlen((x)->d_name)
82 #endif /* USG and not _POSIX_VERSION and not DIRENT */
83
84 extern struct stat hstat; /* Stat struct corresponding */
85
86 #ifndef __MSDOS__
87 extern dev_t ar_dev;
88 extern ino_t ar_ino;
89 #endif
90
91 /* JF */
92 extern struct name *gnu_list_name;
93
94 /*
95 * If there are no symbolic links, there is no lstat(). Use stat().
96 */
97 #ifndef S_ISLNK
98 #define lstat stat
99 #endif
100
101 extern void print_header();
102
103 union record *start_header();
104 void blank_name_list();
105 int check_exclude();
106 PTR ck_malloc();
107 PTR ck_realloc();
108 void clear_buffer();
109 void close_archive();
110 void collect_and_sort_names();
111 int confirm();
112 int deal_with_sparse();
113 void find_new_file_size();
114 void finish_header();
115 int finish_sparse_file();
116 void finduname();
117 void findgname();
118 int is_dot_or_dotdot();
119 void open_archive();
120 char *name_next();
121 void name_close();
122 void to_oct();
123 void dump_file();
124 void write_dir_file();
125 void write_eot();
126 int zero_record();
127
128 /* This code moved from tar.h since create.c is the only file that cares
129 about 'struct link's. This means that other files might not have to
130 include sys/types.h any more. */
131
132 struct link {
133 struct link *next;
134 dev_t dev;
135 ino_t ino;
136 short linkcount;
137 char name[1];
138 };
139
140 struct link *linklist; /* Points to first link in list */
141
142 static nolinks; /* Gets set if we run out of RAM */
143
144 /*
145 * "Scratch" space to store the information about a sparse file before
146 * writing the info into the header or extended header
147 */
148 /* struct sp_array *sparsearray;*/
149
150 /* number of elts storable in the sparsearray */
151 /*int sparse_array_size = 10;*/
152
153 void
154 create_archive()
155 {
156 register char *p;
157 char *name_from_list();
158
159 open_archive(0); /* Open for writing */
160
161 if(f_gnudump) {
162 char *buf = ck_malloc(PATH_MAX);
163 char *q,*bufp;
164
165 collect_and_sort_names();
166
167 while(p=name_from_list())
168 dump_file(p,-1, 1);
169 /* if(!f_dironly) { */
170 blank_name_list();
171 while(p=name_from_list()) {
172 strcpy(buf,p);
173 if(p[strlen(p)-1]!='/')
174 strcat(buf,"/");
175 bufp=buf+strlen(buf);
176 for(q=gnu_list_name->dir_contents;q && *q;q+=strlen(q)+1) {
177 if(*q=='Y') {
178 strcpy(bufp,q+1);
179 dump_file(buf,-1, 1);
180 }
181 }
182 }
183 /* } */
184 free(buf);
185 } else {
186 p = name_next(1);
187 do
188 dump_file(p, -1, 1);
189 while (p = name_next(1));
190 }
191
192 write_eot();
193 close_archive();
194 if(f_gnudump)
195 write_dir_file();
196 name_close();
197 }
198
199 /*
200 * Dump a single file. If it's a directory, recurse.
201 * Result is 1 for success, 0 for failure.
202 * Sets global "hstat" to stat() output for this file.
203 */
204 void
205 dump_file (p, curdev, toplevel)
206 char *p; /* File name to dump */
207 int curdev; /* Device our parent dir was on */
208 int toplevel; /* Whether we are a toplevel call */
209 {
210 union record *header;
211 char type;
212 extern char *save_name; /* JF for multi-volume support */
213 extern long save_totsize;
214 extern long save_sizeleft;
215 union record *exhdr;
216 char save_linkflag;
217 extern time_t new_time;
218 int critical_error = 0;
219 struct utimbuf restore_times;
220 /* int sparse_ind = 0;*/
221
222
223 if(f_confirm && !confirm("add",p))
224 return;
225
226 /*
227 * Use stat if following (rather than dumping) 4.2BSD's
228 * symbolic links. Otherwise, use lstat (which, on non-4.2
229 * systems, is #define'd to stat anyway.
230 */
231 #ifdef STX_HIDDEN /* AIX */
232 if (0 != f_follow_links ?
233 statx (p, &hstat, STATSIZE, STX_HIDDEN):
234 statx (p, &hstat, STATSIZE, STX_HIDDEN|STX_LINK))
235 #else
236 if (0 != f_follow_links? stat(p, &hstat): lstat(p, &hstat))
237 #endif
238 {
239 badperror:
240 msg_perror("can't add file %s",p);
241 badfile:
242 if (!f_ignore_failed_read || critical_error)
243 errors++;
244 return;
245 }
246
247 restore_times.actime = hstat.st_atime;
248 restore_times.modtime = hstat.st_mtime;
249
250 #ifdef S_ISHIDDEN
251 if (S_ISHIDDEN (hstat.st_mode)) {
252 char *new = (char *)alloca (strlen (p) + 2);
253 if (new) {
254 strcpy (new, p);
255 strcat (new, "@");
256 p = new;
257 }
258 }
259 #endif
260
261 /* See if we only want new files, and check if this one is too old to
262 put in the archive. */
263 if( f_new_files
264 && !f_gnudump
265 && new_time>hstat.st_mtime
266 && !S_ISDIR(hstat.st_mode)
267 && (f_new_files>1 || new_time>hstat.st_ctime)) {
268 if(curdev<0) {
269 msg("%s: is unchanged; not dumped",p);
270 }
271 return;
272 }
273
274 #ifndef __MSDOS__
275 /* See if we are trying to dump the archive */
276 if(ar_dev && hstat.st_dev==ar_dev && hstat.st_ino==ar_ino) {
277 msg("%s is the archive; not dumped",p);
278 return;
279 }
280 #endif
281 /*
282 * Check for multiple links.
283 *
284 * We maintain a list of all such files that we've written so
285 * far. Any time we see another, we check the list and
286 * avoid dumping the data again if we've done it once already.
287 */
288 if (hstat.st_nlink > 1
289 && (S_ISREG(hstat.st_mode)
290 #ifdef S_ISCTG
291 || S_ISCTG(hstat.st_mode)
292 #endif
293 #ifdef S_ISCHR
294 || S_ISCHR(hstat.st_mode)
295 #endif
296 #ifdef S_ISBLK
297 || S_ISBLK(hstat.st_mode)
298 #endif
299 #ifdef S_ISFIFO
300 || S_ISFIFO(hstat.st_mode)
301 #endif
302 )) {
303 register struct link *lp;
304
305 /* First quick and dirty. Hashing, etc later FIXME */
306 for (lp = linklist; lp; lp = lp->next) {
307 if (lp->ino == hstat.st_ino &&
308 lp->dev == hstat.st_dev) {
309 char *link_name = lp->name;
310
311 /* We found a link. */
312 while(!f_absolute_paths && *link_name == '/') {
313 static int link_warn = 0;
314
315 if (!link_warn) {
316 msg("Removing leading / from absolute links");
317 link_warn++;
318 }
319 link_name++;
320 }
321 if (link_name - lp->name >= NAMSIZ)
322 write_long (link_name, LF_LONGLINK);
323 current_link_name = link_name;
324
325 hstat.st_size = 0;
326 header = start_header(p, &hstat);
327 if (header == NULL)
328 {
329 critical_error = 1;
330 goto badfile;
331 }
332 strncpy(header->header.arch_linkname,
333 link_name,NAMSIZ);
334
335 /* Force null truncated */
336 header->header.arch_linkname [NAMSIZ-1] = 0;
337
338 header->header.linkflag = LF_LINK;
339 finish_header(header);
340 /* FIXME: Maybe remove from list after all links found? */
341 if (f_remove_files)
342 {
343 if (unlink (p) == -1)
344 msg_perror ("cannot remove %s", p);
345 }
346 return; /* We dumped it */
347 }
348 }
349
350 /* Not found. Add it to the list of possible links. */
351 lp = (struct link *)malloc((unsigned)(sizeof(struct link)+strlen(p)));
352 if (!lp) {
353 if (!nolinks) {
354 msg(
355 "no memory for links, they will be dumped as separate files");
356 nolinks++;
357 }
358 }
359 lp->ino = hstat.st_ino;
360 lp->dev = hstat.st_dev;
361 strcpy(lp->name, p);
362 lp->next = linklist;
363 linklist = lp;
364 }
365
366 /*
367 * This is not a link to a previously dumped file, so dump it.
368 */
369 if (S_ISREG(hstat.st_mode)
370 #ifdef S_ISCTG
371 || S_ISCTG(hstat.st_mode)
372 #endif
373 )
374 {
375 int f; /* File descriptor */
376 long bufsize, count;
377 long sizeleft;
378 register union record *start;
379 int header_moved;
380 char isextended = 0;
381 int upperbound;
382 /* int end_nulls = 0; */
383
384 header_moved = 0;
385
386 #ifdef BSD42
387 if (f_sparse_files) {
388 /*
389 * JK - This is the test for sparseness: whether the
390 * "size" of the file matches the number of blocks
391 * allocated for it. If there is a smaller number
392 * of blocks that would be necessary to accommodate
393 * a file of this size, we have a sparse file, i.e.,
394 * at least one of those records in the file is just
395 * a useless hole.
396 */
397 #ifdef hpux /* Nice of HPUX to gratuitiously change it, huh? - mib */
398 if (hstat.st_size - (hstat.st_blocks * 1024) > 1024 )
399 #else
400 if (hstat.st_size - (hstat.st_blocks * RECORDSIZE) > RECORDSIZE)
401 #endif
402 {
403 int filesize = hstat.st_size;
404 register int i;
405
406 header = start_header(p, &hstat);
407 if (header == NULL)
408 {
409 critical_error = 1;
410 goto badfile;
411 }
412 header->header.linkflag = LF_SPARSE;
413 header_moved++;
414
415 /*
416 * Call the routine that figures out the
417 * layout of the sparse file in question.
418 * UPPERBOUND is the index of the last
419 * element of the "sparsearray," i.e.,
420 * the number of elements it needed to
421 * describe the file.
422 */
423
424 upperbound = deal_with_sparse(p, header);
425
426 /*
427 * See if we'll need an extended header
428 * later
429 */
430 if (upperbound > SPARSE_IN_HDR-1)
431 header->header.isextended++;
432 /*
433 * We store the "real" file size so
434 * we can show that in case someone wants
435 * to list the archive, i.e., tar tvf <file>.
436 * It might be kind of disconcerting if the
437 * shrunken file size was the one that showed
438 * up.
439 */
440 to_oct((long) hstat.st_size, 1+12,
441 header->header.realsize);
442
443 /*
444 * This will be the new "size" of the
445 * file, i.e., the size of the file
446 * minus the records of holes that we're
447 * skipping over.
448 */
449
450 find_new_file_size(&filesize, upperbound);
451 hstat.st_size = filesize;
452 to_oct((long) filesize, 1+12,
453 header->header.size);
454 /* to_oct((long) end_nulls, 1+12,
455 header->header.ending_blanks);*/
456
457 for (i = 0; i < SPARSE_IN_HDR; i++) {
458 if (!sparsearray[i].numbytes)
459 break;
460 to_oct(sparsearray[i].offset, 1+12,
461 header->header.sp[i].offset);
462 to_oct(sparsearray[i].numbytes, 1+12,
463 header->header.sp[i].numbytes);
464 }
465
466 }
467 }
468 #else
469 upperbound=SPARSE_IN_HDR-1;
470 #endif
471
472 sizeleft = hstat.st_size;
473 /* Don't bother opening empty, world readable files. */
474 if (sizeleft > 0 || 0444 != (0444 & hstat.st_mode)) {
475 f = open(p, O_RDONLY|O_BINARY);
476 if (f < 0) goto badperror;
477 } else {
478 f = -1;
479 }
480
481 /* If the file is sparse, we've already taken care of this */
482 if (!header_moved) {
483 header = start_header(p, &hstat);
484 if (header == NULL) {
485 if(f>=0)
486 (void)close(f);
487 critical_error = 1;
488 goto badfile;
489 }
490 }
491 #ifdef S_ISCTG
492 /* Mark contiguous files, if we support them */
493 if (f_standard && S_ISCTG(hstat.st_mode)) {
494 header->header.linkflag = LF_CONTIG;
495 }
496 #endif
497 isextended = header->header.isextended;
498 save_linkflag = header->header.linkflag;
499 finish_header(header);
500 if (isextended) {
501 /* int sum = 0;*/
502 register int i;
503 /* register union record *exhdr;*/
504 /* int arraybound = SPARSE_EXT_HDR;*/
505 /* static */ int index_offset = SPARSE_IN_HDR;
506
507 extend: exhdr = findrec();
508
509 if (exhdr == NULL)
510 {
511 critical_error = 1;
512 goto badfile;
513 }
514 bzero(exhdr->charptr, RECORDSIZE);
515 for (i = 0; i < SPARSE_EXT_HDR; i++) {
516 if (i+index_offset > upperbound)
517 break;
518 to_oct((long) sparsearray[i+index_offset].numbytes,
519 1+12,
520 exhdr->ext_hdr.sp[i].numbytes);
521 to_oct((long) sparsearray[i+index_offset].offset,
522 1+12,
523 exhdr->ext_hdr.sp[i].offset);
524 }
525 userec(exhdr);
526 /* sum += i;
527 if (sum < upperbound)
528 goto extend;*/
529 if (index_offset+i < upperbound) {
530 index_offset += i;
531 exhdr->ext_hdr.isextended++;
532 goto extend;
533 }
534
535 }
536 if (save_linkflag == LF_SPARSE) {
537 if (finish_sparse_file(f, &sizeleft, hstat.st_size, p))
538 goto padit;
539 }
540 else
541 while (sizeleft > 0) {
542
543 if(f_multivol) {
544 save_name = p;
545 save_sizeleft = sizeleft;
546 save_totsize = hstat.st_size;
547 }
548 start = findrec();
549
550 bufsize = endofrecs()->charptr - start->charptr;
551
552 if (sizeleft < bufsize) {
553 /* Last read -- zero out area beyond */
554 bufsize = (int)sizeleft;
555 count = bufsize % RECORDSIZE;
556 if (count)
557 bzero(start->charptr + sizeleft,
558 (int)(RECORDSIZE - count));
559 }
560 count = read(f, start->charptr, bufsize);
561 if (count < 0) {
562 msg_perror("read error at byte %ld, reading\
563 %d bytes, in file %s", hstat.st_size - sizeleft, bufsize,p);
564 goto padit;
565 }
566 sizeleft -= count;
567
568 /* This is nonportable (the type of userec's arg). */
569 userec(start+(count-1)/RECORDSIZE);
570
571 if (count == bufsize) continue;
572 msg( "file %s shrunk by %d bytes, padding with zeros.", p, sizeleft);
573 goto padit; /* Short read */
574 }
575
576 if(f_multivol)
577 save_name = 0;
578
579 if (f >= 0)
580 (void)close(f);
581
582 if (f_remove_files)
583 {
584 if (unlink (p) == -1)
585 msg_perror ("cannot remove %s", p);
586 }
587 if (f_atime_preserve)
588 utime (p, &restore_times);
589 return;
590
591 /*
592 * File shrunk or gave error, pad out tape to match
593 * the size we specified in the header.
594 */
595 padit:
596 while(sizeleft>0) {
597 save_sizeleft=sizeleft;
598 start=findrec();
599 bzero(start->charptr,RECORDSIZE);
600 userec(start);
601 sizeleft-=RECORDSIZE;
602 }
603 if(f_multivol)
604 save_name=0;
605 if(f>=0)
606 (void)close(f);
607 if (f_atime_preserve)
608 utime (p, &restore_times);
609 return;
610 }
611
612 #ifdef S_ISLNK
613 else if(S_ISLNK(hstat.st_mode))
614 {
615 int size;
616 char *buf = alloca (PATH_MAX + 1);
617
618 size = readlink (p, buf, PATH_MAX + 1);
619 if (size < 0)
620 goto badperror;
621 buf[size] = '\0';
622 if (size >= NAMSIZ)
623 write_long (buf, LF_LONGLINK);
624 current_link_name = buf;
625
626 hstat.st_size = 0; /* Force 0 size on symlink */
627 header = start_header(p, &hstat);
628 if (header == NULL)
629 {
630 critical_error = 1;
631 goto badfile;
632 }
633 strncpy (header->header.arch_linkname, buf, NAMSIZ);
634 header->header.arch_linkname[NAMSIZ - 1] = '\0';
635 header->header.linkflag = LF_SYMLINK;
636 finish_header(header); /* Nothing more to do to it */
637 if (f_remove_files)
638 {
639 if (unlink (p) == -1)
640 msg_perror ("cannot remove %s", p);
641 }
642 return;
643 }
644 #endif
645
646 else if (S_ISDIR(hstat.st_mode))
647 {
648 register DIR *dirp;
649 register struct direct *d;
650 char *namebuf;
651 int buflen;
652 register int len;
653 int our_device = hstat.st_dev;
654
655 /* Build new prototype name */
656 len = strlen(p);
657 buflen=len+NAMSIZ;
658 namebuf=ck_malloc(buflen+1);
659 strncpy(namebuf, p, buflen);
660 while (len >= 1 && '/' == namebuf[len-1])
661 len--; /* Delete trailing slashes */
662 namebuf[len++] = '/'; /* Now add exactly one back */
663 namebuf[len] = '\0'; /* Make sure null-terminated */
664
665 /*
666 * Output directory header record with permissions
667 * FIXME, do this AFTER files, to avoid R/O dir problems?
668 * If old archive format, don't write record at all.
669 */
670 if (!f_oldarch) {
671 hstat.st_size = 0; /* Force 0 size on dir */
672 /*
673 * If people could really read standard archives,
674 * this should be: (FIXME)
675 header = start_header(f_standard? p: namebuf, &hstat);
676 * but since they'd interpret LF_DIR records as
677 * regular files, we'd better put the / on the name.
678 */
679 header = start_header(namebuf, &hstat);
680 if (header == NULL)
681 {
682 critical_error = 1;
683 goto badfile; /* eg name too long */
684 }
685
686 if (f_gnudump)
687 header->header.linkflag = LF_DUMPDIR;
688 else if (f_standard)
689 header->header.linkflag = LF_DIR;
690
691 /* If we're gnudumping, we aren't done yet so don't close it. */
692 if(!f_gnudump)
693 finish_header(header); /* Done with directory header */
694 }
695
696 if(f_gnudump) {
697 int sizeleft;
698 int totsize;
699 int bufsize;
700 union record *start;
701 int count;
702 char *buf,*p_buf;
703
704 buf=gnu_list_name->dir_contents; /* FOO */
705 totsize=0;
706 for(p_buf=buf;p_buf && *p_buf;) {
707 int tmp;
708
709 tmp=strlen(p_buf)+1;
710 totsize+=tmp;
711 p_buf+=tmp;
712 }
713 totsize++;
714 to_oct((long)totsize,1+12,header->header.size);
715 finish_header(header);
716 p_buf=buf;
717 sizeleft=totsize;
718 while(sizeleft>0) {
719 if(f_multivol) {
720 save_name=p;
721 save_sizeleft=sizeleft;
722 save_totsize=totsize;
723 }
724 start=findrec();
725 bufsize=endofrecs()->charptr - start->charptr;
726 if(sizeleft<bufsize) {
727 bufsize=sizeleft;
728 count=bufsize%RECORDSIZE;
729 if(count)
730 bzero(start->charptr+sizeleft,RECORDSIZE-count);
731 }
732 bcopy(p_buf,start->charptr,bufsize);
733 sizeleft-=bufsize;
734 p_buf+=bufsize;
735 userec(start+(bufsize-1)/RECORDSIZE);
736 }
737 if(f_multivol)
738 save_name = 0;
739 if (f_atime_preserve)
740 utime (p, &restore_times);
741 return;
742 }
743
744 /* Now output all the files in the directory */
745 #if 0
746 if (f_dironly)
747 return; /* Unless the cmdline said not to */
748 #endif
749 /*
750 * See if we are crossing from one file system to another,
751 * and avoid doing so if the user only wants to dump one file system.
752 */
753 if (f_local_filesys && !toplevel && curdev != hstat.st_dev) {
754 if(f_verbose)
755 msg("%s: is on a different filesystem; not dumped",p);
756 return;
757 }
758
759
760 errno = 0;
761 dirp = opendir(p);
762 if (!dirp) {
763 if (errno) {
764 msg_perror ("can't open directory %s",p);
765 } else {
766 msg("error opening directory %s",
767 p);
768 }
769 return;
770 }
771
772 /* Hack to remove "./" from the front of all the file names */
773 if (len == 2 && namebuf[0] == '.' && namebuf[1]=='/')
774 len = 0;
775
776 /* Should speed this up by cd-ing into the dir, FIXME */
777 while (NULL != (d=readdir(dirp))) {
778 /* Skip . and .. */
779 if(is_dot_or_dotdot(d->d_name))
780 continue;
781
782 if (DP_NAMELEN(d) + len >= buflen) {
783 buflen=len+DP_NAMELEN(d);
784 namebuf=ck_realloc(namebuf,buflen+1);
785 /* namebuf[len]='\0';
786 msg("file name %s%s too long",
787 namebuf, d->d_name);
788 continue; */
789 }
790 strcpy(namebuf+len, d->d_name);
791 if(f_exclude && check_exclude(namebuf))
792 continue;
793 dump_file(namebuf, our_device, 0);
794 }
795
796 closedir(dirp);
797 free(namebuf);
798 if (f_atime_preserve)
799 utime (p, &restore_times);
800 return;
801 }
802
803 #ifdef S_ISCHR
804 else if (S_ISCHR(hstat.st_mode)) {
805 type = LF_CHR;
806 }
807 #endif
808
809 #ifdef S_ISBLK
810 else if (S_ISBLK(hstat.st_mode)) {
811 type = LF_BLK;
812 }
813 #endif
814
815 /* Avoid screwy apollo lossage where S_IFIFO == S_IFSOCK */
816 #if (_ISP__M68K == 0) && (_ISP__A88K == 0) && defined(S_ISFIFO)
817 else if (S_ISFIFO(hstat.st_mode)) {
818 type = LF_FIFO;
819 }
820 #endif
821
822 #ifdef S_ISSOCK
823 else if (S_ISSOCK(hstat.st_mode)) {
824 type = LF_FIFO;
825 }
826 #endif
827 else
828 goto unknown;
829
830 if (!f_standard) goto unknown;
831
832 hstat.st_size = 0; /* Force 0 size */
833 header = start_header(p, &hstat);
834 if (header == NULL)
835 {
836 critical_error = 1;
837 goto badfile; /* eg name too long */
838 }
839
840 header->header.linkflag = type;
841 #if defined(S_IFBLK) || defined(S_IFCHR)
842 if (type != LF_FIFO) {
843 to_oct((long) major(hstat.st_rdev), 8,
844 header->header.devmajor);
845 to_oct((long) minor(hstat.st_rdev), 8,
846 header->header.devminor);
847 }
848 #endif
849
850 finish_header(header);
851 if (f_remove_files)
852 {
853 if (unlink (p) == -1)
854 msg_perror ("cannot remove %s", p);
855 }
856 return;
857
858 unknown:
859 msg("%s: Unknown file type; file ignored.", p);
860 }
861
862 int
863 finish_sparse_file(fd, sizeleft, fullsize, name)
864 int fd;
865 long *sizeleft,
866 fullsize;
867 char *name;
868 {
869 union record *start;
870 char tempbuf[RECORDSIZE];
871 int bufsize,
872 sparse_ind = 0,
873 count;
874 long pos;
875 long nwritten = 0;
876
877
878 while (*sizeleft > 0) {
879 start = findrec();
880 bzero(start->charptr, RECORDSIZE);
881 bufsize = sparsearray[sparse_ind].numbytes;
882 if (!bufsize) { /* we blew it, maybe */
883 msg("Wrote %ld of %ld bytes to file %s",
884 fullsize - *sizeleft, fullsize, name);
885 break;
886 }
887 pos = lseek(fd, sparsearray[sparse_ind++].offset, 0);
888 /*
889 * If the number of bytes to be written here exceeds
890 * the size of the temporary buffer, do it in steps.
891 */
892 while (bufsize > RECORDSIZE) {
893 /* if (amt_read) {
894 count = read(fd, start->charptr+amt_read, RECORDSIZE-amt_read);
895 bufsize -= RECORDSIZE - amt_read;
896 amt_read = 0;
897 userec(start);
898 start = findrec();
899 bzero(start->charptr, RECORDSIZE);
900 }*/
901 /* store the data */
902 count = read(fd, start->charptr, RECORDSIZE);
903 if (count < 0) {
904 msg_perror("read error at byte %ld, reading %d bytes, in file %s",
905 fullsize - *sizeleft, bufsize, name);
906 return 1;
907 }
908 bufsize -= count;
909 *sizeleft -= count;
910 userec(start);
911 nwritten += RECORDSIZE; /* XXX */
912 start = findrec();
913 bzero(start->charptr, RECORDSIZE);
914 }
915
916
917 clear_buffer(tempbuf);
918 count = read(fd, tempbuf, bufsize);
919 bcopy(tempbuf, start->charptr, RECORDSIZE);
920 if (count < 0) {
921 msg_perror("read error at byte %ld, reading %d bytes, in file %s",
922 fullsize - *sizeleft, bufsize, name);
923 return 1;
924 }
925 /* if (amt_read >= RECORDSIZE) {
926 amt_read = 0;
927 userec(start+(count-1)/RECORDSIZE);
928 if (count != bufsize) {
929 msg("file %s shrunk by %d bytes, padding with zeros.", name, sizeleft);
930 return 1;
931 }
932 start = findrec();
933 } else
934 amt_read += bufsize;*/
935 nwritten += count; /* XXX */
936 *sizeleft -= count;
937 userec(start);
938
939 }
940 free(sparsearray);
941 /* printf ("Amount actually written is (I hope) %d.\n", nwritten); */
942 /* userec(start+(count-1)/RECORDSIZE);*/
943 return 0;
944
945 }
946
947 void
948 init_sparsearray()
949 {
950 register int i;
951
952 sp_array_size = 10;
953 /*
954 * Make room for our scratch space -- initially is 10 elts long
955 */
956 sparsearray = (struct sp_array *) malloc(sp_array_size * sizeof(struct sp_array));
957 for (i = 0; i < sp_array_size; i++) {
958 sparsearray[i].offset = 0;
959 sparsearray[i].numbytes = 0;
960 }
961 }
962
963
964
965 /*
966 * Okay, we've got a sparse file on our hands -- now, what we need to do is
967 * make a pass through the file and carefully note where any data is, i.e.,
968 * we want to find how far into the file each instance of data is, and how
969 * many bytes are there. We store this information in the sparsearray,
970 * which will later be translated into header information. For now, we use
971 * the sparsearray as convenient storage.
972 *
973 * As a side note, this routine is a mess. If I could have found a cleaner
974 * way to do it, I would have. If anyone wants to find a nicer way to do
975 * this, feel free.
976 */
977
978 /* There is little point in trimming small amounts of null data at the */
979 /* head and tail of blocks -- it's ok if we only avoid dumping blocks */
980 /* of complete null data */
981 int
982 deal_with_sparse(name, header, nulls_at_end)
983 char *name;
984 union record *header;
985 int nulls_at_end;
986 {
987 long numbytes = 0;
988 long offset = 0;
989 /* long save_offset;*/
990 int fd;
991 /* int current_size = hstat.st_size;*/
992 int sparse_ind = 0,
993 cc;
994 char buf[RECORDSIZE];
995 #if 0
996 int read_last_data = 0; /* did we just read the last record? */
997 #endif
998 int amidst_data = 0;
999
1000 header->header.isextended = 0;
1001 /*
1002 * Can't open the file -- this problem will be caught later on,
1003 * so just return.
1004 */
1005 if ((fd = open(name, O_RDONLY)) < 0)
1006 return 0;
1007
1008 init_sparsearray();
1009 clear_buffer(buf);
1010
1011 while ((cc = read(fd, buf, sizeof buf)) != 0) {
1012
1013 if (sparse_ind > sp_array_size-1) {
1014
1015 /*
1016 * realloc the scratch area, since we've run out of room --
1017 */
1018 sparsearray = (struct sp_array *)
1019 realloc(sparsearray,
1020 2 * sp_array_size * (sizeof(struct sp_array)));
1021 sp_array_size *= 2;
1022 }
1023 if (cc == sizeof buf) {
1024 if (zero_record(buf)) {
1025 if (amidst_data) {
1026 sparsearray[sparse_ind++].numbytes
1027 = numbytes;
1028 amidst_data = 0;
1029 }
1030 } else { /* !zero_record(buf) */
1031 if (amidst_data)
1032 numbytes += cc;
1033 else {
1034 amidst_data = 1;
1035 numbytes = cc;
1036 sparsearray[sparse_ind].offset
1037 = offset;
1038 }
1039 }
1040 } else if (cc < sizeof buf) {
1041 /* This has to be the last bit of the file, so this */
1042 /* is somewhat shorter than the above. */
1043 if (!zero_record(buf)) {
1044 if (!amidst_data) {
1045 amidst_data = 1;
1046 numbytes = cc;
1047 sparsearray[sparse_ind].offset
1048 = offset;
1049 } else
1050 numbytes += cc;
1051 }
1052 }
1053 offset += cc;
1054 clear_buffer(buf);
1055 }
1056 if (amidst_data)
1057 sparsearray[sparse_ind++].numbytes = numbytes;
1058 close(fd);
1059
1060 return sparse_ind - 1;
1061 }
1062
1063 /*
1064 * Just zeroes out the buffer so we don't confuse ourselves with leftover
1065 * data.
1066 */
1067 void
1068 clear_buffer(buf)
1069 char *buf;
1070 {
1071 register int i;
1072
1073 for (i = 0; i < RECORDSIZE; i++)
1074 buf[i] = '\0';
1075 }
1076
1077 #if 0 /* I'm leaving this as a monument to Joy Kendall, who wrote it -mib */
1078 /*
1079 * JK -
1080 * This routine takes a character array, and tells where within that array
1081 * the data can be found. It skips over any zeros, and sets the first
1082 * non-zero point in the array to be the "start", and continues until it
1083 * finds non-data again, which is marked as the "end." This routine is
1084 * mainly for 1) seeing how far into a file we must lseek to data, given
1085 * that we have a sparse file, and 2) determining the "real size" of the
1086 * file, i.e., the number of bytes in the sparse file that are data, as
1087 * opposed to the zeros we are trying to skip.
1088 */
1089 where_is_data(from, to, buffer)
1090 int *from,
1091 *to;
1092 char *buffer;
1093 {
1094 register int i = 0;
1095 register int save_to = *to;
1096 int amidst_data = 0;
1097
1098
1099 while (!buffer[i])
1100 i++;
1101 *from = i;
1102
1103 if (*from < 16) /* don't bother */
1104 *from = 0;
1105 /* keep going to make sure there isn't more real
1106 data in this record */
1107 while (i < RECORDSIZE) {
1108 if (!buffer[i]) {
1109 if (amidst_data) {
1110 save_to = i;
1111 amidst_data = 0;
1112 }
1113 i++;
1114 }
1115 else if (buffer[i]) {
1116 if (!amidst_data)
1117 amidst_data = 1;
1118 i++;
1119 }
1120 }
1121 if (i == RECORDSIZE)
1122 *to = i;
1123 else
1124 *to = save_to;
1125
1126 }
1127 #endif
1128
1129 /* Note that this routine is only called if zero_record returned true */
1130 #if 0 /* But we actually don't need it at all. */
1131 where_is_data (from, to, buffer)
1132 int *from, *to;
1133 char *buffer;
1134 {
1135 char *fp, *tp;
1136
1137 for (fp = buffer; ! *fp; fp++)
1138 ;
1139 for (tp = buffer + RECORDSIZE - 1; ! *tp; tp--)
1140 ;
1141 *from = fp - buffer;
1142 *to = tp - buffer + 1;
1143 }
1144 #endif
1145
1146
1147
1148 /*
1149 * Takes a recordful of data and basically cruises through it to see if
1150 * it's made *entirely* of zeros, returning a 0 the instant it finds
1151 * something that is a non-zero, i.e., useful data.
1152 */
1153 int
1154 zero_record(buffer)
1155 char *buffer;
1156 {
1157 register int i;
1158
1159 for (i = 0; i < RECORDSIZE; i++)
1160 if (buffer[i] != '\000')
1161 return 0;
1162 return 1;
1163 }
1164
1165 void
1166 find_new_file_size(filesize, highest_index)
1167 int *filesize;
1168 int highest_index;
1169 {
1170 register int i;
1171
1172 *filesize = 0;
1173 for (i = 0; sparsearray[i].numbytes && i <= highest_index; i++)
1174 *filesize += sparsearray[i].numbytes;
1175 }
1176
1177 /*
1178 * Make a header block for the file name whose stat info is st .
1179 * Return header pointer for success, NULL if the name is too long.
1180 */
1181 union record *
1182 start_header(name, st)
1183 char *name;
1184 register struct stat *st;
1185 {
1186 register union record *header;
1187
1188 if (strlen (name) >= NAMSIZ)
1189 write_long (name, LF_LONGNAME);
1190
1191 header = (union record *) findrec();
1192 bzero(header->charptr, sizeof(*header)); /* XXX speed up */
1193
1194 /*
1195 * Check the file name and put it in the record.
1196 */
1197 if(!f_absolute_paths) {
1198 static int warned_once = 0;
1199 #ifdef __MSDOS__
1200 if(name[1]==':') {
1201 name+=2;
1202 if(!warned_once++)
1203 msg("Removing drive spec from names in the archive");
1204 }
1205 #endif
1206 while ('/' == *name) {
1207 name++; /* Force relative path */
1208 if (!warned_once++)
1209 msg("Removing leading / from absolute path names in the archive.");
1210 }
1211 }
1212 current_file_name = name;
1213 strncpy(header->header.arch_name, name, NAMSIZ);
1214 header->header.arch_name[NAMSIZ-1] = '\0';
1215
1216 to_oct((long) (st->st_mode & 07777),
1217 8, header->header.mode);
1218 to_oct((long) st->st_uid, 8, header->header.uid);
1219 to_oct((long) st->st_gid, 8, header->header.gid);
1220 to_oct((long) st->st_size, 1+12, header->header.size);
1221 to_oct((long) st->st_mtime, 1+12, header->header.mtime);
1222 /* header->header.linkflag is left as null */
1223 if(f_gnudump) {
1224 to_oct((long) st->st_atime, 1+12, header->header.atime);
1225 to_oct((long) st->st_ctime, 1+12, header->header.ctime);
1226 }
1227
1228 #ifndef NONAMES
1229 /* Fill in new Unix Standard fields if desired. */
1230 if (f_standard) {
1231 header->header.linkflag = LF_NORMAL; /* New default */
1232 strcpy(header->header.magic, TMAGIC); /* Mark as Unix Std */
1233 finduname(header->header.uname, st->st_uid);
1234 findgname(header->header.gname, st->st_gid);
1235 }
1236 #endif
1237 return header;
1238 }
1239
1240 /*
1241 * Finish off a filled-in header block and write it out.
1242 * We also print the file name and/or full info if verbose is on.
1243 */
1244 void
1245 finish_header(header)
1246 register union record *header;
1247 {
1248 register int i, sum;
1249 register char *p;
1250
1251 bcopy(CHKBLANKS, header->header.chksum, sizeof(header->header.chksum));
1252
1253 sum = 0;
1254 p = header->charptr;
1255 for (i = sizeof(*header); --i >= 0; ) {
1256 /*
1257 * We can't use unsigned char here because of old compilers,
1258 * e.g. V7.
1259 */
1260 sum += 0xFF & *p++;
1261 }
1262
1263 /*
1264 * Fill in the checksum field. It's formatted differently
1265 * from the other fields: it has [6] digits, a null, then a
1266 * space -- rather than digits, a space, then a null.
1267 * We use to_oct then write the null in over to_oct's space.
1268 * The final space is already there, from checksumming, and
1269 * to_oct doesn't modify it.
1270 *
1271 * This is a fast way to do:
1272 * (void) sprintf(header->header.chksum, "%6o", sum);
1273 */
1274 to_oct((long) sum, 8, header->header.chksum);
1275 header->header.chksum[6] = '\0'; /* Zap the space */
1276
1277 userec(header);
1278
1279 if (f_verbose) {
1280 extern union record *head; /* Points to current tape header */
1281 extern int head_standard; /* Tape header is in ANSI format */
1282
1283 /* These globals are parameters to print_header, sigh */
1284 head = header;
1285 /* hstat is already set up */
1286 head_standard = f_standard;
1287 print_header();
1288 }
1289
1290 return;
1291 }
1292
1293
1294 /*
1295 * Quick and dirty octal conversion.
1296 * Converts long "value" into a "digs"-digit field at "where",
1297 * including a trailing space and room for a null. "digs"==3 means
1298 * 1 digit, a space, and room for a null.
1299 *
1300 * We assume the trailing null is already there and don't fill it in.
1301 * This fact is used by start_header and finish_header, so don't change it!
1302 *
1303 * This should be equivalent to:
1304 * (void) sprintf(where, "%*lo ", digs-2, value);
1305 * except that sprintf fills in the trailing null and we don't.
1306 */
1307 void
1308 to_oct(value, digs, where)
1309 register long value;
1310 register int digs;
1311 register char *where;
1312 {
1313
1314 --digs; /* Trailing null slot is left alone */
1315 where[--digs] = ' '; /* Put in the space, though */
1316
1317 /* Produce the digits -- at least one */
1318 do {
1319 where[--digs] = '0' + (char)(value & 7); /* one octal digit */
1320 value >>= 3;
1321 } while (digs > 0 && value != 0);
1322
1323 /* Leading spaces, if necessary */
1324 while (digs > 0)
1325 where[--digs] = ' ';
1326
1327 }
1328
1329
1330 /*
1331 * Write the EOT record(s).
1332 * We actually zero at least one record, through the end of the block.
1333 * Old tar writes garbage after two zeroed records -- and PDtar used to.
1334 */
1335 void
1336 write_eot()
1337 {
1338 union record *p;
1339 int bufsize;
1340
1341 p = findrec();
1342 if (p)
1343 {
1344 bufsize = endofrecs()->charptr - p->charptr;
1345 bzero(p->charptr, bufsize);
1346 userec(p);
1347 }
1348 }
1349
1350 /* Write a LF_LONGLINK or LF_LONGNAME record. */
1351 write_long (p, type)
1352 char *p;
1353 char type;
1354 {
1355 int size = strlen (p) + 1;
1356 int bufsize;
1357 union record *header;
1358 struct stat foo;
1359
1360
1361 bzero (&foo, sizeof foo);
1362 foo.st_size = size;
1363
1364 header = start_header ("././@LongLink", &foo);
1365 header->header.linkflag = type;
1366 finish_header (header);
1367
1368 header = findrec ();
1369
1370 bufsize = endofrecs ()->charptr - header->charptr;
1371
1372 while (bufsize < size)
1373 {
1374 bcopy (p, header->charptr, bufsize);
1375 p += bufsize;
1376 size -= bufsize;
1377 userec (header + (bufsize - 1)/RECORDSIZE);
1378 header = findrec ();
1379 bufsize = endofrecs ()->charptr - header->charptr;
1380 }
1381 bcopy (p, header->charptr, size);
1382 bzero (header->charptr + size, bufsize - size);
1383 userec (header + (size - 1)/RECORDSIZE);
1384 }
This page took 0.088998 seconds and 5 git commands to generate.