Subject: Re: SUSv3 extended API set
To: Rui Paulo <rpaulo@fnop.net>
From: Pavel Cahyna <pavel.cahyna@st.mff.cuni.cz>
List: tech-userlevel
Date: 12/18/2005 09:10:48
--mP3DRpeJDSE+ciuQ
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
On Sat, Dec 17, 2005 at 12:03:00AM +0000, Rui Paulo wrote:
> I just saw this on the freebsd-standards mailing list.
> http://lists.freebsd.org/pipermail/freebsd-standards/2005-December/001087.html
>
> We already support some of them, but I guess we should start working
> to implement the new ones.
>
> Thoughts?
I have an implementation of fmemopen(). If you are interested in it, it's
attached.
Bye Pavel
--mP3DRpeJDSE+ciuQ
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="fmemopen.c"
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include "fmemopen.h"
#define READ 1
#define WRITE 2
/* zkratit na nulovou delku */
#define TRUNCATE 4
/* zapis ignoruje cur_pos a misto toho se pripojuje na konec */
#define APPEND 16
typedef struct cookie {
void * buf;
fpos_t cur_pos;
size_t size;
size_t cur_size;
int flags;
} cookie_t;
static int (*appendmem)(void *, const char *, int) = NULL;
int closemem (void * cookie)
{
cookie_t * cookie_p;
cookie_p = ( cookie_t * ) cookie;
assert ( cookie_p->size >= cookie_p->cur_size);
if ( cookie_p->size > cookie_p->cur_size) {
* ((char*) (cookie_p->buf) + cookie_p->cur_size) = 0;
}
return 0;
}
int writemem (void * cookie, const char * src, int nbytes)
{
size_t remain;
long lremain;
cookie_t * cookie_p;
/* printf ("writemem: %d\n", nbytes); */
cookie_p = ( cookie_t * ) cookie;
assert ( cookie_p->size >= cookie_p->cur_size);
if ((nbytes < 0) || (cookie_p->cur_pos < 0) ) {
errno = EINVAL;
return -1;
};
lremain = (long) (cookie_p->size) - (long) (cookie_p->cur_pos);
/* printf("writemem: remain = %ld\n" , lremain ); */
if (lremain < nbytes ) {
printf("writemem: ENOSPC\n");
errno = ENOSPC;
return -1;
}
remain = cookie_p->size - cookie_p->cur_pos;
if ( nbytes) {
if ( (cookie_p->cur_pos - cookie_p->cur_size) > 0) {
bzero (cookie_p->buf + cookie_p->cur_size,
cookie_p->cur_pos - cookie_p->cur_size);
}
memcpy(cookie_p->buf + cookie_p->cur_pos, src, nbytes);
cookie_p->cur_pos += nbytes;
if (cookie_p->cur_pos > cookie_p->cur_size)
cookie_p->cur_size = cookie_p->cur_pos;
}
/* printf("writemem: cur_size = %zd\nsize = %zd\n" , cookie_p->cur_size, cookie_p->size ); */
return nbytes;
}
int readmem (void * cookie, char * dst, int nbytes)
{
size_t len, remain;
cookie_t * cookie_p;
cookie_p = ( cookie_t * ) cookie;
if (nbytes < 0) {
errno = EINVAL;
return 0;
};
assert ( cookie_p->size >= cookie_p->cur_size);
if (((long) (cookie_p->cur_size) < (long) (cookie_p->cur_pos)) ) {
/* printf("readmem: return\n"); */
return 0;
}
remain = cookie_p->cur_size - cookie_p->cur_pos ;
len = ( nbytes > remain ? remain : nbytes);
if ( len) memcpy(dst, cookie_p->buf + cookie_p->cur_pos, len);
cookie_p->cur_pos += len;
return len;
}
fpos_t seekmem (void * cookie, fpos_t off, int whence)
{
fpos_t retval;
cookie_t * cookie_p;
/* printf("seekmem: %d\n", (int) off); */
cookie_p = ( cookie_t * ) cookie;
switch(whence) {
case SEEK_CUR: retval = cookie_p->cur_pos + off;
break;
case SEEK_SET: retval = off;
break;
case SEEK_END: retval = cookie_p->cur_size + off;
break;
}
/*if (retval < 0)
retval = 0;
if (retval > cookie_p->size)
retval = cookie_p->size;
if (retval > cookie_p->cur_size) {
bzero (cookie_p->buf + cookie_p->cur_size,
retval - cookie_p->cur_size);
cookie_p->cur_size = retval;
}
*/
cookie_p->cur_pos = retval;
return retval;
}
FILE * fmemopen (void *BUF, size_t SIZE, const char *OPENTYPE)
{
cookie_t * cookie_p;
int (*rfunc)(void *, char *, int) ;
int (*wfunc)(void *, const char *, int) ;
int flags;
flags = 0;
switch (OPENTYPE[0]) {
case 'r' : flags |= READ;
break;
case 'w' : flags |= (WRITE | TRUNCATE);
break;
case 'a' : flags |= (WRITE | APPEND);
break;
}
if ((strlen(OPENTYPE) == 2) && (OPENTYPE[1] == '+') ) {
flags |= (READ | WRITE);
}
if((cookie_p = malloc(sizeof (cookie_t))) == NULL ) return NULL;
cookie_p->buf = BUF;
cookie_p->size = SIZE;
if (flags & TRUNCATE ) {
cookie_p->cur_size = 0;
} else {
cookie_p->cur_size = SIZE;
}
cookie_p->flags = flags;
cookie_p->cur_pos = 0;
rfunc = (flags & READ) ? readmem : ( int (*)(void *, char *, int)) NULL;
if (flags & WRITE) {
wfunc = (flags & APPEND) ? appendmem : writemem ;
}
else wfunc = (int (*)(void *, const char *, int)) NULL;
return funopen(cookie_p, rfunc, wfunc, seekmem, closemem );
}
--mP3DRpeJDSE+ciuQ
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="fmemopen.h"
FILE * fmemopen (void *, size_t, const char *);
--mP3DRpeJDSE+ciuQ--