srv: Support remove on close

Note that the O_REMCLO only applies to the chan/file *created* in srv,
not the ones made from *opening* a file in srv.  When someone opens a
chan/file in srv, that FD points to a new chan from another device,
(e.g. a pipe), and when *that* FD is closed, we call *that* device's
close.

I don't know what the deal was with O_REMCLO and the commented-out code.
All in all, srv needs a good security review, and optionally a port from
Plan 9.  This one was written since the Inferno one didn't seem to do
what we needed.

Also, srv should have some security checks on setting REMCLO, equivalent
to what we do for remove.  Right now, we have no checks on that, so
whatever.  Also, due to srv's implementation, you can only set REMCLO on
create(), which means a process was the creator.  It seems reasonable to
allow the creator to also remove.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
diff --git a/kern/drivers/dev/srv.c b/kern/drivers/dev/srv.c
index ba4e144..c3d2f65 100644
--- a/kern/drivers/dev/srv.c
+++ b/kern/drivers/dev/srv.c
@@ -204,15 +204,6 @@
 		nexterror();
 	}
 	devpermcheck(srv->user, srv->perm, omode);
-	/* No remove on close support yet */
-#if 0
-	if (omode & ORCLOSE) {
-		if (strcmp(srv->user, up->env->user) != 0)
-			error(EPERM, ERROR_FIXME);
-		else
-			srv->flags |= SORCLOSE;
-	}
-#endif
 	if ((srv->perm & DMEXCL) && atomic_read(&srv->opens))
 		error(EBUSY, ERROR_FIXME);
 	/* srv->chan is write-once, so we don't need to sync. */
@@ -255,15 +246,6 @@
 	return -1;
 }
 
-static void srvclose(struct chan *c)
-{
-	struct srvfile *srv = c->aux;
-	if (!grab_ref(srv))
-		return;
-	atomic_dec(&srv->opens);
-	kref_put(&srv->ref);
-}
-
 static void srvremove(struct chan *c)
 {
 	struct srvfile *srv_i, *temp;
@@ -280,6 +262,18 @@
 		kref_put(&srv_i->ref);	/* dropping ref from the list */
 }
 
+static void srvclose(struct chan *c)
+{
+	struct srvfile *srv = c->aux;
+
+	if (!grab_ref(srv))
+		return;
+	atomic_dec(&srv->opens);
+	kref_put(&srv->ref);
+	if (c->flag & O_REMCLO)
+		srvremove(c);
+}
+
 /* N.B. srvopen gives the chan back. The only 'reading' we do
  * in srv is of the top level directory.
  */