Skip to content

Commit

Permalink
tool/-T: perform non-chunked transfer for stdin if it is a regular file
Browse files Browse the repository at this point in the history
curl will now also compute the content-length of the transfer if stdin
is the file to upload and stdin is a regular file, using its file size.

Since, while being a regular file, stdin could not have its offset at
the start of the file, curl will now also get the current offset into
the upload file's file descriptor and use (filesize - offset) as
content-length for transfer instead of just using the full filesize.
This also fixes a bug on BSDs where open("/dev/fd/N") behaves like
dup(N), so, if N is a file descriptor to a regular file, the file offset
of the file descriptor returned by open() may not have been at the start
of the file despite curl's previous assumption.

Since I don't know anything about VMS systems, I left the behaviour for
VMS unchanged; on VMS, curl will still perform a chunked transfer if the
upload file is stdin.

Fixes curl#12171
Fixes curl#12177
  • Loading branch information
emanuele6 committed Oct 21, 2023
1 parent 014ce7c commit 0216878
Showing 1 changed file with 18 additions and 1 deletion.
19 changes: 18 additions & 1 deletion src/tool_operate.c
Expand Up @@ -267,6 +267,7 @@ static CURLcode pre_transfer(struct GlobalConfig *global,
struct_stat fileinfo;
CURLcode result = CURLE_OK;

#ifdef __VMS
if(per->uploadfile && !stdin_upload(per->uploadfile)) {
/* VMS Note:
*
Expand All @@ -282,7 +283,6 @@ static CURLcode pre_transfer(struct GlobalConfig *global,
* header for VARIABLE header files only the bare record data needs
* to be considered with one appended if implied CC
*/
#ifdef __VMS
/* Calculate the real upload size for VMS */
per->infd = -1;
if(stat(per->uploadfile, &fileinfo) == 0) {
Expand All @@ -300,6 +300,8 @@ static CURLcode pre_transfer(struct GlobalConfig *global,
}
if(per->infd == -1)
#else
if(per->uploadfile) {
if(!stdin_upload(per->uploadfile))
per->infd = open(per->uploadfile, O_RDONLY | O_BINARY);
if((per->infd == -1) || fstat(per->infd, &fileinfo))
#endif
Expand All @@ -315,7 +317,22 @@ static CURLcode pre_transfer(struct GlobalConfig *global,

/* we ignore file size for char/block devices, sockets, etc. */
if(S_ISREG(fileinfo.st_mode))
#ifdef __VMS
uploadfilesize = fileinfo.st_size;
#else
{
/* When the upload file is stdin, or when the upload file is
/dev/std{in,out,err} or /dev/fd/N on BSDs, the offset may not
be 0 */
off_t offset = lseek(per->infd, 0, SEEK_CUR);
if(offset >= 0)
uploadfilesize = fileinfo.st_size - offset;
else {
warnf(global, "Can't get file position of file descriptor %d ('%s')",
per->infd, per->uploadfile);
}
}
#endif

#ifdef DEBUGBUILD
/* allow dedicated test cases to override */
Expand Down

0 comments on commit 0216878

Please sign in to comment.