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