Store.pm 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. package ZSS::Store;
  2. use strict;
  3. use warnings;
  4. use Digest::MD5 qw (md5_hex);
  5. use File::Util qw(escape_filename);
  6. use File::Path qw(make_path);
  7. sub new {
  8. my $class = shift;
  9. # TODO: read from config
  10. my $self = {storagepath => shift};
  11. bless $self, $class;
  12. }
  13. sub get_path {
  14. my $self = shift;
  15. my $key = shift;
  16. my $dirname = md5_hex($key);
  17. my $dir = $self->{storagepath} . substr($dirname, 0, 1) . "/" . $dirname ."/";
  18. return $dir;
  19. }
  20. sub get_filename {
  21. my $self = shift;
  22. my $key = shift;
  23. return escape_filename($key, '_');
  24. }
  25. sub get_filepath {
  26. my $self = shift;
  27. my $key = shift;
  28. return $self->get_path($key) . $self->get_filename($key);
  29. }
  30. sub store_file {
  31. my $self = shift;
  32. my $key = shift;
  33. my $data = shift;
  34. my $meta = shift;
  35. my $dir = $self->get_path($key);
  36. my $file = $self->get_filename($key);
  37. make_path($dir);
  38. # Write data to temp file and rename to the desired name
  39. # This only changes this file and not other hardlinks
  40. open(my $fh, '>:raw', $dir.$file.".temp");
  41. print $fh ($data);
  42. close($fh);
  43. rename($dir.$file.".temp", $dir.$file);
  44. if ($meta) {
  45. open($fh, '>:raw', $dir.$file.".meta.temp");
  46. print $fh ($meta);
  47. close($fh);
  48. rename($dir.$file.".meta.temp", $dir.$file.".meta");
  49. }
  50. }
  51. sub check_exists{
  52. my $self = shift;
  53. my $key = shift;
  54. my $path = $self->get_filepath($key);
  55. unless (-e $path){
  56. return 0;
  57. }
  58. return 1;
  59. }
  60. sub retrieve_file {
  61. my $self = shift;
  62. my $key = shift;
  63. unless($self->check_exists($key)){
  64. return undef;
  65. }
  66. my $path = $self->get_filepath($key);
  67. open(my $fh, '<:raw', $path);
  68. return $fh;
  69. }
  70. sub retrieve_filemeta {
  71. my $self = shift;
  72. my $key = shift;
  73. unless($self->check_exists($key)){
  74. return undef;
  75. }
  76. my $metafile = $self->get_filepath($key) . ".meta";
  77. # check if metadata is present
  78. unless (-e $metafile) {
  79. return undef;
  80. }
  81. # limt size of metadata to 8kB
  82. my $size = -s $metafile;
  83. unless ($size <= 8192) {
  84. return undef;
  85. }
  86. my $meta;
  87. open(my $fh, '<:raw', $metafile);
  88. read ($fh, $meta, $size);
  89. return $meta;
  90. }
  91. sub get_size{
  92. my $self = shift;
  93. my $key = shift;
  94. my $path = $self->get_filepath($key);
  95. unless (-e $path) {
  96. return 0;
  97. }
  98. my $size = -s $path;
  99. return $size;
  100. }
  101. sub link_files{
  102. my $self = shift;
  103. my $source_key = shift;
  104. my $destination_key = shift;
  105. my $source_path = $self->get_filepath($source_key);
  106. my $destination_dir = $self->get_path($destination_key);
  107. my $destination_path = $self->get_filepath($destination_key);
  108. make_path($destination_dir);
  109. link($source_path.".meta", $destination_path.".meta");
  110. return link($source_path, $destination_path);
  111. }
  112. sub delete_file{
  113. my $self = shift;
  114. my $key = shift;
  115. my $dir = $self->get_path($key);
  116. my $file = $self->get_filename($key);
  117. # Remove metadata
  118. unlink($dir.$file.".meta");
  119. unless (unlink($dir.$file)) {
  120. return 1;
  121. }
  122. return rmdir($dir);
  123. }
  124. 1;