Пример #1
0
/*
 * check time and entity tag conditions.
 */
int
checkreq(HConnect *c, HContent *type, HContent *enc, long mtime, char *etag)
{
	Hio *hout;
	int m;

	hout = &c->hout;
	if(c->req.vermaj >= 1 && c->req.vermin >= 1 && !hcheckcontent(type, c->head.oktype, "Content-Type", 0))
		return notaccept(c, type, enc, "Content-Type");
	if(c->req.vermaj >= 1 && c->req.vermin >= 1 && !hcheckcontent(enc, c->head.okencode, "Content-Encoding", 0))
		return notaccept(c, type, enc, "Content-Encoding");

	/*
	 * can use weak match only with get or head;
	 * this always uses strong matches
	 */
	m = etagmatch(1, c->head.ifnomatch, etag);

	if(m && strcmp(c->req.meth, "GET") != 0 && strcmp(c->req.meth, "HEAD") != 0
	|| c->head.ifunmodsince && c->head.ifunmodsince < mtime
	|| c->head.ifmatch != nil && !etagmatch(1, c->head.ifmatch, etag)){
		hprint(hout, "%s 412 Precondition Failed\r\n", hversion);
		hprint(hout, "Server: Plan9\r\n");
		hprint(hout, "Date: %D\r\n", time(nil));
		hprint(hout, "Content-Type: text/html\r\n");
		hprint(hout, "Content-Length: %d\r\n", STRLEN(UNMATCHED));
		if(c->head.closeit)
			hprint(hout, "Connection: close\r\n");
		else if(!http11(c))
			hprint(hout, "Connection: Keep-Alive\r\n");
		hprint(hout, "\r\n");
		if(strcmp(c->req.meth, "HEAD") != 0)
			hprint(hout, "%s", UNMATCHED);
		writelog(c, "Reply: 412 Precondition Failed\n");
		return hflush(hout);
	}

	if(c->head.ifmodsince >= mtime
	&& (m || c->head.ifnomatch == nil)){
		/*
		 * can only send back Date, ETag, Content-Location,
		 * Expires, Cache-Control, and Vary entity-headers
		 */
		hprint(hout, "%s 304 Not Modified\r\n", hversion);
		hprint(hout, "Server: Plan9\r\n");
		hprint(hout, "Date: %D\r\n", time(nil));
		hprint(hout, "ETag: %s\r\n", etag);
		if(c->head.closeit)
			hprint(hout, "Connection: close\r\n");
		else if(!http11(c))
			hprint(hout, "Connection: Keep-Alive\r\n");
		hprint(hout, "\r\n");
		writelog(c, "Reply: 304 Not Modified\n");
		return hflush(hout);
	}
	return 1;
}
Пример #2
0
void
error(char *title, char *fmt, ...)
{
	va_list arg;
	char buf[1024], *out;

	va_start(arg, fmt);
	out = vseprint(buf, buf+sizeof(buf), fmt, arg);
	va_end(arg);
	*out = 0;

	hprint(hout, "%s 404 %s\r\n", hversion, title);
	hprint(hout, "Date: %D\r\n", time(nil));
	hprint(hout, "Server: Plan9\r\n");
	hprint(hout, "Content-type: text/html\r\n");
	hprint(hout, "\r\n");
	doctype();
	hprint(hout, "<html xmlns=\"http://www.w3.org/1999/xhtml\">\n");
	hprint(hout, "<head><title>%s</title></head>\n", title);
	hprint(hout, "<body>\n");
	hprint(hout, "<h1>%s</h1>\n", title);
	hprint(hout, "%s\n", buf);
	hprint(hout, "</body>\n");
	hprint(hout, "</html>\n");
	hflush(hout);
	writelog(connect, "Reply: 404\nReason: %s\n", title);
	exits(nil);
}
Пример #3
0
static int
dindex(HConnect *c)
{
	Hio *hout;
	Index *ix;
	int i, r;

	r = hsettext(c);
	if(r < 0)
		return r;
	hout = &c->hout;


	ix = mainindex;
	hprint(hout, "index=%s version=%d blocksize=%d tabsize=%d\n",
		ix->name, ix->version, ix->blocksize, ix->tabsize);
	hprint(hout, "\tbuckets=%d div=%d\n", ix->buckets, ix->div);
	for(i = 0; i < ix->nsects; i++)
		hprint(hout, "\tsect=%s for buckets [%lld,%lld) buckmax=%d\n", ix->smap[i].name, ix->smap[i].start, ix->smap[i].stop, ix->sects[i]->buckmax);
	for(i = 0; i < ix->narenas; i++){
		if(ix->arenas[i] != nil && ix->arenas[i]->memstats.clumps != 0){
			hprint(hout, "arena=%s at index [%lld,%lld)\n\t", ix->amap[i].name, ix->amap[i].start, ix->amap[i].stop);
			darena(hout, ix->arenas[i]);
		}
	}
	hflush(hout);
	return 0;
}
Пример #4
0
static int
xindex(HConnect *c)
{
	if(hsettype(c, "text/xml") < 0)
		return -1;
	xmlindex(&c->hout, mainindex, "index", 0);
	hflush(&c->hout);
	return 0;
}
Пример #5
0
static int
xloglist(HConnect *c)
{
	if(hsettype(c, "text/html") < 0)
		return -1;
	vtloghlist(&c->hout);
	hflush(&c->hout);
	return 0;
}
Пример #6
0
///////////////////////////////////////////////////////////////////////////////
// hprintf
static void hprintf(HANDLE LogFile, LPCTSTR Format, ...)
{
	hflush(LogFile, (HPRINTF_BUFFER_SIZE-1024));

	va_list arglist;
	va_start( arglist, Format);
	hprintf_index += wvsprintf(&hprintf_buffer[hprintf_index], Format, arglist);
	va_end( arglist);
}
Пример #7
0
static int
fromwebdir(HConnect *c)
{
	char buf[4096], *p, *ext, *type;
	int i, fd, n, defaulted;
	Dir *d;
	
	if(webroot == nil || strstr(c->req.uri, ".."))
		return hnotfound(c);
	snprint(buf, sizeof buf-20, "%s/%s", webroot, c->req.uri+1);
	defaulted = 0;
reopen:
	if((fd = open(buf, OREAD)) < 0)
		return hnotfound(c);
	d = dirfstat(fd);
	if(d == nil){
		close(fd);
		return hnotfound(c);
	}
	if(d->mode&DMDIR){
		if(!defaulted){
			defaulted = 1;
			strcat(buf, "/index.html");
			free(d);
			close(fd);
			goto reopen;
		}
		free(d);
		return hnotfound(c);
	}
	free(d);
	p = buf+strlen(buf);
	type = "application/octet-stream";
	for(i=0; exttab[i].ext; i++){
		ext = exttab[i].ext;
		if(p-strlen(ext) >= buf && strcmp(p-strlen(ext), ext) == 0){
			type = exttab[i].type;
			break;
		}
	}
	if(hsettype(c, type) < 0){
		close(fd);
		return 0;
	}
	while((n = read(fd, buf, sizeof buf)) > 0)
		if(hwrite(&c->hout, buf, n) < 0)
			break;
	close(fd);
	hflush(&c->hout);
	return 0;
}
Пример #8
0
int hclose(hFILE *fp)
{
    int err = fp->has_errno;

    if (writebuffer_is_nonempty(fp) && hflush(fp) < 0) err = fp->has_errno;
    if (fp->backend->close(fp) < 0) err = errno;
    hfile_destroy(fp);

    if (err) {
        errno = err;
        return EOF;
    }
    else return 0;
}
Пример #9
0
static int
xset(HConnect *c)
{
	int i, old;
	char *name, *value;

	if(hsettext(c) < 0)
		return -1;

	if((name = hargstr(c, "name", nil)) == nil || name[0] == 0){
		for(i=0; namedints[i].name; i++)
			hprint(&c->hout, "%s = %d\n", namedints[i].name, *namedints[i].p);
		hflush(&c->hout);
		return 0;
	}

	for(i=0; namedints[i].name; i++)
		if(strcmp(name, namedints[i].name) == 0)
			break;
	if(!namedints[i].name){
		hprint(&c->hout, "%s not found\n", name);
		hflush(&c->hout);
		return 0;
	}

	if((value = hargstr(c, "value", nil)) == nil || value[0] == 0){
		hprint(&c->hout, "%s = %d\n", namedints[i].name, *namedints[i].p);
		hflush(&c->hout);
		return 0;
	}
	
	old = *namedints[i].p;
	*namedints[i].p = atoll(value);
	hprint(&c->hout, "%s = %d (was %d)\n", name, *namedints[i].p, old);
	hflush(&c->hout);
	return 0;
}
Пример #10
0
static int
hmanager(HConnect *c)
{
	Hio *hout;
	int r;
	int i, k;
	Job *j;
	VtLog *l;
	VtLogChunk *ch;

	r = hsethtml(c);
	if(r < 0)
		return r;

	hout = &c->hout;
	hprint(hout, "<html><head><title>venti mgr status</title></head>\n");
	hprint(hout, "<body><h2>venti mgr status</h2>\n");

	for(i=0; i<njob; i++) {
		j = &job[i];
		hprint(hout, "<b>");
		if(j->nrun == 0)
			hprint(hout, "----/--/-- --:--:--");
		else
			hprint(hout, "%+T", (long)(j->runstart + time0));
		hprint(hout, " %s", j->name);
		if(j->nrun > 0) {
			if(j->newok == -1) {
				hprint(hout, " (running)");
			} else if(!j->newok) {
				hprint(hout, " <font color=\"#cc0000\">(FAILED)</font>");
			}
		}
		hprint(hout, "</b>\n");
		hprint(hout, "<font size=-1><pre>\n");
		l = j->newlog;
		ch = l->w;
		for(k=0; k<l->nchunk; k++){
			if(++ch == l->chunk+l->nchunk)
				ch = l->chunk;
			hwrite(hout, ch->p, ch->wp-ch->p);
		}
		hprint(hout, "</pre></font>\n");
		hprint(hout, "\n");
	}
	hprint(hout, "</body></html>\n");
	hflush(hout);
	return 0;
}
Пример #11
0
static int
hicacheempty(HConnect *c)
{
	Hio *hout;
	int r;

	r = hsettext(c);
	if(r < 0)
		return r;
	hout = &c->hout;

	emptyicache();
	hprint(hout, "emptied icache\n");
	hflush(hout);
	return 0;
}
Пример #12
0
static int
hicachekick(HConnect *c)
{
	Hio *hout;
	int r;

	r = hsettext(c);
	if(r < 0)
		return r;
	hout = &c->hout;

	kickicache();
	hprint(hout, "kicked icache\n");
	hflush(hout);
	return 0;
}
Пример #13
0
static int
hdcacheflush(HConnect *c)
{
	Hio *hout;
	int r;

	r = hsettext(c);
	if(r < 0)
		return r;
	hout = &c->hout;

	flushdcache();
	hprint(hout, "flushed dcache\n");
	hflush(hout);
	return 0;
}
Пример #14
0
void
t_push(void)	/* begin a new block */
{
	hflush();
	statep->ssize = size;
	statep->sfont = font;
	statep->shorig = horig;
	statep->svorig = vorig;
	statep->shpos = hpos;
	statep->svpos = vpos;
	horig = hpos;
	vorig = vpos;
	hpos = vpos = 0;
	if (statep++ >= state+MAXSTATE)
		error(FATAL, "{ nested too deep");
	hpos = vpos = 0;
}
Пример #15
0
void
main(int argc, char **argv)
{
	fmtinstall('H', httpfmt);
	fmtinstall('U', hurlfmt);
	fmtinstall('M', dirmodefmt);

	aio = Bopen("/sys/lib/webls.allowed", OREAD);
	dio = Bopen("/sys/lib/webls.denied", OREAD);

	if(argc == 2){
		hinit(&houtb, 1, Hwrite);
		hout = &houtb;
		dols(argv[1]);
		exits(nil);
	}
	close(2);

	connect = init(argc, argv);
	hout = &connect->hout;
	vermaj = connect->req.vermaj;
	if(hparseheaders(connect, HSTIMEOUT) < 0)
		exits("failed");

	if(strcmp(connect->req.meth, "GET") != 0 && strcmp(connect->req.meth, "HEAD") != 0){
		hunallowed(connect, "GET, HEAD");
		exits("not allowed");
	}
	if(connect->head.expectother || connect->head.expectcont){
		hfail(connect, HExpectFail, nil);
		exits("failed");
	}

	bind("/usr/web", "/", MREPL);

	if(connect->req.search != nil)
		dosearch(connect->req.search);
	else
		error("Bad argument", "<p>Need a search argument</p>");
	hflush(hout);
	writelog(connect, "200 webls %ld %ld\n", hout->seek, hout->seek);
	exits(nil);
}
Пример #16
0
static int
sindex(HConnect *c)
{
	Hio *hout;
	Index *ix;
	Arena *arena;
	vlong clumps, cclumps, uncsize, used, size;
	int i, r, active;

	r = hsettext(c);
	if(r < 0)
		return r;
	hout = &c->hout;

	ix = mainindex;

	hprint(hout, "index=%s\n", ix->name);

	active = 0;
	clumps = 0;
	cclumps = 0;
	uncsize = 0;
	used = 0;
	size = 0;
	for(i = 0; i < ix->narenas; i++){
		arena = ix->arenas[i];
		if(arena != nil && arena->memstats.clumps != 0){
			active++;
			clumps += arena->memstats.clumps;
			cclumps += arena->memstats.cclumps;
			uncsize += arena->memstats.uncsize;
			used += arena->memstats.used;
		}
		size += arena->size;
	}
	hprint(hout, "total arenas=%,d active=%,d\n", ix->narenas, active);
	hprint(hout, "total space=%,lld used=%,lld\n", size, used + clumps * ClumpInfoSize);
	hprint(hout, "clumps=%,lld compressed clumps=%,lld data=%,lld compressed data=%,lld\n",
		clumps, cclumps, uncsize, used - clumps * ClumpSize);
	hflush(hout);
	return 0;
}
Пример #17
0
static int
xlog(HConnect *c)
{
	char *name;
	VtLog *l;

	name = hargstr(c, "log", "");
	if(!name[0])
		return xloglist(c);
	l = vtlogopen(name, 0);
	if(l == nil)
		return hnotfound(c);
	if(hsettype(c, "text/html") < 0){
		vtlogclose(l);
		return -1;
	}
	vtloghdump(&c->hout, l);
	vtlogclose(l);
	hflush(&c->hout);
	return 0;
}
Пример #18
0
void
main(int argc, char **argv)
{
	fmtinstall('H', httpfmt);
	fmtinstall('U', hurlfmt);

	if(argc == 2){
		hinit(&houtb, 1, Hwrite);
		hout = &houtb;
		doconvert(argv[1], 0);
		exits(nil);
	}
	close(2);

	connect = init(argc, argv);
	hout = &connect->hout;
	if(hparseheaders(connect, HSTIMEOUT) < 0)
		exits("failed");

	if(strcmp(connect->req.meth, "GET") != 0 && strcmp(connect->req.meth, "HEAD") != 0){
		hunallowed(connect, "GET, HEAD");
		exits("not allowed");
	}
	if(connect->head.expectother || connect->head.expectcont){
		hfail(connect, HExpectFail, nil);
		exits("failed");
	}

	bind("/usr/web/sys/man", "/sys/man", MREPL);

	if(connect->req.search != nil)
		dosearch(connect->req.vermaj, connect->req.search);
	else
		doconvert(connect->req.uri, connect->req.vermaj);
	hflush(hout);
	writelog(connect, "200 man2html %ld %ld\n", hout->seek, hout->seek);
	exits(nil);
}
Пример #19
0
void
httpproc(void *v)
{
	HConnect *c;
	int ok, i, n;

	c = v;

	for(;;){
		/*
		 * No timeout because the signal appears to hit every
		 * proc, not just us.
		 */
		if(hparsereq(c, 0) < 0)
			break;
		
		for(i = 0; i < MaxObjs && objs[i].name[0]; i++){
			n = strlen(objs[i].name);
			if((objs[i].name[n-1] == '/' && strncmp(c->req.uri, objs[i].name, n) == 0)
			|| (objs[i].name[n-1] != '/' && strcmp(c->req.uri, objs[i].name) == 0)){
				ok = (*objs[i].f)(c);
				goto found;
			}
		}
		ok = fromwebdir(c);
	found:
		hflush(&c->hout);
		if(c->head.closeit)
			ok = -1;
		hreqcleanup(c);

		if(ok < 0)
			break;
	}
	hreqcleanup(c);
	close(c->hin.fd);
	free(c);
}
Пример #20
0
/*
 * send back a nice error message if the content is unacceptable
 * to get this message in ie, go to tools, internet options, advanced,
 * and turn off Show Friendly HTTP Error Messages under the Browsing category
 */
static int
notaccept(HConnect *c, HContent *type, HContent *enc, char *which)
{
	Hio *hout;
	char *s, *e;

	hout = &c->hout;
	e = &c->xferbuf[HBufSize];
	s = c->xferbuf;
	s = seprint(s, e, "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">\n");
	s = seprint(s, e, "<html>\n<title>Unacceptable %s</title>\n<body>\n", which);
	s = seprint(s, e, "Your browser will not accept this data, %H, because of its %s.<br>\n", c->req.uri, which);
	s = seprint(s, e, "Its Content-Type is %s/%s", type->generic, type->specific);
	if(enc != nil)
		s = seprint(s, e, ", and Content-Encoding is %s", enc->generic);
	s = seprint(s, e, ".<br>\n\n");

	s = acceptcont(s, e, c->head.oktype, "Content-Type");
	s = acceptcont(s, e, c->head.okencode, "Content-Encoding");
	s = seprint(s, e, "</body>\n</html>\n");

	hprint(hout, "%s 406 Not Acceptable\r\n", hversion);
	hprint(hout, "Server: Plan9\r\n");
	hprint(hout, "Date: %D\r\n", time(nil));
	hprint(hout, "Content-Type: text/html\r\n");
	hprint(hout, "Content-Length: %lud\r\n", s - c->xferbuf);
	if(c->head.closeit)
		hprint(hout, "Connection: close\r\n");
	else if(!http11(c))
		hprint(hout, "Connection: Keep-Alive\r\n");
	hprint(hout, "\r\n");
	if(strcmp(c->req.meth, "HEAD") != 0)
		hwrite(hout, c->xferbuf, s - c->xferbuf);
	writelog(c, "Reply: 406 Not Acceptable\nReason: %s\n", which);
	return hflush(hout);
}
Пример #21
0
static int
herror(HConnect *c)
{
	int n;
	Hio *hout;
	
	hout = &c->hout;
	n = snprint(c->xferbuf, HBufSize, "<html><head><title>Error</title></head>\n<body><h1>Error</h1>\n<pre>%r</pre>\n</body></html>");
	hprint(hout, "%s %s\r\n", hversion, "400 Bad Request");
	hprint(hout, "Date: %D\r\n", time(nil));
	hprint(hout, "Server: Venti\r\n");
	hprint(hout, "Content-Type: text/html\r\n");
	hprint(hout, "Content-Length: %d\r\n", n);
	if(c->head.closeit)
		hprint(hout, "Connection: close\r\n");
	else if(!http11(c))
		hprint(hout, "Connection: Keep-Alive\r\n");
	hprint(hout, "\r\n");

	if(c->req.meth == nil || strcmp(c->req.meth, "HEAD") != 0)
		hwrite(hout, c->xferbuf, n);

	return hflush(hout);
}
Пример #22
0
/*
 *  convert a man page to html and output
 */
void
doconvert(char *uri, int vermaj)
{
	char *p;
	char file[256];
	char title[256];
	char err[ERRMAX];
	int pfd[2];
	Dir *d;
	Waitmsg *w;
	int x;

	if(strstr(uri, ".."))
		error("bad URI", "man page URI cannot contain ..");
	p = strstr(uri, "/intro");

	if(p == nil){
		while(*uri == '/')
			uri++;
		/* redirect section requests */
		snprint(file, sizeof(file), "/sys/man/%s", uri);
		d = dirstat(file);
		if(d == nil){
			strlwr(file);
			if(dirstat(file) != nil){
				snprint(file, sizeof(file), "/magic/man2html/%s", uri);
				strlwr(file);
				redirectto(file);
			}
			error(uri, "man page not found");
		}
		x = d->qid.type;
		free(d);
		if(x & QTDIR){
			if(*uri == 0 || strcmp(uri, "/") == 0)
				redirectto("/sys/man/index.html");
			else {
				snprint(file, sizeof(file), "/sys/man/%s/INDEX.html",
					uri+1);
				redirectto(file);
			}
			return;
		}
	} else {
		/* rewrite the name intro */
		*p = 0;
		snprint(file, sizeof(file), "/sys/man/%s/0intro", uri);
		d = dirstat(file);
		free(d);
		if(d == nil)
			error(uri, "man page not found");
	}

	if(vermaj){
		hokheaders(connect);
		hprint(hout, "Content-type: text/html\r\n");
		hprint(hout, "\r\n");
	}
	hflush(hout);

	if(pipe(pfd) < 0)
		error("out of resources", "pipe failed");

	/* troff -manhtml <file> | troff2html -t '' */
	switch(fork()){
	case -1:
		error("out of resources", "fork failed");
	case 0:
		snprint(title, sizeof(title), "Plan 9 %s", file);
		close(0);
		dup(pfd[0], 0);
		close(pfd[0]);
		close(pfd[1]);
		execl("/bin/troff2html", "troff2html", "-t", title, nil);
		errstr(err, sizeof err);
		exits(err);
	}
	switch(fork()){
	case -1:
		error("out of resources", "fork failed");
	case 0:
		snprint(title, sizeof(title), "Plan 9 %s", file);
		close(0);
		close(1);
		dup(pfd[1], 1);
		close(pfd[0]);
		close(pfd[1]);
		execl("/bin/troff", "troff", "-manhtml", file, nil);
		errstr(err, sizeof err);
		exits(err);
	}
	close(pfd[0]);
	close(pfd[1]);

	/* wait for completion */
	for(;;){
		w = wait();
		if(w == nil)
			break;
		if(w->msg[0] != 0)
			print("whoops %s\n", w->msg);
		free(w);
	}
}
Пример #23
0
int main(void)
{
    static const int size[] = { 1, 13, 403, 999, 30000 };

    char buffer[40000];
    char *original;
    int c, i;
    ssize_t n;
    off_t off;

    reopen("vcf.c", "test/hfile1.tmp");
    while ((c = hgetc(fin)) != EOF) {
        if (hputc(c, fout) == EOF) fail("hputc");
    }
    if (herrno(fin)) { errno = herrno(fin); fail("hgetc"); }

    reopen("test/hfile1.tmp", "test/hfile2.tmp");
    if (hpeek(fin, buffer, 50) < 0) fail("hpeek");
    while ((n = hread(fin, buffer, 17)) > 0) {
        if (hwrite(fout, buffer, n) != n) fail("hwrite");
    }
    if (n < 0) fail("hread");

    reopen("test/hfile2.tmp", "test/hfile3.tmp");
    while ((n = hread(fin, buffer, sizeof buffer)) > 0) {
        if (hwrite(fout, buffer, n) != n) fail("hwrite");
        if (hpeek(fin, buffer, 700) < 0) fail("hpeek");
    }
    if (n < 0) fail("hread");

    reopen("test/hfile3.tmp", "test/hfile4.tmp");
    i = 0;
    off = 0;
    while ((n = hread(fin, buffer, size[i++ % 5])) > 0) {
        off += n;
        buffer[n] = '\0';
        check_offset(fin, off, "pre-peek");
        if (hputs(buffer, fout) == EOF) fail("hputs");
        if ((n = hpeek(fin, buffer, size[(i+3) % 5])) < 0) fail("hpeek");
        check_offset(fin, off, "post-peek");
    }
    if (n < 0) fail("hread");

    reopen("test/hfile4.tmp", "test/hfile5.tmp");
    n = hread(fin, buffer, 200);
    if (n < 0) fail("hread");
    else if (n != 200) fail("hread only got %d", (int)n);
    if (hwrite(fout, buffer, 1000) != 1000) fail("hwrite");
    check_offset(fin, 200, "input/first200");
    check_offset(fout, 1000, "output/first200");

    if (hseek(fin, 800, SEEK_CUR) < 0) fail("hseek/cur");
    check_offset(fin, 1000, "input/seek");
    for (off = 1000; (n = hread(fin, buffer, sizeof buffer)) > 0; off += n)
        if (hwrite(fout, buffer, n) != n) fail("hwrite");
    if (n < 0) fail("hread");
    check_offset(fin, off, "input/eof");
    check_offset(fout, off, "output/eof");

    if (hseek(fin, 200, SEEK_SET) < 0) fail("hseek/set");
    if (hseek(fout, 200, SEEK_SET) < 0) fail("hseek(output)");
    check_offset(fin, 200, "input/backto200");
    check_offset(fout, 200, "output/backto200");
    n = hread(fin, buffer, 800);
    if (n < 0) fail("hread");
    else if (n != 800) fail("hread only got %d", (int)n);
    if (hwrite(fout, buffer, 800) != 800) fail("hwrite");
    check_offset(fin, 1000, "input/wrote800");
    check_offset(fout, 1000, "output/wrote800");

    if (hflush(fout) == EOF) fail("hflush");

    original = slurp("vcf.c");
    for (i = 1; i <= 5; i++) {
        char *text;
        sprintf(buffer, "test/hfile%d.tmp", i);
        text = slurp(buffer);
        if (strcmp(original, text) != 0) {
            fprintf(stderr, "%s differs from vcf.c\n", buffer);
            return EXIT_FAILURE;
        }
        free(text);
    }
    free(original);

    if (hclose(fin) != 0) fail("hclose(input)");
    if (hclose(fout) != 0) fail("hclose(output)");

    fout = hopen("test/hfile_chars.tmp", "w");
    if (fout == NULL) fail("hopen(\"test/hfile_chars.tmp\")");
    for (i = 0; i < 256; i++)
        if (hputc(i, fout) != i) fail("chars: hputc (%d)", i);
    if (hclose(fout) != 0) fail("hclose(test/hfile_chars.tmp)");

    fin = hopen("test/hfile_chars.tmp", "r");
    if (fin == NULL) fail("hopen(\"test/hfile_chars.tmp\") for reading");
    for (i = 0; i < 256; i++)
        if ((c = hgetc(fin)) != i)
            fail("chars: hgetc (%d = 0x%x) returned %d = 0x%x", i, i, c, c);
    if ((c = hgetc(fin)) != EOF) fail("chars: hgetc (EOF) returned %d", c);
    if (hclose(fin) != 0) fail("hclose(test/hfile_chars.tmp) for reading");

    fin = hopen("data:hello, world!\n", "r");
    if (fin == NULL) fail("hopen(\"data:...\")");
    n = hread(fin, buffer, 300);
    if (n < 0) fail("hread");
    buffer[n] = '\0';
    if (strcmp(buffer, "hello, world!\n") != 0) fail("hread result");
    if (hclose(fin) != 0) fail("hclose(\"data:...\")");

    return EXIT_SUCCESS;
}
Пример #24
0
static int
xgraph(HConnect *c)
{
	char *name;
	Hio *hout;
	Memimage *m;
	int dotext;
	Graph g;
	Arg arg;
	char *graph, *a;

	name = hargstr(c, "arg", "");
	if((arg.index = findname(name)) == -1 && strcmp(name, "*") != 0){
		werrstr("unknown name %s", name);
		goto error;
	}
	a = hargstr(c, "arg2", "");
	if(a[0] && (arg.index2 = findname(a)) == -1){
		werrstr("unknown name %s", a);
		goto error;
	}

	g.arg = &arg;
	g.t0 = hargint(c, "t0", -120);
	g.t1 = hargint(c, "t1", 0);
	g.min = hargint(c, "min", -1);
	g.max = hargint(c, "max", -1);
	g.wid = hargint(c, "wid", -1);
	g.ht = hargint(c, "ht", -1);
	dotext = hargstr(c, "text", "")[0] != 0;
	g.fill = hargint(c, "fill", -1);
	
	graph = hargstr(c, "graph", "raw");
	if(strcmp(graph, "raw") == 0)
		g.fn = rawgraph;
	else if(strcmp(graph, "diskbw") == 0)
		g.fn = diskgraph;
	else if(strcmp(graph, "iobw") == 0)
		g.fn = iograph;
	else if(strcmp(graph, "netbw") == 0)
		g.fn = netgraph;
	else if(strcmp(graph, "diff") == 0)
		g.fn = diffgraph;
	else if(strcmp(graph, "pct") == 0)
		g.fn = pctgraph;
	else if(strcmp(graph, "pctdiff") == 0)
		g.fn = pctdiffgraph;
	else if(strcmp(graph, "divdiff") == 0)
		g.fn = divdiffgraph;
	else{
		werrstr("unknown graph %s", graph);
		goto error;
	}

	if(dotext){
		hsettype(c, "text/plain");
		dotextbin(&c->hout, &g);
		hflush(&c->hout);
		return 0;
	}

	m = statgraph(&g);
	if(m == nil)
		goto error;

	if(hsettype(c, "image/png") < 0)
		return -1;
	hout = &c->hout;
	writepng(hout, m);
	qlock(&memdrawlock);
	freememimage(m);
	qunlock(&memdrawlock);
	hflush(hout);
	return 0;

error:
	return herror(c);
}
Пример #25
0
static void
debugread(HConnect *c, u8int *score)
{
	int type;
	Lump *u;
	IAddr ia;
	IEntry ie;
	int i;
	Arena *arena;
	u64int aa;
	ZBlock *zb;
	Clump cl;
	vlong off;
	u8int sc[VtScoreSize];

	if(scorecmp(score, zeroscore) == 0){
		hprint(&c->hout, "zero score\n");
		return;
	}
	
	hprint(&c->hout, "<h2>index search %V</h2><pre>\n", score);
	if(icachelookup(score, -1, &ia) < 0)
		hprint(&c->hout, "  icache: not found\n");
	else
		hprint(&c->hout, "  icache: addr=%#llx size=%d type=%d blocks=%d\n",
			ia.addr, ia.size, ia.type, ia.blocks);
	
	if(loadientry(mainindex, score, -1, &ie) < 0)
		hprint(&c->hout, "  idisk: not found\n");
	else
		hprint(&c->hout, "  idisk: addr=%#llx size=%d type=%d blocks=%d\n",
			ie.ia.addr, ie.ia.size, ie.ia.type, ie.ia.blocks);
	
	hprint(&c->hout, "</pre><h2>lookup %V</h2>\n", score);
	hprint(&c->hout, "<pre>\n");
	
	for(type=0; type < VtMaxType; type++){
		hprint(&c->hout, "%V type %d:", score, type);
		u = lookuplump(score, type);
		if(u->data != nil)
			hprint(&c->hout, " +cache");
		else
			hprint(&c->hout, " -cache");
		putlump(u);
		
		if(lookupscore(score, type, &ia) < 0){
			hprint(&c->hout, " -lookup\n");
			continue;
		}
		hprint(&c->hout, "\n  lookupscore: addr=%#llx size=%d blocks=%d\n",
			ia.addr, ia.size, ia.blocks);
		
		arena = amapitoa(mainindex, ia.addr, &aa);
		if(arena == nil){
			hprint(&c->hout, "  amapitoa failed: %r\n");
			continue;
		}

		hprint(&c->hout, "  amapitoa: aa=%#llx arena="
			"<a href=\"/disk?disk=%s&type=a&arena=%s&score=%V\">%s</a>\n",
			aa, arena->part->name, arena->name, score, arena->name);
		zb = loadclump(arena, aa, ia.blocks, &cl, sc, 1);
		if(zb == nil){
			hprint(&c->hout, "  loadclump failed: %r\n");
			continue;
		}
		
		hprint(&c->hout, "  loadclump: uncsize=%d type=%d score=%V\n",
			cl.info.uncsize, cl.info.type, sc);
		if(ia.size != cl.info.uncsize || ia.type != cl.info.type || scorecmp(score, sc) != 0){
			hprint(&c->hout, "    clump info mismatch\n");
			continue;
		}
	}
	
	if(hargstr(c, "brute", "")[0] == 'y'){
		hprint(&c->hout, "</pre>\n");
		hprint(&c->hout, "<h2>brute force arena search %V</h2>\n", score);
		hprint(&c->hout, "<pre>\n");
		
		for(i=0; i<mainindex->narenas; i++){
			arena = mainindex->arenas[i];
			hprint(&c->hout, "%s...\n", arena->name);
			hflush(&c->hout);
			off = findintoc(nil, arena, score);
			if(off >= 0)
				hprint(&c->hout, "%s %#llx (%#llx)\n", arena->name, off, mainindex->amap[i].start + off);
		}
	}

	hprint(&c->hout, "</pre>\n");
}
Пример #26
0
/*
 * fd references a file which has been authorized & checked for relocations.
 * send back the headers & its contents.
 * includes checks for conditional requests & ranges.
 */
int
sendfd(HConnect *c, int fd, Dir *dir, HContent *type, HContent *enc)
{
	Qid qid;
	HRange *r;
	HContents conts;
	Hio *hout;
	char *boundary, etag[32];
	long mtime;
	ulong tr;
	int n, nw, multir, ok;
	vlong wrote, length;

	hout = &c->hout;
	length = dir->length;
	mtime = dir->mtime;
	qid = dir->qid;
	free(dir);

	/*
	 * figure out the type of file and send headers
	 */
	n = -1;
	r = nil;
	multir = 0;
	boundary = nil;
	if(c->req.vermaj){
		if(type == nil && enc == nil){
			conts = uriclass(c, c->req.uri);
			type = conts.type;
			enc = conts.encoding;
			if(type == nil && enc == nil){
				n = read(fd, c->xferbuf, HBufSize-1);
				if(n > 0){
					c->xferbuf[n] = '\0';
					conts = dataclass(c, c->xferbuf, n);
					type = conts.type;
					enc = conts.encoding;
				}
			}
		}
		if(type == nil)
			type = hmkcontent(c, "application", "octet-stream", nil);

		snprint(etag, sizeof(etag), "\"%lluxv%lux\"", qid.path, qid.vers);
		ok = checkreq(c, type, enc, mtime, etag);
		if(ok <= 0){
			close(fd);
			return ok;
		}

		/*
		 * check for if-range requests
		 */
		if(c->head.range == nil
		|| c->head.ifrangeetag != nil && !etagmatch(1, c->head.ifrangeetag, etag)
		|| c->head.ifrangedate != 0 && c->head.ifrangedate != mtime){
			c->head.range = nil;
			c->head.ifrangeetag = nil;
			c->head.ifrangedate = 0;
		}

		if(c->head.range != nil){
			c->head.range = fixrange(c->head.range, length);
			if(c->head.range == nil){
				if(c->head.ifrangeetag == nil && c->head.ifrangedate == 0){
					hprint(hout, "%s 416 Request range not satisfiable\r\n", hversion);
					hprint(hout, "Date: %D\r\n", time(nil));
					hprint(hout, "Server: Plan9\r\n");
					hprint(hout, "Content-Range: bytes */%lld\r\n", length);
					hprint(hout, "Content-Length: %d\r\n", STRLEN(BADRANGE));
					hprint(hout, "Content-Type: text/html\r\n");
					if(c->head.closeit)
						hprint(hout, "Connection: close\r\n");
					else if(!http11(c))
						hprint(hout, "Connection: Keep-Alive\r\n");
					hprint(hout, "\r\n");
					if(strcmp(c->req.meth, "HEAD") != 0)
						hprint(hout, "%s", BADRANGE);
					hflush(hout);
					writelog(c, "Reply: 416 Request range not satisfiable\n");
					close(fd);
					return 1;
				}
				c->head.ifrangeetag = nil;
				c->head.ifrangedate = 0;
			}
		}
		if(c->head.range == nil)
			hprint(hout, "%s 200 OK\r\n", hversion);
		else
			hprint(hout, "%s 206 Partial Content\r\n", hversion);

		hprint(hout, "Server: Plan9\r\n");
		hprint(hout, "Date: %D\r\n", time(nil));
		hprint(hout, "ETag: %s\r\n", etag);

		/*
		 * can't send some entity headers if partially responding
		 * to an if-range: etag request
		 */
		r = c->head.range;
		if(r == nil)
			hprint(hout, "Content-Length: %lld\r\n", length);
		else if(r->next == nil){
			hprint(hout, "Content-Range: bytes %ld-%ld/%lld\r\n", r->start, r->stop, length);
			hprint(hout, "Content-Length: %ld\r\n", r->stop - r->start);
		}else{
			multir = 1;
			boundary = hmkmimeboundary(c);
			hprint(hout, "Content-Type: multipart/byteranges; boundary=%s\r\n", boundary);
		}
		if(c->head.ifrangeetag == nil){
			hprint(hout, "Last-Modified: %D\r\n", mtime);
			if(!multir)
				printtype(hout, type, enc);
			if(c->head.fresh_thresh)
				hintprint(c, hout, c->req.uri, c->head.fresh_thresh, c->head.fresh_have);
		}

		if(c->head.closeit)
			hprint(hout, "Connection: close\r\n");
		else if(!http11(c))
			hprint(hout, "Connection: Keep-Alive\r\n");
		hprint(hout, "\r\n");
	}
	if(strcmp(c->req.meth, "HEAD") == 0){
		if(c->head.range == nil)
			writelog(c, "Reply: 200 file 0\n");
		else
			writelog(c, "Reply: 206 file 0\n");
		hflush(hout);
		close(fd);
		return 1;
	}

	/*
	 * send the file if it's a normal file
	 */
	if(r == nil){
		hflush(hout);

		wrote = 0;
		if(n > 0)
			wrote = write(hout->fd, c->xferbuf, n);
		if(n <= 0 || wrote == n){
			while((n = read(fd, c->xferbuf, HBufSize)) > 0){
				nw = write(hout->fd, c->xferbuf, n);
				if(nw != n){
					if(nw > 0)
						wrote += nw;
					break;
				}
				wrote += nw;
			}
		}
		writelog(c, "Reply: 200 file %lld %lld\n", length, wrote);
		close(fd);
		if(length == wrote)
			return 1;
		return -1;
	}

	/*
	 * for multipart/byterange messages,
	 * it is not ok for the boundary string to appear within a message part.
	 * however, it probably doesn't matter, since there are lengths for every part.
	 */
	wrote = 0;
	ok = 1;
	for(; r != nil; r = r->next){
		if(multir){
			hprint(hout, "\r\n--%s\r\n", boundary);
			printtype(hout, type, enc);
			hprint(hout, "Content-Range: bytes %ld-%ld/%lld\r\n", r->start, r->stop, length);
			hprint(hout, "Content-Length: %ld\r\n", r->stop - r->start);
			hprint(hout, "\r\n");
		}
		hflush(hout);

		if(seek(fd, r->start, 0) != r->start){
			ok = -1;
			break;
		}
		for(tr = r->stop - r->start + 1; tr; tr -= n){
			n = tr;
			if(n > HBufSize)
				n = HBufSize;
			if(read(fd, c->xferbuf, n) != n){
				ok = -1;
				goto breakout;
			}
			nw = write(hout->fd, c->xferbuf, n);
			if(nw != n){
				if(nw > 0)
					wrote += nw;
				ok = -1;
				goto breakout;
			}
			wrote += nw;
		}
	}
breakout:;
	if(r == nil){
		if(multir){
			hprint(hout, "--%s--\r\n", boundary);
			hflush(hout);
		}
		writelog(c, "Reply: 206 partial content %lld %lld\n", length, wrote);
	}else
		writelog(c, "Reply: 206 partial content, early termination %lld %lld\n", length, wrote);
	close(fd);
	return ok;
}
Пример #27
0
static void
dols(char *dir)
{
	Dir	*d;
	char	*f, *p,*nm;
	long	i, n;
	int	fd;

	cleanname(dir); //  expands "" to "."; ``dir+1'' access below depends on that
	if (!allowed(dir)) {
		error("Permission denied", "<p>Cannot list directory %s: Access prohibited</p>", dir);
		return;
	}
	fd = open(dir, OREAD);
	if (fd < 0) {
		error("Cannot read directory", "<p>Cannot read directory %s: %r</p>", dir);
		return;
	}
	if (vermaj) {
		hokheaders(connect);
		hprint(hout, "Content-type: text/html\r\n");
		hprint(hout, "\r\n");
	}
	doctype();
	hprint(hout, "<html xmlns=\"http://www.w3.org/1999/xhtml\">\n");
	hprint(hout, "<head><title>Index of %s</title></head>\n", dir);
	hprint(hout, "<body>\n");
	hprint(hout, "<h1>Index of ");
	nm = dir;
	while((p = strchr(nm, '/')) != nil){
		*p = '\0';
		f = (*dir == '\0') ? "/" : dir;
		if (!(*dir == '\0' && *(dir+1) == '\0') && allowed(f))
			hprint(hout, "<a href=\"/magic/webls?dir=%H\">%s/</a>", f, nm);
		else
			hprint(hout, "%s/", nm);
		*p = '/';
		nm = p+1;
	}
	hprint(hout, "%s</h1>\n", nm);
	n = dirreadall(fd, &d);
	close(fd);
	maxwidths(d, n);
	qsort(d, n, sizeof(Dir), (int (*)(void *, void *))compar);
	hprint(hout, "<pre>\n");
	for (i = 0; i < n; i++) {
		f = smprint("%s/%s", dir, d[i].name);
		cleanname(f);
		if (d[i].mode & DMDIR) {
			p = smprint("/magic/webls?dir=%H", f);
			free(f);
			f = p;
		}
		hprint(hout, "%M %C %*ud %-*s %-*s %*lld %s <a href=\"%s\">%s</a>\n",
		    d[i].mode, d[i].type,
		    devwidth, d[i].dev,
		    uidwidth, d[i].uid,
		    gidwidth, d[i].gid,
		    lenwidth, d[i].length,
		    asciitime(d[i].mtime), f, d[i].name);
		free(f);
	}
	f = smprint("%s/..", dir);
	cleanname(f);
	if (strcmp(f, dir) != 0 && allowed(f))
		hprint(hout, "\nGo to <a href=\"/magic/webls?dir=%H\">parent</a> directory\n", f);
	else
		hprint(hout, "\nEnd of directory listing\n");
	free(f);
	hprint(hout, "</pre>\n</body>\n</html>\n");
	hflush(hout);
	free(d);
}
Пример #28
0
void
main(int argc, char **argv)
{
	HConnect *c;
	Dir *dir;
	Hio *hin, *hout;
	char *s, *t, *fn;
	int n, nfn, datafd, htmlfd;

	c = init(argc, argv);

	if(dangerous(c->req.uri)){
		hfail(c, HSyntax);
		exits("failed");
	}

	if(hparseheaders(c, HSTIMEOUT) < 0)
		exits("failed");
	hout = &c->hout;
	if(c->head.expectother){
		hfail(c, HExpectFail, nil);
		exits("failed");
	}
	if(c->head.expectcont){
		hprint(hout, "100 Continue\r\n");
		hprint(hout, "\r\n");
		hflush(hout);
	}

	s = nil;
	if(strcmp(c->req.meth, "POST") == 0){
		hin = hbodypush(&c->hin, c->head.contlen, c->head.transenc);
		if(hin != nil){
			alarm(HSTIMEOUT);
			s = hreadbuf(hin, hin->pos);
			alarm(0);
		}
		if(s == nil){
			hfail(c, HBadReq, nil);
			exits("failed");
		}
		t = strchr(s, '\n');
		if(t != nil)
			*t = '\0';
	}else if(strcmp(c->req.meth, "GET") != 0 && strcmp(c->req.meth, "HEAD") != 0){
		hunallowed(c, "GET, HEAD, PUT");
		exits("unallowed");
	}else
		s = c->req.search;
	if(s == nil){
		hfail(c, HNoData, "save");
		exits("failed");
	}

	if(strlen(s) > MaxLog)
		s[MaxLog] = '\0';
	n = snprint(c->xferbuf, HBufSize, "at %ld %s\n", time(0), s);


	nfn = strlen(c->req.uri) + 64;
	fn = halloc(c, nfn);

	/*
	 * open file descriptors & write log line
	 */
	snprint(fn, nfn, "/usr/web/save/%s.html", c->req.uri);
	htmlfd = open(fn, OREAD);
	if(htmlfd < 0 || (dir = dirfstat(htmlfd)) == nil){
		hfail(c, HNotFound, c->req.uri);
		exits("failed");
		return;
	}

	snprint(fn, nfn, "/usr/web/save/%s.data", c->req.uri);
	datafd = openLocked(fn, OWRITE);
	if(datafd < 0){
		errstr(c->xferbuf, sizeof c->xferbuf);
		if(strstr(c->xferbuf, "locked") != nil)
			hfail(c, HTempFail, c->req.uri);
		else
			hfail(c, HNotFound, c->req.uri);
		exits("failed");
	}
	seek(datafd, 0, 2);
	write(datafd, c->xferbuf, n);
	close(datafd);

	sendfd(c, htmlfd, dir, hmkcontent(c, "text", "html", nil), nil);

	exits(nil);
}
Пример #29
0
static int
estats(HConnect *c)
{
	Hio *hout;
	int r;

	r = hsettext(c);
	if(r < 0)
		return r;


	hout = &c->hout;
/*
	hprint(hout, "lump writes=%,ld\n", stats.lumpwrites);
	hprint(hout, "lump reads=%,ld\n", stats.lumpreads);
	hprint(hout, "lump cache read hits=%,ld\n", stats.lumphit);
	hprint(hout, "lump cache read misses=%,ld\n", stats.lumpmiss);

	hprint(hout, "clump disk writes=%,ld\n", stats.clumpwrites);
	hprint(hout, "clump disk bytes written=%,lld\n", stats.clumpbwrites);
	hprint(hout, "clump disk bytes compressed=%,lld\n", stats.clumpbcomp);
	hprint(hout, "clump disk reads=%,ld\n", stats.clumpreads);
	hprint(hout, "clump disk bytes read=%,lld\n", stats.clumpbreads);
	hprint(hout, "clump disk bytes uncompressed=%,lld\n", stats.clumpbuncomp);

	hprint(hout, "clump directory disk writes=%,ld\n", stats.ciwrites);
	hprint(hout, "clump directory disk reads=%,ld\n", stats.cireads);

	hprint(hout, "index disk writes=%,ld\n", stats.indexwrites);
	hprint(hout, "index disk reads=%,ld\n", stats.indexreads);
	hprint(hout, "index disk bloom filter hits=%,ld %d%% falsemisses=%,ld %d%%\n",
		stats.indexbloomhits,
		percent(stats.indexbloomhits, stats.indexreads),
		stats.indexbloomfalsemisses,
		percent(stats.indexbloomfalsemisses, stats.indexreads));
	hprint(hout, "bloom filter bits=%,ld of %,ld %d%%\n",
		stats.bloomones, stats.bloombits, percent(stats.bloomones, stats.bloombits));
	hprint(hout, "index disk reads for modify=%,ld\n", stats.indexwreads);
	hprint(hout, "index disk reads for allocation=%,ld\n", stats.indexareads);
	hprint(hout, "index block splits=%,ld\n", stats.indexsplits);

	hprint(hout, "index cache lookups=%,ld\n", stats.iclookups);
	hprint(hout, "index cache hits=%,ld %d%%\n", stats.ichits,
		percent(stats.ichits, stats.iclookups));
	hprint(hout, "index cache fills=%,ld %d%%\n", stats.icfills,
		percent(stats.icfills, stats.iclookups));
	hprint(hout, "index cache inserts=%,ld\n", stats.icinserts);

	hprint(hout, "disk cache hits=%,ld\n", stats.pchit);
	hprint(hout, "disk cache misses=%,ld\n", stats.pcmiss);
	hprint(hout, "disk cache reads=%,ld\n", stats.pcreads);
	hprint(hout, "disk cache bytes read=%,lld\n", stats.pcbreads);

	hprint(hout, "disk cache writes=%,ld\n", stats.dirtydblocks);
	hprint(hout, "disk cache writes absorbed=%,ld %d%%\n", stats.absorbedwrites,
		percent(stats.absorbedwrites, stats.dirtydblocks));

	hprint(hout, "disk cache flushes=%,ld\n", stats.dcacheflushes);
	hprint(hout, "disk cache flush writes=%,ld (%,ld per flush)\n", 
		stats.dcacheflushwrites,
		stats.dcacheflushwrites/(stats.dcacheflushes ? stats.dcacheflushes : 1));

	hprint(hout, "disk writes=%,ld\n", stats.diskwrites);
	hprint(hout, "disk bytes written=%,lld\n", stats.diskbwrites);
	hprint(hout, "disk reads=%,ld\n", stats.diskreads);
	hprint(hout, "disk bytes read=%,lld\n", stats.diskbreads);
*/

	hflush(hout);
	return 0;
}