Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion java-bridge/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ pub extern "system" fn Java_RustLibrary_umount(
.unwrap()
.remove(&handle)
.unwrap();
match handle.umount().await.map_err(|err| io::Error::other(err)) {
match handle.umount().await.map_err(io::Error::other) {
Ok(()) => Ok(()),
Err(err) => {
error!("Cannot umount, force: {}", err);
Expand Down
17 changes: 16 additions & 1 deletion src/mount/linux.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1099,6 +1099,7 @@ impl Filesystem for EncryptedFsFuse3 {
) -> Result<ReplyDirectory<Self::DirEntryStream<'_>>> {
trace!("");

// Read the directory entries asynchronously
#[allow(clippy::cast_sign_loss)]
let iter = match self.get_fs().read_dir(inode).await {
Err(err) => {
Expand All @@ -1107,15 +1108,29 @@ impl Filesystem for EncryptedFsFuse3 {
}
Ok(iter) => iter,
};

let iter = DirectoryEntryIterator(iter, 0);

// ⚠️ NOTE: The `offset` used here is positional, not the actual FUSE directory entry offset.
// This causes problems when a client (like `rm *`) tries to resume a directory listing
// and expects to pick up exactly where it left off using that offset.
//
// The `skip(offset as usize)` line assumes that FUSE's offset is a zero-based index,
// but that’s not always the case. FUSE may give us back the exact `entry.offset`
// previously emitted — not a count.
//
// This mismatch can lead to clients only *seeing* the first 100 entries (due to a broken resume),
// but still *deleting* everything (because they iterate over all with different offsets).
//
// Fixing this properly would require tracking and matching `entry.offset` values,
// which means rewriting the iterator and reply logic — a much bigger refactor.

Ok(ReplyDirectory {
#[allow(clippy::cast_possible_truncation)]
#[allow(clippy::cast_sign_loss)]
entries: stream::iter(iter.skip(offset as usize)),
})
}

#[instrument(skip(self), err(level = Level::WARN), ret(level = Level::DEBUG))]
async fn releasedir(&self, req: Request, inode: Inode, fh: u64, flags: u32) -> Result<()> {
trace!("");
Expand Down
22 changes: 22 additions & 0 deletions tests/python/copy_a_video_file.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import os
import shutil
import pytest

def test_copy_video():
"""Test copying video3.mp4 from tmp_upload to final."""
src_dir = "tmp_upload"
dest_dir = "final"
file_name = "video3.mp4"
src_path = os.path.join(src_dir, file_name)
dest_path = os.path.join(dest_dir, file_name)

os.makedirs(dest_dir, exist_ok=True)

assert os.path.exists(src_path), "Source video does not exist!"

shutil.copy(src_path, dest_path)

assert os.path.exists(src_path), "Original file should not be deleted!"
assert os.path.exists(dest_path), "File was not copied to destination!"

os.remove(dest_path)
22 changes: 22 additions & 0 deletions tests/python/copy_and_verify_image_file.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import os
import shutil
import filecmp

def test_copy_image_file():
source = "tmp_upload/img1.jpg"
dest_dir = "final"
dest = os.path.join(dest_dir, "img1.jpg")

os.makedirs(dest_dir, exist_ok=True)

try:
shutil.copy2(source, dest)
assert os.path.exists(dest), "Image file was not copied."
assert filecmp.cmp(source, dest, shallow=False), "Copied image content mismatch."
print("✅ Test passed: Image copied and verified.")
except AssertionError as e:
print(f"❌ Test failed: {e}")
finally:
# Clean up
if os.path.exists(dest):
os.remove(dest)
12 changes: 12 additions & 0 deletions tests/python/delete_a_doc_file_and_confirm_absence.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import os
import pytest

def test_delete_doc():
"""Test deleting text1.doc from tmp_upload."""
doc_path = "tmp_upload/text1.doc"

assert os.path.exists(doc_path), "DOC file does not exist!"

os.remove(doc_path)

assert not os.path.exists(doc_path), "DOC file was not deleted!"
22 changes: 22 additions & 0 deletions tests/python/move_a_pdf_file_and_confirm_its_absence.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import os
import shutil
import pytest

def test_move_pdf():
"""Test moving pdf2.pdf from tmp_upload to final."""
src_dir = "tmp_upload"
dest_dir = "final"
file_name = "pdf2.pdf"
src_path = os.path.join(src_dir, file_name)
dest_path = os.path.join(dest_dir, file_name)

os.makedirs(dest_dir, exist_ok=True)

assert os.path.exists(src_path), "Source PDF does not exist!"

shutil.move(src_path, dest_path)

assert not os.path.exists(src_path), "File was not removed from source directory!"
assert os.path.exists(dest_path), "File was not moved to destination directory!"

os.remove(dest_path)
26 changes: 26 additions & 0 deletions tests/python/move_all_mp4_files.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import os
import shutil

def test_move_videos():
"""Test moving all .mp4 files from tmp_upload to final and verifying their absence."""
src_dir = "tmp_upload"
dest_dir = "final"
video_files = ["video1.mp4", "video2.mp4", "video3.mp4"]

os.makedirs(dest_dir, exist_ok=True)

for video in video_files:
src_path = os.path.join(src_dir, video)
dest_path = os.path.join(dest_dir, video)

assert os.path.exists(src_path), f"Source file {video} does not exist!"
shutil.move(src_path, dest_path)
assert not os.path.exists(src_path), f"{video} was not removed from source directory!"
assert os.path.exists(dest_path), f"{video} was not moved to destination directory!"

os.remove(dest_path)

# Undo step: Clean up created test file or restore previous state
# Uncomment the next line to actually remove the file after testing
# os.remove(doc_path)
print("Undo: Cleaned up test artifacts or restored previous state.")
27 changes: 27 additions & 0 deletions tests/python/move_an_image_file.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import os
import shutil
import pytest

def test_move_image():
"""Test moving img1.jpg from tmp_upload to final and verifying its absence in source."""
src_dir = "tmp_upload"
dest_dir = "final"
file_name = "img1.jpg"
src_path = os.path.join(src_dir, file_name)
dest_path = os.path.join(dest_dir, file_name)

os.makedirs(dest_dir, exist_ok=True)

assert os.path.exists(src_path), "Source image does not exist!"

shutil.move(src_path, dest_path)

assert not os.path.exists(src_path), "File was not removed from source directory!"
assert os.path.exists(dest_path), "File was not moved to destination directory!"

os.remove(dest_path)

# Undo step: Clean up created test file or restore previous state
# Uncomment the next line to actually remove the file after testing
# os.remove(doc_path)
print("Undo: Cleaned up test artifacts or restored previous state.")
19 changes: 19 additions & 0 deletions tests/python/rename_an_image_file.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import os
import pytest

def test_rename_image():
"""Test renaming img3.jpg to renamed_img3.jpg."""
img_dir = "tmp_upload"
old_name = "img3.jpg"
new_name = "renamed_img3.jpg"
old_path = os.path.join(img_dir, old_name)
new_path = os.path.join(img_dir, new_name)

assert os.path.exists(old_path), "Original image does not exist!"

os.rename(old_path, new_path)

assert not os.path.exists(old_path), "Old file still exists!"
assert os.path.exists(new_path), "New file was not created!"

os.rename(new_path, old_path) # Revert to original state
18 changes: 18 additions & 0 deletions tests/python/verify_doc_file_exists_and_is_not_empty.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import os

def test_verify_doc():
"""Test if text1.doc exists, is not empty, and has a valid .doc extension."""
doc_path = "tmp_upload/text1.doc"

# Check if file exists
assert os.path.exists(doc_path), f"Error: {doc_path} does not exist!"

# Check if file is not empty
file_size = os.path.getsize(doc_path)
assert file_size > 0, f"Error: {doc_path} is empty!"

# Additional check: Ensure it has a .doc extension
assert doc_path.lower().endswith(".doc"), f"Error: {doc_path} does not have a .doc extension!"

print(f"Test passed: {doc_path} exists, is not empty ({file_size} bytes), and has a valid extension.")

25 changes: 25 additions & 0 deletions tests/python/verify_image_files_exist_and_are_valid.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import os
import pytest

def test_verify_image_files():
"""Test Case 6: Verify that all JPG files exist and are valid images."""
img_files = ["img1.jpg", "img2.jpg", "img3.jpg", "img4.jpg"]
img_dir = "tmp_upload"

for img in img_files:
img_path = os.path.join(img_dir, img)

# Step 1: Check if file exists
assert os.path.exists(img_path), f"Image {img} does not exist!"

# Step 2: Attempt to open and verify the image
try:
with Image.open(img_path) as im: # type: ignore
im.verify() # Verify image integrity
except Exception as e:
pytest.fail(f"Invalid image file {img}: {e}")

print("All image files exist and are valid.")

# Undo step: No destructive operations performed, no cleanup needed
print("Undo: No actions required for image validation.")
13 changes: 13 additions & 0 deletions tests/python/verify_pdf_file_can_be_opened_and_read.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import os
import pytest
from PyPDF2 import PdfReader

def test_read_pdf():
"""Test if a PDF file can be opened and read."""
pdf_path = "tmp_upload/pdf1.pdf"

assert os.path.exists(pdf_path), "PDF file does not exist!"

with open(pdf_path, "rb") as f:
reader = PdfReader(f)
assert len(reader.pages) > 0, "PDF file has no pages!"
23 changes: 23 additions & 0 deletions tests/python/verify_video_file_integrity_after_copying.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import os
import shutil
import pytest

def test_copy_video_integrity():
"""Test copying a video file and verifying its integrity."""
src_path = "tmp_upload/video1.mp4"
dest_path = "final/video1.mp4"

os.makedirs("final", exist_ok=True)

assert os.path.exists(src_path), "Source video does not exist!"

shutil.copy(src_path, dest_path)

assert os.path.exists(dest_path), "Copied video does not exist in final!"

# Compare file sizes
assert os.path.getsize(src_path) == os.path.getsize(dest_path), "File sizes do not match!"

# Compare first 1KB of content
with open(src_path, "rb") as src_file, open(dest_path, "rb") as dest_file:
assert src_file.read(1024) == dest_file.read(1024), "File contents differ!"