diff --git a/.github/workflows/test-fatfs.yml b/.github/workflows/test-fatfs.yml
new file mode 100644
index 000000000..5431351ba
--- /dev/null
+++ b/.github/workflows/test-fatfs.yml
@@ -0,0 +1,178 @@
+name: Test FATFS Support
+
+on:
+ push:
+ branches: [ master ]
+ pull_request:
+ branches: [ master ]
+ workflow_dispatch:
+
+jobs:
+ get-fatfs:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Set up cache key
+ id: cache-key
+ run: echo "CACHE_KEY=ff15a-cache" >> $GITHUB_ENV
+
+ - name: Download FF15a.zip
+ id: download
+ run: |
+ wget http://elm-chan.org/fsw/ff/arc/ff15a.zip -O ff15a.zip
+
+ - name: Cache the downloaded ZIP file
+ uses: actions/cache@v4
+ with:
+ path: ./ff15a.zip
+ key: ${{ env.CACHE_KEY }}
+ restore-keys: |
+ ${{ env.CACHE_KEY }}
+
+ test-fatfs:
+ needs: get-fatfs
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v3
+
+ - name: Checking cache for FATFS
+ uses: actions/cache@v4
+ with:
+ path: ./ff15a.zip
+ key: ff15a-cache
+ fail-on-cache-miss: true
+
+ - name: Install dependencies
+ run: |
+ sudo apt-get update
+ sudo apt-get install -y build-essential autoconf automake libtool pkg-config openssh-server dosfstools
+
+ - name: Clone wolfSSL
+ run: |
+ cd ..
+ git clone https://github.com/wolfSSL/wolfssl.git
+ cd wolfssl
+ ./autogen.sh
+
+ - name: Configure and build wolfSSL
+ run: |
+ cd ../wolfssl
+ ./configure --enable-wolfssh --enable-intelasm --disable-crl --disable-examples --disable-filesystem CFLAGS="-DNO_WOLFSSL_DIR"
+ make
+ sudo make install
+ sudo ldconfig
+
+ - name: Compile FATFS library
+ run: |
+ cd ide/Linux-FATFS
+ unzip ../../ff15a.zip
+ cp ffconf.h source/
+ make
+
+ - name: Configure and build wolfSSH with FATFS
+ run: |
+ ./autogen.sh
+ export LD_LIBRARY_PATH=$(pwd)/ide/Linux-FATFS
+ ./configure --enable-sftp CFLAGS="-DWOLFSSH_FATFS -Iide/Linux-FATFS/source -DSTDIN_FILENO=0 -DPRINTF=printf" LDFLAGS="-Lide/Linux-FATFS -lfatfs"
+ make
+
+
+
+ - name: Create test file
+ run: |
+ dd if=/dev/urandom of=test_file.bin bs=1M count=1
+
+ - name: Setup SSH server
+ run: |
+ sudo mkdir -p /run/sshd
+ sudo /usr/sbin/sshd
+ mkdir -p ~/.ssh
+ ssh-keygen -t rsa -f ~/.ssh/id_rsa -N ""
+ cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
+ chmod 600 ~/.ssh/authorized_keys
+ echo "Host localhost" > ~/.ssh/config
+ echo " StrictHostKeyChecking no" >> ~/.ssh/config
+ echo " UserKnownHostsFile=/dev/null" >> ~/.ssh/config
+ chmod 600 ~/.ssh/config
+
+ - name: Install expect
+ run: |
+ sudo apt-get update
+ sudo apt-get install -y expect
+
+ - name: Run wolfsftp client to get file
+ run: |
+ # Export the library path
+ export LD_LIBRARY_PATH=$(pwd)/ide/Linux-FATFS
+
+ # Get the full path to the test file
+ TEST_FILE_PATH=$(pwd)/test_file.bin
+
+ # Change to the sftpclient directory
+ cd examples/sftpclient
+
+ # Create the FATFS image file directly in the sftpclient directory
+ dd if=/dev/zero of=fatfs_image.img bs=1M count=32
+ mkdosfs fatfs_image.img
+
+ # Create a test user with a known password and add to the same group as the runner
+ sudo useradd -m testuser
+ echo "testuser:password123" | sudo chpasswd
+ sudo usermod -aG $(id -gn) testuser
+
+ # Make the test file accessible to testuser
+ chmod 644 ${TEST_FILE_PATH}
+ sudo chown testuser:$(id -gn) ${TEST_FILE_PATH}
+
+ # Configure SSH server to allow SFTP access
+ sudo sed -i 's/^#Subsystem\s\+sftp.*/Subsystem sftp \/usr\/lib\/openssh\/sftp-server/' /etc/ssh/sshd_config
+ sudo service ssh restart || sudo /etc/init.d/ssh restart || sudo /usr/sbin/sshd -t && sudo kill -HUP $(pgrep -f sshd)
+
+ # Create expect script to automate the wolfsftp client interaction
+ cat > /tmp/sftp_test.exp << EOF
+ #!/usr/bin/expect -f
+ set timeout 60
+ spawn ./wolfsftp -N -h localhost -p 22 -u testuser
+ expect "Password:"
+ send "password123\r"
+ expect "wolfSSH sftp>"
+ send "get ${TEST_FILE_PATH} test_file.bin\r"
+ expect "wolfSSH sftp>"
+ send "exit\r"
+ expect eof
+ EOF
+ chmod +x /tmp/sftp_test.exp
+
+ # Run the expect script
+ /tmp/sftp_test.exp
+
+ - name: Verify file in FATFS image
+ run: |
+ cd examples/sftpclient
+ sudo mkdir -p /mnt/fatfs
+ LOOPDEV=$(sudo losetup -f)
+ sudo losetup $LOOPDEV fatfs_image.img
+ sudo mount $LOOPDEV /mnt/fatfs
+ if [ -f /mnt/fatfs/test_file.bin ]; then
+ echo "File exists in FATFS image!"
+ ls -la /mnt/fatfs/
+
+ # Verify file contents match
+ if cmp -s ../../test_file.bin /mnt/fatfs/test_file.bin; then
+ echo "File contents match! FATFS test PASSED."
+ sudo umount /mnt/fatfs
+ sudo losetup -d $LOOPDEV
+ exit 0
+ else
+ echo "File contents do not match! FATFS test FAILED."
+ sudo umount /mnt/fatfs
+ sudo losetup -d $LOOPDEV
+ exit 1
+ fi
+ else
+ echo "File does not exist in FATFS image! FATFS test FAILED."
+ ls -la /mnt/fatfs/
+ sudo umount /mnt/fatfs
+ sudo losetup -d $LOOPDEV
+ exit 1
+ fi
diff --git a/examples/sftpclient/sftpclient.c b/examples/sftpclient/sftpclient.c
index 12fb7ecd5..744c79b7a 100644
--- a/examples/sftpclient/sftpclient.c
+++ b/examples/sftpclient/sftpclient.c
@@ -1476,6 +1476,9 @@ THREAD_RETURN WOLFSSH_THREAD sftpclient_test(void* args)
int main(int argc, char** argv)
{
+ #ifdef WOLFSSH_FATFS
+ FATFS fs;
+ #endif
func_args args;
args.argc = argc;
@@ -1486,6 +1489,13 @@ THREAD_RETURN WOLFSSH_THREAD sftpclient_test(void* args)
args.sftp_cb = NULL;
#endif
+ #ifdef WOLFSSH_FATFS
+ if (f_mount(&fs, "0:", 1) != FR_OK) {
+ fprintf(stderr, "Failed to mount filesystem\n");
+ return 1;
+ }
+ #endif
+
WSTARTTCP();
#ifdef DEBUG_WOLFSSH
@@ -1499,6 +1509,10 @@ THREAD_RETURN WOLFSSH_THREAD sftpclient_test(void* args)
wolfSSH_Cleanup();
+ #ifdef WOLFSSH_FATFS
+ f_mount(NULL, "0:", 1);
+ #endif
+
#if defined(WOLFSSH_SFTP) && !defined(NO_WOLFSSH_CLIENT)
return args.return_code;
#else
diff --git a/ide/Linux-FATFS/.gitignore b/ide/Linux-FATFS/.gitignore
new file mode 100644
index 000000000..37fbe18b1
--- /dev/null
+++ b/ide/Linux-FATFS/.gitignore
@@ -0,0 +1 @@
+fatfs_image.img
diff --git a/ide/Linux-FATFS/Makefile b/ide/Linux-FATFS/Makefile
new file mode 100644
index 000000000..6c20d3457
--- /dev/null
+++ b/ide/Linux-FATFS/Makefile
@@ -0,0 +1,26 @@
+# Compiler and flags
+CC = gcc
+CFLAGS = -g -Wall -O2 -fPIC -Isource
+LDFLAGS = -shared
+
+# Source files
+SRCS = source/ff.c source/ffunicode.c fatfs_example.c
+
+# Object files
+OBJS = $(SRCS:.c=.o)
+
+# Target library
+TARGET = libfatfs.so
+
+all: $(TARGET)
+
+$(TARGET): $(OBJS)
+ $(CC) $(LDFLAGS) -o $@ $^
+
+%.o: %.c
+ $(CC) $(CFLAGS) -c $< -o $@
+
+clean:
+ rm -f $(OBJS) $(TARGET)
+
+.PHONY: all clean
diff --git a/ide/Linux-FATFS/README.md b/ide/Linux-FATFS/README.md
new file mode 100644
index 000000000..d3994a6cf
--- /dev/null
+++ b/ide/Linux-FATFS/README.md
@@ -0,0 +1,49 @@
+# FATFS Linux Example
+
+This is a FATFS example that uses a single file on the Linux filesystem as the
+FATFS file system.
+
+## Obtaining FATFS
+
+You can download the source code from
+[The FATFS download site](http://elm-chan.org/fsw/ff/archives.html). Extract it
+into this directory.
+
+The example has been tested against FATFS 0.15a
+
+## Compiling Library
+
+First copy the config file into the correct place:
+
+```sh
+cp ffconf.h source/
+```
+
+Then to compile the FATFS library simply run `make`.
+
+## Setup filesystem
+
+The single file used for FATFS should be generated using:
+
+```sh
+dd if=/dev/zero of=fatfs_image.img bs=1M count=32
+mkdosfs fatfs_image.img
+```
+
+Note that this file will need to be local to wherever you execute anything using
+the library.
+
+## Compiling wolfSSH and wolfSSL
+
+### wolfSSL
+
+```sh
+./configure --enable-wolfssh --enable-intelasm --disable-crl --disable-examples --disable-filesystem CFLAGS="-DNO_WOLFSSL_DIR"
+```
+
+### wolfSSH
+
+```sh
+LD_LIBRARY_PATH=ide/Linux-FATFS ./configure --enable-sftp CFLAGS="-DWOLFSSH_FATFS -Iide/Linux-FATFS/source -DSTDIN_FILENO=0 -DPRINTF=printf" LDFLAGS="-Lide/Linux-FATFS -lfatfs"
+```
+
diff --git a/ide/Linux-FATFS/fatfs_example.c b/ide/Linux-FATFS/fatfs_example.c
new file mode 100644
index 000000000..7da8f36b6
--- /dev/null
+++ b/ide/Linux-FATFS/fatfs_example.c
@@ -0,0 +1,135 @@
+/* sftpclient.c
+ *
+ * Copyright (C) 2025 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 .
+ */
+
+#include
+#include
+#include
+#include
+#include "ff.h"
+#include "diskio.h"
+
+#define STORAGE_FILE_PATH "fatfs_image.img"
+
+static FILE *storage_file = NULL;
+
+/* Initialize the storage file */
+DSTATUS disk_initialize(BYTE pdrv) {
+ if (pdrv != 0) return STA_NOINIT; /* Only support one drive (0) */
+
+ /* Open the storage file in read/write binary mode */
+ storage_file = fopen(STORAGE_FILE_PATH, "r+b");
+ if (!storage_file) {
+ perror("Failed to open storage file");
+ return STA_NODISK | STA_NOINIT;
+ }
+
+ return 0; /* Initialization successful */
+}
+
+/* Get the status of the storage file */
+DSTATUS disk_status(BYTE pdrv) {
+ if (pdrv != 0) return STA_NOINIT; /* Only support one drive (0) */
+ if (!storage_file) return STA_NODISK;
+ return 0;
+}
+
+/* Read sectors from the storage file */
+DRESULT disk_read(BYTE pdrv, BYTE* buff, LBA_t sector, UINT count) {
+ if (pdrv != 0) return RES_PARERR; /* Only support one drive (0) */
+ if (!storage_file) return RES_NOTRDY;
+
+ off_t offset = sector * FF_MIN_SS; /* Calculate the byte offset */
+ if (fseek(storage_file, offset, SEEK_SET) != 0) {
+ perror("Failed to seek in storage file");
+ return RES_ERROR;
+ }
+
+ size_t bytes_read = fread(buff, FF_MIN_SS, count, storage_file);
+ if (bytes_read != count) {
+ perror("Failed to read from storage file");
+ return RES_ERROR;
+ }
+
+ return RES_OK;
+}
+
+/* Write sectors to the storage file */
+DRESULT disk_write(BYTE pdrv, const BYTE* buff, LBA_t sector, UINT count) {
+ if (pdrv != 0) return RES_PARERR; /* Only support one drive (0) */
+ if (!storage_file) return RES_NOTRDY;
+
+ off_t offset = sector * FF_MIN_SS; /* Calculate the byte offset */
+ if (fseek(storage_file, offset, SEEK_SET) != 0) {
+ perror("Failed to seek in storage file");
+ return RES_ERROR;
+ }
+
+ size_t bytes_written = fwrite(buff, FF_MIN_SS, count, storage_file);
+ if (bytes_written != count) {
+ perror("Failed to write to storage file");
+ return RES_ERROR;
+ }
+
+ fflush(storage_file); /* Ensure data is written to disk */
+ return RES_OK;
+}
+
+/* Control the device */
+DRESULT disk_ioctl(BYTE pdrv, BYTE cmd, void* buff) {
+ if (pdrv != 0) return RES_PARERR; /* Only support one drive (0) */
+
+ switch (cmd) {
+ case CTRL_SYNC:
+ /* Ensure all data is written to disk */
+ fflush(storage_file);
+ break;
+
+ case GET_SECTOR_SIZE:
+ *(WORD*)buff = FF_MIN_SS;
+ break;
+
+ case GET_BLOCK_SIZE:
+ *(DWORD*)buff = 1; /* One sector per block (minimum) */
+ break;
+
+ default:
+ return RES_PARERR;
+ }
+
+ return RES_OK;
+}
+
+/* Function to deinitialize the storage file */
+DSTATUS disk_deinitialize(BYTE pdrv) {
+ if (pdrv != 0) return STA_NOINIT; /* Only support one drive (0) */
+
+ if (storage_file) {
+ fclose(storage_file);
+ storage_file = NULL;
+ }
+
+ return 0; /* Deinitialization successful */
+}
+
+/* FatFs disk I/O driver interface */
+DSTATUS disk_status_(BYTE pdrv) { return disk_status(pdrv); }
+DRESULT disk_read_(BYTE pdrv, BYTE* buff, LBA_t sector, UINT count) { return disk_read(pdrv, buff, sector, count); }
+DRESULT disk_write_(BYTE pdrv, const BYTE* buff, LBA_t sector, UINT count) { return disk_write(pdrv, buff, sector, count); }
+DRESULT disk_ioctl_(BYTE pdrv, BYTE cmd, void* buff) { return disk_ioctl(pdrv, cmd, buff); }
diff --git a/ide/Linux-FATFS/ffconf.h b/ide/Linux-FATFS/ffconf.h
new file mode 100644
index 000000000..eef441e2e
--- /dev/null
+++ b/ide/Linux-FATFS/ffconf.h
@@ -0,0 +1,296 @@
+/*---------------------------------------------------------------------------/
+/ Configurations of FatFs Module
+/---------------------------------------------------------------------------*/
+
+#define FFCONF_DEF 5380 /* Revision ID */
+
+/*---------------------------------------------------------------------------/
+/ Function Configurations
+/---------------------------------------------------------------------------*/
+
+#define FF_FS_READONLY 0
+/* This option switches read-only configuration. (0:Read/Write or 1:Read-only)
+/ Read-only configuration removes writing API functions, f_write(), f_sync(),
+/ f_unlink(), f_mkdir(), f_chmod(), f_rename(), f_truncate(), f_getfree()
+/ and optional writing functions as well. */
+
+
+#define FF_FS_MINIMIZE 0
+/* This option defines minimization level to remove some basic API functions.
+/
+/ 0: Basic functions are fully enabled.
+/ 1: f_stat(), f_getfree(), f_unlink(), f_mkdir(), f_truncate() and f_rename()
+/ are removed.
+/ 2: f_opendir(), f_readdir() and f_closedir() are removed in addition to 1.
+/ 3: f_lseek() function is removed in addition to 2. */
+
+
+#define FF_USE_FIND 0
+/* This option switches filtered directory read functions, f_findfirst() and
+/ f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */
+
+
+#define FF_USE_MKFS 0
+/* This option switches f_mkfs(). (0:Disable or 1:Enable) */
+
+
+#define FF_USE_FASTSEEK 0
+/* This option switches fast seek feature. (0:Disable or 1:Enable) */
+
+
+#define FF_USE_EXPAND 0
+/* This option switches f_expand(). (0:Disable or 1:Enable) */
+
+
+#define FF_USE_CHMOD 0
+/* This option switches attribute control API functions, f_chmod() and f_utime().
+/ (0:Disable or 1:Enable) Also FF_FS_READONLY needs to be 0 to enable this option. */
+
+
+#define FF_USE_LABEL 0
+/* This option switches volume label API functions, f_getlabel() and f_setlabel().
+/ (0:Disable or 1:Enable) */
+
+
+#define FF_USE_FORWARD 0
+/* This option switches f_forward(). (0:Disable or 1:Enable) */
+
+
+#define FF_USE_STRFUNC 0
+#define FF_PRINT_LLI 0
+#define FF_PRINT_FLOAT 0
+#define FF_STRF_ENCODE 3
+/* FF_USE_STRFUNC switches the string API functions, f_gets(), f_putc(), f_puts()
+/ and f_printf().
+/
+/ 0: Disable. FF_PRINT_LLI, FF_PRINT_FLOAT and FF_STRF_ENCODE have no effect.
+/ 1: Enable without LF - CRLF conversion.
+/ 2: Enable with LF - CRLF conversion.
+/
+/ FF_PRINT_LLI = 1 makes f_printf() support long long argument and FF_PRINT_FLOAT = 1/2
+/ makes f_printf() support floating point argument. These features want C99 or later.
+/ When FF_LFN_UNICODE >= 1 with LFN enabled, string API functions convert the character
+/ encoding in it. FF_STRF_ENCODE selects assumption of character encoding ON THE FILE
+/ to be read/written via those functions.
+/
+/ 0: ANSI/OEM in current CP
+/ 1: Unicode in UTF-16LE
+/ 2: Unicode in UTF-16BE
+/ 3: Unicode in UTF-8
+*/
+
+
+/*---------------------------------------------------------------------------/
+/ Locale and Namespace Configurations
+/---------------------------------------------------------------------------*/
+
+#define FF_CODE_PAGE 932
+/* This option specifies the OEM code page to be used on the target system.
+/ Incorrect code page setting can cause a file open failure.
+/
+/ 437 - U.S.
+/ 720 - Arabic
+/ 737 - Greek
+/ 771 - KBL
+/ 775 - Baltic
+/ 850 - Latin 1
+/ 852 - Latin 2
+/ 855 - Cyrillic
+/ 857 - Turkish
+/ 860 - Portuguese
+/ 861 - Icelandic
+/ 862 - Hebrew
+/ 863 - Canadian French
+/ 864 - Arabic
+/ 865 - Nordic
+/ 866 - Russian
+/ 869 - Greek 2
+/ 932 - Japanese (DBCS)
+/ 936 - Simplified Chinese (DBCS)
+/ 949 - Korean (DBCS)
+/ 950 - Traditional Chinese (DBCS)
+/ 0 - Include all code pages above and configured by f_setcp()
+*/
+
+
+#define FF_USE_LFN 2
+#define FF_MAX_LFN 255
+/* The FF_USE_LFN switches the support for LFN (long file name).
+/
+/ 0: Disable LFN. FF_MAX_LFN has no effect.
+/ 1: Enable LFN with static working buffer on the BSS. Always NOT thread-safe.
+/ 2: Enable LFN with dynamic working buffer on the STACK.
+/ 3: Enable LFN with dynamic working buffer on the HEAP.
+/
+/ To enable the LFN, ffunicode.c needs to be added to the project. The LFN feature
+/ requiers certain internal working buffer occupies (FF_MAX_LFN + 1) * 2 bytes and
+/ additional (FF_MAX_LFN + 44) / 15 * 32 bytes when exFAT is enabled.
+/ The FF_MAX_LFN defines size of the working buffer in UTF-16 code unit and it can
+/ be in range of 12 to 255. It is recommended to be set 255 to fully support the LFN
+/ specification.
+/ When use stack for the working buffer, take care on stack overflow. When use heap
+/ memory for the working buffer, memory management functions, ff_memalloc() and
+/ ff_memfree() exemplified in ffsystem.c, need to be added to the project. */
+
+
+#define FF_LFN_UNICODE 0
+/* This option switches the character encoding on the API when LFN is enabled.
+/
+/ 0: ANSI/OEM in current CP (TCHAR = char)
+/ 1: Unicode in UTF-16 (TCHAR = WCHAR)
+/ 2: Unicode in UTF-8 (TCHAR = char)
+/ 3: Unicode in UTF-32 (TCHAR = DWORD)
+/
+/ Also behavior of string I/O functions will be affected by this option.
+/ When LFN is not enabled, this option has no effect. */
+
+
+#define FF_LFN_BUF 255
+#define FF_SFN_BUF 12
+/* This set of options defines size of file name members in the FILINFO structure
+/ which is used to read out directory items. These values should be suffcient for
+/ the file names to read. The maximum possible length of the read file name depends
+/ on character encoding. When LFN is not enabled, these options have no effect. */
+
+
+#define FF_FS_RPATH 2
+/* This option configures support for relative path.
+/
+/ 0: Disable relative path and remove related API functions.
+/ 1: Enable relative path. f_chdir() and f_chdrive() are available.
+/ 2: f_getcwd() is available in addition to 1.
+*/
+
+
+/*---------------------------------------------------------------------------/
+/ Drive/Volume Configurations
+/---------------------------------------------------------------------------*/
+
+#define FF_VOLUMES 1
+/* Number of volumes (logical drives) to be used. (1-10) */
+
+
+#define FF_STR_VOLUME_ID 0
+#define FF_VOLUME_STRS "RAM","NAND","CF","SD","SD2","USB","USB2","USB3"
+/* FF_STR_VOLUME_ID switches support for volume ID in arbitrary strings.
+/ When FF_STR_VOLUME_ID is set to 1 or 2, arbitrary strings can be used as drive
+/ number in the path name. FF_VOLUME_STRS defines the volume ID strings for each
+/ logical drive. Number of items must not be less than FF_VOLUMES. Valid
+/ characters for the volume ID strings are A-Z, a-z and 0-9, however, they are
+/ compared in case-insensitive. If FF_STR_VOLUME_ID >= 1 and FF_VOLUME_STRS is
+/ not defined, a user defined volume string table is needed as:
+/
+/ const char* VolumeStr[FF_VOLUMES] = {"ram","flash","sd","usb",...
+*/
+
+
+#define FF_MULTI_PARTITION 0
+/* This option switches support for multiple volumes on the physical drive.
+/ By default (0), each logical drive number is bound to the same physical drive
+/ number and only an FAT volume found on the physical drive will be mounted.
+/ When this feature is enabled (1), each logical drive number can be bound to
+/ arbitrary physical drive and partition listed in the VolToPart[]. Also f_fdisk()
+/ will be available. */
+
+
+#define FF_MIN_SS 512
+#define FF_MAX_SS 512
+/* This set of options configures the range of sector size to be supported. (512,
+/ 1024, 2048 or 4096) Always set both 512 for most systems, generic memory card and
+/ harddisk, but a larger value may be required for on-board flash memory and some
+/ type of optical media. When FF_MAX_SS is larger than FF_MIN_SS, FatFs is
+/ configured for variable sector size mode and disk_ioctl() needs to implement
+/ GET_SECTOR_SIZE command. */
+
+
+#define FF_LBA64 0
+/* This option switches support for 64-bit LBA. (0:Disable or 1:Enable)
+/ To enable the 64-bit LBA, also exFAT needs to be enabled. (FF_FS_EXFAT == 1) */
+
+
+#define FF_MIN_GPT 0x10000000
+/* Minimum number of sectors to switch GPT as partitioning format in f_mkfs() and
+/ f_fdisk(). 2^32 sectors maximum. This option has no effect when FF_LBA64 == 0. */
+
+
+#define FF_USE_TRIM 0
+/* This option switches support for ATA-TRIM. (0:Disable or 1:Enable)
+/ To enable this feature, also CTRL_TRIM command should be implemented to
+/ the disk_ioctl(). */
+
+
+
+/*---------------------------------------------------------------------------/
+/ System Configurations
+/---------------------------------------------------------------------------*/
+
+#define FF_FS_TINY 0
+/* This option switches tiny buffer configuration. (0:Normal or 1:Tiny)
+/ At the tiny configuration, size of file object (FIL) is shrinked FF_MAX_SS bytes.
+/ Instead of private sector buffer eliminated from the file object, common sector
+/ buffer in the filesystem object (FATFS) is used for the file data transfer. */
+
+
+#define FF_FS_EXFAT 0
+/* This option switches support for exFAT filesystem. (0:Disable or 1:Enable)
+/ To enable exFAT, also LFN needs to be enabled. (FF_USE_LFN >= 1)
+/ Note that enabling exFAT discards ANSI C (C89) compatibility. */
+
+
+#define FF_FS_NORTC 1
+#define FF_NORTC_MON 11
+#define FF_NORTC_MDAY 1
+#define FF_NORTC_YEAR 2024
+/* The option FF_FS_NORTC switches timestamp feature. If the system does not have
+/ an RTC or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable the
+/ timestamp feature. Every object modified by FatFs will have a fixed timestamp
+/ defined by FF_NORTC_MON, FF_NORTC_MDAY and FF_NORTC_YEAR in local time.
+/ To enable timestamp function (FF_FS_NORTC = 0), get_fattime() need to be added
+/ to the project to read current time form real-time clock. FF_NORTC_MON,
+/ FF_NORTC_MDAY and FF_NORTC_YEAR have no effect.
+/ These options have no effect in read-only configuration (FF_FS_READONLY = 1). */
+
+
+#define FF_FS_NOFSINFO 0
+/* If you need to know correct free space on the FAT32 volume, set bit 0 of this
+/ option, and f_getfree() at the first time after volume mount will force
+/ a full FAT scan. Bit 1 controls the use of last allocated cluster number.
+/
+/ bit0=0: Use free cluster count in the FSINFO if available.
+/ bit0=1: Do not trust free cluster count in the FSINFO.
+/ bit1=0: Use last allocated cluster number in the FSINFO if available.
+/ bit1=1: Do not trust last allocated cluster number in the FSINFO.
+*/
+
+
+#define FF_FS_LOCK 0
+/* The option FF_FS_LOCK switches file lock function to control duplicated file open
+/ and illegal operation to open objects. This option must be 0 when FF_FS_READONLY
+/ is 1.
+/
+/ 0: Disable file lock function. To avoid volume corruption, application program
+/ should avoid illegal open, remove and rename to the open objects.
+/ >0: Enable file lock function. The value defines how many files/sub-directories
+/ can be opened simultaneously under file lock control. Note that the file
+/ lock control is independent of re-entrancy. */
+
+
+#define FF_FS_REENTRANT 0
+#define FF_FS_TIMEOUT 1000
+/* The option FF_FS_REENTRANT switches the re-entrancy (thread safe) of the FatFs
+/ module itself. Note that regardless of this option, file access to different
+/ volume is always re-entrant and volume control functions, f_mount(), f_mkfs()
+/ and f_fdisk(), are always not re-entrant. Only file/directory access to
+/ the same volume is under control of this featuer.
+/
+/ 0: Disable re-entrancy. FF_FS_TIMEOUT have no effect.
+/ 1: Enable re-entrancy. Also user provided synchronization handlers,
+/ ff_mutex_create(), ff_mutex_delete(), ff_mutex_take() and ff_mutex_give(),
+/ must be added to the project. Samples are available in ffsystem.c.
+/
+/ The FF_FS_TIMEOUT defines timeout period in unit of O/S time tick.
+*/
+
+
+
+/*--- End of configuration options ---*/
diff --git a/src/wolfsftp.c b/src/wolfsftp.c
index 24a35329e..d228ccffa 100644
--- a/src/wolfsftp.c
+++ b/src/wolfsftp.c
@@ -1479,7 +1479,8 @@ int wolfSSH_SFTP_read(WOLFSSH* ssh)
wolfSSH_SFTP_buffer_data(&state->buffer),
wolfSSH_SFTP_buffer_size(&state->buffer));
break;
- #if !defined(_WIN32_WCE) && !defined(WOLFSSH_ZEPHYR)
+ #if !defined(_WIN32_WCE) && !defined(WOLFSSH_ZEPHYR) && \
+ !defined(WOLFSSH_FATFS)
case WOLFSSH_FTP_SETSTAT:
ret = wolfSSH_SFTP_RecvSetSTAT(ssh, state->reqId,
wolfSSH_SFTP_buffer_data(&state->buffer),
@@ -4689,6 +4690,10 @@ static int SFTP_GetAttributes(void* fs, const char* fileName,
FRESULT ret;
int sz = (int)WSTRLEN(fileName);
+ (void) fs;
+ (void) noFollow;
+ (void) heap;
+
ret = f_stat(fileName, &info);
if (ret != FR_OK)
return -1;
@@ -5191,7 +5196,7 @@ int wolfSSH_SFTP_RecvLSTAT(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
}
#if !defined(USE_WINDOWS_API) && !defined(WOLFSSH_ZEPHYR) \
- && !defined(WOLFSSH_SFTP_SETMODE)
+ && !defined(WOLFSSH_SFTP_SETMODE) && !defined(WOLFSSH_FATFS)
/* Set the files mode
* return WS_SUCCESS on success */
static int SFTP_SetMode(void* fs, char* name, word32 mode) {
@@ -5204,7 +5209,7 @@ static int SFTP_SetMode(void* fs, char* name, word32 mode) {
#endif
#if !defined(USE_WINDOWS_API) && !defined(WOLFSSH_ZEPHYR) \
- && !defined(WOLFSSH_SFTP_SETMODEHANDLE)
+ && !defined(WOLFSSH_SFTP_SETMODEHANDLE) && !defined(WOLFSSH_FATFS)
/* Set the files mode
* return WS_SUCCESS on success */
static int SFTP_SetModeHandle(void* fs, WFD handle, word32 mode) {
@@ -5216,7 +5221,7 @@ static int SFTP_SetModeHandle(void* fs, WFD handle, word32 mode) {
}
#endif
-#if !defined(_WIN32_WCE) && !defined(WOLFSSH_ZEPHYR)
+#if !defined(_WIN32_WCE) && !defined(WOLFSSH_ZEPHYR) && !defined(WOLFSSH_FATFS)
/* sets a files attributes
* returns WS_SUCCESS on success */
diff --git a/wolfssh/port.h b/wolfssh/port.h
index dbd0de9b9..375bef72b 100644
--- a/wolfssh/port.h
+++ b/wolfssh/port.h
@@ -101,7 +101,7 @@ extern "C" {
#endif
#endif /* !WOLFSSH_HANDLE */
-#ifdef NO_FILESYSTEM
+#if defined(NO_FILESYSTEM) && !defined(WOLFSSH_FATFS)
#define WS_DELIM '/'
#elif defined(WOLFSSL_NUCLEUS)
#include "storage/nu_storage.h"
@@ -255,6 +255,7 @@ extern "C" {
#define WSEEK_SET 0
#define WSEEK_CUR 1
#define WSEEK_END 2
+ #define WFFLUSH(s) ((void)(s))
static inline int ff_fopen(WFILE** f, const char* filename,
const char* mode)
{
@@ -264,11 +265,12 @@ extern "C" {
if (!f) {
return -1;
}
-#ifdef WOLFSSH_XILFATFS
- m = FA_CREATE_ALWAYS;
+
if (*f == 0) {
*f = WMALLOC(sizeof(FIL), NULL, 0);
}
+#ifdef WOLFSSH_XILFATFS
+ m = FA_CREATE_ALWAYS;
#else
m = FA_CREATE_NEW;
#endif
@@ -585,7 +587,8 @@ extern "C" {
#if (defined(WOLFSSH_SFTP) || \
defined(WOLFSSH_SCP) || defined(WOLFSSH_SSHD)) && \
- !defined(NO_WOLFSSH_SERVER) && !defined(NO_FILESYSTEM)
+ !defined(NO_WOLFSSH_SERVER) && \
+ (!defined(NO_FILESYSTEM) || defined(WOLFSSH_FATFS))
#ifndef SIZEOF_OFF_T
/* if not using autoconf then make a guess on off_t size based on sizeof
@@ -1192,7 +1195,7 @@ extern "C" {
#define WSTAT(fs,p,b) f_stat(p,b)
#define WLSTAT(fs,p,b) f_stat(p,b)
#define WREMOVE(fs,d) f_unlink((d))
- #define WRENAME(fs,fd,o,n) f_rename((o),(n))
+ #define WRENAME(fs,o,n) f_rename((o),(n))
#define WMKDIR(fs, p, m) f_mkdir(p)
#define WFD int
diff --git a/wolfssh/settings.h b/wolfssh/settings.h
index 70ada34c9..75db751ad 100644
--- a/wolfssh/settings.h
+++ b/wolfssh/settings.h
@@ -52,6 +52,10 @@ extern "C" {
#define USE_WOLFSSH_MEMORY /* default memory handlers */
#endif /* WMALLOC_USER */
+/* SFTP requires storehandle when fatfs is in use */
+#ifdef WOLFSSH_FATFS
+ #define WOLFSSH_STOREHANDLE
+#endif
#if defined (_WIN32)
#define USE_WINDOWS_API