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