file.rb 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. # Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
  2. class Store::Provider::File
  3. # write file to fs
  4. def self.add(data, sha)
  5. # install file
  6. location = get_location(sha)
  7. permission = '600'
  8. if !File.exist?(location)
  9. Rails.logger.debug { "storge write '#{location}' (#{permission})" }
  10. file = File.new(location, 'wb')
  11. file.write(data)
  12. file.close
  13. end
  14. File.chmod(permission.to_i(8), location)
  15. # check sha
  16. local_sha = Digest::SHA256.hexdigest(get(sha))
  17. if sha != local_sha
  18. raise "ERROR: Corrupt file in fs #{location}, sha should be #{sha} but is #{local_sha}"
  19. end
  20. true
  21. end
  22. # read file from fs
  23. def self.get(sha)
  24. location = get_location(sha)
  25. Rails.logger.debug { "read from fs #{location}" }
  26. if !File.exist?(location)
  27. raise "ERROR: No such file #{location}"
  28. end
  29. data = File.open(location, 'rb')
  30. content = data.read
  31. # check sha
  32. local_sha = Digest::SHA256.hexdigest(content)
  33. if local_sha != sha
  34. raise "ERROR: Corrupt file in fs #{location}, sha should be #{sha} but is #{local_sha}"
  35. end
  36. content
  37. end
  38. # unlink file from fs
  39. def self.delete(sha)
  40. location = get_location(sha)
  41. if File.exist?(location)
  42. Rails.logger.info "storge remove '#{location}'"
  43. File.delete(location)
  44. end
  45. # check if dir need to be removed
  46. locations = location.split('/')
  47. (0..locations.count).reverse_each do |count|
  48. local_location = locations[0, count].join('/')
  49. break if local_location.match?(%r{storage/fs/{0,4}$})
  50. break if Dir["#{local_location}/*"].present?
  51. FileUtils.rmdir(local_location)
  52. end
  53. end
  54. # generate file location
  55. def self.get_location(sha)
  56. # generate directory
  57. base = Rails.root.join('storage', 'fs').to_s
  58. parts = []
  59. length1 = 4
  60. length2 = 5
  61. length3 = 7
  62. last_position = 0
  63. (0..1).each do |_count|
  64. end_position = last_position + length1
  65. parts.push sha[last_position, length1]
  66. last_position = end_position
  67. end
  68. (0..1).each do |_count|
  69. end_position = last_position + length2
  70. parts.push sha[last_position, length2]
  71. last_position = end_position
  72. end
  73. (0..1).each do |_count|
  74. end_position = last_position + length3
  75. parts.push sha[last_position, length3]
  76. last_position = end_position
  77. end
  78. path = parts[ 0..6 ].join('/') + '/'
  79. file = sha[last_position, sha.length]
  80. location = "#{base}/#{path}"
  81. # create directory if not exists
  82. if !File.exist?(location)
  83. FileUtils.mkdir_p(location)
  84. end
  85. full_path = location += file
  86. full_path.gsub('//', '/')
  87. end
  88. end