curl/src/tool_cb_rea.c
Viktor Szakats 554dfa5568
build: drop Windows CE / CeGCC support
Windows CE support was limited to successful builds with ming32ce
(a toolchain that hasn't seen an update since 2009, using an ancient gcc
version and "old mingw"-style SDK headers, that curl deprecated earlier).
Builds with MSVC were broken for a long time. mingw32ce builds were never
actually tested and runtime and unlikely to work due to missing stubs.
Windows CE toolchains also miss to comply with C89. Paired with lack of
demand and support for the platform, curl deprecated it earlier.

This patch removes support from the codebase to ease maintaining Windows
codepaths.

Follow-up to f98c0ba834 #17924
Follow-up to 8491e6574c #17379
Follow-up to 2a292c3984 #15975

Closes #17927
2025-11-15 15:35:23 +01:00

202 lines
5.4 KiB
C

/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at https://curl.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* SPDX-License-Identifier: curl
*
***************************************************************************/
#include "tool_setup.h"
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
#ifdef HAVE_POLL_H
#include <poll.h>
#elif defined(HAVE_SYS_POLL_H)
#include <sys/poll.h>
#endif
#include "tool_cfgable.h"
#include "tool_cb_rea.h"
#include "tool_operate.h"
#include "tool_util.h"
#include "tool_msgs.h"
#include "memdebug.h" /* keep this as LAST include */
#ifndef _WIN32
/* Wait up to a number of milliseconds for socket activity. This function
waits on read activity on a file descriptor that is not a socket which
makes it not work with select() or poll() on Windows. */
static bool waitfd(int waitms, int fd)
{
#ifdef HAVE_POLL
struct pollfd set;
set.fd = fd;
set.events = POLLIN;
set.revents = 0;
if(poll(&set, 1, (int)waitms))
return TRUE; /* timeout */
return FALSE;
#else
fd_set bits;
struct timeval timeout;
if(fd >= FD_SETSIZE)
/* cannot wait! */
return FALSE;
/* wait this long at the most */
timeout.tv_sec = waitms / 1000;
timeout.tv_usec = (int)((waitms % 1000) * 1000);
FD_ZERO(&bits);
#ifdef __DJGPP__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Warith-conversion"
#endif
FD_SET(fd, &bits);
#ifdef __DJGPP__
#pragma GCC diagnostic pop
#endif
if(!select(fd + 1, &bits, NULL, NULL, &timeout))
return TRUE; /* timeout */
return FALSE;
#endif
}
#endif
/*
** callback for CURLOPT_READFUNCTION
*/
size_t tool_read_cb(char *buffer, size_t sz, size_t nmemb, void *userdata)
{
ssize_t rc = 0;
struct per_transfer *per = userdata;
struct OperationConfig *config = per->config;
if((per->uploadfilesize != -1) &&
(per->uploadedsofar == per->uploadfilesize)) {
/* done */
return 0;
}
if(config->timeout_ms) {
struct curltime now = curlx_now();
long msdelta = (long)curlx_timediff_ms(now, per->start);
if(msdelta > config->timeout_ms)
/* timeout */
return 0;
#ifndef _WIN32
else {
long w = config->timeout_ms - msdelta;
if(w > INT_MAX)
w = INT_MAX;
waitfd((int)w, per->infd);
}
#endif
}
/* If we are on Windows, and using `-T .`, then per->infd points to a socket
connected to stdin via a reader thread, and needs to be read with recv()
Make sure we are in non-blocking mode and infd is not regular stdin
On Linux per->infd should be stdin (0) and the block below should not
execute */
if(per->uploadfile && !strcmp(per->uploadfile, ".") && per->infd > 0) {
#if defined(_WIN32) && !defined(CURL_WINDOWS_UWP)
rc = CURL_RECV(per->infd, buffer, curlx_uztosi(sz * nmemb), 0);
if(rc < 0) {
if(SOCKERRNO == SOCKEWOULDBLOCK) {
errno = 0;
config->readbusy = TRUE;
return CURL_READFUNC_PAUSE;
}
rc = 0;
}
#else
warnf("per->infd != 0: FD == %d. This behavior"
" is only supported on desktop Windows", per->infd);
#endif
}
else {
rc = read(per->infd, buffer, sz*nmemb);
if(rc < 0) {
if(errno == EAGAIN) {
errno = 0;
config->readbusy = TRUE;
return CURL_READFUNC_PAUSE;
}
/* since size_t is unsigned we cannot return negative values fine */
rc = 0;
}
}
if((per->uploadfilesize != -1) &&
(per->uploadedsofar + rc > per->uploadfilesize)) {
/* do not allow uploading more than originally set out to do */
curl_off_t delta = per->uploadedsofar + rc - per->uploadfilesize;
warnf("File size larger in the end than when "
"started. Dropping at least %" CURL_FORMAT_CURL_OFF_T " bytes",
delta);
rc = (ssize_t)(per->uploadfilesize - per->uploadedsofar);
}
config->readbusy = FALSE;
/* when select() returned zero here, it timed out */
return (size_t)rc;
}
/*
** callback for CURLOPT_XFERINFOFUNCTION used to unpause busy reads
*/
int tool_readbusy_cb(void *clientp,
curl_off_t dltotal, curl_off_t dlnow,
curl_off_t ultotal, curl_off_t ulnow)
{
struct per_transfer *per = clientp;
struct OperationConfig *config = per->config;
static curl_off_t ulprev;
(void)dltotal;
(void)dlnow;
(void)ultotal;
(void)ulnow;
if(config->readbusy) {
if(ulprev == ulnow) {
#ifndef _WIN32
waitfd(1, per->infd);
#else
/* sleep */
curlx_wait_ms(1);
#endif
}
config->readbusy = FALSE;
curl_easy_pause(per->curl, CURLPAUSE_CONT);
}
ulprev = ulnow;
return per->noprogress ? 0 : CURL_PROGRESSFUNC_CONTINUE;
}