X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=src%2Fcreate.c;h=cea58c1f7b32ddd7c1004451687d89b6f4b2555d;hb=083205ad13a86ee50983f1faf3fbefd3efe99453;hp=c2453409efb076499aea266c67ff7121d5182d19;hpb=b85255a6217c4109e74469f19c8f87e6f995560f;p=chaz%2Ftar diff --git a/src/create.c b/src/create.c index c245340..cea58c1 100644 --- a/src/create.c +++ b/src/create.c @@ -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 #else @@ -44,11 +41,24 @@ extern int errno; #endif #endif +#include "tar.h" +#include "port.h" + #ifndef __MSDOS__ #include #include #endif +#if defined (_POSIX_VERSION) +#include +#else +struct utimbuf +{ + long actime; + long modtime; +}; +#endif + #if defined(_POSIX_VERSION) || defined(DIRENT) #include #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); +}