Files
luban-lite-t3e-pro/packages/third-party/adbd/services/file_exmod.c
刘可亮 9f7ba67007 v1.0.3
2024-01-27 08:47:24 +08:00

691 lines
17 KiB
C

/*
* Copyright (c) 2018, Real-Thread Information Technology Ltd
* All rights reserved
*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018-12-18 tyx the first version
*/
#include <rtthread.h>
#include <string.h>
#include <dfs_posix.h>
#include "file_exmod.h"
#include "file_sync_service.h"
#define DBG_ENABLE
#define DBG_SECTION_NAME "sync_mod"
#define DBG_LEVEL DBG_INFO
#define DBG_COLOR
#include <rtdbg.h>
#ifdef LPKG_ADB_EXTERNAL_MOD_ENABLE
static struct rt_slist_node _excnd_mod_head;
static bool file_exmod_write(struct adb_service *ser, void *buf, int size, int ms)
{
struct adb_packet *p;
if (ser->online == 0)
{
return false;
}
p = adb_packet_new(size);
if (!p)
{
LOG_E("new packet fail. discard packets");
return false;
}
memcpy(p->payload, buf, size);
if (!adb_service_sendpacket(ser, p, ms))
{
LOG_E("send packet fail. delete packets");
adb_packet_delete(p);
return false;
}
return true;
}
static bool file_exmod_read(struct adb_service *ser, void *buf, int size, int ms)
{
struct filesync_ext *ext = (struct filesync_ext *)ser->extptr;
int len;
struct adb_packet *p;
char *dpos = (char*)buf;
char *spos;
while (size)
{
if (!ext->cur)
{
if (!adb_packet_dequeue(&ext->recv_que, &ext->cur, ms))
{
LOG_E("depacket fail. return false");
return false;
}
ext->cur->split = 0; //used as postion of read
}
p = ext->cur;
spos = (char*)(p->payload + p->split);
len = size > p->msg.data_length ? p->msg.data_length : size;
rt_memcpy(dpos, spos, len);
p->msg.data_length -= len;
p->split += len;
dpos += len;
size -= len;
if (p->msg.data_length == 0)
{
ext->cur = 0;
adb_packet_delete(p);
}
}
return true;
}
static bool file_exmod_send_fail(struct adb_service *ser, const char *reason)
{
union file_syncmsg msg = { 0 };
bool ret;
msg.data.id = ID_FAIL;
msg.data.size = strlen(reason);
LOG_D("F:%s L:%d reason:%s", __FUNCTION__, __LINE__, reason);
ret = file_exmod_write(ser, &msg.data, sizeof(msg.data), 50);
if (ret == true)
{
ret = file_exmod_write(ser, (void*)reason, msg.data.size, 50);
}
return ret;
}
int file_exmod_write_data(struct f_exmod *exmod, void *buffer, int size)
{
int curr_size = 0, r;
union file_syncmsg msg = { 0 };
bool ret = true;
LOG_D("F:%s L:%d run. size:%d", __FUNCTION__, __LINE__, size);
if((exmod == NULL) || (buffer == NULL) || (size == 0))
{
return 0;
}
while (curr_size < size)
{
r = (size - curr_size) > SYNC_DATA_MAX ? SYNC_DATA_MAX : size - curr_size;
msg.data.id = ID_DATA;
msg.data.size = r;
ret = file_exmod_write(exmod->ser, &msg.data, sizeof(msg.data), 400);
if (ret)
{
ret = file_exmod_write(exmod->ser, (char*)buffer + curr_size, r, 100);
}
if (!ret)
{
LOG_E("write data err. return");
return 0;
}
curr_size += r;
}
return curr_size;
}
int file_exmod_read_data(struct f_exmod *exmod, void *buffer, int size)
{
union file_syncmsg *msg;
int curr_size = 0, r;
LOG_D("F:%s L:%d run. size:%d", __FUNCTION__, __LINE__, size);
while (curr_size < size)
{
if (exmod->msg == NULL)
{
msg = malloc(sizeof(union file_syncmsg));
if (msg == NULL)
{
file_exmod_send_fail(exmod->ser, "malloc file sync msg head fail");
return 0;
}
if (!file_exmod_read(exmod->ser, &msg->data, sizeof(msg->data), 100))
{
file_exmod_send_fail(exmod->ser, "read data head fail");
return 0;
}
if (msg->data.id != ID_DATA)
{
if (msg->data.id == ID_DONE)
{
free(msg);
exmod->msg = NULL;
LOG_D("read data finish");
break;
}
file_exmod_send_fail(exmod->ser, "invalid data message");
return 0;
}
}
else
{
msg = exmod->msg;
}
/* recv file data */
while ((msg->data.size > 0) && (curr_size < size))
{
r = (msg->data.size > SYNC_DATA_MAX) ? SYNC_DATA_MAX : msg->data.size;
r = r > (size - curr_size) ? (size - curr_size) : r;
if (!file_exmod_read(exmod->ser, (char *)buffer + curr_size, r, 800))
{
file_exmod_send_fail(exmod->ser, "read packet timeout");
return 0;
}
msg->data.size -= r;
curr_size += r;
}
if (msg->data.size > 0)
{
exmod->msg = msg;
break;
}
else
{
free(msg);
exmod->msg = NULL;
}
}
return curr_size;
}
bool file_exmod_do_lstat_v1(struct adb_service *ser, struct f_exmod *exmod)
{
union file_syncmsg msg = {0};
LOG_D("F:%s L:%d run", __FUNCTION__, __LINE__);
msg.stat_v1.id = ID_LSTAT_V1;
msg.stat_v1.mode = 0x000081b6;
msg.stat_v1.size = 0x00000000;
msg.stat_v1.time = 0x00000000;
return file_exmod_write(ser, &msg.stat_v1, sizeof(msg.stat_v1), 50);
}
bool file_exmod_do_list(struct adb_service *ser, struct f_exmod *exmod)
{
union file_syncmsg msg;
bool ret = true;
LOG_D("F:%s L:%d run", __FUNCTION__, __LINE__);
msg.dent.id = ID_DENT;
msg.dent.id = ID_DONE;
msg.dent.mode = 0;
msg.dent.size = 0;
msg.dent.time = 0;
msg.dent.namelen = 0;
ret = file_exmod_write(ser, &msg.dent, sizeof(msg.dent), 50);
return ret;
}
bool file_exmod_do_recv(struct adb_service *ser, struct f_exmod *exmod)
{
union file_syncmsg msg = { 0 };
struct f_exmod_handler *handle;
LOG_D("F:%s L:%d run", __FUNCTION__, __LINE__);
if (exmod == RT_NULL)
{
file_exmod_send_fail(ser, "file exmod is NULL");
return false;
}
handle = file_exmod_find(exmod->name);
if (handle == RT_NULL)
{
file_exmod_send_fail(ser, "not find mod!");
return false;
}
else if (handle->pull == RT_NULL)
{
file_exmod_send_fail(ser, "this mod not support pull mode!");
return false;
}
handle->pull(exmod);
msg.data.id = ID_DONE;
msg.data.size = 0;
return file_exmod_write(ser, &msg.data, sizeof(msg.data), 200);
}
bool file_exmod_do_send(struct adb_service *ser, struct f_exmod *exmod)
{
union file_syncmsg msg;
struct f_exmod_handler *handle;
if (exmod == RT_NULL)
{
file_exmod_send_fail(ser, "file exmod is NULL");
return false;
}
handle = file_exmod_find(exmod->name);
if (handle == RT_NULL)
{
file_exmod_send_fail(ser, "not find mod!");
return false;
}
else if (handle->push == RT_NULL)
{
file_exmod_send_fail(ser, "this mod not support push mode!");
return false;
}
handle->push(exmod);
msg.status.id = ID_OKAY;
msg.status.msglen = 0;
return file_exmod_write(ser, &msg.status, sizeof(msg.status), 100);
}
int file_exmod_register(struct f_exmod_handler *handle)
{
struct rt_slist_node *node, *head;
struct f_exmod_handler *entry;
if ((handle == RT_NULL) || (handle->name == RT_NULL))
{
LOG_E("handle or name is null! return");
return -1;
}
head = &_excnd_mod_head;
for (node = head->next; node != RT_NULL; node = node->next)
{
entry = rt_list_entry(node, struct f_exmod_handler, list);
if (strcmp(handle->name, entry->name) == 0)
{
LOG_E("The same mod name has been registered! return");
return -2;
}
}
rt_slist_init(&handle->list);
rt_slist_append(head, &handle->list);
return 0;
}
struct f_exmod_handler *file_exmod_find(const char *name)
{
struct rt_slist_node *node, *head;
struct f_exmod_handler *entry, *handler = RT_NULL;
LOG_D("F:%s L:%d name:%s", __FUNCTION__, __LINE__, name);
if (name == RT_NULL)
{
return RT_NULL;
}
head = &_excnd_mod_head;
for (node = head->next; node != RT_NULL; node = node->next)
{
entry = rt_list_entry(node, struct f_exmod_handler, list);
if (strcmp(name, entry->name) == 0)
{
handler = entry;
}
}
return handler;
}
struct f_exmod_handler *file_exmod_unregister(const char *name)
{
struct f_exmod_handler *handler = RT_NULL;
struct rt_slist_node *head;
LOG_D("F:%s L:%d name:%s", __FUNCTION__, __LINE__, name);
head = &_excnd_mod_head;
handler = file_exmod_find(name);
if (handler != RT_NULL)
{
rt_slist_remove(head, &handler->list);
}
return handler;
}
struct f_exmod *file_exmod_create(const char *name)
{
const char *str = name, *str_temp;
char *str_index;
int str_len, name_len, i;
struct f_exmod *exmod = RT_NULL;
char size_str[16];
char hex_flag = 0;
LOG_D("F:%s L:%d name:%s", __FUNCTION__, __LINE__, name);
if (name == RT_NULL)
{
return RT_NULL;
}
/* String Length Check */
name_len = strlen(name);
str_len = strlen(FILE_EXMOD_HEAD_PRE);
if (name_len <= str_len)
{
return RT_NULL;
}
/* Find the head of the append command */
if (strncmp(str, FILE_EXMOD_HEAD_PRE, str_len) != 0)
{
return RT_NULL;
}
LOG_D("Find the packet header prefix");
exmod = rt_malloc(sizeof(struct f_exmod));
if (exmod == RT_NULL)
{
LOG_D("malloc f_exmod failed. return");
return RT_NULL;
}
memset(exmod, 0, sizeof(struct f_exmod));
/* Check for head legitimacy */
str += str_len;
str_temp = strstr(str, FILE_EXMOD_HEAD_POS);
if (str_temp == RT_NULL)
{
goto nfound;
}
LOG_D("Find the packet header suffix");
/* Get Name Length And Save Name */
str_len = str_temp - str;
if (str_len != 0)
{
exmod->name = rt_malloc(str_len + 1);
if (exmod->name == RT_NULL)
{
goto nfound;
}
exmod->name[str_len] = '\0';
strncpy(exmod->name, str, str_len);
}
str_len = strlen(FILE_EXMOD_HEAD_POS);
str = str_temp + str_len;
LOG_D("get exmod name:%s", exmod->name);
/* Check file size */
str_len = strlen(FILE_EXMOD_SIZE_PRE);
if (strncmp(str, FILE_EXMOD_SIZE_PRE, str_len) != 0)
{
goto nfound;
}
LOG_D("Find File Size Header Prefix");
str += str_len;
str_temp = strstr(str, FILE_EXMOD_SIZE_POS);
if (str_temp == RT_NULL)
{
goto nfound;
}
LOG_D("Find File Size Header Suffix");
if (str_temp != str)
{
/* Get file size */
if ((str[0] == '0') && ((str[1] == 'x') || (str[1] == 'X')))
{
hex_flag = RT_TRUE;
str += 2;
}
str_len = str_temp - str;
if ((str_len) > sizeof(size_str))
{
goto nfound;
}
for (i = 0; i < str_len; i++)
{
if ((*str >= '0') && (*str <= '9'))
{
size_str[i] = *str - '0';
}
else if ((*str >= 'A') && (*str <= 'F'))
{
size_str[i] = 10 + *str - 'A';
hex_flag = RT_TRUE;
}
else if ((*str >= 'a') && (*str <= 'f'))
{
size_str[i] = 10 + *str - 'F';
hex_flag = RT_TRUE;
}
else
{
goto nfound;
}
str ++;
}
for (i = 0; i < str_len; i++)
{
if (hex_flag == RT_TRUE)
{
exmod->file_size = exmod->file_size * 16 + size_str[i];
}
else
{
exmod->file_size = exmod->file_size * 10 + size_str[i];
}
}
LOG_D("get File Size:%d", exmod->file_size);
}
/* Check whether there are parameters */
str = str_temp + strlen(FILE_EXMOD_SIZE_POS);
/* No parameters, Copy path */
if (*str == '/')
{
exmod->path = strdup(str);
LOG_D("No parameters.get path:%s", exmod->path);
return exmod;
}
str_len = strlen(FILE_EXMOD_PARAM_PRE);
/* Check parameter head */
if (strncmp(str, FILE_EXMOD_PARAM_PRE, str_len) != 0)
{
goto nfound;
}
str += str_len;
LOG_D("find parameter prefix");
/* Find parameter end address */
str_temp = strstr(str, FILE_EXMOD_PARAM_POS);
if (str_temp == RT_NULL)
{
goto nfound;
}
LOG_D("find parameter Suffix");
/* parameters head == parameters end, No parameters */
if (str == str_temp)
{
str_temp += strlen(FILE_EXMOD_PARAM_POS);
if (*str_temp == '/')
{
exmod->path = strdup(str_temp);
LOG_D("The parameter is empty.get path: %s", exmod->path);
return exmod;
}
else
{
LOG_E("Illegal path");
goto nfound;
}
}
/* Get the number of parameters */
str_index = (char *)str;
exmod->param_num = 1;
while ((*str_index != '\0') && (str_index < str_temp))
{
if (*str_index == FILE_EXMOD_PARAM_DIV)
{
exmod->param_num ++;
}
str_index++;
}
LOG_D("get parameter num:%d", exmod->param_num);
/* The parameter region is empty, Copy path and return */
if (exmod->param_num == 0)
{
str = str_temp + strlen(FILE_EXMOD_PARAM_POS);
if (*str == '/')
{
exmod->path = strdup(str);
LOG_D("The number of parameters is 0. get path:%s", exmod->path);
return exmod;
}
else
{
LOG_E("parameters is 0 && Illegal path");
goto nfound;
}
}
/* Cache parameter region */
str_len = str_temp - str;
exmod->param = rt_malloc(str_len + 1);
if (exmod->param == RT_NULL)
{
LOG_E("malloc parameter cache buff failed");
goto nfound;
}
exmod->param[str_len] = '\0';
strncpy(exmod->param, str, str_len);
exmod->param_res = rt_malloc(exmod->param_num * sizeof(struct f_param));
if(exmod->param_res == RT_NULL)
{
LOG_E("malloc Parameter descriptor failed");
goto nfound;
}
memset(exmod->param_res, 0, exmod->param_num * sizeof(struct f_param));
/* Get parameters */
str_index = exmod->param;
for (i = 0; (i < exmod->param_num) && (*str_index != '\0'); i++)
{
if (*str_index == FILE_EXMOD_PARAM_DIV)
{
exmod->param_res[i].key = RT_NULL;
str_index ++;
continue;
}
else
{
exmod->param_res[i].key = str_index;
}
while (*str_index != '\0')
{
if (*str_index == FILE_EXMOD_KEY_DIV)
{
*str_index = '\0';
exmod->param_res[i].value = str_index + 1;
}
else if (*str_index == FILE_EXMOD_PARAM_DIV)
{
*str_index = '\0';
str_index++;
break;
}
str_index++;
}
}
#ifdef DBG_ENABLE
for (i = 0; i < exmod->param_num; i++)
{
LOG_D("param_res[i] %s=%s", exmod->param_res[i].key, exmod->param_res[i].value);
}
#endif
/* get path */
str = str_temp + strlen(FILE_EXMOD_PARAM_POS);
exmod->path = strdup(str);
if (exmod->path == RT_NULL)
{
goto nfound;
}
LOG_D("get file path:%s", exmod->path);
return exmod;
nfound:
if (exmod->name != RT_NULL)
{
rt_free(exmod->name);
}
if (exmod->param != RT_NULL)
{
rt_free(exmod->param);
}
if (exmod->path != RT_NULL)
{
rt_free(exmod->path);
}
if (exmod->param_res != RT_NULL)
{
rt_free(exmod->param_res);
}
if (exmod != RT_NULL)
{
rt_free(exmod);
}
return RT_NULL;
}
void file_exmod_delete(struct f_exmod *exmod)
{
if (exmod == RT_NULL)
{
return;
}
if (exmod->name != RT_NULL)
{
rt_free(exmod->name);
}
if (exmod->param != RT_NULL)
{
rt_free(exmod->param);
}
if (exmod->path != RT_NULL)
{
rt_free(exmod->path);
}
if (exmod->param_res != RT_NULL)
{
rt_free(exmod->param_res);
}
if (exmod != RT_NULL)
{
rt_free(exmod);
}
}
#endif