2 * for GET or POST to /magic/save/foo.
3 * add incoming data to foo.data.
4 * send foo.html as reply.
6 * supports foo.data with "exclusive use" mode to prevent interleaved saves.
7 * thus http://cm.bell-labs.com/magic/save/t?args should access:
8 * -lrw-rw--w- M 21470 ehg web 1533 May 21 18:19 /usr/web/save/t.data
9 * --rw-rw-r-- M 21470 ehg web 73 May 21 18:17 /usr/web/save/t.html
19 MaxLog = 24*1024, /* limit on length of any one log request */
20 LockSecs = MaxLog/500, /* seconds to wait before giving up on opening the data file */
30 * This check shouldn't be needed;
31 * filename folding is already supposed to have happened.
34 while(s = strchr(s,'/')){
35 if(s[1]=='.' && s[2]=='.')
43 * open a file which might be locked.
44 * if it is, spin until available
47 openLocked(char *file, int mode)
52 for(tries = 0; tries < LockSecs*2; tries++){
53 fd = open(file, mode);
56 errstr(buf, sizeof buf);
57 if(strstr(buf, "locked") == nil)
65 main(int argc, char **argv)
71 int n, nfn, datafd, htmlfd;
75 if(dangerous(c->req.uri)){
80 if(hparseheaders(c, HSTIMEOUT) < 0)
83 if(c->head.expectother){
84 hfail(c, HExpectFail, nil);
87 if(c->head.expectcont){
88 hprint(hout, "100 Continue\r\n");
94 if(strcmp(c->req.meth, "POST") == 0){
95 hin = hbodypush(&c->hin, c->head.contlen, c->head.transenc);
98 s = hreadbuf(hin, hin->pos);
102 hfail(c, HBadReq, nil);
108 }else if(strcmp(c->req.meth, "GET") != 0 && strcmp(c->req.meth, "HEAD") != 0){
109 hunallowed(c, "GET, HEAD, PUT");
114 hfail(c, HNoData, "save");
118 if(strlen(s) > MaxLog)
120 n = snprint(c->xferbuf, HBufSize, "at %ld %s\n", time(0), s);
123 nfn = strlen(c->req.uri) + 64;
127 * open file descriptors & write log line
129 snprint(fn, nfn, "/usr/web/save/%s.html", c->req.uri);
130 htmlfd = open(fn, OREAD);
131 if(htmlfd < 0 || (dir = dirfstat(htmlfd)) == nil){
132 hfail(c, HNotFound, c->req.uri);
137 snprint(fn, nfn, "/usr/web/save/%s.data", c->req.uri);
138 datafd = openLocked(fn, OWRITE);
140 errstr(c->xferbuf, sizeof c->xferbuf);
141 if(strstr(c->xferbuf, "locked") != nil)
142 hfail(c, HTempFail, c->req.uri);
144 hfail(c, HNotFound, c->req.uri);
148 write(datafd, c->xferbuf, n);
151 sendfd(c, htmlfd, dir, hmkcontent(c, "text", "html", nil), nil);