diff --git a/Makefile b/Makefile index 5652376..2904787 100644 --- a/Makefile +++ b/Makefile @@ -43,6 +43,7 @@ buffer_0small.o: buffer/buffer_0small.c buffer.h buffer_1.o: buffer/buffer_1.c buffer.h buffer_1small.o: buffer/buffer_1small.c buffer.h buffer_2.o: buffer/buffer_2.c buffer.h +buffer_close.o: buffer/buffer_close.c buffer.h buffer_feed.o: buffer/buffer_feed.c buffer.h buffer_flush.o: buffer/buffer_flush.c buffer.h buffer_fromsa.o: buffer/buffer_fromsa.c stralloc.h buffer.h @@ -66,6 +67,8 @@ buffer_getn.o: buffer/buffer_getn.c byte.h buffer.h buffer_getnewline_sa.o: buffer/buffer_getnewline_sa.c stralloc.h \ buffer.h buffer_init.o: buffer/buffer_init.c buffer.h +buffer_init_free.o: buffer/buffer_init_free.c buffer.h +buffer_mmapread.o: buffer/buffer_mmapread.c buffer.h mmap.h buffer_peek.o: buffer/buffer_peek.c buffer.h buffer_put.o: buffer/buffer_put.c byte.h buffer.h buffer_put8long.o: buffer/buffer_put8long.c buffer.h fmt.h @@ -560,7 +563,7 @@ OPEN_OBJS=open_append.o open_excl.o open_read.o open_rw.o open_trunc.o open_writ STRALLOC_OBJS=stralloc_append.o stralloc_cat.o stralloc_catb.o stralloc_catlong0.o stralloc_catm_internal.o stralloc_cats.o stralloc_catulong0.o stralloc_chomp.o stralloc_chop.o stralloc_copy.o stralloc_copyb.o stralloc_copys.o stralloc_diff.o stralloc_diffs.o stralloc_free.o stralloc_init.o stralloc_ready.o stralloc_readyplus.o stralloc_starts.o stralloc_zero.o UNIX_OBJS=iopause.o ndelay_off.o ndelay_on.o winsock2errno.o SOCKET_OBJS=fmt_ip4.o fmt_ip6.o fmt_ip6_flat.o fmt_ip6c.o fmt_ip6if.o fmt_ip6ifc.o init.o scan_ip4.o scan_ip6.o scan_ip6_flat.o scan_ip6if.o socket_accept4.o socket_accept6.o socket_bind4.o socket_bind4_reuse.o socket_bind6.o socket_bind6_reuse.o socket_broadcast.o socket_connect4.o socket_connect6.o socket_connected.o socket_getifidx.o socket_getifname.o socket_ip4loopback.o socket_listen.o socket_local4.o socket_local6.o socket_mchopcount6.o socket_mcjoin4.o socket_mcjoin6.o socket_mcleave4.o socket_mcleave6.o socket_mcloop4.o socket_mcloop6.o socket_mcttl4.o socket_noipv6.o socket_recv4.o socket_recv6.o socket_remote4.o socket_remote6.o socket_send4.o socket_send6.o socket_tcp4.o socket_tcp6.o socket_tryreservein.o socket_udp4.o socket_udp6.o socket_v4mappedprefix.o socket_v6any.o socket_v6loopback.o -BUFFER_OBJS=buffer_0.o buffer_0small.o buffer_1.o buffer_1small.o buffer_2.o buffer_feed.o buffer_flush.o buffer_fromsa.o buffer_get.o buffer_get_new_token_sa.o buffer_get_new_token_sa_pred.o buffer_get_token.o buffer_get_token_pred.o buffer_get_token_sa.o buffer_get_token_sa_pred.o buffer_getc.o buffer_getline.o buffer_getline_sa.o buffer_getn.o buffer_getnewline_sa.o buffer_init.o buffer_peek.o buffer_put.o buffer_put8long.o buffer_putalign.o buffer_puterror.o buffer_puterror2.o buffer_putflush.o buffer_putlong.o buffer_putlonglong.o buffer_putm_internal.o buffer_putm_internal_flush.o buffer_putnlflush.o buffer_puts.o buffer_putsa.o buffer_putsaflush.o buffer_putsalign.o buffer_putsflush.o buffer_putspace.o buffer_putulong.o buffer_putulonglong.o buffer_putxlong.o buffer_seek.o buffer_stubborn.o buffer_stubborn2.o errmsg_cvt.o errmsg_iam.o errmsg_info.o errmsg_infosys.o errmsg_warn.o errmsg_warnsys.o errmsg_writesys.o +BUFFER_OBJS=buffer_0.o buffer_0small.o buffer_1.o buffer_1small.o buffer_2.o buffer_close.o buffer_feed.o buffer_flush.o buffer_fromsa.o buffer_get.o buffer_get_new_token_sa.o buffer_get_new_token_sa_pred.o buffer_get_token.o buffer_get_token_pred.o buffer_get_token_sa.o buffer_get_token_sa_pred.o buffer_getc.o buffer_getline.o buffer_getline_sa.o buffer_getn.o buffer_getnewline_sa.o buffer_init.o buffer_init_free.o buffer_mmapread.o buffer_peek.o buffer_put.o buffer_put8long.o buffer_putalign.o buffer_puterror.o buffer_puterror2.o buffer_putflush.o buffer_putlong.o buffer_putlonglong.o buffer_putm_internal.o buffer_putm_internal_flush.o buffer_putnlflush.o buffer_puts.o buffer_putsa.o buffer_putsaflush.o buffer_putsalign.o buffer_putsflush.o buffer_putspace.o buffer_putulong.o buffer_putulonglong.o buffer_putxlong.o buffer_seek.o buffer_stubborn.o buffer_stubborn2.o errmsg_cvt.o errmsg_iam.o errmsg_info.o errmsg_infosys.o errmsg_warn.o errmsg_warnsys.o errmsg_writesys.o MMAP_OBJS=mmap_private.o mmap_read.o mmap_shared.o TAIA_OBJS=taia_add.o taia_addsec.o taia_approx.o taia_frac.o taia_less.o taia_now.o taia_pack.o taia_sub.o taia_tai.o taia_uint.o taia_unpack.o TAI_OBJS=tai_add.o tai_now.o tai_pack.o tai_sub.o tai_uint.o tai_unpack.o diff --git a/buffer.h b/buffer.h index 2e31cd0..eb99429 100644 --- a/buffer.h +++ b/buffer.h @@ -8,14 +8,19 @@ typedef struct buffer { unsigned long int a; /* allocated buffer size */ int fd; /* passed as first argument to op */ int (*op)(); /* use read(2) or write(2) */ + enum { NOTHING, FREE, MUNMAP } todo; } buffer; -#define BUFFER_INIT(op,fd,buf,len) { (buf), 0, 0, (len), (fd), (op) } +#define BUFFER_INIT(op,fd,buf,len) { (buf), 0, 0, (len), (fd), (op), NOTHING } +#define BUFFER_INIT_FREE(op,fd,buf,len) { (buf), 0, 0, (len), (fd), (op), FREE } #define BUFFER_INIT_READ(op,fd,buf,len) BUFFER_INIT(op,fd,buf,len) /*obsolete*/ #define BUFFER_INSIZE 8192 #define BUFFER_OUTSIZE 8192 void buffer_init(buffer* b,int (*op)(),int fd,unsigned char* y,unsigned long int ylen); +void buffer_init_free(buffer* b,int (*op)(),int fd,unsigned char* y,unsigned long int ylen); +int buffer_mmapread(buffer* b,const char* filename); +void buffer_close(buffer* b); int buffer_flush(buffer* b); int buffer_put(buffer* b,const unsigned char* x,unsigned long int len); diff --git a/buffer/buffer_close.3 b/buffer/buffer_close.3 new file mode 100644 index 0000000..aecae97 --- /dev/null +++ b/buffer/buffer_close.3 @@ -0,0 +1,13 @@ +.TH buffer_close 3 +.SH NAME +buffer_close \- close buffer +.SH SYNTAX +.B #include + +void \fBbuffer_close\fP(buffer* \fIb\fR); +.SH DESCRIPTION +buffer_close close the file associated with the buffer and frees/unmaps +the memory associated with the buffer if buffer_init_free or +buffer_mmapread were used. +.SH "SEE ALSO" +buffer_init(3), buffer_init_free(3), buffer_mmapread(3) diff --git a/buffer/buffer_close.c b/buffer/buffer_close.c new file mode 100644 index 0000000..6d8127a --- /dev/null +++ b/buffer/buffer_close.c @@ -0,0 +1,13 @@ +#include +#include +#include +#include + +void buffer_close(buffer* b) { + if (b->fd != -1) close(b->fd); + switch (b->todo) { + case FREE: free(b->x); break; + case MUNMAP: munmap(b->x,b->a); break; + default: ; + } +} diff --git a/buffer/buffer_init.c b/buffer/buffer_init.c index 9644154..208b54b 100644 --- a/buffer/buffer_init.c +++ b/buffer/buffer_init.c @@ -8,4 +8,5 @@ void buffer_init(buffer* b,int (*op)(),int fd, b->a=ylen; b->p=0; b->n=0; + b->todo=NOTHING; } diff --git a/buffer/buffer_init_free.3 b/buffer/buffer_init_free.3 new file mode 100644 index 0000000..e16eb83 --- /dev/null +++ b/buffer/buffer_init_free.3 @@ -0,0 +1,14 @@ +.TH buffer_init_free 3 +.SH NAME +buffer_init_free \- initialize buffer structure +.SH SYNTAX +.B #include + +int \fBbuffer_init_free\fR(buffer &\fIb\fR, + int (*\fIop\fR)(int,char*,unsigned int), + int \fIfd\fR, unsigned char* \fIy\fR, unsigned long int \fIylen\fR); +.SH DESCRIPTION +buffer_init_free is like buffer_init except that the memory (\fIy\fR is +marked to be freed by buffer_close(). +.SH "SEE ALSO" +buffer_init(3), buffer_mmap_read(3), buffer(3) diff --git a/buffer/buffer_init_free.c b/buffer/buffer_init_free.c new file mode 100644 index 0000000..4fe851e --- /dev/null +++ b/buffer/buffer_init_free.c @@ -0,0 +1,7 @@ +#include "buffer.h" + +void buffer_init_free(buffer* b,int (*op)(),int fd, + unsigned char* y,unsigned long int ylen) { + buffer_init(b,op,fd,y,ylen); + b->todo=FREE; +} diff --git a/buffer/buffer_mmapread.3 b/buffer/buffer_mmapread.3 new file mode 100644 index 0000000..f6cdbbf --- /dev/null +++ b/buffer/buffer_mmapread.3 @@ -0,0 +1,29 @@ +.TH buffer_mmapread 3 +.SH NAME +buffer_mmapread \- create read-only memory-mapped file buffer +.SH SYNTAX +.B #include + +int \fBbuffer_mmapread\fR(buffer &\fIb\fR,const char* \fIfilename\fR); +.SH DESCRIPTION +buffer_mmapread opens \fIfilename\fR for reading and fills \fIb\fR so +that the contents of the file can be read from it. Using mmap is more +efficient than reading through a real buffer, but you have to call +buffer_close to unmap the memory in the end. +.SH EXAMPLE + #include + #include + + buffer input; + char x; + + buffer_mmapread(&input,"/etc/passwd"); + while (buffer_get(&input,&x,1)==1) { + buffer_put(buffer_1,&x,1); + if (x=='\\n') break; + } + buffer_flush(buffer_1); + buffer_close(&input); + +.SH "SEE ALSO" +buffer_flush(3), buffer(3) diff --git a/buffer/buffer_mmapread.c b/buffer/buffer_mmapread.c new file mode 100644 index 0000000..858bf9b --- /dev/null +++ b/buffer/buffer_mmapread.c @@ -0,0 +1,15 @@ +#include +#include + +static int op() { + return 0; +} + +int buffer_mmapread(buffer* b,const char* filename) { + if (!(b->x=mmap_read(filename,&b->n))) return -1; + b->p=0; b->a=b->n; + b->fd=-1; + b->op=op; + b->todo=MUNMAP; + return 0; +} diff --git a/test/buffer_mmap.c b/test/buffer_mmap.c new file mode 100644 index 0000000..78fedf6 --- /dev/null +++ b/test/buffer_mmap.c @@ -0,0 +1,13 @@ +#include + +int main() { + buffer input; + char x; + buffer_mmapread(&input,"/etc/passwd"); + while (buffer_get(&input,&x,1)==1) { + buffer_put(buffer_1,&x,1); + if (x=='\n') break; + } + buffer_flush(buffer_1); + buffer_close(&input); +}