* This file is part of the openHiTLS project.
*
* openHiTLS is licensed under the 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.
*/
#include "hitls_build.h"
#ifdef HITLS_BSL_UIO_FILE
#include <stdio.h>
#include <string.h>
#include "bsl_sal.h"
#include "bsl_err_internal.h"
#include "bsl_errno.h"
#include "uio_base.h"
#include "uio_abstraction.h"
#include "sal_file.h"
#include "bsl_uio.h"
static int32_t FileWrite(BSL_UIO *uio, const void *buf, uint32_t len, uint32_t *writeLen)
{
bsl_sal_file_handle f = uio->ctx;
if (f == NULL) {
BSL_ERR_PUSH_ERROR(BSL_NULL_INPUT);
return BSL_NULL_INPUT;
}
*writeLen = 0;
if (len == 0) {
return BSL_SUCCESS;
}
int32_t ret = BSL_SAL_FileWrite(f, buf, 1, len);
if (ret != BSL_SUCCESS) {
BSL_ERR_PUSH_ERROR(BSL_UIO_FAIL);
return BSL_UIO_FAIL;
}
*writeLen = len;
return BSL_SUCCESS;
}
static int32_t FileRead(BSL_UIO *uio, void *buf, uint32_t len, uint32_t *readLen)
{
bsl_sal_file_handle f = uio->ctx;
if (f == NULL) {
BSL_ERR_PUSH_ERROR(BSL_NULL_INPUT);
return BSL_NULL_INPUT;
}
*readLen = 0;
size_t rLen;
int32_t ret = BSL_SAL_FileRead(f, buf, 1, len, &rLen);
if (ret != BSL_SUCCESS) {
BSL_ERR_PUSH_ERROR(BSL_UIO_FAIL);
return BSL_UIO_FAIL;
}
*readLen = (uint32_t)rLen;
return BSL_SUCCESS;
}
static int32_t FileDestroy(BSL_UIO *uio)
{
if (BSL_UIO_GetIsUnderlyingClosedByUio(uio)) {
bsl_sal_file_handle f = uio->ctx;
if (f != NULL) {
BSL_SAL_FileClose(f);
uio->ctx = NULL;
}
}
uio->init = false;
return BSL_SUCCESS;
}
static int32_t FileOpen(BSL_UIO *uio, uint32_t flags, const char *filename)
{
bsl_sal_file_handle f = uio->ctx;
if (f != NULL) {
if (BSL_UIO_GetIsUnderlyingClosedByUio(uio)) {
BSL_SAL_FileClose(f);
uio->ctx = NULL;
} else {
return BSL_UIO_EXIST_CONTEXT_NOT_RELEASED;
}
}
const char *mode = NULL;
bsl_sal_file_handle fileHandle = NULL;
if ((flags & BSL_UIO_FILE_APPEND) != 0) {
mode = ((flags & BSL_UIO_FILE_READ) != 0) ? "a+" : "a";
} else if ((flags & BSL_UIO_FILE_READ) != 0) {
mode = ((flags & BSL_UIO_FILE_WRITE) != 0) ? "r+" : "r";
} else if ((flags & BSL_UIO_FILE_WRITE) != 0) {
mode = "w";
} else {
BSL_ERR_PUSH_ERROR(BSL_UIO_FILE_OPEN_FAIL);
return BSL_UIO_FILE_OPEN_FAIL;
}
if (BSL_SAL_FileOpen(&fileHandle, filename, mode) != BSL_SUCCESS) {
BSL_ERR_PUSH_ERROR(BSL_UIO_FILE_OPEN_FAIL);
return BSL_UIO_FILE_OPEN_FAIL;
}
uio->ctx = fileHandle;
BSL_UIO_SetIsUnderlyingClosedByUio(uio, true);
uio->init = true;
return BSL_SUCCESS;
}
static int32_t FilePending(BSL_UIO *uio, int32_t larg, uint64_t *ret)
{
if (larg != sizeof(uint64_t)) {
return BSL_INVALID_ARG;
}
bsl_sal_file_handle f = uio->ctx;
if (f == NULL) {
BSL_ERR_PUSH_ERROR(BSL_NULL_INPUT);
return BSL_NULL_INPUT;
}
long current;
if (SAL_FileTell(f, ¤t) != BSL_SUCCESS) {
BSL_ERR_PUSH_ERROR(BSL_INTERNAL_EXCEPTION);
return BSL_INTERNAL_EXCEPTION;
}
if (SAL_FileSeek(f, 0, SAL_NET_SEEK_END) != BSL_SUCCESS) {
BSL_ERR_PUSH_ERROR(BSL_INTERNAL_EXCEPTION);
return BSL_INTERNAL_EXCEPTION;
}
long max;
if (SAL_FileTell(f, &max) != BSL_SUCCESS || max < current) {
(void)SAL_FileSeek(f, current, SAL_NET_SEEK_SET);
BSL_ERR_PUSH_ERROR(BSL_INTERNAL_EXCEPTION);
return BSL_INTERNAL_EXCEPTION;
}
*ret = (uint64_t)(max - current);
(void)SAL_FileSeek(f, current, SAL_NET_SEEK_SET);
return BSL_SUCCESS;
}
static int32_t FileWpending(int32_t larg, uint64_t *ret)
{
if (larg != sizeof(uint64_t)) {
return BSL_INVALID_ARG;
}
*ret = 0;
return BSL_SUCCESS;
}
static int32_t FileSetPtr(BSL_UIO *uio, int32_t isClosed, bsl_sal_file_handle fp)
{
if (isClosed != 0 && isClosed != 1) {
return BSL_INVALID_ARG;
}
bsl_sal_file_handle file = uio->ctx;
if (file != NULL) {
if (BSL_UIO_GetIsUnderlyingClosedByUio(uio)) {
BSL_SAL_FileClose(file);
uio->ctx = NULL;
} else {
return BSL_UIO_EXIST_CONTEXT_NOT_RELEASED;
}
}
uio->ctx = fp;
BSL_UIO_SetIsUnderlyingClosedByUio(uio, isClosed);
uio->init = true;
return BSL_SUCCESS;
}
static int32_t FileGetPtr(BSL_UIO *uio, bsl_sal_file_handle *fp)
{
bsl_sal_file_handle file = uio->ctx;
if (file != NULL) {
*fp = file;
}
return BSL_SUCCESS;
}
static int32_t FileReset(BSL_UIO *uio, int32_t larg, void *offset)
{
if (larg != sizeof(long)) {
BSL_ERR_PUSH_ERROR(BSL_INVALID_ARG);
return BSL_INVALID_ARG;
}
bsl_sal_file_handle f = uio->ctx;
if (f == NULL) {
BSL_ERR_PUSH_ERROR(BSL_NULL_INPUT);
return BSL_NULL_INPUT;
}
if (SAL_FileSeek(f, *(long *)offset, SAL_NET_SEEK_SET) != 0) {
BSL_ERR_PUSH_ERROR(BSL_INTERNAL_EXCEPTION);
return BSL_INTERNAL_EXCEPTION;
}
return BSL_SUCCESS;
}
static int32_t FileGetEof(BSL_UIO *uio, int32_t larg, bool *isEof)
{
if (larg != 1) {
return BSL_INVALID_ARG;
}
*isEof = false;
bsl_sal_file_handle f = (bsl_sal_file_handle)uio->ctx;
if (f == NULL) {
BSL_ERR_PUSH_ERROR(BSL_NULL_INPUT);
return BSL_NULL_INPUT;
}
if (feof((FILE*)f) != 0) {
*isEof = true;
}
return BSL_SUCCESS;
}
static int32_t FileFlush(BSL_UIO *uio)
{
bsl_sal_file_handle f = (bsl_sal_file_handle)uio->ctx;
if (f == NULL) {
BSL_ERR_PUSH_ERROR(BSL_NULL_INPUT);
return BSL_NULL_INPUT;
}
if (!SAL_Flush(f)) {
return BSL_UIO_IO_EXCEPTION;
}
return BSL_SUCCESS;
}
static int32_t FileTell(BSL_UIO *uio, int32_t larg, void *current)
{
if (larg != sizeof(long)) {
BSL_ERR_PUSH_ERROR(BSL_INVALID_ARG);
return BSL_INVALID_ARG;
}
bsl_sal_file_handle file = (bsl_sal_file_handle)uio->ctx;
if (file == NULL) {
BSL_ERR_PUSH_ERROR(BSL_NULL_INPUT);
return BSL_NULL_INPUT;
}
return SAL_FileTell(file, (long *)current);
}
static int32_t FileCtrl(BSL_UIO *uio, int32_t cmd, int32_t larg, void *parg)
{
if (larg < 0) {
BSL_ERR_PUSH_ERROR(BSL_UIO_FAIL);
return BSL_UIO_FAIL;
}
if (cmd == BSL_UIO_FLUSH) {
return FileFlush(uio);
}
if (cmd == BSL_UIO_RESET) {
long offset = 0;
return FileReset(uio, sizeof(long), &offset);
}
if (parg == NULL) {
BSL_ERR_PUSH_ERROR(BSL_NULL_INPUT);
return BSL_NULL_INPUT;
}
switch (cmd) {
case BSL_UIO_FILE_OPEN:
return FileOpen(uio, (uint32_t)larg, parg);
case BSL_UIO_PENDING:
return FilePending(uio, larg, parg);
case BSL_UIO_WPENDING:
return FileWpending(larg, parg);
case BSL_UIO_FILE_PTR:
return FileSetPtr(uio, larg, parg);
case BSL_UIO_FILE_GET_PTR:
return FileGetPtr(uio, parg);
case BSL_UIO_FILE_SEEK:
return FileReset(uio, larg, parg);
case BSL_UIO_FILE_GET_EOF:
return FileGetEof(uio, larg, parg);
case BSL_UIO_FILE_TELL:
return FileTell(uio, larg, parg);
default:
break;
}
BSL_ERR_PUSH_ERROR(BSL_UIO_FAIL);
return BSL_UIO_FAIL;
}
static int32_t FileGets(BSL_UIO *uio, char *buf, uint32_t *readLen)
{
bsl_sal_file_handle f = uio->ctx;
if (f == NULL) {
BSL_ERR_PUSH_ERROR(BSL_NULL_INPUT);
return BSL_NULL_INPUT;
}
(void)BSL_UIO_ClearFlags(uio, BSL_UIO_FLAGS_RWS | BSL_UIO_FLAGS_SHOULD_RETRY);
if (SAL_FGets(f, buf, (int32_t)*readLen) == NULL) {
*readLen = 0;
if (SAL_FileError(f) == false) {
return BSL_SUCCESS;
}
(void)BSL_UIO_SetFlags(uio, BSL_UIO_FLAGS_READ | BSL_UIO_FLAGS_SHOULD_RETRY);
BSL_ERR_PUSH_ERROR(BSL_UIO_FAIL);
return BSL_UIO_FAIL;
}
*readLen = (uint32_t)strlen(buf);
return BSL_SUCCESS;
}
static int32_t FilePuts(BSL_UIO *uio, const char *buf, uint32_t *writeLen)
{
return FileWrite(uio, buf, (uint32_t)strlen(buf), writeLen);
}
const BSL_UIO_Method *BSL_UIO_FileMethod(void)
{
static const BSL_UIO_Method METHOD = {
BSL_UIO_FILE,
FileWrite,
FileRead,
FileCtrl,
FilePuts,
FileGets,
NULL,
FileDestroy
};
return &METHOD;
}
#endif