From b3504de81d532bc48f84589eab30173dcd59a800 Mon Sep 17 00:00:00 2001 From: ParkerTomatoes Date: Sun, 1 Dec 2024 16:25:27 -0500 Subject: [PATCH] Support single partition mode, fix issue related to memory growth, improve documentation, fix Typescript definitions when importing. --- docs/README.md | 23 +- docs/classes/FatFsDir.md | 50 +- docs/classes/FatFsDisk.md | 254 ++++++-- docs/classes/FatFsDiskPartitionable.md | 866 +++++++++++++++++++++++++ docs/classes/FatFsError.md | 19 +- docs/classes/FatFsFile.md | 72 +- docs/classes/FatFsFileInfo.md | 34 +- docs/enums/FatFsAttrib.md | 10 +- docs/enums/FatFsFormat.md | 10 +- docs/enums/FatFsIoctl.md | 10 +- docs/enums/FatFsMode.md | 14 +- docs/enums/FatFsResult.md | 40 +- docs/modules.md | 50 ++ native/build.sh | 27 +- native/ff15/source/diskio.c | 2 +- native/ff15/source/diskio.h | 3 +- native/ff15/source/ff.h | 2 + native/ff15/source/ffconf.h | 2 +- package.dist.json | 14 +- package.json | 3 +- rollup.config.mjs | 8 +- src/fatfs.ts | 286 ++++++-- src/ff.wasm | Bin 22829 -> 0 bytes src/ff_multi.wasm | Bin 0 -> 22884 bytes src/ff_single.wasm | Bin 0 -> 22493 bytes test/fatfs.test.ts | 24 +- tsconfig.json | 2 +- typedoc.json | 7 + 28 files changed, 1599 insertions(+), 233 deletions(-) create mode 100644 docs/classes/FatFsDiskPartitionable.md delete mode 100755 src/ff.wasm create mode 100755 src/ff_multi.wasm create mode 100755 src/ff_single.wasm create mode 100644 typedoc.json diff --git a/docs/README.md b/docs/README.md index a040650..75fc9e8 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,7 +1,7 @@ fatfs-wasm / [Exports](modules.md) # FatFs-Wasm -FatFs is a generic FAT/exFAT filesystem module for small embedded systems, authored by CHaN. FatFS-Wasm is a library which uses a WebAssembly build of FatFs to manipulate FAT image files from node or the browser. +FatFs is a generic FAT/exFAT filesystem module for small embedded systems, authored by CHaN. FatFs-Wasm is a library which uses a WebAssembly build of FatFs to manipulate FAT image files from node or the browser. Features: * Read, write, rename, stat, chmod, and delete files @@ -68,3 +68,24 @@ for (const file of dir) { } dir.close(); ``` + +See the API documentation for details + +## API Documentation + +[API Documentation](./docs/modules.md) + +## Modifying FatFs C Code +FatFs has many feature gates defined using the preprocessor. See `native/ff15/source/ffconf.h` to make adjustments. Please note that any changes to the C code must be reflected in the `src/fatfs.ts`` wrapper, which is not automatically generated. Make changes at your own risk! + +To build, open a terminal in MacOS, Linux, or WSL with clang installed and run the build script: +``` +cd native +./build.sh +``` +This will build `ff.wasm` and copy it to the `src` directory. + +## Running Tests +``` +npx jest +``` diff --git a/docs/classes/FatFsDir.md b/docs/classes/FatFsDir.md index e4b2d24..3311e83 100644 --- a/docs/classes/FatFsDir.md +++ b/docs/classes/FatFsDir.md @@ -10,6 +10,12 @@ FatFs Directory Reference - [constructor](FatFsDir.md#constructor) +### Properties + +- [#context](FatFsDir.md##context) +- [#dirPtr](FatFsDir.md##dirptr) +- [#exports](FatFsDir.md##exports) + ### Accessors - [dp](FatFsDir.md#dp) @@ -38,7 +44,37 @@ FatFs Directory Reference #### Defined in -src/fatfs.ts:610 +[src/fatfs.ts:665](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L665) + +## Properties + +### #context + +• `Private` **#context**: `FatFsMemoryContext` + +#### Defined in + +[src/fatfs.ts:663](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L663) + +___ + +### #dirPtr + +• `Private` **#dirPtr**: `number` + +#### Defined in + +[src/fatfs.ts:661](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L661) + +___ + +### #exports + +• `Private` **#exports**: `FatFsExports` + +#### Defined in + +[src/fatfs.ts:662](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L662) ## Accessors @@ -52,7 +88,7 @@ src/fatfs.ts:610 #### Defined in -src/fatfs.ts:616 +[src/fatfs.ts:671](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L671) ## Methods @@ -66,7 +102,7 @@ src/fatfs.ts:616 #### Defined in -src/fatfs.ts:672 +[src/fatfs.ts:727](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L727) ___ @@ -82,7 +118,7 @@ Closes the open directory. #### Defined in -src/fatfs.ts:623 +[src/fatfs.ts:678](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L678) ___ @@ -98,7 +134,7 @@ The f_findnext function searches for a next matched object #### Defined in -src/fatfs.ts:660 +[src/fatfs.ts:715](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L715) ___ @@ -116,7 +152,7 @@ Information about the next directory entry #### Defined in -src/fatfs.ts:635 +[src/fatfs.ts:690](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L690) ___ @@ -132,4 +168,4 @@ Rewinds the directory #### Defined in -src/fatfs.ts:650 +[src/fatfs.ts:705](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L705) diff --git a/docs/classes/FatFsDisk.md b/docs/classes/FatFsDisk.md index b302870..8e4f22c 100644 --- a/docs/classes/FatFsDisk.md +++ b/docs/classes/FatFsDisk.md @@ -2,18 +2,30 @@ # Class: FatFsDisk +Represents a FAT filesystem over an array of bytes + +## Hierarchy + +- **`FatFsDisk`** + + ↳ [`FatFsDiskPartitionable`](FatFsDiskPartitionable.md) + ## Table of contents ### Constructors - [constructor](FatFsDisk.md#constructor) +### Properties + +- [#context](FatFsDisk.md##context) +- [#exports](FatFsDisk.md##exports) + ### Methods - [chdir](FatFsDisk.md#chdir) - [chdrive](FatFsDisk.md#chdrive) - [chmod](FatFsDisk.md#chmod) -- [fdisk](FatFsDisk.md#fdisk) - [find](FatFsDisk.md#find) - [findFirst](FatFsDisk.md#findfirst) - [getFree](FatFsDisk.md#getfree) @@ -24,13 +36,16 @@ - [mount](FatFsDisk.md#mount) - [open](FatFsDisk.md#open) - [openDir](FatFsDisk.md#opendir) +- [readFile](FatFsDisk.md#readfile) - [rename](FatFsDisk.md#rename) +- [session](FatFsDisk.md#session) - [setCP](FatFsDisk.md#setcp) - [setLabel](FatFsDisk.md#setlabel) - [stat](FatFsDisk.md#stat) - [unlink](FatFsDisk.md#unlink) - [unmount](FatFsDisk.md#unmount) - [utime](FatFsDisk.md#utime) +- [writeFile](FatFsDisk.md#writefile) - [create](FatFsDisk.md#create) ## Constructors @@ -39,6 +54,8 @@ • **new FatFsDisk**(`context`, `exports`) +Private constructor. Use [create](FatFsDisk.md#create) to create a [FatFsDisk](FatFsDisk.md) object. + #### Parameters | Name | Type | @@ -48,7 +65,27 @@ #### Defined in -src/fatfs.ts:700 +[src/fatfs.ts:792](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L792) + +## Properties + +### #context + +• `Private` **#context**: `FatFsMemoryContext` + +#### Defined in + +[src/fatfs.ts:752](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L752) + +___ + +### #exports + +• `Private` **#exports**: `FatFsExports` + +#### Defined in + +[src/fatfs.ts:753](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L753) ## Methods @@ -70,7 +107,7 @@ The f_chdir function changes the current directory of the logical drive. #### Defined in -src/fatfs.ts:1016 +[src/fatfs.ts:1134](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L1134) ___ @@ -92,7 +129,7 @@ The f_chdrive function changes the current drive. #### Defined in -src/fatfs.ts:1031 +[src/fatfs.ts:1149](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L1149) ___ @@ -118,30 +155,7 @@ OK or error code #### Defined in -src/fatfs.ts:951 - -___ - -### fdisk - -▸ **fdisk**(`pdrv`, `ptbl`): `void` - -The f_fdisk function divides a physical drive. - -#### Parameters - -| Name | Type | Description | -| :------ | :------ | :------ | -| `pdrv` | `number` | Specifies the physical drive to be divided. This is not the logical drive number but the drive identifier passed to the low level disk functions. | -| `ptbl` | `number`[] | List of partition size to create on the drive. | - -#### Returns - -`void` - -#### Defined in - -src/fatfs.ts:715 +[src/fatfs.ts:1069](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L1069) ___ @@ -166,7 +180,7 @@ An iterator to the search results #### Defined in -src/fatfs.ts:873 +[src/fatfs.ts:991](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L991) ___ @@ -191,19 +205,19 @@ The directory, and the first matching entry #### Defined in -src/fatfs.ts:848 +[src/fatfs.ts:966](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L966) ___ ### getFree -▸ **getFree**(`path`): [`number`, `FatFsObject`] +▸ **getFree**(`path?`): [`number`, `FatFsObject`] #### Parameters | Name | Type | Description | | :------ | :------ | :------ | -| `path` | ``null`` \| `string` | Pointer to the null-terminated string that specifies the logical drive. A null-string means the default drive. | +| `path?` | ``null`` \| `string` | Pointer to the null-terminated string that specifies the logical drive. A null-string means the default drive. | #### Returns @@ -214,13 +228,13 @@ tuple with the number of free clusters, and a FATFS #### Defined in -src/fatfs.ts:1064 +[src/fatfs.ts:1182](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L1182) ___ ### getLabel -▸ **getLabel**(`path`): [`string`, `number`] +▸ **getLabel**(`path?`): [`string`, `number`] The f_getlabel function returns volume label and volume serial number of a volume. @@ -229,7 +243,7 @@ of a volume. | Name | Type | Description | | :------ | :------ | :------ | -| `path` | `string` | Pointer to the null-terminated string that specifies the logical drive. Null-string specifies the default drive. | +| `path?` | `string` | Pointer to the null-terminated string that specifies the logical drive. Null-string specifies the default drive. | #### Returns @@ -240,7 +254,7 @@ tuple containing the result, the volume label, and the volume #### Defined in -src/fatfs.ts:1088 +[src/fatfs.ts:1206](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L1206) ___ @@ -259,7 +273,7 @@ The current directory. #### Defined in -src/fatfs.ts:1046 +[src/fatfs.ts:1164](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L1164) ___ @@ -281,13 +295,13 @@ The f_mkdir function creates a new directory. #### Defined in -src/fatfs.ts:1000 +[src/fatfs.ts:1118](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L1118) ___ ### mkfs -▸ **mkfs**(`path`, `opt?`): `void` +▸ **mkfs**(`opt?`): `void` The f_mkfs function creates an FAT/exFAT volume on the logical drive. @@ -295,8 +309,7 @@ The f_mkfs function creates an FAT/exFAT volume on the logical drive. | Name | Type | Description | | :------ | :------ | :------ | -| `path` | `string` | Logical drive number | -| `opt?` | ``null`` \| `FatFsMkfsOptions` | Format options | +| `opt?` | ``null`` \| [`FatFsMkfsOptions`](../modules.md#fatfsmkfsoptions) | Format options | #### Returns @@ -306,13 +319,13 @@ OK or error code #### Defined in -src/fatfs.ts:734 +[src/fatfs.ts:805](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L805) ___ ### mount -▸ **mount**(`path`, `opt`): `FatFsObject` +▸ **mount**(`path?`, `opt?`): `FatFsObject` The f_mount function gives work area to the FatFs module. @@ -320,8 +333,8 @@ The f_mount function gives work area to the FatFs module. | Name | Type | Description | | :------ | :------ | :------ | -| `path` | `string` | Pointer to the null-terminated string that specifies the logical drive. The string without drive number means the default drive. | -| `opt` | `number` | Mounting option. 0: Do not mount now (to be mounted on the first access to the volume), 1: Force mounted the volume to check if it is ready to work. | +| `path?` | `string` | Pointer to the null-terminated string that specifies the logical drive. The string without drive number means the default drive. | +| `opt?` | `number` | Mounting option. 0: Do not mount now (to be mounted on the first access to the volume), 1: Force mounted the volume to check if it is ready to work. | #### Returns @@ -331,7 +344,7 @@ reference to the mounted work area #### Defined in -src/fatfs.ts:764 +[src/fatfs.ts:836](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L836) ___ @@ -356,7 +369,7 @@ File object #### Defined in -src/fatfs.ts:810 +[src/fatfs.ts:882](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L882) ___ @@ -380,7 +393,31 @@ Directory object #### Defined in -src/fatfs.ts:829 +[src/fatfs.ts:947](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L947) + +___ + +### readFile + +▸ **readFile**(`path`): `Uint8Array` + +Read an entire file. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `path` | `string` | Path to the file to read | + +#### Returns + +`Uint8Array` + +The contents of the file + +#### Defined in + +[src/fatfs.ts:915](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L915) ___ @@ -405,7 +442,36 @@ OK or error code #### Defined in -src/fatfs.ts:929 +[src/fatfs.ts:1047](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L1047) + +___ + +### session + +▸ **session**<`T`\>(`action`, `path?`): `ReturnType`<`T`\> + +Mounts the filesystem, executes a user function, and unmounts + +#### Type parameters + +| Name | Type | +| :------ | :------ | +| `T` | extends () => `any` | + +#### Parameters + +| Name | Type | Default value | Description | +| :------ | :------ | :------ | :------ | +| `action` | `T` | `undefined` | The action to perform | +| `path` | `string` | `''` | The logical drive. An empty string without drive number means the default drive. | + +#### Returns + +`ReturnType`<`T`\> + +#### Defined in + +[src/fatfs.ts:901](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L901) ___ @@ -427,7 +493,7 @@ The f_setcp function sets the active code page. #### Defined in -src/fatfs.ts:1124 +[src/fatfs.ts:1242](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L1242) ___ @@ -449,7 +515,7 @@ The f_setlabel function sets/removes the label of a volume. #### Defined in -src/fatfs.ts:1110 +[src/fatfs.ts:1228](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L1228) ___ @@ -473,7 +539,7 @@ OK or error code #### Defined in -src/fatfs.ts:890 +[src/fatfs.ts:1008](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L1008) ___ @@ -495,13 +561,13 @@ The f_unlink function removes a file or sub-directory from the volume. #### Defined in -src/fatfs.ts:908 +[src/fatfs.ts:1026](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L1026) ___ ### unmount -▸ **unmount**(`path`): `void` +▸ **unmount**(`path?`): `void` Unregisters the filesystem object @@ -509,7 +575,7 @@ Unregisters the filesystem object | Name | Type | Description | | :------ | :------ | :------ | -| `path` | `string` | Pointer to the null-terminated string that specifies the logical drive. The string without drive number means the default drive. | +| `path?` | `string` | Pointer to the null-terminated string that specifies the logical drive. The string without drive number means the default drive. | #### Returns @@ -517,7 +583,7 @@ Unregisters the filesystem object #### Defined in -src/fatfs.ts:786 +[src/fatfs.ts:858](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L858) ___ @@ -542,20 +608,82 @@ OK or error code #### Defined in -src/fatfs.ts:970 +[src/fatfs.ts:1088](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L1088) + +___ + +### writeFile + +▸ **writeFile**(`path`, `contents`): `void` + +Write an entire file. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `path` | `string` | Path to the file to write | +| `contents` | `Uint8Array` | Contents to write to the file | + +#### Returns + +`void` + +#### Defined in + +[src/fatfs.ts:932](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L932) ___ ### create -▸ `Static` **create**(`disk`, `sectorSize?`): `Promise`<[`FatFsDisk`](FatFsDisk.md)\> +▸ `Static` **create**(`disk`, `options`): `Promise`<[`FatFsDiskPartitionable`](FatFsDiskPartitionable.md)\> + +Create a new [FatFsDisk](FatFsDisk.md). #### Parameters -| Name | Type | -| :------ | :------ | -| `disk` | `Uint8Array` | -| `sectorSize?` | `number` | +| Name | Type | Description | +| :------ | :------ | :------ | +| `disk` | `Uint8Array` | Array of bytes containing a FAT image (or anything if you would like to format) | +| `options` | [`FatFsDiskOptions`](../modules.md#fatfsdiskoptions) & { `multiPartition`: ``true`` } | Additional options. See [FatFsDiskOptions](../modules.md#fatfsdiskoptions) for more information. Will return a [FatFsDiskPartitionable](FatFsDiskPartitionable.md) if the `multiPartition` option is true. | + +#### Returns + +`Promise`<[`FatFsDiskPartitionable`](FatFsDiskPartitionable.md)\> + +#### Defined in + +[src/fatfs.ts:761](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L761) + +▸ `Static` **create**(`disk`, `options`): `Promise`<[`FatFsDisk`](FatFsDisk.md)\> + +Create a new [FatFsDisk](FatFsDisk.md). + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `disk` | `Uint8Array` | Array of bytes containing a FAT image (or anything if you would like to format) | +| `options` | [`FatFsDiskOptions`](../modules.md#fatfsdiskoptions) | Additional options. See [FatFsDiskOptions](../modules.md#fatfsdiskoptions) for more information. Will return a [FatFsDiskPartitionable](FatFsDiskPartitionable.md) if the `multiPartition` option is true. | + +#### Returns + +`Promise`<[`FatFsDisk`](FatFsDisk.md)\> + +#### Defined in + +[src/fatfs.ts:769](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L769) + +▸ `Static` **create**(`disk`): `Promise`<[`FatFsDisk`](FatFsDisk.md)\> + +Create a new [FatFsDisk](FatFsDisk.md) with defaults + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `disk` | `Uint8Array` | Array of bytes containing a FAT image (or anything if you would like to format) | #### Returns @@ -563,4 +691,4 @@ ___ #### Defined in -src/fatfs.ts:684 +[src/fatfs.ts:776](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L776) diff --git a/docs/classes/FatFsDiskPartitionable.md b/docs/classes/FatFsDiskPartitionable.md new file mode 100644 index 0000000..0e043b0 --- /dev/null +++ b/docs/classes/FatFsDiskPartitionable.md @@ -0,0 +1,866 @@ +[fatfs-wasm](../README.md) / [Exports](../modules.md) / FatFsDiskPartitionable + +# Class: FatFsDiskPartitionable + +Extension of [FatFsDisk](FatFsDisk.md) with extensions for partitioning a FAT drive with up to 4 partitions. + +If multi-partition support is enabled, accessing some types of FAT disks (e.g. floppes) may not work correctly. + +## Hierarchy + +- [`FatFsDisk`](FatFsDisk.md) + + ↳ **`FatFsDiskPartitionable`** + +## Table of contents + +### Constructors + +- [constructor](FatFsDiskPartitionable.md#constructor) + +### Properties + +- [#context](FatFsDiskPartitionable.md##context) +- [#context](FatFsDiskPartitionable.md##context-1) +- [#exports](FatFsDiskPartitionable.md##exports) +- [#exports](FatFsDiskPartitionable.md##exports-1) + +### Methods + +- [chdir](FatFsDiskPartitionable.md#chdir) +- [chdrive](FatFsDiskPartitionable.md#chdrive) +- [chmod](FatFsDiskPartitionable.md#chmod) +- [fdisk](FatFsDiskPartitionable.md#fdisk) +- [find](FatFsDiskPartitionable.md#find) +- [findFirst](FatFsDiskPartitionable.md#findfirst) +- [getFree](FatFsDiskPartitionable.md#getfree) +- [getLabel](FatFsDiskPartitionable.md#getlabel) +- [getcwd](FatFsDiskPartitionable.md#getcwd) +- [mkdir](FatFsDiskPartitionable.md#mkdir) +- [mkfs](FatFsDiskPartitionable.md#mkfs) +- [mount](FatFsDiskPartitionable.md#mount) +- [open](FatFsDiskPartitionable.md#open) +- [openDir](FatFsDiskPartitionable.md#opendir) +- [readFile](FatFsDiskPartitionable.md#readfile) +- [rename](FatFsDiskPartitionable.md#rename) +- [session](FatFsDiskPartitionable.md#session) +- [setCP](FatFsDiskPartitionable.md#setcp) +- [setLabel](FatFsDiskPartitionable.md#setlabel) +- [stat](FatFsDiskPartitionable.md#stat) +- [unlink](FatFsDiskPartitionable.md#unlink) +- [unmount](FatFsDiskPartitionable.md#unmount) +- [utime](FatFsDiskPartitionable.md#utime) +- [writeFile](FatFsDiskPartitionable.md#writefile) +- [create](FatFsDiskPartitionable.md#create) + +## Constructors + +### constructor + +• **new FatFsDiskPartitionable**(`context`, `exports`) + +Private constructor. Use [create](FatFsDisk.md#create) with the `multiPartition` option set to true to create a [FatFsDiskPartitionable](FatFsDiskPartitionable.md). + +#### Parameters + +| Name | Type | +| :------ | :------ | +| `context` | `FatFsMemoryContext` | +| `exports` | `FatFsExports` | + +#### Overrides + +[FatFsDisk](FatFsDisk.md).[constructor](FatFsDisk.md#constructor) + +#### Defined in + +[src/fatfs.ts:1263](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L1263) + +## Properties + +### #context + +• `Private` **#context**: `FatFsMemoryContext` + +#### Inherited from + +[FatFsDisk](FatFsDisk.md).[#context](FatFsDisk.md##context) + +#### Defined in + +[src/fatfs.ts:1257](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L1257) + +___ + +### #context + +• `Private` **#context**: `FatFsMemoryContext` + +#### Inherited from + +FatFsDisk.#context + +#### Defined in + +[src/fatfs.ts:752](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L752) + +___ + +### #exports + +• `Private` **#exports**: `FatFsExports` + +#### Inherited from + +[FatFsDisk](FatFsDisk.md).[#exports](FatFsDisk.md##exports) + +#### Defined in + +[src/fatfs.ts:1258](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L1258) + +___ + +### #exports + +• `Private` **#exports**: `FatFsExports` + +#### Inherited from + +FatFsDisk.#exports + +#### Defined in + +[src/fatfs.ts:753](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L753) + +## Methods + +### chdir + +▸ **chdir**(`path`): `void` + +The f_chdir function changes the current directory of the logical drive. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `path` | `string` | Pointer to the null-terminated string that specifies the directory to be set as current directory. | + +#### Returns + +`void` + +#### Inherited from + +[FatFsDisk](FatFsDisk.md).[chdir](FatFsDisk.md#chdir) + +#### Defined in + +[src/fatfs.ts:1134](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L1134) + +___ + +### chdrive + +▸ **chdrive**(`path`): `void` + +The f_chdrive function changes the current drive. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `path` | `string` | Specifies the logical drive number to be set as the current drive. | + +#### Returns + +`void` + +#### Inherited from + +[FatFsDisk](FatFsDisk.md).[chdrive](FatFsDisk.md#chdrive) + +#### Defined in + +[src/fatfs.ts:1149](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L1149) + +___ + +### chmod + +▸ **chmod**(`path`, `attr`, `mask`): `void` + +The f_chmod function changes the attribute of a file or sub-directory. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `path` | `string` | Pointer to the null-terminated string that specifies an object to be changed | +| `attr` | `number` | Attribute flags to be set in one or more combination. The specified flags are set and others are cleared. | +| `mask` | `number` | Attribute mask that specifies which attribute is changed. The specified attributes are set or cleared and others are left unchanged. | + +#### Returns + +`void` + +OK or error code + +#### Inherited from + +[FatFsDisk](FatFsDisk.md).[chmod](FatFsDisk.md#chmod) + +#### Defined in + +[src/fatfs.ts:1069](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L1069) + +___ + +### fdisk + +▸ **fdisk**(`ptbl`, `pdrv?`): `void` + +The f_fdisk function divides a physical drive. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `ptbl` | `number`[] | List of partition size to create on the drive. | +| `pdrv?` | `number` | Specifies the physical drive to be divided. This is not the logical drive number but the drive identifier passed to the low level disk functions. | + +#### Returns + +`void` + +#### Defined in + +[src/fatfs.ts:1279](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L1279) + +___ + +### find + +▸ **find**(`path`, `pattern`): `IterableIterator`<[`FatFsFileInfo`](FatFsFileInfo.md)\> + +Searches a directory + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `path` | `string` | The directory name to be opened. | +| `pattern` | `string` | The pattern to search for | + +#### Returns + +`IterableIterator`<[`FatFsFileInfo`](FatFsFileInfo.md)\> + +An iterator to the search results + +#### Inherited from + +[FatFsDisk](FatFsDisk.md).[find](FatFsDisk.md#find) + +#### Defined in + +[src/fatfs.ts:991](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L991) + +___ + +### findFirst + +▸ **findFirst**(`path`, `pattern`): [[`FatFsDir`](FatFsDir.md), [`FatFsFileInfo`](FatFsFileInfo.md)] + +Searches a directory for an item. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `path` | `string` | The directory name to be opened. | +| `pattern` | `string` | The pattern to search for | + +#### Returns + +[[`FatFsDir`](FatFsDir.md), [`FatFsFileInfo`](FatFsFileInfo.md)] + +The directory, and the first matching entry + +#### Inherited from + +[FatFsDisk](FatFsDisk.md).[findFirst](FatFsDisk.md#findfirst) + +#### Defined in + +[src/fatfs.ts:966](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L966) + +___ + +### getFree + +▸ **getFree**(`path?`): [`number`, `FatFsObject`] + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `path?` | ``null`` \| `string` | Pointer to the null-terminated string that specifies the logical drive. A null-string means the default drive. | + +#### Returns + +[`number`, `FatFsObject`] + +tuple with the number of free clusters, and a FATFS + object containing number of sectors per cluster. + +#### Inherited from + +[FatFsDisk](FatFsDisk.md).[getFree](FatFsDisk.md#getfree) + +#### Defined in + +[src/fatfs.ts:1182](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L1182) + +___ + +### getLabel + +▸ **getLabel**(`path?`): [`string`, `number`] + +The f_getlabel function returns volume label and volume serial number +of a volume. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `path?` | `string` | Pointer to the null-terminated string that specifies the logical drive. Null-string specifies the default drive. | + +#### Returns + +[`string`, `number`] + +tuple containing the result, the volume label, and the volume + serial number + +#### Inherited from + +[FatFsDisk](FatFsDisk.md).[getLabel](FatFsDisk.md#getlabel) + +#### Defined in + +[src/fatfs.ts:1206](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L1206) + +___ + +### getcwd + +▸ **getcwd**(): `string` + +The f_getcwd function retrieves the current directory of the current +drive. + +#### Returns + +`string` + +The current directory. + +#### Inherited from + +[FatFsDisk](FatFsDisk.md).[getcwd](FatFsDisk.md#getcwd) + +#### Defined in + +[src/fatfs.ts:1164](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L1164) + +___ + +### mkdir + +▸ **mkdir**(`path`): `void` + +The f_mkdir function creates a new directory. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `path` | `string` | Pointer to the null-terminated string that specifies the directory name to create. | + +#### Returns + +`void` + +#### Inherited from + +[FatFsDisk](FatFsDisk.md).[mkdir](FatFsDisk.md#mkdir) + +#### Defined in + +[src/fatfs.ts:1118](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L1118) + +___ + +### mkfs + +▸ **mkfs**(`opt?`): `void` + +The f_mkfs function creates an FAT/exFAT volume on the logical drive. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `opt?` | ``null`` \| [`FatFsMkfsOptions`](../modules.md#fatfsmkfsoptions) | Format options | + +#### Returns + +`void` + +OK or error code + +#### Inherited from + +[FatFsDisk](FatFsDisk.md).[mkfs](FatFsDisk.md#mkfs) + +#### Defined in + +[src/fatfs.ts:805](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L805) + +___ + +### mount + +▸ **mount**(`path?`, `opt?`): `FatFsObject` + +The f_mount function gives work area to the FatFs module. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `path?` | `string` | Pointer to the null-terminated string that specifies the logical drive. The string without drive number means the default drive. | +| `opt?` | `number` | Mounting option. 0: Do not mount now (to be mounted on the first access to the volume), 1: Force mounted the volume to check if it is ready to work. | + +#### Returns + +`FatFsObject` + +reference to the mounted work area + +#### Inherited from + +[FatFsDisk](FatFsDisk.md).[mount](FatFsDisk.md#mount) + +#### Defined in + +[src/fatfs.ts:836](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L836) + +___ + +### open + +▸ **open**(`path`, `mode`): [`FatFsFile`](FatFsFile.md) + +The f_open function opens a file. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `path` | `string` | Pointer to the null-terminated string that specifies the file name to open or create. | +| `mode` | [`FatFsMode`](../enums/FatFsMode.md) | Mode flags that specifies the type of access and open method for the file. It is specified by a combination of following flags. | + +#### Returns + +[`FatFsFile`](FatFsFile.md) + +File object + +#### Inherited from + +[FatFsDisk](FatFsDisk.md).[open](FatFsDisk.md#open) + +#### Defined in + +[src/fatfs.ts:882](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L882) + +___ + +### openDir + +▸ **openDir**(`path`): [`FatFsDir`](FatFsDir.md) + +The f_opendir function opens a directory. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `path` | `string` | Pointer to the null-terminated string that specifies the directory name to be opened. | + +#### Returns + +[`FatFsDir`](FatFsDir.md) + +Directory object + +#### Inherited from + +[FatFsDisk](FatFsDisk.md).[openDir](FatFsDisk.md#opendir) + +#### Defined in + +[src/fatfs.ts:947](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L947) + +___ + +### readFile + +▸ **readFile**(`path`): `Uint8Array` + +Read an entire file. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `path` | `string` | Path to the file to read | + +#### Returns + +`Uint8Array` + +The contents of the file + +#### Inherited from + +[FatFsDisk](FatFsDisk.md).[readFile](FatFsDisk.md#readfile) + +#### Defined in + +[src/fatfs.ts:915](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L915) + +___ + +### rename + +▸ **rename**(`oldName`, `newName`): `void` + +The f_rename function renames and/or moves a file or sub-directory. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `oldName` | `string` | Pointer to a null-terminated string that specifies the existing file or sub-directory to be renamed. | +| `newName` | `string` | Pointer to a null-terminated string that specifies the new object name. A drive number may be specified in this string but it is ignored and assumed as the same drive of the old_name. Any object with this path name except old_name must not be exist, or the function fails with FR_EXIST. | + +#### Returns + +`void` + +OK or error code + +#### Inherited from + +[FatFsDisk](FatFsDisk.md).[rename](FatFsDisk.md#rename) + +#### Defined in + +[src/fatfs.ts:1047](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L1047) + +___ + +### session + +▸ **session**<`T`\>(`action`, `path?`): `ReturnType`<`T`\> + +Mounts the filesystem, executes a user function, and unmounts + +#### Type parameters + +| Name | Type | +| :------ | :------ | +| `T` | extends () => `any` | + +#### Parameters + +| Name | Type | Default value | Description | +| :------ | :------ | :------ | :------ | +| `action` | `T` | `undefined` | The action to perform | +| `path` | `string` | `''` | The logical drive. An empty string without drive number means the default drive. | + +#### Returns + +`ReturnType`<`T`\> + +#### Inherited from + +[FatFsDisk](FatFsDisk.md).[session](FatFsDisk.md#session) + +#### Defined in + +[src/fatfs.ts:901](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L901) + +___ + +### setCP + +▸ **setCP**(`cp`): `void` + +The f_setcp function sets the active code page. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `cp` | `number` | OEM code page to be used for the path name. | + +#### Returns + +`void` + +#### Inherited from + +[FatFsDisk](FatFsDisk.md).[setCP](FatFsDisk.md#setcp) + +#### Defined in + +[src/fatfs.ts:1242](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L1242) + +___ + +### setLabel + +▸ **setLabel**(`label`): `void` + +The f_setlabel function sets/removes the label of a volume. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `label` | `string` | Pointer to the null-terminated string that specifies the volume label to be set. | + +#### Returns + +`void` + +#### Inherited from + +[FatFsDisk](FatFsDisk.md).[setLabel](FatFsDisk.md#setlabel) + +#### Defined in + +[src/fatfs.ts:1228](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L1228) + +___ + +### stat + +▸ **stat**(`path`): [`FatFsFileInfo`](FatFsFileInfo.md) + +The f_stat function checks the existence of a file or sub-directory. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `path` | `string` | Pointer to the null-terminated string that specifies the object to get its information. The object must not be the root direcotry. | + +#### Returns + +[`FatFsFileInfo`](FatFsFileInfo.md) + +OK or error code + +#### Inherited from + +[FatFsDisk](FatFsDisk.md).[stat](FatFsDisk.md#stat) + +#### Defined in + +[src/fatfs.ts:1008](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L1008) + +___ + +### unlink + +▸ **unlink**(`path`): `void` + +The f_unlink function removes a file or sub-directory from the volume. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `path` | `string` | Pointer to a null-terminated string that specifies the file or sub-directory to be removed. | + +#### Returns + +`void` + +#### Inherited from + +[FatFsDisk](FatFsDisk.md).[unlink](FatFsDisk.md#unlink) + +#### Defined in + +[src/fatfs.ts:1026](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L1026) + +___ + +### unmount + +▸ **unmount**(`path?`): `void` + +Unregisters the filesystem object + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `path?` | `string` | Pointer to the null-terminated string that specifies the logical drive. The string without drive number means the default drive. | + +#### Returns + +`void` + +#### Inherited from + +[FatFsDisk](FatFsDisk.md).[unmount](FatFsDisk.md#unmount) + +#### Defined in + +[src/fatfs.ts:858](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L858) + +___ + +### utime + +▸ **utime**(`path`, `time`): `void` + +The f_utime function changes the timestamp of a file or sub-directory. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `path` | `string` | Pointer to the null-terminated string that specifies an object to be changed. | +| `time` | `Date` | Pointer to the file information structure that has a timestamp to be set in member fdate and ftime. Do not care any other members. | + +#### Returns + +`void` + +OK or error code + +#### Inherited from + +[FatFsDisk](FatFsDisk.md).[utime](FatFsDisk.md#utime) + +#### Defined in + +[src/fatfs.ts:1088](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L1088) + +___ + +### writeFile + +▸ **writeFile**(`path`, `contents`): `void` + +Write an entire file. + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `path` | `string` | Path to the file to write | +| `contents` | `Uint8Array` | Contents to write to the file | + +#### Returns + +`void` + +#### Inherited from + +[FatFsDisk](FatFsDisk.md).[writeFile](FatFsDisk.md#writefile) + +#### Defined in + +[src/fatfs.ts:932](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L932) + +___ + +### create + +▸ `Static` **create**(`disk`, `options`): `Promise`<[`FatFsDiskPartitionable`](FatFsDiskPartitionable.md)\> + +Create a new [FatFsDisk](FatFsDisk.md). + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `disk` | `Uint8Array` | Array of bytes containing a FAT image (or anything if you would like to format) | +| `options` | [`FatFsDiskOptions`](../modules.md#fatfsdiskoptions) & { `multiPartition`: ``true`` } | Additional options. See [FatFsDiskOptions](../modules.md#fatfsdiskoptions) for more information. Will return a [FatFsDiskPartitionable](FatFsDiskPartitionable.md) if the `multiPartition` option is true. | + +#### Returns + +`Promise`<[`FatFsDiskPartitionable`](FatFsDiskPartitionable.md)\> + +#### Inherited from + +[FatFsDisk](FatFsDisk.md).[create](FatFsDisk.md#create) + +#### Defined in + +[src/fatfs.ts:761](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L761) + +▸ `Static` **create**(`disk`, `options`): `Promise`<[`FatFsDisk`](FatFsDisk.md)\> + +Create a new [FatFsDisk](FatFsDisk.md). + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `disk` | `Uint8Array` | Array of bytes containing a FAT image (or anything if you would like to format) | +| `options` | [`FatFsDiskOptions`](../modules.md#fatfsdiskoptions) | Additional options. See [FatFsDiskOptions](../modules.md#fatfsdiskoptions) for more information. Will return a [FatFsDiskPartitionable](FatFsDiskPartitionable.md) if the `multiPartition` option is true. | + +#### Returns + +`Promise`<[`FatFsDisk`](FatFsDisk.md)\> + +#### Inherited from + +[FatFsDisk](FatFsDisk.md).[create](FatFsDisk.md#create) + +#### Defined in + +[src/fatfs.ts:769](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L769) + +▸ `Static` **create**(`disk`): `Promise`<[`FatFsDisk`](FatFsDisk.md)\> + +Create a new [FatFsDisk](FatFsDisk.md) with defaults + +#### Parameters + +| Name | Type | Description | +| :------ | :------ | :------ | +| `disk` | `Uint8Array` | Array of bytes containing a FAT image (or anything if you would like to format) | + +#### Returns + +`Promise`<[`FatFsDisk`](FatFsDisk.md)\> + +#### Inherited from + +[FatFsDisk](FatFsDisk.md).[create](FatFsDisk.md#create) + +#### Defined in + +[src/fatfs.ts:776](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L776) diff --git a/docs/classes/FatFsError.md b/docs/classes/FatFsError.md index f0e2619..16ed181 100644 --- a/docs/classes/FatFsError.md +++ b/docs/classes/FatFsError.md @@ -18,6 +18,7 @@ Exception thrown when a FatFs export returns a non-OK result ### Properties +- [cause](FatFsError.md#cause) - [message](FatFsError.md#message) - [name](FatFsError.md#name) - [result](FatFsError.md#result) @@ -48,10 +49,24 @@ Error.constructor #### Defined in -src/fatfs.ts:376 +[src/fatfs.ts:429](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L429) ## Properties +### cause + +• `Optional` **cause**: `unknown` + +#### Inherited from + +Error.cause + +#### Defined in + +node_modules/typescript/lib/lib.es2022.error.d.ts:24 + +___ + ### message • **message**: `string` @@ -86,7 +101,7 @@ ___ #### Defined in -src/fatfs.ts:375 +[src/fatfs.ts:428](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L428) ___ diff --git a/docs/classes/FatFsFile.md b/docs/classes/FatFsFile.md index 539c9a1..71d8f48 100644 --- a/docs/classes/FatFsFile.md +++ b/docs/classes/FatFsFile.md @@ -10,6 +10,12 @@ FatFs file object - [constructor](FatFsFile.md#constructor) +### Properties + +- [#context](FatFsFile.md##context) +- [#exports](FatFsFile.md##exports) +- [#filePtr](FatFsFile.md##fileptr) + ### Accessors - [fp](FatFsFile.md#fp) @@ -48,7 +54,37 @@ FatFs file object #### Defined in -src/fatfs.ts:392 +[src/fatfs.ts:445](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L445) + +## Properties + +### #context + +• `Private` **#context**: `FatFsMemoryContext` + +#### Defined in + +[src/fatfs.ts:443](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L443) + +___ + +### #exports + +• `Private` **#exports**: `FatFsExports` + +#### Defined in + +[src/fatfs.ts:442](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L442) + +___ + +### #filePtr + +• `Private` **#filePtr**: `number` + +#### Defined in + +[src/fatfs.ts:441](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L441) ## Accessors @@ -56,13 +92,15 @@ src/fatfs.ts:392 • `get` **fp**(): `number` +Low level pointer to the file descriptor + #### Returns `number` #### Defined in -src/fatfs.ts:402 +[src/fatfs.ts:458](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L458) ## Methods @@ -78,7 +116,7 @@ The f_close function closes an open file and destroys the file object. #### Defined in -src/fatfs.ts:455 +[src/fatfs.ts:510](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L510) ___ @@ -104,7 +142,7 @@ The f_eof function returns a non-zero value #### Defined in -src/fatfs.ts:579 +[src/fatfs.ts:634](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L634) ___ @@ -129,7 +167,7 @@ Returns a non-zero value if a hard error has occured; #### Defined in -src/fatfs.ts:596 +[src/fatfs.ts:651](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L651) ___ @@ -153,7 +191,7 @@ the file. #### Defined in -src/fatfs.ts:514 +[src/fatfs.ts:569](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L569) ___ @@ -177,7 +215,7 @@ the string #### Defined in -src/fatfs.ts:525 +[src/fatfs.ts:580](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L580) ___ @@ -201,7 +239,7 @@ object. It can also be used to expand the file size #### Defined in -src/fatfs.ts:484 +[src/fatfs.ts:539](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L539) ___ @@ -227,7 +265,7 @@ When the character was written successfuly, it returns number #### Defined in -src/fatfs.ts:543 +[src/fatfs.ts:598](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L598) ___ @@ -254,7 +292,7 @@ When the string was written successfuly, it returns number #### Defined in -src/fatfs.ts:557 +[src/fatfs.ts:612](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L612) ___ @@ -279,7 +317,7 @@ number of bytes read #### Defined in -src/fatfs.ts:412 +[src/fatfs.ts:468](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L468) ___ @@ -293,7 +331,7 @@ ___ #### Defined in -src/fatfs.ts:491 +[src/fatfs.ts:546](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L546) ___ @@ -311,7 +349,7 @@ Returns the size of the file in unit of byte. #### Defined in -src/fatfs.ts:587 +[src/fatfs.ts:642](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L642) ___ @@ -327,7 +365,7 @@ The f_sync function flushes the cached information of a writing file. #### Defined in -src/fatfs.ts:469 +[src/fatfs.ts:524](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L524) ___ @@ -345,7 +383,7 @@ Returns current read/write pointer of the file. #### Defined in -src/fatfs.ts:569 +[src/fatfs.ts:624](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L624) ___ @@ -362,7 +400,7 @@ read/write pointer. #### Defined in -src/fatfs.ts:499 +[src/fatfs.ts:554](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L554) ___ @@ -387,4 +425,4 @@ number of bytes written #### Defined in -src/fatfs.ts:437 +[src/fatfs.ts:493](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L493) diff --git a/docs/classes/FatFsFileInfo.md b/docs/classes/FatFsFileInfo.md index 05846b1..29cc781 100644 --- a/docs/classes/FatFsFileInfo.md +++ b/docs/classes/FatFsFileInfo.md @@ -2,6 +2,8 @@ # Class: FatFsFileInfo +Represents file information returned from [stat](FatFsDisk.md#stat) and iteration functions. + ## Table of contents ### Constructors @@ -44,7 +46,7 @@ #### Defined in -src/fatfs.ts:333 +[src/fatfs.ts:367](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L367) ## Properties @@ -54,7 +56,7 @@ src/fatfs.ts:333 #### Defined in -src/fatfs.ts:330 +[src/fatfs.ts:364](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L364) ___ @@ -64,7 +66,7 @@ ___ #### Defined in -src/fatfs.ts:329 +[src/fatfs.ts:363](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L363) ___ @@ -74,7 +76,7 @@ ___ #### Defined in -src/fatfs.ts:331 +[src/fatfs.ts:365](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L365) ___ @@ -84,7 +86,7 @@ ___ #### Defined in -src/fatfs.ts:328 +[src/fatfs.ts:362](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L362) ## Accessors @@ -92,13 +94,15 @@ src/fatfs.ts:328 • `get` **isArchive**(): `boolean` +Whether or not the file or directory is archived + #### Returns `boolean` #### Defined in -src/fatfs.ts:369 +[src/fatfs.ts:418](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L418) ___ @@ -106,13 +110,15 @@ ___ • `get` **isDirectory**(): `boolean` +Whether or not the filesystem object is a directory or not + #### Returns `boolean` #### Defined in -src/fatfs.ts:367 +[src/fatfs.ts:408](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L408) ___ @@ -120,13 +126,15 @@ ___ • `get` **isHidden**(): `boolean` +Whether or not the file or directory is hidden + #### Returns `boolean` #### Defined in -src/fatfs.ts:368 +[src/fatfs.ts:413](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L413) ___ @@ -134,13 +142,15 @@ ___ • `get` **isReadOnly**(): `boolean` +Whether or not the file or directory is read-only + #### Returns `boolean` #### Defined in -src/fatfs.ts:366 +[src/fatfs.ts:403](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L403) ___ @@ -148,13 +158,15 @@ ___ • `get` **isSystem**(): `boolean` +Whether or not the file or directory is a system file or directory + #### Returns `boolean` #### Defined in -src/fatfs.ts:370 +[src/fatfs.ts:423](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L423) ## Methods @@ -174,4 +186,4 @@ src/fatfs.ts:370 #### Defined in -src/fatfs.ts:340 +[src/fatfs.ts:374](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L374) diff --git a/docs/enums/FatFsAttrib.md b/docs/enums/FatFsAttrib.md index 6740e3f..e9bc6f9 100644 --- a/docs/enums/FatFsAttrib.md +++ b/docs/enums/FatFsAttrib.md @@ -22,7 +22,7 @@ File attribute bits for directory entry (FILINFO.fattrib) #### Defined in -src/fatfs.ts:55 +[src/fatfs.ts:56](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L56) ___ @@ -32,7 +32,7 @@ ___ #### Defined in -src/fatfs.ts:54 +[src/fatfs.ts:55](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L55) ___ @@ -42,7 +42,7 @@ ___ #### Defined in -src/fatfs.ts:52 +[src/fatfs.ts:53](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L53) ___ @@ -52,7 +52,7 @@ ___ #### Defined in -src/fatfs.ts:51 +[src/fatfs.ts:52](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L52) ___ @@ -62,4 +62,4 @@ ___ #### Defined in -src/fatfs.ts:53 +[src/fatfs.ts:54](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L54) diff --git a/docs/enums/FatFsFormat.md b/docs/enums/FatFsFormat.md index 1599d4c..17b13d5 100644 --- a/docs/enums/FatFsFormat.md +++ b/docs/enums/FatFsFormat.md @@ -22,7 +22,7 @@ Format options (2nd argument of f_mkfs) #### Defined in -src/fatfs.ts:21 +[src/fatfs.ts:22](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L22) ___ @@ -32,7 +32,7 @@ ___ #### Defined in -src/fatfs.ts:20 +[src/fatfs.ts:21](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L21) ___ @@ -42,7 +42,7 @@ ___ #### Defined in -src/fatfs.ts:18 +[src/fatfs.ts:19](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L19) ___ @@ -52,7 +52,7 @@ ___ #### Defined in -src/fatfs.ts:19 +[src/fatfs.ts:20](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L20) ___ @@ -62,4 +62,4 @@ ___ #### Defined in -src/fatfs.ts:22 +[src/fatfs.ts:23](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L23) diff --git a/docs/enums/FatFsIoctl.md b/docs/enums/FatFsIoctl.md index a8e0a1b..84d79eb 100644 --- a/docs/enums/FatFsIoctl.md +++ b/docs/enums/FatFsIoctl.md @@ -22,7 +22,7 @@ Disk I/O control commands (for disk_ioctl) #### Defined in -src/fatfs.ts:9 +[src/fatfs.ts:10](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L10) ___ @@ -32,7 +32,7 @@ ___ #### Defined in -src/fatfs.ts:13 +[src/fatfs.ts:14](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L14) ___ @@ -42,7 +42,7 @@ ___ #### Defined in -src/fatfs.ts:12 +[src/fatfs.ts:13](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L13) ___ @@ -52,7 +52,7 @@ ___ #### Defined in -src/fatfs.ts:10 +[src/fatfs.ts:11](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L11) ___ @@ -62,4 +62,4 @@ ___ #### Defined in -src/fatfs.ts:11 +[src/fatfs.ts:12](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L12) diff --git a/docs/enums/FatFsMode.md b/docs/enums/FatFsMode.md index d043c73..3d5d310 100644 --- a/docs/enums/FatFsMode.md +++ b/docs/enums/FatFsMode.md @@ -27,7 +27,7 @@ overwritten. #### Defined in -src/fatfs.ts:82 +[src/fatfs.ts:83](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L83) ___ @@ -40,7 +40,7 @@ existing. #### Defined in -src/fatfs.ts:77 +[src/fatfs.ts:78](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L78) ___ @@ -52,7 +52,7 @@ Opens the file if it is existing. If not, a new file will be created. #### Defined in -src/fatfs.ts:86 +[src/fatfs.ts:87](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L87) ___ @@ -65,7 +65,7 @@ file. #### Defined in -src/fatfs.ts:91 +[src/fatfs.ts:92](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L92) ___ @@ -77,7 +77,7 @@ Opens a file. The function fails if the file is not existing. (Default) #### Defined in -src/fatfs.ts:72 +[src/fatfs.ts:73](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L73) ___ @@ -89,7 +89,7 @@ Specifies read access to the file. Data can be read from the file. #### Defined in -src/fatfs.ts:63 +[src/fatfs.ts:64](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L64) ___ @@ -102,4 +102,4 @@ Combine with FA_READ for read-write access. #### Defined in -src/fatfs.ts:68 +[src/fatfs.ts:69](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L69) diff --git a/docs/enums/FatFsResult.md b/docs/enums/FatFsResult.md index 6ee300f..782aa94 100644 --- a/docs/enums/FatFsResult.md +++ b/docs/enums/FatFsResult.md @@ -35,7 +35,7 @@ #### Defined in -src/fatfs.ts:34 +[src/fatfs.ts:35](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L35) ___ @@ -45,7 +45,7 @@ ___ #### Defined in -src/fatfs.ts:28 +[src/fatfs.ts:29](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L29) ___ @@ -55,7 +55,7 @@ ___ #### Defined in -src/fatfs.ts:35 +[src/fatfs.ts:36](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L36) ___ @@ -65,7 +65,7 @@ ___ #### Defined in -src/fatfs.ts:29 +[src/fatfs.ts:30](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L30) ___ @@ -75,7 +75,7 @@ ___ #### Defined in -src/fatfs.ts:38 +[src/fatfs.ts:39](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L39) ___ @@ -85,7 +85,7 @@ ___ #### Defined in -src/fatfs.ts:33 +[src/fatfs.ts:34](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L34) ___ @@ -95,7 +95,7 @@ ___ #### Defined in -src/fatfs.ts:36 +[src/fatfs.ts:37](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L37) ___ @@ -105,7 +105,7 @@ ___ #### Defined in -src/fatfs.ts:46 +[src/fatfs.ts:47](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L47) ___ @@ -115,7 +115,7 @@ ___ #### Defined in -src/fatfs.ts:43 +[src/fatfs.ts:44](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L44) ___ @@ -125,7 +125,7 @@ ___ #### Defined in -src/fatfs.ts:41 +[src/fatfs.ts:42](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L42) ___ @@ -135,7 +135,7 @@ ___ #### Defined in -src/fatfs.ts:39 +[src/fatfs.ts:40](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L40) ___ @@ -145,7 +145,7 @@ ___ #### Defined in -src/fatfs.ts:44 +[src/fatfs.ts:45](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L45) ___ @@ -155,7 +155,7 @@ ___ #### Defined in -src/fatfs.ts:30 +[src/fatfs.ts:31](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L31) ___ @@ -165,7 +165,7 @@ ___ #### Defined in -src/fatfs.ts:31 +[src/fatfs.ts:32](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L32) ___ @@ -175,7 +175,7 @@ ___ #### Defined in -src/fatfs.ts:40 +[src/fatfs.ts:41](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L41) ___ @@ -185,7 +185,7 @@ ___ #### Defined in -src/fatfs.ts:32 +[src/fatfs.ts:33](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L33) ___ @@ -195,7 +195,7 @@ ___ #### Defined in -src/fatfs.ts:27 +[src/fatfs.ts:28](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L28) ___ @@ -205,7 +205,7 @@ ___ #### Defined in -src/fatfs.ts:42 +[src/fatfs.ts:43](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L43) ___ @@ -215,7 +215,7 @@ ___ #### Defined in -src/fatfs.ts:45 +[src/fatfs.ts:46](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L46) ___ @@ -225,4 +225,4 @@ ___ #### Defined in -src/fatfs.ts:37 +[src/fatfs.ts:38](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L38) diff --git a/docs/modules.md b/docs/modules.md index aabf7c6..c751011 100644 --- a/docs/modules.md +++ b/docs/modules.md @@ -2,6 +2,8 @@ # fatfs-wasm +High-level interface for creating and accessing FAT images using the FatFS library by CHaN. + ## Table of contents ### Enumerations @@ -16,6 +18,54 @@ - [FatFsDir](classes/FatFsDir.md) - [FatFsDisk](classes/FatFsDisk.md) +- [FatFsDiskPartitionable](classes/FatFsDiskPartitionable.md) - [FatFsError](classes/FatFsError.md) - [FatFsFile](classes/FatFsFile.md) - [FatFsFileInfo](classes/FatFsFileInfo.md) + +### Type Aliases + +- [FatFsDiskOptions](modules.md#fatfsdiskoptions) +- [FatFsMkfsOptions](modules.md#fatfsmkfsoptions) + +## Type Aliases + +### FatFsDiskOptions + +Ƭ **FatFsDiskOptions**: `Object` + +Options for creating a [FatFsDisk](classes/FatFsDisk.md). + +#### Type declaration + +| Name | Type | +| :------ | :------ | +| `multiPartition?` | `boolean` | +| `sectorSize?` | `number` | + +#### Defined in + +[src/fatfs.ts:738](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L738) + +___ + +### FatFsMkfsOptions + +Ƭ **FatFsMkfsOptions**: `Object` + +Options provided to [mkfs](classes/FatFsDisk.md#mkfs) + +#### Type declaration + +| Name | Type | +| :------ | :------ | +| `align?` | `number` | +| `auSize?` | `number` | +| `fmt?` | [`FatFsFormat`](enums/FatFsFormat.md) | +| `nFat?` | `number` | +| `nRoot?` | `number` | +| `path?` | `string` | + +#### Defined in + +[src/fatfs.ts:260](https://github.com/parkertomatoes/fatfs-wasm/blob/fa8ebf7/src/fatfs.ts#L260) diff --git a/native/build.sh b/native/build.sh index 47e7c0f..94a020f 100755 --- a/native/build.sh +++ b/native/build.sh @@ -1,10 +1,21 @@ mkdir -p obj clang ./ff15/source/ff.c ./libc/string.c ./libc/walloc.c \ - --target=wasm32 `# use webassembly` \ - -nostdlib `# don't include libc` \ - -I./libc `# allow code to find libc substitute` \ - -Wl,--no-entry `# no "main" function` \ - -Wl,--export-all `# export all functions into wasm` \ - -Wl,--import-memory `# let JS define memory` \ - -Os `# optimize for size` \ - -o ../src/ff.wasm + -DFF_MULTI_PARTITION=1 `# build with multi-partition option` \ + --target=wasm32 `# use webassembly` \ + -nostdlib `# don't include libc` \ + -I./libc `# allow code to find libc substitute` \ + -Wl,--no-entry `# no "main" function` \ + -Wl,--export-all `# export all functions into wasm` \ + -Wl,--import-memory `# let JS define memory` \ + -Os `# optimize for size` \ + -o ../src/ff_multi.wasm +clang ./ff15/source/ff.c ./libc/string.c ./libc/walloc.c \ + -DFF_MULTI_PARTITION=0 `# build without multi-partition option` \ + --target=wasm32 `# use webassembly` \ + -nostdlib `# don't include libc` \ + -I./libc `# allow code to find libc substitute` \ + -Wl,--no-entry `# no "main" function` \ + -Wl,--export-all `# export all functions into wasm` \ + -Wl,--import-memory `# let JS define memory` \ + -Os `# optimize for size` \ + -o ../src/ff_single.wasm diff --git a/native/ff15/source/diskio.c b/native/ff15/source/diskio.c index 3008c10..5df0c5c 100644 --- a/native/ff15/source/diskio.c +++ b/native/ff15/source/diskio.c @@ -31,7 +31,7 @@ DSTATUS disk_status ( { if (pdrv != 0 || ram_disk.initialized == 0) return STA_NOINIT; - ram_disk.initialized = + ram_disk.initialized = 1; return 0; } diff --git a/native/ff15/source/diskio.h b/native/ff15/source/diskio.h index d7067aa..f0d8199 100644 --- a/native/ff15/source/diskio.h +++ b/native/ff15/source/diskio.h @@ -24,10 +24,11 @@ typedef enum { /*---------------------------------------*/ /* Prototypes for disk control functions */ - +#if FF_MULTI_PARTITION PARTITION VolToPart[FF_VOLUMES] = { { 0, 1 } // "0:" ==> 1st partition in PD#0 }; +#endif __attribute__((import_module("env"), import_name("disk_initialize"))) DSTATUS disk_initialize (BYTE pdrv); diff --git a/native/ff15/source/ff.h b/native/ff15/source/ff.h index a291610..e03e6e2 100644 --- a/native/ff15/source/ff.h +++ b/native/ff15/source/ff.h @@ -252,6 +252,7 @@ typedef struct { /* Format parameter structure (MKFS_PARM) */ +#pragma pack(push, 1) typedef struct { BYTE fmt; /* Format option (FM_FAT, FM_FAT32, FM_EXFAT and FM_SFD) */ BYTE n_fat; /* Number of FATs */ @@ -259,6 +260,7 @@ typedef struct { UINT n_root; /* Number of root directory entries */ DWORD au_size; /* Cluster size (byte) */ } MKFS_PARM; +#pragma pack(pop) /* File function return code (FRESULT) */ diff --git a/native/ff15/source/ffconf.h b/native/ff15/source/ffconf.h index 8728168..48de5a8 100644 --- a/native/ff15/source/ffconf.h +++ b/native/ff15/source/ffconf.h @@ -184,7 +184,7 @@ */ -#define FF_MULTI_PARTITION 1 +//#define FF_MULTI_PARTITION 1 // (defined in build) /* 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. diff --git a/package.dist.json b/package.dist.json index 60a1664..8760550 100644 --- a/package.dist.json +++ b/package.dist.json @@ -1,13 +1,19 @@ { "name": "fatfs-wasm", - "version": "2.0.2", + "version": "3.0.1", "description": "High level bindings over a WASM port of FatFS by ChaN", "main": "./fatfs.min.js", + "typings": "fatfs.d.ts", "exports": { - "import": "./fatfs.min.mjs", - "require": "./fatfs.min.js" + "import": { + "default": "./fatfs.min.mjs", + "types": "./fatfs.d.ts" + }, + "require": { + "default": "./fatfs.min.js", + "types": "./fatfs.d.ts" + } }, - "typings": "fatfs.d.ts", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, diff --git a/package.json b/package.json index 052c250..983660d 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,12 @@ { "name": "fatfs-wasm", - "version": "2.0.1", + "version": "3.0.1", "description": "High level bindings over a WASM port of FatFS by ChaN", "main": "dist/fatfs.min.js", "module": "dist/fatfs.min.mjs", "scripts": { "build": "rollup -c", + "buildDocs": "typedoc", "test": "jest" }, "author": "parkertomatoes", diff --git a/rollup.config.mjs b/rollup.config.mjs index 72e89a6..5441974 100644 --- a/rollup.config.mjs +++ b/rollup.config.mjs @@ -17,7 +17,9 @@ export default [{ }], external: ['node:path', 'node:url', 'node:fs/promises'], plugins: [ - typescript(), + typescript({ + rootDir: './src' + }), terser({ sourceMap: { includeSources: true, @@ -26,7 +28,9 @@ export default [{ }), copy({ targets: [ - { src: './src/ff.wasm', dest: 'dist' }, + { src: './README.md', dest: 'dist' }, + { src: './src/ff_multi.wasm', dest: 'dist' }, + { src: './src/ff_single.wasm', dest: 'dist' }, { src: './package.dist.json', dest: 'dist', rename: 'package.json' } ] }) diff --git a/src/fatfs.ts b/src/fatfs.ts index 347ffe2..55b6fe4 100644 --- a/src/fatfs.ts +++ b/src/fatfs.ts @@ -1,3 +1,8 @@ +/** + * High-level interface for creating and accessing FAT images using the FatFS library by CHaN. + * @module fatfs-wasm + */ + /* CONSTANTS */ /** Disk I/O control commands (for disk_ioctl) */ @@ -87,7 +92,6 @@ export enum FatFsMode { OPEN_APPEND = 0x30 } - const FF_MAX_SS = 512; /** Max sector size (must match ffconf.h) */ const DEFAULT_SECTOR_SIZE = 512; /** Default sector size */ const SIZE_FILINFO = 24; @@ -98,11 +102,14 @@ const OFFSET_FATFS_CSIZE = 10; /* HELPER FUNCTIONS */ -async function getWasm(importObject: WebAssembly.Imports) { +async function getWasm(importObject: WebAssembly.Imports, options: FatFsDiskOptions) { if (typeof window !== 'undefined') { // Browser const url = import.meta.url const parentUrl = url.substring( 0, url.lastIndexOf( "/" ) + 1); - return await WebAssembly.instantiateStreaming(fetch(`${parentUrl}/ff.wasm`), importObject); + const wasmUrl = options?.multiPartition + ? `${parentUrl}/ff_multi.wasm` + : `${parentUrl}/ff_single.wasm` + return await WebAssembly.instantiateStreaming(fetch(wasmUrl), importObject); } // NodeJS: use ESM syntax and let rollup convert to CommonJS @@ -110,7 +117,9 @@ async function getWasm(importObject: WebAssembly.Imports) { const { join, dirname } = await import('node:path'); const { fileURLToPath } = await import('node:url'); const filePath = fileURLToPath(import.meta.url); - const wasmPath = join(dirname(filePath), 'ff.wasm'); + const wasmPath = join(dirname(filePath), options?.multiPartition + ? 'ff_multi.wasm' + : 'ff_single.wasm'); const wasmData = await readFile(wasmPath); return await WebAssembly.instantiate(wasmData, importObject); } @@ -125,13 +134,11 @@ function throwIfError(actionName: string, action: () => FatFsResult, onError?: ( function createImportObject( memory: WebAssembly.Memory, - heap: Uint8Array, - view: DataView, disk: Uint8Array, sectorSize?: number ): WebAssembly.Imports { const ss = (sectorSize ?? DEFAULT_SECTOR_SIZE) | 0; - const sectorCount = (heap.byteLength / ss) | 0; + const sectorCount = (disk.byteLength / ss) | 0; return { env: { @@ -144,15 +151,18 @@ function createImportObject( }, disk_read: (pdrv: number, buff: number, sector: number, count: number) => { const src = disk.subarray(sector * ss, (sector + count) * ss); + const heap = new Uint8Array(memory.buffer); heap.set(src, buff); return FatFsResult.OK; }, disk_write: (pdrv: number, buff: number, sector: number, count: number) => { + const heap = new Uint8Array(memory.buffer); const src = heap.subarray(buff, buff + (count * ss)); disk.set(src, sector * ss); return FatFsResult.OK; }, disk_ioctl: (pdrv: number, cmd: number, buff: number) => { + const view = new DataView(memory.buffer); switch (cmd) { case FatFsIoctl.CTRL_SYNC: // Nothing to do for this command if each write operation @@ -198,7 +208,6 @@ function createImportObject( /* STRUCTURES */ - type FatFsExports = { malloc: (size: number) => number; free: (ptr: number) => void; @@ -245,12 +254,16 @@ type HeapScope = { allocString: (text: string | null) => number; }; -type FatFsMkfsOptions = { - fmt: FatFsFormat; /* Format option (FM_FAT, FM_FAT32, FM_EXFAT and FM_SFD) */ - nFat: number; /* Number of FATs */ - align: number; /* Data area alignment (sector) */ - nRoot: number; /* Number of root directory entries */ - auSize: number; /* Cluster size (byte) */ +/** + * Options provided to {@link FatFsDisk.mkfs} + */ +export type FatFsMkfsOptions = { + fmt?: FatFsFormat; /* Format option (FM_FAT, FM_FAT32, FM_EXFAT and FM_SFD) */ + nFat?: number; /* Number of FATs */ + align?: number; /* Data area alignment (sector) */ + nRoot?: number; /* Number of root directory entries */ + auSize?: number; /* Cluster size (byte) */ + path?: string; /* Drive number to format. Empty string uses default drive */ } class FatFsObject { @@ -274,16 +287,22 @@ class FatFsObject { } class FatFsMemoryContext { - readonly heap: Uint8Array; - readonly view: DataView; + #memory: WebAssembly.Memory; #exports: FatFsExports; constructor(memory: WebAssembly.Memory, exports: FatFsExports) { - this.heap = new Uint8Array(memory.buffer); - this.view = new DataView(memory.buffer); + this.#memory = memory; this.#exports = exports; } + get heap() { + return new Uint8Array(this.#memory.buffer); + } + + get view() { + return new DataView(this.#memory.buffer); + } + allocString(text: string | null): number { if (typeof text === 'undefined' || text === null) return 0; @@ -336,11 +355,14 @@ class FatFsMemoryContext { } } +/** + * Represents file information returned from {@link FatFsDisk.stat} and iteration functions. + */ export class FatFsFileInfo { - readonly size: number; - readonly date: Date; - readonly attrib: number; - readonly name: string; + readonly size: number; /** The size of the file or directory */ + readonly date: Date; /** The last modified date of the file or directory */ + readonly attrib: number; /** File attribute flags (see is* methods to get specific flags) */ + readonly name: string; /** The name of the file or directory */ constructor(size: number, date: Date, attrib: number, name: string) { this.size = size; @@ -375,10 +397,29 @@ export class FatFsFileInfo { return new FatFsFileInfo(size, date, attrib, name); } + /** + * Whether or not the file or directory is read-only + */ get isReadOnly(): boolean { return !!(this.attrib & FatFsAttrib.RDO); } + + /** + * Whether or not the filesystem object is a directory or not + */ get isDirectory(): boolean { return !!(this.attrib & FatFsAttrib.DIR); } + + /** + * Whether or not the file or directory is hidden + */ get isHidden(): boolean { return !!(this.attrib & FatFsAttrib.HID); } + + /** + * Whether or not the file or directory is archived + */ get isArchive(): boolean { return !!(this.attrib & FatFsAttrib.ARC); } + + /** + * Whether or not the file or directory is a system file or directory + */ get isSystem(): boolean { return !!(this.attrib & FatFsAttrib.SYS); } } @@ -411,6 +452,9 @@ export class FatFsFile { this.#context = context; } + /** + * Low level pointer to the file descriptor + */ get fp() { return this.#filePtr; } @@ -688,21 +732,63 @@ export class FatFsDir { } } +/** + * Options for creating a {@link FatFsDisk}. + */ +export type FatFsDiskOptions = { + sectorSize?: number; /** The size of the filesystem disk sectors, in bytes. Uses 512 if not provided. */ + multiPartition?: boolean; /** Whether or not to enable multi-partition disks, which enables {@link FatFsDisk#fdisk} */ +} + +const FATFS_DISK_OPTION_DEFAULTS: Required = { + multiPartition: false, + sectorSize: DEFAULT_SECTOR_SIZE +} + +/** + * Represents a FAT filesystem over an array of bytes + */ export class FatFsDisk { #context: FatFsMemoryContext #exports: FatFsExports; - static async create(disk: Uint8Array, sectorSize?: number): Promise { + /** + * @overload + * Create a new {@link FatFsDisk}. + * @param disk Array of bytes containing a FAT image (or anything if you would like to format) + * @param options Additional options. See {@link FatFsDiskOptions} for more information. Will return a {@link FatFsDiskPartitionable} if the `multiPartition` option is true. + */ + static async create(disk: Uint8Array, options: FatFsDiskOptions & { multiPartition: true }): Promise; + + /** + * @overload + * Create a new {@link FatFsDisk}. + * @param disk Array of bytes containing a FAT image (or anything if you would like to format) + * @param options Additional options. See {@link FatFsDiskOptions} for more information. Will return a {@link FatFsDiskPartitionable} if the `multiPartition` option is true. + */ + static async create(disk: Uint8Array, options: FatFsDiskOptions): Promise; + + /** + * @overload + * Create a new {@link FatFsDisk} with defaults + * @param disk Array of bytes containing a FAT image (or anything if you would like to format) + */ + static async create(disk: Uint8Array): Promise; + static async create(disk: Uint8Array, options?: FatFsDiskOptions): Promise { const memory = new WebAssembly.Memory({ initial: 8 }); - const heap = new Uint8Array(memory.buffer); - const view = new DataView(memory.buffer); - const importObject = createImportObject(memory, heap, view, disk, sectorSize); - const source = await getWasm(importObject); + const validOptions = { ...FATFS_DISK_OPTION_DEFAULTS, ...(options ?? {}) }; + const importObject = createImportObject(memory, disk, validOptions.sectorSize); + const source = await getWasm(importObject, validOptions); const exports = source.instance.exports as FatFsExports; const context = new FatFsMemoryContext(memory, exports); - return new FatFsDisk(context, exports); + return validOptions.multiPartition + ? new FatFsDiskPartitionable(context, exports) + : new FatFsDisk(context, exports); } + /** + * Private constructor. Use {@link FatFsDisk.create} to create a {@link FatFsDisk} object. + */ constructor( context: FatFsMemoryContext, exports: FatFsExports, @@ -711,43 +797,23 @@ export class FatFsDisk { this.#exports = exports; } - /** - * The f_fdisk function divides a physical drive. - * @param pdrv Specifies the physical drive to be divided. This is not the - * logical drive number but the drive identifier passed to the low - * level disk functions. - * @param ptbl List of partition size to create on the drive. - */ - fdisk(pdrv: number, ptbl: number[]): void { - this.#context.enterScope(scope => { - const workAreaPtr = scope.alloc(FF_MAX_SS); - const ptblPtr = scope.alloc(ptbl.length * 4); - for (let i = 0; i < ptbl.length; i++) - this.#context.view.setUint32(ptblPtr + (i * 4), ptbl[i]); - throwIfError( - "partitioning disk", - () => this.#exports.f_fdisk(pdrv, ptblPtr, workAreaPtr) - ); - }); - } - /** * The f_mkfs function creates an FAT/exFAT volume on the logical drive. - * @param path Logical drive number * @param opt Format options * @returns OK or error code */ - mkfs(path: string, opt?: FatFsMkfsOptions | null): void { + mkfs(opt?: FatFsMkfsOptions | null): void { this.#context.enterScope(scope => { - const pathPtr = scope.allocString(path); + const pathPtr = scope.allocString(opt?.path ?? ''); let optPtr = 0; if (typeof opt !== 'undefined' && opt !== null) { optPtr = scope.alloc(16); const view = this.#context.view; - view.setUint8(optPtr + 1, opt.nFat); - view.setUint32(optPtr + 4, opt.align, true); - view.setUint32(optPtr + 8, opt.nRoot, true); - view.setUint32(optPtr + 12, opt.auSize, true); + view.setUint8(optPtr, opt?.fmt ?? 0); + view.setUint8(optPtr + 1, opt?.nFat ?? 0); + view.setUint32(optPtr + 2, opt?.align ?? 0, true); + view.setUint32(optPtr + 6, opt?.nRoot ?? 0, true); + view.setUint32(optPtr + 10, opt?.auSize ?? 0, true); } const workAreaPtr = scope.alloc(4096); throwIfError( @@ -767,16 +833,16 @@ export class FatFsDisk { * volume to check if it is ready to work. * @returns reference to the mounted work area */ - mount(path: string, opt: number): FatFsObject { + mount(path?: string, opt?: number): FatFsObject { const malloc = (size: number) => this.#context.alloc(size); return this.#context.enterScope(scope => { const fsPtr = malloc(SIZE_FATFS_OBJ); for (let i = 0; i < SIZE_FATFS_OBJ; i++) this.#context.heap[fsPtr + i] = 0; - const pathPtr = scope.allocString(path); + const pathPtr = scope.allocString(path ?? ''); throwIfError( "mounting workspace", - () => this.#exports.f_mount(fsPtr, pathPtr, opt), + () => this.#exports.f_mount(fsPtr, pathPtr, opt ?? 0), () => this.#context.free(fsPtr) ); return new FatFsObject(fsPtr, this.#context); @@ -789,17 +855,17 @@ export class FatFsDisk { * the logical drive. The string without drive number means the * default drive. */ - unmount(path: string): void { + unmount(path?: string): void { return this.#context.enterScope(scope => { - const [, fs] = this.getFree(path); + //const [, fs] = this.getFree(path ?? ''); try { - const pathPtr = scope.allocString(path); + const pathPtr = scope.allocString(path ?? ''); throwIfError( "unmounting workspace", () => this.#exports.f_mount(0, pathPtr, 0) ); } finally { - this.#context.free(fs.ptr); + //this.#context.free(fs.ptr); } }); } @@ -826,6 +892,52 @@ export class FatFsDisk { }); } + /** + * Mounts the filesystem, executes a user function, and unmounts + * @param action The action to perform + * @param path The logical drive. An empty string without drive number + * means the default drive. + */ + session any>(action: T, path: string = ''): ReturnType { + this.mount(path); + try { + return action(); + } finally { + this.unmount(path); + } + } + + /** + * Read an entire file. + * @param path Path to the file to read + * @returns The contents of the file + */ + readFile(path: string): Uint8Array { + const info = this.stat(path); + const result = new Uint8Array(info.size); + const file = this.open(path, FatFsMode.READ); + try { + file.read(result); + return result; + } finally { + file.close(); + } + } + + /** + * Write an entire file. + * @param path Path to the file to write + * @param contents Contents to write to the file + */ + writeFile(path: string, contents: Uint8Array): void { + const file = this.open(path, FatFsMode.WRITE | FatFsMode.OPEN_ALWAYS); + try { + file.write(contents); + } finally { + file.close(); + } + } + /** * The f_opendir function opens a directory. * @param path Pointer to the null-terminated string that specifies the @@ -1067,9 +1179,9 @@ export class FatFsDisk { * @returns tuple with the number of free clusters, and a FATFS * object containing number of sectors per cluster. */ - getFree(path: string | null): [number, FatFsObject] { + getFree(path?: string | null): [number, FatFsObject] { return this.#context.enterScope(scope => { - const pathPtr = scope.allocString(path); + const pathPtr = scope.allocString(path ?? ''); const nclst = scope.alloc(4); const fatfsPtr = scope.alloc(4); throwIfError( @@ -1091,9 +1203,9 @@ export class FatFsDisk { * @returns tuple containing the result, the volume label, and the volume * serial number */ - getLabel(path: string): [string, number] { + getLabel(path?: string): [string, number] { return this.#context.enterScope(scope => { - const pathPtr = scope.allocString(path); + const pathPtr = scope.allocString(path ?? ''); const label = scope.alloc(13); this.#context.heap[label + 12] = 0; const vsn = scope.alloc(4); @@ -1135,3 +1247,45 @@ export class FatFsDisk { ); } } + +/** + * Extension of {@link FatFsDisk} with extensions for partitioning a FAT drive with up to 4 partitions. + * + * If multi-partition support is enabled, accessing some types of FAT disks (e.g. floppes) may not work correctly. + */ +export class FatFsDiskPartitionable extends FatFsDisk { + #context: FatFsMemoryContext; + #exports: FatFsExports; + + /** + * Private constructor. Use {@link FatFsDisk.create} with the `multiPartition` option set to true to create a {@link FatFsDiskPartitionable}. + */ + constructor( + context: FatFsMemoryContext, + exports: FatFsExports, + ) { + super(context, exports); + this.#context = context; + this.#exports = exports; + } + + /** + * The f_fdisk function divides a physical drive. + * @param ptbl List of partition size to create on the drive. + * @param pdrv Specifies the physical drive to be divided. This is not the + * logical drive number but the drive identifier passed to the low + * level disk functions. + */ + fdisk(ptbl: number[], pdrv?: number): void { + this.#context.enterScope(scope => { + const workAreaPtr = scope.alloc(FF_MAX_SS); + const ptblPtr = scope.alloc(ptbl.length * 4); + for (let i = 0; i < ptbl.length; i++) + this.#context.view.setUint32(ptblPtr + (i * 4), ptbl[i]); + throwIfError( + "partitioning disk", + () => this.#exports.f_fdisk(pdrv ?? 0, ptblPtr, workAreaPtr) + ); + }); + } +} diff --git a/src/ff.wasm b/src/ff.wasm deleted file mode 100755 index 8323e1d3ae61432d07da3e141553e8075087da50..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 22829 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 diff --git a/src/ff_multi.wasm b/src/ff_multi.wasm new file mode 100755 index 0000000000000000000000000000000000000000..aa6ef4a08e54ab4695204eeb0e21c834dff7b91c GIT binary patch literal 22884 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 literal 0 HcmV?d00001 diff --git a/src/ff_single.wasm b/src/ff_single.wasm new file mode 100755 index 0000000000000000000000000000000000000000..c72263cc1f2d8bde5d29e84d39d07e3a2db5712f GIT binary patch literal 22493 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 U-4_lrUD;D#nY(Lo9~}3;0MS@M+yDRo literal 0 HcmV?d00001 diff --git a/test/fatfs.test.ts b/test/fatfs.test.ts index 885a600..f851326 100644 --- a/test/fatfs.test.ts +++ b/test/fatfs.test.ts @@ -1,21 +1,35 @@ import { describe, expect, test, beforeEach } from 'vitest' -import { FatFsDisk, FatFsMode, FatFsAttrib } from '../src/fatfs'; +import { FatFsDisk, FatFsMode, FatFsAttrib, FatFsFormat } from '../src/fatfs'; import { readFile } from 'fs/promises'; import path from 'path'; describe('FatFs Disk Tests', () => { test('should partition without error', async () => { const data = new Uint8Array(1<<16); // 8MB - const disk = await FatFsDisk.create(data); - disk.fdisk(0, [100]); + const disk = await FatFsDisk.create(data, { multiPartition: true }); + disk.fdisk([100]); }); test('should format without error', async () => { const data = await readFile(path.join(__dirname, 'assets/emptyPartition.img')); - const disk = await FatFsDisk.create(new Uint8Array(data)); - disk.mkfs(''); + const disk = await FatFsDisk.create(new Uint8Array(data), { multiPartition: true }); + disk.mkfs(); }); + test('should format using options without error', async () => { + const data = await readFile(path.join(__dirname, 'assets/emptyPartition.img')); + const disk = await FatFsDisk.create(new Uint8Array(data), { multiPartition: true }); + disk.mkfs({ + fmt: FatFsFormat.FAT, + nFat: 0, // default + align: 0, // default + nRoot: 0, // default + auSize: 0, // default + path: '' // default + }); + }); + + test('should mount a workspace without error', async () => { const data = await readFile(path.join(__dirname, 'assets/emptyFormattedVolume.img')); const disk = await FatFsDisk.create(new Uint8Array(data)); diff --git a/tsconfig.json b/tsconfig.json index 6e96810..f79c308 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -12,7 +12,7 @@ "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ "declarationMap": true, "declarationDir": "./dist", - "rootDir": "./src", + "rootDir": ".", "sourceMap": true, /* Create source map files for emitted JavaScript files. */ "inlineSourceMap": false, /* Include sourcemap files inside the emitted JavaScript. */ "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ diff --git a/typedoc.json b/typedoc.json new file mode 100644 index 0000000..1776d28 --- /dev/null +++ b/typedoc.json @@ -0,0 +1,7 @@ +{ + "$schema": "https://typedoc-plugin-markdown.org/schema.json", + "entryPoints": ["./src/fatfs.ts"], + "out": "docs", + "plugin": ["typedoc-plugin-markdown"], +} + \ No newline at end of file