Imported ngfs libgio. This is a library to create virtual file descriptors, similar to common lisp grey-streams or golang's io.Reader/io.Writer. Now 95% bug-free.

This commit is contained in:
Matthew Veety 2016-02-09 16:24:41 -05:00
parent 9c3de0c87a
commit a54782d69b
8 changed files with 409 additions and 0 deletions

24
sys/include/gio.h Normal file
View file

@ -0,0 +1,24 @@
#pragma lib "libgio.a"
#pragma src "/sys/src/libgio"
typedef struct ReadWriter ReadWriter;
struct ReadWriter {
RWLock;
int (*open)(ReadWriter*);
int (*close)(ReadWriter*);
long (*pread)(ReadWriter*, void*, long, vlong);
long (*pwrite)(ReadWriter*, void*, long, vlong);
void *aux;
u64int offset;
u64int length;
};
ReadWriter* getrdstruct(int);
int gopen(ReadWriter*, void*);
int gclose(int);
long gread(int, void*, long, vlong);
long gwrite(int, void*, long, vlong);
vlong gseek(int, vlong, int);
int fd2gio(int);

94
sys/man/2/gio Normal file
View file

@ -0,0 +1,94 @@
.TH GIO 2
.SH NAME
gopen, gclose, gseek, gread, gwrite, fd2gio \- Programmable streams
.SH SYNOPSIS
.B #include <u.h>
.br
.B #include <libc.h>
.br
.B #include <gio.h>
.PP
.ft L
.nf
typedef struct ReadWriter {
RWLock;
int (*open)(ReadWriter*);
int (*close)(ReadWriter*);
long (*pread)(ReadWriter*, void*, long, vlong);
long (*pwrite)(ReadWriter*, void*, long, vlong);
void *aux;
u64int offset;
u64int length;
} ReadWriter;
.fi
.PP
.B
int gopen(ReadWriter *r, void *aux)
.PP
.B
int gclose(int gfd)
.PP
.B
vlong gseek(int gfd, vlong offset, int whence)
.PP
.B
long gread(int gfd, void *buf, long nbytes, vlong offset)
.PP
.B
long gwrite(int gfd, void *buf, long nbytes, vlong offset)
.PP
.B
int fd2gio(int fd)
.SH DESCRIPTION
.I gopen
takes a ReadWriter struct and creates a new instance of a gio fd.
.I aux
is an auxillary argument that may or may not be optional depending on how the gio stream is implemented.
.I gclose
closes a gio fd and frees any resources allocated to it.
.I gseek
changes the fd in a similar way to
.IR seek (2).
.I gread
and
.I gwrite
are the gio equivalents to
.IR pread (2)
and
.IR pwrite (2).
They are functionally equivalent and have nearly the same usage.
.I fd2gio
takes a Plan 9 file descriptor and returns a gio descriptor made from that fd.
.SH SOURCE
.B /sys/src/libgio
.SH NOTES
The gio functions automatically lock the ReadWriter struct in use hopefully making things work better with
.IR thread (2).
.SH BUGS
Things get interesting with
.IR rfork (2)
when you disable shared memory.
.br
The file descriptor table is poorly implemented.
.br
You cannot easily mix gio file descriptors with functions that want Plan 9 ones.
.br
.SH SEE ALSO
.IR read (2),
.IR seek (2),
.IR open (2)
.SH DIAGNOSTICS
By default, no. Users can have their methods set
.I errstr,
and
.I gopen,
.I gclose,
.I gread,
and
.I gwrite
will return -2 if a function pointer is nil.
.SH HISTORY
First appeared as part of
.IR ngfs (8)
in September 2015; imported into 9front February 2016.

59
sys/src/libgio/fd.c Normal file
View file

@ -0,0 +1,59 @@
#include <u.h>
#include <libc.h>
#include <gio.h>
int fdopen(ReadWriter*);
int fdclose(ReadWriter*);
long fdread(ReadWriter*, void*, long, vlong);
long fdwrite(ReadWriter*, void*, long, vlong);
ReadWriter fdrdwr = {
.open = fdopen,
.close = fdclose,
.pread = fdread,
.pwrite = fdwrite,
};
int
fdopen(ReadWriter *rd)
{
int *afd = (int*)rd->aux;
rd->offset = 0;
rd->length = (u64int) seek(*afd, 0, 2);
seek(*afd, 0, 0);
return 0;
}
int
fdclose(ReadWriter *rd)
{
void *x = rd->aux;
free(x);
return 0;
}
long
fdread(ReadWriter *rd, void *bf, long len, vlong offset)
{
int *afd = (int*)rd->aux;
return pread(*afd, bf, len, offset);
}
long
fdwrite(ReadWriter *rd, void *bf, long len, vlong offset)
{
int *afd = (int*)rd->aux;
return pwrite(*afd, bf, len, offset);
}
int
fd2gio(int fd)
{
void *x = malloc(sizeof(int));
memcpy(x, &fd, sizeof(int));
return gopen(&fdrdwr, x);
}

19
sys/src/libgio/mkfile Normal file
View file

@ -0,0 +1,19 @@
</$objtype/mkfile
LIB=/$objtype/lib/libgio.a
OFILES=\
fd.$O \
openclose.$O \
readp.$O \
writep.$O \
HFILES=\
/sys/include/gio.h\
UPDATE=\
mkfile\
$HFILES\
${OFILES:%.$O=%.c}\
${LIB:/$objtype/%=/386/%}\
</sys/src/cmd/mksyslib

View file

@ -0,0 +1,82 @@
#include <u.h>
#include <libc.h>
#include <gio.h>
RWLock giolock;
ReadWriter *gio_filedes[256];
uchar gio_filedes_st[256];
int
getnext(void)
{
int i;
for(i = 0; i < 256; i++)
if(gio_filedes_st[i] == 0)
break;
if(i == 256)
return -1;
return i;
}
ReadWriter*
getrdstruct(int fd)
{
rlock(&giolock);
ReadWriter *rval;
if(gio_filedes_st[fd] != 1)
rval = nil;
rval = gio_filedes[fd];
runlock(&giolock);
return rval;
}
int
gopen(ReadWriter* rd, void *aux)
{
int pfd;
ReadWriter *buf;
wlock(&giolock);
if(pfd == -1){
wunlock(&giolock);
return -1;
}
buf = malloc(sizeof(ReadWriter));
if(buf == nil)
exits("bad malloc");
memcpy(buf, rd, sizeof(ReadWriter));
buf->aux = aux;
buf->offset = 0;
if(buf->open != nil){
if((buf->open(buf)) != 0){
buf->close(buf);
free(buf);
wunlock(&giolock);
return -1;
}
}
gio_filedes[pfd] = buf;
gio_filedes_st[pfd] = 1;
wunlock(&giolock);
return pfd;
}
int
gclose(int fd)
{
ReadWriter *bf;
int rval = 0;
if(gio_filedes_st[fd] == 0)
return -1;
wlock(&giolock);
bf = gio_filedes[fd];
if(bf->close != nil)
rval = bf->close(bf);
free(bf);
gio_filedes_st[fd] = 0;
gio_filedes[fd] = nil;
wunlock(&giolock);
return rval;
}

45
sys/src/libgio/readp.c Normal file
View file

@ -0,0 +1,45 @@
#include <u.h>
#include <libc.h>
#include <gio.h>
long
gread(int fd, void *bf, long len, vlong offset)
{
ReadWriter *rd;
long rval = 0;
rd = getrdstruct(fd);
if(rd == nil)
return -1;
if(rd->pread == nil)
return -2;
rlock(rd);
rval = rd->pread(rd, bf, offset, len);
runlock(rd);
return rval;
}
vlong
gseek(int fd, vlong offset, int type)
{
ReadWriter *rd;
rd = getrdstruct(fd);
if(rd == nil)
return -1;
wlock(rd);
switch(type){
case 0:
rd->offset = (u64int)offset;
break;
case 1:
rd->offset = rd->offset + (u64int)offset;
break;
case 2:
rd->offset = rd->length + (u64int)offset;
break;
}
wunlock(rd);
return rd->offset;
}

65
sys/src/libgio/test.c Normal file
View file

@ -0,0 +1,65 @@
#include <u.h>
#include <libc.h>
#include <gio.h>
int topen(ReadWriter*);
int tclose(ReadWriter*);
long tread(ReadWriter*, void*, long, vlong);
long twrite(ReadWriter*, void*, long, vlong);
ReadWriter tester = {
.open = topen,
.close = tclose,
.pread = tread,
.pwrite = twrite,
};
void
main(int argc, char *argv[])
{
int gfd = gopen(&tester, nil);
if(gfd < 0){
print("gio_test: failed to open gio fd\n");
exits("failure");
}
char *test1 = "Hello World!\n";
char test2[256];
gread(gfd, &test2, 256, 23);
gwrite(gfd, test1, sizeof(test1), 8);
print("gio_test: %s\n", test2);
gclose(gfd);
print("gio_test: passed\n");
exits(nil);
}
int
topen(ReadWriter *rd)
{
print("gio_test: topen: file opened!\n");
return 0;
}
int
tclose(ReadWriter *rd)
{
print("gio_test: tclose: file closed!\n");
return 0;
}
long
tread(ReadWriter *rd, void *bf, long len, vlong offset)
{
char *test = "this is a read string!";
memcpy(bf, test, strlen(test)+1);
print("gio_test: tread: len = %ud, offset = %ud\n", len, offset);
return len;
}
long
twrite(ReadWriter *rd, void *bf, long len, vlong offset)
{
print("gio_test: twrite: written string: %s\n", bf);
print("gio_test: twrite: len = %ud, offset = %ud\n", len, offset);
return len;
}

21
sys/src/libgio/writep.c Normal file
View file

@ -0,0 +1,21 @@
#include <u.h>
#include <libc.h>
#include <gio.h>
long
gwrite(int fd, void *buf, long len, vlong offset)
{
ReadWriter *rd;
long rval;
rd = getrdstruct(fd);
if(rd == nil)
return -1;
if(rd->pwrite == nil)
return -2;
wlock(rd);
rval = rd->pwrite(rd, buf, len, offset);
wunlock(rd);
return rval;
}