mirror of
https://github.com/libsdl-org/SDL.git
synced 2025-09-29 06:28:29 +00:00
io: POSIX implementation tries to get status information on short reads/writes.
Fixes #13413.
This commit is contained in:
@@ -421,18 +421,36 @@ static size_t SDLCALL fd_read(void *userdata, void *ptr, size_t size, SDL_IOStat
|
|||||||
ssize_t bytes;
|
ssize_t bytes;
|
||||||
do {
|
do {
|
||||||
bytes = read(iodata->fd, ptr, size);
|
bytes = read(iodata->fd, ptr, size);
|
||||||
} while (bytes < 0 && errno == EINTR);
|
} while ((bytes < 0) && (errno == EINTR));
|
||||||
|
|
||||||
if (bytes < 0) {
|
ssize_t result = bytes;
|
||||||
|
if ((bytes > 0) && (bytes < size)) { // was it a short read, EOF, or error?
|
||||||
|
// try to read the difference, so we can rule out a short read.
|
||||||
|
do {
|
||||||
|
result = read(iodata->fd, ((Uint8 *) ptr) + bytes, size - bytes);
|
||||||
|
} while ((result < 0) && (errno == EINTR));
|
||||||
|
|
||||||
|
if (result > 0) {
|
||||||
|
bytes += result;
|
||||||
|
result = bytes;
|
||||||
|
SDL_assert(bytes <= size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result < 0) {
|
||||||
if (errno == EAGAIN) {
|
if (errno == EAGAIN) {
|
||||||
*status = SDL_IO_STATUS_NOT_READY;
|
*status = SDL_IO_STATUS_NOT_READY;
|
||||||
} else {
|
} else {
|
||||||
*status = SDL_IO_STATUS_ERROR;
|
*status = SDL_IO_STATUS_ERROR;
|
||||||
SDL_SetError("Error reading from datastream: %s", strerror(errno));
|
SDL_SetError("Error reading from datastream: %s", strerror(errno));
|
||||||
}
|
}
|
||||||
|
if (bytes < 0) {
|
||||||
bytes = 0;
|
bytes = 0;
|
||||||
} else if (bytes == 0) {
|
}
|
||||||
|
} else if (result == 0) {
|
||||||
*status = SDL_IO_STATUS_EOF;
|
*status = SDL_IO_STATUS_EOF;
|
||||||
|
} else if (result < size) {
|
||||||
|
*status = SDL_IO_STATUS_NOT_READY;;
|
||||||
}
|
}
|
||||||
return (size_t)bytes;
|
return (size_t)bytes;
|
||||||
}
|
}
|
||||||
@@ -443,17 +461,36 @@ static size_t SDLCALL fd_write(void *userdata, const void *ptr, size_t size, SDL
|
|||||||
ssize_t bytes;
|
ssize_t bytes;
|
||||||
do {
|
do {
|
||||||
bytes = write(iodata->fd, ptr, size);
|
bytes = write(iodata->fd, ptr, size);
|
||||||
} while (bytes < 0 && errno == EINTR);
|
} while ((bytes < 0) && (errno == EINTR));
|
||||||
|
|
||||||
if (bytes < 0) {
|
ssize_t result = bytes;
|
||||||
|
if ((bytes > 0) && (bytes < size)) { // was it a short write, or error?
|
||||||
|
// try to write the difference, so we can rule out a short read.
|
||||||
|
do {
|
||||||
|
result = write(iodata->fd, ((Uint8 *) ptr) + bytes, size - bytes);
|
||||||
|
} while ((result < 0) && (errno == EINTR));
|
||||||
|
|
||||||
|
if (result > 0) {
|
||||||
|
bytes += result;
|
||||||
|
result = bytes;
|
||||||
|
SDL_assert(bytes <= size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result < 0) {
|
||||||
if (errno == EAGAIN) {
|
if (errno == EAGAIN) {
|
||||||
*status = SDL_IO_STATUS_NOT_READY;
|
*status = SDL_IO_STATUS_NOT_READY;
|
||||||
} else {
|
} else {
|
||||||
*status = SDL_IO_STATUS_ERROR;
|
*status = SDL_IO_STATUS_ERROR;
|
||||||
SDL_SetError("Error writing to datastream: %s", strerror(errno));
|
SDL_SetError("Error writing to datastream: %s", strerror(errno));
|
||||||
}
|
}
|
||||||
|
if (bytes < 0) {
|
||||||
bytes = 0;
|
bytes = 0;
|
||||||
}
|
}
|
||||||
|
} else if (result < size) {
|
||||||
|
*status = SDL_IO_STATUS_NOT_READY;;
|
||||||
|
}
|
||||||
|
|
||||||
return (size_t)bytes;
|
return (size_t)bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user