position.c revision 250469
1238106Sdes/*- 2238106Sdes * Copyright (c) 1991, 1993, 1994 3238106Sdes * The Regents of the University of California. All rights reserved. 4238106Sdes * 5238106Sdes * This code is derived from software contributed to Berkeley by 6238106Sdes * Keith Muller of the University of California, San Diego and Lance 7238106Sdes * Visser of Convex Computer Corporation. 8238106Sdes * 9238106Sdes * Redistribution and use in source and binary forms, with or without 10238106Sdes * modification, are permitted provided that the following conditions 11238106Sdes * are met: 12238106Sdes * 1. Redistributions of source code must retain the above copyright 13238106Sdes * notice, this list of conditions and the following disclaimer. 14238106Sdes * 2. Redistributions in binary form must reproduce the above copyright 15238106Sdes * notice, this list of conditions and the following disclaimer in the 16238106Sdes * documentation and/or other materials provided with the distribution. 17238106Sdes * 4. Neither the name of the University nor the names of its contributors 18238106Sdes * may be used to endorse or promote products derived from this software 19238106Sdes * without specific prior written permission. 20238106Sdes * 21238106Sdes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22238106Sdes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23238106Sdes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24269257Sdes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25269257Sdes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26269257Sdes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27269257Sdes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28269257Sdes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29269257Sdes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30269257Sdes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31269257Sdes * SUCH DAMAGE. 32269257Sdes */ 33269257Sdes 34238106Sdes#ifndef lint 35238106Sdes#if 0 36238106Sdesstatic char sccsid[] = "@(#)position.c 8.3 (Berkeley) 4/2/94"; 37238106Sdes#endif 38238106Sdes#endif /* not lint */ 39238106Sdes#include <sys/cdefs.h> 40238106Sdes__FBSDID("$FreeBSD: head/bin/dd/position.c 250469 2013-05-10 18:43:36Z eadler $"); 41238106Sdes 42238106Sdes#include <sys/types.h> 43238106Sdes#include <sys/mtio.h> 44238106Sdes 45238106Sdes#include <err.h> 46238106Sdes#include <errno.h> 47238106Sdes#include <inttypes.h> 48238106Sdes#include <signal.h> 49238106Sdes#include <unistd.h> 50238106Sdes 51238106Sdes#include "dd.h" 52238106Sdes#include "extern.h" 53238106Sdes 54238106Sdes/* 55238106Sdes * Position input/output data streams before starting the copy. Device type 56238106Sdes * dependent. Seekable devices use lseek, and the rest position by reading. 57238106Sdes * Seeking past the end of file can cause null blocks to be written to the 58238106Sdes * output. 59238106Sdes */ 60238106Sdesvoid 61238106Sdespos_in(void) 62238106Sdes{ 63238106Sdes off_t cnt; 64238106Sdes int warned; 65238106Sdes ssize_t nr; 66238106Sdes size_t bcnt; 67238106Sdes 68238106Sdes /* If known to be seekable, try to seek on it. */ 69238106Sdes if (in.flags & ISSEEK) { 70238106Sdes errno = 0; 71238106Sdes if (lseek(in.fd, in.offset * in.dbsz, SEEK_CUR) == -1 && 72238106Sdes errno != 0) 73238106Sdes err(1, "%s", in.name); 74238106Sdes return; 75238106Sdes } 76238106Sdes 77238106Sdes /* Don't try to read a really weird amount (like negative). */ 78238106Sdes if (in.offset < 0) 79238106Sdes errx(1, "%s: illegal offset", "iseek/skip"); 80238106Sdes 81238106Sdes /* 82238106Sdes * Read the data. If a pipe, read until satisfy the number of bytes 83238106Sdes * being skipped. No differentiation for reading complete and partial 84238106Sdes * blocks for other devices. 85238106Sdes */ 86238106Sdes for (bcnt = in.dbsz, cnt = in.offset, warned = 0; cnt;) { 87238106Sdes if ((nr = read(in.fd, in.db, bcnt)) > 0) { 88238106Sdes if (in.flags & ISPIPE) { 89238106Sdes if (!(bcnt -= nr)) { 90238106Sdes bcnt = in.dbsz; 91238106Sdes --cnt; 92238106Sdes } 93238106Sdes } else 94238106Sdes --cnt; 95238106Sdes if (need_summary) 96238106Sdes summary(); 97238106Sdes continue; 98238106Sdes } 99238106Sdes 100238106Sdes if (nr == 0) { 101238106Sdes if (files_cnt > 1) { 102238106Sdes --files_cnt; 103238106Sdes continue; 104238106Sdes } 105238106Sdes errx(1, "skip reached end of input"); 106238106Sdes } 107238106Sdes 108238106Sdes /* 109238106Sdes * Input error -- either EOF with no more files, or I/O error. 110238106Sdes * If noerror not set die. POSIX requires that the warning 111238106Sdes * message be followed by an I/O display. 112238106Sdes */ 113238106Sdes if (ddflags & C_NOERROR) { 114238106Sdes if (!warned) { 115238106Sdes warn("%s", in.name); 116238106Sdes warned = 1; 117238106Sdes summary(); 118238106Sdes } 119238106Sdes continue; 120238106Sdes } 121238106Sdes err(1, "%s", in.name); 122238106Sdes } 123238106Sdes} 124238106Sdes 125238106Sdesvoid 126238106Sdespos_out(void) 127238106Sdes{ 128238106Sdes struct mtop t_op; 129238106Sdes off_t cnt; 130238106Sdes ssize_t n; 131238106Sdes 132238106Sdes /* 133238106Sdes * If not a tape, try seeking on the file. Seeking on a pipe is 134238106Sdes * going to fail, but don't protect the user -- they shouldn't 135238106Sdes * have specified the seek operand. 136238106Sdes */ 137238106Sdes if (out.flags & (ISSEEK | ISPIPE)) { 138238106Sdes errno = 0; 139238106Sdes if (lseek(out.fd, out.offset * out.dbsz, SEEK_CUR) == -1 && 140238106Sdes errno != 0) 141238106Sdes err(1, "%s", out.name); 142238106Sdes return; 143238106Sdes } 144238106Sdes 145238106Sdes /* Don't try to read a really weird amount (like negative). */ 146238106Sdes if (out.offset < 0) 147238106Sdes errx(1, "%s: illegal offset", "oseek/seek"); 148238106Sdes 149238106Sdes /* If no read access, try using mtio. */ 150238106Sdes if (out.flags & NOREAD) { 151238106Sdes t_op.mt_op = MTFSR; 152238106Sdes t_op.mt_count = out.offset; 153238106Sdes 154238106Sdes if (ioctl(out.fd, MTIOCTOP, &t_op) == -1) 155238106Sdes err(1, "%s", out.name); 156238106Sdes return; 157238106Sdes } 158238106Sdes 159238106Sdes /* Read it. */ 160238106Sdes for (cnt = 0; cnt < out.offset; ++cnt) { 161238106Sdes if ((n = read(out.fd, out.db, out.dbsz)) > 0) 162238106Sdes continue; 163238106Sdes 164238106Sdes if (n == -1) 165238106Sdes err(1, "%s", out.name); 166238106Sdes 167238106Sdes /* 168238106Sdes * If reach EOF, fill with NUL characters; first, back up over 169238106Sdes * the EOF mark. Note, cnt has not yet been incremented, so 170238106Sdes * the EOF read does not count as a seek'd block. 171238106Sdes */ 172238106Sdes t_op.mt_op = MTBSR; 173238106Sdes t_op.mt_count = 1; 174238106Sdes if (ioctl(out.fd, MTIOCTOP, &t_op) == -1) 175238106Sdes err(1, "%s", out.name); 176238106Sdes 177238106Sdes while (cnt++ < out.offset) { 178238106Sdes n = write(out.fd, out.db, out.dbsz); 179238106Sdes if (n == -1) 180238106Sdes err(1, "%s", out.name); 181238106Sdes if ((size_t)n != out.dbsz) 182238106Sdes errx(1, "%s: write failure", out.name); 183238106Sdes } 184238106Sdes break; 185238106Sdes } 186238106Sdes} 187238106Sdes