<?php

# $Id: disk.php 503 2005-03-23 22:47:42Z bb $

# creates a pie chart of harddisk space
#
# @param size integer
#    Height of the returned image
# @param mount string
#    If present just shows the selected mount point,
#    otherwise shows all partitions.
# @param nolegend bool
#    Suppresses the legend if true.
#    The legend is automatically suppressed if the image
#    is smaller than 200px.

// calculate degrees from bytes
function calcdegrees($values) {
  foreach ($values as $value)
    $sum += $value;
  if ($sum)
    foreach ($values as $value)
      $degrees[] = 360 * $value / $sum;
  else
    $degrees = array();
  return $degrees;
}

// allocate a random light color
function randomcol($im) {
  return imagecolorallocate($im, rand(128, 224), rand(128, 224), rand(128, 224));
}

// revert "human-readable" size from df output to bytes
$units = array(
  'K' => 1024,
  'M' => 1024 * 1024,
  'G' => 1024 * 1024 * 1024,
  'T' => 1024 * 1024 * 1024 * 1024
);

function unit($s) {
  global $units;
  return floatval(substr($s, 0, -1)) * $units[substr($s, -1)];
}

// get disk capacity, collapse more than one space
$df = explode("\n", `df -Ph | sed -ne "/^\/dev/s/  */ /gp"`);

foreach ($df as $part) {
  $words = explode(' ', $part);
  // partition selection
  if ($_GET['mount'] && $_GET['mount'] != $words[5])
    continue;
  // $words = array(device, size, used, avail, used%, mountpoint)
  if (sizeof($words) == 6) {
    $values[] = unit($words[2]);
    $labels[] = sprintf('%-7s  %4s or %4s used', $words[5], $words[2], $words[4]);
    $values[] = unit($words[3]);
    $labels[] = sprintf('%-7s  %4s of %4s free', '', $words[3], $words[1]);
  }
}

$values = calcdegrees($values);

// determine image size and legend position
$size = intval($_GET['size']);
if ($size <= 0)
  $size = 400;
$radius = $size - 2;
$legend_size = ($size < 200 || $_GET['nolegend']) ? 0 : 200;    // no legend on small images
$legend_dy = 16;
$legend_x = $size + 16;
$legend_y = $size / 20;

// create the image
$im = imagecreatetruecolor($size + $legend_size, $size);

// fill with a transparent background
$bg = imagecolorallocate($im, 1, 1, 1);
imagecolortransparent($im, $bg);
imagefill($im, 0, 0, $bg);

$black = imagecolorallocate($im, 0, 0, 0);

$offset = 270;
foreach ($values as $i => $value) {
  // get color
  if ($i & 1)            // free part
    $color += 0x181818;        // lighter color than the used part
  else                // used part
    $color = randomcol($im);
  // display circle segment
  imagefilledarc(
    $im,
    $size / 2, $size / 2,
    $radius, $radius,
    $offset, $offset + $value,
    $color, IMG_ARC_PIE
  );
  $offset += $value;
  if ($legend_size) {
    // display legend
    imagefilledrectangle($im, 
      $legend_x, $legend_y,
      $legend_x + 8, $legend_y + 8,
      $color
    );
    imagestring($im, 2, $legend_x + 16, $legend_y - 3, $labels[$i], $black);
    $legend_y += $legend_dy;
  }
}

// return the image
header("Content-type: image/png");
imagepng($im);
imagedestroy($im);

?>