zte's code,first commit
Change-Id: I9a04da59e459a9bc0d67f101f700d9d7dc8d681b
diff --git a/ap/app/zte_log_agent/log_agent_tool.c b/ap/app/zte_log_agent/log_agent_tool.c
new file mode 100644
index 0000000..a5ec0f2
--- /dev/null
+++ b/ap/app/zte_log_agent/log_agent_tool.c
@@ -0,0 +1,605 @@
+/**
+ *
+ * @file log_agent_tool.c
+ * @brief
+ * This file is part of ZCAT.
+ * zcatÓ¦Óòãlog_agent´¦ÀíÊý¾ÝÔ´µÄ°ïÖúº¯Êý
+ *
+ * @details
+ * @author Tools Team.
+ * @email
+ * @copyright Copyright (C) 2013 Sanechips Technology Co., Ltd.
+ * @warning
+ * @date 2019/02/02
+ * @version 1.2
+ * @pre
+ * @post
+ *
+ * @par
+ * Change History :
+ * ---------------------------------------------------------------------------
+ * date version author description
+ * ---------------------------------------------------------------------------
+ * 2017/07/17 1.0 hou.bing Create file
+ * 2019/01/24 1.1 jiang.fenglin 1.Ìí¼Óusblog¶ÁÐ´Ëø
+ * 2.Ìí¼ÓÏß³ÌÃû³Æ
+ * 2019/02/02 1.2 jiang.fenglin ÐÞ¸Ä×¢ÊÍ·½Ê½Îªdoxygen
+ * 2019/07/08 1.3 jiang.fenglin Ôö¼ÓAPFS/CPFSģʽ
+ * ---------------------------------------------------------------------------
+ *
+ *
+ */
+
+
+/**
+* Í·Îļþ°üº¬
+*/
+#include <string.h>
+#include <signal.h>
+#include <time.h>
+#include <pthread.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include "log_agent.h"
+
+#define MAX_PACKET_LEN (0x10000)
+#define MAX_ENCODE_PACKET_LEN (MAX_PACKET_LEN * 2)
+#define COMM_MDLNO_ZCAT_FLAG 115
+#define COMM_MDLNO_RAMDUMP_FLAG 119
+#define MAX_AP_LOG_BUFF_LEN 2048
+
+extern E_ZCAT_MODE g_log_dir;
+extern E_ZCAT_STATE g_log_state;
+
+extern int send_message_to_client(unsigned char* buf, int len);
+extern int send_message_to_usblog(unsigned char* buf, int len);
+extern int send_message_to_sdcard(unsigned char* buf, int len);
+extern int init_sdcard_log_dir(E_FLASH_MODE mode);
+extern int init_fs_log_dir();
+extern int zCat_MountSd();
+extern BOOL hdlc_encode(T_HDLC_BUFFER_TYPE *dest, const T_HDLC_BUFFER_TYPE *src);
+extern BOOL hdlc_decode(T_HDLC_BUFFER_TYPE *dest, T_HDLC_BUFFER_TYPE *src);
+
+
+int deal_with_encoded_data(unsigned char* buffer, int buf_len);
+
+int hb_flag = 0;
+int bFirst = 1;
+/*É豸¾ä±ú*/
+extern int ramdump_fd;
+extern int kernellog_fd;
+extern int applog_fd;
+extern int cplog_fd;
+
+/*Ï̻߳¥³âËø*/
+static pthread_mutex_t mutex_AP;
+static pthread_mutex_t mutex_SD;
+
+static T_HDLC_BUFFER_TYPE g_recvBuf = {0};
+
+static unsigned int gCommEncodeBuffer[MAX_ENCODE_PACKET_LEN / 4] = {0};
+static unsigned int gCommDecodeBuffer[MAX_ENCODE_PACKET_LEN / 4] = {0};
+static unsigned int gCommRecvBuffer[MAX_ENCODE_PACKET_LEN / 4] = {0};
+
+BOOL bSDSet = FALSE;
+
+void init_log_agent_tools()
+{
+ g_recvBuf.buf = (unsigned char *)gCommRecvBuffer;
+ g_recvBuf.bufIndex = 0;
+ g_recvBuf.bufSize = 0;
+ pthread_mutex_init(&mutex_AP, NULL);
+ pthread_mutex_init(&mutex_SD, NULL);
+}
+
+int g_cp_log_count = 0;
+int g_ap_log_count = 0;
+
+/**
+ * @brief ´òӡʱ¼äµÄ°ïÖúº¯Êý
+ * @param[in] void
+ * @return void
+ * @note
+ * @see
+ */
+char* zte_time()
+{
+ time_t timep;
+ struct tm *p;
+ static char buf[22];
+ memset(buf, 0, 22);
+ time(&timep);
+ p =localtime(&timep);
+ if(p != NULL)
+ snprintf(buf,21,"%4d/%02d/%02d %02d:%02d:%02d ",1900 + p->tm_year,1 + p->tm_mon,p->tm_mday,p->tm_hour,p->tm_min,p->tm_sec);
+ return buf;
+}
+
+/**
+ * @brief ½«¹æÔòÎļþ¡¢ÐÄÌø°üµÄÏÂÐÐÊý¾Ý·¢Ë͵½cp
+ * @param[in] buf ´ý·¢Ë͵ÄÊý¾ÝÖ¸Õë
+ * @param[in] len ´ý·¢Ë͵ÄÊý¾Ý³¤¶È
+ * @return ʵ¼Ê·¢Ë͵ÄÊý¾Ý³¤¶È
+ * @note
+ * @see
+ */
+int send_log_to_cp(unsigned char *buf, int len)
+{
+ int write_len = 0;
+ if(buf == NULL || cplog_fd == -1)
+ {
+ printf("[zcat] send_log_to_cp fail\n");
+ return 0;
+ }
+ write_len = write(cplog_fd, buf, len);
+
+ return write_len;
+}
+
+/**
+ * @brief ¸ù¾Ýzcat_mode£¬·¢ËÍlogµ½²»Í¬µÄÍâÉ裺usb¡¢Íø¿¨¡¢sd¿¨
+ * @param[in] buf ´ý·¢Ë͵ÄÊý¾ÝÖ¸Õë
+ * @param[in] len ´ý·¢Ë͵ÄÊý¾Ý³¤¶È
+ * @return void
+ * @note
+ * @see
+ */
+void send_log_out(unsigned char* buf, int len)
+{
+ if(g_log_state != ZCAT_STATE_RUNNING)
+ {
+ printf("[zcat] send_log_out fail, state = %d.\n", g_log_state);
+ return;
+ }
+
+ if(g_log_dir == ZCAT_MODE_AP_NET)
+ {
+ send_message_to_client(buf, len);
+ }
+ else if(g_log_dir == ZCAT_MODE_AP_USB)
+ {
+ int i;
+ int cnt = len / MAX_AP_LOG_BUFF_LEN;
+
+ for(i = 0; i < cnt; i++)
+ {
+ g_cp_log_count++;
+ send_message_to_usblog(buf + i * MAX_AP_LOG_BUFF_LEN, MAX_AP_LOG_BUFF_LEN);
+ }
+
+ cnt = len % MAX_AP_LOG_BUFF_LEN;
+ if(cnt > 0)
+ {
+ g_cp_log_count++;
+ send_message_to_usblog(buf + i * MAX_AP_LOG_BUFF_LEN, cnt);
+ }
+ }
+ else if(g_log_dir == ZCAT_MODE_AP_TF)
+ {
+ if(bSDSet == FALSE )
+ {
+ if(zCat_MountSd())
+ return;
+
+ bSDSet = TRUE;
+ if(init_sdcard_log_dir(FLASH_MODE_NOMAL) < 0) //³õʼ»¯cpÊä³öÎļþ¼Ð¼°²ÎÊý
+ {
+ bSDSet = FALSE;
+ return;
+ }
+ hb_flag = 1;
+ return;
+ }
+ if(bSDSet == TRUE)
+ {
+ pthread_mutex_lock(&mutex_SD);
+ send_message_to_sdcard(buf, len);
+ pthread_mutex_unlock(&mutex_SD);
+ }
+ }
+ else if(g_log_dir == ZCAT_MODE_AP_FS)
+ {
+ if(bSDSet == FALSE )
+ {
+ bSDSet = TRUE;
+ if(init_fs_log_dir() < 0) //³õʼ»¯cpÊä³öÎļþ¼Ð¼°²ÎÊý
+ {
+ bSDSet = FALSE;
+ return;
+ }
+ hb_flag = 1;
+ return;
+ }
+ if(bSDSet == TRUE)
+ {
+ pthread_mutex_lock(&mutex_SD);
+ send_message_to_sdcard(buf, len);
+ pthread_mutex_unlock(&mutex_SD);
+ }
+ }
+ else
+ {
+ deal_with_encoded_data(buf, len);
+ }
+}
+
+/**
+ * @brief ½«ap²àprintf¡¢printk²úÉúµÄlogÊý¾Ý·¢ËͳöÈ¥
+ * @param[in] commHeader ´ý·¢Ë͵ÄÊý¾Ý
+ * @return void
+ * @note
+ * @see
+ */
+static void send_ap_log_out(T_COMM_TYPE *commHeader)
+{
+ T_HDLC_BUFFER_TYPE srcBuf = {0};
+ //T_ZCAT_HEADER *zcatHeader = (T_ZCAT_HEADER *)(((unsigned char*)commHeader) + sizeof(T_COMM_TYPE));
+ T_HDLC_BUFFER_TYPE destBuf = {(unsigned char *)gCommEncodeBuffer, 0, MAX_ENCODE_PACKET_LEN};
+ //int cmd_code = zcatHeader->cmd_code;
+
+ //UINT16 times = 0;
+ //UINT16 ipLast = 0;
+
+ srcBuf.buf = (unsigned char *)(commHeader);
+ srcBuf.bufIndex = 0;
+ srcBuf.bufSize = sizeof(T_COMM_TYPE) + commHeader->buf_len;
+ destBuf.bufIndex = 0;
+ if(g_log_state != ZCAT_STATE_RUNNING)
+ {
+ free((void*)commHeader);
+ return;
+ }
+ pthread_mutex_lock(&mutex_AP); // ¼Ó»¥³âËø£¬·Àֹͬʱ²Ù×÷gCommEncodeBuffer
+ if (hdlc_encode(&destBuf, &srcBuf)) // ±àÂë
+ {
+ if(g_log_dir == ZCAT_MODE_CP_USB || g_log_dir == ZCAT_MODE_CP_TF || g_log_dir == ZCAT_MODE_CP_FS)
+ {
+ send_log_to_cp(destBuf.buf, destBuf.bufIndex);
+ }
+ else
+ {
+ send_log_out(destBuf.buf, destBuf.bufIndex);
+ }
+ }
+ pthread_mutex_unlock(&mutex_AP); // ½â³ý»¥³âËø
+ free((void*)commHeader);
+}
+
+/**
+ * @brief ·¢ËÍÊý¾Ýµ½"ͳһ»º´æ"ÖÐ
+ * @param[in] buf ·¢ËÍÊý¾Ý(±ØÐëÊÇÓÉComm_MallocÉêÇëµÄÄÚ´æ!!!)
+ * @param[in] buf_len ·¢ËÍÊý¾ÝµÄ³¤¶È
+ * @param[in] tgt_mdl_no Ä¿±êÄ£¿éºÅ£¬ÊÖ»ú»òPCµÈ
+ * @param[in] tgt_submdl_no Ä¿±ê×ÓÄ£¿éºÅ
+ * @param[in] src_submdl_no Ô´×ÓÄ£¿éºÅ
+ * @return ³É¹¦·µ»ØZOSS_SUCCESS, ·ñÔò·µ»ØZOSS_ERROR
+ * @note
+ * @see
+ */
+unsigned int zTools_SendData(unsigned char *buf, unsigned int buf_len,
+ unsigned char tgt_mdl_no, unsigned char tgt_submdl_no, unsigned char src_submdl_no)
+{
+ T_COMM_TYPE *commHeader = NULL;
+
+ /* Èë²ÎÅÐ¶Ï */
+ if (buf == NULL || buf_len == 0 || tgt_mdl_no == 0 || tgt_submdl_no == 0 || src_submdl_no == 0)
+ {
+ return -1;
+ }
+
+ commHeader = (T_COMM_TYPE *)(buf - sizeof(T_COMM_TYPE));
+
+ commHeader->msg_type = 1;
+ commHeader->pad = 0xAA;
+ commHeader->reserved = 0xAAAA;
+ commHeader->tgt_mdl_no = tgt_mdl_no; // Ä¿±êÄ£¿é
+ commHeader->tgt_submdl_no = tgt_submdl_no; // Ä¿±ê×ÓÄ£¿é
+ commHeader->src_mdl_no = MDL_PHONE; // Ô´Ä£¿é
+ commHeader->src_submdl_no = src_submdl_no; // Ô´×ÓÄ£¿é
+ commHeader->buf_len = buf_len; // Êý¾ÝÇø³¤¶È
+
+ send_ap_log_out(commHeader);
+ return 0;
+}
+
+/**
+ * @brief ZCATÏûϢͷ³õʼ»¯
+ * @param[out] zcatHeader ÏûϢͷָÕë
+ * @param[in] cmd_code ÏûÏ¢Âë
+ * @param[in] len ÏûÏ¢³¤¶È
+ * @return N/A
+ * @note
+ * @see
+ */
+VOID zCatAgt_HeaderInit(T_ZCAT_HEADER *zcatHeader, unsigned char cmd_code, unsigned int len)
+{
+ struct timeval tmpTimeVal = {0};
+
+ zcatHeader->cmd_code = cmd_code;
+ zcatHeader->reserved = 0xBBBB;
+ zcatHeader->timeStamp[1] = 0;
+ zcatHeader->length = len;
+ zcatHeader->timeStamp[0] = 0;//corem»ñȡʱ¼ä
+ gettimeofday(&tmpTimeVal, NULL);
+ zcatHeader->timeStamp[1] = tmpTimeVal.tv_sec;
+}
+
+/**
+ * @brief ·¢ËÍZCATÏûÏ¢µ½"ÍâÉè"
+ * @param[in] cmd_code ÏûÏ¢Âë
+ * @param[in] buf ÏûÏ¢Êý¾ÝÖ¸Õë
+ * @param[in] len ÏûÏ¢Êý¾Ý³¤¶È
+ * @return ³É¹¦·µ»ØZOSS_SUCCESS, ·ñÔò·µ»ØZOSS_ERROR
+ * @note
+ * @see
+ */
+unsigned int zCatAgt_SendMsg(unsigned char cmd_code, unsigned char *buf, unsigned int len)
+{
+ T_ZCAT_HEADER *zcatHeader = (T_ZCAT_HEADER *)(buf - sizeof(T_ZCAT_HEADER));
+
+ zCatAgt_HeaderInit(zcatHeader, cmd_code, len);
+
+ return zTools_SendData((unsigned char *)zcatHeader, sizeof(T_ZCAT_HEADER) + len, MDL_ZCAT, 1, SUBMDL_ZCATAGT);
+}
+
+/**
+ * @brief »ñȡģ¿éºÍµÈ¼¶
+ * @param[in] buf ÏûÏ¢Êý¾ÝÖ¸Õë
+ * @param[in] bufLen ÏûÏ¢Êý¾Ý³¤¶È
+ * @param[in] priority ÏûÏ¢µÈ¼¶
+ * @param[in] mod Ä£¿é±àºÅ
+ * @return void
+ * @note
+ * @see
+ */
+VOID zCatAgt_Ap_GetModAndPri(unsigned char **buf, unsigned short *bufLen, unsigned char *pPriority, unsigned char *pMod)
+{
+ unsigned char *p = *buf;
+ unsigned short len = *bufLen;
+
+ if (len > 3 && p[0] == '<' && p[1] >= '0' && p[1] <= '7' && p[2] == '>')
+ {
+ *pPriority = p[1] - '0';
+ p += 3;
+ len -= 3;
+
+ if (len > 3 && p[0] == '<' && p[1] > '0' && p[1] <= '9')
+ {
+ if (p[2] == '>')
+ {
+ *pMod = p[1] - '0';
+ p += 3;
+ len -= 3;
+ }
+ else if (len > 4 && p[2] >= '0' && p[2] <= '9')
+ {
+ if (p[3] == '>')
+ {
+ *pMod = (p[1] - '0') * 10 + (p[2] - '0');
+ p += 4;
+ len -= 4;
+ }
+ else if (len > 5 && p[3] >= '0' && p[3] <= '9' && p[4] == '>')
+ {
+ *pMod = (p[1] - '0') * 100 + (p[2] - '0') * 10 + (p[3] - '0');
+ p += 5;
+ len -= 5;
+ }
+ }
+ }
+ }
+
+ *buf = p;
+ *bufLen = len;
+}
+
+/**
+ * @brief ·¢ËÍAP LOGµ½"ͳһ»º´æ"ÖÐ
+ * @param[in] cmd_code ÏûÏ¢Âë
+ * @param[in] priority ÏûÏ¢µÈ¼¶
+ * @param[in] mod Ä£¿é±àºÅ
+ * @param[in] buf ÏûÏ¢Êý¾ÝÖ¸Õë
+ * @param[in] len ÏûÏ¢Êý¾Ý³¤¶È
+ * @return ³É¹¦·µ»ØZOSS_SUCCESS, ·ñÔò·µ»ØZOSS_ERROR
+ * @note
+ * @see
+ */
+unsigned int zCatAgt_Ap_SendMsg(unsigned char cmd_code, unsigned char priority, unsigned char mod, unsigned char *buf, unsigned int len)
+{
+ T_ZCAT_APLOG_HEADER *apHeader = NULL;
+ unsigned char *newBuffer = malloc(sizeof(T_ZCAT_APLOG_HEADER) + sizeof(T_ZCAT_HEADER) + sizeof(T_COMM_TYPE) + len);
+
+ if(newBuffer == NULL)
+ {
+ printf("[zcat] malloc buffer failed!\n");
+ return -1;
+ }
+ apHeader = (T_ZCAT_APLOG_HEADER *)(newBuffer + sizeof(T_ZCAT_HEADER) + sizeof(T_COMM_TYPE));
+ #if 0
+ if (apHeader == NULL)
+ {
+ printf("[zcat] apHeader is null.\n");
+ return -1;
+ }
+ else
+ #endif
+ {
+ apHeader->priority = priority;
+ apHeader->mod = mod;
+ apHeader->len = len;
+ memcpy(apHeader + 1, buf, len);
+ return zCatAgt_SendMsg(cmd_code, (unsigned char *)apHeader, sizeof(T_ZCAT_APLOG_HEADER) + len);
+ }
+
+}
+
+/**
+ * @brief ·ÖÎöAP LOG£¬°´»»ÐÐÖØÐ·ָî
+ * @param[in] src Դ
+ * @param[in] dst Ä¿µÄ
+ * @return Èç¹û³É¹¦·µ»ØTRUE, ·ñÔò·µ»ØFALSE
+ * @note
+ * @see
+ */
+BOOL zCatAgt_Ap_ReadBuffer(T_AP_SRC_BUFFER_TYPE *src, T_AP_DEST_BUFFER_TYPE *dest)
+{
+ if (src != NULL && src->buf != NULL && src->bufSize > src->beginIndex && dest != NULL )
+ {
+ unsigned char *src_buf = src->buf + src->beginIndex;
+ unsigned int src_length = src->bufSize - src->beginIndex;
+ unsigned int buf_length = src_length > AP_LOG_MAX_LENGTH ? AP_LOG_MAX_LENGTH : src_length;
+ unsigned int i = 0;
+
+ for (; i < buf_length; i++)
+ {
+ if (src_buf[i] == '\n')
+ {
+ i++;
+ dest->newLine = 1;
+ break;
+ }
+ }
+
+ dest->buf = src->buf + src->beginIndex;
+ dest->len = i;
+ src->beginIndex += i;
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+void timer(int sig)
+{
+ hb_flag = 0;
+
+ return;
+}
+
+/**
+ * @brief ´¦Àíδ±àÂëµÄÊý¾Ý£¬¸ù¾ÝÀàÐÍ·Ö±ð½øÐÐÏàÓ¦´¦Àí
+ * @param[in] buffer »º´æÖ¸Õë
+ * @param[in] buf_len »º´æ³¤¶È
+ * @return ³É¹¦·µ»Ø0£»Ê§°Ü·µ»Ø-1
+ * @note
+ * @see
+ */
+void deal_with_rawdata(unsigned char* buf, unsigned short buf_len)
+{
+ T_COMM_TYPE commHeader = {0};
+
+ if(buf_len > sizeof(T_COMM_TYPE))
+ {
+ memcpy(&commHeader, buf, sizeof(T_COMM_TYPE));
+ if(commHeader.src_mdl_no == COMM_MDLNO_ZCAT_FLAG) //aplogÏûÏ¢£¬È¥³ýcomÍ·zcatÍ·diagÍ·
+ {
+ T_ZCAT_HEADER *zcatHeader = (T_ZCAT_HEADER*)(buf+sizeof(T_COMM_TYPE));
+ if(zcatHeader->cmd_code >= ZCAT_CMDCODE_MAX)
+ {
+ printf("[zcat] zcatHeader->cmd_code:%d > ZCAT_CMDCODE_MAX\n", zcatHeader->cmd_code);
+ return;
+ }
+ else if(zcatHeader->cmd_code == ZCAT_DIAG_REPORT)
+ {
+ hb_flag = 1;
+ if(bFirst)
+ {
+ signal(SIGALRM, timer);
+ bFirst = 0;
+ }
+ alarm(5);
+
+ T_ZCAT_DIAG_HEADER *zdiagHeader = (T_ZCAT_DIAG_HEADER*)(buf + sizeof(T_COMM_TYPE)+sizeof(T_ZCAT_HEADER));
+ if (zdiagHeader->diag_id == DIAG_FILTER_CONFIG)
+ {
+ T_ZCAT_DIAG_CONFIG_REQ *diag_config = (T_ZCAT_DIAG_CONFIG_REQ *)(zdiagHeader + 1);
+ int headerLen = sizeof(T_COMM_TYPE)+sizeof(T_ZCAT_HEADER)+sizeof(T_ZCAT_DIAG_HEADER);
+ if(diag_config->type == ZCAT_AP_APP_TYPE)
+ {
+ ioctl(applog_fd, 5, buf + headerLen);
+ }
+ else if(diag_config->type == ZCAT_AP_KERNEL_TYPE)
+ {
+ ioctl(kernellog_fd, 5, buf + headerLen);
+ }
+ }
+ }
+ }
+ }
+}
+
+/**
+ * @brief ´¦Àí±àÂëºóµÄÊý¾Ý£¬¸ù¾ÝÀàÐÍ·Ö±ð½øÐÐÏàÓ¦´¦Àí
+ * @param[in] buffer »º´æÖ¸Õë
+ * @param[in] buf_len »º´æ³¤¶È
+ * @return ³É¹¦·µ»Ø0£»Ê§°Ü·µ»Ø-1
+ * @note
+ * @see
+ */
+int deal_with_encoded_data(unsigned char* buffer, int buf_len)
+{
+ static T_HDLC_BUFFER_TYPE dest = {(unsigned char *)gCommDecodeBuffer, 0, MAX_ENCODE_PACKET_LEN};
+ T_HDLC_BUFFER_TYPE *src = &g_recvBuf;
+ unsigned int remainLen = 0;
+ BOOL ret_decode = FALSE;
+
+ if(buffer == NULL)
+ {
+ printf("[zcat] deal_with_encoded_data input error!\n");
+ return -1;
+ }
+
+ src->bufIndex=0;
+
+ // ½«ÐÂÏûÏ¢Êý¾Ý¿½È뻺³åÇø
+ if (src->bufSize + buf_len <= MAX_ENCODE_PACKET_LEN)
+ {
+ memcpy(src->buf + src->bufSize, buffer, buf_len);
+ src->bufSize += buf_len;
+ }
+ else if (buf_len <= MAX_ENCODE_PACKET_LEN)
+ {
+ memcpy(src->buf, buffer, buf_len);
+ src->bufSize = buf_len;
+ }
+ else
+ {
+ src->bufSize = 0;
+ }
+
+ remainLen = src->bufSize - src->bufIndex;
+
+ while (remainLen > 0)
+ {
+ ret_decode = hdlc_decode(&dest, src);
+ if(!ret_decode)
+ {
+ if (dest.bufIndex != 0 || src->bufSize - src->bufIndex == remainLen)
+ {
+ break;
+ }
+ }
+ else
+ {
+ deal_with_rawdata(dest.buf, dest.bufIndex);
+ dest.bufIndex = 0;
+ }
+ remainLen = src->bufSize - src->bufIndex;
+ }//end while
+ if (dest.bufSize <= dest.bufIndex)
+ {
+ dest.bufIndex = 0;
+ }
+ if (src->bufSize > src->bufIndex)
+ {
+ src->bufSize -= src->bufIndex;
+ memmove(src->buf, src->buf + src->bufIndex, src->bufSize);
+ }
+ else
+ {
+ src->bufSize = 0;
+ }
+ src->bufIndex = 0;
+ return 0;
+}