Skip to content

Commit 8c72d10

Browse files
committed
fix: override r--r--r--
1 parent 8a9fd73 commit 8c72d10

File tree

1 file changed

+50
-0
lines changed

1 file changed

+50
-0
lines changed

crates/ccsync-core/src/sync/executor.rs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,32 @@ impl FileOperationExecutor {
130130
.with_context(|| format!("Failed to create directory: {}", parent.display()))?;
131131
}
132132

133+
// If destination exists and is read-only, make it writable first
134+
if dest.exists() {
135+
let metadata = fs::metadata(dest)
136+
.with_context(|| format!("Failed to read metadata: {}", dest.display()))?;
137+
let perms = metadata.permissions();
138+
139+
if perms.readonly() {
140+
#[cfg(unix)]
141+
{
142+
use std::os::unix::fs::PermissionsExt;
143+
// On Unix, add write permission for owner only
144+
let mode = perms.mode();
145+
let new_perms = fs::Permissions::from_mode(mode | 0o200); // Add owner write
146+
fs::set_permissions(dest, new_perms)
147+
.with_context(|| format!("Failed to make file writable: {}", dest.display()))?;
148+
}
149+
#[cfg(not(unix))]
150+
{
151+
let mut new_perms = perms.clone();
152+
new_perms.set_readonly(false);
153+
fs::set_permissions(dest, new_perms)
154+
.with_context(|| format!("Failed to make file writable: {}", dest.display()))?;
155+
}
156+
}
157+
}
158+
133159
// Copy file
134160
fs::copy(source, dest).with_context(|| {
135161
format!("Failed to copy {} to {}", source.display(), dest.display())
@@ -296,4 +322,28 @@ mod tests {
296322
assert!(dst.exists());
297323
assert!(dst.is_dir());
298324
}
325+
326+
#[test]
327+
fn test_copy_file_overwrites_readonly_destination() {
328+
use std::os::unix::fs::PermissionsExt;
329+
330+
let tmp = TempDir::new().unwrap();
331+
let src = tmp.path().join("source.txt");
332+
let dst = tmp.path().join("dest.txt");
333+
334+
// Create source file with new content
335+
fs::write(&src, "new content").unwrap();
336+
337+
// Create destination file with old content and make it read-only
338+
fs::write(&dst, "old content").unwrap();
339+
let mut perms = fs::metadata(&dst).unwrap().permissions();
340+
perms.set_mode(0o444); // read-only for all
341+
fs::set_permissions(&dst, perms).unwrap();
342+
343+
// This should succeed even though destination is read-only
344+
FileOperationExecutor::copy_file(&src, &dst).unwrap();
345+
346+
// Verify the file was overwritten with new content
347+
assert_eq!(fs::read_to_string(&dst).unwrap(), "new content");
348+
}
299349
}

0 commit comments

Comments
 (0)