@@ -15,17 +15,26 @@ class FileSystem
1515 :signeddir => 0755
1616 }
1717
18- def self . instance
19- @instance ||= new
20- end
21-
22- def self . write_file ( *args )
23- instance . write_file ( *args )
18+ def self . write_file ( path , one_or_more_objects , mode )
19+ File . open ( path , 'w' , mode ) do |f |
20+ Array ( one_or_more_objects ) . each do |object |
21+ f . puts object . to_s
22+ end
23+ end
24+ ensure_ownership ( path )
2425 end
2526
2627 def self . ensure_dirs ( one_or_more_dirs )
2728 Array ( one_or_more_dirs ) . each do |directory |
28- instance . ensure_dir ( directory )
29+ ensure_dir ( directory )
30+ end
31+ end
32+
33+ # Warning: directory mode should be specified in DIR_MODES above
34+ def self . ensure_dir ( directory )
35+ if !File . exist? ( directory )
36+ FileUtils . mkdir_p ( directory , mode : DIR_MODES [ directory ] )
37+ ensure_ownership ( directory )
2938 end
3039 end
3140
@@ -53,56 +62,30 @@ def self.check_for_existing_files(one_or_more_paths)
5362 def self . forcibly_symlink ( source , link_target )
5463 FileUtils . remove_dir ( link_target , true )
5564 FileUtils . symlink ( source , link_target )
56- # Ensure the symlink has the same ownership as the source.
57- # This requires using `FileUtils.chown` rather than `File.chown`, as
58- # the latter will update the ownership of the source rather than the
59- # link itself.
60- # Symlink permissions are ignored in favor of the source's permissions,
61- # so we don't have to change those.
62- source_info = File . stat ( source )
63- FileUtils . chown ( source_info . uid , source_info . gid , link_target )
64- end
65-
66- def initialize
67- @user , @group = find_user_and_group
65+ ensure_ownership ( link_target )
6866 end
6967
70- def find_user_and_group
71- if !running_as_root?
72- return Process . euid , Process . egid
73- else
74- if pe_puppet_exists?
75- return 'pe-puppet' , 'pe-puppet'
76- else
77- return 'puppet' , 'puppet'
78- end
79- end
68+ # Chown the path to the puppet user when running as root.
69+ # Skipped otherwise: a non-root process can only have created the path
70+ # as itself, so ownership is already correct, and chowning to any other
71+ # user would require CAP_CHOWN (unavailable in rootless containers).
72+ #
73+ # Uses `FileUtils.chown` rather than `File.chown` so that when `path`
74+ # is a symlink it operates on the link itself rather than its target.
75+ def self . ensure_ownership ( path )
76+ return unless running_as_root?
77+ user = pe_puppet_exists? ? 'pe-puppet' : 'puppet'
78+ group = pe_puppet_exists? ? 'pe-puppet' : 'puppet'
79+ FileUtils . chown ( user , group , path )
8080 end
8181
82- def running_as_root?
82+ def self . running_as_root?
8383 !Gem . win_platform? && Process . euid == 0
8484 end
8585
86- def pe_puppet_exists?
86+ def self . pe_puppet_exists?
8787 !!( Etc . getpwnam ( 'pe-puppet' ) rescue nil )
8888 end
89-
90- def write_file ( path , one_or_more_objects , mode )
91- File . open ( path , 'w' , mode ) do |f |
92- Array ( one_or_more_objects ) . each do |object |
93- f . puts object . to_s
94- end
95- end
96- FileUtils . chown ( @user , @group , path )
97- end
98-
99- # Warning: directory mode should be specified in DIR_MODES above
100- def ensure_dir ( directory )
101- if !File . exist? ( directory )
102- FileUtils . mkdir_p ( directory , mode : DIR_MODES [ directory ] )
103- FileUtils . chown ( @user , @group , directory )
104- end
105- end
10689 end
10790 end
10891 end
0 commit comments