Stebalien / tempfile

Temporary file library for rust
http://stebalien.com/projects/tempfile-rs
Apache License 2.0
1.2k stars 120 forks source link

Support iOS #283

Closed simlay closed 6 months ago

simlay commented 6 months ago

The file paths for iOS writable locations is a bit rough and hard to figure out. Like, the pwd of an iOS (simulator) app when running is /. The Data Container in for an App Sandbox is kinda hard to find.

A few weeks ago a friend asked me how to do this and I came up with:

use std::fs::File;
use std::io::Write;
use objc2_foundation::NSFileManager;
use std::path::PathBuf;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let ns_file_manager = unsafe { NSFileManager::defaultManager() };
    let temp_dir = unsafe { ns_file_manager.temporaryDirectory() };
    let path = unsafe { temp_dir.relativePath() }.expect("Failed to get path from temp dir");
    let path = path.to_string();

    let path = PathBuf::from(path.clone()).join("results.txt");
    println!("WRITING TO PATH: {path:?}");
    let mut output = File::create(path)?;
    let line = "hello";
    let _ = write!(output, "{}", line);
    Ok(())
}

The objc2_foundation dependency in the Cargo.toml is:

[dependencies]
objc2-foundation = {version = "0.2.0", features = ["NSFileManager", "NSURL", "NSString"] }

This might also be useful for other apple device targets.

This would be helpful for:

When I get the time, I'm happy to submit a PR for this feature (and help maintain it) though let me know if such a feature is out of the scope of this project.

Stebalien commented 6 months ago

This sounds like something that should be fixed in the rust standard library. This package calls std::env::tempdir which should return the platform-specific temporary directory.

simlay commented 6 months ago

This sounds like something that should be fixed in the rust standard library. This package calls std::env::tempdir which should return the platform-specific temporary directory.

Huh. You're right. Well that's a little embarrassing on my part.

I'll admit I didn't actually try using std::env::tempdir when investigating this issue and when trying to to write a file assumed it would be using the NSFileManager thing.

Interestingly, I ran the cargo tests via cargo-dinghy in the iOS simulator and all but the test_make_uds* succeeded. This is the failure output:

failures:

---- test_make_uds stdout ----
thread 'test_make_uds' panicked at tests/namedtempfile.rs:393:10:
called `Result::unwrap()` on an `Err` value: Error { kind: InvalidInput, message: "path must be shorter than SUN_LEN" }
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

---- test_make_uds_conflict stdout ----
thread 'test_make_uds_conflict' panicked at tests/namedtempfile.rs:436:46:
called `Result::unwrap()` on an `Err` value: Error { kind: InvalidInput, message: "path must be shorter than SUN_LEN" }

failures:
    test_make_uds
    test_make_uds_conflict

Should the next person wondering, SUN_LEN is the max length that bind can handle on linux it's 108 bytes. When I run the example from std::env::tempdir, I get a /Users/simlay/Library/Developer/CoreSimulator/Devices/5ECD8296-E130-4781-91DC-FB1B42171AFE/data/Containers/Data/Application/2E347885-E108-4DEB-8487-65120F638CBA/tmp which is 164 characters.

If you're interested, I can fix those tests for iOS but I don't consider it all that necessary so I'm closing this issue.

Thanks for the quick response!

Stebalien commented 6 months ago

Bleh. Honestly, those tests should likely just be excluded on iOS.