1 /*
2 * Copyright (c) 2016 Intel Corporation.
3 * Copyright (c) 2020-2021 Nordic Semiconductor ASA
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8 #ifndef ZEPHYR_INCLUDE_FS_FS_H_
9 #define ZEPHYR_INCLUDE_FS_FS_H_
10
11 #include <sys/types.h>
12
13 #include <sys/dlist.h>
14 #include <fs/fs_interface.h>
15
16 #ifdef __cplusplus
17 extern "C" {
18 #endif
19
20 /**
21 * @brief File System APIs
22 * @defgroup file_system_api File System APIs
23 * @{
24 */
25 struct fs_file_system_t;
26
27 enum fs_dir_entry_type {
28 /** Identifier for file entry */
29 FS_DIR_ENTRY_FILE = 0,
30 /** Identifier for directory entry */
31 FS_DIR_ENTRY_DIR
32 };
33
34 /** @brief Enumeration to uniquely identify file system types.
35 *
36 * Zephyr supports in-tree file systems and external ones. Each
37 * requires a unique identifier used to register the file system
38 * implementation and to associate a mount point with the file system
39 * type. This anonymous enum defines global identifiers for the
40 * in-tree file systems.
41 *
42 * External file systems should be registered using unique identifiers
43 * starting at @c FS_TYPE_EXTERNAL_BASE. It is the responsibility of
44 * applications that use external file systems to ensure that these
45 * identifiers are unique if multiple file system implementations are
46 * used by the application.
47 */
48 enum {
49 /** Identifier for in-tree FatFS file system. */
50 FS_FATFS = 0,
51
52 /** Identifier for in-tree LittleFS file system. */
53 FS_LITTLEFS,
54
55 /** Base identifier for external file systems. */
56 FS_TYPE_EXTERNAL_BASE,
57 };
58
59 /** Flag prevents formatting device if requested file system not found */
60 #define FS_MOUNT_FLAG_NO_FORMAT BIT(0)
61 /** Flag makes mounted file system read-only */
62 #define FS_MOUNT_FLAG_READ_ONLY BIT(1)
63 /** Flag used in pre-defined mount structures that are to be mounted
64 * on startup.
65 *
66 * This flag has no impact in user-defined mount structures.
67 */
68 #define FS_MOUNT_FLAG_AUTOMOUNT BIT(2)
69
70
71 /**
72 * @brief File system mount info structure
73 *
74 * @param node Entry for the fs_mount_list list
75 * @param type File system type
76 * @param mnt_point Mount point directory name (ex: "/fatfs")
77 * @param fs_data Pointer to file system specific data
78 * @param storage_dev Pointer to backend storage device
79 * @param mountp_len Length of Mount point string
80 * @param fs Pointer to File system interface of the mount point
81 * @param flags Mount flags
82 */
83 struct fs_mount_t {
84 sys_dnode_t node;
85 int type;
86 const char *mnt_point;
87 void *fs_data;
88 void *storage_dev;
89 /* fields filled by file system core */
90 size_t mountp_len;
91 const struct fs_file_system_t *fs;
92 uint8_t flags;
93 };
94
95 /**
96 * @brief Structure to receive file or directory information
97 *
98 * Used in functions that reads the directory entries to get
99 * file or directory information.
100 *
101 * @param dir_entry_type Whether file or directory
102 * - FS_DIR_ENTRY_FILE
103 * - FS_DIR_ENTRY_DIR
104 * @param name Name of directory or file
105 * @param size Size of file. 0 if directory
106 */
107 struct fs_dirent {
108 enum fs_dir_entry_type type;
109 char name[MAX_FILE_NAME + 1];
110 size_t size;
111 };
112
113 /**
114 * @brief Structure to receive volume statistics
115 *
116 * Used to retrieve information about total and available space
117 * in the volume.
118 *
119 * @param f_bsize Optimal transfer block size
120 * @param f_frsize Allocation unit size
121 * @param f_blocks Size of FS in f_frsize units
122 * @param f_bfree Number of free blocks
123 */
124 struct fs_statvfs {
125 unsigned long f_bsize;
126 unsigned long f_frsize;
127 unsigned long f_blocks;
128 unsigned long f_bfree;
129 };
130
131
132 /**
133 * @name fs_open open and creation mode flags
134 * @{
135 */
136 /** Open for read flag */
137 #define FS_O_READ 0x01
138 /** Open for write flag */
139 #define FS_O_WRITE 0x02
140 /** Open for read-write flag combination */
141 #define FS_O_RDWR (FS_O_READ | FS_O_WRITE)
142 /** Bitmask for read and write flags */
143 #define FS_O_MODE_MASK 0x03
144
145 /** Create file if it does not exist */
146 #define FS_O_CREATE 0x10
147 /** Open/create file for append */
148 #define FS_O_APPEND 0x20
149 /** Bitmask for open/create flags */
150 #define FS_O_FLAGS_MASK 0x30
151
152 /** Bitmask for open flags */
153 #define FS_O_MASK (FS_O_MODE_MASK | FS_O_FLAGS_MASK)
154 /**
155 * @}
156 */
157
158 /**
159 * @name fs_seek whence parameter values
160 * @{
161 */
162 #ifndef FS_SEEK_SET
163 /** Seek from the beginning of file */
164 #define FS_SEEK_SET 0
165 #endif
166 #ifndef FS_SEEK_CUR
167 /** Seek from a current position */
168 #define FS_SEEK_CUR 1
169 #endif
170 #ifndef FS_SEEK_END
171 /** Seek from the end of file */
172 #define FS_SEEK_END 2
173 #endif
174 /**
175 * @}
176 */
177
178 /*
179 * @brief Get the common mount flags for an fstab entry.
180
181 * @param node_id the node identifier for a child entry in a
182 * zephyr,fstab node.
183 * @return a value suitable for initializing an fs_mount_t flags
184 * member.
185 */
186 #define FSTAB_ENTRY_DT_MOUNT_FLAGS(node_id) \
187 ((DT_PROP(node_id, automount) ? FS_MOUNT_FLAG_AUTOMOUNT : 0) \
188 | (DT_PROP(node_id, read_only) ? FS_MOUNT_FLAG_READ_ONLY : 0) \
189 | (DT_PROP(node_id, no_format) ? FS_MOUNT_FLAG_NO_FORMAT : 0))
190
191 /**
192 * @brief The name under which a zephyr,fstab entry mount structure is
193 * defined.
194 */
195 #define FS_FSTAB_ENTRY(node_id) _CONCAT(z_fsmp_, node_id)
196
197 /**
198 * @brief Generate a declaration for the externally defined fstab
199 * entry.
200 *
201 * This will evaluate to the name of a struct fs_mount_t object.
202 */
203 #define FS_FSTAB_DECLARE_ENTRY(node_id) \
204 extern struct fs_mount_t FS_FSTAB_ENTRY(node_id)
205
206 /**
207 * @brief Initialize fs_file_t object
208 *
209 * Initializes the fs_file_t object; the function needs to be invoked
210 * on object before first use with fs_open.
211 *
212 * @param zfp Pointer to file object
213 *
214 */
fs_file_t_init(struct fs_file_t * zfp)215 static inline void fs_file_t_init(struct fs_file_t *zfp)
216 {
217 *zfp = (struct fs_file_t){ 0 };
218 }
219
220 /**
221 * @brief Initialize fs_dir_t object
222 *
223 * Initializes the fs_dir_t object; the function needs to be invoked
224 * on object before first use with fs_opendir.
225 *
226 * @param zdp Pointer to file object
227 *
228 */
fs_dir_t_init(struct fs_dir_t * zdp)229 static inline void fs_dir_t_init(struct fs_dir_t *zdp)
230 {
231 *zdp = (struct fs_dir_t){ 0 };
232 }
233
234 /**
235 * @brief Open or create file
236 *
237 * Opens or possibly creates a file and associates a stream with it.
238 *
239 * @details
240 * @p flags can be 0 or a binary combination of one or more of the following
241 * identifiers:
242 * - @c FS_O_READ open for read
243 * - @c FS_O_WRITE open for write
244 * - @c FS_O_RDWR open for read/write (<tt>FS_O_READ | FS_O_WRITE</tt>)
245 * - @c FS_O_CREATE create file if it does not exist
246 * - @c FS_O_APPEND move to end of file before each write
247 *
248 * If @p flags are set to 0 the function will attempt to open an existing file
249 * with no read/write access; this may be used to e.g. check if the file exists.
250 *
251 * @param zfp Pointer to a file object
252 * @param file_name The name of a file to open
253 * @param flags The mode flags
254 *
255 * @retval 0 on success;
256 * @retval -EINVAL when a bad file name is given;
257 * @retval -EROFS when opening read-only file for write, or attempting to
258 * create a file on a system that has been mounted with the
259 * FS_MOUNT_FLAG_READ_ONLY flag;
260 * @retval -ENOENT when the file path is not possible (bad mount point);
261 * @retval <0 an other negative errno code, depending on a file system back-end.
262 */
263 int fs_open(struct fs_file_t *zfp, const char *file_name, fs_mode_t flags);
264
265 /**
266 * @brief Close file
267 *
268 * Flushes the associated stream and closes the file.
269 *
270 * @param zfp Pointer to the file object
271 *
272 * @retval 0 on success;
273 * @retval <0 a negative errno code on error.
274 */
275 int fs_close(struct fs_file_t *zfp);
276
277 /**
278 * @brief Unlink file
279 *
280 * Deletes the specified file or directory
281 *
282 * @param path Path to the file or directory to delete
283 *
284 * @retval 0 on success;
285 * @retval -EROFS if file is read-only, or when file system has been mounted
286 * with the FS_MOUNT_FLAG_READ_ONLY flag;
287 * @retval -ENOTSUP when not implemented by underlying file system driver;
288 * @retval <0 an other negative errno code on error.
289 */
290 int fs_unlink(const char *path);
291
292 /**
293 * @brief Rename file or directory
294 *
295 * Performs a rename and / or move of the specified source path to the
296 * specified destination. The source path can refer to either a file or a
297 * directory. All intermediate directories in the destination path must
298 * already exist. If the source path refers to a file, the destination path
299 * must contain a full filename path, rather than just the new parent
300 * directory. If an object already exists at the specified destination path,
301 * this function causes it to be unlinked prior to the rename (i.e., the
302 * destination gets clobbered).
303 * @note Current implementation does not allow moving files between mount
304 * points.
305 *
306 * @param from The source path
307 * @param to The destination path
308 *
309 * @retval 0 on success;
310 * @retval -ENOTSUP when not implemented by underlying file system driver;
311 * @retval <0 an other negative errno code on error.
312 */
313 int fs_rename(const char *from, const char *to);
314
315 /**
316 * @brief Read file
317 *
318 * Reads up to @p size bytes of data to @p ptr pointed buffer, returns number
319 * of bytes read. A returned value may be lower than @p size if there were
320 * fewer bytes available than requested.
321 *
322 * @param zfp Pointer to the file object
323 * @param ptr Pointer to the data buffer
324 * @param size Number of bytes to be read
325 *
326 * @retval >=0 a number of bytes read, on success;
327 * @retval <0 a negative errno code on error.
328 */
329 ssize_t fs_read(struct fs_file_t *zfp, void *ptr, size_t size);
330
331 /**
332 * @brief Write file
333 *
334 * Attempts to write @p size number of bytes to the specified file.
335 * If a negative value is returned from the function, the file pointer has not
336 * been advanced.
337 * If the function returns a non-negative number that is lower than @p size,
338 * the global @c errno variable should be checked for an error code,
339 * as the device may have no free space for data.
340 *
341 * @param zfp Pointer to the file object
342 * @param ptr Pointer to the data buffer
343 * @param size Number of bytes to be written
344 *
345 * @retval >=0 a number of bytes written, on success;
346 * @retval -ENOTSUP when not implemented by underlying file system driver;
347 * @retval <0 an other negative errno code on error.
348 */
349 ssize_t fs_write(struct fs_file_t *zfp, const void *ptr, size_t size);
350
351 /**
352 * @brief Seek file
353 *
354 * Moves the file position to a new location in the file. The @p offset is added
355 * to file position based on the @p whence parameter.
356 *
357 * @param zfp Pointer to the file object
358 * @param offset Relative location to move the file pointer to
359 * @param whence Relative location from where offset is to be calculated.
360 * - @c FS_SEEK_SET for the beginning of the file;
361 * - @c FS_SEEK_CUR for the current position;
362 * - @c FS_SEEK_END for the end of the file.
363 *
364 * @retval 0 on success;
365 * @retval -ENOTSUP if not supported by underlying file system driver;
366 * @retval <0 an other negative errno code on error.
367 */
368 int fs_seek(struct fs_file_t *zfp, off_t offset, int whence);
369
370 /**
371 * @brief Get current file position.
372 *
373 * Retrieves and returns the current position in the file stream.
374 *
375 * @param zfp Pointer to the file object
376 *
377 * @retval >= 0 a current position in file;
378 * @retval -ENOTSUP if not supported by underlying file system driver;
379 * @retval <0 an other negative errno code on error.
380 *
381 * The current revision does not validate the file object.
382 */
383 off_t fs_tell(struct fs_file_t *zfp);
384
385 /**
386 * @brief Truncate or extend an open file to a given size
387 *
388 * Truncates the file to the new length if it is shorter than the current
389 * size of the file. Expands the file if the new length is greater than the
390 * current size of the file. The expanded region would be filled with zeroes.
391 *
392 * @note In the case of expansion, if the volume got full during the
393 * expansion process, the function will expand to the maximum possible length
394 * and return success. Caller should check if the expanded size matches the
395 * requested length.
396 *
397 * @param zfp Pointer to the file object
398 * @param length New size of the file in bytes
399 *
400 * @retval 0 on success;
401 * @retval -ENOTSUP when not implemented by underlying file system driver;
402 * @retval <0 an other negative errno code on error.
403 */
404 int fs_truncate(struct fs_file_t *zfp, off_t length);
405
406 /**
407 * @brief Flush cached write data buffers of an open file
408 *
409 * The function flushes the cache of an open file; it can be invoked to ensure
410 * data gets written to the storage media immediately, e.g. to avoid data loss
411 * in case if power is removed unexpectedly.
412 * @note Closing a file will cause caches to be flushed correctly so the
413 * function need not be called when the file is being closed.
414 *
415 * @param zfp Pointer to the file object
416 *
417 * @retval 0 on success;
418 * @retval <0 a negative errno code on error.
419 */
420 int fs_sync(struct fs_file_t *zfp);
421
422 /**
423 * @brief Directory create
424 *
425 * Creates a new directory using specified path.
426 *
427 * @param path Path to the directory to create
428 *
429 * @retval 0 on success;
430 * @retval -ENOTSUP when not implemented by underlying file system driver;
431 * @retval <0 an other negative errno code on error
432 */
433 int fs_mkdir(const char *path);
434
435 /**
436 * @brief Directory open
437 *
438 * Opens an existing directory specified by the path.
439 *
440 * @param zdp Pointer to the directory object
441 * @param path Path to the directory to open
442 *
443 * @retval 0 on success;
444 * @retval <0 a negative errno code on error.
445 */
446 int fs_opendir(struct fs_dir_t *zdp, const char *path);
447
448 /**
449 * @brief Directory read entry
450 *
451 * Reads directory entries of an open directory. In end-of-dir condition,
452 * the function will return 0 and set the <tt>entry->name[0]</tt> to 0.
453 *
454 * @note: Most existing underlying file systems do not generate POSIX
455 * special directory entries "." or "..". For consistency the
456 * abstraction layer will remove these from lower layer results so
457 * higher layers see consistent results.
458 *
459 * @param zdp Pointer to the directory object
460 * @param entry Pointer to zfs_dirent structure to read the entry into
461 *
462 * @retval 0 on success or end-of-dir;;
463 * @retval <0 a negative errno code on error.
464 */
465 int fs_readdir(struct fs_dir_t *zdp, struct fs_dirent *entry);
466
467 /**
468 * @brief Directory close
469 *
470 * Closes an open directory.
471 *
472 * @param zdp Pointer to the directory object
473 *
474 * @retval 0 on success;
475 * @retval <0 a negative errno code on error.
476 */
477 int fs_closedir(struct fs_dir_t *zdp);
478
479 /**
480 * @brief Mount filesystem
481 *
482 * Perform steps needed for mounting a file system like
483 * calling the file system specific mount function and adding
484 * the mount point to mounted file system list.
485 *
486 * @note Current implementation of ELM FAT driver allows only following mount
487 * points: "/RAM:","/NAND:","/CF:","/SD:","/SD2:","/USB:","/USB2:","/USB3:"
488 * or mount points that consist of single digit, e.g: "/0:", "/1:" and so forth.
489 *
490 * @param mp Pointer to the fs_mount_t structure. Referenced object
491 * is not changed if the mount operation failed.
492 * A reference is captured in the fs infrastructure if the
493 * mount operation succeeds, and the application must not
494 * mutate the structure contents until fs_unmount is
495 * successfully invoked on the same pointer.
496 *
497 * @retval 0 on success;
498 * @retval -ENOENT when file system type has not been registered;
499 * @retval -ENOTSUP when not supported by underlying file system driver;
500 * @retval -EROFS if system requires formatting but @c FS_MOUNT_FLAG_READ_ONLY
501 * has been set;
502 * @retval <0 an other negative errno code on error.
503 */
504 int fs_mount(struct fs_mount_t *mp);
505
506 /**
507 * @brief Unmount filesystem
508 *
509 * Perform steps needed to unmount a file system like
510 * calling the file system specific unmount function and removing
511 * the mount point from mounted file system list.
512 *
513 * @param mp Pointer to the fs_mount_t structure
514 *
515 * @retval 0 on success;
516 * @retval -EINVAL if no system has been mounted at given mount point;
517 * @retval -ENOTSUP when not supported by underlying file system driver;
518 * @retval <0 an other negative errno code on error.
519 */
520 int fs_unmount(struct fs_mount_t *mp);
521
522 /**
523 * @brief Get path of mount point at index
524 *
525 * This function iterates through the list of mount points and returns
526 * the directory name of the mount point at the given @p index.
527 * On success @p index is incremented and @p name is set to the mount directory
528 * name. If a mount point with the given @p index does not exist, @p name will
529 * be set to @c NULL.
530 *
531 * @param index Pointer to mount point index
532 * @param name Pointer to pointer to path name
533 *
534 * @retval 0 on success;
535 * @retval -ENOENT if there is no mount point with given index.
536 */
537 int fs_readmount(int *index, const char **name);
538
539 /**
540 * @brief File or directory status
541 *
542 * Checks the status of a file or directory specified by the @p path.
543 * @note The file on a storage device may not be updated until it is closed.
544 *
545 * @param path Path to the file or directory
546 * @param entry Pointer to the zfs_dirent structure to fill if the file or
547 * directory exists.
548 *
549 * @retval 0 on success;
550 * @retval <0 negative errno code on error.
551 */
552 int fs_stat(const char *path, struct fs_dirent *entry);
553
554 /**
555 * @brief Retrieves statistics of the file system volume
556 *
557 * Returns the total and available space in the file system volume.
558 *
559 * @param path Path to the mounted directory
560 * @param stat Pointer to the zfs_statvfs structure to receive the fs
561 * statistics
562 *
563 * @retval 0 on success;
564 * @retval -ENOTSUP when not implemented by underlying file system driver;
565 * @retval <0 an other negative errno code on error.
566 */
567 int fs_statvfs(const char *path, struct fs_statvfs *stat);
568
569 /**
570 * @brief Register a file system
571 *
572 * Register file system with virtual file system.
573 *
574 * @param type Type of file system (ex: @c FS_FATFS)
575 * @param fs Pointer to File system
576 *
577 * @retval 0 on success;
578 * @retval <0 negative errno code on error.
579 */
580 int fs_register(int type, const struct fs_file_system_t *fs);
581
582 /**
583 * @brief Unregister a file system
584 *
585 * Unregister file system from virtual file system.
586 *
587 * @param type Type of file system (ex: @c FS_FATFS)
588 * @param fs Pointer to File system
589 *
590 * @retval 0 on success;
591 * @retval <0 negative errno code on error.
592 */
593 int fs_unregister(int type, const struct fs_file_system_t *fs);
594
595 /**
596 * @}
597 */
598
599
600 #ifdef __cplusplus
601 }
602 #endif
603
604 #endif /* ZEPHYR_INCLUDE_FS_FS_H_ */
605