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