111a9947fSrtm #include "types.h" 21f544842Skaashoek #include "stat.h" 311a9947fSrtm #include "param.h" 411a9947fSrtm #include "x86.h" 511a9947fSrtm #include "mmu.h" 611a9947fSrtm #include "proc.h" 711a9947fSrtm #include "defs.h" 811a9947fSrtm #include "spinlock.h" 911a9947fSrtm #include "buf.h" 1011a9947fSrtm #include "fs.h" 1111a9947fSrtm #include "fsvar.h" 126fa5ffb5Skaashoek #include "dev.h" 1311a9947fSrtm 1411a9947fSrtm // these are inodes currently in use 1511a9947fSrtm // an entry is free if count == 0 1611a9947fSrtm struct inode inode[NINODE]; 175be0039cSrtm struct spinlock inode_table_lock; 1811a9947fSrtm 199d3fb671Srtm uint rootdev = 1; 209d3fb671Srtm 215be0039cSrtm void 225be0039cSrtm iinit(void) 235be0039cSrtm { 245be0039cSrtm initlock(&inode_table_lock, "inode_table"); 255be0039cSrtm } 265be0039cSrtm 2724111398Skaashoek static uint 2824111398Skaashoek balloc(uint dev) 2924111398Skaashoek { 3024111398Skaashoek int b; 3124111398Skaashoek struct buf *bp; 3224111398Skaashoek struct superblock *sb; 3328d9ef04Skaashoek int bi = 0; 3424111398Skaashoek int size; 3524111398Skaashoek int ninodes; 3624111398Skaashoek uchar m; 3724111398Skaashoek 3824111398Skaashoek bp = bread(dev, 1); 3924111398Skaashoek sb = (struct superblock *) bp->data; 4024111398Skaashoek size = sb->size; 4124111398Skaashoek ninodes = sb->ninodes; 4224111398Skaashoek 4324111398Skaashoek for (b = 0; b < size; b++) { 4424111398Skaashoek if (b % BPB == 0) { 4524111398Skaashoek brelse(bp); 4624111398Skaashoek bp = bread(dev, BBLOCK(b, ninodes)); 4724111398Skaashoek } 4824111398Skaashoek bi = b % BPB; 4924111398Skaashoek m = 0x1 << (bi % 8); 5024111398Skaashoek if ((bp->data[bi/8] & m) == 0) { // is block free? 5124111398Skaashoek break; 5224111398Skaashoek } 5324111398Skaashoek } 5424111398Skaashoek if (b >= size) 5524111398Skaashoek panic("balloc: out of blocks\n"); 5624111398Skaashoek 5724111398Skaashoek bp->data[bi/8] |= 0x1 << (bi % 8); 5805e97551Srtm bwrite (bp, BBLOCK(b, ninodes)); // mark it allocated on disk 5928d9ef04Skaashoek brelse(bp); 6024111398Skaashoek return b; 6124111398Skaashoek } 6224111398Skaashoek 6328d9ef04Skaashoek static void 6428d9ef04Skaashoek bfree(int dev, uint b) 6528d9ef04Skaashoek { 6628d9ef04Skaashoek struct buf *bp; 6728d9ef04Skaashoek struct superblock *sb; 6828d9ef04Skaashoek int bi; 6928d9ef04Skaashoek int ninodes; 7028d9ef04Skaashoek uchar m; 7128d9ef04Skaashoek 7228d9ef04Skaashoek bp = bread(dev, 1); 7328d9ef04Skaashoek sb = (struct superblock *) bp->data; 7428d9ef04Skaashoek ninodes = sb->ninodes; 7528d9ef04Skaashoek brelse(bp); 7628d9ef04Skaashoek 77c372e8dcSkaashoek bp = bread(dev, b); 78c372e8dcSkaashoek memset(bp->data, 0, BSIZE); 79c372e8dcSkaashoek bwrite(bp, b); 80c372e8dcSkaashoek brelse(bp); 81c372e8dcSkaashoek 8228d9ef04Skaashoek bp = bread(dev, BBLOCK(b, ninodes)); 8328d9ef04Skaashoek bi = b % BPB; 8428d9ef04Skaashoek m = ~(0x1 << (bi %8)); 8528d9ef04Skaashoek bp->data[bi/8] &= m; 8605e97551Srtm bwrite (bp, BBLOCK(b, ninodes)); // mark it free on disk 8728d9ef04Skaashoek brelse(bp); 8828d9ef04Skaashoek } 8924111398Skaashoek 909d3fb671Srtm // returns an inode with busy set and incremented reference count. 9111a9947fSrtm struct inode * 9211a9947fSrtm iget(uint dev, uint inum) 9311a9947fSrtm { 9417e3cf15Srtm struct inode *ip, *nip; 9511a9947fSrtm struct dinode *dip; 9611a9947fSrtm struct buf *bp; 9711a9947fSrtm 9811a9947fSrtm acquire(&inode_table_lock); 9911a9947fSrtm 10011a9947fSrtm loop: 10117e3cf15Srtm nip = 0; 10211a9947fSrtm for(ip = &inode[0]; ip < &inode[NINODE]; ip++){ 10311a9947fSrtm if(ip->count > 0 && ip->dev == dev && ip->inum == inum){ 10411a9947fSrtm if(ip->busy){ 10511a9947fSrtm sleep(ip, &inode_table_lock); 10611a9947fSrtm goto loop; 10711a9947fSrtm } 10811a9947fSrtm ip->count++; 10917a85657Srtm ip->busy = 1; 11011a9947fSrtm release(&inode_table_lock); 11111a9947fSrtm return ip; 11211a9947fSrtm } 11311a9947fSrtm if(nip == 0 && ip->count == 0) 11411a9947fSrtm nip = ip; 11511a9947fSrtm } 11611a9947fSrtm 11711a9947fSrtm if(nip == 0) 11811a9947fSrtm panic("out of inodes"); 11911a9947fSrtm 12011a9947fSrtm nip->dev = dev; 12111a9947fSrtm nip->inum = inum; 12211a9947fSrtm nip->count = 1; 12311a9947fSrtm nip->busy = 1; 12411a9947fSrtm 12511a9947fSrtm release(&inode_table_lock); 12611a9947fSrtm 12724111398Skaashoek bp = bread(dev, IBLOCK(inum)); 12811a9947fSrtm dip = &((struct dinode *)(bp->data))[inum % IPB]; 12911a9947fSrtm nip->type = dip->type; 130e8d11c2eSkaashoek nip->major = dip->major; 131e8d11c2eSkaashoek nip->minor = dip->minor; 13211a9947fSrtm nip->nlink = dip->nlink; 13311a9947fSrtm nip->size = dip->size; 13411a9947fSrtm memmove(nip->addrs, dip->addrs, sizeof(nip->addrs)); 13511a9947fSrtm brelse(bp); 13611a9947fSrtm 13711a9947fSrtm return nip; 13811a9947fSrtm } 13911a9947fSrtm 14028d9ef04Skaashoek void 14128d9ef04Skaashoek iupdate (struct inode *ip) 14228d9ef04Skaashoek { 14328d9ef04Skaashoek struct buf *bp; 14428d9ef04Skaashoek struct dinode *dip; 14528d9ef04Skaashoek 14628d9ef04Skaashoek bp = bread(ip->dev, IBLOCK(ip->inum)); 14728d9ef04Skaashoek dip = &((struct dinode *)(bp->data))[ip->inum % IPB]; 14828d9ef04Skaashoek dip->type = ip->type; 14928d9ef04Skaashoek dip->major = ip->major; 15028d9ef04Skaashoek dip->minor = ip->minor; 15128d9ef04Skaashoek dip->nlink = ip->nlink; 15228d9ef04Skaashoek dip->size = ip->size; 15328d9ef04Skaashoek memmove(dip->addrs, ip->addrs, sizeof(ip->addrs)); 15405e97551Srtm bwrite (bp, IBLOCK(ip->inum)); // mark it allocated on the disk 15528d9ef04Skaashoek brelse(bp); 15628d9ef04Skaashoek } 15728d9ef04Skaashoek 158e8d11c2eSkaashoek struct inode * 159e8d11c2eSkaashoek ialloc(uint dev, short type) 160e8d11c2eSkaashoek { 161e8d11c2eSkaashoek struct inode *ip; 162e8d11c2eSkaashoek struct dinode *dip = 0; 163e8d11c2eSkaashoek struct superblock *sb; 164e8d11c2eSkaashoek int ninodes; 165e8d11c2eSkaashoek int inum; 166e8d11c2eSkaashoek struct buf *bp; 167e8d11c2eSkaashoek 168e8d11c2eSkaashoek bp = bread(dev, 1); 16924111398Skaashoek sb = (struct superblock *) bp->data; 170e8d11c2eSkaashoek ninodes = sb->ninodes; 171e8d11c2eSkaashoek brelse(bp); 172e8d11c2eSkaashoek 173e8d11c2eSkaashoek for (inum = 1; inum < ninodes; inum++) { // loop over inode blocks 17424111398Skaashoek bp = bread(dev, IBLOCK(inum)); 175e8d11c2eSkaashoek dip = &((struct dinode *)(bp->data))[inum % IPB]; 176e8d11c2eSkaashoek if (dip->type == 0) { // a free inode 177e8d11c2eSkaashoek break; 178e8d11c2eSkaashoek } 179e8d11c2eSkaashoek brelse(bp); 180e8d11c2eSkaashoek } 181e8d11c2eSkaashoek 18217e3cf15Srtm if (inum >= ninodes) 18324111398Skaashoek panic ("ialloc: no inodes left\n"); 184e8d11c2eSkaashoek 185e8d11c2eSkaashoek dip->type = type; 18605e97551Srtm bwrite (bp, IBLOCK(inum)); // mark it allocated on the disk 187e8d11c2eSkaashoek brelse(bp); 188e8d11c2eSkaashoek ip = iget (dev, inum); 189e8d11c2eSkaashoek return ip; 190e8d11c2eSkaashoek } 191e8d11c2eSkaashoek 19228d9ef04Skaashoek static void 19324437cd5Skaashoek ifree(struct inode *ip) 194e8d11c2eSkaashoek { 19528d9ef04Skaashoek ip->type = 0; 19628d9ef04Skaashoek iupdate(ip); 197e8d11c2eSkaashoek } 198e8d11c2eSkaashoek 19911a9947fSrtm void 2009d3fb671Srtm ilock(struct inode *ip) 2019d3fb671Srtm { 2029d3fb671Srtm if(ip->count < 1) 2039d3fb671Srtm panic("ilock"); 2049d3fb671Srtm 2059d3fb671Srtm acquire(&inode_table_lock); 2069d3fb671Srtm 2079d3fb671Srtm while(ip->busy) 2089d3fb671Srtm sleep(ip, &inode_table_lock); 2099d3fb671Srtm ip->busy = 1; 2109d3fb671Srtm 2119d3fb671Srtm release(&inode_table_lock); 2129d3fb671Srtm } 2139d3fb671Srtm 2149d3fb671Srtm // caller is holding onto a reference to this inode, but no 2159d3fb671Srtm // longer needs to examine or change it, so clear ip->busy. 2169d3fb671Srtm void 2179d3fb671Srtm iunlock(struct inode *ip) 2189d3fb671Srtm { 21917e3cf15Srtm if(ip->busy != 1 || ip->count < 1) 2209d3fb671Srtm panic("iunlock"); 2219d3fb671Srtm 2229d3fb671Srtm acquire(&inode_table_lock); 2239d3fb671Srtm 2249d3fb671Srtm ip->busy = 0; 2259d3fb671Srtm wakeup(ip); 2269d3fb671Srtm 2279d3fb671Srtm release(&inode_table_lock); 2289d3fb671Srtm } 2299d3fb671Srtm 23022bac2cbSkaashoek uint 23122bac2cbSkaashoek bmap(struct inode *ip, uint bn) 23222bac2cbSkaashoek { 23322bac2cbSkaashoek unsigned x; 234*ea2909b6Skaashoek uint *a; 235*ea2909b6Skaashoek struct buf *inbp; 23622bac2cbSkaashoek 237*ea2909b6Skaashoek if(bn >= MAXFILE) 23822bac2cbSkaashoek panic("bmap 1"); 239*ea2909b6Skaashoek if (bn < NDIRECT) { 24022bac2cbSkaashoek x = ip->addrs[bn]; 24122bac2cbSkaashoek if (x == 0) 24222bac2cbSkaashoek panic("bmap 2"); 243*ea2909b6Skaashoek } else { 244*ea2909b6Skaashoek cprintf("indirect block read\n"); 245*ea2909b6Skaashoek inbp = bread(ip->dev, INDIRECT); 246*ea2909b6Skaashoek a = (uint *) inbp->data; 247*ea2909b6Skaashoek x = a[bn - NDIRECT]; 248*ea2909b6Skaashoek brelse(inbp); 249*ea2909b6Skaashoek if (x == 0) 250*ea2909b6Skaashoek panic("bmap 3"); 251*ea2909b6Skaashoek } 25222bac2cbSkaashoek return x; 25322bac2cbSkaashoek } 25422bac2cbSkaashoek 25522bac2cbSkaashoek void 25622bac2cbSkaashoek iunlink(struct inode *ip) 25722bac2cbSkaashoek { 258*ea2909b6Skaashoek int i, j; 25922bac2cbSkaashoek 26022bac2cbSkaashoek // free inode, its blocks, and remove dir entry 261*ea2909b6Skaashoek for (i = 0; i < NADDRS; i++) { 26222bac2cbSkaashoek if (ip->addrs[i] != 0) { 263*ea2909b6Skaashoek if (i == INDIRECT) { 264*ea2909b6Skaashoek for (j = 0; j < NINDIRECT; j++) { 265*ea2909b6Skaashoek uint *a = (uint *) (ip->addrs[i]); 266*ea2909b6Skaashoek if (a[j] != 0) { 267*ea2909b6Skaashoek bfree(ip->dev, a[j]); 268*ea2909b6Skaashoek a[j] = 0; 269*ea2909b6Skaashoek } 270*ea2909b6Skaashoek } 271*ea2909b6Skaashoek } 272*ea2909b6Skaashoek else 27322bac2cbSkaashoek bfree(ip->dev, ip->addrs[i]); 27422bac2cbSkaashoek ip->addrs[i] = 0; 27522bac2cbSkaashoek } 27622bac2cbSkaashoek } 27722bac2cbSkaashoek ip->size = 0; 27822bac2cbSkaashoek ip->major = 0; 27922bac2cbSkaashoek ip->minor = 0; 28022bac2cbSkaashoek iupdate(ip); 28122bac2cbSkaashoek ifree(ip); // is this the right order? 28222bac2cbSkaashoek } 28322bac2cbSkaashoek 2849d3fb671Srtm // caller is releasing a reference to this inode. 2859d3fb671Srtm // you must have the inode lock. 2869d3fb671Srtm void 28711a9947fSrtm iput(struct inode *ip) 28811a9947fSrtm { 2899d3fb671Srtm if(ip->count < 1 || ip->busy != 1) 2909d3fb671Srtm panic("iput"); 2919d3fb671Srtm 29217e3cf15Srtm if ((ip->count == 1) && (ip->nlink == 0)) 29322bac2cbSkaashoek iunlink(ip); 29422bac2cbSkaashoek 29511a9947fSrtm acquire(&inode_table_lock); 29611a9947fSrtm 29711a9947fSrtm ip->count -= 1; 29811a9947fSrtm ip->busy = 0; 29911a9947fSrtm wakeup(ip); 30011a9947fSrtm 30111a9947fSrtm release(&inode_table_lock); 30211a9947fSrtm } 3039d3fb671Srtm 3049d3fb671Srtm void 30532630628Srtm idecref(struct inode *ip) 3069d3fb671Srtm { 307211ff0c6Srtm ilock(ip); 308211ff0c6Srtm iput(ip); 3099d3fb671Srtm } 3109d3fb671Srtm 3111f544842Skaashoek void 312e958c538Skaashoek iincref(struct inode *ip) 313e958c538Skaashoek { 314e958c538Skaashoek ilock(ip); 315e958c538Skaashoek ip->count++; 316e958c538Skaashoek iunlock(ip); 317e958c538Skaashoek } 318e958c538Skaashoek 319e958c538Skaashoek void 3201f544842Skaashoek stati(struct inode *ip, struct stat *st) 3211f544842Skaashoek { 3221f544842Skaashoek st->st_dev = ip->dev; 3231f544842Skaashoek st->st_ino = ip->inum; 3241f544842Skaashoek st->st_type = ip->type; 3251f544842Skaashoek st->st_nlink = ip->nlink; 3261f544842Skaashoek st->st_size = ip->size; 3271f544842Skaashoek } 3281f544842Skaashoek 32922bac2cbSkaashoek #define min(a, b) ((a) < (b) ? (a) : (b)) 33022bac2cbSkaashoek 331c59361f1Srtm int 33217a85657Srtm readi(struct inode *ip, char *dst, uint off, uint n) 333c59361f1Srtm { 334c59361f1Srtm uint target = n, n1; 335c59361f1Srtm struct buf *bp; 336c59361f1Srtm 337939f9edeSkaashoek if (ip->type == T_DEV) { 338939f9edeSkaashoek if (ip->major < 0 || ip->major >= NDEV || !devsw[ip->major].d_read) 339939f9edeSkaashoek return -1; 34017a85657Srtm return devsw[ip->major].d_read (ip->minor, dst, n); 341939f9edeSkaashoek } 342939f9edeSkaashoek 343c59361f1Srtm while(n > 0 && off < ip->size){ 34424111398Skaashoek bp = bread(ip->dev, bmap(ip, off / BSIZE)); 345c59361f1Srtm n1 = min(n, ip->size - off); 34624111398Skaashoek n1 = min(n1, BSIZE - (off % BSIZE)); 34724111398Skaashoek memmove(dst, bp->data + (off % BSIZE), n1); 348c59361f1Srtm n -= n1; 349c59361f1Srtm off += n1; 350c59361f1Srtm dst += n1; 351c59361f1Srtm brelse(bp); 352c59361f1Srtm } 353c59361f1Srtm 354c59361f1Srtm return target - n; 355c59361f1Srtm } 356c59361f1Srtm 3576fa5ffb5Skaashoek int 358*ea2909b6Skaashoek newblock(struct inode *ip, uint lbn) 359*ea2909b6Skaashoek { 360*ea2909b6Skaashoek struct buf *inbp; 361*ea2909b6Skaashoek uint *inaddrs; 362*ea2909b6Skaashoek uint b; 363*ea2909b6Skaashoek 364*ea2909b6Skaashoek if (lbn < NDIRECT) { 365*ea2909b6Skaashoek if (ip->addrs[lbn] == 0) { 366*ea2909b6Skaashoek b = balloc(ip->dev); 367*ea2909b6Skaashoek if (b <= 0) return -1; 368*ea2909b6Skaashoek ip->addrs[lbn] = b; 369*ea2909b6Skaashoek } 370*ea2909b6Skaashoek } else { 371*ea2909b6Skaashoek cprintf("newblock: use indirect block\n"); 372*ea2909b6Skaashoek if (ip->addrs[INDIRECT] == 0) { 373*ea2909b6Skaashoek cprintf("newblock: allocate indirect block\n"); 374*ea2909b6Skaashoek b = balloc(ip->dev); 375*ea2909b6Skaashoek if (b <= 0) return -1; 376*ea2909b6Skaashoek ip->addrs[INDIRECT] = b; 377*ea2909b6Skaashoek } 378*ea2909b6Skaashoek inbp = bread(ip->dev, bmap(ip, INDIRECT)); 379*ea2909b6Skaashoek inaddrs = (uint *) inbp->data; 380*ea2909b6Skaashoek if (inaddrs[lbn - NDIRECT] == 0) { 381*ea2909b6Skaashoek b = balloc(ip->dev); 382*ea2909b6Skaashoek if (b <= 0) return -1; 383*ea2909b6Skaashoek inaddrs[lbn - NDIRECT] = b; 384*ea2909b6Skaashoek bwrite(inbp, INDIRECT); 385*ea2909b6Skaashoek } 386*ea2909b6Skaashoek brelse(inbp); 387*ea2909b6Skaashoek } 388*ea2909b6Skaashoek return 0; 389*ea2909b6Skaashoek } 390*ea2909b6Skaashoek 391*ea2909b6Skaashoek int 39217a85657Srtm writei(struct inode *ip, char *addr, uint off, uint n) 3936fa5ffb5Skaashoek { 3946fa5ffb5Skaashoek if (ip->type == T_DEV) { 395939f9edeSkaashoek if (ip->major < 0 || ip->major >= NDEV || !devsw[ip->major].d_write) 396939f9edeSkaashoek return -1; 3976fa5ffb5Skaashoek return devsw[ip->major].d_write (ip->minor, addr, n); 398*ea2909b6Skaashoek } else if (ip->type == T_FILE || ip->type == T_DIR) { 39928d9ef04Skaashoek struct buf *bp; 40028d9ef04Skaashoek int r = 0; 40128d9ef04Skaashoek int m; 40228d9ef04Skaashoek int lbn; 40328d9ef04Skaashoek while (r < n) { 40428d9ef04Skaashoek lbn = off / BSIZE; 405*ea2909b6Skaashoek if (lbn >= MAXFILE) return r; 406*ea2909b6Skaashoek if (newblock(ip, lbn) < 0) { 407*ea2909b6Skaashoek cprintf("newblock failed\n"); 408*ea2909b6Skaashoek return r; 40928d9ef04Skaashoek } 41022bac2cbSkaashoek m = min(BSIZE - off % BSIZE, n-r); 411*ea2909b6Skaashoek bp = bread(ip->dev, bmap(ip, lbn)); 41228d9ef04Skaashoek memmove (bp->data + off % BSIZE, addr, m); 413*ea2909b6Skaashoek bwrite (bp, bmap(ip, lbn)); 41428d9ef04Skaashoek brelse (bp); 41528d9ef04Skaashoek r += m; 41628d9ef04Skaashoek off += m; 41728d9ef04Skaashoek } 41828d9ef04Skaashoek if (r > 0) { 41928d9ef04Skaashoek if (off > ip->size) { 420bdb66433Skaashoek if (ip->type == T_DIR) ip->size = ((off / BSIZE) + 1) * BSIZE; 421bdb66433Skaashoek else ip->size = off; 42228d9ef04Skaashoek } 42328d9ef04Skaashoek iupdate(ip); 42428d9ef04Skaashoek } 42528d9ef04Skaashoek return r; 4266fa5ffb5Skaashoek } else { 4276fa5ffb5Skaashoek panic ("writei: unknown type\n"); 4288a8be1b8Srtm return 0; 4296fa5ffb5Skaashoek } 4306fa5ffb5Skaashoek } 4316fa5ffb5Skaashoek 432211ff0c6Srtm // look up a path name, in one of three modes. 433211ff0c6Srtm // NAMEI_LOOKUP: return locked target inode. 434211ff0c6Srtm // NAMEI_CREATE: return locked parent inode. 435211ff0c6Srtm // but return 0 if name does exist. 436211ff0c6Srtm // NAMEI_DELETE: return locked parent inode, offset of dirent in *ret_off. 437211ff0c6Srtm // return 0 if name doesn't exist. 4389d3fb671Srtm struct inode * 439211ff0c6Srtm namei(char *path, int mode, uint *ret_off) 4409d3fb671Srtm { 4419d3fb671Srtm struct inode *dp; 4428787cd01Skaashoek struct proc *p = curproc[cpu()]; 443211ff0c6Srtm char *cp = path, *cp1; 4449d3fb671Srtm uint off, dev; 4459d3fb671Srtm struct buf *bp; 4469d3fb671Srtm struct dirent *ep; 447211ff0c6Srtm int i, atend; 4489d3fb671Srtm unsigned ninum; 4499d3fb671Srtm 4508787cd01Skaashoek if (*cp == '/') dp = iget(rootdev, 1); 4518787cd01Skaashoek else { 4528787cd01Skaashoek dp = p->cwd; 4538787cd01Skaashoek iincref(dp); 4548787cd01Skaashoek ilock(dp); 4558787cd01Skaashoek } 4569d3fb671Srtm 4579d3fb671Srtm while(*cp == '/') 4589d3fb671Srtm cp++; 4599d3fb671Srtm 4609d3fb671Srtm while(1){ 4610633b971Skaashoek if(*cp == '\0'){ 462211ff0c6Srtm if(mode == NAMEI_LOOKUP) 4639d3fb671Srtm return dp; 464211ff0c6Srtm iput(dp); 465211ff0c6Srtm return 0; 4660633b971Skaashoek } 4679d3fb671Srtm 4689d3fb671Srtm if(dp->type != T_DIR){ 4699d3fb671Srtm iput(dp); 4709d3fb671Srtm return 0; 4719d3fb671Srtm } 4729d3fb671Srtm 47324111398Skaashoek for(off = 0; off < dp->size; off += BSIZE){ 47424111398Skaashoek bp = bread(dp->dev, bmap(dp, off / BSIZE)); 4759d3fb671Srtm for(ep = (struct dirent *) bp->data; 47624111398Skaashoek ep < (struct dirent *) (bp->data + BSIZE); 4779d3fb671Srtm ep++){ 4789d3fb671Srtm if(ep->inum == 0) 4799d3fb671Srtm continue; 4809d3fb671Srtm for(i = 0; i < DIRSIZ && cp[i] != '/' && cp[i]; i++) 4819d3fb671Srtm if(cp[i] != ep->name[i]) 4829d3fb671Srtm break; 4839d3fb671Srtm if((cp[i] == '\0' || cp[i] == '/') && (i >= DIRSIZ || ep->name[i] == '\0')){ 484211ff0c6Srtm off += (uchar*)ep - bp->data; 4859d3fb671Srtm ninum = ep->inum; 4869d3fb671Srtm brelse(bp); 4879d3fb671Srtm cp += i; 4889d3fb671Srtm goto found; 4899d3fb671Srtm } 4909d3fb671Srtm } 4919d3fb671Srtm brelse(bp); 4929d3fb671Srtm } 493211ff0c6Srtm atend = 1; 494211ff0c6Srtm for(cp1 = cp; *cp1; cp1++) 495211ff0c6Srtm if(*cp1 == '/') 496211ff0c6Srtm atend = 0; 497211ff0c6Srtm if(mode == NAMEI_CREATE && atend) 498211ff0c6Srtm return dp; 499211ff0c6Srtm 5009d3fb671Srtm iput(dp); 5019d3fb671Srtm return 0; 5029d3fb671Srtm 5039d3fb671Srtm found: 504211ff0c6Srtm if(mode == NAMEI_DELETE && *cp == '\0'){ 505211ff0c6Srtm *ret_off = off; 506211ff0c6Srtm return dp; 507211ff0c6Srtm } 5089d3fb671Srtm dev = dp->dev; 5099d3fb671Srtm iput(dp); 5109d3fb671Srtm dp = iget(dev, ninum); 5117ce01cf9Srtm if(dp->type == 0 || dp->nlink < 1) 5127ce01cf9Srtm panic("namei"); 5139d3fb671Srtm while(*cp == '/') 5149d3fb671Srtm cp++; 5159d3fb671Srtm } 5169d3fb671Srtm } 517e8d11c2eSkaashoek 5189e5970d5Srtm void 5199e5970d5Srtm wdir(struct inode *dp, char *name, uint ino) 5209e5970d5Srtm { 5219e5970d5Srtm uint off; 522e4bcd2a3Srtm struct dirent de; 5239e5970d5Srtm int i; 5249e5970d5Srtm 525e4bcd2a3Srtm for(off = 0; off < dp->size; off += sizeof(de)){ 526e4bcd2a3Srtm if(readi(dp, (char *) &de, off, sizeof(de)) != sizeof(de)) 527e4bcd2a3Srtm panic("wdir read"); 528e4bcd2a3Srtm if(de.inum == 0) 529e4bcd2a3Srtm break; 530e4bcd2a3Srtm } 531211ff0c6Srtm 532e4bcd2a3Srtm de.inum = ino; 5339e5970d5Srtm for(i = 0; i < DIRSIZ && name[i]; i++) 534e4bcd2a3Srtm de.name[i] = name[i]; 5359e5970d5Srtm for( ; i < DIRSIZ; i++) 536e4bcd2a3Srtm de.name[i] = '\0'; 537e4bcd2a3Srtm 538e4bcd2a3Srtm if(writei(dp, (char *) &de, off, sizeof(de)) != sizeof(de)) 539e4bcd2a3Srtm panic("wdir write"); 5409e5970d5Srtm } 5419e5970d5Srtm 542e8d11c2eSkaashoek struct inode * 5430633b971Skaashoek mknod(char *cp, short type, short major, short minor) 544e8d11c2eSkaashoek { 5450633b971Skaashoek struct inode *ip, *dp; 546e8d11c2eSkaashoek 547211ff0c6Srtm if ((dp = namei(cp, NAMEI_CREATE, 0)) == 0) 5480633b971Skaashoek return 0; 549211ff0c6Srtm 550e8d11c2eSkaashoek ip = ialloc(dp->dev, type); 5510633b971Skaashoek if (ip == 0) { 5520633b971Skaashoek iput(dp); 5530633b971Skaashoek return 0; 5540633b971Skaashoek } 555e8d11c2eSkaashoek ip->major = major; 556e8d11c2eSkaashoek ip->minor = minor; 5576c0e444fSkaashoek ip->size = 0; 5587ce01cf9Srtm ip->nlink = 1; 5596c0e444fSkaashoek 5606c0e444fSkaashoek iupdate (ip); // write new inode to disk 561e8d11c2eSkaashoek 5629e5970d5Srtm wdir(dp, cp, ip->inum); 5630633b971Skaashoek iput(dp); 564e8d11c2eSkaashoek return ip; 565e8d11c2eSkaashoek } 56624437cd5Skaashoek 56724437cd5Skaashoek int 56824437cd5Skaashoek unlink(char *cp) 56924437cd5Skaashoek { 570211ff0c6Srtm struct inode *ip, *dp; 571211ff0c6Srtm struct dirent de; 57217e3cf15Srtm uint off, inum, dev; 57324437cd5Skaashoek 57417e3cf15Srtm if ((dp = namei(cp, NAMEI_DELETE, &off)) == 0) 57524437cd5Skaashoek return -1; 57624437cd5Skaashoek 57717e3cf15Srtm dev = dp->dev; 57817e3cf15Srtm 57917e3cf15Srtm if(readi(dp, (char*)&de, off, sizeof(de)) != sizeof(de) || de.inum == 0) 580211ff0c6Srtm panic("unlink no entry"); 58117e3cf15Srtm 582211ff0c6Srtm inum = de.inum; 58324437cd5Skaashoek 584211ff0c6Srtm memset(&de, 0, sizeof(de)); 585211ff0c6Srtm if(writei(dp, (char*)&de, off, sizeof(de)) != sizeof(de)) 586211ff0c6Srtm panic("unlink dir write"); 58724437cd5Skaashoek 58824437cd5Skaashoek iupdate(dp); 58924437cd5Skaashoek iput(dp); 590211ff0c6Srtm 59117e3cf15Srtm ip = iget(dev, inum); 592211ff0c6Srtm 593211ff0c6Srtm ip->nlink--; 594211ff0c6Srtm 595211ff0c6Srtm iupdate(ip); 59622bac2cbSkaashoek iput(ip); 597211ff0c6Srtm 59824437cd5Skaashoek return 0; 59924437cd5Skaashoek } 6009e5970d5Srtm 6019e5970d5Srtm int 6029e5970d5Srtm link(char *name1, char *name2) 6039e5970d5Srtm { 604211ff0c6Srtm struct inode *ip, *dp; 6059e5970d5Srtm 60617e3cf15Srtm if ((ip = namei(name1, NAMEI_LOOKUP, 0)) == 0) 6079e5970d5Srtm return -1; 608211ff0c6Srtm if(ip->type == T_DIR){ 609211ff0c6Srtm iput(ip); 610211ff0c6Srtm return -1; 611211ff0c6Srtm } 6129e5970d5Srtm 613211ff0c6Srtm iunlock(ip); 614211ff0c6Srtm 615211ff0c6Srtm if ((dp = namei(name2, NAMEI_CREATE, 0)) == 0) { 616211ff0c6Srtm idecref(ip); 617211ff0c6Srtm return -1; 618211ff0c6Srtm } 619211ff0c6Srtm if(dp->dev != ip->dev){ 620211ff0c6Srtm idecref(ip); 621211ff0c6Srtm iput(dp); 622211ff0c6Srtm return -1; 623211ff0c6Srtm } 624211ff0c6Srtm 625211ff0c6Srtm ilock(ip); 6269e5970d5Srtm ip->nlink += 1; 6279e5970d5Srtm iupdate (ip); 6289e5970d5Srtm 6299e5970d5Srtm wdir(dp, name2, ip->inum); 6309e5970d5Srtm iput(dp); 6319e5970d5Srtm iput(ip); 6329e5970d5Srtm 6339e5970d5Srtm return 0; 6349e5970d5Srtm } 635