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