initial commit of file from CVS for smeserver-durep on Sat Sep 7 20:21:52 AEST 2024

This commit is contained in:
Trevor Batley 2024-09-07 20:21:52 +10:00
parent b7162f2054
commit ce6f5341b1
30 changed files with 1974 additions and 2 deletions

4
.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
*.rpm
*.log
*spec-20*
*.tar.gz

21
Makefile Normal file
View File

@ -0,0 +1,21 @@
# Makefile for source rpm: smeserver-durep
# $Id: Makefile,v 1.1 2020/10/23 10:38:14 brianr Exp $
NAME := smeserver-durep
SPECFILE = $(firstword $(wildcard *.spec))
define find-makefile-common
for d in common ../common ../../common ; do if [ -f $$d/Makefile.common ] ; then if [ -f $$d/CVS/Root -a -w $$/Makefile.common ] ; then cd $$d ; cvs -Q update ; fi ; echo "$$d/Makefile.common" ; break ; fi ; done
endef
MAKEFILE_COMMON := $(shell $(find-makefile-common))
ifeq ($(MAKEFILE_COMMON),)
# attept a checkout
define checkout-makefile-common
test -f CVS/Root && { cvs -Q -d $$(cat CVS/Root) checkout common && echo "common/Makefile.common" ; } || { echo "ERROR: I can't figure out how to checkout the 'common' module." ; exit -1 ; } >&2
endef
MAKEFILE_COMMON := $(shell $(checkout-makefile-common))
endif
include $(MAKEFILE_COMMON)

View File

@ -1,3 +1,15 @@
# smeserver-durep
# <img src="https://www.koozali.org/images/koozali/Logo/Png/Koozali_logo_2016.png" width="25%" vertical="auto" style="vertical-align:bottom"> smeserver-durep
SMEServer Koozali developed git repo for smeserver-durep smecontribs
SMEServer Koozali developed git repo for smeserver-durep smecontribs
## Wiki
<br />https://wiki.koozali.org/Durep
## Bugzilla
Show list of outstanding bugs: [here](https://bugs.koozali.org/buglist.cgi?component=smeserver-durep&product=SME%20Contribs&query_format=advanced&limit=0&bug_status=UNCONFIRMED&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&bug_status=CONFIRMED)
## Description
<br />*This description has been generated by an LLM AI system and cannot be relied on to be fully correct.*
*Once it has been checked, then this comment will be deleted*
<br />

18
additional/CHANGELOG.git Normal file
View File

@ -0,0 +1,18 @@
commit b29b1c88044b93702cf926739a05792467cc2ab8
Author: Stephane de Labrusse <stephdl@de-labrusse.fr>
Date: Sat Jun 21 12:27:27 2014 +0200
modification find in thread https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=482061 of closedir() attempted on invalid dirhandle DIR
commit 519860b663752fd066111497d32ab24411c31ec9
Author: Stephane de Labrusse <stephdl@de-labrusse.fr>
Date: Sat Jun 21 11:57:46 2014 +0200
* Sat Jun 21 2014 stephane de Labrusse <stephdl@de-labrusse.fr> 1.5.0-1.sme
- Initial release to sme9
commit e81c813da1cb02ddd21c31241ccac8b6cdbd9e1d
Author: Stephane de Labrusse <stephdl@de-labrusse.fr>
Date: Sat Jun 21 11:55:52 2014 +0200
first commit to SME Server 9

1
additional/README.md Normal file
View File

@ -0,0 +1 @@
smeserver-durep is a contrib for SME Server, a Linux distro oriented server. see http://wiki.contribs.org

View File

@ -0,0 +1,99 @@
# $Id: smeserver-durep.spec,v 1.3 2012/08/15 22:15:30 unnilennium Exp $
# Authority: unnilennnium
# Name: JP Pialasse
%define name smeserver-durep
Name: %{name}
%define version 1.5.0
Version: %{version}
%define release 1
Release: %{release}%{?dist}
License: GPL
Source: %{name}-%{version}.tar.gz
BuildRoot: /var/tmp/%{name}-%{version}-buildroot
BuildRequires: e-smith-devtools
BuildArch: noarch
Group: Networking/Daemons
Summary: DUREP - Graphic Report for Disk Usage
Requires: perl(Data::Dumper)
Requires: perl(MLDBM) >= 1.21-4
Obsoletes: smeserver-durep-saco
Obsoletes: e-smith-durep
%changelog
* Sat Jun 21 2014 stephane de Labrusse <stephdl@de-labrusse.fr> 1.5.0-1.sme
- Initial release to sme9
* Thu Sep 13 2012 JP Pialasse <test@pialasse.com> 1.3.0-6.sme
- add Obsoletes smeserver-durep-saco e-smith-durep [SME 7108]
- TODO cleaning spec file post and filelist chmod
* Mon Sep 10 2012 JP Pialasse <test@pialasse.com> 1.3.0-5.sme
- fix do not copy files and filelist [SME 7098]
- patch df of plugged disk
* Sun Sep 09 2012 JP Pialasse <test@pialasse.com> 1.3.0-4.sme
- dependencies resolution
* Fri Aug 31 2012 JP Pialasse <test@pialasse.com> 1.3.0-3.sme
- build error fix : prep setup
* Wed Aug 15 2012 JP Pialasse <test@pialasse.com> 1.3.0-1.sme
- update from 1.03-02sn to comply with SME8 and SME7
- moved archives to /var/lib/durep
- moved web files to manager/html
- cleaned spec
%description
DUREP is a Report Generator that creates graphical Output for the "du" command
%prep
%setup
%install
/bin/rm -rf $RPM_BUILD_ROOT
(cd root; /usr/bin/find . -depth -print | /bin/cpio -dump $RPM_BUILD_ROOT)
/bin/rm -f %{name}-%{version}-filelist
/sbin/e-smith/genfilelist $RPM_BUILD_ROOT > %{name}-%{version}-filelist
%clean
/bin/rm -rf $RPM_BUILD_ROOT
%files -f %{name}-%{version}-filelist
%defattr(-,root,root)
#%attr(0644 root root) "/etc/e-smith/templates/etc/crontab/durep"
#%attr(4750 root admin) "/etc/e-smith/web/functions/durep"
#%attr(0777 root root) "/etc/e-smith/web/panels/manager/cgi-bin/durep"
#%attr(0644 root root) "/usr/local/bin/durep"
#%dir %attr(0755 root root) "/usr/local/man"
#%dir %attr(0755 root root) "/usr/local/man/man1"
#%attr(0644 root root) "/usr/local/man/man1/durep.1"
#%dir %attr(0755 root root) "/usr/sbin"
#%attr(0644 root root) "/usr/sbin/durep.daily"
#%dir %attr(0755 root root) "/var/lib/durep"
#%dir %attr(0755 root root) "/etc/e-smith/web/panels/manager/html/durep"
#%attr(0644 root root) "/etc/e-smith/web/panels/manager/html/durep/bar.png"
#%attr(0644 root root) "/etc/e-smith/web/panels/manager/html/durep/durep.cgi"
#%attr(0644 root root) "/etc/e-smith/web/panels/manager/html/durep/style.css"
%pre -p /bin/sh
%post -p /bin/sh
chmod 755 /usr/local/bin/durep
chmod 755 /usr/sbin/durep.daily
/sbin/e-smith/expand-template /etc/crontab
echo "Initial run of durep ... please wait."
/usr/sbin/durep.daily >/dev/null
/etc/e-smith/events/actions/navigation-conf >/dev/null 2>&1
%preun -p /bin/sh
%postun -p /bin/sh
if [ "$1" = 0 ]; then
/sbin/e-smith/expand-template /etc/crontab
/etc/e-smith/events/actions/navigation-conf 2>/dev/null
fi

1
contriborbase Normal file
View File

@ -0,0 +1 @@
contribs10

33
createlinks Normal file
View File

@ -0,0 +1,33 @@
#!/usr/bin/perl -w
# This script creates the symlinks needed by this RPM
# Specific support exists to create symlinks within e-smith web "panels"
# and for links from named "events" directories into the "actions" directory
use esmith::Build::CreateLinks qw(:all);
safe_symlink("/etc/e-smith/web/functions/wrapper","root/etc/e-smith/web/panels/manager/cgi-bin/durep");
#--------------------------------------------------
# actions for post-upgrade:
#--------------------------------------------------
$event = "post-upgrade";
event_link("durep-init", $event, "90");
#--------------------------------------------------
# actions for smeserver-durep-update event:
#--------------------------------------------------
$event = "smeserver-durep-update";
event_link("navigation-conf", $event, "50");
event_link("durep-init", $event, "90");
templates2events("/etc/crontab", $event );
safe_symlink('restart', "root/etc/e-smith/events/$event/services2adjust/smanager");
event_link('navigation2-conf', "$event", '80');
event_link('routes2-conf', "$event", '80');
event_link('locales2-conf', "$event", '80');
safe_symlink('/etc/e-smith/web/panels/manager/html/durep/bar.png', 'root/usr/share/smanager/themes/default/public/images/bar.png');
use esmith::Build::Backup qw(:all);
backup_includes("smeserver-durep", qw(
/var/lib/durep
));

View File

@ -0,0 +1 @@

View File

@ -0,0 +1 @@
enabled

View File

@ -0,0 +1 @@
service

View File

@ -0,0 +1,3 @@
#!/bin/bash
echo "Initial run of durep ... please wait."
/usr/sbin/durep.daily >/dev/null

View File

@ -0,0 +1,4 @@
# Generate DUREP reports
01 0 * * * root /usr/sbin/durep.daily

View File

@ -0,0 +1,41 @@
#------------------------------------------------------------
# durep for user panel
#------------------------------------------------------------
{
use esmith::db;
my %accounts;
tie %accounts, 'esmith::config', '/home/e-smith/db/accounts';
my $globalpanels = db_get_prop(\%accounts, 'globalUP', 'AdminPanels');
$globalpanels = '' if ( ! defined ($globalpanels) );
my @globalpanels = split (/,/, $globalpanels, -1);
my $key;
my $value;
my $file = "durep";
my $require = "require user ";
while (($key,$value) = each %accounts)
{
my ($type, %properties) = split (/\|/, $value, -1);
if ($type eq 'user')
{
my $adminpanels = db_get_prop(\%accounts, $key, 'AdminPanels');
$adminpanels = "" if (! defined $adminpanels );
my @adminpanels = split (/,/, $adminpanels, -1);
push @adminpanels, @globalpanels ;
if (grep (/^$file$/, @adminpanels))
{
# Build a files require line for each panel
$panelshash{$file} .= " $key"
}
}
}
$OUT .= "\n";
$OUT .= " <Directory \"/etc/e-smith/web/panels/manager/html/durep\"> \n";
$OUT .= " require user admin$panelshash{$file}\n";
$OUT .= " </Directory>\n";
}

View File

@ -0,0 +1,73 @@
#!/usr/bin/perl -wT
#----------------------------------------------------------------------
# heading : Administration
# description : Disk usage report
# navigation : 4000 4390
#
#----------------------------------------------------------------------
package esmith;
use strict;
use CGI ':all';
use CGI::Carp qw(fatalsToBrowser);
use esmith::cgi;
use esmith::db;
use esmith::util;
sub showInitial ($);
BEGIN
{
# Clear PATH and related environment variables so that calls to
# external programs do not cause results to be tainted. See
# "perlsec" manual page for details.
$ENV {'PATH'} = '/bin:/usr/bin';
$ENV {'SHELL'} = '/bin/bash';
delete $ENV {'ENV'};
}
esmith::util::setRealToEffective ();
$CGI::POST_MAX=1024 * 100; # max 100K posts
$CGI::DISABLE_UPLOADS = 1; # no uploads
my %conf;
tie %conf, 'esmith::config';
#------------------------------------------------------------
# examine state parameter and display the appropriate form
#------------------------------------------------------------
my $q = new CGI;
if (! grep (/^state$/, $q->param))
{
showInitial ($q);
}
else
{
esmith::cgi::genStateError ($q, \%conf);
}
exit (0);
#------------------------------------------------------------
# subroutine to display initial form
#------------------------------------------------------------
sub showInitial ($)
{
my ($q) = @_;
my $url = "/server-manager/durep/durep.cgi";
print $q->redirect(-location => $url);
## these lines aren't that important, they just prevent a
## premature end of script headers error
esmith::cgi::genHeaderNonCacheable ($q, \%conf, 'DUREP reports');
esmith::cgi::genFooter ($q);
}

View File

@ -0,0 +1 @@
../../../functions/durep

Binary file not shown.

After

Width:  |  Height:  |  Size: 205 B

View File

@ -0,0 +1,379 @@
#!/usr/bin/perl -w
#############################################################################
# durep - Disk Usage Report Generator #
# #
# Copyright (C) 2004 Damian Kramer (psiren@hibernaculum.net) #
# #
# You may distribute this program under the terms of the Artistic License. #
# #
# This program is distributed in the hope that it will be useful, but #
# WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# Artistic License for more details. #
#############################################################################
use MLDBM qw(DB_File Storable);
use POSIX;
use strict;
## Set these variables as appropriate.
## --------------------------------------------------
our $datadir = "/var/lib/durep"; # Filesystem path to the data files.
our $css_file = "/server-manager/durep/style.css"; # URL to CSS file
our $bar_image = "/server-manager/durep/bar.png"; # URL to image used in bar graph
our $show_mtime = 1; # Show file modifcation time
our $show_opts = 0; # Show options used
## --------------------------------------------------
### NO USER-SERVICEABLE PARTS BEYOND THIS POINT ###
our ($me, $data, @ancestors, @records, %input, $temp, $version, $top_node, $collated);
our ($TYPE_FILE, $TYPE_DIR, $TYPE_EMPTY, $TYPE_COALESCED, $TYPE_COLLAPSED);
$me = $ENV{SCRIPT_NAME};
$TYPE_FILE = 0;
$TYPE_DIR = 1;
$TYPE_EMPTY = 2;
$TYPE_COALESCED = 4;
$TYPE_COLLAPSED = 8;
$version = "0.9";
$ENV{PATH} = "/bin:/usr/bin";
$top_node = {};
$collated = loadCollateFile($datadir);
getInput();
if(%input) {
fetchData();
displayData();
}
else {
displayList();
}
# Return to system
exit 0;
sub getInput {
if($ENV{REQUEST_METHOD} eq 'POST') {
chomp($_ = <STDIN>);
}
elsif($ENV{REQUEST_METHOD} eq 'GET') {
$_ = $ENV{QUERY_STRING};
}
else {
return;
}
for $temp (split("&", $_)) {
my ($var, $val) = split ('=', $temp);
$val =~ s/\+/ /g;
$val =~ s/%(..)/pack("H2", $1)/eg;
if(defined $input{$var}) {
$input{$var} .= "\0$val";
}
else {
$input{$var} = $val;
}
}
}
sub displayInput {
print "Content-type: text/html\n\n";
my ($key, $val);
print "<html><head><title>SMESERVER Disk Usage Report</title></head>";
print "<body bgcolor='#FFFFFF' text='#000000' link='#0000FF' vlink='#0000AA'><br><br>";
print "<table cellpadding=0 cellspacing=0 border=1>";
while(($key, $val) = each %input) {
my $length = length $val;
print "<tr><td><pre>$key</pre></td><td><pre>[$length]</pre></td><td><pre>[$val]</pre></td></tr>\n";
}
print "</table></pre>";
print "</body></html>";
}
sub fetchData {
my $root_node = {};
my $node;
tie %{$root_node}, 'MLDBM', "$datadir/$collated->{$input{fid}}->{FILENAME}", O_RDONLY, 0640 or errorPage();
%{$data} = (%{$root_node->{DATA}});
%{$top_node} = (%{$root_node->{$input{nid}}});
$node = $top_node;
while($node->{PARENT}) {
my $tmp = {};
%{$tmp} = (%{$root_node->{$node->{PARENT}}});
unshift @ancestors, $tmp;
$node = $tmp;
}
foreach $node (@{$top_node->{CHILDREN}}) {
my $tmp = {};
%{$tmp} = (%{$root_node->{$node}});
push @records, $tmp;
}
@records = reverse sort sortBySize @records;
untie %{$root_node};
}
sub displayList {
print "Content-type: text/html\n\n";
my $hash = sortCollateFile($collated);
my ($key, $val);
print qq{
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<title>Disk Usage Report</title>
<link rel="stylesheet" href="$css_file" type="text/css"/>
</head>
<body>
<h1>Disk Usage Report</h1>
<table class='list' cellpadding=0 cellspacing=0 border=0>
<tr><th>&nbsp;</th><th>Path</th><th>Description</th><th>Size</th><th>Dirs</th><th>Files</th><th>Date</th></tr>
};
foreach my $host (keys %{$hash}) {
print "<tr><td colspan=7 class='dark'>$host</td></tr>\n";
my $flip = 0;
foreach my $e (reverse sort sortByDate @{$hash->{$host}}) {
if($flip) { print "<tr class='mid'>"; }
else { print "<tr class='light'>"; }
$flip = !$flip;
print "<td>&nbsp;</td>";
print "<td><a href='$me?fid=$e->{ID}&nid=1'>$e->{PATH}</a></td>";
printf "<td><a href='$me?fid=$e->{ID}&nid=1'>%s</a></td>", $e->{DESC} || "-";
printf "<td>%s</td>", prettyFileSize($e->{SIZE});
printf "<td>%s</td>", prettyNum($e->{DIR_COUNT});
printf "<td>%s</td>", prettyNum($e->{FILE_COUNT});
printf "<td>%s</td>", prettyDate($e->{LAST_UPDATE});
print "</tr>\n";
}
}
# table to show df of all disk on main page
print qq{
</table>
<table class='list' cellpadding=0 cellspacing=0 border=0>
<tr><th>Filesystem</th><th>Sized</th><th>Used</th><th>Available</th><th>Use %</th><th>Mounted on</th></tr>
};
my $dflist = `df -hP|grep -v 'Use%'|sed 's#^#<tr><td>#g'|sed 's#\$#</td></tr>#g'`;
$dflist =~ s/[ ]+/<\/td><td>/g;
print $dflist;
print qq{
</table>
</body>
</html>
};
}
sub displayData {
print "Content-type: text/html\n\n";
my ($key, $val);
print qq{
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<title>Disk Usage Report ($data->{HOSTNAME})</title>
<link rel="stylesheet" href="$css_file" type="text/css"/>
</head>
<body>
<h1>Disk Usage Report ($data->{HOSTNAME})</h1>
<div class='tbar'><table class='location'><tr><td>[<a href='$me'>Home</a>]
};
foreach my $tmp (@ancestors) {
printf "<a href='$me?fid=$input{fid}&nid=%d'>$tmp->{NAME}</a>%s", $tmp->{ID}, (($tmp->{NAME} =~ m|\/$|) ? "" : "/");
}
print "$top_node->{NAME}</td>";
printf "<td class='right'>%s</td>", prettyFileSize($top_node->{SIZE});
print "</tr></table></div>";
print "<table class='report' cellpadding=0 cellspacing=0 border=0>\n";
print "<tr class='dark'><th>Size</th><th colspan=2>Percentage</th>";
print "<th class='right'>Dirs</th><th class='right'>Files</th>";
print "<th>Modified</th>" if $show_mtime;
print "<th>File</th></tr>";
my $flip = 0;
foreach my $node (@records) {
my $percent = $top_node->{SIZE} ? ($node->{SIZE}/$top_node->{SIZE}*100) : 0;
if($flip) { print "<tr class='mid'>"; }
else { print "<tr class='light'>"; }
$flip = !$flip;
print "<td class='right'>";
print prettyFileSize($node->{SIZE});
print "</td><td>";
print barChart($percent);
printf("</td><td class='right'>%4.2f%%</td>", $percent);
if($node->{TYPE} & $TYPE_DIR) {
if($node->{TYPE} & $TYPE_EMPTY) {
print "<td class='right'>0</td><td class='right'>0</td>";
printf("<td>%s</td>", shortDate($node->{MTIME})) if $show_mtime;
print "<td><span class='empty'>$node->{NAME}/</span></td>";
}
else {
printf("<td class='right'>%d</td>", $node->{DCOUNT});
printf("<td class='right'>%d</td>", $node->{FCOUNT});
printf("<td>%s</td>", shortDate($node->{MTIME})) if $show_mtime;
print "<td><span class='dir'><a href='$me?fid=$input{fid}&nid=$node->{ID}'>$node->{NAME}/</a></span></td>";
}
}
elsif($node->{TYPE} & $TYPE_COALESCED) {
printf "<td>&nbsp;</td><td class='right'>%d</td>", $node->{FCOUNT};
printf("<td>%s</td>", shortDate($node->{MTIME})) if $show_mtime;
print "<td><span class='coalesced'>$node->{NAME}</span></td>";
}
else {
print "<td>&nbsp;</td><td>&nbsp;</td>";
printf("<td>%s</td>", shortDate($node->{MTIME})) if $show_mtime;
print "<td>$node->{NAME}</td>";
}
print "</tr>\n";
}
print "</table>\n";
print "<div class='bbar'><table class='location'><tr>";
printf "<td>%s</td>", scalar localtime($data->{LAST_UPDATE});
print "<td class='right'>Generated by <a href='http://www.hibernaculum.net/'>durep</a> v. $version</td>";
print "</tr></table></div>\n";
if($show_opts && $data->{OPTIONS}) {
print "<div class='options'><ul>";
print "<li>Scanning files only.</li>" if $data->{OPTIONS}->{FILES};
print "<li>Restricting to single filesystem.</li>" if $data->{OPTIONS}->{ONEFILESYSTEM};
printf "<li>Collapsing paths matching <b>%s</b>.</li>", $data->{OPTIONS}->{COLLAPSEPATH} if $data->{OPTIONS}->{COLLAPSEPATH};
printf "<li>Excluding paths matching <b>%s</b>.</li>", $data->{OPTIONS}->{EXCLUDEPATH} if $data->{OPTIONS}->{EXCLUDEPATH};
printf "<li>Coalescing files below <b>%s</b>.</li>", prettyFileSize($data->{OPTIONS}->{COALESCEFILES}) if $data->{OPTIONS}->{COALESCEFILES};
print "</ul></div>";
}
print "</body></html>";
}
### All this does is create an HTML table bar graph type thingy.
sub barChart {
my $percent = int($_[0]*2+0.5);
my $rv = "<div class='graph'>";
if($percent) {
$rv .= "<img src='$bar_image' style=\"width:${percent}px; height: 15px;\"/>";
}
else {
$rv .= "&nbsp;";
}
$rv .= "</div>";
return $rv;
}
# Generates a human readable file size string
sub prettyFileSize {
my $val = $_[0];
my $dtype = "b";
if($val >= 1024) {
$val /= 1024;
$dtype = "K";
}
if($val >= 1024) {
$val /= 1024;
$dtype = "M";
}
if($val >= 1024) {
$val /= 1024;
$dtype = "G";
}
if($dtype eq "b") {
return sprintf("%d%s", $val, $dtype);
}
else {
return sprintf("%.1f%s", $val, $dtype);
}
}
sub prettyDate {
return POSIX::strftime("%T %a %b %e %Y", localtime $_[0]);
}
sub shortDate {
if($_[0] < (time - 31536000)) {
return POSIX::strftime("%b %e %Y", localtime $_[0]);
}
return POSIX::strftime("%b %e %H:%M", localtime $_[0]);
}
sub prettyNum {
my $r = reverse shift;
$r =~ s/(\d\d\d)(?=\d)(?!\d*\.)/$1,/g;
return scalar reverse $r;
}
sub sortBySize {
return $a->{SIZE} <=> $b->{SIZE};
}
sub sortByDate {
return $a->{LAST_UPDATE} <=> $b->{LAST_UPDATE};
}
sub sortByPath {
return $a->{PATH} cmp $b->{PATH};
}
sub loadCollateFile {
my $dir = shift;
my %db;
my $r;
tie %db, 'MLDBM', "$dir/durep.cds", O_RDONLY, 0640 or errorPage();
foreach my $key (keys %db) {
$r->{$key} = \%{$db{$key}};
}
untie %db;
return $r;
}
sub sortCollateFile {
my $hash = shift;
my $r;
foreach my $key (keys %{$hash}) {
my $hostname = $hash->{$key}->{HOSTNAME};
push @{$r->{$hostname}}, \%{$hash->{$key}};
}
return $r;
}
sub errorPage {
print "Content-type: text/html\n\n";
print qq{
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<title>Disk Usage Report</title>
<link rel="stylesheet" href="$css_file" type="text/css"/>
</head>
<body>
<h1>Durep encountered an error!</h1>
<p>Please check that you have collated the files and that the permissions on them are correct.</p>
</body>
</html>
};
exit 0;
}

View File

@ -0,0 +1,125 @@
a:hover {
background-color: #DDDDDD;
}
body {
text-align: center;
background-color: #ffffff;
}
div.tbar {
text-align: left;
width: 100%;
background-color: #EEEEEE;
border-top: solid 1px #DDDDDD;
border-bottom: solid 1px #DDDDDD;
}
div.bbar {
text-align: left;
width: 100%;
background-color: #EEEEEE;
border-top: solid 1px #DDDDDD;
border-bottom: solid 1px #DDDDDD;
}
div.bbar * {
font-size: 90%;
}
div.options {
text-align: left;
margin: 2em;
background-color: #EEEEEE;
border: solid 1px #DDDDDD;
}
.light {
background-color: #ffffff;
}
.mid {
background-color: #f6f6f6;
}
.dark {
background-color: #f0f0f0;
}
.tbar table {
width: 100%;
padding-left: 2pt;
font-weight: bold;
}
.bbar table {
width: 100%;
padding-left: 2pt;
}
table.list {
margin: 2em 0px;
border: solid 1px #CCCCCC;
margin-left: auto;
margin-right: auto;
}
table.list td {
text-align: left;
padding: 2px 5px;
}
table.list th {
text-align: left;
padding: 2px 5px;
text-align: left;
background-color: #DDDDDD;
}
table.report {
margin: 2em 0px;
border: solid 1px #CCCCCC;
text-align: left;
margin-left: auto;
margin-right: auto;
}
table.report td {
padding: 2px 5px;
}
table.report th {
padding: 2px 5px;
text-align: left;
background-color: #DDDDDD;
}
.graph {
padding: 0px;
background-color: #eeeeee;
width: 200px;
height: 15px;
}
th.right {
text-align: right;
}
td.right {
text-align: right;
}
span.dir {
font-weight: bold;
}
span.empty {
color: #006600;
font-weight: bold;
}
span.coalesced {
color: #880000;
font-weight: bold;
}

View File

@ -0,0 +1 @@
/etc/e-smith/web/panels/manager/html/durep

452
root/usr/local/bin/durep Executable file
View File

@ -0,0 +1,452 @@
#!/usr/bin/perl -w
#############################################################################
# durep - Disk Usage Report Generator #
# #
# Copyright (C) 2004 Damian Kramer (psiren@hibernaculum.net) #
# #
# You may distribute this program under the terms of the Artistic License. #
# #
# This program is distributed in the hope that it will be useful, but #
# WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# Artistic License for more details. #
#############################################################################
use Getopt::Long;
use File::Basename;
use MLDBM qw(DB_File Storable);
use Fcntl;
use Sys::Hostname;
use POSIX;
use Cwd qw(cwd);
use strict;
our ($version, %options);
our ($root_node, $filesystem_id, @stats);
our ($opt_help, $opt_version, $opt_textdepth, $opt_hidesize, $opt_showdate, $opt_nosort, $opt_quiet);
our ($opt_savefile, $opt_loadfile, $opt_desc, $opt_collate);
our ($opt_files, $opt_onefilesystem, $opt_collapsepath, $opt_excludepath, $opt_coalescefiles);
our ($root_dir, $file_count, $dir_count, $next_id);
our ($TYPE_FILE, $TYPE_DIR, $TYPE_EMPTY, $TYPE_COALESCED, $TYPE_COLLAPSED);
$TYPE_FILE = 0;
$TYPE_DIR = 1;
$TYPE_EMPTY = 2;
$TYPE_COALESCED = 4;
$TYPE_COLLAPSED = 8;
$version = "0.9";
$| = 1;
$SIG{INT} = \&catchError;
%options = ("h|help" => \$opt_help,
"v|version" => \$opt_version,
"td|text-depth=i" => \$opt_textdepth,
"hs|hide-size=s" => \$opt_hidesize,
"sd|show-date" => \$opt_showdate,
"ns|nosort" => \$opt_nosort,
"q|quiet" => \$opt_quiet,
"sf|save-file=s" => \$opt_savefile,
"lf|load-file=s" => \$opt_loadfile,
"d|desc=s" => \$opt_desc,
"c|collate=s" => \$opt_collate,
"f|files" => \$opt_files,
"x|one-file-system" => \$opt_onefilesystem,
"cp|collapse-path=s" => \$opt_collapsepath,
"ep|exclude-path=s" => \$opt_excludepath,
"cf|coalesce-files=s" => \$opt_coalescefiles
);
&usage unless (GetOptions(%options));
&usage if(defined $opt_help);
if(defined $opt_version) {
print "durep version $version\n";
exit 0;
}
## Process options
if($opt_collate) {
collate();
exit 0;
}
$opt_hidesize = processSizeOption($opt_hidesize) if(defined $opt_hidesize);
$opt_coalescefiles = processSizeOption($opt_coalescefiles) if(defined $opt_coalescefiles);
doAbort("Depth must be greater than 0.") if(defined $opt_textdepth && $opt_textdepth < 1);
doAbort("You must specify a save file if you use --quiet.") if(defined $opt_quiet && !defined $opt_savefile);
doAbort("You can't use --load-file and --save-file at the same time.") if(defined $opt_loadfile && defined $opt_savefile);
if($opt_savefile) {
$opt_savefile .= ".ds" unless $opt_savefile =~ /\.ds$/;
}
push @ARGV, "." unless @ARGV;
$root_dir = shift;
chop $root_dir if $root_dir =~ m|./$|; # Remove trailing /
doAbort("`$root_dir' not a valid directory.") unless -d $root_dir;
# Get the absolute pathname rather than relative pathname
$_ = cwd();
chdir($root_dir) or doAbort("Unable to chdir to '$root_dir'.");
$root_dir = cwd();
chdir($_);
if($opt_loadfile) {
tie %{$root_node}, 'MLDBM', "$opt_loadfile", O_RDONLY, 0640 or doAbort("Unable to tie file '$opt_loadfile'.");
}
else {
## Perform scan
$file_count = 0;
$dir_count = 0;
$next_id = 1;
$root_node = {};
if($opt_savefile) {
if(-r $opt_savefile) {
print "Removing existing savefile '$opt_savefile'.\n" unless $opt_quiet;
unlink $opt_savefile;
}
tie %{$root_node}, 'MLDBM', "$opt_savefile", O_CREAT|O_RDWR, 0640 or doAbort("Unable to tie file '$opt_savefile'.");
}
($filesystem_id) = stat $root_dir if defined $opt_onefilesystem;
$root_node->{1} = recursiveScan($root_dir, undef, 1);
my $data;
$data->{FILE_COUNT} = $file_count;
$data->{DIR_COUNT} = $dir_count;
$data->{LAST_UPDATE} = time;
$data->{HOSTNAME} = hostname();
$data->{DESC} = $opt_desc if $opt_desc;
$data->{OPTIONS}->{FILES} = 1 if $opt_files;
$data->{OPTIONS}->{ONEFILESYSTEM} = 1 if $opt_onefilesystem;
$data->{OPTIONS}->{COLLAPSEPATH} = $opt_collapsepath if $opt_collapsepath;
$data->{OPTIONS}->{EXCLUDEPATH} = $opt_excludepath if $opt_excludepath;
$data->{OPTIONS}->{COALESCEFILES} = $opt_coalescefiles if $opt_coalescefiles;
$root_node->{DATA} = $data;
}
# use Data::Dumper;
# print Dumper($root_node);
if(!$opt_quiet) {
printf "[ %s %s (%d files, %d dirs) ]\n", $root_node->{1}->{NAME}, prettyFileSize($root_node->{1}->{SIZE}),
$root_node->{1}->{FCOUNT}, $root_node->{1}->{DCOUNT};
printDir($root_node->{1}, 0);
}
if($opt_savefile || $opt_loadfile) {
untie %{$root_node};
}
exit 0;
## End of program.
sub recursiveScan {
my ($dir, $parent, $store) = @_;
my @children;
my $coalesced_count = 0;
my $coalesced_size = 0;
my $node = {};
my $temp;
my $dirhandle;
$node->{ID} = $next_id++;
if(defined $parent) {
$node->{NAME} = basename($dir);
$node->{PARENT} = $parent;
}
else {
$node->{NAME} = $dir;
}
$node->{SIZE} = 0;
$node->{TYPE} = $TYPE_DIR;
$node->{DCOUNT} = 0;
$node->{FCOUNT} = 0;
if($store) {
$store = 0 if($opt_collapsepath && $dir =~ m/$opt_collapsepath/);
}
$node->{TYPE} &= $TYPE_COLLAPSED unless $store;
opendir($dirhandle, $dir) or warn "Unable to open dir '$dir': $!\n" and return $node;
foreach(readdir($dirhandle)) {
@stats = lstat "$dir/$_" or warn "Unable to lstat '$dir/$_': $!\n" and next;
$node->{MTIME} = $stats[9] if($_ eq ".");
# Skip '.' and '..'
next if(/^\.{1,2}$/);
if(-d _ && ! -l _ && !$opt_files) {
if(! -x _) {
warn "Unable to read directory `$dir/$_'. Skipping.\n";
next;
}
next if($opt_excludepath && "$dir/$_" =~ m/$opt_excludepath/);
next if($opt_onefilesystem && ($stats[0] != $filesystem_id));
$temp = recursiveScan("$dir/$_", $node->{ID}, $store);
$node->{SIZE} += $temp->{SIZE};
if($store) {
$root_node->{$temp->{ID}} = $temp;
push @children, $temp->{ID};
$dir_count++;
$node->{DCOUNT}++;
}
next;
}
if($opt_coalescefiles && $stats[7] < $opt_coalescefiles) {
$coalesced_count++;
$coalesced_size += $stats[7];
}
else {
if($store) {
my $file = {};
$file->{ID} = $next_id++;
$file->{NAME} = $_;
$file->{SIZE} = $stats[7];
$file->{PARENT} = $node->{ID};
$file->{TYPE} = $TYPE_FILE;
$file->{MTIME} = $stats[9];
$root_node->{$file->{ID}} = $file;
push @children, $file->{ID};
}
$node->{SIZE} += $stats[7];
}
$file_count++;
$node->{FCOUNT}++;
}
closedir($dirhandle);
if($coalesced_count) {
if($store) {
my $file = {};
$file->{ID} = $next_id++;
$file->{NAME} = "[COALESCED FILES]";
$file->{SIZE} = $coalesced_size;
$file->{PARENT} = $node->{ID};
$file->{TYPE} = $TYPE_FILE|$TYPE_COALESCED;
$file->{MTIME} = 0;
$file->{FCOUNT} = $coalesced_count;
$root_node->{$file->{ID}} = $file;
push @children, $file->{ID};
}
$node->{SIZE} += $coalesced_size;
}
if(@children) {
$node->{CHILDREN} = \@children;
}
else {
$node->{TYPE} = $TYPE_DIR|$TYPE_EMPTY;
}
# $root_node->{$node->{ID}} = $node;
return $node;
}
sub collate {
my %db;
doAbort("'$opt_collate' is not a valid directory.") unless -d $opt_collate;
tie %db, 'MLDBM', "$opt_collate/durep.cds", O_CREAT|O_RDWR, 0640 or doAbort("Unable to tie file '$opt_collate/durep.cds'");
my @files;
my $next_id = 1;
opendir(DIR, $opt_collate) or doAbort("Unable to open dir '$opt_collate': $!");
foreach(readdir(DIR)) {
# Skip unless a .ds file
next unless(/\.ds$/);
push @files, $_;
}
closedir(DIR);
foreach my $file (sort @files) {
my $id = $next_id++;
my %temp;
tie %temp, 'MLDBM', "$opt_collate/$file", O_RDONLY, 0640 or doAbort("Unable to tie file '$opt_collate/$file'");
my %data = (%{$temp{DATA}});
$data{FILENAME} = $file;
$data{SIZE} = $temp{1}->{SIZE};
$data{ID} = $id;
$data{PATH} = $temp{1}->{NAME};
$db{$id} = \%data;
untie %temp;
}
untie %db;
}
sub printDir {
my ($dir, $indent) = @_;
my @entries;
foreach my $entry (@{$dir->{CHILDREN}}) {
$entry = $root_node->{$entry};
next if(defined $opt_hidesize && $entry->{SIZE} < $opt_hidesize);
my $e = {};
$e->{NAME} = $entry->{NAME};
$e->{SIZE} = $entry->{SIZE};
$e->{TYPE} = $entry->{TYPE};
$e->{MTIME} = $entry->{MTIME};
$e->{CHILDREN} = $entry->{CHILDREN} if $entry->{CHILDREN};
push @entries, $e;
}
@entries = reverse sort sortBySize @entries unless $opt_nosort;
foreach my $entry (@entries) {
my $numofchars;
my $percent = $dir->{SIZE} == 0 ? 0 : ($entry->{SIZE}/$dir->{SIZE})*100;
print " " x $indent;
print prettyFileSize($entry->{SIZE});
$numofchars = int ((30 / 100) * $percent);
printf(" [%s%s] ", "#" x $numofchars, " " x (30-$numofchars));
printf("%6.2f%% ", $percent);
printf("%s ", shortDate($entry->{MTIME})) if $opt_showdate;
printf("%s%s\n", $entry->{NAME}, $entry->{TYPE} & $TYPE_DIR ? "/" : "");
if($entry->{TYPE} & $TYPE_DIR) {
printDir($entry, $indent+1) if(!defined $opt_textdepth || ($opt_textdepth > $indent+1));
}
}
}
sub processSizeOption {
my ($size, $temp);
if($_[0] =~ m/[bBkKmMgG]$/) {
($size, $temp) = $_[0] =~ m/^(.+)([bBkKmMgG])$/;
}
else {
$size = $_[0];
}
unless (defined $size && ($size =~ m/^\d+$/ || $size =~ m/^\d+\.\d+$/)) {
doAbort("Malformed argument: $_[0]");
}
if(defined $temp) {
if($temp =~ m/^[kK]/) {
return $size * 1024;
}
elsif ($temp =~ m/^[mM]/) {
return $size * 1048576;
}
elsif ($temp =~ m/^[mM]/) {
return $size * 1048576 * 1024;
}
return $size;
}
}
sub prettyFileSize {
my $val = $_[0];
my $dtype = "b";
if($val >= 1024) {
$val /= 1024;
$dtype = "K";
}
if($val >= 1024) {
$val /= 1024;
$dtype = "M";
}
if($val >= 1024) {
$val /= 1024;
$dtype = "G";
}
if($dtype eq "b") {
return sprintf("%6d%s", $val, $dtype);
}
else {
return sprintf("%6.1f%s", $val, $dtype);
}
}
sub shortDate {
if($_[0] < (time - 31536000)) {
return POSIX::strftime("%b %e %Y", localtime $_[0]);
}
return POSIX::strftime("%b %e %H:%M", localtime $_[0]);
}
sub sortBySize {
return $a->{SIZE} <=> $b->{SIZE};
}
### End program with error message
sub doAbort {
warn "Error: $_[0]\n";
exit 1;
}
sub catchError {
warn "Program interrupted.\n";
if($opt_savefile || $opt_loadfile) {
untie %{$root_node};
}
exit 1;
}
sub usage {
print <<EOF;
Usage: durep [OPTION(S)] [DIRECTORY]
-h, --help this help
-v, --version show version number
Text Ouput Options:
-td, --text-depth=N limit text report on directories to depth N
-hs, --hide-size=N[bkmg] do not display entries using N Bytes/Kb/Mb/Gb
or less (default Bytes)
-sd, --show-date show modification date
-ns, --nosort do not sort results by size
-q, --quiet do not produce text output
File Options:
-sf, --save-file=<file> save the results of the scan into this file
-lf, --load-file=<file> load the results of a scan from this file
-d, --desc=<description> give description of save file
-c, --collate=<dir> collate save files in dir for web report
Inclusion Options:
-f, --files do not descend into subdirs, only report files
-x, --one-file-system do not traverse file systems
-cp, --collapse-path=<regexp> hide entries below paths that match regexp
-ep, --exclude-path=<regexp> ignore paths that match regexp
-cf, --coalesce-files=N[bkmg] coalesce files less than N Bytes/Kb/Mb/Gb
into one entry (default Bytes)
EOF
exit 0;
}

View File

@ -0,0 +1,290 @@
.\" Automatically generated by Pod::Man version 1.15
.\" Fri Nov 26 12:13:59 2004
.\"
.\" Standard preamble:
.\" ======================================================================
.de Sh \" Subsection heading
.br
.if t .Sp
.ne 5
.PP
\fB\\$1\fR
.PP
..
.de Sp \" Vertical space (when we can't use .PP)
.if t .sp .5v
.if n .sp
..
.de Ip \" List item
.br
.ie \\n(.$>=3 .ne \\$3
.el .ne 3
.IP "\\$1" \\$2
..
.de Vb \" Begin verbatim text
.ft CW
.nf
.ne \\$1
..
.de Ve \" End verbatim text
.ft R
.fi
..
.\" Set up some character translations and predefined strings. \*(-- will
.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
.\" double quote, and \*(R" will give a right double quote. | will give a
.\" real vertical bar. \*(C+ will give a nicer C++. Capital omega is used
.\" to do unbreakable dashes and therefore won't be available. \*(C` and
.\" \*(C' expand to `' in nroff, nothing in troff, for use with C<>
.tr \(*W-|\(bv\*(Tr
.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
.ie n \{\
. ds -- \(*W-
. ds PI pi
. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
. ds L" ""
. ds R" ""
. ds C` ""
. ds C' ""
'br\}
.el\{\
. ds -- \|\(em\|
. ds PI \(*p
. ds L" ``
. ds R" ''
'br\}
.\"
.\" If the F register is turned on, we'll generate index entries on stderr
.\" for titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and
.\" index entries marked with X<> in POD. Of course, you'll have to process
.\" the output yourself in some meaningful fashion.
.if \nF \{\
. de IX
. tm Index:\\$1\t\\n%\t"\\$2"
..
. nr % 0
. rr F
.\}
.\"
.\" For nroff, turn off justification. Always turn off hyphenation; it
.\" makes way too many mistakes in technical documents.
.hy 0
.if n .na
.\"
.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
.\" Fear. Run. Save yourself. No user-serviceable parts.
.bd B 3
. \" fudge factors for nroff and troff
.if n \{\
. ds #H 0
. ds #V .8m
. ds #F .3m
. ds #[ \f1
. ds #] \fP
.\}
.if t \{\
. ds #H ((1u-(\\\\n(.fu%2u))*.13m)
. ds #V .6m
. ds #F 0
. ds #[ \&
. ds #] \&
.\}
. \" simple accents for nroff and troff
.if n \{\
. ds ' \&
. ds ` \&
. ds ^ \&
. ds , \&
. ds ~ ~
. ds /
.\}
.if t \{\
. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
.\}
. \" troff and (daisy-wheel) nroff accents
.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
.ds ae a\h'-(\w'a'u*4/10)'e
.ds Ae A\h'-(\w'A'u*4/10)'E
. \" corrections for vroff
.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
. \" for low resolution devices (crt and lpr)
.if \n(.H>23 .if \n(.V>19 \
\{\
. ds : e
. ds 8 ss
. ds o a
. ds d- d\h'-1'\(ga
. ds D- D\h'-1'\(hy
. ds th \o'bp'
. ds Th \o'LP'
. ds ae ae
. ds Ae AE
.\}
.rm #[ #] #H #V #F C
.\" ======================================================================
.\"
.IX Title "DUREP 1"
.TH DUREP 1 "durep version " "2004-09-05" "Disk Usage Report Generator"
.UC
.SH "NAME"
durep \- disk usage report generator
.SH "SYNOPSIS"
.IX Header "SYNOPSIS"
durep [\s-1OPTIONS\s0]... [\s-1DIRECTORY\s0]
.SH "DESCRIPTION"
.IX Header "DESCRIPTION"
\&\fBdurep\fR creates disk usage reports with bar graphs, allowing one to
easily deduce which directories are using the most space. Although
\&\fBdurep\fR can produce text output similar to du, its real power lies in
the ability to store reports in a file, which can then be viewed as a
web page with the supplied cgi script.
.SH "OPTIONS"
.IX Header "OPTIONS"
Options are groubed into three distinct sections.
.Sh "Text Output Options"
.IX Subsection "Text Output Options"
These options are for controlling the text report output.
.Ip "\fB\-td, \-\-text-depth\fR=\fIN\fR" 7
.IX Item "-td, --text-depth=N"
Limit text report on directories to depth \fIN\fR. No directories below
this level will be shown in the report.
.Ip "\fB \-hs, \-\-hide-size\fR=\fIN[bkmg]\fR" 7
.IX Item " -hs, --hide-size=N[bkmg]"
Do not display entries using \fIN\fR Bytes/Kb/Mb/Gb or less (default
Bytes). This is to reduce clutter in the reports. It allows you to
remove small files from the text report.
.Ip "\fB \-sd, \-\-show-date\fR" 7
.IX Item " -sd, --show-date"
Display the modification date of the file or directory in the report.
.Ip "\fB\-ns, \-\-nosort\fR" 7
.IX Item "-ns, --nosort"
Do not sort results by size. Leaves results in the order in which they
were scanned, which is highly dependant on the filesystem.
.Ip "\fB\-q, \-\-quiet\fR" 7
.IX Item "-q, --quiet"
Do not produce text output. This stops the creation of a text report,
and is useful when you are only interested in generating a save-file
for use with the web report.
.Sh "File Options"
.IX Subsection "File Options"
These options control load and save files.
.Ip "\fB\-sf, \-\-save-file\fR=\fI\s-1FILE\s0\fR" 7
.IX Item "-sf, --save-file=FILE"
Save the results of the scan into this file. This can be loaded for a
text report, but is generally used by the cgi script to display web
reports. The filename should end in \fI.ds\fR (it is appended if it does
not).
.Ip "\fB\-lf, \-\-load-file\fR=\fI\s-1FILE\s0\fR" 7
.IX Item "-lf, --load-file=FILE"
Load the results of a scan from this file. This takes the place of
scanning a directory. Inclusion options (described below) will not
take effect if this option is used.
.Ip "\fB\-d, \-\-desc\fR=\fI\s-1DESCRIPTION\s0\fR" 7
.IX Item "-d, --desc=DESCRIPTION"
Give a description to be stored in the save-file. This is displayed on
the web report summary page.
.Ip "\fB\-c, \-\-collate=\fR=\fI\s-1DIR\s0\fR" 7
.IX Item "-c, --collate==DIR"
Collate the save-files in the given directory. This creates a
\&\fIdurep.cds\fR file, which is used by the cgi script to manage and
display save-files. See \fBWeb Reports\fR section below for more detail.
.Sh "Inclusion Options"
.IX Subsection "Inclusion Options"
These options control which directories and files should be included in the report.
.Ip "\fB\-f, \-\-files\fR" 7
.IX Item "-f, --files"
Do not descend into sub-directories, only report files.
.Ip "\fB\-x, \-\-one-file-system\fR" 7
.IX Item "-x, --one-file-system"
Do not traverse file systems. This is similar to the \fB\-x\fR option for
du, allowing easy checking of an entire filesystem such as /.
.Ip "\fB\-cp, \-\-collapse-path=\fR\fI\s-1PATTERN\s0\fR" 7
.IX Item "-cp, --collapse-path=PATTERN"
Hide entries below paths that match \fI\s-1PATTERN\s0\fR. This allows you to
conceal the contents of certain directories in the report. You may
wish perhaps to show home directories in a report but not show their
content in which case you could use the option \f(CW\*(C`\-cp
\&'/home'\*(C'\fR.
.Ip "\fB\-ep, \-\-exclude-path\fR=\fI\s-1PATTERN\s0\fR" 7
.IX Item "-ep, --exclude-path=PATTERN"
Ignore paths that match \fI\s-1PATTERN\s0\fR. This works in a smilar manner to
\&\f(CW\*(C`\-cp\*(C'\fR above, except it excludes the directory from the scan itself.
.Ip "\fB\-cf, \-\-coalesce-files=\fR=\fIN[bkmg]\fR" 7
.IX Item "-cf, --coalesce-files==N[bkmg]"
Coalesces entries for files below the given size into one entry. This
is useful for reducing clutter in reports.
.SH "WEB REPORTS"
.IX Header "WEB REPORTS"
Since version 0.9, durep no longer directly generates html files for
its web reports. It now uses a cgi script that reads data from
save-files. The script will handle multiple save-files, potentially
from multiple hosts, so you can consolidate your reports into one
place. Copying save-files from other hosts is left as an exercise for
the reader.
.PP
It is necessary to collate the save-files before viewing them via the
cgi script. This process creates the file \f(CW\*(C`durep.cds\*(C'\fR which contains
metadata about all of the save-files. From this a summary page is
shown where you can choose which report you wish to view. The
collation must be done any time a save-file is added or overwritten.
.PP
The cgi-script has some configurable variables at the top. These tell
the script where to look for the css file and the graphic used for the
bar graphs. There are also options to set whether the modification
date, and/or the options used to create the save-file should be
shown. These are both set to 1 by default.
.PP
As always, you should take care when installing the cgi script. I've
done my best, but I make no guarantees about its security. It would
probably be unwise to allow this script to be accessed from the
internet at large.
.SH "EXAMPLES"
.IX Header "EXAMPLES"
.Ip "1." 3
\&\fBdurep \-td 2\fR
.Sp
This would print the directory tree starting from the current
directory to depth 2.
.Ip "2." 3
\&\fBdurep \-f /var/spool/mail\fR
.Sp
This might be useful for keeping a check on the mail directory. The
\&\f(CW\*(C`\-f\*(C'\fR switch tells durep to just scan files and not descend into
directories.
.Ip "3." 3
\&\fBdurep \-x \-cp \*(L"/(etc|usr/share)\*(R" \-ep \*(L"/var\*(R" \-sf /var/lib/durep/root.ds /\fR
.Sp
This more complicated version does the following. It scans the root
filesystem only, collapses the contents of any paths begining \fI/etc\fR
or \fI/usr/share\fR and skips the contents of the \fI/var\fR directory. It
saves the output of this report into the file
\&\fI/var/lib/durep/root.ds\fR. No text report is produced.
.Ip "4." 3
\&\fBdurep \-lf /var/lib/durep/root.ds \-hs 1m\fR
.Sp
This reads the save-file \fI/var/lib/durep/root.ds\fR and produces a text
report from it, hiding any files below 1 megabyte.
.Ip "5." 3
\&\fBdurep \-c /var/lib/durep\fR
.Sp
This collates any save-files in \fI/var/lib/durep\fR.
.SH "SEE ALSO"
.IX Header "SEE ALSO"
\&\fIdu\fR\|(1), \fIperl\fR\|(1)
.SH "AUTHOR"
.IX Header "AUTHOR"
Damian Kramer <psiren@hibernaculum.net>

41
root/usr/sbin/durep.daily Normal file
View File

@ -0,0 +1,41 @@
#!/bin/bash
# shall we run ?
status=$(/sbin/e-smith/db configuration getprop durep status || echo 'enabled')
if [[ "$status" == "disabled" ]]; then
exit
fi
# original folders to be accounted
/usr/local/bin/durep -q -x -sf /var/lib/durep/user.ds /home/e-smith/files/users
/usr/local/bin/durep -q -x -sf /var/lib/durep/ibays.ds /home/e-smith/files/ibays
# known folder from contribs and from base
folders=( "/home/e-smith/files/ezmlm" "/home/e-smith/files/shares" "/home/e-smith/db" "/opt/webshare")
# user added folder to stat
userfolders=$(/sbin/e-smith/db configuration getprop durep folders || echo '')
ufolders=(${userfolders//,/ })
folders=("${folders[@]}" "${ufolders[@]}")
for folder in "${folders[@]}"
do
name=` echo ${folder//\//_}`
#name=`basename $folder`
if [ -d "$folder" ]; then
/usr/local/bin/durep -q -x -sf /var/lib/durep/$name.ds $folder
else
if [ -f "/var/lib/durep/$name.ds" ];then
rm /var/lib/durep/$name.ds -f
fi
fi
done
# make the stats viewable
/usr/local/bin/durep -c /var/lib/durep/
chmod 644 /var/lib/durep/*
chown root:admin /etc/e-smith/web/panels/manager/html/durep/*.cgi
chmod 750 /etc/e-smith/web/panels/manager/html/durep/*.cgi
# remove ds file not renewd for more than 24 hours
find /var/lib/durep/ -type f -iname *.ds -mtime +"1" |xargs rm -f

View File

@ -0,0 +1,67 @@
package SrvMngr::Controller::Durep;
#----------------------------------------------------------------------
# heading : System
# description : Disk usage report
# navigation : 4000 390
# menu : A
#
# name : durep, method : get, url : /durep, ctlact : durep#main
#
# routes : end
#----------------------------------------------------------------------
use strict;
use warnings;
use Mojo::Base 'Mojolicious::Controller';
use Locale::gettext;
use SrvMngr::I18N;
use SrvMngr qw(theme_list init_session);
sub main {
my $c = shift;
$c->app->log->info($c->log_req);
my $modul = get_du( $c );
$c->stash( modul => $modul );
$c->render(template => 'durep');
}
sub get_du {
my ($c) = @_;
my $tx = $c->tx;
my $req = $tx->req;
# 3 env variables for durep.cgi
$ENV{'SCRIPT_NAME'} = 'durep';
$ENV{'REQUEST_METHOD'} = $req->method;
$ENV{'QUERY_STRING'} = $req->url->query->to_string;
my $res = `/etc/e-smith/web/panels/manager/html/durep/durep.cgi`;
$res =~ s|server-manager/durep|smanager/images|g;
my $step = 0; my $out;
my @lines = split /\n/, $res;
# remove except 'body'
foreach my $line (@lines) {
if ( $line =~ m|<body>| ) {
$step = 1;
} elsif ( $line =~ m|</body>| ) {
$step = 2;
} elsif ( $step == 1 ) {
$out .= $line;
}
}
return $out;
}
1;

View File

@ -0,0 +1 @@
'dur_FORM_TITLE' => 'Disk usage report',

View File

@ -0,0 +1,127 @@
/*
a:hover {
background-color: #DDDDDD;
}
body {
text-align: center;
background-color: #ffffff;
}
*/
div.tbar {
text-align: left;
width: 100%;
background-color: #EEEEEE;
border-top: solid 1px #DDDDDD;
border-bottom: solid 1px #DDDDDD;
}
div.bbar {
text-align: left;
width: 100%;
background-color: #EEEEEE;
border-top: solid 1px #DDDDDD;
border-bottom: solid 1px #DDDDDD;
}
div.bbar * {
font-size: 90%;
}
div.options {
text-align: left;
margin: 2em;
background-color: #EEEEEE;
border: solid 1px #DDDDDD;
}
.light {
background-color: #ffffff;
}
.mid {
background-color: #f6f6f6;
}
.dark {
background-color: #f0f0f0;
}
.tbar table {
width: 100%;
padding-left: 2pt;
font-weight: bold;
}
.bbar table {
width: 100%;
padding-left: 2pt;
}
table.list {
margin: 2em 0px;
border: solid 1px #CCCCCC;
margin-left: auto;
margin-right: auto;
}
table.list td {
text-align: left;
padding: 2px 5px;
}
table.list th {
text-align: left;
padding: 2px 5px;
text-align: left;
background-color: #DDDDDD;
}
table.report {
margin: 2em 0px;
border: solid 1px #CCCCCC;
text-align: left;
margin-left: auto;
margin-right: auto;
}
table.report td {
padding: 2px 5px;
}
table.report th {
padding: 2px 5px;
text-align: left;
background-color: #DDDDDD;
}
.graph {
padding: 0px;
background-color: #eeeeee;
width: 200px;
height: 15px;
}
th.right {
text-align: right;
}
td.right {
text-align: right;
}
span.dir {
font-weight: bold;
}
span.empty {
color: #006600;
font-weight: bold;
}
span.coalesced {
color: #880000;
font-weight: bold;
}

View File

@ -0,0 +1,24 @@
% layout 'default', title => 'Sme server 2 - Durep';
% content_for 'head_contrib' => begin
%= stylesheet '/css/durep.css'
%end
% content_for 'module' => begin
% if ($config->{debug} == 1) {
<p>
%= dumper $c->current_route
</p>
% }
<div id="central" class="module durep-panel">
% if ( stash 'error' ) {
<br><div class=sme-error>
%= $c->render_to_string(inline => stash 'error')
</div>
%}
%= $c->render_to_string(inline => $modul)
</div>
% end

0
root/var/lib/durep/.gitignore vendored Normal file
View File

0
root/var/www/.gitignore vendored Normal file
View File

151
smeserver-durep.spec Normal file
View File

@ -0,0 +1,151 @@
# $Id: smeserver-durep.spec,v 1.15 2024/03/01 15:05:04 brianr Exp $
# Authority: unnilennnium
# Name: JP Pialasse
%define name smeserver-durep
Name: %{name}
%define version 1.5.0
Version: %{version}
%define release 18
Release: %{release}%{?dist}
License: GPL
Source: %{name}-%{version}.tar.xz
BuildRoot: /var/tmp/%{name}-%{version}-buildroot
BuildRequires: e-smith-devtools
BuildArch: noarch
Group: Networking/Daemons
Summary: DUREP - Graphic Report for Disk Usage
Requires: perl(Data::Dumper)
Requires: perl(MLDBM) >= 1.21-4
Obsoletes: smeserver-durep-saco
Obsoletes: e-smith-durep
AutoReqProv: no
%changelog
* Sat Sep 07 2024 cvs2git.sh aka Brian Read <brianr@koozali.org> 1.5.0-18.sme
- Roll up patches and move to git repo [SME: 12338]
* Sat Sep 07 2024 BogusDateBot
- Eliminated rpmbuild "bogus date" warnings due to inconsistent weekday,
by assuming the date is correct and changing the weekday.
* Fri Mar 01 2024 Brian Read <brianr@koozali.org> 1.5.0-17.sme
- Edit SM2 Menu entry to conform to new arrangements [SME: 12493]
* Thu Mar 23 2023 Michel Begue <mab974@misouk.com> 1.5.0-16.sme
- fix typo in previous release [SME: 12342]
* Wed Mar 22 2023 Michel Begue <mab974@misouk.com> 1.5.0-15.sme
- allow access to bar.png image in SM2 [SME: 12342]
* Sat Jul 30 2022 Brian Read <brianr@bjsystems.co.uk> 1.5.0-14.sme
- Re-build and link to latest devtools [SME: 11997]
* Fri Jul 22 2022 Jean-Philippe Pialasse <tests@pialasse.com> 1.5.0-13.sme
- add to core backup [SME: 12007]
* Wed May 18 2022 Jean-Philippe Pialasse <tests@pialasse.com> 1.5.0-12.sme
- allow access to user with userpanel [SME: 11975]
* Sat Jan 08 2022 Michel Begue <mab974@misouk.com> 1.5.0-11.sme
- Re-build and link to latest devtools wrong localisation directory [SME: 11841]
* Fri Jan 07 2022 Brian Read <brianr@bjsystems.co.uk> 1.5.0-10.sme
- Add-class-to-div-for-AdminLTE [SME: 11835]
* Thu Jun 03 2021 Michel Begue <mab974@gmail.com> 1.5.0-9.sme
- first use with smeserver-manager [SME: 11618]
* Thu Mar 04 2021 Jean-Philipe Pialasse <tests@pialasse.com> 1.5.0-8.sme
- Re-build and link to latest devtools permissions of cgi inside spec file too
* Thu Mar 04 2021 Michel Begue <mab974@gmail.com> 1.5.0-7.sme
- Re-build and link to latest devtools permissions of cgi and data files
* Mon Feb 22 2021 Jean-Philipe Pialasse <tests@pialasse.com> 1.5.0-6.sme
- add smeserver-durep-update event [SME: 10893]
make up spec file
* Fri Oct 23 2020 Brian Read <brianr@bjsystems.co.uk> 1.5.0-5.sme
- Initial import to SME10 tree [SME: 10893]
- Add in link to wrapper in createlinks
* Sat Dec 28 2019 Jean-Philipe Pialasse <tests@pialasse.com> 1.5.0-4.sme
- output all mounted points with df on one line using Posix
* Sat Feb 10 2018 Jean-Philipe Pialasse <tests@pialasse.com> 1.5.0-3.sme
- add hability to stat more directories [SME: 10118]
- add status enabled or disabled
* Sat Aug 22 2015 stephane de Labrusse <stephdl@de-labrusse.fr> 1.5.0-2.sme
- Initial release to contribs9
* Sat Jun 21 2014 stephane de Labrusse <stephdl@de-labrusse.fr> 1.5.0-1.sme
- Initial release to sme9
* Thu Sep 13 2012 JP Pialasse <test@pialasse.com> 1.3.0-6.sme
- add Obsoletes smeserver-durep-saco e-smith-durep [SME 7108]
- TODO cleaning spec file post and filelist chmod
* Mon Sep 10 2012 JP Pialasse <test@pialasse.com> 1.3.0-5.sme
- Re-build and link to latest devtools do not copy files and filelist [SME 7098]
- patch df of plugged disk
* Sun Sep 09 2012 JP Pialasse <test@pialasse.com> 1.3.0-4.sme
- dependencies resolution
* Fri Aug 31 2012 JP Pialasse <test@pialasse.com> 1.3.0-3.sme
- build error fix : prep setup
* Wed Aug 15 2012 JP Pialasse <test@pialasse.com> 1.3.0-1.sme
- update from 1.03-02sn to comply with SME8 and SME7
- moved archives to /var/lib/durep
- moved web files to manager/html
- cleaned spec
%description
DUREP is a Report Generator that creates graphical Output for the "du" command
%prep
%setup
%build
perl createlinks
%install
/bin/rm -rf $RPM_BUILD_ROOT
(cd root; /usr/bin/find . -depth -print | /bin/cpio -dump $RPM_BUILD_ROOT)
/bin/rm -f %{name}-%{version}-filelist
/sbin/e-smith/genfilelist $RPM_BUILD_ROOT \
--file "/usr/local/bin/durep" 'attr(0755,root,root)' \
--file "/usr/sbin/durep.daily" 'attr(0755,root,root)' \
--file '/etc/e-smith/web/panels/manager/html/durep/durep.cgi' 'attr(0750,root,admin)' \
> %{name}-%{version}-filelist
%clean
/bin/rm -rf $RPM_BUILD_ROOT
%files -f %{name}-%{version}-filelist
%defattr(-,root,root)
%pre -p /bin/sh
%post -p /bin/sh
if (systemctl list-unit-files |grep smanager) then
echo "Smanager restart in spec file"
/sbin/e-smith/signal-event smanager-refresh;
fi
%preun -p /bin/sh
%postun -p /bin/sh
if [ $1 = 0 ] ; then
/bin/rm -f /usr/share/smanager/themes/default/images/bar.png
fi
true