all lists on lists.proxmox.com
 help / color / mirror / Atom feed
* [pbs-devel] [PATCH pbs-client v5] fix #3699: client: prefer xdg cache directory for tmp files
@ 2024-07-17 10:18 Maximiliano Sandoval
  2024-07-17 11:40 ` [pbs-devel] applied: " Thomas Lamprecht
  0 siblings, 1 reply; 2+ messages in thread
From: Maximiliano Sandoval @ 2024-07-17 10:18 UTC (permalink / raw)
  To: pbs-devel

Adds a helper to create temporal files in XDG_CACHE_HOME. If we cannot
create a file there, we fallback to /tmp as before.

Note that the temporary files stored by the client might grow
arbitrarily in size, making XDG_RUNTIME_DIR a less desirable option.
Citing the Arch wiki [1]:

> Should not store large files as it may be mounted as a tmpfs.

[1] https://wiki.archlinux.org/title/XDG_Base_Directory

Signed-off-by: Maximiliano Sandoval <m.sandoval@proxmox.com>
---

Differences from v4:
 - Use backticks in documentation for `/tmp` and `XDG_CACHE_HOME`

Differences from v3:
 - Link create_tmp_file in docs
 - Improve commit message

Differences from v2:
 - Files are created at XDG_CACHE_HOME directly
 - If opening fails, we try opening at /tmp
 - We check if the directory exists as part of the error handling of open()

 pbs-client/src/backup_reader.rs      | 31 ++++++++--------------------
 pbs-client/src/backup_writer.rs      | 13 ++----------
 pbs-client/src/tools/mod.rs          | 26 +++++++++++++++++++++++
 proxmox-backup-client/src/catalog.rs | 19 +++--------------
 4 files changed, 40 insertions(+), 49 deletions(-)

diff --git a/pbs-client/src/backup_reader.rs b/pbs-client/src/backup_reader.rs
index 36d8ebcf..4706abc7 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 (See [`crate::tools::create_tmp_file`] for
+    /// details). 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 (See [`crate::tools::create_tmp_file`] for
+    /// details). 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 (See [`crate::tools::create_tmp_file`] for
+    /// details). 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 813c8d60..d63c09b5 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};
 
@@ -531,11 +530,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
@@ -570,11 +565,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 90fac696..772cc126 100644
--- a/pbs-client/src/tools/mod.rs
+++ b/pbs-client/src/tools/mod.rs
@@ -5,9 +5,11 @@ use std::ffi::OsStr;
 use std::fs::File;
 use std::io::{BufRead, BufReader};
 use std::os::unix::ffi::OsStrExt;
+use std::os::unix::fs::OpenOptionsExt;
 use std::os::unix::io::FromRawFd;
 use std::path::PathBuf;
 use std::process::Command;
+use std::sync::OnceLock;
 
 use anyhow::{bail, format_err, Context, Error};
 use serde_json::{json, Value};
@@ -736,3 +738,27 @@ pub async fn pxar_metadata_catalog_lookup<T: Clone + ReadAt>(
 
     Ok(entries)
 }
+
+/// Creates a temporary file (with `O_TMPFILE`) in `XDG_CACHE_HOME`. If we
+/// cannot create the file there it will be created in `/tmp` instead.
+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(|| {
+        xdg::BaseDirectories::new()
+            .map(|base| base.get_cache_home())
+            .unwrap_or_else(|_| std::path::PathBuf::from("/tmp"))
+    });
+
+    let mut open_opts_binding = std::fs::OpenOptions::new();
+    let builder = open_opts_binding
+        .write(true)
+        .read(true)
+        .custom_flags(libc::O_TMPFILE);
+    builder.open(tmp_path).or_else(|err| {
+        if tmp_path != std::path::Path::new("/tmp") {
+            builder.open("/tmp")
+        } else {
+            Err(err)
+        }
+    })
+}
diff --git a/proxmox-backup-client/src/catalog.rs b/proxmox-backup-client/src/catalog.rs
index 276457c1..0a374c01 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};
@@ -106,11 +105,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))?;
@@ -198,11 +193,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))?;
@@ -233,11 +224,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



_______________________________________________
pbs-devel mailing list
pbs-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2024-07-17 11:39 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-07-17 10:18 [pbs-devel] [PATCH pbs-client v5] fix #3699: client: prefer xdg cache directory for tmp files Maximiliano Sandoval
2024-07-17 11:40 ` [pbs-devel] applied: " Thomas Lamprecht

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal