+ * Unlink system call.
+ * Hard to avoid races here, especially
+ * in unlinking directories.
+ */
+unlink()
+{
+ register struct inode *ip, *pp;
+ struct a {
+ char *fname;
+ };
+ struct fs *fs;
+ struct buf *bp;
+ int lbn, bn, base;
+
+ pp = namei(uchar, 2, 0);
+ if(pp == NULL)
+ return;
+ /*
+ * Check for unlink(".")
+ * to avoid hanging on the iget
+ */
+ if (pp->i_number == u.u_dent.d_ino) {
+ ip = pp;
+ ip->i_count++;
+ } else
+ ip = iget(pp->i_dev, pp->i_fs, u.u_dent.d_ino);
+ if(ip == NULL)
+ goto out1;
+ if((ip->i_mode&IFMT)==IFDIR && !suser())
+ goto out;
+ /*
+ * Don't unlink a mounted file.
+ */
+ if (ip->i_dev != pp->i_dev) {
+ u.u_error = EBUSY;
+ goto out;
+ }
+ if (ip->i_flag&ITEXT)
+ xrele(ip); /* try once to free text */
+/*
+ if ((ip->i_flag&ITEXT) && ip->i_nlink==1) {
+ u.u_error = ETXTBSY;
+ goto out;
+ }
+*/
+ if (u.u_count == 0) {
+ /*
+ * first entry in block, so set d_ino to zero.
+ */
+ u.u_base = (caddr_t)&u.u_dent;
+ u.u_count = DIRSIZ(&u.u_dent);
+ u.u_dent.d_ino = 0;
+ writei(pp);
+ } else {
+ /*
+ * updating preceeding entry to skip over current entry.
+ */
+ fs = pp->i_fs;
+ lbn = lblkno(fs, u.u_offset);
+ base = blkoff(fs, u.u_offset);
+ bn = fsbtodb(fs, bmap(pp, lbn, B_WRITE, base + u.u_count));
+ bp = bread(pp->i_dev, bn, blksize(fs, pp, lbn));
+ if (bp->b_flags & B_ERROR) {
+ brelse(bp);
+ goto out;
+ }
+ ((struct direct *)(bp->b_un.b_addr + base))->d_reclen +=
+ u.u_dent.d_reclen;
+ bwrite(bp);
+ pp->i_flag |= IUPD|ICHG;
+ }
+ ip->i_nlink--;
+ ip->i_flag |= ICHG;
+
+out:
+ iput(ip);
+out1:
+ iput(pp);
+}
+
+/*
+ * Seek system call