2019-11-14 23:15:48 +00:00
|
|
|
#include <u.h>
|
|
|
|
#include <libc.h>
|
|
|
|
#include <draw.h>
|
|
|
|
#include <thread.h>
|
|
|
|
#include <cursor.h>
|
|
|
|
#include <mouse.h>
|
|
|
|
#include <keyboard.h>
|
2022-02-22 05:52:56 +00:00
|
|
|
#include "libframe/frame.h"
|
2019-11-14 23:15:48 +00:00
|
|
|
#include <fcall.h>
|
|
|
|
#include <plumb.h>
|
|
|
|
#include <libsec.h>
|
|
|
|
#include "dat.h"
|
|
|
|
#include "fns.h"
|
|
|
|
|
2021-06-13 05:54:54 +00:00
|
|
|
static Block* blist;
|
2019-11-14 23:15:48 +00:00
|
|
|
|
2021-06-13 05:54:54 +00:00
|
|
|
int tempfile(void) {
|
|
|
|
char buf[128];
|
|
|
|
int i, fd;
|
2019-11-14 23:15:48 +00:00
|
|
|
|
2021-06-13 05:54:54 +00:00
|
|
|
snprint(buf, sizeof buf, "/tmp/X%d.%.4sacme", getpid(), getuser());
|
|
|
|
for (i = 'A'; i <= 'Z'; i++) {
|
|
|
|
buf[5] = i;
|
|
|
|
if (access(buf, AEXIST) == 0)
|
|
|
|
continue;
|
|
|
|
fd = create(buf, ORDWR | ORCLOSE | OCEXEC, 0600);
|
|
|
|
if (fd >= 0)
|
|
|
|
return fd;
|
|
|
|
}
|
|
|
|
return -1;
|
2019-11-14 23:15:48 +00:00
|
|
|
}
|
|
|
|
|
2021-06-13 05:54:54 +00:00
|
|
|
Disk* diskinit() {
|
|
|
|
Disk* d;
|
2019-11-14 23:15:48 +00:00
|
|
|
|
2021-06-13 05:54:54 +00:00
|
|
|
d = emalloc(sizeof(Disk));
|
|
|
|
d->fd = tempfile();
|
|
|
|
if (d->fd < 0) {
|
|
|
|
fprint(2, "acme: can't create temp file: %r\n");
|
|
|
|
threadexitsall("diskinit");
|
|
|
|
}
|
|
|
|
return d;
|
2019-11-14 23:15:48 +00:00
|
|
|
}
|
|
|
|
|
2021-06-13 05:54:54 +00:00
|
|
|
static uint ntosize(uint n, uint* ip) {
|
|
|
|
uint size;
|
2019-11-14 23:15:48 +00:00
|
|
|
|
2021-06-13 05:54:54 +00:00
|
|
|
if (n > Maxblock)
|
|
|
|
error("internal error: ntosize");
|
|
|
|
size = n;
|
|
|
|
if (size & (Blockincr - 1))
|
|
|
|
size += Blockincr - (size & (Blockincr - 1));
|
|
|
|
/* last bucket holds blocks of exactly Maxblock */
|
|
|
|
if (ip)
|
|
|
|
*ip = size / Blockincr;
|
|
|
|
return size * sizeof(Rune);
|
2019-11-14 23:15:48 +00:00
|
|
|
}
|
|
|
|
|
2021-06-13 05:54:54 +00:00
|
|
|
Block* disknewblock(Disk* d, uint n) {
|
|
|
|
uint i, j, size;
|
|
|
|
Block* b;
|
2019-11-14 23:15:48 +00:00
|
|
|
|
2021-06-13 05:54:54 +00:00
|
|
|
size = ntosize(n, &i);
|
|
|
|
b = d->free[i];
|
|
|
|
if (b)
|
|
|
|
d->free[i] = b->u.next;
|
|
|
|
else {
|
|
|
|
/* allocate in chunks to reduce malloc overhead */
|
|
|
|
if (blist == nil) {
|
|
|
|
blist = emalloc(100 * sizeof(Block));
|
|
|
|
for (j = 0; j < 100 - 1; j++)
|
|
|
|
blist[j].u.next = &blist[j + 1];
|
|
|
|
}
|
|
|
|
b = blist;
|
|
|
|
blist = b->u.next;
|
|
|
|
b->addr = d->addr;
|
|
|
|
if (d->addr + size < d->addr) {
|
|
|
|
error("temp file overflow");
|
|
|
|
}
|
|
|
|
d->addr += size;
|
|
|
|
}
|
|
|
|
b->u.n = n;
|
|
|
|
return b;
|
2019-11-14 23:15:48 +00:00
|
|
|
}
|
|
|
|
|
2021-06-13 05:54:54 +00:00
|
|
|
void diskrelease(Disk* d, Block* b) {
|
|
|
|
uint i;
|
2019-11-14 23:15:48 +00:00
|
|
|
|
2021-06-13 05:54:54 +00:00
|
|
|
ntosize(b->u.n, &i);
|
|
|
|
b->u.next = d->free[i];
|
|
|
|
d->free[i] = b;
|
2019-11-14 23:15:48 +00:00
|
|
|
}
|
|
|
|
|
2021-06-13 05:54:54 +00:00
|
|
|
void diskwrite(Disk* d, Block** bp, Rune* r, uint n) {
|
|
|
|
int size, nsize;
|
|
|
|
Block* b;
|
2019-11-14 23:15:48 +00:00
|
|
|
|
2021-06-13 05:54:54 +00:00
|
|
|
b = *bp;
|
|
|
|
size = ntosize(b->u.n, nil);
|
|
|
|
nsize = ntosize(n, nil);
|
|
|
|
if (size != nsize) {
|
|
|
|
diskrelease(d, b);
|
|
|
|
b = disknewblock(d, n);
|
|
|
|
*bp = b;
|
|
|
|
}
|
|
|
|
if (pwrite(d->fd, r, n * sizeof(Rune), b->addr) != n * sizeof(Rune))
|
|
|
|
error("write error to temp file");
|
|
|
|
b->u.n = n;
|
2019-11-14 23:15:48 +00:00
|
|
|
}
|
|
|
|
|
2021-06-13 05:54:54 +00:00
|
|
|
void diskread(Disk* d, Block* b, Rune* r, uint n) {
|
|
|
|
if (n > b->u.n)
|
|
|
|
error("internal error: diskread");
|
2019-11-14 23:15:48 +00:00
|
|
|
|
2021-06-13 05:54:54 +00:00
|
|
|
ntosize(b->u.n, nil);
|
|
|
|
if (pread(d->fd, r, n * sizeof(Rune), b->addr) != n * sizeof(Rune))
|
|
|
|
error("read error from temp file");
|
2019-11-14 23:15:48 +00:00
|
|
|
}
|