acme9k/disk.c

119 lines
2.4 KiB
C
Raw Normal View History

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>
#include <frame.h>
#include <fcall.h>
#include <plumb.h>
#include <libsec.h>
#include "dat.h"
#include "fns.h"
static Block* blist;
2019-11-14 23:15:48 +00:00
int tempfile(void) {
char buf[128];
int i, fd;
2019-11-14 23:15:48 +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
}
Disk* diskinit() {
Disk* d;
2019-11-14 23:15:48 +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
}
static uint ntosize(uint n, uint* ip) {
uint size;
2019-11-14 23:15:48 +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
}
Block* disknewblock(Disk* d, uint n) {
uint i, j, size;
Block* b;
2019-11-14 23:15:48 +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
}
void diskrelease(Disk* d, Block* b) {
uint i;
2019-11-14 23:15:48 +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
}
void diskwrite(Disk* d, Block** bp, Rune* r, uint n) {
int size, nsize;
Block* b;
2019-11-14 23:15:48 +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
}
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
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
}