Update README.md
[mfat.git] / mfat.h
blob6e317f75a7147d7fd08333882139430fd3f6c394
1 //--------------------------------------------------------------------------------------------------
2 // Copyright (C) 2022 Marcus Geelnard
3 //
4 // Redistribution and use in source and binary forms, with or without modification, are permitted
5 // provided that the following conditions are met:
6 //
7 // 1. Redistributions of source code must retain the above copyright notice, this list of
8 // conditions and the following disclaimer.
9 //
10 // 2. Redistributions in binary form must reproduce the above copyright notice, this list of
11 // conditions and the following disclaimer in the documentation and/or other materials provided
12 // with the distribution.
14 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
15 // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
16 // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
17 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
20 // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
21 // WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22 //--------------------------------------------------------------------------------------------------
24 //--------------------------------------------------------------------------------------------------
25 // MFAT - A minimal I/O library for FAT (File Allocation Table) volumes
27 // The API of this library is modelled after the POSIX.1-2017 file I/O C API:s (but it is not fully
28 // POSIX compliant).
29 //--------------------------------------------------------------------------------------------------
31 #ifndef MFAT_H_
32 #define MFAT_H_
34 #include <stdint.h>
36 #ifdef __cplusplus
37 extern "C" {
38 #endif
40 // Block size.
41 #define MFAT_BLOCK_SIZE 512
43 // Flags for mfat_open().
44 #define MFAT_O_RDONLY 1
45 #define MFAT_O_WRONLY 2
46 #define MFAT_O_RDWR (MFAT_O_RDONLY | MFAT_O_WRONLY)
47 #define MFAT_O_APPEND 4
48 #define MFAT_O_CREAT 8
49 #define MFAT_O_DIRECTORY 16
51 // Whence values for mfat_lseek().
52 #define MFAT_SEEK_SET 0 ///< The offset is set to offset bytes.
53 #define MFAT_SEEK_CUR 1 ///< The offset is set to its current location plus offset bytes.
54 #define MFAT_SEEK_END 2 ///< The offset is set to the size of the file plus offset bytes.
56 // Values for mfat_stat_t.st_mode (OR:able bits).
57 #define MFAT_S_IFREG 0x8000 ///< Regular file.
58 #define MFAT_S_IFDIR 0x4000 ///< Directory.
59 #define MFAT_S_IRUSR 0x0100 ///< R for owner.
60 #define MFAT_S_IWUSR 0x0080 ///< W for owner.
61 #define MFAT_S_IXUSR 0x0040 ///< X for owner.
62 #define MFAT_S_IRGRP 0x0020 ///< R for group (same as MFAT_S_IRUSR).
63 #define MFAT_S_IWGRP 0x0010 ///< W for group (same as MFAT_S_IWUSR).
64 #define MFAT_S_IXGRP 0x0008 ///< X for group (same as MFAT_S_IXUSR).
65 #define MFAT_S_IROTH 0x0004 ///< R for other (same as MFAT_S_IRUSR).
66 #define MFAT_S_IWOTH 0x0002 ///< W for other (same as MFAT_S_IWUSR).
67 #define MFAT_S_IXOTH 0x0001 ///< X for other (same as MFAT_S_IXUSR).
69 // Macros for decoding the st_mode field of mfat_stat_t.
70 #define MFAT_S_ISREG(m) (((m)&MFAT_S_IFREG) != 0U)
71 #define MFAT_S_ISDIR(m) (((m)&MFAT_S_IFDIR) != 0U)
73 // Maximum length of a filename (for mfat_dirent_t).
74 #define MFAT_NAME_MAX 12
76 // The values of this struct are compatible with struct tm in <time.h>, so it is easy to convert the
77 // date/time to other representations using mktime(), for instance.
78 typedef struct {
79 uint16_t year; ///< Year (1980-2235).
80 uint8_t month; ///< Month of year (1-12).
81 uint8_t day; ///< Day of month (1-31).
82 uint8_t hour; ///< Hour of day (0-23).
83 uint8_t minute; ///< Minute of hour (0-59).
84 uint8_t second; ///< Second of minute (0-59).
85 } mfat_time_t;
87 typedef struct {
88 uint32_t st_mode; ///< File permission bits plus MFAT_S_IFREG or MFAT_S_IFDIR.
89 uint32_t st_size; ///< Size in bytes.
90 mfat_time_t st_mtim; ///< Modification time.
91 } mfat_stat_t;
93 typedef struct {
94 char d_name[MFAT_NAME_MAX + 1]; ///< Filename of the directory entry.
95 } mfat_dirent_t;
97 struct mfat_dir_struct;
98 typedef struct mfat_dir_struct mfat_dir_t;
100 /// @brief Block reader function pointer.
101 /// @param ptr Pointer to the buffer to read to.
102 /// @param block_no The block to read (relative to start of the storage medium).
103 /// @param custom The custom data pointer that was passed to mfat_init().
104 /// @returns zero (0) on success, or -1 on failure.
105 typedef int (*mfat_read_block_fun_t)(char* ptr, unsigned block_no, void* custom);
107 /// @brief Block writer function pointer.
108 /// @param ptr Pointer to the buffer to write from.
109 /// @param block_no The block to write (relative to start of the storage medium).
110 /// @param custom The custom data pointer that was passed to mfat_init().
111 /// @returns zero (0) on success, or -1 on failure.
112 typedef int (*mfat_write_block_fun_t)(const char* ptr, unsigned block_no, void* custom);
114 /// @brief Mount FAT volumes.
116 /// The provided read and write functions implement access to the storage medium, and the optional
117 /// custom data pointer can be used by these functions for keeping track of necessary state.
119 /// Before the function returns, it will identify and "mount" all FAT volumes on the storage medium.
120 /// If no FAT volumes are found, the function will return -1 (indicating failure).
122 /// This function needs to be called before calling any other library functions.
123 /// @param read_fun A block reader function pointer.
124 /// @param write_fun A block writer function pointer.
125 /// @param custom A custom data handle that is passed to the read/write functions (may be NULL).
126 /// @returns zero (0) on success, or -1 on failure.
127 int mfat_mount(mfat_read_block_fun_t read_fun, mfat_write_block_fun_t write_fun, void* custom);
129 /// @brief Unmount all FAT volumes.
131 /// Any pending write operations will be flushed to the storage medium.
132 void mfat_unmount(void);
134 /// @brief Select which partition to use.
135 /// @param partition_no The partition number.
136 /// @returns zero (0) on success, or -1 on failure.
137 int mfat_select_partition(int partition_no);
139 /// @brief Flush pending data updates to storage.
140 void mfat_sync(void);
142 /// @brief Obtain information about a open file.
143 /// @param fd The file descriptor.
144 /// @param stat Pointer to a stat structure into which information is placed concerning the file.
145 /// @returns zero (0) on success, or -1 on failure.
146 int mfat_fstat(int fd, mfat_stat_t* stat);
148 /// @brief Obtain information about a file.
149 /// @param path The path to the file.
150 /// @param stat Pointer to a stat structure into which information is placed concerning the file.
151 /// @returns zero (0) on success, or -1 on failure.
152 int mfat_stat(const char* path, mfat_stat_t* stat);
154 /// @brief Open a file.
155 /// @param path The path to the file.
156 /// @param oflag The open flags (OR of MFAT_O_* flags).
157 /// @returns a non-negative integer representing the lowest numbered unused file descriptor, or -1
158 /// on failure.
159 /// @note Be aware that valid file descriptors are in the range 0..N-1, where N is the maximum
160 /// number of file descriptors (defined at compile time). This is in contrast to most POSIX
161 /// systems where 0, 1 and 2 are usually reserved for stdin, stdout and stderr, respectively.
162 int mfat_open(const char* path, int oflag);
164 /// @brief Close a file descriptor.
165 /// @param fd The file descriptor.
166 /// @returns zero (0) on success, or -1 on failure.
167 int mfat_close(int fd);
169 /// @brief Read from a file.
170 /// @param fd The file descriptor.
171 /// @param buf Buffer to read data into.
172 /// @param nbyte Number of bytes to read.
173 /// @returns a non-negative integer indicating the number of bytes actually read if the operation
174 /// was succesful, zero (0) if the seek offset was at the end of the file when the function was
175 /// called, or -1 on failure.
176 int64_t mfat_read(int fd, void* buf, uint32_t nbyte);
178 /// @brief Write to a file.
179 /// @param fd The file descriptor.
180 /// @param buf Buffer that contains the data to write.
181 /// @param nbyte Number of bytes to write.
182 /// @returns a non-negative integer indicating the number of bytes actually written if the operation
183 /// was succesful, or -1 on failure.
184 int64_t mfat_write(int fd, const void* buf, uint32_t nbyte);
186 /// @brief Reposition read/write file offset.
187 /// @param fd The file descriptor.
188 /// @param offset The offset.
189 /// @param whence How the offset is interpreted.
190 /// @returns the resulting offset location as measured in bytes from the beginning of the file if
191 /// the operation was successful, or -1 on failure.
192 /// @note It is possible to query the current file position with mfat_lseek(fd, 0, MFAT_SEEK_CUR).
193 int64_t mfat_lseek(int fd, int64_t offset, int whence);
195 /// @brief Open directory associated with file descriptor.
196 /// @param fd The file descriptor.
197 /// @returns a pointer to a directory stream object, or NULL if the directory could not be opened.
198 mfat_dir_t* mfat_fdopendir(int fd);
200 /// @brief Open directory with the given name.
201 /// @param path The path to the directory.
202 /// @returns a pointer to a directory stream object, or NULL if the directory could not be opened.
203 mfat_dir_t* mfat_opendir(const char* path);
205 /// @brief Close a directory stream.
206 /// @param dirp A pointer to the directory stream object.
207 /// @returns zero (0) on success, or -1 on failure.
208 int mfat_closedir(mfat_dir_t* dirp);
210 /// @brief Read the next directory entry of a directory stream.
211 /// @param dirp A pointer to the directory stream object.
212 /// @returns a pointer to a structure representing the directory entry at the current position in
213 /// the directory stream, or NULL if the end of the directory was reached or an error occurred.
214 mfat_dirent_t* mfat_readdir(mfat_dir_t* dirp);
216 #ifdef __cplusplus
218 #endif
220 #endif // MFAT_H_