commit: e18b5bdc80e3c59ac03dd1d6b7f682e3c9a01c4e
parent d123b8b11e60c5a0fddba6c4c221ceb1968529ad
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date: Fri, 10 May 2024 21:17:13 +0200
cmd/install: Move copy_file_range wrapper to lib/fs.c
Diffstat:
M | cmd/install.c | 50 | +------------------------------------------------- |
M | lib/fs.c | 55 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
M | lib/fs.h | 11 | +++++++++++ |
3 files changed, 67 insertions(+), 49 deletions(-)
diff --git a/cmd/install.c b/cmd/install.c
@@ -19,7 +19,7 @@
#include <stdio.h> // fprintf
#include <string.h> // strerror
#include <sys/stat.h>
-#include <unistd.h> // getopt, copy_file_range
+#include <unistd.h> // getopt
bool preserve_times = false, create_directories = false;
@@ -32,54 +32,6 @@ uid_t user = (uid_t)-1;
gid_t group = (gid_t)-1;
char *argv0 = "install";
-#undef MIN
-#define MIN(a, b) (((a) < (b)) ? (a) : (b))
-static int
-manual_file_copy(int fd_in, int fd_out, off_t len, int flags)
-{
- do
- {
- char buf[BUFSIZ];
-
- ssize_t nread = read(fd_in, buf, MIN(BUFSIZ, len));
- if(nread < 0) return nread;
-
- ssize_t nwrite = write(fd_out, buf, (size_t)nread);
- if(nwrite < 0) return nwrite;
-
- len -= nwrite;
- } while(len > 0);
-
- return 0;
-}
-
-#ifdef HAS_COPY_FILE_RANGE
-static int
-auto_file_copy(int fd_in, int fd_out, off_t len, int flags)
-{
- off_t ret = -1;
- do
- {
- ret = copy_file_range(fd_in, NULL, fd_out, NULL, len, 0);
- if(ret < 0)
- {
- if(errno == EXDEV)
- {
- errno = 0;
- return manual_file_copy(fd_in, fd_out, len, flags);
- }
-
- return ret;
- }
- len -= ret;
- } while(len > 0 && ret > 0);
-
- return 0;
-}
-#else
-#define auto_file_copy manual_file_copy
-#endif
-
static int
do_install(char *src, char *dest, bool is_dir)
{
diff --git a/lib/fs.c b/lib/fs.c
@@ -2,9 +2,16 @@
// SPDX-FileCopyrightText: 2017 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me>
// SPDX-License-Identifier: MPL-2.0
+// For copy_file_range
+#define _GNU_SOURCE // musl, glibc
+#define _DEFAULT_SOURCE // FreeBSD
+
#include "./fs.h"
+#include <errno.h>
+#include <stdio.h> // BUFSIZ
#include <string.h> // strrchr
+#include <unistd.h> // copy_file_range
char *
static_basename(char *path)
@@ -35,3 +42,51 @@ path_split_static(char *path, bool trim)
return child;
}
+
+#ifndef MIN
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+#endif
+
+int
+manual_file_copy(int fd_in, int fd_out, off_t len, int flags)
+{
+ do
+ {
+ char buf[BUFSIZ];
+
+ ssize_t nread = read(fd_in, buf, MIN(BUFSIZ, len));
+ if(nread < 0) return nread;
+
+ ssize_t nwrite = write(fd_out, buf, (size_t)nread);
+ if(nwrite < 0) return nwrite;
+
+ len -= nwrite;
+ } while(len > 0);
+
+ return 0;
+}
+
+#ifdef HAS_COPY_FILE_RANGE
+int
+auto_file_copy(int fd_in, int fd_out, off_t len, int flags)
+{
+ off_t ret = -1;
+ do
+ {
+ ret = copy_file_range(fd_in, NULL, fd_out, NULL, len, 0);
+ if(ret < 0)
+ {
+ if(errno == EXDEV)
+ {
+ errno = 0;
+ return manual_file_copy(fd_in, fd_out, len, flags);
+ }
+
+ return ret;
+ }
+ len -= ret;
+ } while(len > 0 && ret > 0);
+
+ return 0;
+}
+#endif
diff --git a/lib/fs.h b/lib/fs.h
@@ -4,6 +4,7 @@
#include <stdbool.h>
#include <stddef.h> // size_t
+#include <stdio.h> // off_t
// barebones basename, returns what's after the rightmost slash
char *static_basename(char *path);
@@ -11,3 +12,13 @@ char *static_basename(char *path);
// Modifies a path in-place to given a parent (dirname-like) and a child (basename-like)
// optionally trims the tailing slashes prior to splitting
char *path_split_static(char *path, bool trim);
+
+// Copy data from fd_in to fd_out, with a max of len (flag is ignored for now)
+int manual_file_copy(int fd_in, int fd_out, off_t len, int flags);
+
+#ifndef HAS_COPY_FILE_RANGE
+#define auto_file_copy manual_file_copy
+#else
+// Copy data with copy_file_range(2) for <len> amount of data, with fallback to manual_file_copy when cross-device
+int auto_file_copy(int fd_in, int fd_out, off_t len, int flags);
+#endif