示例#1
0
void
filein(register Archive_t* ap, register File_t* f)
{
	register off_t	c;
	register int	n;
	register char*	s;
	int		dfd;
	int		wfd;
	long		checksum;
	Filter_t*	fp;
	Proc_t*		pp;
	Tv_t		t1;
	Tv_t		t2;
	struct stat	st;

	if (f->skip)
		goto skip;
	else if (state.list)
	{
		if (fp = filter(ap, f))
		{
			for (n = 0; s = fp->argv[n]; n++)
			{
				while (*s)
					if (*s++ == '%' && *s == '(')
						break;
				if (*s)
				{
					s = fp->argv[n];
					listprintf(state.tmp.str, ap, f, s);
					if (!(fp->argv[n] = sfstruse(state.tmp.str)))
						nospace();
					break;
				}
			}
			pp = procopen(*fp->argv, fp->argv, NiL, NiL, PROC_WRITE);
			if (s)
				fp->argv[n] = s;
			if (!pp)
			{
				error(2, "%s: %s: cannot execute filter %s", ap->name, f->path, *fp->argv);
				goto skip;
			}
			if (!ap->format->getdata || !(*ap->format->getdata)(&state, ap, f, pp->wfd))
			{
				checksum = 0;
				for (c = f->st->st_size; c > 0; c -= n)
				{
					n = (c > state.buffersize) ? state.buffersize : c;
					if (!(s = bget(ap, n, NiL)))
					{
						error(ERROR_SYSTEM|2, "%s: read error", f->name);
						break;
					}
					if (write(pp->wfd, s, n) != n)
					{
						error(ERROR_SYSTEM|2, "%s: write error", f->name);
						break;
					}
					if (ap->format->checksum)
						checksum = (*ap->format->checksum)(&state, ap, f, s, n, checksum);
				}
			}
			if (ap->format->checksum && checksum != f->checksum)
				error(1, "%s: %s checksum error (0x%08x != 0x%08x)", f->name, ap->format->name, checksum, f->checksum);
			/*
			 * explicitly ignore exit status
			 */

			procclose(pp);
			return;
		}
		listentry(f);
		goto skip;
	}
	else switch (f->delta.op)
	{
	case DELTA_create:
		if (f->delta.base)
			error(3, "%s: base archive mismatch [%s#%d]", f->name, __FILE__, __LINE__);
		if (ap->delta->format->flags & PSEUDO)
			goto regular;
		if ((wfd = openout(ap, f)) < 0)
			goto skip;
		else
			paxdelta(NiL, ap, f, DELTA_TAR|DELTA_FD|DELTA_FREE|DELTA_OUTPUT|DELTA_COUNT, wfd, DELTA_DEL|DELTA_BIO|DELTA_SIZE, ap, f->st->st_size, 0);
		break;
	case DELTA_update:
		if (!f->delta.base || (unsigned long)f->delta.base->mtime.tv_sec >= (unsigned long)f->st->st_mtime)
			error(3, "%s: base archive mismatch [%s#%d]", f->name, __FILE__, __LINE__);
		c = f->st->st_size;
		if ((wfd = openout(ap, f)) < 0)
			goto skip;
		if (state.ordered)
		{
			if (!f->delta.base->uncompressed)
				paxdelta(NiL, ap, f, DELTA_SRC|DELTA_BIO|DELTA_SIZE, ap->delta->base, f->delta.base->size, DELTA_TAR|DELTA_FD|DELTA_FREE|DELTA_OUTPUT|DELTA_COUNT, wfd, DELTA_DEL|DELTA_BIO|DELTA_SIZE, ap, c, 0);
			else if (!paxdelta(NiL, ap, f, DELTA_DEL|DELTA_BIO|DELTA_SIZE, ap->delta->base, f->delta.base->size, DELTA_TAR|DELTA_TEMP|DELTA_OUTPUT, &dfd, 0))
				paxdelta(NiL, ap, f, DELTA_SRC|DELTA_FD|DELTA_SIZE|DELTA_FREE, dfd, f->delta.base->uncompressed, DELTA_TAR|DELTA_FD|DELTA_FREE|DELTA_OUTPUT|DELTA_COUNT, wfd, DELTA_DEL|DELTA_BIO|DELTA_SIZE, ap, c, 0);
		}
		else if (!f->delta.base->uncompressed)
			paxdelta(NiL, ap, f, DELTA_SRC|DELTA_FD|DELTA_OFFSET|DELTA_SIZE, ap->delta->base->io->fd, f->delta.base->offset, f->delta.base->size, DELTA_TAR|DELTA_FD|DELTA_FREE|DELTA_OUTPUT|DELTA_COUNT, wfd, DELTA_DEL|DELTA_BIO|DELTA_SIZE, ap, c, 0);
		else if (!paxdelta(NiL, ap, f, DELTA_DEL|DELTA_FD|DELTA_OFFSET|DELTA_SIZE, ap->delta->base->io->fd, f->delta.base->offset, f->delta.base->size, DELTA_TAR|DELTA_TEMP|DELTA_OUTPUT, &dfd, 0))
			paxdelta(NiL, ap, f, DELTA_SRC|DELTA_FD|DELTA_SIZE|DELTA_FREE, dfd, f->delta.base->uncompressed, DELTA_TAR|DELTA_FD|DELTA_FREE|DELTA_OUTPUT|DELTA_COUNT, wfd, DELTA_DEL|DELTA_BIO|DELTA_SIZE, ap, c, 0);
		break;
	case DELTA_verify:
		if (!f->delta.base || f->delta.base->mtime.tv_sec != f->st->st_mtime)
			error(3, "%s: base archive mismatch [%s#%d]", f->name, __FILE__, __LINE__);
		if ((*state.statf)(f->name, &st))
			error(2, "%s: not copied from base archive", f->name);
		else if (st.st_size != f->delta.base->size || state.modtime && tvcmp(tvmtime(&t1, &st), tvmtime(&t2, f->st)))
			error(1, "%s: changed from base archive", f->name);
		break;
	case DELTA_delete:
		if (!f->delta.base)
			error(3, "%s: base archive mismatch [%s#%d]", f->name, __FILE__, __LINE__);
		/*FALLTHROUGH*/
	default:
	regular:
		wfd = openout(ap, f);
		if (wfd >= 0)
		{
			holeinit(wfd);
			if (!ap->format->getdata || !(*ap->format->getdata)(&state, ap, f, wfd))
			{
				checksum = 0;
				for (c = f->st->st_size; c > 0; c -= n)
				{
					n = (c > state.buffersize) ? state.buffersize : c;
					if (!(s = bget(ap, n, NiL)))
					{
						error(ERROR_SYSTEM|2, "%s: read error", f->name);
						break;
					}
					if (holewrite(wfd, s, n) != n)
					{
						error(ERROR_SYSTEM|2, "%s: write error", f->name);
						break;
					}
					if (ap->format->checksum)
						checksum = (*ap->format->checksum)(&state, ap, f, s, n, checksum);
				}
			}
			holedone(wfd);
			closeout(ap, f, wfd);
			setfile(ap, f);
			if (ap->format->checksum && checksum != f->checksum)
				error(1, "%s: %s checksum error (0x%08x != 0x%08x)", f->name, ap->format->name, checksum, f->checksum);
		}
		else if (ap->format->getdata)
			(*ap->format->getdata)(&state, ap, f, wfd);
		else
		{
			if (wfd < -1)
				listentry(f);
			goto skip;
		}
		break;
	}
	listentry(f);
	return;
 skip:
	fileskip(ap, f);
}
示例#2
0
int
copyinout(Ftw_t* ftw)
{
	register File_t*	f = &state.out->file;
	register char*		s;
	register off_t		c;
	register ssize_t	n;
	register int		rfd;
	register int		wfd;

	if (getfile(state.out, f, ftw) && selectfile(state.out, f))
	{
		s = f->name;
		f->name = stash(&state.out->path.copy, NiL, state.pwdlen + f->namesize);
		strcpy(stpcpy(f->name, state.pwd), s + (*s == '/'));
		if ((wfd = openout(state.out, f)) >= 0)
		{
			if ((rfd = openin(state.out, f)) >= 0)
			{
#if defined(SEEK_DATA) && defined(SEEK_HOLE)
				off_t		data;
				off_t		hole;
				int		more;

				data = 0;
				more = 1;
				while (more)
				{
					if ((hole = lseek(rfd, data, SEEK_HOLE)) < data)
					{
						hole = lseek(rfd, 0, SEEK_END);
						more = 0;
					}
					while ((c = hole - data) > 0)
					{
						if (c > state.buffersize)
							c = state.buffersize;
						if (lseek(rfd, data, SEEK_SET) != data || (n = read(rfd, state.tmp.buffer, (size_t)c)) <= 0)
						{
							error(ERROR_SYSTEM|2, "%s: read error", f->name);
							more = 0;
							break;
						}
						if (lseek(wfd, data, SEEK_SET) != data || write(wfd, state.tmp.buffer, n) != n)
						{
							error(ERROR_SYSTEM|2, "%s: write error", f->name);
							more = 0;
							break;
						}
						state.out->io->count += n;
						data += n;
					}
					if (!more)
						break;
					if ((data = lseek(rfd, hole, SEEK_DATA)) < hole)
					{
						if ((data = lseek(rfd, -1, SEEK_END)) < 0 || (data + 1) > hole && (lseek(wfd, data, SEEK_SET) != data || write(wfd, "", 1) != 1))
							error(ERROR_SYSTEM|2, "%s: write error", f->name);
						state.out->io->count += 1;
						break;
					}
				}
#else
				holeinit(wfd);
				for (c = f->st->st_size; c > 0; c -= n)
				{
					if ((n = read(rfd, state.tmp.buffer, (size_t)((c > state.buffersize) ? state.buffersize : c))) <= 0)
					{
						error(ERROR_SYSTEM|2, "%s: read error", f->name);
						break;
					}
					if (holewrite(wfd, state.tmp.buffer, n) != n)
					{
						error(ERROR_SYSTEM|2, "%s: write error", f->name);
						break;
					}
					state.out->io->count += n;
				}
				holedone(wfd);
#endif
				closeout(state.out, f, wfd);
				closein(state.out, f, rfd);
				setfile(state.out, f);
				listentry(f);
			}
			else
				closeout(state.out, f, wfd);
		}
		else if (wfd != -1)
			listentry(f);
	}
	return 0;
}
示例#3
0
static int
paxdata(Pax_t* pax, Paxarchive_t* ap, Paxfile_t* f, int fd, void* b, off_t n)
{
	return holewrite(fd, b, n) == n ? 0 : -1;
}