extern char cm_CachePath[];
extern cm_config_data_t cm_data;
extern int smb_hideDotFiles;
- size_t cm_CachePathLen = strlen(cm_CachePath);
+ size_t CachePathLen;
+ DWORD TempPathLen;
size_t err;
- DWORD TempPathLen = ExpandEnvironmentStringsW(L"%TEMP%", NULL, 0);
MEMORYSTATUSEX memStatus;
DWORD maxMemoryCacheSize;
+ char FullCachePath[MAX_PATH];
+ char TempPath[MAX_PATH];
+ char FullTempPath[MAX_PATH];
+
+ /*
+ * The %TEMP% environment variable may be relative instead
+ * of absolute which can result in the redirector referring
+ * to a different directory than the service. The full path
+ * must therefore be obtained first.
+ */
+
+ CachePathLen = GetFullPathNameA(cm_CachePath, MAX_PATH, FullCachePath, NULL);
+ if (CachePathLen == 0) {
+ osi_Log0(afsd_logp, "RDR_SetInitParams Unable to obtain Full Cache Path");
+ return STATUS_OBJECT_NAME_NOT_FOUND;
+ }
+
+ TempPathLen = ExpandEnvironmentStringsA("%TEMP%", TempPath, MAX_PATH);
+ if (TempPathLen == 0) {
+ osi_Log0(afsd_logp, "RDR_SetInitParams Unable to expand %%TEMP%%");
+ return STATUS_OBJECT_NAME_NOT_FOUND;
+ }
+
+ TempPathLen = GetFullPathNameA(TempPath, MAX_PATH, FullTempPath, NULL);
+ if (TempPathLen == 0) {
+ osi_Log0(afsd_logp, "RDR_SetInitParams Unable to obtain Full Temp Path");
+ return STATUS_OBJECT_NAME_NOT_FOUND;
+ }
memStatus.dwLength = sizeof(memStatus);
if (GlobalMemoryStatusEx(&memStatus)) {
maxMemoryCacheSize = 65536;
}
- *pRedirInitInfoLen = (DWORD) (sizeof(AFSRedirectorInitInfo) + (cm_CachePathLen + TempPathLen) * sizeof(WCHAR));
+ *pRedirInitInfoLen = (DWORD) (sizeof(AFSRedirectorInitInfo) + (CachePathLen + TempPathLen) * sizeof(WCHAR));
*ppRedirInitInfo = (AFSRedirectorInitInfo *)malloc(*pRedirInitInfoLen);
(*ppRedirInitInfo)->Flags = smb_hideDotFiles ? AFS_REDIR_INIT_FLAG_HIDE_DOT_FILES : 0;
(*ppRedirInitInfo)->Flags |= cm_shortNames ? 0 : AFS_REDIR_INIT_FLAG_DISABLE_SHORTNAMES;
+ (*ppRedirInitInfo)->Flags |= cm_directIO ? AFS_REDIR_INIT_PERFORM_SERVICE_IO : 0;
(*ppRedirInitInfo)->MaximumChunkLength = cm_data.chunkSize;
(*ppRedirInitInfo)->GlobalFileId.Cell = cm_data.rootFid.cell;
(*ppRedirInitInfo)->GlobalFileId.Volume = cm_data.rootFid.volume;
} else {
(*ppRedirInitInfo)->MemoryCacheOffset.QuadPart = 0;
(*ppRedirInitInfo)->MemoryCacheLength.QuadPart = 0;
- (*ppRedirInitInfo)->CacheFileNameLength = (ULONG) (cm_CachePathLen * sizeof(WCHAR));
- err = mbstowcs((*ppRedirInitInfo)->CacheFileName, cm_CachePath, (cm_CachePathLen + 1) *sizeof(WCHAR));
+ (*ppRedirInitInfo)->CacheFileNameLength = (ULONG) (CachePathLen * sizeof(WCHAR));
+ err = mbstowcs((*ppRedirInitInfo)->CacheFileName, FullCachePath, (CachePathLen + 1) *sizeof(WCHAR));
if (err == -1) {
free(*ppRedirInitInfo);
osi_Log0(afsd_logp, "RDR_SetInitParams Invalid Object Name");
}
(*ppRedirInitInfo)->DumpFileLocationOffset = FIELD_OFFSET(AFSRedirectorInitInfo, CacheFileName) + (*ppRedirInitInfo)->CacheFileNameLength;
(*ppRedirInitInfo)->DumpFileLocationLength = (TempPathLen - 1) * sizeof(WCHAR);
- ExpandEnvironmentStringsW(L"%TEMP%",
- (LPWSTR)(((PBYTE)(*ppRedirInitInfo)) + (*ppRedirInitInfo)->DumpFileLocationOffset),
- TempPathLen);
+
+ err = mbstowcs((((PBYTE)(*ppRedirInitInfo)) + (*ppRedirInitInfo)->DumpFileLocationOffset),
+ FullTempPath, (TempPathLen + 1) *sizeof(WCHAR));
+ if (err == -1) {
+ free(*ppRedirInitInfo);
+ osi_Log0(afsd_logp, "RDR_SetInitParams Invalid Object Name");
+ return STATUS_OBJECT_NAME_INVALID;
+ }
osi_Log0(afsd_logp,"RDR_SetInitParams Success");
return 0;
IN WCHAR *FileNameCounted,
IN DWORD FileNameLength,
IN BOOL CaseSensitive,
+ IN BOOL LastComponent,
IN BOOL bWow64,
IN BOOL bHoldFid,
IN BOOL bNoFollow,
size_t cbName;
BOOL bVol = FALSE;
wchar_t FileName[260];
+ afs_uint32 lookupFlags;
StringCchCopyNW(FileName, 260, FileNameCounted, FileNameLength / sizeof(WCHAR));
ParentID.Cell, ParentID.Volume, ParentID.Vnode, ParentID.Unique);
/* Allocate enough room to add a volume prefix if necessary */
- cbName = FileNameLength + (CM_PREFIX_VOL_CCH + 1) * sizeof(WCHAR);
+ cbName = FileNameLength + (CM_PREFIX_VOL_CCH + 64) * sizeof(WCHAR);
wszName = malloc(cbName);
if (!wszName) {
osi_Log0(afsd_logp, "RDR_EvaluateNodeByName Out of Memory");
return;
}
- code = cm_Lookup(dscp, wszName, CM_FLAG_CHECKPATH, userp, &req, &scp);
+ lookupFlags = CM_FLAG_NOMOUNTCHASE;
+
+ if ( !LastComponent )
+ lookupFlags |= CM_FLAG_CHECKPATH;
+ code = cm_Lookup(dscp, wszName, lookupFlags, userp, &req, &scp);
+
+ if (!CaseSensitive &&
+ (code == CM_ERROR_NOSUCHPATH || code == CM_ERROR_NOSUCHFILE || code == CM_ERROR_BPLUS_NOMATCH)) {
+ lookupFlags |= CM_FLAG_CASEFOLD;
+ code = cm_Lookup(dscp, wszName, lookupFlags, userp, &req, &scp);
+ }
if ((code == CM_ERROR_NOSUCHPATH || code == CM_ERROR_NOSUCHFILE || code == CM_ERROR_BPLUS_NOMATCH) &&
- (wcschr(wszName, '%') != NULL || wcschr(wszName, '#') != NULL)) {
- /*
- * A volume reference: <cell>{%,#}<volume> -> @vol:<cell>{%,#}<volume>
- */
- StringCchCopyNW(wszName, cbName, _C(CM_PREFIX_VOL), CM_PREFIX_VOL_CCH);
- StringCbCatNW(wszName, cbName, FileName, FileNameLength);
- bVol = TRUE;
+ dscp == cm_data.rootSCachep) {
+
+ if (wcschr(wszName, '%') != NULL || wcschr(wszName, '#') != NULL) {
+ /*
+ * A volume reference: <cell>{%,#}<volume> -> @vol:<cell>{%,#}<volume>
+ */
+ StringCchCopyNW(wszName, cbName, _C(CM_PREFIX_VOL), CM_PREFIX_VOL_CCH);
+ StringCbCatNW(wszName, cbName, FileName, FileNameLength);
+ bVol = TRUE;
- code = cm_EvaluateVolumeReference(wszName, CM_FLAG_CHECKPATH, userp, &req, &scp);
+ code = cm_EvaluateVolumeReference(wszName, CM_FLAG_CHECKPATH, userp, &req, &scp);
+ }
+#ifdef AFS_FREELANCE_CLIENT
+ else if (dscp->fid.cell == AFS_FAKE_ROOT_CELL_ID && dscp->fid.volume == AFS_FAKE_ROOT_VOL_ID &&
+ dscp->fid.vnode == 1 && dscp->fid.unique == 1) {
+ /*
+ * If this is the Freelance volume root directory then treat unrecognized
+ * names as cell names and attempt to find the appropriate "root.cell".
+ */
+ StringCchCopyNW(wszName, cbName, _C(CM_PREFIX_VOL), CM_PREFIX_VOL_CCH);
+ if (FileName[0] == L'.') {
+ StringCbCatNW(wszName, cbName, &FileName[1], FileNameLength);
+ StringCbCatNW(wszName, cbName, L"%", sizeof(WCHAR));
+ } else {
+ StringCbCatNW(wszName, cbName, FileName, FileNameLength);
+ StringCbCatNW(wszName, cbName, L"#", sizeof(WCHAR));
+ }
+ StringCbCatNW(wszName, cbName, L"root.cell", 9 * sizeof(WCHAR));
+ bVol = TRUE;
+
+ code = cm_EvaluateVolumeReference(wszName, CM_FLAG_CHECKPATH, userp, &req, &scp);
+ }
+#endif
}
if (code == 0 && scp) {
}
cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
- if ((bLastHandle || bFlushFile) &&
+ if (bLastHandle && (scp->fileType == CM_SCACHETYPE_FILE) &&
scp->redirBufCount > 0)
{
LARGE_INTEGER heldExtents;
/* If not a readonly object, flush dirty data and update metadata */
if (!(scp->flags & CM_SCACHEFLAG_RO)) {
- if ((bLastHandle || bFlushFile) &&
- buf_DirtyBuffersExist(&scp->fid)) {
- if (!bScpLocked) {
- lock_ObtainWrite(&scp->rw);
- bScpLocked = TRUE;
- }
- code = cm_SyncOp(scp, NULL, userp, &req, PRSFS_WRITE,
- CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+ if ((scp->fileType == CM_SCACHETYPE_FILE) && (bLastHandle || bFlushFile)) {
+ /* Serialize with any outstanding AsyncStore operation */
+ code = cm_SyncOp(scp, NULL, userp, &req, 0, CM_SCACHESYNC_ASYNCSTORE);
if (code == 0) {
- if (bScpLocked) {
- lock_ReleaseWrite(&scp->rw);
- bScpLocked = FALSE;
+ cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_ASYNCSTORE);
+
+ code = cm_SyncOp(scp, NULL, userp, &req, PRSFS_WRITE,
+ CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+ /*
+ * If we only have 'i' bits, then we should still be able to
+ * set flush the file.
+ */
+ if (code == CM_ERROR_NOACCESS && scp->creator == userp) {
+ code = cm_SyncOp(scp, NULL, userp, &req, PRSFS_INSERT,
+ CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
}
+ if (code == 0) {
+ if (bScpLocked) {
+ lock_ReleaseWrite(&scp->rw);
+ bScpLocked = FALSE;
+ }
- code = cm_FSync(scp, userp, &req, bScpLocked);
+ code = cm_FSync(scp, userp, &req, bScpLocked);
+ }
}
if (bLastHandle && code)
goto unlock;
userp, &req, &ldp);
if (code == 0)
code = RDR_CheckAccess(scp, userp, &req, OpenCB->DesiredAccess, &pResultCB->GrantedAccess);
+
+
cm_CheckNTOpenDone(scp, userp, &req, &ldp);
} while (count < 100 && (code == CM_ERROR_RETRY || code == CM_ERROR_WOULDBLOCK));
}
/* do the background fetch. */
afs_int32
-RDR_BkgFetch(cm_scache_t *scp, afs_uint32 p1, afs_uint32 p2, afs_uint32 p3, afs_uint32 p4,
- cm_user_t *userp, cm_req_t *reqp)
+RDR_BkgFetch(cm_scache_t *scp, void *rockp, cm_user_t *userp, cm_req_t *reqp)
{
osi_hyper_t length;
osi_hyper_t base;
fetched.LowPart = 0;
fetched.HighPart = 0;
tblocksize = ConvertLongToLargeInteger(cm_data.buf_blockSize);
- base.LowPart = p1;
- base.HighPart = p2;
- length.LowPart = p3;
- length.HighPart = p4;
-
+ base = ((rock_BkgFetch_t *)rockp)->base;
+ length = ((rock_BkgFetch_t *)rockp)->length;
end = LargeIntegerAdd(base, length);
osi_Log5(afsd_logp, "Starting BKG Fetch scp 0x%p offset 0x%x:%x length 0x%x:%x",
- scp, p2, p1, p4, p3);
+ scp, base.HighPart, base.LowPart, length.HighPart, length.LowPart);
/*
* Make sure we have a callback.
rwheld = 0;
}
- code = buf_Get(scp, &offset, reqp, &bufp);
+ code = buf_Get(scp, &offset, reqp, 0, &bufp);
if (code) {
/*
* any error from buf_Get() is non-fatal.
case CM_ERROR_QUOTA:
case CM_ERROR_LOCK_CONFLICT:
case EIO:
+ case CM_ERROR_INVAL_NET_RESP:
+ case CM_ERROR_UNKNOWN:
/*
* these are fatal errors. deliver what we can
* and halt.
QueueLength = 0;
thyper.QuadPart = ByteOffset.QuadPart;
- code = buf_Get(scp, &thyper, &req, &bufp);
+ code = buf_Get(scp, &thyper, &req, 0, &bufp);
if (code == 0) {
lock_ObtainMutex(&bufp->mx);
bBufRelease = TRUE;
buf_Release(bufp);
if (QueueLength) {
- cm_QueueBKGRequest(scp, RDR_BkgFetch, QueueOffset.LowPart, QueueOffset.HighPart,
- QueueLength, 0, userp, &req);
- osi_Log3(afsd_logp, "RDR_RequestFileExtentsAsync Queued a Background Fetch offset 0x%x:%x length 0x%x",
- QueueOffset.HighPart, QueueOffset.LowPart, QueueLength);
+ rock_BkgFetch_t * rockp = malloc(sizeof(*rockp));
+
+ if (rockp) {
+ req.flags &= ~CM_REQ_NORETRY;
+ rockp->base = QueueOffset;
+ rockp->length.LowPart = QueueLength;
+ rockp->length.HighPart = 0;
+
+ cm_QueueBKGRequest(scp, RDR_BkgFetch, rockp, userp, &req);
+ osi_Log3(afsd_logp, "RDR_RequestFileExtentsAsync Queued a Background Fetch offset 0x%x:%x length 0x%x",
+ QueueOffset.HighPart, QueueOffset.LowPart, QueueLength);
+ req.flags |= CM_REQ_NORETRY;
+ } else {
+ code = ENOMEM;
+ }
}
} else {
/* No error from buf_Get() can be fatal */
if (BeginOffset.QuadPart != EndOffset.QuadPart) {
afs_uint32 length = (afs_uint32)(EndOffset.QuadPart - BeginOffset.QuadPart);
+ rock_BkgFetch_t * rockp = malloc(sizeof(*rockp));
+
+ if (rockp) {
+ req.flags &= ~CM_REQ_NORETRY;
+ rockp->base = BeginOffset;
+ rockp->length.LowPart = length;
+ rockp->length.HighPart = 0;
- cm_QueueBKGRequest(scp, RDR_BkgFetch, BeginOffset.LowPart, BeginOffset.HighPart,
- length, 0, userp, &req);
- osi_Log3(afsd_logp, "RDR_RequestFileExtentsAsync Queued a Background Fetch offset 0x%x:%x length 0x%x",
- BeginOffset.HighPart, BeginOffset.LowPart, length);
+ cm_QueueBKGRequest(scp, RDR_BkgFetch, rockp, userp, &req);
+ osi_Log3(afsd_logp, "RDR_RequestFileExtentsAsync Queued a Background Fetch offset 0x%x:%x length 0x%x",
+ BeginOffset.HighPart, BeginOffset.LowPart, length);
+ } else {
+ code = ENOMEM;
+ }
}
cm_ReleaseSCache(scp);
int released = 0;
int deleted = 0;
DWORD status;
+ rock_BkgStore_t *rockp;
#ifdef ODS_DEBUG
#ifdef VALIDATE_CHECK_SUM
char md5dbg[33], md5dbg2[33], md5dbg3[33];
lock_ObtainWrite(&scp->rw);
code = cm_SyncOp(scp, NULL, userp, &req, PRSFS_WRITE,
CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+ if (code == CM_ERROR_NOACCESS && scp->creator == userp) {
+ code = cm_SyncOp(scp, NULL, userp, &req, PRSFS_INSERT,
+ CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+ }
lock_ReleaseWrite(&scp->rw);
if (code == 0)
code = cm_FSync(scp, userp, &req, FALSE);
lock_ObtainWrite(&scp->rw);
code = cm_SyncOp(scp, NULL, userp, &req, PRSFS_WRITE,
CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+ if (code == CM_ERROR_NOACCESS && scp->creator == userp) {
+ code = cm_SyncOp(scp, NULL, userp, &req, PRSFS_INSERT,
+ CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+ }
lock_ReleaseWrite(&scp->rw);
if (code == 0) {
/*
{
length += cm_data.buf_blockSize;
} else {
- if (!(offset.QuadPart == 0 && length == 0))
- cm_QueueBKGRequest(scp, cm_BkgStore, offset.LowPart, offset.HighPart,
- length, 0, userp, &req);
+ if (!(offset.QuadPart == 0 && length == 0)) {
+ rockp = malloc(sizeof(*rockp));
+ if (rockp) {
+ rockp->length = length;
+ rockp->offset = offset;
+
+ cm_QueueBKGRequest(scp, cm_BkgStore, rockp, userp, &req);
+
+ /* rock is freed by cm_BkgStore */
+ }
+ }
offset.QuadPart = ReleaseExtentsCB->FileExtents[count].FileOffset.QuadPart;
length = cm_data.buf_blockSize;
}
}
- cm_QueueBKGRequest(scp, cm_BkgStore, offset.LowPart, offset.HighPart,
- length, 0, userp, &req);
+
+ /* Store whatever is left */
+ rockp = malloc(sizeof(*rockp));
+ if (rockp) {
+ rockp->length = length;
+ rockp->offset = offset;
+
+ cm_QueueBKGRequest(scp, cm_BkgStore, rockp, userp, &req);
+
+ /* rock is freed by cm_BkgStore */
+ }
}
}
cm_ReleaseSCache(scp);
cm_buf_t *bufp;
unsigned int fileno, extentno, total_extents = 0;
AFSReleaseFileExtentsResultFileCB *pNextFileCB;
+ rock_BkgStore_t *rockp;
#ifdef ODS_DEBUG
#ifdef VALIDATE_CHECK_SUM
char md5dbg[33], md5dbg2[33], md5dbg3[33];
length < cm_chunkSize) {
length += cm_data.buf_blockSize;
} else {
- if (!(offset.QuadPart == 0 && length == 0))
- cm_QueueBKGRequest(scp, cm_BkgStore, offset.LowPart, offset.HighPart,
- length, 0, userp, &req);
+ if (!(offset.QuadPart == 0 && length == 0)) {
+ rockp = malloc(sizeof(*rockp));
+ if (rockp) {
+ rockp->offset = offset;
+ rockp->length = length;
+
+ cm_QueueBKGRequest(scp, cm_BkgStore, rockp, userp, &req);
+ } else {
+ code = ENOMEM;
+ }
+ }
offset.QuadPart = pExtent->FileOffset.QuadPart;
length = cm_data.buf_blockSize;
}
}
- cm_QueueBKGRequest(scp, cm_BkgStore, offset.LowPart, offset.HighPart,
- length, 0, userp, &req);
+
+ /* Background store the rest */
+ rockp = malloc(sizeof(*rockp));
+ if (rockp) {
+ rockp->offset = offset;
+ rockp->length = length;
+
+ cm_QueueBKGRequest(scp, cm_BkgStore, rockp, userp, &req);
+ } else {
+ code = ENOMEM;
+ }
}
osi_Log5(afsd_logp, "RDR_ProcessReleaseFileExtentsResult File FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x Released %d",
cm_scache_t *scp = NULL;
cm_volume_t *volp = NULL;
afs_uint32 volType;
- cm_cell_t *cellp = NULL;
cm_fid_t Fid;
afs_uint32 code;
cm_req_t req;
memcpy(&pResultCB->VolumeCreationTime, &ft, sizeof(ft));
pResultCB->AvailableAllocationUnits.QuadPart = 0;
- pResultCB->Characteristics |= FILE_READ_ONLY_DEVICE;
+ pResultCB->FileSystemAttributes |= FILE_READ_ONLY_VOLUME;
pResultCB->VolumeLabelLength = cm_Utf8ToUtf16( "Freelance.Local.Root", -1, pResultCB->VolumeLabel,
(sizeof(pResultCB->VolumeLabel) / sizeof(WCHAR)) + 1);
if ( pResultCB->VolumeLabelLength )
pResultCB->VolumeLabelLength--;
+
+ pResultCB->CellLength = cm_Utf8ToUtf16( "Freelance.Local", -1, pResultCB->Cell,
+ (sizeof(pResultCB->Cell) / sizeof(WCHAR)) + 1);
+ if ( pResultCB->CellLength )
+ pResultCB->CellLength--;
} else {
memcpy(&pResultCB->VolumeCreationTime, &ft, sizeof(ft));
}
volType = cm_VolumeType(volp, scp->fid.volume);
- pResultCB->Characteristics |= ((volType == ROVOL || volType == BACKVOL) ? FILE_READ_ONLY_DEVICE : 0);
+ if (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) {
- if (volStat.MaxQuota)
- {
- pResultCB->TotalAllocationUnits.QuadPart = volStat.MaxQuota;
- if (volType == ROVOL || volType == BACKVOL) {
- pResultCB->AvailableAllocationUnits.QuadPart = 0;
- }
- else
+ if (volType == ROVOL || volType == BACKVOL) {
+ pResultCB->TotalAllocationUnits.QuadPart = volStat.BlocksInUse;
+ pResultCB->AvailableAllocationUnits.QuadPart = 0;
+ } else {
+ if (volStat.MaxQuota)
{
+ pResultCB->TotalAllocationUnits.QuadPart = volStat.MaxQuota;
pResultCB->AvailableAllocationUnits.QuadPart =
min(volStat.MaxQuota - volStat.BlocksInUse, volStat.PartBlocksAvail);
}
- }
- else
- {
- pResultCB->TotalAllocationUnits.QuadPart = volStat.PartMaxBlocks;
- if (volType == ROVOL || volType == BACKVOL) {
- pResultCB->AvailableAllocationUnits.QuadPart = 0;
- }
else
{
+ pResultCB->TotalAllocationUnits.QuadPart = volStat.PartMaxBlocks;
pResultCB->AvailableAllocationUnits.QuadPart = volStat.PartBlocksAvail;
}
}
pResultCB->VolumeLabelLength = cm_Utf8ToUtf16( volp->namep, -1, pResultCB->VolumeLabel,
(sizeof(pResultCB->VolumeLabel) / sizeof(WCHAR)) + 1);
+
+ if ( pResultCB->VolumeLabelLength) {
+
+ /* add .readonly and .backup if appropriate */
+ switch ( volType) {
+ case ROVOL:
+ pResultCB->VolumeLabelLength--;
+ pResultCB->VolumeLabelLength += cm_Utf8ToUtf16( ".readonly", -1,
+ &pResultCB->VolumeLabel[ pResultCB->VolumeLabelLength],
+ (sizeof(pResultCB->VolumeLabel) / sizeof(WCHAR)) - pResultCB->VolumeLabelLength + 1);
+ break;
+
+ case BACKVOL:
+ pResultCB->VolumeLabelLength--;
+ pResultCB->VolumeLabelLength += cm_Utf8ToUtf16( ".backup", -1,
+ &pResultCB->VolumeLabel[ pResultCB->VolumeLabelLength],
+ (sizeof(pResultCB->VolumeLabel) / sizeof(WCHAR)) - pResultCB->VolumeLabelLength + 1);
+ break;
+ }
+ }
+
+ /* do not include the trailing nul */
if ( pResultCB->VolumeLabelLength )
pResultCB->VolumeLabelLength--;
+ pResultCB->CellLength = cm_Utf8ToUtf16( volp->cellp->name, -1, pResultCB->Cell,
+ (sizeof(pResultCB->Cell) / sizeof(WCHAR)) + 1);
+
+ /* do not include the trailing nul */
+ if ( pResultCB->CellLength )
+ pResultCB->CellLength--;
+
if (sync_done) {
if (!scp_locked) {
lock_ObtainWrite(&scp->rw);
}
}
pResultCB->VolumeLabelLength *= sizeof(WCHAR); /* convert to bytes from chars */
+ pResultCB->CellLength *= sizeof(WCHAR); /* convert to bytes from chars */
_done:
if (scp_locked)
cm_scache_t *scp = NULL;
cm_volume_t *volp = NULL;
afs_uint32 volType;
- cm_cell_t *cellp = NULL;
cm_fid_t Fid;
afs_uint32 code;
cm_req_t req;
}
if (code == 0) {
- if (volStat.MaxQuota)
- {
- pResultCB->TotalAllocationUnits.QuadPart = volStat.MaxQuota;
- if (volType == ROVOL || volType == BACKVOL) {
- pResultCB->AvailableAllocationUnits.QuadPart = 0;
- }
- else
+ if (volType == ROVOL || volType == BACKVOL) {
+ pResultCB->TotalAllocationUnits.QuadPart = volStat.BlocksInUse;
+ pResultCB->AvailableAllocationUnits.QuadPart = 0;
+ } else {
+ if (volStat.MaxQuota)
{
+ pResultCB->TotalAllocationUnits.QuadPart = volStat.MaxQuota;
pResultCB->AvailableAllocationUnits.QuadPart =
min(volStat.MaxQuota - volStat.BlocksInUse, volStat.PartBlocksAvail);
}
- }
- else
- {
- pResultCB->TotalAllocationUnits.QuadPart = volStat.PartMaxBlocks;
- if (volType == ROVOL || volType == BACKVOL) {
- pResultCB->AvailableAllocationUnits.QuadPart = 0;
- }
else
{
+ pResultCB->TotalAllocationUnits.QuadPart = volStat.PartMaxBlocks;
pResultCB->AvailableAllocationUnits.QuadPart = volStat.PartBlocksAvail;
}
}
(*ResultCB)->ResultStatus = 0;
osi_Log0(afsd_logp, "RDR_Pipe_Transceive SUCCESS");
}
+
+void
+RDR_ReadFile( IN cm_user_t *userp,
+ IN AFSFileID FileID,
+ IN LARGE_INTEGER *Offset,
+ IN ULONG BytesToRead,
+ IN PVOID Buffer,
+ IN BOOL bWow64,
+ IN BOOL bCacheBypass,
+ IN DWORD ResultBufferLength,
+ IN OUT AFSCommResult **ResultCB)
+{
+ AFSFileIOResultCB * pFileIOResultCB;
+ DWORD status;
+ ULONG Length;
+ ULONG ulBytesRead = 0;
+ afs_uint32 code = 0;
+ cm_fid_t fid;
+ cm_scache_t * scp = NULL;
+ cm_req_t req;
+
+ RDR_InitReq(&req, bWow64);
+
+ osi_Log4(afsd_logp, "RDR_ReadFile FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
+ FileID.Cell, FileID.Volume, FileID.Vnode, FileID.Unique);
+
+ Length = sizeof(AFSFileIOResultCB);
+ if (Length > ResultBufferLength) {
+ *ResultCB = (AFSCommResult *)malloc(sizeof(AFSCommResult) );
+ if (!(*ResultCB))
+ return;
+ memset( *ResultCB, 0, sizeof(AFSCommResult));
+ (*ResultCB)->ResultStatus = STATUS_BUFFER_OVERFLOW;
+ return;
+ }
+ *ResultCB = (AFSCommResult *)malloc( Length + sizeof( AFSCommResult) );
+ if (!(*ResultCB))
+ return;
+ memset( *ResultCB, '\0', Length );
+ (*ResultCB)->ResultBufferLength = Length;
+ pFileIOResultCB = (AFSFileIOResultCB *)(*ResultCB)->ResultData;
+
+ if ( Buffer == NULL) {
+ (*ResultCB)->ResultStatus = STATUS_INVALID_PARAMETER;
+ osi_Log0(afsd_logp, "RDR_ReadFile Null IOctl Buffer");
+ return;
+ }
+
+ if (FileID.Cell != 0) {
+ fid.cell = FileID.Cell;
+ fid.volume = FileID.Volume;
+ fid.vnode = FileID.Vnode;
+ fid.unique = FileID.Unique;
+ fid.hash = FileID.Hash;
+
+ code = cm_GetSCache(&fid, NULL, &scp, userp, &req);
+ if (code) {
+ smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
+ (*ResultCB)->ResultStatus = status;
+ osi_Log2(afsd_logp, "RDR_ReadFile cm_GetSCache failure code=0x%x status=0x%x",
+ code, status);
+ return;
+ }
+ } else {
+ (*ResultCB)->ResultStatus = STATUS_OBJECT_NAME_INVALID;
+ osi_Log0(afsd_logp, "RDR_ReadFile Object Name Invalid - Cell = 0");
+ return;
+ }
+
+ /* Ensure that the caller can access this file */
+ lock_ObtainWrite(&scp->rw);
+ code = cm_SyncOp(scp, NULL, userp, &req, PRSFS_READ,
+ CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+ if (code) {
+ smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
+ (*ResultCB)->ResultStatus = status;
+ lock_ReleaseWrite(&scp->rw);
+ cm_ReleaseSCache(scp);
+ osi_Log2(afsd_logp, "RDR_ReadFile cm_SyncOp failure code=0x%x status=0x%x",
+ code, status);
+ return;
+ }
+
+ cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+
+ if (scp->fileType == CM_SCACHETYPE_DIRECTORY) {
+ (*ResultCB)->ResultStatus = STATUS_FILE_IS_A_DIRECTORY;
+ lock_ReleaseWrite(&scp->rw);
+ cm_ReleaseSCache(scp);
+ osi_Log1(afsd_logp, "RDR_ReadFile File is a Directory scp=0x%p",
+ scp);
+ return;
+ }
+
+ if (scp->fileType != CM_SCACHETYPE_FILE) {
+ (*ResultCB)->ResultStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
+ lock_ReleaseWrite(&scp->rw);
+ cm_ReleaseSCache(scp);
+ osi_Log1(afsd_logp, "RDR_ReadFile File is a MountPoint or Link scp=0x%p",
+ scp);
+ return;
+ }
+
+ if ( bCacheBypass) {
+ //
+ // Read the file directly into the buffer bypassing the AFS Cache
+ //
+ code = cm_GetData( scp, Offset, Buffer, BytesToRead, &ulBytesRead, userp, &req);
+ } else {
+ //
+ // Read the file via the AFS Cache
+ //
+ code = raw_ReadData( scp, Offset, BytesToRead, Buffer, &ulBytesRead, userp, &req);
+ }
+
+ if (code) {
+ smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
+ (*ResultCB)->ResultStatus = status;
+ osi_Log2(afsd_logp, "RDR_ReadFile failure code=0x%x status=0x%x",
+ code, status);
+ } else {
+ (*ResultCB)->ResultStatus = STATUS_SUCCESS;
+ pFileIOResultCB->Length = ulBytesRead;
+ pFileIOResultCB->DataVersion.QuadPart = scp->dataVersion;
+ pFileIOResultCB->Expiration.QuadPart = scp->cbExpires;
+ }
+
+ lock_ReleaseWrite(&scp->rw);
+ cm_ReleaseSCache(scp);
+ return;
+}
+
+void
+RDR_WriteFile( IN cm_user_t *userp,
+ IN AFSFileID FileID,
+ IN AFSFileIOCB *FileIOCB,
+ IN LARGE_INTEGER *Offset,
+ IN ULONG BytesToWrite,
+ IN PVOID Buffer,
+ IN BOOL bWow64,
+ IN BOOL bCacheBypass,
+ IN DWORD ResultBufferLength,
+ IN OUT AFSCommResult **ResultCB)
+{
+ AFSFileIOResultCB * pFileIOResultCB;
+ DWORD status;
+ ULONG Length;
+ ULONG ulBytesWritten = 0;
+ afs_uint32 code = 0;
+ cm_fid_t fid;
+ cm_scache_t * scp = NULL;
+ cm_req_t req;
+
+ RDR_InitReq(&req, bWow64);
+
+ osi_Log4(afsd_logp, "RDR_WriteFile FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
+ FileID.Cell, FileID.Volume, FileID.Vnode, FileID.Unique);
+
+ Length = sizeof(AFSFileIOResultCB);
+ if (Length > ResultBufferLength) {
+ *ResultCB = (AFSCommResult *)malloc(sizeof(AFSCommResult) );
+ if (!(*ResultCB))
+ return;
+ memset( *ResultCB, 0, sizeof(AFSCommResult));
+ (*ResultCB)->ResultStatus = STATUS_BUFFER_OVERFLOW;
+ return;
+ }
+ *ResultCB = (AFSCommResult *)malloc( Length + sizeof( AFSCommResult) );
+ if (!(*ResultCB))
+ return;
+ memset( *ResultCB, '\0', Length );
+ (*ResultCB)->ResultBufferLength = Length;
+ pFileIOResultCB = (AFSFileIOResultCB *)(*ResultCB)->ResultData;
+
+ if ( Buffer == NULL) {
+ (*ResultCB)->ResultStatus = STATUS_INVALID_PARAMETER;
+ osi_Log0(afsd_logp, "RDR_WriteFile Null IOctl Buffer");
+ return;
+ }
+
+ if (FileID.Cell != 0) {
+ fid.cell = FileID.Cell;
+ fid.volume = FileID.Volume;
+ fid.vnode = FileID.Vnode;
+ fid.unique = FileID.Unique;
+ fid.hash = FileID.Hash;
+
+ code = cm_GetSCache(&fid, NULL, &scp, userp, &req);
+ if (code) {
+ smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
+ (*ResultCB)->ResultStatus = status;
+ osi_Log2(afsd_logp, "RDR_WriteFile cm_GetSCache failure code=0x%x status=0x%x",
+ code, status);
+ return;
+ }
+ } else {
+ (*ResultCB)->ResultStatus = STATUS_OBJECT_NAME_INVALID;
+ osi_Log0(afsd_logp, "RDR_WriteFile Object Name Invalid - Cell = 0");
+ return;
+ }
+
+ /* Ensure that the caller can access this file */
+ lock_ObtainWrite(&scp->rw);
+ code = cm_SyncOp(scp, NULL, userp, &req, PRSFS_WRITE,
+ CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+ if (code == CM_ERROR_NOACCESS && scp->creator == userp) {
+ code = cm_SyncOp(scp, NULL, userp, &req, PRSFS_INSERT,
+ CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+ }
+ if (code) {
+ smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
+ (*ResultCB)->ResultStatus = status;
+ lock_ReleaseWrite(&scp->rw);
+ cm_ReleaseSCache(scp);
+ osi_Log2(afsd_logp, "RDR_WriteFile cm_SyncOp failure code=0x%x status=0x%x",
+ code, status);
+ return;
+ }
+
+ cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+
+ if (scp->fileType == CM_SCACHETYPE_DIRECTORY) {
+ (*ResultCB)->ResultStatus = STATUS_FILE_IS_A_DIRECTORY;
+ lock_ReleaseWrite(&scp->rw);
+ cm_ReleaseSCache(scp);
+ osi_Log1(afsd_logp, "RDR_WriteFile File is a Directory scp=0x%p",
+ scp);
+ return;
+ }
+
+ if (scp->fileType != CM_SCACHETYPE_FILE) {
+ (*ResultCB)->ResultStatus = STATUS_REPARSE_POINT_NOT_RESOLVED;
+ lock_ReleaseWrite(&scp->rw);
+ cm_ReleaseSCache(scp);
+ osi_Log1(afsd_logp, "RDR_WriteFile File is a MountPoint or Link scp=0x%p",
+ scp);
+ return;
+ }
+
+ if (FileIOCB->EndOfFile.QuadPart != scp->length.QuadPart)
+ {
+ cm_attr_t setAttr;
+
+ memset(&setAttr, 0, sizeof(cm_attr_t));
+ if (FileIOCB->EndOfFile.QuadPart != scp->length.QuadPart) {
+ osi_Log4(afsd_logp, "RDR_WriteFile new length fid vol 0x%x vno 0x%x length 0x%x:%x",
+ scp->fid.volume, scp->fid.vnode,
+ FileIOCB->EndOfFile.HighPart,
+ FileIOCB->EndOfFile.LowPart);
+
+ setAttr.mask |= CM_ATTRMASK_LENGTH;
+ setAttr.length.LowPart = FileIOCB->EndOfFile.LowPart;
+ setAttr.length.HighPart = FileIOCB->EndOfFile.HighPart;
+ lock_ReleaseWrite(&scp->rw);
+ code = cm_SetAttr(scp, &setAttr, userp, &req);
+ osi_Log2(afsd_logp, "RDR_WriteFile cm_SetAttr failure scp=0x%p code 0x%x",
+ scp, code);
+ code = 0; /* ignore failure */
+ lock_ObtainWrite(&scp->rw);
+ }
+ }
+
+ /*
+ * The input buffer may contain data beyond the end of the file.
+ * Such data must be discarded.
+ */
+ if ( Offset->QuadPart + BytesToWrite > scp->length.QuadPart)
+ {
+ if ( Offset->QuadPart > scp->length.QuadPart) {
+ (*ResultCB)->ResultStatus = STATUS_SUCCESS;
+ lock_ReleaseWrite(&scp->rw);
+ cm_ReleaseSCache(scp);
+ osi_Log1(afsd_logp, "RDR_WriteFile Nothing to do scp=0x%p",
+ scp);
+ return;
+ }
+
+ BytesToWrite -= (afs_uint32)(Offset->QuadPart + BytesToWrite - scp->length.QuadPart);
+ }
+
+ if (bCacheBypass) {
+ code = cm_DirectWrite( scp, Offset, BytesToWrite,
+ CM_DIRECT_SCP_LOCKED,
+ userp, &req, Buffer, &ulBytesWritten);
+ } else {
+ code = raw_WriteData( scp, Offset, BytesToWrite, Buffer, userp, &req, &ulBytesWritten);
+ }
+
+ if (code) {
+ smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
+ (*ResultCB)->ResultStatus = status;
+ osi_Log2(afsd_logp, "RDR_WriteFile failure code=0x%x status=0x%x",
+ code, status);
+ } else {
+ (*ResultCB)->ResultStatus = STATUS_SUCCESS;
+ pFileIOResultCB->Length = ulBytesWritten;
+ pFileIOResultCB->DataVersion.QuadPart = scp->dataVersion;
+ pFileIOResultCB->Expiration.QuadPart = scp->cbExpires;
+ }
+
+ lock_ReleaseWrite(&scp->rw);
+ cm_ReleaseSCache(scp);
+ return;
+}