position.c revision 1556
11556Srgrimes/*- 21556Srgrimes * Copyright (c) 1991, 1993, 1994 31556Srgrimes * The Regents of the University of California. All rights reserved. 41556Srgrimes * 51556Srgrimes * This code is derived from software contributed to Berkeley by 61556Srgrimes * Keith Muller of the University of California, San Diego and Lance 71556Srgrimes * Visser of Convex Computer Corporation. 81556Srgrimes * 91556Srgrimes * Redistribution and use in source and binary forms, with or without 101556Srgrimes * modification, are permitted provided that the following conditions 111556Srgrimes * are met: 121556Srgrimes * 1. Redistributions of source code must retain the above copyright 131556Srgrimes * notice, this list of conditions and the following disclaimer. 141556Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 151556Srgrimes * notice, this list of conditions and the following disclaimer in the 161556Srgrimes * documentation and/or other materials provided with the distribution. 171556Srgrimes * 3. All advertising materials mentioning features or use of this software 181556Srgrimes * must display the following acknowledgement: 191556Srgrimes * This product includes software developed by the University of 201556Srgrimes * California, Berkeley and its contributors. 211556Srgrimes * 4. Neither the name of the University nor the names of its contributors 221556Srgrimes * may be used to endorse or promote products derived from this software 231556Srgrimes * without specific prior written permission. 241556Srgrimes * 251556Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 261556Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 271556Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 281556Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 291556Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 301556Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 311556Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 321556Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 331556Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 341556Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 351556Srgrimes * SUCH DAMAGE. 361556Srgrimes */ 371556Srgrimes 381556Srgrimes#ifndef lint 391556Srgrimesstatic char sccsid[] = "@(#)position.c 8.3 (Berkeley) 4/2/94"; 401556Srgrimes#endif /* not lint */ 411556Srgrimes 421556Srgrimes#include <sys/types.h> 431556Srgrimes#include <sys/stat.h> 441556Srgrimes#include <sys/ioctl.h> 451556Srgrimes#include <sys/mtio.h> 461556Srgrimes 471556Srgrimes#include <err.h> 481556Srgrimes#include <errno.h> 491556Srgrimes#include <string.h> 501556Srgrimes#include <unistd.h> 511556Srgrimes 521556Srgrimes#include "dd.h" 531556Srgrimes#include "extern.h" 541556Srgrimes 551556Srgrimes/* 561556Srgrimes * Position input/output data streams before starting the copy. Device type 571556Srgrimes * dependent. Seekable devices use lseek, and the rest position by reading. 581556Srgrimes * Seeking past the end of file can cause null blocks to be written to the 591556Srgrimes * output. 601556Srgrimes */ 611556Srgrimesvoid 621556Srgrimespos_in() 631556Srgrimes{ 641556Srgrimes int bcnt, cnt, nr, warned; 651556Srgrimes 661556Srgrimes /* If not a character, pipe or tape device, try to seek on it. */ 671556Srgrimes if (!(in.flags & (ISCHR|ISPIPE|ISTAPE))) { 681556Srgrimes if (lseek(in.fd, (off_t)(in.offset * in.dbsz), SEEK_CUR) == -1) 691556Srgrimes err(1, "%s", in.name); 701556Srgrimes return; 711556Srgrimes } 721556Srgrimes 731556Srgrimes /* 741556Srgrimes * Read the data. If a pipe, read until satisfy the number of bytes 751556Srgrimes * being skipped. No differentiation for reading complete and partial 761556Srgrimes * blocks for other devices. 771556Srgrimes */ 781556Srgrimes for (bcnt = in.dbsz, cnt = in.offset, warned = 0; cnt;) { 791556Srgrimes if ((nr = read(in.fd, in.db, bcnt)) > 0) { 801556Srgrimes if (in.flags & ISPIPE) { 811556Srgrimes if (!(bcnt -= nr)) { 821556Srgrimes bcnt = in.dbsz; 831556Srgrimes --cnt; 841556Srgrimes } 851556Srgrimes } else 861556Srgrimes --cnt; 871556Srgrimes continue; 881556Srgrimes } 891556Srgrimes 901556Srgrimes if (nr == 0) { 911556Srgrimes if (files_cnt > 1) { 921556Srgrimes --files_cnt; 931556Srgrimes continue; 941556Srgrimes } 951556Srgrimes errx(1, "skip reached end of input"); 961556Srgrimes } 971556Srgrimes 981556Srgrimes /* 991556Srgrimes * Input error -- either EOF with no more files, or I/O error. 1001556Srgrimes * If noerror not set die. POSIX requires that the warning 1011556Srgrimes * message be followed by an I/O display. 1021556Srgrimes */ 1031556Srgrimes if (ddflags & C_NOERROR) { 1041556Srgrimes if (!warned) { 1051556Srgrimes warn("%s", in.name); 1061556Srgrimes warned = 1; 1071556Srgrimes summary(); 1081556Srgrimes } 1091556Srgrimes continue; 1101556Srgrimes } 1111556Srgrimes err(1, "%s", in.name); 1121556Srgrimes } 1131556Srgrimes} 1141556Srgrimes 1151556Srgrimesvoid 1161556Srgrimespos_out() 1171556Srgrimes{ 1181556Srgrimes struct mtop t_op; 1191556Srgrimes int cnt, n; 1201556Srgrimes 1211556Srgrimes /* 1221556Srgrimes * If not a tape, try seeking on the file. Seeking on a pipe is 1231556Srgrimes * going to fail, but don't protect the user -- they shouldn't 1241556Srgrimes * have specified the seek operand. 1251556Srgrimes */ 1261556Srgrimes if (!(out.flags & ISTAPE)) { 1271556Srgrimes if (lseek(out.fd, 1281556Srgrimes (off_t)out.offset * out.dbsz, SEEK_SET) == -1) 1291556Srgrimes err(1, "%s", out.name); 1301556Srgrimes return; 1311556Srgrimes } 1321556Srgrimes 1331556Srgrimes /* If no read access, try using mtio. */ 1341556Srgrimes if (out.flags & NOREAD) { 1351556Srgrimes t_op.mt_op = MTFSR; 1361556Srgrimes t_op.mt_count = out.offset; 1371556Srgrimes 1381556Srgrimes if (ioctl(out.fd, MTIOCTOP, &t_op) < 0) 1391556Srgrimes err(1, "%s", out.name); 1401556Srgrimes return; 1411556Srgrimes } 1421556Srgrimes 1431556Srgrimes /* Read it. */ 1441556Srgrimes for (cnt = 0; cnt < out.offset; ++cnt) { 1451556Srgrimes if ((n = read(out.fd, out.db, out.dbsz)) > 0) 1461556Srgrimes continue; 1471556Srgrimes 1481556Srgrimes if (n < 0) 1491556Srgrimes err(1, "%s", out.name); 1501556Srgrimes 1511556Srgrimes /* 1521556Srgrimes * If reach EOF, fill with NUL characters; first, back up over 1531556Srgrimes * the EOF mark. Note, cnt has not yet been incremented, so 1541556Srgrimes * the EOF read does not count as a seek'd block. 1551556Srgrimes */ 1561556Srgrimes t_op.mt_op = MTBSR; 1571556Srgrimes t_op.mt_count = 1; 1581556Srgrimes if (ioctl(out.fd, MTIOCTOP, &t_op) == -1) 1591556Srgrimes err(1, "%s", out.name); 1601556Srgrimes 1611556Srgrimes while (cnt++ < out.offset) 1621556Srgrimes if ((n = write(out.fd, out.db, out.dbsz)) != out.dbsz) 1631556Srgrimes err(1, "%s", out.name); 1641556Srgrimes break; 1651556Srgrimes } 1661556Srgrimes} 167