Skip to content

Commit 9399d95

Browse files
Merge pull request #340 from danielinux/fatfs
Added support for FatFs
2 parents a6e4d46 + 338d3ba commit 9399d95

2 files changed

Lines changed: 440 additions & 0 deletions

File tree

src/wolfsftp.c

Lines changed: 296 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,7 @@ static int SendPacketType(WOLFSSH* ssh, byte type, byte* buf, word32 bufSz);
395395
static int SFTP_ParseAtributes_buffer(WOLFSSH* ssh, WS_SFTP_FILEATRB* atr,
396396
byte* buf, word32* idx, word32 maxIdx);
397397
static WS_SFTPNAME* wolfSSH_SFTPNAME_new(void* heap);
398+
static int SFTP_CreateLongName(WS_SFTPNAME* name);
398399

399400

400401
static byte* wolfSSH_SFTP_buffer_data(WS_SFTP_BUFFER* buffer)
@@ -1755,6 +1756,105 @@ int wolfSSH_SFTP_RecvMKDIR(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
17551756
}
17561757

17571758

1759+
#ifdef WOLFSSH_FATFS
1760+
#ifndef WOLFSSH_FATFS_MAX_FILES
1761+
#define WOLFSSH_FATFS_MAX_FILES 32
1762+
#endif
1763+
1764+
1765+
struct fd_entry {
1766+
FIL f;
1767+
int used;
1768+
};
1769+
1770+
static struct fd_entry fd_pool[WOLFSSH_FATFS_MAX_FILES] = { };
1771+
1772+
int ff_open(const char *fname, int flag, int perm)
1773+
{
1774+
int i;
1775+
BYTE mode;
1776+
(void)perm;
1777+
PRINTF("\r\nfatFS open: %s", fname);
1778+
1779+
if (flag & WOLFSSH_O_RDONLY) {
1780+
mode = FA_READ;
1781+
1782+
} else if (flag & WOLFSSH_O_RDWR) {
1783+
if ((flag & WOLFSSH_O_CREAT) &&
1784+
(flag & WOLFSSH_O_TRUNC)) {
1785+
mode = FA_READ | FA_WRITE | FA_CREATE_ALWAYS;
1786+
1787+
} else if ((flag & WOLFSSH_O_CREAT) &&
1788+
(flag & WOLFSSH_O_APPEND)) {
1789+
mode = FA_READ | FA_WRITE | FA_CREATE_NEW | FA_OPEN_APPEND;
1790+
1791+
} else {
1792+
mode = AM_ARC;
1793+
}
1794+
} else if (flag & WOLFSSH_O_WRONLY) {
1795+
if ((flag & WOLFSSH_O_CREAT) &&
1796+
(flag & WOLFSSH_O_TRUNC)) {
1797+
mode = FA_READ | FA_CREATE_ALWAYS | FA_WRITE;
1798+
} else if ((flag & WOLFSSH_O_CREAT) &&
1799+
(flag & WOLFSSH_O_APPEND)) {
1800+
mode = FA_READ | FA_WRITE | FA_CREATE_NEW | FA_OPEN_APPEND;
1801+
}
1802+
} else {
1803+
return -1;
1804+
}
1805+
1806+
1807+
for (i = 0; i < WOLFSSH_FATFS_MAX_FILES; i++) {
1808+
if (fd_pool[i].used == 0) {
1809+
if (f_open(&(fd_pool[i].f), fname, mode) == FR_OK) {
1810+
fd_pool[i].used = 1;
1811+
PRINTF("\r\nfatFS open success: %d", i);
1812+
return i;
1813+
1814+
} else {
1815+
return -1;
1816+
}
1817+
}
1818+
}
1819+
return -1;
1820+
}
1821+
1822+
int ff_close(int fd)
1823+
{
1824+
f_close(&fd_pool[fd].f);
1825+
if (fd_pool[fd].used)
1826+
fd_pool[fd].used = 0;
1827+
return 0;
1828+
}
1829+
1830+
int ff_pwrite(int fd, const byte *buffer, int sz)
1831+
{
1832+
FIL *f = &fd_pool[fd].f;
1833+
FRESULT ret;
1834+
unsigned int rsz;
1835+
if (fd_pool[fd].used == 0)
1836+
return -1;
1837+
ret = f_write(f, buffer, sz, &rsz);
1838+
if (ret != FR_OK)
1839+
return -1;
1840+
return rsz;
1841+
}
1842+
int ff_pread(int fd, byte *buffer, int sz)
1843+
{
1844+
FIL *f = &fd_pool[fd].f;
1845+
FRESULT ret;
1846+
unsigned int rsz;
1847+
if (fd_pool[fd].used == 0)
1848+
return -1;
1849+
ret = f_read(f, buffer, sz, &rsz);
1850+
if (ret != FR_OK)
1851+
return -1;
1852+
return rsz;
1853+
}
1854+
1855+
1856+
#endif /* WOLFSSH_FATFS */
1857+
17581858
/* Handles packet to open a file
17591859
*
17601860
* returns WS_SUCCESS on success
@@ -2678,6 +2778,87 @@ static int wolfSSH_SFTPNAME_readdir(WOLFSSH* ssh, WDIR* dir, WS_SFTPNAME* out,
26782778
return WS_SUCCESS;
26792779
}
26802780

2781+
#elif defined(WOLFSSH_FATFS)
2782+
2783+
/* helper function that gets file information from reading directory
2784+
*
2785+
* returns WS_SUCCESS on success
2786+
*/
2787+
static int wolfSSH_SFTPNAME_readdir(WOLFSSH* ssh, WDIR* dir, WS_SFTPNAME* out,
2788+
char* dirName)
2789+
{
2790+
FILINFO f;
2791+
FILINFO *dp;
2792+
int sz;
2793+
2794+
if (dir == NULL || ssh == NULL || out == NULL) {
2795+
return WS_BAD_ARGUMENT;
2796+
}
2797+
dp = &f;
2798+
2799+
if (f_readdir(dir, dp) != FR_OK) {
2800+
return WS_FATAL_ERROR;
2801+
}
2802+
sz = (int)WSTRLEN(dp->fname);
2803+
out->fName = (char*)WMALLOC(sz + 1, out->heap, DYNTYPE_SFTP);
2804+
if (out->fName == NULL) {
2805+
return WS_MEMORY_E;
2806+
}
2807+
2808+
WMEMCPY(out->fName, dp->fname, sz);
2809+
out->fName[sz] = '\0';
2810+
out->fSz = sz;
2811+
2812+
/* attempt to get file attributes. Could be directory or have none */
2813+
{
2814+
char* buf;
2815+
int bufSz;
2816+
int tmpSz;
2817+
2818+
bufSz = out->fSz + (int)WSTRLEN(dirName) + sizeof(WS_DELIM);
2819+
buf = (char*)WMALLOC(bufSz + 1, out->heap, DYNTYPE_SFTP);
2820+
if (buf == NULL) {
2821+
WFREE(out->fName, out->heap, DYNTYPE_SFTP);
2822+
return WS_MEMORY_E;
2823+
}
2824+
buf[0] = '\0';
2825+
WSTRNCAT(buf, dirName, bufSz + 1);
2826+
tmpSz = (int)WSTRLEN(buf);
2827+
2828+
/* add delimiter between path and file/dir name */
2829+
if (tmpSz + 1 < bufSz) {
2830+
buf[tmpSz] = WS_DELIM;
2831+
buf[tmpSz+1] = '\0';
2832+
}
2833+
WSTRNCAT(buf, out->fName, bufSz + 1);
2834+
if (XSTRLEN(out->fName) == 0) {
2835+
WFREE(buf, out->heap, DYNTYPE_SFTP);
2836+
return WS_EOF;
2837+
}
2838+
if (wolfSSH_CleanPath(ssh, buf) < 0) {
2839+
WFREE(buf, out->heap, DYNTYPE_SFTP);
2840+
return WS_FATAL_ERROR;
2841+
}
2842+
2843+
if (SFTP_GetAttributes(ssh->fs, buf, &out->atrb, 0, ssh->ctx->heap)
2844+
!= WS_SUCCESS) {
2845+
WLOG(WS_LOG_SFTP, "Unable to get attribute values for %s",
2846+
out->fName);
2847+
WFREE(buf, out->heap, DYNTYPE_SFTP);
2848+
return WS_FATAL_ERROR;
2849+
}
2850+
WFREE(buf, out->heap, DYNTYPE_SFTP);
2851+
}
2852+
2853+
/* Use attributes and fName to create long name */
2854+
if (SFTP_CreateLongName(out) != WS_SUCCESS) {
2855+
WLOG(WS_LOG_DEBUG, "Error creating long name for %s", out->fName);
2856+
WFREE(out->fName, out->heap, DYNTYPE_SFTP);
2857+
return WS_FATAL_ERROR;
2858+
}
2859+
return WS_SUCCESS;
2860+
}
2861+
26812862
#else
26822863

26832864
/* helper function that gets file information from reading directory
@@ -4200,6 +4381,121 @@ int SFTP_GetAttributes_Handle(WOLFSSH* ssh, byte* handle, int handleSz,
42004381
return WS_SUCCESS;
42014382
}
42024383

4384+
#elif defined(WOLFSSH_FATFS)
4385+
4386+
/* FatFs has its own structure for file attributes */
4387+
4388+
static int SFTP_GetAttributes(void* fs, const char* fileName,
4389+
WS_SFTP_FILEATRB* atr, byte link, void* heap)
4390+
{
4391+
FILINFO info;
4392+
FRESULT ret;
4393+
int sz = (int)WSTRLEN(fileName);
4394+
4395+
ret = f_stat(fileName, &info);
4396+
if (ret != FR_OK)
4397+
return -1;
4398+
WMEMSET(atr, 0, sizeof(WS_SFTP_FILEATRB));
4399+
if (sz > 2 && fileName[sz - 2] == ':') {
4400+
atr->flags |= WOLFSSH_FILEATRB_PERM;
4401+
atr->per |= 0x4000;
4402+
return WS_SUCCESS;
4403+
}
4404+
4405+
/* handle case of "/" */
4406+
if (sz < 3 && fileName[0] == WS_DELIM) {
4407+
atr->flags |= WOLFSSH_FILEATRB_PERM;
4408+
atr->per |= 0x4000;
4409+
return WS_SUCCESS;
4410+
}
4411+
4412+
if (ret != FR_OK) {
4413+
return WS_BAD_FILE_E;
4414+
}
4415+
4416+
atr->flags |= WOLFSSH_FILEATRB_SIZE;
4417+
atr->sz[0] = (word32)(info.fsize);
4418+
atr->sz[1] = (word32)(0);
4419+
4420+
/* get additional attributes */
4421+
{
4422+
byte atrib = info.fattrib;
4423+
atr->flags |= WOLFSSH_FILEATRB_PERM;
4424+
if (atrib & AM_DIR) {
4425+
atr->per |= 0x41ED; /* 755 with directory */
4426+
}
4427+
else {
4428+
atr->per |= 0x8000;
4429+
}
4430+
if ((atrib & AM_ARC) == AM_ARC) {
4431+
atr->per |= 0x1ED; /* octal 755 */
4432+
}
4433+
if ((atrib & AM_SYS) || (atrib & AM_RDO)) {
4434+
atr->per |= 0x124; /* octal 444 */
4435+
}
4436+
}
4437+
4438+
#ifndef NO_WOLFSSH_MKTIME
4439+
/* get file times */
4440+
atr->flags |= WOLFSSH_FILEATRB_TIME;
4441+
atr->atime = info.fdate;
4442+
atr->mtime = info.fdate;
4443+
#endif /* NO_WOLFSSH_MKTIME */
4444+
return WS_SUCCESS;
4445+
}
4446+
4447+
static int SFTP_GetAttributes_Handle(WOLFSSH* ssh, byte* handle, int handleSz,
4448+
WS_SFTP_FILEATRB* atr)
4449+
{
4450+
FILINFO info;
4451+
WS_HANDLE_LIST *cur;
4452+
4453+
if (handle == NULL || atr == NULL) {
4454+
return WS_FATAL_ERROR;
4455+
}
4456+
4457+
cur = SFTP_GetHandleNode(ssh, handle, handleSz);
4458+
if (cur == NULL) {
4459+
WLOG(WS_LOG_SFTP, "Unknown handle");
4460+
return WS_BAD_FILE_E;
4461+
}
4462+
4463+
if (f_stat(cur->name, &info) != FR_OK) {
4464+
return WS_FATAL_ERROR;
4465+
}
4466+
4467+
WMEMSET(atr, 0, sizeof(WS_SFTP_FILEATRB));
4468+
4469+
atr->flags |= WOLFSSH_FILEATRB_SIZE;
4470+
atr->sz[0] = (word32)(info.fsize);
4471+
atr->sz[1] = (word32)(0);
4472+
4473+
{
4474+
byte atrib = info.fattrib;
4475+
atr->flags |= WOLFSSH_FILEATRB_PERM;
4476+
if (atrib & AM_DIR) {
4477+
atr->per |= 0x41ED; /* 755 with directory */
4478+
}
4479+
else {
4480+
atr->per |= 0x8000;
4481+
}
4482+
if ((atrib & AM_ARC) == AM_ARC) {
4483+
atr->per |= 0x1ED; /* octal 755 */
4484+
}
4485+
if ((atrib & AM_RDO) || (atrib & AM_SYS)) {
4486+
atr->per |= 0x124; /* octal 444 */
4487+
}
4488+
}
4489+
4490+
#ifndef NO_WOLFSSH_MKTIME
4491+
/* get file times */
4492+
atr->flags |= WOLFSSH_FILEATRB_TIME;
4493+
atr->atime = info.ftime;
4494+
atr->mtime = info.ftime;
4495+
#endif /* NO_WOLFSSH_MKTIME */
4496+
return WS_SUCCESS;
4497+
}
4498+
42034499
#elif defined(WOLFSSH_USER_FILESYSTEM)
42044500
/* User-defined I/O support */
42054501

0 commit comments

Comments
 (0)