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 27f5527388Srsc // Allocate a disk block. 2824111398Skaashoek static uint 2924111398Skaashoek balloc(uint dev) 3024111398Skaashoek { 3124111398Skaashoek int b; 3224111398Skaashoek struct buf *bp; 3324111398Skaashoek struct superblock *sb; 3428d9ef04Skaashoek int bi = 0; 3524111398Skaashoek int size; 3624111398Skaashoek int ninodes; 3724111398Skaashoek uchar m; 3824111398Skaashoek 3924111398Skaashoek bp = bread(dev, 1); 4024111398Skaashoek sb = (struct superblock*) bp->data; 4124111398Skaashoek size = sb->size; 4224111398Skaashoek ninodes = sb->ninodes; 4324111398Skaashoek 4424111398Skaashoek for(b = 0; b < size; b++) { 4524111398Skaashoek if(b % BPB == 0) { 4624111398Skaashoek brelse(bp); 4724111398Skaashoek bp = bread(dev, BBLOCK(b, ninodes)); 4824111398Skaashoek } 4924111398Skaashoek bi = b % BPB; 5024111398Skaashoek m = 0x1 << (bi % 8); 5124111398Skaashoek if((bp->data[bi/8] & m) == 0) { // is block free? 5224111398Skaashoek break; 5324111398Skaashoek } 5424111398Skaashoek } 5524111398Skaashoek if(b >= size) 562aa4c3bcSrtm panic("balloc: out of blocks"); 5724111398Skaashoek 5824111398Skaashoek bp->data[bi/8] |= 0x1 << (bi % 8); 5905e97551Srtm bwrite(bp, BBLOCK(b, ninodes)); // mark it allocated on disk 6028d9ef04Skaashoek brelse(bp); 6124111398Skaashoek return b; 6224111398Skaashoek } 6324111398Skaashoek 6428d9ef04Skaashoek static void 6528d9ef04Skaashoek bfree(int dev, uint b) 6628d9ef04Skaashoek { 6728d9ef04Skaashoek struct buf *bp; 6828d9ef04Skaashoek struct superblock *sb; 6928d9ef04Skaashoek int bi; 7028d9ef04Skaashoek int ninodes; 7128d9ef04Skaashoek uchar m; 7228d9ef04Skaashoek 7328d9ef04Skaashoek bp = bread(dev, 1); 7428d9ef04Skaashoek sb = (struct superblock*) bp->data; 7528d9ef04Skaashoek ninodes = sb->ninodes; 7628d9ef04Skaashoek brelse(bp); 7728d9ef04Skaashoek 78c372e8dcSkaashoek bp = bread(dev, b); 79c372e8dcSkaashoek memset(bp->data, 0, BSIZE); 80c372e8dcSkaashoek bwrite(bp, b); 81c372e8dcSkaashoek brelse(bp); 82c372e8dcSkaashoek 8328d9ef04Skaashoek bp = bread(dev, BBLOCK(b, ninodes)); 8428d9ef04Skaashoek bi = b % BPB; 8528d9ef04Skaashoek m = ~(0x1 << (bi %8)); 8628d9ef04Skaashoek bp->data[bi/8] &= m; 8705e97551Srtm bwrite(bp, BBLOCK(b, ninodes)); // mark it free on disk 8828d9ef04Skaashoek brelse(bp); 8928d9ef04Skaashoek } 9024111398Skaashoek 91f5527388Srsc // Find the inode with number inum on device dev 92f5527388Srsc // and return an in-memory copy. Loads the inode 93f5527388Srsc // from disk into the in-core table if necessary. 94f5527388Srsc // The returned inode has busy set and has its ref count incremented. 95f5527388Srsc // Caller must iput the return value when done with it. 9611a9947fSrtm struct inode* 9711a9947fSrtm iget(uint dev, uint inum) 9811a9947fSrtm { 9917e3cf15Srtm struct inode *ip, *nip; 10011a9947fSrtm struct dinode *dip; 10111a9947fSrtm struct buf *bp; 10211a9947fSrtm 10311a9947fSrtm acquire(&inode_table_lock); 10411a9947fSrtm 10511a9947fSrtm loop: 10617e3cf15Srtm nip = 0; 10711a9947fSrtm for(ip = &inode[0]; ip < &inode[NINODE]; ip++){ 10811a9947fSrtm if(ip->count > 0 && ip->dev == dev && ip->inum == inum){ 10911a9947fSrtm if(ip->busy){ 11011a9947fSrtm sleep(ip, &inode_table_lock); 11111a9947fSrtm goto loop; 11211a9947fSrtm } 11311a9947fSrtm ip->count++; 11417a85657Srtm ip->busy = 1; 11511a9947fSrtm release(&inode_table_lock); 11611a9947fSrtm return ip; 11711a9947fSrtm } 11811a9947fSrtm if(nip == 0 && ip->count == 0) 11911a9947fSrtm nip = ip; 12011a9947fSrtm } 12111a9947fSrtm 12211a9947fSrtm if(nip == 0) 12311a9947fSrtm panic("out of inodes"); 12411a9947fSrtm 12511a9947fSrtm nip->dev = dev; 12611a9947fSrtm nip->inum = inum; 12711a9947fSrtm nip->count = 1; 12811a9947fSrtm nip->busy = 1; 12911a9947fSrtm 13011a9947fSrtm release(&inode_table_lock); 13111a9947fSrtm 13224111398Skaashoek bp = bread(dev, IBLOCK(inum)); 13311a9947fSrtm dip = &((struct dinode*)(bp->data))[inum % IPB]; 13411a9947fSrtm nip->type = dip->type; 135e8d11c2eSkaashoek nip->major = dip->major; 136e8d11c2eSkaashoek nip->minor = dip->minor; 13711a9947fSrtm nip->nlink = dip->nlink; 13811a9947fSrtm nip->size = dip->size; 13911a9947fSrtm memmove(nip->addrs, dip->addrs, sizeof(nip->addrs)); 14011a9947fSrtm brelse(bp); 14111a9947fSrtm 14211a9947fSrtm return nip; 14311a9947fSrtm } 14411a9947fSrtm 14528d9ef04Skaashoek void 14628d9ef04Skaashoek iupdate(struct inode *ip) 14728d9ef04Skaashoek { 14828d9ef04Skaashoek struct buf *bp; 14928d9ef04Skaashoek struct dinode *dip; 15028d9ef04Skaashoek 15128d9ef04Skaashoek bp = bread(ip->dev, IBLOCK(ip->inum)); 15228d9ef04Skaashoek dip = &((struct dinode*)(bp->data))[ip->inum % IPB]; 15328d9ef04Skaashoek dip->type = ip->type; 15428d9ef04Skaashoek dip->major = ip->major; 15528d9ef04Skaashoek dip->minor = ip->minor; 15628d9ef04Skaashoek dip->nlink = ip->nlink; 15728d9ef04Skaashoek dip->size = ip->size; 15828d9ef04Skaashoek memmove(dip->addrs, ip->addrs, sizeof(ip->addrs)); 15905e97551Srtm bwrite(bp, IBLOCK(ip->inum)); // mark it allocated on the disk 16028d9ef04Skaashoek brelse(bp); 16128d9ef04Skaashoek } 16228d9ef04Skaashoek 163e8d11c2eSkaashoek struct inode* 164e8d11c2eSkaashoek ialloc(uint dev, short type) 165e8d11c2eSkaashoek { 166e8d11c2eSkaashoek struct inode *ip; 167e8d11c2eSkaashoek struct dinode *dip = 0; 168e8d11c2eSkaashoek struct superblock *sb; 169e8d11c2eSkaashoek int ninodes; 170e8d11c2eSkaashoek int inum; 171e8d11c2eSkaashoek struct buf *bp; 172e8d11c2eSkaashoek 173e8d11c2eSkaashoek bp = bread(dev, 1); 17424111398Skaashoek sb = (struct superblock*) bp->data; 175e8d11c2eSkaashoek ninodes = sb->ninodes; 176e8d11c2eSkaashoek brelse(bp); 177e8d11c2eSkaashoek 178e8d11c2eSkaashoek for(inum = 1; inum < ninodes; inum++) { // loop over inode blocks 17924111398Skaashoek bp = bread(dev, IBLOCK(inum)); 180e8d11c2eSkaashoek dip = &((struct dinode*)(bp->data))[inum % IPB]; 181e8d11c2eSkaashoek if(dip->type == 0) { // a free inode 182e8d11c2eSkaashoek break; 183e8d11c2eSkaashoek } 184e8d11c2eSkaashoek brelse(bp); 185e8d11c2eSkaashoek } 186e8d11c2eSkaashoek 18717e3cf15Srtm if(inum >= ninodes) 1882aa4c3bcSrtm panic("ialloc: no inodes left"); 189e8d11c2eSkaashoek 1902aa4c3bcSrtm memset(dip, 0, sizeof(*dip)); 191e8d11c2eSkaashoek dip->type = type; 19205e97551Srtm bwrite(bp, IBLOCK(inum)); // mark it allocated on the disk 193e8d11c2eSkaashoek brelse(bp); 194e8d11c2eSkaashoek ip = iget(dev, inum); 195e8d11c2eSkaashoek return ip; 196e8d11c2eSkaashoek } 197e8d11c2eSkaashoek 19828d9ef04Skaashoek static void 19924437cd5Skaashoek ifree(struct inode *ip) 200e8d11c2eSkaashoek { 20128d9ef04Skaashoek ip->type = 0; 20228d9ef04Skaashoek iupdate(ip); 203e8d11c2eSkaashoek } 204e8d11c2eSkaashoek 20511a9947fSrtm void 2069d3fb671Srtm ilock(struct inode *ip) 2079d3fb671Srtm { 2089d3fb671Srtm if(ip->count < 1) 2099d3fb671Srtm panic("ilock"); 2109d3fb671Srtm 2119d3fb671Srtm acquire(&inode_table_lock); 2129d3fb671Srtm 2139d3fb671Srtm while(ip->busy) 2149d3fb671Srtm sleep(ip, &inode_table_lock); 2159d3fb671Srtm ip->busy = 1; 2169d3fb671Srtm 2179d3fb671Srtm release(&inode_table_lock); 2189d3fb671Srtm } 2199d3fb671Srtm 2209d3fb671Srtm // caller is holding onto a reference to this inode, but no 2219d3fb671Srtm // longer needs to examine or change it, so clear ip->busy. 2229d3fb671Srtm void 2239d3fb671Srtm iunlock(struct inode *ip) 2249d3fb671Srtm { 22517e3cf15Srtm if(ip->busy != 1 || ip->count < 1) 2269d3fb671Srtm panic("iunlock"); 2279d3fb671Srtm 2289d3fb671Srtm acquire(&inode_table_lock); 2299d3fb671Srtm 2309d3fb671Srtm ip->busy = 0; 2319d3fb671Srtm wakeup(ip); 2329d3fb671Srtm 2339d3fb671Srtm release(&inode_table_lock); 2349d3fb671Srtm } 2359d3fb671Srtm 23622bac2cbSkaashoek uint 23722bac2cbSkaashoek bmap(struct inode *ip, uint bn) 23822bac2cbSkaashoek { 23922bac2cbSkaashoek unsigned x; 240ea2909b6Skaashoek uint *a; 241ea2909b6Skaashoek struct buf *inbp; 24222bac2cbSkaashoek 243ea2909b6Skaashoek if(bn >= MAXFILE) 24422bac2cbSkaashoek panic("bmap 1"); 245ea2909b6Skaashoek if(bn < NDIRECT) { 24622bac2cbSkaashoek x = ip->addrs[bn]; 24722bac2cbSkaashoek if(x == 0) 24822bac2cbSkaashoek panic("bmap 2"); 249ea2909b6Skaashoek } else { 2505051da6dSrtm if(ip->addrs[INDIRECT] == 0) 2515051da6dSrtm panic("bmap 3"); 2521be76685Skaashoek inbp = bread(ip->dev, ip->addrs[INDIRECT]); 253ea2909b6Skaashoek a = (uint*) inbp->data; 254ea2909b6Skaashoek x = a[bn - NDIRECT]; 255ea2909b6Skaashoek brelse(inbp); 256ea2909b6Skaashoek if(x == 0) 2575051da6dSrtm panic("bmap 4"); 258ea2909b6Skaashoek } 25922bac2cbSkaashoek return x; 26022bac2cbSkaashoek } 26122bac2cbSkaashoek 26222bac2cbSkaashoek void 2632aa4c3bcSrtm itrunc(struct inode *ip) 26422bac2cbSkaashoek { 265ea2909b6Skaashoek int i, j; 2661be76685Skaashoek struct buf *inbp; 26722bac2cbSkaashoek 268ea2909b6Skaashoek for(i = 0; i < NADDRS; i++) { 26922bac2cbSkaashoek if(ip->addrs[i] != 0) { 270ea2909b6Skaashoek if(i == INDIRECT) { 2711be76685Skaashoek inbp = bread(ip->dev, ip->addrs[INDIRECT]); 2721be76685Skaashoek uint *a = (uint*) inbp->data; 273bcfb84b6Srtm for(j = 0; j < NINDIRECT; j++) { 274ea2909b6Skaashoek if(a[j] != 0) { 275ea2909b6Skaashoek bfree(ip->dev, a[j]); 276ea2909b6Skaashoek a[j] = 0; 277ea2909b6Skaashoek } 278ea2909b6Skaashoek } 2791be76685Skaashoek brelse(inbp); 280ea2909b6Skaashoek } 28122bac2cbSkaashoek bfree(ip->dev, ip->addrs[i]); 28222bac2cbSkaashoek ip->addrs[i] = 0; 28322bac2cbSkaashoek } 28422bac2cbSkaashoek } 28522bac2cbSkaashoek ip->size = 0; 28622bac2cbSkaashoek iupdate(ip); 28722bac2cbSkaashoek } 28822bac2cbSkaashoek 2899d3fb671Srtm // caller is releasing a reference to this inode. 2909d3fb671Srtm // you must have the inode lock. 2919d3fb671Srtm void 29211a9947fSrtm iput(struct inode *ip) 29311a9947fSrtm { 2949d3fb671Srtm if(ip->count < 1 || ip->busy != 1) 2959d3fb671Srtm panic("iput"); 2969d3fb671Srtm 2972aa4c3bcSrtm if((ip->count == 1) && (ip->nlink == 0)) { 2982aa4c3bcSrtm itrunc(ip); 2992aa4c3bcSrtm ifree(ip); 3002aa4c3bcSrtm } 30122bac2cbSkaashoek 30211a9947fSrtm acquire(&inode_table_lock); 30311a9947fSrtm 30411a9947fSrtm ip->count -= 1; 30511a9947fSrtm ip->busy = 0; 30611a9947fSrtm wakeup(ip); 30711a9947fSrtm 30811a9947fSrtm release(&inode_table_lock); 30911a9947fSrtm } 3109d3fb671Srtm 3119d3fb671Srtm void 31232630628Srtm idecref(struct inode *ip) 3139d3fb671Srtm { 314211ff0c6Srtm ilock(ip); 315211ff0c6Srtm iput(ip); 3169d3fb671Srtm } 3179d3fb671Srtm 3181f544842Skaashoek void 319e958c538Skaashoek iincref(struct inode *ip) 320e958c538Skaashoek { 321e958c538Skaashoek ilock(ip); 322e958c538Skaashoek ip->count++; 323e958c538Skaashoek iunlock(ip); 324e958c538Skaashoek } 325e958c538Skaashoek 326e958c538Skaashoek void 3271f544842Skaashoek stati(struct inode *ip, struct stat *st) 3281f544842Skaashoek { 3291f544842Skaashoek st->st_dev = ip->dev; 3301f544842Skaashoek st->st_ino = ip->inum; 3311f544842Skaashoek st->st_type = ip->type; 3321f544842Skaashoek st->st_nlink = ip->nlink; 3331f544842Skaashoek st->st_size = ip->size; 3341f544842Skaashoek } 3351f544842Skaashoek 33622bac2cbSkaashoek #define min(a, b) ((a) < (b) ? (a) : (b)) 33722bac2cbSkaashoek 338c59361f1Srtm int 33917a85657Srtm readi(struct inode *ip, char *dst, uint off, uint n) 340c59361f1Srtm { 341c59361f1Srtm uint target = n, n1; 342c59361f1Srtm struct buf *bp; 343c59361f1Srtm 344939f9edeSkaashoek if(ip->type == T_DEV) { 345939f9edeSkaashoek if(ip->major < 0 || ip->major >= NDEV || !devsw[ip->major].d_read) 346939f9edeSkaashoek return -1; 34717a85657Srtm return devsw[ip->major].d_read(ip->minor, dst, n); 348939f9edeSkaashoek } 349939f9edeSkaashoek 350c59361f1Srtm while(n > 0 && off < ip->size){ 35124111398Skaashoek bp = bread(ip->dev, bmap(ip, off / BSIZE)); 352c59361f1Srtm n1 = min(n, ip->size - off); 35324111398Skaashoek n1 = min(n1, BSIZE - (off % BSIZE)); 35424111398Skaashoek memmove(dst, bp->data + (off % BSIZE), n1); 355c59361f1Srtm n -= n1; 356c59361f1Srtm off += n1; 357c59361f1Srtm dst += n1; 358c59361f1Srtm brelse(bp); 359c59361f1Srtm } 360c59361f1Srtm 361c59361f1Srtm return target - n; 362c59361f1Srtm } 363c59361f1Srtm 3641be76685Skaashoek static int 365ea2909b6Skaashoek newblock(struct inode *ip, uint lbn) 366ea2909b6Skaashoek { 367ea2909b6Skaashoek struct buf *inbp; 368ea2909b6Skaashoek uint *inaddrs; 369ea2909b6Skaashoek uint b; 370ea2909b6Skaashoek 371ea2909b6Skaashoek if(lbn < NDIRECT) { 372ea2909b6Skaashoek if(ip->addrs[lbn] == 0) { 373ea2909b6Skaashoek b = balloc(ip->dev); 374*48b82470Srsc if(b <= 0) 375*48b82470Srsc return -1; 376ea2909b6Skaashoek ip->addrs[lbn] = b; 377ea2909b6Skaashoek } 378ea2909b6Skaashoek } else { 379ea2909b6Skaashoek if(ip->addrs[INDIRECT] == 0) { 380ea2909b6Skaashoek b = balloc(ip->dev); 381*48b82470Srsc if(b <= 0) 382*48b82470Srsc return -1; 383ea2909b6Skaashoek ip->addrs[INDIRECT] = b; 384ea2909b6Skaashoek } 3851be76685Skaashoek inbp = bread(ip->dev, ip->addrs[INDIRECT]); 386ea2909b6Skaashoek inaddrs = (uint*) inbp->data; 387ea2909b6Skaashoek if(inaddrs[lbn - NDIRECT] == 0) { 388ea2909b6Skaashoek b = balloc(ip->dev); 389*48b82470Srsc if(b <= 0) 390*48b82470Srsc return -1; 391ea2909b6Skaashoek inaddrs[lbn - NDIRECT] = b; 3921be76685Skaashoek bwrite(inbp, ip->addrs[INDIRECT]); 393ea2909b6Skaashoek } 394ea2909b6Skaashoek brelse(inbp); 395ea2909b6Skaashoek } 396ea2909b6Skaashoek return 0; 397ea2909b6Skaashoek } 398ea2909b6Skaashoek 399ea2909b6Skaashoek int 40017a85657Srtm writei(struct inode *ip, char *addr, uint off, uint n) 4016fa5ffb5Skaashoek { 4026fa5ffb5Skaashoek if(ip->type == T_DEV) { 403939f9edeSkaashoek if(ip->major < 0 || ip->major >= NDEV || !devsw[ip->major].d_write) 404939f9edeSkaashoek return -1; 4056fa5ffb5Skaashoek return devsw[ip->major].d_write(ip->minor, addr, n); 406ea2909b6Skaashoek } else if(ip->type == T_FILE || ip->type == T_DIR) { 40728d9ef04Skaashoek struct buf *bp; 40828d9ef04Skaashoek int r = 0; 40928d9ef04Skaashoek int m; 41028d9ef04Skaashoek int lbn; 41128d9ef04Skaashoek while(r < n) { 41228d9ef04Skaashoek lbn = off / BSIZE; 413*48b82470Srsc if(lbn >= MAXFILE) 414*48b82470Srsc return r; 415ea2909b6Skaashoek if(newblock(ip, lbn) < 0) { 416ea2909b6Skaashoek cprintf("newblock failed\n"); 417ea2909b6Skaashoek return r; 41828d9ef04Skaashoek } 41922bac2cbSkaashoek m = min(BSIZE - off % BSIZE, n-r); 420ea2909b6Skaashoek bp = bread(ip->dev, bmap(ip, lbn)); 42128d9ef04Skaashoek memmove(bp->data + off % BSIZE, addr, m); 422ea2909b6Skaashoek bwrite(bp, bmap(ip, lbn)); 42328d9ef04Skaashoek brelse(bp); 42428d9ef04Skaashoek r += m; 42528d9ef04Skaashoek off += m; 42628d9ef04Skaashoek } 42728d9ef04Skaashoek if(r > 0) { 42828d9ef04Skaashoek if(off > ip->size) { 429*48b82470Srsc if(ip->type == T_DIR) 430*48b82470Srsc ip->size = ((off / BSIZE) + 1) * BSIZE; 431*48b82470Srsc else 432*48b82470Srsc ip->size = off; 43328d9ef04Skaashoek } 43428d9ef04Skaashoek iupdate(ip); 43528d9ef04Skaashoek } 43628d9ef04Skaashoek return r; 4376fa5ffb5Skaashoek } else { 4382aa4c3bcSrtm panic("writei: unknown type"); 4398a8be1b8Srtm return 0; 4406fa5ffb5Skaashoek } 4416fa5ffb5Skaashoek } 4426fa5ffb5Skaashoek 443211ff0c6Srtm // look up a path name, in one of three modes. 444211ff0c6Srtm // NAMEI_LOOKUP: return locked target inode. 445211ff0c6Srtm // NAMEI_CREATE: return locked parent inode. 4465051da6dSrtm // return 0 if name does exist. 4475051da6dSrtm // *ret_last points to last path component (i.e. new file name). 4485051da6dSrtm // *ret_ip points to the the name that did exist, if it did. 4495051da6dSrtm // *ret_ip and *ret_last may be zero even if return value is zero. 450211ff0c6Srtm // NAMEI_DELETE: return locked parent inode, offset of dirent in *ret_off. 451211ff0c6Srtm // return 0 if name doesn't exist. 4529d3fb671Srtm struct inode* 4535051da6dSrtm namei(char *path, int mode, uint *ret_off, char **ret_last, struct inode **ret_ip) 4549d3fb671Srtm { 4559d3fb671Srtm struct inode *dp; 4568787cd01Skaashoek struct proc *p = curproc[cpu()]; 457211ff0c6Srtm char *cp = path, *cp1; 4589d3fb671Srtm uint off, dev; 4599d3fb671Srtm struct buf *bp; 4609d3fb671Srtm struct dirent *ep; 461211ff0c6Srtm int i, atend; 4629d3fb671Srtm unsigned ninum; 4639d3fb671Srtm 4645051da6dSrtm if(ret_off) 4655051da6dSrtm *ret_off = 0xffffffff; 4665051da6dSrtm if(ret_last) 4675051da6dSrtm *ret_last = 0; 4685051da6dSrtm if(ret_ip) 4695051da6dSrtm *ret_ip = 0; 4705051da6dSrtm 471*48b82470Srsc if(*cp == '/') 472*48b82470Srsc dp = iget(rootdev, 1); 4738787cd01Skaashoek else { 4748787cd01Skaashoek dp = p->cwd; 4758787cd01Skaashoek iincref(dp); 4768787cd01Skaashoek ilock(dp); 4778787cd01Skaashoek } 4789d3fb671Srtm 4799d3fb671Srtm while(*cp == '/') 4809d3fb671Srtm cp++; 4819d3fb671Srtm 4829d3fb671Srtm while(1){ 4830633b971Skaashoek if(*cp == '\0'){ 484211ff0c6Srtm if(mode == NAMEI_LOOKUP) 4859d3fb671Srtm return dp; 4865051da6dSrtm if(mode == NAMEI_CREATE && ret_ip){ 4875051da6dSrtm *ret_ip = dp; 4885051da6dSrtm return 0; 4895051da6dSrtm } 490211ff0c6Srtm iput(dp); 491211ff0c6Srtm return 0; 4920633b971Skaashoek } 4939d3fb671Srtm 4949d3fb671Srtm if(dp->type != T_DIR){ 4959d3fb671Srtm iput(dp); 4969d3fb671Srtm return 0; 4979d3fb671Srtm } 4989d3fb671Srtm 49924111398Skaashoek for(off = 0; off < dp->size; off += BSIZE){ 50024111398Skaashoek bp = bread(dp->dev, bmap(dp, off / BSIZE)); 5019d3fb671Srtm for(ep = (struct dirent*) bp->data; 50224111398Skaashoek ep < (struct dirent*) (bp->data + BSIZE); 5039d3fb671Srtm ep++){ 5049d3fb671Srtm if(ep->inum == 0) 5059d3fb671Srtm continue; 5069d3fb671Srtm for(i = 0; i < DIRSIZ && cp[i] != '/' && cp[i]; i++) 5079d3fb671Srtm if(cp[i] != ep->name[i]) 5089d3fb671Srtm break; 50903c70cc2Srtm if((cp[i] == '\0' || cp[i] == '/' || i >= DIRSIZ) && 51003c70cc2Srtm (i >= DIRSIZ || ep->name[i] == '\0')){ 51103c70cc2Srtm while(cp[i] != '\0' && cp[i] != '/') 51203c70cc2Srtm i++; 513211ff0c6Srtm off += (uchar*)ep - bp->data; 5149d3fb671Srtm ninum = ep->inum; 5159d3fb671Srtm brelse(bp); 5169d3fb671Srtm cp += i; 5179d3fb671Srtm goto found; 5189d3fb671Srtm } 5199d3fb671Srtm } 5209d3fb671Srtm brelse(bp); 5219d3fb671Srtm } 522211ff0c6Srtm atend = 1; 523211ff0c6Srtm for(cp1 = cp; *cp1; cp1++) 524211ff0c6Srtm if(*cp1 == '/') 525211ff0c6Srtm atend = 0; 5265051da6dSrtm if(mode == NAMEI_CREATE && atend){ 5275051da6dSrtm if(*cp == '\0'){ 5285051da6dSrtm iput(dp); 5295051da6dSrtm return 0; 5305051da6dSrtm } 5315051da6dSrtm *ret_last = cp; 532211ff0c6Srtm return dp; 5335051da6dSrtm } 534211ff0c6Srtm 5359d3fb671Srtm iput(dp); 5369d3fb671Srtm return 0; 5379d3fb671Srtm 5389d3fb671Srtm found: 539211ff0c6Srtm if(mode == NAMEI_DELETE && *cp == '\0'){ 540211ff0c6Srtm *ret_off = off; 541211ff0c6Srtm return dp; 542211ff0c6Srtm } 5439d3fb671Srtm dev = dp->dev; 5449d3fb671Srtm iput(dp); 5459d3fb671Srtm dp = iget(dev, ninum); 5467ce01cf9Srtm if(dp->type == 0 || dp->nlink < 1) 5477ce01cf9Srtm panic("namei"); 5489d3fb671Srtm while(*cp == '/') 5499d3fb671Srtm cp++; 5509d3fb671Srtm } 5519d3fb671Srtm } 552e8d11c2eSkaashoek 5539e5970d5Srtm void 5549e5970d5Srtm wdir(struct inode *dp, char *name, uint ino) 5559e5970d5Srtm { 5569e5970d5Srtm uint off; 557e4bcd2a3Srtm struct dirent de; 5589e5970d5Srtm int i; 5599e5970d5Srtm 560e4bcd2a3Srtm for(off = 0; off < dp->size; off += sizeof(de)){ 561e4bcd2a3Srtm if(readi(dp, (char*) &de, off, sizeof(de)) != sizeof(de)) 562e4bcd2a3Srtm panic("wdir read"); 563e4bcd2a3Srtm if(de.inum == 0) 564e4bcd2a3Srtm break; 565e4bcd2a3Srtm } 566211ff0c6Srtm 567e4bcd2a3Srtm de.inum = ino; 5682aa4c3bcSrtm for(i = 0; i < DIRSIZ && name[i]; i++) 569e4bcd2a3Srtm de.name[i] = name[i]; 5709e5970d5Srtm for( ; i < DIRSIZ; i++) 571e4bcd2a3Srtm de.name[i] = '\0'; 572e4bcd2a3Srtm 573e4bcd2a3Srtm if(writei(dp, (char*) &de, off, sizeof(de)) != sizeof(de)) 574e4bcd2a3Srtm panic("wdir write"); 5759e5970d5Srtm } 5769e5970d5Srtm 577e8d11c2eSkaashoek struct inode* 5780633b971Skaashoek mknod(char *cp, short type, short major, short minor) 579e8d11c2eSkaashoek { 5800633b971Skaashoek struct inode *ip, *dp; 5815051da6dSrtm char *last; 582e8d11c2eSkaashoek 5835051da6dSrtm if((dp = namei(cp, NAMEI_CREATE, 0, &last, 0)) == 0) 5840633b971Skaashoek return 0; 585211ff0c6Srtm 5865051da6dSrtm ip = mknod1(dp, last, type, major, minor); 5875051da6dSrtm 5885051da6dSrtm iput(dp); 5895051da6dSrtm 5905051da6dSrtm return ip; 5915051da6dSrtm } 5925051da6dSrtm 5935051da6dSrtm struct inode* 5945051da6dSrtm mknod1(struct inode *dp, char *name, short type, short major, short minor) 5955051da6dSrtm { 5965051da6dSrtm struct inode *ip; 5975051da6dSrtm 598e8d11c2eSkaashoek ip = ialloc(dp->dev, type); 5992aa4c3bcSrtm if(ip == 0) 6000633b971Skaashoek return 0; 601e8d11c2eSkaashoek ip->major = major; 602e8d11c2eSkaashoek ip->minor = minor; 6036c0e444fSkaashoek ip->size = 0; 6047ce01cf9Srtm ip->nlink = 1; 6056c0e444fSkaashoek 6066c0e444fSkaashoek iupdate(ip); // write new inode to disk 607e8d11c2eSkaashoek 6085051da6dSrtm wdir(dp, name, ip->inum); 6095051da6dSrtm 610e8d11c2eSkaashoek return ip; 611e8d11c2eSkaashoek } 61224437cd5Skaashoek 61324437cd5Skaashoek int 61424437cd5Skaashoek unlink(char *cp) 61524437cd5Skaashoek { 616211ff0c6Srtm struct inode *ip, *dp; 617211ff0c6Srtm struct dirent de; 61817e3cf15Srtm uint off, inum, dev; 61924437cd5Skaashoek 6205051da6dSrtm dp = namei(cp, NAMEI_DELETE, &off, 0, 0); 6215051da6dSrtm if(dp == 0) 62224437cd5Skaashoek return -1; 62324437cd5Skaashoek 62417e3cf15Srtm dev = dp->dev; 62517e3cf15Srtm 62617e3cf15Srtm if(readi(dp, (char*)&de, off, sizeof(de)) != sizeof(de) || de.inum == 0) 627211ff0c6Srtm panic("unlink no entry"); 62817e3cf15Srtm 629211ff0c6Srtm inum = de.inum; 63024437cd5Skaashoek 631211ff0c6Srtm memset(&de, 0, sizeof(de)); 632211ff0c6Srtm if(writei(dp, (char*)&de, off, sizeof(de)) != sizeof(de)) 633211ff0c6Srtm panic("unlink dir write"); 63424437cd5Skaashoek 63524437cd5Skaashoek iupdate(dp); 63624437cd5Skaashoek iput(dp); 637211ff0c6Srtm 63817e3cf15Srtm ip = iget(dev, inum); 639211ff0c6Srtm 640bcfb84b6Srtm if(ip->nlink < 1) 641bcfb84b6Srtm panic("unlink nlink < 1"); 642bcfb84b6Srtm 643211ff0c6Srtm ip->nlink--; 644211ff0c6Srtm 645211ff0c6Srtm iupdate(ip); 64622bac2cbSkaashoek iput(ip); 647211ff0c6Srtm 64824437cd5Skaashoek return 0; 64924437cd5Skaashoek } 6509e5970d5Srtm 6519e5970d5Srtm int 6529e5970d5Srtm link(char *name1, char *name2) 6539e5970d5Srtm { 654211ff0c6Srtm struct inode *ip, *dp; 6555051da6dSrtm char *last; 6569e5970d5Srtm 6575051da6dSrtm if((ip = namei(name1, NAMEI_LOOKUP, 0, 0, 0)) == 0) 6589e5970d5Srtm return -1; 659211ff0c6Srtm if(ip->type == T_DIR){ 660211ff0c6Srtm iput(ip); 661211ff0c6Srtm return -1; 662211ff0c6Srtm } 6639e5970d5Srtm 664211ff0c6Srtm iunlock(ip); 665211ff0c6Srtm 6665051da6dSrtm if((dp = namei(name2, NAMEI_CREATE, 0, &last, 0)) == 0) { 667211ff0c6Srtm idecref(ip); 668211ff0c6Srtm return -1; 669211ff0c6Srtm } 670211ff0c6Srtm if(dp->dev != ip->dev){ 671211ff0c6Srtm idecref(ip); 672211ff0c6Srtm iput(dp); 673211ff0c6Srtm return -1; 674211ff0c6Srtm } 675211ff0c6Srtm 676211ff0c6Srtm ilock(ip); 6779e5970d5Srtm ip->nlink += 1; 6789e5970d5Srtm iupdate(ip); 6799e5970d5Srtm 6805051da6dSrtm wdir(dp, last, ip->inum); 6819e5970d5Srtm iput(dp); 6829e5970d5Srtm iput(ip); 6839e5970d5Srtm 6849e5970d5Srtm return 0; 6859e5970d5Srtm } 686