sdl3_sys/generated/storage.rs
1//! The storage API is a high-level API designed to abstract away the
2//! portability issues that come up when using something lower-level (in SDL's
3//! case, this sits on top of the [Filesystem](CategoryFilesystem) and
4//! [IOStream](CategoryIOStream) subsystems). It is significantly more
5//! restrictive than a typical filesystem API, for a number of reasons:
6//!
7//! 1. **What to Access:** A common pitfall with existing filesystem APIs is
8//! the assumption that all storage is monolithic. However, many other
9//! platforms (game consoles in particular) are more strict about what _type_
10//! of filesystem is being accessed; for example, game content and user data
11//! are usually two separate storage devices with entirely different
12//! characteristics (and possibly different low-level APIs altogether!).
13//!
14//! 2. **How to Access:** Another common mistake is applications assuming that
15//! all storage is universally writeable - again, many platforms treat game
16//! content and user data as two separate storage devices, and only user data
17//! is writeable while game content is read-only.
18//!
19//! 3. **When to Access:** The most common portability issue with filesystem
20//! access is _timing_ - you cannot always assume that the storage device is
21//! always accessible all of the time, nor can you assume that there are no
22//! limits to how long you have access to a particular device.
23//!
24//! Consider the following example:
25//!
26//! ```c
27//! void ReadGameData(void)
28//! {
29//! extern char** fileNames;
30//! extern size_t numFiles;
31//! for (size_t i = 0; i < numFiles; i += 1) {
32//! FILE *data = fopen(fileNames[i], "rwb");
33//! if (data == NULL) {
34//! // Something bad happened!
35//! } else {
36//! // A bunch of stuff happens here
37//! fclose(data);
38//! }
39//! }
40//! }
41//!
42//! void ReadSave(void)
43//! {
44//! FILE *save = fopen("saves/save0.sav", "rb");
45//! if (save == NULL) {
46//! // Something bad happened!
47//! } else {
48//! // A bunch of stuff happens here
49//! fclose(save);
50//! }
51//! }
52//!
53//! void WriteSave(void)
54//! {
55//! FILE *save = fopen("saves/save0.sav", "wb");
56//! if (save == NULL) {
57//! // Something bad happened!
58//! } else {
59//! // A bunch of stuff happens here
60//! fclose(save);
61//! }
62//! }
63//! ```
64//!
65//! Going over the bullet points again:
66//!
67//! 1. **What to Access:** This code accesses a global filesystem; game data
68//! and saves are all presumed to be in the current working directory (which
69//! may or may not be the game's installation folder!).
70//!
71//! 2. **How to Access:** This code assumes that content paths are writeable,
72//! and that save data is also writeable despite being in the same location as
73//! the game data.
74//!
75//! 3. **When to Access:** This code assumes that they can be called at any
76//! time, since the filesystem is always accessible and has no limits on how
77//! long the filesystem is being accessed.
78//!
79//! Due to these assumptions, the filesystem code is not portable and will fail
80//! under these common scenarios:
81//!
82//! - The game is installed on a device that is read-only, both content loading
83//! and game saves will fail or crash outright
84//! - Game/User storage is not implicitly mounted, so no files will be found
85//! for either scenario when a platform requires explicitly mounting
86//! filesystems
87//! - Save data may not be safe since the I/O is not being flushed or
88//! validated, so an error occurring elsewhere in the program may result in
89//! missing/corrupted save data
90//!
91//! When using [`SDL_Storage`], these types of problems are virtually impossible to
92//! trip over:
93//!
94//! ```c
95//! void ReadGameData(void)
96//! {
97//! extern char** fileNames;
98//! extern size_t numFiles;
99//!
100//! SDL_Storage *title = SDL_OpenTitleStorage(NULL, 0);
101//! if (title == NULL) {
102//! // Something bad happened!
103//! }
104//! while (!SDL_StorageReady(title)) {
105//! SDL_Delay(1);
106//! }
107//!
108//! for (size_t i = 0; i < numFiles; i += 1) {
109//! void* dst;
110//! Uint64 dstLen = 0;
111//!
112//! if (SDL_GetStorageFileSize(title, fileNames[i], &dstLen) && dstLen > 0) {
113//! dst = SDL_malloc(dstLen);
114//! if (SDL_ReadStorageFile(title, fileNames[i], dst, dstLen)) {
115//! // A bunch of stuff happens here
116//! } else {
117//! // Something bad happened!
118//! }
119//! SDL_free(dst);
120//! } else {
121//! // Something bad happened!
122//! }
123//! }
124//!
125//! SDL_CloseStorage(title);
126//! }
127//!
128//! void ReadSave(void)
129//! {
130//! SDL_Storage *user = SDL_OpenUserStorage("libsdl", "Storage Example", 0);
131//! if (user == NULL) {
132//! // Something bad happened!
133//! }
134//! while (!SDL_StorageReady(user)) {
135//! SDL_Delay(1);
136//! }
137//!
138//! Uint64 saveLen = 0;
139//! if (SDL_GetStorageFileSize(user, "save0.sav", &saveLen) && saveLen > 0) {
140//! void* dst = SDL_malloc(saveLen);
141//! if (SDL_ReadStorageFile(user, "save0.sav", dst, saveLen)) {
142//! // A bunch of stuff happens here
143//! } else {
144//! // Something bad happened!
145//! }
146//! SDL_free(dst);
147//! } else {
148//! // Something bad happened!
149//! }
150//!
151//! SDL_CloseStorage(user);
152//! }
153//!
154//! void WriteSave(void)
155//! {
156//! SDL_Storage *user = SDL_OpenUserStorage("libsdl", "Storage Example", 0);
157//! if (user == NULL) {
158//! // Something bad happened!
159//! }
160//! while (!SDL_StorageReady(user)) {
161//! SDL_Delay(1);
162//! }
163//!
164//! extern void *saveData; // A bunch of stuff happened here...
165//! extern Uint64 saveLen;
166//! if (!SDL_WriteStorageFile(user, "save0.sav", saveData, saveLen)) {
167//! // Something bad happened!
168//! }
169//!
170//! SDL_CloseStorage(user);
171//! }
172//! ```
173//!
174//! Note the improvements that [`SDL_Storage`] makes:
175//!
176//! 1. **What to Access:** This code explicitly reads from a title or user
177//! storage device based on the context of the function.
178//!
179//! 2. **How to Access:** This code explicitly uses either a read or write
180//! function based on the context of the function.
181//!
182//! 3. **When to Access:** This code explicitly opens the device when it needs
183//! to, and closes it when it is finished working with the filesystem.
184//!
185//! The result is an application that is significantly more robust against the
186//! increasing demands of platforms and their filesystems!
187//!
188//! A publicly available example of an [`SDL_Storage`] backend is the
189//! [Steam Cloud](https://partner.steamgames.com/doc/features/cloud)
190//! backend - you can initialize Steamworks when starting the program, and then
191//! SDL will recognize that Steamworks is initialized and automatically use
192//! ISteamRemoteStorage when the application opens user storage. More
193//! importantly, when you _open_ storage it knows to begin a "batch" of
194//! filesystem operations, and when you _close_ storage it knows to end and
195//! flush the batch. This is used by Steam to support
196//! [Dynamic Cloud Sync](https://steamcommunity.com/groups/steamworks/announcements/detail/3142949576401813670)
197//! ; users can save data on one PC, put the device to sleep, and then continue
198//! playing on another PC (and vice versa) with the save data fully
199//! synchronized across all devices, allowing for a seamless experience without
200//! having to do full restarts of the program.
201//!
202//! ## Notes on valid paths
203//!
204//! All paths in the Storage API use Unix-style path separators ('/'). Using a
205//! different path separator will not work, even if the underlying platform
206//! would otherwise accept it. This is to keep code using the Storage API
207//! portable between platforms and Storage implementations and simplify app
208//! code.
209//!
210//! Paths with relative directories ("." and "..") are forbidden by the Storage
211//! API.
212//!
213//! All valid UTF-8 strings (discounting the NULL terminator character and the
214//! '/' path separator) are usable for filenames, however, an underlying
215//! Storage implementation may not support particularly strange sequences and
216//! refuse to create files with those names, etc.
217
218use super::stdinc::*;
219
220use super::error::*;
221
222use super::filesystem::*;
223
224use super::properties::*;
225
226/// Function interface for [`SDL_Storage`].
227///
228/// Apps that want to supply a custom implementation of [`SDL_Storage`] will fill
229/// in all the functions in this struct, and then pass it to [`SDL_OpenStorage`] to
230/// create a custom [`SDL_Storage`] object.
231///
232/// It is not usually necessary to do this; SDL provides standard
233/// implementations for many things you might expect to do with an [`SDL_Storage`].
234///
235/// This structure should be initialized using [`SDL_INIT_INTERFACE()`]
236///
237/// ## Availability
238/// This struct is available since SDL 3.2.0.
239///
240/// ## See also
241/// - [`SDL_INIT_INTERFACE`]
242///
243/// ## Notes for `sdl3-sys`
244/// This interface struct can be initialized with [`SDL_StorageInterface::new()`] or `Default::default()`.
245#[repr(C)]
246#[cfg_attr(feature = "debug-impls", derive(Debug))]
247pub struct SDL_StorageInterface {
248 pub version: Uint32,
249 pub close: ::core::option::Option<
250 unsafe extern "C" fn(userdata: *mut ::core::ffi::c_void) -> ::core::primitive::bool,
251 >,
252 pub ready: ::core::option::Option<
253 unsafe extern "C" fn(userdata: *mut ::core::ffi::c_void) -> ::core::primitive::bool,
254 >,
255 pub enumerate: ::core::option::Option<
256 unsafe extern "C" fn(
257 userdata: *mut ::core::ffi::c_void,
258 path: *const ::core::ffi::c_char,
259 callback: SDL_EnumerateDirectoryCallback,
260 callback_userdata: *mut ::core::ffi::c_void,
261 ) -> ::core::primitive::bool,
262 >,
263 pub info: ::core::option::Option<
264 unsafe extern "C" fn(
265 userdata: *mut ::core::ffi::c_void,
266 path: *const ::core::ffi::c_char,
267 info: *mut SDL_PathInfo,
268 ) -> ::core::primitive::bool,
269 >,
270 pub read_file: ::core::option::Option<
271 unsafe extern "C" fn(
272 userdata: *mut ::core::ffi::c_void,
273 path: *const ::core::ffi::c_char,
274 destination: *mut ::core::ffi::c_void,
275 length: Uint64,
276 ) -> ::core::primitive::bool,
277 >,
278 pub write_file: ::core::option::Option<
279 unsafe extern "C" fn(
280 userdata: *mut ::core::ffi::c_void,
281 path: *const ::core::ffi::c_char,
282 source: *const ::core::ffi::c_void,
283 length: Uint64,
284 ) -> ::core::primitive::bool,
285 >,
286 pub mkdir: ::core::option::Option<
287 unsafe extern "C" fn(
288 userdata: *mut ::core::ffi::c_void,
289 path: *const ::core::ffi::c_char,
290 ) -> ::core::primitive::bool,
291 >,
292 pub remove: ::core::option::Option<
293 unsafe extern "C" fn(
294 userdata: *mut ::core::ffi::c_void,
295 path: *const ::core::ffi::c_char,
296 ) -> ::core::primitive::bool,
297 >,
298 pub rename: ::core::option::Option<
299 unsafe extern "C" fn(
300 userdata: *mut ::core::ffi::c_void,
301 oldpath: *const ::core::ffi::c_char,
302 newpath: *const ::core::ffi::c_char,
303 ) -> ::core::primitive::bool,
304 >,
305 pub copy: ::core::option::Option<
306 unsafe extern "C" fn(
307 userdata: *mut ::core::ffi::c_void,
308 oldpath: *const ::core::ffi::c_char,
309 newpath: *const ::core::ffi::c_char,
310 ) -> ::core::primitive::bool,
311 >,
312 pub space_remaining:
313 ::core::option::Option<unsafe extern "C" fn(userdata: *mut ::core::ffi::c_void) -> Uint64>,
314}
315
316impl SDL_StorageInterface {
317 /// Create a new `SDL_StorageInterface` initialized with `SDL_INIT_INTERFACE`
318 #[inline]
319 pub const fn new() -> Self {
320 const { ::core::assert!(::core::mem::size_of::<Self>() <= ::core::primitive::u32::MAX as usize) };
321 let mut this = unsafe { ::core::mem::MaybeUninit::<Self>::zeroed().assume_init() };
322 this.version = ::core::mem::size_of::<Self>() as ::core::primitive::u32;
323 this
324 }
325}
326
327impl ::core::default::Default for SDL_StorageInterface {
328 /// Create a new `SDL_StorageInterface` initialized with `SDL_INIT_INTERFACE`
329 #[inline(always)]
330 fn default() -> Self {
331 Self::new()
332 }
333}
334
335const _: () = ::core::assert!(
336 (((::core::mem::size_of::<*mut ::core::ffi::c_void>() == 4_usize)
337 && (::core::mem::size_of::<SDL_StorageInterface>() == 48_usize))
338 || ((::core::mem::size_of::<*mut ::core::ffi::c_void>() == 8_usize)
339 && (::core::mem::size_of::<SDL_StorageInterface>() == 96_usize)))
340);
341
342unsafe extern "C" {
343 /// Opens up a read-only container for the application's filesystem.
344 ///
345 /// By default, [`SDL_OpenTitleStorage`] uses the generic storage implementation.
346 /// When the path override is not provided, the generic implementation will use
347 /// the output of [`SDL_GetBasePath`] as the base path.
348 ///
349 /// ## Parameters
350 /// - `override`: a path to override the backend's default title root.
351 /// - `props`: a property list that may contain backend-specific information.
352 ///
353 /// ## Return value
354 /// Returns a title storage container on success or NULL on failure; call
355 /// [`SDL_GetError()`] for more information.
356 ///
357 /// ## Availability
358 /// This function is available since SDL 3.2.0.
359 ///
360 /// ## See also
361 /// - [`SDL_CloseStorage`]
362 /// - [`SDL_GetStorageFileSize`]
363 /// - [`SDL_OpenUserStorage`]
364 /// - [`SDL_ReadStorageFile`]
365 pub fn SDL_OpenTitleStorage(
366 r#override: *const ::core::ffi::c_char,
367 props: SDL_PropertiesID,
368 ) -> *mut SDL_Storage;
369}
370
371unsafe extern "C" {
372 /// Opens up a container for a user's unique read/write filesystem.
373 ///
374 /// While title storage can generally be kept open throughout runtime, user
375 /// storage should only be opened when the client is ready to read/write files.
376 /// This allows the backend to properly batch file operations and flush them
377 /// when the container has been closed; ensuring safe and optimal save I/O.
378 ///
379 /// ## Parameters
380 /// - `org`: the name of your organization.
381 /// - `app`: the name of your application.
382 /// - `props`: a property list that may contain backend-specific information.
383 ///
384 /// ## Return value
385 /// Returns a user storage container on success or NULL on failure; call
386 /// [`SDL_GetError()`] for more information.
387 ///
388 /// ## Availability
389 /// This function is available since SDL 3.2.0.
390 ///
391 /// ## See also
392 /// - [`SDL_CloseStorage`]
393 /// - [`SDL_GetStorageFileSize`]
394 /// - [`SDL_GetStorageSpaceRemaining`]
395 /// - [`SDL_OpenTitleStorage`]
396 /// - [`SDL_ReadStorageFile`]
397 /// - [`SDL_StorageReady`]
398 /// - [`SDL_WriteStorageFile`]
399 pub fn SDL_OpenUserStorage(
400 org: *const ::core::ffi::c_char,
401 app: *const ::core::ffi::c_char,
402 props: SDL_PropertiesID,
403 ) -> *mut SDL_Storage;
404}
405
406unsafe extern "C" {
407 /// Opens up a container for local filesystem storage.
408 ///
409 /// This is provided for development and tools. Portable applications should
410 /// use [`SDL_OpenTitleStorage()`] for access to game data and
411 /// [`SDL_OpenUserStorage()`] for access to user data.
412 ///
413 /// ## Parameters
414 /// - `path`: the base path prepended to all storage paths, or NULL for no
415 /// base path.
416 ///
417 /// ## Return value
418 /// Returns a filesystem storage container on success or NULL on failure; call
419 /// [`SDL_GetError()`] for more information.
420 ///
421 /// ## Availability
422 /// This function is available since SDL 3.2.0.
423 ///
424 /// ## See also
425 /// - [`SDL_CloseStorage`]
426 /// - [`SDL_GetStorageFileSize`]
427 /// - [`SDL_GetStorageSpaceRemaining`]
428 /// - [`SDL_OpenTitleStorage`]
429 /// - [`SDL_OpenUserStorage`]
430 /// - [`SDL_ReadStorageFile`]
431 /// - [`SDL_WriteStorageFile`]
432 pub fn SDL_OpenFileStorage(path: *const ::core::ffi::c_char) -> *mut SDL_Storage;
433}
434
435unsafe extern "C" {
436 /// Opens up a container using a client-provided storage interface.
437 ///
438 /// Applications do not need to use this function unless they are providing
439 /// their own [`SDL_Storage`] implementation. If you just need an [`SDL_Storage`], you
440 /// should use the built-in implementations in SDL, like [`SDL_OpenTitleStorage()`]
441 /// or [`SDL_OpenUserStorage()`].
442 ///
443 /// This function makes a copy of `iface` and the caller does not need to keep
444 /// it around after this call.
445 ///
446 /// ## Parameters
447 /// - `iface`: the interface that implements this storage, initialized using
448 /// [`SDL_INIT_INTERFACE()`].
449 /// - `userdata`: the pointer that will be passed to the interface functions.
450 ///
451 /// ## Return value
452 /// Returns a storage container on success or NULL on failure; call
453 /// [`SDL_GetError()`] for more information.
454 ///
455 /// ## Availability
456 /// This function is available since SDL 3.2.0.
457 ///
458 /// ## See also
459 /// - [`SDL_CloseStorage`]
460 /// - [`SDL_GetStorageFileSize`]
461 /// - [`SDL_GetStorageSpaceRemaining`]
462 /// - [`SDL_INIT_INTERFACE`]
463 /// - [`SDL_ReadStorageFile`]
464 /// - [`SDL_StorageReady`]
465 /// - [`SDL_WriteStorageFile`]
466 pub fn SDL_OpenStorage(
467 iface: *const SDL_StorageInterface,
468 userdata: *mut ::core::ffi::c_void,
469 ) -> *mut SDL_Storage;
470}
471
472unsafe extern "C" {
473 /// Closes and frees a storage container.
474 ///
475 /// ## Parameters
476 /// - `storage`: a storage container to close.
477 ///
478 /// ## Return value
479 /// Returns true if the container was freed with no errors, false otherwise;
480 /// call [`SDL_GetError()`] for more information. Even if the function
481 /// returns an error, the container data will be freed; the error is
482 /// only for informational purposes.
483 ///
484 /// ## Availability
485 /// This function is available since SDL 3.2.0.
486 ///
487 /// ## See also
488 /// - [`SDL_OpenFileStorage`]
489 /// - [`SDL_OpenStorage`]
490 /// - [`SDL_OpenTitleStorage`]
491 /// - [`SDL_OpenUserStorage`]
492 pub fn SDL_CloseStorage(storage: *mut SDL_Storage) -> ::core::primitive::bool;
493}
494
495unsafe extern "C" {
496 /// Checks if the storage container is ready to use.
497 ///
498 /// This function should be called in regular intervals until it returns true -
499 /// however, it is not recommended to spinwait on this call, as the backend may
500 /// depend on a synchronous message loop. You might instead poll this in your
501 /// game's main loop while processing events and drawing a loading screen.
502 ///
503 /// ## Parameters
504 /// - `storage`: a storage container to query.
505 ///
506 /// ## Return value
507 /// Returns true if the container is ready, false otherwise.
508 ///
509 /// ## Availability
510 /// This function is available since SDL 3.2.0.
511 pub fn SDL_StorageReady(storage: *mut SDL_Storage) -> ::core::primitive::bool;
512}
513
514unsafe extern "C" {
515 /// Query the size of a file within a storage container.
516 ///
517 /// ## Parameters
518 /// - `storage`: a storage container to query.
519 /// - `path`: the relative path of the file to query.
520 /// - `length`: a pointer to be filled with the file's length.
521 ///
522 /// ## Return value
523 /// Returns true if the file could be queried or false on failure; call
524 /// [`SDL_GetError()`] for more information.
525 ///
526 /// ## Availability
527 /// This function is available since SDL 3.2.0.
528 ///
529 /// ## See also
530 /// - [`SDL_ReadStorageFile`]
531 /// - [`SDL_StorageReady`]
532 pub fn SDL_GetStorageFileSize(
533 storage: *mut SDL_Storage,
534 path: *const ::core::ffi::c_char,
535 length: *mut Uint64,
536 ) -> ::core::primitive::bool;
537}
538
539unsafe extern "C" {
540 /// Synchronously read a file from a storage container into a client-provided
541 /// buffer.
542 ///
543 /// The value of `length` must match the length of the file exactly; call
544 /// [`SDL_GetStorageFileSize()`] to get this value. This behavior may be relaxed in
545 /// a future release.
546 ///
547 /// ## Parameters
548 /// - `storage`: a storage container to read from.
549 /// - `path`: the relative path of the file to read.
550 /// - `destination`: a client-provided buffer to read the file into.
551 /// - `length`: the length of the destination buffer.
552 ///
553 /// ## Return value
554 /// Returns true if the file was read or false on failure; call [`SDL_GetError()`]
555 /// for more information.
556 ///
557 /// ## Availability
558 /// This function is available since SDL 3.2.0.
559 ///
560 /// ## See also
561 /// - [`SDL_GetStorageFileSize`]
562 /// - [`SDL_StorageReady`]
563 /// - [`SDL_WriteStorageFile`]
564 pub fn SDL_ReadStorageFile(
565 storage: *mut SDL_Storage,
566 path: *const ::core::ffi::c_char,
567 destination: *mut ::core::ffi::c_void,
568 length: Uint64,
569 ) -> ::core::primitive::bool;
570}
571
572unsafe extern "C" {
573 /// Synchronously write a file from client memory into a storage container.
574 ///
575 /// ## Parameters
576 /// - `storage`: a storage container to write to.
577 /// - `path`: the relative path of the file to write.
578 /// - `source`: a client-provided buffer to write from.
579 /// - `length`: the length of the source buffer.
580 ///
581 /// ## Return value
582 /// Returns true if the file was written or false on failure; call
583 /// [`SDL_GetError()`] for more information.
584 ///
585 /// ## Availability
586 /// This function is available since SDL 3.2.0.
587 ///
588 /// ## See also
589 /// - [`SDL_GetStorageSpaceRemaining`]
590 /// - [`SDL_ReadStorageFile`]
591 /// - [`SDL_StorageReady`]
592 pub fn SDL_WriteStorageFile(
593 storage: *mut SDL_Storage,
594 path: *const ::core::ffi::c_char,
595 source: *const ::core::ffi::c_void,
596 length: Uint64,
597 ) -> ::core::primitive::bool;
598}
599
600unsafe extern "C" {
601 /// Create a directory in a writable storage container.
602 ///
603 /// ## Parameters
604 /// - `storage`: a storage container.
605 /// - `path`: the path of the directory to create.
606 ///
607 /// ## Return value
608 /// Returns true on success or false on failure; call [`SDL_GetError()`] for more
609 /// information.
610 ///
611 /// ## Availability
612 /// This function is available since SDL 3.2.0.
613 ///
614 /// ## See also
615 /// - [`SDL_StorageReady`]
616 pub fn SDL_CreateStorageDirectory(
617 storage: *mut SDL_Storage,
618 path: *const ::core::ffi::c_char,
619 ) -> ::core::primitive::bool;
620}
621
622unsafe extern "C" {
623 /// Enumerate a directory in a storage container through a callback function.
624 ///
625 /// This function provides every directory entry through an app-provided
626 /// callback, called once for each directory entry, until all results have been
627 /// provided or the callback returns either [`SDL_ENUM_SUCCESS`] or
628 /// [`SDL_ENUM_FAILURE`].
629 ///
630 /// This will return false if there was a system problem in general, or if a
631 /// callback returns [`SDL_ENUM_FAILURE`]. A successful return means a callback
632 /// returned [`SDL_ENUM_SUCCESS`] to halt enumeration, or all directory entries
633 /// were enumerated.
634 ///
635 /// If `path` is NULL, this is treated as a request to enumerate the root of
636 /// the storage container's tree. An empty string also works for this.
637 ///
638 /// ## Parameters
639 /// - `storage`: a storage container.
640 /// - `path`: the path of the directory to enumerate, or NULL for the root.
641 /// - `callback`: a function that is called for each entry in the directory.
642 /// - `userdata`: a pointer that is passed to `callback`.
643 ///
644 /// ## Return value
645 /// Returns true on success or false on failure; call [`SDL_GetError()`] for more
646 /// information.
647 ///
648 /// ## Availability
649 /// This function is available since SDL 3.2.0.
650 ///
651 /// ## See also
652 /// - [`SDL_StorageReady`]
653 pub fn SDL_EnumerateStorageDirectory(
654 storage: *mut SDL_Storage,
655 path: *const ::core::ffi::c_char,
656 callback: SDL_EnumerateDirectoryCallback,
657 userdata: *mut ::core::ffi::c_void,
658 ) -> ::core::primitive::bool;
659}
660
661unsafe extern "C" {
662 /// Remove a file or an empty directory in a writable storage container.
663 ///
664 /// ## Parameters
665 /// - `storage`: a storage container.
666 /// - `path`: the path of the directory to enumerate.
667 ///
668 /// ## Return value
669 /// Returns true on success or false on failure; call [`SDL_GetError()`] for more
670 /// information.
671 ///
672 /// ## Availability
673 /// This function is available since SDL 3.2.0.
674 ///
675 /// ## See also
676 /// - [`SDL_StorageReady`]
677 pub fn SDL_RemoveStoragePath(
678 storage: *mut SDL_Storage,
679 path: *const ::core::ffi::c_char,
680 ) -> ::core::primitive::bool;
681}
682
683unsafe extern "C" {
684 /// Rename a file or directory in a writable storage container.
685 ///
686 /// ## Parameters
687 /// - `storage`: a storage container.
688 /// - `oldpath`: the old path.
689 /// - `newpath`: the new path.
690 ///
691 /// ## Return value
692 /// Returns true on success or false on failure; call [`SDL_GetError()`] for more
693 /// information.
694 ///
695 /// ## Availability
696 /// This function is available since SDL 3.2.0.
697 ///
698 /// ## See also
699 /// - [`SDL_StorageReady`]
700 pub fn SDL_RenameStoragePath(
701 storage: *mut SDL_Storage,
702 oldpath: *const ::core::ffi::c_char,
703 newpath: *const ::core::ffi::c_char,
704 ) -> ::core::primitive::bool;
705}
706
707unsafe extern "C" {
708 /// Copy a file in a writable storage container.
709 ///
710 /// ## Parameters
711 /// - `storage`: a storage container.
712 /// - `oldpath`: the old path.
713 /// - `newpath`: the new path.
714 ///
715 /// ## Return value
716 /// Returns true on success or false on failure; call [`SDL_GetError()`] for more
717 /// information.
718 ///
719 /// ## Availability
720 /// This function is available since SDL 3.2.0.
721 ///
722 /// ## See also
723 /// - [`SDL_StorageReady`]
724 pub fn SDL_CopyStorageFile(
725 storage: *mut SDL_Storage,
726 oldpath: *const ::core::ffi::c_char,
727 newpath: *const ::core::ffi::c_char,
728 ) -> ::core::primitive::bool;
729}
730
731unsafe extern "C" {
732 /// Get information about a filesystem path in a storage container.
733 ///
734 /// ## Parameters
735 /// - `storage`: a storage container.
736 /// - `path`: the path to query.
737 /// - `info`: a pointer filled in with information about the path, or NULL to
738 /// check for the existence of a file.
739 ///
740 /// ## Return value
741 /// Returns true on success or false if the file doesn't exist, or another
742 /// failure; call [`SDL_GetError()`] for more information.
743 ///
744 /// ## Availability
745 /// This function is available since SDL 3.2.0.
746 ///
747 /// ## See also
748 /// - [`SDL_StorageReady`]
749 pub fn SDL_GetStoragePathInfo(
750 storage: *mut SDL_Storage,
751 path: *const ::core::ffi::c_char,
752 info: *mut SDL_PathInfo,
753 ) -> ::core::primitive::bool;
754}
755
756unsafe extern "C" {
757 /// Queries the remaining space in a storage container.
758 ///
759 /// ## Parameters
760 /// - `storage`: a storage container to query.
761 ///
762 /// ## Return value
763 /// Returns the amount of remaining space, in bytes.
764 ///
765 /// ## Availability
766 /// This function is available since SDL 3.2.0.
767 ///
768 /// ## See also
769 /// - [`SDL_StorageReady`]
770 /// - [`SDL_WriteStorageFile`]
771 pub fn SDL_GetStorageSpaceRemaining(storage: *mut SDL_Storage) -> Uint64;
772}
773
774unsafe extern "C" {
775 /// Enumerate a directory tree, filtered by pattern, and return a list.
776 ///
777 /// Files are filtered out if they don't match the string in `pattern`, which
778 /// may contain wildcard characters `*` (match everything) and `?` (match one
779 /// character). If pattern is NULL, no filtering is done and all results are
780 /// returned. Subdirectories are permitted, and are specified with a path
781 /// separator of '/'. Wildcard characters `*` and `?` never match a path
782 /// separator.
783 ///
784 /// `flags` may be set to [`SDL_GLOB_CASEINSENSITIVE`] to make the pattern matching
785 /// case-insensitive.
786 ///
787 /// The returned array is always NULL-terminated, for your iterating
788 /// convenience, but if `count` is non-NULL, on return it will contain the
789 /// number of items in the array, not counting the NULL terminator.
790 ///
791 /// If `path` is NULL, this is treated as a request to enumerate the root of
792 /// the storage container's tree. An empty string also works for this.
793 ///
794 /// ## Parameters
795 /// - `storage`: a storage container.
796 /// - `path`: the path of the directory to enumerate, or NULL for the root.
797 /// - `pattern`: the pattern that files in the directory must match. Can be
798 /// NULL.
799 /// - `flags`: `SDL_GLOB_*` bitflags that affect this search.
800 /// - `count`: on return, will be set to the number of items in the returned
801 /// array. Can be NULL.
802 ///
803 /// ## Return value
804 /// Returns an array of strings on success or NULL on failure; call
805 /// [`SDL_GetError()`] for more information. The caller should pass the
806 /// returned pointer to [`SDL_free`] when done with it. This is a single
807 /// allocation that should be freed with [`SDL_free()`] when it is no
808 /// longer needed.
809 ///
810 /// ## Thread safety
811 /// It is safe to call this function from any thread, assuming
812 /// the `storage` object is thread-safe.
813 ///
814 /// ## Availability
815 /// This function is available since SDL 3.2.0.
816 pub fn SDL_GlobStorageDirectory(
817 storage: *mut SDL_Storage,
818 path: *const ::core::ffi::c_char,
819 pattern: *const ::core::ffi::c_char,
820 flags: SDL_GlobFlags,
821 count: *mut ::core::ffi::c_int,
822 ) -> *mut *mut ::core::ffi::c_char;
823}
824
825/// An abstract interface for filesystem access.
826///
827/// This is an opaque datatype. One can create this object using standard SDL
828/// functions like [`SDL_OpenTitleStorage`] or [`SDL_OpenUserStorage`], etc, or create
829/// an object with a custom implementation using [`SDL_OpenStorage`].
830///
831/// ## Availability
832/// This struct is available since SDL 3.2.0.
833#[repr(C)]
834pub struct SDL_Storage {
835 _opaque: [::core::primitive::u8; 0],
836}
837
838#[cfg(doc)]
839use crate::everything::*;