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


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.debug("Touching #{file} to create it")
  FileUtils.touch(file)
end

#deploy(src, dst) ⇒ Object


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
# 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.debug("Reading modes from #{dst} file")
  stat = ::File.stat(dst)
  mode = stat.mode & 07777
  uid  = stat.uid
  gid  = stat.gid

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

  # i own the inode, so should be able to at least chmod it
  ::File.chmod(mode, 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 commmand
  # (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

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