Skip to content
Merged
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
26 changes: 26 additions & 0 deletions spec/std/file_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -1687,6 +1687,32 @@ describe "File" do
File.same_content?(src_path, out_path).should be_true
end
end

it "copies read-only permission" do
with_tempfile("cp-permissions-src.txt", "cp-permissions-out.txt") do |src_path, out_path|
File.write(src_path, "foo")
File.chmod(src_path, 0o444)

File.copy(src_path, out_path)

File.info(out_path).permissions.should eq normalize_permissions(0o444, directory: false)
File.same_content?(src_path, out_path).should be_true
end
end

it "copies read-only permission over existing file" do
with_tempfile("cp-permissions-src.txt", "cp-permissions-out.txt") do |src_path, out_path|
File.write(src_path, "foo")
File.chmod(src_path, 0o444)

File.write(out_path, "bar")

File.copy(src_path, out_path)

File.info(out_path).permissions.should eq normalize_permissions(0o444, directory: false)
File.same_content?(src_path, out_path).should be_true
end
end
end

describe ".match?" do
Expand Down
14 changes: 9 additions & 5 deletions src/file.cr
Original file line number Diff line number Diff line change
Expand Up @@ -846,13 +846,17 @@ class File < IO::FileDescriptor
# ```
def self.copy(src : String | Path, dst : String | Path) : Nil
open(src) do |s|
open(dst, "wb") do |d|
permissions = s.info.permissions
open(dst, "wb", perm: permissions) do |d|
# If permissions don't match, we opened a pre-existing file with
# different permissions and need to change them explicitly.
# The permission change does not have any effect on the open file descriptor d.
if d.info.permissions != permissions
d.chmod(permissions)
end

# TODO use sendfile or copy_file_range syscall. See #8926, #8919
IO.copy(s, d)
d.flush # need to flush in case permissions are read-only

# Set the permissions after the content is written in case src permissions is read-only
d.chmod(s.info.permissions)
end
end
end
Expand Down