require 'dl'
module LibC
require 'dl/import'
extend DL::Importable
dlload "/lib/libc.so.6"
extern "int statvfs(const char *, struct statvfs *)"
alias :sym_statvfs :statvfs
module_function :sym_statvfs
FLAGS_BITS = [
[ :st_rdonly, 1 ], # Mount read-only.
[ :st_nosuid, 2 ], # Ignore suid and sgid bits.
[ :st_nodev, 4 ], # Disallow access to device special files.
[ :st_noexec, 8 ], # Disallow program execution.
[ :st_synchronous, 16 ], # Writes are synced at once.
[ :st_mandlock, 64 ], # Allow mandatory locks on an FS.
[ :st_write, 128 ], # Write on file/directory/symlink.
[ :st_append, 256 ], # Append-only file.
[ :st_immutable, 512 ], # Immutable file.
[ :st_noatime, 1024 ], # Do not update access times.
[ :st_nodiratime, 2048 ], # Do not update directory access times.
[ :st_relatime, 4096 ], # Update atime relative to mtime/ctime.
].map {|name, value| eval "#{name.to_s.upcase} = #{value}"; [ name, value ]}
def pretty_flags(bitfield, flagdef = [])
flags = []
flagdef.each {|flag, value|
flags << flag if (bitfield & value) == value
}
flags
end
module_function :pretty_flags
def statvfs(path)
path = path.to_s
raise "path not found" unless File.exists?(path)
# Proto: [ :name, :sizecode, :ignore ]
proto = [
[ :f_bsize, :L ],
[ :f_frsize, :L ],
[ :f_blocks, :L ],
[ :f_bfree, :L ],
[ :f_bavail, :L ],
[ :f_files, :L ],
[ :f_ffree, :L ],
[ :f_favail, :L ],
[ :f_fsid, :L ],
[ :__f_unused, :L, true ],
[ :f_flag, :L ],
[ :f_namemax, :L ],
[ :__f_spare0, :L, true ],
[ :__f_spare1, :L, true ],
[ :__f_spare2, :L, true ],
[ :__f_spare3, :L, true ],
[ :__f_spare4, :L, true ],
[ :__f_spare5, :L, true ],
]
names = proto.map {|thing| thing[0] }
descr = proto.map {|thing| thing[1] }.join
statvfs = DL.malloc(DL.sizeof(descr))
statvfs.struct!(descr, *names)
res = sym_statvfs(path, statvfs)
raise "extern statvfs returned %u" % res unless res.zero?
res = Hash[*names.map {|name| [ name, statvfs[name] ] if proto.select {|p| p[0] == name && p[2] }.empty? }.compact.flatten]
res[:flags] = self.pretty_flags(res[:f_flag], FLAGS_BITS)
return res
end
module_function :statvfs
end