position.c revision 250469
117683Spst/*- 217683Spst * Copyright (c) 1991, 1993, 1994 317683Spst * The Regents of the University of California. All rights reserved. 417683Spst * 517683Spst * This code is derived from software contributed to Berkeley by 617683Spst * Keith Muller of the University of California, San Diego and Lance 717683Spst * Visser of Convex Computer Corporation. 817683Spst * 917683Spst * Redistribution and use in source and binary forms, with or without 1017683Spst * modification, are permitted provided that the following conditions 1117683Spst * are met: 1217683Spst * 1. Redistributions of source code must retain the above copyright 1317683Spst * notice, this list of conditions and the following disclaimer. 1417683Spst * 2. Redistributions in binary form must reproduce the above copyright 1517683Spst * notice, this list of conditions and the following disclaimer in the 1617683Spst * documentation and/or other materials provided with the distribution. 1717683Spst * 4. Neither the name of the University nor the names of its contributors 1817683Spst * may be used to endorse or promote products derived from this software 1917683Spst * without specific prior written permission. 2026175Sfenner * 2126175Sfenner * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2226175Sfenner * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2317683Spst * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2426175Sfenner * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2575107Sfenner * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2675107Sfenner * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2775107Sfenner * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2875107Sfenner * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2917683Spst * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3017683Spst * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3117683Spst * SUCH DAMAGE. 3217683Spst */ 3317683Spst 3417683Spst#ifndef lint 3517683Spst#if 0 3617683Spststatic char sccsid[] = "@(#)position.c 8.3 (Berkeley) 4/2/94"; 3717683Spst#endif 3817683Spst#endif /* not lint */ 3917683Spst#include <sys/cdefs.h> 4017683Spst__FBSDID("$FreeBSD: head/bin/dd/position.c 250469 2013-05-10 18:43:36Z eadler $"); 4117683Spst 4217683Spst#include <sys/types.h> 4317683Spst#include <sys/mtio.h> 4417683Spst 4517683Spst#include <err.h> 4617683Spst#include <errno.h> 4717683Spst#include <inttypes.h> 4817683Spst#include <signal.h> 4917683Spst#include <unistd.h> 5017683Spst 5117683Spst#include "dd.h" 5217683Spst#include "extern.h" 5317683Spst 5417683Spst/* 5517683Spst * Position input/output data streams before starting the copy. Device type 5617683Spst * dependent. Seekable devices use lseek, and the rest position by reading. 5717683Spst * Seeking past the end of file can cause null blocks to be written to the 5817683Spst * output. 59127664Sbms */ 60190225Srpaulovoid 61127664Sbmspos_in(void) 62127664Sbms{ 63127664Sbms off_t cnt; 64127664Sbms int warned; 65127664Sbms ssize_t nr; 6617683Spst size_t bcnt; 6717683Spst 6817683Spst /* If known to be seekable, try to seek on it. */ 6917683Spst if (in.flags & ISSEEK) { 7017683Spst errno = 0; 7117683Spst if (lseek(in.fd, in.offset * in.dbsz, SEEK_CUR) == -1 && 72276768Sdelphij errno != 0) 73276768Sdelphij err(1, "%s", in.name); 74276768Sdelphij return; 75276768Sdelphij } 76276768Sdelphij 77276768Sdelphij /* Don't try to read a really weird amount (like negative). */ 78276768Sdelphij if (in.offset < 0) 79276768Sdelphij errx(1, "%s: illegal offset", "iseek/skip"); 80276768Sdelphij 81276768Sdelphij /* 82276768Sdelphij * Read the data. If a pipe, read until satisfy the number of bytes 83276768Sdelphij * being skipped. No differentiation for reading complete and partial 84276768Sdelphij * blocks for other devices. 85276768Sdelphij */ 86276768Sdelphij for (bcnt = in.dbsz, cnt = in.offset, warned = 0; cnt;) { 87276768Sdelphij if ((nr = read(in.fd, in.db, bcnt)) > 0) { 88276768Sdelphij if (in.flags & ISPIPE) { 89276768Sdelphij if (!(bcnt -= nr)) { 90127664Sbms bcnt = in.dbsz; 91127664Sbms --cnt; 9217683Spst } 9317683Spst } else 9417683Spst --cnt; 9517683Spst if (need_summary) 9617683Spst summary(); 9717683Spst continue; 9817683Spst } 9917683Spst 100127664Sbms if (nr == 0) { 101127664Sbms if (files_cnt > 1) { 10217683Spst --files_cnt; 103276768Sdelphij continue; 10417683Spst } 10517683Spst errx(1, "skip reached end of input"); 10617683Spst } 10717683Spst 10817683Spst /* 10917683Spst * Input error -- either EOF with no more files, or I/O error. 11017683Spst * If noerror not set die. POSIX requires that the warning 11117683Spst * message be followed by an I/O display. 11217683Spst */ 11317683Spst if (ddflags & C_NOERROR) { 11417683Spst if (!warned) { 11517683Spst warn("%s", in.name); 11617683Spst warned = 1; 11717683Spst summary(); 11817683Spst } 11917683Spst continue; 12017683Spst } 12117683Spst err(1, "%s", in.name); 12217683Spst } 12317683Spst} 12417683Spst 12517683Spstvoid 12617683Spstpos_out(void) 12717683Spst{ 12817683Spst struct mtop t_op; 12917683Spst off_t cnt; 13075107Sfenner ssize_t n; 13117683Spst 13217683Spst /* 13317683Spst * If not a tape, try seeking on the file. Seeking on a pipe is 13417683Spst * going to fail, but don't protect the user -- they shouldn't 13517683Spst * have specified the seek operand. 13617683Spst */ 13717683Spst if (out.flags & (ISSEEK | ISPIPE)) { 13817683Spst errno = 0; 13917683Spst if (lseek(out.fd, out.offset * out.dbsz, SEEK_CUR) == -1 && 14017683Spst errno != 0) 141147894Ssam err(1, "%s", out.name); 14217683Spst return; 143127664Sbms } 144127664Sbms 145127664Sbms /* Don't try to read a really weird amount (like negative). */ 146127664Sbms if (out.offset < 0) 147127664Sbms errx(1, "%s: illegal offset", "oseek/seek"); 148127664Sbms 149127664Sbms /* If no read access, try using mtio. */ 150127664Sbms if (out.flags & NOREAD) { 151127664Sbms t_op.mt_op = MTFSR; 152127664Sbms t_op.mt_count = out.offset; 153127664Sbms 154127664Sbms if (ioctl(out.fd, MTIOCTOP, &t_op) == -1) 155127664Sbms err(1, "%s", out.name); 156127664Sbms return; 157127664Sbms } 158127664Sbms 159127664Sbms /* Read it. */ 160127664Sbms for (cnt = 0; cnt < out.offset; ++cnt) { 161127664Sbms if ((n = read(out.fd, out.db, out.dbsz)) > 0) 16217683Spst continue; 16375107Sfenner 16475107Sfenner if (n == -1) 16517683Spst err(1, "%s", out.name); 16617683Spst 16717683Spst /* 16817683Spst * If reach EOF, fill with NUL characters; first, back up over 16917683Spst * the EOF mark. Note, cnt has not yet been incremented, so 17017683Spst * the EOF read does not count as a seek'd block. 17117683Spst */ 17217683Spst t_op.mt_op = MTBSR; 17317683Spst t_op.mt_count = 1; 17417683Spst if (ioctl(out.fd, MTIOCTOP, &t_op) == -1) 17575107Sfenner err(1, "%s", out.name); 17675107Sfenner 17717683Spst while (cnt++ < out.offset) { 17817683Spst n = write(out.fd, out.db, out.dbsz); 17917683Spst if (n == -1) 18017683Spst err(1, "%s", out.name); 18117683Spst if ((size_t)n != out.dbsz) 18217683Spst errx(1, "%s: write failure", out.name); 18317683Spst } 18417683Spst break; 18517683Spst } 18617683Spst} 18717683Spst