@@ -552,6 +552,22 @@ void ReverseDisplacements(std::vector<std::size_t> &displacements, ROOT::Interna
552552 }
553553}
554554
555+ struct RPutReadState {
556+ const unsigned char *fData ;
557+ std::size_t fLength ;
558+ std::size_t fOffset = 0 ;
559+ };
560+
561+ std::size_t CallbackPutRead (char *buffer, std::size_t size, std::size_t nmemb, void *userdata)
562+ {
563+ auto *state = static_cast <RPutReadState *>(userdata);
564+ std::size_t remaining = state->fLength - state->fOffset ;
565+ std::size_t toCopy = std::min (size * nmemb, remaining);
566+ memcpy (buffer, state->fData + state->fOffset , toCopy);
567+ state->fOffset += toCopy;
568+ return toCopy;
569+ }
570+
555571std::string GetCurlErrorString (CURLcode code)
556572{
557573 return std::string (curl_easy_strerror (code)) + " (" + std::to_string (code) + " )" ;
@@ -849,6 +865,42 @@ ROOT::Internal::RCurlConnection::SendRangesReq(std::size_t N, RUserRange *ranges
849865 return status;
850866}
851867
868+ ROOT ::Internal::RCurlConnection::RStatus
869+ ROOT::Internal::RCurlConnection::SendPutReq (const unsigned char *data, std::size_t length)
870+ {
871+ auto rc = curl_easy_setopt (fHandle , CURLOPT_UPLOAD , 1L );
872+ R__ASSERT (rc == CURLE_OK );
873+ rc = curl_easy_setopt (fHandle , CURLOPT_INFILESIZE_LARGE , static_cast <curl_off_t >(length));
874+ R__ASSERT (rc == CURLE_OK );
875+
876+ // Reset sticky options that may have been set by previous HEAD or GET calls on this handle
877+ rc = curl_easy_setopt (fHandle , CURLOPT_NOBODY , 0L );
878+ R__ASSERT (rc == CURLE_OK );
879+ rc = curl_easy_setopt (fHandle , CURLOPT_HTTPGET , 0L );
880+ R__ASSERT (rc == CURLE_OK );
881+ rc = curl_easy_setopt (fHandle , CURLOPT_RANGE , NULL );
882+ R__ASSERT (rc == CURLE_OK );
883+
884+ RPutReadState readState{data, length, 0 };
885+ rc = curl_easy_setopt (fHandle , CURLOPT_READFUNCTION , CallbackPutRead);
886+ R__ASSERT (rc == CURLE_OK );
887+ rc = curl_easy_setopt (fHandle , CURLOPT_READDATA , &readState);
888+ R__ASSERT (rc == CURLE_OK );
889+
890+ RStatus status;
891+ Perform (status);
892+
893+ // Reset upload options so that subsequent GET/HEAD calls on this handle are not affected
894+ rc = curl_easy_setopt (fHandle , CURLOPT_UPLOAD , 0L );
895+ R__ASSERT (rc == CURLE_OK );
896+ rc = curl_easy_setopt (fHandle , CURLOPT_READFUNCTION , NULL );
897+ R__ASSERT (rc == CURLE_OK );
898+ rc = curl_easy_setopt (fHandle , CURLOPT_READDATA , NULL );
899+ R__ASSERT (rc == CURLE_OK );
900+
901+ return status;
902+ }
903+
852904void ROOT::Internal::RCurlConnection::SetCredentials (const RS3Credentials &credentials)
853905{
854906 ClearCredentials ();
0 commit comments