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