From owner-freebsd-hackers@freebsd.org Thu Aug 22 20:28:43 2019 Return-Path: Delivered-To: freebsd-hackers@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id CDCFCD1D2A for ; Thu, 22 Aug 2019 20:28:43 +0000 (UTC) (envelope-from cse.cem@gmail.com) Received: from mail-io1-f51.google.com (mail-io1-f51.google.com [209.85.166.51]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits) server-signature RSA-PSS (4096 bits) client-signature RSA-PSS (2048 bits) client-digest SHA256) (Client CN "smtp.gmail.com", Issuer "GTS CA 1O1" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 46Dx2267GFz3P4Y for ; Thu, 22 Aug 2019 20:28:42 +0000 (UTC) (envelope-from cse.cem@gmail.com) Received: by mail-io1-f51.google.com with SMTP id j4so6443034iog.11 for ; Thu, 22 Aug 2019 13:28:42 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:reply-to :from:date:message-id:subject:to:cc:content-transfer-encoding; bh=cQsAP+df6Z6GEGHjY2g8jfROCTZrHrYVXRm6DzSOxdI=; b=dqvPJOhZonDo9tTyop5ZJ/CN3+gAN4f27b7AcX2qoneAQYCmLOdDCYhlk/0TaXhRpK JqC0DkOqy5N5OLIi1esD1TbS/SYkwdryn+tVe+XEmCK/OspnLXVYpiNp4bCzSgaFay23 hkESWATpAqQMtX+nJrKYQk3dURxiFQDkST5izTi/Vy8mEEqfpNa3sDl1DkkEDnYWLClW ExnasGYQBKivZCLJ+kaweXDd+5PzCwsgdcrQ6imWokm9/rR7b7w0XWIaha+mtp5gdS0i KJFqvg3ADGGQ8UB358a+tbGkKFkInMpwZ6vZdC6Yb6WoV5kCP1BUXerhmdvAQZsRPwcQ hiUg== X-Gm-Message-State: APjAAAVRD52XEiybULqexQ2o/QkNPZ/uQsp/lFnW3ZtGN6ZOWFaesmhO h0p/r/jqsSaxXtnun9kG/a6Sl/tt X-Google-Smtp-Source: APXvYqzVshsGzt2gs0EBhDYKL5e4mEfJcv1gODFdUuKjEtEVSN+EvODH4CqQ25Q1AjvQlvdumCGUDg== X-Received: by 2002:a02:650b:: with SMTP id u11mr1451891jab.81.1566505721528; Thu, 22 Aug 2019 13:28:41 -0700 (PDT) Received: from mail-io1-f49.google.com (mail-io1-f49.google.com. [209.85.166.49]) by smtp.gmail.com with ESMTPSA id y5sm460313ioc.86.2019.08.22.13.28.40 for (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Thu, 22 Aug 2019 13:28:40 -0700 (PDT) Received: by mail-io1-f49.google.com with SMTP id x4so14679412iog.13 for ; Thu, 22 Aug 2019 13:28:40 -0700 (PDT) X-Received: by 2002:a5e:c101:: with SMTP id v1mr958126iol.231.1566505720779; Thu, 22 Aug 2019 13:28:40 -0700 (PDT) MIME-Version: 1.0 References: <519c2fce85fe0db1cd189d2060f09a0f@farhan.codes> In-Reply-To: <519c2fce85fe0db1cd189d2060f09a0f@farhan.codes> Reply-To: cem@freebsd.org From: Conrad Meyer Date: Thu, 22 Aug 2019 13:28:30 -0700 X-Gmail-Original-Message-ID: Message-ID: Subject: Re: Trouble using and understanding funopen(3) To: Farhan Khan Cc: "freebsd-hackers@freebsd.org" Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Rspamd-Queue-Id: 46Dx2267GFz3P4Y X-Spamd-Bar: ----- Authentication-Results: mx1.freebsd.org; dkim=none; dmarc=none; spf=pass (mx1.freebsd.org: domain of csecem@gmail.com designates 209.85.166.51 as permitted sender) smtp.mailfrom=csecem@gmail.com X-Spamd-Result: default: False [-5.54 / 15.00]; TO_DN_EQ_ADDR_SOME(0.00)[]; RCVD_VIA_SMTP_AUTH(0.00)[]; HAS_REPLYTO(0.00)[cem@freebsd.org]; TO_DN_SOME(0.00)[]; R_SPF_ALLOW(-0.20)[+ip4:209.85.128.0/17]; REPLYTO_ADDR_EQ_FROM(0.00)[]; RCVD_COUNT_THREE(0.00)[4]; NEURAL_HAM_SHORT(-1.00)[-0.996,0]; RCPT_COUNT_TWO(0.00)[2]; FORGED_SENDER(0.30)[cem@freebsd.org,csecem@gmail.com]; MIME_TRACE(0.00)[0:+]; R_DKIM_NA(0.00)[]; FREEMAIL_ENVFROM(0.00)[gmail.com]; ASN(0.00)[asn:15169, ipnet:209.85.128.0/17, country:US]; TAGGED_FROM(0.00)[]; ARC_NA(0.00)[]; NEURAL_HAM_MEDIUM(-1.00)[-1.000,0]; FROM_NEQ_ENVFROM(0.00)[cem@freebsd.org,csecem@gmail.com]; FROM_HAS_DN(0.00)[]; NEURAL_HAM_LONG(-1.00)[-1.000,0]; MIME_GOOD(-0.10)[text/plain]; PREVIOUSLY_DELIVERED(0.00)[freebsd-hackers@freebsd.org]; DMARC_NA(0.00)[freebsd.org]; TO_MATCH_ENVRCPT_SOME(0.00)[]; RCVD_IN_DNSWL_NONE(0.00)[51.166.85.209.list.dnswl.org : 127.0.5.0]; IP_SCORE(-2.55)[ip: (-6.99), ipnet: 209.85.128.0/17(-3.35), asn: 15169(-2.35), country: US(-0.05)]; RCVD_TLS_ALL(0.00)[] X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 22 Aug 2019 20:28:43 -0000 Hi Farhan, First, I'd suggest using the more portable fopencookie(3) interface, which is similar to funopen(3). Second, read functions return 0 to indicate end of file. Finally, the file cookie routines are stateful. If you want to create a pseudo-FILE that only has 10 bytes in it, you have to track the current file offset by creating a cookie. Here is a minimal example of using a cookie. struct my_file { off_t offset; }; my_read(void *v, buf, len) { struct my_file *f =3D v; size_t rlen; /* Indicate EOF for reads past EOF. */ if (f->offset >=3D 10) return (0); rlen =3D MIN(len, 10 - f->offset); memcpy(buf, "AAAAAAAAAA", rlen); f->offset +=3D rlen; return ((int)rlen); } main() { struct my_file *cookie; FILE *f; char buf[100]; size_t x; cookie =3D calloc(1, sizeof(*cookie)); f =3D fopencookie(cookie, "rb", { .read =3D my_read, }); x =3D fread(buf, 1, sizeof(buf), f); ... } Conrad On Thu, Aug 22, 2019 at 9:24 AM Farhan Khan via freebsd-hackers wrote: > > Hi all, > > I am having trouble understanding how funopen(3)'s read function works. S= pecifically, how do I have the readfn return with less than the requested a= mount 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 handle= r 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 th= an the numbe of requested bytes? For example, what if the calling fread() f= unction requests 100 bytes, but the readfn can only return 10 bytes? What m= echanism do I need to implement so that the fread(3) returns "10" bytes rat= her 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 u= se buffering and append the bytes they read to the memory object they were = initially passed. Somehow they return with the number of bytes they actuall= y read, not necessarily the requested amount. But it is not clear to me how= they make this distinction and avoid having their respective readfn functi= on re-rerun. Also, in the examples I did look up there does not appear to b= e any use of setvbuf(). > > Below is a very simple test case to illustrate the issue. > > ------ > #include > #include > #include > > 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 =3D funopen(NULL, ssh_readfn, ssh_writefn, NULL, NULL); > if (f =3D=3D NULL) { > printf("funopen failed, exiting.\n"); > exit(0); > } > > x =3D fread(buf, 1, 100, f); > printf("Bytes read: %d\n", x); > } > ------ > > This displays 10 "Running readfn handler" lines fllowed by "Bytes read: 1= 00" even though I am explicitly returning 10 in ssh_readfn. Please advise w= hat the mechanism is only return with less than the requested number of byt= es. > > Thanks! > --- > Farhan Khan > PGP Fingerprint: 1312 89CE 663E 1EB2 179C 1C83 C41D 2281 F8DA C0DE > _______________________________________________ > freebsd-hackers@freebsd.org mailing list > https://lists.freebsd.org/mailman/listinfo/freebsd-hackers > To unsubscribe, send any mail to "freebsd-hackers-unsubscribe@freebsd.org= "