* [pbs-devel] [PATCH backup] fix-3699: pbs-client/tools: use xdg basedirectories for tmp files
@ 2024-01-31 10:10 Maximiliano Sandoval
2024-01-31 10:19 ` Maximiliano Sandoval
0 siblings, 1 reply; 2+ messages in thread
From: Maximiliano Sandoval @ 2024-01-31 10:10 UTC (permalink / raw)
To: pbs-devel
Adds a helper to create temporal files in XDG_CACHE_HOME. If the we
cannot use that path, we fallback to /tmp as before.
Signed-off-by: Maximiliano Sandoval <m.sandoval@proxmox.com>
---
pbs-client/src/backup_reader.rs | 31 ++++++++--------------------
pbs-client/src/backup_writer.rs | 13 ++----------
pbs-client/src/tools/mod.rs | 28 +++++++++++++++++++++++++
proxmox-backup-client/src/catalog.rs | 19 +++--------------
4 files changed, 42 insertions(+), 49 deletions(-)
diff --git a/pbs-client/src/backup_reader.rs b/pbs-client/src/backup_reader.rs
index 36d8ebcf..6483f5b2 100644
--- a/pbs-client/src/backup_reader.rs
+++ b/pbs-client/src/backup_reader.rs
@@ -1,7 +1,6 @@
use anyhow::{format_err, Error};
use std::fs::File;
use std::io::{Seek, SeekFrom, Write};
-use std::os::unix::fs::OpenOptionsExt;
use std::sync::Arc;
use futures::future::AbortHandle;
@@ -141,18 +140,14 @@ impl BackupReader {
/// Download a .blob file
///
- /// This creates a temporary file in /tmp (using O_TMPFILE). The data is verified using
- /// the provided manifest.
+ /// This creates a temporary file (using O_TMPFILE). The data is verified
+ /// using the provided manifest.
pub async fn download_blob(
&self,
manifest: &BackupManifest,
name: &str,
) -> Result<DataBlobReader<'_, File>, Error> {
- let mut tmpfile = std::fs::OpenOptions::new()
- .write(true)
- .read(true)
- .custom_flags(libc::O_TMPFILE)
- .open("/tmp")?;
+ let mut tmpfile = crate::tools::create_tmp_file()?;
self.download(name, &mut tmpfile).await?;
@@ -167,18 +162,14 @@ impl BackupReader {
/// Download dynamic index file
///
- /// This creates a temporary file in /tmp (using O_TMPFILE). The index is verified using
- /// the provided manifest.
+ /// This creates a temporary file (using O_TMPFILE). The index is verified
+ /// using the provided manifest.
pub async fn download_dynamic_index(
&self,
manifest: &BackupManifest,
name: &str,
) -> Result<DynamicIndexReader, Error> {
- let mut tmpfile = std::fs::OpenOptions::new()
- .write(true)
- .read(true)
- .custom_flags(libc::O_TMPFILE)
- .open("/tmp")?;
+ let mut tmpfile = crate::tools::create_tmp_file()?;
self.download(name, &mut tmpfile).await?;
@@ -194,18 +185,14 @@ impl BackupReader {
/// Download fixed index file
///
- /// This creates a temporary file in /tmp (using O_TMPFILE). The index is verified using
- /// the provided manifest.
+ /// This creates a temporary file (using O_TMPFILE). The index is verified
+ /// using the provided manifest.
pub async fn download_fixed_index(
&self,
manifest: &BackupManifest,
name: &str,
) -> Result<FixedIndexReader, Error> {
- let mut tmpfile = std::fs::OpenOptions::new()
- .write(true)
- .read(true)
- .custom_flags(libc::O_TMPFILE)
- .open("/tmp")?;
+ let mut tmpfile = crate::tools::create_tmp_file()?;
self.download(name, &mut tmpfile).await?;
diff --git a/pbs-client/src/backup_writer.rs b/pbs-client/src/backup_writer.rs
index 8a03d8ea..f184c750 100644
--- a/pbs-client/src/backup_writer.rs
+++ b/pbs-client/src/backup_writer.rs
@@ -1,6 +1,5 @@
use std::collections::HashSet;
use std::future::Future;
-use std::os::unix::fs::OpenOptionsExt;
use std::sync::atomic::{AtomicU64, AtomicUsize, Ordering};
use std::sync::{Arc, Mutex};
@@ -523,11 +522,7 @@ impl BackupWriter {
manifest: &BackupManifest,
known_chunks: Arc<Mutex<HashSet<[u8; 32]>>>,
) -> Result<FixedIndexReader, Error> {
- let mut tmpfile = std::fs::OpenOptions::new()
- .write(true)
- .read(true)
- .custom_flags(libc::O_TMPFILE)
- .open("/tmp")?;
+ let mut tmpfile = crate::tools::create_tmp_file()?;
let param = json!({ "archive-name": archive_name });
self.h2
@@ -562,11 +557,7 @@ impl BackupWriter {
manifest: &BackupManifest,
known_chunks: Arc<Mutex<HashSet<[u8; 32]>>>,
) -> Result<DynamicIndexReader, Error> {
- let mut tmpfile = std::fs::OpenOptions::new()
- .write(true)
- .read(true)
- .custom_flags(libc::O_TMPFILE)
- .open("/tmp")?;
+ let mut tmpfile = crate::tools::create_tmp_file()?;
let param = json!({ "archive-name": archive_name });
self.h2
diff --git a/pbs-client/src/tools/mod.rs b/pbs-client/src/tools/mod.rs
index 1b0123a3..8046b815 100644
--- a/pbs-client/src/tools/mod.rs
+++ b/pbs-client/src/tools/mod.rs
@@ -3,8 +3,10 @@ use std::collections::HashMap;
use std::env::VarError::{NotPresent, NotUnicode};
use std::fs::File;
use std::io::{BufRead, BufReader};
+use std::os::unix::fs::OpenOptionsExt;
use std::os::unix::io::FromRawFd;
use std::process::Command;
+use std::sync::OnceLock;
use anyhow::{bail, format_err, Context, Error};
use serde_json::{json, Value};
@@ -526,3 +528,29 @@ pub fn place_xdg_file(
.and_then(|base| base.place_config_file(file_name).map_err(Error::from))
.with_context(|| format!("failed to place {} in xdg home", description))
}
+
+/// Creates a temporal file (created with O_TMPFILE) in either
+/// XDG_CACHE_HOME/proxmox-backup if the directories can be created, or in /tmp.
+pub fn create_tmp_file() -> std::io::Result<std::fs::File> {
+ static TMP_PATH: OnceLock<std::path::PathBuf> = OnceLock::new();
+
+ let tmp_path = TMP_PATH.get_or_init(|| {
+ let base = match base_directories() {
+ Ok(v) => v,
+ Err(_) => return std::path::PathBuf::from("/tmp"),
+ };
+ let cache_home = base.get_cache_home();
+
+ match std::fs::create_dir_all(&cache_home) {
+ Err(err) if err.kind() == std::io::ErrorKind::AlreadyExists => cache_home,
+ Ok(()) => cache_home,
+ Err(_) => std::path::PathBuf::from("/tmp"),
+ }
+ });
+
+ std::fs::OpenOptions::new()
+ .write(true)
+ .read(true)
+ .custom_flags(libc::O_TMPFILE)
+ .open(tmp_path)
+}
diff --git a/proxmox-backup-client/src/catalog.rs b/proxmox-backup-client/src/catalog.rs
index 72b22e67..f3bc4ede 100644
--- a/proxmox-backup-client/src/catalog.rs
+++ b/proxmox-backup-client/src/catalog.rs
@@ -1,5 +1,4 @@
use std::io::{Seek, SeekFrom};
-use std::os::unix::fs::OpenOptionsExt;
use std::sync::Arc;
use anyhow::{bail, format_err, Error};
@@ -104,11 +103,7 @@ async fn dump_catalog(param: Value) -> Result<Value, Error> {
let mut reader = BufferedDynamicReader::new(index, chunk_reader);
- let mut catalogfile = std::fs::OpenOptions::new()
- .write(true)
- .read(true)
- .custom_flags(libc::O_TMPFILE)
- .open("/tmp")?;
+ let mut catalogfile = pbs_client::tools::create_tmp_file()?;
std::io::copy(&mut reader, &mut catalogfile)
.map_err(|err| format_err!("unable to download catalog - {}", err))?;
@@ -196,11 +191,7 @@ async fn catalog_shell(param: Value) -> Result<(), Error> {
)
.await?;
- let mut tmpfile = std::fs::OpenOptions::new()
- .write(true)
- .read(true)
- .custom_flags(libc::O_TMPFILE)
- .open("/tmp")?;
+ let mut tmpfile = pbs_client::tools::create_tmp_file()?;
let (manifest, _) = client.download_manifest().await?;
manifest.check_fingerprint(crypt_config.as_ref().map(Arc::as_ref))?;
@@ -240,11 +231,7 @@ async fn catalog_shell(param: Value) -> Result<(), Error> {
most_used,
);
let mut reader = BufferedDynamicReader::new(index, chunk_reader);
- let mut catalogfile = std::fs::OpenOptions::new()
- .write(true)
- .read(true)
- .custom_flags(libc::O_TMPFILE)
- .open("/tmp")?;
+ let mut catalogfile = pbs_client::tools::create_tmp_file()?;
std::io::copy(&mut reader, &mut catalogfile)
.map_err(|err| format_err!("unable to download catalog - {}", err))?;
--
2.39.2
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [pbs-devel] [PATCH backup] fix-3699: pbs-client/tools: use xdg basedirectories for tmp files
2024-01-31 10:10 [pbs-devel] [PATCH backup] fix-3699: pbs-client/tools: use xdg basedirectories for tmp files Maximiliano Sandoval
@ 2024-01-31 10:19 ` Maximiliano Sandoval
0 siblings, 0 replies; 2+ messages in thread
From: Maximiliano Sandoval @ 2024-01-31 10:19 UTC (permalink / raw)
To: Maximiliano Sandoval; +Cc: pbs-devel
Found an issue, will send v2 in a bit.
Maximiliano Sandoval <m.sandoval@proxmox.com> writes:
> Adds a helper to create temporal files in XDG_CACHE_HOME. If the we
> cannot use that path, we fallback to /tmp as before.
>
> Signed-off-by: Maximiliano Sandoval <m.sandoval@proxmox.com>
> ---
> pbs-client/src/backup_reader.rs | 31 ++++++++--------------------
> pbs-client/src/backup_writer.rs | 13 ++----------
> pbs-client/src/tools/mod.rs | 28 +++++++++++++++++++++++++
> proxmox-backup-client/src/catalog.rs | 19 +++--------------
> 4 files changed, 42 insertions(+), 49 deletions(-)
>
> diff --git a/pbs-client/src/backup_reader.rs b/pbs-client/src/backup_reader.rs
> index 36d8ebcf..6483f5b2 100644
> --- a/pbs-client/src/backup_reader.rs
> +++ b/pbs-client/src/backup_reader.rs
> @@ -1,7 +1,6 @@
> use anyhow::{format_err, Error};
> use std::fs::File;
> use std::io::{Seek, SeekFrom, Write};
> -use std::os::unix::fs::OpenOptionsExt;
> use std::sync::Arc;
>
> use futures::future::AbortHandle;
> @@ -141,18 +140,14 @@ impl BackupReader {
>
> /// Download a .blob file
> ///
> - /// This creates a temporary file in /tmp (using O_TMPFILE). The data is verified using
> - /// the provided manifest.
> + /// This creates a temporary file (using O_TMPFILE). The data is verified
> + /// using the provided manifest.
> pub async fn download_blob(
> &self,
> manifest: &BackupManifest,
> name: &str,
> ) -> Result<DataBlobReader<'_, File>, Error> {
> - let mut tmpfile = std::fs::OpenOptions::new()
> - .write(true)
> - .read(true)
> - .custom_flags(libc::O_TMPFILE)
> - .open("/tmp")?;
> + let mut tmpfile = crate::tools::create_tmp_file()?;
>
> self.download(name, &mut tmpfile).await?;
>
> @@ -167,18 +162,14 @@ impl BackupReader {
>
> /// Download dynamic index file
> ///
> - /// This creates a temporary file in /tmp (using O_TMPFILE). The index is verified using
> - /// the provided manifest.
> + /// This creates a temporary file (using O_TMPFILE). The index is verified
> + /// using the provided manifest.
> pub async fn download_dynamic_index(
> &self,
> manifest: &BackupManifest,
> name: &str,
> ) -> Result<DynamicIndexReader, Error> {
> - let mut tmpfile = std::fs::OpenOptions::new()
> - .write(true)
> - .read(true)
> - .custom_flags(libc::O_TMPFILE)
> - .open("/tmp")?;
> + let mut tmpfile = crate::tools::create_tmp_file()?;
>
> self.download(name, &mut tmpfile).await?;
>
> @@ -194,18 +185,14 @@ impl BackupReader {
>
> /// Download fixed index file
> ///
> - /// This creates a temporary file in /tmp (using O_TMPFILE). The index is verified using
> - /// the provided manifest.
> + /// This creates a temporary file (using O_TMPFILE). The index is verified
> + /// using the provided manifest.
> pub async fn download_fixed_index(
> &self,
> manifest: &BackupManifest,
> name: &str,
> ) -> Result<FixedIndexReader, Error> {
> - let mut tmpfile = std::fs::OpenOptions::new()
> - .write(true)
> - .read(true)
> - .custom_flags(libc::O_TMPFILE)
> - .open("/tmp")?;
> + let mut tmpfile = crate::tools::create_tmp_file()?;
>
> self.download(name, &mut tmpfile).await?;
>
> diff --git a/pbs-client/src/backup_writer.rs b/pbs-client/src/backup_writer.rs
> index 8a03d8ea..f184c750 100644
> --- a/pbs-client/src/backup_writer.rs
> +++ b/pbs-client/src/backup_writer.rs
> @@ -1,6 +1,5 @@
> use std::collections::HashSet;
> use std::future::Future;
> -use std::os::unix::fs::OpenOptionsExt;
> use std::sync::atomic::{AtomicU64, AtomicUsize, Ordering};
> use std::sync::{Arc, Mutex};
>
> @@ -523,11 +522,7 @@ impl BackupWriter {
> manifest: &BackupManifest,
> known_chunks: Arc<Mutex<HashSet<[u8; 32]>>>,
> ) -> Result<FixedIndexReader, Error> {
> - let mut tmpfile = std::fs::OpenOptions::new()
> - .write(true)
> - .read(true)
> - .custom_flags(libc::O_TMPFILE)
> - .open("/tmp")?;
> + let mut tmpfile = crate::tools::create_tmp_file()?;
>
> let param = json!({ "archive-name": archive_name });
> self.h2
> @@ -562,11 +557,7 @@ impl BackupWriter {
> manifest: &BackupManifest,
> known_chunks: Arc<Mutex<HashSet<[u8; 32]>>>,
> ) -> Result<DynamicIndexReader, Error> {
> - let mut tmpfile = std::fs::OpenOptions::new()
> - .write(true)
> - .read(true)
> - .custom_flags(libc::O_TMPFILE)
> - .open("/tmp")?;
> + let mut tmpfile = crate::tools::create_tmp_file()?;
>
> let param = json!({ "archive-name": archive_name });
> self.h2
> diff --git a/pbs-client/src/tools/mod.rs b/pbs-client/src/tools/mod.rs
> index 1b0123a3..8046b815 100644
> --- a/pbs-client/src/tools/mod.rs
> +++ b/pbs-client/src/tools/mod.rs
> @@ -3,8 +3,10 @@ use std::collections::HashMap;
> use std::env::VarError::{NotPresent, NotUnicode};
> use std::fs::File;
> use std::io::{BufRead, BufReader};
> +use std::os::unix::fs::OpenOptionsExt;
> use std::os::unix::io::FromRawFd;
> use std::process::Command;
> +use std::sync::OnceLock;
>
> use anyhow::{bail, format_err, Context, Error};
> use serde_json::{json, Value};
> @@ -526,3 +528,29 @@ pub fn place_xdg_file(
> .and_then(|base| base.place_config_file(file_name).map_err(Error::from))
> .with_context(|| format!("failed to place {} in xdg home", description))
> }
> +
> +/// Creates a temporal file (created with O_TMPFILE) in either
> +/// XDG_CACHE_HOME/proxmox-backup if the directories can be created, or in /tmp.
> +pub fn create_tmp_file() -> std::io::Result<std::fs::File> {
> + static TMP_PATH: OnceLock<std::path::PathBuf> = OnceLock::new();
> +
> + let tmp_path = TMP_PATH.get_or_init(|| {
> + let base = match base_directories() {
> + Ok(v) => v,
> + Err(_) => return std::path::PathBuf::from("/tmp"),
> + };
> + let cache_home = base.get_cache_home();
> +
> + match std::fs::create_dir_all(&cache_home) {
> + Err(err) if err.kind() == std::io::ErrorKind::AlreadyExists => cache_home,
> + Ok(()) => cache_home,
> + Err(_) => std::path::PathBuf::from("/tmp"),
> + }
> + });
> +
> + std::fs::OpenOptions::new()
> + .write(true)
> + .read(true)
> + .custom_flags(libc::O_TMPFILE)
> + .open(tmp_path)
> +}
> diff --git a/proxmox-backup-client/src/catalog.rs b/proxmox-backup-client/src/catalog.rs
> index 72b22e67..f3bc4ede 100644
> --- a/proxmox-backup-client/src/catalog.rs
> +++ b/proxmox-backup-client/src/catalog.rs
> @@ -1,5 +1,4 @@
> use std::io::{Seek, SeekFrom};
> -use std::os::unix::fs::OpenOptionsExt;
> use std::sync::Arc;
>
> use anyhow::{bail, format_err, Error};
> @@ -104,11 +103,7 @@ async fn dump_catalog(param: Value) -> Result<Value, Error> {
>
> let mut reader = BufferedDynamicReader::new(index, chunk_reader);
>
> - let mut catalogfile = std::fs::OpenOptions::new()
> - .write(true)
> - .read(true)
> - .custom_flags(libc::O_TMPFILE)
> - .open("/tmp")?;
> + let mut catalogfile = pbs_client::tools::create_tmp_file()?;
>
> std::io::copy(&mut reader, &mut catalogfile)
> .map_err(|err| format_err!("unable to download catalog - {}", err))?;
> @@ -196,11 +191,7 @@ async fn catalog_shell(param: Value) -> Result<(), Error> {
> )
> .await?;
>
> - let mut tmpfile = std::fs::OpenOptions::new()
> - .write(true)
> - .read(true)
> - .custom_flags(libc::O_TMPFILE)
> - .open("/tmp")?;
> + let mut tmpfile = pbs_client::tools::create_tmp_file()?;
>
> let (manifest, _) = client.download_manifest().await?;
> manifest.check_fingerprint(crypt_config.as_ref().map(Arc::as_ref))?;
> @@ -240,11 +231,7 @@ async fn catalog_shell(param: Value) -> Result<(), Error> {
> most_used,
> );
> let mut reader = BufferedDynamicReader::new(index, chunk_reader);
> - let mut catalogfile = std::fs::OpenOptions::new()
> - .write(true)
> - .read(true)
> - .custom_flags(libc::O_TMPFILE)
> - .open("/tmp")?;
> + let mut catalogfile = pbs_client::tools::create_tmp_file()?;
>
> std::io::copy(&mut reader, &mut catalogfile)
> .map_err(|err| format_err!("unable to download catalog - {}", err))?;
--
Maximiliano
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2024-01-31 10:19 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-01-31 10:10 [pbs-devel] [PATCH backup] fix-3699: pbs-client/tools: use xdg basedirectories for tmp files Maximiliano Sandoval
2024-01-31 10:19 ` Maximiliano Sandoval
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox