/*
* Copyright (c) 2008 Secure Endpoints, Inc.
- * Copyright (c) 2009-2013 Your File System, Inc.
+ * Copyright (c) 2009-2014 Your File System, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
fid->hash = FileId->Hash;
}
+unsigned long
+RDR_ExtAttributes(cm_scache_t *scp)
+{
+ unsigned long attrs;
+
+ if (scp->fileType == CM_SCACHETYPE_DIRECTORY ||
+ scp->fid.vnode & 0x1)
+ {
+ attrs = SMB_ATTR_DIRECTORY;
+#ifdef SPECIAL_FOLDERS
+ attrs |= SMB_ATTR_SYSTEM; /* FILE_ATTRIBUTE_SYSTEM */
+#endif /* SPECIAL_FOLDERS */
+ } else if ( scp->fileType == CM_SCACHETYPE_MOUNTPOINT ||
+ scp->fileType == CM_SCACHETYPE_DFSLINK ||
+ scp->fileType == CM_SCACHETYPE_INVALID)
+ {
+ attrs = SMB_ATTR_DIRECTORY | SMB_ATTR_REPARSE_POINT;
+ } else if ( scp->fileType == CM_SCACHETYPE_SYMLINK) {
+ attrs = SMB_ATTR_REPARSE_POINT;
+ } else {
+ attrs = 0;
+ }
+
+ if ((scp->unixModeBits & 0200) == 0)
+ attrs |= SMB_ATTR_READONLY; /* Read-only */
+
+ if (attrs == 0)
+ attrs = SMB_ATTR_NORMAL; /* FILE_ATTRIBUTE_NORMAL */
+
+ return attrs;
+}
+
DWORD
RDR_SetInitParams( OUT AFSRedirectorInitInfo **ppRedirInitInfo, OUT DWORD * pRedirInitInfoLen )
{
(*ppRedirInitInfo)->CacheBlockSize = cm_data.blockSize;
(*ppRedirInitInfo)->MaxPathLinkCount = MAX_FID_COUNT;
(*ppRedirInitInfo)->NameArrayLength = MAX_FID_COUNT;
+ (*ppRedirInitInfo)->GlobalReparsePointPolicy = rdr_ReparsePointPolicy;
if (cm_virtualCache || cm_data.bufferSize <= maxMemoryCacheSize) {
osi_Log0(afsd_logp, "RDR_SetInitParams Initializing Memory Extent Interface");
(*ppRedirInitInfo)->MemoryCacheOffset.QuadPart = (LONGLONG)cm_data.bufDataBaseAddress;
if (code) {
osi_Log2(afsd_logp, "RDR_PopulateCurrentEntry RDR_BulkStatLookup failed for scp=0x%p code=0x%x",
scp, code);
- return code;
+ if (code != CM_ERROR_NOACCESS)
+ return code;
}
lock_ObtainWrite(&scp->rw);
/*
pCurrentEntry->ChangeTime = pCurrentEntry->CreationTime;
pCurrentEntry->EndOfFile = scp->length;
- pCurrentEntry->AllocationSize = scp->length;
+ pCurrentEntry->AllocationSize.QuadPart =
+ ((scp->length.QuadPart/1024)+1)*1024;
if (bMustFake) {
switch (scp->fileType) {
break;
case CM_SCACHETYPE_MOUNTPOINT:
case CM_SCACHETYPE_INVALID:
+ case CM_SCACHETYPE_DFSLINK:
pCurrentEntry->FileAttributes = SMB_ATTR_DIRECTORY | SMB_ATTR_REPARSE_POINT;
break;
case CM_SCACHETYPE_SYMLINK:
pCurrentEntry->FileAttributes = SMB_ATTR_NORMAL;
}
} else
- pCurrentEntry->FileAttributes = smb_ExtAttributes(scp);
+ pCurrentEntry->FileAttributes = RDR_ExtAttributes(scp);
pCurrentEntry->EaSize = 0;
pCurrentEntry->Links = scp->linkCount;
if (!(dwFlags & RDR_POP_NO_GETSTATUS))
cm_SyncOpDone( scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
- if ((dwFlags & RDR_POP_NO_GETSTATUS) || !cm_HaveCallback(scp)) {
- pCurrentEntry->TargetNameOffset = 0;
- pCurrentEntry->TargetNameLength = 0;
- }
- else
+ pCurrentEntry->TargetNameOffset = 0;
+ pCurrentEntry->TargetNameLength = 0;
+ if (!(dwFlags & RDR_POP_NO_GETSTATUS) && cm_HaveCallback(scp)) {
switch (scp->fileType) {
case CM_SCACHETYPE_MOUNTPOINT:
- if (dwFlags & RDR_POP_FOLLOW_MOUNTPOINTS) {
+ {
if ((code2 = cm_ReadMountPoint(scp, userp, reqp)) == 0) {
cm_scache_t *targetScp = NULL;
#endif
pCurrentEntry->TargetNameLength = (ULONG)(sizeof(WCHAR) * len);
- code2 = cm_FollowMountPoint(scp, dscp, userp, reqp, &targetScp);
-
- if (code2 == 0) {
- pCurrentEntry->TargetFileId.Cell = targetScp->fid.cell;
- pCurrentEntry->TargetFileId.Volume = targetScp->fid.volume;
- pCurrentEntry->TargetFileId.Vnode = targetScp->fid.vnode;
- pCurrentEntry->TargetFileId.Unique = targetScp->fid.unique;
- pCurrentEntry->TargetFileId.Hash = targetScp->fid.hash;
-
- osi_Log4(afsd_logp, "RDR_PopulateCurrentEntry target FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
- pCurrentEntry->TargetFileId.Cell, pCurrentEntry->TargetFileId.Volume,
- pCurrentEntry->TargetFileId.Vnode, pCurrentEntry->TargetFileId.Unique);
-
- cm_ReleaseSCache(targetScp);
- } else {
- osi_Log2(afsd_logp, "RDR_PopulateCurrentEntry cm_FollowMountPoint failed scp=0x%p code=0x%x",
- scp, code2);
+ if (dwFlags & RDR_POP_FOLLOW_MOUNTPOINTS) {
+ code2 = cm_FollowMountPoint(scp, dscp, userp, reqp, &targetScp);
+ if (code2 == 0) {
+ pCurrentEntry->TargetFileId.Cell = targetScp->fid.cell;
+ pCurrentEntry->TargetFileId.Volume = targetScp->fid.volume;
+ pCurrentEntry->TargetFileId.Vnode = targetScp->fid.vnode;
+ pCurrentEntry->TargetFileId.Unique = targetScp->fid.unique;
+ pCurrentEntry->TargetFileId.Hash = targetScp->fid.hash;
+
+ osi_Log4(afsd_logp, "RDR_PopulateCurrentEntry target FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
+ pCurrentEntry->TargetFileId.Cell, pCurrentEntry->TargetFileId.Volume,
+ pCurrentEntry->TargetFileId.Vnode, pCurrentEntry->TargetFileId.Unique);
+
+ cm_ReleaseSCache(targetScp);
+ } else {
+ osi_Log2(afsd_logp, "RDR_PopulateCurrentEntry cm_FollowMountPoint failed scp=0x%p code=0x%x",
+ scp, code2);
+ if (code2 == CM_ERROR_TOO_MANY_SYMLINKS)
+ code = CM_ERROR_TOO_MANY_SYMLINKS;
+ }
}
} else {
osi_Log2(afsd_logp, "RDR_PopulateCurrentEntry cm_ReadMountPoint failed scp=0x%p code=0x%x",
wtarget = (WCHAR *)((PBYTE)pCurrentEntry + pCurrentEntry->TargetNameOffset);
if (dwFlags & RDR_POP_EVALUATE_SYMLINKS) {
- char * mp;
code2 = cm_HandleLink(scp, userp, reqp);
if (code2 == 0) {
- mp = scp->mountPointStringp;
- len = strlen(mp);
- if ( len != 0 ) {
- /* Strip off the msdfs: prefix from the target name for the file system */
- if (scp->fileType == CM_SCACHETYPE_DFSLINK) {
- osi_Log0(afsd_logp, "RDR_PopulateCurrentEntry DFSLink Detected");
- pCurrentEntry->FileType = scp->fileType;
-
- if (!strncmp("msdfs:", mp, 6)) {
- mp += 6;
- len -= 6;
- }
+ if (scp->mountPointStringp[0]) {
+ char * mp;
+ char * s;
+ size_t offset = 0;
+ size_t wtarget_len = 0;
+
+ len = strlen(scp->mountPointStringp) + 1;
+ mp = strdup(scp->mountPointStringp);
+
+ for (s=mp; *s; s++) {
+ if (*s == '/')
+ *s = '\\';
}
- /* only send one slash to the redirector */
- if (mp[0] == '\\' && mp[1] == '\\') {
- mp++;
- len--;
+
+ if (strncmp("msdfs:", mp, 6) == 0) {
+ offset = 6;
}
+
+
+ if ( mp[offset + 1] == ':' && mp[offset] != '\\') {
+ /* Local drive letter. Must return <drive>:\<path> */
+ pCurrentEntry->FileType = CM_SCACHETYPE_DFSLINK;
+ wtarget_len = len - offset;
#ifdef UNICODE
- cch = MultiByteToWideChar( CP_UTF8, 0, mp,
- len * sizeof(char),
- wtarget,
- len * sizeof(WCHAR));
+ cch = MultiByteToWideChar( CP_UTF8, 0, &mp[offset],
+ wtarget_len * sizeof(char),
+ wtarget,
+ wtarget_len * sizeof(WCHAR));
#else
- mbstowcs(wtarget, mp, len);
+ mbstowcs(wtarget, &mp[offset], wtarget_len);
#endif
- }
- pCurrentEntry->TargetNameLength = (ULONG)(sizeof(WCHAR) * len);
+ } else if (mp[offset] == '\\') {
+ size_t nbNameLen = strlen(cm_NetbiosName);
+
+ if ( strnicmp(&mp[offset + 1], cm_NetbiosName, nbNameLen) == 0 &&
+ mp[offset + nbNameLen + 1] == '\\')
+ {
+ /* an AFS symlink */
+ pCurrentEntry->FileType = CM_SCACHETYPE_SYMLINK;
+ wtarget_len = len - offset;
+#ifdef UNICODE
+ cch = MultiByteToWideChar( CP_UTF8, 0, &mp[offset],
+ wtarget_len * sizeof(char),
+ wtarget,
+ wtarget_len * sizeof(WCHAR));
+#else
+ mbstowcs(wtarget, &mp[offset], wtarget_len);
+#endif
+ } else if ( mp[offset + 1] == '\\' &&
+ strnicmp(&mp[offset + 2], cm_NetbiosName, strlen(cm_NetbiosName)) == 0 &&
+ mp[offset + nbNameLen + 2] == '\\')
+ {
+ /* an AFS symlink */
+ pCurrentEntry->FileType = CM_SCACHETYPE_SYMLINK;
+ wtarget_len = len - offset - 1;
+#ifdef UNICODE
+ cch = MultiByteToWideChar( CP_UTF8, 0, &mp[offset + 1],
+ wtarget_len * sizeof(char),
+ wtarget,
+ wtarget_len * sizeof(WCHAR));
+#else
+ mbstowcs(wtarget, &mp[offset + 1], wtarget_len);
+#endif
+ } else {
+ /*
+ * treat as a UNC path. Needs to be \<server>\<share\<path>
+ */
+ pCurrentEntry->FileType = CM_SCACHETYPE_DFSLINK;
+
+ if ( mp[offset] == '\\' && mp[offset + 1] == '\\')
+ offset++;
+
+ wtarget_len = len - offset;
+#ifdef UNICODE
+ cch = MultiByteToWideChar( CP_UTF8, 0, &mp[offset],
+ wtarget_len * sizeof(char),
+ wtarget,
+ wtarget_len * sizeof(WCHAR));
+#else
+ mbstowcs(wtarget, &mp[offset], wtarget_len);
+#endif
+ }
+ } else {
+ /* Relative AFS Symlink */
+ pCurrentEntry->FileType = CM_SCACHETYPE_SYMLINK;
+ wtarget_len = len - offset;
+#ifdef UNICODE
+ cch = MultiByteToWideChar( CP_UTF8, 0, &mp[offset],
+ wtarget_len * sizeof(char),
+ wtarget,
+ wtarget_len * sizeof(WCHAR));
+#else
+ mbstowcs(wtarget, &mp[offset], wtarget_len);
+#endif
+ }
+
+ free(mp);
+
+ pCurrentEntry->TargetNameLength = (ULONG)(sizeof(WCHAR) * (wtarget_len - 1));
+ }
} else {
osi_Log2(afsd_logp, "RDR_PopulateCurrentEntry cm_HandleLink failed scp=0x%p code=0x%x",
scp, code2);
pCurrentEntry->TargetNameOffset = 0;
pCurrentEntry->TargetNameLength = 0;
}
+ }
lock_ReleaseWrite(&scp->rw);
dwEntryLength += pCurrentEntry->FileNameLength + pCurrentEntry->TargetNameLength;
pCurrentEntry->FileId.Unique = fidp->unique;
pCurrentEntry->FileId.Hash = fidp->hash;
- pCurrentEntry->FileType = CM_SCACHETYPE_UNKNOWN;
-
pCurrentEntry->DataVersion.QuadPart = CM_SCACHE_VERSION_BAD;
cm_LargeSearchTimeFromUnixTime(&ft, 0);
pCurrentEntry->EndOfFile.QuadPart = 0;
pCurrentEntry->AllocationSize.QuadPart = 0;
- pCurrentEntry->FileAttributes = 0;
+ if (fidp->vnode & 0x1) {
+ pCurrentEntry->FileType = CM_SCACHETYPE_DIRECTORY;
+ pCurrentEntry->FileAttributes = SMB_ATTR_DIRECTORY;
+ } else {
+ pCurrentEntry->FileType = CM_SCACHETYPE_UNKNOWN;
+ pCurrentEntry->FileAttributes = SMB_ATTR_NORMAL;
pCurrentEntry->EaSize = 0;
+ }
pCurrentEntry->Links = 0;
len = wcslen(shortName);
entryp->name,
cm_shortNames && cm_Is8Dot3(entryp->name) ? NULL : entryp->shortName,
(bWow64 ? RDR_POP_WOW64 : 0) |
- (bSkipStatus ? RDR_POP_NO_GETSTATUS : 0),
+ (bSkipStatus ? RDR_POP_NO_GETSTATUS : 0) |
+ RDR_POP_EVALUATE_SYMLINKS,
code,
&pCurrentEntry, &dwMaxEntryLength);
cm_ReleaseSCache(scp);
IN BOOL CaseSensitive,
IN BOOL LastComponent,
IN BOOL bWow64,
- IN BOOL bHoldFid,
IN BOOL bNoFollow,
+ IN BOOL bHoldFid,
IN DWORD ResultBufferLength,
IN OUT AFSCommResult **ResultCB)
{
dscp, scp, userp, &req,
FileName, shortName,
(bWow64 ? RDR_POP_WOW64 : 0) |
- (bNoFollow ? 0 : (RDR_POP_FOLLOW_MOUNTPOINTS | RDR_POP_EVALUATE_SYMLINKS)),
+ (bNoFollow ? 0 : RDR_POP_FOLLOW_MOUNTPOINTS) |
+ RDR_POP_EVALUATE_SYMLINKS,
0, NULL, &dwRemaining);
if (bHoldFid)
RDR_FlagScpInUse( scp, FALSE );
code = RDR_PopulateCurrentEntry(pCurrentEntry, dwRemaining,
dscp, scp, userp, &req, NULL, NULL,
(bWow64 ? RDR_POP_WOW64 : 0) |
- (bNoFollow ? 0 : (RDR_POP_FOLLOW_MOUNTPOINTS | RDR_POP_EVALUATE_SYMLINKS)),
+ (bNoFollow ? 0 : RDR_POP_FOLLOW_MOUNTPOINTS) |
+ RDR_POP_EVALUATE_SYMLINKS,
0, NULL, &dwRemaining);
if (bHoldFid)
}
lock_ObtainWrite(&dscp->rw);
- bScpLocked = TRUE;
code = cm_SyncOp(dscp, NULL, userp, &req, 0,
CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
if (code) {
cm_SyncOpDone(dscp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
lock_ReleaseWrite(&dscp->rw);
- bScpLocked = FALSE;
if (dscp->fileType != CM_SCACHETYPE_DIRECTORY) {
(*ResultCB)->ResultStatus = STATUS_NOT_A_DIRECTORY;
bScpLocked = TRUE;
}
code = cm_SyncOp(scp, NULL, userp, &req, 0,
- CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_LOCK);
+ CM_SCACHESYNC_LOCK);
if (code) {
osi_Log2(afsd_logp, "RDR_CleanupFileEntry cm_SyncOp (2) failure scp=0x%p code=0x%x",
scp, code);
bDeleteFile ? CM_UNLOCK_FLAG_BY_FID : 0,
userp, &req);
- cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_LOCK);
+ cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_LOCK);
if (code)
goto on_error;
}
code = cm_Lookup(dscp, FileName, 0, userp, &req, &scp);
- if (code) {
+ if (code && code != CM_ERROR_INEXACT_MATCH) {
smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
(*ResultCB)->ResultStatus = status;
(*ResultCB)->ResultBufferLength = 0;
return;
}
+ if (scp->fileType == CM_SCACHETYPE_DIRECTORY) {
+ cm_dirOp_t dirop;
+
+ lock_ReleaseWrite(&scp->rw);
+
+ code = cm_BeginDirOp(scp, userp, &req, CM_DIRLOCK_READ,
+ CM_DIROP_FLAG_NONE, &dirop);
+ if (code == 0) {
+ /* is the directory empty? if not, CM_ERROR_NOTEMPTY */
+ afs_uint32 bEmpty;
+
+ code = cm_BPlusDirIsEmpty(&dirop, &bEmpty);
+ if (code == 0 && !bEmpty)
+ code = CM_ERROR_NOTEMPTY;
+
+ cm_EndDirOp(&dirop);
+ }
+
+ if (code) {
+ smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
+ (*ResultCB)->ResultStatus = status;
+ (*ResultCB)->ResultBufferLength = 0;
+ cm_ReleaseSCache(scp);
+ cm_ReleaseSCache(dscp);
+ osi_Log3(afsd_logp, "RDR_DeleteFileEntry cm_SyncOp failure scp=0x%p code=0x%x status=0x%x",
+ scp, code, status);
+ return;
+ }
+ lock_ObtainWrite(&scp->rw);
+ }
+
if (!bCheckOnly) {
/* Drop all locks since the file is being deleted */
code = cm_SyncOp(scp, NULL, userp, &req, 0,
- CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_LOCK);
+ CM_SCACHESYNC_LOCK);
if (code) {
smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
(*ResultCB)->ResultStatus = status;
CM_UNLOCK_FLAG_BY_FID,
userp, &req);
- cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_LOCK);
+ cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_LOCK);
lock_ReleaseWrite(&scp->rw);
if (scp->fileType == CM_SCACHETYPE_DIRECTORY)
cm_EndDirOp(&dirop);
}
- if (code != 0) {
+ if (code != 0 && code != CM_ERROR_INEXACT_MATCH) {
osi_Log1(afsd_logp, "RDR_RenameFileEntry cm_BPlusDirLookup failed code 0x%x",
code);
(*ResultCB)->ResultStatus = STATUS_OBJECT_PATH_INVALID;
cm_EndDirOp(&dirop);
}
- if (code != 0) {
+ if (code != 0 && code != CM_ERROR_INEXACT_MATCH) {
osi_Log1(afsd_logp, "RDR_HardLinkFileEntry cm_BPlusDirLookup failed code 0x%x",
code);
(*ResultCB)->ResultStatus = STATUS_OBJECT_PATH_INVALID;
cm_fid_t RootFid;
cm_req_t req;
- RDR_InitReq(&req, bWow64);
+ cm_InitReq(&req);
*ResultCB = (AFSCommResult *)malloc( sizeof( AFSCommResult));
if (!(*ResultCB))
cm_req_t req;
DWORD status;
- RDR_InitReq(&req, bWow64);
+ cm_InitReq(&req);
*ResultCB = (AFSCommResult *)malloc( sizeof( AFSCommResult) + sizeof(AFSPIOCtlIOResultCB));
if (!(*ResultCB))
DWORD status;
afs_uint32 pflags = (bIsLocalSystem ? AFSCALL_FLAG_LOCAL_SYSTEM : 0);
- RDR_InitReq(&req, bWow64);
+ cm_InitReq(&req);
*ResultCB = (AFSCommResult *)malloc( sizeof( AFSCommResult) + sizeof(AFSPIOCtlIOResultCB));
if (!(*ResultCB))
/* start by looking up the file's end */
code = cm_SyncOp(scp, NULL, userp, &req, 0,
- CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_LOCK);
+ CM_SCACHESYNC_LOCK);
if (code) {
lock_ReleaseWrite(&scp->rw);
smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
}
}
- cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_LOCK);
+ cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_LOCK);
lock_ReleaseWrite(&scp->rw);
cm_ReleaseSCache(scp);
/* start by looking up the file's end */
code = cm_SyncOp(scp, NULL, userp, &req, 0,
- CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_LOCK);
+ CM_SCACHESYNC_LOCK);
if (code) {
lock_ReleaseWrite(&scp->rw);
smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
pResultCB->Result[i].Status = status;
}
- cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_LOCK);
+ cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_LOCK);
lock_ReleaseWrite(&scp->rw);
cm_ReleaseSCache(scp);
/* start by looking up the file's end */
code = cm_SyncOp(scp, NULL, userp, &req, 0,
- CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_LOCK);
+ CM_SCACHESYNC_LOCK);
if (code) {
lock_ReleaseWrite(&scp->rw);
smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
code = cm_UnlockByKey(scp, key, 0, userp, &req);
- cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_LOCK);
+ cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_LOCK);
lock_ReleaseWrite(&scp->rw);
cm_ReleaseSCache(scp);
char *OfflineMsg;
char *MOTD;
struct rx_connection * rxconnp;
- int sync_done = 0;
int scp_locked = 0;
RDR_InitReq(&req, bWow64);
pResultCB->CellID = scp->fid.cell;
pResultCB->VolumeID = scp->fid.volume;
pResultCB->Characteristics = FILE_REMOTE_DEVICE;
- pResultCB->FileSystemAttributes = FILE_CASE_PRESERVED_NAMES | FILE_UNICODE_ON_DISK |
- FILE_SUPPORTS_HARD_LINKS | FILE_SUPPORTS_REPARSE_POINTS;
+ pResultCB->FileSystemAttributes = FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES |
+ FILE_UNICODE_ON_DISK | FILE_SUPPORTS_HARD_LINKS | FILE_SUPPORTS_REPARSE_POINTS;
if (scp->fid.cell==AFS_FAKE_ROOT_CELL_ID &&
scp->fid.volume==AFS_FAKE_ROOT_VOL_ID)
memcpy(&pResultCB->VolumeCreationTime, &ft, sizeof(ft));
pResultCB->AvailableAllocationUnits.QuadPart = 0;
- pResultCB->FileSystemAttributes |= FILE_READ_ONLY_VOLUME;
+ if (cm_volumeInfoReadOnlyFlag)
+ pResultCB->FileSystemAttributes |= FILE_READ_ONLY_VOLUME;
pResultCB->VolumeLabelLength = cm_Utf8ToUtf16( "Freelance.Local.Root", -1, pResultCB->VolumeLabel,
(sizeof(pResultCB->VolumeLabel) / sizeof(WCHAR)) + 1);
if ( pResultCB->CellLength )
pResultCB->CellLength--;
} else {
- memcpy(&pResultCB->VolumeCreationTime, &ft, sizeof(ft));
-
- volp = cm_GetVolumeByFID(&scp->fid);
- if (!volp) {
+ volp = cm_FindVolumeByFID(&scp->fid, userp, &req);
+ if (!volp) {
code = CM_ERROR_NOSUCHVOLUME;
goto _done;
}
+
volType = cm_VolumeType(volp, scp->fid.volume);
- if (volType == ROVOL || volType == BACKVOL)
+ if (cm_volumeInfoReadOnlyFlag && (volType == ROVOL || volType == BACKVOL))
pResultCB->FileSystemAttributes |= FILE_READ_ONLY_VOLUME;
- code = cm_SyncOp(scp, NULL, userp, &req, PRSFS_READ,
- CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
- if (code == 0)
- {
- sync_done = 1;
-
- Name = volName;
- OfflineMsg = offLineMsg;
- MOTD = motd;
- lock_ReleaseWrite(&scp->rw);
- scp_locked = 0;
-
- do {
- code = cm_ConnFromFID(&scp->fid, userp, &req, &connp);
- if (code) continue;
+ code = -1;
- rxconnp = cm_GetRxConn(connp);
- code = RXAFS_GetVolumeStatus(rxconnp, scp->fid.volume,
- &volStat, &Name, &OfflineMsg, &MOTD);
- rx_PutConnection(rxconnp);
-
- } while (cm_Analyze(connp, userp, &req, &scp->fid, NULL, 0, NULL, NULL, NULL, NULL, code));
- code = cm_MapRPCError(code, &req);
+ if ( volType == ROVOL &&
+ (volp->flags & CM_VOLUMEFLAG_RO_SIZE_VALID))
+ {
+ lock_ObtainRead(&volp->rw);
+ if (volp->flags & CM_VOLUMEFLAG_RO_SIZE_VALID) {
+ volStat.BlocksInUse = volp->volumeSizeRO / 1024;
+ code = 0;
+ }
+ lock_ReleaseRead(&volp->rw);
+ }
+
+ if (code == -1)
+ {
+ Name = volName;
+ OfflineMsg = offLineMsg;
+ MOTD = motd;
+ lock_ReleaseWrite(&scp->rw);
+ scp_locked = 0;
+
+ do {
+ code = cm_ConnFromFID(&scp->fid, userp, &req, &connp);
+ if (code) continue;
+
+ rxconnp = cm_GetRxConn(connp);
+ code = RXAFS_GetVolumeStatus(rxconnp, scp->fid.volume,
+ &volStat, &Name, &OfflineMsg, &MOTD);
+ rx_PutConnection(rxconnp);
+
+ } while (cm_Analyze(connp, userp, &req, &scp->fid, NULL, 0, NULL, NULL, NULL, NULL, code));
+ code = cm_MapRPCError(code, &req);
+
+ if (code == 0 && volType == ROVOL)
+ {
+ lock_ObtainWrite(&volp->rw);
+ volp->volumeSizeRO = volStat.BlocksInUse * 1024;
+ _InterlockedOr(&volp->flags, CM_VOLUMEFLAG_RO_SIZE_VALID);
+ lock_ReleaseWrite(&volp->rw);
+ }
}
+ if ( scp->volumeCreationDate )
+ cm_LargeSearchTimeFromUnixTime(&ft, scp->volumeCreationDate);
+ memcpy(&pResultCB->VolumeCreationTime, &ft, sizeof(ft));
+
if (code == 0) {
if (volType == ROVOL || volType == BACKVOL) {
pResultCB->TotalAllocationUnits.QuadPart = volStat.BlocksInUse;
pResultCB->AvailableAllocationUnits.QuadPart = volStat.PartBlocksAvail;
}
}
- } else {
+ } else if ( code != CM_ERROR_ALLBUSY &&
+ code != CM_ERROR_ALLOFFLINE &&
+ code != CM_ERROR_ALLDOWN)
+ {
/*
* Lie about the available space. Out of quota errors will need
* detected when the file server rejects the store data.
/* do not include the trailing nul */
if ( pResultCB->CellLength )
pResultCB->CellLength--;
-
- if (sync_done) {
- if (!scp_locked) {
- lock_ObtainWrite(&scp->rw);
- scp_locked = 1;
- }
- cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
- }
}
pResultCB->VolumeLabelLength *= sizeof(WCHAR); /* convert to bytes from chars */
pResultCB->CellLength *= sizeof(WCHAR); /* convert to bytes from chars */
char *OfflineMsg;
char *MOTD;
struct rx_connection * rxconnp;
- int sync_done = 0;
int scp_locked = 0;
RDR_InitReq(&req, bWow64);
pResultCB->TotalAllocationUnits.QuadPart = 100;
pResultCB->AvailableAllocationUnits.QuadPart = 0;
} else {
- volp = cm_GetVolumeByFID(&scp->fid);
- if (!volp) {
+ volp = cm_FindVolumeByFID(&scp->fid, userp, &req);
+ if (!volp) {
code = CM_ERROR_NOSUCHVOLUME;
goto _done;
}
volType = cm_VolumeType(volp, scp->fid.volume);
- code = cm_SyncOp(scp, NULL, userp, &req, PRSFS_READ,
- CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
- if (code == 0)
- {
- sync_done = 1;
+ code = -1;
- Name = volName;
- OfflineMsg = offLineMsg;
- MOTD = motd;
- lock_ReleaseWrite(&scp->rw);
- scp_locked = 0;
-
- do {
- code = cm_ConnFromFID(&scp->fid, userp, &req, &connp);
- if (code) continue;
-
- rxconnp = cm_GetRxConn(connp);
- code = RXAFS_GetVolumeStatus(rxconnp, scp->fid.volume,
- &volStat, &Name, &OfflineMsg, &MOTD);
- rx_PutConnection(rxconnp);
-
- } while (cm_Analyze(connp, userp, &req, &scp->fid, NULL, 0, NULL, NULL, NULL, NULL, code));
- code = cm_MapRPCError(code, &req);
+ if ( volType == ROVOL &&
+ (volp->flags & CM_VOLUMEFLAG_RO_SIZE_VALID))
+ {
+ lock_ObtainRead(&volp->rw);
+ if (volp->flags & CM_VOLUMEFLAG_RO_SIZE_VALID) {
+ volStat.BlocksInUse = volp->volumeSizeRO / 1024;
+ code = 0;
+ }
+ lock_ReleaseRead(&volp->rw);
+ }
+
+ if (code == -1)
+ {
+ Name = volName;
+ OfflineMsg = offLineMsg;
+ MOTD = motd;
+ lock_ReleaseWrite(&scp->rw);
+ scp_locked = 0;
+
+ do {
+ code = cm_ConnFromFID(&scp->fid, userp, &req, &connp);
+ if (code) continue;
+
+ rxconnp = cm_GetRxConn(connp);
+ code = RXAFS_GetVolumeStatus(rxconnp, scp->fid.volume,
+ &volStat, &Name, &OfflineMsg, &MOTD);
+ rx_PutConnection(rxconnp);
+
+ } while (cm_Analyze(connp, userp, &req, &scp->fid, NULL, 0, NULL, NULL, NULL, NULL, code));
+ code = cm_MapRPCError(code, &req);
+
+ if (code == 0 && volType == ROVOL)
+ {
+ lock_ObtainWrite(&volp->rw);
+ volp->volumeSizeRO = volStat.BlocksInUse * 1024;
+ _InterlockedOr(&volp->flags, CM_VOLUMEFLAG_RO_SIZE_VALID);
+ lock_ReleaseWrite(&volp->rw);
+ }
}
if (code == 0) {
pResultCB->AvailableAllocationUnits.QuadPart = (volType == ROVOL || volType == BACKVOL) ? 0 : 0x3F000000;
code = 0;
}
-
- if (sync_done) {
- if (!scp_locked) {
- lock_ObtainWrite(&scp->rw);
- scp_locked = 1;
- }
- cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
- }
}
_done:
/* Ensure that the caller can access this file */
lock_ObtainWrite(&scp->rw);
- code = cm_SyncOp(scp, NULL, userp, &req, PRSFS_WRITE,
+ /*
+ * Request PRSFS_WRITE | PRSFS_LOCK in order to bypass the unix mode
+ * check in cm_HaveAccessRights(). By the time RDR_WriteFile is called
+ * it is already too late to deny the write due to the readonly attribute.
+ * The Windows cache may have already accepted the data. Only if the
+ * user does not have real write permission should the write be denied.
+ */
+ code = cm_SyncOp(scp, NULL, userp, &req, PRSFS_WRITE | PRSFS_LOCK,
CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
if (code == CM_ERROR_NOACCESS && scp->creator == userp) {
code = cm_SyncOp(scp, NULL, userp, &req, PRSFS_INSERT,