⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 create.c

📁 unix 下tar 执行程序的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
			 * This will be the new "size" of the
			 * file, i.e., the size of the file
			 * minus the records of holes that we're
			 * skipping over. 
			 */
				 
				find_new_file_size(&filesize, upperbound);
				hstat.st_size = filesize;
				to_oct((long) filesize, 1+12,
 						header->header.size);
/*				to_oct((long) end_nulls, 1+12, 
						header->header.ending_blanks);*/
						
				for (i = 0; i < SPARSE_IN_HDR; i++) {
					if (!sparsearray[i].numbytes)
						break;
					to_oct(sparsearray[i].offset, 1+12,
						header->header.sp[i].offset);
					to_oct(sparsearray[i].numbytes, 1+12,
						header->header.sp[i].numbytes);
				}
					
			}
		}
#else
		upperbound=SPARSE_IN_HDR-1;
#endif
		
		sizeleft = hstat.st_size;
		/* Don't bother opening empty, world readable files. */
		if (sizeleft > 0 || 0444 != (0444 & hstat.st_mode)) {
			f = open(p, O_RDONLY|O_BINARY);
			if (f < 0) goto badperror;
		} else {
			f = -1;
		}
		
		/* If the file is sparse, we've already taken care of this */
		if (!header_moved) {
			header = start_header(p, &hstat);
			if (header == NULL) {
				if(f>=0)
					(void)close(f);
				goto badfile;
			}
		}
#ifdef S_IFCTG
		/* Mark contiguous files, if we support them */
		if (f_standard && (hstat.st_mode & S_IFMT) == S_IFCTG) {
			header->header.linkflag = LF_CONTIG;
		}
#endif
		isextended = header->header.isextended;
		save_linkflag = header->header.linkflag;
		finish_header(header);
		if (isextended) {
			int	 sum = 0;
			register int i;
/*			register union record *exhdr;*/
			int	 arraybound = SPARSE_EXT_HDR;
			/* static */ int index_offset = SPARSE_IN_HDR;
			
	extend:		exhdr = findrec();
			
			if (exhdr == NULL) goto badfile;
			bzero(exhdr->charptr, RECORDSIZE);
			for (i = 0; i < SPARSE_EXT_HDR; i++) {
				if (i+index_offset > upperbound)
					break;
				to_oct((long) sparsearray[i+index_offset].numbytes,
 					1+12,
					exhdr->ext_hdr.sp[i].numbytes);
				to_oct((long) sparsearray[i+index_offset].offset,
 					1+12,
					exhdr->ext_hdr.sp[i].offset);
			}
			userec(exhdr);
/*			sum += i;
			if (sum < upperbound)
				goto extend;*/
			if (index_offset+i < upperbound) {
				index_offset += i;
				exhdr->ext_hdr.isextended++;
				goto extend;
			}
				
		}
		if (save_linkflag == LF_SPARSE) {
			if (finish_sparse_file(f, &sizeleft, hstat.st_size, p))
				goto padit;
		}
		else
		  while (sizeleft > 0) {
			
			if(f_multivol) {   
				save_name = p;
				save_sizeleft = sizeleft;
				save_totsize = hstat.st_size;
			}
			start = findrec();

			bufsize = endofrecs()->charptr - start->charptr;
				
			if (sizeleft < bufsize) {
				/* Last read -- zero out area beyond */
				bufsize = (int)sizeleft;
				count = bufsize % RECORDSIZE;
				if (count) 
					bzero(start->charptr + sizeleft,
						(int)(RECORDSIZE - count));
			}
			count = read(f, start->charptr, bufsize);
			if (count < 0) {
				msg_perror("read error at byte %ld, reading\
 %d bytes, in file %s",  hstat.st_size - sizeleft, bufsize,p);
				goto padit;
			}
			sizeleft -= count;

			/* This is nonportable (the type of userec's arg). */
			userec(start+(count-1)/RECORDSIZE);

			if (count == bufsize) continue;
			msg( "file %s shrunk by %d bytes, padding with zeros.", p, sizeleft);
			goto padit;		/* Short read */
		}

		if(f_multivol)
			save_name = 0;

		if (f >= 0)
			(void)close(f);

		break;

		/*
		 * File shrunk or gave error, pad out tape to match
		 * the size we specified in the header.
		 */
	padit:
		while(sizeleft>0) {
			save_sizeleft=sizeleft;
			start=findrec();
			bzero(start->charptr,RECORDSIZE);
			userec(start);
			sizeleft-=RECORDSIZE;
		}
		if(f_multivol)
			save_name=0;
		if(f>=0)
			(void)close(f);
		break;
/*		abort(); */
	}

#ifdef S_IFLNK
	case S_IFLNK:			/* Symbolic link */
	{
		int size;

		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[MAXPATHLEN];

			readlink(p,buf,MAXPATHLEN);
			/* 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); */
		} else
			header->header.linkname[size] = '\0';
		header->header.linkflag = LF_SYMLINK;
		finish_header(header);		/* Nothing more to do to it */
	}
		break;
#endif

	case S_IFDIR:			/* Directory */
	{
		register DIR *dirp;
		register struct direct *d;
		char *namebuf;
		int buflen;
		register int len;
		int our_device = hstat.st_dev;
		extern char *ck_malloc(),*ck_realloc();

		/* Build new prototype name */
		len = strlen(p);
		buflen=len+NAMSIZ;
		namebuf=ck_malloc(buflen+1);
		strncpy(namebuf, p, buflen);
		while (len >= 1 && '/' == namebuf[len-1]) 
			len--;			/* Delete trailing slashes */
		namebuf[len++] = '/';		/* Now add exactly one back */
		namebuf[len] = '\0';		/* Make sure null-terminated */

		/*
		 * Output directory header record with permissions
		 * FIXME, do this AFTER files, to avoid R/O dir problems?
		 * If old archive format, don't write record at all.
		 */
		if (!f_oldarch) {
			hstat.st_size = 0;	/* Force 0 size on dir */
			/*
			 * If people could really read standard archives,
			 * this should be:		(FIXME)
			header = start_header(f_standard? p: namebuf, &hstat);
			 * but since they'd interpret LF_DIR records as
			 * regular files, we'd better put the / on the name.
			 */
			header = start_header(namebuf, &hstat);
			if (header == NULL)
				goto badfile;	/* eg name too long */

			if (f_gnudump)
				header->header.linkflag = LF_DUMPDIR;
			else if (f_standard)
				header->header.linkflag = LF_DIR;

			/* If we're gnudumping, we aren't done yet so don't close it. */
			if(!f_gnudump)
				finish_header(header);	/* Done with directory header */
		}

		if(f_gnudump) {
			int sizeleft;
			int totsize;
			int bufsize;
			union record *start;
			int count;
			char *buf,*p_buf;

			buf=gnu_list_name->dir_contents; /* FOO */
			totsize=0;
			for(p_buf=buf;p_buf && *p_buf;) {
				int tmp;

				tmp=strlen(p_buf)+1;
				totsize+=tmp;
				p_buf+=tmp;
			}
			totsize++;
			to_oct((long)totsize,1+12,header->header.size);
			finish_header(header);
			p_buf=buf;
			sizeleft=totsize;
			while(sizeleft>0) {
				if(f_multivol) {
					save_name=p;
					save_sizeleft=sizeleft;
					save_totsize=totsize;
				}
				start=findrec();
				bufsize=endofrecs()->charptr - start->charptr;
				if(sizeleft<bufsize) {
					bufsize=sizeleft;
					count=bufsize%RECORDSIZE;
					if(count)
						bzero(start->charptr+sizeleft,RECORDSIZE-count);
				}
				bcopy(p_buf,start->charptr,bufsize);
				sizeleft-=bufsize;
				p_buf+=bufsize;
				userec(start+(bufsize-1)/RECORDSIZE);
			}
			if(f_multivol)
				save_name = 0;
 			break;
		}

		/* Now output all the files in the directory */
		/* if (f_dironly)
			break;		/* Unless the cmdline said not to */
		/*
		 * 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_verbose)
				msg("%s: is on a different filesystem; not dumped",p);
			break;
		}


		errno = 0;
		dirp = opendir(p);
		if (!dirp) {
			if (errno) {
				msg_perror ("can't open directory %s",p);
			} else {
				msg("error opening directory %s",
					p);
			}
			break;
		}

		/* Hack to remove "./" from the front of all the file names */
		if (len == 2 && namebuf[0] == '.' && namebuf[1]=='/')
			len = 0;

		/* Should speed this up by cd-ing into the dir, FIXME */
		while (NULL != (d=readdir(dirp))) {
			/* Skip . and .. */
			if(is_dot_or_dotdot(d->d_name))
				continue;

			if (DP_NAMELEN(d) + len >= buflen) {
				buflen=len+DP_NAMELEN(d);
				namebuf=ck_realloc(namebuf,buflen+1);
				/* namebuf[len]='\0';
				msg("file name %s%s too long", 
					namebuf, d->d_name);
				continue; */
			}
			strcpy(namebuf+len, d->d_name);
			if(f_exclude && check_exclude(namebuf))
				continue;
			dump_file(namebuf, our_device);
		}

		closedir(dirp);
		free(namebuf);
	}
		break;

#ifdef S_IFCHR
	case S_IFCHR:			/* Character special file */
		type = LF_CHR;
		goto easy;
#endif

#ifdef S_IFBLK
	case S_IFBLK:			/* Block     special file */
		type = LF_BLK;
		goto easy;
#endif

/* Avoid screwy apollo lossage where S_IFIFO == S_IFSOCK */
#if ((_ISP__M68K == 0) && (_ISP__A88K == 0))
#ifdef S_IFIFO
	case S_IFIFO:			/* Fifo      special file */
		
		type = LF_FIFO;
		goto easy;
#endif
#endif

#ifdef S_IFSOCK
	case S_IFSOCK:			/* Socket	pretend its a fifo? */
		type = LF_FIFO;
		goto easy;
#endif

	easy:
		if (!f_standard) goto unknown;

		hstat.st_size = 0;		/* Force 0 size */
		header = start_header(p, &hstat);
		if (header == NULL) goto badfile;	/* eg name too long */

		header->header.linkflag = type;
		if (type != LF_FIFO) {
			to_oct((long) major(hstat.st_rdev), 8,
				header->header.devmajor);
			to_oct((long) minor(hstat.st_rdev), 8,
				header->header.devminor);
		}

		finish_header(header);
		break;

	default:
	unknown:
		msg("%s: Unknown file type; file ignored.", p);
		break;
	}
}

int
finish_sparse_file(fd, sizeleft, fullsize, name)
	int	fd;
	long 	*sizeleft,
		fullsize;
	char	*name;
{
	union record	*start;
	char		tempbuf[RECORDSIZE];
	int		bufsize,
			sparse_ind = 0,
			count;
	long		pos;
	long		nwritten = 0;


	while (*sizeleft > 0) {
		start = findrec();
		bzero(start->charptr, RECORDSIZE);
		bufsize = sparsearray[sparse_ind].numbytes;
		if (!bufsize) {  /* we blew it, maybe */
		        msg("Wrote %ld of %ld bytes to file %s",
			           fullsize - *sizeleft, fullsize, name);
			break;
 	        }
		pos = lseek(fd, sparsearray[sparse_ind++].offset, 0);
		/* 
		 * If the number of bytes to be written here exceeds
		 * the size of the temporary buffer, do it in steps.
		 */
		while (bufsize > RECORDSIZE) {
/*			if (amt_read) {
				count = read(fd, start->charptr+amt_read, RECORDSIZE-amt_read);
				bufsize -= RECORDSIZE - amt_read;
				amt_read = 0;
				userec(start);
				start = findrec();
				bzero(start->charptr, RECORDSIZE);
			}*/
			/* store the data */
			count = read(fd, start->charptr, RECORDSIZE);
			if (count < 0) 	{
				msg_perror("read error at byte %ld, reading %d bytes, in file %s", 
						fullsize - *sizeleft, bufsize, name);
				return 1;
			}			
			bufsize -= count;
			*sizeleft -= count;
			userec(start);
			nwritten += RECORDSIZE;	/* XXX */
			start = findrec();
			bzero(start->charptr, RECORDSIZE);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -