xref: /plan9/sys/src/cmd/acme/disk.c (revision aaee222289330fcec0b5b011953f18cc626114b4)
1 #include <u.h>
2 #include <libc.h>
3 #include <draw.h>
4 #include <thread.h>
5 #include <cursor.h>
6 #include <mouse.h>
7 #include <keyboard.h>
8 #include <frame.h>
9 #include <fcall.h>
10 #include <plumb.h>
11 #include "dat.h"
12 #include "fns.h"
13 
14 static	Block	*blist;
15 
16 int
tempfile(void)17 tempfile(void)
18 {
19 	char buf[128];
20 	int i, fd;
21 
22 	snprint(buf, sizeof buf, "/tmp/X%d.%.4sacme", getpid(), getuser());
23 	for(i='A'; i<='Z'; i++){
24 		buf[5] = i;
25 		if(access(buf, AEXIST) == 0)
26 			continue;
27 		fd = create(buf, ORDWR|ORCLOSE|OCEXEC, 0600);
28 		if(fd >= 0)
29 			return fd;
30 	}
31 	return -1;
32 }
33 
34 Disk*
diskinit()35 diskinit()
36 {
37 	Disk *d;
38 
39 	d = emalloc(sizeof(Disk));
40 	d->fd = tempfile();
41 	if(d->fd < 0){
42 		fprint(2, "acme: can't create temp file: %r\n");
43 		threadexitsall("diskinit");
44 	}
45 	return d;
46 }
47 
48 static
49 uint
ntosize(uint n,uint * ip)50 ntosize(uint n, uint *ip)
51 {
52 	uint size;
53 
54 	if(n > Maxblock)
55 		error("internal error: ntosize");
56 	size = n;
57 	if(size & (Blockincr-1))
58 		size += Blockincr - (size & (Blockincr-1));
59 	/* last bucket holds blocks of exactly Maxblock */
60 	if(ip)
61 		*ip = size/Blockincr;
62 	return size * sizeof(Rune);
63 }
64 
65 Block*
disknewblock(Disk * d,uint n)66 disknewblock(Disk *d, uint n)
67 {
68 	uint i, j, size;
69 	Block *b;
70 
71 	size = ntosize(n, &i);
72 	b = d->free[i];
73 	if(b)
74 		d->free[i] = b->next;
75 	else{
76 		/* allocate in chunks to reduce malloc overhead */
77 		if(blist == nil){
78 			blist = emalloc(100*sizeof(Block));
79 			for(j=0; j<100-1; j++)
80 				blist[j].next = &blist[j+1];
81 		}
82 		b = blist;
83 		blist = b->next;
84 		b->addr = d->addr;
85 		d->addr += size;
86 	}
87 	b->n = n;
88 	return b;
89 }
90 
91 void
diskrelease(Disk * d,Block * b)92 diskrelease(Disk *d, Block *b)
93 {
94 	uint i;
95 
96 	ntosize(b->n, &i);
97 	b->next = d->free[i];
98 	d->free[i] = b;
99 }
100 
101 void
diskwrite(Disk * d,Block ** bp,Rune * r,uint n)102 diskwrite(Disk *d, Block **bp, Rune *r, uint n)
103 {
104 	int size, nsize;
105 	Block *b;
106 
107 	b = *bp;
108 	size = ntosize(b->n, nil);
109 	nsize = ntosize(n, nil);
110 	if(size != nsize){
111 		diskrelease(d, b);
112 		b = disknewblock(d, n);
113 		*bp = b;
114 	}
115 	if(pwrite(d->fd, r, n*sizeof(Rune), b->addr) != n*sizeof(Rune))
116 		error("write error to temp file");
117 	b->n = n;
118 }
119 
120 void
diskread(Disk * d,Block * b,Rune * r,uint n)121 diskread(Disk *d, Block *b, Rune *r, uint n)
122 {
123 	int tot, nr;
124 	char *p;
125 
126 	if(n > b->n)
127 		error("internal error: diskread");
128 
129 	ntosize(b->n, nil);
130 	n *= sizeof(Rune);
131 	p = (char*)r;
132 	for(tot = 0; tot < n; tot += nr){
133 		nr = pread(d->fd, p+tot, n-tot, b->addr+tot);
134 		if(nr <= 0)
135 			break;		/* tot < n, so error */
136 	}
137 	if(tot != n)
138 		error("read error from temp file");
139 }
140