Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[rust] Check more part of metadata on unix system for getattr #9395

Draft
wants to merge 8 commits into
base: releases/3.2
Choose a base branch
from
11 changes: 11 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ libsqlite3-sys = { version = "0.26.0", default-features = false }
log = { version = "0.4.22", default-features = false }
miniserde = { version = "0.1.40", default-features = false }
neon = { version = "1.0.0", default-features = false }
nix = { version = "0.29.0", default-features = false }
once_cell = { version = "1.20.2", default-features = false }
openssl = { version = "0.10.68", default-features = false }
paste = { version = "1.0.15", default-features = false }
Expand Down
5 changes: 4 additions & 1 deletion libparsec/crates/platform_mountpoint/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,12 @@ env_logger = { workspace = true }
libparsec_client_connection = { workspace = true }
libparsec_tests_fixtures = { workspace = true, features = ["default"] }
libparsec_tests_lite = { workspace = true }
tokio = { workspace = true, features = ["fs"] }
tokio = { workspace = true, features = ["fs", "process"] }
windows-sys = { workspace = true, features = ["Win32"] }

[target.'cfg(target_family = "unix")'.dev-dependencies]
nix = { workspace = true }

[target.'cfg(target_os = "windows")'.build-dependencies]
winfsp_wrs_build = { workspace = true }

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#!/usr/bin/osascript

Check warning on line 1 in libparsec/crates/platform_mountpoint/scripts/macos/copy-using-finder.scpt

View workflow job for this annotation

GitHub Actions / spelling / cspell

Unknown word (osascript)

on run argv
-- Get file and dest path from arguments
set file_path to item 1 of argv
set dest_path to item 2 of argv

-- Use Finder to copy the file to dest
tell application "Finder"
set source_file to POSIX file file_path as alias
set destination_folder to POSIX file dest_path as alias
duplicate source_file to destination_folder
end tell
end run


Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
use std::path::PathBuf;

use libparsec_tests_fixtures::{tmp_path, TestbedEnv, TmpPath};
use libparsec_tests_lite::parsec_test;

use crate::operations::utils::mount_and_test;

#[parsec_test(testbed = "minimal_client_ready")]
async fn copy_file_using_finder(tmp_path: TmpPath, env: &TestbedEnv) {
mount_and_test!(
env,
&tmp_path,
|_client, _wksp_ops, mountpoint_path: PathBuf| async move {
const FILE_CONTENT: &str = "I'm the file content that should be copied";
let src_file = tmp_path.join("source.txt");
let dst_file = mountpoint_path.join("source.txt");
let script_path = std::path::PathBuf::from(std::env!("CARGO_MANIFEST_DIR"))
.join("scripts/macos/copy-using-finder.scpt");

Check warning on line 18 in libparsec/crates/platform_mountpoint/tests/unit/operations/macos/copy.rs

View workflow job for this annotation

GitHub Actions / spelling / cspell

Unknown word (scpt)

assert!(
!tokio::fs::try_exists(&dst_file).await.unwrap(),
"The destination file should not exist before the copy"
);

// Create the source file with some content
tokio::fs::write(&src_file, FILE_CONTENT).await.unwrap();

// Call the osascript that perform the copy using Finder.app

Check warning on line 28 in libparsec/crates/platform_mountpoint/tests/unit/operations/macos/copy.rs

View workflow job for this annotation

GitHub Actions / spelling / cspell

Unknown word (osascript)
let status = tokio::process::Command::new("osascript")

Check warning on line 29 in libparsec/crates/platform_mountpoint/tests/unit/operations/macos/copy.rs

View workflow job for this annotation

GitHub Actions / spelling / cspell

Unknown word (osascript)
.args([&script_path, &src_file, &mountpoint_path])
.status()
.await
.unwrap();
assert!(status.success());

// Verify the content of the copied file
let data = tokio::fs::read_to_string(&dst_file).await.unwrap();
assert_eq!(data, FILE_CONTENT);
}
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
mod copy;
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
mod create_folder;
mod flush_file;
mod list_directory;
#[cfg(target_os = "macos")]
mod macos;
mod mount_unmount;
mod move_entry;
mod open_file;
Expand All @@ -12,6 +14,8 @@ mod remove_folder;
mod rename_entry;
mod stat_entry;
mod to_os_path;
#[cfg(target_family = "unix")]
mod unix;
mod utils;
mod write_file;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,24 @@
let stat = std::fs::metadata(file_path).unwrap();
assert!(stat.is_file());
p_assert_eq!(stat.len(), expected_size);

#[cfg(target_family = "unix")]
{
use std::os::unix::fs::MetadataExt;
const BLK_SIZE: u64 = 512;

let current_uid = unsafe { libc::getuid() };

Check failure on line 86 in libparsec/crates/platform_mountpoint/tests/unit/operations/stat_entry.rs

View workflow job for this annotation

GitHub Actions / rust / 🐧 Linux: 🦀 Rust tests

unsafe block missing a safety comment
let current_gid = unsafe { libc::getgid() };

Check failure on line 87 in libparsec/crates/platform_mountpoint/tests/unit/operations/stat_entry.rs

View workflow job for this annotation

GitHub Actions / rust / 🐧 Linux: 🦀 Rust tests

unsafe block missing a safety comment

assert_eq!(stat.mode() & 0o700, 0o700);
assert_eq!(stat.uid(), current_uid);
assert_eq!(stat.gid(), current_gid);
assert_eq!(stat.nlink(), 1); // We do not handle file link so the file will have a
// single link
assert_eq!(stat.blocks(), (expected_size + BLK_SIZE - 1) / BLK_SIZE);
assert_eq!(stat.blksize(), 512); // Value of blocksize that we define during the
// filesystem impl
}
})
.await
.unwrap();
Expand Down Expand Up @@ -116,6 +134,24 @@
};
let stat = std::fs::metadata(folder_path).unwrap();
assert!(stat.is_dir());

#[cfg(target_family = "unix")]
{
use std::os::unix::fs::MetadataExt;

let current_uid = unsafe { libc::getuid() };

Check failure on line 142 in libparsec/crates/platform_mountpoint/tests/unit/operations/stat_entry.rs

View workflow job for this annotation

GitHub Actions / rust / 🐧 Linux: 🦀 Rust tests

unsafe block missing a safety comment
let current_gid = unsafe { libc::getgid() };

Check failure on line 143 in libparsec/crates/platform_mountpoint/tests/unit/operations/stat_entry.rs

View workflow job for this annotation

GitHub Actions / rust / 🐧 Linux: 🦀 Rust tests

unsafe block missing a safety comment

assert_eq!(stat.mode() & 0o700, 0o700);
assert_eq!(stat.uid(), current_uid);
assert_eq!(stat.gid(), current_gid);
assert_eq!(stat.nlink(), 1); // We do not handle file link so the file will have a
// single link
assert_eq!(stat.size(), 0); // A dir does not have a size
assert_eq!(stat.blocks(), 0); // no size mean no block used
assert_eq!(stat.blksize(), 512); // Value of blocksize that we define during the
// filesystem impl
}
})
.await
.unwrap();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Parsec Cloud (https://parsec.cloud) Copyright (c) BUSL-1.1 2016-present Scille SAS

use std::{path::PathBuf, sync::Arc};

use libparsec_client::WorkspaceOps;
use libparsec_tests_fixtures::{tmp_path, TestbedEnv, TmpPath};
use libparsec_tests_lite::parsec_test;

use crate::operations::utils::mount_and_test;

// NOTE: We cannot test the behavoir of readlink since our filesystem does not support links.

Check warning on line 11 in libparsec/crates/platform_mountpoint/tests/unit/operations/unix/hardlink.rs

View workflow job for this annotation

GitHub Actions / spelling / cspell

Unknown word (behavoir)
// Calling `readlink` with a file will just result in the error
// [`std::io::ErrorKind::InvalidInput`] because the "system" will actual do a pre-check with
// `lookup` on the path and discover that it is not a link.

#[parsec_test(testbed = "minimal_client_ready")]
async fn linkat_not_supported(tmp_path: TmpPath, env: &TestbedEnv) {
mount_and_test!(
env,
&tmp_path,
|_client, _wksp1_ops: Arc<WorkspaceOps>, mountpoint_path: PathBuf| async move {
let result = tokio::fs::hard_link(
mountpoint_path.join("bar.txt"),
mountpoint_path.join("bar2.txt"),
)
.await;
assert!(result.is_err());
let err = result.unwrap_err();
assert_eq!(err.kind(), std::io::ErrorKind::PermissionDenied);
}
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
mod hardlink;
mod setattr;
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// Parsec Cloud (https://parsec.cloud) Copyright (c) BUSL-1.1 2016-present Scille SAS

// TODO: setattr is not supported, but must test the behavior nevertheless
// - Resize file (increase/decrease) with/out file descriptor
// - Change access/modification time with/out file descriptor

use std::path::PathBuf;

use libparsec_tests_fixtures::{tmp_path, TestbedEnv, TmpPath};
use libparsec_tests_lite::parsec_test;

use crate::operations::utils::mount_and_test;

#[parsec_test(testbed = "minimal_client_ready")]
async fn unhandled_attr_change_nothing(tmp_path: TmpPath, env: &TestbedEnv) {
mount_and_test!(
env,
&tmp_path,
|_client, _wksp_ops, mountpoint_path: PathBuf| async move {
use std::os::unix::fs::{MetadataExt, PermissionsExt};

let file_path = mountpoint_path.join("bar.txt");
let orig_metadata = tokio::fs::metadata(&file_path).await.unwrap();
tokio::fs::set_permissions(&file_path, std::fs::Permissions::from_mode(0o755))
.await
.unwrap();
let new_metadata = tokio::fs::metadata(&file_path).await.unwrap();
assert_eq!(orig_metadata.file_type(), new_metadata.file_type());
assert_eq!(
orig_metadata.accessed().unwrap(),
new_metadata.accessed().unwrap()
);
// FIXME: Currently the filesystem does not support creation time
// The following code will panic with the above reason
// assert_eq!(
// orig_metadata.created().unwrap(),
// new_metadata.created().unwrap()
// );
assert_eq!(
orig_metadata.modified().unwrap(),
new_metadata.modified().unwrap()
);
assert_eq!(orig_metadata.len(), new_metadata.len());
assert_eq!(orig_metadata.permissions(), new_metadata.permissions());
assert_eq!(orig_metadata.dev(), new_metadata.dev());
assert_eq!(orig_metadata.ino(), new_metadata.ino());
assert_eq!(orig_metadata.mode(), new_metadata.mode());
assert_eq!(orig_metadata.nlink(), new_metadata.nlink());
assert_eq!(orig_metadata.uid(), new_metadata.uid());
assert_eq!(orig_metadata.gid(), new_metadata.gid());
assert_eq!(orig_metadata.rdev(), new_metadata.rdev());
assert_eq!(orig_metadata.atime(), new_metadata.atime());
assert_eq!(orig_metadata.atime_nsec(), new_metadata.atime_nsec());
assert_eq!(orig_metadata.mtime(), new_metadata.mtime());
assert_eq!(orig_metadata.mtime_nsec(), new_metadata.mtime_nsec());
assert_eq!(orig_metadata.ctime(), new_metadata.ctime());
assert_eq!(orig_metadata.ctime_nsec(), new_metadata.ctime_nsec());
assert_eq!(orig_metadata.blksize(), new_metadata.blksize());
}
);
}

This file was deleted.

This file was deleted.

Loading