Charles.Forsyth20080116-1340f4bb33e18 years agoHistory
97 lines · 2.2 KB · Brainfuck
RawDownload
implement Ramfile;include "sys.m";	sys: Sys;include "draw.m"; # synthesise a file that can be treated just like any other# file. limitations of file2chan mean that it's not possible# to know when an open should have truncated the file, so# we do the only possible thing, and truncate it when we get# a write at offset 0. thus it can be edited with an editor,# but can't be used to store seekable, writable data records# (unless the first record is never written) # there should be some way to determine when the file should# go away - file2chan sends a nil channel whenever the file# is closed by anyone, which is not good enough. stderr: ref Sys->FD; Ramfile: module {	init: fn(nil: ref Draw->Context, argv: list of string);}; init(nil: ref Draw->Context, argv: list of string){	sys = load Sys Sys->PATH;	stderr = sys->fildes(2);	if (len argv < 2 || len argv > 3) {		sys->fprint(stderr, "usage: ramfile path [data]\n");		return;	}	path := hd tl argv;	(dir, f) := pathsplit(path); 	if (sys->bind("#s", dir, Sys->MBEFORE|Sys->MCREATE) == -1) {		sys->fprint(stderr, "ramfile: %r\n");		return;	}	fio := sys->file2chan(dir, f);	if (fio == nil) {		sys->fprint(stderr, "ramfile: file2chan failed: %r\n");		return;	}	data := array[0] of byte;	if (tl tl argv != nil)		data = array of byte hd tl tl argv; 	spawn server(fio, data);	data = nil;} server(fio: ref Sys->FileIO, data: array of byte){	for (;;) alt {	(offset, count, nil, rc) := <-fio.read =>		if (rc != nil) {			if (offset > len data)				rc <-= (nil, nil);			else {				end := offset + count;				if (end > len data)					end = len data;				rc <-= (data[offset:end], nil);			}		}	(offset, d, nil, wc) := <-fio.write =>		if (wc != nil) {			if (offset == 0)				data = array[0] of byte;			end := offset + len d;			if (end > len data) {				ndata := array[end] of byte;				ndata[0:] = data;				data = ndata;				ndata = nil;			}			data[offset:] = d;			wc <-= (len d, nil);		}	}} pathsplit(p: string): (string, string){	for (i := len p - 1; i >= 0; i--)		if (p[i] != '/')			break;	if (i < 0)		return (p, nil);	p = p[0:i+1];	for (i = len p - 1; i >=0; i--)		if (p[i] == '/')			break;	if (i < 0)		return (".", p);	return (p[0:i+1], p[i+1:]);}