position.c revision 51335
1145519Sdarrenr/*-
2145519Sdarrenr * Copyright (c) 1991, 1993, 1994
331183Speter *	The Regents of the University of California.  All rights reserved.
431183Speter *
5255332Scy * This code is derived from software contributed to Berkeley by
631183Speter * Keith Muller of the University of California, San Diego and Lance
7145519Sdarrenr * Visser of Convex Computer Corporation.
831183Speter *
9161357Sguido * Redistribution and use in source and binary forms, with or without
1063537Sarchie * modification, are permitted provided that the following conditions
1131183Speter * are met:
1253024Sguido * 1. Redistributions of source code must retain the above copyright
1331183Speter *    notice, this list of conditions and the following disclaimer.
1431183Speter * 2. Redistributions in binary form must reproduce the above copyright
1531183Speter *    notice, this list of conditions and the following disclaimer in the
1631183Speter *    documentation and/or other materials provided with the distribution.
17170268Sdarrenr * 3. All advertising materials mentioning features or use of this software
1831183Speter *    must display the following acknowledgement:
19170268Sdarrenr *	This product includes software developed by the University of
2031183Speter *	California, Berkeley and its contributors.
2131183Speter * 4. Neither the name of the University nor the names of its contributors
2231183Speter *    may be used to endorse or promote products derived from this software
2331183Speter *    without specific prior written permission.
2431183Speter *
2531183Speter * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2631183Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2731183Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2831183Speter * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29255332Scy * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3031183Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3131183Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3231183Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3331183Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34170268Sdarrenr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35255332Scy * SUCH DAMAGE.
36170268Sdarrenr */
3731183Speter
3831183Speter#ifndef lint
3931183Speter#if 0
4031183Speterstatic char sccsid[] = "@(#)position.c	8.3 (Berkeley) 4/2/94";
4131183Speter#endif
4231183Speterstatic const char rcsid[] =
4331183Speter  "$FreeBSD: head/bin/dd/position.c 51335 1999-09-16 19:50:59Z green $";
4431183Speter#endif /* not lint */
4531183Speter
4631183Speter#include <sys/types.h>
4731183Speter#include <sys/mtio.h>
4864591Sdarrenr
49145519Sdarrenr#include <err.h>
5031183Speter#include <errno.h>
5137074Speter#include <unistd.h>
5231183Speter
5331183Speter#include "dd.h"
5431183Speter#include "extern.h"
5531183Speter
5631183Speter/*
5731183Speter * Position input/output data streams before starting the copy.  Device type
5831183Speter * dependent.  Seekable devices use lseek, and the rest position by reading.
5931183Speter * Seeking past the end of file can cause null blocks to be written to the
6031183Speter * output.
6131183Speter */
6231183Spetervoid
6331183Speterpos_in()
6431183Speter{
6531183Speter	off_t cnt;
6631183Speter	int warned;
6731183Speter	ssize_t nr;
6831183Speter	size_t bcnt;
6931183Speter
7031183Speter	/* If known to be seekable, try to seek on it. */
7131183Speter	if (in.flags & ISSEEK) {
7231183Speter		errno = 0;
7331183Speter		if (lseek(in.fd, in.offset * in.dbsz, SEEK_CUR) == -1 &&
7431183Speter		    errno != 0)
7531183Speter			err(1, "%s", in.name);
7631183Speter		return;
7731183Speter	}
7831183Speter
7931183Speter	/*
8031183Speter	 * Read the data.  If a pipe, read until satisfy the number of bytes
8131183Speter	 * being skipped.  No differentiation for reading complete and partial
8231183Speter	 * blocks for other devices.
8331183Speter	 */
8431183Speter	for (bcnt = in.dbsz, cnt = in.offset, warned = 0; cnt;) {
8531183Speter		if ((nr = read(in.fd, in.db, bcnt)) > 0) {
8631183Speter			if (in.flags & ISPIPE) {
8731183Speter				if (!(bcnt -= nr)) {
8831183Speter					bcnt = in.dbsz;
8931183Speter					--cnt;
9031183Speter				}
9131183Speter			} else
9231183Speter				--cnt;
9331183Speter			continue;
9431183Speter		}
9531183Speter
9631183Speter		if (nr == 0) {
9731183Speter			if (files_cnt > 1) {
9831183Speter				--files_cnt;
9931183Speter				continue;
10031183Speter			}
10131183Speter			errx(1, "skip reached end of input");
10231183Speter		}
10331183Speter
10431183Speter		/*
10531183Speter		 * Input error -- either EOF with no more files, or I/O error.
10631183Speter		 * If noerror not set die.  POSIX requires that the warning
10731183Speter		 * message be followed by an I/O display.
10831183Speter		 */
10931183Speter		if (ddflags & C_NOERROR) {
11031183Speter			if (!warned) {
11131183Speter				warn("%s", in.name);
11231183Speter				warned = 1;
11331183Speter				summary();
11431183Speter			}
11531183Speter			continue;
11631183Speter		}
11731183Speter		err(1, "%s", in.name);
11831183Speter	}
11931183Speter}
12031183Speter
12131183Spetervoid
12231183Speterpos_out()
12331183Speter{
12431183Speter	struct mtop t_op;
12531183Speter	off_t cnt;
12631183Speter	ssize_t n;
12731183Speter
12831183Speter	/*
12931183Speter	 * If not a tape, try seeking on the file.  Seeking on a pipe is
13031183Speter	 * going to fail, but don't protect the user -- they shouldn't
13131183Speter	 * have specified the seek operand.
13231183Speter	 */
13331183Speter	if (!(out.flags & ISTAPE)) {
13431183Speter		errno = 0;
13531183Speter		if (lseek(out.fd, out.offset * out.dbsz, SEEK_CUR) == -1 &&
13631183Speter		    errno != 0)
13731183Speter			err(1, "%s", out.name);
13831183Speter		return;
13931183Speter	}
14031183Speter
14131183Speter	/* If no read access, try using mtio. */
14231183Speter	if (out.flags & NOREAD) {
14331183Speter		t_op.mt_op = MTFSR;
14431183Speter		t_op.mt_count = out.offset;
14531183Speter
14631183Speter		if (ioctl(out.fd, MTIOCTOP, &t_op) == -1)
14731183Speter			err(1, "%s", out.name);
14831183Speter		return;
14931183Speter	}
15031183Speter
15131183Speter	/* Read it. */
15231183Speter	for (cnt = 0; cnt < out.offset; ++cnt) {
15331183Speter		if ((n = read(out.fd, out.db, out.dbsz)) > 0)
15431183Speter			continue;
15531183Speter
15631183Speter		if (n == -1)
15731183Speter			err(1, "%s", out.name);
15831183Speter
15931183Speter		/*
16031183Speter		 * If reach EOF, fill with NUL characters; first, back up over
16131183Speter		 * the EOF mark.  Note, cnt has not yet been incremented, so
16231183Speter		 * the EOF read does not count as a seek'd block.
16331183Speter		 */
16431183Speter		t_op.mt_op = MTBSR;
16555924Sguido		t_op.mt_count = 1;
16631183Speter		if (ioctl(out.fd, MTIOCTOP, &t_op) == -1)
16731183Speter			err(1, "%s", out.name);
16831183Speter
16931183Speter		while (cnt++ < out.offset)
17031183Speter			if ((n = write(out.fd, out.db, out.dbsz)) != out.dbsz)
17131183Speter				err(1, "%s", out.name);
17231183Speter		break;
17331183Speter	}
17431183Speter}
17531183Speter