summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelix von Leitner <felix-libowfat@fefe.de>2003-09-02 00:14:04 +0000
committerFelix von Leitner <felix-libowfat@fefe.de>2003-09-02 00:14:04 +0000
commitbb3243fbe239521f5f2661954aba246aaed50b3f (patch)
tree20faf67d381eda4b14f0f1e71779ae900205fcff
parent58bf3e91a36e7097c99a97cd2a65cfadd9574bfd (diff)
downloadlibowfat-bb3243fbe239521f5f2661954aba246aaed50b3f.tar.gz
libowfat-bb3243fbe239521f5f2661954aba246aaed50b3f.zip
beginnings of the io library
-rw-r--r--GNUmakefile14
-rw-r--r--array.h3
-rw-r--r--array/array.392
-rw-r--r--io.h4
-rw-r--r--io/io_close.c8
-rw-r--r--io/io_closeonexec.c8
-rw-r--r--io/io_createfile.c15
-rw-r--r--io/io_dontwantread.c11
-rw-r--r--io/io_dontwantwrite.c11
-rw-r--r--io/io_fd.c16
-rw-r--r--io/io_nonblock.c11
-rw-r--r--io/io_pipe.c18
-rw-r--r--io/io_readfile.c15
-rw-r--r--io/io_tryread.c41
-rw-r--r--io/io_trywrite.c39
-rw-r--r--io/io_wait.c34
-rw-r--r--io/io_wantread.c11
-rw-r--r--io/io_wantwrite.c11
-rw-r--r--io_internal.h15
-rw-r--r--test/array.c5
20 files changed, 376 insertions, 6 deletions
diff --git a/GNUmakefile b/GNUmakefile
index 7bcf902..6225b6d 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -10,7 +10,7 @@ INCLUDEDIR=${prefix}/include
MAN3DIR=${prefix}/man/man3
LIBS=byte.a fmt.a scan.a str.a uint.a open.a stralloc.a unix.a socket.a \
-buffer.a mmap.a taia.a tai.a dns.a case.a mult.a
+buffer.a mmap.a taia.a tai.a dns.a case.a mult.a array.a io.a
all: t $(LIBS) libowfat.a
@@ -18,11 +18,11 @@ all: t $(LIBS) libowfat.a
# diet libc (http://www.fefe.de/dietlibc/).
DIET=/opt/diet/bin/diet -Os
CC=gcc
-CFLAGS=-I. -pipe -Wall -O2 -fomit-frame-pointer
+CFLAGS=-pipe -Wall -O2 -fomit-frame-pointer
#CFLAGS=-pipe -Os -march=pentiumpro -mcpu=pentiumpro -fomit-frame-pointer -fschedule-insns2 -Wall
# startrip
-VPATH=str:byte:fmt:scan:uint:open:stralloc:unix:socket:buffer:mmap:textcode:taia:tai:dns:case:array:mult
+VPATH=str:byte:fmt:scan:uint:open:stralloc:unix:socket:buffer:mmap:textcode:taia:tai:dns:case:array:mult:io
BYTE_OBJS=$(patsubst byte/%.c,%.o,$(wildcard byte/*.c))
FMT_OBJS=$(patsubst fmt/%.c,%.o,$(wildcard fmt/*.c))
@@ -42,6 +42,7 @@ DNS_OBJS=$(patsubst dns/%.c,%.o,$(wildcard dns/*.c))
CASE_OBJS=$(patsubst case/%.c,%.o,$(wildcard case/*.c))
ARRAY_OBJS=$(patsubst array/%.c,%.o,$(wildcard array/*.c))
MULT_OBJS=$(patsubst mult/%.c,%.o,$(wildcard mult/*.c))
+IO_OBJS=$(patsubst io/%.c,%.o,$(wildcard io/*.c))
$(BYTE_OBJS): byte.h
$(FMT_OBJS): fmt.h
@@ -59,6 +60,7 @@ $(DNS_OBJS): dns.h stralloc.h taia.h tai.h uint64.h iopause.h
$(CASE_OBJS): case.h
$(ARRAY_OBJS): uint64.h array.h
$(MULT_OBJS): uint64.h uint32.h uint16.h safemult.h
+$(IO_OBJS): uint64.h array.h io.h
iopause.o: select.h
openreadclose.o readclose.o: readclose.h
@@ -83,14 +85,16 @@ dns.a: $(DNS_OBJS)
case.a: $(CASE_OBJS)
array.a: $(ARRAY_OBJS)
mult.a: $(MULT_OBJS)
+io.a: $(IO_OBJS)
libowfat.a: $(DNS_OBJS) $(BYTE_OBJS) $(FMT_OBJS) $(SCAN_OBJS) \
$(STR_OBJS) $(UINT_OBJS) $(OPEN_OBJS) $(STRA_OBJS) $(UNIX_OBJS) \
$(SOCKET_OBJS) $(BUFFER_OBJS) $(MMAP_OBJS) $(TEXTCODE_OBJS) \
-$(TAIA_OBJS) $(TAI_OBJS) $(CASE_OBJS) $(ARRAY_OBJS) $(MULT_OBJS)
+$(TAIA_OBJS) $(TAI_OBJS) $(CASE_OBJS) $(ARRAY_OBJS) $(MULT_OBJS) \
+$(IO_OBJS)
%.o: %.c
- $(DIET) $(CC) -c $< -o $@ $(CFLAGS)
+ $(DIET) $(CC) -c $< -o $@ -I. $(CFLAGS)
%.a:
ar cr $@ $^
diff --git a/array.h b/array.h
index 0889f23..0afbdc9 100644
--- a/array.h
+++ b/array.h
@@ -31,4 +31,7 @@ void array_cats0(array* to,const char* from);
void array_cat0(array* to);
void array_cate(array* to,const array* const from,int64 pos,int64 stop);
+#define array_failed(x) (array_bytes(x)==-1)
+#define array_allocated(x) (array_bytes(x)==0)
+
#endif
diff --git a/array/array.3 b/array/array.3
new file mode 100644
index 0000000..762b925
--- /dev/null
+++ b/array/array.3
@@ -0,0 +1,92 @@
+.TH array 3
+.SH NAME
+array \- The array library interface
+.SH SYNTAX
+.B #include <array.h>
+
+.SH DESCRIPTION
+An \fBallocated\fR array variable keeps track of
+
+.sp 1
+.IP \(bu
+a (nonzero) pointer to a dynamically allocated region of memory;
+.IP \(bu
+the number of bytes allocated (always positive); and
+.IP \(bu
+the number of bytes initialized (between 0 and the number of bytes
+allocated).
+.PP
+
+There are two other possibilities for the state of an array variable:
+\fBunallocated\fR and \fIfailed\fR. In both cases, there is no
+dynamically allocated region of memory.
+
+A new array variable is normally created as a static variable:
+
+ #include "array.h"
+
+ static array x;
+
+At this point it is unallocated. The array library provides various
+allocation and inspection functions.
+
+A new array variable can also be created dynamically. It must be
+initialized to all-0, meaning unallocated, before it is given to any of
+the array functions. It must be returned to the unallocated (or failed)
+state, for example with array_reset, before it is destroyed. These rules
+prevent all memory leaks.
+.SH "Expansion and inspection"
+
+ array x;
+
+ t* p1 = array_allocate(&x,sizeof(t),pos);
+
+ t* p2 = array_get(&x,sizeof(t),pos);
+
+ t* p3 = array_start(&x);
+
+ int64 len = array_length(&x,sizeof(t));
+
+ int64 bytes = array_bytes(&x);
+
+.SH "Truncation and deallocation"
+
+ array x;
+
+ array_truncate(&x,sizeof(t),len);
+
+ array_trunc(&x);
+
+ array_reset(&x);
+
+ array_fail(&x);
+
+.SH "Comparison"
+
+ array x;
+ array y;
+
+ if (array_equal(&x,&y))
+ /* arrays are equal... */
+
+.SH "Concatenation"
+
+ array x;
+ array y;
+
+ array_cat(&x,&y);
+
+ array_catb(&x,"fnord",5);
+
+ array_cats(&x,"fnord");
+
+ array_cats0(&x,"fnord"); /* also append the \\0 */
+
+ array_cat0(&x); /* append \\0 */
+
+ array_cate(&x,"fnord",1,4); /* append "nor" */
+
+.SH "ORIGINAL API DEFINITION"
+http://cr.yp.to/lib/array.html
+.SH "SEE ALSO"
+array_get(3), array_start(3), array_fail(3)
diff --git a/io.h b/io.h
index 71ae38b..327fe8a 100644
--- a/io.h
+++ b/io.h
@@ -4,7 +4,7 @@
/* http://cr.yp.to/lib/io.html */
#include "uint64.h"
-#include "tai.h"
+#include "taia.h"
/* like open(s,O_RDONLY) */
int io_readfile(int64* d,const char* s);
@@ -58,4 +58,6 @@ void io_nonblock(int64 d);
/* put descriptor in close-on-exec mode */
void io_closeonexec(int64 d);
+void io_close(int64 d);
+
#endif
diff --git a/io/io_close.c b/io/io_close.c
new file mode 100644
index 0000000..b00a211
--- /dev/null
+++ b/io/io_close.c
@@ -0,0 +1,8 @@
+#include <unistd.h>
+#include "io_internal.h"
+
+void io_close(int64 d) {
+ close(d);
+ io_entry* e=array_get(&io_fds,sizeof(io_entry),d);
+ if (e) e->inuse=0;
+}
diff --git a/io/io_closeonexec.c b/io/io_closeonexec.c
new file mode 100644
index 0000000..a305993
--- /dev/null
+++ b/io/io_closeonexec.c
@@ -0,0 +1,8 @@
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include "io_internal.h"
+
+void io_closeonexec(int64 d) {
+ fcntl(d,F_SETFL,fcntl(d,F_GETFL,0) | FD_CLOEXEC);
+}
diff --git a/io/io_createfile.c b/io/io_createfile.c
new file mode 100644
index 0000000..4344849
--- /dev/null
+++ b/io/io_createfile.c
@@ -0,0 +1,15 @@
+#include <unistd.h>
+#include <fcntl.h>
+#include "io_internal.h"
+
+int io_createfile(int64* d,const char* s) {
+ long fd=open(s,O_WRONLY|O_CREAT|O_TRUNC,0600);
+ if (fd != -1) {
+ if (io_fd(fd)) {
+ *d=fd;
+ return 1;
+ }
+ close(fd);
+ }
+ return 0;
+}
diff --git a/io/io_dontwantread.c b/io/io_dontwantread.c
new file mode 100644
index 0000000..db8d91c
--- /dev/null
+++ b/io/io_dontwantread.c
@@ -0,0 +1,11 @@
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include "io_internal.h"
+
+void io_dontwantread(int64 d) {
+ io_entry* e=array_get(&io_fds,sizeof(io_entry),d);
+ if (!e) return;
+ if (e->wantread && !e->wantwrite) --io_wanted_fds;
+ e->wantread=0;
+}
diff --git a/io/io_dontwantwrite.c b/io/io_dontwantwrite.c
new file mode 100644
index 0000000..a0e4716
--- /dev/null
+++ b/io/io_dontwantwrite.c
@@ -0,0 +1,11 @@
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include "io_internal.h"
+
+void io_dontwantwrite(int64 d) {
+ io_entry* e=array_get(&io_fds,sizeof(io_entry),d);
+ if (!e) return;
+ if (!e->wantread && e->wantwrite) --io_wanted_fds;
+ e->wantwrite=0;
+}
diff --git a/io/io_fd.c b/io/io_fd.c
new file mode 100644
index 0000000..cfc4e11
--- /dev/null
+++ b/io/io_fd.c
@@ -0,0 +1,16 @@
+#include <sys/types.h>
+#include <fcntl.h>
+
+#include "io_internal.h"
+
+/* put d on internal data structure, return 1 on success, 0 on error */
+int io_fd(int64 d) {
+ long r;
+ io_entry* e;
+ if ((r=fcntl(d,F_GETFL,0) & O_NDELAY) == -1)
+ return 0; /* file descriptor not open */
+ if (!(e=array_allocate(&io_fds,sizeof(io_entry),d))) return 0;
+ e->inuse=1;
+ if (r&O_NDELAY) e->nonblock=1;
+ return 1;
+}
diff --git a/io/io_nonblock.c b/io/io_nonblock.c
new file mode 100644
index 0000000..ac26c24
--- /dev/null
+++ b/io/io_nonblock.c
@@ -0,0 +1,11 @@
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include "io_internal.h"
+
+void io_nonblock(int64 d) {
+ io_entry* e=array_get(&io_fds,sizeof(io_entry),d);
+ if (e && e->nonblock) return;
+ fcntl(d,F_SETFL,fcntl(d,F_GETFL,0) | O_NDELAY);
+ if (e) e->nonblock=1;
+}
diff --git a/io/io_pipe.c b/io/io_pipe.c
new file mode 100644
index 0000000..6f40413
--- /dev/null
+++ b/io/io_pipe.c
@@ -0,0 +1,18 @@
+#include <unistd.h>
+#include "io_internal.h"
+
+int io_pipe(int64* d) {
+ int fds[2];
+ if (pipe(fds)==-1)
+ return 0;
+ if (io_fd(fds[1])) {
+ if (io_fd(fds[0])) {
+ d[0]=fds[0];
+ d[1]=fds[1];
+ return 1;
+ }
+ io_close(fds[1]);
+ }
+ close(fds[0]);
+ return 0;
+}
diff --git a/io/io_readfile.c b/io/io_readfile.c
new file mode 100644
index 0000000..99261f5
--- /dev/null
+++ b/io/io_readfile.c
@@ -0,0 +1,15 @@
+#include <unistd.h>
+#include <fcntl.h>
+#include "io_internal.h"
+
+int io_readfile(int64* d,const char* s) {
+ long fd=open(s,O_RDONLY);
+ if (fd != -1) {
+ if (io_fd(fd)) {
+ *d=fd;
+ return 1;
+ }
+ close(fd);
+ }
+ return 0;
+}
diff --git a/io/io_tryread.c b/io/io_tryread.c
new file mode 100644
index 0000000..4cd922b
--- /dev/null
+++ b/io/io_tryread.c
@@ -0,0 +1,41 @@
+#include <unistd.h>
+#include <sys/time.h>
+#include <poll.h>
+#include <errno.h>
+#include "io_internal.h"
+
+int64 io_tryread(int64 d,char* buf,int64 len) {
+ long r;
+ struct itimerval old,new;
+ struct pollfd p;
+ io_entry* e=array_get(&io_fds,sizeof(io_entry),d);
+ if (!e) { errno=EBADF; return -3; }
+ if (!e->nonblock) {
+ p.fd=d;
+ if (p.fd != d) { errno=EBADF; return -3; } /* catch overflow */
+ p.events=POLLIN;
+ switch (poll(&p,1,0)) {
+ case -1: return -3;
+ case 0: errno=EAGAIN; return -1;
+ }
+ new.it_interval.tv_usec=0;
+ new.it_interval.tv_sec=0;
+ new.it_value.tv_usec=10000;
+ new.it_value.tv_sec=0;
+ setitimer(ITIMER_REAL,&new,&old);
+ }
+ r=read(d,buf,len);
+ if (!e->nonblock) {
+ new.it_interval.tv_usec=0;
+ new.it_interval.tv_sec=0;
+ new.it_value.tv_usec=0;
+ new.it_value.tv_sec=0;
+ setitimer(ITIMER_REAL,&new,&old);
+ }
+ if (r==-1) {
+ if (errno==EINTR) errno=EAGAIN;
+ if (errno!=EAGAIN)
+ r=-3;
+ }
+ return r;
+}
diff --git a/io/io_trywrite.c b/io/io_trywrite.c
new file mode 100644
index 0000000..21bd2d9
--- /dev/null
+++ b/io/io_trywrite.c
@@ -0,0 +1,39 @@
+#include <unistd.h>
+#include <sys/time.h>
+#include <poll.h>
+#include <errno.h>
+#include "io_internal.h"
+
+int64 io_trywrite(int64 d,const char* buf,int64 len) {
+ long r;
+ struct itimerval old,new;
+ struct pollfd p;
+ io_entry* e=array_get(&io_fds,sizeof(io_entry),d);
+ if (!e) { errno=EBADF; return -3; }
+ if (!e->nonblock) {
+ p.fd=d;
+ if (p.fd != d) { errno=EBADF; return -3; } /* catch overflow */
+ p.events=POLLOUT;
+ switch (poll(&p,1,0)) {
+ case -1: return -3;
+ case 0: errno=EAGAIN; return -1;
+ }
+ new.it_interval.tv_usec=0;
+ new.it_interval.tv_sec=0;
+ new.it_value.tv_usec=10000;
+ new.it_value.tv_sec=0;
+ setitimer(ITIMER_REAL,&new,&old);
+ }
+ r=write(d,buf,len);
+ if (!e->nonblock) {
+ new.it_interval.tv_usec=0;
+ new.it_interval.tv_sec=0;
+ new.it_value.tv_usec=0;
+ new.it_value.tv_sec=0;
+ setitimer(ITIMER_REAL,&new,&old);
+ }
+ if (r==-1)
+ if (errno!=EAGAIN)
+ r=-3;
+ return r;
+}
diff --git a/io/io_wait.c b/io/io_wait.c
new file mode 100644
index 0000000..7ea4d8c
--- /dev/null
+++ b/io/io_wait.c
@@ -0,0 +1,34 @@
+#include <unistd.h>
+#include <sys/time.h>
+#include <poll.h>
+#include <errno.h>
+#include "io_internal.h"
+
+void io_wait() {
+ struct pollfd* p;
+ long i,r;
+ if (!io_wanted_fds) return;
+ for (i=r=0; i<array_length(&io_fds,sizeof(io_entry)); ++i) {
+ io_entry* e=array_get(&io_fds,sizeof(io_entry),i);
+ if (!e) return;
+ e->canread=e->canwrite=0;
+ if (e->wantread || e->wantwrite) {
+ struct pollfd* p;
+ if ((p=array_allocate(&io_pollfds,sizeof(struct pollfd),r))) {
+ p->fd=i;
+ p->events=(e->wantread?POLLIN:0) + (e->wantwrite?POLLOUT:0);
+ ++r;
+ } else
+ return;
+ }
+ }
+ p=array_start(&io_pollfds);
+ while ((i=poll(array_start(&io_pollfds),r,99999999))==0);
+ if (i==-1) return;
+ for (i=0; i<r; ++i) {
+ io_entry* e=array_get(&io_fds,sizeof(io_entry),p->fd);
+ if (p->revents&POLLIN) e->canread=1;
+ if (p->revents&POLLOUT) e->canwrite=1;
+ p++;
+ }
+}
diff --git a/io/io_wantread.c b/io/io_wantread.c
new file mode 100644
index 0000000..c136514
--- /dev/null
+++ b/io/io_wantread.c
@@ -0,0 +1,11 @@
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include "io_internal.h"
+
+void io_wantread(int64 d) {
+ io_entry* e=array_get(&io_fds,sizeof(io_entry),d);
+ if (!e) return;
+ if (!e->wantread && !e->wantwrite) ++io_wanted_fds;
+ e->wantread=1;
+}
diff --git a/io/io_wantwrite.c b/io/io_wantwrite.c
new file mode 100644
index 0000000..127b4c5
--- /dev/null
+++ b/io/io_wantwrite.c
@@ -0,0 +1,11 @@
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include "io_internal.h"
+
+void io_wantwrite(int64 d) {
+ io_entry* e=array_get(&io_fds,sizeof(io_entry),d);
+ if (!e) return;
+ if (!e->wantread && !e->wantwrite) ++io_wanted_fds;
+ e->wantwrite=1;
+}
diff --git a/io_internal.h b/io_internal.h
new file mode 100644
index 0000000..768e97e
--- /dev/null
+++ b/io_internal.h
@@ -0,0 +1,15 @@
+#include "io.h"
+#include "array.h"
+
+typedef struct {
+ unsigned int wantread:1;
+ unsigned int wantwrite:1;
+ unsigned int canread:1;
+ unsigned int canwrite:1;
+ unsigned int nonblock:1;
+ unsigned int inuse:1;
+} io_entry;
+
+array io_fds;
+uint64 io_wanted_fds;
+array io_pollfds;
diff --git a/test/array.c b/test/array.c
index e198bbd..c3217c3 100644
--- a/test/array.c
+++ b/test/array.c
@@ -9,5 +9,10 @@ main() {
array_cat(&x,&y);
array_fail(&y);
array_cat(&y,&x);
+ assert(array_failed(&y));
+ array_reset(&y);
+ array_cats(&y,"fnord");
assert(byte_equal(x.p,11,"fnordfoobar"));
+ array_cate(&x,&y,1,4);
+ assert(x.initialized=14 && byte_equal(x.p,14,"fnordfoobarnor"));
}