]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/hjfs/dev.c
merge
[plan9front.git] / sys / src / cmd / hjfs / dev.c
1 #include <u.h>
2 #include <libc.h>
3 #include <thread.h>
4 #include "dat.h"
5 #include "fns.h"
6
7 Dev *devs;
8
9 void
10 devwork(void *v)
11 {
12         Dev *d;
13         Buf *b;
14         Channel *r;
15         uchar buf[BLOCK];
16         
17         d = v;
18         for(;;){
19                 qlock(&d->workl);
20                 while(d->work.wnext == &d->work)
21                         rsleep(&d->workr);
22                 b = d->work.wnext;
23                 b->wnext->wprev = b->wprev;
24                 b->wprev->wnext = b->wnext;
25                 b->wnext = b->wprev = nil;
26                 qunlock(&d->workl);
27                 if(b->d == nil) /* this is a sync request */
28                         goto reply;
29                 if(b->off >= d->size){
30                         b->error = Einval;
31                         goto reply;
32                 }
33                 seek(d->fd, b->off * BLOCK, 0);
34                 b->error = nil;
35                 if(b->op & BWRITE){
36                         memset(buf, 0, sizeof(buf));
37                         pack(b, buf);
38                         if(write(d->fd, buf, BLOCK) < BLOCK){
39                                 dprint("hjfs: write: %r\n");
40                                 b->error = Eio;
41                         }
42                 }else{
43                         if(readn(d->fd, buf, BLOCK) < 0){
44                                 dprint("hjfs: read: %r\n");
45                                 b->error = Eio;
46                         }else
47                                 unpack(b, buf);
48                 }
49         reply:
50                 r = b->resp;
51                 b->resp = nil;
52                 if(r != nil)
53                         send(r, &b);
54         }
55 }
56
57 Dev *
58 newdev(char *file)
59 {
60         Dev *d, **e;
61         Dir *dir;
62         Buf *b;
63         
64         d = emalloc(sizeof(*d));
65         d->fd = open(file, ORDWR);
66         if(d->fd < 0){
67                 free(d);
68                 return nil;
69         }
70         dir = dirfstat(d->fd);
71         if(dir == nil){
72         error:
73                 close(d->fd);
74                 free(d);
75                 return nil;
76         }
77         d->size = dir->length / BLOCK;
78         free(dir);
79         if(d->size == 0){
80                 werrstr("device file too short");
81                 goto error;
82         }
83         d->name = estrdup(file);
84         for(b = d->buf; b < d->buf + BUFHASH + 1; b++)
85                 b->dnext = b->dprev = b;
86         d->workr.l = &d->workl;
87         d->work.wnext = d->work.wprev = &d->work;
88         proccreate(devwork, d, mainstacksize);
89         for(e = &devs; *e != nil; e = &(*e)->next)
90                 ;
91         *e = d;
92         return d;
93 }