|
|
1.1 ! root 1: /* ! 2: * files-11 subroutines, ! 3: * mostly concerned directly with ! 4: * filesystem structures ! 5: */ ! 6: ! 7: #include <time.h> ! 8: #include <ctype.h> ! 9: #include <rf.h> ! 10: #include "files11.h" ! 11: #include "f11.h" ! 12: ! 13: #define NULL 0 ! 14: ! 15: /* ! 16: * convert files-11 ascii time to unix binary time ! 17: * 13 bytes: DDMMMYYhhmmss ! 18: */ ! 19: ! 20: static char *months[] = { ! 21: "JAN", "FEB", "MAR", "APR", "MAY", "JUN", ! 22: "JUL", "AUG", "SEP", "OCT", "NOV", "DEC", 0 ! 23: }; ! 24: ! 25: static int i2val(); ! 26: ! 27: long ! 28: htoutime(ht) ! 29: register char *ht; ! 30: { ! 31: struct tm tm; ! 32: register int mon; ! 33: ! 34: if (*ht == 0) ! 35: return (0); ! 36: tm.tm_yday = 0; ! 37: tm.tm_mday = i2val(ht); ! 38: ht += 2; ! 39: for (mon = 0; months[mon]; mon++) ! 40: if (strncmp(ht, months[mon], 3) == 0) ! 41: break; ! 42: tm.tm_mon = mon; ! 43: ht += 3; ! 44: tm.tm_year = i2val(ht); ! 45: ht += 2; ! 46: tm.tm_hour = i2val(ht); ! 47: ht += 2; ! 48: tm.tm_min = i2val(ht); ! 49: ht += 2; ! 50: tm.tm_sec = i2val(ht); ! 51: return (timelocal(&tm, (char *)NULL)); ! 52: } ! 53: ! 54: static int ! 55: i2val(s) ! 56: register char *s; ! 57: { ! 58: if (!isdigit(s[0]) || !isdigit(s[1])) ! 59: return (0); ! 60: return ((s[0]-'0') * 10 + (s[1]-'0')); ! 61: } ! 62: ! 63: /* ! 64: * convert f11 protection to unix permissions ! 65: * information is lost, most importantly the delete flag ! 66: */ ! 67: int ! 68: htouperm(hp) ! 69: register int hp; ! 70: { ! 71: register int up; ! 72: register int i; ! 73: ! 74: hp >>= 4; /* discard `system' field */ ! 75: up = 0; ! 76: for (i = 0; i < 3; i++) { /* and do owner, group, world */ ! 77: up <<= 3; ! 78: if ((hp & 1) == 0) /* read */ ! 79: up |= 4; ! 80: if ((hp & 2) == 0) /* write */ ! 81: up |= 2; ! 82: if ((hp & 4) == 0) /* execute */ ! 83: up |= 1; ! 84: hp >>= 4; ! 85: } ! 86: return (up); ! 87: } ! 88: ! 89: /* ! 90: * compute the file size ! 91: * use the FCS attributes if they look valid, ! 92: * else just count the blocks ! 93: */ ! 94: ! 95: long ! 96: hfilesize(h) ! 97: register struct header *h; ! 98: { ! 99: register int i; ! 100: register long sz; ! 101: register Bmap *bp; ! 102: ! 103: if (h->h_fcs.f_rtyp != 0) { ! 104: sz = plong(h->h_fcs.f_efbk) - 1; ! 105: sz *= BLKSIZ; ! 106: sz += h->h_fcs.f_ffby; ! 107: return (sz); ! 108: } ! 109: for (sz = 0, i = 0; bp = getmap(&h->h_map, i); i++) ! 110: sz += bp->count; ! 111: return (sz * BLKSIZ); ! 112: } ! 113: ! 114: /* ! 115: * search a directory ! 116: * return the file id ! 117: */ ! 118: ! 119: int ! 120: f11walk(df, name) ! 121: Rfile *df; ! 122: char *name; ! 123: { ! 124: struct filnam fn; ! 125: register struct directory *dp; ! 126: register struct filnam *fp; ! 127: register unsigned short bestfid, bestver; ! 128: char buf[BLKSIZ]; ! 129: long bno; ! 130: ! 131: if (utohname(name, &fn) == 0) { ! 132: fserrno = RFEINVAL; ! 133: return (0); ! 134: } ! 135: bestfid = 0; ! 136: bestver = 0; ! 137: fp = &fn; ! 138: for (bno = 0; f11rblk(df, bno, buf) > 0; bno++) { ! 139: dp = (struct directory *)buf; ! 140: for (; dp < (struct directory *)&buf[BLKSIZ]; dp++) { ! 141: if (dp->d_fid.f_num == 0) ! 142: continue; ! 143: if (dp->d_fname.f_nam[0] != fp->f_nam[0] ! 144: || dp->d_fname.f_nam[1] != fp->f_nam[1] ! 145: || dp->d_fname.f_nam[2] != fp->f_nam[2] ! 146: || dp->d_fname.f_typ != fp->f_typ) ! 147: continue; ! 148: if (dp->d_fname.f_ver == fp->f_ver) ! 149: return (dp->d_fid.f_num); /* exact match */ ! 150: if (fp->f_ver) ! 151: continue; /* exact wanted */ ! 152: if (dp->d_fname.f_ver > bestver) { ! 153: bestver = dp->d_fname.f_ver; ! 154: bestfid = dp->d_fid.f_num; ! 155: } ! 156: } ! 157: } ! 158: if (bestfid == 0) ! 159: fserrno = RFENOENT; ! 160: return (bestfid); ! 161: } ! 162: ! 163: /* ! 164: * convert an ascii filename into a files-11 one ! 165: * unspecified parts are left 0 ! 166: * returns 0 for bad filename, 1 for ok ! 167: */ ! 168: ! 169: int ! 170: utohname(name, f) ! 171: char *name; ! 172: register struct filnam *f; ! 173: { ! 174: char *n; ! 175: register char *e; ! 176: register int i; ! 177: register int x; ! 178: ! 179: f->f_nam[0] = f->f_nam[1] = f->f_nam[2] = 0; ! 180: f->f_typ = 0; ! 181: f->f_ver = 0; ! 182: n = name; ! 183: for (e = n; *e && *e != '.'; e++) ! 184: ; ! 185: if (e - n > 9) ! 186: return (0); ! 187: if (*e) ! 188: *e++ = 0; ! 189: for (i = 0; i < 3; i++) { ! 190: if ((x = ator50(&n)) < 0) ! 191: return (0); ! 192: f->f_nam[i] = x; ! 193: } ! 194: n = e; ! 195: for (; *e && *e != '.'; e++) ! 196: ; ! 197: if (e - n > 3) ! 198: return (0); ! 199: if (*e) ! 200: *e++ = 0; ! 201: if ((x = ator50(&n)) < 0) ! 202: return (0); ! 203: f->f_typ = x; ! 204: if (*e) { ! 205: x = atoi(e); ! 206: if (x < 0 || x > 65535) ! 207: return (0); ! 208: f->f_ver = x; ! 209: } ! 210: return (1); ! 211: } ! 212: ! 213: /* ! 214: * read a block from a file ! 215: */ ! 216: int ! 217: f11rblk(f, bno, buf) ! 218: Rfile *f; ! 219: long bno; ! 220: char *buf; ! 221: { ! 222: register Bmap *bp; ! 223: ! 224: if ((bp = getblk(fsp(f), bno)) == NULL) ! 225: return (0); ! 226: lseek(diskfd, (long)bp->bno * BLKSIZ, 0); ! 227: if (read(diskfd, buf, BLKSIZ) != BLKSIZ) ! 228: return (-1); ! 229: return (1); ! 230: } ! 231: ! 232: /* ! 233: * get the header for a file ! 234: */ ! 235: ! 236: int ! 237: gethdr(fid, hp) ! 238: unsigned short fid; ! 239: struct header *hp; ! 240: { ! 241: long bno; ! 242: register Bmap *bp; ! 243: ! 244: bno = IBITMAP + home.H_ibsz + fidtob(fid); ! 245: if ((bp = getblk(&indexf, bno)) == NULL) ! 246: return (0); ! 247: lseek(diskfd, (long)bp->bno * BLKSIZ, 0); ! 248: if (read(diskfd, (char *)hp, sizeof(*hp)) != sizeof(*hp)) ! 249: return (0); ! 250: if (hp->h_fnum != fid) ! 251: fprint(2, "gethdr: wanted fid %d, got %d\n", fid, hp->h_fnum); ! 252: return (1); ! 253: } ! 254: ! 255: /* ! 256: * get the map for a chunk of a file, ! 257: * starting at block bno ! 258: */ ! 259: ! 260: Bmap * ! 261: getblk(fsf, bno) ! 262: register Fsfile *fsf; ! 263: long bno; ! 264: { ! 265: static Bmap b; ! 266: long offset; ! 267: int mi; ! 268: long mbno; ! 269: register Bmap *bp; ! 270: ! 271: offset = bno - fsf->lbase; ! 272: if (offset > 0 && offset < fsf->lmap.count) { /* within cached map */ ! 273: b.count = fsf->lmap.count - offset; ! 274: b.bno = fsf->lmap.bno + offset; ! 275: return (&b); ! 276: } ! 277: if (offset > 0) { ! 278: mi = fsf->lmi + 1; ! 279: mbno = fsf->lbase + fsf->lmap.count; ! 280: } else { ! 281: mi = 0; ! 282: mbno = 0; ! 283: } ! 284: while ((bp = getmap(&fsf->h.h_map, mi)) != NULL) { ! 285: if (mbno + bp->count < bno) { ! 286: mbno += bp->count; ! 287: mi++; ! 288: continue; ! 289: } ! 290: fsf->lbase = mbno; ! 291: fsf->lmi = mi; ! 292: fsf->lmap = *bp; ! 293: offset = bno - mbno; ! 294: b.count = bp->count - offset; ! 295: b.bno = bp->bno + offset; ! 296: return (&b); ! 297: } ! 298: return (NULL); ! 299: } ! 300: ! 301: /* ! 302: * fetch the n'th retrieval pointer from a map ! 303: * no hope for extended headers yet ! 304: */ ! 305: ! 306: #define RS(c, l) ((c << 8)|l) ! 307: ! 308: Bmap * ! 309: getmap(m, n) ! 310: register struct map *m; ! 311: int n; ! 312: { ! 313: static Bmap b; ! 314: register unsigned char *p; ! 315: register int off; ! 316: ! 317: off = m->m_ctsz + m->m_lbsz; ! 318: off *= n; ! 319: if (off >= m->m_use * sizeof(short)) ! 320: return (NULL); ! 321: p = m->m_rtrvp + off; ! 322: switch (RS(m->m_ctsz, m->m_lbsz)) { ! 323: case RS(1, 3): ! 324: b.count = p[1]; ! 325: b.bno = (p[0]<<24) | p[2] | (p[3]<<8); ! 326: break; ! 327: ! 328: case RS(2, 2): ! 329: b.count = p[0] | (p[1]<<8); ! 330: b.bno = p[2] | (p[3]<<8); ! 331: break; ! 332: ! 333: case RS(2, 4): ! 334: b.count = p[0] | (p[1]<<8); ! 335: b.bno = (p[3]<<16) | (p[4]<<24) | p[4] | (p[5]<<8); ! 336: break; ! 337: ! 338: default: ! 339: return (NULL); ! 340: } ! 341: b.count++; ! 342: return (&b); ! 343: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.