|
|
1.1 ! root 1: /* ! 2: * face server, library style ! 3: */ ! 4: #include <rf.h> ! 5: #include <ipc.h> ! 6: #include <signal.h> ! 7: #include "faceproto.h" ! 8: ! 9: #define NULL 0 ! 10: char *malloc(); ! 11: ! 12: ! 13: /* ! 14: * ignore permissions from server for now (who cares?) ! 15: * uid, gid always RFNOID ! 16: * permissions always read for everyone ! 17: */ ! 18: #define FPERM ((RFPRD<<RFPOWNER)|(RFPRD<<RFPGROUP)|(RFPRD<<RFPOTHER)) ! 19: #define DPERM (FPERM|(RFPDS<<RFPOWNER)|(RFPDS<<RFPGROUP)|(RFPDS<<RFPOTHER)) ! 20: ! 21: char *server; ! 22: int commfd = -1; ! 23: static int ininit; ! 24: ! 25: #define TIMEOUT (2*60) /* disconnect if idle this long */ ! 26: ! 27: /* ! 28: * init: ! 29: * we have to return something, ! 30: * but the server might not be running when we start ! 31: * so fake up a root for now ! 32: */ ! 33: ! 34: Rfile * ! 35: fsinit(argc, argv) ! 36: int argc; ! 37: char **argv; ! 38: { ! 39: register Rfile *f; ! 40: int timeout(); ! 41: ! 42: if (argc <= 1) ! 43: rfpanic("usage: a.out server\n"); ! 44: server = argv[1]; ! 45: if ((f = (Rfile *)malloc(sizeof(Rfile))) == NULL) ! 46: rfpanic("no mem for root\n"); ! 47: f->fs = "/"; ! 48: f->ino = FROOT; ! 49: f->dev = 0; ! 50: f->type = RFTDIR; ! 51: f->mode = DPERM; ! 52: f->size = 512; /* something nonzero */ ! 53: f->nlink = 1; ! 54: f->ta = f->tm = f->tc = 0; ! 55: signal(SIGALRM, timeout); ! 56: ininit = 1; ! 57: if (fsstat(f) < 0) ! 58: fserrno = 0; /* ignore error, use the fake data */ ! 59: ininit = 0; ! 60: return (f); ! 61: } ! 62: ! 63: timeout(s) ! 64: int s; ! 65: { ! 66: signal(s, timeout); ! 67: if (rfdebug) ! 68: rflog("timeout\n"); ! 69: callshutdown(); ! 70: } ! 71: ! 72: /* ! 73: * cheap hack: ! 74: * if we've already checked the root, ! 75: * short-circuit namei calls for it, ! 76: * so status programs (like netb setup) won't make us ! 77: * keep a circuit open ! 78: */ ! 79: Rfile * ! 80: fswalk(df, name) ! 81: Rfile *df; ! 82: char *name; ! 83: { ! 84: register Rfile *f; ! 85: char stbuf[FMAXDATA]; ! 86: long rcode; ! 87: char *nname; ! 88: ! 89: if (df->ino == FROOT ! 90: && (name[0] == 0 || (name[0] == '.' && name[1] == 0))) ! 91: return (df); ! 92: if (df->ino == FROOT && strcmp(name, "..") == 0) { ! 93: fserrno = 0; ! 94: return (NULL); ! 95: } ! 96: if ((nname = malloc(FMAXPATH)) == NULL) { ! 97: rflog("no mem for name: %s/%s\n", df->fs, name); ! 98: fserrno = RFEINVAL; ! 99: return (NULL); ! 100: } ! 101: strcpy(nname, df->fs); ! 102: strcat(nname, "/"); ! 103: strcat(nname, name); ! 104: if (facecall(nname, DOSTAT, 0L, 0L, stbuf, &rcode) < STLEN) { ! 105: /* call failed or network botch */ ! 106: fserrno = RFEINVAL; ! 107: free(nname); ! 108: return (NULL); ! 109: } ! 110: if (rcode < 0) { ! 111: fserrno = RFENOENT; ! 112: free(nname); ! 113: return (NULL); ! 114: } ! 115: if ((f = (Rfile *)malloc(sizeof(Rfile))) == NULL) { ! 116: rflog("no mem for file: %s\n", nname); ! 117: fserrno = RFEINVAL; ! 118: free(nname); ! 119: return (NULL); ! 120: } ! 121: f->fs = nname; ! 122: stunpack(stbuf, f); ! 123: return (f); ! 124: } ! 125: ! 126: int ! 127: fsput(f) ! 128: Rfile *f; ! 129: { ! 130: free(f->fs); ! 131: free((char *)f); ! 132: return (0); ! 133: } ! 134: ! 135: int ! 136: fsstat(f) ! 137: Rfile *f; ! 138: { ! 139: char stbuf[FMAXDATA]; ! 140: long rcode; ! 141: ! 142: if (f->ino == FROOT && ininit == 0) ! 143: return (0); /* and don't call */ ! 144: if (facecall(f->fs, DOSTAT, 0L, 0L, stbuf, &rcode) < STLEN) { ! 145: fserrno = RFEINVAL; ! 146: return (-1); ! 147: } ! 148: if (rcode < 0) { ! 149: fserrno = RFEINVAL; ! 150: return (-1); ! 151: } ! 152: stunpack(stbuf, f); ! 153: return (0); ! 154: } ! 155: ! 156: /* ! 157: * read directories ! 158: */ ! 159: int ! 160: fsdirread(f, off, buf, len, noffp) ! 161: Rfile *f; ! 162: long off; ! 163: char *buf; ! 164: int len; ! 165: long *noffp; ! 166: { ! 167: char dirbuf[FDLEN*32]; /* some even multiple */ ! 168: char onebuf[FDLEN-FD_NAME + 10]; /* enough for one entry */ ! 169: register unsigned char *dp; ! 170: register int nread, n; ! 171: register char *bp; ! 172: ! 173: if ((off%FDLEN) != 0) { ! 174: rflog("unaligned fsdirread: off %ld\n", off); ! 175: fserrno = RFEINVAL; ! 176: return (-1); ! 177: } ! 178: bp = buf; ! 179: while ((nread = fsread(f, off, dirbuf, sizeof(dirbuf))) > 0) { ! 180: dp = (unsigned char *)dirbuf; ! 181: while (nread >= FDLEN) { ! 182: /* should check ino==0 here */ ! 183: sprintf(onebuf, "%d\t%.*s", frfshort(dp, FD_INO), ! 184: FDLEN - FD_NAME, dp + FD_NAME); ! 185: n = strlen(onebuf)+1; /* including NUL */ ! 186: if ((len -= n) < 0) ! 187: goto out; ! 188: memcpy(bp, onebuf, n); ! 189: bp += n; ! 190: off += FDLEN; ! 191: dp += FDLEN; ! 192: nread -= FDLEN; ! 193: } ! 194: } ! 195: out: ! 196: *noffp = off; ! 197: if (bp != buf) /* if we read anything, return it */ ! 198: return (bp - buf); ! 199: if (len < 0) { /* first entry too large */ ! 200: fserrno = RFENOSPC; ! 201: return (-1); ! 202: } ! 203: return (nread); /* must be 0 or -1 */ ! 204: } ! 205: ! 206: int ! 207: fsread(f, off, buf, len) ! 208: Rfile *f; ! 209: char *buf; ! 210: int len; ! 211: long off; ! 212: { ! 213: char data[FMAXDATA]; ! 214: long rcode; ! 215: ! 216: if (facecall(f->fs, DOREAD, off, (long)len, data, &rcode) < 0) { ! 217: fserrno = RFEINVAL; ! 218: return (-1); ! 219: } ! 220: if (rcode < 0) { ! 221: fserrno = RFEIO; ! 222: return (-1); ! 223: } ! 224: if (rcode > len) ! 225: rfpanic("fsread wanted %d got %ld\n", len, rcode); ! 226: if (rcode) ! 227: memcpy(buf, data, (int)rcode); ! 228: return (rcode); ! 229: } ! 230: ! 231: /* need fsdirread too */ ! 232: ! 233: /* ! 234: * one function call to the server ! 235: * interface is overly general and underused ! 236: * there are a filename, a function code, and two long parameters; ! 237: * some data is returned in result, ! 238: * and a long status code is returned in *codep ! 239: * the function return value is the length of the data; ! 240: * -1 means error ! 241: */ ! 242: int ! 243: facecall(file, func, p1, p2, result, codep) ! 244: char *file; ! 245: int func; ! 246: long p1, p2; ! 247: char *result; ! 248: long *codep; ! 249: { ! 250: register unsigned char *p; ! 251: register char msg[F_DATA+FMAXDATA]; ! 252: int len; ! 253: ! 254: alarm(0); ! 255: if (commfd < 0 && callsetup() < 0) ! 256: return (-1); ! 257: len = strlen(file) + 1; ! 258: if (len > FMAXDATA) ! 259: rfpanic("facecall: name too long\n"); ! 260: p = (unsigned char *)msg; ! 261: p[F_TYPE] = func; ! 262: p[F_TYPE+1] = 0; /* safety for old servers */ ! 263: tofshort(p, F_LEN, len); ! 264: toflong(p, F_P1, p1); ! 265: toflong(p, F_P2, p2); ! 266: memcpy(&p[F_DATA], file, len); ! 267: if (rfdebug) ! 268: rflog("facecall: %s: func %d p %ld %ld\n", file, func, p1, p2); ! 269: if (write(commfd, msg, len+F_DATA) != len+F_DATA) { ! 270: rflog("net write error\n"); ! 271: callshutdown(); ! 272: return (-1); ! 273: } ! 274: if (gread(commfd, msg, F_DATA, F_DATA) != F_DATA) { ! 275: rflog("net read error\n"); ! 276: callshutdown(); ! 277: return (-1); ! 278: } ! 279: len = frfshort(p, F_LEN); ! 280: if (len < 0 || len > FMAXDATA) { ! 281: rflog("net ill len %d\n", len); ! 282: callshutdown(); ! 283: return (-1); ! 284: } ! 285: if (len > 0 && gread(commfd, result, len, len) != len) { ! 286: rflog("net read error (body)\n"); ! 287: callshutdown(); ! 288: return (-1); ! 289: } ! 290: *codep = frflong(p, F_P1); ! 291: if (rfdebug) ! 292: rflog("... len %d p1 %ld\n", len, *codep); ! 293: alarm(TIMEOUT); ! 294: return (len); ! 295: } ! 296: ! 297: /* ! 298: * call server ! 299: */ ! 300: callsetup() ! 301: { ! 302: extern char *errstr; ! 303: ! 304: if (rfdebug) ! 305: rflog("call %s\n", server); ! 306: if ((commfd = ipcopen(ipcpath(server, "", ""), "")) < 0) ! 307: rflog("can't call %s: %s\n", server, errstr); ! 308: return (commfd); ! 309: } ! 310: ! 311: callshutdown() ! 312: { ! 313: close(commfd); ! 314: commfd = -1; ! 315: } ! 316: ! 317: /* ! 318: * unpack stat buffer into a file ! 319: */ ! 320: ! 321: stunpack(buf, f) ! 322: char *buf; ! 323: register Rfile *f; ! 324: { ! 325: register unsigned char *p; ! 326: ! 327: p = (unsigned char *)buf; ! 328: f->ino = frfshort(p, ST_INO); ! 329: f->dev = 0; ! 330: if ((frfshort(p, ST_MODE) & STFMT) == STDIR) { ! 331: f->type = RFTDIR; ! 332: f->mode = DPERM; ! 333: } else { ! 334: f->type = RFTREG; ! 335: f->mode = FPERM; ! 336: } ! 337: f->nlink = frfshort(p, ST_NLINK); ! 338: f->uid = RFNOID; ! 339: f->gid = RFNOID; ! 340: f->size = frflong(p, ST_SIZE); ! 341: f->ta = frflong(p, ST_ATIME); ! 342: f->tm = frflong(p, ST_MTIME); ! 343: f->tc = frflong(p, ST_CTIME); ! 344: } ! 345: ! 346: /* ! 347: * gather data that may come in dribs and drabs: ! 348: * read size bytes into buf, ! 349: * but keep looking until at least minsize have arrived ! 350: */ ! 351: ! 352: int ! 353: gread(fd, buf, size, minsize) ! 354: int fd; ! 355: char *buf; ! 356: int size; ! 357: register int minsize; ! 358: { ! 359: register int n, tot; ! 360: ! 361: tot = 0; ! 362: while (minsize > 0) { ! 363: if ((n = read(fd, buf, size)) <= 0) ! 364: break; ! 365: buf += n; ! 366: size -= n; ! 367: minsize -= n; ! 368: tot += n; ! 369: } ! 370: if (tot) ! 371: return (tot); ! 372: return (n); ! 373: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.