Class: Fstab
- Inherits:
-
Object
- Object
- Fstab
- Defined in:
- lib/fstab.rb
Constant Summary collapse
- VERSION =
"0.1.1"
Class Method Summary collapse
-
.get_blkdev_fs_attrs(dev) ⇒ Object
returns { :uuid => UUID, :label => LABEL, :fstype => FSTYPE, :dev => DEVICE }.
-
.get_blockdev(id) ⇒ Object
Get block device from UUID/Label.
- .get_label(dev) ⇒ Object
- .get_uuid(dev) ⇒ Object
- .get_uuid_from_label(label) ⇒ Object
Instance Method Summary collapse
-
#add_entry(opts = {}) ⇒ Object
:label => label or :uuid => uuid or :dev => dev_path :mount_point => mp :type => type :opts => opts :dump => dump :pass => pass.
- #add_fs(dev, mpoint, type, opts, dump = 0, pass = 0) ⇒ Object
- #auto_header ⇒ Object
- #entries ⇒ Object
-
#find_device(dev) ⇒ Object
Accepts UUID/LABEL/dev.
- #has_device?(dev) ⇒ Boolean
-
#initialize(file = '/etc/fstab', opts = {}) ⇒ Fstab
constructor
if safe_mode true, non existing devices won’t be added to fstab.
- #invalid_entries ⇒ Object
- #line_count ⇒ Object
- #parse ⇒ Object
- #reload ⇒ Object
-
#remove_invalid_entries ⇒ Object
May rise exception.
- #valid_entries ⇒ Object
Constructor Details
#initialize(file = '/etc/fstab', opts = {}) ⇒ Fstab
if safe_mode true, non existing devices won’t be added to fstab. Adding a non existing device to fstab will raise an exception. Trying to add a device without a filesystem will also rise an exception
9 10 11 12 13 14 15 |
# File 'lib/fstab.rb', line 9 def initialize(file = '/etc/fstab', opts = {}) @file = file @contents = File.read file @backup = opts[:backup].nil? ? true : opts[:backup] @safe_mode = opts[:safe_mode].nil? ? true : opts[:safe_mode] @backup_dir = opts[:backup_dir] || '/etc/' end |
Class Method Details
.get_blkdev_fs_attrs(dev) ⇒ Object
returns
:uuid => UUID,
:label => LABEL,
:fstype => FSTYPE,
:dev => DEVICE
All the attributes except dev may be nil at any given time since device may not have a valid filesystem or label.
229 230 231 232 233 234 235 236 237 238 |
# File 'lib/fstab.rb', line 229 def self.get_blkdev_fs_attrs(dev) raise ArgumentError.new("Invalid device path #{dev}") unless File.blockdev?(dev) blkid = `/sbin/blkid #{dev}` attrs = {} attrs[:uuid] = blkid.match(/UUID="(.*?)"/)[1] rescue nil attrs[:label] = blkid.match(/LABEL="(.*?)"/)[1] rescue nil attrs[:fstype] = blkid.match(/TYPE="(.*?)"/)[1] rescue nil attrs[:dev] = blkid.match(/\/dev\/(.*):/)[1] rescue nil attrs end |
.get_blockdev(id) ⇒ Object
Get block device from UUID/Label
242 243 244 245 246 247 248 249 250 251 252 253 254 |
# File 'lib/fstab.rb', line 242 def self.get_blockdev(id) if File.blockdev?(id) and !File.symlink?(id) return id end path = nil # Try to get blockdev from UUID first, then label begin path = File.readlink("/dev/disk/by-uuid/#{id}") rescue path = File.readlink("/dev/disk/by-label/#{id}") end "/dev/#{path.split('/').last}" end |
.get_label(dev) ⇒ Object
265 266 267 |
# File 'lib/fstab.rb', line 265 def self.get_label(dev) Fstab.get_blkdev_fs_attrs(dev)[:label] end |
.get_uuid(dev) ⇒ Object
256 257 258 259 |
# File 'lib/fstab.rb', line 256 def self.get_uuid(dev) #`/sbin/blkid #{dev}`.match(/UUID="(.*?)"/)[1] rescue nil Fstab.get_blkdev_fs_attrs(dev)[:uuid] end |
.get_uuid_from_label(label) ⇒ Object
261 262 263 |
# File 'lib/fstab.rb', line 261 def self.get_uuid_from_label(label) Fstab.get_blkdev_fs_attrs("/dev/disk/by-label/#{label}")[:uuid] end |
Instance Method Details
#add_entry(opts = {}) ⇒ Object
:label => label or :uuid => uuid or :dev => dev_path :mount_point => mp :type => type :opts => opts :dump => dump :pass => pass
27 28 29 30 31 32 33 34 35 36 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 74 75 76 77 78 79 80 81 |
# File 'lib/fstab.rb', line 27 def add_entry(opts = {}) raise ArgumentError.new(":dev key is required (fs_spec).") unless opts[:dev] dev = opts[:dev].strip.chomp uuid = nil label = nil case dev when /\/dev\// # device path pdev = dev when /^\/\/\w+(\.\w+)*((\/)|\w+|\.)*/ #smbfs/cifs when /^(tmpfs|proc|usbfs|devpts|none|sysfs)/ #special FS when /^\w+:\/?\w*(\/\w+)*/ # NFS when /[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}/i # UUID uuid = dev else # Asume FS label, rise exception if FS label does not exist if File.blockdev?("/dev/disk/by-label/#{dev}") label = dev else raise Exception.new "Unsupported filesystem #{dev}" end end if opts[:mount_point].nil? or opts[:type].nil? or \ opts[:opts].nil? or opts[:dump].nil? or opts[:pass].nil? raise ArgumentError.new("Missing :mount_point, :type, :opts, :dump or :pass options") end if @safe_mode if label raise ArgumentError.new("Invalid device label #{label}") unless \ File.blockdev?("/dev/disk/by-label/#{opts[:label]}") opts[:uuid] = Fstab.get_uuid_from_label(label) elsif uuid raise ArgumentError.new("Invalid device UUID #{uuid}") unless \ File.blockdev?("/dev/disk/by-uuid/#{uuid}") opts[:uuid] = uuid elsif pdev raise ArgumentError.new("Invalid device path #{pdev}") unless \ File.blockdev?("#{pdev}") opts[:uuid] = Fstab.get_uuid(pdev) else # Asume special device special = true end unless special raise ArgumentError.new("Duplicated entry found (safe_mode=on)") if has_device?(dev) end end backup_fstab File.open @file, 'w' do |f| f.puts @contents f.puts format_entry(dev, opts) end reload end |
#add_fs(dev, mpoint, type, opts, dump = 0, pass = 0) ⇒ Object
83 84 85 86 87 88 89 90 91 92 |
# File 'lib/fstab.rb', line 83 def add_fs(dev, mpoint, type, opts, dump = 0, pass = 0) o = {} o[:dev] = dev o[:mount_point] = mpoint o[:type] = type o[:opts] = opts o[:dump] = dump o[:pass] = pass add_entry o end |
#auto_header ⇒ Object
174 175 176 177 178 |
# File 'lib/fstab.rb', line 174 def auto_header @header ||= "#\n" + "# This file was autogenerated at #{Time.now.to_s}\n" + "#\n" end |
#entries ⇒ Object
17 18 19 |
# File 'lib/fstab.rb', line 17 def entries parse end |
#find_device(dev) ⇒ Object
Accepts UUID/LABEL/dev
203 204 205 206 207 208 209 210 211 212 213 |
# File 'lib/fstab.rb', line 203 def find_device(dev) # get canonical device_name begin dev = Fstab.get_blockdev(dev) parse.each do |k, v| return { k => v } if k == dev end rescue end nil end |
#has_device?(dev) ⇒ Boolean
215 216 217 |
# File 'lib/fstab.rb', line 215 def has_device?(dev) !find_device(dev).nil? end |
#invalid_entries ⇒ Object
196 197 198 |
# File 'lib/fstab.rb', line 196 def invalid_entries Hash[parse.find_all { |k,v| v[:invalid] }] end |
#line_count ⇒ Object
94 95 96 |
# File 'lib/fstab.rb', line 94 def line_count @lcount end |
#parse ⇒ Object
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 |
# File 'lib/fstab.rb', line 102 def parse raise Exception.new("/sbin/blkid not found") unless File.exist?('/sbin/blkid') fslist = {} ucount = 0 @lcount = 0 @contents.each_line do |l| next if l.strip.chomp.empty? @lcount += 1 next if l =~ /\s*#/ fs, mp, type, opts, dump, pass = l.split # FSTAB(5) states that pass and dump are optional, defaults to 0 pass = "0" unless pass dump = "0" unless dump pdev = nil label = nil uuid = nil special = false if l =~ /^\s*LABEL=/ # by LABEL label = fs.split("=").last.strip.chomp pdev = "/dev/" + File.readlink("/dev/disk/by-label/#{label}").split("/").last rescue "unknown_#{ucount}" uuid = Fstab.get_uuid pdev elsif l =~ /^\s*UUID=/ # by UUID uuid = fs.split("=").last.strip.chomp pdev = "/dev/" + File.readlink("/dev/disk/by-uuid/#{uuid}").split("/").last rescue "unknown_#{ucount}" label = Fstab.get_label pdev rescue nil elsif l =~ /^\s*\/dev/ # by dev path pdev = fs blkid = `/sbin/blkid #{pdev}` label = blkid.match(/LABEL="(.*?)"/)[1] rescue nil uuid = blkid.match(/UUID="(.*?)"/)[1] rescue nil else # FIXME: somewhat risky to assume that everything else # can be considered a special device, but validating this # is really tricky. special = true pdev = fs end # Fstab entries not matching real devices have pdev unknown invalid = (l.split.count != 6) # invalid entry if < 6 columns if (uuid.nil? and label.nil? and !special) or pdev =~ /^unknown_/ or \ (!File.exist?(pdev) and !special) invalid = true ucount += 1 end invalid = true unless (dump =~ /0|1|2/ and pass =~ /0|1|2/) fslist[pdev] = { :label => label, :uuid => uuid, :mount_point => mp, :type => type, :opts => opts, :dump => dump, :pass => pass, :special => special, :line_number => @lcount, :invalid => invalid, } end fslist end |
#reload ⇒ Object
98 99 100 |
# File 'lib/fstab.rb', line 98 def reload @contents = File.read @file end |
#remove_invalid_entries ⇒ Object
May rise exception
183 184 185 186 187 188 189 190 191 192 193 194 |
# File 'lib/fstab.rb', line 183 def remove_invalid_entries return false if invalid_entries.empty? backup_fstab File.open @file, 'w' do |f| f.puts auto_header valid_entries.each do |k,v| f.puts format_entry(k, v) end end reload true end |
#valid_entries ⇒ Object
170 171 172 |
# File 'lib/fstab.rb', line 170 def valid_entries Hash[parse.find_all { |k,v| !v[:invalid] }] end |