Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
lua.pkg_copy: use copy_file_range(2) if it exists
Baptiste Daroussin committed 4 years ago
commit dce033e35b18698f1b55510d845396eac73ac39c
parent 8d94fb9
4 files changed +54 -28
modified auto.def
@@ -176,7 +176,8 @@ cc-check-includes stdint.h inttypes.h
cc-check-functions arc4random arc4random_stir basename_r chflagsat \
	closefrom dirfd eaccess fopencookie fstatfs funopen getprogname strnstr \
	strtofflags strtonum sysconf utimensat __res_setservers unlinkat \
-
	faccessat fstatat openat readlinkat fflagstostr reallocarray strchrnul
+
	faccessat fstatat openat readlinkat fflagstostr reallocarray strchrnul \
+
	copy_file_range

cc-with { -includes { libutil.h }} {
	if {[cc-check-decls humanize_number]} {
modified libpkg/lua.c
@@ -194,7 +194,6 @@ lua_pkg_copy(lua_State *L)
	    "pkg.copy takes exactly two arguments");
	const char* src = luaL_checkstring(L, 1);
	const char* dst = luaL_checkstring(L, 2);
-
	char *buf1, *buf2;
	struct stat s1;
	int fd1, fd2;
	struct timespec ts[2];
@@ -213,42 +212,19 @@ lua_pkg_copy(lua_State *L)
		lua_pushinteger(L, 2);
		return (1);
	}
-
	/* 
-
	 * We should be using O_WRONLY but a weird aarch64 pmap
-
	 * bug is preventing us doing that
-
	 * See https://bugs.freebsd.org/250271
-
	 */
+

	fd2 = openat(rootfd, RELATIVE_PATH(dst), O_RDWR | O_CREAT | O_TRUNC | O_EXCL, s1.st_mode);
	if (fd2 == -1) {
		lua_pushinteger(L, 2);
		return (1);
	}
-
	if (ftruncate(fd2, s1.st_size) != 0) {
-
		lua_pushinteger(L, -1);
-
		return (1);
-
	}
-
	buf1 = mmap(NULL, s1.st_size, PROT_READ, MAP_SHARED, fd1, 0);
-
	if (buf1 == NULL) {
-
		lua_pushinteger(L, -1);
-
		return (1);
-
	}
-
	/* 
-
	 * We should be using only PROT_WRITE but a weird aarch64 pmap
-
	 * bug is preventing us doing that
-
	 * https://bugs.freebsd.org/250271
-
	 */
-
	buf2 = mmap(NULL, s1.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd2, 0);
-
	if (buf2 == NULL) {
+

+
	if (!copy_file(fd1, fd2)) {
		lua_pushinteger(L, -1);
		return (1);
	}

-
	memcpy(buf2, buf1, s1.st_size);
-

-
	munmap(buf1, s1.st_size);
-
	munmap(buf2, s1.st_size);
	fsync(fd2);
-

	close(fd1);
	close(fd2);

modified libpkg/private/utils.h
@@ -113,5 +113,6 @@ int checkflags(const char *mode, int *optr);
bool match_ucl_lists(const char *buffer, const ucl_object_t *globs, const ucl_object_t *regexes);
char *get_dirname(char *dir);
char *rtrimspace(char *buf);
+
bool copy_file(int from, int to);

#endif
modified libpkg/utils.c
@@ -869,3 +869,51 @@ rtrimspace(char *buf)

	return (buf);
}
+

+
static int
+
_copy_file(int from, int to)
+
{
+
	char buf[BUFSIZ];
+
	ssize_t r, wresid, w = 0;
+
	char *bufp;
+
	r = read(from, buf, BUFSIZ);
+
	if (r < 0)
+
		return (r);
+
	for (bufp = buf, wresid = r; ; bufp += w, wresid -= w) {
+
		w = write(to, bufp, wresid);
+
		if (w <= 0)
+
			break;
+
		if (w >= (ssize_t)wresid)
+
			break;
+
	}
+
	return (w < 0 ? w : r);
+
}
+

+
bool
+
copy_file(int from, int to)
+
{
+
#ifdef HAVE_COPY_FILE_RANGE
+
	bool cfr = true;
+
#endif
+
	int r;
+

+
	do {
+
#ifdef HAVE_COPY_FILE_RANGE
+
		if (cfr) {
+
			r = copy_file_range(from, NULL, to, NULL, SSIZE_MAX,
+
			    0);
+
			if (r < 0 && errno == EINVAL) {
+
				/* probably a non seekable FD */
+
				cfr = false;
+
			}
+
		}
+
		if (!cfr) {
+
#endif
+
			r = _copy_file(from, to);
+
#ifdef HAVE_COPY_FILE_RANGE
+
		}
+
#endif
+
	} while (r > 0);
+

+
	return (r >= 0);
+
}