Index: src/afs/afs_call.c
===================================================================
RCS file: /cvs/openafs/src/afs/afs_call.c,v
retrieving revision 1.14.2.18
diff -u -r1.14.2.18 afs_call.c
--- src/afs/afs_call.c	23 Mar 2003 19:47:53 -0000	1.14.2.18
+++ src/afs/afs_call.c	7 Apr 2003 18:32:52 -0000
@@ -731,8 +731,10 @@
 #endif
 	afs_cold_shutdown = 0;
 	if (parm == 1) afs_cold_shutdown = 1;
+#ifndef AFS_DARWIN_ENV
 	if (afs_globalVFS != 0) 
 	    afs_warn("AFS isn't unmounted yet!\n");
+#endif
 
 	afs_shutdown();
     }
Index: src/afs/DARWIN/osi_vfsops.c
===================================================================
RCS file: /cvs/openafs/src/afs/DARWIN/osi_vfsops.c,v
retrieving revision 1.4.2.1
diff -u -r1.4.2.1 osi_vfsops.c
--- src/afs/DARWIN/osi_vfsops.c	24 Apr 2002 01:41:22 -0000	1.4.2.1
+++ src/afs/DARWIN/osi_vfsops.c	7 Apr 2003 18:32:52 -0000
@@ -67,7 +67,7 @@
     AFS_GLOCK();
     AFS_STATCNT(afs_mount);
 
-    if (afs_globalVFS) { /* Don't allow remounts. */
+    if (data == NULL && afs_globalVFS) { /* Don't allow remounts. */
 	AFS_GUNLOCK();
 	return (EBUSY);
     }
@@ -80,8 +80,51 @@
     (void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN-1, &size);
     memset(mp->mnt_stat.f_mntonname + size, 0, MNAMELEN - size);
     memset(mp->mnt_stat.f_mntfromname, 0, MNAMELEN);
-    strcpy(mp->mnt_stat.f_mntfromname, "AFS");
-    /* null terminated string "AFS" will fit, just leave it be. */
+
+    if (data == NULL) {
+	strcpy(mp->mnt_stat.f_mntfromname, "AFS");
+	/* null terminated string "AFS" will fit, just leave it be. */
+	mp->mnt_data = (qaddr_t)NULL;
+    } else {
+	struct VenusFid *rootFid = NULL;
+	struct volume *tvp;
+	char volName[MNAMELEN];
+
+	(void) copyinstr((char *)data, volName, MNAMELEN-1, &size);
+	memset(volName + size, 0, MNAMELEN - size);
+
+	if (volName[0] == 0) {
+	    strcpy(mp->mnt_stat.f_mntfromname, "AFS");
+	    mp->mnt_data = (qaddr_t)&afs_rootFid;	    
+	} else {
+	    struct cell *localcell = afs_GetPrimaryCell(READ_LOCK);
+	    if (localcell == NULL) {
+		AFS_GUNLOCK();
+		return ENODEV;
+	    }
+
+	    /* Set the volume identifier to "AFS:volume.name" */
+	    snprintf(mp->mnt_stat.f_mntfromname, MNAMELEN-1, "AFS:%s",
+		     volName);
+	    tvp = afs_GetVolumeByName(volName, localcell->cellNum, 1,
+				      (struct vrequest *)0, READ_LOCK);
+	    
+	    if (tvp) {
+		int volid = (tvp->roVol ? tvp->roVol : tvp->volume);
+		MALLOC(rootFid, struct VenusFid *, sizeof(*rootFid), 
+		       M_UFSMNT, M_WAITOK);
+		rootFid->Cell = localcell->cellNum;
+		rootFid->Fid.Volume = volid;
+		rootFid->Fid.Vnode = 1;
+		rootFid->Fid.Unique = 1;
+	    } else {
+		AFS_GUNLOCK();
+		return ENODEV;
+	    }
+	
+	    mp->mnt_data = (qaddr_t)rootFid;
+	}
+    }
     strcpy(mp->mnt_stat.f_fstypename, "afs");
     AFS_GUNLOCK();
     (void) afs_statfs(mp, &mp->mnt_stat, p);
@@ -97,8 +140,23 @@
     
     AFS_GLOCK();
     AFS_STATCNT(afs_unmount);
-    afs_globalVFS = 0;
-    afs_shutdown();
+
+    if (mp->mnt_data != (qaddr_t)-1) {
+	if (mp->mnt_data != NULL) {
+	    FREE(mp->mnt_data, M_UFSMNT);
+	    mp->mnt_data = (qaddr_t)-1;
+	} else {
+	    if (flags & MNT_FORCE) {
+		afs_globalVFS = 0;
+		afs_shutdown();
+	    } else {
+		AFS_GUNLOCK();
+		return EBUSY;
+	    }
+	}
+	mp->mnt_flag &= ~MNT_LOCAL;
+    }
+
     AFS_GUNLOCK();
 
     return 0;
@@ -119,18 +177,24 @@
     pcred_unlock(p);
     AFS_GLOCK();
     AFS_STATCNT(afs_root);
-    if (afs_globalVp && (afs_globalVp->states & CStatd)) {
+    if (mp->mnt_data == NULL
+	&& afs_globalVp && (afs_globalVp->states & CStatd)) {
 	tvp = afs_globalVp;
         error=0;
+    } else if (mp->mnt_data == (qaddr_t)-1) {
+	error = ENOENT;
     } else {
+	struct VenusFid *rootFid = (mp->mnt_data == NULL)
+	    ? &afs_rootFid : (struct VenusFid *)mp->mnt_data;
 	
 	if (!(error = afs_InitReq(&treq, &cr)) &&
 	    !(error = afs_CheckInit())) {
-	    tvp = afs_GetVCache(&afs_rootFid, &treq, (afs_int32 *)0,
+	    tvp = afs_GetVCache(rootFid, &treq, (afs_int32 *)0,
 	                        (struct vcache*)0, WRITE_LOCK);
 	    /* we really want this to stay around */
 	    if (tvp) {
-	        afs_globalVp = tvp;
+		if (mp->mnt_data == NULL)
+		    afs_globalVp = tvp;
 	    } else
 	        error = ENOENT;
 	}
@@ -140,9 +204,12 @@
     AFS_GUNLOCK();
         vn_lock(AFSTOV(tvp), LK_EXCLUSIVE | LK_RETRY, p);
     AFS_GLOCK();
-	afs_globalVFS = mp;
+        if (mp->mnt_data == NULL) {
+	    afs_globalVFS = mp;
+	}	
 	*vpp = AFSTOV(tvp);
         AFSTOV(tvp)->v_flag |= VROOT;
+	AFSTOV(tvp)->v_vfsp = mp;
     }
 
     afs_Trace2(afs_iclSetp, CM_TRACE_VFSROOT, ICL_TYPE_POINTER, *vpp,
@@ -165,7 +232,7 @@
     }
     error = vget(vp, lfl, current_proc());
     if (!error)
-	insmntque(vp, afs_globalVFS);   /* take off free list */
+	insmntque(vp, mp);   /* take off free list */
     return error;
 }
 
Index: src/afs/DARWIN/osi_vnodeops.c
===================================================================
RCS file: /cvs/openafs/src/afs/DARWIN/osi_vnodeops.c,v
retrieving revision 1.4.2.6
diff -u -r1.4.2.6 osi_vnodeops.c
--- src/afs/DARWIN/osi_vnodeops.c	26 Jan 2003 00:02:28 -0000	1.4.2.6
+++ src/afs/DARWIN/osi_vnodeops.c	7 Apr 2003 18:32:53 -0000
@@ -173,6 +173,7 @@
 	return (error);
     }
     vp = AFSTOV(vcp);  /* always get a node if no error */
+    vp->v_vfsp = dvp->v_vfsp;
 
     /* The parent directory comes in locked.  We unlock it on return
        unless the caller wants it left locked.
@@ -237,6 +238,7 @@
 
     if (vcp) {
 	*ap->a_vpp = AFSTOV(vcp);
+	(*ap->a_vpp)->v_vfsp = dvp->v_vfsp;
 	vn_lock(*ap->a_vpp, LK_EXCLUSIVE| LK_RETRY, p);
         if (UBCINFOMISSING(*ap->a_vpp) ||
             UBCINFORECLAIMED(*ap->a_vpp))
@@ -810,11 +812,6 @@
 
     GETNAME();
     p=cnp->cn_proc;
-    if (dvp->v_mount != vp->v_mount) {
-	VOP_ABORTOP(vp, cnp);
-	error = EXDEV;
-	goto out;
-    }
     if (vp->v_type == VDIR) {
 	VOP_ABORTOP(vp, cnp);
 	error = EISDIR;
@@ -859,25 +856,6 @@
     struct proc *p=fcnp->cn_proc;
 
     /*
-     * Check for cross-device rename.
-     */
-    if ((fvp->v_mount != tdvp->v_mount) ||
-	(tvp && (fvp->v_mount != tvp->v_mount))) {
-	error = EXDEV;
-abortit:
-	VOP_ABORTOP(tdvp, tcnp); /* XXX, why not in NFS? */
-	if (tdvp == tvp)
-	    vrele(tdvp);
-	else
-	    vput(tdvp);
-	if (tvp)
-	    vput(tvp);
-	VOP_ABORTOP(fdvp, fcnp); /* XXX, why not in NFS? */
-	vrele(fdvp);
-	vrele(fvp);
-	return (error);
-    }
-    /*
      * if fvp == tvp, we're just removing one name of a pair of
      * directory entries for the same element.  convert call into rename.
      ( (pinched from NetBSD 1.0's ufs_rename())
@@ -885,7 +863,18 @@
     if (fvp == tvp) {
 	if (fvp->v_type == VDIR) {
 	    error = EINVAL;
-	    goto abortit;
+	abortit:
+	    VOP_ABORTOP(tdvp, tcnp); /* XXX, why not in NFS? */
+	    if (tdvp == tvp)
+		vrele(tdvp);
+	    else
+		vput(tdvp);
+	    if (tvp)
+		vput(tvp);
+	    VOP_ABORTOP(fdvp, fcnp); /* XXX, why not in NFS? */
+	    vrele(fdvp);
+	    vrele(fvp);
+	    return (error);
 	}
 
 	/* Release destination completely. */
@@ -968,6 +957,7 @@
     }
     if (vcp) {
 	*ap->a_vpp = AFSTOV(vcp);
+	(*ap->a_vpp)->v_vfsp = dvp->v_vfsp;
 	vn_lock(*ap->a_vpp, LK_EXCLUSIVE|LK_RETRY, p);
     } else
 	*ap->a_vpp = 0;
Index: src/afsd/Makefile.in
===================================================================
RCS file: /cvs/openafs/src/afsd/Makefile.in,v
retrieving revision 1.6.2.3
diff -u -r1.6.2.3 Makefile.in
--- src/afsd/Makefile.in	13 Jan 2003 23:47:18 -0000	1.6.2.3
+++ src/afsd/Makefile.in	7 Apr 2003 18:32:53 -0000
@@ -52,6 +52,8 @@
 		${CC} ${CFLAGS} -g -o afsd afsd.o $(NON_SHARED) $(LDFLAGS) $(AFSLIBS) ${XLIBS} /usr/lib/libdwarf.a /usr/lib/libelf.a ;; \
 	sgi_64 | sgi_65 ) \
 		${CC} ${CFLAGS} -g -o afsd afsd.o $(NON_SHARED) $(LDFLAGS) $(AFSLIBS) ${XLIBS} /usr/lib32/libdwarf.a /usr/lib32/libelf.a ;; \
+	ppc_darwin* ) \
+		${CC} ${CFLAGS} -g -o afsd afsd.o $(NON_SHARED) $(LDFLAGS) $(AFSLIBS) ${XLIBS} -F/System/Library/PrivateFrameworks -framework DiskArbitration ;; \
 	* ) \
 		${CC} ${CFLAGS} -g -o afsd afsd.o $(NON_SHARED) $(LDFLAGS) $(AFSLIBS) ${XLIBS} ;; \
 	esac
Index: src/afsd/afsd.c
===================================================================
RCS file: /cvs/openafs/src/afsd/afsd.c,v
retrieving revision 1.13.2.13
diff -u -r1.13.2.13 afsd.c
--- src/afsd/afsd.c	23 Mar 2003 19:47:55 -0000	1.13.2.13
+++ src/afsd/afsd.c	7 Apr 2003 18:32:59 -0000
@@ -146,6 +146,27 @@
 #ifdef AFS_LINUX20_ENV
 #include <sys/resource.h>
 #endif
+#ifdef AFS_DARWIN_ENV
+#include <mach/mach.h>
+/* Relevant definitions from DiskArbitration.h (not included with Mac OS X) */
+#ifndef __DISKARBITRATION_H
+typedef char    DiskArbDiskIdentifier[1024];
+typedef char    DiskArbMountpoint[1024];
+kern_return_t   DiskArbStart(mach_port_t * portPtr);
+kern_return_t   DiskArbDiskAppearedWithMountpointPing_auto(
+    DiskArbDiskIdentifier diskIdentifier,
+    unsigned flags,
+    DiskArbMountpoint mountpoint);
+kern_return_t   DiskArbDiskDisappearedPing_auto(
+    DiskArbDiskIdentifier diskIdentifier,
+    unsigned flags);
+enum {
+    kDiskArbDiskAppearedNoFlags = 0x00000000,
+    kDiskArbDiskAppearedEjectableMask = 1 << 1,
+    kDiskArbDiskAppearedNetworkDiskMask = 1 << 3
+};
+#endif /* __DISKARBITRATION_H */
+#endif /* AFS_DARWIN_ENV */
 
 #ifndef MOUNT_AFS
 #define	MOUNT_AFS AFS_MOUNT_AFS
@@ -246,6 +267,7 @@
 #endif
 static int enable_dynroot = 0;		/* enable dynroot support */
 static int enable_fakestat = 0;		/* enable fakestat support */
+static int enable_nomount = 0;		/* do not mount */
 #ifdef notdef
 static int inodes = 60;		        /* VERY conservative, but has to be */
 #endif
@@ -1343,6 +1365,10 @@
 	/* -fakestat-all */
 	enable_fakestat = 1;
     }
+    if (as->parms[29].items) {
+	/* -nomount */
+	enable_nomount = 1;
+    }
 
     /*
      * Pull out all the configuration info for the workstation's AFS cache and
@@ -1811,6 +1837,8 @@
 	exit(1);
     }
 
+    if (!enable_nomount) {
+
     mountFlags = 0;	/* Read/write file system, can do setuid() */
 #if	defined(AFS_SUN_ENV) || defined(AFS_SUN5_ENV)
 #ifdef	AFS_SUN5_ENV
@@ -1893,6 +1921,8 @@
 
     HandleMTab();
 
+    }
+
     if (afsd_rmtsys) {
 	if (afsd_verbose)
 	    printf("%s: Forking 'rmtsys' daemon.\n", rn);
@@ -1956,6 +1986,7 @@
     cmd_AddParm(ts, "-dynroot", CMD_FLAG, CMD_OPTIONAL, "Enable dynroot support");
     cmd_AddParm(ts, "-fakestat", CMD_FLAG, CMD_OPTIONAL, "Enable fakestat support for cross-cell mounts");
     cmd_AddParm(ts, "-fakestat-all", CMD_FLAG, CMD_OPTIONAL, "Enable fakestat support for all mounts");
+    cmd_AddParm(ts, "-nomount", CMD_FLAG, CMD_OPTIONAL, "Do not mount AFS");
     return (cmd_Dispatch(argc, argv));
 }
 
@@ -2029,6 +2060,18 @@
 #endif	/* AFS_SGI_ENV */
 #endif	/* AFS_SUN5_ENV */
 #endif	/* unreasonable systems */
+#ifdef AFS_DARWIN_ENV
+    mach_port_t diskarb_port;
+    kern_return_t status;
+
+    status = DiskArbStart(&diskarb_port);
+    if (status == KERN_SUCCESS) {
+	status = DiskArbDiskAppearedWithMountpointPing_auto("AFS",
+	             kDiskArbDiskAppearedNetworkDiskMask, cacheMountDir);
+    }
+
+    return status;
+#endif /* AFS_DARWIN_ENV */
     return 0;
 }
 
