mirror of
https://github.com/gfacciol/zotero_dataserver-docker.git
synced 2021-05-12 18:32:26 +03:00
165 lines
2.9 KiB
Perl
165 lines
2.9 KiB
Perl
package ZSS::Store;
|
|
|
|
use strict;
|
|
use warnings;
|
|
|
|
use Digest::MD5 qw (md5_hex);
|
|
use File::Util qw(escape_filename);
|
|
use File::Path qw(make_path);
|
|
|
|
sub new {
|
|
my $class = shift;
|
|
|
|
# TODO: read from config
|
|
my $self = {storagepath => shift};
|
|
|
|
bless $self, $class;
|
|
}
|
|
|
|
sub get_path {
|
|
my $self = shift;
|
|
my $key = shift;
|
|
|
|
my $dirname = md5_hex($key);
|
|
|
|
my $dir = $self->{storagepath} . substr($dirname, 0, 1) . "/" . $dirname ."/";
|
|
|
|
return $dir;
|
|
}
|
|
|
|
sub get_filename {
|
|
my $self = shift;
|
|
my $key = shift;
|
|
|
|
return escape_filename($key, '_');
|
|
}
|
|
|
|
sub get_filepath {
|
|
my $self = shift;
|
|
my $key = shift;
|
|
|
|
return $self->get_path($key) . $self->get_filename($key);
|
|
}
|
|
|
|
sub store_file {
|
|
my $self = shift;
|
|
my $key = shift;
|
|
my $data = shift;
|
|
my $meta = shift;
|
|
|
|
my $dir = $self->get_path($key);
|
|
my $file = $self->get_filename($key);
|
|
|
|
make_path($dir);
|
|
|
|
# Write data to temp file and rename to the desired name
|
|
# This only changes this file and not other hardlinks
|
|
open(my $fh, '>:raw', $dir.$file.".temp");
|
|
print $fh ($data);
|
|
close($fh);
|
|
rename($dir.$file.".temp", $dir.$file);
|
|
|
|
if ($meta) {
|
|
open($fh, '>:raw', $dir.$file.".meta.temp");
|
|
print $fh ($meta);
|
|
close($fh);
|
|
rename($dir.$file.".meta.temp", $dir.$file.".meta");
|
|
}
|
|
}
|
|
|
|
sub check_exists{
|
|
my $self = shift;
|
|
my $key = shift;
|
|
|
|
my $path = $self->get_filepath($key);
|
|
unless (-e $path){
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
sub retrieve_file {
|
|
my $self = shift;
|
|
my $key = shift;
|
|
|
|
unless($self->check_exists($key)){
|
|
return undef;
|
|
}
|
|
my $path = $self->get_filepath($key);
|
|
open(my $fh, '<:raw', $path);
|
|
return $fh;
|
|
}
|
|
|
|
sub retrieve_filemeta {
|
|
my $self = shift;
|
|
my $key = shift;
|
|
|
|
unless($self->check_exists($key)){
|
|
return undef;
|
|
}
|
|
my $metafile = $self->get_filepath($key) . ".meta";
|
|
|
|
# check if metadata is present
|
|
unless (-e $metafile) {
|
|
return undef;
|
|
}
|
|
|
|
# limt size of metadata to 8kB
|
|
my $size = -s $metafile;
|
|
unless ($size <= 8192) {
|
|
return undef;
|
|
}
|
|
|
|
my $meta;
|
|
open(my $fh, '<:raw', $metafile);
|
|
read ($fh, $meta, $size);
|
|
return $meta;
|
|
}
|
|
|
|
sub get_size{
|
|
my $self = shift;
|
|
my $key = shift;
|
|
|
|
my $path = $self->get_filepath($key);
|
|
|
|
unless (-e $path) {
|
|
return 0;
|
|
}
|
|
my $size = -s $path;
|
|
return $size;
|
|
}
|
|
|
|
sub link_files{
|
|
my $self = shift;
|
|
my $source_key = shift;
|
|
my $destination_key = shift;
|
|
|
|
my $source_path = $self->get_filepath($source_key);
|
|
my $destination_dir = $self->get_path($destination_key);
|
|
my $destination_path = $self->get_filepath($destination_key);
|
|
|
|
make_path($destination_dir);
|
|
|
|
link($source_path.".meta", $destination_path.".meta");
|
|
|
|
return link($source_path, $destination_path);
|
|
}
|
|
|
|
sub delete_file{
|
|
my $self = shift;
|
|
my $key = shift;
|
|
|
|
my $dir = $self->get_path($key);
|
|
my $file = $self->get_filename($key);
|
|
|
|
# Remove metadata
|
|
unlink($dir.$file.".meta");
|
|
|
|
unless (unlink($dir.$file)) {
|
|
return 1;
|
|
}
|
|
return rmdir($dir);
|
|
}
|
|
|
|
1;
|