Class: Fstab
- Inherits:
-
Object
- Object
- Fstab
- Defined in:
- lib/fstab.rb
Constant Summary collapse
- VERSION =
"0.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(reload = true) ⇒ 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.
224 225 226 227 228 229 230 231 232 233 |
# File 'lib/fstab.rb', line 224 def self.get_blkdev_fs_attrs(dev) raise ArgumentError.new("Invalid device path") 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
237 238 239 240 241 242 243 244 245 246 247 248 249 |
# File 'lib/fstab.rb', line 237 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
260 261 262 |
# File 'lib/fstab.rb', line 260 def self.get_label(dev) Fstab.get_blkdev_fs_attrs(dev)[:label] end |
.get_uuid(dev) ⇒ Object
251 252 253 254 |
# File 'lib/fstab.rb', line 251 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
256 257 258 |
# File 'lib/fstab.rb', line 256 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 |
# 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 end |
#add_fs(dev, mpoint, type, opts, dump = 0, pass = 0) ⇒ Object
82 83 84 85 86 87 88 89 90 91 |
# File 'lib/fstab.rb', line 82 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
170 171 172 173 174 |
# File 'lib/fstab.rb', line 170 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
198 199 200 201 202 203 204 205 206 207 208 |
# File 'lib/fstab.rb', line 198 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
210 211 212 |
# File 'lib/fstab.rb', line 210 def has_device?(dev) !find_device(dev).nil? end |
#invalid_entries ⇒ Object
191 192 193 |
# File 'lib/fstab.rb', line 191 def invalid_entries Hash[parse.find_all { |k,v| v[:invalid] }] end |
#line_count ⇒ Object
93 94 95 |
# File 'lib/fstab.rb', line 93 def line_count @lcount end |
#parse(reload = true) ⇒ Object
97 98 99 100 101 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 |
# File 'lib/fstab.rb', line 97 def parse(reload = true) @contents = File.read @file if reload 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 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 |
#remove_invalid_entries ⇒ Object
May rise exception
179 180 181 182 183 184 185 186 187 188 189 |
# File 'lib/fstab.rb', line 179 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 true end |
#valid_entries ⇒ Object
166 167 168 |
# File 'lib/fstab.rb', line 166 def valid_entries Hash[parse.find_all { |k,v| !v[:invalid] }] end |