]> Dogcows Code - chaz/tar/blobdiff - src/create.c
*** empty log message ***
[chaz/tar] / src / create.c
index c2453409efb076499aea266c67ff7121d5182d19..cea58c1f7b32ddd7c1004451687d89b6f4b2555d 100644 (file)
@@ -1,5 +1,5 @@
 /* Create a tar archive.
-   Copyright (C) 1988 Free Software Foundation
+   Copyright (C) 1985, 1992 Free Software Foundation
 
 This file is part of GNU Tar.
 
@@ -33,9 +33,6 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 extern int     errno;
 #endif
 
-#include "tar.h"
-#include "port.h"
-
 #ifdef BSD42
 #include <sys/file.h>
 #else
@@ -44,11 +41,24 @@ extern int  errno;
 #endif
 #endif
 
+#include "tar.h"
+#include "port.h"
+
 #ifndef        __MSDOS__
 #include <pwd.h>
 #include <grp.h>
 #endif
 
+#if defined (_POSIX_VERSION)
+#include <utime.h>
+#else
+struct utimbuf
+{
+  long actime;
+  long modtime;
+};
+#endif
+
 #if defined(_POSIX_VERSION) || defined(DIRENT)
 #include <dirent.h>
 #ifdef direct
@@ -91,8 +101,6 @@ extern struct name *gnu_list_name;
 extern void print_header();
 
 union record *start_header();
-void add_mangle();
-void add_symlink_mangle();
 void blank_name_list();
 int check_exclude();
 PTR ck_malloc();
@@ -115,7 +123,6 @@ void to_oct();
 void dump_file();
 void write_dir_file();
 void write_eot();
-void write_mangled();
 int zero_record();
 
 /* This code moved from tar.h since create.c is the only file that cares
@@ -152,13 +159,13 @@ create_archive()
        open_archive(0);                /* Open for writing */
 
        if(f_gnudump) {
-               char *buf = ck_malloc(NAME_MAX);
+               char *buf = ck_malloc(PATH_MAX);
                char *q,*bufp;
 
                collect_and_sort_names();
 
                while(p=name_from_list())
-                       dump_file(p,-1);
+                       dump_file(p,-1, 1);
                /* if(!f_dironly) { */
                        blank_name_list();
                        while(p=name_from_list()) {
@@ -169,7 +176,7 @@ create_archive()
                                for(q=gnu_list_name->dir_contents;q && *q;q+=strlen(q)+1) {
                                        if(*q=='Y') {
                                                strcpy(bufp,q+1);
-                                               dump_file(buf,-1);
+                                               dump_file(buf,-1, 1);
                                        }
                                }
                        }
@@ -177,15 +184,11 @@ create_archive()
                free(buf);
        } else {
                p = name_next(1);
-               if(!p)
-                       dump_file(".", -1);
-               else {
-                       do dump_file(p, -1);
-                       while (p = name_next(1));
-               }
+               do 
+                 dump_file(p, -1, 1);
+               while (p = name_next(1));
        }
 
-       write_mangled();
        write_eot();
        close_archive();
        if(f_gnudump)
@@ -199,9 +202,10 @@ create_archive()
  * Sets global "hstat" to stat() output for this file.
  */
 void
-dump_file (p, curdev)
+dump_file (p, curdev, toplevel)
        char    *p;                     /* File name to dump */
        int     curdev;                 /* Device our parent dir was on */
+       int     toplevel;               /* Whether we are a toplevel call */
 {
        union record    *header;
        char type;
@@ -211,6 +215,8 @@ dump_file (p, curdev)
        union record    *exhdr;
        char save_linkflag;
        extern time_t new_time;
+       int critical_error = 0;
+       struct utimbuf restore_times;
 /*     int sparse_ind = 0;*/
 
 
@@ -233,9 +239,13 @@ dump_file (p, curdev)
 badperror:
                msg_perror("can't add file %s",p);
 badfile:
-               errors++;
+               if (!f_ignore_failed_read || critical_error)
+                 errors++;
                return;
        }
+       
+       restore_times.actime = hstat.st_atime;
+       restore_times.modtime = hstat.st_mtime;
 
 #ifdef S_ISHIDDEN
        if (S_ISHIDDEN (hstat.st_mode)) {
@@ -299,9 +309,6 @@ badfile:
                                char *link_name = lp->name;
 
                                /* We found a link. */
-                               hstat.st_size = 0;
-                               header = start_header(p, &hstat);
-                               if (header == NULL) goto badfile;
                                while(!f_absolute_paths && *link_name == '/') {
                                        static int link_warn = 0;
 
@@ -311,19 +318,31 @@ badfile:
                                        }
                                        link_name++;
                                }
-                               strncpy(header->header.linkname,
+                               if (link_name - lp->name >= NAMSIZ)
+                                 write_long (link_name, LF_LONGLINK);
+                               current_link_name = link_name;
+
+                               hstat.st_size = 0;
+                               header = start_header(p, &hstat);
+                               if (header == NULL) 
+                                 {
+                                   critical_error = 1;
+                                   goto badfile;
+                                 }
+                               strncpy(header->header.arch_linkname,
                                        link_name,NAMSIZ);
-                               if(header->header.linkname[NAMSIZ-1]) {
-                                       char *mangled;
-                                       extern char *find_mangled();
 
-                                       mangled=find_mangled(link_name);
-                                       msg("%s: link name too long: mangled to %s",link_name,mangled);
-                                       strncpy(header->header.linkname,mangled,NAMSIZ);
-                               }
+                               /* Force null truncated */
+                               header->header.arch_linkname [NAMSIZ-1] = 0;
+
                                header->header.linkflag = LF_LINK;
                                finish_header(header);
                /* FIXME: Maybe remove from list after all links found? */
+                               if (f_remove_files)
+                                 {
+                                   if (unlink (p) == -1)
+                                     msg_perror ("cannot remove %s", p);
+                                 }
                                return;         /* We dumped it */
                        }
                }
@@ -386,7 +405,10 @@ badfile:
                                
                                header = start_header(p, &hstat);
                                if (header == NULL)
-                                       goto badfile;
+                                 {
+                                   critical_error = 1;
+                                   goto badfile;
+                                 }
                                header->header.linkflag = LF_SPARSE;
                                header_moved++;
                                
@@ -462,6 +484,7 @@ badfile:
                        if (header == NULL) {
                                if(f>=0)
                                        (void)close(f);
+                               critical_error = 1;
                                goto badfile;
                        }
                }
@@ -483,7 +506,11 @@ badfile:
                        
        extend:         exhdr = findrec();
                        
-                       if (exhdr == NULL) goto badfile;
+                       if (exhdr == NULL) 
+                         {
+                           critical_error = 1;
+                           goto badfile;
+                         }
                        bzero(exhdr->charptr, RECORDSIZE);
                        for (i = 0; i < SPARSE_EXT_HDR; i++) {
                                if (i+index_offset > upperbound)
@@ -514,7 +541,7 @@ badfile:
                  while (sizeleft > 0) {
                        
                        if(f_multivol) {   
-                               save_name = header->header.name;
+                               save_name = p;
                                save_sizeleft = sizeleft;
                                save_totsize = hstat.st_size;
                        }
@@ -552,6 +579,13 @@ badfile:
                if (f >= 0)
                        (void)close(f);
 
+               if (f_remove_files)
+                 {
+                   if (unlink (p) == -1)
+                     msg_perror ("cannot remove %s", p);
+                 }
+               if (f_atime_preserve)
+                 utime (p, &restore_times);
                return;
 
                /*
@@ -570,32 +604,41 @@ badfile:
                        save_name=0;
                if(f>=0)
                        (void)close(f);
-             return;
+               if (f_atime_preserve)
+                 utime (p, &restore_times);
+               return;
        }
 
 #ifdef S_ISLNK
        else if(S_ISLNK(hstat.st_mode))
        {
                int size;
+               char *buf = alloca (PATH_MAX + 1);
+
+               size = readlink (p, buf, PATH_MAX + 1);
+               if (size < 0) 
+                 goto badperror;
+               buf[size] = '\0';
+               if (size >= NAMSIZ)
+                 write_long (buf, LF_LONGLINK);
+               current_link_name = buf;
 
                hstat.st_size = 0;              /* Force 0 size on symlink */
                header = start_header(p, &hstat);
-               if (header == NULL) goto badfile;
-               size = readlink(p, header->header.linkname, NAMSIZ);
-               if (size < 0) goto badperror;
-               if (size == NAMSIZ) {
-                       char *buf = ck_malloc(PATH_MAX);
-
-                       readlink(p,buf,PATH_MAX);
-                       /* next_mangle(header->header.linkname); */
-                       add_symlink_mangle(buf,p,header->header.linkname);
-                       msg("symbolic link %s too long: mangling to %s",p, header->header.linkname);
-                       /* size=strlen(header->header.linkname); */
-                       free(buf);
-               } else
-                       header->header.linkname[size] = '\0';
+               if (header == NULL) 
+                 {
+                   critical_error = 1;
+                   goto badfile;
+                 }
+               strncpy (header->header.arch_linkname, buf, NAMSIZ);
+               header->header.arch_linkname[NAMSIZ - 1] = '\0';
                header->header.linkflag = LF_SYMLINK;
                finish_header(header);          /* Nothing more to do to it */
+               if (f_remove_files)
+                 {
+                   if (unlink (p) == -1)
+                     msg_perror ("cannot remove %s", p);
+                 }
                return;
        }
 #endif
@@ -635,7 +678,10 @@ badfile:
                         */
                        header = start_header(namebuf, &hstat);
                        if (header == NULL)
-                               goto badfile;   /* eg name too long */
+                         {
+                           critical_error = 1;
+                           goto badfile;       /* eg name too long */
+                         }
 
                        if (f_gnudump)
                                header->header.linkflag = LF_DUMPDIR;
@@ -690,6 +736,8 @@ badfile:
                        }
                        if(f_multivol)
                                save_name = 0;
+                       if (f_atime_preserve)
+                         utime (p, &restore_times);
                        return;
                }
 
@@ -702,7 +750,7 @@ badfile:
                 * See if we are crossing from one file system to another,
                 * and avoid doing so if the user only wants to dump one file system.
                 */
-               if (f_local_filesys && curdev >= 0 && curdev != hstat.st_dev) {
+               if (f_local_filesys && !toplevel && curdev != hstat.st_dev) {
                        if(f_verbose)
                                msg("%s: is on a different filesystem; not dumped",p);
                        return;
@@ -742,11 +790,13 @@ badfile:
                        strcpy(namebuf+len, d->d_name);
                        if(f_exclude && check_exclude(namebuf))
                                continue;
-                       dump_file(namebuf, our_device);
+                       dump_file(namebuf, our_device, 0);
                }
 
                closedir(dirp);
                free(namebuf);
+               if (f_atime_preserve)
+                 utime (p, &restore_times);
                return;
        }
 
@@ -781,7 +831,11 @@ badfile:
 
        hstat.st_size = 0;              /* Force 0 size */
        header = start_header(p, &hstat);
-       if (header == NULL) goto badfile;       /* eg name too long */
+       if (header == NULL) 
+         {
+           critical_error = 1;
+           goto badfile;       /* eg name too long */
+         }
 
        header->header.linkflag = type;
 #if defined(S_IFBLK) || defined(S_IFCHR)
@@ -794,6 +848,11 @@ badfile:
 #endif
 
        finish_header(header);
+       if (f_remove_files)
+         {
+           if (unlink (p) == -1)
+             msg_perror ("cannot remove %s", p);
+         }
        return;
 
        unknown:
@@ -879,7 +938,7 @@ finish_sparse_file(fd, sizeleft, fullsize, name)
 
        }
        free(sparsearray);
-       printf ("Amount actually written is (I hope) %d.\n", nwritten);
+/*     printf ("Amount actually written is (I hope) %d.\n", nwritten); */
 /*     userec(start+(count-1)/RECORDSIZE);*/
        return 0;
 
@@ -1126,6 +1185,9 @@ start_header(name, st)
 {
        register union record *header;
 
+       if (strlen (name) >= NAMSIZ)
+         write_long (name, LF_LONGNAME);
+
        header = (union record *) findrec();
        bzero(header->charptr, sizeof(*header)); /* XXX speed up */
 
@@ -1147,14 +1209,9 @@ start_header(name, st)
                                msg("Removing leading / from absolute path names in the archive.");
                }
        }
-       strncpy(header->header.name, name, NAMSIZ);
-       if (header->header.name[NAMSIZ-1]) {
-/*             char *mangled;*/
-
-               /* next_mangle(header->header.name); */
-               add_mangle(name,header->header.name);
-               msg("%s: is too long: mangling to %s", name, header->header.name);
-       }
+       current_file_name = name;
+       strncpy(header->header.arch_name, name, NAMSIZ);
+       header->header.arch_name[NAMSIZ-1] = '\0';
 
        to_oct((long) (st->st_mode & 07777),
                                        8,  header->header.mode);
@@ -1289,3 +1346,39 @@ write_eot()
            userec(p);
          }
 }
+
+/* Write a LF_LONGLINK or LF_LONGNAME record. */
+write_long (p, type)
+     char *p;
+     char type;
+{
+  int size = strlen (p) + 1;
+  int bufsize;
+  union record *header;
+  struct stat foo;
+  
+
+  bzero (&foo, sizeof foo);
+  foo.st_size = size;
+
+  header = start_header ("././@LongLink", &foo);
+  header->header.linkflag = type;
+  finish_header (header);
+
+  header = findrec ();
+  
+  bufsize = endofrecs ()->charptr - header->charptr;
+  
+  while (bufsize < size)
+    {
+      bcopy (p, header->charptr, bufsize);
+      p += bufsize;
+      size -= bufsize;
+      userec (header + (bufsize - 1)/RECORDSIZE);
+      header = findrec ();
+      bufsize = endofrecs ()->charptr - header->charptr;
+    }
+  bcopy (p, header->charptr, size);
+  bzero (header->charptr + size, bufsize - size);
+  userec (header + (size - 1)/RECORDSIZE);
+}
This page took 0.033991 seconds and 4 git commands to generate.