How to compile a Unix-specific file permissions method on all platforms

Viewed 86

My goal is to disallow other users on a Unix system to read the content of the file.

How do I set file permissions in Linux while still allowing the program to compile for Windows?

Compiling for Unix machine, I can do this:

use std::os::unix::fs::PermissionsExt;
fs::set_permissions("/path", fs::Permissions::from_mode(0o655)).unwrap();

But this will not compile on Windows. How can I work around that?

3 Answers

Use #[cfg(unix)] to conditionally compile code for Unix, and #[cfg(windows)] or #[cfg(not(unix))] for a non-Unix branch.

#[cfg(unix)]
{
    use std::os::unix::fs::PermissionsExt;
    fs::set_permissions("/path", fs::Permissions::from_mode(0o655))?;
}

#[cfg(not(unix))]
{
    todo!();
}

You probably want to use Rust's conditional compilation feature (Similar to ifdef-ing in C/C++).

You can choose to compile code on a specific operating system using:

// The function is only included in the build when compiling for macOS
#[cfg(target_os = "macos")]
fn set_permissions(path: &str) {
  use std::os::unix::fs::PermissionsExt;
  fs::set_permissions(path, fs::Permissions::from_mode(0o655)).unwrap();
}

#[cfg(not(target_os = "macos"))]
fn set_permissions(path: &str) {
  ...
}

(Keep in mind you probably need an empty stub for other platforms for the code to compile)

Supported values are: "windows", "macos", "ios", "linux", "android", "freebsd", "dragonfly", "openbsd", "netbsd"

Or you could use more generic specifier, such as target_family:

// The function is only included in the build when compile for unix systems
#[cfg(target_family = "unix")]
fn set_permissions(path: &str) {
  use std::os::unix::fs::PermissionsExt;
  fs::set_permissions(path, fs::Permissions::from_mode(0o655)).unwrap();
}

Supported values: "unix", "windows", "wasm"

The easiest way to handle this is probably with configuration attributes.

For instance, you might want something like this:

#[cfg(target_family = "unix")]
fn set_permissions(path: &str) {
  use std::os::unix::fs::PermissionsExt;
  fs::set_permissions(path, fs::Permissions::from_mode(0o655)).unwrap();
}

#[cfg(not(target_family = "unix"))]
fn set_permissions(path: &str) {} 

More examples here and reference documentation here.

Related