Windows: CM_ERROR_INEXACT_MATCH is not a fatal error
[openafs.git] / src / WINNT / afsd / cm_ioctl.c
index d9bbc60..c6230a4 100644 (file)
@@ -104,8 +104,7 @@ cm_FlushFile(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp)
 
 #ifdef AFS_FREELANCE_CLIENT
     if ( scp->fid.cell == AFS_FAKE_ROOT_CELL_ID && scp->fid.volume == AFS_FAKE_ROOT_VOL_ID ) {
-       cm_noteLocalMountPointChange(FALSE);
-       return 0;
+       return CM_ERROR_NOACCESS;
     }
 #endif
 
@@ -124,6 +123,11 @@ cm_FlushFile(cm_scache_t *scp, cm_user_t *userp, cm_req_t *reqp)
         lock_ObtainWrite(&scp->dirlock);
     lock_ObtainWrite(&scp->rw);
     cm_DiscardSCache(scp);
+    if (scp->fileType == CM_SCACHETYPE_MOUNTPOINT ||
+       scp->fileType == CM_SCACHETYPE_SYMLINK) {
+       scp->mpDataVersion = CM_SCACHE_VERSION_BAD;
+       scp->mountPointStringp[0] = '\0';
+    }
     if (scp->fileType == CM_SCACHETYPE_DIRECTORY) {
         cm_ResetSCacheDirectory(scp, 1);
         lock_ReleaseWrite(&scp->dirlock);
@@ -166,8 +170,7 @@ cm_FlushVolume(cm_user_t *userp, cm_req_t *reqp, afs_uint32 cell, afs_uint32 vol
 
 #ifdef AFS_FREELANCE_CLIENT
     if ( cell == AFS_FAKE_ROOT_CELL_ID && volume == AFS_FAKE_ROOT_VOL_ID ) {
-       cm_noteLocalMountPointChange(FALSE);
-       return 0;
+       return CM_ERROR_NOACCESS;
     }
 #endif
 
@@ -187,7 +190,7 @@ cm_FlushVolume(cm_user_t *userp, cm_req_t *reqp, afs_uint32 cell, afs_uint32 vol
     }
     lock_ReleaseWrite(&cm_scacheLock);
 
-    return code;
+    return 0;
 }
 
 /*
@@ -439,7 +442,7 @@ cm_IoctlGetACL(cm_ioctl_t *ioctlp, cm_user_t *userp, cm_scache_t *scp, cm_req_t
             code = RXAFS_FetchACL(rxconnp, &afid, &acl, &fileStatus, &volSync);
             rx_PutConnection(rxconnp);
 
-        } while (cm_Analyze(connp, userp, reqp, &scp->fid, &volSync, NULL, NULL, code));
+        } while (cm_Analyze(connp, userp, reqp, &scp->fid, NULL, 0, &fileStatus, &volSync, NULL, NULL, code));
         code = cm_MapRPCError(code, reqp);
 
         if (code)
@@ -537,7 +540,7 @@ cm_IoctlSetACL(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scache_t *scp,
             code = RXAFS_StoreACL(rxconnp, &fid, &acl, &fileStatus, &volSync);
             rx_PutConnection(rxconnp);
 
-        } while (cm_Analyze(connp, userp, reqp, &scp->fid, &volSync, NULL, NULL, code));
+        } while (cm_Analyze(connp, userp, reqp, &scp->fid, NULL, 1, &fileStatus, &volSync, NULL, NULL, code));
         code = cm_MapRPCError(code, reqp);
 
         /* invalidate cache info, since we just trashed the ACL cache */
@@ -579,7 +582,11 @@ cm_IoctlFlushAllVolumes(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_req_t
     }
     lock_ReleaseWrite(&cm_scacheLock);
 
-    return code;
+#ifdef AFS_FREELANCE_CLIENT
+    cm_noteLocalMountPointChange(FALSE);
+#endif
+
+    return 0;
 }
 
 /*
@@ -591,21 +598,15 @@ cm_IoctlFlushAllVolumes(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_req_t
 afs_int32
 cm_IoctlFlushVolume(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scache_t *scp, cm_req_t *reqp)
 {
-    afs_int32 code;
-    afs_uint32 volume;
-    afs_uint32 cell;
 
 #ifdef AFS_FREELANCE_CLIENT
     if ( scp->fid.cell == AFS_FAKE_ROOT_CELL_ID && scp->fid.volume == AFS_FAKE_ROOT_VOL_ID ) {
-       code = CM_ERROR_NOACCESS;
-    } else
-#endif
-    {
-        volume = scp->fid.volume;
-        cell = scp->fid.cell;
-        code = cm_FlushVolume(userp, reqp, cell, volume);
+       cm_noteLocalMountPointChange(FALSE);
+       return 0;
     }
-    return code;
+#endif
+
+    return cm_FlushVolume(userp, reqp, scp->fid.cell, scp->fid.volume);
 }
 
 /*
@@ -621,13 +622,11 @@ cm_IoctlFlushFile(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scache_t *s
 
 #ifdef AFS_FREELANCE_CLIENT
     if ( scp->fid.cell == AFS_FAKE_ROOT_CELL_ID && scp->fid.volume == AFS_FAKE_ROOT_VOL_ID ) {
-       code = CM_ERROR_NOACCESS;
-    } else
-#endif
-    {
-        cm_FlushFile(scp, userp, reqp);
+       return CM_ERROR_NOACCESS;
     }
-    return 0;
+#endif
+
+    return cm_FlushFile(scp, userp, reqp);
 }
 
 
@@ -710,7 +709,7 @@ cm_IoctlSetVolumeStatus(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scach
                                          &storeStat, volName, offLineMsg, motd);
             rx_PutConnection(rxconnp);
 
-        } while (cm_Analyze(tcp, userp, reqp, &scp->fid, NULL, NULL, NULL, code));
+        } while (cm_Analyze(tcp, userp, reqp, &scp->fid, NULL, 1, NULL, NULL, NULL, NULL, code));
         code = cm_MapRPCError(code, reqp);
     }
 
@@ -774,20 +773,30 @@ cm_IoctlGetVolumeStatus(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scach
     } else
 #endif
     {
-       Name = volName;
-       OfflineMsg = offLineMsg;
-       MOTD = motd;
-       do {
-           code = cm_ConnFromFID(&scp->fid, userp, reqp, &connp);
-           if (code) continue;
+        cm_fid_t    vfid;
+        cm_scache_t *vscp;
+
+        cm_SetFid(&vfid, scp->fid.cell, scp->fid.volume, 1, 1);
+        code = cm_GetSCache(&vfid, NULL, &vscp, userp, reqp);
+        if (code)
+            return code;
+
+        Name = volName;
+        OfflineMsg = offLineMsg;
+        MOTD = motd;
+        do {
+            code = cm_ConnFromFID(&vfid, userp, reqp, &connp);
+            if (code) continue;
 
-           rxconnp = cm_GetRxConn(connp);
-           code = RXAFS_GetVolumeStatus(rxconnp, scp->fid.volume,
-                                        &volStat, &Name, &OfflineMsg, &MOTD);
-           rx_PutConnection(rxconnp);
+            rxconnp = cm_GetRxConn(connp);
+            code = RXAFS_GetVolumeStatus(rxconnp, vfid.volume,
+                                         &volStat, &Name, &OfflineMsg, &MOTD);
+            rx_PutConnection(rxconnp);
+
+        } while (cm_Analyze(connp, userp, reqp, &vfid, NULL, 0, NULL, NULL, NULL, NULL, code));
+        code = cm_MapRPCError(code, reqp);
 
-       } while (cm_Analyze(connp, userp, reqp, &scp->fid, NULL, NULL, NULL, code));
-       code = cm_MapRPCError(code, reqp);
+        cm_ReleaseSCache(vscp);
     }
 
     if (code)
@@ -1040,7 +1049,7 @@ cm_IoctlWhereIs(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scache_t *scp
 
         cp = ioctlp->outDatap;
 
-        tsrpp = cm_GetVolServers(tvp, volume, userp, reqp);
+        tsrpp = cm_GetVolServers(tvp, volume, userp, reqp, NULL);
         if (tsrpp == NULL) {
             code = CM_ERROR_NOSUCHVOLUME;
         } else {
@@ -1080,7 +1089,7 @@ cm_IoctlStatMountPoint(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scache
     cp = cm_ParseIoctlStringAlloc(ioctlp, NULL);
 
     code = cm_Lookup(dscp, cp[0] ? cp : L".", CM_FLAG_NOMOUNTCHASE, userp, reqp, &scp);
-    if (code)
+    if (code && code != CM_ERROR_INEXACT_MATCH)
         goto done_2;
 
     lock_ObtainWrite(&scp->rw);
@@ -1137,7 +1146,7 @@ cm_IoctlDeleteMountPoint(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scac
     code = cm_Lookup(dscp, cp[0] ? cp : L".", CM_FLAG_NOMOUNTCHASE, userp, reqp, &scp);
 
     /* if something went wrong, bail out now */
-    if (code)
+    if (code && code != CM_ERROR_INEXACT_MATCH)
         goto done3;
 
     lock_ObtainWrite(&scp->rw);
@@ -1288,7 +1297,9 @@ cm_IoctlCheckServers(struct cm_ioctl *ioctlp, struct cm_user *userp)
     /* now return the current down server list */
     cp = ioctlp->outDatap;
     lock_ObtainRead(&cm_serverLock);
-    for (tsp = cm_allServersp; tsp; tsp=tsp->allNextp) {
+    for (tsp = cm_serversAllFirstp;
+        tsp;
+        tsp = (cm_server_t *)osi_QNext(&tsp->allq)) {
         if (cellp && tsp->cellp != cellp)
             continue;  /* cell spec'd and wrong */
         if (tsp->flags & CM_SERVERFLAG_DOWN) {
@@ -1297,7 +1308,9 @@ cm_IoctlCheckServers(struct cm_ioctl *ioctlp, struct cm_user *userp)
              * is up, do not report the server as down.
              */
             if (tsp->type == CM_SERVER_FILE) {
-                for (csp = cm_allServersp; csp; csp=csp->allNextp) {
+                for (csp = cm_serversAllFirstp;
+                    csp;
+                    csp = (cm_server_t *)osi_QNext(&csp->allq)) {
                     if (csp->type == CM_SERVER_FILE &&
                         !(csp->flags & CM_SERVERFLAG_DOWN) &&
                         afs_uuid_equal(&tsp->uuid, &csp->uuid)) {
@@ -1426,13 +1439,16 @@ cm_IoctlGetCacheParms(struct cm_ioctl *ioctlp, struct cm_user *userp)
 
     memset(&parms, 0, sizeof(parms));
 
-    /* first we get, in 1K units, the cache size */
+    /* the cache size */
     parms.parms[0] = cm_data.buf_nbuffers * (cm_data.buf_blockSize / 1024);
 
-    /* and then the actual # of buffers in use (not in the free list, I guess,
-     * will be what we do).
+    /*
+     * the used cache space.  this number is not available on windows.
+     * the cm_data.buf_freeCount represents all buffers eligible for recycling.
+     * so we report the entire cache in use since reporting 0 in use disturbs
+     * many users.
      */
-    parms.parms[1] = (cm_data.buf_nbuffers - cm_data.buf_freeCount) * (cm_data.buf_blockSize / 1024);
+    parms.parms[1] = cm_data.buf_usedCount * (cm_data.buf_blockSize / 1024);
 
     memcpy(ioctlp->outDatap, &parms, sizeof(parms));
     ioctlp->outDatap += sizeof(parms);
@@ -1925,9 +1941,9 @@ cm_IoctlSetSPrefs(struct cm_ioctl *ioctlp, struct cm_user *userp)
         if ( tsp )             /* an existing server - ref count increased */
         {
             lock_ObtainMutex(&tsp->mx);
-            tsp->ipRank = rank;
+            tsp->adminRank = rank;
             _InterlockedOr(&tsp->flags, CM_SERVERFLAG_PREF_SET);
-           tsp->adminRank = tsp->ipRank;
+            cm_RankServer(tsp);
             lock_ReleaseMutex(&tsp->mx);
 
             switch (type) {
@@ -1949,11 +1965,9 @@ cm_IoctlSetSPrefs(struct cm_ioctl *ioctlp, struct cm_user *userp)
         {
             tsp = cm_NewServer(&tmp, type, NULL, NULL, CM_FLAG_NOPROBE); /* refcount = 1 */
             lock_ObtainMutex(&tsp->mx);
-            tsp->ipRank = rank;
+            tsp->adminRank = rank;
             _InterlockedOr(&tsp->flags, CM_SERVERFLAG_PREF_SET);
-           tsp->adminRank = tsp->ipRank;
             lock_ReleaseMutex(&tsp->mx);
-            tsp->ipRank = rank;
         }
        cm_PutServer(tsp);  /* decrease refcount */
     }
@@ -1983,7 +1997,9 @@ cm_IoctlGetSPrefs(struct cm_ioctl *ioctlp, struct cm_user *userp)
 
     lock_ObtainRead(&cm_serverLock); /* get server lock */
 
-    for (tsp=cm_allServersp, i=0; tsp && noServers; tsp=tsp->allNextp,i++){
+    for (tsp = cm_serversAllFirstp, i=0;
+        tsp && noServers;
+        tsp = (cm_server_t *)osi_QNext(&tsp->allq),i++){
         if (spin->offset > i) {
             continue;    /* catch up to where we left off */
         }
@@ -1994,7 +2010,7 @@ cm_IoctlGetSPrefs(struct cm_ioctl *ioctlp, struct cm_user *userp)
             continue;   /* ignore vlservers */
 
         srvout->host = tsp->addr.sin_addr;
-        srvout->rank = tsp->ipRank;
+        srvout->rank = tsp->activeRank;
         srvout++;
         spout->num_servers++;
         noServers--;
@@ -2042,6 +2058,13 @@ cm_IoctlCreateMountPoint(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scac
 
     /* Extract the possibly partial cell name */
     mpp = cm_ParseIoctlStringAlloc(ioctlp, NULL);
+
+    len = cm_ClientStrLen(mpp);
+    if (len <= 1 || mpp[len-1] != L'.') {
+        code = CM_ERROR_INVAL;
+        goto done;
+    }
+
     cell = cm_ClientCharNext(mpp);
     if (cp = cm_ClientStrChr(cell, ':')) {
 
@@ -2059,7 +2082,8 @@ cm_IoctlCreateMountPoint(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scac
             goto done;
         }
 
-        StringCbPrintfA(mpInfo, sizeof(mpInfo), "%c%s:%s.", (char) *mpp,
+        /* fsvolume includes the trailing dot */
+        StringCbPrintfA(mpInfo, sizeof(mpInfo), "%c%s:%s", (char) *mpp,
                         fullCell, fsvolume);
 
     } else {
@@ -2069,10 +2093,9 @@ cm_IoctlCreateMountPoint(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scac
         cellp = cm_FindCellByID(dscp->fid.cell, CM_FLAG_NOPROBE);
     }
 
-    /* remove the trailing dot if it is present */
+    /* remove the trailing dot */
     len = strlen(fsvolume);
-    if (len > 1 && fsvolume[len-1] == '.')
-        fsvolume[len-1] = '\0';
+    fsvolume[len-1] = '\0';
 
     /* validate the target info */
     if (cm_VolNameIsID(fsvolume)) {
@@ -2106,10 +2129,16 @@ cm_IoctlCreateMountPoint(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scac
         code = cm_SymLink(dscp, leaf, mpInfo, 0, &tattr, userp, reqp, NULL);
     }
 
-    if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
-        smb_NotifyChange(FILE_ACTION_ADDED,
-                         FILE_NOTIFY_CHANGE_DIR_NAME,
-                         dscp, leaf, NULL, TRUE);
+    if (code == 0) {
+        if (dscp->flags & CM_SCACHEFLAG_ANYWATCH)
+            smb_NotifyChange(FILE_ACTION_ADDED,
+                             FILE_NOTIFY_CHANGE_DIR_NAME,
+                             dscp, leaf, NULL, TRUE);
+
+        if (RDR_Initialized)
+            RDR_InvalidateObject(dscp->fid.cell, dscp->fid.volume, dscp->fid.vnode, dscp->fid.unique,
+                                 dscp->fid.hash, dscp->fileType, AFS_INVALIDATE_DATA_VERSION);
+    }
 
   done:
     if (volp)
@@ -2175,11 +2204,18 @@ cm_IoctlSymlink(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scache_t *dsc
         code = cm_SymLink(dscp, leaf, cp, 0, &tattr, userp, reqp, NULL);
     }
 
-    if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
-        smb_NotifyChange(FILE_ACTION_ADDED,
-                          FILE_NOTIFY_CHANGE_FILE_NAME
-                          | FILE_NOTIFY_CHANGE_DIR_NAME,
-                          dscp, leaf, NULL, TRUE);
+    if (code == 0) {
+        if (dscp->flags & CM_SCACHEFLAG_ANYWATCH)
+            smb_NotifyChange(FILE_ACTION_ADDED,
+                             FILE_NOTIFY_CHANGE_FILE_NAME
+                             | FILE_NOTIFY_CHANGE_DIR_NAME,
+                             dscp, leaf, NULL, TRUE);
+
+        if (RDR_Initialized)
+            RDR_InvalidateObject(dscp->fid.cell, dscp->fid.volume, dscp->fid.vnode, dscp->fid.unique,
+                                 dscp->fid.hash, dscp->fileType, AFS_INVALIDATE_DATA_VERSION);
+    }
+
     return code;
 }
 
@@ -2209,7 +2245,7 @@ cm_IoctlListlink(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scache_t *ds
     clientp = cm_Utf8ToClientStringAlloc(cp, -1, NULL);
     code = cm_Lookup(dscp, clientp[0] ? clientp : L".", CM_FLAG_NOMOUNTCHASE, userp, reqp, &scp);
     free(clientp);
-    if (code)
+    if (code && code != CM_ERROR_INEXACT_MATCH)
         return code;
 
     /* Check that it's a real symlink */
@@ -2278,7 +2314,7 @@ cm_IoctlIslink(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scache_t *dscp
     clientp = cm_Utf8ToClientStringAlloc(cp, -1, NULL);
     code = cm_Lookup(dscp, clientp[0] ? clientp : L".", CM_FLAG_NOMOUNTCHASE, userp, reqp, &scp);
     free(clientp);
-    if (code)
+    if (code && code != CM_ERROR_INEXACT_MATCH)
         return code;
 
     /* Check that it's a real symlink */
@@ -2316,7 +2352,7 @@ cm_IoctlDeletelink(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scache_t *
     code = cm_Lookup(dscp, clientp[0] ? clientp : L".", CM_FLAG_NOMOUNTCHASE, userp, reqp, &scp);
 
     /* if something went wrong, bail out now */
-    if (code)
+    if (code && code != CM_ERROR_INEXACT_MATCH)
         goto done3;
 
     lock_ObtainWrite(&scp->rw);
@@ -3283,11 +3319,11 @@ cm_IoctlMemoryDump(struct cm_ioctl *ioctlp, struct cm_user *userp)
     /* dump all interesting data */
     cm_MemDumpDirStats(hLogFile, cookie, 1);
     cm_MemDumpBPlusStats(hLogFile, cookie, 1);
-    cm_DumpCells(hLogFile, cookie, 1);
-    cm_DumpVolumes(hLogFile, cookie, 1);
-    cm_DumpSCache(hLogFile, cookie, 1);
-    cm_DumpBufHashTable(hLogFile, cookie, 1);
-    cm_DumpServers(hLogFile, cookie, 1);
+    cm_DumpCells(hLogFile, cookie, !RDR_Initialized);
+    cm_DumpVolumes(hLogFile, cookie, !RDR_Initialized);
+    cm_DumpSCache(hLogFile, cookie, !RDR_Initialized);
+    cm_DumpBufHashTable(hLogFile, cookie, !RDR_Initialized);
+    cm_DumpServers(hLogFile, cookie, !RDR_Initialized);
     smb_DumpVCP(hLogFile, cookie, 1);
     rx_DumpCalls(hLogFile, cookie);
     rx_DumpPackets(hLogFile, cookie);
@@ -3308,17 +3344,18 @@ cm_CheckServersStatus(cm_serverRef_t *serversp)
     afs_int32 code = 0;
     cm_serverRef_t *tsrp;
     cm_server_t *tsp;
-    int someBusy = 0, someOffline = 0, allOffline = 1, allBusy = 1, allDown = 1;
+    int someBusy = 0, someOffline = 0, allOffline = 1, allBusy = 1, allDown = 1, allDeleted = 1;
 
     if (serversp == NULL) {
-       osi_Log1(afsd_logp, "cm_CheckServersStatus returning 0x%x", CM_ERROR_ALLDOWN);
-       return CM_ERROR_ALLDOWN;
+       osi_Log1(afsd_logp, "cm_CheckServersStatus returning 0x%x", CM_ERROR_EMPTY);
+       return CM_ERROR_EMPTY;
     }
 
     lock_ObtainRead(&cm_serverLock);
     for (tsrp = serversp; tsrp; tsrp=tsrp->next) {
         if (tsrp->status == srv_deleted)
             continue;
+        allDeleted = 0;
         if (tsp = tsrp->server) {
             cm_GetServerNoLock(tsp);
             if (!(tsp->flags & CM_SERVERFLAG_DOWN)) {
@@ -3341,7 +3378,9 @@ cm_CheckServersStatus(cm_serverRef_t *serversp)
     }
     lock_ReleaseRead(&cm_serverLock);
 
-    if (allDown)
+    if (allDeleted)
+        code = CM_ERROR_EMPTY;
+    else if (allDown)
         code = CM_ERROR_ALLDOWN;
     else if (allBusy)
         code = CM_ERROR_ALLBUSY;
@@ -3564,3 +3603,69 @@ cm_IoctlSetUnixMode(struct cm_ioctl *ioctlp, struct cm_user *userp, cm_scache_t
     }
     return code;
 }
+
+/*
+ * VIOC_GETVERIFYDATA internals.
+ *
+ * Assumes that pioctl path has been parsed or skipped.
+ */
+afs_int32
+cm_IoctlGetVerifyData(cm_ioctl_t *ioctlp)
+{
+    memcpy(ioctlp->outDatap, &cm_verifyData, sizeof(cm_verifyData));
+    ioctlp->outDatap += sizeof(cm_verifyData);
+
+    return 0;
+}
+
+/*
+ * VIOC_SETVERIFYDATA internals.
+ *
+ * Assumes that pioctl path has been parsed or skipped.
+ */
+afs_int32
+cm_IoctlSetVerifyData(cm_ioctl_t *ioctlp)
+{
+    memcpy(&cm_verifyData, ioctlp->inDatap, sizeof(cm_verifyData));
+
+    return 0;
+}
+
+/*
+ * VIOC_GETCALLERACCESS internals.
+ *
+ * Assumes that pioctl path has been parsed or skipped.
+ */
+
+afs_int32
+cm_IoctlGetCallerAccess(cm_ioctl_t *ioctlp, struct cm_user *userp, cm_scache_t *scp, cm_req_t *reqp)
+{
+    afs_int32 code;
+    afs_uint32 rights = 0;
+    int haveRights = 0;
+    char *cp;
+
+    lock_ObtainWrite(&scp->rw);
+    code = cm_SyncOp(scp, NULL, userp, reqp, 0,
+                     CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+    if (code == 0) {
+        haveRights = cm_HaveAccessRights(scp, userp, reqp, 0xFF0000FF, &rights);
+        cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+    }
+    lock_ReleaseWrite(&scp->rw);
+
+    cp = ioctlp->outDatap;
+    /* Copy all this junk into msg->im_data, keeping track of the lengths. */
+    if (haveRights)
+        memcpy(cp, (char *)&rights, sizeof(afs_uint32));
+    else
+        memcpy(cp, (char *)&scp->anyAccess, sizeof(afs_uint32));
+    cp += sizeof(afs_uint32);
+    memcpy(cp, (char *)&scp->anyAccess, sizeof(afs_uint32));
+    cp += sizeof(afs_uint32);
+
+    /* return new size */
+    ioctlp->outDatap = cp;
+
+    return code;
+}