mirror of
https://github.com/libsdl-org/SDL.git
synced 2025-09-30 23:18:29 +00:00
filesystem: Improve docs, make some promises about overwrites and file caches.
Note that SDL_FlushIO() doesn't make promises about file data sync but that is intended to be changed in the IOStream code in a later commit. Fixes #10886.
This commit is contained in:
@@ -289,7 +289,10 @@ extern SDL_DECLSPEC bool SDLCALL SDL_EnumerateDirectory(const char *path, SDL_En
|
|||||||
/**
|
/**
|
||||||
* Remove a file or an empty directory.
|
* Remove a file or an empty directory.
|
||||||
*
|
*
|
||||||
* \param path the path of the directory to enumerate.
|
* Directories that are not empty will fail; this function will not recursely
|
||||||
|
* delete directory trees.
|
||||||
|
*
|
||||||
|
* \param path the path to remove from the filesystem.
|
||||||
* \returns true on success or false on failure; call SDL_GetError() for more
|
* \returns true on success or false on failure; call SDL_GetError() for more
|
||||||
* information.
|
* information.
|
||||||
*
|
*
|
||||||
@@ -300,6 +303,17 @@ extern SDL_DECLSPEC bool SDLCALL SDL_RemovePath(const char *path);
|
|||||||
/**
|
/**
|
||||||
* Rename a file or directory.
|
* Rename a file or directory.
|
||||||
*
|
*
|
||||||
|
* If the file at `newpath` already exists, it will replaced.
|
||||||
|
*
|
||||||
|
* Note that this will not copy files across filesystems/drives/volumes, as
|
||||||
|
* that is a much more complicated (and possibly time-consuming) operation.
|
||||||
|
*
|
||||||
|
* Which is to say, if this function fails, SDL_CopyFile() to a temporary
|
||||||
|
* file in the same directory as `newpath`, then SDL_RenamePath() from the
|
||||||
|
* temporary file to `newpath` and SDL_RemovePath() on `oldpath` might work
|
||||||
|
* for files. Renaming a non-empty directory across filesystems is
|
||||||
|
* dramatically more complex, however.
|
||||||
|
*
|
||||||
* \param oldpath the old path.
|
* \param oldpath the old path.
|
||||||
* \param newpath the new path.
|
* \param newpath the new path.
|
||||||
* \returns true on success or false on failure; call SDL_GetError() for more
|
* \returns true on success or false on failure; call SDL_GetError() for more
|
||||||
@@ -312,6 +326,35 @@ extern SDL_DECLSPEC bool SDLCALL SDL_RenamePath(const char *oldpath, const char
|
|||||||
/**
|
/**
|
||||||
* Copy a file.
|
* Copy a file.
|
||||||
*
|
*
|
||||||
|
* If the file at `newpath` already exists, it will be overwritten with the
|
||||||
|
* contents of the file at `oldpath`.
|
||||||
|
*
|
||||||
|
* This function will block until the copy is complete, which might be a
|
||||||
|
* significant time for large files on slow disks. On some platforms, the
|
||||||
|
* copy can be handed off to the OS itself, but on others SDL might just open
|
||||||
|
* both paths, and read from one and write to the other.
|
||||||
|
*
|
||||||
|
* Note that this is not an atomic operation! If something tries to read from
|
||||||
|
* `newpath` while the copy is in progress, it will see an incomplete copy
|
||||||
|
* of the data, and if the calling thread terminates (or the power goes out)
|
||||||
|
* during the copy, `oldpath`'s previous contents will be gone, replaced with
|
||||||
|
* an incomplete copy of the data. To avoid this risk, it is recommended that
|
||||||
|
* the app copy to a temporary file in the same directory as `newpath`, and
|
||||||
|
* if the copy is successful, use SDL_RenamePath() to replace `newpath` with
|
||||||
|
* the temporary file. This will ensure that reads of `newpath` will either
|
||||||
|
* see a complete copy of the data, or it will see the pre-copy state of
|
||||||
|
* `newpath`.
|
||||||
|
*
|
||||||
|
* This function attempts to synchronize the newly-copied data to disk before
|
||||||
|
* returning, if the platform allows it, so that the renaming trick will not
|
||||||
|
* have a problem in a system crash or power failure, where the file could
|
||||||
|
* be renamed but the contents never made it from the system file cache to
|
||||||
|
* the physical disk.
|
||||||
|
*
|
||||||
|
* If the copy fails for any reason, the state of `newpath` is undefined. It
|
||||||
|
* might be half a copy, it might be the untouched data of what was already
|
||||||
|
* there, or it might be a zero-byte file, etc.
|
||||||
|
*
|
||||||
* \param oldpath the old path.
|
* \param oldpath the old path.
|
||||||
* \param newpath the new path.
|
* \param newpath the new path.
|
||||||
* \returns true on success or false on failure; call SDL_GetError() for more
|
* \returns true on success or false on failure; call SDL_GetError() for more
|
||||||
|
@@ -147,8 +147,11 @@ typedef struct SDL_IOStreamInterface
|
|||||||
/**
|
/**
|
||||||
* Close and free any allocated resources.
|
* Close and free any allocated resources.
|
||||||
*
|
*
|
||||||
|
* This does not guarantee file writes will sync to physical media; they
|
||||||
|
* can be in the system's file cache, waiting to go to disk.
|
||||||
|
*
|
||||||
* The SDL_IOStream is still destroyed even if this fails, so clean up anything
|
* The SDL_IOStream is still destroyed even if this fails, so clean up anything
|
||||||
* even if flushing to disk returns an error.
|
* even if flushing buffers, etc, returns an error.
|
||||||
*
|
*
|
||||||
* \return true if successful or false on write error when flushing data.
|
* \return true if successful or false on write error when flushing data.
|
||||||
*/
|
*/
|
||||||
@@ -406,8 +409,17 @@ extern SDL_DECLSPEC SDL_IOStream * SDLCALL SDL_OpenIO(const SDL_IOStreamInterfac
|
|||||||
* returns true on success, or false if the stream failed to flush to its
|
* returns true on success, or false if the stream failed to flush to its
|
||||||
* output (e.g. to disk).
|
* output (e.g. to disk).
|
||||||
*
|
*
|
||||||
* Note that if this fails to flush the stream to disk, this function reports
|
* Note that if this fails to flush the stream for any reason, this function
|
||||||
* an error, but the SDL_IOStream is still invalid once this function returns.
|
* reports an error, but the SDL_IOStream is still invalid once this function
|
||||||
|
* returns.
|
||||||
|
*
|
||||||
|
* This call flushes any buffered writes to the operating system, but there
|
||||||
|
* are no guarantees that those writes have gone to physical media; they might
|
||||||
|
* be in the OS's file cache, waiting to go to disk later. If it's absolutely
|
||||||
|
* crucial that writes go to disk immediately, so they are definitely stored
|
||||||
|
* even if the power fails before the file cache would have caught up, one
|
||||||
|
* should call SDL_FlushIO() before closing. Note that flushing takes time and
|
||||||
|
* makes the system and your app operate less efficiently, so do so sparingly.
|
||||||
*
|
*
|
||||||
* \param context SDL_IOStream structure to close.
|
* \param context SDL_IOStream structure to close.
|
||||||
* \returns true on success or false on failure; call SDL_GetError() for more
|
* \returns true on success or false on failure; call SDL_GetError() for more
|
||||||
|
@@ -121,7 +121,12 @@ bool SDL_SYS_CopyFile(const char *oldpath, const char *newpath)
|
|||||||
SDL_CloseIO(input);
|
SDL_CloseIO(input);
|
||||||
input = NULL;
|
input = NULL;
|
||||||
|
|
||||||
|
if (!SDL_FlushIO(output)) {
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
if (!SDL_CloseIO(output)) {
|
if (!SDL_CloseIO(output)) {
|
||||||
|
output = NULL; // it's gone, even if it failed.
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
output = NULL;
|
output = NULL;
|
||||||
|
@@ -151,7 +151,7 @@ bool SDL_SYS_CopyFile(const char *oldpath, const char *newpath)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const BOOL rc = CopyFileW(woldpath, wnewpath, TRUE);
|
const BOOL rc = CopyFileExW(woldpath, wnewpath, NULL, NULL, NULL, COPY_FILE_ALLOW_DECRYPTED_DESTINATION|COPY_FILE_NO_BUFFERING);
|
||||||
SDL_free(wnewpath);
|
SDL_free(wnewpath);
|
||||||
SDL_free(woldpath);
|
SDL_free(woldpath);
|
||||||
if (!rc) {
|
if (!rc) {
|
||||||
|
Reference in New Issue
Block a user