+sub file_size {
+ my ( $self, $user, $path ) = @_;
+ $user = $self->user_info($user) unless ref $user eq 'HASH';
+
+ my $full_path = "$user->{dir}/$path";
+ my $size = -s $full_path;
+ warn "# file_size $full_path = $size bytes\n";
+ return $size;
+}
+
+sub list_files {
+ my ( $self, $user, $path ) = @_;
+
+ $user =~ s{/+$}{} && warn "cleanup list_files arg [$user]";
+
+ $user = $self->user_info($user) unless ref $user eq 'HASH';
+
+ die "no dir for ",dump($user) unless exists $user->{dir};
+
+ my $files = $user->{dir} . '/.meta/files';
+ $self->mkbasepath( $files, { uid => $user->{uid} } );
+ if ( -e $files && -s $files > 0 && -e "$files.usage") {
+ local $/ = undef;
+ open(my $fh, '<', $files);
+ my $list = <$fh>;
+ close($fh);
+ warn "# list_files $user->{login} from cache ", length($list), " bytes\n";
+ return $list;
+ }
+
+ my $dir = $user->{dir};
+ open(my $pipe, '-|', qq|find -L $dir -printf "%y %s %p\n"|);
+ open(my $fh, '>', "$files.new");
+ my $total_usage = 0;
+ my $list_txt;
+ while(<$pipe>) {
+ chomp;
+ my ( $type, $size, $name ) = split(/\s/, $_, 3);
+ $name =~ s{$dir}{./};
+ $name =~ s{//+}{/}g;
+ my $line = "$type $size $name\n";
+ print $fh $line;
+ $list_txt .= $line;
+ $total_usage += $size;
+ }
+ close($pipe);
+ close($fh);
+ rename "$files.new", $files;
+
+ open(my $usage, '>', "$files.usage.new");
+ print $usage $total_usage;
+ close($usage);
+ rename "$files.usage.new", "$files.usage";
+
+ warn "# list_files $dir usage: $total_usage\n";
+
+ return $list_txt;
+}
+
+sub refresh_file_list {
+ my ( $self, $user ) = @_;
+ $user = $self->user_info($user) unless ref $user eq 'HASH';
+ my $full_path = "$user->{dir}/.meta/files";
+ if ( -e $full_path ) {
+ warn "## refresh_file_list $full_path";
+ unlink $full_path || warn "unlink $full_path: $!";
+ } else {
+ warn "## refresh_file_list $full_path missing";
+ }