svn commit: r246120 - in head: include lib/libc/stdio tools/regression/lib/libc/stdio

John Baldwin jhb at freebsd.org
Thu Jan 31 17:04:19 UTC 2013


On Wednesday, January 30, 2013 9:59:26 am Pietro Cerutti wrote:
> Author: gahr (ports committer)
> Date: Wed Jan 30 14:59:26 2013
> New Revision: 246120
> URL: http://svnweb.freebsd.org/changeset/base/246120
> 
> Log:
>   Add fmemopen(3), an interface to get a FILE * from a buffer in memory, along
>   with the respective regression test.
>   See http://pubs.opengroup.org/onlinepubs/9699919799/functions/fmemopen.html
>   
>   Reviewed by:	cognet
>   Approved by:	cognet

A few style suggestions:
 
> Added: head/lib/libc/stdio/fmemopen.c
> ==============================================================================
> --- /dev/null	00:00:00 1970	(empty, because file is newly added)
> +++ head/lib/libc/stdio/fmemopen.c	Wed Jan 30 14:59:26 2013	(r246120)
> @@ -0,0 +1,182 @@
> +/*-
> +Copyright (C) 2013 Pietro Cerutti <gahr at FreeBSD.org>
> +
> +Redistribution and use in source and binary forms, with or without
> +modification, are permitted provided that the following conditions
> +are met:

This is atypical style for license blocks.  They always have a leading
' *' in other C files.  In as much as possible this should match the
template in /usr/share/examples/etc/bsd-style-copyright as much as
possible.

> +static int	fmemopen_read  (void *cookie, char *buf, int nbytes);
> +static int	fmemopen_write (void *cookie, const char *buf, int nbytes);
> +static fpos_t	fmemopen_seek  (void *cookie, fpos_t offset, int whence);
> +static int	fmemopen_close (void *cookie);

BSD style does not have spaces between function names and the list of arguments
both in prototypes and calls.

> +
> +FILE *
> +fmemopen (void * __restrict buf, size_t size, const char * __restrict mode)
> +{
> +	/* allocate cookie */

Banal comment (this is already obvious from the code).

> +	struct __fmemopen_cookie *ck = malloc (sizeof (struct __fmemopen_cookie));

Extra spaces after 'malloc' and 'sizeof'.  Bruce also generally frowns upon
assignments in declarations.

> +	if (ck == NULL) {
> +		errno = ENOMEM;
> +		return (NULL);
> +	}
> +
> +	ck->off = 0;
> +	ck->len = size;
> +
> +	/* do we have to allocate the buffer ourselves? */

Capitalize 'do' here as this is a sentence.  (Comments should be full
sentences when possible)

> +	ck->own = ((ck->buf = buf) == NULL);
> +	if (ck->own) {
> +		ck->buf = malloc (size);
> +		if (ck->buf == NULL) {
> +			free (ck);

Not sure if you should save errno around free (once you let the malloc()
error fall through per jilles@ notes).

> +			errno = ENOMEM;
> +			return (NULL);
> +		}
> +		ck->buf[0] = '\0';
> +	}
> +
> +	if (mode[0] == 'a')
> +		ck->off = strnlen(ck->buf, ck->len);
> +
> +	/* actuall wrapper */

s/actuall/actual/, but I would just remove this comment instead.

> +	FILE *f = funopen ((void *)ck, fmemopen_read, fmemopen_write,
> +	    fmemopen_seek, fmemopen_close);

Cast to (void *) is not required in ANSI C and is just ugly.

> +	/* turn off buffering, so a write past the end of the buffer
> +	 * correctly returns a short object count */

Please format this per style(9):

	/*
	 * Turn off buffering so a write past the end of the buffer
	 * correctl returns a short object count.
	 */

> +	setvbuf (f, (char *) NULL, _IONBF, 0);

Note that a user can override this by calling setvbuf() on the
returned FILE object.  Not sure that is worth obsessing over.

> +static int
> +fmemopen_read (void *cookie, char *buf, int nbytes)
> +{
> +	struct __fmemopen_cookie *ck = cookie;
> +
> +	if (nbytes > ck->len - ck->off)
> +		nbytes = ck->len - ck->off;
> +
> +	if (nbytes == 0)
> +		return (0);
> +
> +	memcpy (buf, ck->buf + ck->off, nbytes);
> +
> +	ck->off += nbytes;
> +
> +	return (nbytes);

I would probably trim the blank lines here a bit.  Certainly between the
memcpy() and ck->off assignment, but I would probably trim this down to
just one blank line between the variable declarations and the code body.
Similar in other places.

> +static fpos_t
> +fmemopen_seek (void *cookie, fpos_t offset, int whence)
> +{
> +	struct __fmemopen_cookie *ck = cookie;
> +
> +
> +	switch (whence) {
> +	case SEEK_SET:
> +		if (offset > ck->len) {
> +			errno = EINVAL;
> +			return (-1);

This should return POS_ERR on failure.

-- 
John Baldwin


More information about the svn-src-head mailing list