Top Level Namespace

Defined Under Namespace

Classes: Hash

Instance Method Summary collapse

Instance Method Details

#collect_filters(opts) ⇒ Object



62
63
64
65
66
67
68
# File 'lib/umount-many.rb', line 62

def collect_filters(opts)
  filters = []
  opts.hash_at(:mount_point, :device, :type, :options).each do |filter, v|
    filters.push filter if v && !v.empty?
  end
  filters.map{|e| [method("filter_by_" + e.to_s), e]}
end

#filter_by_device(filesystems, device) ⇒ Object



46
47
48
# File 'lib/umount-many.rb', line 46

def filter_by_device(filesystems, device)
  filesystems.select {|e| e[:device] == device}
end

#filter_by_mount_point(filesystems, mp) ⇒ Object



50
51
52
# File 'lib/umount-many.rb', line 50

def filter_by_mount_point(filesystems, mp)
  filesystems.select {|e| e[:mount_point] == mp}
end

#filter_by_options(filesystems, option) ⇒ Object



58
59
60
# File 'lib/umount-many.rb', line 58

def filter_by_options(filesystems, option)
  filesystems.select {|e| e[:options].include?(option)}
end

#filter_by_type(filesystems, type) ⇒ Object



54
55
56
# File 'lib/umount-many.rb', line 54

def filter_by_type(filesystems, type)
  filesystems.select {|e| e[:type].downcase == type.downcase}
end

#matched_devices(opts) ⇒ Object



101
102
103
104
105
106
107
108
109
110
# File 'lib/umount-many.rb', line 101

def matched_devices(opts)
  filesystems = parse_file_systems
  filters = collect_filters(opts)
  to_unmount = Set.new
  results = filters.map {|meth, name| meth.call(filesystems, opts[name])}
  results.each {|devices| to_unmount += Set.new(devices)}
  to_unmount = to_unmount.to_a
  to_unmount.reverse! if opts[:reverse]
  to_unmount
end

#parse_file_systemsObject



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/umount-many.rb', line 25

def parse_file_systems
  # TODO: Currently calls +mount+ and parses stdout. Not such a good 
  # approach, is it?
  # TODO: I just can the regex gurantee to work for my box (which is a linux
  # 2.6.31 with +mount+ from util-linux-ng 2.16)
  
  filesystems = []
  IO.popen("mount") do |pipe|
    pipe.each_line do |line|
      if line =~ /([^\s]+) on ([^\s]+) type ([^\s]+) \((.*)\)/
        filesystems.push({:device => $1, :mount_point => $2, :type => $3, 
                          :options => $4.split(",")})
      else
        STDERR.puts("Couldn't parse output from mount. " +
                    "Skipping current line")
      end
    end
  end
  filesystems
end

#report_results(to_unmount, format) ⇒ Object



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/umount-many.rb', line 70

def report_results(to_unmount, format)
  unless ["yaml", "json", "xml"].include?(format)
    puts "Not a supported format for reporting: #{format}"
    puts "See the help (-h) for a list"
    exit 2
  end
  if format.downcase == "xml"
    # TODO: I am not quite sure if XmlSimple makes proper output
    STDERR.puts "WARNING: XML format is experimental."
    require 'xmlsimple'
    puts XmlSimple.xml_out(to_unmount)
  else
    require format
    meth = to_unmount.method("to_" + format)
    puts meth.call
  end
end

#unmount_devices(devices, verbose) ⇒ Object



88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/umount-many.rb', line 88

def unmount_devices(devices, verbose)
  devices.each do |device|
    if verbose
      print ("Unmounting #{device[:device]} mounted on " +
             "#{device[:mount_point]}... ")
    end
    system "umount \"#{device[:device]}\""
    # Needed because umount takes a bit of time
    sleep 0.2
    puts "DONE" if verbose
  end
end

#unmount_many_fs(opts) ⇒ Object



112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/umount-many.rb', line 112

def unmount_many_fs(opts)
  to_unmount = matched_devices(opts)
  if opts[:simulate]
    # TODO: think of a human readable format for -s
    require 'pp'
    pp to_unmount
  elsif opts[:reporting]
    report_results(to_unmount, opts[:reporting])
  else
    unmount_devices(to_unmount, opts[:verbose])
  end
end