1 # Functions for getting usage
7 $usage_tree_file = "$module_config_directory/tree";
8 $heiropen_file = "$module_config_directory/heiropen";
9 $cron_cmd = "$module_config_directory/usage.pl";
11 # build_root_usage_tree(&dirs)
12 # Returns a usage tree from / containing all the specified directories
13 sub build_root_usage_tree
15 local $root = { 'dir' => '/',
18 foreach my $dir (@{$_[0]}) {
19 # No need to do a directory that has already been done by a parent
20 local $already = &find_in_tree($root, $dir);
21 next if ($already && $dir ne "/");
23 local $tree = &build_usage_tree($dir);
28 # Insert into root at correct location
30 $tree->{'dir'} =~ /^(.*)\/(.*)$/;
31 local $pdir = $1 || "/";
33 local $par = &find_in_tree($root, $pdir);
35 # Found a parent .. link to it
36 push(@{$par->{'subs'}}, $tree);
37 $tree->{'parent'} = $parent;
39 # Increase the totals for all parents
41 $par->{'total'} += $tree->{'total'};
42 $par = $par->{'parent'};
47 # Need to make up a parent
48 $par = { 'dir' => $pdir, 'subs' => [ $tree ],
49 'total' => $tree->{'total'},
51 $tree->{'parent'} = $par;
60 # build_usage_tree(dir)
61 # Given a base directory, returns a structure containing details about it and
66 local ($total, $files) = (0, 0);
68 local @files = readdir(DIR);
70 local $rv = { 'dir' => $dir, 'subs' => [ ] };
71 local @pst = stat($dir);
73 local $skip = &get_skip_dirs();
74 foreach my $f (@files) {
75 next if ($f eq "." || $f eq "..");
76 local $path = $dir eq "/" ? "/$f" : "$dir/$f";
77 next if ($skip->{$path});
78 local @st = lstat($path);
79 if ($config{'bsize'}) {
80 $total += $st[12]*$config{'bsize'};
81 $files += $st[12]*$config{'bsize'};
87 if ($config{'xdev'} && $st[0] != $pst[0]) {
88 next; # Don't go to another filesystem
91 # A directory .. recurse into it
92 local $subdir = &build_usage_tree($path, $rv);
93 $subdir->{'parent'} = $rv;
94 $total += $subdir->{'total'};
95 push(@{$rv->{'subs'}}, $subdir);
98 $rv->{'total'} = $total;
99 $rv->{'files'} = $files;
106 local (%tree, %pmap);
107 &read_file($usage_tree_file, \%tree) || return undef;
108 foreach my $k (keys %tree) {
109 if ($k ne "/" && $k =~ /^(.*)\/(.*)$/) {
110 local $dir = $1 || "/";
112 push(@{$pmap{$dir}}, $k);
115 return &hash_to_tree($tree{'root'}, \%tree, \%pmap);
118 # hash_to_tree(dir, &hash, &parentmap)
121 local ($dir, $hash, $pmap) = @_;
122 local $rv = { 'dir' => $dir, 'subs' => [ ] };
123 ($rv->{'total'}, $rv->{'files'}) = split(/ /, $hash->{$dir});
124 foreach my $subdir (@{$pmap->{$dir}}) {
125 local $substr = &hash_to_tree($subdir, $hash, $pmap);
126 $substr->{'parent'} = $rv;
127 push(@{$rv->{'subs'}}, $substr);
132 # save_usage_tree(&tree)
137 &tree_to_hash($dir, \%tree);
138 $tree{'root'} = $dir->{'dir'};
139 &write_file($usage_tree_file, \%tree);
142 # tree_to_hash(&dir, &hash)
143 # Adds to the hash entries for some tree node and sub-nodes
146 local ($dir, $hash) = @_;
147 $hash->{$dir->{'dir'}} = $dir->{'total'}." ".$dir->{'files'};
148 foreach my $subdir (@{$dir->{'subs'}}) {
149 &tree_to_hash($subdir, $hash);
153 # find_in_tree(&tree, dir)
154 # Returns the node for some directory, or undef
157 local ($tree, $dir) = @_;
158 return $tree if ($tree->{'dir'} eq $dir);
159 if ($tree->{'dir'} eq "/" ||
160 $dir =~ /^$tree->{'dir'}\//) {
161 foreach my $subdir (@{$tree->{'subs'}}) {
162 local $found = &find_in_tree($subdir, $dir);
163 return $found if ($found);
170 # Returns an array of open categories
173 open(HEIROPEN, $heiropen_file);
174 local @heiropen = <HEIROPEN>;
180 # save_heiropen(&heir)
183 &open_tempfile(HEIR, ">$heiropen_file");
184 foreach $h (@{$_[0]}) {
185 &print_tempfile(HEIR, $h,"\n");
187 &close_tempfile(HEIR);
192 local @jobs = &cron::list_cron_jobs();
193 local ($job) = grep { $_->{'user'} eq 'root' &&
194 $_->{'command'} eq $cron_cmd } @jobs;
199 # Returns a hash reference of directories to skip, based on the skip list
204 %skip_cache = map { $_, 1 } split(/\t+/, $config{'skip'});
205 if (&foreign_check("mount")) {
206 &foreign_require("mount", "mount-lib.pl");
207 local %fsskip = map { $_, 1 } split(/\s+/, $config{'fs'});
208 foreach my $m (&mount::list_mounted()) {
209 if ($fsskip{$m->[2]}) {
210 $skip_cache{$m->[0]} = 1;