Trouble using and understanding funopen(3)

Farhan Khan farhan at farhan.codes
Thu Aug 22 16:24:29 UTC 2019


Hi all,

I am having trouble understanding how funopen(3)'s read function works. Specifically, how do I have the readfn return with less than the requested amount of bytes.

My understanding: I believe that funopen(3) allows you to assign the read, write and close methods to a FILE stream. When a program runs fread(3) on a FILE stream opened by funopen(3), the program will run the readfn handler in a loop until it returns either returns the requested number of bytes, 0 or -1 (error).

Question: How do I structure the code so that readfn returns with less than the numbe of requested bytes? For example, what if the calling fread() function requests 100 bytes, but the readfn can only return 10 bytes? What mechanism do I need to implement so that the fread(3) returns "10" bytes rather than the readfn handler running 10 times? This results in the fread()'s return value as 100, even though only 10 bytes were *actually* read.

I have looked at a few examples from the src tree. Clearly they have to use buffering and append the bytes they read to the memory object they were initially passed. Somehow they return with the number of bytes they actually read, not necessarily the requested amount. But it is not clear to me how they make this distinction and avoid having their respective readfn function re-rerun. Also, in the examples I did look up there does not appear to be any use of setvbuf().

Below is a very simple test case to illustrate the issue.

------
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

static int
ssh_readfn(void *v, char *buf, int len)
{
	printf("Running readfn handler\n");
	memcpy(buf, "AAAAAAAAAA", 10);
	return 10;
}

static int
ssh_writefn(void *v, const char *buf, int len)
{
	return 0;
}

int
main()
{
	int x;
	char buf[1000];
	FILE *f;

	f = funopen(NULL, ssh_readfn, ssh_writefn, NULL, NULL);
	if (f == NULL) {
		printf("funopen failed, exiting.\n");
		exit(0);
	}

	x = fread(buf, 1, 100, f);
	printf("Bytes read: %d\n", x);
}
------

This displays 10 "Running readfn handler" lines fllowed by "Bytes read: 100" even though I am explicitly returning 10 in ssh_readfn. Please advise what the mechanism is only return with less than the requested number of bytes.

Thanks!
---
Farhan Khan
PGP Fingerprint: 1312 89CE 663E 1EB2 179C 1C83 C41D 2281 F8DA C0DE


More information about the freebsd-hackers mailing list