From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from lists.gentoo.org (pigeon.gentoo.org [208.92.234.80]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by finch.gentoo.org (Postfix) with ESMTPS id 128BF158086 for ; Sun, 26 Dec 2021 14:00:04 +0000 (UTC) Received: from pigeon.gentoo.org (localhost [127.0.0.1]) by pigeon.gentoo.org (Postfix) with SMTP id 9871F2BC02E; Sun, 26 Dec 2021 13:59:58 +0000 (UTC) Received: from smtp.gentoo.org (mail.gentoo.org [IPv6:2001:470:ea4a:1:5054:ff:fec7:86e4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by pigeon.gentoo.org (Postfix) with ESMTPS id 7A5952BC026 for ; Sun, 26 Dec 2021 13:59:57 +0000 (UTC) Received: from oystercatcher.gentoo.org (unknown [IPv6:2a01:4f8:202:4333:225:90ff:fed9:fc84]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by smtp.gentoo.org (Postfix) with ESMTPS id 1B0A4342BB9 for ; Sun, 26 Dec 2021 13:59:55 +0000 (UTC) Received: from localhost.localdomain (localhost [IPv6:::1]) by oystercatcher.gentoo.org (Postfix) with ESMTP id 973921FB for ; Sun, 26 Dec 2021 13:59:53 +0000 (UTC) From: "Fabian Groffen" To: gentoo-commits@lists.gentoo.org Content-Transfer-Encoding: 8bit Content-type: text/plain; charset=UTF-8 Reply-To: gentoo-dev@lists.gentoo.org, "Fabian Groffen" Message-ID: <1640526529.117869a1b0d19c5e3a6b59e9e43e6849ed92efd4.grobian@gentoo> Subject: [gentoo-commits] proj/portage-utils:master commit in: libq/ X-VCS-Repository: proj/portage-utils X-VCS-Files: libq/Makefile.am libq/move_file.c libq/move_file.h X-VCS-Directories: libq/ X-VCS-Committer: grobian X-VCS-Committer-Name: Fabian Groffen X-VCS-Revision: 117869a1b0d19c5e3a6b59e9e43e6849ed92efd4 X-VCS-Branch: master Date: Sun, 26 Dec 2021 13:59:53 +0000 (UTC) Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-Id: Gentoo Linux mail X-BeenThere: gentoo-commits@lists.gentoo.org X-Auto-Response-Suppress: DR, RN, NRN, OOF, AutoReply X-Archives-Salt: c4715926-2c9b-4388-9f2b-82e7660e28b8 X-Archives-Hash: ac7c216d28c9e22120681122f86f6873 commit: 117869a1b0d19c5e3a6b59e9e43e6849ed92efd4 Author: Fabian Groffen gentoo org> AuthorDate: Sun Dec 26 13:48:49 2021 +0000 Commit: Fabian Groffen gentoo org> CommitDate: Sun Dec 26 13:48:49 2021 +0000 URL: https://gitweb.gentoo.org/proj/portage-utils.git/commit/?id=117869a1 libq/move_file: code to move a file or copy+remove it This code originated from qmerge.c, it was adapted to be more generic in a function. Signed-off-by: Fabian Groffen gentoo.org> libq/Makefile.am | 1 + libq/move_file.c | 105 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ libq/move_file.h | 21 +++++++++++ 3 files changed, 127 insertions(+) diff --git a/libq/Makefile.am b/libq/Makefile.am index da100b6..c0402a4 100644 --- a/libq/Makefile.am +++ b/libq/Makefile.am @@ -11,6 +11,7 @@ QFILES = \ hash.c hash.h \ human_readable.c human_readable.h \ i18n.h \ + move_file.c move_file.h \ prelink.c prelink.h \ profile.c profile.h \ rmspace.c rmspace.h \ diff --git a/libq/move_file.c b/libq/move_file.c new file mode 100644 index 0000000..07cf69f --- /dev/null +++ b/libq/move_file.c @@ -0,0 +1,105 @@ +/* + * Copyright 2005-2021 Gentoo Authors + * Distributed under the terms of the GNU General Public License v2 + * + * Copyright 2005-2010 Ned Ludd - + * Copyright 2005-2014 Mike Frysinger - + * Copyright 2018- Fabian Groffen - + */ + +#include "main.h" + +#include +#include +#include +#include +#include "stat-time.h" + +#include "copy_file.h" +#include "move_file.h" + +int +move_file(int rootfd_src, const char *name_src, + int rootfd_dst, const char *name_dst, + struct stat *stat_src) +{ + /* first try fast path -- src/dst are same device, else + * fall back to slow path -- manual read/write */ + if (renameat(rootfd_src, name_src, rootfd_dst, name_dst) != 0) { + int fd_src; + int fd_dst; + char tmpname_dst[_Q_PATH_MAX]; + struct stat st; + struct timespec times[2]; + + fd_src = openat(rootfd_src, name_src, O_RDONLY|O_CLOEXEC); + if (fd_src < 0) { + warnp("could not read source file %s", name_src); + return fd_src; + } + + if (stat_src == NULL) { + if (fstat(fd_src, &st) != 0) { + warnp("could not stat source file %s", name_src); + return -1; + } + + stat_src = &st; + } + + /* do not write the file in place ... + * will fail with files that are in use + * plus it isn't atomic, so we could leave a mess */ + snprintf(tmpname_dst, sizeof(tmpname_dst), ".%u.%s", + getpid(), name_dst); + fd_dst = openat(rootfd_dst, tmpname_dst, + O_WRONLY|O_CLOEXEC|O_CREAT|O_TRUNC, + stat_src->st_mode); + if (fd_dst < 0) { + warnp("could not open destination file %s (for %s)", + tmpname_dst, name_dst); + close(fd_src); + return fd_dst; + } + + /* make sure owner/mode is sane before we write out data */ + if (fchown(fd_dst, stat_src->st_uid, stat_src->st_gid) != 0) { + warnp("could not set ownership (%zu/%zu) for %s", + (size_t)stat_src->st_uid, (size_t)stat_src->st_gid, name_dst); + return -1; + } + if (fchmod(fd_dst, stat_src->st_mode) != 0) { + warnp("could not set permission (%u) for %s", + (int)stat_src->st_mode, name_dst); + return -1; + } + + /* do the actual data copy */ + if (copy_file_fd(fd_src, fd_dst)) { + warnp("could not write to file %s", name_dst); + if (unlinkat(rootfd_dst, tmpname_dst, 0) != 0) { + /* don't care */; + } + close(fd_src); + close(fd_dst); + return -1; + } + + /* Preserve the file times */ + times[0] = get_stat_atime(&st); + times[1] = get_stat_mtime(&st); + futimens(fd_dst, times); + + close(fd_src); + close(fd_dst); + + /* finally move the new tmp dst file to the right place, which + * should be on the same FS/device now */ + if (renameat(rootfd_dst, tmpname_dst, rootfd_dst, name_dst)) { + warnp("could not rename %s to %s", tmpname_dst, name_dst); + return -1; + } + } + + return 0; +} diff --git a/libq/move_file.h b/libq/move_file.h new file mode 100644 index 0000000..a454165 --- /dev/null +++ b/libq/move_file.h @@ -0,0 +1,21 @@ +/* + * Copyright 2005-2021 Gentoo Authors + * Distributed under the terms of the GNU General Public License v2 + * + * Copyright 2005-2010 Ned Ludd - + * Copyright 2005-2014 Mike Frysinger - + * Copyright 2018- Fabian Groffen - + */ + +#ifndef _MOVE_FILE_H + +#define _MOVE_FILE_H 1 + +#include +#include + +int move_file(int rootfd_src, const char *name_src, + int rootfd_dst, const char *name_dst, + struct stat *stat_src); + +#endif