diff options
author | Florian Pritz <bluewind@xinu.at> | 2011-10-23 22:01:53 +0200 |
---|---|---|
committer | Florian Pritz <bluewind@xinu.at> | 2011-10-23 22:02:18 +0200 |
commit | ebc82b27288df5c58194083ead4a6e6de7f52d21 (patch) | |
tree | 30d4e874cc19a03dfc62a0ee7c6c5e6c9756d4ec /philesight | |
parent | 44c6e7dfa4967843b05ee961fd243f655ed31717 (diff) | |
download | aur-packages-ebc82b27288df5c58194083ead4a6e6de7f52d21.tar.gz aur-packages-ebc82b27288df5c58194083ead4a6e6de7f52d21.tar.xz |
mass update (again :( )
Signed-off-by: Florian Pritz <bluewind@xinu.at>
Diffstat (limited to 'philesight')
-rw-r--r-- | philesight/README | 100 | ||||
-rwxr-xr-x | philesight/philesight | 62 | ||||
-rwxr-xr-x | philesight/philesight.cgi | 127 | ||||
-rw-r--r-- | philesight/philesight.rb | 458 |
4 files changed, 0 insertions, 747 deletions
diff --git a/philesight/README b/philesight/README deleted file mode 100644 index 1a9905e..0000000 --- a/philesight/README +++ /dev/null @@ -1,100 +0,0 @@ - -Summary -======= - -Philesight is a tool to browse your filesystem and see where the diskspace is -being used at a glance. Philesight is implemented as a simple command line -program that generates PNG files; a wrapper CGI script is supplied to allow -navigating through the filesystem. - -Philesight is actually a clone of the filelight program. Wheres filelight is -ment as an interactive, user friendly application for the X-windows desktop, -philesight is designed to run on a remote server without graphical user -interface. - - -Dependencies -============ - -Philesight is written in ruby1.8, and requires the berkely-db4 and cairo -ruby-libraries. - -Changelog -========= - -2008-05-29 Added option (use_gradients) to enable/disable gradients - in circular graph. Added option to set graph size. - -2008-04-16 Added optional table with file list to cgi, some bugfixes, - increased default graph size to 800. (Thanks to Guillaume - Sachot) - -2008-03-17 Fixed bug where no image was shown with CGI's running - on apache-mpm-worker. - -2007-03-12 Fixed crash when indexing file named 'rest' - -2006-12-09 Workaround for segmentaion fault with ruby 1.8.5 - -Usage -===== - -Philesight can be run in different modes: first, the filesystem is indexed -and the results are stored in a database. When the database is generated, the -tool can used to generate PNG files with the graphs. The database should be -updated every once in a while of course. - - * Index bulding: - - ./philesight --db {db} --index {path} - - {db} is the name of the database file that will be generated. It is a good - idea to throw away existing database files before indexing to avoid removed - files showing in your graph. - - {path} is the top-level directory to start indexing. Usually, '/' is a - good choice. - - This process might take some time, since it traverses the whole tree - from path-to-index downward and stores the data into the db. Make - sure to remove previous database files before indexing. - - - * PNG generating: In this mode, philesight generates a graph of the - filesystem from path and 4 levels downward. i - - ./philesight --db {db} --path {path} --draw {png} - - {db} is the filename of the index file that was generated earlier, - {path} is the directory which should be drawn, and {png} is the filename - of the to-be-generated PNG image file - - - * CGI: Philesight comes with a CGI module that can be run from within a - web server. Edit the configurable parameters in the top of this file - to point to the database. Make sure the datbase file is readable by - the webserver! - - Available options: - - * db: Path to database file. - - * default_path: default path to show when CGI first loads. - - * size: graph size. 800 pixels is often a good choice. - - * show_list: render list of directories and their sizes blow graph. - - * use_gradients: use gradient colors in graph (set to 'false' to generate - smaller PNG files) - - -Bugs -==== - - * Philesight is a ruby program, and thus is not particulary fast. - * Indexing takes longer than necassery. - * Proper error handling is mostly missing. - * Not very well tested. - * It might eat your disks. - diff --git a/philesight/philesight b/philesight/philesight deleted file mode 100755 index 5ab0e09..0000000 --- a/philesight/philesight +++ /dev/null @@ -1,62 +0,0 @@ -#!/usr/bin/ruby -# vi: ts=2 sw=2 - -require 'getoptlong' -require 'philesight' - -opts = GetoptLong.new( - [ "--index", "-i", GetoptLong::REQUIRED_ARGUMENT ], - [ "--draw", "-d", GetoptLong::REQUIRED_ARGUMENT ], - [ "--path", "-p", GetoptLong::REQUIRED_ARGUMENT ], - [ "--db", "-D", GetoptLong::REQUIRED_ARGUMENT ], - [ "--dump", "-u", GetoptLong::NO_ARGUMENT ], - [ "--help", "-h", GetoptLong::NO_ARGUMENT ] -) - -def usage - puts - puts "usage: philesight <options>" - puts - puts "Options:" - puts " --db <db> Set path to database file" - puts " --path <path> Path to show in generated image" - puts " --index <path> Top-level directory to start indexing" - puts " --dump Dump database to readable format" - puts - puts "Examples:" - puts " Index to database: philesight --db <db> --index <path>" - puts " Generate PNG: philesight --db <db> --path <path> --draw <png>" - puts -end - - -t = Philesight.new -path = "" - -opts.each do |opt, arg| - - case opt - when "--draw" - t.draw(path, arg) - - when "--index" - t.readdir(arg) - - when "--path" - path = arg - - when "--db" - t.db_open(arg) - - when "--dump" - t.dump - - else - usage - - end -end - -# -# End -# diff --git a/philesight/philesight.cgi b/philesight/philesight.cgi deleted file mode 100755 index 969269a..0000000 --- a/philesight/philesight.cgi +++ /dev/null @@ -1,127 +0,0 @@ -#!/usr/bin/ruby -# vi: ts=4 sw=4 - -require 'philesight' -require 'cgi' - -# Config variables - -db = "./ps.db" -default_path = "/" -size = 800 -show_list = true -use_gradients = true - -# Get parameters from environment and CGI. ISMAP image maps do not return a -# proper CGI parameter, but only the coordinates appended after a question -# mark. If this is found in the QUERY_STRING, assume the 'find' command - -cgi = CGI.new; -qs = ENV["QUERY_STRING"] -cmd = cgi.params['cmd'][0] -path = cgi.params['path'][0] || default_path - -if(qs && qs =~ /\?(\d+,\d+)/ ) then - find_pos = $1 - cmd = 'find' -end - -ps = Philesight.new(4, size, use_gradients) -ps.db_open(db) - -# Perform action depending on 'cmd' parameter - -case cmd - - when "img" - puts "Content-type: image/png" - puts - $stdout.flush - ps.draw(path, "-") - - when "find" - if(find_pos =~ /(\d+),(\d+)/) then - x, y = $1.to_i, $2.to_i - url = "?path=%s" % ps.find(path, x, y) - puts "Content-type: text/html" - puts - puts '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">' - puts '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr" >' - puts '<head>' - puts ' <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />' - puts ' <meta http-equiv="refresh" content="0; url=' + "#{url}" + '">' - puts '</head>' - puts '<body></body>' - puts '</html>' - end - - else - random = "" - 1.upto(32) { random += (rand(26) + ?a).chr } - puts "Content-type: text/html" - puts - puts '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">' - puts '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr" >' - puts '<head>' - puts ' <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />' - puts " <title>Disk usage : #{path}</title>" - puts ' <style type="text/css">' - puts ' <!--' - puts ' body {color:black;text-align:center;background:#FAFAFA;}' - puts ' table {margin:auto;width:780px;}' - puts ' table,td {border:0;}' - puts ' td {padding:4px;text-align:left;}' - puts ' td.size {text-align:right;}' - puts ' thead td {font-weight:bold;border-bottom:1px solid black;background:#EEE;}' - puts ' tbody td {background:#F0F0F0;}' - puts ' tbody tr.parentdir td {background:#E5D0D0;}' - puts ' tbody tr.evenrow td {background:#E4E4E4;}' - puts ' ' - puts ' -->' - puts ' </style>' - puts '</head>' - puts '<body>' - puts ' <p><a href="' + "?path=#{path}&" + '">' - puts ' <img style="border:0" width="#{size}" height="#{size}" src="?cmd=img&r=' + "#{random}&path=#{path}" + '" ismap="ismap" alt="' + "#{path}" + '" />' - puts ' </a></p>' - - if show_list then - # Array of files - content = ps.listcontent("#{path}") - if(content && content[0]) then - puts ' <table summary="File lists">' - puts ' <thead>' - puts ' <tr><td>Filename</td><td class="size">Size</td></tr>' - puts ' </thead>' - puts ' <tbody>' - puts ' <tr class="parentdir"><td>' + content[0][:path].to_s + '</td><td class="size">' + content[0][:humansize].to_s + '</td></tr>' - - if(content[1].size > 0) then - linenum = 0 - - content[1] = content[1].sort_by { |f| - f[:size] } - content[1].each do |f| - if(linenum%2 == 0) then - print ' <tr class="evenrow">' - else - print ' <tr>' - end - - puts '<td><a href="?path='+ CGI.escape(f[:path].to_s) +'">' + f[:path].to_s + '</a></td><td class="size">' + f[:humansize].to_s + '</td></tr>' - - linenum += 1 - end - end - puts ' </tbody>' - puts ' </table>' - end - end - - puts '</body>' - puts '</html>' -end - -# -# End -# - diff --git a/philesight/philesight.rb b/philesight/philesight.rb deleted file mode 100644 index b669927..0000000 --- a/philesight/philesight.rb +++ /dev/null @@ -1,458 +0,0 @@ -#!/usr/bin/ruby -# vi: ts=2 sw=2 - -require 'getoptlong' -require 'cgi' -require 'cairo' -require 'bdb' - -class PNGWriter - - def initialize(fname) - if fname != "-" then - @fd = File.open(fname, "w") - end - end - - def write(data) - if @fd then - @fd.write(data) - else - print(data) - end - return data.length - end -end - - -class Philesight - - def initialize(ringcount=4, size=800, use_gradient=true) - @max_files_per_dir = 50 - @w = size - @h = size - @cx = @w / 2 - @cy = @h / 2 - @ringcount = ringcount - @ringwidth = ((size-50)/2) / (ringcount+1) - @use_gradient = use_gradient - @find_a = 0 - @find_r = 0 - end - - - # - # Open the database. Try read-write mode first, if this fails, re-open readonly - # - - def db_open(fname) - begin - @db = BDB::Btree.open fname , nil, BDB::CREATE, 0644, "set_pagesize" => 1024, "set_cachesize" => [0, 32*1024,0] - rescue - @db = BDB::Btree.open fname , nil, BDB::RDONLY, 0644, "set_pagesize" => 1024, "set_cachesize" => [0, 32*1024,0] - end - end - - - # - # Dump database in human-readable form - # - - def dump - @db.keys.each do |f| - puts "%s %s" % [ f, Marshal::load(@db[f]).inspect ] - end - end - - - # - # Concatenate a directory and a filename - # - - def addpath(a, b) - return a + b if(a =~ /\/$/) - return a + "/" + b - end - - - # - # Read a directory and add to the database; this function is recursive - # for sub-directories - # - - def readdir(dir) - - size_file = {} - size_dir = {} - size_total = 0 - - # Traverse the directory and collect the size of all files and - # directories - - begin - Dir.foreach(dir) do |f| - - if(f != "." && f != "..") then - - f_full = addpath(dir, f) - stat = File.lstat(f_full) - - if(!stat.symlink?) then - - if(stat.file?) then - size = File.size(f_full) - size_file[f] = size - size_total += size - end - - if(stat.directory?) then - size = readdir(f_full) - if(size > 0) then - size_dir[f] = size - size_total += size - end - end - end - end - - end - rescue SystemCallError => errmsg - puts errmsg - end - - # If there are a lot of small files in this directory, group - # the smallest into one entry to avoid clutter - - if(size_file.keys.length > @max_files_per_dir) then - list = size_file.keys.select { |f| size_file[f] < size_total / @max_files_per_dir } - rest = 0 - list.each do |f| - rest += size_file[f] - size_file.delete(f) - end - size_file['rest'] = rest - end - - # Store the files in the database - - size_file.keys.each do |f| - f_full = addpath(dir, f) - @db[f_full] = Marshal::dump( [ size_file[f], [] ] ) - end - - # Store this directory with the list of children in the database - - size = size_dir.merge(size_file) - children = size.keys.sort - @db[dir] = Marshal::dump( [ size_total, children ] ) - return size_total - end - - - # - # Draw one section - # - - def draw_section(cr, ang_from, ang_to, r_from, r_to, brightness) - - ang_to, ang_from = ang_from, ang_to if (ang_to < ang_from) - - if(brightness > 0) then - r, g, b = hsv2rgb((ang_from+ang_to)*0.5 / (Math::PI*2), 1.0-brightness, brightness/2+0.5) - else - r, g, b = 0.9, 0.9, 0.9 - end - - # Instead of using the r_from and r_to for the radial pattern, the stops - # are calculated. This is to work around a bug in cairo - - r_total = ((@w - 50) / 2).to_f - pat = Cairo::RadialPattern.new(@cx, @cy, 0, @cx, @cy, r_total) - if @use_gradient then - pat.add_color_stop_rgb(r_from / r_total, r*0.8, g*0.8, b*0.8) - pat.add_color_stop_rgb(r_to / r_total, r*1.5, g*1.5, b*1.5) - else - pat.add_color_stop_rgb(0, r, g, b) - end - - cr.new_path - cr.arc(@cx, @cy, r_from, ang_from, ang_to) - cr.arc_negative(@cx, @cy, r_to, ang_to, ang_from) - cr.close_path - - cr.set_source(pat) - cr.fill_preserve - end - - - # - # Draw ring. This function is recursive for the outer rings - # - - def draw_ring(cr, level, ang_min, ang_max, path) - - ang_from = ang_min - ang_to = ang_min - ang_range = (ang_max - ang_min).to_f - r_from = level * @ringwidth - r_to = r_from + @ringwidth - - unless(@db[path]) then - return "/" - end - - total_path, child_path = Marshal::load( @db[path] ) - - # Draw a section proportional to the size of each file or subdir - - child_path.each do |f| - - f_full = addpath(path, f) - total_f, child_f = Marshal::load( @db[f_full] ) - - # Calculate start and end angles and draw section - - ang_from = ang_to - ang_to += ang_range * total_f / total_path if(total_path > 0) - brightness = r_from.to_f / @cx - brightness = 0 if(f == 'rest') - draw_section(cr, ang_from, ang_to, r_from, r_to, brightness) if(cr) - - # If we are looking for the path of an (x,y) pair, check if this section matches - - if( (@find_a >= ang_from) && (@find_a <= ang_to) && (@find_r >= r_from) && (@find_r <= r_to) ) then - @find_path = f_full - end - - # Draw outer rings - - if(level < @ringcount) then - draw_ring(cr, level+1, ang_from, ang_to, f_full) - else - draw_section(cr, ang_from, ang_to, r_to, r_to+5, 0.5) if(cr && child_f.nitems > 0) - end - - # Generate and save labels of filenames/sizes - - if(cr && (ang_to - ang_from > 0.2)) then - size = filesize_readable(total_f) - x, y = pol2xy((ang_from+ang_to)/2, (r_from+r_to)/2) - label = {} - label[:x] = x - label[:y] = y - label[:text] = "%s\n%s" % [ f, size] - @labels << label - end - end - end - - - # - # Draw graph of the given path - # - - def draw(path, fname) - - # Create drawing context, white background - - format = Cairo::FORMAT_ARGB32 - surf = Cairo::ImageSurface.new(format, @w, @h) - cr = Cairo::Context.new(surf) - writer = PNGWriter.new(fname) - - # Draw top level filename and size - - unless(@db[path]) then - draw_text(cr, @cx, @cy, "Path '#{path}' not found in database", 12) - cr.target.write_to_png(writer) - return - end - - total_path, child_path = Marshal::load( @db[path] ) - draw_text(cr, @cx, 10, "%s (%s)" % [ path, filesize_readable(total_path) ], 14, true) - draw_text(cr, @cx, @cy, "cd ..", 14, true) - - # Draw rings, recursively - - @labels = [] - draw_ring(cr, 1, 0, Math::PI*2, path) - - # Draw circles on ring borders - - cr.set_source_rgba(0, 0, 0, 0.7) - 0.upto(@ringcount+1) do | level | - cr.new_path - cr.set_line_width(0.3) - cr.arc(@cx, @cy, level * @ringwidth, 0, 2*Math::PI) - cr.stroke - end - - # Draw labels on top of graph - - @labels.each do |label| - - cr.select_font_face("Sans", Cairo::FONT_SLANT_NORMAL, Cairo::FONT_WEIGHT_NORMAL) - cr.set_font_size(9) - - # Draw text 4 times in a dark color, one time white on top - - [[-1, 0, 0.2], [+1, 0, 0.2], [0, -1, 0.2], [0, +1, 0.2], [0, 0, 0.9]].each do |dx, dy, color| - cr.set_source_rgba(color, color, color, 1.0) - draw_text(cr, label[:x]+dx, label[:y]+dy, label[:text]) - end - - end - - # Generate PNG file - - cr.target.write_to_png(writer) - end - - - # - # List files/dir of the given path - # - - def listcontent(path) - - unless(@db[path]) then - return nil - end - - dircontent = [] - - total_path, child_path = Marshal::load( @db[path] ) - - currentdir = {} - currentdir[:path] = path - currentdir[:humansize] = filesize_readable(total_path) - - child_path.each do |f| - f_full = addpath(path, f) - total_f, child_f = Marshal::load( @db[f_full] ) - - fileinfo = {} - fileinfo[:path] = f_full - fileinfo[:size] = Integer(total_f) - fileinfo[:humansize] = filesize_readable(total_f) - dircontent << fileinfo - end - - return [currentdir, dircontent] - end - - - # - # Find the path belonging to a (x,y) position in the graph - # - - def find(path, x, y) - @find_a, @find_r = xy2pol(x, y) - @find_path = File.dirname(path) - draw_ring(nil, 1, 0, Math::PI*2, path) - @find_path - end - - - private - - - # - # Draw text on pos x,y - # - - def draw_text(cr, x, y, text, size=11, bold=false) - - lines = text.count("\n") + 1 - y -= (lines-1) * (size+2) / 2.0 - - cr.select_font_face("Sans", Cairo::FONT_SLANT_NORMAL, bold ? Cairo::FONT_WEIGHT_BOLD : Cairo::FONT_WEIGHT_NORMAL) - cr.set_font_size(size) - - text.split("\n").each do |line| - extents = cr.text_extents(line) - w = extents.width - h = extents.height - cr.move_to(x - w/2, y + h/2) - cr.show_text(line) - y += size+2 - end - end - - - # - # convert color from (h,s,v) to (r,g,b) colorspace - # - - def hsv2rgb(h, s, v) - - h = h.to_f - s = s.to_f - v = v.to_f - - h *= 6.0 - i = h.floor - f = h - i - f = 1-f if ((i & 1) == 0) - m = v * (1 - s) - n = v * (1 - s * f) - i=0 if(i<0) - i=6 if(i>6) - - case i - when 0, 6: r=v; g=n; b=m - when 1: r=n; g=v; b=m - when 2: r=m; g=v; b=n - when 3: r=m; g=n; b=v - when 4: r=n; g=m; b=v - when 5: r=v; g=m; b=n - end - - [r, g, b] - end - - - # - # Convert polair (ang,radius) coordinate to cartesian (x,y) - # - - def pol2xy(a, r) - x = Math.cos(a) * r + @cx - y = Math.sin(a) * r + @cy - [x, y] - end - - # - # Convert cartesian (x,y) coordinate to polair (ang, radius) - # - - def xy2pol(x, y) - x -= @cx; - y -= @cy; - a = Math.atan2(y, x) - a += 2*Math::PI if(a<0) - r = Math.sqrt(x*x + y*y) - [a, r] - end - - - # - # Convert a filesize in bytes to a human readable form - # - - def filesize_readable(size) - if(size > 1024*1024*1024) then - return "%.1fG" % (size / (1024.0*1024*1024)) - elsif(size > 1024*1024) then - return "%.1fM" % (size / (1024.0*1024)) - elsif(size > 1024) then - return "%.1fK" % (size / (1024.0)) - end - size - end - -end - -# -# End -# |