[Feature][task-view-564][FOTA] add full fota from ftp for zhenkang
Only Configure: No
Affected branch: ZK-first-oem-release
Affected module: FOTA
Is it affected on both ZXIC and MTK: only MTK
Self-test: Yes
Doc Update: No
Change-Id: I94df8adf40986cb761f182862c502a024955f707
diff --git a/LYNQ_PUBLIC/IC_meta/mtk/2735/liblynq-ftp-fota/liblynq-ftp-fota.bb b/LYNQ_PUBLIC/IC_meta/mtk/2735/liblynq-ftp-fota/liblynq-ftp-fota.bb
new file mode 100755
index 0000000..37e4e31
--- /dev/null
+++ b/LYNQ_PUBLIC/IC_meta/mtk/2735/liblynq-ftp-fota/liblynq-ftp-fota.bb
@@ -0,0 +1,66 @@
+inherit externalsrc package
+
+DESCRIPTION = "lynq-fota.so demo"
+SECTION = "base"
+#LICENSE = "MediaTekProprietary"
+LICENSE = "CLOSED"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=e1696b147d49d491bcb4da1a57173fff"
+
+DEPENDS += "bootctrl nandapi liblynq-protcl liblynq-log liblynq-uci zlib"
+
+inherit workonsrc
+WORKONSRC = "${TOPDIR}/../LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-ftp-fota"
+
+TARGET_CC_ARCH += "${LDFLAGS}"
+BB_INCLUDE_ADD = "--sysroot=${STAGING_DIR_HOST}"
+BB_LDFLAGS_ADD = "--sysroot=${STAGING_DIR_HOST} -Wl,--hash-style=gnu"
+#Parameters passed to do_compile()
+EXTRA_OEMAKE = "'RAT_CONFIG_C2K_SUPPORT = ${RAT_CONFIG_C2K_SUPPORT}'\
+ 'MTK_MULTI_SIM_SUPPORT = ${MTK_MULTI_SIM_SUPPORT}'\
+ 'TARGET_PLATFORM = ${TARGET_PLATFORM}'"
+
+
+FILES_${PN} = "${base_libdir}/*.so \
+ ${base_bindir}\
+ ${base_sbindir}"
+
+
+FILES_${PN}-dev = "/test \
+ ${includedir}"
+
+FILES_${PN}-doc = "/doc"
+
+FILES_${PN}-dbg ="${base_bindir}/.debug \
+ ${base_libdir}/.debug \
+ ${base_sbindir}/.debug"
+
+INSANE_SKIP_${PN} += "already-stripped"
+INSANE_SKIP_${PN} += "installed-vs-shipped"
+
+
+#INHIBIT_PACKAGE_STRIP = "1"
+do_compile () {
+ if [ "${PACKAGE_ARCH}" = "cortexa7hf-vfp-vfpv4-neon" ]; then
+ oe_runmake all ROOT=${STAGING_DIR_HOST} OFLAGS="--sysroot=${STAGING_DIR_HOST} -Os -mhard-float -Wl,--hash-style=gnu -DTELEPHONYWARE"
+ elif [ "${PACKAGE_ARCH}" = "cortexa7hf-neon-vfpv4" ]; then
+ oe_runmake all ROOT=${STAGING_DIR_HOST} OFLAGS="--sysroot=${STAGING_DIR_HOST} -Os -mhard-float -Wl,--hash-style=gnu -DTELEPHONYWARE"
+ elif [ "${PACKAGE_ARCH}" = "cortexa53hf-neon-fp-armv8" ]; then
+ oe_runmake all ROOT=${STAGING_DIR_HOST} OFLAGS="--sysroot=${STAGING_DIR_HOST} -Os -mhard-float -Wl,--hash-style=gnu -DTELEPHONYWARE -mhard-float -mfpu=neon-fp-armv8 -mfloat-abi=hard -mcpu=cortex-a53 -mtune=cortex-a53"
+ else
+ oe_runmake all ROOT=${STAGING_DIR_HOST} OFLAGS="--sysroot=${STAGING_DIR_HOST} -Os -Wl,--hash-style=gnu -DTELEPHONYWARE"
+ fi
+}
+
+do_install () {
+ oe_runmake install ROOT=${D}
+
+ if [ -d "${WORKONSRC}" ] ; then
+ install -d ${D}${includedir}/
+ cp -af ${S}/include/ ${D}${includedir}/
+ fi
+}
+
+addtask bachclean
+do_bachclean () {
+ oe_runmake clean
+}
diff --git a/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-ftp-fota/MD5/base64.c b/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-ftp-fota/MD5/base64.c
new file mode 100644
index 0000000..16db0fd
--- /dev/null
+++ b/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-ftp-fota/MD5/base64.c
@@ -0,0 +1,132 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2014, STMicroelectronics International N.V.
+ */
+#include "base64.h"
+
+static const char base64_table[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+size_t base64_enc_len(size_t size)
+{
+ return 4 * ((size + 2) / 3) + 1;
+}
+
+bool base64_enc(const void *data, size_t dlen, char *buf, size_t *blen)
+{
+ size_t n;
+ size_t boffs = 0;
+ const char *d = data;
+
+ n = base64_enc_len(dlen);
+ if (*blen < n) {
+ *blen = n;
+ return false;
+ }
+
+ for (n = 0; n < dlen; n += 3) {
+ uint32_t igrp;
+
+ igrp = d[n];
+ igrp <<= 8;
+
+ if ((n + 1) < dlen)
+ igrp |= d[n + 1];
+ igrp <<= 8;
+
+ if ((n + 2) < dlen)
+ igrp |= d[n + 2];
+
+ buf[boffs] = base64_table[(igrp >> 18) & 0x3f];
+ buf[boffs + 1] = base64_table[(igrp >> 12) & 0x3f];
+ if ((n + 1) < dlen)
+ buf[boffs + 2] = base64_table[(igrp >> 6) & 0x3f];
+ else
+ buf[boffs + 2] = '=';
+ if ((n + 2) < dlen)
+ buf[boffs + 3] = base64_table[igrp & 0x3f];
+ else
+ buf[boffs + 3] = '=';
+
+ boffs += 4;
+ }
+ buf[boffs++] = '\0';
+
+ *blen = boffs;
+ return true;
+}
+
+static bool get_idx(char ch, uint8_t *idx)
+{
+ size_t n;
+
+ for (n = 0; base64_table[n] != '\0'; n++) {
+ if (ch == base64_table[n]) {
+ *idx = n;
+ return true;
+ }
+ }
+ return false;
+}
+
+bool base64_dec(const char *data, size_t size, void *buf, size_t *blen)
+{
+ size_t n;
+ uint8_t idx;
+ uint8_t *b = buf;
+ size_t m = 0;
+ size_t s = 0;
+
+ for (n = 0; n < size && data[n] != '\0'; n++) {
+ if (data[n] == '=')
+ break; /* Reached pad characters, we're done */
+
+ if (!get_idx(data[n], &idx))
+ continue;
+
+ if (m > *blen)
+ b = NULL;
+
+ switch (s) {
+ case 0:
+ if (b)
+ b[m] = idx << 2;
+ s++;
+ break;
+ case 1:
+ if (b)
+ b[m] |= idx >> 4;
+ m++;
+ if (m > *blen)
+ b = NULL;
+ if (b)
+ b[m] = (idx & 0xf) << 4;
+ s++;
+ break;
+ case 2:
+ if (b)
+ b[m] |= idx >> 2;
+ m++;
+ if (m > *blen)
+ b = NULL;
+ if (b)
+ b[m] = (idx & 0x3) << 6;
+ s++;
+ break;
+ case 3:
+ if (b)
+ b[m] |= idx;
+ m++;
+ s = 0;
+ break;
+ default:
+ return false; /* "Can't happen" */
+ }
+ }
+ /* We don't detect if input was bad, but that's OK with the spec. */
+ *blen = m;
+ if (b)
+ return true;
+ else
+ return false;
+}
diff --git a/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-ftp-fota/MD5/md5.c b/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-ftp-fota/MD5/md5.c
new file mode 100755
index 0000000..5dd9ff3
--- /dev/null
+++ b/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-ftp-fota/MD5/md5.c
@@ -0,0 +1,161 @@
+#include "string.h"
+#include "md5.h"
+
+unsigned char PADDING[]={0x80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+
+void MD5Init(MD5_CTX *context)
+{
+ context->count[0] = 0;
+ context->count[1] = 0;
+ context->state[0] = 0x67452301;
+ context->state[1] = 0xEFCDAB89;
+ context->state[2] = 0x98BADCFE;
+ context->state[3] = 0x10325476;
+}
+void MD5Update(MD5_CTX *context,unsigned char *input,unsigned int inputlen)
+{
+ unsigned int i = 0,index = 0,partlen = 0;
+ index = (context->count[0] >> 3) & 0x3F;
+ partlen = 64 - index;
+ context->count[0] += inputlen << 3;
+ if(context->count[0] < (inputlen << 3))
+ context->count[1]++;
+ context->count[1] += inputlen >> 29;
+
+ if(inputlen >= partlen)
+ {
+ memcpy(&context->buffer[index],input,partlen);
+ MD5Transform(context->state,context->buffer);
+ for(i = partlen;i+64 <= inputlen;i+=64)
+ MD5Transform(context->state,&input[i]);
+ index = 0;
+ }
+ else
+ {
+ i = 0;
+ }
+ memcpy(&context->buffer[index],&input[i],inputlen-i);
+}
+void MD5Final(MD5_CTX *context,unsigned char digest[16])
+{
+ unsigned int index = 0,padlen = 0;
+ unsigned char bits[8];
+ index = (context->count[0] >> 3) & 0x3F;
+ padlen = (index < 56)?(56-index):(120-index);
+ MD5Encode(bits,context->count,8);
+ MD5Update(context,PADDING,padlen);
+ MD5Update(context,bits,8);
+ MD5Encode(digest,context->state,16);
+}
+void MD5Encode(unsigned char *output,unsigned int *input,unsigned int len)
+{
+ unsigned int i = 0,j = 0;
+ while(j < len)
+ {
+ output[j] = input[i] & 0xFF;
+ output[j+1] = (input[i] >> 8) & 0xFF;
+ output[j+2] = (input[i] >> 16) & 0xFF;
+ output[j+3] = (input[i] >> 24) & 0xFF;
+ i++;
+ j+=4;
+ }
+}
+void MD5Decode(unsigned int *output,unsigned char *input,unsigned int len)
+{
+ unsigned int i = 0,j = 0;
+ while(j < len)
+ {
+ output[i] = (input[j]) |
+ (input[j+1] << 8) |
+ (input[j+2] << 16) |
+ (input[j+3] << 24);
+ i++;
+ j+=4;
+ }
+}
+void MD5Transform(unsigned int state[4],unsigned char block[64])
+{
+ unsigned int a = state[0];
+ unsigned int b = state[1];
+ unsigned int c = state[2];
+ unsigned int d = state[3];
+ unsigned int x[64];
+ MD5Decode(x,block,64);
+ FF(a, b, c, d, x[ 0], 7, 0xd76aa478); /* 1 */
+ FF(d, a, b, c, x[ 1], 12, 0xe8c7b756); /* 2 */
+ FF(c, d, a, b, x[ 2], 17, 0x242070db); /* 3 */
+ FF(b, c, d, a, x[ 3], 22, 0xc1bdceee); /* 4 */
+ FF(a, b, c, d, x[ 4], 7, 0xf57c0faf); /* 5 */
+ FF(d, a, b, c, x[ 5], 12, 0x4787c62a); /* 6 */
+ FF(c, d, a, b, x[ 6], 17, 0xa8304613); /* 7 */
+ FF(b, c, d, a, x[ 7], 22, 0xfd469501); /* 8 */
+ FF(a, b, c, d, x[ 8], 7, 0x698098d8); /* 9 */
+ FF(d, a, b, c, x[ 9], 12, 0x8b44f7af); /* 10 */
+ FF(c, d, a, b, x[10], 17, 0xffff5bb1); /* 11 */
+ FF(b, c, d, a, x[11], 22, 0x895cd7be); /* 12 */
+ FF(a, b, c, d, x[12], 7, 0x6b901122); /* 13 */
+ FF(d, a, b, c, x[13], 12, 0xfd987193); /* 14 */
+ FF(c, d, a, b, x[14], 17, 0xa679438e); /* 15 */
+ FF(b, c, d, a, x[15], 22, 0x49b40821); /* 16 */
+
+ /* Round 2 */
+ GG(a, b, c, d, x[ 1], 5, 0xf61e2562); /* 17 */
+ GG(d, a, b, c, x[ 6], 9, 0xc040b340); /* 18 */
+ GG(c, d, a, b, x[11], 14, 0x265e5a51); /* 19 */
+ GG(b, c, d, a, x[ 0], 20, 0xe9b6c7aa); /* 20 */
+ GG(a, b, c, d, x[ 5], 5, 0xd62f105d); /* 21 */
+ GG(d, a, b, c, x[10], 9, 0x2441453); /* 22 */
+ GG(c, d, a, b, x[15], 14, 0xd8a1e681); /* 23 */
+ GG(b, c, d, a, x[ 4], 20, 0xe7d3fbc8); /* 24 */
+ GG(a, b, c, d, x[ 9], 5, 0x21e1cde6); /* 25 */
+ GG(d, a, b, c, x[14], 9, 0xc33707d6); /* 26 */
+ GG(c, d, a, b, x[ 3], 14, 0xf4d50d87); /* 27 */
+ GG(b, c, d, a, x[ 8], 20, 0x455a14ed); /* 28 */
+ GG(a, b, c, d, x[13], 5, 0xa9e3e905); /* 29 */
+ GG(d, a, b, c, x[ 2], 9, 0xfcefa3f8); /* 30 */
+ GG(c, d, a, b, x[ 7], 14, 0x676f02d9); /* 31 */
+ GG(b, c, d, a, x[12], 20, 0x8d2a4c8a); /* 32 */
+
+ /* Round 3 */
+ HH(a, b, c, d, x[ 5], 4, 0xfffa3942); /* 33 */
+ HH(d, a, b, c, x[ 8], 11, 0x8771f681); /* 34 */
+ HH(c, d, a, b, x[11], 16, 0x6d9d6122); /* 35 */
+ HH(b, c, d, a, x[14], 23, 0xfde5380c); /* 36 */
+ HH(a, b, c, d, x[ 1], 4, 0xa4beea44); /* 37 */
+ HH(d, a, b, c, x[ 4], 11, 0x4bdecfa9); /* 38 */
+ HH(c, d, a, b, x[ 7], 16, 0xf6bb4b60); /* 39 */
+ HH(b, c, d, a, x[10], 23, 0xbebfbc70); /* 40 */
+ HH(a, b, c, d, x[13], 4, 0x289b7ec6); /* 41 */
+ HH(d, a, b, c, x[ 0], 11, 0xeaa127fa); /* 42 */
+ HH(c, d, a, b, x[ 3], 16, 0xd4ef3085); /* 43 */
+ HH(b, c, d, a, x[ 6], 23, 0x4881d05); /* 44 */
+ HH(a, b, c, d, x[ 9], 4, 0xd9d4d039); /* 45 */
+ HH(d, a, b, c, x[12], 11, 0xe6db99e5); /* 46 */
+ HH(c, d, a, b, x[15], 16, 0x1fa27cf8); /* 47 */
+ HH(b, c, d, a, x[ 2], 23, 0xc4ac5665); /* 48 */
+
+ /* Round 4 */
+ II(a, b, c, d, x[ 0], 6, 0xf4292244); /* 49 */
+ II(d, a, b, c, x[ 7], 10, 0x432aff97); /* 50 */
+ II(c, d, a, b, x[14], 15, 0xab9423a7); /* 51 */
+ II(b, c, d, a, x[ 5], 21, 0xfc93a039); /* 52 */
+ II(a, b, c, d, x[12], 6, 0x655b59c3); /* 53 */
+ II(d, a, b, c, x[ 3], 10, 0x8f0ccc92); /* 54 */
+ II(c, d, a, b, x[10], 15, 0xffeff47d); /* 55 */
+ II(b, c, d, a, x[ 1], 21, 0x85845dd1); /* 56 */
+ II(a, b, c, d, x[ 8], 6, 0x6fa87e4f); /* 57 */
+ II(d, a, b, c, x[15], 10, 0xfe2ce6e0); /* 58 */
+ II(c, d, a, b, x[ 6], 15, 0xa3014314); /* 59 */
+ II(b, c, d, a, x[13], 21, 0x4e0811a1); /* 60 */
+ II(a, b, c, d, x[ 4], 6, 0xf7537e82); /* 61 */
+ II(d, a, b, c, x[11], 10, 0xbd3af235); /* 62 */
+ II(c, d, a, b, x[ 2], 15, 0x2ad7d2bb); /* 63 */
+ II(b, c, d, a, x[ 9], 21, 0xeb86d391); /* 64 */
+ state[0] += a;
+ state[1] += b;
+ state[2] += c;
+ state[3] += d;
+}
\ No newline at end of file
diff --git a/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-ftp-fota/MD5/md5_encode.c b/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-ftp-fota/MD5/md5_encode.c
new file mode 100755
index 0000000..918d634
--- /dev/null
+++ b/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-ftp-fota/MD5/md5_encode.c
@@ -0,0 +1,264 @@
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <log/log.h>
+//xf.li@20230822 add for ab recover start
+#include <errno.h>
+//xf.li@20230822 add for ab recover end
+#include "md5.h"
+#include "mtk_device_wrap.h"
+#include "liblog/lynq_deflog.h"
+#define LOG_TAG "LYNQ_FOTA"
+
+int ota_file_open(char* path, char* flag)
+{
+#if 1
+ if(strcmp(flag, "r") == 0 || strcmp(flag, "rb") == 0)
+ return mtk_device_wrap_open(path, O_RDONLY);
+ else if(strcmp(flag, "r+") == 0 || strcmp(flag, "rb+") == 0)
+ return mtk_device_wrap_open(path, O_RDWR | O_CREAT);
+ else if(strcmp(flag, "w+") == 0 ||strcmp(flag, "wb+") == 0 || strcmp(flag, "w") == 0 || strcmp(flag, "wb") == 0 )
+ return mtk_device_wrap_open(path, O_RDWR | O_CREAT | O_TRUNC);
+ else if(strcmp(flag, "a+") == 0 ||strcmp(flag, "ab+") == 0 || strcmp(flag, "a") == 0 || strcmp(flag, "ab") == 0 )
+ return mtk_device_wrap_open(path, O_RDWR | O_CREAT | O_APPEND);
+#endif
+}
+
+
+int ota_file_seek(int handle, int offset, int flag)
+{
+ return mtk_device_wrap_seek(handle,offset,flag);
+}
+
+
+
+int ota_file_read(char* buffer, size_t count, int file)
+{
+ return mtk_device_wrap_read(file,buffer,count);
+}
+
+
+
+void ota_file_close(int handle)
+{
+ mtk_device_wrap_close(handle);
+}
+
+#define MD5_READ_BUFFER_LEN 4*1024
+int lynq_md5_file_verfy(char* filePath, char* file_md5)
+{
+ int ret = -1;
+ int handle;
+
+ LYVERBLOG("[+MD5]:calc file md5: %s\n", filePath);
+ handle = open(filePath, O_RDONLY);
+ LYVERBLOG("[+MD5]:handle:%d\n",handle);
+ if(handle >= 0){
+ {
+ int read_len = 0;
+ unsigned char buffer[MD5_READ_BUFFER_LEN] = {0};
+ unsigned char decrypt[16];
+ int i;
+ MD5_CTX md5;
+ MD5Init(&md5);
+ //strcpy(buffer,"12345");
+ while ((read_len = read(handle,buffer, MD5_READ_BUFFER_LEN)) > 0)
+ {
+ //printf("readlen:%d\n",read_len);
+ MD5Update(&md5, (unsigned char*)buffer, read_len);
+ memset(buffer,0,sizeof(buffer));
+ }
+ MD5Final(&md5, (unsigned char*)decrypt);
+ memset(buffer, 0, MD5_READ_BUFFER_LEN);
+ for(i = 0; i < 16; i++)
+ {
+ sprintf((char*)(buffer + i * 2), "%02x",decrypt[i]);
+ }
+ LYVERBLOG("[+MD5]:md5:%s\n", buffer);
+ LYVERBLOG("[+MD5]:md5:%s\n", file_md5);
+
+ ret = strncmp((const char*)buffer, (const char*)file_md5,32);
+ LYVERBLOG("[+MD5]:ret:%d\n", ret);
+ }
+ close(handle);
+ }
+ return ret;
+}
+//xf.li@20230822 add for ab recover start
+#define MD5_VERFY_ERROR 5
+int lynq_md5_file_verfy_ab(char* filePath, char* file_md5)
+{
+ int ret = -1;
+ int handle;
+
+ RLOGD("[+MD5]:calc file md5: %s\n", filePath);
+ handle = open(filePath, O_RDONLY);
+ RLOGD("[+MD5]:handle:%d\n",handle);
+ if(handle == -1)
+ {
+ RLOGD("[+MD5]: can't open the file, errno is %d\n",errno);
+ }
+ if(handle >= 0)
+ {
+ int read_len = 0;
+ unsigned char buffer[MD5_READ_BUFFER_LEN] = {0};
+ unsigned char decrypt[16];
+ int i;
+ MD5_CTX md5;
+ MD5Init(&md5);
+ while ((read_len = read(handle,buffer, MD5_READ_BUFFER_LEN)) > 0)
+ {
+ MD5Update(&md5, (unsigned char*)buffer, read_len);
+ memset(buffer,0,sizeof(buffer));
+ usleep(1000);
+ }
+ MD5Final(&md5, (unsigned char*)decrypt);
+ memset(buffer, 0, MD5_READ_BUFFER_LEN);
+ for(i = 0; i < 16; i++)
+ {
+ sprintf((char*)(buffer + i * 2), "%02x",decrypt[i]);
+ }
+ RLOGD("[+MD5]:buffer md5:%s\n", buffer);
+ RLOGD("[+MD5]:file_md5 md5:%s\n", file_md5);
+
+ ret = strncmp((const char*)buffer, (const char*)file_md5,32);
+ RLOGD("[+MD5]:ret:%d\n", ret);
+ close(handle);
+ }
+ if(ret != 0)
+ {
+ return MD5_VERFY_ERROR;
+ }
+ return ret;
+}
+int calculate_file_md5_value(char* filePath, unsigned char buffer_out[])
+{
+ //int ret = -1;
+ int handle;
+
+ RLOGD("[+MD5]:calc file md5: %s\n", filePath);
+ handle = open(filePath, O_RDONLY);
+ RLOGD("[+MD5]:handle:%d\n",handle);
+ if(handle == -1)
+ {
+ RLOGD("[+MD5]: can't open the file, errno is %d\n",errno);
+ }
+ if(handle >= 0)
+ {
+ int read_len = 0;
+ unsigned char buffer[MD5_READ_BUFFER_LEN] = {0};
+ unsigned char decrypt[16];
+ int i;
+ MD5_CTX md5;
+ MD5Init(&md5);
+ while ((read_len = read(handle,buffer, MD5_READ_BUFFER_LEN)) > 0)
+ {
+ MD5Update(&md5, (unsigned char*)buffer, read_len);
+ memset(buffer,0,sizeof(buffer));
+ usleep(1000);
+ }
+ MD5Final(&md5, (unsigned char*)decrypt);
+ memset(buffer, 0, MD5_READ_BUFFER_LEN);
+ for(i = 0; i < 16; i++)
+ {
+ sprintf((char*)(buffer + i * 2), "%02x",decrypt[i]);
+ }
+ RLOGD("[+MD5]: md5 of %s : %s\n", filePath, buffer);
+ memcpy(buffer_out, buffer, MD5_READ_BUFFER_LEN);
+ close(handle);
+ }
+ else
+ {
+ return -1;
+ }
+ return 0;
+}
+
+int lynq_md5_two_file_verfy(char* filePath_1, char* filePath_2)
+{
+ int ret = -1;
+ int handle_1, handle_2;
+ unsigned char buffer_1[MD5_READ_BUFFER_LEN] = {0};
+ unsigned char buffer_2[MD5_READ_BUFFER_LEN] = {0};
+
+ ret = calculate_file_md5_value(filePath_1, buffer_1);
+ if(ret < 0)
+ {
+ RLOGD("[+MD5]:calculate file1 md5 value ERROE!!!\n");
+ return ret;
+ }
+ ret = calculate_file_md5_value(filePath_2, buffer_2);
+ if(ret < 0)
+ {
+ RLOGD("[+MD5]:calculate file2 md5 value ERROE!!!\n");
+ return ret;
+ }
+ RLOGD("buffer_1 is %s, buffer_2 is %s\n", buffer_1, buffer_2);
+ ret = strncmp((const char*)buffer_1, (const char*)buffer_2, 32);
+ RLOGD("[+MD5]:strncmp ret:%d\n", ret);
+
+ if(ret != 0)
+ {
+ return MD5_VERFY_ERROR;
+ }
+ return 0;
+}
+//xf.li@20230822 add for ab recover end
+#if 0
+int md5_file_verfy_new(char* filePath, char* file_md5,int packe_len)
+{
+ int ret = -1;
+ int handle;
+ int tatal_packe_len = 0;
+
+ LYVERBLOG("[+MD5]:calc file md5: %s\n", filePath);
+ handle = mtk_device_wrap_open(filePath, O_RDONLY);
+ LYVERBLOG("[+MD5]:handle:%d\n",handle);
+ if(handle >= 0){
+ {
+ int read_len = 0;
+ unsigned char buffer[MD5_READ_BUFFER_LEN] = {0};
+ unsigned char decrypt[16];
+ int i;
+ MD5_CTX md5;
+ MD5Init(&md5);
+ //strcpy(buffer,"12345");
+ tatal_packe_len = packe_len;
+ LYVERBLOG("[+MD5]:tatal_packe_len:%d\n", tatal_packe_len);
+ while ((read_len = mtk_device_wrap_read(handle,buffer, MD5_READ_BUFFER_LEN)) > 0)
+ {
+ //printf("readlen:%d\n",read_len);
+ if(tatal_packe_len >= read_len)
+ {
+ MD5Update(&md5, (unsigned char*)buffer, read_len);
+ tatal_packe_len -= read_len;
+ }
+ else if(tatal_packe_len > 0)
+ {
+ LYVERBLOG("[+MD5]:tatal_packe_len:%d\n", tatal_packe_len);
+ MD5Update(&md5, (unsigned char*)buffer, tatal_packe_len);
+ tatal_packe_len -= read_len;
+ }
+ LYVERBLOG("[+MD5]:tatal_packe_len:%d\n", tatal_packe_len);
+ memset(buffer,0,sizeof(buffer));
+ }
+ MD5Final(&md5, (unsigned char*)decrypt);
+ memset(buffer, 0, MD5_READ_BUFFER_LEN);
+ for(i = 0; i < 16; i++)
+ {
+ sprintf((char*)(buffer + i * 2), "%02x",decrypt[i]);
+ }
+ LYVERBLOG("[+MD5]:md5:%s\n", buffer);
+ LYVERBLOG("[+MD5]:md5:%s\n", file_md5);
+
+ ret = strncmp((const char*)buffer, (const char*)file_md5,32);
+ LYVERBLOG("[+MD5]:ret:%d\n", ret);
+ }
+ mtk_device_wrap_close(handle);
+ }
+ return ret;
+}
+#endif
\ No newline at end of file
diff --git a/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-ftp-fota/include/base64.h b/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-ftp-fota/include/base64.h
new file mode 100644
index 0000000..a341175
--- /dev/null
+++ b/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-ftp-fota/include/base64.h
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (c) 2014, STMicroelectronics International N.V.
+ */
+#ifndef BASE64_H
+#define BASE64_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+bool base64_enc(const void *data, size_t size, char *buf, size_t *blen);
+bool base64_dec(const char *data, size_t size, void *buf, size_t *blen);
+size_t base64_enc_len(size_t size);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BASE64_H */
diff --git a/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-ftp-fota/include/iot_rock.h b/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-ftp-fota/include/iot_rock.h
new file mode 100755
index 0000000..37b3c3e
--- /dev/null
+++ b/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-ftp-fota/include/iot_rock.h
@@ -0,0 +1,114 @@
+#ifndef _IOT_ROCK_H_
+#define _IOT_ROCK_H_
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+/* public */
+
+#define E_ROCK_SUCCESS (0)
+#define E_ROCK_INVALID_DELTA (-1)
+#define E_ROCK_DELTA_MISMATCH (-2)
+#define E_ROCK_DELTA_CHUNK_MISMATCH (-3)
+#define E_ROCK_READ_DELTA_ERROR (-4)
+#define E_ROCK_READ_BLOCK_ERROR (-11)
+#define E_ROCK_WRITE_BLOCK_ERROR (-12)
+#define E_ROCK_RAM_NOT_ENOUGH (-20)
+#define E_ROCK_INVALID_CTX (-30)
+#define E_ROCK_FOTA_ADDR (-50)
+
+#define MAX_OTA_ROLE (128)
+#define REAL_OTA_ROLE (32)
+
+#define MODE_NORMAL 0
+#define MODE_A2B 1
+#define MODE_B2A 2
+
+#define WAIT 0xff
+#define PASS 0
+#define ERROR -1
+
+typedef struct {
+ void* user_context;
+ unsigned int rom_base; // old rom start
+ unsigned char* ram_base; // ram working buffer start
+ unsigned int ram_len; // ram working buffer len
+
+ unsigned int backup_base; // ram backup storage start
+ unsigned int backup_len; // ram backup storage len
+
+ unsigned int update_nvram; // nvram update flag
+
+ int read_rom_directly;
+ int first_run;
+} IOT_UPDATA_CONTEXT;
+
+
+
+
+typedef struct {
+
+ char fota_flag[32]; //fota 标志保留
+ int update_result; //升级结果
+ int ota_run; //
+ char cid[32];
+ char did[32];
+} UPDATE_INFO;
+
+
+typedef struct {
+ int need_update;
+ int check_delta;
+ int check_rom;
+ int update_result;
+
+} UPDATE_STATUS;
+
+
+typedef struct {
+ int ota_run;
+ UPDATE_STATUS update_status[MAX_OTA_ROLE];
+ int update_result;
+ int switch_slot;
+
+} OTA_STATUS;
+
+
+
+
+
+//#define DELTA_HEARD_SIZE (4*5)
+
+//#define DELTA_HEARD_SIZE (4*11 + 4*11)
+#define DELTA_HEARD_SIZE 512
+#define DELTA_FULL_HEARD_SIZE 8
+
+
+
+int iot_patch(IOT_UPDATA_CONTEXT* update_ctx);
+int lynq_read_process(void);
+unsigned int iot_hash(unsigned char *buf,unsigned int len, unsigned int* value);
+int lynq_md5_file_verfy(char* filePath, char* file_md5);
+//xf.li@20230822 add for ab recover start
+int lynq_md5_file_verfy_ab(char* filePath, char* file_md5);
+int calculate_file_md5_value(char* filePath, unsigned char buffer_out[]);
+int lynq_md5_two_file_verfy(char* filePath_1, char* filePath_2);
+//xf.li@20230822 add for ab recover end
+//int md5_file_verfy_new(char* filePath, char* file_md5,int packe_len);
+int lynq_rock_main(int first_run);
+int lynq_fota_func(void);
+int lynq_nand_open(const char *pathname, int flags);
+ssize_t lynq_nand_read(int fd, void *buf, size_t count);
+ssize_t lynq_nand_write(int fd, void *buf, size_t count);
+int lynq_nand_close(int fd);
+int lynq_get_upgrade_status(void);
+void lynq_reboot_device(void);
+int lynq_fota_nrestart(void);
+int lynq_fota_set_addr_value(char *value,int size);
+int lynq_fota_get_addr_value(char *tmp);
+#endif
+
+
+
diff --git a/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-ftp-fota/include/iot_rock_ipl.h b/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-ftp-fota/include/iot_rock_ipl.h
new file mode 100755
index 0000000..77c7c2a
--- /dev/null
+++ b/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-ftp-fota/include/iot_rock_ipl.h
@@ -0,0 +1,22 @@
+#ifndef _IOT_ROCK_IPL_H_
+#define _IOT_ROCK_IPL_H_
+
+void rock_trace(void* ctx, const char* fmt, ...);
+void rock_progress(void* ctx, int percent);
+int rock_read_block(void* ctx, unsigned char* dest, unsigned int start, unsigned int size);
+int rock_read_delta(void* ctx, unsigned char* dest, unsigned int offset, unsigned int size);
+int rock_write_block(void* ctx, unsigned char* src, unsigned int start, unsigned int size);
+int rock_process_block(void* ctx, unsigned char* data, unsigned int start, unsigned int size);
+int rock_get_blocksize(void* ctx);
+
+int rock_read_file(void* ctx, void* name, unsigned char* dest, unsigned int offset, unsigned int size);
+int rock_write_file(void* ctx, void* name, unsigned char* src, unsigned int offset, unsigned int size);
+
+int rock_delete_file(void* ctx, void* name);
+
+int rock_fatal(void* ctx, int error_code);
+
+int rock_mismatch(void* ctx, unsigned char* buf, unsigned int start, unsigned int size,
+ unsigned int source_hash,unsigned int target_hash);
+#endif
+
diff --git a/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-ftp-fota/include/lynq_fota_file.h b/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-ftp-fota/include/lynq_fota_file.h
new file mode 100755
index 0000000..0193de6
--- /dev/null
+++ b/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-ftp-fota/include/lynq_fota_file.h
@@ -0,0 +1,18 @@
+#ifndef LYNQ_FOTA_FILE_H
+#define LYNQ_FOTA_FILE_H
+
+#include <unistd.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int lynq_fota_open(const char * pathname, const char * file_name, int flags);
+ssize_t lynq_fota_read(int fd, void *buf, size_t count);
+int lynq_fota_close(int fd);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // LYNQ_FOTA_FILE_H
diff --git a/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-ftp-fota/include/md5.h b/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-ftp-fota/include/md5.h
new file mode 100755
index 0000000..f0e3a1b
--- /dev/null
+++ b/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-ftp-fota/include/md5.h
@@ -0,0 +1,48 @@
+#ifndef MD5_H
+#define MD5_H
+
+typedef struct
+{
+ unsigned int count[2];
+ unsigned int state[4];
+ unsigned char buffer[64];
+}MD5_CTX;
+
+
+#define F(x,y,z) ((x & y) | (~x & z))
+#define G(x,y,z) ((x & z) | (y & ~z))
+#define H(x,y,z) (x^y^z)
+#define I(x,y,z) (y ^ (x | ~z))
+#define ROTATE_LEFT(x,n) ((x << n) | (x >> (32-n)))
+#define FF(a,b,c,d,x,s,ac) \
+{ \
+ a += F(b,c,d) + x + ac; \
+ a = ROTATE_LEFT(a,s); \
+ a += b; \
+}
+#define GG(a,b,c,d,x,s,ac) \
+{ \
+ a += G(b,c,d) + x + ac; \
+ a = ROTATE_LEFT(a,s); \
+ a += b; \
+}
+#define HH(a,b,c,d,x,s,ac) \
+{ \
+ a += H(b,c,d) + x + ac; \
+ a = ROTATE_LEFT(a,s); \
+ a += b; \
+}
+#define II(a,b,c,d,x,s,ac) \
+{ \
+ a += I(b,c,d) + x + ac; \
+ a = ROTATE_LEFT(a,s); \
+ a += b; \
+}
+void MD5Init(MD5_CTX *context);
+void MD5Update(MD5_CTX *context,unsigned char *input,unsigned int inputlen);
+void MD5Final(MD5_CTX *context,unsigned char digest[16]);
+void MD5Transform(unsigned int state[4],unsigned char block[64]);
+void MD5Encode(unsigned char *output,unsigned int *input,unsigned int len);
+void MD5Decode(unsigned int *output,unsigned char *input,unsigned int len);
+
+#endif
\ No newline at end of file
diff --git a/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-ftp-fota/include/md5_encode.h b/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-ftp-fota/include/md5_encode.h
new file mode 100755
index 0000000..c3e5d38
--- /dev/null
+++ b/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-ftp-fota/include/md5_encode.h
@@ -0,0 +1,33 @@
+#ifndef MD5_ENCODE_H_
+#define MD5_ENCODE_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+//打开文件
+int ota_file_open(char* path, char* flag);
+//文件偏移位置
+int ota_file_seek(int handle, int offset, int flag);
+//读文件内容
+int ota_file_read(char* buffer, size_t count, int file);
+//关闭文件
+void ota_file_close(int handle);
+
+
+/***
+ * @description: 校验文件的MD5
+ * @param filePath 文件路径
+ * @param file_md5 待校验MD5值
+ * @return 0:校验成功; 其他:校验失败
+ */
+int md5_file_verfy(char* filePath, char* file_md5);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
diff --git a/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-ftp-fota/include/sha.h b/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-ftp-fota/include/sha.h
new file mode 100755
index 0000000..ea0c773
--- /dev/null
+++ b/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-ftp-fota/include/sha.h
@@ -0,0 +1,78 @@
+/* sha.h
+**
+** Copyright 2008, The Android Open Source Project
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+** * Neither the name of Google Inc. nor the names of its contributors may
+** be used to endorse or promote products derived from this software
+** without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR
+** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+** EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+** OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef _EMBEDDED_SHA_H_
+#define _EMBEDDED_SHA_H_
+
+#include <inttypes.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct SHA_CTX {
+ uint64_t count;
+ uint32_t state[5];
+#if defined(HAVE_ENDIAN_H) && defined(HAVE_LITTLE_ENDIAN)
+ union {
+ uint8_t b[64];
+ uint32_t w[16];
+ } buf;
+#else
+ uint8_t buf[64];
+#endif
+} SHA_CTX;
+
+void SHA_init(SHA_CTX* ctx);
+void SHA_update(SHA_CTX* ctx, const void* data, int len);
+const uint8_t* SHA_final(SHA_CTX* ctx);
+
+/* Convenience method. Returns digest parameter value. */
+const uint8_t* SHA(const void* data, int len, uint8_t* digest);
+
+#define SHA_DIGEST_SIZE 20
+
+typedef enum check_status_t{
+ ERROR_SHA = -3, // sha1输入参数错误
+ PATCH_ERR = -2, // 检测hash既不等于source_hash也不等于target_hash, 一般错误情况
+ NOT_EXIST_FILE = -1, // 检测文件不存在
+ SOURCE_SUCC = 0, // 检测hash等于目标source_hash, 一般正常情况
+ PATCH_SUCC = 1, // 检测hash等于目标target_hash, up to data
+}Check_status;
+
+int ParseSha1(const char* str, uint8_t* digest);
+
+const uint8_t* ROCK_SHA(const char *file_name, uint8_t *digest);
+const uint8_t* ROCK_SHA_FILE(int fd_sha, int offset,int totle_size, uint8_t *digest);
+const uint8_t* ROCK_SHA_FILE_COMMON(int fd_sha, int offset,int totle_size, uint8_t *digest);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-ftp-fota/makefile b/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-ftp-fota/makefile
new file mode 100755
index 0000000..767c3f9
--- /dev/null
+++ b/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-ftp-fota/makefile
@@ -0,0 +1,85 @@
+SHELL = /bin/sh
+RM = rm -f
+
+LOCAL_CFLAGS := -Wall \
+ -g -Os \
+ -flto \
+ -fpermissive \
+ -DRIL_SHLIB \
+ -DATCI_PARSE \
+ -DKEEP_ALIVE \
+ -D__LINUX_OS__ \
+ -DECALL_SUPPORT
+
+CFLAGS += -fPIC -O2 $(INCLUDE) -D_LARGEFILE64_SOURCE
+
+$(warning ################# rock ROOT: $(ROOT),includedir:$(includedir))
+LOCAL_PATH = .
+
+LOCAL_C_INCLUDES = \
+ -I. \
+ -I./include \
+ -I$(LOCAL_PATH)/../include \
+ -I$(ROOT)$(includedir)/logger \
+ -I$(ROOT)$(includedir)/liblog \
+ -I$(ROOT)$(includedir)/ftp \
+ -I$(ROOT)$(includedir)/glib-2.0 \
+ -I$(ROOT)$(libdir)/glib-2.0/include \
+
+
+
+LOCAL_LIBS := \
+ -L. \
+ -L./lib \
+ -ldl \
+ -lpthread \
+ -llog \
+ -lstdc++ \
+ -lnandapi \
+ -lbootctrl \
+ -llynq-log \
+ -llynq-protcl \
+ -llynq-uci \
+ -lz
+
+SOURCES = $(wildcard *.c wildcard *.h rock_ua/*.c MD5/*c rock_ua/*.cpp)
+
+EXECUTABLE = liblynq-ftp-fota.so
+
+OBJECTS=$(SOURCES:.c=.o)
+
+CPP_SOURCES = $(wildcard rock_ua/*.cpp)
+
+
+CPP_OBJECTS=$(CPP_SOURCES:.cpp=.o)
+
+.PHONY: build clean install pack_rootfs
+
+all: build
+$(EXECUTABLE): $(OBJECTS) $(CPP_OBJECTS)
+ $(CXX) -shared -Wl,--no-undefined $(OBJECTS) $(LOCAL_LIBS) $(CFLAGS) $(LOCAL_CFLAGS) $(LOCAL_C_INCLUDES) -o $@
+
+%.o : %.c
+ $(CC) $(LOCAL_C_INCLUDES) $(CFLAGS) $(LOCAL_CFLAGS) $(LOCAL_LIBS) -o $@ -c $<
+
+%.o : %.cpp
+ $(CXX) $(LOCAL_C_INCLUDES) $(CFLAGS) $(LOCAL_CFLAGS) $(LOCAL_LIBS) -o $@ -c $<
+
+build: $(EXECUTABLE)
+ $(warning ########## build $(EXECUTABLE) ##########)
+
+install:
+ mkdir -p $(ROOT)$(base_libdir)/
+ install $(EXECUTABLE) $(ROOT)$(base_libdir)/
+ mkdir -p $(ROOT)$(includedir)/$(NAME)/sdk
+
+pack_rootfs:
+ mkdir -p $(PACK_INITRAMFS_TO)$(base_libdir)/
+ cp -af $(EXECUTABLE) $(PACK_INITRAMFS_TO)$(base_libdir)/
+ $(CROSS)strip $(PACK_INITRAMFS_TO)$(base_libdir)/$(EXECUTABLE)
+ mkdir -p $(PACK_TO)$(base_libdir)/
+ cp -af $(EXECUTABLE) $(PACK_TO)$(base_libdir)/
+ $(CROSS)strip $(PACK_TO)$(base_libdir)/$(EXECUTABLE)
+.PHONY: clean
+clean:
+ $(RM) $(OBJECTS) $(EXECUTABLE)
diff --git a/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-ftp-fota/rock_ua/ioapi.c b/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-ftp-fota/rock_ua/ioapi.c
new file mode 100755
index 0000000..782d324
--- /dev/null
+++ b/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-ftp-fota/rock_ua/ioapi.c
@@ -0,0 +1,231 @@
+/* ioapi.h -- IO base function header for compress/uncompress .zip
+ part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )
+
+ Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )
+
+ Modifications for Zip64 support
+ Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
+
+ For more info read MiniZip_info.txt
+
+*/
+
+#if defined(_WIN32) && (!(defined(_CRT_SECURE_NO_WARNINGS)))
+ #define _CRT_SECURE_NO_WARNINGS
+#endif
+
+#if defined(__APPLE__) || defined(IOAPI_NO_64) || defined(__HAIKU__) || defined(MINIZIP_FOPEN_NO_64)
+// In darwin and perhaps other BSD variants off_t is a 64 bit value, hence no need for specific 64 bit functions
+#define FOPEN_FUNC(filename, mode) fopen(filename, mode)
+#define FTELLO_FUNC(stream) ftello(stream)
+#define FSEEKO_FUNC(stream, offset, origin) fseeko(stream, offset, origin)
+#else
+#define FOPEN_FUNC(filename, mode) fopen64(filename, mode)
+#define FTELLO_FUNC(stream) ftello64(stream)
+#define FSEEKO_FUNC(stream, offset, origin) fseeko64(stream, offset, origin)
+#endif
+
+
+#include "ioapi.h"
+
+voidpf call_zopen64 (const zlib_filefunc64_32_def* pfilefunc, const void*filename, int mode) {
+ if (pfilefunc->zfile_func64.zopen64_file != NULL)
+ return (*(pfilefunc->zfile_func64.zopen64_file)) (pfilefunc->zfile_func64.opaque,filename,mode);
+ else
+ {
+ return (*(pfilefunc->zopen32_file))(pfilefunc->zfile_func64.opaque,(const char*)filename,mode);
+ }
+}
+
+long call_zseek64 (const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin) {
+ if (pfilefunc->zfile_func64.zseek64_file != NULL)
+ return (*(pfilefunc->zfile_func64.zseek64_file)) (pfilefunc->zfile_func64.opaque,filestream,offset,origin);
+ else
+ {
+ uLong offsetTruncated = (uLong)offset;
+ if (offsetTruncated != offset)
+ return -1;
+ else
+ return (*(pfilefunc->zseek32_file))(pfilefunc->zfile_func64.opaque,filestream,offsetTruncated,origin);
+ }
+}
+
+ZPOS64_T call_ztell64 (const zlib_filefunc64_32_def* pfilefunc, voidpf filestream) {
+ if (pfilefunc->zfile_func64.zseek64_file != NULL)
+ return (*(pfilefunc->zfile_func64.ztell64_file)) (pfilefunc->zfile_func64.opaque,filestream);
+ else
+ {
+ uLong tell_uLong = (uLong)(*(pfilefunc->ztell32_file))(pfilefunc->zfile_func64.opaque,filestream);
+ if ((tell_uLong) == MAXU32)
+ return (ZPOS64_T)-1;
+ else
+ return tell_uLong;
+ }
+}
+
+void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32, const zlib_filefunc_def* p_filefunc32) {
+ p_filefunc64_32->zfile_func64.zopen64_file = NULL;
+ p_filefunc64_32->zopen32_file = p_filefunc32->zopen_file;
+ p_filefunc64_32->zfile_func64.zread_file = p_filefunc32->zread_file;
+ p_filefunc64_32->zfile_func64.zwrite_file = p_filefunc32->zwrite_file;
+ p_filefunc64_32->zfile_func64.ztell64_file = NULL;
+ p_filefunc64_32->zfile_func64.zseek64_file = NULL;
+ p_filefunc64_32->zfile_func64.zclose_file = p_filefunc32->zclose_file;
+ p_filefunc64_32->zfile_func64.zerror_file = p_filefunc32->zerror_file;
+ p_filefunc64_32->zfile_func64.opaque = p_filefunc32->opaque;
+ p_filefunc64_32->zseek32_file = p_filefunc32->zseek_file;
+ p_filefunc64_32->ztell32_file = p_filefunc32->ztell_file;
+}
+
+
+
+static voidpf ZCALLBACK fopen_file_func(voidpf opaque, const char* filename, int mode) {
+ FILE* file = NULL;
+ const char* mode_fopen = NULL;
+ (void)opaque;
+ if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ)
+ mode_fopen = "rb";
+ else
+ if (mode & ZLIB_FILEFUNC_MODE_EXISTING)
+ mode_fopen = "r+b";
+ else
+ if (mode & ZLIB_FILEFUNC_MODE_CREATE)
+ mode_fopen = "wb";
+
+ if ((filename!=NULL) && (mode_fopen != NULL))
+ file = fopen(filename, mode_fopen);
+ return file;
+}
+
+static voidpf ZCALLBACK fopen64_file_func(voidpf opaque, const void* filename, int mode) {
+ FILE* file = NULL;
+ const char* mode_fopen = NULL;
+ (void)opaque;
+ if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ)
+ mode_fopen = "rb";
+ else
+ if (mode & ZLIB_FILEFUNC_MODE_EXISTING)
+ mode_fopen = "r+b";
+ else
+ if (mode & ZLIB_FILEFUNC_MODE_CREATE)
+ mode_fopen = "wb";
+
+ if ((filename!=NULL) && (mode_fopen != NULL))
+ file = FOPEN_FUNC((const char*)filename, mode_fopen);
+ return file;
+}
+
+
+static uLong ZCALLBACK fread_file_func(voidpf opaque, voidpf stream, void* buf, uLong size) {
+ uLong ret;
+ (void)opaque;
+ ret = (uLong)fread(buf, 1, (size_t)size, (FILE *)stream);
+ return ret;
+}
+
+static uLong ZCALLBACK fwrite_file_func(voidpf opaque, voidpf stream, const void* buf, uLong size) {
+ uLong ret;
+ (void)opaque;
+ ret = (uLong)fwrite(buf, 1, (size_t)size, (FILE *)stream);
+ return ret;
+}
+
+static long ZCALLBACK ftell_file_func(voidpf opaque, voidpf stream) {
+ long ret;
+ (void)opaque;
+ ret = ftell((FILE *)stream);
+ return ret;
+}
+
+
+static ZPOS64_T ZCALLBACK ftell64_file_func(voidpf opaque, voidpf stream) {
+ ZPOS64_T ret;
+ (void)opaque;
+ ret = (ZPOS64_T)FTELLO_FUNC((FILE *)stream);
+ return ret;
+}
+
+static long ZCALLBACK fseek_file_func(voidpf opaque, voidpf stream, uLong offset, int origin) {
+ int fseek_origin=0;
+ long ret;
+ (void)opaque;
+ switch (origin)
+ {
+ case ZLIB_FILEFUNC_SEEK_CUR :
+ fseek_origin = SEEK_CUR;
+ break;
+ case ZLIB_FILEFUNC_SEEK_END :
+ fseek_origin = SEEK_END;
+ break;
+ case ZLIB_FILEFUNC_SEEK_SET :
+ fseek_origin = SEEK_SET;
+ break;
+ default: return -1;
+ }
+ ret = 0;
+ if (fseek((FILE *)stream, (long)offset, fseek_origin) != 0)
+ ret = -1;
+ return ret;
+}
+
+static long ZCALLBACK fseek64_file_func(voidpf opaque, voidpf stream, ZPOS64_T offset, int origin) {
+ int fseek_origin=0;
+ long ret;
+ (void)opaque;
+ switch (origin)
+ {
+ case ZLIB_FILEFUNC_SEEK_CUR :
+ fseek_origin = SEEK_CUR;
+ break;
+ case ZLIB_FILEFUNC_SEEK_END :
+ fseek_origin = SEEK_END;
+ break;
+ case ZLIB_FILEFUNC_SEEK_SET :
+ fseek_origin = SEEK_SET;
+ break;
+ default: return -1;
+ }
+ ret = 0;
+
+ if(FSEEKO_FUNC((FILE *)stream, (z_off64_t)offset, fseek_origin) != 0)
+ ret = -1;
+
+ return ret;
+}
+
+
+static int ZCALLBACK fclose_file_func(voidpf opaque, voidpf stream) {
+ int ret;
+ (void)opaque;
+ ret = fclose((FILE *)stream);
+ return ret;
+}
+
+static int ZCALLBACK ferror_file_func(voidpf opaque, voidpf stream) {
+ int ret;
+ (void)opaque;
+ ret = ferror((FILE *)stream);
+ return ret;
+}
+
+void fill_fopen_filefunc(zlib_filefunc_def* pzlib_filefunc_def) {
+ pzlib_filefunc_def->zopen_file = fopen_file_func;
+ pzlib_filefunc_def->zread_file = fread_file_func;
+ pzlib_filefunc_def->zwrite_file = fwrite_file_func;
+ pzlib_filefunc_def->ztell_file = ftell_file_func;
+ pzlib_filefunc_def->zseek_file = fseek_file_func;
+ pzlib_filefunc_def->zclose_file = fclose_file_func;
+ pzlib_filefunc_def->zerror_file = ferror_file_func;
+ pzlib_filefunc_def->opaque = NULL;
+}
+
+void fill_fopen64_filefunc(zlib_filefunc64_def* pzlib_filefunc_def) {
+ pzlib_filefunc_def->zopen64_file = fopen64_file_func;
+ pzlib_filefunc_def->zread_file = fread_file_func;
+ pzlib_filefunc_def->zwrite_file = fwrite_file_func;
+ pzlib_filefunc_def->ztell64_file = ftell64_file_func;
+ pzlib_filefunc_def->zseek64_file = fseek64_file_func;
+ pzlib_filefunc_def->zclose_file = fclose_file_func;
+ pzlib_filefunc_def->zerror_file = ferror_file_func;
+ pzlib_filefunc_def->opaque = NULL;
+}
diff --git a/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-ftp-fota/rock_ua/ioapi.h b/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-ftp-fota/rock_ua/ioapi.h
new file mode 100755
index 0000000..c588a18
--- /dev/null
+++ b/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-ftp-fota/rock_ua/ioapi.h
@@ -0,0 +1,210 @@
+/* ioapi.h -- IO base function header for compress/uncompress .zip
+ part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )
+
+ Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )
+
+ Modifications for Zip64 support
+ Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
+
+ For more info read MiniZip_info.txt
+
+ Changes
+
+ Oct-2009 - Defined ZPOS64_T to fpos_t on windows and u_int64_t on linux. (might need to find a better why for this)
+ Oct-2009 - Change to fseeko64, ftello64 and fopen64 so large files would work on linux.
+ More if/def section may be needed to support other platforms
+ Oct-2009 - Defined fxxxx64 calls to normal fopen/ftell/fseek so they would compile on windows.
+ (but you should use iowin32.c for windows instead)
+
+*/
+
+#ifndef _ZLIBIOAPI64_H
+#define _ZLIBIOAPI64_H
+
+#if (!defined(_WIN32)) && (!defined(WIN32)) && (!defined(__APPLE__))
+
+ // Linux needs this to support file operation on files larger then 4+GB
+ // But might need better if/def to select just the platforms that needs them.
+
+ #ifndef __USE_FILE_OFFSET64
+ #define __USE_FILE_OFFSET64
+ #endif
+ #ifndef __USE_LARGEFILE64
+ #define __USE_LARGEFILE64
+ #endif
+ #ifndef _LARGEFILE64_SOURCE
+ #define _LARGEFILE64_SOURCE
+ #endif
+ #ifndef _FILE_OFFSET_BIT
+ #define _FILE_OFFSET_BIT 64
+ #endif
+
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "zlib.h"
+
+#if defined(USE_FILE32API)
+#define fopen64 fopen
+#define ftello64 ftell
+#define fseeko64 fseek
+#else
+#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__HAIKU__) || defined(MINIZIP_FOPEN_NO_64)
+#define fopen64 fopen
+#define ftello64 ftello
+#define fseeko64 fseeko
+#endif
+#ifdef _MSC_VER
+ #define fopen64 fopen
+ #if (_MSC_VER >= 1400) && (!(defined(NO_MSCVER_FILE64_FUNC)))
+ #define ftello64 _ftelli64
+ #define fseeko64 _fseeki64
+ #else // old MSC
+ #define ftello64 ftell
+ #define fseeko64 fseek
+ #endif
+#endif
+#endif
+
+/*
+#ifndef ZPOS64_T
+ #ifdef _WIN32
+ #define ZPOS64_T fpos_t
+ #else
+ #include <stdint.h>
+ #define ZPOS64_T uint64_t
+ #endif
+#endif
+*/
+
+#ifdef HAVE_MINIZIP64_CONF_H
+#include "mz64conf.h"
+#endif
+
+/* a type chosen by DEFINE */
+#ifdef HAVE_64BIT_INT_CUSTOM
+typedef 64BIT_INT_CUSTOM_TYPE ZPOS64_T;
+#else
+#ifdef HAS_STDINT_H
+#include "stdint.h"
+typedef uint64_t ZPOS64_T;
+#else
+
+
+
+#if defined(_MSC_VER) || defined(__BORLANDC__)
+typedef unsigned __int64 ZPOS64_T;
+#else
+typedef unsigned long long int ZPOS64_T;
+#endif
+#endif
+#endif
+
+/* Maximum unsigned 32-bit value used as placeholder for zip64 */
+#ifndef MAXU32
+#define MAXU32 (0xffffffff)
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#define ZLIB_FILEFUNC_SEEK_CUR (1)
+#define ZLIB_FILEFUNC_SEEK_END (2)
+#define ZLIB_FILEFUNC_SEEK_SET (0)
+
+#define ZLIB_FILEFUNC_MODE_READ (1)
+#define ZLIB_FILEFUNC_MODE_WRITE (2)
+#define ZLIB_FILEFUNC_MODE_READWRITEFILTER (3)
+
+#define ZLIB_FILEFUNC_MODE_EXISTING (4)
+#define ZLIB_FILEFUNC_MODE_CREATE (8)
+
+
+#ifndef ZCALLBACK
+ #if (defined(WIN32) || defined(_WIN32) || defined (WINDOWS) || defined (_WINDOWS)) && defined(CALLBACK) && defined (USEWINDOWS_CALLBACK)
+ #define ZCALLBACK CALLBACK
+ #else
+ #define ZCALLBACK
+ #endif
+#endif
+
+
+
+
+typedef voidpf (ZCALLBACK *open_file_func) (voidpf opaque, const char* filename, int mode);
+typedef uLong (ZCALLBACK *read_file_func) (voidpf opaque, voidpf stream, void* buf, uLong size);
+typedef uLong (ZCALLBACK *write_file_func) (voidpf opaque, voidpf stream, const void* buf, uLong size);
+typedef int (ZCALLBACK *close_file_func) (voidpf opaque, voidpf stream);
+typedef int (ZCALLBACK *testerror_file_func) (voidpf opaque, voidpf stream);
+
+typedef long (ZCALLBACK *tell_file_func) (voidpf opaque, voidpf stream);
+typedef long (ZCALLBACK *seek_file_func) (voidpf opaque, voidpf stream, uLong offset, int origin);
+
+
+/* here is the "old" 32 bits structure structure */
+typedef struct zlib_filefunc_def_s
+{
+ open_file_func zopen_file;
+ read_file_func zread_file;
+ write_file_func zwrite_file;
+ tell_file_func ztell_file;
+ seek_file_func zseek_file;
+ close_file_func zclose_file;
+ testerror_file_func zerror_file;
+ voidpf opaque;
+} zlib_filefunc_def;
+
+typedef ZPOS64_T (ZCALLBACK *tell64_file_func) (voidpf opaque, voidpf stream);
+typedef long (ZCALLBACK *seek64_file_func) (voidpf opaque, voidpf stream, ZPOS64_T offset, int origin);
+typedef voidpf (ZCALLBACK *open64_file_func) (voidpf opaque, const void* filename, int mode);
+
+typedef struct zlib_filefunc64_def_s
+{
+ open64_file_func zopen64_file;
+ read_file_func zread_file;
+ write_file_func zwrite_file;
+ tell64_file_func ztell64_file;
+ seek64_file_func zseek64_file;
+ close_file_func zclose_file;
+ testerror_file_func zerror_file;
+ voidpf opaque;
+} zlib_filefunc64_def;
+
+void fill_fopen64_filefunc(zlib_filefunc64_def* pzlib_filefunc_def);
+void fill_fopen_filefunc(zlib_filefunc_def* pzlib_filefunc_def);
+
+/* now internal definition, only for zip.c and unzip.h */
+typedef struct zlib_filefunc64_32_def_s
+{
+ zlib_filefunc64_def zfile_func64;
+ open_file_func zopen32_file;
+ tell_file_func ztell32_file;
+ seek_file_func zseek32_file;
+} zlib_filefunc64_32_def;
+
+
+#define ZREAD64(filefunc,filestream,buf,size) ((*((filefunc).zfile_func64.zread_file)) ((filefunc).zfile_func64.opaque,filestream,buf,size))
+#define ZWRITE64(filefunc,filestream,buf,size) ((*((filefunc).zfile_func64.zwrite_file)) ((filefunc).zfile_func64.opaque,filestream,buf,size))
+//#define ZTELL64(filefunc,filestream) ((*((filefunc).ztell64_file)) ((filefunc).opaque,filestream))
+//#define ZSEEK64(filefunc,filestream,pos,mode) ((*((filefunc).zseek64_file)) ((filefunc).opaque,filestream,pos,mode))
+#define ZCLOSE64(filefunc,filestream) ((*((filefunc).zfile_func64.zclose_file)) ((filefunc).zfile_func64.opaque,filestream))
+#define ZERROR64(filefunc,filestream) ((*((filefunc).zfile_func64.zerror_file)) ((filefunc).zfile_func64.opaque,filestream))
+
+voidpf call_zopen64(const zlib_filefunc64_32_def* pfilefunc,const void*filename,int mode);
+long call_zseek64(const zlib_filefunc64_32_def* pfilefunc,voidpf filestream, ZPOS64_T offset, int origin);
+ZPOS64_T call_ztell64(const zlib_filefunc64_32_def* pfilefunc,voidpf filestream);
+
+void fill_zlib_filefunc64_32_def_from_filefunc32(zlib_filefunc64_32_def* p_filefunc64_32,const zlib_filefunc_def* p_filefunc32);
+
+#define ZOPEN64(filefunc,filename,mode) (call_zopen64((&(filefunc)),(filename),(mode)))
+#define ZTELL64(filefunc,filestream) (call_ztell64((&(filefunc)),(filestream)))
+#define ZSEEK64(filefunc,filestream,pos,mode) (call_zseek64((&(filefunc)),(filestream),(pos),(mode)))
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-ftp-fota/rock_ua/lynq_fota_zip_file.cpp b/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-ftp-fota/rock_ua/lynq_fota_zip_file.cpp
new file mode 100755
index 0000000..94c3eae
--- /dev/null
+++ b/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-ftp-fota/rock_ua/lynq_fota_zip_file.cpp
@@ -0,0 +1,91 @@
+#include <iostream>
+#include "zlib.h"
+#include <vector>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include "unzip.h"
+#include "lynq_fota_file.h"
+
+static unzFile g_zip_file = NULL;
+static int g_org_type = 0;
+
+//curl -o test.dat ftp://cv2x:lynq@192.168.1.100:6521/T800_RTK_TMP/fota.delta -r 100-599
+
+static inline int zip_file_to_int()
+{
+ int *p = (int*)&g_zip_file;
+ return *p;
+}
+
+int lynq_fota_open(const char * pathname, const char * file_name, int flags)
+{
+ g_org_type = 0;
+
+ printf("cy: to pen %s\n", pathname);
+ if (file_name == NULL)
+ {
+ g_org_type = 1;
+ //printf("cy: to open org type %s\n", pathname);
+ return open(pathname, flags);
+ }
+ //printf("cy: org file name %s\n", file_name);
+ g_zip_file = unzOpen(pathname);
+ if (g_zip_file == NULL)
+ {
+ printf("cy: open zip file fail\n");
+ return -1;
+ }
+ if (UNZ_OK != unzLocateFile(g_zip_file, file_name, 0))
+ {
+ //printf("goto file fail [%s]\n", file_name);
+ unzClose(g_zip_file);
+ return -1;
+ }
+ if (UNZ_OK != unzOpenCurrentFile(g_zip_file))
+ {
+ //printf("open file fail\n");
+ unzClose(g_zip_file);
+ return -1;
+ }
+ return zip_file_to_int();
+}
+
+ssize_t lynq_fota_read(int fd, void *buf, size_t count)
+{
+ //printf("cy: read file %d, %d\n", fd, count);
+ if (g_org_type)
+ {
+ return read(fd, buf, count);
+ }
+
+ //printf("cy: read file %d, %d\n", fd, count);
+
+ if (fd != zip_file_to_int())
+ return -1;
+
+ return unzReadCurrentFile(g_zip_file, buf, count);
+}
+
+ssize_t lynq_fota_write(int fd, const void *buf, size_t count)
+{
+ if (g_org_type)
+ {
+ return write(fd, buf, count);
+ }
+ return -1;
+}
+
+int lynq_fota_close(int fd)
+{
+ //printf("cy: lynq_fota_close %d, %d\n", fd, g_org_type);
+ if (g_org_type)
+ {
+ return close(fd);
+ }
+ g_org_type = 0;
+ if (fd != zip_file_to_int())
+ return -1;
+ unzCloseCurrentFile(g_zip_file);
+ return unzClose(g_zip_file);
+}
diff --git a/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-ftp-fota/rock_ua/rock_ua.cpp b/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-ftp-fota/rock_ua/rock_ua.cpp
new file mode 100755
index 0000000..5fd004f
--- /dev/null
+++ b/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-ftp-fota/rock_ua/rock_ua.cpp
@@ -0,0 +1,2122 @@
+// 2017-07-31 carota Rock FOTA ua porting file
+
+
+#define ROCK_FOTA_SUPPORT
+
+#ifdef ROCK_FOTA_SUPPORT
+
+
+extern "C" {
+#include "iot_rock.h"
+#include "iot_rock_ipl.h"
+#include "base64.h"
+};
+
+#include "sha.h"
+#include <log/log.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <dlfcn.h>
+#include <stdint.h>
+
+
+#include <hardware/boot_control.h>
+#include <hardware/hardware.h>
+#include <sys/reboot.h>
+
+
+
+#include "liblog/lynq_deflog.h"
+#include "mtk_device_wrap.h"
+#include <include/lynq_uci.h>
+#include "lynq_fota_file.h"
+
+#define ROCK_DEFAULT_BLOCK_SIZE 0x40000
+#define ROCK_RAM_LEN (1024*1024)
+
+#define LOG_TAG "LYNQ_FOTA"
+#define ROCK_BACKUP_LEN ROCK_DEFAULT_BLOCK_SIZE
+
+
+#define FILENAME_SIZE 50
+
+char full_partition_filename[REAL_OTA_ROLE][FILENAME_SIZE];
+
+struct fota_header{
+ unsigned int delta_head[DELTA_HEARD_SIZE/sizeof(unsigned int)];
+ char full_type[DELTA_FULL_HEARD_SIZE];
+};
+
+struct fota_header g_header;
+
+
+#define FOTA_UCI_MODULE "lynq_fota"
+#define FOTA_UCI_FILE "lynq_uci"
+#define FOTA_UCI_ADDR "lynq_fota_addr"
+#define FOTA_UCI_STATE "lynq_fota_state"
+
+#define FILE_UPDATE_STATE "/data/.update_status"
+#define FILE_UPDATE_FLAG "/tmp/update_flag"
+#define FILE_FOTA_STATE "/data/.fota_status"
+
+#define NAND_PAGE_SIZE 4096
+
+
+#define BOOTDEV_TYPE_NAND 1
+
+#define BACKUP_ADDR_FLAG 0xffffffff
+#define FILE_BACKUP "/data/.backup"
+
+#define SLOT_A 0
+#define SLOT_B 1
+
+#define FULL_HEAD "full-zip"
+
+//xf.li@20230822 add for ab rollback start
+#define DEV_SYSTEM_A "/dev/disk/by-partlabel/system_a"
+#define DEV_SYSTEM_B "/dev/disk/by-partlabel/system_b"
+
+#define DEV_BOOT_A "/dev/disk/by-partlabel/boot_a"
+#define DEV_BOOT_B "/dev/disk/by-partlabel/boot_b"
+
+#define DEV_SPM_A "/dev/disk/by-partlabel/spm_a"
+#define DEV_SPM_B "/dev/disk/by-partlabel/spm_b"
+
+#define DEV_MD1IMG_A "/dev/disk/by-partlabel/md1img_a"
+#define DEV_MD1IMG_B "/dev/disk/by-partlabel/md1img_b"
+
+#define DEV_TEE_A "/dev/disk/by-partlabel/tee_a"
+#define DEV_TEE_B "/dev/disk/by-partlabel/tee_b"
+
+#define DEV_VBMETA_A "/dev/disk/by-partlabel/vbmeta_a"
+#define DEV_VBMETA_B "/dev/disk/by-partlabel/vbmeta_b"
+
+#define DEV_BL2_A "/dev/disk/by-partlabel/bl2_a"
+#define DEV_BL2_B "/dev/disk/by-partlabel/bl2_b"
+
+#define DEV_BL33_A "/dev/disk/by-partlabel/bl33_a"
+#define DEV_BL33_B "/dev/disk/by-partlabel/bl33_b"
+
+#define DEV_MEDMCU_A "/dev/disk/by-partlabel/medmcu_a"
+#define DEV_MEDMCU_B "/dev/disk/by-partlabel/medmcu_b"
+
+#define DEV_OEMAPP_A "/dev/disk/by-partlabel/oemapp_a"
+#define DEV_OEMAPP_B "/dev/disk/by-partlabel/oemapp_b"
+
+#define DEV_OEMAPP2_A "/dev/disk/by-partlabel/oemapp2_a"
+#define DEV_OEMAPP2_B "/dev/disk/by-partlabel/oemapp2_b"
+
+
+#define DEV_MISC "/dev/disk/by-partlabel/misc"
+
+#define BACKUP_UBI_NUM 31 //max ubi number
+#define MTD_SYSTEM_A 14
+#define MTD_SYSTEM_B 15
+#define MD5_RETRY_TIME 3
+#define MD5_VERFY_ERROR 5
+#define MD5_READ_BUFFER_LEN 4*1024
+#define FOTA_FIRST 0
+#define RECOVER_FIRST 1
+int fota_interrupt = 1;
+//xf.li@20230822 add for ab rollback end
+
+
+//int fd_system_a,fd_system_b,fd_boot_a,fd_boot_b,fd_tee_a,fd_tee_b,fd_bl2,fd_bl33,fd_curr,fd_log,fd_update_status,fd_md1img_a,fd_md1img_b,fd_fota_status,fd_md1dsp_a,fd_md1dsp_b,fd_vbmeta_a,fd_vbmeta_b,fd_oemapp_a,fd_oemapp_b,fd_oemapp2_a,fd_oemapp2_b,fd_medmcu_a,fd_medmcu_b,fd_bl33_a,fd_bl33_b;
+int fd_curr,fd_log,fd_update_status,fd_fota_status;
+int fd_write,fd_read;
+int full_partition_num;
+static unsigned int delta_offset = 0;
+static unsigned int now_patch = 0;
+unsigned int current_slot = 0;
+unsigned char rock_debug_buffer[512];
+
+extern const hw_module_t HAL_MODULE_INFO_SYM;
+boot_control_module_t* module;
+
+static void lynq_init_wake_lock_func(void);
+static void lynq_fota_grab_artial_wake_lock(void);
+static void lynq_fota_release_wake_lock(void);
+int check(int sys_size);
+int check_cpu();
+
+
+#include <string>
+#include <vector>
+
+class PartitionInfo
+{
+public:
+ std::string dest_part_name;
+ std::string org_file_name;
+ unsigned int file_offset;
+ unsigned int part_org_size;
+ unsigned int part_size;
+ unsigned int zip_flag;
+ unsigned int part_index;
+ char part_sha[SHA_DIGEST_SIZE];
+ PartitionInfo(){
+ file_offset = -1;
+ part_org_size = -1;
+ part_size = -1;
+ zip_flag = -1;
+ part_index = -1;
+ dest_part_name = "";
+ org_file_name = "";
+ memset(part_sha, 0 , SHA_DIGEST_SIZE);
+ }
+ PartitionInfo(const PartitionInfo &org){
+ if (this == &org)
+ return;
+ this->file_offset = org.file_offset;
+ this->part_org_size = org.part_org_size;
+ this->part_size = org.part_size;
+ this->zip_flag = org.zip_flag;
+ this->part_index = org.part_index;
+ memcpy(this->part_sha, org.part_sha, SHA_DIGEST_SIZE);
+ this->dest_part_name = org.dest_part_name;
+ this->org_file_name = org.org_file_name;
+ }
+ PartitionInfo& operator=(const PartitionInfo& org) {
+ if (this == &org)
+ return *this;
+ this->file_offset = org.file_offset;
+ this->part_org_size = org.part_org_size;
+ this->part_size = org.part_size;
+ this->zip_flag = org.zip_flag;
+ this->part_index = org.part_index;
+ memcpy(this->part_sha, org.part_sha, SHA_DIGEST_SIZE);
+ this->dest_part_name = org.dest_part_name;
+ this->org_file_name = org.org_file_name;
+ return *this;
+ }
+};
+
+struct partition_desc
+{
+ int part_index;
+ int zip_flag;
+ int part_size;
+ int part_org_size;
+ char sha_value[SHA_DIGEST_SIZE];
+};
+
+std::vector<PartitionInfo> g_lstPartitionInfo;
+std::string g_strFtpAddress;
+
+class FotaTool {
+public:
+ FotaTool() {
+ m_bLockState = false;
+ }
+ ~FotaTool() {
+ if (m_fdFotaFlag >= 0)
+ close(m_fdFotaFlag);
+ ClosePartionFile();
+
+ system("echo fota-interface >/sys/power/wake_unlock");
+ m_bLockState = false;
+ }
+ bool Init() {
+ m_fdFotaFlag = open(FILE_UPDATE_FLAG,O_RDWR | O_CREAT,0777);
+ if (m_fdFotaFlag < 0)
+ {
+ RLOGE("+[UA]: can't open file /tmp/update_flag.\n");
+ return false;
+ }
+ m_strTempFileName = "/tmp/ftp_fota_part";
+ m_fdLocalFile =-1;
+ const hw_module_t* hw_module = &HAL_MODULE_INFO_SYM;
+
+ if (!hw_module ||
+ strcmp(BOOT_CONTROL_HARDWARE_MODULE_ID, hw_module->id) != 0) {
+ RLOGD("+[UA]: Error loading boot_control HAL implementation.\n");
+ return false;
+ }
+
+ module = (boot_control_module_t*)hw_module;
+ module->init(module);
+
+
+ if (module == NULL) {
+ RLOGD("+[UA]: Error getting bootctrl module.\n");
+ return false;
+ }
+
+ lynq_init_wake_lock_func();
+ lynq_fota_grab_artial_wake_lock();
+ /************* Bootctrl Init End *************/
+
+ m_bLockState = true;
+ return m_bLockState;
+ }
+ bool PreparePartionFile(PartitionInfo * pt_info)
+ {
+ int ret, fd;
+ char digest_s[SHA_DIGEST_SIZE];
+ m_pPartitionInfo = pt_info;
+ ClosePartionFile();
+ std::string range = " -r ";
+ if (pt_info->part_size == -1)
+ {
+ range += std::to_string(pt_info->file_offset);
+ }
+ else
+ {
+ range += std::to_string(pt_info->file_offset) + "-" + std::to_string(pt_info->file_offset + pt_info->part_size - 1);
+ }
+ std::string strFtpCmd = "curl -o " + m_strTempFileName + " " + g_strFtpAddress + range;
+
+ ret = system(strFtpCmd.c_str());
+ if (ret < 0)
+ {
+ RLOGE("+[UA]: down load file fail [ %s ]\n", strFtpCmd.c_str());
+ return false;
+ }
+ if (pt_info->org_file_name != "")
+ {
+ memset(digest_s,0,SHA_DIGEST_SIZE);
+
+ fd=open(m_strTempFileName.c_str(),O_RDONLY);
+ ROCK_SHA_FILE_COMMON(fd ,0 ,pt_info->part_size, digest_s);
+ close(fd);
+ if (memcmp(digest_s, pt_info->part_sha, SHA_DIGEST_SIZE) != 0)
+ {
+ RLOGE("+[UA]: sha check fail [ %s ]\n", pt_info->org_file_name.c_str());
+ return false;
+ }
+ }
+ m_fdLocalFile = lynq_fota_open(m_strTempFileName.c_str(), pt_info->zip_flag == 0 ? NULL : pt_info->org_file_name.c_str(), O_RDONLY);
+ return m_fdLocalFile >= 0;
+ }
+ int ReadPartionFileData(void *buf, size_t count)
+ {
+ //printf("cy: to read file %d\n", count);
+ if (m_fdLocalFile < 0)
+ return -1;
+ return lynq_fota_read(m_fdLocalFile, buf, count);
+ }
+ int ClosePartionFile()
+ {
+ if (m_fdLocalFile < 0)
+ return 0;
+ int ret = lynq_fota_close(m_fdLocalFile);
+ if (access(m_strTempFileName.c_str(), F_OK) != -1)
+ remove(m_strTempFileName.c_str());
+ m_fdLocalFile = -1;
+ return ret;
+ }
+private:
+ int m_fdFotaFlag;
+ bool m_bLockState;
+ std::string m_strTempFileName;
+ int m_fdLocalFile;
+ PartitionInfo * m_pPartitionInfo;
+};
+
+OTA_STATUS fota_status;
+UPDATE_INFO up_info;
+
+static const char hex_chars[] = "0123456789abcdef";
+
+/**
+ * @brief The following is the wake up
+ * start
+ */
+
+#define ANDROID_WAKE_LOCK_NAME "fota-interface"
+
+void *dlHandle_wakelock;
+
+enum {
+ PARTIAL_WAKE_LOCK = 1, // the cpu stays on, but the screen is off
+ FULL_WAKE_LOCK = 2 // the screen is also on
+};
+
+// while you have a lock held, the device will stay on at least at the
+// level you request.
+
+int (*acquire_wake_lock)(int lock, const char* id);
+int (*release_wake_lock)(const char* id);
+
+void convert_hex(unsigned char *sha, unsigned char *shastr)
+{
+ int i;
+ int j = 0;
+ unsigned int c;
+
+ for (i = 0; i < 20; i++) {
+ c = (sha[i] >> 4) & 0x0f;
+ shastr[j++] = hex_chars[c];
+ shastr[j++] = hex_chars[sha[i] & 0x0f];
+ }
+ shastr[40] = '\0';
+}
+
+
+
+
+int rock_mismatch(void* ctx, unsigned char* buf, unsigned int start, unsigned int size,
+ unsigned int source_hash,unsigned int target_hash) {
+
+ return 0;
+}
+
+int rock_fatal(void* ctx, int error_code) {
+ return 0;
+}
+
+void rock_trace(void* ctx, const char* fmt, ...) {
+
+ va_list ap;
+ memset(rock_debug_buffer,0x0,sizeof(rock_debug_buffer));
+ va_start (ap, fmt);
+
+
+ vsnprintf(rock_debug_buffer,sizeof(rock_debug_buffer),fmt,ap);
+ LYDBGLOG("+[UA]: %s",rock_debug_buffer);
+
+
+ va_end (ap);
+
+}
+
+static int save_fota_status()
+{
+ int err;
+ fd_fota_status = open(FILE_FOTA_STATE,O_RDWR | O_CREAT,0777);
+
+ if (fd_fota_status < 0) {
+ err = errno;
+ RLOGD("+[UA]: save_fota_status: Error opening metadata file: %s\n",strerror(errno));
+ return -err;
+ }
+
+ write(fd_fota_status, &fota_status,sizeof(fota_status));
+ sync();
+
+ close(fd_fota_status);
+}
+
+int lynq_read_process(void)
+{
+ int err;
+ fd_fota_status = open(FILE_FOTA_STATE,O_RDWR | O_CREAT,0777);
+
+ if (fd_fota_status < 0) {
+ err = errno;
+ RLOGD("+[UA]: save_fota_status: Error opening metadata file: %s\n",strerror(errno));
+ return -err;
+ }
+ memset(&fota_status, 0 , sizeof(fota_status));
+ read(fd_fota_status, &fota_status,sizeof(fota_status));
+ sync();
+ close(fd_fota_status);
+ return fota_status.ota_run;
+}
+
+static int save_fota_info()
+{
+ int err;
+ fd_update_status = open(FILE_UPDATE_STATE,O_RDWR);
+
+ if (fd_update_status < 0) {
+ err = errno;
+ RLOGD("+[UA]: save_fota_status: Error opening metadata file: %s\n",strerror(errno));
+ return -err;
+ }
+
+ write(fd_update_status, &up_info, sizeof(fota_status));
+ sync();
+ close(fd_update_status);
+}
+
+
+
+void rock_progress(void* ctx, int percent) {
+ int i = 0;
+ static int tmp_percent = -1;
+ rock_trace(ctx, "rock update progress %d\n", percent);
+
+ if (tmp_percent != percent) {
+ tmp_percent = percent;
+ if (percent > 20) {
+ i = fota_status.ota_run;
+ if (fota_status.update_status[i-1].check_delta != PASS) {
+ fota_status.update_status[i-1].check_delta = PASS;
+ fota_status.update_status[i-1].check_rom= PASS;
+ save_fota_status();
+ }
+ }
+ }
+}
+
+int rock_process_block(void* ctx, unsigned char* data, unsigned int start, unsigned int size){
+
+ int writen = 0;
+ int ret,err;
+
+ if (start == BACKUP_ADDR_FLAG) {
+ int fd_backup = open(FILE_BACKUP,O_RDWR | O_CREAT,0777);
+ while (writen < size) {
+ write(fd_backup,data,ROCK_DEFAULT_BLOCK_SIZE);
+ sync();
+ writen += ROCK_DEFAULT_BLOCK_SIZE;
+ }
+ close(fd_backup);
+ return size;
+ }
+
+ writen = 0;
+
+ if (mtk_device_wrap_seek(fd_write, start, SEEK_SET) < 0) {
+ err = errno;
+ rock_trace(ctx, "mtk_device_wrap_seek write\n");
+ return err;
+ }
+
+ while (writen < size) {
+ ret = mtk_device_wrap_write(fd_write,data+writen, ROCK_DEFAULT_BLOCK_SIZE);
+ writen += ROCK_DEFAULT_BLOCK_SIZE;
+ }
+
+
+ return size;
+}
+
+int rock_write_block(void* ctx, unsigned char* src, unsigned int start, unsigned int size){
+
+#if 0
+
+ int writen = 0;
+ int ret,err;
+
+
+ if (start == BACKUP_ADDR_FLAG) {
+ int fd_backup = open(FILE_BACKUP,O_RDWR | O_CREAT,0777);
+ while (writen < size) {
+ write(fd_backup,src,ROCK_DEFAULT_BLOCK_SIZE);
+ sync();
+ writen += ROCK_DEFAULT_BLOCK_SIZE;
+ }
+ close(fd_backup);
+ return size;
+ }
+
+ writen = 0;
+
+ if (mtk_device_wrap_seek(fd_curr, start, SEEK_SET) < 0) {
+ err = errno;
+ rock_trace(ctx, "mtk_device_wrap_seek write\n");
+ return err;
+ }
+
+ while (writen < size) {
+ ret = mtk_device_wrap_write(fd_curr,src+writen, ROCK_DEFAULT_BLOCK_SIZE);
+ writen += ROCK_DEFAULT_BLOCK_SIZE;
+ }
+
+
+#endif
+
+ return size;
+
+}
+
+int rock_read_block(void* ctx, unsigned char* dest, unsigned int start, unsigned int size){
+
+
+ int ret,err;
+
+
+ if (start == BACKUP_ADDR_FLAG) {
+ int fd_backup = open(FILE_BACKUP,O_RDONLY);
+ read(fd_backup,dest,size);
+ sync();
+ close(fd_backup);
+ return size;
+ }
+
+
+
+ if (mtk_device_wrap_seek(fd_read, start, SEEK_SET) < 0) {
+ err = errno;
+ rock_trace(ctx, "mtk_device_wrap_seek read block err\n");
+ }
+
+ do {
+
+ ret = mtk_device_wrap_read(fd_read, dest, size);
+
+ if (ret == 0) {
+ break;
+ } else if (ret < 0) {
+ if (errno == EINTR) {
+ continue;
+ }
+ err = -errno;
+ rock_trace(ctx,"%s Error reading metadata file\n");
+
+ mtk_device_wrap_close(fd_read);
+
+ return err;
+ }
+ size -= ret;
+ dest += ret;
+ } while(size > 0);
+
+
+ return ret;
+
+
+}
+
+
+int rock_get_blocksize(void* ctx) {
+ return ROCK_DEFAULT_BLOCK_SIZE;
+}
+
+int rock_read_file(void* ctx, void* name, unsigned char* dest, unsigned int offset, unsigned int size){return 0;}
+int rock_write_file(void* ctx, void* name, unsigned char* src, unsigned int offset, unsigned int size){return 0;}
+int rock_delete_file(void* ctx, void* name){return 0;}
+/* ROCK IPL end */
+
+void delete_enter(char data[])
+{
+ char *find = strchr(data, ':');
+ if(find)
+ *find = '\0';
+ return ;
+}
+
+static void func_buf(char* str)
+{
+ char* dest = str;
+ while (*str) {
+ if (*str != '"' && *str != '\n') {
+ *dest++ = *str;
+ }
+ str++;
+ }
+ *dest = '\0';
+ return ;
+}
+
+int get_full_filename(void)
+{
+ int i;
+ int len;
+ FILE *fp;
+ char buffer[64];
+ fp = popen("cat /proc/mtd|grep _a|awk '{print $4}'","r");
+ i = 0;
+ while(fgets(buffer, 63, fp) != NULL)
+ {
+ func_buf(buffer);
+ len = strlen(buffer);
+ buffer[len -2] = '\0';
+ strcpy(full_partition_filename[i],buffer);
+ RLOGD("full_partition_filename[%d]:%s\n", i, full_partition_filename[i]);
+ i++;
+ }
+ pclose(fp);
+ full_partition_num = i;
+ return 0;
+}
+
+
+static int init_dev_fd()
+{
+
+ int err;
+ int ret;
+ int result;
+ char lynq_fota_addr[128] = {0};
+ char ftp_addr[128] = {0};
+ char fota_name[]= "fota.delta";
+ int n;
+ size_t size = 1024;
+ ret = lynq_fota_get_addr_value(lynq_fota_addr);
+ if(0 != ret)
+ {
+ RLOGE("+[UA]: lynq_fota_get_addr_value fail %d\n", ret);
+ return E_ROCK_FOTA_ADDR;
+ }
+ RLOGD("+[UA]: get fota pack addr: %s\n",lynq_fota_addr);
+ if (!base64_dec(lynq_fota_addr, strlen(lynq_fota_addr), ftp_addr, &size))
+ {
+ RLOGE("+[UA]: base64_dec fota addr fail\n");
+ return E_ROCK_FOTA_ADDR;
+ }
+ g_strFtpAddress = ftp_addr;
+ RLOGD("+[UA]: get fota pack addr: %s\n", g_strFtpAddress.c_str());
+
+ fd_update_status = open(FILE_UPDATE_STATE,O_RDWR | O_CREAT,0777);
+ if (fd_update_status < 0) {
+ err = errno;
+ RLOGD("+[UA]: Error opening metadata file: %s\n",strerror(errno));
+ return -err;
+ }
+ memset(&up_info, 0, sizeof(up_info));
+ lseek(fd_update_status,0,SEEK_SET);
+ read(fd_update_status,(unsigned char *)&up_info,sizeof(up_info));
+ close(fd_update_status);
+ return 0;
+}
+
+
+
+
+
+static int close_dev_fd(int fd)
+{
+ lynq_fota_close(fd);
+}
+
+
+
+static int reboot_device() {
+
+ reboot(RB_AUTOBOOT);
+
+ while (1) pause();
+}
+
+
+int nand_copyto_nand(char *source, char *target)
+{
+ int fd_source,fd_target,size;
+
+ char delta_data[ROCK_DEFAULT_BLOCK_SIZE];
+
+ fd_source = mtk_device_wrap_open(source,O_RDONLY);
+
+ if (fd_source < 0) {
+ RLOGD("+[UA]: open source error\n");
+ return 1;
+ }
+
+ fd_target = mtk_device_wrap_open(target,O_RDWR);
+
+ if (fd_target < 0) {
+ mtk_device_wrap_close(fd_target);
+ mtk_device_wrap_close(fd_source);
+ RLOGD("+[UA]: open target error\n");
+ return 1;
+ }
+
+ while(( size = mtk_device_wrap_read(fd_source,delta_data,ROCK_DEFAULT_BLOCK_SIZE))>0) {
+ mtk_device_wrap_write(fd_target,delta_data,ROCK_DEFAULT_BLOCK_SIZE);
+ }
+
+ mtk_device_wrap_close(fd_target);
+ mtk_device_wrap_close(fd_source);
+ return 0;
+}
+
+int delta_copyto_nand_new(FotaTool * tool, PartitionInfo * pi, uint8_t *digest)
+{
+
+ char delta_data[NAND_PAGE_SIZE];
+ unsigned int ret = 0;
+ int err, i, to_read = 0;
+ int size = pi->part_org_size;
+
+ const uint8_t *p;
+ SHA_CTX ctx;
+ SHA_init(&ctx);
+
+ if (!tool->PreparePartionFile(pi)) {
+ LYERRLOG("+[UA]: delta_copyto_nand prepare err\n");
+ return -1;
+ }
+
+ if (mtk_device_wrap_seek(fd_curr, 0, SEEK_SET) < 0) {
+ LYERRLOG("+[UA]: delta_copyto_nand seek err\n");
+ return -1;
+ }
+
+
+ do {
+ memset(delta_data,0xff,NAND_PAGE_SIZE);
+ to_read = NAND_PAGE_SIZE;
+ if (size < to_read)
+ to_read = size;
+ ret = tool->ReadPartionFileData(delta_data, to_read);
+
+ if (ret == 0) {
+ break;
+ } else if (ret < 0) {
+ if (errno == EINTR) {
+ continue;
+ }
+ err = -errno;
+
+ return err;
+ }
+
+ SHA_update(&ctx, delta_data, ret);
+ size -= NAND_PAGE_SIZE;
+ mtk_device_wrap_write(fd_curr,delta_data,NAND_PAGE_SIZE);
+ //mtk_device_wrap_write(fd_curr,delta_data,ret);
+
+ } while(size > 0);
+
+ p = SHA_final(&ctx);
+ for (i = 0; i < SHA_DIGEST_SIZE; ++i)
+ {
+ digest[i] = *p++;
+ }
+
+ return 0;
+
+}
+
+
+unsigned char ram_buffer[ROCK_RAM_LEN];
+
+/*
+int check(int sys_size)
+{
+ int fd;
+ int i=0;
+ int j=0;
+ int num=i;
+ int n = 0;
+ const uint8_t data[] = { 0x74, 0x77, 0x6f, 0x63, 0x6f, 0x72, 0x65};
+ const char * core_flag="twocore\n";
+
+ uint8_t buffer[16];
+
+ if(sys_size == 0)//for only upgrade oemapp and oemapp2
+ {
+ return 0;
+ }
+ n = strlen(core_flag);
+ lynq_fota_lseek(fd_delta,520,SEEK_SET);
+ lynq_fota_lseek(fd_delta,sys_size,SEEK_CUR);
+ lynq_fota_lseek(fd_delta, -1*n, SEEK_CUR);
+ lynq_fota_read(fd_delta, buffer, n);
+ lynq_fota_lseek(fd_delta,0,SEEK_SET);//file reset
+ if (memcmp(buffer, core_flag, n) == 0)
+ {
+ return 0;
+ }
+ return -1;
+
+}
+
+int check_cpu(void)
+{
+ int i=0;
+ int ret;
+ char buffer[3][64];
+ FILE *fp;
+ char num;
+ fp = popen("od -x /proc/device-tree/chosen/atag,devinfo","r");
+
+ for(i=0;i<3;i++)
+ {
+ fgets(buffer[i], 64, fp);
+ }
+
+ for(i=0;i<3;i++)
+ {
+ RLOGD("buffer[i] = %s\n",buffer[i]);
+ }
+ RLOGD("%c\n", buffer[2][14]);
+
+ num = buffer[2][14];
+
+
+ RLOGD("num=%c\n", num);
+ if(num == '0' || num == '1')
+ {
+ printf("this is four core\n");
+ return 4;
+ }
+ else if(num == '2' || num == '3')
+ {
+ printf("this is two core\n");
+ return 2;
+ }
+ else
+ {
+ RLOGD("this char is error\n");
+ return -1;
+ }
+ pclose(fp);
+
+ return -1;
+}
+*/
+static PartitionInfo * find_partition_info_by_index(int index)
+{
+ for(auto it = g_lstPartitionInfo.begin(); it != g_lstPartitionInfo.end(); ++it)
+ {
+ if (it->part_index == index)
+ return &*it;
+ }
+ return NULL;
+}
+static int prepare_header_and_check(FotaTool *pFotaTool)
+{
+ int i, size, total_read, count;
+ ssize_t file_offset = sizeof(g_header);
+ std::string left_data;
+ struct partition_desc * pDesc = NULL;
+ const char * pName = NULL;
+ const int max_partition_size = 1024*1024*250;
+ if (pFotaTool == NULL)
+ return -1;
+ for(i = MAX_OTA_ROLE/2;i<(MAX_OTA_ROLE/2+full_partition_num); i++) {
+ if (g_header.delta_head[i] > 0) {
+ fota_status.update_status[i].need_update = 1;
+
+ PartitionInfo pi;
+ pi.part_index = i-MAX_OTA_ROLE/2;
+ pi.zip_flag = 0;
+ pi.part_org_size = -1;
+ pi.org_file_name = "";
+ pi.dest_part_name = full_partition_filename[pi.part_index];
+ pi.file_offset = file_offset;
+ pi.part_size = g_header.delta_head[i];
+ file_offset += pi.part_size;
+ g_lstPartitionInfo.push_back(pi);
+ RLOGD("cy: count %d, last index %d, name %s\n",
+ g_lstPartitionInfo.size(), g_lstPartitionInfo.rbegin()->part_index,g_lstPartitionInfo.rbegin()->dest_part_name.c_str());
+ }
+ RLOGD("+[UA]: %s,full size = %d, i=%d\n",full_partition_filename[i-MAX_OTA_ROLE/2],g_header.delta_head[i], i);
+ }
+
+ PartitionInfo pi;
+ pi.part_index = -1;
+ pi.zip_flag = 0;
+ pi.file_offset = file_offset;
+ pi.part_size = -1;
+ pi.part_org_size = -1;
+ pi.org_file_name = "";
+
+ left_data.reserve(1024*1024);
+ total_read = 0;
+ if (!pFotaTool->PreparePartionFile(&pi))
+ return -1;
+ while(total_read < 1024 * 1023)
+ {
+ size = pFotaTool->ReadPartionFileData((char*)(left_data.c_str() + total_read), 1024);
+ if (size > 0)
+ total_read += size;
+ if (size < 1024)
+ break;
+ }
+
+ count = *(int*)(left_data.c_str());
+ if (count <=0 || count >= MAX_OTA_ROLE/2 )
+ {
+ RLOGE("+[UA]: get bad partition count %d\n", count);
+ return -1;
+ }
+
+ pDesc = (struct partition_desc *)(left_data.c_str() + sizeof(int));
+ pName = (const char*)(left_data.c_str() + sizeof(int) + count*sizeof(struct partition_desc));
+ for(i=0;i<count;i++)
+ {
+ if (pDesc->part_index < 0 || pDesc->part_index >= full_partition_num)
+ {
+ RLOGE("+[UA]: get bad partition desc %d, index %d\n", i, pDesc->part_index);
+ return -1;
+ }
+ if (pDesc->part_size <=0 || pDesc->part_size > max_partition_size ||
+ pDesc->part_org_size <=0 || pDesc->part_org_size > max_partition_size)
+ {
+ RLOGE("+[UA]: get bad partition desc %d, index %d, part_size %s, part_org_size %d \n",
+ i, pDesc->part_index, pDesc->part_size, pDesc->part_org_size);
+ return -1;
+ }
+ std::string name = pName;
+ auto pos = name.find(".");
+ if ( pos != std::string::npos)
+ {
+ name = name.substr(0, pos);
+ }
+ PartitionInfo *p = find_partition_info_by_index(pDesc->part_index);
+ if (p == NULL){
+ RLOGE("+[UA]: partition desc is not equal %d, name %s\n", pDesc->part_index, pName);
+ return -1;
+ }
+ if (p->part_size != pDesc->part_size || name != p->dest_part_name)
+ {
+ RLOGE("+[UA]: get bad partition desc size %d, name %s, %s-%s\n", pDesc->part_size, pName, p->dest_part_name.c_str(), name.c_str());
+ return -1;
+ }
+ p->part_org_size = pDesc->part_org_size;
+ p->org_file_name = pName;
+ p->zip_flag = pDesc->zip_flag;
+ memcpy(p->part_sha, pDesc->sha_value, SHA_DIGEST_SIZE);
+ pName += strlen(pName) + 1;
+ pDesc++;
+
+ }
+
+ return 0;
+}
+
+static const char *get_dest_part_suffix()
+{
+ if(current_slot==SLOT_B) {
+ return "_a";
+ } else {
+ return "_b";
+ }
+}
+
+static const char *get_src_part_suffix()
+{
+ if(current_slot==SLOT_B) {
+ return "_b";
+ } else {
+ return "_a";
+ }
+}
+
+static bool check_memory(int try_count)
+{
+ FILE *fp;
+ int value;
+ char buffer[64] = {0};
+ fp = popen("free -m | grep Mem | awk '{print $7}'","r");
+ if(fgets(buffer, 63, fp) != NULL)
+ {
+ value = atoi(buffer);
+ if (value > 100)
+ return true;
+ else if (strlen(buffer) >= 0)
+ return false;
+ }
+ fclose(fp);
+ if (try_count > 0)
+ {
+ try_count --;
+ sleep(1);
+ return check_memory(try_count);
+ }
+ return false;
+}
+
+static int rock_update_main(unsigned int rom_base, unsigned int backup_base, unsigned int backup_len, int read_rom_directly, int first_run, int switch_slot_flag, int
+ reboot_flag, int backup_mode) {
+ int status,err,start,fd;
+ int ret = 0;
+ int i = 0;
+ int slot = 0;
+ int retry_cnt = 0;
+ int cpu_flag;
+ IOT_UPDATA_CONTEXT ctx;
+
+ //OTA_STATUS fota_status;
+
+
+ unsigned int update_mode = MODE_NORMAL;
+
+ char digest_s[SHA_DIGEST_SIZE];
+ char digest_t[SHA_DIGEST_SIZE];
+ char str_sha[40];
+ char cmd_sys[100];
+ int core_num;
+ int sha_size = 0;
+ int is_need_fullupdate = 0;
+ int fd_partition_a,fd_partition_b;
+ time_t t1 = time(NULL);
+
+ FotaTool stFotaTool;
+ if (!stFotaTool.Init())
+ return -1;
+
+ if (!check_memory(3))
+ {
+ RLOGD("+[UA]: not enough memory to to fota\n");
+ return -1;
+ }
+
+ //xf.li@20230830 add for ab_recover start
+ //xf.li@20230830 add for ab_recover end
+ memset(&fota_status,0,sizeof(fota_status));
+ fota_status.ota_run = 1;
+ save_fota_status();
+
+
+ current_slot = module->getCurrentSlot(module);
+
+ int is_successful = module->isSlotMarkedSuccessful(module, current_slot);
+
+ RLOGD("Booting slot = %d, : isSlotMarkedSuccessful= %d\n",current_slot,is_successful);
+
+
+
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.rom_base = 0;
+ ctx.ram_base =(unsigned char *)&ram_buffer[0];
+ ctx.ram_len = ROCK_RAM_LEN;
+ ctx.backup_base = BACKUP_ADDR_FLAG;
+ //ctx.backup_len = ROCK_DEFAULT_BLOCK_SIZE;
+ ctx.backup_len = 0;
+ ctx.update_nvram = 0;
+ ctx.read_rom_directly = read_rom_directly;
+ //ctx.first_run = first_run;
+ ctx.first_run = 1;
+
+ if(0 != init_dev_fd())
+ {
+ RLOGD("+[UA]: get fota addr error\n");
+ return E_ROCK_FOTA_ADDR;
+ }
+
+ RLOGD("+[UA]: up_info.ota_run = %d\n",up_info.ota_run);
+
+#if 0
+ if ((up_info.ota_run>PATCH_BL33)||(up_info.ota_run<PATCH_SYSTEM))
+ {
+ up_info.ota_run = 0;
+ }
+#endif
+
+ up_info.ota_run = 0;
+ if(backup_mode == 1)
+ {
+ if(current_slot == 0)
+ {
+ update_mode = MODE_A2B;
+ }else
+ {
+ update_mode = MODE_B2A;
+ }
+ }
+ else
+ {
+ update_mode = MODE_NORMAL;
+ }
+
+ RLOGD("+[UA]: up_info.fota_flag = %s\n",up_info.fota_flag);
+ RLOGD("+[UA]: update_mode = %d\n",update_mode);
+
+ memset(&g_header, 0, sizeof(g_header));
+ PartitionInfo pi;
+ pi.zip_flag = 0;
+ pi.file_offset = 0;
+ pi.org_file_name = "";
+ pi.part_size = sizeof(g_header);
+ if (!stFotaTool.PreparePartionFile(&pi) || stFotaTool.ReadPartionFileData(&g_header, sizeof(g_header)) != sizeof(g_header))
+ {
+ RLOGE("read header fail\n");
+ return -1;
+ }
+
+ get_full_filename();
+
+ /*
+ core_num= check_cpu();
+ if(core_num == 2)
+ {
+ cpu_flag = check(delta_head[64]);
+ if(cpu_flag < 0)
+ {
+ RLOGD("cpu core is error\n");
+ system("echo fota-interface >/sys/power/wake_unlock");
+ return -1;
+ }
+ else
+ {
+ RLOGD("cpu core match\n");
+ }
+ }
+ else if(core_num == 4)
+ {
+ RLOGD("the cpu core is four!!!\n");
+ }
+ else
+ {
+ RLOGD("read the cpu core fail");
+ system("echo fota-interface >/sys/power/wake_unlock");
+ return -1;
+ }
+*/
+ fota_status.switch_slot = WAIT;
+ save_fota_status();
+
+ ret = prepare_header_and_check(&stFotaTool);
+ if (ret != 0)
+ {
+ RLOGD("delta sha verify fail!\n");
+ return -1;
+ }
+ now_patch = 0;
+ up_info.ota_run = 0;
+
+ fota_status.switch_slot = WAIT;
+ save_fota_status();
+ if (memcmp(g_header.full_type, FULL_HEAD, DELTA_FULL_HEARD_SIZE) != 0) {
+ RLOGD("+[UA]: invalid full delta header\r\n");
+ up_info.fota_flag[0] = 'e';
+ up_info.fota_flag[1] = 'n';
+ up_info.fota_flag[2] = 'd';
+ up_info.update_result = -1;
+ up_info.ota_run = 0;
+ save_fota_info();
+
+ //for (i = FULL_SYSTEM;i<=FULL_BL33;i++){
+
+ for (i = MAX_OTA_ROLE/2;i<(MAX_OTA_ROLE/2+full_partition_num);i++){
+ if (fota_status.update_status[i].need_update ==1) {
+ fota_status.ota_run = i - MAX_OTA_ROLE/2;
+ fota_status.update_status[i].check_delta = ERROR;
+ fota_status.update_status[i].check_rom= WAIT;
+ fota_status.update_status[i].update_result= ERROR;
+ }
+ }
+ fota_status.update_result = ERROR;
+ save_fota_status();
+ return -1;
+ }
+
+
+ for(auto it = g_lstPartitionInfo.begin(); it != g_lstPartitionInfo.end(); ++it) {
+ std::string dest_part_file = std::string("/dev/disk/by-partlabel/") + full_partition_filename[it->part_index] + get_dest_part_suffix();
+ sprintf(cmd_sys,"flash_erase %s 0 0", dest_part_file.c_str());
+ system(cmd_sys);
+
+ fd_curr = mtk_device_wrap_open(dest_part_file.c_str(), O_RDWR);
+ if (fd_curr < 0) {
+ err = errno;
+ RLOGE("+[UA]: Error opening full id_a[%d] file: %s, %s\n", it->part_index,
+ dest_part_file.c_str(), strerror(errno));
+ return -err;
+ }
+ fota_status.ota_run = it->part_index+1;
+ save_fota_status();
+ up_info.ota_run = it->part_index+1;
+ save_fota_info();
+ retry_cnt = 0;
+ RLOGD("+[UA]: Start upgrading %s full.\n",dest_part_file.c_str());
+ do{
+ status = delta_copyto_nand_new(&stFotaTool,&*it, digest_s);
+ if (status != 0)
+ {
+ if (retry_cnt++ < 3)
+ continue;
+ else
+ break;
+ }
+
+ //ROCK_SHA_FILE_COMMON(fd_delta,delta_offset,delta_head[i],digest_s);
+ ROCK_SHA_FILE(fd_curr,0,it->part_org_size,digest_t);
+ retry_cnt++;
+ }while((strncmp(digest_s,digest_t,SHA_DIGEST_SIZE)!=0)&&(retry_cnt <= 3));
+
+ mtk_device_wrap_close(fd_curr);
+
+ RLOGD("+[UA]: %s full retry_cnt = %d\n",dest_part_file.c_str(),retry_cnt);
+
+ if (retry_cnt>3) {
+ if (status == 0) {
+ status = retry_cnt;
+ }
+ std::string src_part_file = std::string("/dev/disk/by-partlabel/") + full_partition_filename[it->part_index] + get_src_part_suffix();
+ nand_copyto_nand(src_part_file.c_str(), dest_part_file.c_str());
+ }
+
+ RLOGD("+[UA]: %s full upgrade result:%d\n",full_partition_filename[it->part_index],status);
+
+ fota_status.update_result = status;
+ fota_status.update_status[i].update_result = status;
+ save_fota_status();
+
+ if (status != 0)
+ {
+
+ up_info.fota_flag[0] = 'e';
+ up_info.fota_flag[1] = 'n';
+ up_info.fota_flag[2] = 'd';
+ up_info.update_result = status;
+ up_info.ota_run = 0;
+ save_fota_info();
+ return status;
+ }
+
+ }
+
+
+ if(update_mode != MODE_NORMAL){ //need backup
+ if(current_slot == SLOT_A) {
+ up_info.fota_flag[0] = 'B';
+ up_info.fota_flag[1] = '-';
+ up_info.fota_flag[2] = 'A';
+
+ }else{
+ up_info.fota_flag[0] = 'A';
+ up_info.fota_flag[1] = '-';
+ up_info.fota_flag[2] = 'B';
+
+ }
+
+ }else{
+ up_info.fota_flag[0] = 'e';
+ up_info.fota_flag[1] = 'n';
+ up_info.fota_flag[2] = 'd';
+
+ }
+
+
+ up_info.update_result = status;
+ up_info.ota_run = 0;
+ save_fota_info();
+
+ //close_dev_fd(fd_curr);
+
+
+
+ close(fd_update_status);
+ sync();
+
+
+ slot = (current_slot == 0) ? 1 : 0;
+
+ RLOGD("+[UA]: slot SLOT = %d\n",slot);
+
+ if(switch_slot_flag==1)
+ {
+ module->setActiveBootSlot(module,slot);
+ RLOGD("+[UA]: upgrade is success!!!!\n");
+ }
+
+ fota_status.ota_run = 0;
+ fota_status.switch_slot = PASS;
+ fota_status.update_result = status;
+ save_fota_status();
+
+ sleep(5);
+ sync();
+ sleep(5);
+
+ time_t t2 = time(NULL);
+ printf("total cost %d\n", t2 - t1);
+
+ if(reboot_flag==1){
+ reboot_device();
+ }
+
+ return status;
+}
+
+
+
+static void rock_fail_handler()
+{
+ int ret = 0;
+ RLOGD("rock_fail_handler start\n");
+ //ret = rock_update_main(0, 0, 0, 0, 1, 1);
+ if(ret)
+ {
+ RLOGD("fota update fail again!\n");
+ }
+}
+
+/* main entrpoint */
+int lynq_rock_main(int first_run)
+{
+
+ int ret = 0;
+
+#if 0
+
+ printf("-********copy delta ***-\n");
+ test_write_delta("/data/delta",DEV_DELTA);
+
+#endif
+
+ ret = rock_update_main(0, 0, 0, 0, first_run, 1, 1, 1);
+ RLOGD("rock_update_main ret = %d\n", ret);
+ if(ret)
+ {
+ RLOGD("fota update fail!\n");
+ }
+ return ret;
+}
+
+#endif
+
+//xf.li@20230403 add for verfy start
+int lynq_file_md5_verfy(char *source, unsigned char *source_md5, char *target)
+{
+ int fd, size, ret, is_system = 0;
+ int need_copy = 1;
+ int system_mtd_num = 0;
+ int system_ubi_num = BACKUP_UBI_NUM;//max ubi number
+ char cmd_ubi_attach[128] = {0};
+ char cmd_ubi_detach[128] = {0};
+ char md5_target_file_patch[128] = {0};
+
+ RLOGD("in lynq_file_md5_verfy, source:%s, target:%s\n", source, target);
+ if(strcmp(source, DEV_SYSTEM_A) == 0 || strcmp(source, DEV_SYSTEM_B) == 0)
+ {
+ RLOGD("verfy system.img\n");
+ is_system = 1;
+ if(strcmp(source, DEV_SYSTEM_A) == 0)
+ {
+ system_mtd_num = MTD_SYSTEM_B;
+ }
+ else if(strcmp(source, DEV_SYSTEM_B) == 0)
+ {
+ system_mtd_num = MTD_SYSTEM_A;
+ }
+ else
+ {
+ RLOGD("source:%s, target:%s\n", source, target);
+ }
+ for( ; system_ubi_num >= 10; system_ubi_num--)//try from ubi31 to ubi10
+ {
+ sprintf(md5_target_file_patch, "/dev/ubi%d", system_ubi_num);
+ RLOGD("ubi_num = %d\n", system_ubi_num);
+ if((access(md5_target_file_patch, F_OK)) == -1)
+ {
+ RLOGD("no the ubi file, can use this ubi.\n");
+ break;
+ }
+ }
+ if(system_ubi_num < 10)
+ {
+ RLOGE("no the ubi file, can use this ubi.\n");
+ return -1;
+ }
+ }
+ //=========================caculate md5sum start=====================
+ if(is_system == 1)
+ {
+ RLOGD("in system caculate\n");
+ RLOGD("system_mtd_num = %d, ubi_num = %d\n", system_mtd_num, system_ubi_num);
+ sprintf(cmd_ubi_attach, "ubiattach /dev/ubi_ctrl -m %d -d %d", system_mtd_num, system_ubi_num);
+ RLOGD("cmd_ubi_attach:%s", cmd_ubi_attach);
+ ret = system(cmd_ubi_attach);
+ if(ret != 0)
+ {
+ RLOGE("ubi attach error!!!\n");
+ return need_copy;
+ }
+ RLOGD("attach over\n");
+ //attach success
+ sprintf(md5_target_file_patch, "/dev/ubi%d_0", system_ubi_num);
+ RLOGD("md5_target_file_patch:%s", md5_target_file_patch);
+ //make sure the ubi volume is exist
+ if((access(md5_target_file_patch, F_OK)) == -1)
+ {
+ RLOGD("no the ubi file.\n");
+ sprintf(cmd_ubi_detach, "ubidetach -m %d", system_mtd_num);
+ ret = system(cmd_ubi_detach);
+ if(ret != 0)
+ {
+ RLOGD("ubi dettach error!!!\n");
+ }
+
+ return need_copy;
+ }
+ //calculate md5sum
+ //ret = lynq_md5_two_file_verfy("/dev/ubi0_0", md5_target_file_patch);
+ ret = lynq_md5_file_verfy_ab(md5_target_file_patch, source_md5);
+ if(ret == MD5_VERFY_ERROR)
+ {
+ //ubidetach
+ sprintf(cmd_ubi_detach, "ubidetach -m %d", system_mtd_num);
+ ret = system(cmd_ubi_detach);
+ if(ret != 0)
+ {
+ RLOGD("ubi dettach error!!!\n");
+ }
+ return need_copy;
+ }
+ if(ret != 0)
+ {
+ //ubidetach
+ sprintf(cmd_ubi_detach, "ubidetach -m %d", system_mtd_num);
+ ret = system(cmd_ubi_detach);
+ if(ret != 0)
+ {
+ RLOGD("ubi dettach error!!!\n");
+ }
+ RLOGD("calculate system error!!!\n");
+ return -1;
+ }
+
+ RLOGD("verfy system.img over\n");
+ }
+ else
+ {
+ RLOGD("verfy else img\n");
+ //calculate md5sum
+ //ret = lynq_md5_two_file_verfy(source, target);
+ ret = lynq_md5_file_verfy_ab(target, source_md5);
+ if(ret == MD5_VERFY_ERROR)
+ {
+ return need_copy;
+ }
+ if(ret != 0)
+ {
+ RLOGD("calculate %s and %s error!!!\n", source, target);
+ return -1;
+ }
+ }
+ //====================caculate md5sum end======================
+ return 0;
+}
+//xf.li@20230403 add for verfy end
+
+
+//xf.li@20230401 add for ab rollback start
+
+int backup_nand_copyto_nand(char *source, char *target)
+{
+ int fd_source, fd_target, size;
+ int ret = -1;
+ int sleep_count = 0;
+ char cmd_erase_target[128] = {0};
+ int retry = MD5_RETRY_TIME;
+ unsigned char source_md5[MD5_READ_BUFFER_LEN] = {0};
+ char delta_data[ROCK_DEFAULT_BLOCK_SIZE];
+ //caclculate source md5 start
+ if(strcmp(source, DEV_SYSTEM_A) == 0 || strcmp(source, DEV_SYSTEM_B) == 0)
+ {
+ RLOGD("backup_nand_copyto_nand: verfy system.img\n");
+
+ ret = calculate_file_md5_value("/dev/ubi0_0", source_md5);
+ if(ret < 0)
+ {
+ RLOGD("[+MD5]:calculate source md5 value ERROE!!!\n");
+ return ret;
+ }
+ RLOGD("source_md5 is %s\n", source_md5);
+ }
+ else
+ {
+ ret = calculate_file_md5_value(source, source_md5);
+ if(ret < 0)
+ {
+ RLOGD("[+MD5]:calculate source md5 value ERROE!!!\n");
+ return ret;
+ }
+ RLOGD("source_md5 is %s\n", source_md5);
+ }
+ //caclculate source md5 end
+ //ret = lynq_file_md5_verfy(source, target);//verfy md5 value
+ ret = lynq_file_md5_verfy(source, source_md5, target);//verfy md5 value
+ RLOGD("+[UA]: md5_file_verfy :ret=%d\n", ret);
+ if(ret == 0)
+ {
+ RLOGD("+[UA]: nand_copyto_nand don't neet copy\n");
+ }
+ for(; ret > 0 && retry > 0; retry--)
+ {
+ //erase nand-target start
+ if(fota_interrupt == FOTA_FIRST && (access(FILE_UPDATE_FLAG, F_OK)) == 0)
+ {
+ RLOGD("+[UA]: fota runing\n");
+ return -1;
+ }
+ acquire_wake_lock(PARTIAL_WAKE_LOCK, "ab_recover");//lock
+ RLOGD("+[UA]: ready to flash_erase\n");
+ sprintf(cmd_erase_target, "flash_erase %s 0 0", target);
+ ret = system(cmd_erase_target);
+ release_wake_lock("ab_recover");//unlock
+ if(ret != 0)
+ {
+ RLOGD("+[UA]: erase %s fail\n", target);
+ return -1;
+ }
+ sleep(1);//sleep 1s
+
+ //erase nand-target end
+ RLOGD("+[UA]: ready to copy\n");
+ fd_source = mtk_device_wrap_open(source, O_RDONLY);
+ if (fd_source < 0) {
+ RLOGD("+[UA]: open source error\n");
+ return -1;
+ }
+
+ fd_target = mtk_device_wrap_open(target, O_RDWR);
+ if (fd_target < 0) {
+ RLOGD("+[UA]: open target error\n");
+ return -1;
+ }
+ ret = 0;//init ret
+ acquire_wake_lock(PARTIAL_WAKE_LOCK, "ab_recover");//lock
+ while(( size = mtk_device_wrap_read(fd_source,delta_data,ROCK_DEFAULT_BLOCK_SIZE))>0)
+ {
+ if(fota_interrupt == FOTA_FIRST && (access(FILE_UPDATE_FLAG, F_OK)) == 0)
+ {
+ RLOGD("+[UA]: fota runing\n");
+ ret = -1;
+ break;
+ }
+ usleep(40000);//sleep 40ms
+ mtk_device_wrap_write(fd_target,delta_data,ROCK_DEFAULT_BLOCK_SIZE);
+ usleep(60000);//sleep 60ms
+ sleep_count++;
+ if(sleep_count >= 20)
+ {
+ //unlock
+ release_wake_lock("ab_recover");
+ sleep(1);//sleep 1s
+ //lock
+ acquire_wake_lock(PARTIAL_WAKE_LOCK, "ab_recover");
+ sleep_count = 0;
+ RLOGD("+[UA]: try sleep one time");
+ }
+ }
+ release_wake_lock("ab_recover");//unlock
+ RLOGD("+[UA]: copy end\n");
+ mtk_device_wrap_close(fd_target);
+ mtk_device_wrap_close(fd_source);
+ if(ret < 0)
+ {
+ RLOGD("+[UA]: ret < 0\n");
+ return -1;
+ }
+ RLOGD("+[UA]: ready to md5_verfy\n");
+ //ret = lynq_file_md5_verfy(source, target);//verfy md5 value
+ ret = lynq_file_md5_verfy(source, source_md5, target);//verfy md5 value
+ RLOGD("+[UA]: md5_file_verfy :ret=%d\n", ret);
+ if(ret == 0)
+ {
+ RLOGD("+[UA]: nand_copyto_nand copy success\n");
+ break;
+ }
+ }
+ if(ret != 0)
+ {
+ RLOGD("+[UA]: md5_file_verfy FAIL!!!\n");
+ }
+ return ret;
+}
+//xf.li@20230401 add for ab rollback end
+
+//xf.li@20230822 add for ab rollback start
+
+int lynq_backup_main()
+{
+ const hw_module_t* hw_module;
+ hw_module = &HAL_MODULE_INFO_SYM;
+ int is_successful;
+ int ret = 0;
+
+
+ if (!hw_module || strcmp(BOOT_CONTROL_HARDWARE_MODULE_ID, hw_module->id) != 0)
+ {
+ ret = -1;
+ }
+ RLOGD("ret = %d\n", ret);
+ if (ret != 0)
+ {
+ RLOGD("+[UA]: Error loading boot_control HAL implementation.\n");
+ return -1;
+ }
+ module = (boot_control_module_t*)hw_module;
+ module->init(module);
+ if (module == NULL)
+ {
+ RLOGD("+[UA]: Error getting bootctrl module.\n");
+ return -1;
+ }
+ lynq_init_wake_lock_func();
+ current_slot = module->getCurrentSlot(module);
+ is_successful = module->isSlotMarkedSuccessful(module, current_slot);
+ RLOGD("+[UA]: Booting slot = %d, : isSlotMarkedSuccessful= %d\n",current_slot,is_successful);
+ fota_interrupt = RECOVER_FIRST;
+ if(current_slot==SLOT_B)
+ {
+ ret = backup_nand_copyto_nand(DEV_SPM_B,DEV_SPM_A);
+ if(ret != 0)
+ {
+ RLOGD("+[UA]: backup spm_a fail\n");
+ return 1;
+ }
+ fota_interrupt = FOTA_FIRST;
+ ret = backup_nand_copyto_nand(DEV_SYSTEM_B,DEV_SYSTEM_A);
+ if(ret != 0)
+ {
+ RLOGD("+[UA]: backup system_a fail\n");
+ return 1;
+ }
+ ret = backup_nand_copyto_nand(DEV_BOOT_B,DEV_BOOT_A);
+ if(ret != 0)
+ {
+ RLOGD("+[UA]: backup boot_a fail\n");
+ return 1;
+ }
+ ret = backup_nand_copyto_nand(DEV_TEE_B,DEV_TEE_A);
+ if(ret != 0)
+ {
+ RLOGD("+[UA]: backup tee_a fail\n");
+ return 1;
+ }
+ ret = backup_nand_copyto_nand(DEV_MD1IMG_B,DEV_MD1IMG_A);
+ if(ret != 0)
+ {
+ RLOGD("+[UA]: backup md1img_a fail\n");
+ return 1;
+ }
+ ret = backup_nand_copyto_nand(DEV_VBMETA_B,DEV_VBMETA_A);
+ if(ret != 0)
+ {
+ RLOGD("+[UA]: backup vbmeta_a fail\n");
+ return 1;
+ }
+ ret = backup_nand_copyto_nand(DEV_MEDMCU_B,DEV_MEDMCU_A);
+ if(ret != 0)
+ {
+ RLOGD("+[UA]: backup medmcu_a fail\n");
+ return 1;
+ }
+ ret = backup_nand_copyto_nand(DEV_BL2_B,DEV_BL2_A);
+ if(ret != 0)
+ {
+ RLOGD("+[UA]: backup bl2_a fail\n");
+ return 1;
+ }
+ ret = backup_nand_copyto_nand(DEV_BL33_B,DEV_BL33_A);
+ if(ret != 0)
+ {
+ RLOGD("+[UA]: backup bl33_a fail\n");
+ return 1;
+ }
+ ret = backup_nand_copyto_nand(DEV_OEMAPP_B,DEV_OEMAPP_A);
+ if(ret != 0)
+ {
+ RLOGD("+[UA]: backup oemapp_a fail\n");
+ return 1;
+ }
+ ret = backup_nand_copyto_nand(DEV_OEMAPP2_B,DEV_OEMAPP2_A);
+ if(ret != 0)
+ {
+ RLOGD("+[UA]: backup oemapp2_a fail\n");
+ return 1;
+ }
+ }
+ else
+ {
+ ret = backup_nand_copyto_nand(DEV_SPM_A,DEV_SPM_B);
+ if(ret != 0)
+ {
+ RLOGD("+[UA]: backup spm_a fail\n");
+ return 1;
+ }
+ fota_interrupt = FOTA_FIRST;
+ ret = backup_nand_copyto_nand(DEV_SYSTEM_A,DEV_SYSTEM_B);
+ if(ret != 0)
+ {
+ RLOGD("+[UA]: backup system_b fail\n");
+ return 1;
+ }
+ ret = backup_nand_copyto_nand(DEV_BOOT_A,DEV_BOOT_B);
+ if(ret != 0)
+ {
+ RLOGD("+[UA]: backup boot_b fail\n");
+ return 1;
+ }
+
+ ret = backup_nand_copyto_nand(DEV_TEE_A,DEV_TEE_B);
+ if(ret != 0)
+ {
+ RLOGD("+[UA]: backup tee_b fail\n");
+ return 1;
+ }
+ ret = backup_nand_copyto_nand(DEV_MD1IMG_A,DEV_MD1IMG_B);
+ if(ret != 0)
+ {
+ RLOGD("+[UA]: backup md1img_b fail\n");
+ return 1;
+ }
+ ret = backup_nand_copyto_nand(DEV_VBMETA_A,DEV_VBMETA_B);
+ if(ret != 0)
+ {
+ RLOGD("+[UA]: backup vbmeta_b fail\n");
+ return 1;
+ }
+ ret = backup_nand_copyto_nand(DEV_MEDMCU_A,DEV_MEDMCU_B);
+ if(ret != 0)
+ {
+ RLOGD("+[UA]: backup medmcu_b fail\n");
+ return 1;
+ }
+ ret = backup_nand_copyto_nand(DEV_BL2_A,DEV_BL2_B);
+ if(ret != 0)
+ {
+ RLOGD("+[UA]: backup bl2_a fail\n");
+ return 1;
+ }
+ ret = backup_nand_copyto_nand(DEV_BL33_A,DEV_BL33_B);
+ if(ret != 0)
+ {
+ RLOGD("+[UA]: backup bl33_a fail\n");
+ return 1;
+ }
+ ret = backup_nand_copyto_nand(DEV_OEMAPP_A,DEV_OEMAPP_B);
+ if(ret != 0)
+ {
+ RLOGD("+[UA]: backup oemapp_b fail\n");
+ return 1;
+ }
+ ret = backup_nand_copyto_nand(DEV_OEMAPP2_A,DEV_OEMAPP2_B);
+ if(ret != 0)
+ {
+ RLOGD("+[UA]: backup oemapp2_b fail\n");
+ return 1;
+ }
+ }
+ RLOGD("+[UA]: lynq_backup_main success \n");
+ return 0;
+}
+//xf.li@20230822 add for ab rollback end
+
+
+int lynq_check_oemapp(char* name)
+{
+ FILE *fp;
+ char check_result[64];
+ int ret;
+ if(strcmp(name, "oemapp") == 0)
+ {
+ RLOGD("lynq_check_oemapp oemapp");
+ ret = system("cat /proc/mtd|grep oemapp");
+ if(ret != 0)
+ {
+ return 0;
+ }
+ if(system("df -lh|grep oemapp |grep -v oemapp2") != 0)
+ {
+ return -1;
+ }
+ else
+ {
+ return 0;
+ }
+ }
+ else if(strcmp(name, "oemapp2") == 0)
+ {
+ RLOGD("lynq_check_oemapp oemapp2");
+ ret = system("cat /proc/mtd|grep oemapp2");
+ if(ret != 0)
+ {
+ return 0;
+ }
+ if(system("df -lh|grep oemapp2") != 0)
+ {
+ return -1;
+ }
+ else
+ {
+ return 0;
+ }
+ }
+ return 0;
+}
+
+//lt add @2021.9.23 for deal with power down \ backup or upgrade.
+int lynq_fota_func(void)
+{
+ int fd;
+ int first_run = 1;
+ int ret = 0;
+ UPDATE_INFO lynq_up_info;
+ //xf.li@20230822 add for ab backup start
+ unsigned int current_slot, other_slot;
+ int is_other_slot_bootable;
+ const hw_module_t* hw_module;
+ //xf.li@20230822 add for ab backup end
+ RLOGD("[+UP]: ******lynq_fota_func start******\n");
+ //xf.li@20230822 add for ab backup start
+ //----------get current slot and whether other slot is bootable
+ hw_module = &HAL_MODULE_INFO_SYM;
+ if (!hw_module ||
+ strcmp(BOOT_CONTROL_HARDWARE_MODULE_ID, hw_module->id) != 0) {
+ ret = -EINVAL;
+ }
+ if (ret != 0) {
+ RLOGD("+[UA]: Error loading boot_control HAL implementation.\n");
+ return -1;
+ }
+ module = (boot_control_module_t*)hw_module;
+ module->init(module);
+ if (module == NULL) {
+ RLOGD("+[UA]: Error getting bootctrl module.\n");
+ return -1;
+ }
+ current_slot = module->getCurrentSlot(module);
+ other_slot = (current_slot == 0) ? 1 : 0;
+ is_other_slot_bootable = module->isSlotBootable(module, other_slot);
+ //-----------end
+ RLOGD("current slot:%u, is_other_slot_bootable : %d\n",current_slot, is_other_slot_bootable);
+ //xf.li@20230822 add for ab backup end
+
+ memset(&lynq_up_info, 0, sizeof(lynq_up_info));
+ fd = open(FILE_UPDATE_STATE,O_RDWR | O_CREAT,0777);
+ if (fd < 0)
+ {
+ return -1;
+ }
+ read(fd,(unsigned char *)&lynq_up_info,sizeof(lynq_up_info));
+ close(fd);
+
+ RLOGD("[+UP]: lynq_up_info.ota_run=%d\n",lynq_up_info.ota_run);
+ if((lynq_check_oemapp("oemapp") != 0) || (lynq_check_oemapp("oemapp2") != 0))
+ {
+ RLOGD("ENTER LYNQ_CHECK_OEMAPP\n");
+ system("echo mode 001 0 > /sys/devices/platform/10005000.pinctrl/mt_gpio");
+ system("echo dir 001 1 > /sys/devices/platform/10005000.pinctrl/mt_gpio");
+ system("echo out 001 1 > /sys/devices/platform/10005000.pinctrl/mt_gpio");
+ RLOGD("need setUnbootable.\n");
+ module->setSlotAsUnbootable(module,current_slot);
+ RLOGD("+[UA]: setSlotAsUnbootable!!!!\n");
+ sync();
+ if(((lynq_up_info.fota_flag[0]=='A')&&(lynq_up_info.fota_flag[1]=='-')&&(lynq_up_info.fota_flag[2]=='B'))||
+ ((lynq_up_info.fota_flag[0]=='B')&&(lynq_up_info.fota_flag[1]=='-')&&(lynq_up_info.fota_flag[2]=='A')))
+ {
+ RLOGD("mark oemapp mount fail\n");
+ lynq_set_value(FOTA_UCI_MODULE,FOTA_UCI_STATE, "1");
+ }
+ sleep(5);
+ reboot_device();
+ }
+
+
+ if(lynq_up_info.ota_run != 0)
+ {
+ //Power off, call UA
+ RLOGD("[+UP]: ***Power off, call UA***\n");
+ ret = rock_update_main(0, 0, 0, 0, first_run, 1, 0, 1);
+ RLOGD("rock_update_main ret = %d\n", ret);
+ if(ret)
+ {
+ RLOGD("fota update fail!\n");
+ }
+ }
+
+ if(((lynq_up_info.fota_flag[0]=='A')&&(lynq_up_info.fota_flag[1]=='-')&&(lynq_up_info.fota_flag[2]=='B'))||
+ ((lynq_up_info.fota_flag[0]=='B')&&(lynq_up_info.fota_flag[1]=='-')&&(lynq_up_info.fota_flag[2]=='A')))
+ {
+ //Upgrade the other side and call UA
+ RLOGD("[+UP]: ***Upgrade the other side and call UA***\n");
+ ret = rock_update_main(0, 0, 0, 0, first_run, 0, 0, 0);
+ RLOGD("rock_update_main ret = %d\n", ret);
+ if(ret)
+ {
+ RLOGD("fota update fail!\n");
+ }
+ }
+ //xf.li@20230822 add for ab backup start
+ else if(is_other_slot_bootable == 0)
+ {
+ RLOGD("need backup\n");
+ ret = lynq_backup_main();
+ if(ret != 0)
+ {
+ RLOGD("ERROE: backup fail!!!\n");
+ }
+ else
+ {
+ RLOGD("backup success!!!\n");
+ module->setCompleteBackup(module, current_slot);
+ }
+ }
+ else
+ {
+ RLOGD("Don't need backup\n");
+ }
+ //xf.li@20230822 add for ab backup end
+
+ return 0;
+}
+
+int lynq_nand_open(const char *pathname, int flags)
+{
+ // printf("pathname:%s---flags:%d",pathname,flags);
+ return open(pathname,flags);
+}
+
+ssize_t lynq_nand_read(int fd, void *buf, size_t count)
+{
+ // printf("rfd:%d---buf:%s---count:%d",fd,buf,count);
+ return read(fd,buf,count);
+}
+
+ssize_t lynq_nand_write(int fd, void *buf, size_t count)
+{
+ // printf("wfd:%d---buf:%s---count:%d",fd,buf,count);
+ return write(fd,buf,count);
+}
+
+int lynq_nand_close(int fd)
+{
+ return close(fd);
+}
+
+/**
+ * @brief Obtain the upgrade result
+ *
+ * @param void
+ * @return 0xff:open file fail,0:upgrade success,1,upgrade wait
+ */
+int lynq_get_upgrade_status(void)
+{
+ int lynq_state_fd;
+ int lynq_upgrade_wait = 1;
+ OTA_STATUS lynq_ota_status;
+
+ memset(&lynq_ota_status, 0, sizeof(lynq_ota_status));
+
+ lynq_state_fd = open(FILE_FOTA_STATE,O_RDWR | O_CREAT,0777);
+
+ if (lynq_state_fd < 0)
+ {
+ return 0xff;
+ }
+ read(lynq_state_fd,(unsigned char *)&lynq_ota_status,sizeof(lynq_ota_status));
+ close(lynq_state_fd);
+ if((lynq_ota_status.ota_run != 0) && (lynq_ota_status.update_result == 0))
+ {
+ return lynq_upgrade_wait;
+ }
+ return lynq_ota_status.update_result;
+}
+
+/**
+ * @brief reboot device
+ *
+ * @param void
+ * @return void
+ */
+void lynq_reboot_device(void)
+{
+ reboot_device();
+ return ;
+}
+
+/**
+ * @brief fota no resatrt
+ *
+ * @param void
+ * @return 0:fota success -Other values:fota fail
+ */
+
+int lynq_fota_nrestart(void)
+{
+
+ int ret = 0;
+#if 0
+ printf("-********copy delta ***-\n");
+ test_write_delta("/data/delta",DEV_DELTA);
+#endif
+
+ RLOGD("lynq-fota-zip start\n");
+ time_t t1 = time(NULL);
+ ret = rock_update_main(0, 0, 0, 0, 1, 1, 0, 1);
+ RLOGD("rock_update_nrestart ret = %d\n", ret);
+ if(ret)
+ {
+ RLOGD("fota update fail!\n");
+ }
+ time_t t2 = time(NULL);
+ RLOGE("cy: fota update cost %d\n", t2 - t1);
+ return ret;
+}
+
+std::string g_base_addr;
+/**
+ * @brief Set the upgrade package address
+ *
+ * @param1 value:fota addr
+ * @param1 szie:fota addr length
+ * @return 0:set success other:set fail
+ */
+int lynq_fota_set_addr_value(char *value,int size)
+{
+ int ret;
+ printf("cy: lynq_fota_set_addr_value %s %d!\n", value, size);
+ RLOGE("cy: lynq_fota_set_addr_value %s %d!\n", value, size);
+ if(size < 120)
+ {
+ ret = lynq_set_value(FOTA_UCI_MODULE,FOTA_UCI_ADDR, value);
+ if (ret != 0){
+ RLOGE("cy: lynq_fota_set_addr_value fail %d\n", ret);
+ g_base_addr = value;
+ return 0;
+ }
+ return ret;
+ }
+ return -1;
+}
+/**
+ * @brief get the upgrade package address
+ *
+ * @param1 value:fota addr
+ * @return 0:get success other:set fail
+ */
+int lynq_fota_get_addr_value(char *tmp)
+{
+ return lynq_get_value(FOTA_UCI_FILE, FOTA_UCI_MODULE,FOTA_UCI_ADDR, tmp);
+}
+
+/**
+ * @brief Porting wakes up the demo content
+ */
+static void lynq_init_wake_lock_func(void)
+{
+ const char *lynqLibPath_WakeLock = "/usr/lib64/libpower.so";
+
+ dlHandle_wakelock = dlopen(lynqLibPath_WakeLock, RTLD_NOW);
+ if (dlHandle_wakelock == NULL)
+ {
+ printf("dlopen lynqLibPath_WakeLock failed: %s", dlerror());
+ exit(EXIT_FAILURE);
+ }
+
+ acquire_wake_lock = (int(*)(int,const char*))dlsym(dlHandle_wakelock, "acquire_wake_lock");
+ if (acquire_wake_lock == NULL) {
+ printf("acquire_wake_lock not defined or exported in %s", lynqLibPath_WakeLock);
+ exit(EXIT_FAILURE);
+ }
+ release_wake_lock = (int(*)( const char*))dlsym(dlHandle_wakelock, "release_wake_lock");
+ if (release_wake_lock == NULL) {
+ printf("release_wake_lock not defined or exported in %s", lynqLibPath_WakeLock);
+ exit(EXIT_FAILURE);
+ }
+ dlerror(); // Clear any previous dlerror
+
+ return;
+}
+
+/**
+ * @brief fota wake lock
+ *
+ * @param1 value:void
+ * @return ;
+ */
+static void lynq_fota_grab_artial_wake_lock(void)
+{
+ acquire_wake_lock(PARTIAL_WAKE_LOCK, ANDROID_WAKE_LOCK_NAME);
+}
+
+/**
+ * @brief get the upgrade package address
+ *
+ * @param1 value:void
+ * @return ;
+ */
+static void lynq_fota_release_wake_lock(void)
+{
+ release_wake_lock(ANDROID_WAKE_LOCK_NAME);
+}
+/**
+ * @brief This is the wake up call
+ * end
+ */
diff --git a/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-ftp-fota/rock_ua/sha.c b/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-ftp-fota/rock_ua/sha.c
new file mode 100755
index 0000000..b1a1936
--- /dev/null
+++ b/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-ftp-fota/rock_ua/sha.c
@@ -0,0 +1,432 @@
+/* sha.c
+**
+** Copyright 2008, The Android Open Source Project
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+** * Neither the name of Google Inc. nor the names of its contributors may
+** be used to endorse or promote products derived from this software
+** without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR
+** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+** EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+** OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "sha.h"
+
+
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "lynq_fota_file.h"
+
+#include "mtk_device_wrap.h"
+
+// Some machines lack byteswap.h and endian.h. These have to use the
+// slower code, even if they're little-endian.
+
+#if defined(HAVE_ENDIAN_H) && defined(HAVE_LITTLE_ENDIAN)
+
+#include <byteswap.h>
+#include <memory.h>
+
+
+
+// This version is about 28% faster than the generic version below,
+// but assumes little-endianness.
+
+static inline uint32_t ror27(uint32_t val) {
+ return (val >> 27) | (val << 5);
+}
+static inline uint32_t ror2(uint32_t val) {
+ return (val >> 2) | (val << 30);
+}
+static inline uint32_t ror31(uint32_t val) {
+ return (val >> 31) | (val << 1);
+}
+
+static void SHA1_Transform(SHA_CTX* ctx) {
+ uint32_t W[80];
+ register uint32_t A, B, C, D, E;
+ int t;
+
+ A = ctx->state[0];
+ B = ctx->state[1];
+ C = ctx->state[2];
+ D = ctx->state[3];
+ E = ctx->state[4];
+
+#define SHA_F1(A,B,C,D,E,t) \
+ E += ror27(A) + \
+ (W[t] = bswap_32(ctx->buf.w[t])) + \
+ (D^(B&(C^D))) + 0x5A827999; \
+ B = ror2(B);
+
+ for (t = 0; t < 15; t += 5) {
+ SHA_F1(A,B,C,D,E,t + 0);
+ SHA_F1(E,A,B,C,D,t + 1);
+ SHA_F1(D,E,A,B,C,t + 2);
+ SHA_F1(C,D,E,A,B,t + 3);
+ SHA_F1(B,C,D,E,A,t + 4);
+ }
+ SHA_F1(A,B,C,D,E,t + 0); // 16th one, t == 15
+
+#undef SHA_F1
+
+#define SHA_F1(A,B,C,D,E,t) \
+ E += ror27(A) + \
+ (W[t] = ror31(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16])) + \
+ (D^(B&(C^D))) + 0x5A827999; \
+ B = ror2(B);
+
+ SHA_F1(E,A,B,C,D,t + 1);
+ SHA_F1(D,E,A,B,C,t + 2);
+ SHA_F1(C,D,E,A,B,t + 3);
+ SHA_F1(B,C,D,E,A,t + 4);
+
+#undef SHA_F1
+
+#define SHA_F2(A,B,C,D,E,t) \
+ E += ror27(A) + \
+ (W[t] = ror31(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16])) + \
+ (B^C^D) + 0x6ED9EBA1; \
+ B = ror2(B);
+
+ for (t = 20; t < 40; t += 5) {
+ SHA_F2(A,B,C,D,E,t + 0);
+ SHA_F2(E,A,B,C,D,t + 1);
+ SHA_F2(D,E,A,B,C,t + 2);
+ SHA_F2(C,D,E,A,B,t + 3);
+ SHA_F2(B,C,D,E,A,t + 4);
+ }
+
+#undef SHA_F2
+
+#define SHA_F3(A,B,C,D,E,t) \
+ E += ror27(A) + \
+ (W[t] = ror31(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16])) + \
+ ((B&C)|(D&(B|C))) + 0x8F1BBCDC; \
+ B = ror2(B);
+
+ for (; t < 60; t += 5) {
+ SHA_F3(A,B,C,D,E,t + 0);
+ SHA_F3(E,A,B,C,D,t + 1);
+ SHA_F3(D,E,A,B,C,t + 2);
+ SHA_F3(C,D,E,A,B,t + 3);
+ SHA_F3(B,C,D,E,A,t + 4);
+ }
+
+#undef SHA_F3
+
+#define SHA_F4(A,B,C,D,E,t) \
+ E += ror27(A) + \
+ (W[t] = ror31(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16])) + \
+ (B^C^D) + 0xCA62C1D6; \
+ B = ror2(B);
+
+ for (; t < 80; t += 5) {
+ SHA_F4(A,B,C,D,E,t + 0);
+ SHA_F4(E,A,B,C,D,t + 1);
+ SHA_F4(D,E,A,B,C,t + 2);
+ SHA_F4(C,D,E,A,B,t + 3);
+ SHA_F4(B,C,D,E,A,t + 4);
+ }
+
+#undef SHA_F4
+
+ ctx->state[0] += A;
+ ctx->state[1] += B;
+ ctx->state[2] += C;
+ ctx->state[3] += D;
+ ctx->state[4] += E;
+}
+
+void SHA_update(SHA_CTX* ctx, const void* data, int len) {
+ int i = ctx->count % sizeof(ctx->buf);
+ const uint8_t* p = (const uint8_t*)data;
+
+ ctx->count += len;
+
+ while (len > sizeof(ctx->buf) - i) {
+ memcpy(&ctx->buf.b[i], p, sizeof(ctx->buf) - i);
+ len -= sizeof(ctx->buf) - i;
+ p += sizeof(ctx->buf) - i;
+ SHA1_Transform(ctx);
+ i = 0;
+ }
+
+ while (len--) {
+ ctx->buf.b[i++] = *p++;
+ if (i == sizeof(ctx->buf)) {
+ SHA1_Transform(ctx);
+ i = 0;
+ }
+ }
+}
+
+
+const uint8_t* SHA_final(SHA_CTX* ctx) {
+ uint64_t cnt = ctx->count * 8;
+ int i;
+
+ SHA_update(ctx, (uint8_t*)"\x80", 1);
+ while ((ctx->count % sizeof(ctx->buf)) != (sizeof(ctx->buf) - 8)) {
+ SHA_update(ctx, (uint8_t*)"\0", 1);
+ }
+ for (i = 0; i < 8; ++i) {
+ uint8_t tmp = cnt >> ((7 - i) * 8);
+ SHA_update(ctx, &tmp, 1);
+ }
+
+ for (i = 0; i < 5; i++) {
+ ctx->buf.w[i] = bswap_32(ctx->state[i]);
+ }
+
+ return ctx->buf.b;
+}
+
+#else // #if defined(HAVE_ENDIAN_H) && defined(HAVE_LITTLE_ENDIAN)
+
+#define rol(bits, value) (((value) << (bits)) | ((value) >> (32 - (bits))))
+
+static void SHA1_transform(SHA_CTX *ctx) {
+ uint32_t W[80];
+ uint32_t A, B, C, D, E;
+ uint8_t *p = ctx->buf;
+ int t;
+
+ for(t = 0; t < 16; ++t) {
+ uint32_t tmp = *p++ << 24;
+ tmp |= *p++ << 16;
+ tmp |= *p++ << 8;
+ tmp |= *p++;
+ W[t] = tmp;
+ }
+
+ for(; t < 80; t++) {
+ W[t] = rol(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);
+ }
+
+ A = ctx->state[0];
+ B = ctx->state[1];
+ C = ctx->state[2];
+ D = ctx->state[3];
+ E = ctx->state[4];
+
+ for(t = 0; t < 80; t++) {
+ uint32_t tmp = rol(5,A) + E + W[t];
+
+ if (t < 20)
+ tmp += (D^(B&(C^D))) + 0x5A827999;
+ else if ( t < 40)
+ tmp += (B^C^D) + 0x6ED9EBA1;
+ else if ( t < 60)
+ tmp += ((B&C)|(D&(B|C))) + 0x8F1BBCDC;
+ else
+ tmp += (B^C^D) + 0xCA62C1D6;
+
+ E = D;
+ D = C;
+ C = rol(30,B);
+ B = A;
+ A = tmp;
+ }
+
+ ctx->state[0] += A;
+ ctx->state[1] += B;
+ ctx->state[2] += C;
+ ctx->state[3] += D;
+ ctx->state[4] += E;
+}
+
+void SHA_update(SHA_CTX *ctx, const void *data, int len) {
+ int i = ctx->count % sizeof(ctx->buf);
+ const uint8_t* p = (const uint8_t*)data;
+
+ ctx->count += len;
+
+ while (len--) {
+ ctx->buf[i++] = *p++;
+ if (i == sizeof(ctx->buf)) {
+ SHA1_transform(ctx);
+ i = 0;
+ }
+ }
+}
+const uint8_t *SHA_final(SHA_CTX *ctx) {
+ uint8_t *p = ctx->buf;
+ uint64_t cnt = ctx->count * 8;
+ int i;
+
+ SHA_update(ctx, (uint8_t*)"\x80", 1);
+ while ((ctx->count % sizeof(ctx->buf)) != (sizeof(ctx->buf) - 8)) {
+ SHA_update(ctx, (uint8_t*)"\0", 1);
+ }
+ for (i = 0; i < 8; ++i) {
+ uint8_t tmp = cnt >> ((7 - i) * 8);
+ SHA_update(ctx, &tmp, 1);
+ }
+
+ for (i = 0; i < 5; i++) {
+ uint32_t tmp = ctx->state[i];
+ *p++ = tmp >> 24;
+ *p++ = tmp >> 16;
+ *p++ = tmp >> 8;
+ *p++ = tmp >> 0;
+ }
+
+ return ctx->buf;
+}
+
+#endif // endianness
+
+void SHA_init(SHA_CTX* ctx) {
+ ctx->state[0] = 0x67452301;
+ ctx->state[1] = 0xEFCDAB89;
+ ctx->state[2] = 0x98BADCFE;
+ ctx->state[3] = 0x10325476;
+ ctx->state[4] = 0xC3D2E1F0;
+ ctx->count = 0;
+}
+
+/* Convenience function */
+const uint8_t* SHA(const void *data, int len, uint8_t *digest) {
+ const uint8_t *p;
+ int i;
+
+ SHA_CTX ctx;
+ SHA_init(&ctx);
+ SHA_update(&ctx, data, len);
+ p = SHA_final(&ctx);
+ for (i = 0; i < SHA_DIGEST_SIZE; ++i) {
+ digest[i] = *p++;
+ }
+ return digest;
+}
+
+#define NAND_PAGE_SIZE_SHA 4096
+
+const uint8_t* ROCK_SHA_FILE_COMMON(int fd_sha, int offset,int totle_size, uint8_t *digest) {
+ const uint8_t *p;
+ int i = 0;
+ //int fd_sha;
+ int size = 0;
+ int totale_size_common = totle_size;
+ char data[NAND_PAGE_SIZE_SHA];
+
+
+ lseek(fd_sha, offset, SEEK_SET);
+ SHA_CTX ctx;
+ SHA_init(&ctx);
+ //int fd = open("/tmp/fota.delta", O_RDWR|O_CREAT);
+
+ do{
+ if(totale_size_common >= NAND_PAGE_SIZE_SHA)
+ {
+ size = read(fd_sha,data,NAND_PAGE_SIZE_SHA);
+ }
+ else
+ {
+ size = read(fd_sha,data,totale_size_common);
+ }
+ if (size == 0){
+ break;
+ }
+ //write(fd, data, size);
+ SHA_update(&ctx, data, size);
+ totale_size_common -= size;
+
+ }while(totale_size_common>0);
+ p = SHA_final(&ctx);
+ for (i = 0; i < SHA_DIGEST_SIZE; ++i)
+ {
+ digest[i] = *p++;
+ }
+ //close(fd);
+ return digest;
+}
+
+const uint8_t* ROCK_SHA_FILE(int fd_sha, int offset,int totle_size, uint8_t *digest) {
+ const uint8_t *p;
+ int i = 0;
+ //int fd_sha;
+ int size = 0;
+ int totale_size_file = totle_size;
+ char data[NAND_PAGE_SIZE_SHA];
+
+
+ mtk_device_wrap_seek(fd_sha, offset, SEEK_SET);
+ SHA_CTX ctx;
+ SHA_init(&ctx);
+
+ do{
+ if(totale_size_file >= NAND_PAGE_SIZE_SHA)
+ {
+ size = mtk_device_wrap_read(fd_sha,data,NAND_PAGE_SIZE_SHA);
+ }
+ else
+ {
+ size = mtk_device_wrap_read(fd_sha,data,totale_size_file);
+ }
+ if (size == 0){
+ break;
+ }
+ SHA_update(&ctx, data, size);
+ totale_size_file -= size;
+
+ }while(totale_size_file>0);
+ p = SHA_final(&ctx);
+ for (i = 0; i < SHA_DIGEST_SIZE; ++i)
+ {
+ digest[i] = *p++;
+ }
+ return digest;
+}
+
+
+
+// Take a string 'str' of 40 hex digits and parse it into the 20
+// byte array 'digest'. 'str' may contain only the digest or be of
+// the form "<digest>:<anything>". Return 0 on success, -1 on any
+// error.
+int ParseSha1(const char* str, uint8_t* digest) {
+ int i;
+ const char* ps = str;
+ uint8_t* pd = digest;
+ for (i = 0; i < SHA_DIGEST_SIZE * 2; ++i, ++ps) {
+ int digit;
+ if (*ps >= '0' && *ps <= '9') {
+ digit = *ps - '0';
+ } else if (*ps >= 'a' && *ps <= 'f') {
+ digit = *ps - 'a' + 10;
+ } else if (*ps >= 'A' && *ps <= 'F') {
+ digit = *ps - 'A' + 10;
+ } else {
+ return -1;
+ }
+ if (i % 2 == 0) {
+ *pd = digit << 4;
+ } else {
+ *pd |= digit;
+ ++pd;
+ }
+ }
+ if (*ps != '\0') return -1;
+ return 0;
+}
diff --git a/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-ftp-fota/rock_ua/unzip.c b/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-ftp-fota/rock_ua/unzip.c
new file mode 100755
index 0000000..ed763f8
--- /dev/null
+++ b/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-ftp-fota/rock_ua/unzip.c
@@ -0,0 +1,1985 @@
+/* unzip.c -- IO for uncompress .zip files using zlib
+ Version 1.1, February 14h, 2010
+ part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )
+
+ Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )
+
+ Modifications of Unzip for Zip64
+ Copyright (C) 2007-2008 Even Rouault
+
+ Modifications for Zip64 support on both zip and unzip
+ Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
+
+ For more info read MiniZip_info.txt
+
+
+ ------------------------------------------------------------------------------------
+ Decryption code comes from crypt.c by Info-ZIP but has been greatly reduced in terms of
+ compatibility with older software. The following is from the original crypt.c.
+ Code woven in by Terry Thorsen 1/2003.
+
+ Copyright (c) 1990-2000 Info-ZIP. All rights reserved.
+
+ See the accompanying file LICENSE, version 2000-Apr-09 or later
+ (the contents of which are also included in zip.h) for terms of use.
+ If, for some reason, all these files are missing, the Info-ZIP license
+ also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html
+
+ crypt.c (full version) by Info-ZIP. Last revised: [see crypt.h]
+
+ The encryption/decryption parts of this source code (as opposed to the
+ non-echoing password parts) were originally written in Europe. The
+ whole source package can be freely distributed, including from the USA.
+ (Prior to January 2000, re-export from the US was a violation of US law.)
+
+ This encryption code is a direct transcription of the algorithm from
+ Roger Schlafly, described by Phil Katz in the file appnote.txt. This
+ file (appnote.txt) is distributed with the PKZIP program (even in the
+ version without encryption capabilities).
+
+ ------------------------------------------------------------------------------------
+
+ Changes in unzip.c
+
+ 2007-2008 - Even Rouault - Addition of cpl_unzGetCurrentFileZStreamPos
+ 2007-2008 - Even Rouault - Decoration of symbol names unz* -> cpl_unz*
+ 2007-2008 - Even Rouault - Remove old C style function prototypes
+ 2007-2008 - Even Rouault - Add unzip support for ZIP64
+
+ Copyright (C) 2007-2008 Even Rouault
+
+
+ Oct-2009 - Mathias Svensson - Removed cpl_* from symbol names (Even Rouault added them but since this is now moved to a new project (minizip64) I renamed them again).
+ Oct-2009 - Mathias Svensson - Fixed problem if uncompressed size was > 4G and compressed size was <4G
+ should only read the compressed/uncompressed size from the Zip64 format if
+ the size from normal header was 0xFFFFFFFF
+ Oct-2009 - Mathias Svensson - Applied some bug fixes from patches received from Gilles Vollant
+ Oct-2009 - Mathias Svensson - Applied support to unzip files with compression method BZIP2 (bzip2 lib is required)
+ Patch created by Daniel Borca
+
+ Jan-2010 - back to unzip and minizip 1.0 name scheme, with compatibility layer
+
+ Copyright (C) 1998 - 2010 Gilles Vollant, Even Rouault, Mathias Svensson
+
+*/
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifndef NOUNCRYPT
+ #define NOUNCRYPT
+#endif
+
+#include "zlib.h"
+#include "unzip.h"
+
+#ifdef STDC
+# include <stddef.h>
+#endif
+#ifdef NO_ERRNO_H
+ extern int errno;
+#else
+# include <errno.h>
+#endif
+
+
+#ifndef local
+# define local static
+#endif
+/* compile with -Dlocal if your debugger can't find static symbols */
+
+
+#ifndef CASESENSITIVITYDEFAULT_NO
+# if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES)
+# define CASESENSITIVITYDEFAULT_NO
+# endif
+#endif
+
+
+#ifndef UNZ_BUFSIZE
+#define UNZ_BUFSIZE (16384)
+#endif
+
+#ifndef UNZ_MAXFILENAMEINZIP
+#define UNZ_MAXFILENAMEINZIP (256)
+#endif
+
+#ifndef ALLOC
+# define ALLOC(size) (malloc(size))
+#endif
+
+#define SIZECENTRALDIRITEM (0x2e)
+#define SIZEZIPLOCALHEADER (0x1e)
+
+
+const char unz_copyright[] =
+ " unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll";
+
+/* unz_file_info_interntal contain internal info about a file in zipfile*/
+typedef struct unz_file_info64_internal_s
+{
+ ZPOS64_T offset_curfile;/* relative offset of local header 8 bytes */
+} unz_file_info64_internal;
+
+
+/* file_in_zip_read_info_s contain internal information about a file in zipfile,
+ when reading and decompress it */
+typedef struct
+{
+ char *read_buffer; /* internal buffer for compressed data */
+ z_stream stream; /* zLib stream structure for inflate */
+
+#ifdef HAVE_BZIP2
+ bz_stream bstream; /* bzLib stream structure for bziped */
+#endif
+
+ ZPOS64_T pos_in_zipfile; /* position in byte on the zipfile, for fseek*/
+ uLong stream_initialised; /* flag set if stream structure is initialised*/
+
+ ZPOS64_T offset_local_extrafield;/* offset of the local extra field */
+ uInt size_local_extrafield;/* size of the local extra field */
+ ZPOS64_T pos_local_extrafield; /* position in the local extra field in read*/
+ ZPOS64_T total_out_64;
+
+ uLong crc32; /* crc32 of all data uncompressed */
+ uLong crc32_wait; /* crc32 we must obtain after decompress all */
+ ZPOS64_T rest_read_compressed; /* number of byte to be decompressed */
+ ZPOS64_T rest_read_uncompressed;/*number of byte to be obtained after decomp*/
+ zlib_filefunc64_32_def z_filefunc;
+ voidpf filestream; /* io structure of the zipfile */
+ uLong compression_method; /* compression method (0==store) */
+ ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
+ int raw;
+} file_in_zip64_read_info_s;
+
+
+/* unz64_s contain internal information about the zipfile
+*/
+typedef struct
+{
+ zlib_filefunc64_32_def z_filefunc;
+ int is64bitOpenFunction;
+ voidpf filestream; /* io structure of the zipfile */
+ unz_global_info64 gi; /* public global information */
+ ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
+ ZPOS64_T num_file; /* number of the current file in the zipfile*/
+ ZPOS64_T pos_in_central_dir; /* pos of the current file in the central dir*/
+ ZPOS64_T current_file_ok; /* flag about the usability of the current file*/
+ ZPOS64_T central_pos; /* position of the beginning of the central dir*/
+
+ ZPOS64_T size_central_dir; /* size of the central directory */
+ ZPOS64_T offset_central_dir; /* offset of start of central directory with
+ respect to the starting disk number */
+
+ unz_file_info64 cur_file_info; /* public info about the current file in zip*/
+ unz_file_info64_internal cur_file_info_internal; /* private info about it*/
+ file_in_zip64_read_info_s* pfile_in_zip_read; /* structure about the current
+ file if we are decompressing it */
+ int encrypted;
+
+ int isZip64;
+
+# ifndef NOUNCRYPT
+ unsigned long keys[3]; /* keys defining the pseudo-random sequence */
+ const z_crc_t* pcrc_32_tab;
+# endif
+} unz64_s;
+
+
+#ifndef NOUNCRYPT
+#include "crypt.h"
+#endif
+
+
+/* ===========================================================================
+ Reads a long in LSB order from the given gz_stream. Sets
+*/
+
+local int unz64local_getShort(const zlib_filefunc64_32_def* pzlib_filefunc_def,
+ voidpf filestream,
+ uLong *pX) {
+ unsigned char c[2];
+ int err = (int)ZREAD64(*pzlib_filefunc_def,filestream,c,2);
+ if (err==2)
+ {
+ *pX = c[0] | ((uLong)c[1] << 8);
+ return UNZ_OK;
+ }
+ else
+ {
+ *pX = 0;
+ if (ZERROR64(*pzlib_filefunc_def,filestream))
+ return UNZ_ERRNO;
+ else
+ return UNZ_EOF;
+ }
+}
+
+local int unz64local_getLong(const zlib_filefunc64_32_def* pzlib_filefunc_def,
+ voidpf filestream,
+ uLong *pX) {
+ unsigned char c[4];
+ int err = (int)ZREAD64(*pzlib_filefunc_def,filestream,c,4);
+ if (err==4)
+ {
+ *pX = c[0] | ((uLong)c[1] << 8) | ((uLong)c[2] << 16) | ((uLong)c[3] << 24);
+ return UNZ_OK;
+ }
+ else
+ {
+ *pX = 0;
+ if (ZERROR64(*pzlib_filefunc_def,filestream))
+ return UNZ_ERRNO;
+ else
+ return UNZ_EOF;
+ }
+}
+
+
+local int unz64local_getLong64(const zlib_filefunc64_32_def* pzlib_filefunc_def,
+ voidpf filestream,
+ ZPOS64_T *pX) {
+ unsigned char c[8];
+ int err = (int)ZREAD64(*pzlib_filefunc_def,filestream,c,8);
+ if (err==8)
+ {
+ *pX = c[0] | ((ZPOS64_T)c[1] << 8) | ((ZPOS64_T)c[2] << 16) | ((ZPOS64_T)c[3] << 24)
+ | ((ZPOS64_T)c[4] << 32) | ((ZPOS64_T)c[5] << 40) | ((ZPOS64_T)c[6] << 48) | ((ZPOS64_T)c[7] << 56);
+ return UNZ_OK;
+ }
+ else
+ {
+ *pX = 0;
+ if (ZERROR64(*pzlib_filefunc_def,filestream))
+ return UNZ_ERRNO;
+ else
+ return UNZ_EOF;
+ }
+}
+
+/* My own strcmpi / strcasecmp */
+local int strcmpcasenosensitive_internal(const char* fileName1, const char* fileName2) {
+ for (;;)
+ {
+ char c1=*(fileName1++);
+ char c2=*(fileName2++);
+ if ((c1>='a') && (c1<='z'))
+ c1 -= 0x20;
+ if ((c2>='a') && (c2<='z'))
+ c2 -= 0x20;
+ if (c1=='\0')
+ return ((c2=='\0') ? 0 : -1);
+ if (c2=='\0')
+ return 1;
+ if (c1<c2)
+ return -1;
+ if (c1>c2)
+ return 1;
+ }
+}
+
+
+#ifdef CASESENSITIVITYDEFAULT_NO
+#define CASESENSITIVITYDEFAULTVALUE 2
+#else
+#define CASESENSITIVITYDEFAULTVALUE 1
+#endif
+
+#ifndef STRCMPCASENOSENTIVEFUNCTION
+#define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal
+#endif
+
+/*
+ Compare two filenames (fileName1,fileName2).
+ If iCaseSensitivity = 1, comparison is case sensitive (like strcmp)
+ If iCaseSensitivity = 2, comparison is not case sensitive (like strcmpi
+ or strcasecmp)
+ If iCaseSensitivity = 0, case sensitivity is default of your operating system
+ (like 1 on Unix, 2 on Windows)
+
+*/
+extern int ZEXPORT unzStringFileNameCompare (const char* fileName1,
+ const char* fileName2,
+ int iCaseSensitivity) {
+ if (iCaseSensitivity==0)
+ iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE;
+
+ if (iCaseSensitivity==1)
+ return strcmp(fileName1,fileName2);
+
+ return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2);
+}
+
+#ifndef BUFREADCOMMENT
+#define BUFREADCOMMENT (0x400)
+#endif
+
+#ifndef CENTRALDIRINVALID
+#define CENTRALDIRINVALID ((ZPOS64_T)(-1))
+#endif
+
+/*
+ Locate the Central directory of a zipfile (at the end, just before
+ the global comment)
+*/
+local ZPOS64_T unz64local_SearchCentralDir(const zlib_filefunc64_32_def* pzlib_filefunc_def, voidpf filestream) {
+ unsigned char* buf;
+ ZPOS64_T uSizeFile;
+ ZPOS64_T uBackRead;
+ ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */
+ ZPOS64_T uPosFound=CENTRALDIRINVALID;
+
+ if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
+ return CENTRALDIRINVALID;
+
+
+ uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream);
+
+ if (uMaxBack>uSizeFile)
+ uMaxBack = uSizeFile;
+
+ buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
+ if (buf==NULL)
+ return CENTRALDIRINVALID;
+
+ uBackRead = 4;
+ while (uBackRead<uMaxBack)
+ {
+ uLong uReadSize;
+ ZPOS64_T uReadPos ;
+ int i;
+ if (uBackRead+BUFREADCOMMENT>uMaxBack)
+ uBackRead = uMaxBack;
+ else
+ uBackRead+=BUFREADCOMMENT;
+ uReadPos = uSizeFile-uBackRead ;
+
+ uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?
+ (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos);
+ if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0)
+ break;
+
+ if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)
+ break;
+
+ for (i=(int)uReadSize-3; (i--)>0;)
+ if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&
+ ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))
+ {
+ uPosFound = uReadPos+(unsigned)i;
+ break;
+ }
+
+ if (uPosFound!=CENTRALDIRINVALID)
+ break;
+ }
+ free(buf);
+ return uPosFound;
+}
+
+
+/*
+ Locate the Central directory 64 of a zipfile (at the end, just before
+ the global comment)
+*/
+local ZPOS64_T unz64local_SearchCentralDir64(const zlib_filefunc64_32_def* pzlib_filefunc_def,
+ voidpf filestream) {
+ unsigned char* buf;
+ ZPOS64_T uSizeFile;
+ ZPOS64_T uBackRead;
+ ZPOS64_T uMaxBack=0xffff; /* maximum size of global comment */
+ ZPOS64_T uPosFound=CENTRALDIRINVALID;
+ uLong uL;
+ ZPOS64_T relativeOffset;
+
+ if (ZSEEK64(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0)
+ return CENTRALDIRINVALID;
+
+
+ uSizeFile = ZTELL64(*pzlib_filefunc_def,filestream);
+
+ if (uMaxBack>uSizeFile)
+ uMaxBack = uSizeFile;
+
+ buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
+ if (buf==NULL)
+ return CENTRALDIRINVALID;
+
+ uBackRead = 4;
+ while (uBackRead<uMaxBack)
+ {
+ uLong uReadSize;
+ ZPOS64_T uReadPos;
+ int i;
+ if (uBackRead+BUFREADCOMMENT>uMaxBack)
+ uBackRead = uMaxBack;
+ else
+ uBackRead+=BUFREADCOMMENT;
+ uReadPos = uSizeFile-uBackRead ;
+
+ uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?
+ (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos);
+ if (ZSEEK64(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0)
+ break;
+
+ if (ZREAD64(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize)
+ break;
+
+ for (i=(int)uReadSize-3; (i--)>0;)
+ if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&
+ ((*(buf+i+2))==0x06) && ((*(buf+i+3))==0x07))
+ {
+ uPosFound = uReadPos+(unsigned)i;
+ break;
+ }
+
+ if (uPosFound!=CENTRALDIRINVALID)
+ break;
+ }
+ free(buf);
+ if (uPosFound == CENTRALDIRINVALID)
+ return CENTRALDIRINVALID;
+
+ /* Zip64 end of central directory locator */
+ if (ZSEEK64(*pzlib_filefunc_def,filestream, uPosFound,ZLIB_FILEFUNC_SEEK_SET)!=0)
+ return CENTRALDIRINVALID;
+
+ /* the signature, already checked */
+ if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)
+ return CENTRALDIRINVALID;
+
+ /* number of the disk with the start of the zip64 end of central directory */
+ if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)
+ return CENTRALDIRINVALID;
+ if (uL != 0)
+ return CENTRALDIRINVALID;
+
+ /* relative offset of the zip64 end of central directory record */
+ if (unz64local_getLong64(pzlib_filefunc_def,filestream,&relativeOffset)!=UNZ_OK)
+ return CENTRALDIRINVALID;
+
+ /* total number of disks */
+ if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)
+ return CENTRALDIRINVALID;
+ if (uL != 1)
+ return CENTRALDIRINVALID;
+
+ /* Goto end of central directory record */
+ if (ZSEEK64(*pzlib_filefunc_def,filestream, relativeOffset,ZLIB_FILEFUNC_SEEK_SET)!=0)
+ return CENTRALDIRINVALID;
+
+ /* the signature */
+ if (unz64local_getLong(pzlib_filefunc_def,filestream,&uL)!=UNZ_OK)
+ return CENTRALDIRINVALID;
+
+ if (uL != 0x06064b50)
+ return CENTRALDIRINVALID;
+
+ return relativeOffset;
+}
+
+/*
+ Open a Zip file. path contain the full pathname (by example,
+ on a Windows NT computer "c:\\test\\zlib114.zip" or on an Unix computer
+ "zlib/zlib114.zip".
+ If the zipfile cannot be opened (file doesn't exist or in not valid), the
+ return value is NULL.
+ Else, the return value is a unzFile Handle, usable with other function
+ of this unzip package.
+*/
+local unzFile unzOpenInternal(const void *path,
+ zlib_filefunc64_32_def* pzlib_filefunc64_32_def,
+ int is64bitOpenFunction) {
+ unz64_s us;
+ unz64_s *s;
+ ZPOS64_T central_pos;
+ uLong uL;
+
+ uLong number_disk; /* number of the current dist, used for
+ spanning ZIP, unsupported, always 0*/
+ uLong number_disk_with_CD; /* number the the disk with central dir, used
+ for spanning ZIP, unsupported, always 0*/
+ ZPOS64_T number_entry_CD; /* total number of entries in
+ the central dir
+ (same than number_entry on nospan) */
+
+ int err=UNZ_OK;
+
+ if (unz_copyright[0]!=' ')
+ return NULL;
+
+ us.z_filefunc.zseek32_file = NULL;
+ us.z_filefunc.ztell32_file = NULL;
+ if (pzlib_filefunc64_32_def==NULL)
+ fill_fopen64_filefunc(&us.z_filefunc.zfile_func64);
+ else
+ us.z_filefunc = *pzlib_filefunc64_32_def;
+ us.is64bitOpenFunction = is64bitOpenFunction;
+
+
+
+ us.filestream = ZOPEN64(us.z_filefunc,
+ path,
+ ZLIB_FILEFUNC_MODE_READ |
+ ZLIB_FILEFUNC_MODE_EXISTING);
+ if (us.filestream==NULL)
+ return NULL;
+
+ central_pos = unz64local_SearchCentralDir64(&us.z_filefunc,us.filestream);
+ if (central_pos!=CENTRALDIRINVALID)
+ {
+ uLong uS;
+ ZPOS64_T uL64;
+
+ us.isZip64 = 1;
+
+ if (ZSEEK64(us.z_filefunc, us.filestream,
+ central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0)
+ err=UNZ_ERRNO;
+
+ /* the signature, already checked */
+ if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ /* size of zip64 end of central directory record */
+ if (unz64local_getLong64(&us.z_filefunc, us.filestream,&uL64)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ /* version made by */
+ if (unz64local_getShort(&us.z_filefunc, us.filestream,&uS)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ /* version needed to extract */
+ if (unz64local_getShort(&us.z_filefunc, us.filestream,&uS)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ /* number of this disk */
+ if (unz64local_getLong(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ /* number of the disk with the start of the central directory */
+ if (unz64local_getLong(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ /* total number of entries in the central directory on this disk */
+ if (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.gi.number_entry)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ /* total number of entries in the central directory */
+ if (unz64local_getLong64(&us.z_filefunc, us.filestream,&number_entry_CD)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if ((number_entry_CD!=us.gi.number_entry) ||
+ (number_disk_with_CD!=0) ||
+ (number_disk!=0))
+ err=UNZ_BADZIPFILE;
+
+ /* size of the central directory */
+ if (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.size_central_dir)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ /* offset of start of central directory with respect to the
+ starting disk number */
+ if (unz64local_getLong64(&us.z_filefunc, us.filestream,&us.offset_central_dir)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ us.gi.size_comment = 0;
+ }
+ else
+ {
+ central_pos = unz64local_SearchCentralDir(&us.z_filefunc,us.filestream);
+ if (central_pos==CENTRALDIRINVALID)
+ err=UNZ_ERRNO;
+
+ us.isZip64 = 0;
+
+ if (ZSEEK64(us.z_filefunc, us.filestream,
+ central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0)
+ err=UNZ_ERRNO;
+
+ /* the signature, already checked */
+ if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ /* number of this disk */
+ if (unz64local_getShort(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ /* number of the disk with the start of the central directory */
+ if (unz64local_getShort(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ /* total number of entries in the central dir on this disk */
+ if (unz64local_getShort(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
+ err=UNZ_ERRNO;
+ us.gi.number_entry = uL;
+
+ /* total number of entries in the central dir */
+ if (unz64local_getShort(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
+ err=UNZ_ERRNO;
+ number_entry_CD = uL;
+
+ if ((number_entry_CD!=us.gi.number_entry) ||
+ (number_disk_with_CD!=0) ||
+ (number_disk!=0))
+ err=UNZ_BADZIPFILE;
+
+ /* size of the central directory */
+ if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
+ err=UNZ_ERRNO;
+ us.size_central_dir = uL;
+
+ /* offset of start of central directory with respect to the
+ starting disk number */
+ if (unz64local_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK)
+ err=UNZ_ERRNO;
+ us.offset_central_dir = uL;
+
+ /* zipfile comment length */
+ if (unz64local_getShort(&us.z_filefunc, us.filestream,&us.gi.size_comment)!=UNZ_OK)
+ err=UNZ_ERRNO;
+ }
+
+ if ((central_pos<us.offset_central_dir+us.size_central_dir) &&
+ (err==UNZ_OK))
+ err=UNZ_BADZIPFILE;
+
+ if (err!=UNZ_OK)
+ {
+ ZCLOSE64(us.z_filefunc, us.filestream);
+ return NULL;
+ }
+
+ us.byte_before_the_zipfile = central_pos -
+ (us.offset_central_dir+us.size_central_dir);
+ us.central_pos = central_pos;
+ us.pfile_in_zip_read = NULL;
+ us.encrypted = 0;
+
+
+ s=(unz64_s*)ALLOC(sizeof(unz64_s));
+ if( s != NULL)
+ {
+ *s=us;
+ unzGoToFirstFile((unzFile)s);
+ }
+ return (unzFile)s;
+}
+
+
+extern unzFile ZEXPORT unzOpen2(const char *path,
+ zlib_filefunc_def* pzlib_filefunc32_def) {
+ if (pzlib_filefunc32_def != NULL)
+ {
+ zlib_filefunc64_32_def zlib_filefunc64_32_def_fill;
+ fill_zlib_filefunc64_32_def_from_filefunc32(&zlib_filefunc64_32_def_fill,pzlib_filefunc32_def);
+ return unzOpenInternal(path, &zlib_filefunc64_32_def_fill, 0);
+ }
+ else
+ return unzOpenInternal(path, NULL, 0);
+}
+
+extern unzFile ZEXPORT unzOpen2_64(const void *path,
+ zlib_filefunc64_def* pzlib_filefunc_def) {
+ if (pzlib_filefunc_def != NULL)
+ {
+ zlib_filefunc64_32_def zlib_filefunc64_32_def_fill;
+ zlib_filefunc64_32_def_fill.zfile_func64 = *pzlib_filefunc_def;
+ zlib_filefunc64_32_def_fill.ztell32_file = NULL;
+ zlib_filefunc64_32_def_fill.zseek32_file = NULL;
+ return unzOpenInternal(path, &zlib_filefunc64_32_def_fill, 1);
+ }
+ else
+ return unzOpenInternal(path, NULL, 1);
+}
+
+extern unzFile ZEXPORT unzOpen(const char *path) {
+ return unzOpenInternal(path, NULL, 0);
+}
+
+extern unzFile ZEXPORT unzOpen64(const void *path) {
+ return unzOpenInternal(path, NULL, 1);
+}
+
+/*
+ Close a ZipFile opened with unzOpen.
+ If there is files inside the .Zip opened with unzOpenCurrentFile (see later),
+ these files MUST be closed with unzCloseCurrentFile before call unzClose.
+ return UNZ_OK if there is no problem. */
+extern int ZEXPORT unzClose(unzFile file) {
+ unz64_s* s;
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz64_s*)file;
+
+ if (s->pfile_in_zip_read!=NULL)
+ unzCloseCurrentFile(file);
+
+ ZCLOSE64(s->z_filefunc, s->filestream);
+ free(s);
+ return UNZ_OK;
+}
+
+
+/*
+ Write info about the ZipFile in the *pglobal_info structure.
+ No preparation of the structure is needed
+ return UNZ_OK if there is no problem. */
+extern int ZEXPORT unzGetGlobalInfo64(unzFile file, unz_global_info64* pglobal_info) {
+ unz64_s* s;
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz64_s*)file;
+ *pglobal_info=s->gi;
+ return UNZ_OK;
+}
+
+extern int ZEXPORT unzGetGlobalInfo(unzFile file, unz_global_info* pglobal_info32) {
+ unz64_s* s;
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz64_s*)file;
+ /* to do : check if number_entry is not truncated */
+ pglobal_info32->number_entry = (uLong)s->gi.number_entry;
+ pglobal_info32->size_comment = s->gi.size_comment;
+ return UNZ_OK;
+}
+/*
+ Translate date/time from Dos format to tm_unz (readable more easily)
+*/
+local void unz64local_DosDateToTmuDate(ZPOS64_T ulDosDate, tm_unz* ptm) {
+ ZPOS64_T uDate;
+ uDate = (ZPOS64_T)(ulDosDate>>16);
+ ptm->tm_mday = (int)(uDate&0x1f) ;
+ ptm->tm_mon = (int)((((uDate)&0x1E0)/0x20)-1) ;
+ ptm->tm_year = (int)(((uDate&0x0FE00)/0x0200)+1980) ;
+
+ ptm->tm_hour = (int) ((ulDosDate &0xF800)/0x800);
+ ptm->tm_min = (int) ((ulDosDate&0x7E0)/0x20) ;
+ ptm->tm_sec = (int) (2*(ulDosDate&0x1f)) ;
+}
+
+/*
+ Get Info about the current file in the zipfile, with internal only info
+*/
+local int unz64local_GetCurrentFileInfoInternal(unzFile file,
+ unz_file_info64 *pfile_info,
+ unz_file_info64_internal
+ *pfile_info_internal,
+ char *szFileName,
+ uLong fileNameBufferSize,
+ void *extraField,
+ uLong extraFieldBufferSize,
+ char *szComment,
+ uLong commentBufferSize) {
+ unz64_s* s;
+ unz_file_info64 file_info;
+ unz_file_info64_internal file_info_internal;
+ int err=UNZ_OK;
+ uLong uMagic;
+ long lSeek=0;
+ uLong uL;
+
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz64_s*)file;
+ if (ZSEEK64(s->z_filefunc, s->filestream,
+ s->pos_in_central_dir+s->byte_before_the_zipfile,
+ ZLIB_FILEFUNC_SEEK_SET)!=0)
+ err=UNZ_ERRNO;
+
+
+ /* we check the magic */
+ if (err==UNZ_OK)
+ {
+ if (unz64local_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)
+ err=UNZ_ERRNO;
+ else if (uMagic!=0x02014b50)
+ err=UNZ_BADZIPFILE;
+ }
+
+ if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.version) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.version_needed) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.flag) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.compression_method) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.dosDate) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ unz64local_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date);
+
+ if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.crc) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK)
+ err=UNZ_ERRNO;
+ file_info.compressed_size = uL;
+
+ if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK)
+ err=UNZ_ERRNO;
+ file_info.uncompressed_size = uL;
+
+ if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.size_filename) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_extra) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_comment) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.disk_num_start) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unz64local_getShort(&s->z_filefunc, s->filestream,&file_info.internal_fa) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.external_fa) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ // relative offset of local header
+ if (unz64local_getLong(&s->z_filefunc, s->filestream,&uL) != UNZ_OK)
+ err=UNZ_ERRNO;
+ file_info_internal.offset_curfile = uL;
+
+ lSeek+=file_info.size_filename;
+ if ((err==UNZ_OK) && (szFileName!=NULL))
+ {
+ uLong uSizeRead ;
+ if (file_info.size_filename<fileNameBufferSize)
+ {
+ *(szFileName+file_info.size_filename)='\0';
+ uSizeRead = file_info.size_filename;
+ }
+ else
+ uSizeRead = fileNameBufferSize;
+
+ if ((file_info.size_filename>0) && (fileNameBufferSize>0))
+ if (ZREAD64(s->z_filefunc, s->filestream,szFileName,uSizeRead)!=uSizeRead)
+ err=UNZ_ERRNO;
+ lSeek -= uSizeRead;
+ }
+
+ // Read extrafield
+ if ((err==UNZ_OK) && (extraField!=NULL))
+ {
+ ZPOS64_T uSizeRead ;
+ if (file_info.size_file_extra<extraFieldBufferSize)
+ uSizeRead = file_info.size_file_extra;
+ else
+ uSizeRead = extraFieldBufferSize;
+
+ if (lSeek!=0)
+ {
+ if (ZSEEK64(s->z_filefunc, s->filestream,(ZPOS64_T)lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
+ lSeek=0;
+ else
+ err=UNZ_ERRNO;
+ }
+
+ if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0))
+ if (ZREAD64(s->z_filefunc, s->filestream,extraField,(uLong)uSizeRead)!=uSizeRead)
+ err=UNZ_ERRNO;
+
+ lSeek += file_info.size_file_extra - (uLong)uSizeRead;
+ }
+ else
+ lSeek += file_info.size_file_extra;
+
+
+ if ((err==UNZ_OK) && (file_info.size_file_extra != 0))
+ {
+ uLong acc = 0;
+
+ // since lSeek now points to after the extra field we need to move back
+ lSeek -= file_info.size_file_extra;
+
+ if (lSeek!=0)
+ {
+ if (ZSEEK64(s->z_filefunc, s->filestream,(ZPOS64_T)lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
+ lSeek=0;
+ else
+ err=UNZ_ERRNO;
+ }
+
+ while(acc < file_info.size_file_extra)
+ {
+ uLong headerId;
+ uLong dataSize;
+
+ if (unz64local_getShort(&s->z_filefunc, s->filestream,&headerId) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unz64local_getShort(&s->z_filefunc, s->filestream,&dataSize) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ /* ZIP64 extra fields */
+ if (headerId == 0x0001)
+ {
+ if(file_info.uncompressed_size == MAXU32)
+ {
+ if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK)
+ err=UNZ_ERRNO;
+ }
+
+ if(file_info.compressed_size == MAXU32)
+ {
+ if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK)
+ err=UNZ_ERRNO;
+ }
+
+ if(file_info_internal.offset_curfile == MAXU32)
+ {
+ /* Relative Header offset */
+ if (unz64local_getLong64(&s->z_filefunc, s->filestream,&file_info_internal.offset_curfile) != UNZ_OK)
+ err=UNZ_ERRNO;
+ }
+
+ if(file_info.disk_num_start == 0xffff)
+ {
+ /* Disk Start Number */
+ if (unz64local_getLong(&s->z_filefunc, s->filestream,&file_info.disk_num_start) != UNZ_OK)
+ err=UNZ_ERRNO;
+ }
+
+ }
+ else
+ {
+ if (ZSEEK64(s->z_filefunc, s->filestream,dataSize,ZLIB_FILEFUNC_SEEK_CUR)!=0)
+ err=UNZ_ERRNO;
+ }
+
+ acc += 2 + 2 + dataSize;
+ }
+ }
+
+ if ((err==UNZ_OK) && (szComment!=NULL))
+ {
+ uLong uSizeRead ;
+ if (file_info.size_file_comment<commentBufferSize)
+ {
+ *(szComment+file_info.size_file_comment)='\0';
+ uSizeRead = file_info.size_file_comment;
+ }
+ else
+ uSizeRead = commentBufferSize;
+
+ if (lSeek!=0)
+ {
+ if (ZSEEK64(s->z_filefunc, s->filestream,(ZPOS64_T)lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0)
+ lSeek=0;
+ else
+ err=UNZ_ERRNO;
+ }
+
+ if ((file_info.size_file_comment>0) && (commentBufferSize>0))
+ if (ZREAD64(s->z_filefunc, s->filestream,szComment,uSizeRead)!=uSizeRead)
+ err=UNZ_ERRNO;
+ lSeek+=file_info.size_file_comment - uSizeRead;
+ }
+ else
+ lSeek+=file_info.size_file_comment;
+
+
+ if ((err==UNZ_OK) && (pfile_info!=NULL))
+ *pfile_info=file_info;
+
+ if ((err==UNZ_OK) && (pfile_info_internal!=NULL))
+ *pfile_info_internal=file_info_internal;
+
+ return err;
+}
+
+
+
+/*
+ Write info about the ZipFile in the *pglobal_info structure.
+ No preparation of the structure is needed
+ return UNZ_OK if there is no problem.
+*/
+extern int ZEXPORT unzGetCurrentFileInfo64(unzFile file,
+ unz_file_info64 * pfile_info,
+ char * szFileName, uLong fileNameBufferSize,
+ void *extraField, uLong extraFieldBufferSize,
+ char* szComment, uLong commentBufferSize) {
+ return unz64local_GetCurrentFileInfoInternal(file,pfile_info,NULL,
+ szFileName,fileNameBufferSize,
+ extraField,extraFieldBufferSize,
+ szComment,commentBufferSize);
+}
+
+extern int ZEXPORT unzGetCurrentFileInfo(unzFile file,
+ unz_file_info * pfile_info,
+ char * szFileName, uLong fileNameBufferSize,
+ void *extraField, uLong extraFieldBufferSize,
+ char* szComment, uLong commentBufferSize) {
+ int err;
+ unz_file_info64 file_info64;
+ err = unz64local_GetCurrentFileInfoInternal(file,&file_info64,NULL,
+ szFileName,fileNameBufferSize,
+ extraField,extraFieldBufferSize,
+ szComment,commentBufferSize);
+ if ((err==UNZ_OK) && (pfile_info != NULL))
+ {
+ pfile_info->version = file_info64.version;
+ pfile_info->version_needed = file_info64.version_needed;
+ pfile_info->flag = file_info64.flag;
+ pfile_info->compression_method = file_info64.compression_method;
+ pfile_info->dosDate = file_info64.dosDate;
+ pfile_info->crc = file_info64.crc;
+
+ pfile_info->size_filename = file_info64.size_filename;
+ pfile_info->size_file_extra = file_info64.size_file_extra;
+ pfile_info->size_file_comment = file_info64.size_file_comment;
+
+ pfile_info->disk_num_start = file_info64.disk_num_start;
+ pfile_info->internal_fa = file_info64.internal_fa;
+ pfile_info->external_fa = file_info64.external_fa;
+
+ pfile_info->tmu_date = file_info64.tmu_date;
+
+
+ pfile_info->compressed_size = (uLong)file_info64.compressed_size;
+ pfile_info->uncompressed_size = (uLong)file_info64.uncompressed_size;
+
+ }
+ return err;
+}
+/*
+ Set the current file of the zipfile to the first file.
+ return UNZ_OK if there is no problem
+*/
+extern int ZEXPORT unzGoToFirstFile(unzFile file) {
+ int err=UNZ_OK;
+ unz64_s* s;
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz64_s*)file;
+ s->pos_in_central_dir=s->offset_central_dir;
+ s->num_file=0;
+ err=unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info,
+ &s->cur_file_info_internal,
+ NULL,0,NULL,0,NULL,0);
+ s->current_file_ok = (err == UNZ_OK);
+ return err;
+}
+
+/*
+ Set the current file of the zipfile to the next file.
+ return UNZ_OK if there is no problem
+ return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
+*/
+extern int ZEXPORT unzGoToNextFile(unzFile file) {
+ unz64_s* s;
+ int err;
+
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz64_s*)file;
+ if (!s->current_file_ok)
+ return UNZ_END_OF_LIST_OF_FILE;
+ if (s->gi.number_entry != 0xffff) /* 2^16 files overflow hack */
+ if (s->num_file+1==s->gi.number_entry)
+ return UNZ_END_OF_LIST_OF_FILE;
+
+ s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename +
+ s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ;
+ s->num_file++;
+ err = unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info,
+ &s->cur_file_info_internal,
+ NULL,0,NULL,0,NULL,0);
+ s->current_file_ok = (err == UNZ_OK);
+ return err;
+}
+
+
+/*
+ Try locate the file szFileName in the zipfile.
+ For the iCaseSensitivity signification, see unzStringFileNameCompare
+
+ return value :
+ UNZ_OK if the file is found. It becomes the current file.
+ UNZ_END_OF_LIST_OF_FILE if the file is not found
+*/
+extern int ZEXPORT unzLocateFile(unzFile file, const char *szFileName, int iCaseSensitivity) {
+ unz64_s* s;
+ int err;
+
+ /* We remember the 'current' position in the file so that we can jump
+ * back there if we fail.
+ */
+ unz_file_info64 cur_file_infoSaved;
+ unz_file_info64_internal cur_file_info_internalSaved;
+ ZPOS64_T num_fileSaved;
+ ZPOS64_T pos_in_central_dirSaved;
+
+
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+
+ if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP)
+ return UNZ_PARAMERROR;
+
+ s=(unz64_s*)file;
+ if (!s->current_file_ok)
+ return UNZ_END_OF_LIST_OF_FILE;
+
+ /* Save the current state */
+ num_fileSaved = s->num_file;
+ pos_in_central_dirSaved = s->pos_in_central_dir;
+ cur_file_infoSaved = s->cur_file_info;
+ cur_file_info_internalSaved = s->cur_file_info_internal;
+
+ err = unzGoToFirstFile(file);
+
+ while (err == UNZ_OK)
+ {
+ char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1];
+ err = unzGetCurrentFileInfo64(file,NULL,
+ szCurrentFileName,sizeof(szCurrentFileName)-1,
+ NULL,0,NULL,0);
+ if (err == UNZ_OK)
+ {
+ if (unzStringFileNameCompare(szCurrentFileName,
+ szFileName,iCaseSensitivity)==0)
+ return UNZ_OK;
+ err = unzGoToNextFile(file);
+ }
+ }
+
+ /* We failed, so restore the state of the 'current file' to where we
+ * were.
+ */
+ s->num_file = num_fileSaved ;
+ s->pos_in_central_dir = pos_in_central_dirSaved ;
+ s->cur_file_info = cur_file_infoSaved;
+ s->cur_file_info_internal = cur_file_info_internalSaved;
+ return err;
+}
+
+
+/*
+///////////////////////////////////////////
+// Contributed by Ryan Haksi (mailto://cryogen@infoserve.net)
+// I need random access
+//
+// Further optimization could be realized by adding an ability
+// to cache the directory in memory. The goal being a single
+// comprehensive file read to put the file I need in a memory.
+*/
+
+/*
+typedef struct unz_file_pos_s
+{
+ ZPOS64_T pos_in_zip_directory; // offset in file
+ ZPOS64_T num_of_file; // # of file
+} unz_file_pos;
+*/
+
+extern int ZEXPORT unzGetFilePos64(unzFile file, unz64_file_pos* file_pos) {
+ unz64_s* s;
+
+ if (file==NULL || file_pos==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz64_s*)file;
+ if (!s->current_file_ok)
+ return UNZ_END_OF_LIST_OF_FILE;
+
+ file_pos->pos_in_zip_directory = s->pos_in_central_dir;
+ file_pos->num_of_file = s->num_file;
+
+ return UNZ_OK;
+}
+
+extern int ZEXPORT unzGetFilePos(unzFile file, unz_file_pos* file_pos) {
+ unz64_file_pos file_pos64;
+ int err = unzGetFilePos64(file,&file_pos64);
+ if (err==UNZ_OK)
+ {
+ file_pos->pos_in_zip_directory = (uLong)file_pos64.pos_in_zip_directory;
+ file_pos->num_of_file = (uLong)file_pos64.num_of_file;
+ }
+ return err;
+}
+
+extern int ZEXPORT unzGoToFilePos64(unzFile file, const unz64_file_pos* file_pos) {
+ unz64_s* s;
+ int err;
+
+ if (file==NULL || file_pos==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz64_s*)file;
+
+ /* jump to the right spot */
+ s->pos_in_central_dir = file_pos->pos_in_zip_directory;
+ s->num_file = file_pos->num_of_file;
+
+ /* set the current file */
+ err = unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info,
+ &s->cur_file_info_internal,
+ NULL,0,NULL,0,NULL,0);
+ /* return results */
+ s->current_file_ok = (err == UNZ_OK);
+ return err;
+}
+
+extern int ZEXPORT unzGoToFilePos(unzFile file, unz_file_pos* file_pos) {
+ unz64_file_pos file_pos64;
+ if (file_pos == NULL)
+ return UNZ_PARAMERROR;
+
+ file_pos64.pos_in_zip_directory = file_pos->pos_in_zip_directory;
+ file_pos64.num_of_file = file_pos->num_of_file;
+ return unzGoToFilePos64(file,&file_pos64);
+}
+
+/*
+// Unzip Helper Functions - should be here?
+///////////////////////////////////////////
+*/
+
+/*
+ Read the local header of the current zipfile
+ Check the coherency of the local header and info in the end of central
+ directory about this file
+ store in *piSizeVar the size of extra info in local header
+ (filename and size of extra field data)
+*/
+local int unz64local_CheckCurrentFileCoherencyHeader(unz64_s* s, uInt* piSizeVar,
+ ZPOS64_T * poffset_local_extrafield,
+ uInt * psize_local_extrafield) {
+ uLong uMagic,uData,uFlags;
+ uLong size_filename;
+ uLong size_extra_field;
+ int err=UNZ_OK;
+
+ *piSizeVar = 0;
+ *poffset_local_extrafield = 0;
+ *psize_local_extrafield = 0;
+
+ if (ZSEEK64(s->z_filefunc, s->filestream,s->cur_file_info_internal.offset_curfile +
+ s->byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0)
+ return UNZ_ERRNO;
+
+
+ if (err==UNZ_OK)
+ {
+ if (unz64local_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK)
+ err=UNZ_ERRNO;
+ else if (uMagic!=0x04034b50)
+ err=UNZ_BADZIPFILE;
+ }
+
+ if (unz64local_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)
+ err=UNZ_ERRNO;
+/*
+ else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion))
+ err=UNZ_BADZIPFILE;
+*/
+ if (unz64local_getShort(&s->z_filefunc, s->filestream,&uFlags) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unz64local_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK)
+ err=UNZ_ERRNO;
+ else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method))
+ err=UNZ_BADZIPFILE;
+
+ if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) &&
+/* #ifdef HAVE_BZIP2 */
+ (s->cur_file_info.compression_method!=Z_BZIP2ED) &&
+/* #endif */
+ (s->cur_file_info.compression_method!=Z_DEFLATED))
+ err=UNZ_BADZIPFILE;
+
+ if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* date/time */
+ err=UNZ_ERRNO;
+
+ if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* crc */
+ err=UNZ_ERRNO;
+ else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) && ((uFlags & 8)==0))
+ err=UNZ_BADZIPFILE;
+
+ if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size compr */
+ err=UNZ_ERRNO;
+ else if (uData != 0xFFFFFFFF && (err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) && ((uFlags & 8)==0))
+ err=UNZ_BADZIPFILE;
+
+ if (unz64local_getLong(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) /* size uncompr */
+ err=UNZ_ERRNO;
+ else if (uData != 0xFFFFFFFF && (err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) && ((uFlags & 8)==0))
+ err=UNZ_BADZIPFILE;
+
+ if (unz64local_getShort(&s->z_filefunc, s->filestream,&size_filename) != UNZ_OK)
+ err=UNZ_ERRNO;
+ else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename))
+ err=UNZ_BADZIPFILE;
+
+ *piSizeVar += (uInt)size_filename;
+
+ if (unz64local_getShort(&s->z_filefunc, s->filestream,&size_extra_field) != UNZ_OK)
+ err=UNZ_ERRNO;
+ *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile +
+ SIZEZIPLOCALHEADER + size_filename;
+ *psize_local_extrafield = (uInt)size_extra_field;
+
+ *piSizeVar += (uInt)size_extra_field;
+
+ return err;
+}
+
+/*
+ Open for reading data the current file in the zipfile.
+ If there is no error and the file is opened, the return value is UNZ_OK.
+*/
+extern int ZEXPORT unzOpenCurrentFile3(unzFile file, int* method,
+ int* level, int raw, const char* password) {
+ int err=UNZ_OK;
+ uInt iSizeVar;
+ unz64_s* s;
+ file_in_zip64_read_info_s* pfile_in_zip_read_info;
+ ZPOS64_T offset_local_extrafield; /* offset of the local extra field */
+ uInt size_local_extrafield; /* size of the local extra field */
+# ifndef NOUNCRYPT
+ char source[12];
+# else
+ if (password != NULL)
+ return UNZ_PARAMERROR;
+# endif
+
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz64_s*)file;
+ if (!s->current_file_ok)
+ return UNZ_PARAMERROR;
+
+ if (s->pfile_in_zip_read != NULL)
+ unzCloseCurrentFile(file);
+
+ if (unz64local_CheckCurrentFileCoherencyHeader(s,&iSizeVar, &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK)
+ return UNZ_BADZIPFILE;
+
+ pfile_in_zip_read_info = (file_in_zip64_read_info_s*)ALLOC(sizeof(file_in_zip64_read_info_s));
+ if (pfile_in_zip_read_info==NULL)
+ return UNZ_INTERNALERROR;
+
+ pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE);
+ pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield;
+ pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;
+ pfile_in_zip_read_info->pos_local_extrafield=0;
+ pfile_in_zip_read_info->raw=raw;
+
+ if (pfile_in_zip_read_info->read_buffer==NULL)
+ {
+ free(pfile_in_zip_read_info);
+ return UNZ_INTERNALERROR;
+ }
+
+ pfile_in_zip_read_info->stream_initialised=0;
+
+ if (method!=NULL)
+ *method = (int)s->cur_file_info.compression_method;
+
+ if (level!=NULL)
+ {
+ *level = 6;
+ switch (s->cur_file_info.flag & 0x06)
+ {
+ case 6 : *level = 1; break;
+ case 4 : *level = 2; break;
+ case 2 : *level = 9; break;
+ }
+ }
+
+ if ((s->cur_file_info.compression_method!=0) &&
+/* #ifdef HAVE_BZIP2 */
+ (s->cur_file_info.compression_method!=Z_BZIP2ED) &&
+/* #endif */
+ (s->cur_file_info.compression_method!=Z_DEFLATED))
+
+ err=UNZ_BADZIPFILE;
+
+ pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc;
+ pfile_in_zip_read_info->crc32=0;
+ pfile_in_zip_read_info->total_out_64=0;
+ pfile_in_zip_read_info->compression_method = s->cur_file_info.compression_method;
+ pfile_in_zip_read_info->filestream=s->filestream;
+ pfile_in_zip_read_info->z_filefunc=s->z_filefunc;
+ pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile;
+
+ pfile_in_zip_read_info->stream.total_out = 0;
+
+ if ((s->cur_file_info.compression_method==Z_BZIP2ED) && (!raw))
+ {
+#ifdef HAVE_BZIP2
+ pfile_in_zip_read_info->bstream.bzalloc = (void *(*) (void *, int, int))0;
+ pfile_in_zip_read_info->bstream.bzfree = (free_func)0;
+ pfile_in_zip_read_info->bstream.opaque = (voidpf)0;
+ pfile_in_zip_read_info->bstream.state = (voidpf)0;
+
+ pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
+ pfile_in_zip_read_info->stream.zfree = (free_func)0;
+ pfile_in_zip_read_info->stream.opaque = (voidpf)0;
+ pfile_in_zip_read_info->stream.next_in = (voidpf)0;
+ pfile_in_zip_read_info->stream.avail_in = 0;
+
+ err=BZ2_bzDecompressInit(&pfile_in_zip_read_info->bstream, 0, 0);
+ if (err == Z_OK)
+ pfile_in_zip_read_info->stream_initialised=Z_BZIP2ED;
+ else
+ {
+ free(pfile_in_zip_read_info->read_buffer);
+ free(pfile_in_zip_read_info);
+ return err;
+ }
+#else
+ pfile_in_zip_read_info->raw=1;
+#endif
+ }
+ else if ((s->cur_file_info.compression_method==Z_DEFLATED) && (!raw))
+ {
+ pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
+ pfile_in_zip_read_info->stream.zfree = (free_func)0;
+ pfile_in_zip_read_info->stream.opaque = (voidpf)0;
+ pfile_in_zip_read_info->stream.next_in = 0;
+ pfile_in_zip_read_info->stream.avail_in = 0;
+
+ err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS);
+ if (err == Z_OK)
+ pfile_in_zip_read_info->stream_initialised=Z_DEFLATED;
+ else
+ {
+ free(pfile_in_zip_read_info->read_buffer);
+ free(pfile_in_zip_read_info);
+ return err;
+ }
+ /* windowBits is passed < 0 to tell that there is no zlib header.
+ * Note that in this case inflate *requires* an extra "dummy" byte
+ * after the compressed stream in order to complete decompression and
+ * return Z_STREAM_END.
+ * In unzip, i don't wait absolutely Z_STREAM_END because I known the
+ * size of both compressed and uncompressed data
+ */
+ }
+ pfile_in_zip_read_info->rest_read_compressed =
+ s->cur_file_info.compressed_size ;
+ pfile_in_zip_read_info->rest_read_uncompressed =
+ s->cur_file_info.uncompressed_size ;
+
+
+ pfile_in_zip_read_info->pos_in_zipfile =
+ s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER +
+ iSizeVar;
+
+ pfile_in_zip_read_info->stream.avail_in = (uInt)0;
+
+ s->pfile_in_zip_read = pfile_in_zip_read_info;
+ s->encrypted = 0;
+
+# ifndef NOUNCRYPT
+ if (password != NULL)
+ {
+ int i;
+ s->pcrc_32_tab = get_crc_table();
+ init_keys(password,s->keys,s->pcrc_32_tab);
+ if (ZSEEK64(s->z_filefunc, s->filestream,
+ s->pfile_in_zip_read->pos_in_zipfile +
+ s->pfile_in_zip_read->byte_before_the_zipfile,
+ SEEK_SET)!=0)
+ return UNZ_INTERNALERROR;
+ if(ZREAD64(s->z_filefunc, s->filestream,source, 12)<12)
+ return UNZ_INTERNALERROR;
+
+ for (i = 0; i<12; i++)
+ zdecode(s->keys,s->pcrc_32_tab,source[i]);
+
+ s->pfile_in_zip_read->pos_in_zipfile+=12;
+ s->encrypted=1;
+ }
+# endif
+
+
+ return UNZ_OK;
+}
+
+extern int ZEXPORT unzOpenCurrentFile(unzFile file) {
+ return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL);
+}
+
+extern int ZEXPORT unzOpenCurrentFilePassword(unzFile file, const char* password) {
+ return unzOpenCurrentFile3(file, NULL, NULL, 0, password);
+}
+
+extern int ZEXPORT unzOpenCurrentFile2(unzFile file, int* method, int* level, int raw) {
+ return unzOpenCurrentFile3(file, method, level, raw, NULL);
+}
+
+/** Addition for GDAL : START */
+
+extern ZPOS64_T ZEXPORT unzGetCurrentFileZStreamPos64(unzFile file) {
+ unz64_s* s;
+ file_in_zip64_read_info_s* pfile_in_zip_read_info;
+ s=(unz64_s*)file;
+ if (file==NULL)
+ return 0; //UNZ_PARAMERROR;
+ pfile_in_zip_read_info=s->pfile_in_zip_read;
+ if (pfile_in_zip_read_info==NULL)
+ return 0; //UNZ_PARAMERROR;
+ return pfile_in_zip_read_info->pos_in_zipfile +
+ pfile_in_zip_read_info->byte_before_the_zipfile;
+}
+
+/** Addition for GDAL : END */
+
+/*
+ Read bytes from the current file.
+ buf contain buffer where data must be copied
+ len the size of buf.
+
+ return the number of byte copied if some bytes are copied
+ return 0 if the end of file was reached
+ return <0 with error code if there is an error
+ (UNZ_ERRNO for IO error, or zLib error for uncompress error)
+*/
+extern int ZEXPORT unzReadCurrentFile(unzFile file, voidp buf, unsigned len) {
+ int err=UNZ_OK;
+ uInt iRead = 0;
+ unz64_s* s;
+ file_in_zip64_read_info_s* pfile_in_zip_read_info;
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz64_s*)file;
+ pfile_in_zip_read_info=s->pfile_in_zip_read;
+
+ if (pfile_in_zip_read_info==NULL)
+ return UNZ_PARAMERROR;
+
+
+ if (pfile_in_zip_read_info->read_buffer == NULL)
+ return UNZ_END_OF_LIST_OF_FILE;
+ if (len==0)
+ return 0;
+
+ pfile_in_zip_read_info->stream.next_out = (Bytef*)buf;
+
+ pfile_in_zip_read_info->stream.avail_out = (uInt)len;
+
+ if ((len>pfile_in_zip_read_info->rest_read_uncompressed) &&
+ (!(pfile_in_zip_read_info->raw)))
+ pfile_in_zip_read_info->stream.avail_out =
+ (uInt)pfile_in_zip_read_info->rest_read_uncompressed;
+
+ if ((len>pfile_in_zip_read_info->rest_read_compressed+
+ pfile_in_zip_read_info->stream.avail_in) &&
+ (pfile_in_zip_read_info->raw))
+ pfile_in_zip_read_info->stream.avail_out =
+ (uInt)pfile_in_zip_read_info->rest_read_compressed+
+ pfile_in_zip_read_info->stream.avail_in;
+
+ while (pfile_in_zip_read_info->stream.avail_out>0)
+ {
+ if ((pfile_in_zip_read_info->stream.avail_in==0) &&
+ (pfile_in_zip_read_info->rest_read_compressed>0))
+ {
+ uInt uReadThis = UNZ_BUFSIZE;
+ if (pfile_in_zip_read_info->rest_read_compressed<uReadThis)
+ uReadThis = (uInt)pfile_in_zip_read_info->rest_read_compressed;
+ if (uReadThis == 0)
+ return UNZ_EOF;
+ if (ZSEEK64(pfile_in_zip_read_info->z_filefunc,
+ pfile_in_zip_read_info->filestream,
+ pfile_in_zip_read_info->pos_in_zipfile +
+ pfile_in_zip_read_info->byte_before_the_zipfile,
+ ZLIB_FILEFUNC_SEEK_SET)!=0)
+ return UNZ_ERRNO;
+ if (ZREAD64(pfile_in_zip_read_info->z_filefunc,
+ pfile_in_zip_read_info->filestream,
+ pfile_in_zip_read_info->read_buffer,
+ uReadThis)!=uReadThis)
+ return UNZ_ERRNO;
+
+
+# ifndef NOUNCRYPT
+ if(s->encrypted)
+ {
+ uInt i;
+ for(i=0;i<uReadThis;i++)
+ pfile_in_zip_read_info->read_buffer[i] =
+ zdecode(s->keys,s->pcrc_32_tab,
+ pfile_in_zip_read_info->read_buffer[i]);
+ }
+# endif
+
+
+ pfile_in_zip_read_info->pos_in_zipfile += uReadThis;
+
+ pfile_in_zip_read_info->rest_read_compressed-=uReadThis;
+
+ pfile_in_zip_read_info->stream.next_in =
+ (Bytef*)pfile_in_zip_read_info->read_buffer;
+ pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis;
+ }
+
+ if ((pfile_in_zip_read_info->compression_method==0) || (pfile_in_zip_read_info->raw))
+ {
+ uInt uDoCopy,i ;
+
+ if ((pfile_in_zip_read_info->stream.avail_in == 0) &&
+ (pfile_in_zip_read_info->rest_read_compressed == 0))
+ return (iRead==0) ? UNZ_EOF : (int)iRead;
+
+ if (pfile_in_zip_read_info->stream.avail_out <
+ pfile_in_zip_read_info->stream.avail_in)
+ uDoCopy = pfile_in_zip_read_info->stream.avail_out ;
+ else
+ uDoCopy = pfile_in_zip_read_info->stream.avail_in ;
+
+ for (i=0;i<uDoCopy;i++)
+ *(pfile_in_zip_read_info->stream.next_out+i) =
+ *(pfile_in_zip_read_info->stream.next_in+i);
+
+ pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uDoCopy;
+
+ pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,
+ pfile_in_zip_read_info->stream.next_out,
+ uDoCopy);
+ pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy;
+ pfile_in_zip_read_info->stream.avail_in -= uDoCopy;
+ pfile_in_zip_read_info->stream.avail_out -= uDoCopy;
+ pfile_in_zip_read_info->stream.next_out += uDoCopy;
+ pfile_in_zip_read_info->stream.next_in += uDoCopy;
+ pfile_in_zip_read_info->stream.total_out += uDoCopy;
+ iRead += uDoCopy;
+ }
+ else if (pfile_in_zip_read_info->compression_method==Z_BZIP2ED)
+ {
+#ifdef HAVE_BZIP2
+ uLong uTotalOutBefore,uTotalOutAfter;
+ const Bytef *bufBefore;
+ uLong uOutThis;
+
+ pfile_in_zip_read_info->bstream.next_in = (char*)pfile_in_zip_read_info->stream.next_in;
+ pfile_in_zip_read_info->bstream.avail_in = pfile_in_zip_read_info->stream.avail_in;
+ pfile_in_zip_read_info->bstream.total_in_lo32 = pfile_in_zip_read_info->stream.total_in;
+ pfile_in_zip_read_info->bstream.total_in_hi32 = 0;
+ pfile_in_zip_read_info->bstream.next_out = (char*)pfile_in_zip_read_info->stream.next_out;
+ pfile_in_zip_read_info->bstream.avail_out = pfile_in_zip_read_info->stream.avail_out;
+ pfile_in_zip_read_info->bstream.total_out_lo32 = pfile_in_zip_read_info->stream.total_out;
+ pfile_in_zip_read_info->bstream.total_out_hi32 = 0;
+
+ uTotalOutBefore = pfile_in_zip_read_info->bstream.total_out_lo32;
+ bufBefore = (const Bytef *)pfile_in_zip_read_info->bstream.next_out;
+
+ err=BZ2_bzDecompress(&pfile_in_zip_read_info->bstream);
+
+ uTotalOutAfter = pfile_in_zip_read_info->bstream.total_out_lo32;
+ uOutThis = uTotalOutAfter-uTotalOutBefore;
+
+ pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uOutThis;
+
+ pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,bufBefore, (uInt)(uOutThis));
+ pfile_in_zip_read_info->rest_read_uncompressed -= uOutThis;
+ iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);
+
+ pfile_in_zip_read_info->stream.next_in = (Bytef*)pfile_in_zip_read_info->bstream.next_in;
+ pfile_in_zip_read_info->stream.avail_in = pfile_in_zip_read_info->bstream.avail_in;
+ pfile_in_zip_read_info->stream.total_in = pfile_in_zip_read_info->bstream.total_in_lo32;
+ pfile_in_zip_read_info->stream.next_out = (Bytef*)pfile_in_zip_read_info->bstream.next_out;
+ pfile_in_zip_read_info->stream.avail_out = pfile_in_zip_read_info->bstream.avail_out;
+ pfile_in_zip_read_info->stream.total_out = pfile_in_zip_read_info->bstream.total_out_lo32;
+
+ if (err==BZ_STREAM_END)
+ return (iRead==0) ? UNZ_EOF : iRead;
+ if (err!=BZ_OK)
+ break;
+#endif
+ } // end Z_BZIP2ED
+ else
+ {
+ ZPOS64_T uTotalOutBefore,uTotalOutAfter;
+ const Bytef *bufBefore;
+ ZPOS64_T uOutThis;
+ int flush=Z_SYNC_FLUSH;
+
+ uTotalOutBefore = pfile_in_zip_read_info->stream.total_out;
+ bufBefore = pfile_in_zip_read_info->stream.next_out;
+
+ /*
+ if ((pfile_in_zip_read_info->rest_read_uncompressed ==
+ pfile_in_zip_read_info->stream.avail_out) &&
+ (pfile_in_zip_read_info->rest_read_compressed == 0))
+ flush = Z_FINISH;
+ */
+ err=inflate(&pfile_in_zip_read_info->stream,flush);
+
+ if ((err>=0) && (pfile_in_zip_read_info->stream.msg!=NULL))
+ err = Z_DATA_ERROR;
+
+ uTotalOutAfter = pfile_in_zip_read_info->stream.total_out;
+ /* Detect overflow, because z_stream.total_out is uLong (32 bits) */
+ if (uTotalOutAfter<uTotalOutBefore)
+ uTotalOutAfter += 1LL << 32; /* Add maximum value of uLong + 1 */
+ uOutThis = uTotalOutAfter-uTotalOutBefore;
+
+ pfile_in_zip_read_info->total_out_64 = pfile_in_zip_read_info->total_out_64 + uOutThis;
+
+ pfile_in_zip_read_info->crc32 =
+ crc32(pfile_in_zip_read_info->crc32,bufBefore,
+ (uInt)(uOutThis));
+
+ pfile_in_zip_read_info->rest_read_uncompressed -=
+ uOutThis;
+
+ iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);
+
+ if (err==Z_STREAM_END)
+ return (iRead==0) ? UNZ_EOF : (int)iRead;
+ if (err!=Z_OK)
+ break;
+ }
+ }
+
+ if (err==Z_OK)
+ return (int)iRead;
+ return err;
+}
+
+
+/*
+ Give the current position in uncompressed data
+*/
+extern z_off_t ZEXPORT unztell(unzFile file) {
+ unz64_s* s;
+ file_in_zip64_read_info_s* pfile_in_zip_read_info;
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz64_s*)file;
+ pfile_in_zip_read_info=s->pfile_in_zip_read;
+
+ if (pfile_in_zip_read_info==NULL)
+ return UNZ_PARAMERROR;
+
+ return (z_off_t)pfile_in_zip_read_info->stream.total_out;
+}
+
+extern ZPOS64_T ZEXPORT unztell64(unzFile file) {
+
+ unz64_s* s;
+ file_in_zip64_read_info_s* pfile_in_zip_read_info;
+ if (file==NULL)
+ return (ZPOS64_T)-1;
+ s=(unz64_s*)file;
+ pfile_in_zip_read_info=s->pfile_in_zip_read;
+
+ if (pfile_in_zip_read_info==NULL)
+ return (ZPOS64_T)-1;
+
+ return pfile_in_zip_read_info->total_out_64;
+}
+
+
+/*
+ return 1 if the end of file was reached, 0 elsewhere
+*/
+extern int ZEXPORT unzeof(unzFile file) {
+ unz64_s* s;
+ file_in_zip64_read_info_s* pfile_in_zip_read_info;
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz64_s*)file;
+ pfile_in_zip_read_info=s->pfile_in_zip_read;
+
+ if (pfile_in_zip_read_info==NULL)
+ return UNZ_PARAMERROR;
+
+ if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
+ return 1;
+ else
+ return 0;
+}
+
+
+
+/*
+Read extra field from the current file (opened by unzOpenCurrentFile)
+This is the local-header version of the extra field (sometimes, there is
+more info in the local-header version than in the central-header)
+
+ if buf==NULL, it return the size of the local extra field that can be read
+
+ if buf!=NULL, len is the size of the buffer, the extra header is copied in
+ buf.
+ the return value is the number of bytes copied in buf, or (if <0)
+ the error code
+*/
+extern int ZEXPORT unzGetLocalExtrafield(unzFile file, voidp buf, unsigned len) {
+ unz64_s* s;
+ file_in_zip64_read_info_s* pfile_in_zip_read_info;
+ uInt read_now;
+ ZPOS64_T size_to_read;
+
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz64_s*)file;
+ pfile_in_zip_read_info=s->pfile_in_zip_read;
+
+ if (pfile_in_zip_read_info==NULL)
+ return UNZ_PARAMERROR;
+
+ size_to_read = (pfile_in_zip_read_info->size_local_extrafield -
+ pfile_in_zip_read_info->pos_local_extrafield);
+
+ if (buf==NULL)
+ return (int)size_to_read;
+
+ if (len>size_to_read)
+ read_now = (uInt)size_to_read;
+ else
+ read_now = (uInt)len ;
+
+ if (read_now==0)
+ return 0;
+
+ if (ZSEEK64(pfile_in_zip_read_info->z_filefunc,
+ pfile_in_zip_read_info->filestream,
+ pfile_in_zip_read_info->offset_local_extrafield +
+ pfile_in_zip_read_info->pos_local_extrafield,
+ ZLIB_FILEFUNC_SEEK_SET)!=0)
+ return UNZ_ERRNO;
+
+ if (ZREAD64(pfile_in_zip_read_info->z_filefunc,
+ pfile_in_zip_read_info->filestream,
+ buf,read_now)!=read_now)
+ return UNZ_ERRNO;
+
+ return (int)read_now;
+}
+
+/*
+ Close the file in zip opened with unzOpenCurrentFile
+ Return UNZ_CRCERROR if all the file was read but the CRC is not good
+*/
+extern int ZEXPORT unzCloseCurrentFile(unzFile file) {
+ int err=UNZ_OK;
+
+ unz64_s* s;
+ file_in_zip64_read_info_s* pfile_in_zip_read_info;
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz64_s*)file;
+ pfile_in_zip_read_info=s->pfile_in_zip_read;
+
+ if (pfile_in_zip_read_info==NULL)
+ return UNZ_PARAMERROR;
+
+
+ if ((pfile_in_zip_read_info->rest_read_uncompressed == 0) &&
+ (!pfile_in_zip_read_info->raw))
+ {
+ if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait)
+ err=UNZ_CRCERROR;
+ }
+
+
+ free(pfile_in_zip_read_info->read_buffer);
+ pfile_in_zip_read_info->read_buffer = NULL;
+ if (pfile_in_zip_read_info->stream_initialised == Z_DEFLATED)
+ inflateEnd(&pfile_in_zip_read_info->stream);
+#ifdef HAVE_BZIP2
+ else if (pfile_in_zip_read_info->stream_initialised == Z_BZIP2ED)
+ BZ2_bzDecompressEnd(&pfile_in_zip_read_info->bstream);
+#endif
+
+
+ pfile_in_zip_read_info->stream_initialised = 0;
+ free(pfile_in_zip_read_info);
+
+ s->pfile_in_zip_read=NULL;
+
+ return err;
+}
+
+
+/*
+ Get the global comment string of the ZipFile, in the szComment buffer.
+ uSizeBuf is the size of the szComment buffer.
+ return the number of byte copied or an error code <0
+*/
+extern int ZEXPORT unzGetGlobalComment(unzFile file, char * szComment, uLong uSizeBuf) {
+ unz64_s* s;
+ uLong uReadThis ;
+ if (file==NULL)
+ return (int)UNZ_PARAMERROR;
+ s=(unz64_s*)file;
+
+ uReadThis = uSizeBuf;
+ if (uReadThis>s->gi.size_comment)
+ uReadThis = s->gi.size_comment;
+
+ if (ZSEEK64(s->z_filefunc,s->filestream,s->central_pos+22,ZLIB_FILEFUNC_SEEK_SET)!=0)
+ return UNZ_ERRNO;
+
+ if (uReadThis>0)
+ {
+ *szComment='\0';
+ if (ZREAD64(s->z_filefunc,s->filestream,szComment,uReadThis)!=uReadThis)
+ return UNZ_ERRNO;
+ }
+
+ if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment))
+ *(szComment+s->gi.size_comment)='\0';
+ return (int)uReadThis;
+}
+
+/* Additions by RX '2004 */
+extern ZPOS64_T ZEXPORT unzGetOffset64(unzFile file) {
+ unz64_s* s;
+
+ if (file==NULL)
+ return 0; //UNZ_PARAMERROR;
+ s=(unz64_s*)file;
+ if (!s->current_file_ok)
+ return 0;
+ if (s->gi.number_entry != 0 && s->gi.number_entry != 0xffff)
+ if (s->num_file==s->gi.number_entry)
+ return 0;
+ return s->pos_in_central_dir;
+}
+
+extern uLong ZEXPORT unzGetOffset(unzFile file) {
+ ZPOS64_T offset64;
+
+ if (file==NULL)
+ return 0; //UNZ_PARAMERROR;
+ offset64 = unzGetOffset64(file);
+ return (uLong)offset64;
+}
+
+extern int ZEXPORT unzSetOffset64(unzFile file, ZPOS64_T pos) {
+ unz64_s* s;
+ int err;
+
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz64_s*)file;
+
+ s->pos_in_central_dir = pos;
+ s->num_file = s->gi.number_entry; /* hack */
+ err = unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info,
+ &s->cur_file_info_internal,
+ NULL,0,NULL,0,NULL,0);
+ s->current_file_ok = (err == UNZ_OK);
+ return err;
+}
+
+extern int ZEXPORT unzSetOffset (unzFile file, uLong pos) {
+ return unzSetOffset64(file,pos);
+}
diff --git a/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-ftp-fota/rock_ua/unzip.h b/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-ftp-fota/rock_ua/unzip.h
new file mode 100755
index 0000000..1410584
--- /dev/null
+++ b/LYNQ_PUBLIC/IC_src/mtk/lib/liblynq-ftp-fota/rock_ua/unzip.h
@@ -0,0 +1,437 @@
+/* unzip.h -- IO for uncompress .zip files using zlib
+ Version 1.1, February 14h, 2010
+ part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )
+
+ Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )
+
+ Modifications of Unzip for Zip64
+ Copyright (C) 2007-2008 Even Rouault
+
+ Modifications for Zip64 support on both zip and unzip
+ Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
+
+ For more info read MiniZip_info.txt
+
+ ---------------------------------------------------------------------------------
+
+ Condition of use and distribution are the same than zlib :
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ ---------------------------------------------------------------------------------
+
+ Changes
+
+ See header of unzip64.c
+
+*/
+
+#ifndef _unz64_H
+#define _unz64_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _ZLIB_H
+#include "zlib.h"
+#endif
+
+#ifndef _ZLIBIOAPI_H
+#include "ioapi.h"
+#endif
+
+#ifdef HAVE_BZIP2
+#include "bzlib.h"
+#endif
+
+#define Z_BZIP2ED 12
+
+#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP)
+/* like the STRICT of WIN32, we define a pointer that cannot be converted
+ from (void*) without cast */
+typedef struct TagunzFile__ { int unused; } unzFile__;
+typedef unzFile__ *unzFile;
+#else
+typedef voidp unzFile;
+#endif
+
+
+#define UNZ_OK (0)
+#define UNZ_END_OF_LIST_OF_FILE (-100)
+#define UNZ_ERRNO (Z_ERRNO)
+#define UNZ_EOF (0)
+#define UNZ_PARAMERROR (-102)
+#define UNZ_BADZIPFILE (-103)
+#define UNZ_INTERNALERROR (-104)
+#define UNZ_CRCERROR (-105)
+
+/* tm_unz contain date/time info */
+typedef struct tm_unz_s
+{
+ int tm_sec; /* seconds after the minute - [0,59] */
+ int tm_min; /* minutes after the hour - [0,59] */
+ int tm_hour; /* hours since midnight - [0,23] */
+ int tm_mday; /* day of the month - [1,31] */
+ int tm_mon; /* months since January - [0,11] */
+ int tm_year; /* years - [1980..2044] */
+} tm_unz;
+
+/* unz_global_info structure contain global data about the ZIPfile
+ These data comes from the end of central dir */
+typedef struct unz_global_info64_s
+{
+ ZPOS64_T number_entry; /* total number of entries in
+ the central dir on this disk */
+ uLong size_comment; /* size of the global comment of the zipfile */
+} unz_global_info64;
+
+typedef struct unz_global_info_s
+{
+ uLong number_entry; /* total number of entries in
+ the central dir on this disk */
+ uLong size_comment; /* size of the global comment of the zipfile */
+} unz_global_info;
+
+/* unz_file_info contain information about a file in the zipfile */
+typedef struct unz_file_info64_s
+{
+ uLong version; /* version made by 2 bytes */
+ uLong version_needed; /* version needed to extract 2 bytes */
+ uLong flag; /* general purpose bit flag 2 bytes */
+ uLong compression_method; /* compression method 2 bytes */
+ uLong dosDate; /* last mod file date in Dos fmt 4 bytes */
+ uLong crc; /* crc-32 4 bytes */
+ ZPOS64_T compressed_size; /* compressed size 8 bytes */
+ ZPOS64_T uncompressed_size; /* uncompressed size 8 bytes */
+ uLong size_filename; /* filename length 2 bytes */
+ uLong size_file_extra; /* extra field length 2 bytes */
+ uLong size_file_comment; /* file comment length 2 bytes */
+
+ uLong disk_num_start; /* disk number start 2 bytes */
+ uLong internal_fa; /* internal file attributes 2 bytes */
+ uLong external_fa; /* external file attributes 4 bytes */
+
+ tm_unz tmu_date;
+} unz_file_info64;
+
+typedef struct unz_file_info_s
+{
+ uLong version; /* version made by 2 bytes */
+ uLong version_needed; /* version needed to extract 2 bytes */
+ uLong flag; /* general purpose bit flag 2 bytes */
+ uLong compression_method; /* compression method 2 bytes */
+ uLong dosDate; /* last mod file date in Dos fmt 4 bytes */
+ uLong crc; /* crc-32 4 bytes */
+ uLong compressed_size; /* compressed size 4 bytes */
+ uLong uncompressed_size; /* uncompressed size 4 bytes */
+ uLong size_filename; /* filename length 2 bytes */
+ uLong size_file_extra; /* extra field length 2 bytes */
+ uLong size_file_comment; /* file comment length 2 bytes */
+
+ uLong disk_num_start; /* disk number start 2 bytes */
+ uLong internal_fa; /* internal file attributes 2 bytes */
+ uLong external_fa; /* external file attributes 4 bytes */
+
+ tm_unz tmu_date;
+} unz_file_info;
+
+extern int ZEXPORT unzStringFileNameCompare(const char* fileName1,
+ const char* fileName2,
+ int iCaseSensitivity);
+/*
+ Compare two filenames (fileName1,fileName2).
+ If iCaseSensitivity = 1, comparison is case sensitive (like strcmp)
+ If iCaseSensitivity = 2, comparison is not case sensitive (like strcmpi
+ or strcasecmp)
+ If iCaseSensitivity = 0, case sensitivity is default of your operating system
+ (like 1 on Unix, 2 on Windows)
+*/
+
+
+extern unzFile ZEXPORT unzOpen(const char *path);
+extern unzFile ZEXPORT unzOpen64(const void *path);
+/*
+ Open a Zip file. path contain the full pathname (by example,
+ on a Windows XP computer "c:\\zlib\\zlib113.zip" or on an Unix computer
+ "zlib/zlib113.zip".
+ If the zipfile cannot be opened (file don't exist or in not valid), the
+ return value is NULL.
+ Else, the return value is a unzFile Handle, usable with other function
+ of this unzip package.
+ the "64" function take a const void* pointer, because the path is just the
+ value passed to the open64_file_func callback.
+ Under Windows, if UNICODE is defined, using fill_fopen64_filefunc, the path
+ is a pointer to a wide unicode string (LPCTSTR is LPCWSTR), so const char*
+ does not describe the reality
+*/
+
+
+extern unzFile ZEXPORT unzOpen2(const char *path,
+ zlib_filefunc_def* pzlib_filefunc_def);
+/*
+ Open a Zip file, like unzOpen, but provide a set of file low level API
+ for read/write the zip file (see ioapi.h)
+*/
+
+extern unzFile ZEXPORT unzOpen2_64(const void *path,
+ zlib_filefunc64_def* pzlib_filefunc_def);
+/*
+ Open a Zip file, like unz64Open, but provide a set of file low level API
+ for read/write the zip file (see ioapi.h)
+*/
+
+extern int ZEXPORT unzClose(unzFile file);
+/*
+ Close a ZipFile opened with unzOpen.
+ If there is files inside the .Zip opened with unzOpenCurrentFile (see later),
+ these files MUST be closed with unzCloseCurrentFile before call unzClose.
+ return UNZ_OK if there is no problem. */
+
+extern int ZEXPORT unzGetGlobalInfo(unzFile file,
+ unz_global_info *pglobal_info);
+
+extern int ZEXPORT unzGetGlobalInfo64(unzFile file,
+ unz_global_info64 *pglobal_info);
+/*
+ Write info about the ZipFile in the *pglobal_info structure.
+ No preparation of the structure is needed
+ return UNZ_OK if there is no problem. */
+
+
+extern int ZEXPORT unzGetGlobalComment(unzFile file,
+ char *szComment,
+ uLong uSizeBuf);
+/*
+ Get the global comment string of the ZipFile, in the szComment buffer.
+ uSizeBuf is the size of the szComment buffer.
+ return the number of byte copied or an error code <0
+*/
+
+
+/***************************************************************************/
+/* Unzip package allow you browse the directory of the zipfile */
+
+extern int ZEXPORT unzGoToFirstFile(unzFile file);
+/*
+ Set the current file of the zipfile to the first file.
+ return UNZ_OK if there is no problem
+*/
+
+extern int ZEXPORT unzGoToNextFile(unzFile file);
+/*
+ Set the current file of the zipfile to the next file.
+ return UNZ_OK if there is no problem
+ return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
+*/
+
+extern int ZEXPORT unzLocateFile(unzFile file,
+ const char *szFileName,
+ int iCaseSensitivity);
+/*
+ Try locate the file szFileName in the zipfile.
+ For the iCaseSensitivity signification, see unzStringFileNameCompare
+
+ return value :
+ UNZ_OK if the file is found. It becomes the current file.
+ UNZ_END_OF_LIST_OF_FILE if the file is not found
+*/
+
+
+/* ****************************************** */
+/* Ryan supplied functions */
+/* unz_file_info contain information about a file in the zipfile */
+typedef struct unz_file_pos_s
+{
+ uLong pos_in_zip_directory; /* offset in zip file directory */
+ uLong num_of_file; /* # of file */
+} unz_file_pos;
+
+extern int ZEXPORT unzGetFilePos(
+ unzFile file,
+ unz_file_pos* file_pos);
+
+extern int ZEXPORT unzGoToFilePos(
+ unzFile file,
+ unz_file_pos* file_pos);
+
+typedef struct unz64_file_pos_s
+{
+ ZPOS64_T pos_in_zip_directory; /* offset in zip file directory */
+ ZPOS64_T num_of_file; /* # of file */
+} unz64_file_pos;
+
+extern int ZEXPORT unzGetFilePos64(
+ unzFile file,
+ unz64_file_pos* file_pos);
+
+extern int ZEXPORT unzGoToFilePos64(
+ unzFile file,
+ const unz64_file_pos* file_pos);
+
+/* ****************************************** */
+
+extern int ZEXPORT unzGetCurrentFileInfo64(unzFile file,
+ unz_file_info64 *pfile_info,
+ char *szFileName,
+ uLong fileNameBufferSize,
+ void *extraField,
+ uLong extraFieldBufferSize,
+ char *szComment,
+ uLong commentBufferSize);
+
+extern int ZEXPORT unzGetCurrentFileInfo(unzFile file,
+ unz_file_info *pfile_info,
+ char *szFileName,
+ uLong fileNameBufferSize,
+ void *extraField,
+ uLong extraFieldBufferSize,
+ char *szComment,
+ uLong commentBufferSize);
+/*
+ Get Info about the current file
+ if pfile_info!=NULL, the *pfile_info structure will contain some info about
+ the current file
+ if szFileName!=NULL, the filemane string will be copied in szFileName
+ (fileNameBufferSize is the size of the buffer)
+ if extraField!=NULL, the extra field information will be copied in extraField
+ (extraFieldBufferSize is the size of the buffer).
+ This is the Central-header version of the extra field
+ if szComment!=NULL, the comment string of the file will be copied in szComment
+ (commentBufferSize is the size of the buffer)
+*/
+
+
+/** Addition for GDAL : START */
+
+extern ZPOS64_T ZEXPORT unzGetCurrentFileZStreamPos64(unzFile file);
+
+/** Addition for GDAL : END */
+
+
+/***************************************************************************/
+/* for reading the content of the current zipfile, you can open it, read data
+ from it, and close it (you can close it before reading all the file)
+ */
+
+extern int ZEXPORT unzOpenCurrentFile(unzFile file);
+/*
+ Open for reading data the current file in the zipfile.
+ If there is no error, the return value is UNZ_OK.
+*/
+
+extern int ZEXPORT unzOpenCurrentFilePassword(unzFile file,
+ const char* password);
+/*
+ Open for reading data the current file in the zipfile.
+ password is a crypting password
+ If there is no error, the return value is UNZ_OK.
+*/
+
+extern int ZEXPORT unzOpenCurrentFile2(unzFile file,
+ int* method,
+ int* level,
+ int raw);
+/*
+ Same than unzOpenCurrentFile, but open for read raw the file (not uncompress)
+ if raw==1
+ *method will receive method of compression, *level will receive level of
+ compression
+ note : you can set level parameter as NULL (if you did not want known level,
+ but you CANNOT set method parameter as NULL
+*/
+
+extern int ZEXPORT unzOpenCurrentFile3(unzFile file,
+ int* method,
+ int* level,
+ int raw,
+ const char* password);
+/*
+ Same than unzOpenCurrentFile, but open for read raw the file (not uncompress)
+ if raw==1
+ *method will receive method of compression, *level will receive level of
+ compression
+ note : you can set level parameter as NULL (if you did not want known level,
+ but you CANNOT set method parameter as NULL
+*/
+
+
+extern int ZEXPORT unzCloseCurrentFile(unzFile file);
+/*
+ Close the file in zip opened with unzOpenCurrentFile
+ Return UNZ_CRCERROR if all the file was read but the CRC is not good
+*/
+
+extern int ZEXPORT unzReadCurrentFile(unzFile file,
+ voidp buf,
+ unsigned len);
+/*
+ Read bytes from the current file (opened by unzOpenCurrentFile)
+ buf contain buffer where data must be copied
+ len the size of buf.
+
+ return the number of byte copied if some bytes are copied
+ return 0 if the end of file was reached
+ return <0 with error code if there is an error
+ (UNZ_ERRNO for IO error, or zLib error for uncompress error)
+*/
+
+extern z_off_t ZEXPORT unztell(unzFile file);
+
+extern ZPOS64_T ZEXPORT unztell64(unzFile file);
+/*
+ Give the current position in uncompressed data
+*/
+
+extern int ZEXPORT unzeof(unzFile file);
+/*
+ return 1 if the end of file was reached, 0 elsewhere
+*/
+
+extern int ZEXPORT unzGetLocalExtrafield(unzFile file,
+ voidp buf,
+ unsigned len);
+/*
+ Read extra field from the current file (opened by unzOpenCurrentFile)
+ This is the local-header version of the extra field (sometimes, there is
+ more info in the local-header version than in the central-header)
+
+ if buf==NULL, it return the size of the local extra field
+
+ if buf!=NULL, len is the size of the buffer, the extra header is copied in
+ buf.
+ the return value is the number of bytes copied in buf, or (if <0)
+ the error code
+*/
+
+/***************************************************************************/
+
+/* Get the current file offset */
+extern ZPOS64_T ZEXPORT unzGetOffset64 (unzFile file);
+extern uLong ZEXPORT unzGetOffset (unzFile file);
+
+/* Set the current file offset */
+extern int ZEXPORT unzSetOffset64 (unzFile file, ZPOS64_T pos);
+extern int ZEXPORT unzSetOffset (unzFile file, uLong pos);
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _unz64_H */
diff --git a/meta/meta-mediatek-mt2735/recipes-core/images/mtk-image-2735.bb b/meta/meta-mediatek-mt2735/recipes-core/images/mtk-image-2735.bb
index e70eec0..866d1bf 100755
--- a/meta/meta-mediatek-mt2735/recipes-core/images/mtk-image-2735.bb
+++ b/meta/meta-mediatek-mt2735/recipes-core/images/mtk-image-2735.bb
@@ -153,6 +153,7 @@
rng-tools \
${@bb.utils.contains("MOBILETEK_NFS_CFG", "yes", "nfs-utils", "", d)} \
ntpq \
+ liblynq-ftp-fota \
"
do_populate_sdk_prepend() {