From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68]) (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 lists.proxmox.com (Postfix) with ESMTPS id EEAFC60E43 for ; Fri, 25 Sep 2020 16:13:30 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id EB9F91C19F for ; Fri, 25 Sep 2020 16:13:30 +0200 (CEST) Received: from proxmox-new.maurer-it.com (proxmox-new.maurer-it.com [212.186.127.180]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by firstgate.proxmox.com (Proxmox) with ESMTPS id EC1AA1C15B for ; Fri, 25 Sep 2020 16:13:28 +0200 (CEST) Received: from proxmox-new.maurer-it.com (localhost.localdomain [127.0.0.1]) by proxmox-new.maurer-it.com (Proxmox) with ESMTP id B69E0456ED for ; Fri, 25 Sep 2020 16:13:28 +0200 (CEST) From: Dominik Csapak To: pbs-devel@lists.proxmox.com Date: Fri, 25 Sep 2020 16:13:15 +0200 Message-Id: <20200925141327.25024-3-d.csapak@proxmox.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200925141327.25024-1-d.csapak@proxmox.com> References: <20200925141327.25024-1-d.csapak@proxmox.com> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-SPAM-LEVEL: Spam detection results: 0 AWL -0.176 Adjusted score from AWL reputation of From: address KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment KAM_LAZY_DOMAIN_SECURITY 1 Sending domain does not have any anti-forgery methods NO_DNS_FOR_FROM 0.379 Envelope sender has no MX or A DNS records RCVD_IN_DNSWL_MED -2.3 Sender listed at https://www.dnswl.org/, medium trust SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_NONE 0.001 SPF: sender does not publish an SPF Record URIBL_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to URIBL was blocked. See http://wiki.apache.org/spamassassin/DnsBlocklists#dnsbl-block for more information. [fs.rs] Subject: [pbs-devel] [PATCH proxmox 2/3] proxmox/tools/fs: create tmpfile helper X-BeenThere: pbs-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox Backup Server development discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 25 Sep 2020 14:13:31 -0000 by factoring out the code we had in 'replace_file' Signed-off-by: Dominik Csapak --- proxmox/src/tools/fs.rs | 39 ++++++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/proxmox/src/tools/fs.rs b/proxmox/src/tools/fs.rs index 2cd1a1b..3f96d9e 100644 --- a/proxmox/src/tools/fs.rs +++ b/proxmox/src/tools/fs.rs @@ -4,7 +4,7 @@ use std::ffi::CStr; use std::fs::{File, OpenOptions}; use std::io::{self, BufRead, BufReader, Write}; use std::os::unix::io::{AsRawFd, FromRawFd, RawFd}; -use std::path::Path; +use std::path::{Path, PathBuf}; use std::time::Duration; use anyhow::{bail, format_err, Error}; @@ -121,14 +121,12 @@ pub fn file_read_firstline>(path: P) -> Result { .map_err(|err: Error| format_err!("unable to read {:?} - {}", path, err)) } -/// Atomically replace a file. -/// -/// This first creates a temporary file and then rotates it in place. -pub fn replace_file>( +/// Takes a Path and CreateOptions, creates a tmpfile from it and returns +/// a RawFd and PathBuf for it +pub fn make_tmp_file>( path: P, - data: &[u8], options: CreateOptions, -) -> Result<(), Error> { +) -> Result<(RawFd, PathBuf), Error> { let path = path.as_ref(); // Note: we use mkstemp heŕe, because this worka with different @@ -140,8 +138,6 @@ pub fn replace_file>( Err(err) => bail!("mkstemp {:?} failed: {}", template, err), }; - let tmp_path = tmp_path.as_path(); - // clippy bug?: from_bits_truncate is actually a const fn... #[allow(clippy::or_fun_call)] let mode: stat::Mode = options @@ -149,27 +145,40 @@ pub fn replace_file>( .unwrap_or(stat::Mode::from_bits_truncate(0o644)); if let Err(err) = stat::fchmod(fd, mode) { - let _ = unistd::unlink(tmp_path); + let _ = unistd::unlink(&tmp_path); bail!("fchmod {:?} failed: {}", tmp_path, err); } if options.owner.is_some() || options.group.is_some() { if let Err(err) = fchown(fd, options.owner, options.group) { - let _ = unistd::unlink(tmp_path); + let _ = unistd::unlink(&tmp_path); bail!("fchown {:?} failed: {}", tmp_path, err); } } + Ok((fd, tmp_path)) +} + +/// Atomically replace a file. +/// +/// This first creates a temporary file and then rotates it in place. +pub fn replace_file>( + path: P, + data: &[u8], + options: CreateOptions, +) -> Result<(), Error> { + let (fd, tmp_path) = make_tmp_file(&path, options)?; + let mut file = unsafe { File::from_raw_fd(fd) }; if let Err(err) = file.write_all(data) { - let _ = unistd::unlink(tmp_path); + let _ = unistd::unlink(&tmp_path); bail!("write failed: {}", err); } - if let Err(err) = std::fs::rename(tmp_path, path) { - let _ = unistd::unlink(tmp_path); - bail!("Atomic rename failed for file {:?} - {}", path, err); + if let Err(err) = std::fs::rename(&tmp_path, &path) { + let _ = unistd::unlink(&tmp_path); + bail!("Atomic rename failed for file {:?} - {}", path.as_ref(), err); } Ok(()) -- 2.20.1