file_for_patch.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461
  1. //file_for_patch.c
  2. // patch demo file tool
  3. //
  4. /*
  5. This is the HDiffPatch copyright.
  6. Copyright (c) 2012-2019 HouSisong All Rights Reserved.
  7. Permission is hereby granted, free of charge, to any person
  8. obtaining a copy of this software and associated documentation
  9. files (the "Software"), to deal in the Software without
  10. restriction, including without limitation the rights to use,
  11. copy, modify, merge, publish, distribute, sublicense, and/or sell
  12. copies of the Software, and to permit persons to whom the
  13. Software is furnished to do so, subject to the following
  14. conditions:
  15. The above copyright notice and this permission notice shall be
  16. included in all copies of the Software.
  17. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  18. EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  19. OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  20. NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  21. HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  22. WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  23. FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  24. OTHER DEALINGS IN THE SOFTWARE.
  25. */
  26. #define _LARGEFILE64_SOURCE
  27. #define _FILE_OFFSET_BITS 64
  28. #include "mmcsd_core.h"
  29. #include "file_for_patch.h"
  30. /*
  31. #ifdef _MSC_VER
  32. # include <io.h> //_chsize_s
  33. #endif
  34. */
  35. const char *hpatch_NofsFileName[] =
  36. {
  37. "ldr",
  38. "app",
  39. "animation",
  40. "resource",
  41. };
  42. #ifndef HPATCH_FILE_USE_FILESYSTEM
  43. static uint32_t patchFileSize;
  44. /* if define HPATCH_FILE_USE_FILESYSTEM, you must call this function
  45. to set the patch file size */
  46. void hpatch_setPatchFileSize(uint32_t size)
  47. {
  48. patchFileSize = size;
  49. }
  50. #endif
  51. hpatch_inline static
  52. hpatch_BOOL _import_fileSeek64(hpatch_FileHandle file,hpatch_StreamPos_t seekPos,int whence){
  53. #ifdef HPATCH_FILE_USE_FILESYSTEM
  54. return ff_fseek(file,seekPos,whence)==0;
  55. #else
  56. if (whence == SEEK_SET) {
  57. file->pos = seekPos;
  58. } else if (whence == SEEK_CUR) {
  59. if ((file->pos + seekPos) > file->size)
  60. return hpatch_FALSE;
  61. else
  62. file->pos += seekPos;
  63. } else if (whence == SEEK_END) {
  64. file->pos = file->size;
  65. }
  66. return hpatch_TRUE;
  67. #endif
  68. }
  69. hpatch_inline static
  70. hpatch_BOOL _import_fileSeek64To(hpatch_FileHandle file,hpatch_StreamPos_t seekPos){
  71. return _import_fileSeek64(file,seekPos,SEEK_SET);
  72. }
  73. hpatch_inline static
  74. hpatch_BOOL _import_fileTell64(hpatch_FileHandle file,hpatch_StreamPos_t* outPos){
  75. #ifdef HPATCH_FILE_USE_FILESYSTEM
  76. off_t pos=ff_ftell(file);
  77. #else
  78. off_t pos = file->pos;
  79. #endif
  80. *outPos=(hpatch_StreamPos_t)pos;
  81. return (pos>=0);
  82. }
  83. hpatch_inline static
  84. hpatch_BOOL _import_fileClose(hpatch_FileHandle* pfile){
  85. hpatch_FileHandle file=*pfile;
  86. if (file){
  87. *pfile=0;
  88. #ifdef HPATCH_FILE_USE_FILESYSTEM
  89. if (0!=ff_fclose(file))
  90. return hpatch_FALSE;
  91. #else
  92. vPortFree(file);
  93. #endif
  94. }
  95. return hpatch_TRUE;
  96. }
  97. # define _import_fileClose_No_errno(pfile) _import_fileClose(pfile)
  98. hpatch_BOOL _import_fileRead(hpatch_FileHandle file,TByte* buf,TByte* buf_end){
  99. while (buf<buf_end) {
  100. size_t readLen=(size_t)(buf_end-buf);
  101. if (readLen>hpatch_kFileIOBestMaxSize) readLen=hpatch_kFileIOBestMaxSize;
  102. #ifdef HPATCH_FILE_USE_FILESYSTEM
  103. if (readLen!=ff_fread(buf,1,readLen,file)) return hpatch_FALSE;
  104. #else
  105. #if DEVICE_TYPE_SELECT == EMMC_FLASH
  106. if (0 != emmc_read(file->offset + file->pos, readLen, buf))
  107. return hpatch_FALSE;
  108. #else
  109. if (SFUD_SUCCESS != sfud_read(file->sflash, file->offset + file->pos, readLen, buf))
  110. return hpatch_FALSE;
  111. #endif
  112. #ifdef HPATCH_FILE_CHECK_DEBUG
  113. memcpy(file->filebuf + file->pos, buf, readLen);
  114. #endif
  115. file->pos += readLen;
  116. #endif
  117. buf+=readLen;
  118. }
  119. return buf==buf_end;
  120. }
  121. hpatch_BOOL _import_fileWrite(hpatch_FileHandle file,const TByte* data,const TByte* data_end){
  122. while (data<data_end) {
  123. size_t writeLen=(size_t)(data_end-data);
  124. if (writeLen>hpatch_kFileIOBestMaxSize) writeLen=hpatch_kFileIOBestMaxSize;
  125. #ifdef HPATCH_FILE_USE_FILESYSTEM
  126. if (writeLen!=ff_fwrite(data,1,writeLen,file)) return hpatch_FALSE;
  127. #else
  128. #if DEVICE_TYPE_SELECT == EMMC_FLASH
  129. if (0 != emmc_write(file->offset + file->pos, writeLen, (uint8_t *)data))
  130. return hpatch_FALSE;
  131. #else
  132. if (SFUD_SUCCESS != sfud_write(file->sflash, file->offset + file->pos, writeLen, data))
  133. return hpatch_FALSE;
  134. #endif
  135. #ifdef HPATCH_FILE_CHECK_DEBUG
  136. memcpy(file->filebuf + file->pos, data, writeLen);
  137. #endif
  138. file->pos += writeLen;
  139. #endif
  140. data+=writeLen;
  141. }
  142. return data==data_end;
  143. }
  144. hpatch_inline static
  145. hpatch_BOOL _import_fileFlush(hpatch_FileHandle writedFile){
  146. //return (0==ff_fflush(writedFile));
  147. return hpatch_TRUE;
  148. }
  149. /* // retained data error
  150. hpatch_BOOL _import_fileTruncate(hpatch_FileHandle file,hpatch_StreamPos_t new_file_length){
  151. #ifdef _MSC_VER
  152. int fno=_fileno(file);
  153. if (fno==-1) return hpatch_FALSE;
  154. if (_chsize_s(fno,new_file_length)!=0) return hpatch_FALSE;
  155. #else
  156. int fno=fileno(file);
  157. if (fno==-1) return hpatch_FALSE;
  158. if (ftruncate(fno,new_file_length)!=0) return hpatch_FALSE;
  159. #endif
  160. return hpatch_TRUE;
  161. }*/
  162. # define _FileModeType const char*
  163. # define _kFileReadMode "rb"
  164. # define _kFileWriteMode "wb+"
  165. # define _kFileReadWriteMode "rb+"
  166. hpatch_inline static
  167. hpatch_FileHandle _import_fileOpen(const char* fileName_utf8,_FileModeType mode){
  168. #ifdef HPATCH_FILE_USE_FILESYSTEM
  169. return ff_fopen(fileName_utf8,mode);
  170. #else
  171. int filetype;
  172. hpatch_FileHandle file = pvPortMalloc(sizeof(DEV_FILE));
  173. if (file) {
  174. file->filetype = -1;
  175. if (!strcmp(fileName_utf8, "patch")) {
  176. assert (patchFileSize != 0);
  177. file->filetype = UPFILE_TYPE_NUM;
  178. file->newfile = 0;
  179. file->offset = OTA_MEDIA_OFFSET;
  180. file->size = patchFileSize;
  181. file->pos = 0;
  182. #if DEVICE_TYPE_SELECT == SPI_NOR_FLASH
  183. file->sflash = sfud_get_device(0);
  184. #endif
  185. #ifdef HPATCH_FILE_CHECK_DEBUG
  186. file->filebuf = pvPortMalloc(file->size);
  187. #endif
  188. return file;
  189. } else if (!strncmp(fileName_utf8, "new", 3)) {
  190. for (filetype = 0; filetype < UPFILE_TYPE_NUM; filetype++) {
  191. if (!strcmp(hpatch_NofsFileName[filetype], fileName_utf8 + 3)) {
  192. file->filetype = filetype;
  193. file->newfile = 1;
  194. break;
  195. }
  196. }
  197. } else {
  198. for (filetype = 0; filetype < UPFILE_TYPE_NUM; filetype++) {
  199. if (!strcmp(hpatch_NofsFileName[filetype], fileName_utf8)) {
  200. file->filetype = filetype;
  201. file->newfile = 0;
  202. break;
  203. }
  204. }
  205. }
  206. if (file->filetype >= 0) {
  207. file->offset = get_upfile_offset(file->filetype, file->newfile);
  208. if (file->newfile)
  209. file->size = 0;
  210. else
  211. file->size = get_upfile_size(filetype);
  212. file->pos = 0;
  213. #if DEVICE_TYPE_SELECT == SPI_NOR_FLASH
  214. file->sflash = sfud_get_device(0);
  215. #endif
  216. #ifdef HPATCH_FILE_CHECK_DEBUG
  217. if (!file->newfile)
  218. file->filebuf = pvPortMalloc(file->size);
  219. #endif
  220. return file;
  221. } else {
  222. vPortFree(file);
  223. return NULL;
  224. }
  225. }
  226. return NULL;
  227. #endif
  228. }
  229. static hpatch_FileHandle _import_fileOpenWithSize(const char* fileName_utf8,_FileModeType mode,hpatch_StreamPos_t* out_fileSize){
  230. hpatch_FileHandle file=0;
  231. file=_import_fileOpen(fileName_utf8,mode);
  232. if ((out_fileSize==0)||(file==0)) return file;
  233. if (_import_fileSeek64(file,0,SEEK_END)){
  234. if (_import_fileTell64(file,out_fileSize)){
  235. if (_import_fileSeek64(file,0,SEEK_SET)){
  236. return file;
  237. }
  238. }
  239. }
  240. //error clear
  241. _import_fileClose(&file);
  242. return 0;
  243. }
  244. static hpatch_inline
  245. hpatch_BOOL _import_fileOpenRead(const char* fileName_utf8,hpatch_FileHandle* out_fileHandle,
  246. hpatch_StreamPos_t* out_fileSize){
  247. hpatch_FileHandle file=0;
  248. assert(out_fileHandle!=0);
  249. if (out_fileHandle==0) { _set_errno_new(EINVAL); return hpatch_FALSE; }
  250. file=_import_fileOpenWithSize(fileName_utf8,_kFileReadMode,out_fileSize);
  251. if (file==0) return hpatch_FALSE;
  252. *out_fileHandle=file;
  253. return hpatch_TRUE;
  254. }
  255. static hpatch_inline
  256. hpatch_BOOL _import_fileOpenCreateOrReWrite(const char* fileName_utf8,hpatch_FileHandle* out_fileHandle){
  257. hpatch_FileHandle file=0;
  258. assert(out_fileHandle!=0);
  259. if (out_fileHandle==0) { _set_errno_new(EINVAL); return hpatch_FALSE; }
  260. file=_import_fileOpen(fileName_utf8,_kFileWriteMode);
  261. if (file==0) return hpatch_FALSE;
  262. *out_fileHandle=file;
  263. return hpatch_TRUE;
  264. }
  265. static
  266. hpatch_BOOL _import_fileReopenWrite(const char* fileName_utf8,hpatch_FileHandle* out_fileHandle,
  267. hpatch_StreamPos_t* out_curFileWritePos){
  268. hpatch_FileHandle file=0;
  269. hpatch_StreamPos_t curFileSize=0;
  270. assert(out_fileHandle!=0);
  271. if (out_fileHandle==0) { _set_errno_new(EINVAL); return hpatch_FALSE; }
  272. file=_import_fileOpenWithSize(fileName_utf8,_kFileReadWriteMode,&curFileSize);
  273. if (file==0) return hpatch_FALSE;
  274. if (out_curFileWritePos!=0) *out_curFileWritePos=curFileSize;
  275. if (!_import_fileSeek64To(file,curFileSize))
  276. { _import_fileClose_No_errno(&file); return hpatch_FALSE; }
  277. *out_fileHandle=file;
  278. return hpatch_TRUE;
  279. }
  280. #define _ferr_return() { _update_ferr(self->fileError); return hpatch_FALSE; }
  281. #define _ferr_returnv(v) { _update_ferrv(self->fileError,v); return hpatch_FALSE; }
  282. #define _rw_ferr_return() { self->m_fpos=hpatch_kNullStreamPos; _ferr_return(); }
  283. #define _rw_ferr_returnv(v) { self->m_fpos=hpatch_kNullStreamPos; _ferr_returnv(v); }
  284. static hpatch_BOOL _TFileStreamInput_read_file(const hpatch_TStreamInput* stream,hpatch_StreamPos_t readFromPos,
  285. TByte* out_data,TByte* out_data_end){
  286. size_t readLen;
  287. hpatch_TFileStreamInput* self=(hpatch_TFileStreamInput*)stream->streamImport;
  288. assert(out_data<=out_data_end);
  289. readLen=(size_t)(out_data_end-out_data);
  290. if (readLen==0) return hpatch_TRUE;
  291. if ((readLen>self->base.streamSize)
  292. ||(readFromPos>self->base.streamSize-readLen)) _ferr_returnv(EFBIG);
  293. if (self->m_fpos!=readFromPos+self->m_offset){
  294. if (!_import_fileSeek64To(self->m_file,readFromPos+self->m_offset)) _rw_ferr_return();
  295. }
  296. if (!_import_fileRead(self->m_file,out_data,out_data+readLen)) _rw_ferr_return();
  297. self->m_fpos=readFromPos+self->m_offset+readLen;
  298. return hpatch_TRUE;
  299. }
  300. hpatch_BOOL hpatch_TFileStreamInput_open(hpatch_TFileStreamInput* self,const char* fileName_utf8){
  301. assert(self->m_file==0);
  302. self->fileError=hpatch_FALSE;
  303. if (self->m_file) _ferr_returnv(EINVAL);
  304. if (!_import_fileOpenRead(fileName_utf8,&self->m_file,&self->base.streamSize))
  305. _ferr_return();
  306. self->base.streamImport=self;
  307. self->base.read=_TFileStreamInput_read_file;
  308. self->m_fpos=0;
  309. self->m_offset=0;
  310. return hpatch_TRUE;
  311. }
  312. hpatch_BOOL hpatch_TFileStreamInput_setOffset(hpatch_TFileStreamInput* self,hpatch_StreamPos_t offset){
  313. if (self->base.streamSize<offset)
  314. _ferr_returnv(EFBIG);
  315. self->m_offset+=offset;
  316. self->base.streamSize-=offset;
  317. return hpatch_TRUE;
  318. }
  319. hpatch_BOOL hpatch_TFileStreamInput_close(hpatch_TFileStreamInput* self){
  320. if (!_import_fileClose(&self->m_file)) _ferr_return();
  321. return hpatch_TRUE;
  322. }
  323. static hpatch_BOOL _TFileStreamOutput_write_file(const hpatch_TStreamOutput* stream,hpatch_StreamPos_t writeToPos,
  324. const TByte* data,const TByte* data_end){
  325. size_t writeLen;
  326. hpatch_TFileStreamOutput* self=(hpatch_TFileStreamOutput*)stream->streamImport;
  327. assert(data<=data_end);
  328. assert(self->m_offset==0);
  329. writeLen=(size_t)(data_end-data);
  330. if (writeLen==0) return hpatch_TRUE;
  331. if ((writeLen>self->base.streamSize)
  332. ||(writeToPos>self->base.streamSize-writeLen)) _ferr_returnv(EFBIG);
  333. if (self->is_in_readModel){
  334. self->is_in_readModel=hpatch_FALSE;
  335. self->m_fpos=hpatch_kNullStreamPos;
  336. }
  337. if (writeToPos!=self->m_fpos){
  338. if (self->is_random_out){
  339. if (!_import_fileFlush(self->m_file)) _rw_ferr_return(); //for lseek64 safe
  340. if (!_import_fileSeek64To(self->m_file,writeToPos)) _rw_ferr_return();
  341. self->m_fpos=writeToPos;
  342. }else{
  343. _ferr_returnv(ERANGE); //must continue write at self->m_fpos
  344. }
  345. }
  346. if (!_import_fileWrite(self->m_file,data,data+writeLen)) _rw_ferr_return();
  347. self->m_fpos=writeToPos+writeLen;
  348. self->out_length=(self->out_length>=self->m_fpos)?self->out_length:self->m_fpos;
  349. return hpatch_TRUE;
  350. }
  351. static hpatch_BOOL _hpatch_TFileStreamOutput_read_file(const hpatch_TStreamOutput* stream,
  352. hpatch_StreamPos_t readFromPos,
  353. TByte* out_data,TByte* out_data_end){
  354. //hpatch_TFileStreamOutput is A hpatch_TFileStreamInput !
  355. hpatch_TFileStreamOutput* self=(hpatch_TFileStreamOutput*)stream->streamImport;
  356. const hpatch_TStreamInput* in_stream=(const hpatch_TStreamInput*)stream;
  357. if (!self->is_in_readModel){
  358. if (!hpatch_TFileStreamOutput_flush(self)) _rw_ferr_return();
  359. self->is_in_readModel=hpatch_TRUE;
  360. self->m_fpos=hpatch_kNullStreamPos;
  361. }
  362. return _TFileStreamInput_read_file(in_stream,readFromPos,out_data,out_data_end);
  363. }
  364. hpatch_BOOL hpatch_TFileStreamOutput_open(hpatch_TFileStreamOutput* self,const char* fileName_utf8,
  365. hpatch_StreamPos_t max_file_length){
  366. assert(self->m_file==0);
  367. self->fileError=hpatch_FALSE;
  368. if (self->m_file) _ferr_returnv(EINVAL);
  369. if (!_import_fileOpenCreateOrReWrite(fileName_utf8,&self->m_file))
  370. _ferr_return();
  371. self->base.streamImport=self;
  372. self->base.streamSize=max_file_length;
  373. self->base.read_writed=_hpatch_TFileStreamOutput_read_file;
  374. self->base.write=_TFileStreamOutput_write_file;
  375. self->m_fpos=0;
  376. self->m_offset=0;
  377. self->is_in_readModel=hpatch_FALSE;
  378. self->is_random_out=hpatch_FALSE;
  379. self->out_length=0;
  380. return hpatch_TRUE;
  381. }
  382. hpatch_BOOL hpatch_TFileStreamOutput_reopen(hpatch_TFileStreamOutput* self,const char* fileName_utf8,
  383. hpatch_StreamPos_t max_file_length){
  384. hpatch_StreamPos_t curFileWritePos=0;
  385. assert(self->m_file==0);
  386. self->fileError=hpatch_FALSE;
  387. if (self->m_file) _ferr_returnv(EINVAL);
  388. if (!_import_fileReopenWrite(fileName_utf8,&self->m_file,&curFileWritePos))
  389. _ferr_return();
  390. if (curFileWritePos>max_file_length){
  391. //note: now not support reset file length to max_file_length
  392. _import_fileClose(&self->m_file);
  393. _ferr_returnv(EFBIG);
  394. }
  395. self->base.streamImport=self;
  396. self->base.streamSize=max_file_length;
  397. self->base.read_writed=_hpatch_TFileStreamOutput_read_file;
  398. self->base.write=_TFileStreamOutput_write_file;
  399. self->m_fpos=curFileWritePos;
  400. self->m_offset=0;
  401. self->is_in_readModel=hpatch_FALSE;
  402. self->is_random_out=hpatch_FALSE;
  403. self->out_length=curFileWritePos;
  404. return hpatch_TRUE;
  405. }
  406. /*
  407. hpatch_BOOL hpatch_TFileStreamOutput_truncate(hpatch_TFileStreamOutput* self,hpatch_StreamPos_t new_file_length){
  408. if (!_import_fileTruncate(self->m_file,new_file_length))
  409. _ferr_return();
  410. return hpatch_TRUE;
  411. }*/
  412. hpatch_BOOL hpatch_TFileStreamOutput_flush(hpatch_TFileStreamOutput* self){
  413. if (!_import_fileFlush(self->m_file))
  414. _ferr_return();
  415. return hpatch_TRUE;
  416. }
  417. hpatch_BOOL hpatch_TFileStreamOutput_close(hpatch_TFileStreamOutput* self){
  418. if (!_import_fileClose(&self->m_file))
  419. _ferr_return();
  420. return hpatch_TRUE;
  421. }