OVMS3/OVMS.V3/components/wolfssh/wolfssh/port.h

1116 lines
33 KiB
C

/* port.h
*
* Copyright (C) 2014-2020 wolfSSL Inc.
*
* This file is part of wolfSSH.
*
* wolfSSH is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* wolfSSH is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with wolfSSH. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* The port module wraps standard C library functions with macros to
* cover portablility issues when building in environments that rename
* those functions. This module also provides local versions of some
* standard C library functions that are missing on some platforms.
*/
#ifndef _WOLFSSH_PORT_H_
#define _WOLFSSH_PORT_H_
#include <wolfssh/settings.h>
#include <wolfssh/log.h>
#ifdef __cplusplus
extern "C" {
#endif
#define PORT_DYNTYPE_STRING 500
/* This value needs to stay in sync with the actual value of DYNTYPE_STRING
* from internal.h. */
/* setup memory handling */
#ifndef WMALLOC_USER
#ifdef WOLFSSL_USER_SETTINGS
#include <wolfssl/wolfcrypt/settings.h>
#else
#include <wolfssl/options.h>
#endif
#include <wolfssl/wolfcrypt/types.h>
#define WMALLOC(s, h, t) XMALLOC(s, h, t)
#define WFREE(p, h, t) XFREE(p, h, t)
#define WREALLOC(p, n, h, t) XREALLOC(p, n, h, t)
#define wolfSSH_SetAllocators wolfSSL_SetAllocators
#endif /* WMALLOC_USER */
#ifndef WFGETS
#define WFGETS fgets
#endif
#ifndef WFPUTS
#define WFPUTS fputs
#endif
#ifndef WOLFSSH_HANDLE
/* handle for console to use during Linux console code translations */
#ifdef USE_WINDOWS_API
#define WOLFSSH_HANDLE HANDLE
#else
#define WOLFSSH_HANDLE int
#endif
#endif /* !WOLFSSH_HANDLE */
#ifdef NO_FILESYSTEM
#define WS_DELIM '/'
#elif defined(WOLFSSL_NUCLEUS)
#include "storage/nu_storage.h"
#define WFILE int
WOLFSSH_API int wfopen(WFILE**, const char*, const char*);
#define WFOPEN(f,fn,m) wfopen((f),(fn),(m))
#define WFCLOSE(f) NU_Close(*(f))
#define WFWRITE(b,x,s,f) ((s) != 0)? NU_Write(*(f),(const CHAR*)(b),(s)): 0
#define WFREAD(b,x,s,f) NU_Read(*(f),(CHAR*)(b),(s))
#define WFSEEK(s,o,w) NU_Seek(*(s),(o),(w))
#define WFTELL(s) NU_Seek(*(s), 0, PSEEK_CUR)
#define WREWIND(s) NU_Seek(*(s), 0, PSEEK_SET)
#define WSEEK_END PSEEK_END
#define WS_DELIM '\\'
#define WOLFSSH_O_RDWR PO_RDWR
#define WOLFSSH_O_RDONLY PO_RDONLY
#define WOLFSSH_O_WRONLY PO_WRONLY
#define WOLFSSH_O_APPEND PO_APPEND
#define WOLFSSH_O_CREAT PO_CREAT
#define WOLFSSH_O_TRUNC PO_TRUNC
#define WOLFSSH_O_EXCL PO_EXCL
#ifndef WOPEN
static inline int wOpen(const char* f, short flag, short mode)
{
/* @TODO could use PS_IWRITE only or PS_IREAD only? */
return NU_Open(f, PO_TEXT | flag, (PS_IWRITE | PS_IREAD));
}
#define WOPEN(f,m,p) wOpen((f),(m),(p))
#endif
#define WCLOSE(fd) NU_Close((fd))
static inline int wChmod(const char* f, int mode) {
unsigned char atr = 0;
if (f == NULL) {
return -1;
}
if (NU_Get_Attributes(&atr, f) != NU_SUCCESS) {
return -1;
}
/* Set attribute value */
atr = atr & 0xF0; /* clear first byte */
if (mode == 0x124) {
atr |= ARDONLY; /* set read only value */
}
else {
/* if not setting read only set to normal */
atr |= ANORMAL;
}
if (NU_Set_Attributes(f, atr) != NU_SUCCESS) {
return -1;
}
else {
return 0;
}
}
#define WCHMOD(fs,f,m) wChmod((f),(m))
#elif defined(FREESCALE_MQX)
/* Freescale MQX 4.2 (Classic) */
#include "mfs.h"
#include "mqx.h"
#include "fio.h"
#include "rtcs.h"
#define WFILE MQX_FILE
#define WOLFSSH_MAX_FILENAME PATHNAME_SIZE
/* default to "a:" drive, user can override */
#ifndef MQX_MFS_DEVICE
#define MQX_MFS_DEVICE "a:"
#endif
WOLFSSH_API int wfopen(WFILE**, const char*, const char*);
#define WFOPEN(f,fn,m) wfopen((f),(fn),(m))
#define WFCLOSE(f) fclose((f))
#define WFREAD(b,s,a,f) fread((b),(s),(a),(f))
#define WFWRITE(b,x,s,f) fwrite((b),(x),(s),(f))
#define WFSEEK(s,o,w) fseek((s),(o),(w))
#define WFTELL(s) ftell((s))
#define WREWIND(s) fseek((s), 0, IO_SEEK_SET)
#define WSEEK_END IO_SEEK_END
#define WBADFILE NULL
static inline int wChmod(void* fs, const char* f, int mode)
{
int err;
MQX_FILE_PTR mfs_ptr;
MFS_FILE_ATTR_PARAM attr;
unsigned char attribute = 0;
if (fs == NULL || f == NULL) {
return -1;
}
mfs_ptr = (MQX_FILE_PTR)fs;
attr.ATTRIBUTE_PTR = &attribute;
attr.PATHNAME = (char*)f;
/* check that filesystem handle is valid */
if (_io_is_fs_valid(mfs_ptr) == 0) {
WLOG(WS_LOG_SFTP, "Invalid file system pointer");
return -1;
}
/* get file attributes */
err = ioctl(mfs_ptr, IO_IOCTL_GET_FILE_ATTR, (uint32_t*)&attr);
if (err != MFS_NO_ERROR) {
WLOG(WS_LOG_SFTP, "Unable to get file attributes");
return -1;
}
/* set file attributes */
if (mode == 0x124) {
/* set read only value */
attribute |= MFS_ATTR_READ_ONLY;
err = ioctl(mfs_ptr, IO_IOCTL_SET_FILE_ATTR, (uint32_t*)&attr);
if (err != MFS_NO_ERROR) {
WLOG(WS_LOG_SFTP, "Unable to set file attributes");
return -1;
}
}
return 0;
}
#define WCHMOD(fs,f,m) wChmod((fs),(f),(m))
#else
#include <stdlib.h>
#if !defined(_WIN32_WCE) && !defined(FREESCALE_MQX)
#include <stdio.h>
#endif
#define WFILE FILE
WOLFSSH_API int wfopen(WFILE**, const char*, const char*);
#define WFOPEN(f,fn,m) wfopen((f),(fn),(m))
#define WFCLOSE(f) fclose(f)
#define WFREAD(b,s,a,f) fread((b),(s),(a),(f))
#define WFWRITE(b,s,a,f) fwrite((b),(s),(a),(f))
#define WFSEEK(s,o,w) fseek((s),(o),(w))
#define WFTELL(s) ftell((s))
#define WREWIND(s) rewind((s))
#define WSEEK_END SEEK_END
#define WBADFILE NULL
#ifdef WOLFSSL_VXWORKS
#define WUTIMES(f,t) (WS_SUCCESS)
#else
#define WUTIMES(f,t) utimes((f),(t))
#endif
#ifndef USE_WINDOWS_API
#define WCHMOD(fs,f,m) chmod((f),(m))
#else
#define WCHMOD(fs,f,m) _chmod((f),(m))
#endif
#if (defined(WOLFSSH_SCP) || defined(WOLFSSH_SFTP)) && \
!defined(WOLFSSH_SCP_USER_CALLBACKS)
#ifdef USE_WINDOWS_API
WOLFSSH_LOCAL void* WS_CreateFileA(const char* fileName,
unsigned long desiredAccess, unsigned long shareMode,
unsigned long creationDisposition, unsigned long flags,
void* heap);
WOLFSSH_LOCAL void* WS_FindFirstFileA(const char* fileName,
char* realFileName, size_t realFileNameSz, int* isDir,
void* heap);
WOLFSSH_LOCAL int WS_FindNextFileA(void* findHandle,
char* realFileName, size_t realFileNameSz);
WOLFSSH_LOCAL int WS_GetFileAttributesExA(const char* fileName,
void* fileInfo, void* heap);
WOLFSSH_LOCAL int WS_RemoveDirectoryA(const char* dirName,
void* heap);
WOLFSSH_LOCAL int WS_CreateDirectoryA(const char* dirName,
void* heap);
WOLFSSH_LOCAL int WS_MoveFileA(const char* oldName,
const char* newName, void* heap);
WOLFSSH_LOCAL int WS_DeleteFileA(const char* fileName,
void* heap);
#ifndef _WIN32_WCE
#include <direct.h>
#define WCHDIR(p) _chdir((p))
#define WMKDIR(fs,p,m) _mkdir((p))
#endif
#else
#include <unistd.h>
#include <sys/stat.h>
#define WCHDIR(p) chdir((p))
#ifdef WOLFSSL_VXWORKS
#define WMKDIR(fs,p,m) mkdir((p))
#else
#define WMKDIR(fs,p,m) mkdir((p),(m))
#endif
#endif
#endif
#endif
/* setup string handling */
#ifndef WSTRING_USER
#ifdef WOLFSSL_VXWORKS
#include <strings.h>
#else
#include <string.h>
#endif
#define WMEMCPY(d,s,l) memcpy((d),(s),(l))
#define WMEMSET(b,c,l) memset((b),(c),(l))
#define WMEMCMP(s1,s2,n) memcmp((s1),(s2),(n))
#define WMEMMOVE(d,s,l) memmove((d),(s),(l))
#define WSTRLEN(s1) strlen((s1))
#define WSTRSTR(s1,s2) strstr((s1),(s2))
#define WSTRNCMP(s1,s2,n) strncmp((s1),(s2),(n))
#define WSTRSPN(s1,s2) strspn((s1),(s2))
#define WSTRCSPN(s1,s2) strcspn((s1),(s2))
/* for these string functions use internal versions */
WOLFSSH_API char* wstrnstr(const char*, const char*, unsigned int);
WOLFSSH_API char* wstrncat(char*, const char*, size_t);
WOLFSSL_API char* wstrdup(const char*, void*, int);
#define WSTRNSTR(s1,s2,n) wstrnstr((s1),(s2),(n))
#define WSTRNCAT(s1,s2,n) wstrncat((s1),(s2),(n))
#define WSTRDUP(s,h,t) wstrdup((s),(h),(t))
#ifdef USE_WINDOWS_API
#define WSTRNCPY(s1,s2,n) strncpy_s((s1),(n),(s2),(n))
#define WSTRNCASECMP(s1,s2,n) _strnicmp((s1),(s2),(n))
#define WSNPRINTF(s,n,f,...) _snprintf_s((s),(n),(n),(f),##__VA_ARGS__)
#define WVSNPRINTF(s,n,f,...) _vsnprintf_s((s),(n),(n),(f),##__VA_ARGS__)
#define WSTRTOK(s1,s2,s3) strtok_s((s1),(s2),(s3))
#elif defined(MICROCHIP_MPLAB_HARMONY) || defined(MICROCHIP_PIC32)
#include <stdio.h>
#define WSTRNCPY(s1,s2,n) strncpy((s1),(s2),(n))
#define WSTRNCASECMP(s1, s2, n) strncmp((s1), (s2), (n))
#define WSNPRINTF(s,n,f,...) snprintf((s),(n),(f),##__VA_ARGS__)
#define WVSNPRINTF(s,n,f,...) vsnprintf((s),(n),(f),##__VA_ARGS__)
#define WSTRTOK(s1,s2,s3) strtok_r((s1),(s2),(s3))
#elif defined(RENESAS_CSPLUS)
#include <stdio.h>
#define WSTRNCPY(s1,s2,n) strncpy((s1),(s2),(n))
#define WSTRNCASECMP(s1,s2,n) strncasecmp((s1),(s2),(n))
#define WSNPRINTF(s,n,f,...) snprintf((s),(n),(f),__VA_ARGS__)
#define WVSNPRINTF(s,n,f,...) vsnprintf((s),(n),(f),__VA_ARGS__)
#define WSTRTOK(s1,s2,s3) strtok_r((s1),(s2),(s3))
#else
#ifndef FREESCALE_MQX
#include <stdio.h>
#endif
#define WSTRNCPY(s1,s2,n) strncpy((s1),(s2),(n))
#define WSTRNCASECMP(s1,s2,n) strncasecmp((s1),(s2),(n))
#define WSNPRINTF(s,n,f,...) snprintf((s),(n),(f),##__VA_ARGS__)
#define WVSNPRINTF(s,n,f,...) vsnprintf((s),(n),(f),##__VA_ARGS__)
#define WSTRTOK(s1,s2,s3) strtok_r((s1),(s2),(s3))
#endif
#endif /* WSTRING_USER */
/* get local time for debug print out */
#ifdef USE_WINDOWS_API
#define WTIME time
#define WLOCALTIME(c,r) (localtime_s((r),(c))==0)
#elif defined(MICROCHIP_MPLAB_HARMONY)
#define WTIME XTIME
#define WLOCALTIME(c,r) (localtime((c)) != NULL && \
WMEMCPY((r), localtime((c)), sizeof(struct tm)))
#elif defined(FREESCALE_MQX)
static inline time_t mqx_time(time_t* timer)
{
time_t localTime;
TIME_STRUCT time_s;
if (timer == NULL)
timer = &localTime;
_time_get(&time_s);
*timer = (time_t)time_s.SECONDS;
return *timer;
}
#define WTIME(t1) mqx_time((t1))
#define WLOCALTIME(c,r) (localtime_r((c),(r))!=NULL)
#define WOLFSSH_NO_TIMESTAMP /* no strftime() */
#else
#define WTIME time
#define WLOCALTIME(c,r) (localtime_r((c),(r))!=NULL)
#endif
#if (defined(WOLFSSH_SFTP) || defined(WOLFSSH_SCP)) && \
!defined(NO_WOLFSSH_SERVER) && !defined(NO_FILESYSTEM)
#ifndef SIZEOF_OFF_T
/* if not using autoconf then make a guess on off_t size based on sizeof
* long long */
#if defined(SIZEOF_LONG) && SIZEOF_LONG == 8
#define SIZEOF_OFF_T 8
#else
#define SIZEOF_OFF_T 4
#endif
#endif
#ifdef WOLFSSL_NUCLEUS
#define WSTAT_T struct stat
#define WRMDIR(fs,d) (NU_Remove_Dir((d)) == NU_SUCCESS)?0:1
#define WMKDIR(fs,d,m) (NU_Make_Dir((d)) == NU_SUCCESS)?0:1
#define WSTAT(p,b) NU_Get_First((b),(p))
#define WLSTAT(p,b) NU_Get_First((b),(p))
#define WREMOVE(fs,d) NU_Delete((d))
#ifndef WS_MAX_RENAME_BUF
#define WS_MAX_RENAME_BUF 256
#endif
static inline int wRename(char* o, char* n)
{
int ret;
if (o == NULL || n == NULL) {
return NUF_BADPARM;
}
ret = NU_Rename(o, n);
/* try to handle case of from one drive to another */
if (ret == NUF_BADPARM && o[0] != n[0]) {
WFILE* fOld;
WFILE* fNew;
unsigned char buf[WS_MAX_RENAME_BUF];
if ((ret = WFOPEN(&fOld, o, "rb")) != 0) {
return ret;
}
if ((ret = WFOPEN(&fNew, n, "rwb")) != 0) {
WFCLOSE(fOld);
return ret;
}
/* read from the file in chunks and write chunks to new file */
do {
ret = WFREAD(buf, 1, WS_MAX_RENAME_BUF, fOld);
if (ret > 0) {
if ((WFWRITE(buf, 1, ret, fNew)) != ret) {
WFCLOSE(fOld);
WFCLOSE(fNew);
WREMOVE(NULL, n);
return NUF_BADPARM;
}
}
} while (ret > 0);
if (WFTELL(fOld) == WFSEEK(fOld, 0, WSEEK_END)) {
/* wrote everything from file */
WFCLOSE(fOld);
WREMOVE(NULL, o);
WFCLOSE(fNew);
}
else {
/* unable to write everything to file */
WFCLOSE(fNew);
WREMOVE(NULL, n);
WFCLOSE(fOld);
return NUF_BADPARM;
}
return 0;
}
/* not special case so just return value from NU_Rename */
return ret;
}
#define WRENAME(fs,o,n) wRename((o),(n))
#define WFD int
#ifndef WGETCWD
static inline char* wGetCwd(char* buf, unsigned int bufSz)
{
int ret;
MNT_LIST_S* list = NU_NULL;
if (buf == NULL || bufSz < 3) {
return NULL;
}
ret = NU_List_Mount(&list);
if (ret != NU_SUCCESS) {
return NULL;
}
buf[0] = list->mnt_name[0];
buf[1] = ':';
buf[2] = '\0';
return buf;
}
#define WGETCWD(fs,r,rSz) wGetCwd((r),(rSz))
#endif
#ifndef WPWRITE
static inline int wPwrite(WFD fd, unsigned char* buf, unsigned int sz,
const unsigned int* shortOffset)
{
INT32 ofst = shortOffset[0];
if (ofst > 0) {
NU_Seek(fd, ofst, 0);
}
return NU_Write(fd, (const CHAR*)buf, sz);
}
#define WPWRITE(fd,b,s,o) wPwrite((fd),(b),(s),(o))
#endif
#ifndef WPREAD
static inline int wPread(WFD fd, unsigned char* buf, unsigned int sz,
const unsigned int* shortOffset)
{
INT32 ofst = shortOffset[0];
if (ofst > 0) {
NU_Seek(fd, ofst, 0);
}
return NU_Read(fd, (CHAR*)buf, sz);
}
#define WPREAD(fd,b,s,o) wPread((fd),(b),(s),(o))
#endif
static inline int wUtimes(const char* f, struct timeval t[2])
{
DSTAT stat;
int ret = -1;
if (NU_Get_First(&stat, f) == NU_SUCCESS) {
ret = NU_Utime(&stat, 0xFFFF, t[0].tv_sec, 0xFFFF, t[1].tv_sec,
0xFFFF, 0xFFFF);
NU_Done(&stat);
if (ret == NU_SUCCESS) {
ret = 0;
}
else {
ret = -1;
}
}
return ret;
}
#define WUTIMES(f,t) wUtimes((f), (t))
#ifndef NO_WOLFSSH_DIR
#define WDIR DSTAT
#ifndef WOPENDIR
static inline int wOpenDir(WDIR* d, const char* dir)
{
int ret;
int idx = WSTRLEN(dir);
char tmp[256]; /* default max file name size */
/* handle special case at "/" to list all drives */
if (idx < 3 && dir[0] == WS_DELIM) {
d->fsize = 0; /* used to count number of drives */
return NU_SUCCESS;
}
if (idx < 3) {
return -1;
}
memcpy(tmp, dir, idx);
if (tmp[idx - 1] == '.') {
tmp[idx - 1] = '*';
}
else {
/* if opening a directory then make sure pattern '/' '*' is used */
unsigned char atrib = 0;
if (NU_Get_Attributes(&atrib, dir) == NU_SUCCESS) {
if (atrib & ADIRENT) {
if (tmp[idx-1] != WS_DELIM) {
if (idx + 2 > sizeof(tmp)) {
/* not enough space */
return -1;
}
tmp[idx++] = WS_DELIM;
tmp[idx++] = '*';
}
}
}
}
if (tmp[idx - 1] == WS_DELIM) {
if (idx + 1 > sizeof(tmp)) {
/* not enough space */
return -1;
}
tmp[idx++] = '*';
}
tmp[idx] = '\0';
ret = NU_Get_First(d, tmp);
/* if back to root directory i.e. A:/ then handle case
* where file system has nothing in it. */
if (dir[idx - 3] == ':' && ret == NUF_NOFILE) {
memset(d, 0, sizeof(WDIR));
ret = NU_SUCCESS;
}
if (ret == NU_SUCCESS) {
return 0;
}
return -1;
}
#define WOPENDIR(fs,h,c,d) wOpenDir((c),(d))
#endif
#define WCLOSEDIR(d) NU_Done((d))
#define WREADDIR(d) (NU_Get_Next((d)) == NU_SUCCESS)?(d):NULL
#endif /* NO_WOLFSSH_DIR */
#elif defined(FREESCALE_MQX)
/* Freescale MQX 4.2 (Classic)
* TODO for SCP support:
* - implement WUTIMES / wUtimes
* - implement WREADDIR() */
#define WFD MQX_FILE_PTR
#define WS_DELIM '/'
#ifndef MQX_DEFAULT_SFTP_NAME_SZ
#define MQX_DEFAULT_SFTP_NAME_SZ 256
#endif
/* flags can be accessed through MQX_FILE_PTR->FLAGS & IO_O_RDONLY */
/* these are from io.h */
#define WOLFSSH_O_RDWR IO_O_RDWR /* not used? */
#define WOLFSSH_O_RDONLY IO_O_RDONLY
#define WOLFSSH_O_WRONLY IO_O_WRONLY /* not used? */
#define WOLFSSH_O_APPEND IO_O_APPEND /* not used? */
#define WOLFSSH_O_CREAT IO_O_CREAT /* not used? */
#define WOLFSSH_O_TRUNC IO_O_TRUNC /* not used? */
#define WOLFSSH_O_EXCL IO_O_EXCL /* not used? */
#ifndef WOPEN
static inline WFD wOpen(const char* f, int flag, unsigned int per)
{
char* mode;
/* translate open() flags to fopen() mode */
if (flag & WOLFSSH_O_RDONLY) {
mode = "r";
} else if (flag & WOLFSSH_O_RDWR) {
if ((flag & WOLFSSH_O_CREAT) &&
(flag & WOLFSSH_O_TRUNC)) {
mode = "w+";
} else if ((flag & WOLFSSH_O_CREAT) &&
(flag & WOLFSSH_O_APPEND)) {
mode = "a+";
} else {
mode = "r+";
}
} else if (flag & WOLFSSH_O_WRONLY) {
if ((flag & WOLFSSH_O_CREAT) &&
(flag & WOLFSSH_O_TRUNC)) {
mode = "w";
} else if ((flag & WOLFSSH_O_CREAT) &&
(flag & WOLFSSH_O_APPEND)) {
mode = "a";
}
} else {
return NULL;
}
return fopen(f, mode);
}
#define WOPEN(f,m,p) wOpen((f),(m),(p))
#endif
#ifndef WRMDIR
static inline int wRmDir(void* fs, const char* path)
{
MQX_FILE_PTR mfs_ptr;
uint32_t err;
if (fs == NULL || path == NULL) {
return -1;
}
mfs_ptr = (MQX_FILE_PTR)fs;
/* check that filesystem handle is valid */
if (_io_is_fs_valid(mfs_ptr) == 0) {
WLOG(WS_LOG_SFTP, "Invalid file system pointer");
return -1;
}
/* try to delete subdirectory */
err = ioctl(mfs_ptr, IO_IOCTL_REMOVE_SUBDIR, (uint32_t*)path);
if (err != MFS_NO_ERROR) {
return -1;
}
return 0;
}
#define WRMDIR(fs,d) wRmDir((fs),(d))
#endif /* WRMDIR */
#ifndef WMKDIR
static inline int wMkDir(void* fs, const char* path)
{
MQX_FILE_PTR mfs_ptr;
uint32_t err;
if (fs == NULL || path == NULL) {
return -1;
}
mfs_ptr = (MQX_FILE_PTR)fs;
/* check that filesystem handle is valid */
if (_io_is_fs_valid(mfs_ptr) == 0) {
WLOG(WS_LOG_SFTP, "Invalid file system pointer");
return -1;
}
/* try to create subdirectory */
err = ioctl(mfs_ptr, IO_IOCTL_CREATE_SUBDIR, (uint32_t*)path);
if (err != MFS_NO_ERROR) {
return -1;
}
return 0;
}
#define WMKDIR(fs,d,m) wMkDir((fs),(d))
#endif /* WMKDIR */
#ifndef WREMOVE
static inline int wRemove(void* fs, const char* path)
{
MQX_FILE_PTR mfs_ptr;
uint32_t err;
if (fs == NULL || path == NULL) {
return -1;
}
mfs_ptr = (MQX_FILE_PTR)fs;
/* check that filesystem handle is valid */
if (_io_is_fs_valid(mfs_ptr) == 0) {
WLOG(WS_LOG_SFTP, "Invalid file system pointer");
return -1;
}
/* try to create subdirectory */
err = ioctl(mfs_ptr, IO_IOCTL_DELETE_FILE, (uint32_t*)path);
if (err != MFS_NO_ERROR) {
return -1;
}
return 0;
}
#define WREMOVE(fs,d) wRemove((fs),(d))
#endif /* WREMOVE */
#ifndef WRENAME
static inline int wRename(void* fs, const char* oldpath,
const char* newpath)
{
int err;
MQX_FILE_PTR mfs_ptr;
MFS_RENAME_PARAM rename;
if (fs == NULL || oldpath == NULL || newpath == NULL) {
return -1;
}
mfs_ptr = (MQX_FILE_PTR)fs;
/* check that filesystem handle is valid */
if (_io_is_fs_valid(mfs_ptr) == 0) {
WLOG(WS_LOG_SFTP, "Invalid file system pointer");
return -1;
}
rename.OLD_PATHNAME = (char*)oldpath;
rename.NEW_PATHNAME = (char*)newpath;
/* try to create subdirectory */
err = ioctl(mfs_ptr, IO_IOCTL_RENAME_FILE, (uint32_t*)&rename);
if (err != MFS_NO_ERROR) {
return -1;
}
return 0;
}
#define WRENAME(fs,o,n) wRename((fs),(o),(n))
#endif /* WRENAME */
#ifndef WGETCWD
static inline char* wGetCwd(void* fs, char* buf, unsigned int bufSz)
{
MQX_FILE_PTR mfs_ptr;
int err, dirSz, labelSz;
if (buf == NULL || bufSz == 0) {
return NULL;
}
if (fs == NULL) {
WLOG(WS_LOG_SFTP, "Must set MFS file system handle with "
"wolfSSH_SetFilesystemHandle()");
return NULL;
}
mfs_ptr = (MQX_FILE_PTR)fs;
/* check that filesystem handle is valid */
if (_io_is_fs_valid(mfs_ptr) == 0) {
WLOG(WS_LOG_SFTP, "Invalid file system pointer");
return NULL;
}
/* check bufSz against MFS path size */
if (bufSz < PATHNAME_SIZE) {
WLOG(WS_LOG_SFTP, "Buf size smaller than max MFS path size");
return NULL;
}
/* try to get current directory */
err = ioctl(mfs_ptr, IO_IOCTL_GET_CURRENT_DIR, (uint32_t*)buf);
if (err != MFS_NO_ERROR) {
return NULL;
}
/* add drive to beginning of path */
dirSz = WSTRLEN(buf);
labelSz = WSTRLEN(MQX_MFS_DEVICE);
if (dirSz + labelSz + 1 > bufSz) {
WLOG(WS_LOG_SFTP, "Buffer too small to prepend drive label");
return NULL;
}
WMEMMOVE(buf + labelSz, buf, dirSz);
WMEMCPY(buf, MQX_MFS_DEVICE, labelSz);
buf[labelSz + dirSz] = '\0';
/* remove trailing '\' if present */
if (buf[labelSz + dirSz - 1] == '\\') {
buf[labelSz + dirSz - 1] = '\0';
}
return buf;
}
#define WGETCWD(fs,r,rSz) wGetCwd((fs),(r),(rSz))
#endif /* WGETCWD */
#define WCLOSE fclose
#ifndef WPWRITE
static inline int wPwrite(WFD fd, unsigned char* buf, unsigned int sz,
const unsigned int* shortOffset)
{
unsigned int ofst;
ofst = shortOffset[0];
if (ofst > 0) {
fseek(fd, ofst, 0);
}
return fwrite(buf, sz, 1, fd);
}
#define WPWRITE(fd,b,s,o) wPwrite((fd),(b),(s),(o))
#endif
#ifndef WPREAD
static inline int wPread(WFD fd, unsigned char* buf, unsigned int sz,
const unsigned int* shortOffset)
{
unsigned int ofst;
ofst = shortOffset[0];
if (ofst > 0) {
fseek(fd, ofst, 0);
}
return fread(buf, 1, sz, fd);
}
#define WPREAD(fd,b,s,o) wPread((fd),(b),(s),(o))
#endif
#ifndef NO_WOLFSSH_DIR
typedef struct {
void* dirStruct; /* MFS DIR_STRUCT_PTR */
char pathname[PATHNAME_SIZE];
void* heap;
} MQXDIR;
#define WDIR MQXDIR*
#ifndef WOPENDIR
static inline int wOpenDir(void* fs, void* heap, WDIR* d, char* dir)
{
int pathSz;
MQXDIR* mqxdir;
MQX_FILE_PTR mfs_ptr;
void* dir_ptr;
char* mode_ptr = "f";
if (fs == NULL || d == NULL || dir == NULL) {
return -1;
}
mfs_ptr = (MQX_FILE_PTR)fs;
/* check that filesystem handle is valid */
if (_io_is_fs_valid(mfs_ptr) == 0) {
WLOG(WS_LOG_SFTP, "Invalid file system pointer");
return -1;
}
/* allocate MQXDIR struct to hold handle and modified pathname */
mqxdir = (MQXDIR*)WMALLOC(sizeof(MQXDIR), mqxdir->heap,
DYNTYPE_SFTP);
if (mqxdir == NULL) {
WLOG(WS_LOG_SFTP, "Unable to allocate MQXDIR in wOpenDir");
return -1;
}
WMEMSET(mqxdir, 0, sizeof(MQXDIR));
mqxdir->heap = heap;
/* copy dir to pathname */
pathSz = WSTRLEN(dir);
if (pathSz > sizeof(mqxdir->pathname)) {
WLOG(WS_LOG_SFTP, "dir name too large for buffer");
WFREE(mqxdir, mqxdir->heap, DYNTYPE_SFTP);
return -1;
}
WMEMCPY(mqxdir->pathname, dir, pathSz);
/* remove trailing '.' */
if (mqxdir->pathname[pathSz-1] == '.' &&
mqxdir->pathname[pathSz-2] != '.') {
mqxdir->pathname[pathSz-1] = '\0';
pathSz--;
}
/* add trailing delimiter if not present */
if (mqxdir->pathname[pathSz-1] != WS_DELIM) {
if (pathSz + 2 > sizeof(mqxdir->pathname)) {
WFREE(mqxdir, mqxdir->heap, DYNTYPE_SFTP);
return -1;
}
mqxdir->pathname[pathSz] = WS_DELIM;
mqxdir->pathname[pathSz + 1] = '\0';
}
dir_ptr = _io_mfs_dir_open(mfs_ptr, mqxdir->pathname, mode_ptr);
if (dir_ptr == NULL) {
WLOG(WS_LOG_SFTP, "MFS file not found");
WFREE(mqxdir, mqxdir->heap, DYNTYPE_SFTP);
return -1;
}
mqxdir->dirStruct = dir_ptr;
*d = mqxdir;
return 0;
}
#define WOPENDIR(fs,h,c,d) wOpenDir((fs),(h),(c),(d))
#endif
#ifndef WCLOSEDIR
static inline int wCloseDir(WDIR* d)
{
MQXDIR* mqxdir = NULL;
if (d != NULL) {
mqxdir = *d;
_io_mfs_dir_close(mqxdir->dirStruct);
WFREE(mqxdir, mqxdir->heap, DYNTYPE_SFTP);
}
return 0;
}
#define WCLOSEDIR(d) wCloseDir((d))
#endif /* WCLOSEDIR */
#endif /* NO_WOLFSSH_DIR */
#elif defined(USE_WINDOWS_API)
#include <windows.h>
#ifndef _WIN32_WCE
#include <sys/types.h>
#include <sys/stat.h>
#include <io.h>
#include <direct.h>
#include <fcntl.h>
#endif
#define WSTAT_T struct _stat
#define WRMDIR(fs,d) _rmdir((d))
#define WSTAT(p,b) _stat((p),(b))
#define WLSTAT(p,b) _stat((p),(b))
#define WREMOVE(fs,d) remove((d))
#define WRENAME(fs,o,n) rename((o),(n))
#define WGETCWD(fs,r,rSz) _getcwd((r),(rSz))
#define WOPEN(f,m,p) _open((f),(m),(p))
#define WCLOSE(fd) _close((fd))
#define WFD int
int wPwrite(WFD, unsigned char*, unsigned int, const unsigned int*);
int wPread(WFD, unsigned char*, unsigned int, const unsigned int*);
#define WPWRITE(fd,b,s,o) wPwrite((fd),(b),(s),(o))
#define WPREAD(fd,b,s,o) wPread((fd),(b),(s),(o))
#define WS_DELIM '\\'
#define WOLFSSH_O_RDWR _O_RDWR
#define WOLFSSH_O_RDONLY _O_RDONLY
#define WOLFSSH_O_WRONLY _O_WRONLY
#define WOLFSSH_O_APPEND _O_APPEND
#define WOLFSSH_O_CREAT _O_CREAT
#define WOLFSSH_O_TRUNC _O_TRUNC
#define WOLFSSH_O_EXCL _O_EXCL
#ifndef NO_WOLFSSH_DIR
#define WDIR HANDLE
#endif /* NO_WOLFSSH_DIR */
#else
#include <unistd.h> /* used for rmdir */
#include <sys/stat.h> /* used for mkdir, stat, and lstat */
#include <stdio.h> /* used for remove and rename */
#include <dirent.h> /* used for opening directory and reading */
#define WSTAT_T struct stat
#define WRMDIR(fs,d) rmdir((d))
#define WSTAT(p,b) stat((p),(b))
#ifndef USE_OSE_API
#define WLSTAT(p,b) lstat((p),(b))
#else
#define WLSTAT(p,b) stat((p),(b))
#endif
#define WREMOVE(fs,d) remove((d))
#define WRENAME(fs,o,n) rename((o),(n))
#define WGETCWD(fs,r,rSz) getcwd((r),(rSz))
#define WS_DELIM '/'
#include <fcntl.h> /* used for open, close, pwrite, and pread */
#define WFD int
#define WOLFSSH_O_RDWR O_RDWR
#define WOLFSSH_O_RDONLY O_RDONLY
#define WOLFSSH_O_WRONLY O_WRONLY
#define WOLFSSH_O_APPEND O_APPEND
#define WOLFSSH_O_CREAT O_CREAT
#define WOLFSSH_O_TRUNC O_TRUNC
#define WOLFSSH_O_EXCL O_EXCL
#define WOPEN(f,m,p) open((f),(m),(p))
#define WCLOSE(fd) close((fd))
int wPwrite(WFD, unsigned char*, unsigned int, const unsigned int*);
int wPread(WFD, unsigned char*, unsigned int, const unsigned int*);
#define WPWRITE(fd,b,s,o) wPwrite((fd),(b),(s),(o))
#define WPREAD(fd,b,s,o) wPread((fd),(b),(s),(o))
#ifndef NO_WOLFSSH_DIR
#include <dirent.h> /* used for opendir, readdir, and closedir */
#define WDIR DIR*
/* returns 0 on success */
#define WOPENDIR(fs,h,c,d) ((*(c) = opendir((d))) == NULL)
#define WCLOSEDIR(d) closedir(*(d))
#define WREADDIR(d) readdir(*(d))
#endif /* NO_WOLFSSH_DIR */
#endif
#endif /* WOLFSSH_SFTP or WOLFSSH_SCP */
/* setup compiler inlining */
#ifndef INLINE
#ifndef NO_INLINE
#ifdef _MSC_VER
#define INLINE __inline
#elif defined(__GNUC__)
#define INLINE inline
#elif defined(__IAR_SYSTEMS_ICC__)
#define INLINE inline
#elif defined(THREADX)
#define INLINE _Inline
#else
#define INLINE
#endif
#else
#define INLINE
#endif
#endif /* INLINE */
/* GCC 7 has new switch() fall-through detection */
#if defined(__GNUC__) && !defined(FALL_THROUGH)
#if ((__GNUC__ > 7) || ((__GNUC__ == 7) && (__GNUC_MINOR__ >= 1)))
#define FALL_THROUGH __attribute__ ((fallthrough))
#endif
#endif
#ifndef FALL_THROUGH
#define FALL_THROUGH
#endif
#if defined(USE_WINDOWS_API)
#define WS_SOCKET_T SOCKET
#else
#define WS_SOCKET_T int
#endif
#if !defined(NO_TERMIOS) && defined(WOLFSSH_TERM)
#if !defined(USE_WINDOWS_API) && !defined(MICROCHIP_PIC32)
#include <termios.h>
#define WOLFSSH_TERMIOS struct termios
#elif defined(USE_WINDOWS_API)
#define WOLFSSH_TERMIOS DWORD
#else
#define NO_TERMIOS
#endif
#endif
#ifdef __cplusplus
}
#endif
#endif /* _WOLFSSH_PORT_H_ */