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:
parent
9c3de0c87a
commit
a54782d69b
8 changed files with 409 additions and 0 deletions
24
sys/include/gio.h
Normal file
24
sys/include/gio.h
Normal 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
94
sys/man/2/gio
Normal 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
59
sys/src/libgio/fd.c
Normal 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
19
sys/src/libgio/mkfile
Normal 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
|
82
sys/src/libgio/openclose.c
Normal file
82
sys/src/libgio/openclose.c
Normal 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
45
sys/src/libgio/readp.c
Normal 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
65
sys/src/libgio/test.c
Normal 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
21
sys/src/libgio/writep.c
Normal 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;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue