ValidateFileCommon.cpp 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. #include <Os/ValidateFile.hpp>
  2. #include <Os/File.hpp>
  3. #include <Utils/Hash/Hash.hpp>
  4. #include <Os/FileSystem.hpp>
  5. namespace Os {
  6. File::Status computeHash(const char* fileName, Utils::HashBuffer &hashBuffer) {
  7. File::Status status;
  8. // Open file:
  9. File file;
  10. status = file.open(fileName, File::OPEN_READ);
  11. if( File::OP_OK != status ) {
  12. return status;
  13. }
  14. // Get the file size:
  15. FileSystem::Status fs_status;
  16. FwSizeType fileSize = 0;
  17. fs_status = FileSystem::getFileSize(fileName, fileSize); //!< gets the size of the file (in bytes) at location path
  18. // fileSize will be used as a NATIVE_INT_TYPE below and thus must cast cleanly to that type
  19. if( FileSystem::OP_OK != fs_status || static_cast<FwSizeType>(static_cast<NATIVE_INT_TYPE>(fileSize)) != fileSize) {
  20. return File::BAD_SIZE;
  21. }
  22. const NATIVE_INT_TYPE max_itr = static_cast<NATIVE_INT_TYPE>(fileSize/VFILE_HASH_CHUNK_SIZE + 1);
  23. // Read all data from file and update hash:
  24. Utils::Hash hash;
  25. hash.init();
  26. U8 buffer[VFILE_HASH_CHUNK_SIZE];
  27. NATIVE_INT_TYPE size = 0;
  28. NATIVE_INT_TYPE cnt = 0;
  29. while( cnt <= max_itr ) {
  30. // Read out chunk from file:
  31. size = sizeof(buffer);
  32. status = file.read(&buffer, size, false);
  33. if( File::OP_OK != status ) {
  34. return status;
  35. }
  36. // If end of file, break:
  37. if( size == 0 ) {
  38. break;
  39. }
  40. // Add chunk to hash calculation:
  41. hash.update(&buffer, size);
  42. cnt++;
  43. }
  44. file.close();
  45. // We should not have left the loop because of cnt > max_itr:
  46. FW_ASSERT(size == 0);
  47. FW_ASSERT(cnt <= max_itr);
  48. // Calculate hash:
  49. Utils::HashBuffer computedHashBuffer;
  50. hash.final(computedHashBuffer);
  51. hashBuffer = computedHashBuffer;
  52. return status;
  53. }
  54. File::Status readHash(const char* hashFileName, Utils::HashBuffer &hashBuffer) {
  55. File::Status status;
  56. // Open hash file:
  57. File hashFile;
  58. status = hashFile.open(hashFileName, File::OPEN_READ);
  59. if( File::OP_OK != status ) {
  60. return status;
  61. }
  62. // Read hash from checksum file:
  63. unsigned char savedHash[HASH_DIGEST_LENGTH];
  64. NATIVE_INT_TYPE size = hashBuffer.getBuffCapacity();
  65. status = hashFile.read(&savedHash[0], size);
  66. if( File::OP_OK != status ) {
  67. return status;
  68. }
  69. if( size != static_cast<NATIVE_INT_TYPE>(hashBuffer.getBuffCapacity()) ) {
  70. return File::BAD_SIZE;
  71. }
  72. hashFile.close();
  73. // Return the hash buffer:
  74. Utils::HashBuffer savedHashBuffer(savedHash, size);
  75. hashBuffer = savedHashBuffer;
  76. return status;
  77. }
  78. File::Status writeHash(const char* hashFileName, Utils::HashBuffer hashBuffer) {
  79. // Open hash file:
  80. File hashFile;
  81. File::Status status;
  82. status = hashFile.open(hashFileName, File::OPEN_WRITE);
  83. if( File::OP_OK != status ) {
  84. return status;
  85. }
  86. // Write out the hash
  87. NATIVE_INT_TYPE size = hashBuffer.getBuffLength();
  88. status = hashFile.write(hashBuffer.getBuffAddr(), size, false);
  89. if( File::OP_OK != status ) {
  90. return status;
  91. }
  92. if( size != static_cast<NATIVE_INT_TYPE>(hashBuffer.getBuffLength()) ) {
  93. return File::BAD_SIZE;
  94. }
  95. hashFile.close();
  96. return status;
  97. }
  98. // Enum and function for translating from a status to a validation status:
  99. typedef enum {
  100. FileType,
  101. HashFileType
  102. } StatusFileType;
  103. ValidateFile::Status translateStatus(File::Status status, StatusFileType type) {
  104. switch (type) {
  105. case FileType:
  106. switch (status) {
  107. case File::OP_OK:
  108. return ValidateFile::VALIDATION_OK;
  109. case File::DOESNT_EXIST:
  110. return ValidateFile::FILE_DOESNT_EXIST;
  111. case File::NO_SPACE:
  112. return ValidateFile::NO_SPACE;
  113. case File::NO_PERMISSION:
  114. return ValidateFile::FILE_NO_PERMISSION;
  115. case File::BAD_SIZE:
  116. return ValidateFile::FILE_BAD_SIZE;
  117. case File::NOT_OPENED:
  118. return ValidateFile::OTHER_ERROR;
  119. case File::OTHER_ERROR:
  120. return ValidateFile::OTHER_ERROR;
  121. default:
  122. FW_ASSERT(0, status);
  123. }
  124. break;
  125. case HashFileType:
  126. switch (status) {
  127. case File::OP_OK:
  128. return ValidateFile::VALIDATION_OK;
  129. case File::DOESNT_EXIST:
  130. return ValidateFile::VALIDATION_FILE_DOESNT_EXIST;
  131. case File::NO_SPACE:
  132. return ValidateFile::NO_SPACE;
  133. case File::NO_PERMISSION:
  134. return ValidateFile::VALIDATION_FILE_NO_PERMISSION;
  135. case File::BAD_SIZE:
  136. return ValidateFile::VALIDATION_FILE_BAD_SIZE;
  137. case File::NOT_OPENED:
  138. return ValidateFile::OTHER_ERROR;
  139. case File::OTHER_ERROR:
  140. return ValidateFile::OTHER_ERROR;
  141. default:
  142. FW_ASSERT(0, status);
  143. }
  144. break;
  145. default:
  146. FW_ASSERT(0, type);
  147. }
  148. return ValidateFile::OTHER_ERROR;
  149. }
  150. ValidateFile::Status ValidateFile::validate(const char* fileName, const char* hashFileName) {
  151. Utils::HashBuffer hashBuffer; // pass by reference - final value is unused
  152. return validate(fileName, hashFileName, hashBuffer);
  153. }
  154. ValidateFile::Status ValidateFile::validate(const char* fileName, const char* hashFileName, Utils::HashBuffer &hashBuffer) {
  155. File::Status status;
  156. // Read the hash file:
  157. Utils::HashBuffer savedHash;
  158. status = readHash(hashFileName, savedHash);
  159. if( File::OP_OK != status ) {
  160. return translateStatus(status, HashFileType);
  161. }
  162. // Compute the file's hash:
  163. Utils::HashBuffer computedHash;
  164. status = computeHash(fileName, computedHash);
  165. if( File::OP_OK != status ) {
  166. return translateStatus(status, FileType);
  167. }
  168. // Compare hashes and return:
  169. if( savedHash != computedHash ){
  170. return ValidateFile::VALIDATION_FAIL;
  171. }
  172. hashBuffer = savedHash;
  173. return ValidateFile::VALIDATION_OK;
  174. }
  175. ValidateFile::Status ValidateFile::createValidation(const char* fileName, const char* hashFileName, Utils::HashBuffer &hashBuffer) {
  176. File::Status status;
  177. // Compute the file's hash:
  178. status = computeHash(fileName, hashBuffer);
  179. if( File::OP_OK != status ) {
  180. return translateStatus(status, FileType);
  181. }
  182. status = writeHash(hashFileName, hashBuffer);
  183. if( File::OP_OK != status ) {
  184. return translateStatus(status, HashFileType);
  185. }
  186. return ValidateFile::VALIDATION_OK;
  187. }
  188. ValidateFile::Status ValidateFile::createValidation(const char* fileName, const char* hashFileName) {
  189. Utils::HashBuffer hashBuffer; // pass by reference - final value is unused
  190. return createValidation(fileName, hashFileName, hashBuffer);
  191. }
  192. }