157df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey/* $NetBSD: utils.c,v 1.41 2012/01/04 15:58:37 christos Exp $ */ 257df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey 357df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey/*- 457df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey * Copyright (c) 1991, 1993, 1994 557df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey * The Regents of the University of California. All rights reserved. 657df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey * 757df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey * Redistribution and use in source and binary forms, with or without 857df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey * modification, are permitted provided that the following conditions 957df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey * are met: 1057df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey * 1. Redistributions of source code must retain the above copyright 1157df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey * notice, this list of conditions and the following disclaimer. 1257df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey * 2. Redistributions in binary form must reproduce the above copyright 1357df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey * notice, this list of conditions and the following disclaimer in the 1457df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey * documentation and/or other materials provided with the distribution. 1557df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey * 3. Neither the name of the University nor the names of its contributors 1657df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey * may be used to endorse or promote products derived from this software 1757df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey * without specific prior written permission. 1857df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey * 1957df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2057df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2157df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2257df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2357df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2457df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2557df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2657df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2757df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2857df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2957df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey * SUCH DAMAGE. 3057df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey */ 3157df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey 3257df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey#include <sys/cdefs.h> 3357df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey#ifndef lint 3457df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey#if 0 3557df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkeystatic char sccsid[] = "@(#)utils.c 8.3 (Berkeley) 4/1/94"; 3657df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey#else 3757df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey__RCSID("$NetBSD: utils.c,v 1.41 2012/01/04 15:58:37 christos Exp $"); 3857df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey#endif 3957df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey#endif /* not lint */ 4057df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey 4157df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey#include <sys/mman.h> 4257df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey#include <sys/param.h> 4357df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey#include <sys/stat.h> 4457df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey#include <sys/time.h> 4557df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey#ifndef ANDROID 4657df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey#include <sys/extattr.h> 4757df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey#endif 4857df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey 4957df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey#include <err.h> 5057df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey#include <errno.h> 5157df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey#include <fcntl.h> 5257df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey#include <fts.h> 5357df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey#include <stdbool.h> 5457df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey#include <stdio.h> 5557df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey#include <stdlib.h> 5657df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey#include <string.h> 5757df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey#include <unistd.h> 5857df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey 5957df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey#include "extern.h" 6057df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey 6157df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey#ifdef ANDROID 6257df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey#define MAXBSIZE 65536 6357df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey#endif 6457df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey 6557df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey#define MMAP_MAX_SIZE (8 * 1048576) 6657df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey#define MMAP_MAX_WRITE (64 * 1024) 6757df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey 6857df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkeyint 6957df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkeyset_utimes(const char *file, struct stat *fs) 7057df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey{ 7157df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey static struct timeval tv[2]; 7257df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey 7357df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey#ifdef ANDROID 7457df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey tv[0].tv_sec = fs->st_atime; 7557df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey tv[0].tv_usec = 0; 7657df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey tv[1].tv_sec = fs->st_mtime; 7757df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey tv[1].tv_usec = 0; 7857df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey 7957df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey if (utimes(file, tv)) { 8057df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey warn("utimes: %s", file); 8157df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey return 1; 8257df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey } 8357df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey#else 8457df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey TIMESPEC_TO_TIMEVAL(&tv[0], &fs->st_atimespec); 8557df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey TIMESPEC_TO_TIMEVAL(&tv[1], &fs->st_mtimespec); 8657df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey 8757df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey if (lutimes(file, tv)) { 8857df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey warn("lutimes: %s", file); 8957df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey return (1); 9057df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey } 9157df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey#endif 9257df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey return (0); 9357df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey} 9457df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey 9557df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkeystruct finfo { 9657df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey const char *from; 9757df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey const char *to; 9857df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey size_t size; 9957df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey}; 10057df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey 10157df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkeystatic void 10257df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkeyprogress(const struct finfo *fi, size_t written) 10357df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey{ 10457df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey int pcent = (int)((100.0 * written) / fi->size); 10557df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey 10657df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey pinfo = 0; 10757df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey (void)fprintf(stderr, "%s => %s %zu/%zu bytes %d%% written\n", 10857df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey fi->from, fi->to, written, fi->size, pcent); 10957df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey} 11057df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey 11157df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkeyint 11257df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkeycopy_file(FTSENT *entp, int dne) 11357df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey{ 11457df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey static char buf[MAXBSIZE]; 11557df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey struct stat to_stat, *fs; 11657df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey int ch, checkch, from_fd, rcount, rval, to_fd, tolnk, wcount; 11757df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey char *p; 11857df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey size_t ptotal = 0; 11957df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey 12057df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey if ((from_fd = open(entp->fts_path, O_RDONLY, 0)) == -1) { 12157df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey warn("%s", entp->fts_path); 12257df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey return (1); 12357df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey } 12457df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey 12557df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey to_fd = -1; 12657df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey fs = entp->fts_statp; 12757df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey tolnk = ((Rflag && !(Lflag || Hflag)) || Pflag); 12857df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey 12957df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey /* 13057df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey * If the file exists and we're interactive, verify with the user. 13157df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey * If the file DNE, set the mode to be the from file, minus setuid 13257df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey * bits, modified by the umask; arguably wrong, but it makes copying 13357df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey * executables work right and it's been that way forever. (The 13457df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey * other choice is 666 or'ed with the execute bits on the from file 13557df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey * modified by the umask.) 13657df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey */ 13757df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey if (!dne) { 13857df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey struct stat sb; 13957df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey int sval; 14057df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey 14157df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey if (iflag) { 14257df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey (void)fprintf(stderr, "overwrite %s? ", to.p_path); 14357df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey checkch = ch = getchar(); 14457df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey while (ch != '\n' && ch != EOF) 14557df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey ch = getchar(); 14657df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey if (checkch != 'y' && checkch != 'Y') { 14757df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey (void)close(from_fd); 14857df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey return (0); 14957df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey } 15057df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey } 15157df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey 15257df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey sval = tolnk ? 15357df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey lstat(to.p_path, &sb) : stat(to.p_path, &sb); 15457df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey if (sval == -1) { 15557df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey warn("stat: %s", to.p_path); 15657df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey (void)close(from_fd); 15757df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey return (1); 15857df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey } 15957df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey 16057df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey if (!(tolnk && S_ISLNK(sb.st_mode))) 16157df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey to_fd = open(to.p_path, O_WRONLY | O_TRUNC, 0); 16257df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey } else 16357df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey to_fd = open(to.p_path, O_WRONLY | O_TRUNC | O_CREAT, 16457df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey fs->st_mode & ~(S_ISUID | S_ISGID)); 16557df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey 16657df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey if (to_fd == -1 && (fflag || tolnk)) { 16757df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey /* 16857df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey * attempt to remove existing destination file name and 16957df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey * create a new file 17057df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey */ 17157df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey (void)unlink(to.p_path); 17257df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey to_fd = open(to.p_path, O_WRONLY | O_TRUNC | O_CREAT, 17357df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey fs->st_mode & ~(S_ISUID | S_ISGID)); 17457df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey } 17557df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey 17657df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey if (to_fd == -1) { 17757df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey warn("%s", to.p_path); 17857df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey (void)close(from_fd); 17957df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey return (1); 18057df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey } 18157df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey 18257df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey rval = 0; 18357df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey 18457df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey /* if hard linking then simply close the open fds, link and return */ 18557df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey if (lflag) { 18657df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey (void)close(from_fd); 18757df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey (void)close(to_fd); 18857df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey (void)unlink(to.p_path); 18957df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey if (link(entp->fts_path, to.p_path)) { 19057df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey warn("%s", to.p_path); 19157df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey return (1); 19257df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey } 19357df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey return (0); 19457df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey } 19557df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey /* NOTREACHED */ 19657df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey 19757df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey /* 19857df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey * There's no reason to do anything other than close the file 19957df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey * now if it's empty, so let's not bother. 20057df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey */ 20157df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey if (fs->st_size > 0) { 20257df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey struct finfo fi; 20357df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey 20457df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey fi.from = entp->fts_path; 20557df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey fi.to = to.p_path; 20657df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey fi.size = (size_t)fs->st_size; 20757df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey 20857df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey /* 20957df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey * Mmap and write if less than 8M (the limit is so 21057df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey * we don't totally trash memory on big files). 21157df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey * This is really a minor hack, but it wins some CPU back. 21257df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey */ 21357df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey bool use_read; 21457df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey 21557df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey use_read = true; 21657df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey if (fs->st_size <= MMAP_MAX_SIZE) { 21757df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey size_t fsize = (size_t)fs->st_size; 21857df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey p = mmap(NULL, fsize, PROT_READ, MAP_FILE|MAP_SHARED, 21957df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey from_fd, (off_t)0); 22057df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey if (p != MAP_FAILED) { 22157df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey size_t remainder; 22257df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey 22357df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey use_read = false; 22457df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey 22557df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey (void) madvise(p, (size_t)fs->st_size, 22657df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey MADV_SEQUENTIAL); 22757df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey 22857df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey /* 22957df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey * Write out the data in small chunks to 23057df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey * avoid locking the output file for a 23157df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey * long time if the reading the data from 23257df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey * the source is slow. 23357df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey */ 23457df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey remainder = fsize; 23557df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey do { 23657df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey ssize_t chunk; 23757df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey 23857df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey chunk = (remainder > MMAP_MAX_WRITE) ? 23957df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey MMAP_MAX_WRITE : remainder; 24057df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey if (write(to_fd, &p[fsize - remainder], 24157df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey chunk) != chunk) { 24257df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey warn("%s", to.p_path); 24357df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey rval = 1; 24457df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey break; 24557df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey } 24657df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey remainder -= chunk; 24757df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey ptotal += chunk; 24857df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey if (pinfo) 24957df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey progress(&fi, ptotal); 25057df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey } while (remainder > 0); 25157df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey 25257df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey if (munmap(p, fsize) < 0) { 25357df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey warn("%s", entp->fts_path); 25457df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey rval = 1; 25557df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey } 25657df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey } 25757df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey } 25857df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey 25957df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey if (use_read) { 26057df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey while ((rcount = read(from_fd, buf, MAXBSIZE)) > 0) { 26157df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey wcount = write(to_fd, buf, (size_t)rcount); 26257df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey if (rcount != wcount || wcount == -1) { 26357df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey warn("%s", to.p_path); 26457df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey rval = 1; 26557df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey break; 26657df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey } 26757df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey ptotal += wcount; 26857df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey if (pinfo) 26957df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey progress(&fi, ptotal); 27057df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey } 27157df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey if (rcount < 0) { 27257df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey warn("%s", entp->fts_path); 27357df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey rval = 1; 27457df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey } 27557df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey } 27657df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey } 27757df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey 27857df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey#ifndef ANDROID 27957df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey if (pflag && (fcpxattr(from_fd, to_fd) != 0)) 28057df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey warn("%s: error copying extended attributes", to.p_path); 28157df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey#endif 28257df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey 28357df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey (void)close(from_fd); 28457df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey 28557df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey if (rval == 1) { 28657df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey (void)close(to_fd); 28757df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey return (1); 28857df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey } 28957df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey 29057df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey if (pflag && setfile(fs, to_fd)) 29157df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey rval = 1; 29257df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey /* 29357df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey * If the source was setuid or setgid, lose the bits unless the 29457df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey * copy is owned by the same user and group. 29557df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey */ 29657df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey#define RETAINBITS \ 29757df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey (S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO) 29857df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey if (!pflag && dne 29957df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey && fs->st_mode & (S_ISUID | S_ISGID) && fs->st_uid == myuid) { 30057df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey if (fstat(to_fd, &to_stat)) { 30157df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey warn("%s", to.p_path); 30257df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey rval = 1; 30357df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey } else if (fs->st_gid == to_stat.st_gid && 30457df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey fchmod(to_fd, fs->st_mode & RETAINBITS & ~myumask)) { 30557df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey warn("%s", to.p_path); 30657df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey rval = 1; 30757df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey } 30857df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey } 30957df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey if (close(to_fd)) { 31057df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey warn("%s", to.p_path); 31157df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey rval = 1; 31257df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey } 31357df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey /* set the mod/access times now after close of the fd */ 31457df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey if (pflag && set_utimes(to.p_path, fs)) { 31557df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey rval = 1; 31657df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey } 31757df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey return (rval); 31857df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey} 31957df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey 32057df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkeyint 32157df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkeycopy_link(FTSENT *p, int exists) 32257df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey{ 32357df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey int len; 32457df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey char target[MAXPATHLEN]; 32557df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey 32657df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey if ((len = readlink(p->fts_path, target, sizeof(target)-1)) == -1) { 32757df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey warn("readlink: %s", p->fts_path); 32857df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey return (1); 32957df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey } 33057df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey target[len] = '\0'; 33157df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey if (exists && unlink(to.p_path)) { 33257df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey warn("unlink: %s", to.p_path); 33357df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey return (1); 33457df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey } 33557df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey if (symlink(target, to.p_path)) { 33657df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey warn("symlink: %s", target); 33757df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey return (1); 33857df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey } 33957df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey return (pflag ? setfile(p->fts_statp, 0) : 0); 34057df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey} 34157df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey 34257df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkeyint 34357df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkeycopy_fifo(struct stat *from_stat, int exists) 34457df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey{ 34557df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey if (exists && unlink(to.p_path)) { 34657df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey warn("unlink: %s", to.p_path); 34757df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey return (1); 34857df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey } 34957df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey if (mkfifo(to.p_path, from_stat->st_mode)) { 35057df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey warn("mkfifo: %s", to.p_path); 35157df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey return (1); 35257df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey } 35357df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey return (pflag ? setfile(from_stat, 0) : 0); 35457df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey} 35557df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey 35657df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkeyint 35757df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkeycopy_special(struct stat *from_stat, int exists) 35857df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey{ 35957df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey if (exists && unlink(to.p_path)) { 36057df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey warn("unlink: %s", to.p_path); 36157df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey return (1); 36257df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey } 36357df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey if (mknod(to.p_path, from_stat->st_mode, from_stat->st_rdev)) { 36457df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey warn("mknod: %s", to.p_path); 36557df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey return (1); 36657df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey } 36757df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey return (pflag ? setfile(from_stat, 0) : 0); 36857df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey} 36957df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey 37057df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey 37157df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey/* 37257df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey * Function: setfile 37357df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey * 37457df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey * Purpose: 37557df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey * Set the owner/group/permissions for the "to" file to the information 37657df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey * in the stat structure. If fd is zero, also call set_utimes() to set 37757df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey * the mod/access times. If fd is non-zero, the caller must do a utimes 37857df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey * itself after close(fd). 37957df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey */ 38057df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkeyint 38157df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkeysetfile(struct stat *fs, int fd) 38257df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey{ 38357df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey int rval, islink; 38457df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey 38557df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey rval = 0; 38657df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey islink = S_ISLNK(fs->st_mode); 38757df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey fs->st_mode &= S_ISUID | S_ISGID | S_IRWXU | S_IRWXG | S_IRWXO; 38857df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey 38957df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey /* 39057df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey * Changing the ownership probably won't succeed, unless we're root 39157df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey * or POSIX_CHOWN_RESTRICTED is not set. Set uid/gid before setting 39257df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey * the mode; current BSD behavior is to remove all setuid bits on 39357df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey * chown. If chown fails, lose setuid/setgid bits. 39457df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey */ 39557df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey if (fd ? fchown(fd, fs->st_uid, fs->st_gid) : 39657df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey lchown(to.p_path, fs->st_uid, fs->st_gid)) { 39757df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey if (errno != EPERM) { 39857df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey warn("chown: %s", to.p_path); 39957df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey rval = 1; 40057df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey } 40157df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey fs->st_mode &= ~(S_ISUID | S_ISGID); 40257df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey } 40357df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey#ifdef ANDROID 40457df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey if (fd ? fchmod(fd, fs->st_mode) : chmod(to.p_path, fs->st_mode)) { 40557df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey#else 40657df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey if (fd ? fchmod(fd, fs->st_mode) : lchmod(to.p_path, fs->st_mode)) { 40757df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey#endif 40857df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey warn("chmod: %s", to.p_path); 40957df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey rval = 1; 41057df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey } 41157df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey 41257df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey#ifndef ANDROID 41357df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey if (!islink && !Nflag) { 41457df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey unsigned long fflags = fs->st_flags; 41557df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey /* 41657df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey * XXX 41757df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey * NFS doesn't support chflags; ignore errors unless 41857df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey * there's reason to believe we're losing bits. 41957df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey * (Note, this still won't be right if the server 42057df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey * supports flags and we were trying to *remove* flags 42157df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey * on a file that we copied, i.e., that we didn't create.) 42257df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey */ 42357df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey errno = 0; 42457df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey if ((fd ? fchflags(fd, fflags) : 42557df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey chflags(to.p_path, fflags)) == -1) 42657df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey if (errno != EOPNOTSUPP || fs->st_flags != 0) { 42757df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey warn("chflags: %s", to.p_path); 42857df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey rval = 1; 42957df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey } 43057df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey } 43157df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey#endif 43257df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey /* if fd is non-zero, caller must call set_utimes() after close() */ 43357df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey if (fd == 0 && set_utimes(to.p_path, fs)) 43457df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey rval = 1; 43557df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey return (rval); 43657df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey} 43757df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey 43857df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkeyvoid 43957df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkeycp_usage(void) 44057df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey{ 44157df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey (void)fprintf(stderr, 44257df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey "usage: cp [-R [-H | -L | -P]] [-f | -i] [-alNpv] src target\n" 44357df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey " cp [-R [-H | -L | -P]] [-f | -i] [-alNpv] src1 ... srcN directory\n"); 44457df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey exit(1); 44557df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey /* NOTREACHED */ 44657df14c654a968e5b85d508cbd0871632011cb0eJeff Sharkey} 447