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