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