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