4 |
use threads::shared; |
use threads::shared; |
5 |
|
|
6 |
use Fuse; |
use Fuse; |
|
use IO::File; |
|
7 |
use POSIX qw(ENOENT ENOSYS EEXIST EPERM O_RDONLY O_RDWR O_APPEND O_CREAT); |
use POSIX qw(ENOENT ENOSYS EEXIST EPERM O_RDONLY O_RDWR O_APPEND O_CREAT); |
8 |
use Fcntl qw(S_ISBLK S_ISCHR S_ISFIFO SEEK_SET); |
use Fcntl qw(S_ISBLK S_ISCHR S_ISFIFO SEEK_SET); |
9 |
require 'syscall.ph'; # for SYS_mknod and SYS_lchown |
require 'syscall.ph'; # for SYS_mknod and SYS_lchown |
23 |
my $skip_extensions_regex = qr/\.(?:sw[a-z]|gif|png|jpeg|jpg|avi|rar|zip|bz2|gz|tgz|avi|mpeg|mpg|tmp|temp)$/i; |
my $skip_extensions_regex = qr/\.(?:sw[a-z]|gif|png|jpeg|jpg|avi|rar|zip|bz2|gz|tgz|avi|mpeg|mpg|tmp|temp)$/i; |
24 |
|
|
25 |
# don't compress files smaller than this |
# don't compress files smaller than this |
26 |
my $min_compress_size = 256; |
my $min_compress_size = 512; |
27 |
|
|
28 |
foreach my $dir ( keys %$mount ) { |
foreach my $dir ( keys %$mount ) { |
29 |
if ( ! -e $mount->{$dir} ) { |
if ( ! -e $mount->{$dir} ) { |
70 |
|
|
71 |
sub unlink_all { |
sub unlink_all { |
72 |
my $file = shift; |
my $file = shift; |
73 |
foreach my $dir ( keys %$mount ) { |
warn "# unlink_all( $file )\n"; |
74 |
my $path = $mount->{$dir} . '/' . $file; |
|
75 |
|
my $path = fixup( $file ); |
76 |
map { |
unlink $path || return 0; |
77 |
my $path = $_; |
|
78 |
if ( -e $path ) { |
my $tmp = $mount->{tmp} . '/' . $file; |
79 |
if ( unlink $path ) { |
unlink $tmp if ( -e $tmp ); |
80 |
warn "## unlink $path\n" if $debug; |
|
|
} else { |
|
|
warn "can't unlink $path: $!\n"; |
|
|
return 0; |
|
|
} |
|
|
} |
|
|
} [ $path, $path . '.gz' ]; |
|
|
} |
|
81 |
delete( $pending->{$file} ); |
delete( $pending->{$file} ); |
82 |
return 1; |
return 1; |
83 |
} |
} |
118 |
chmod $mode, $d_path || warn "chmod( $mode $d_path ) failed: $!\n"; |
chmod $mode, $d_path || warn "chmod( $mode $d_path ) failed: $!\n"; |
119 |
chown $uid,$gid,$d_path || warn "chown( $uid $gid $d_path ) failed: $!\n"; |
chown $uid,$gid,$d_path || warn "chown( $uid $gid $d_path ) failed: $!\n"; |
120 |
utime $atime,$mtime,$d_path || warn "utime( $atime $mtime $d_path ) failed: $!\n"; |
utime $atime,$mtime,$d_path || warn "utime( $atime $mtime $d_path ) failed: $!\n"; |
121 |
|
|
122 |
|
undef $d; |
123 |
|
undef $s; |
124 |
} |
} |
125 |
|
|
126 |
sub x_open { |
sub x_open { |
127 |
my ($file) = shift; |
my ($file) = shift; |
128 |
my ($mode) = shift; |
my ($mode) = shift; |
129 |
$pending->{$file}->{open}++; |
$pending->{$file}->{open}++; |
130 |
warn "# open( $file, $mode ) pending: ", $pending->{$file}->{open}, "\n"; |
|
131 |
|
my $mode_desc = { |
132 |
|
rdonly => $mode && O_RDONLY, |
133 |
|
rdwr => $mode && O_RDWR, |
134 |
|
append => $mode && O_APPEND, |
135 |
|
create => $mode && O_CREAT, |
136 |
|
}; |
137 |
|
warn "# open( $file, $mode ) pending: ", $pending->{$file}->{open}, " mode: ", dump( $mode_desc ),"\n"; |
138 |
my $fh; |
my $fh; |
139 |
if ( $pending->{$file}->{open} == 1 ) { |
|
140 |
my $path = fixup($file); |
my $path = fixup($file); |
141 |
my $tmp = $mount->{tmp} . '/' . $file; |
my $tmp = $mount->{tmp} . '/' . $file; |
142 |
warn ">>> open abs path: $path\n"; |
if ( -e $tmp ) { |
143 |
if ( -e $tmp ) { |
$path = $tmp; |
144 |
$path = $tmp; |
} elsif ( $path =~ m/\.gz$/ ) { |
145 |
} elsif ( $path =~ m/\.gz$/ ) { |
my $dest_path = $tmp; |
146 |
my $dest_path = $tmp; |
$dest_path =~ s!/[^/]+$!!; #!vim-fix |
147 |
$dest_path =~ s!/[^/]+$!!; #!vim-fix |
mkpath $dest_path unless -e $dest_path; |
148 |
mkpath $dest_path unless -e $dest_path; |
file_copy( '<:gzip', $path, '>', $tmp ); |
149 |
file_copy( '<:gzip', $path, '>', $tmp ); |
$path = $tmp; |
150 |
$path = $tmp; |
} |
151 |
} |
warn ">>> open abs path: $path ", -s $path, " bytes\n"; |
152 |
return -$! unless sysopen($fh , $path, $mode); |
return -$! unless sysopen($fh , $path, $mode); |
153 |
$pending->{$file}->{fh} = $fh; |
|
154 |
$pending->{$file}->{path} = $path; |
$pending->{$file}->{fh} = $fh; |
155 |
} elsif ( ! defined( $pending->{$file}->{fh} ) ) { |
$pending->{$file}->{path} = $path; |
156 |
confess "can't find fh for $file ", dump($pending); |
$pending->{$file}->{mode} = { |
157 |
|
rdonly => $mode && O_RDONLY, |
158 |
|
rdwr => $mode && O_RDWR, |
159 |
|
append => $mode && O_APPEND, |
160 |
|
create => $mode && O_CREAT, |
161 |
}; |
}; |
162 |
return 0; |
return 0; |
163 |
} |
} |
256 |
# cleanup old compressed copy |
# cleanup old compressed copy |
257 |
if ( $dest =~ /\.gz$/ ) { |
if ( $dest =~ /\.gz$/ ) { |
258 |
warn "## remove old $dest\n"; |
warn "## remove old $dest\n"; |
259 |
unlink_all( $file ) || confess "can't remove $dest: $!"; |
unlink $dest || confess "can't remove $dest: $!"; |
260 |
$dest =~ s/\.gz$//; |
$dest =~ s/\.gz$//; |
261 |
} |
} |
262 |
|
|
273 |
file_copy( '<', $path, '>:gzip', $dest . '.gz' ); |
file_copy( '<', $path, '>:gzip', $dest . '.gz' ); |
274 |
|
|
275 |
# FIXME add timeout to remove uncompressed version? |
# FIXME add timeout to remove uncompressed version? |
276 |
unlink_all( $file ) || warn "can't remove $path: $!"; |
unlink $path || warn "can't remove $path: $!"; |
277 |
} |
} |
278 |
} else { |
} else { |
279 |
warn "release $file, but still used ", $pending->{$file}->{open} , " times, delaying compression\n"; |
warn "release $file, but still used ", $pending->{$file}->{open} , " times, delaying compression\n"; |