logo

utils-std

Collection of commonly available Unix tools
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:

Mcmd/install.c50+-------------------------------------------------
Mlib/fs.c55+++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mlib/fs.h11+++++++++++
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