Rahul
Rahul

Reputation: 1423

ftell function giving -1 in C for stdout

I want to wget in C and I am using popen to do so.

FILE *stdoutPtr = popen(command,"r");
fseek(stdoutPtr, 0L, SEEK_END);
long pos = ftell(stdoutPtr);

Here I want to get the size of stdout so that I can initialize buffer. But pos variable is always -1. pos is supposed to tell me current position of read pointer.

Please help....

Upvotes: 1

Views: 2197

Answers (2)

zwol
zwol

Reputation: 140846

The FILE returned by popen is not a regular file, but a thing called a pipe. (That's what the p stands for.) Data flows through the pipe from the stdout of the command you invoked to your program. Because it's a communications channel and not a file on disk, a pipe does not have a definite size, and you cannot seek to different locations in the data stream. Therefore, fseek and ftell will both fail when applied to this FILE, and that's what a -1 return value means. If you inspect errno immediately after the call to ftell you will discover that it has the value ESPIPE, which means "You can't do that to a pipe."

If you're trying to read all of the output from the command into a single char* buffer, the only way to do it is to repeatedly call one of the read functions until it indicates end-of-file, and enlarge the buffer as necessary using realloc. If the output is potentially large, it would be better to change your program to process the data in chunks, if there's any way to do that.

Upvotes: 7

David Schwartz
David Schwartz

Reputation: 182865

You can't use pipes that way. For one thing, the information would be obsolete the instant you got it, since more data could be written to the pipe by then. You have to use a different allocation strategy.

The most common strategy is to allocate a fixed-size buffer and just keep reading until you reach end of file. You can process the data as you read it, if you like.

If you need to process the data all in one chunk, you can allocate a large buffer and start reading into that. If it does get full, then use realloc to enlarge the buffer and keep going until you have it all.

A common pattern is to keep a buffer pointer, a buffer count, and an allocation size. Initially, set the allocation size to, say, 64K. Set the count to zero. Allocate a 64K buffer. Read up to size-count bytes into the buffer. If you hit EOF, stop. If the buffer is nearly full, bump up the allocation size by 50% and realloc the buffer.

Upvotes: 1

Related Questions