file.rb 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  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. base = "#{Rails.root}/storage/fs"
  47. locations = location.split('/')
  48. (0..locations.count).reverse_each { |count|
  49. local_location = locations[0, count].join('/')
  50. break if local_location =~ %r{storage/fs/{0,4}$}
  51. break if !Dir["#{local_location}/*"].empty?
  52. FileUtils.rmdir(local_location)
  53. }
  54. end
  55. # generate file location
  56. def self.get_location(sha)
  57. # generate directory
  58. base = "#{Rails.root}/storage/fs/"
  59. parts = []
  60. length1 = 4
  61. length2 = 5
  62. length3 = 7
  63. last_position = 0
  64. (0..1).each { |_count|
  65. end_position = last_position + length1
  66. parts.push sha[last_position, length1]
  67. last_position = end_position
  68. }
  69. (0..1).each { |_count|
  70. end_position = last_position + length2
  71. parts.push sha[last_position, length2]
  72. last_position = end_position
  73. }
  74. (0..1).each { |_count|
  75. end_position = last_position + length3
  76. parts.push sha[last_position, length3]
  77. last_position = end_position
  78. }
  79. path = parts[ 0..6 ].join('/') + '/'
  80. file = sha[last_position, sha.length]
  81. location = "#{base}/#{path}"
  82. # create directory if not exists
  83. if !File.exist?(location)
  84. FileUtils.mkdir_p(location)
  85. end
  86. full_path = location += file
  87. full_path.gsub('//', '/')
  88. end
  89. end