From f706fffc6c1298b61d1951839b8078ad85616320 Mon Sep 17 00:00:00 2001 From: "L. E. Segovia" <13498015+amyspark@users.noreply.github.com> Date: Fri, 12 Apr 2019 18:46:57 +0000 Subject: [PATCH] atomic_write: repair permissions after writing This restores the original file uid, gid and permissions separately. (ActiveSupport does it in a single step - atomically. This is not useful in our use case because it may lead to ACL changes.) Fixes #5916 --- Library/Homebrew/extend/pathname.rb | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/Library/Homebrew/extend/pathname.rb b/Library/Homebrew/extend/pathname.rb index c27322e232..afb076f191 100644 --- a/Library/Homebrew/extend/pathname.rb +++ b/Library/Homebrew/extend/pathname.rb @@ -163,9 +163,29 @@ class Pathname # NOTE: This always overwrites. def atomic_write(content) + old_stat = (stat if exist?) File.atomic_write(self) do |file| file.write(content) end + + return unless old_stat + + # Try to restore original file's permissions separately + # atomic_write does it itself, but it actually erases + # them if chown fails + begin + # Set correct permissions on new file + chown(old_stat.uid, nil) + chown(nil, old_stat.gid) + rescue Errno::EPERM, Errno::EACCES # rubocop:disable Lint/HandleExceptions + # Changing file ownership failed, moving on. + end + begin + # This operation will affect filesystem ACL's + chmod(old_stat.mode) + rescue Errno::EPERM, Errno::EACCES # rubocop:disable Lint/HandleExceptions + # Changing file permissions failed, moving on. + end end # @private