Class: Chef::FileContentManagement::Deploy::MvUnix

Inherits:
Object
  • Object
show all
Defined in:
lib/chef/file_content_management/deploy/mv_unix.rb

Overview

PURPOSE: this strategy is atomic, and attempts to preserve file modes

NOTE: there is no preserve flag to FileUtils.mv, and we want to preserve the dst file

modes rather than the src file modes (preserve = true is what mv does already, we
would like preserve = false which is tricky).

Instance Method Summary collapse

Instance Method Details

#create(file) ⇒ Object

[View source]

30
31
32
33
34
35
# File 'lib/chef/file_content_management/deploy/mv_unix.rb', line 30

def create(file)
  # this is very simple, but it ensures that ownership and file modes take
  # good defaults, in particular mode needs to obey umask on create
  Chef::Log.trace("Touching #{file} to create it")
  FileUtils.touch(file)
end

#deploy(src, dst) ⇒ Object

[View source]

37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/chef/file_content_management/deploy/mv_unix.rb', line 37

def deploy(src, dst)
  # we are only responsible for content so restore the dst files perms
  Chef::Log.trace("Reading modes from #{dst} file")
  stat = ::File.stat(dst)
  mode = stat.mode & 07777
  uid  = stat.uid
  gid  = stat.gid

  Chef::Log.trace("Applying mode = #{mode.to_s(8)}, uid = #{uid}, gid = #{gid} to #{src}")

  # we may be running as non-root in which case because we are doing an mv we cannot preserve
  # the file modes.  after the mv we have a different inode and if we don't have rights to
  # chown/chgrp on the inode then we can't fix the ownership.
  #
  # in the case where i'm running chef-solo on my homedir as myself and some root-shell
  # work has caused dotfiles of mine to change to root-owned, i'm fine with this not being
  # exceptional, and i think most use cases will consider this to not be exceptional, and
  # the right thing is to fix the ownership of the file to the user running the command
  # (which requires write perms to the directory, or mv will throw an exception)
  begin
    ::File.chown(uid, nil, src)
  rescue Errno::EPERM
    Chef::Log.warn("Could not set uid = #{uid} on #{src}, file modes not preserved")
  end
  begin
    ::File.chown(nil, gid, src)
  rescue Errno::EPERM
    Chef::Log.warn("Could not set gid = #{gid} on #{src}, file modes not preserved")
  end

  # i own the inode, so should be able to at least chmod it
  # NOTE: this must come last due to POSIX stripping sticky mode bits on chown/chgrp
  ::File.chmod(mode, src)

  Chef::Log.trace("Moving temporary file #{src} into place at #{dst}")
  FileUtils.mv(src, dst)
end