]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/cdfs/buf.c
exec(2): fix prototypes
[plan9front.git] / sys / src / cmd / cdfs / buf.c
1 /*
2  * Buffered I/O on block devices.
3  * Write buffering ignores offset.
4  */
5
6 #include <u.h>
7 #include <libc.h>
8 #include <disk.h>
9 #include "dat.h"
10 #include "fns.h"
11
12 Buf*
13 bopen(long (*fn)(Buf*, void*, long, ulong), int omode, int bs, int nblock)
14 {
15         Buf *b;
16
17         assert(omode == OREAD || OWRITE);
18         assert(bs > 0 && nblock > 0);
19         assert(fn != nil);
20
21         b = emalloc(sizeof(*b));
22         b->data = emalloc(bs*nblock);
23         b->ndata = 0;
24         b->nblock = nblock;
25         b->bs = bs;
26         b->omode = omode;
27         b->fn = fn;             /* function to read or write bs-byte blocks */
28
29         return b;
30 }
31
32 long
33 bread(Buf *b, void *v, long n, vlong off)
34 {
35         long m;
36         vlong noff;
37
38         assert(b->omode == OREAD);
39
40         /* Refill buffer */
41         if(b->off > off || off >= b->off+b->ndata) {
42                 noff = off - off % b->bs;
43                 if(vflag)
44                         fprint(2, "try refill at %lld...", noff);
45                 if((m = b->fn(b, b->data, b->nblock, noff/b->bs)) <= 0) {
46                         if (vflag)
47                                 fprint(2, "failed\n");
48                         return m;
49                 }
50                 b->ndata = b->bs * m;
51                 b->off = noff;
52                 if(vflag)
53                         fprint(2, "got %ld\n", b->ndata);
54         }
55
56 //      fprint(2, "read %ld at %ld\n", n, off);
57         /* Satisfy request from buffer */
58         off -= b->off;
59         if(n > b->ndata - off)
60                 n = b->ndata - off;
61         memmove(v, b->data+off, n);
62         return n;
63 }
64
65 long
66 bwrite(Buf *b, void *v, long n)
67 {
68         long on, m, mdata;
69         uchar *p;
70
71         p = v;
72         on = n;
73
74         /* Fill buffer */
75         mdata = b->bs*b->nblock;
76         m = mdata - b->ndata;
77         if(m > n)
78                 m = n;
79         memmove(b->data+b->ndata, p, m);
80         p += m;
81         n -= m;
82         b->ndata += m;
83
84         /* Flush buffer */
85         if(b->ndata == mdata) {
86                 if(b->fn(b, b->data, b->nblock, 0) < 0) {
87                         if(vflag)
88                                 fprint(2, "write fails: %r\n");
89                         return -1;
90                 }
91                 b->ndata = 0;
92         }
93
94         /* For now, don't worry about big writes; 9P only does 8k */
95         assert(n < mdata);
96
97         /* Add remainder to buffer */
98         if(n) {
99                 memmove(b->data, p, n);
100                 b->ndata = n;
101         }
102
103         return on;
104 }
105
106 void
107 bterm(Buf *b)
108 {
109         /* DVD & BD prefer full ecc blocks (tracks), but can cope with less */
110         if(b->omode == OWRITE && b->ndata)
111                 b->fn(b, b->data, (b->ndata + b->bs - 1)/b->bs, 0); 
112
113         free(b->data);
114         free(b);
115 }