SDL
201 строка · 5.7 Кб
1/*
2Simple DirectMedia Layer
3Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
4
5This software is provided 'as-is', without any express or implied
6warranty. In no event will the authors be held liable for any damages
7arising from the use of this software.
8
9Permission is granted to anyone to use this software for any purpose,
10including commercial applications, and to alter it and redistribute it
11freely, subject to the following restrictions:
12
131. The origin of this software must not be misrepresented; you must not
14claim that you wrote the original software. If you use this software
15in a product, an acknowledgment in the product documentation would be
16appreciated but is not required.
172. Altered source versions must be plainly marked as such, and must not be
18misrepresented as being the original software.
193. This notice may not be removed or altered from any source distribution.
20*/
21
22#include "SDL_internal.h"
23
24#if defined(SDL_FSOPS_POSIX)
25
26/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
27// System dependent filesystem routines
28
29#include "../SDL_sysfilesystem.h"
30
31#include <stdio.h>
32#include <string.h>
33#include <errno.h>
34#include <dirent.h>
35#include <sys/stat.h>
36
37int SDL_SYS_EnumerateDirectory(const char *path, const char *dirname, SDL_EnumerateDirectoryCallback cb, void *userdata)
38{
39int result = 1;
40
41DIR *dir = opendir(path);
42if (!dir) {
43SDL_SetError("Can't open directory: %s", strerror(errno));
44return -1;
45}
46
47struct dirent *ent;
48while ((result == 1) && ((ent = readdir(dir)) != NULL))
49{
50const char *name = ent->d_name;
51if ((SDL_strcmp(name, ".") == 0) || (SDL_strcmp(name, "..") == 0)) {
52continue;
53}
54result = cb(userdata, dirname, name);
55}
56
57closedir(dir);
58
59return result;
60}
61
62bool SDL_SYS_RemovePath(const char *path)
63{
64int rc = remove(path);
65if (rc < 0) {
66if (errno == ENOENT) {
67// It's already gone, this is a success
68return true;
69}
70return SDL_SetError("Can't remove path: %s", strerror(errno));
71}
72return true;
73}
74
75bool SDL_SYS_RenamePath(const char *oldpath, const char *newpath)
76{
77if (rename(oldpath, newpath) < 0) {
78return SDL_SetError("Can't remove path: %s", strerror(errno));
79}
80return true;
81}
82
83bool SDL_SYS_CopyFile(const char *oldpath, const char *newpath)
84{
85char *buffer = NULL;
86char *tmppath = NULL;
87SDL_IOStream *input = NULL;
88SDL_IOStream *output = NULL;
89const size_t maxlen = 4096;
90size_t len;
91bool result = false;
92
93if (SDL_asprintf(&tmppath, "%s.tmp", newpath) < 0) {
94goto done;
95}
96
97input = SDL_IOFromFile(oldpath, "rb");
98if (!input) {
99goto done;
100}
101
102output = SDL_IOFromFile(tmppath, "wb");
103if (!output) {
104goto done;
105}
106
107buffer = (char *)SDL_malloc(maxlen);
108if (!buffer) {
109goto done;
110}
111
112while ((len = SDL_ReadIO(input, buffer, maxlen)) > 0) {
113if (SDL_WriteIO(output, buffer, len) < len) {
114goto done;
115}
116}
117if (SDL_GetIOStatus(input) != SDL_IO_STATUS_EOF) {
118goto done;
119}
120
121SDL_CloseIO(input);
122input = NULL;
123
124if (!SDL_CloseIO(output)) {
125goto done;
126}
127output = NULL;
128
129if (!SDL_RenamePath(tmppath, newpath)) {
130SDL_RemovePath(tmppath);
131goto done;
132}
133
134result = true;
135
136done:
137if (output) {
138SDL_CloseIO(output);
139SDL_RemovePath(tmppath);
140}
141if (input) {
142SDL_CloseIO(input);
143}
144SDL_free(tmppath);
145SDL_free(buffer);
146
147return result;
148}
149
150bool SDL_SYS_CreateDirectory(const char *path)
151{
152const int rc = mkdir(path, 0770);
153if (rc < 0) {
154const int origerrno = errno;
155if (origerrno == EEXIST) {
156struct stat statbuf;
157if ((stat(path, &statbuf) == 0) && (S_ISDIR(statbuf.st_mode))) {
158return true; // it already exists and it's a directory, consider it success.
159}
160}
161return SDL_SetError("Can't create directory: %s", strerror(origerrno));
162}
163return true;
164}
165
166bool SDL_SYS_GetPathInfo(const char *path, SDL_PathInfo *info)
167{
168struct stat statbuf;
169const int rc = stat(path, &statbuf);
170if (rc < 0) {
171return SDL_SetError("Can't stat: %s", strerror(errno));
172} else if (S_ISREG(statbuf.st_mode)) {
173info->type = SDL_PATHTYPE_FILE;
174info->size = (Uint64) statbuf.st_size;
175} else if (S_ISDIR(statbuf.st_mode)) {
176info->type = SDL_PATHTYPE_DIRECTORY;
177info->size = 0;
178} else {
179info->type = SDL_PATHTYPE_OTHER;
180info->size = (Uint64) statbuf.st_size;
181}
182
183#if defined(HAVE_ST_MTIM)
184// POSIX.1-2008 standard
185info->create_time = (SDL_Time)SDL_SECONDS_TO_NS(statbuf.st_ctim.tv_sec) + statbuf.st_ctim.tv_nsec;
186info->modify_time = (SDL_Time)SDL_SECONDS_TO_NS(statbuf.st_mtim.tv_sec) + statbuf.st_mtim.tv_nsec;
187info->access_time = (SDL_Time)SDL_SECONDS_TO_NS(statbuf.st_atim.tv_sec) + statbuf.st_atim.tv_nsec;
188#elif defined(SDL_PLATFORM_APPLE)
189/* Apple platform stat structs use 'st_*timespec' naming. */
190info->create_time = (SDL_Time)SDL_SECONDS_TO_NS(statbuf.st_ctimespec.tv_sec) + statbuf.st_ctimespec.tv_nsec;
191info->modify_time = (SDL_Time)SDL_SECONDS_TO_NS(statbuf.st_mtimespec.tv_sec) + statbuf.st_mtimespec.tv_nsec;
192info->access_time = (SDL_Time)SDL_SECONDS_TO_NS(statbuf.st_atimespec.tv_sec) + statbuf.st_atimespec.tv_nsec;
193#else
194info->create_time = (SDL_Time)SDL_SECONDS_TO_NS(statbuf.st_ctime);
195info->modify_time = (SDL_Time)SDL_SECONDS_TO_NS(statbuf.st_mtime);
196info->access_time = (SDL_Time)SDL_SECONDS_TO_NS(statbuf.st_atime);
197#endif
198return true;
199}
200
201#endif // SDL_FSOPS_POSIX
202
203