* Copyright (c) 2022 Huawei Technologies Co.,Ltd.
*
* GR is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
*
* http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
* -------------------------------------------------------------------------
*
* gr_api_impl.c
*
*
* IDENTIFICATION
* src/common_api/gr_api_impl.c
*
* -------------------------------------------------------------------------
*/
#include "cm_system.h"
#include "cm_date.h"
#include "gr_defs.h"
#include "gr_diskgroup.h"
#include "gr_file.h"
#include "gr_file_def.h"
#include "gr_latch.h"
#include "gr_malloc.h"
#include "gr_api_impl.h"
#include "gr_defs.h"
#include "gr_thv.h"
#include "gr_stats.h"
#include "gr_cli_conn.h"
#include "gr_error_handler.h"
#include "gr_param_validator.h"
#include <stdint.h>
#include <openssl/sha.h>
#ifdef __cplusplus
extern "C" {
#endif
#define GR_ACCMODE 00000003
#define GR_OPEN_MODE(flag) ((flag + 1) & GR_ACCMODE)
int32_t g_gr_tcp_conn_timeout = GR_TCP_CONNECT_TIMEOUT;
typedef struct str_files_rw_ctx {
int32_t handle;
int32_t size;
bool32 read;
int64 offset;
} files_rw_ctx_t;
status_t gr_connect(const char *server_locator, gr_conn_opt_t *options, gr_conn_t *conn)
{
LOG_DEBUG_INF("gr connect entry, server_locator:%s", server_locator);
if (server_locator == NULL) {
GR_THROW_ERROR(ERR_GR_TCP_INVALID_URL, "NULL", 0);
return CM_ERROR;
}
if ((conn->flag == CM_TRUE) && (conn->pipe.link.tcp.closed == CM_FALSE)) {
LOG_DEBUG_INF("gr connect already connected");
return CM_SUCCESS;
}
conn->flag = CM_FALSE;
conn->cli_vg_handles = NULL;
conn->pipe.options = 0;
int32_t timeout = options != NULL ? options->timeout : g_gr_tcp_conn_timeout;
conn->pipe.connect_timeout = timeout < 0 ? GR_TCP_CONNECT_TIMEOUT : timeout;
conn->pipe.socket_timeout = GR_TCP_SOCKET_TIMEOUT;
conn->pipe.link.tcp.sock = CS_INVALID_SOCKET;
conn->pipe.link.tcp.closed = CM_FALSE;
conn->pipe.type = CS_TYPE_SSL;
conn->session = NULL;
status_t ret = cs_connect(
server_locator, &conn->pipe, NULL);
if (ret != CM_SUCCESS) {
LOG_RUN_ERR("connect server failed, ip port:%s", server_locator);
return ret;
}
gr_init_packet(&conn->pack, conn->pipe.options);
conn->flag = CM_TRUE;
return CM_SUCCESS;
}
void gr_disconnect(gr_conn_t *conn)
{
LOG_DEBUG_INF("gr disconnect entry");
gr_set_thv_run_ctx_item(GR_THV_RUN_CTX_ITEM_SESSION, NULL);
if (conn->flag == CM_TRUE) {
cs_disconnect(&conn->pipe);
gr_free_packet_buffer(&conn->pack);
conn->flag = CM_FALSE;
}
LOG_DEBUG_INF("gr disconnect leave");
return;
}
status_t gr_set_session_id(gr_conn_t *conn, uint32_t objectid)
{
if (objectid >= gr_get_max_total_session_cnt()) {
LOG_RUN_ERR_INHIBIT(LOG_INHIBIT_LEVEL1, "objectid error, objectid is %u, max session cnt is %u.", objectid,
gr_get_max_total_session_cnt());
return ERR_GR_SESSION_INVALID_ID;
}
return CM_SUCCESS;
}
static status_t gr_set_server_info(gr_conn_t *conn, char *home, uint32_t objectid, uint32_t max_open_file)
{
status_t status = gr_init_client(max_open_file, home);
GR_RETURN_IFERR3(status, LOG_RUN_ERR_INHIBIT(LOG_INHIBIT_LEVEL1, "gr client init failed."), gr_disconnect(conn));
status = cli_init_ssl(&conn->cli_ssl_inst);
GR_RETURN_IFERR3(status,
LOG_RUN_ERR_INHIBIT(LOG_INHIBIT_LEVEL1, "gr client init ssl failed."), gr_disconnect(conn));
status = gr_set_session_id(conn, objectid);
GR_RETURN_IFERR3(status, LOG_RUN_ERR_INHIBIT(LOG_INHIBIT_LEVEL1, "gr client failed to initialize session."),
gr_disconnect(conn));
return CM_SUCCESS;
}
status_t gr_cli_handshake(gr_conn_t *conn, uint32_t max_open_file)
{
conn->cli_info.cli_pid = cm_sys_pid();
conn->cli_info.thread_id = cm_get_current_thread_id();
status_t status = cm_sys_process_start_time(conn->cli_info.cli_pid, &conn->cli_info.start_time);
if (status != CM_SUCCESS) {
LOG_RUN_ERR_INHIBIT(LOG_INHIBIT_LEVEL1, "Failed to get process start time pid %llu.\n", conn->cli_info.cli_pid);
return CM_ERROR;
}
LOG_DEBUG_INF("The process start time is:%lld.", conn->cli_info.start_time);
errno_t err;
err = strcpy_s(conn->cli_info.process_name, sizeof(conn->cli_info.process_name), cm_sys_program_name());
if (err != EOK) {
LOG_RUN_ERR("System call strcpy_s error %d.", err);
return CM_ERROR;
}
conn->cli_info.connect_time = cm_clock_monotonic_now();
gr_get_server_info_t output_info = {NULL, GR_INVALID_SESSIONID, CM_FALSE};
CM_RETURN_IFERR(gr_msg_interact(conn, GR_CMD_HANDSHAKE, (void *)&conn->cli_info, (void *)&output_info));
if (getenv(GR_ENV_HOME) != NULL) {
output_info.home = getenv(GR_ENV_HOME);
}
conn->hash_auth_enable = output_info.hash_auth_enable;
LOG_RUN_INF("[GR_CONNECT]Client received HASH_AUTH_ENABLE=%d from server", conn->hash_auth_enable);
return gr_set_server_info(conn, output_info.home, output_info.objectid, max_open_file);
}
status_t gr_cli_ssl_connect(gr_conn_t *conn)
{
LOG_DEBUG_INF("gr cli ssl connect entry");
status_t status = cli_ssl_connect(&conn->cli_ssl_inst, &conn->pipe);
if (status != CM_SUCCESS) {
LOG_RUN_ERR("Failed to do cli ssl certification.");
return CM_ERROR;
}
LOG_DEBUG_INF("gr cli ssl connect leave");
return CM_SUCCESS;
}
void gr_disconnect_ex(gr_conn_t *conn)
{
gr_env_t *gr_env = gr_get_env();
gr_disconnect(conn);
gr_latch_x(&gr_env->conn_latch);
if (gr_env->conn_count > 0) {
gr_env->conn_count--;
}
if (gr_env->conn_count == 0) {
gr_destroy();
}
uint32_t count = gr_env->conn_count;
gr_unlatch(&gr_env->conn_latch);
LOG_DEBUG_INF("Remain conn count:%u when disconnect.", count);
return;
}
status_t gr_vfs_create_impl(gr_conn_t *conn, const char *dir_name, unsigned long long attrFlag)
{
text_t text;
cm_str2text((char *)dir_name, &text);
if (text.len >= GR_MAX_NAME_LEN) {
GR_THROW_ERROR_EX(
ERR_GR_DIR_CREATE, "Length of dir name(%s) is too long, maximum is %u.", T2S(&text), GR_MAX_NAME_LEN);
return CM_ERROR;
}
GR_RETURN_IF_ERROR(gr_check_name(dir_name));
LOG_DEBUG_INF("gr make dir entry, dir_name:%s", dir_name);
gr_make_dir_info_t send_info;
send_info.name = dir_name;
send_info.attrFlag = attrFlag;
status_t status = gr_msg_interact(conn, GR_CMD_MKDIR, (void *)&send_info, NULL);
LOG_DEBUG_INF("gr make dir leave");
return status;
}
status_t gr_vfs_delete_impl(gr_conn_t *conn, const char *dir, unsigned long long attrFlag)
{
GR_RETURN_IF_ERROR(gr_check_device_path(dir));
LOG_DEBUG_INF("gr remove dir entry, dir:%s", dir);
gr_remove_dir_info_t send_info;
send_info.name = dir;
send_info.attrFlag = attrFlag;
status_t status = gr_msg_interact(conn, GR_CMD_RMDIR, (void *)&send_info, NULL);
LOG_DEBUG_INF("gr remove dir leave");
return status;
}
status_t gr_vfs_mount_impl(gr_conn_t *conn, gr_vfs_handle *vfs_handle, unsigned long long attrFlag)
{
if (vfs_handle == NULL || vfs_handle->vfs_name[0] == '\0') {
LOG_RUN_ERR("vfs handle is NULL or vfs name is empty.");
return CM_ERROR;
}
LOG_DEBUG_INF("gr mount vfs entry, vfs_name:%s", vfs_handle->vfs_name);
gr_mount_vfs_info_t send_info;
send_info.vfs_name = vfs_handle->vfs_name;
send_info.dir = 0;
status_t status = gr_msg_interact(conn, GR_CMD_MOUNT_VFS, (void *)&send_info, (void *)&send_info);
vfs_handle->dir_handle = send_info.dir;
LOG_DEBUG_INF("gr mount vfs leave");
return status;
}
status_t gr_vfs_unmount_impl(gr_conn_t *conn, gr_vfs_handle *vfs_handle)
{
GR_PARAM_CHECK_RETURN(vfs_handle != NULL, ERR_GR_INVALID_PARAM, "vfs handle is NULL");
GR_PARAM_CHECK_RETURN(vfs_handle->vfs_name[0] != '\0', ERR_GR_INVALID_PARAM, "vfs name is empty");
LOG_DEBUG_INF("gr unmount vfs entry, vfs_name:%s", vfs_handle->vfs_name);
gr_mount_vfs_info_t send_info;
send_info.dir = vfs_handle->dir_handle;
status_t status = gr_msg_interact(conn, GR_CMD_UNMOUNT_VFS, (void *)&send_info, (void *)&send_info);
LOG_DEBUG_INF("gr unmount vfs leave");
return status;
}
status_t gr_vfs_query_file_num_impl(gr_conn_t *conn, gr_vfs_handle vfs_handle, uint32_t *file_num)
{
LOG_DEBUG_INF("gr query file num entry");
gr_query_file_num_info_t send_info;
send_info.dir = vfs_handle.dir_handle;
send_info.file_num = *file_num;
status_t status = gr_msg_interact(conn, GR_CMD_QUERY_FILE_NUM, (void *)&send_info, (void *)&send_info);
if (status != CM_SUCCESS) {
LOG_RUN_ERR("gr query file num error");
return CM_ERROR;
}
*file_num = send_info.file_num;
LOG_DEBUG_INF("gr query file num leave");
return status;
}
status_t gr_vfs_query_file_info_impl(gr_conn_t *conn, gr_vfs_handle vfs_handle, gr_file_item_t *file_info, bool is_continue)
{
LOG_DEBUG_INF("Client query file info entry, vfs_name: %s", vfs_handle.vfs_name);
gr_query_file_num_info_t send_info;
send_info.dir = vfs_handle.dir_handle;
send_info.is_continue = is_continue;
status_t status = gr_msg_interact(conn, GR_CMD_QUERY_FILE_INFO, (void *)&send_info, (void *)file_info);
if (status != CM_SUCCESS) {
LOG_RUN_ERR("Failed to interact with server for file info query");
return CM_ERROR;
}
LOG_DEBUG_INF("Client query file info leave.");
return CM_SUCCESS;
}
status_t gr_create_file_impl(gr_conn_t *conn, const char *file_path, int flag)
{
LOG_DEBUG_INF("gr create file entry, file path:%s, flag:%d", file_path, flag);
GR_RETURN_IF_ERROR(gr_check_device_path(file_path));
gr_create_file_info_t send_info;
send_info.file_path = file_path;
send_info.flag = (uint32_t)flag;
status_t status = gr_msg_interact(conn, GR_CMD_CREATE_FILE, (void *)&send_info, NULL);
LOG_DEBUG_INF("gr create file leave");
return status;
}
status_t gr_remove_file_impl(gr_conn_t *conn, const char *file_path, unsigned long long attrFlag)
{
LOG_DEBUG_INF("gr remove file entry, file path:%s", file_path);
GR_RETURN_IF_ERROR(gr_check_device_path(file_path));
gr_remove_file_info_t send_info;
send_info.name = file_path;
send_info.attrFlag = attrFlag;
status_t status = gr_msg_interact(conn, GR_CMD_DELETE_FILE, (void *)&send_info, NULL);
LOG_DEBUG_INF("gr remove file leave");
return status;
}
status_t gr_open_file_on_server(gr_conn_t *conn, const char *file_path, int flag, gr_file_handle *file_handle)
{
LOG_DEBUG_INF("gr open file on server entry, file_path:%s, flag:%d", file_path, flag);
gr_open_file_info_t send_info;
send_info.file_path = file_path;
send_info.flag = flag;
return gr_msg_interact(conn, GR_CMD_OPEN_FILE, (void*)&send_info, (void*)file_handle);
}
status_t gr_open_file_impl(gr_conn_t *conn, const char *file_path, int flag, gr_file_handle* file_handle)
{
LOG_DEBUG_INF("gr begin to open file, file path:%s, flag:%d", file_path, flag);
GR_RETURN_IF_ERROR(gr_check_device_path(file_path));
GR_RETURN_IF_ERROR(gr_check_file_flag(flag));
if (gr_open_file_on_server(conn, file_path, flag, file_handle) != CM_SUCCESS) {
LOG_RUN_ERR("Failed to open file on server, file path:%s, flag:%d", file_path, flag);
return CM_ERROR;
}
LOG_DEBUG_INF("gr open file successfully, file_path:%s, flag:%d, handle:%d", file_path, flag, file_handle->fd);
return CM_SUCCESS;
}
status_t gr_postpone_file_time_impl(gr_conn_t *conn, const char *file_name, const char *time)
{
LOG_DEBUG_INF("gr extend file expired time, file name: %s, add time: %s", file_name, time);
GR_RETURN_IF_ERROR(gr_check_device_path(file_name));
gr_postpone_file_time_t send_info;
send_info.file_name = file_name;
send_info.file_atime = time;
status_t status = gr_msg_interact(conn, GR_CMD_POSTPONE_FILE_TIME, (void *)&send_info, NULL);
LOG_DEBUG_INF("gr extend file expired time");
return status;
}
status_t gr_close_file_impl(gr_conn_t *conn, int handle, bool need_lock)
{
LOG_DEBUG_INF("gr close file entry, handle:%d", handle);
status_t ret = gr_close_file_on_server(conn, handle, need_lock);
if (ret != CM_SUCCESS) {
LOG_DEBUG_INF("Failed to fclose, handle:%d.", handle);
return ret;
}
LOG_DEBUG_INF("Success to fclose, handle:%d.", handle);
return CM_SUCCESS;
}
status_t gr_exist_impl(gr_conn_t *conn, const char *path, bool32 *result, gft_item_type_t *type)
{
LOG_DEBUG_INF("gr exits file entry, name:%s", path);
GR_RETURN_IF_ERROR(gr_check_device_path(path));
gr_exist_recv_info_t recv_info;
GR_RETURN_IF_ERROR(gr_msg_interact(conn, GR_CMD_EXIST, (void *)path, (void *)&recv_info));
*result = (bool32)recv_info.result;
*type = (gft_item_type_t)recv_info.type;
LOG_DEBUG_INF("gr exits file or dir leave, name:%s, result:%d, type:%u", path, *result, *type);
return CM_SUCCESS;
}
status_t gr_check_path_exist(gr_conn_t *conn, const char *path)
{
bool32 exist = false;
gft_item_type_t type;
GR_RETURN_IFERR2(
gr_exist_impl(conn, path, &exist, &type),
GR_THROW_ERROR(ERR_GR_FILE_NOT_EXIST, "Failed to check the path %s exists.\n", path));
if (!exist) {
GR_THROW_ERROR(ERR_GR_FILE_NOT_EXIST, "%s not exist, please check", path);
return CM_ERROR;
}
if (type != GFT_PATH) {
LOG_RUN_ERR("%s is not a directory.\n", path);
return CM_ERROR;
}
return CM_SUCCESS;
}
status_t gr_check_file_exist(gr_conn_t *conn, const char *path, bool *is_exist)
{
if (is_exist == NULL) {
GR_THROW_ERROR(ERR_GR_INVALID_PARAM, "is_exist parameter is NULL");
return CM_ERROR;
}
bool32 exist = false;
gft_item_type_t type;
status_t status = gr_exist_impl(conn, path, &exist, &type);
if (status != CM_SUCCESS) {
GR_THROW_ERROR(ERR_GR_FILE_NOT_EXIST, "Failed to check the path %s exists.", path);
LOG_RUN_ERR("Failed to check the path %s exists.", path);
return status;
}
*is_exist = (exist && type == GFT_FILE);
return CM_SUCCESS;
}
status_t gr_check_file_flag(int flag)
{
if ((flag & O_CREAT) == O_CREAT || (flag & O_TRUNC) == O_TRUNC) {
GR_THROW_ERROR(ERR_GR_FILE_INVALID_FLAG);
return CM_ERROR;
}
return CM_SUCCESS;
}
int64 gr_pwrite_file_impl(gr_conn_t *conn, gr_file_handle *file_handle, const void *buf, unsigned long long size, long long offset)
{
LOG_DEBUG_INF("gr pwrite file entry, handle:%d, size:%lld, offset:%lld",
HANDLE_VALUE(file_handle->fd), size, offset);
gr_write_file_info_t send_info;
send_info.handle = HANDLE_VALUE(file_handle->fd);
status_t status;
unsigned long long total_size = 0;
unsigned long long remaining_size = size;
long long int rel_size = 0;
uint8_t hash[SHA256_DIGEST_LENGTH];
const char *buf_ptr = (const char *)buf;
while (total_size < size) {
const unsigned long long curr_size = (remaining_size > GR_RW_STEP_SIZE) ?
GR_RW_STEP_SIZE : remaining_size;
send_info.offset = offset + total_size;
send_info.size = curr_size;
send_info.buf = (char *)(buf_ptr + total_size);
if (conn->hash_auth_enable) {
status = calculate_data_hash(send_info.buf, curr_size, hash);
if (status != CM_SUCCESS) {
LOG_RUN_ERR("Failed to calculate data hash.");
GR_THROW_ERROR(ERR_GR_HASH_AUTH_FAILED, "Failed to calculate data hash.");
return CM_ERROR;
}
status = xor_sha256_hash(hash, file_handle->hash, send_info.hash);
if (status != CM_SUCCESS) {
LOG_RUN_ERR("Failed to calculate combine_hash.");
GR_THROW_ERROR(ERR_GR_HASH_AUTH_FAILED, "Failed to calculate combine_hash.");
return CM_ERROR;
}
}
status = gr_msg_interact(conn, GR_CMD_WRITE_FILE, (void *)&send_info, (void *)&rel_size);
if (status != CM_SUCCESS) {
LOG_RUN_ERR("Failed to write file, total_size:%lld, remaining:%lld, offset:%lld.",
total_size, remaining_size, offset);
return CM_ERROR;
}
if (rel_size != curr_size) {
LOG_RUN_WAR("Partial write: expected %lld, actual %lld, total_size:%lld, offset:%lld",
curr_size, rel_size, total_size, offset);
total_size += rel_size;
break;
}
total_size += curr_size;
remaining_size -= curr_size;
errno_t errcode = memcpy_s(file_handle->hash, SHA256_DIGEST_LENGTH,
send_info.hash, SHA256_DIGEST_LENGTH);
if (errcode != EOK) {
LOG_RUN_ERR("Failed to memcpy hash, size:%d.", SHA256_DIGEST_LENGTH);
GR_THROW_ERROR(ERR_SYSTEM_CALL, errcode);
return CM_ERROR;
}
}
LOG_DEBUG_INF("gr pwrite file leave, total written: %lld", total_size);
return total_size;
}
int64 gr_append_file_impl(gr_conn_t *conn, gr_file_handle *file_handle, const void *buf, unsigned long long size)
{
LOG_DEBUG_INF("gr append file entry, handle:%d, size:%lld",
HANDLE_VALUE(file_handle->fd), size);
gr_write_file_info_t send_info;
send_info.handle = HANDLE_VALUE(file_handle->fd);
send_info.size = size;
send_info.buf = (char *)buf;
status_t status;
unsigned long long total_size = 0;
unsigned long long remaining_size = size;
long long int rel_size = 0;
uint8_t hash[SHA256_DIGEST_LENGTH];
const char *buf_ptr = (const char *)buf;
while (total_size < size) {
const unsigned long long curr_size = (remaining_size > GR_RW_STEP_SIZE) ?
GR_RW_STEP_SIZE : remaining_size;
send_info.size = curr_size;
send_info.buf = (char *)(buf_ptr + total_size);
if (conn->hash_auth_enable) {
status = calculate_data_hash(send_info.buf, curr_size, hash);
if (status != CM_SUCCESS) {
LOG_RUN_ERR("Failed to calculate data hash.");
GR_THROW_ERROR(ERR_GR_HASH_AUTH_FAILED, "Failed to calculate data hash.");
return CM_ERROR;
}
status = xor_sha256_hash(hash, file_handle->hash, send_info.hash);
if (status != CM_SUCCESS) {
LOG_RUN_ERR("Failed to calculate combine_hash.");
GR_THROW_ERROR(ERR_GR_HASH_AUTH_FAILED, "Failed to calculate combine_hash.");
return CM_ERROR;
}
}
status = gr_msg_interact(conn, GR_CMD_APPEND_FILE, (void *)&send_info, (void *)&rel_size);
if (status != CM_SUCCESS) {
LOG_RUN_ERR("Failed to append file, total_size:%lld, remaining:%lld.",
total_size, remaining_size);
return CM_ERROR;
}
if (rel_size != curr_size) {
LOG_RUN_WAR("Partial append: expected %lld, actual %lld, total_size:%lld",
curr_size, rel_size, total_size);
total_size += rel_size;
break;
}
total_size += curr_size;
remaining_size -= curr_size;
errno_t errcode = memcpy_s(file_handle->hash, SHA256_DIGEST_LENGTH,
send_info.hash, SHA256_DIGEST_LENGTH);
if (errcode != EOK) {
LOG_RUN_ERR("Failed to memcpy hash, size:%d.", SHA256_DIGEST_LENGTH);
GR_THROW_ERROR(ERR_SYSTEM_CALL, errcode);
return CM_ERROR;
}
}
LOG_DEBUG_INF("gr append file leave, total written: %lld", total_size);
return total_size;
}
int64 gr_pread_file_impl(gr_conn_t *conn, int handle, const void *buf, unsigned long long size, long long offset)
{
if (size < 0) {
LOG_RUN_ERR("File size is invalid: %lld.", size);
return CM_ERROR;
}
LOG_DEBUG_INF("gr pread file entry, handle:%d, size:%lld, offset:%lld", handle, size, offset);
gr_read_file_info_t send_info;
send_info.handle = handle;
status_t status;
int64 total_size = 0;
int64 curr_size = 0;
int64 remaining_size = size;
while (total_size < size) {
curr_size = (remaining_size > GR_RW_STEP_SIZE) ? GR_RW_STEP_SIZE : remaining_size;
send_info.offset = offset + total_size;
send_info.size = curr_size;
send_info.buf = (char *)buf + total_size;
status = gr_msg_interact(conn, GR_CMD_READ_FILE, (void *)&send_info, (void *)&send_info);
if (status != CM_SUCCESS) {
LOG_RUN_ERR("Failed to read file, total_size:%lld, size:%lld, offset:%lld, errmsg:%s.",
total_size, size - total_size, offset, strerror(errno));
return CM_ERROR;
}
if (send_info.rel_size != curr_size) {
LOG_RUN_WAR("Failed to read file, total_size:%lld, size:%lld, offset:%lld, rel_size:%lld, errmsg:%s.",
total_size, size - total_size, offset, send_info.rel_size, strerror(errno));
total_size += send_info.rel_size;
break;
}
total_size += curr_size;
remaining_size -= curr_size;
}
LOG_DEBUG_INF("gr pread file leave");
return total_size;
}
status_t gr_stat_file_impl(
gr_conn_t *conn, const char *fileName, long long *offset, unsigned long long *size, int *mode, char **time)
{
LOG_DEBUG_INF("gr stat file entry, fileName:%s", fileName);
gr_stat_file_info_t send_info;
send_info.name = fileName;
send_info.offset = 0;
send_info.size = 0;
send_info.mode = 0;
send_info.expire_time = NULL;
status_t status = gr_msg_interact(conn, GR_CMD_STAT_FILE, (void *)&send_info, (void *)&send_info);
*offset = send_info.offset;
*size = send_info.size;
*mode = (int)send_info.mode;
*time = send_info.expire_time;
LOG_DEBUG_INF("gr stat file leave, offset:%lld, size:%llu, mode:%d", *offset, *size, *mode);
return status;
}
void gr_heartbeat_entry(thread_t *thread)
{
return;
}
static status_t gr_init_err_proc(
gr_env_t *gr_env, const char *errmsg, status_t errcode)
{
gr_unlatch(&gr_env->latch);
if (errmsg != NULL) {
LOG_RUN_ERR("init error: %s", errmsg);
}
return errcode;
}
status_t gr_init_client(uint32_t max_open_files, char *home)
{
LOG_DEBUG_INF("gr init client entry, max_open_files:%u, home:%s", max_open_files, home ? home : "NULL");
if (max_open_files > GR_MAX_OPEN_FILES) {
GR_THROW_ERROR(ERR_INVALID_VALUE, "max_open_files", max_open_files);
return CM_ERROR;
}
gr_env_t *gr_env = gr_get_env();
if (gr_env->initialized) {
LOG_DEBUG_INF("gr init client already initialized");
return CM_SUCCESS;
}
gr_latch_x(&gr_env->latch);
if (gr_env->initialized) {
#ifdef ENABLE_GRTEST
if (gr_env->inittor_pid == getpid()) {
#endif
return gr_init_err_proc(gr_env, NULL, CM_SUCCESS);
#ifdef ENABLE_GRTEST
} else {
LOG_RUN_INF("gr client need re-initalization gr env, last init pid:%llu.", (uint64)gr_env->inittor_pid);
(void)gr_init_err_proc(gr_env, "need reinit by a new process", CM_SUCCESS);
gr_env->initialized = CM_FALSE;
gr_env->inittor_pid = 0;
}
#endif
}
status_t status = gr_set_cfg_dir(home, &gr_env->inst_cfg);
if (status != CM_SUCCESS) {
return gr_init_err_proc(gr_env, "Environment variant GR_HOME not found", status);
}
status = gr_load_config(&gr_env->inst_cfg);
if (status != CM_SUCCESS) {
return gr_init_err_proc(gr_env, "load config failed", status);
}
status = gr_load_cli_ssl(&gr_env->inst_cfg);
if (status != CM_SUCCESS) {
return gr_init_err_proc(gr_env, "load client ssl config failed", status);
}
status = cm_create_thread(gr_heartbeat_entry, SIZE_K(512), NULL, &gr_env->thread_heartbeat);
if (status != CM_SUCCESS) {
return gr_init_err_proc(gr_env, "GR failed to create heartbeat thread", status);
}
#ifdef ENABLE_GRTEST
gr_env->inittor_pid = getpid();
#endif
gr_env->initialized = CM_TRUE;
gr_unlatch(&gr_env->latch);
return CM_SUCCESS;
}
void gr_destroy(void)
{
LOG_DEBUG_INF("gr destroy entry");
gr_env_t *gr_env = gr_get_env();
gr_latch_x(&gr_env->latch);
if (!gr_env->initialized) {
gr_unlatch(&gr_env->latch);
LOG_DEBUG_INF("gr destroy already destroyed");
return;
}
cm_close_thread_nowait(&gr_env->thread_heartbeat);
gr_env->initialized = 0;
gr_unlatch(&gr_env->latch);
LOG_DEBUG_INF("gr destroy leave");
}
status_t gr_setcfg_impl(gr_conn_t *conn, const char *name, const char *value, const char *scope)
{
LOG_DEBUG_INF("gr set cfg entry, name:%s, value:%s, scope:%s", name, value, scope);
GR_RETURN_IF_ERROR(gr_check_str_not_null(name, "name"));
GR_RETURN_IF_ERROR(gr_check_str_not_null(value, "value"));
GR_RETURN_IF_ERROR(gr_check_str_not_null(scope, "scope"));
gr_setcfg_info_t send_info;
send_info.name = name;
send_info.value = value;
send_info.scope = scope;
status_t status = gr_msg_interact(conn, GR_CMD_SETCFG, (void *)&send_info, NULL);
LOG_DEBUG_INF("gr set cfg leave");
return status;
}
status_t gr_getcfg_impl(gr_conn_t *conn, const char *name, char *out_str, size_t str_len)
{
LOG_DEBUG_INF("gr get cfg entry, name:%s", name);
GR_RETURN_IF_ERROR(gr_check_str_not_null(name, "name"));
text_t extra_info = CM_NULL_TEXT;
GR_RETURN_IF_ERROR(gr_msg_interact(conn, GR_CMD_GETCFG, (void *)name, (void *)&extra_info));
if (extra_info.len == 0) {
LOG_DEBUG_INF("Client get cfg is NULL.");
return CM_SUCCESS;
}
errno_t err = strncpy_s(out_str, str_len, extra_info.str, extra_info.len);
if (SECUREC_UNLIKELY(err != EOK)) {
GR_THROW_ERROR(ERR_GR_INVALID_PARAM, "value of str_len is not large enough when getcfg.");
return CM_ERROR;
}
LOG_DEBUG_INF("gr get cfg leave, value:%s", (strlen(out_str) == 0) ? "NULL" : out_str);
return CM_SUCCESS;
}
status_t gr_get_inst_status_on_server(gr_conn_t *conn, gr_server_status_t *gr_status)
{
LOG_DEBUG_INF("gr get inst status entry");
if (gr_status == NULL) {
GR_THROW_ERROR_EX(ERR_GR_INVALID_PARAM, "gr_status");
return CM_ERROR;
}
text_t extra_info = CM_NULL_TEXT;
GR_RETURN_IF_ERROR(gr_msg_interact(conn, GR_CMD_GET_INST_STATUS, NULL, (void *)&extra_info));
*gr_status = *(gr_server_status_t *)extra_info.str;
LOG_DEBUG_INF("gr get inst status leave, status:%s", gr_status->instance_status);
return CM_SUCCESS;
}
status_t gr_get_time_stat_on_server(gr_conn_t *conn, gr_stat_item_t *time_stat, uint64 size)
{
LOG_DEBUG_INF("gr get time stat entry");
text_t stat_info = CM_NULL_TEXT;
GR_RETURN_IF_ERROR(gr_msg_interact(conn, GR_CMD_GET_TIME_STAT, NULL, (void *)&stat_info));
for (uint64 i = 0; i < GR_EVT_COUNT; i++) {
time_stat[i] = *(gr_stat_item_t *)(stat_info.str + i * (uint64)sizeof(gr_stat_item_t));
}
LOG_DEBUG_INF("gr get time stat leave");
return CM_SUCCESS;
}
status_t gr_set_main_inst_impl(gr_conn_t *conn)
{
LOG_DEBUG_INF("gr set main inst entry");
status_t status = gr_msg_interact(conn, GR_CMD_SET_MAIN_INST, NULL, NULL);
LOG_DEBUG_INF("gr set main inst leave, status:%d", status);
return status;
}
status_t gr_reload_certs_impl(gr_conn_t *conn)
{
LOG_DEBUG_INF("gr reload certs entry");
status_t status = gr_msg_interact(conn, GR_CMD_RELOAD_CERTS, NULL, NULL);
LOG_DEBUG_INF("gr reload certs leave, status:%d", status);
return status;
}
status_t gr_reload_cfg_impl(gr_conn_t *conn)
{
return gr_msg_interact(conn, GR_CMD_RELOAD_CFG, NULL, NULL);
}
status_t gr_get_disk_usage_impl(gr_conn_t *conn, gr_disk_usage_info_t *info)
{
LOG_DEBUG_INF("gr get disk usage entry");
gr_disk_usage_ack_t ack_info = {0};
GR_RETURN_IF_ERROR(gr_msg_interact(conn, GR_CMD_GET_DISK_USAGE, NULL, (void *)&ack_info));
info->available_bytes = ack_info.available_bytes;
info->total_bytes = ack_info.total_bytes;
info->used_bytes = ack_info.used_bytes;
info->usage_percent = ack_info.usage_percent;
LOG_DEBUG_INF("gr get disk usage leave, total:%lu, used:%lu, avail:%lu",
info->total_bytes, info->used_bytes, info->available_bytes);
return CM_SUCCESS;
}
status_t gr_close_file_on_server(gr_conn_t *conn, int64 fd, bool need_lock)
{
LOG_DEBUG_INF("gr close file on server entry, fd:%lld, need_lock:%d", fd, need_lock);
gr_close_file_info_t send_info;
send_info.fd = fd;
send_info.need_lock = (int)need_lock;
return gr_msg_interact(conn, GR_CMD_CLOSE_FILE, (void *)&send_info, NULL);
}
status_t gr_stop_server_impl(gr_conn_t *conn)
{
LOG_DEBUG_INF("gr stop server entry");
status_t status = gr_msg_interact(conn, GR_CMD_STOP_SERVER, NULL, NULL);
LOG_DEBUG_INF("gr stop server leave, status:%d", status);
return status;
}
static status_t gr_encode_setcfg(gr_conn_t *conn, gr_packet_t *pack, void *send_info)
{
gr_setcfg_info_t *info = (gr_setcfg_info_t *)send_info;
CM_RETURN_IFERR(gr_put_str(pack, info->name));
CM_RETURN_IFERR(gr_put_str(pack, info->value));
CM_RETURN_IFERR(gr_put_str(pack, info->scope));
return CM_SUCCESS;
}
static status_t gr_encode_postpone_file_time(gr_conn_t *conn, gr_packet_t *pack, void *send_info)
{
gr_postpone_file_time_t *info = (gr_postpone_file_time_t *)send_info;
CM_RETURN_IFERR(gr_put_str(pack, info->file_name));
CM_RETURN_IFERR(gr_put_str(pack, info->file_atime));
return CM_SUCCESS;
}
static status_t gr_encode_handshake(gr_conn_t *conn, gr_packet_t *pack, void *send_info)
{
CM_RETURN_IFERR(gr_put_data(pack, send_info, sizeof(gr_cli_info_t)));
return CM_SUCCESS;
}
static status_t gr_encode_mount_vfs(gr_conn_t *conn, gr_packet_t *pack, void *send_info)
{
gr_mount_vfs_info_t *info = (gr_mount_vfs_info_t *)send_info;
CM_RETURN_IFERR(gr_put_str(pack, info->vfs_name));
return CM_SUCCESS;
}
static status_t gr_encode_unmount_vfs(gr_conn_t *conn, gr_packet_t *pack, void *send_info)
{
gr_mount_vfs_info_t *info = (gr_mount_vfs_info_t *)send_info;
CM_RETURN_IFERR(gr_put_int64(pack, (int64)info->dir));
return CM_SUCCESS;
}
static status_t gr_encode_query_file_num(gr_conn_t *conn, gr_packet_t *pack, void *send_info)
{
gr_query_file_num_info_t *info = (gr_query_file_num_info_t *)send_info;
CM_RETURN_IFERR(gr_put_int64(pack, (int64)info->dir));
return CM_SUCCESS;
}
static status_t gr_encode_query_file_info(gr_conn_t *conn, gr_packet_t *pack, void *send_info)
{
gr_query_file_num_info_t *info = (gr_query_file_num_info_t *)send_info;
CM_RETURN_IFERR(gr_put_int32(pack, info->is_continue));
CM_RETURN_IFERR(gr_put_int64(pack, (int64)info->dir));
return CM_SUCCESS;
}
static status_t gr_decode_stat_file(gr_packet_t *ack_pack, void *ack)
{
gr_stat_file_info_t *info = (gr_stat_file_info_t *)ack;
CM_RETURN_IFERR(gr_get_int64(ack_pack, &(info->offset)));
CM_RETURN_IFERR(gr_get_int64(ack_pack, &(info->size)));
CM_RETURN_IFERR(gr_get_int32(ack_pack, &(info->mode)));
CM_RETURN_IFERR(gr_get_str(ack_pack, &(info->expire_time)));
return CM_SUCCESS;
}
static status_t gr_decode_mount_vfs(gr_packet_t *ack_pack, void *ack)
{
gr_mount_vfs_info_t *info = (gr_mount_vfs_info_t *)ack;
CM_RETURN_IFERR(gr_get_int64(ack_pack, (int64*)&(info->dir)));
return CM_SUCCESS;
}
static status_t gr_decode_query_file_num(gr_packet_t *ack_pack, void *ack)
{
gr_query_file_num_info_t *info = (gr_query_file_num_info_t *)ack;
CM_RETURN_IFERR(gr_get_int32(ack_pack, (int32*)&(info->file_num)));
return CM_SUCCESS;
}
static status_t gr_decode_query_file_info(gr_packet_t *ack_pack, void *ack)
{
int32_t file_num = 0;
gr_file_item_t *info = (gr_file_item_t *)ack;
gr_file_item_t *tmp;
CM_RETURN_IFERR(gr_get_int32(ack_pack, &file_num));
for (uint32_t i = 0; i < file_num; i++) {
CM_RETURN_IFERR(gr_get_data(ack_pack, sizeof(gr_file_item_t), (void **)&tmp));
memcpy_s(&info[i], sizeof(gr_file_item_t), tmp, sizeof(gr_file_item_t));
}
return CM_SUCCESS;
}
static status_t gr_decode_write_file(gr_packet_t *ack_pack, void *ack)
{
int64 *info = (int64*)ack;
CM_RETURN_IFERR(gr_get_int64(ack_pack, info));
return CM_SUCCESS;
}
static status_t gr_decode_append_file(gr_packet_t *ack_pack, void *ack)
{
int64 *info = (int64*)ack;
CM_RETURN_IFERR(gr_get_int64(ack_pack, info));
return CM_SUCCESS;
}
static status_t gr_decode_read_file(gr_packet_t *ack_pack, void *ack)
{
text_t ack_info = CM_NULL_TEXT;
gr_read_file_info_t *info = (gr_read_file_info_t *)ack;
CM_RETURN_IFERR(gr_get_text(ack_pack, &ack_info));
info->rel_size = ack_info.len;
if (ack_info.len == 0) {
return CM_SUCCESS;
}
errno_t errcode = memcpy_s(info->buf, info->size, ack_info.str, ack_info.len);
if (errcode != EOK) {
GR_THROW_ERROR(ERR_GR_CLI_EXEC_FAIL, gr_get_cmd_desc(GR_CMD_READ_FILE), "get read file data error");
return CM_ERROR;
}
return CM_SUCCESS;
}
static status_t gr_decode_handshake(gr_packet_t *ack_pack, void *ack)
{
text_t ack_info = CM_NULL_TEXT;
CM_RETURN_IFERR(gr_get_text(ack_pack, &ack_info));
if (ack_info.len == 0 || ack_info.len >= GR_MAX_PATH_BUFFER_SIZE) {
GR_THROW_ERROR(ERR_GR_CLI_EXEC_FAIL, gr_get_cmd_desc(GR_CMD_HANDSHAKE), "get home info length error");
return CM_ERROR;
}
gr_get_server_info_t *output_info = (gr_get_server_info_t *)ack;
output_info->home = ack_info.str;
CM_RETURN_IFERR(gr_get_int32(ack_pack, (int32_t *)&output_info->objectid));
int32_t hash_auth_enable_int;
CM_RETURN_IFERR(gr_get_int32(ack_pack, &hash_auth_enable_int));
output_info->hash_auth_enable = (bool32)hash_auth_enable_int;
LOG_RUN_INF("[GR_CONNECT]Received HASH_AUTH_ENABLE=%d from server", output_info->hash_auth_enable);
return CM_SUCCESS;
}
static status_t gr_encode_exist(gr_conn_t *conn, gr_packet_t *pack, void *send_info)
{
return gr_put_str(pack, (const char *)send_info);
}
static status_t gr_decode_exist(gr_packet_t *ack_pack, void *ack)
{
gr_exist_recv_info_t *info = (gr_exist_recv_info_t *)ack;
if (gr_get_int32(ack_pack, &(info->result)) != CM_SUCCESS) {
GR_THROW_ERROR(ERR_GR_CLI_EXEC_FAIL, gr_get_cmd_desc(GR_CMD_EXIST), "get result data error");
LOG_RUN_ERR("get result data error.");
return CM_ERROR;
}
if (gr_get_int32(ack_pack, &(info->type)) != CM_SUCCESS) {
GR_THROW_ERROR(ERR_GR_CLI_EXEC_FAIL, gr_get_cmd_desc(GR_CMD_EXIST), "get type data error");
LOG_RUN_ERR("get type data error.");
return CM_ERROR;
}
return CM_SUCCESS;
}
static status_t gr_encode_getcfg(gr_conn_t *conn, gr_packet_t *pack, void *send_info)
{
return gr_put_str(pack, (const char *)send_info);
}
static status_t gr_decode_getcfg(gr_packet_t *ack_pack, void *ack)
{
text_t *info = (text_t *)ack;
if (gr_get_text(ack_pack, info) != CM_SUCCESS) {
GR_THROW_ERROR(ERR_GR_CLI_EXEC_FAIL, gr_get_cmd_desc(GR_CMD_GETCFG), "get cfg connect error");
return CM_ERROR;
}
if (info->len >= GR_MAX_PACKET_SIZE - sizeof(gr_packet_head_t) - sizeof(int32_t)) {
GR_THROW_ERROR(ERR_GR_CLI_EXEC_FAIL, gr_get_cmd_desc(GR_CMD_GETCFG), "get cfg length error");
return CM_ERROR;
}
return CM_SUCCESS;
}
static status_t gr_decode_get_inst_status(gr_packet_t *ack_pack, void *ack)
{
text_t *info = (text_t *)ack;
if (gr_get_text(ack_pack, info) != CM_SUCCESS) {
GR_THROW_ERROR(ERR_GR_CLI_EXEC_FAIL, gr_get_cmd_desc(GR_CMD_GET_INST_STATUS), "get inst status error");
return CM_ERROR;
}
if (info->len != sizeof(gr_server_status_t)) {
GR_THROW_ERROR(
ERR_GR_CLI_EXEC_FAIL, gr_get_cmd_desc(GR_CMD_GET_INST_STATUS), "get inst status length error");
return CM_ERROR;
}
return CM_SUCCESS;
}
static status_t gr_decode_get_time_stat(gr_packet_t *ack_pack, void *ack)
{
text_t *time_stat = (text_t *)ack;
if (gr_get_text(ack_pack, time_stat) != CM_SUCCESS) {
GR_THROW_ERROR(ERR_GR_CLI_EXEC_FAIL, gr_get_cmd_desc(GR_CMD_GET_TIME_STAT), "get time stat error");
return CM_ERROR;
}
return CM_SUCCESS;
}
static status_t gr_decode_get_disk_usage(gr_packet_t *ack_pack, void *ack)
{
gr_disk_usage_ack_t *info = (gr_disk_usage_ack_t *)ack;
if (gr_get_int64(ack_pack, &info->total_bytes) != CM_SUCCESS) {
GR_THROW_ERROR(ERR_GR_CLI_EXEC_FAIL, gr_get_cmd_desc(GR_CMD_GET_DISK_USAGE), "get total_bytes error");
return CM_ERROR;
}
if (gr_get_int64(ack_pack, &info->used_bytes) != CM_SUCCESS) {
GR_THROW_ERROR(ERR_GR_CLI_EXEC_FAIL, gr_get_cmd_desc(GR_CMD_GET_DISK_USAGE), "get used_bytes error");
return CM_ERROR;
}
if (gr_get_int64(ack_pack, &info->available_bytes) != CM_SUCCESS) {
GR_THROW_ERROR(ERR_GR_CLI_EXEC_FAIL, gr_get_cmd_desc(GR_CMD_GET_DISK_USAGE), "get available_bytes error");
return CM_ERROR;
}
if (gr_get_int64(ack_pack, (int64*)&info->usage_percent) != CM_SUCCESS) {
GR_THROW_ERROR(ERR_GR_CLI_EXEC_FAIL, gr_get_cmd_desc(GR_CMD_GET_DISK_USAGE), "get usage_percent error");
return CM_ERROR;
}
return CM_SUCCESS;
}
static status_t gr_encode_stat_file(gr_conn_t *conn, gr_packet_t *pack, void *send_info)
{
gr_stat_file_info_t *info = (gr_stat_file_info_t *)send_info;
CM_RETURN_IFERR(gr_put_str(pack, info->name));
return CM_SUCCESS;
}
static status_t gr_encode_write_file(gr_conn_t *conn, gr_packet_t *pack, void *send_info)
{
gr_write_file_info_t *info = (gr_write_file_info_t *)send_info;
CM_RETURN_IFERR(gr_put_int64(pack, info->offset));
CM_RETURN_IFERR(gr_put_int32(pack, info->handle));
CM_RETURN_IFERR(gr_put_int64(pack, info->size));
CM_RETURN_IFERR(gr_put_sha256(pack, info->hash));
CM_RETURN_IFERR(gr_put_data(pack, info->buf, info->size));
return CM_SUCCESS;
}
static status_t gr_encode_append_file(gr_conn_t *conn, gr_packet_t *pack, void *send_info)
{
gr_write_file_info_t *info = (gr_write_file_info_t *)send_info;
CM_RETURN_IFERR(gr_put_int32(pack, info->handle));
CM_RETURN_IFERR(gr_put_int64(pack, info->size));
CM_RETURN_IFERR(gr_put_sha256(pack, info->hash));
CM_RETURN_IFERR(gr_put_data(pack, info->buf, info->size));
return CM_SUCCESS;
}
static status_t gr_encode_read_file(gr_conn_t *conn, gr_packet_t *pack, void *send_info)
{
gr_read_file_info_t *info = (gr_read_file_info_t *)send_info;
CM_RETURN_IFERR(gr_put_int64(pack, info->offset));
CM_RETURN_IFERR(gr_put_int32(pack, info->handle));
CM_RETURN_IFERR(gr_put_int64(pack, info->size));
return CM_SUCCESS;
}
static status_t gr_encode_rename_file(gr_conn_t *conn, gr_packet_t *pack, void *send_info)
{
gr_rename_file_info_t *info = (gr_rename_file_info_t *)send_info;
CM_RETURN_IFERR(gr_put_str(pack, info->src));
CM_RETURN_IFERR(gr_put_str(pack, info->dst));
return CM_SUCCESS;
}
static status_t gr_encode_make_dir(gr_conn_t *conn, gr_packet_t *pack, void *send_info)
{
gr_make_dir_info_t *info = (gr_make_dir_info_t *)send_info;
CM_RETURN_IFERR(gr_put_str(pack, info->name));
return CM_SUCCESS;
}
static status_t gr_encode_remove_dir(gr_conn_t *conn, gr_packet_t *pack, void *send_info)
{
gr_remove_dir_info_t *info = (gr_remove_dir_info_t *)send_info;
CM_RETURN_IFERR(gr_put_str(pack, info->name));
CM_RETURN_IFERR(gr_put_int64(pack, info->attrFlag));
return CM_SUCCESS;
}
static status_t gr_encode_open_file(gr_conn_t *conn, gr_packet_t *pack, void *send_info)
{
gr_open_file_info_t *info = (gr_open_file_info_t *)send_info;
CM_RETURN_IFERR(gr_put_str(pack, info->file_path));
CM_RETURN_IFERR(gr_put_int32(pack, (uint32_t)info->flag));
return CM_SUCCESS;
}
static status_t gr_encode_close_file(gr_conn_t *conn, gr_packet_t *pack, void *send_info)
{
gr_close_file_info_t *info = (gr_close_file_info_t *)send_info;
CM_RETURN_IFERR(gr_put_int64(pack, info->fd));
CM_RETURN_IFERR(gr_put_int32(pack, info->need_lock));
return CM_SUCCESS;
}
static status_t gr_encode_create_file(gr_conn_t *conn, gr_packet_t *pack, void *send_info)
{
gr_create_file_info_t *info = (gr_create_file_info_t *)send_info;
CM_RETURN_IFERR(gr_put_str(pack, info->file_path));
CM_RETURN_IFERR(gr_put_int32(pack, info->flag));
return CM_SUCCESS;
}
static status_t gr_decode_create_file(gr_packet_t *ack_pack, void *ack)
{
CM_RETURN_IFERR(gr_get_sha256(ack_pack, (uint8_t *)ack));
return CM_SUCCESS;
}
static status_t gr_encode_delete_file(gr_conn_t *conn, gr_packet_t *pack, void *send_info)
{
gr_remove_file_info_t *info = (gr_remove_file_info_t *)send_info;
CM_RETURN_IFERR(gr_put_str(pack, info->name));
CM_RETURN_IFERR(gr_put_int64(pack, info->attrFlag));
return CM_SUCCESS;
}
static status_t gr_decode_open_file(gr_packet_t *ack_pack, void *ack)
{
gr_file_handle *file_handle = (gr_file_handle*)ack;
CM_RETURN_IFERR(gr_get_int32(ack_pack, &file_handle->fd));
CM_RETURN_IFERR(gr_get_sha256(ack_pack, file_handle->hash));
return CM_SUCCESS;
}
typedef status_t (*gr_encode_packet_proc_t)(gr_conn_t *conn, gr_packet_t *pack, void *send_info);
typedef status_t (*gr_decode_packet_proc_t)(gr_packet_t *ack_pack, void *ack);
typedef struct st_gr_packet_proc {
gr_encode_packet_proc_t encode_proc;
gr_decode_packet_proc_t decode_proc;
char *cmd_info;
} gr_packet_proc_t;
gr_packet_proc_t g_gr_packet_proc[GR_CMD_END] =
{
[GR_CMD_MKDIR] = {gr_encode_make_dir, NULL, "make dir"},
[GR_CMD_RMDIR] = {gr_encode_remove_dir, NULL, "remove dir"},
[GR_CMD_MOUNT_VFS] = {gr_encode_mount_vfs, gr_decode_mount_vfs, "mount vfs"},
[GR_CMD_UNMOUNT_VFS] = {gr_encode_unmount_vfs, NULL, "unmount vfs"},
[GR_CMD_QUERY_FILE_NUM] = {gr_encode_query_file_num, gr_decode_query_file_num, "query file num"},
[GR_CMD_QUERY_FILE_INFO] = {gr_encode_query_file_info, gr_decode_query_file_info, "query file info"},
[GR_CMD_OPEN_FILE] = {gr_encode_open_file, gr_decode_open_file, "open file"},
[GR_CMD_CLOSE_FILE] = {gr_encode_close_file, NULL, "close file"},
[GR_CMD_CREATE_FILE] = {gr_encode_create_file, gr_decode_create_file, "create file"},
[GR_CMD_DELETE_FILE] = {gr_encode_delete_file, NULL, "delete file"},
[GR_CMD_WRITE_FILE] = {gr_encode_write_file, gr_decode_write_file, "write file"},
[GR_CMD_APPEND_FILE] = {gr_encode_append_file, gr_decode_append_file, "append file"},
[GR_CMD_READ_FILE] = {gr_encode_read_file, gr_decode_read_file, "read file"},
[GR_CMD_RENAME_FILE] = {gr_encode_rename_file, NULL, "rename file"},
[GR_CMD_STAT_FILE] = {gr_encode_stat_file, gr_decode_stat_file, "stat file"},
[GR_CMD_STOP_SERVER] = {NULL, NULL, "stop server"},
[GR_CMD_SETCFG] = {gr_encode_setcfg, NULL, "setcfg"},
[GR_CMD_SET_MAIN_INST] = {NULL, NULL, "set main inst"},
[GR_CMD_POSTPONE_FILE_TIME] = {gr_encode_postpone_file_time, NULL, "postpone file expired time"},
[GR_CMD_HANDSHAKE] = {gr_encode_handshake, gr_decode_handshake, "handshake with server"},
[GR_CMD_EXIST] = {gr_encode_exist, gr_decode_exist, "exist"},
[GR_CMD_GETCFG] = {gr_encode_getcfg, gr_decode_getcfg, "getcfg"},
[GR_CMD_GET_INST_STATUS] = {NULL, gr_decode_get_inst_status, "get inst status"},
[GR_CMD_GET_TIME_STAT] = {NULL, gr_decode_get_time_stat, "get time stat"},
[GR_CMD_GET_DISK_USAGE] = {NULL, gr_decode_get_disk_usage, "get disk usage"},
[GR_CMD_RELOAD_CFG] = {NULL, NULL, "reload cfg"},
};
status_t gr_decode_packet(gr_packet_proc_t *make_proc, gr_packet_t *ack_pack, void *ack)
{
if (ack == NULL || make_proc->decode_proc == NULL) {
return CM_SUCCESS;
}
gr_init_get(ack_pack);
status_t ret = make_proc->decode_proc(ack_pack, ack);
GR_RETURN_IFERR2(ret, LOG_RUN_ERR("Decode %s msg failed", make_proc->cmd_info));
return ret;
}
status_t gr_msg_interact(gr_conn_t *conn, uint8 cmd, void *send_info, void *ack)
{
gr_packet_t *send_pack = &conn->pack;
gr_packet_t *ack_pack = &conn->pack;
gr_packet_proc_t *make_proc;
do {
gr_init_packet(&conn->pack, conn->pipe.options);
gr_init_set(&conn->pack, conn->proto_version);
send_pack->head->cmd = cmd;
send_pack->head->flags = 0;
make_proc = &g_gr_packet_proc[cmd];
if (make_proc->encode_proc != NULL) {
status_t ret = make_proc->encode_proc(conn, send_pack, send_info);
if (ret != CM_SUCCESS) {
LOG_RUN_ERR("Encode %s msg failed", make_proc->cmd_info);
return ret;
}
}
ack_pack = &conn->pack;
GR_RETURN_IF_ERROR(gr_call_ex(&conn->pipe, send_pack, ack_pack));
if (ack_pack->head->result != CM_SUCCESS) {
int32_t errcode = gr_get_pack_err(conn, ack_pack);
if (errcode == ERR_GR_VERSION_NOT_MATCH) {
continue;
}
return errcode;
}
break;
} while (1);
conn->server_version = gr_get_version(ack_pack);
conn->proto_version = MIN(GR_PROTO_VERSION, conn->server_version);
return gr_decode_packet(make_proc, ack_pack, ack);
}
void gr_clean_file_handle(gr_file_handle *file_handle)
{
file_handle->fd = -1;
file_handle->hash[0] = '\0';
file_handle->file_name[0] = '\0';
}
bool32 gr_get_conn_hash_auth_enable(gr_conn_t *conn)
{
if (conn == NULL) {
return CM_FALSE;
}
return conn->hash_auth_enable;
}
#ifdef __cplusplus
}
#endif