/*
* Copyright (c) 2008 Secure Endpoints, Inc.
- * Copyright (c) 2009-2011 Your File System, Inc.
+ * Copyright (c) 2009-2013 Your File System, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
static CHAR * RDR_extentBaseAddress = NULL;
void
-RDR_InitReq(cm_req_t *reqp)
+RDR_InitReq(cm_req_t *reqp, BOOL bWow64)
{
cm_InitReq(reqp);
reqp->flags |= CM_REQ_SOURCE_REDIR;
+ if (bWow64)
+ reqp->flags |= CM_REQ_WOW64;
}
void
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 )
{
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;
(*ppRedirInitInfo)->GlobalFileId.Hash = cm_data.rootFid.hash;
(*ppRedirInitInfo)->ExtentCount.QuadPart = cm_data.buf_nbuffers;
(*ppRedirInitInfo)->CacheBlockSize = cm_data.blockSize;
- (*ppRedirInitInfo)->MaxPathLinkCount = 512; /* this needs to become a registry value */
- (*ppRedirInitInfo)->NameArrayLength = 32; /* this needs to become a registry value */
+ (*ppRedirInitInfo)->MaxPathLinkCount = MAX_FID_COUNT;
+ (*ppRedirInitInfo)->NameArrayLength = MAX_FID_COUNT;
if (cm_virtualCache || cm_data.bufferSize <= maxMemoryCacheSize) {
osi_Log0(afsd_logp, "RDR_SetInitParams Initializing Memory Extent Interface");
(*ppRedirInitInfo)->MemoryCacheOffset.QuadPart = (LONGLONG)cm_data.bufDataBaseAddress;
} 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;
}
+static wchar_t cname[MAX_COMPUTERNAME_LENGTH+1] = L"";
+
cm_user_t *
RDR_GetLocalSystemUser( void)
{
smb_username_t *unp;
cm_user_t *userp = NULL;
- wchar_t cname[MAX_COMPUTERNAME_LENGTH+1];
- int cnamelen = MAX_COMPUTERNAME_LENGTH+1;
-
- GetComputerNameW(cname, &cnamelen);
- _wcsupr(cname);
+ if ( cname[0] == '\0') {
+ int len = MAX_COMPUTERNAME_LENGTH+1;
+ GetComputerNameW(cname, &len);
+ _wcsupr(cname);
+ }
unp = smb_FindUserByName(NTSID_LOCAL_SYSTEM, cname, SMB_FLAG_CREATE);
lock_ObtainMutex(&unp->mx);
if (!unp->userp)
smb_username_t *unp;
cm_user_t * userp = NULL;
RPC_WSTR UuidString = NULL;
- wchar_t cname[MAX_COMPUTERNAME_LENGTH+1];
- int cnamelen = MAX_COMPUTERNAME_LENGTH+1;
if (UuidToStringW((UUID *)pGuid, &UuidString) != RPC_S_OK)
goto done;
- GetComputerNameW(cname, &cnamelen);
- _wcsupr(cname);
+ if ( cname[0] == '\0') {
+ int len = MAX_COMPUTERNAME_LENGTH+1;
+ GetComputerNameW(cname, &len);
+ _wcsupr(cname);
+ }
unp = smb_FindUserByName(UuidString, cname, SMB_FLAG_CREATE);
lock_ObtainMutex(&unp->mx);
- if (!unp->userp)
+ if (!unp->userp) {
unp->userp = cm_NewUser();
+ memcpy(&unp->userp->authgroup, pGuid, sizeof(GUID));
+ }
unp->flags |= SMB_USERNAMEFLAG_SID;
lock_ReleaseMutex(&unp->mx);
userp = unp->userp;
}
/*
- * Obtain the status information for the specified object and
- *
+ * Obtain the status information for the specified object using
+ * an inline bulk status rpc. cm_BPlusDirEnumBulkStatOne() will
+ * obtain current status for the directory object, the object
+ * which is the focus of the inquiry and as many other objects
+ * in the directory for which there are not callbacks registered
+ * since we are likely to be asked for other objects in the directory.
*/
static afs_uint32
RDR_BulkStatLookup( cm_scache_t *dscp,
code);
}
-
if (enump)
{
code = cm_BPlusDirEnumBulkStatOne(enump, scp);
#define RDR_POP_WOW64 0x04
#define RDR_POP_NO_GETSTATUS 0x08
-afs_uint32
+static afs_uint32
RDR_PopulateCurrentEntry( IN AFSDirEnumEntry * pCurrentEntry,
IN DWORD dwMaxEntryLength,
IN cm_scache_t * dscp,
IN wchar_t * name,
IN wchar_t * shortName,
IN DWORD dwFlags,
+ IN afs_uint32 cmError,
OUT AFSDirEnumEntry **ppNextEntry,
OUT DWORD * pdwRemainingLength)
{
* status information. If not, perform a bulk status lookup of multiple
* entries in order to reduce the number of RPCs issued to the file server.
*/
- if ((scp->flags & CM_SCACHEFLAG_EACCESS))
+ if (cm_EAccesFindEntry(userp, &scp->fid))
bMustFake = TRUE;
else if (!cm_HaveCallback(scp)) {
lock_ReleaseWrite(&scp->rw);
code = RDR_BulkStatLookup(dscp, scp, userp, reqp);
if (code) {
- osi_Log2(afsd_logp, "RDR_PopulateCurrentEntry RXR_BulkStatLookup failed for scp=0x%p code=0x%x",
+ osi_Log2(afsd_logp, "RDR_PopulateCurrentEntry RDR_BulkStatLookup failed for scp=0x%p code=0x%x",
scp, code);
return code;
}
bMustFake = TRUE;
}
}
-
}
+ /* Populate the error code */
+ smb_MapNTError(cmError, &pCurrentEntry->NTStatus, TRUE);
+
/* Populate the real or fake data */
pCurrentEntry->FileId.Cell = scp->fid.cell;
pCurrentEntry->FileId.Volume = scp->fid.volume;
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;
wcsncpy(wname, name, len);
pCurrentEntry->FileNameLength = (ULONG)(sizeof(WCHAR) * len);
- osi_Log2(afsd_logp, "RDR_PopulateCurrentEntry scp=0x%p fileType=%d",
- scp, scp->fileType);
+ osi_Log3(afsd_logp, "RDR_PopulateCurrentEntry scp=0x%p fileType=%d dv=%u",
+ scp, scp->fileType, (afs_uint32)scp->dataVersion);
if (!(dwFlags & RDR_POP_NO_GETSTATUS))
cm_SyncOpDone( scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
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;
- }
+ size_t wtarget_len = 0;
+
+ if (scp->mountPointStringp[0]) {
+ char * mp;
+ char * s;
+ size_t offset = 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[offset],
+ wtarget_len * sizeof(char),
+ wtarget,
+ wtarget_len * sizeof(WCHAR));
+#else
+ mbstowcs(wtarget, &mp[offset], wtarget_len);
+#endif
+ } 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,
- 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
+ }
+ } 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) * len);
+
+ 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);
return code;
}
-afs_uint32
+static afs_uint32
RDR_PopulateCurrentEntryNoScp( IN AFSDirEnumEntry * pCurrentEntry,
IN DWORD dwMaxEntryLength,
IN cm_scache_t * dscp,
IN wchar_t * name,
IN wchar_t * shortName,
IN DWORD dwFlags,
+ IN afs_uint32 cmError,
OUT AFSDirEnumEntry **ppNextEntry,
OUT DWORD * pdwRemainingLength)
{
dwEntryLength = sizeof(AFSDirEnumEntry);
+ /* Populate the error code */
+ smb_MapNTError(cmError, &pCurrentEntry->NTStatus, TRUE);
+
+ /* Populate the fake data */
pCurrentEntry->FileId.Cell = fidp->cell;
pCurrentEntry->FileId.Volume = fidp->volume;
pCurrentEntry->FileId.Vnode = fidp->vnode;
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);
cm_scache_t * dscp = NULL;
cm_req_t req;
- RDR_InitReq(&req);
- if ( bWow64 )
- req.flags |= CM_REQ_WOW64;
+ RDR_InitReq(&req, bWow64);
osi_Log4(afsd_logp, "RDR_EnumerateDirectory FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
DirID.Cell, DirID.Volume, DirID.Vnode, DirID.Unique);
fid.unique = DirID.Unique;
fid.hash = DirID.Hash;
- code = cm_GetSCache(&fid, &dscp, userp, &req);
+ code = cm_GetSCache(&fid, NULL, &dscp, userp, &req);
if (code) {
smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
(*ResultCB)->ResultStatus = status;
return;
}
+ osi_Log1(afsd_logp, "RDR_EnumerateDirectory dv=%u", (afs_uint32)dscp->dataVersion);
+
/*
* If there is no enumeration handle, then this is a new query
- * and we must perform an enumeration for the specified object
+ * and we must perform an enumeration for the specified object.
*/
if (QueryCB->EnumHandle == (ULONG_PTR)NULL) {
cm_dirOp_t dirop;
code = cm_BeginDirOp(dscp, userp, &req, CM_DIRLOCK_READ, CM_DIROP_FLAG_NONE, &dirop);
if (code == 0) {
- code = cm_BPlusDirEnumerate(dscp, userp, &req, TRUE, NULL, !bSkipStatus, &enump);
+ code = cm_BPlusDirEnumerate(dscp, userp, &req,
+ TRUE /* dir locked */, NULL /* no mask */,
+ TRUE /* fetch status? */, &enump);
if (code) {
osi_Log1(afsd_logp, "RDR_EnumerateDirectory cm_BPlusDirEnumerate failure code=0x%x",
code);
enump = (cm_direnum_t *)QueryCB->EnumHandle;
}
- if (enump && ResultBufferLength) {
- cm_direnum_entry_t * entryp = NULL;
+ if (enump) {
+ if (ResultBufferLength == 0) {
+ code = cm_BPlusDirEnumBulkStat(enump);
+ if (code) {
+ osi_Log1(afsd_logp, "RDR_EnumerateDirectory cm_BPlusDirEnumBulkStat failure code=0x%x",
+ code);
+ }
+ } else {
+ cm_direnum_entry_t * entryp = NULL;
- getnextentry:
- if (dwMaxEntryLength < sizeof(AFSDirEnumEntry) + (MAX_PATH + MOUNTPOINTLEN) * sizeof(wchar_t)) {
- osi_Log0(afsd_logp, "RDR_EnumerateDirectory out of space, returning");
- goto outofspace;
- }
+ pDirEnumResp->SnapshotDataVersion.QuadPart = enump->dataVersion;
- code = cm_BPlusDirNextEnumEntry(enump, &entryp);
+ getnextentry:
+ if (dwMaxEntryLength < sizeof(AFSDirEnumEntry) + (MAX_PATH + MOUNTPOINTLEN) * sizeof(wchar_t)) {
+ osi_Log0(afsd_logp, "RDR_EnumerateDirectory out of space, returning");
+ goto outofspace;
+ }
- if ((code == 0 || code == CM_ERROR_STOPNOW) && entryp) {
- cm_scache_t *scp;
- int stopnow = (code == CM_ERROR_STOPNOW);
+ code = cm_BPlusDirNextEnumEntry(enump, &entryp);
- if ( !wcscmp(L".", entryp->name) || !wcscmp(L"..", entryp->name) ) {
- osi_Log0(afsd_logp, "RDR_EnumerateDirectory skipping . or ..");
- if (stopnow)
- goto outofspace;
- goto getnextentry;
- }
+ if ((code == 0 || code == CM_ERROR_STOPNOW) && entryp) {
+ cm_scache_t *scp = NULL;
+ int stopnow = (code == CM_ERROR_STOPNOW);
- if ( FALSE /* bSkipStatus */) {
- scp = cm_FindSCache(&entryp->fid);
- code = 0;
- } else {
- code = cm_GetSCache(&entryp->fid, &scp, userp, &req);
- }
+ if ( !wcscmp(L".", entryp->name) || !wcscmp(L"..", entryp->name) ) {
+ osi_Log0(afsd_logp, "RDR_EnumerateDirectory skipping . or ..");
+ if (stopnow)
+ goto outofspace;
+ goto getnextentry;
+ }
+
+ if (bSkipStatus) {
+ code = cm_GetSCache(&entryp->fid, &dscp->fid, &scp, userp, &req);
+ if (code) {
+ osi_Log5(afsd_logp, "RDR_EnumerateDirectory cm_GetSCache failure cell %u vol %u vnode %u uniq %u code=0x%x",
+ entryp->fid.cell, entryp->fid.volume, entryp->fid.vnode, entryp->fid.unique, code);
+ }
+ } else {
+ code = entryp->errorCode;
+ scp = code ? NULL : cm_FindSCache(&entryp->fid);
+ }
- if (!code) {
if (scp) {
- code = RDR_PopulateCurrentEntry(pCurrentEntry, dwMaxEntryLength,
+ code = RDR_PopulateCurrentEntry( pCurrentEntry, dwMaxEntryLength,
dscp, scp, userp, &req,
entryp->name,
- cm_Is8Dot3(entryp->name) ? NULL : entryp->shortName,
+ cm_shortNames && cm_Is8Dot3(entryp->name) ? NULL : entryp->shortName,
(bWow64 ? RDR_POP_WOW64 : 0) |
(bSkipStatus ? RDR_POP_NO_GETSTATUS : 0),
+ code,
&pCurrentEntry, &dwMaxEntryLength);
cm_ReleaseSCache(scp);
} else {
code = RDR_PopulateCurrentEntryNoScp( pCurrentEntry, dwMaxEntryLength,
dscp, &entryp->fid, userp, &req,
entryp->name,
- cm_Is8Dot3(entryp->name) ? NULL : entryp->shortName,
+ cm_shortNames && cm_Is8Dot3(entryp->name) ? NULL : entryp->shortName,
(bWow64 ? RDR_POP_WOW64 : 0),
+ code,
&pCurrentEntry, &dwMaxEntryLength);
}
if (stopnow)
goto outofspace;
goto getnextentry;
- } else {
- osi_Log2(afsd_logp, "RDR_EnumerateDirectory cm_GetSCache failure scp=0x%p code=0x%x",
- scp, code);
- if (stopnow)
- goto outofspace;
- goto getnextentry;
}
}
}
- if (enump && ResultBufferLength == 0) {
- code = cm_BPlusDirEnumBulkStat(enump);
- if (code) {
- osi_Log1(afsd_logp, "RDR_EnumerateDirectory cm_BPlusDirEnumBulkStat failure code=0x%x",
- code);
- }
- }
outofspace:
if (code || enump->next == enump->count || ResultBufferLength == 0) {
(*ResultCB)->ResultBufferLength = ResultBufferLength - dwMaxEntryLength;
pDirEnumResp->EnumHandle = (ULONG_PTR) enump;
+ pDirEnumResp->CurrentDataVersion.QuadPart = dscp->dataVersion;
}
if (dscp)
IN WCHAR *FileNameCounted,
IN DWORD FileNameLength,
IN BOOL CaseSensitive,
+ IN BOOL LastComponent,
IN BOOL bWow64,
IN BOOL bHoldFid,
IN BOOL bNoFollow,
IN DWORD ResultBufferLength,
IN OUT AFSCommResult **ResultCB)
{
+ AFSFileEvalResultCB *pEvalResultCB = NULL;
AFSDirEnumEntry * pCurrentEntry;
- size_t size = sizeof(AFSCommResult) + ResultBufferLength - 1;
+ size_t size = ResultBufferLength ? sizeof(AFSCommResult) + ResultBufferLength - 1 : sizeof(AFSCommResult);
afs_uint32 code = 0;
cm_scache_t * scp = NULL;
cm_scache_t * dscp = NULL;
size_t cbName;
BOOL bVol = FALSE;
wchar_t FileName[260];
+ afs_uint32 lookupFlags;
StringCchCopyNW(FileName, 260, FileNameCounted, FileNameLength / sizeof(WCHAR));
- RDR_InitReq(&req);
- if ( bWow64 )
- req.flags |= CM_REQ_WOW64;
+ RDR_InitReq(&req, bWow64);
osi_Log4(afsd_logp, "RDR_EvaluateNodeByName parent FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
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");
}
memset(*ResultCB, 0, size);
- (*ResultCB)->ResultBufferLength = ResultBufferLength;
- if (ResultBufferLength)
- pCurrentEntry = (AFSDirEnumEntry *)&(*ResultCB)->ResultData;
+ (*ResultCB)->ResultBufferLength = 0;
+ dwRemaining = ResultBufferLength;
+ if (ResultBufferLength >= sizeof( AFSFileEvalResultCB)) {
+ pEvalResultCB = (AFSFileEvalResultCB *)&(*ResultCB)->ResultData;
+ pCurrentEntry = &pEvalResultCB->DirEnum;
+ dwRemaining -= (sizeof( AFSFileEvalResultCB) - sizeof( AFSDirEnumEntry));
+ }
if (ParentID.Cell != 0) {
parentFid.cell = ParentID.Cell;
parentFid.unique = ParentID.Unique;
parentFid.hash = ParentID.Hash;
- code = cm_GetSCache(&parentFid, &dscp, userp, &req);
+ code = cm_GetSCache(&parentFid, NULL, &dscp, userp, &req);
if (code) {
smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
(*ResultCB)->ResultStatus = status;
+ if ( status == STATUS_INVALID_HANDLE)
+ status = STATUS_OBJECT_PATH_INVALID;
osi_Log2(afsd_logp, "RDR_EvaluateNodeByName cm_GetSCache parentFID failure code=0x%x status=0x%x",
code, status);
free(wszName);
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);
- cm_strlwr_utf16(wszName);
- 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);
+ }
+#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);
+ code = cm_EvaluateVolumeReference(wszName, CM_FLAG_CHECKPATH, userp, &req, &scp);
+ }
+#endif
}
if (code == 0 && scp) {
wchar_t shortName[13]=L"";
- if (bVol) {
+ if (!cm_shortNames) {
+ shortName[0] = L'\0';
+ } else if (bVol) {
cm_Gen8Dot3VolNameW(scp->fid.cell, scp->fid.volume, shortName, NULL);
} else if (!cm_Is8Dot3(wszName)) {
cm_dirFid_t dfid;
cm_Gen8Dot3NameIntW(FileName, &dfid, shortName, NULL);
} else {
- shortName[0] = '\0';
+ shortName[0] = L'\0';
}
- code = RDR_PopulateCurrentEntry(pCurrentEntry, ResultBufferLength,
+ code = RDR_PopulateCurrentEntry(pCurrentEntry, dwRemaining,
dscp, scp, userp, &req,
FileName, shortName,
(bWow64 ? RDR_POP_WOW64 : 0) |
(bNoFollow ? 0 : (RDR_POP_FOLLOW_MOUNTPOINTS | RDR_POP_EVALUATE_SYMLINKS)),
- NULL, &dwRemaining);
+ 0, NULL, &dwRemaining);
if (bHoldFid)
RDR_FlagScpInUse( scp, FALSE );
cm_ReleaseSCache(scp);
osi_Log2(afsd_logp, "RDR_EvaluateNodeByName FAILURE code=0x%x status=0x%x",
code, status);
} else {
+ pEvalResultCB->ParentDataVersion.QuadPart = dscp->dataVersion;
(*ResultCB)->ResultStatus = STATUS_SUCCESS;
(*ResultCB)->ResultBufferLength = ResultBufferLength - dwRemaining;
osi_Log0(afsd_logp, "RDR_EvaluateNodeByName SUCCESS");
IN DWORD ResultBufferLength,
IN OUT AFSCommResult **ResultCB)
{
- AFSDirEnumEntry * pCurrentEntry;
- size_t size = sizeof(AFSCommResult) + ResultBufferLength - 1;
+ AFSFileEvalResultCB *pEvalResultCB = NULL;
+ AFSDirEnumEntry * pCurrentEntry = NULL;
+ size_t size = ResultBufferLength ? sizeof(AFSCommResult) + ResultBufferLength - 1 : sizeof(AFSCommResult);
afs_uint32 code = 0;
cm_scache_t * scp = NULL;
cm_scache_t * dscp = NULL;
}
memset(*ResultCB, 0, size);
- (*ResultCB)->ResultBufferLength = ResultBufferLength;
+ (*ResultCB)->ResultBufferLength = 0;
dwRemaining = ResultBufferLength;
- if (ResultBufferLength)
- pCurrentEntry = (AFSDirEnumEntry *)&(*ResultCB)->ResultData;
+ if (ResultBufferLength >= sizeof( AFSFileEvalResultCB)) {
+ pEvalResultCB = (AFSFileEvalResultCB *)&(*ResultCB)->ResultData;
+ pCurrentEntry = &pEvalResultCB->DirEnum;
+ dwRemaining -= (sizeof( AFSFileEvalResultCB) - sizeof( AFSDirEnumEntry));
+ }
- RDR_InitReq(&req);
- if ( bWow64 )
- req.flags |= CM_REQ_WOW64;
+ RDR_InitReq(&req, bWow64);
if (SourceID.Cell != 0) {
- Fid.cell = SourceID.Cell;
- Fid.volume = SourceID.Volume;
- Fid.vnode = SourceID.Vnode;
- Fid.unique = SourceID.Unique;
- Fid.hash = SourceID.Hash;
-
- code = cm_GetSCache(&Fid, &scp, userp, &req);
+ cm_SetFid(&Fid, SourceID.Cell, SourceID.Volume, SourceID.Vnode, SourceID.Unique);
+ code = cm_GetSCache(&Fid, NULL, &scp, userp, &req);
if (code) {
smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
(*ResultCB)->ResultStatus = status;
if (ParentID.Cell != 0) {
cm_SetFid(&parentFid, ParentID.Cell, ParentID.Volume, ParentID.Vnode, ParentID.Unique);
- code = cm_GetSCache(&parentFid, &dscp, userp, &req);
+ code = cm_GetSCache(&parentFid, NULL, &dscp, userp, &req);
if (code) {
cm_ReleaseSCache(scp);
smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
+ if ( status == STATUS_INVALID_HANDLE)
+ status = STATUS_OBJECT_PATH_INVALID;
(*ResultCB)->ResultStatus = status;
osi_Log2(afsd_logp, "RDR_EvaluateNodeByID cm_GetSCache parentFID failure code=0x%x status=0x%x",
code, status);
cm_HoldSCache(dscp);
} else if (scp->parentVnode) {
cm_SetFid(&parentFid, SourceID.Cell, SourceID.Volume, scp->parentVnode, scp->parentUnique);
- code = cm_GetSCache(&parentFid, &dscp, userp, &req);
+ code = cm_GetSCache(&parentFid, NULL, &dscp, userp, &req);
if (code) {
cm_ReleaseSCache(scp);
smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
+ if ( status == STATUS_INVALID_HANDLE)
+ status = STATUS_OBJECT_PATH_INVALID;
(*ResultCB)->ResultStatus = status;
osi_Log2(afsd_logp, "RDR_EvaluateNodeByID cm_GetSCache parentFID failure code=0x%x status=0x%x",
code, status);
return;
}
- code = RDR_PopulateCurrentEntry(pCurrentEntry, ResultBufferLength,
+ 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)),
- NULL, &dwRemaining);
+ 0, NULL, &dwRemaining);
if (bHoldFid)
RDR_FlagScpInUse( scp, FALSE );
osi_Log2(afsd_logp, "RDR_EvaluateNodeByID FAILURE code=0x%x status=0x%x",
code, status);
} else {
+ pEvalResultCB->ParentDataVersion.QuadPart = dscp->dataVersion;
+
(*ResultCB)->ResultStatus = STATUS_SUCCESS;
(*ResultCB)->ResultBufferLength = ResultBufferLength - dwRemaining;
osi_Log0(afsd_logp, "RDR_EvaluateNodeByID SUCCESS");
CreateCB->ParentId.Vnode, CreateCB->ParentId.Unique);
osi_Log1(afsd_logp, "... name=%S", osi_LogSaveStringW(afsd_logp, FileName));
- RDR_InitReq(&req);
- if ( bWow64 )
- req.flags |= CM_REQ_WOW64;
+ RDR_InitReq(&req, bWow64);
memset(&setAttr, 0, sizeof(cm_attr_t));
*ResultCB = (AFSCommResult *)malloc(size);
parentFid.unique = CreateCB->ParentId.Unique;
parentFid.hash = CreateCB->ParentId.Hash;
- code = cm_GetSCache(&parentFid, &dscp, userp, &req);
+ code = cm_GetSCache(&parentFid, NULL, &dscp, userp, &req);
if (code) {
smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
(*ResultCB)->ResultStatus = status;
+ if ( status == STATUS_INVALID_HANDLE)
+ status = STATUS_OBJECT_PATH_INVALID;
osi_Log2(afsd_logp, "RDR_CreateFileEntry cm_GetSCache ParentFID failure code=0x%x status=0x%x",
code, status);
return;
cm_SyncOpDone(dscp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
lock_ReleaseWrite(&dscp->rw);
- dfid.vnode = htonl(scp->fid.vnode);
- dfid.unique = htonl(scp->fid.unique);
+ if (cm_shortNames) {
+ dfid.vnode = htonl(scp->fid.vnode);
+ dfid.unique = htonl(scp->fid.unique);
- if (!cm_Is8Dot3(FileName))
- cm_Gen8Dot3NameIntW(FileName, &dfid, shortName, NULL);
- else
- shortName[0] = '\0';
+ if (!cm_Is8Dot3(FileName))
+ cm_Gen8Dot3NameIntW(FileName, &dfid, shortName, NULL);
+ else
+ shortName[0] = '\0';
+ }
code = RDR_PopulateCurrentEntry(&pResultCB->DirEnum, dwRemaining,
dscp, scp, userp, &req, FileName, shortName,
RDR_POP_FOLLOW_MOUNTPOINTS | RDR_POP_EVALUATE_SYMLINKS,
- NULL, &dwRemaining);
+ 0, NULL, &dwRemaining);
if (bHoldFid)
RDR_FlagScpInUse( scp, FALSE );
DWORD status;
BOOL bScpLocked = FALSE;
- RDR_InitReq(&req);
- if ( bWow64 )
- req.flags |= CM_REQ_WOW64;
+ RDR_InitReq(&req, bWow64);
memset(&setAttr, 0, sizeof(cm_attr_t));
osi_Log4(afsd_logp, "RDR_UpdateFileEntry parent FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
parentFid.unique = UpdateCB->ParentId.Unique;
parentFid.hash = UpdateCB->ParentId.Hash;
- code = cm_GetSCache(&parentFid, &dscp, userp, &req);
+ code = cm_GetSCache(&parentFid, NULL, &dscp, userp, &req);
if (code) {
smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
(*ResultCB)->ResultStatus = status;
+ if ( status == STATUS_INVALID_HANDLE)
+ status = STATUS_OBJECT_PATH_INVALID;
osi_Log2(afsd_logp, "RDR_UpdateFileEntry cm_GetSCache ParentFID failure code=0x%x status=0x%x",
code, status);
return;
}
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;
Fid.unique = FileId.Unique;
Fid.hash = FileId.Hash;
- code = cm_GetSCache(&Fid, &scp, userp, &req);
+ code = cm_GetSCache(&Fid, &dscp->fid, &scp, userp, &req);
if (code) {
smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
(*ResultCB)->ResultStatus = status;
pResultCB = (AFSFileUpdateResultCB *)(*ResultCB)->ResultData;
+ pResultCB->ParentDataVersion.QuadPart = dscp->dataVersion;
+
code = RDR_PopulateCurrentEntry(&pResultCB->DirEnum, dwRemaining,
dscp, scp, userp, &req, NULL, NULL,
RDR_POP_FOLLOW_MOUNTPOINTS | RDR_POP_EVALUATE_SYMLINKS,
- NULL, &dwRemaining);
+ 0, NULL, &dwRemaining);
(*ResultCB)->ResultBufferLength = ResultBufferLength - dwRemaining;
osi_Log0(afsd_logp, "RDR_UpdateFileEntry SUCCESS");
} else {
IN DWORD ResultBufferLength,
IN OUT AFSCommResult **ResultCB)
{
- size_t size = sizeof(AFSCommResult);
+ AFSFileCleanupResultCB *pResultCB = NULL;
+ size_t size = sizeof(AFSCommResult) + ResultBufferLength - 1;
cm_fid_t Fid;
cm_fid_t parentFid;
afs_uint32 code = 0;
BOOL bFlushFile = FALSE;
cm_key_t key;
- RDR_InitReq(&req);
- if ( bWow64 )
- req.flags |= CM_REQ_WOW64;
+ RDR_InitReq(&req, bWow64);
memset(&setAttr, 0, sizeof(cm_attr_t));
osi_Log4(afsd_logp, "RDR_CleanupFileEntry parent FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
parentFid.hash = CleanupCB->ParentId.Hash;
if (parentFid.cell) {
- code = cm_GetSCache(&parentFid, &dscp, userp, &req);
+ code = cm_GetSCache(&parentFid, NULL, &dscp, userp, &req);
if (code) {
smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
+ if ( status == STATUS_INVALID_HANDLE)
+ status = STATUS_OBJECT_PATH_INVALID;
(*ResultCB)->ResultStatus = status;
osi_Log2(afsd_logp, "RDR_CleanupFileEntry cm_GetSCache ParentFID failure code=0x%x status=0x%x",
code, status);
Fid.unique = FileId.Unique;
Fid.hash = FileId.Hash;
- code = cm_GetSCache(&Fid, &scp, userp, &req);
+ code = cm_GetSCache(&Fid, dscp ? &dscp->fid : NULL, &scp, userp, &req);
if (code) {
osi_Log1(afsd_logp, "RDR_CleanupFileEntry cm_GetSCache object FID failure code=0x%x",
code);
}
cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
- if (scp->redirBufCount > 0) {
+ if (bLastHandle && (scp->fileType == CM_SCACHETYPE_FILE) &&
+ scp->redirBufCount > 0)
+ {
LARGE_INTEGER heldExtents;
AFSFileExtentCB extentList[1024];
DWORD extentCount = 0;
scp->flags &= ~CM_SCACHEFLAG_RDR_IN_USE;
}
- if (bLastHandle || bFlushFile) {
- if (bScpLocked) {
- lock_ReleaseWrite(&scp->rw);
- bScpLocked = FALSE;
- }
- code = cm_FSync(scp, userp, &req, bScpLocked);
- if (bLastHandle && code)
- goto on_error;
- }
-
- if (bUnlockFile || bDeleteFile) {
- if (!bScpLocked) {
- lock_ObtainWrite(&scp->rw);
- bScpLocked = TRUE;
- }
- code = cm_SyncOp(scp, NULL, userp, &req, 0,
- CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_LOCK);
- if (code) {
- osi_Log2(afsd_logp, "RDR_CleanupFileEntry cm_SyncOp (2) failure scp=0x%p code=0x%x",
- scp, code);
- goto on_error;
- }
-
- key = cm_GenerateKey(CM_SESSION_IFS, CleanupCB->ProcessId, 0);
-
- /* the scp is now locked and current */
- code = cm_UnlockByKey(scp, key,
- bDeleteFile ? CM_UNLOCK_FLAG_BY_FID : 0,
- userp, &req);
+ /* If not a readonly object, flush dirty data and update metadata */
+ if (!(scp->flags & CM_SCACHEFLAG_RO)) {
+ 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) {
+ cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_ASYNCSTORE);
- cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_LOCK);
+ 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;
+ }
- if (code)
- goto on_error;
- }
+ code = cm_FSync(scp, userp, &req, bScpLocked);
+ }
+ }
+ if (bLastHandle && code)
+ goto unlock;
+ }
- if (CleanupCB->ChangeTime.QuadPart) {
+ if (CleanupCB->ChangeTime.QuadPart) {
- if (scp->fileType == CM_SCACHETYPE_FILE) {
- /* Do not set length and other attributes at the same time */
- if (scp->length.QuadPart != CleanupCB->AllocationSize.QuadPart) {
- osi_Log2(afsd_logp, "RDR_CleanupFileEntry Length Change 0x%x -> 0x%x",
- (afs_uint32)scp->length.QuadPart, (afs_uint32)CleanupCB->AllocationSize.QuadPart);
- setAttr.mask |= CM_ATTRMASK_LENGTH;
- setAttr.length.LowPart = CleanupCB->AllocationSize.LowPart;
- setAttr.length.HighPart = CleanupCB->AllocationSize.HighPart;
+ if (scp->fileType == CM_SCACHETYPE_FILE) {
+ /* Do not set length and other attributes at the same time */
+ if (scp->length.QuadPart != CleanupCB->AllocationSize.QuadPart) {
+ osi_Log2(afsd_logp, "RDR_CleanupFileEntry Length Change 0x%x -> 0x%x",
+ (afs_uint32)scp->length.QuadPart, (afs_uint32)CleanupCB->AllocationSize.QuadPart);
+ setAttr.mask |= CM_ATTRMASK_LENGTH;
+ setAttr.length.LowPart = CleanupCB->AllocationSize.LowPart;
+ setAttr.length.HighPart = CleanupCB->AllocationSize.HighPart;
- if (bScpLocked) {
- lock_ReleaseWrite(&scp->rw);
- bScpLocked = FALSE;
+ if (bScpLocked) {
+ lock_ReleaseWrite(&scp->rw);
+ bScpLocked = FALSE;
+ }
+ code = cm_SetAttr(scp, &setAttr, userp, &req);
+ if (code)
+ goto unlock;
+ setAttr.mask = 0;
}
- code = cm_SetAttr(scp, &setAttr, userp, &req);
- if (code)
- goto on_error;
- setAttr.mask = 0;
}
- }
- if (!bScpLocked) {
- lock_ObtainWrite(&scp->rw);
- bScpLocked = TRUE;
- }
+ if (!bScpLocked) {
+ lock_ObtainWrite(&scp->rw);
+ bScpLocked = TRUE;
+ }
- if ((scp->unixModeBits & 0200) && (CleanupCB->FileAttributes & FILE_ATTRIBUTE_READONLY)) {
- setAttr.mask |= CM_ATTRMASK_UNIXMODEBITS;
- setAttr.unixModeBits = scp->unixModeBits & ~0222;
- } else if (!(scp->unixModeBits & 0200) && !(CleanupCB->FileAttributes & FILE_ATTRIBUTE_READONLY)) {
- setAttr.mask |= CM_ATTRMASK_UNIXMODEBITS;
- setAttr.unixModeBits = scp->unixModeBits | 0222;
+ if ((scp->unixModeBits & 0200) && (CleanupCB->FileAttributes & FILE_ATTRIBUTE_READONLY)) {
+ setAttr.mask |= CM_ATTRMASK_UNIXMODEBITS;
+ setAttr.unixModeBits = scp->unixModeBits & ~0222;
+ } else if (!(scp->unixModeBits & 0200) && !(CleanupCB->FileAttributes & FILE_ATTRIBUTE_READONLY)) {
+ setAttr.mask |= CM_ATTRMASK_UNIXMODEBITS;
+ setAttr.unixModeBits = scp->unixModeBits | 0222;
+ }
}
- }
- if (CleanupCB->LastWriteTime.QuadPart) {
- ft.dwLowDateTime = CleanupCB->LastWriteTime.LowPart;
- ft.dwHighDateTime = CleanupCB->LastWriteTime.HighPart;
+ if (CleanupCB->LastWriteTime.QuadPart) {
+ ft.dwLowDateTime = CleanupCB->LastWriteTime.LowPart;
+ ft.dwHighDateTime = CleanupCB->LastWriteTime.HighPart;
- cm_UnixTimeFromLargeSearchTime(&clientModTime, &ft);
- if (scp->clientModTime != clientModTime) {
- setAttr.mask |= CM_ATTRMASK_CLIENTMODTIME;
- setAttr.clientModTime = clientModTime;
+ cm_UnixTimeFromLargeSearchTime(&clientModTime, &ft);
+ if (scp->clientModTime != clientModTime) {
+ setAttr.mask |= CM_ATTRMASK_CLIENTMODTIME;
+ setAttr.clientModTime = clientModTime;
+ }
}
- }
- /* call setattr */
- if (setAttr.mask) {
- lock_ReleaseWrite(&scp->rw);
- bScpLocked = FALSE;
- code = cm_SetAttr(scp, &setAttr, userp, &req);
- } else
- code = 0;
+ /* call setattr */
+ if (setAttr.mask) {
+ if (bScpLocked) {
+ lock_ReleaseWrite(&scp->rw);
+ bScpLocked = FALSE;
+ }
+ code = cm_SetAttr(scp, &setAttr, userp, &req);
+ } else
+ code = 0;
+ }
+ unlock:
/* Now drop the lock enforcing the share access */
if ( CleanupCB->FileAccess != AFS_FILE_ACCESS_NOLOCK) {
unsigned int sLockType;
}
}
+ if (bUnlockFile || bDeleteFile) {
+ if (!bScpLocked) {
+ lock_ObtainWrite(&scp->rw);
+ bScpLocked = TRUE;
+ }
+ code = cm_SyncOp(scp, NULL, userp, &req, 0,
+ CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_LOCK);
+ if (code) {
+ osi_Log2(afsd_logp, "RDR_CleanupFileEntry cm_SyncOp (2) failure scp=0x%p code=0x%x",
+ scp, code);
+ goto on_error;
+ }
+
+ key = cm_GenerateKey(CM_SESSION_IFS, CleanupCB->ProcessId, 0);
+
+ /* the scp is now locked and current */
+ code = cm_UnlockByKey(scp, key,
+ bDeleteFile ? CM_UNLOCK_FLAG_BY_FID : 0,
+ userp, &req);
+
+ cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_LOCK);
+
+ if (code)
+ goto on_error;
+ }
+
on_error:
if (bDscpLocked)
lock_ReleaseWrite(&dscp->rw);
if (bScpLocked)
lock_ReleaseWrite(&scp->rw);
- if (dscp && bDeleteFile) {
+ if (code == 0 && dscp && bDeleteFile) {
WCHAR FileName[260];
StringCchCopyNW(FileName, 260, FileNameCounted, FileNameLength / sizeof(WCHAR));
}
if (code == 0) {
+ if ( ResultBufferLength >= sizeof( AFSFileCleanupResultCB))
+ {
+ (*ResultCB)->ResultBufferLength = sizeof( AFSFileCleanupResultCB);
+ pResultCB = (AFSFileCleanupResultCB *)&(*ResultCB)->ResultData;
+ pResultCB->ParentDataVersion.QuadPart = dscp ? dscp->dataVersion : 0;
+ } else {
+ (*ResultCB)->ResultBufferLength = 0;
+ }
+
(*ResultCB)->ResultStatus = 0;
- (*ResultCB)->ResultBufferLength = 0;
osi_Log0(afsd_logp, "RDR_CleanupFileEntry SUCCESS");
} else {
smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
(*ResultCB)->ResultStatus = status;
- (*ResultCB)->ResultBufferLength = 0;
osi_Log2(afsd_logp, "RDR_CleanupFileEntry FAILURE code=0x%x status=0x%x",
code, status);
}
+
if (scp)
cm_ReleaseSCache(scp);
if (dscp)
osi_LogSaveStringW(afsd_logp, FileName),
bCheckOnly);
- RDR_InitReq(&req);
- if ( bWow64 )
- req.flags |= CM_REQ_WOW64;
+ RDR_InitReq(&req, bWow64);
memset(&setAttr, 0, sizeof(cm_attr_t));
*ResultCB = (AFSCommResult *)malloc( size);
parentFid.unique = ParentId.Unique;
parentFid.hash = ParentId.Hash;
- code = cm_GetSCache(&parentFid, &dscp, userp, &req);
+ code = cm_GetSCache(&parentFid, NULL, &dscp, userp, &req);
if (code) {
smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
+ if ( status == STATUS_INVALID_HANDLE)
+ status = STATUS_OBJECT_PATH_INVALID;
(*ResultCB)->ResultStatus = status;
osi_Log2(afsd_logp, "RDR_DeleteFileEntry cm_GetSCache ParentFID failure code=0x%x status=0x%x",
code, status);
return;
}
- 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);
- if (code) {
- smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
- (*ResultCB)->ResultStatus = status;
- (*ResultCB)->ResultBufferLength = 0;
- lock_ReleaseWrite(&scp->rw);
+ 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);
+ if (code) {
+ smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
+ (*ResultCB)->ResultStatus = status;
+ (*ResultCB)->ResultBufferLength = 0;
+ lock_ReleaseWrite(&scp->rw);
cm_ReleaseSCache(scp);
cm_ReleaseSCache(dscp);
osi_Log3(afsd_logp, "RDR_DeleteFileEntry cm_SyncOp Lock failure scp=0x%p code=0x%x status=0x%x",
DWORD TargetFileNameLength = pRenameCB->TargetNameLength;
cm_fid_t SourceParentFid;
cm_fid_t TargetParentFid;
+ cm_fid_t SourceFid;
+ cm_fid_t OrigTargetFid = {0,0,0,0,0};
+ cm_fid_t TargetFid;
cm_scache_t * oldDscp;
cm_scache_t * newDscp;
+ cm_dirOp_t dirop;
wchar_t shortName[13];
wchar_t SourceFileName[260];
wchar_t TargetFileName[260];
afs_uint32 code;
DWORD status;
- RDR_InitReq(&req);
- if ( bWow64 )
- req.flags |= CM_REQ_WOW64;
+ RDR_InitReq(&req, bWow64);
StringCchCopyNW(SourceFileName, 260, SourceFileNameCounted, SourceFileNameLength / sizeof(WCHAR));
StringCchCopyNW(TargetFileName, 260, TargetFileNameCounted, TargetFileNameLength / sizeof(WCHAR));
TargetParentFid.unique = TargetParentId.Unique;
TargetParentFid.hash = TargetParentId.Hash;
- code = cm_GetSCache(&SourceParentFid, &oldDscp, userp, &req);
+ code = cm_GetSCache(&SourceParentFid, NULL, &oldDscp, userp, &req);
if (code) {
osi_Log1(afsd_logp, "RDR_RenameFileEntry cm_GetSCache source parent failed code 0x%x", code);
smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
+ if ( status == STATUS_INVALID_HANDLE)
+ status = STATUS_OBJECT_PATH_INVALID;
(*ResultCB)->ResultStatus = status;
return;
}
if (code) {
osi_Log2(afsd_logp, "RDR_RenameFileEntry cm_SyncOp oldDscp 0x%p failed code 0x%x", oldDscp, code);
smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
+ if ( status == STATUS_INVALID_HANDLE)
+ status = STATUS_OBJECT_PATH_INVALID;
(*ResultCB)->ResultStatus = status;
lock_ReleaseWrite(&oldDscp->rw);
cm_ReleaseSCache(oldDscp);
return;
}
- code = cm_GetSCache(&TargetParentFid, &newDscp, userp, &req);
+ code = cm_GetSCache(&TargetParentFid, NULL, &newDscp, userp, &req);
if (code) {
osi_Log1(afsd_logp, "RDR_RenameFileEntry cm_GetSCache target parent failed code 0x%x", code);
smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
return;
}
+ /* Obtain the original FID just for debugging purposes */
+ code = cm_BeginDirOp( oldDscp, userp, &req, CM_DIRLOCK_READ, CM_DIROP_FLAG_NONE, &dirop);
+ if (code == 0) {
+ code = cm_BPlusDirLookup(&dirop, SourceFileName, &SourceFid);
+ code = cm_BPlusDirLookup(&dirop, TargetFileName, &OrigTargetFid);
+ cm_EndDirOp(&dirop);
+ }
+
code = cm_Rename( oldDscp, NULL, SourceFileName,
newDscp, TargetFileName, userp, &req);
if (code == 0) {
- cm_dirOp_t dirop;
- cm_fid_t targetFid;
cm_scache_t *scp = 0;
DWORD dwRemaining;
code = cm_BeginDirOp( newDscp, userp, &req, CM_DIRLOCK_READ, CM_DIROP_FLAG_NONE, &dirop);
if (code == 0) {
- code = cm_BPlusDirLookup(&dirop, TargetFileName, &targetFid);
+ code = cm_BPlusDirLookup(&dirop, TargetFileName, &TargetFid);
cm_EndDirOp(&dirop);
}
}
osi_Log4(afsd_logp, "RDR_RenameFileEntry Target FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
- targetFid.cell, targetFid.volume,
- targetFid.vnode, targetFid.unique);
+ TargetFid.cell, TargetFid.volume,
+ TargetFid.vnode, TargetFid.unique);
- code = cm_GetSCache(&targetFid, &scp, userp, &req);
+ code = cm_GetSCache(&TargetFid, &newDscp->fid, &scp, userp, &req);
if (code) {
osi_Log1(afsd_logp, "RDR_RenameFileEntry cm_GetSCache target failed code 0x%x", code);
smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
return;
}
- cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
- lock_ReleaseWrite(&scp->rw);
+ cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+ lock_ReleaseWrite(&scp->rw);
+
+ if (cm_shortNames) {
+ dfid.vnode = htonl(scp->fid.vnode);
+ dfid.unique = htonl(scp->fid.unique);
+
+ if (!cm_Is8Dot3(TargetFileName))
+ cm_Gen8Dot3NameIntW(TargetFileName, &dfid, shortName, NULL);
+ else
+ shortName[0] = '\0';
+ }
+
+ RDR_PopulateCurrentEntry(&pResultCB->DirEnum, dwRemaining,
+ newDscp, scp, userp, &req, TargetFileName, shortName,
+ RDR_POP_FOLLOW_MOUNTPOINTS | RDR_POP_EVALUATE_SYMLINKS,
+ 0, NULL, &dwRemaining);
+ (*ResultCB)->ResultBufferLength = ResultBufferLength - dwRemaining;
+ cm_ReleaseSCache(scp);
+
+ osi_Log0(afsd_logp, "RDR_RenameFileEntry SUCCESS");
+ } else {
+ osi_Log3(afsd_logp, "RDR_RenameFileEntry cm_Rename oldDscp 0x%p newDscp 0x%p failed code 0x%x",
+ oldDscp, newDscp, code);
+ smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
+ (*ResultCB)->ResultStatus = status;
+ (*ResultCB)->ResultBufferLength = 0;
+ }
+
+ cm_ReleaseSCache(oldDscp);
+ cm_ReleaseSCache(newDscp);
+ return;
+}
+
+/*
+ * AFS does not support cross-directory hard links but RDR_HardLinkFileEntry
+ * is written as if AFS does. The check for cross-directory links is
+ * implemented in cm_Link().
+ *
+ * Windows supports optional ReplaceIfExists functionality. The AFS file
+ * server does not. If the target name already exists and bReplaceIfExists
+ * is true, check to see if the user has insert permission before calling
+ * cm_Unlink() on the existing object. If the user does not have insert
+ * permission return STATUS_ACCESS_DENIED.
+ */
+
+void
+RDR_HardLinkFileEntry( IN cm_user_t *userp,
+ IN WCHAR *SourceFileNameCounted,
+ IN DWORD SourceFileNameLength,
+ IN AFSFileID SourceFileId,
+ IN AFSFileHardLinkCB *pHardLinkCB,
+ IN BOOL bWow64,
+ IN DWORD ResultBufferLength,
+ IN OUT AFSCommResult **ResultCB)
+{
+
+ AFSFileHardLinkResultCB *pResultCB = NULL;
+ size_t size = sizeof(AFSCommResult) + ResultBufferLength - 1;
+ AFSFileID SourceParentId = pHardLinkCB->SourceParentId;
+ AFSFileID TargetParentId = pHardLinkCB->TargetParentId;
+ WCHAR * TargetFileNameCounted = pHardLinkCB->TargetName;
+ DWORD TargetFileNameLength = pHardLinkCB->TargetNameLength;
+ cm_fid_t SourceParentFid;
+ cm_fid_t TargetParentFid;
+ cm_fid_t SourceFid;
+ cm_fid_t OrigTargetFid = {0,0,0,0,0};
+ cm_scache_t * srcDscp = NULL;
+ cm_scache_t * targetDscp = NULL;
+ cm_scache_t * srcScp = NULL;
+ cm_dirOp_t dirop;
+ wchar_t shortName[13];
+ wchar_t SourceFileName[260];
+ wchar_t TargetFileName[260];
+ cm_dirFid_t dfid;
+ cm_req_t req;
+ afs_uint32 code;
+ DWORD status;
+
+ RDR_InitReq(&req, bWow64);
+
+ StringCchCopyNW(SourceFileName, 260, SourceFileNameCounted, SourceFileNameLength / sizeof(WCHAR));
+ StringCchCopyNW(TargetFileName, 260, TargetFileNameCounted, TargetFileNameLength / sizeof(WCHAR));
+
+ osi_Log4(afsd_logp, "RDR_HardLinkFileEntry Source Parent FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
+ SourceParentId.Cell, SourceParentId.Volume,
+ SourceParentId.Vnode, SourceParentId.Unique);
+ osi_Log2(afsd_logp, "... Source Name=%S Length %u", osi_LogSaveStringW(afsd_logp, SourceFileName), SourceFileNameLength);
+ osi_Log4(afsd_logp, "... Target Parent FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
+ TargetParentId.Cell, TargetParentId.Volume,
+ TargetParentId.Vnode, TargetParentId.Unique);
+ osi_Log2(afsd_logp, "... Target Name=%S Length %u", osi_LogSaveStringW(afsd_logp, TargetFileName), TargetFileNameLength);
+
+ *ResultCB = (AFSCommResult *)malloc( size);
+ if (!(*ResultCB))
+ return;
+
+ memset( *ResultCB,
+ '\0',
+ size);
+
+ pResultCB = (AFSFileHardLinkResultCB *)(*ResultCB)->ResultData;
+
+ if (SourceFileNameLength == 0 || TargetFileNameLength == 0)
+ {
+ osi_Log2(afsd_logp, "RDR_HardLinkFileEntry Invalid Name Length: src %u target %u",
+ SourceFileNameLength, TargetFileNameLength);
+ (*ResultCB)->ResultStatus = STATUS_INVALID_PARAMETER;
+ return;
+ }
+
+ SourceFid.cell = SourceFileId.Cell;
+ SourceFid.volume = SourceFileId.Volume;
+ SourceFid.vnode = SourceFileId.Vnode;
+ SourceFid.unique = SourceFileId.Unique;
+ SourceFid.hash = SourceFileId.Hash;
+
+ SourceParentFid.cell = SourceParentId.Cell;
+ SourceParentFid.volume = SourceParentId.Volume;
+ SourceParentFid.vnode = SourceParentId.Vnode;
+ SourceParentFid.unique = SourceParentId.Unique;
+ SourceParentFid.hash = SourceParentId.Hash;
+
+ TargetParentFid.cell = TargetParentId.Cell;
+ TargetParentFid.volume = TargetParentId.Volume;
+ TargetParentFid.vnode = TargetParentId.Vnode;
+ TargetParentFid.unique = TargetParentId.Unique;
+ TargetParentFid.hash = TargetParentId.Hash;
+
+ code = cm_GetSCache(&SourceFid, NULL, &srcScp, userp, &req);
+ if (code) {
+ osi_Log1(afsd_logp, "RDR_HardLinkFileEntry cm_GetSCache source failed code 0x%x", code);
+ smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
+ (*ResultCB)->ResultStatus = status;
+ return;
+ }
+
+ code = cm_GetSCache(&TargetParentFid, NULL, &targetDscp, userp, &req);
+ if (code) {
+ osi_Log1(afsd_logp, "RDR_HardLinkFileEntry cm_GetSCache target parent failed code 0x%x", code);
+ smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
+ (*ResultCB)->ResultStatus = status;
+ cm_ReleaseSCache(srcScp);
+ return;
+ }
+
+ lock_ObtainWrite(&targetDscp->rw);
+ code = cm_SyncOp(targetDscp, NULL, userp, &req, PRSFS_INSERT,
+ CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+ if (code) {
+ osi_Log2(afsd_logp, "RDR_HardLinkFileEntry cm_SyncOp targetDscp 0x%p failed code 0x%x", targetDscp, code);
+ smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
+ (*ResultCB)->ResultStatus = status;
+ lock_ReleaseWrite(&targetDscp->rw);
+ cm_ReleaseSCache(srcScp);
+ cm_ReleaseSCache(targetDscp);
+ return;
+ }
+
+ cm_SyncOpDone(targetDscp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+ lock_ReleaseWrite(&targetDscp->rw);
+
+ if (targetDscp->fileType != CM_SCACHETYPE_DIRECTORY) {
+ osi_Log1(afsd_logp, "RDR_HardLinkFileEntry targetDscp 0x%p not a directory", targetDscp);
+ (*ResultCB)->ResultStatus = STATUS_NOT_A_DIRECTORY;
+ cm_ReleaseSCache(srcScp);
+ cm_ReleaseSCache(targetDscp);
+ return;
+ }
+
+ if ( cm_FidCmp(&SourceParentFid, &TargetParentFid) ) {
+ code = cm_GetSCache(&SourceParentFid, NULL, &srcDscp, userp, &req);
+ if (code) {
+ osi_Log1(afsd_logp, "RDR_HardLinkFileEntry cm_GetSCache source parent failed code 0x%x", code);
+ smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
+ if ( status == STATUS_INVALID_HANDLE)
+ status = STATUS_OBJECT_PATH_INVALID;
+ (*ResultCB)->ResultStatus = status;
+ cm_ReleaseSCache(srcScp);
+ cm_ReleaseSCache(targetDscp);
+ return;
+ }
+
+ lock_ObtainWrite(&srcDscp->rw);
+ code = cm_SyncOp(srcDscp, NULL, userp, &req, 0,
+ CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+ if (code) {
+ osi_Log2(afsd_logp, "RDR_HardLinkFileEntry cm_SyncOp srcDscp 0x%p failed code 0x%x", srcDscp, code);
+ smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
+ if ( status == STATUS_INVALID_HANDLE)
+ status = STATUS_OBJECT_PATH_INVALID;
+ (*ResultCB)->ResultStatus = status;
+ lock_ReleaseWrite(&srcDscp->rw);
+ if (srcDscp != targetDscp)
+ cm_ReleaseSCache(srcDscp);
+ cm_ReleaseSCache(targetDscp);
+ cm_ReleaseSCache(srcScp);
+ return;
+ }
+
+ cm_SyncOpDone(srcDscp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+ lock_ReleaseWrite(&srcDscp->rw);
+
+ if (srcDscp->fileType != CM_SCACHETYPE_DIRECTORY) {
+ osi_Log1(afsd_logp, "RDR_HardLinkFileEntry srcDscp 0x%p not a directory", srcDscp);
+ (*ResultCB)->ResultStatus = STATUS_NOT_A_DIRECTORY;
+ if (srcDscp != targetDscp)
+ cm_ReleaseSCache(srcDscp);
+ cm_ReleaseSCache(targetDscp);
+ cm_ReleaseSCache(srcScp);
+ return;
+ }
+ } else {
+ srcDscp = targetDscp;
+ }
+
+ /* Obtain the target FID if it exists */
+ code = cm_BeginDirOp( targetDscp, userp, &req, CM_DIRLOCK_READ, CM_DIROP_FLAG_NONE, &dirop);
+ if (code == 0) {
+ code = cm_BPlusDirLookup(&dirop, TargetFileName, &OrigTargetFid);
+ cm_EndDirOp(&dirop);
+ }
+
+ if (OrigTargetFid.vnode) {
+
+ /* An object exists with the target name */
+ if (!pHardLinkCB->bReplaceIfExists) {
+ osi_Log0(afsd_logp, "RDR_HardLinkFileEntry target name collision and !ReplaceIfExists");
+ (*ResultCB)->ResultStatus = STATUS_OBJECT_NAME_COLLISION;
+ if (srcDscp != targetDscp)
+ cm_ReleaseSCache(srcDscp);
+ cm_ReleaseSCache(targetDscp);
+ cm_ReleaseSCache(srcScp);
+ return;
+ }
+
+ lock_ObtainWrite(&targetDscp->rw);
+ code = cm_SyncOp(targetDscp, NULL, userp, &req, PRSFS_INSERT | PRSFS_DELETE,
+ CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+ if (code) {
+ smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
+ (*ResultCB)->ResultStatus = status;
+ lock_ReleaseWrite(&srcDscp->rw);
+ if (srcDscp != targetDscp)
+ cm_ReleaseSCache(srcDscp);
+ cm_ReleaseSCache(targetDscp);
+ cm_ReleaseSCache(srcScp);
+ return;
+ }
+ cm_SyncOpDone(targetDscp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+ lock_ReleaseWrite(&targetDscp->rw);
+
+ code = cm_Unlink(targetDscp, NULL, TargetFileName, userp, &req);
+ if (code) {
+ osi_Log1(afsd_logp, "RDR_HardLinkFileEntry cm_Unlink code 0x%x", code);
+ smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
+ (*ResultCB)->ResultStatus = status;
+ lock_ReleaseWrite(&srcDscp->rw);
+ if (srcDscp != targetDscp)
+ cm_ReleaseSCache(srcDscp);
+ cm_ReleaseSCache(targetDscp);
+ cm_ReleaseSCache(srcScp);
+ return;
+ }
+ }
+
+ code = cm_Link( targetDscp, TargetFileName, srcScp, 0, userp, &req);
+ if (code == 0) {
+ cm_fid_t TargetFid;
+ cm_scache_t *targetScp = 0;
+ DWORD dwRemaining;
+
+ (*ResultCB)->ResultBufferLength = ResultBufferLength;
+ dwRemaining = ResultBufferLength - sizeof( AFSFileHardLinkResultCB) + sizeof( AFSDirEnumEntry);
+ (*ResultCB)->ResultStatus = 0;
+
+ pResultCB->SourceParentDataVersion.QuadPart = srcDscp->dataVersion;
+ pResultCB->TargetParentDataVersion.QuadPart = targetDscp->dataVersion;
+
+ osi_Log2(afsd_logp, "RDR_HardLinkFileEntry cm_Link srcDscp 0x%p targetDscp 0x%p SUCCESS",
+ srcDscp, targetDscp);
+
+ code = cm_BeginDirOp( targetDscp, userp, &req, CM_DIRLOCK_READ, CM_DIROP_FLAG_NONE, &dirop);
+ if (code == 0) {
+ code = cm_BPlusDirLookup(&dirop, TargetFileName, &TargetFid);
+ cm_EndDirOp(&dirop);
+ }
+
+ if (code != 0) {
+ osi_Log1(afsd_logp, "RDR_HardLinkFileEntry cm_BPlusDirLookup failed code 0x%x",
+ code);
+ (*ResultCB)->ResultStatus = STATUS_OBJECT_PATH_INVALID;
+ if (srcDscp != targetDscp)
+ cm_ReleaseSCache(srcDscp);
+ cm_ReleaseSCache(srcScp);
+ cm_ReleaseSCache(targetDscp);
+ return;
+ }
+
+ osi_Log4(afsd_logp, "RDR_HardLinkFileEntry Target FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
+ TargetFid.cell, TargetFid.volume,
+ TargetFid.vnode, TargetFid.unique);
+
+ code = cm_GetSCache(&TargetFid, &targetDscp->fid, &targetScp, userp, &req);
+ if (code) {
+ osi_Log1(afsd_logp, "RDR_HardLinkFileEntry cm_GetSCache target failed code 0x%x", code);
+ smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
+ (*ResultCB)->ResultStatus = status;
+ if (srcDscp != targetDscp)
+ cm_ReleaseSCache(srcDscp);
+ cm_ReleaseSCache(srcScp);
+ cm_ReleaseSCache(targetDscp);
+ return;
+ }
+
+ /* Make sure the source vnode is current */
+ lock_ObtainWrite(&targetScp->rw);
+ code = cm_SyncOp(targetScp, NULL, userp, &req, 0,
+ CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+ if (code) {
+ osi_Log2(afsd_logp, "RDR_HardLinkFileEntry cm_SyncOp scp 0x%p failed code 0x%x",
+ targetScp, code);
+ smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
+ (*ResultCB)->ResultStatus = status;
+ lock_ReleaseWrite(&targetScp->rw);
+ cm_ReleaseSCache(targetScp);
+ if (srcDscp != targetDscp)
+ cm_ReleaseSCache(srcDscp);
+ cm_ReleaseSCache(srcScp);
+ cm_ReleaseSCache(targetDscp);
+ return;
+ }
+
+ cm_SyncOpDone(targetScp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+ lock_ReleaseWrite(&targetScp->rw);
+
+ if (cm_shortNames) {
+ dfid.vnode = htonl(targetScp->fid.vnode);
+ dfid.unique = htonl(targetScp->fid.unique);
+
+ if (!cm_Is8Dot3(TargetFileName))
+ cm_Gen8Dot3NameIntW(TargetFileName, &dfid, shortName, NULL);
+ else
+ shortName[0] = '\0';
+ }
+
+ RDR_PopulateCurrentEntry(&pResultCB->DirEnum, dwRemaining,
+ targetDscp, targetScp, userp, &req, TargetFileName, shortName,
+ RDR_POP_FOLLOW_MOUNTPOINTS | RDR_POP_EVALUATE_SYMLINKS,
+ 0, NULL, &dwRemaining);
+ (*ResultCB)->ResultBufferLength = ResultBufferLength - dwRemaining;
+ cm_ReleaseSCache(targetScp);
+
+ osi_Log0(afsd_logp, "RDR_HardLinkFileEntry SUCCESS");
+ } else {
+ osi_Log3(afsd_logp, "RDR_HardLinkFileEntry cm_Link srcDscp 0x%p targetDscp 0x%p failed code 0x%x",
+ srcDscp, targetDscp, code);
+ smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
+ (*ResultCB)->ResultStatus = status;
+ (*ResultCB)->ResultBufferLength = 0;
+ }
+
+ cm_ReleaseSCache(srcScp);
+ if (srcDscp != targetDscp)
+ cm_ReleaseSCache(srcDscp);
+ cm_ReleaseSCache(targetDscp);
+ return;
+}
+
+
+void
+RDR_CreateSymlinkEntry( IN cm_user_t *userp,
+ IN AFSFileID FileId,
+ IN WCHAR *FileNameCounted,
+ IN DWORD FileNameLength,
+ IN AFSCreateSymlinkCB *SymlinkCB,
+ IN BOOL bWow64,
+ IN DWORD ResultBufferLength,
+ IN OUT AFSCommResult **ResultCB)
+{
+ AFSCreateSymlinkResultCB *pResultCB = NULL;
+ size_t size = sizeof(AFSCommResult) + ResultBufferLength - 1;
+ cm_fid_t parentFid;
+ cm_fid_t Fid;
+ afs_uint32 code;
+ cm_scache_t * dscp = NULL;
+ afs_uint32 flags = 0;
+ cm_attr_t setAttr;
+ cm_scache_t * scp = NULL;
+ cm_req_t req;
+ DWORD status;
+ wchar_t FileName[260];
+ char *TargetPath = NULL;
+
+ StringCchCopyNW(FileName, 260, FileNameCounted, FileNameLength / sizeof(WCHAR));
+ TargetPath = cm_Utf16ToUtf8Alloc( SymlinkCB->TargetName, SymlinkCB->TargetNameLength / sizeof(WCHAR), NULL);
+
+ osi_Log4( afsd_logp, "RDR_CreateSymlinkEntry parent FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
+ SymlinkCB->ParentId.Cell, SymlinkCB->ParentId.Volume,
+ SymlinkCB->ParentId.Vnode, SymlinkCB->ParentId.Unique);
+ osi_Log1(afsd_logp, "... name=%S", osi_LogSaveStringW(afsd_logp, FileName));
+
+ RDR_InitReq(&req, bWow64);
+ memset(&setAttr, 0, sizeof(cm_attr_t));
+
+ *ResultCB = (AFSCommResult *)malloc(size);
+ if (!(*ResultCB)) {
+ osi_Log0(afsd_logp, "RDR_CreateSymlinkEntry out of memory");
+ free(TargetPath);
+ return;
+ }
+
+ memset( *ResultCB,
+ '\0',
+ size);
+
+ parentFid.cell = SymlinkCB->ParentId.Cell;
+ parentFid.volume = SymlinkCB->ParentId.Volume;
+ parentFid.vnode = SymlinkCB->ParentId.Vnode;
+ parentFid.unique = SymlinkCB->ParentId.Unique;
+ parentFid.hash = SymlinkCB->ParentId.Hash;
+
+ code = cm_GetSCache(&parentFid, NULL, &dscp, userp, &req);
+ if (code) {
+ smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
+ (*ResultCB)->ResultStatus = status;
+ if ( status == STATUS_INVALID_HANDLE)
+ status = STATUS_OBJECT_PATH_INVALID;
+ osi_Log2(afsd_logp, "RDR_CreateSymlinkEntry cm_GetSCache ParentFID failure code=0x%x status=0x%x",
+ code, status);
+ free(TargetPath);
+ return;
+ }
+
+ lock_ObtainWrite(&dscp->rw);
+ code = cm_SyncOp(dscp, NULL, userp, &req, 0,
+ CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+ if (code) {
+ smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
+ (*ResultCB)->ResultStatus = status;
+ lock_ReleaseWrite(&dscp->rw);
+ cm_ReleaseSCache(dscp);
+ osi_Log3(afsd_logp, "RDR_CreateSymlinkEntry cm_SyncOp failure (1) dscp=0x%p code=0x%x status=0x%x",
+ dscp, code, status);
+ free(TargetPath);
+ return;
+ }
+
+ cm_SyncOpDone(dscp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+ lock_ReleaseWrite(&dscp->rw);
+
+ if (dscp->fileType != CM_SCACHETYPE_DIRECTORY) {
+ (*ResultCB)->ResultStatus = STATUS_NOT_A_DIRECTORY;
+ cm_ReleaseSCache(dscp);
+ osi_Log1(afsd_logp, "RDR_CreateSymlinkEntry Not a Directory dscp=0x%p",
+ dscp);
+ free(TargetPath);
+ return;
+ }
+
+ 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;
+ if ( status == STATUS_INVALID_HANDLE)
+ status = STATUS_OBJECT_PATH_INVALID;
+ osi_Log2(afsd_logp, "RDR_CreateSymlinkEntry cm_GetSCache FID failure code=0x%x status=0x%x",
+ code, status);
+ free(TargetPath);
+ return;
+ }
+
+ lock_ObtainWrite(&scp->rw);
+ code = cm_SyncOp(scp, NULL, userp, &req, 0,
+ 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_Log3(afsd_logp, "RDR_CreateSymlinkEntry cm_SyncOp failure (1) scp=0x%p code=0x%x status=0x%x",
+ scp, code, status);
+ free(TargetPath);
+ return;
+ }
+
+ cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+ lock_ReleaseWrite(&scp->rw);
+
+ /* Remove the temporary object */
+ if (scp->fileType == CM_SCACHETYPE_DIRECTORY)
+ code = cm_RemoveDir(dscp, NULL, FileName, userp, &req);
+ else
+ code = cm_Unlink(dscp, NULL, FileName, userp, &req);
+ cm_ReleaseSCache(scp);
+ scp = NULL;
+ if (code && code != CM_ERROR_NOSUCHFILE) {
+ smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
+ (*ResultCB)->ResultStatus = status;
+ cm_ReleaseSCache(dscp);
+ osi_Log2(afsd_logp, "RDR_CreateSymlinkEntry Unable to delete file dscp=0x%p code=0x%x",
+ dscp, code);
+ free(TargetPath);
+ return;
+ }
+
+ /*
+ * The target path is going to be provided by the redirector in one of the following forms:
+ *
+ * 1. Relative path.
+ * 2. Absolute path prefaced as \??\UNC\<server>\<share>\<path>
+ * 3. Absolute path prefaced as \??\<drive-letter>:\<path>
+ *
+ * Relative paths can be used with just slash conversion. Absolute paths must be converted.
+ * UNC paths with a server name that matches cm_NetbiosName then the path is an AFS path and
+ * it must be converted to /<server>/<share>/<path>. Other UNC paths must be converted to
+ * msdfs:\\<server>\<share>\<path>. Local disk paths should be converted to
+ * msdfs:<drive-letter>:<path>.
+ */
+
+ if ( TargetPath[0] == '\\' ) {
+ size_t nbNameLen = strlen(cm_NetbiosName);
+ size_t len;
+ char *s;
+
+ if ( strncmp(TargetPath, "\\??\\UNC\\", 8) == 0) {
+
+ if (strncmp(&TargetPath[8], cm_NetbiosName, nbNameLen) == 0 &&
+ TargetPath[8 + nbNameLen] == '\\')
+ {
+ /* AFS path */
+ s = strdup(&TargetPath[8 + nbNameLen]);
+ free(TargetPath);
+ TargetPath = s;
+ for (; *s; s++) {
+ if (*s == '\\')
+ *s = '/';
+ }
+ } else {
+ /*
+ * non-AFS UNC path (msdfs:\\server\share\path)
+ * strlen("msdfs:\\") == 7 + 1 for the NUL
+ */
+ len = 8 + strlen(&TargetPath[7]);
+ s = malloc(8 + strlen(&TargetPath[7]));
+ StringCbCopy(s, len, "msdfs:\\");
+ StringCbCat(s, len, &TargetPath[7]);
+ free(TargetPath);
+ TargetPath = s;
+ }
+ } else {
+ /* non-UNC path (msdfs:<drive>:\<path> */
+ s = strdup(&TargetPath[4]);
+ free(TargetPath);
+ TargetPath = s;
+ }
+
+ } else {
+ /* relative paths require slash conversion */
+ char *s = TargetPath;
+ for (; *s; s++) {
+ if (*s == '\\')
+ *s = '/';
+ }
+ }
+
+ /* Use current time */
+ setAttr.mask = CM_ATTRMASK_UNIXMODEBITS | CM_ATTRMASK_CLIENTMODTIME;
+ setAttr.unixModeBits = 0755;
+ setAttr.clientModTime = time(NULL);
+
+ code = cm_SymLink(dscp, FileName, TargetPath, flags, &setAttr, userp, &req, &scp);
+ free(TargetPath);
+
+ if (code == 0) {
+ wchar_t shortName[13]=L"";
+ cm_dirFid_t dfid;
+ DWORD dwRemaining;
+
+ if (dscp->flags & CM_SCACHEFLAG_ANYWATCH) {
+ smb_NotifyChange(FILE_ACTION_ADDED,
+ FILE_NOTIFY_CHANGE_DIR_NAME,
+ dscp, FileName, NULL, TRUE);
+ }
+
+ (*ResultCB)->ResultStatus = 0; // We will be able to fit all the data in here
+
+ (*ResultCB)->ResultBufferLength = sizeof( AFSCreateSymlinkResultCB);
+
+ pResultCB = (AFSCreateSymlinkResultCB *)(*ResultCB)->ResultData;
+
+ dwRemaining = ResultBufferLength - sizeof( AFSCreateSymlinkResultCB) + sizeof( AFSDirEnumEntry);
+
+ lock_ObtainWrite(&dscp->rw);
+ code = cm_SyncOp(dscp, NULL, userp, &req, 0,
+ CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+ if (code) {
+ smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
+ (*ResultCB)->ResultStatus = status;
+ lock_ReleaseWrite(&dscp->rw);
+ cm_ReleaseSCache(dscp);
+ cm_ReleaseSCache(scp);
+ osi_Log3(afsd_logp, "RDR_CreateSymlinkEntry cm_SyncOp failure (2) dscp=0x%p code=0x%x status=0x%x",
+ dscp, code, status);
+ return;
+ }
+
+ pResultCB->ParentDataVersion.QuadPart = dscp->dataVersion;
- dfid.vnode = htonl(scp->fid.vnode);
- dfid.unique = htonl(scp->fid.unique);
+ cm_SyncOpDone(dscp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
+ lock_ReleaseWrite(&dscp->rw);
- if (!cm_Is8Dot3(TargetFileName))
- cm_Gen8Dot3NameIntW(TargetFileName, &dfid, shortName, NULL);
- else
- shortName[0] = '\0';
+ if (cm_shortNames) {
+ dfid.vnode = htonl(scp->fid.vnode);
+ dfid.unique = htonl(scp->fid.unique);
- RDR_PopulateCurrentEntry(&pResultCB->DirEnum, dwRemaining,
- newDscp, scp, userp, &req, TargetFileName, shortName,
- RDR_POP_FOLLOW_MOUNTPOINTS | RDR_POP_EVALUATE_SYMLINKS,
- NULL, &dwRemaining);
- (*ResultCB)->ResultBufferLength = ResultBufferLength - dwRemaining;
- cm_ReleaseSCache(scp);
+ if (!cm_Is8Dot3(FileName))
+ cm_Gen8Dot3NameIntW(FileName, &dfid, shortName, NULL);
+ else
+ shortName[0] = '\0';
+ }
- osi_Log0(afsd_logp, "RDR_RenameFileEntry SUCCESS");
+ code = RDR_PopulateCurrentEntry(&pResultCB->DirEnum, dwRemaining,
+ dscp, scp, userp, &req, FileName, shortName,
+ RDR_POP_FOLLOW_MOUNTPOINTS | RDR_POP_EVALUATE_SYMLINKS,
+ 0, NULL, &dwRemaining);
+ cm_ReleaseSCache(scp);
+ (*ResultCB)->ResultBufferLength = ResultBufferLength - dwRemaining;
+ osi_Log0(afsd_logp, "RDR_CreateSymlinkEntry SUCCESS");
} else {
- osi_Log3(afsd_logp, "RDR_RenameFileEntry cm_Rename oldDscp 0x%p newDscp 0x%p failed code 0x%x",
- oldDscp, newDscp, code);
- smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
- (*ResultCB)->ResultStatus = status;
+ (*ResultCB)->ResultStatus = STATUS_FILE_DELETED;
(*ResultCB)->ResultBufferLength = 0;
+ osi_Log2(afsd_logp, "RDR_CreateSymlinkEntry FAILURE code=0x%x status=0x%x",
+ code, STATUS_FILE_DELETED);
}
- cm_ReleaseSCache(oldDscp);
- cm_ReleaseSCache(newDscp);
+ cm_ReleaseSCache(dscp);
+
return;
}
+
void
RDR_FlushFileEntry( IN cm_user_t *userp,
IN AFSFileID FileId,
char dbgstr[1024];
#endif
- RDR_InitReq(&req);
- if ( bWow64 )
- req.flags |= CM_REQ_WOW64;
+ RDR_InitReq(&req, bWow64);
osi_Log4(afsd_logp, "RDR_FlushFileEntry File FID cell 0x%x vol 0x%x vno 0x%x uniq 0x%x",
FileId.Cell, FileId.Volume,
Fid.unique = FileId.Unique;
Fid.hash = FileId.Hash;
- code = cm_GetSCache(&Fid, &scp, userp, &req);
+ code = cm_GetSCache(&Fid, NULL, &scp, userp, &req);
if (code) {
smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
(*ResultCB)->ResultStatus = status;
cm_req_t req;
DWORD status;
- RDR_InitReq(&req);
- if ( bWow64 )
- req.flags |= CM_REQ_WOW64;
+ RDR_InitReq(&req, bWow64);
osi_Log4(afsd_logp, "RDR_OpenFileEntry File FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
FileId.Cell, FileId.Volume,
Fid.unique = FileId.Unique;
Fid.hash = FileId.Hash;
- code = cm_GetSCache(&Fid, &scp, userp, &req);
+ code = cm_GetSCache(&Fid, NULL, &scp, userp, &req);
if (code) {
smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
(*ResultCB)->ResultStatus = status;
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));
}
cm_req_t req;
DWORD status;
- RDR_InitReq(&req);
- if ( bWow64 )
- req.flags |= CM_REQ_WOW64;
+ RDR_InitReq(&req, bWow64);
osi_Log4(afsd_logp, "RDR_ReleaseFileAccess File FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
FileId.Cell, FileId.Volume,
Fid.unique = FileId.Unique;
Fid.hash = FileId.Hash;
- code = cm_GetSCache(&Fid, &scp, userp, &req);
+ code = cm_GetSCache(&Fid, NULL, &scp, userp, &req);
if (code) {
smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
(*ResultCB)->ResultStatus = status;
/* 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;
FileId.Unique = scp->fid.unique;
FileId.Hash = scp->fid.hash;
- if ((GetTickCount() - reqp->startTime) / 1000 > HardDeadtimeout * 5) {
- RDR_SetFileStatus( &scp->fid, STATUS_IO_TIMEOUT);
- return 0;
- }
-
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.
osi_Log2(afsd_logp, "RDR_BkgFetch cm_SyncOp failure scp=0x%p code=0x%x",
scp, code);
smb_MapNTError(cm_MapRPCError(code, reqp), &status, TRUE);
- RDR_SetFileStatus( &scp->fid, status);
+ RDR_SetFileStatus( &scp->fid, &userp->authgroup, status);
return code;
}
lock_ReleaseWrite(&scp->rw);
- dwResultBufferLength = (DWORD)(sizeof( AFSSetFileExtentsCB) + sizeof( AFSSetFileExtentsCB) * (length.QuadPart / cm_data.blockSize + 1));
+ dwResultBufferLength = (DWORD)(sizeof( AFSSetFileExtentsCB) + sizeof( AFSFileExtentCB) * (length.QuadPart / cm_data.blockSize + 1));
pResultCB = (AFSSetFileExtentsCB *)malloc( dwResultBufferLength );
if (!pResultCB)
return CM_ERROR_RETRY;
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.
* we need to re-queue this extent fetch.
*/
force_retry = 1;
- continue;
+ break;
}
if (!rwheld) {
code = cm_GetBuffer(scp, bufp, NULL, userp, reqp);
if (code == 0) {
- if (bufp->flags & CM_BUF_DIRTY)
- cm_BufWrite(scp, &bufp->offset, cm_chunkSize, CM_BUF_WRITE_SCP_LOCKED, userp, reqp);
-
if (!(bufp->qFlags & CM_BUF_QREDIR)) {
#ifdef VALIDATE_CHECK_SUM
#ifdef ODS_DEBUG
char dbgstr[1024];
#endif
#endif
+ if (bufp->flags & CM_BUF_DIRTY)
+ cm_BufWrite(scp, &bufp->offset, cm_data.buf_blockSize, CM_BUF_WRITE_SCP_LOCKED, userp, reqp);
+
lock_ObtainWrite(&buf_globalLock);
if (!(bufp->flags & CM_BUF_DIRTY) &&
bufp->cmFlags == 0 &&
case RXKADNOAUTH:
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.
* non-fatal errors. re-queue the exent
*/
code = CM_ERROR_RETRY;
+ force_retry = 1;
}
}
if (reportErrorToRedir) {
smb_MapNTError(cm_MapRPCError(code, reqp), &status, TRUE);
- RDR_SetFileStatus( &scp->fid, status);
+ RDR_SetFileStatus( &scp->fid, &userp->authgroup, status);
}
osi_Log4(afsd_logp, "Ending BKG Fetch scp 0x%p code 0x%x fetched 0x%x:%x",
cm_req_t req;
BOOLEAN bBufRelease = TRUE;
- RDR_InitReq(&req);
- if ( bWow64 )
- req.flags |= CM_REQ_WOW64;
+ RDR_InitReq(&req, bWow64);
req.flags |= CM_REQ_NORETRY;
osi_Log4(afsd_logp, "RDR_RequestFileExtentsAsync File FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
Fid.unique = FileId.Unique;
Fid.hash = FileId.Hash;
- code = cm_GetSCache(&Fid, &scp, userp, &req);
+ code = cm_GetSCache(&Fid, NULL, &scp, userp, &req);
if (code) {
osi_Log1(afsd_logp, "RDR_RequestFileExtentsAsync cm_GetSCache FID failure code=0x%x",
code);
osi_Log2(afsd_logp, "RDR_RequestFileExtentsAsync cm_SyncOp failure scp=0x%p code=0x%x",
scp, code);
smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
- RDR_SetFileStatus( &scp->fid, status);
+ RDR_SetFileStatus( &scp->fid, &userp->authgroup, status);
return FALSE;
}
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;
break;
default:
smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
- RDR_SetFileStatus(&FileId, status);
+ RDR_SetFileStatus(&FileId, &userp->authgroup, status);
bHaveBuffer = FALSE;
code = 0;
}
minLength = scp->length;
if (LargeIntegerGreaterThanOrEqualTo(bufp->offset, minLength)) {
- memset(bufp->datap, 0, cm_data.buf_blockSize);
- bufp->dataVersion = scp->dataVersion;
- bHaveBuffer = TRUE;
+ if (!bHaveBuffer) {
+ memset(bufp->datap, 0, cm_data.buf_blockSize);
+ bufp->dataVersion = scp->dataVersion;
+ bHaveBuffer = TRUE;
+ }
+ else if (bufp->dataVersion == CM_BUF_VERSION_BAD) {
+ bufp->dataVersion = scp->dataVersion;
+ }
}
- lock_ReleaseRead(&scp->rw);
-
- if ((RequestExtentsCB->Flags & AFS_EXTENT_FLAG_CLEAN) &&
- ByteOffset.QuadPart <= bufp->offset.QuadPart &&
- EndOffset.QuadPart >= bufp->offset.QuadPart + cm_data.blockSize) {
+ else if ((RequestExtentsCB->Flags & AFS_EXTENT_FLAG_CLEAN) &&
+ ByteOffset.QuadPart <= bufp->offset.QuadPart &&
+ EndOffset.QuadPart >= bufp->offset.QuadPart + cm_data.blockSize)
+ {
memset(bufp->datap, 0, cm_data.blockSize);
bufp->dataVersion = scp->dataVersion;
buf_SetDirty(bufp, &req, 0, cm_data.blockSize, userp);
bHaveBuffer = TRUE;
}
+ lock_ReleaseRead(&scp->rw);
}
/*
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);
cm_req_t req;
int dirty = 0;
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];
char dbgstr[1024];
#endif
- RDR_InitReq(&req);
- if ( bWow64 )
- req.flags |= CM_REQ_WOW64;
+ RDR_InitReq(&req, bWow64);
osi_Log4(afsd_logp, "RDR_ReleaseFileExtents File FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
FileId.Cell, FileId.Volume,
Fid.unique = FileId.Unique;
Fid.hash = FileId.Hash;
- code = cm_GetSCache(&Fid, &scp, userp, &req);
+ code = cm_GetSCache(&Fid, NULL, &scp, userp, &req);
if (code) {
smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
(*ResultCB)->ResultStatus = status;
code, status);
}
+ deleted = scp && (scp->flags & CM_SCACHEFLAG_DELETED);
+
/*
* We do not stop processing as a result of being unable to find the cm_scache object.
* If this occurs something really bad has happened since the cm_scache object must have
* been recycled while extents were held by the redirector. However, we will be resilient
* and carry on without it.
+ *
+ * If the file is known to be deleted, there is no point attempting to ask the
+ * file server about it or update the attributes.
*/
- if (scp && ReleaseExtentsCB->AllocationSize.QuadPart != scp->length.QuadPart) {
+ if (scp && ReleaseExtentsCB->AllocationSize.QuadPart != scp->length.QuadPart &&
+ !deleted)
+ {
cm_attr_t setAttr;
memset(&setAttr, 0, sizeof(cm_attr_t));
pExtent->CacheOffset.LowPart);
osi_Log5( afsd_logp, "... belongs to bp 0x%p vol 0x%x vno 0x%x foffset 0x%x:%x",
wbp, wbp->fid.volume, wbp->fid.vnode, wbp->offset.HighPart, wbp->offset.LowPart);
-#ifdef DEBUG
- DebugBreak();
-#endif
}
buf_Release(bufp);
}
}
if (scp) {
- if (ReleaseExtentsCB->Flags & AFS_EXTENT_FLAG_FLUSH) {
- code = buf_CleanVnode(scp, userp, &req);
+ if (deleted) {
+ code = 0;
+ } else if (ReleaseExtentsCB->Flags & AFS_EXTENT_FLAG_FLUSH) {
+ 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);
}
else if (dirty) {
osi_hyper_t offset = {0,0};
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];
#endif
char dbgstr[1024];
#endif
- RDR_InitReq(&req);
+ RDR_InitReq(&req, FALSE);
for ( fileno = 0, pNextFileCB = &ReleaseFileExtentsResultCB->Files[0];
fileno < ReleaseFileExtentsResultCB->FileCount;
cm_scache_t * scp = NULL;
int dirty = 0;
int released = 0;
+ int deleted = 0;
char * p;
userp = RDR_UserFromAuthGroup( &pFileCB->AuthGroup);
goto cleanup_file;
}
- code = cm_GetSCache(&Fid, &scp, userp, &req);
+ code = cm_GetSCache(&Fid, NULL, &scp, userp, &req);
if (code) {
osi_Log1(afsd_logp, "RDR_ProcessReleaseFileExtentsResult cm_GetSCache FID failure code=0x%x",
code);
*/
}
+ deleted = scp && (scp->flags & CM_SCACHEFLAG_DELETED);
+
/* if the scp was not found, do not perform the length check */
if (scp && (pFileCB->AllocationSize.QuadPart != scp->length.QuadPart)) {
cm_attr_t setAttr;
#endif
}
- if ( (ReleaseFileExtentsResultCB->Flags & AFS_EXTENT_FLAG_DIRTY) ||
- (pExtent->Flags & AFS_EXTENT_FLAG_DIRTY) )
+ if ((ReleaseFileExtentsResultCB->Flags & AFS_EXTENT_FLAG_DIRTY) ||
+ (pExtent->Flags & AFS_EXTENT_FLAG_DIRTY))
{
#ifdef VALIDATE_CHECK_SUM
if ( buf_ValidateCheckSum(bufp) ) {
pExtent->CacheOffset.HighPart,
pExtent->CacheOffset.LowPart);
- buf_SetDirty(bufp, &req, pExtent->DirtyOffset, pExtent->DirtyLength, userp);
- dirty++;
+ if (!deleted) {
+ buf_SetDirty(bufp, &req, pExtent->DirtyOffset, pExtent->DirtyLength, userp);
+ dirty++;
+ }
} else {
#ifdef ODS_DEBUG
snprintf(dbgstr, 1024,
}
}
#else /* !VALIDATE_CHECK_SUM */
- buf_SetDirty(bufp, &req, pExtent->DirtyOffset, pExtent->DirtyLength, userp);
- dirty++;
+ if (!deleted) {
+ buf_SetDirty(bufp, &req, pExtent->DirtyOffset, pExtent->DirtyLength, userp);
+ dirty++;
+ }
#ifdef ODS_DEBUG
snprintf(dbgstr, 1024,
"RDR_ProcessReleaseFileExtentsResult dirty! vol 0x%x vno 0x%x uniq 0x%x foffset 0x%x:%x coffset 0x%x:%x\n",
#ifdef ODS_DEBUG
HexCheckSum(md5dbg, sizeof(md5dbg), bufp->md5cksum);
#endif
- if ( !buf_ValidateCheckSum(bufp) ) {
+ if (!buf_ValidateCheckSum(bufp) ) {
buf_ComputeCheckSum(bufp);
#ifdef ODS_DEBUG
HexCheckSum(md5dbg3, sizeof(md5dbg2), bufp->md5cksum);
osi_Log2(afsd_logp, "... coffset 0x%x:%x",
pExtent->CacheOffset.HighPart,
pExtent->CacheOffset.LowPart);
-#ifdef DEBUG
- DebugBreak();
-#endif
- buf_SetDirty(bufp, &req, pExtent->DirtyOffset, pExtent->DirtyLength, userp);
- dirty++;
+
+ if (!deleted) {
+ buf_SetDirty(bufp, &req, pExtent->DirtyOffset, pExtent->DirtyLength, userp);
+ dirty++;
+ }
} else {
buf_ComputeCheckSum(bufp);
#ifdef ODS_DEBUG
wbp, wbp->fid.volume, wbp->fid.vnode, wbp->offset.HighPart, wbp->offset.LowPart);
else
osi_Log0(afsd_logp, "... coffset cannot be found");
-#ifdef DEBUG
- DebugBreak();
-#endif
}
buf_Release(bufp);
} else {
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;
int dirty = 0;
- RDR_InitReq(&req);
+ RDR_InitReq(&req, FALSE);
osi_Log4(afsd_logp, "RDR_ReleaseFailedSetFileExtents %d.%d.%d.%d",
SetFileExtentsResultCB->FileId.Cell, SetFileExtentsResultCB->FileId.Volume,
goto cleanup_file;
}
- code = cm_GetSCache(&Fid, &scp, userp, &req);
+ code = cm_GetSCache(&Fid, NULL, &scp, userp, &req);
if (code) {
osi_Log1(afsd_logp, "RDR_ReleaseFailedSetFileExtents cm_GetSCache FID failure code=0x%x",
code);
{
cm_fid_t ParentFid;
cm_fid_t RootFid;
+ cm_req_t req;
+
+ RDR_InitReq(&req, bWow64);
*ResultCB = (AFSCommResult *)malloc( sizeof( AFSCommResult));
if (!(*ResultCB))
RootFid.hash = pPioctlCB->RootId.Hash;
/* Create the pioctl index */
- RDR_SetupIoctl(pPioctlCB->RequestId, &ParentFid, &RootFid, userp);
+ RDR_SetupIoctl(pPioctlCB->RequestId, &ParentFid, &RootFid, userp, &req);
return;
}
cm_req_t req;
DWORD status;
- RDR_InitReq(&req);
- if ( bWow64 )
- req.flags |= CM_REQ_WOW64;
+ RDR_InitReq(&req, bWow64);
*ResultCB = (AFSCommResult *)malloc( sizeof( AFSCommResult) + sizeof(AFSPIOCtlIOResultCB));
if (!(*ResultCB))
pResultCB = (AFSPIOCtlIOResultCB *)(*ResultCB)->ResultData;
- code = RDR_IoctlWrite(userp, pPioctlCB->RequestId, pPioctlCB->BufferLength, pPioctlCB->MappedBuffer, &req);
+ code = RDR_IoctlWrite(userp, pPioctlCB->RequestId, pPioctlCB->BufferLength, pPioctlCB->MappedBuffer);
if (code) {
smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
(*ResultCB)->ResultStatus = status;
DWORD status;
afs_uint32 pflags = (bIsLocalSystem ? AFSCALL_FLAG_LOCAL_SYSTEM : 0);
- RDR_InitReq(&req);
- if ( bWow64 )
- req.flags |= CM_REQ_WOW64;
+ RDR_InitReq(&req, bWow64);
*ResultCB = (AFSCommResult *)malloc( sizeof( AFSCommResult) + sizeof(AFSPIOCtlIOResultCB));
if (!(*ResultCB))
pResultCB = (AFSPIOCtlIOResultCB *)(*ResultCB)->ResultData;
code = RDR_IoctlRead(userp, pPioctlCB->RequestId, pPioctlCB->BufferLength, pPioctlCB->MappedBuffer,
- &pResultCB->BytesProcessed, &req, pflags);
+ &pResultCB->BytesProcessed, pflags);
if (code) {
smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
(*ResultCB)->ResultStatus = status;
ProcessId.QuadPart = pBRLRequestCB->ProcessId;
- RDR_InitReq(&req);
- if ( bWow64 )
- req.flags |= CM_REQ_WOW64;
+ RDR_InitReq(&req, bWow64);
osi_Log4(afsd_logp, "RDR_ByteRangeLockSync File FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
FileId.Cell, FileId.Volume,
Fid.unique = FileId.Unique;
Fid.hash = FileId.Hash;
- code = cm_GetSCache(&Fid, &scp, userp, &req);
+ code = cm_GetSCache(&Fid, NULL, &scp, userp, &req);
if (code) {
smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
(*ResultCB)->ResultStatus = status;
ProcessId.QuadPart = pBRURequestCB->ProcessId;
- RDR_InitReq(&req);
- if ( bWow64 )
- req.flags |= CM_REQ_WOW64;
+ RDR_InitReq(&req, bWow64);
osi_Log4(afsd_logp, "RDR_ByteRangeUnlock File FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
FileId.Cell, FileId.Volume,
Fid.unique = FileId.Unique;
Fid.hash = FileId.Hash;
- code = cm_GetSCache(&Fid, &scp, userp, &req);
+ code = cm_GetSCache(&Fid, NULL, &scp, userp, &req);
if (code) {
smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
(*ResultCB)->ResultStatus = status;
ProcessId.QuadPart = pBRURequestCB->ProcessId;
- RDR_InitReq(&req);
- if ( bWow64 )
- req.flags |= CM_REQ_WOW64;
+ RDR_InitReq(&req, bWow64);
osi_Log4(afsd_logp, "RDR_ByteRangeUnlockAll File FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
FileId.Cell, FileId.Volume,
Fid.unique = FileId.Unique;
Fid.hash = FileId.Hash;
- code = cm_GetSCache(&Fid, &scp, userp, &req);
+ code = cm_GetSCache(&Fid, NULL, &scp, userp, &req);
if (code) {
smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
(*ResultCB)->ResultStatus = status;
DWORD Length;
cm_scache_t *scp = NULL;
cm_volume_t *volp = NULL;
- cm_vol_state_t *volstatep = NULL;
afs_uint32 volType;
- cm_cell_t *cellp = NULL;
cm_fid_t Fid;
afs_uint32 code;
cm_req_t req;
DWORD status;
FILETIME ft = {0x832cf000, 0x01abfcc4}; /* October 1, 1982 00:00:00 +0600 */
+ afs_uint32 flags;
char volName[32]="(unknown)";
char offLineMsg[256]="server temporarily inaccessible";
char *OfflineMsg;
char *MOTD;
struct rx_connection * rxconnp;
+ int sync_done = 0;
+ int scp_locked = 0;
- RDR_InitReq(&req);
- if ( bWow64 )
- req.flags |= CM_REQ_WOW64;
+ RDR_InitReq(&req, bWow64);
osi_Log4(afsd_logp, "RDR_GetVolumeInfo File FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
FileId.Cell, FileId.Volume,
(*ResultCB)->ResultBufferLength = sizeof(AFSVolumeInfoCB);
pResultCB = (AFSVolumeInfoCB *)(*ResultCB)->ResultData;
- /* Allocate the extents from the buffer package */
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, &scp, userp, &req);
+ cm_SetFid(&Fid, FileId.Cell, FileId.Volume, 1, 1);
+ code = cm_GetSCache(&Fid, NULL, &scp, userp, &req);
if (code) {
smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
(*ResultCB)->ResultStatus = status;
}
} else {
(*ResultCB)->ResultStatus = STATUS_OBJECT_NAME_INVALID;
- osi_Log0(afsd_logp, "RDR_GetVolumeInfo Object Name Invalid - Cell = 0");
+ osi_Log0(afsd_logp, "RDR_GetVolumeInfo Object Name Invalid - Cell = 0");
+ return;
+ }
+ lock_ObtainWrite(&scp->rw);
+ scp_locked = 1;
+
+ pResultCB->SectorsPerAllocationUnit = 1;
+ pResultCB->BytesPerSector = 1024;
+
+ 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;
+
+ if (scp->fid.cell==AFS_FAKE_ROOT_CELL_ID &&
+ scp->fid.volume==AFS_FAKE_ROOT_VOL_ID)
+ {
+ pResultCB->TotalAllocationUnits.QuadPart = 100;
+ memcpy(&pResultCB->VolumeCreationTime, &ft, sizeof(ft));
+
+ pResultCB->AvailableAllocationUnits.QuadPart = 0;
+ 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->VolumeLabelLength )
+ pResultCB->VolumeLabelLength--;
+
+ pResultCB->CellLength = cm_Utf8ToUtf16( "Freelance.Local", -1, pResultCB->Cell,
+ (sizeof(pResultCB->Cell) / sizeof(WCHAR)) + 1);
+ if ( pResultCB->CellLength )
+ pResultCB->CellLength--;
+ } else {
+ volp = cm_GetVolumeByFID(&scp->fid);
+ if (!volp) {
+ code = CM_ERROR_NOSUCHVOLUME;
+ goto _done;
+ }
+ volType = cm_VolumeType(volp, scp->fid.volume);
+
+ if (cm_volumeInfoReadOnlyFlag && (volType == ROVOL || volType == BACKVOL))
+ pResultCB->FileSystemAttributes |= FILE_READ_ONLY_VOLUME;
+
+ code = -1;
+
+ 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)
+ {
+ flags = CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS;
+ if (scp->volumeCreationDate == 0)
+ flags |= CM_SCACHESYNC_FORCECB;
+ code = cm_SyncOp(scp, NULL, userp, &req, PRSFS_READ, flags);
+ 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;
+
+ 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 = 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;
+ pResultCB->AvailableAllocationUnits.QuadPart = volStat.PartBlocksAvail;
+ }
+ }
+ } else {
+ /*
+ * Lie about the available space. Out of quota errors will need
+ * detected when the file server rejects the store data.
+ */
+ pResultCB->TotalAllocationUnits.QuadPart = 0x7FFFFFFF;
+ pResultCB->AvailableAllocationUnits.QuadPart = (volType == ROVOL || volType == BACKVOL) ? 0 : 0x3F000000;
+ code = 0;
+ }
+
+ 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);
+ 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 */
+
+ _done:
+ if (scp_locked)
+ lock_ReleaseWrite(&scp->rw);
+ if (volp)
+ cm_PutVolume(volp);
+ cm_ReleaseSCache(scp);
+
+ smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
+ (*ResultCB)->ResultStatus = status;
+ osi_Log0(afsd_logp, "RDR_GetVolumeInfo SUCCESS");
+ return;
+}
+
+void
+RDR_GetVolumeSizeInfo( IN cm_user_t *userp,
+ IN AFSFileID FileId,
+ IN BOOL bWow64,
+ IN DWORD ResultBufferLength,
+ IN OUT AFSCommResult **ResultCB)
+{
+ AFSVolumeSizeInfoCB *pResultCB = NULL;
+ DWORD Length;
+ cm_scache_t *scp = NULL;
+ cm_volume_t *volp = NULL;
+ afs_uint32 volType;
+ cm_fid_t Fid;
+ afs_uint32 code;
+ cm_req_t req;
+ DWORD status;
+
+ char volName[32]="(unknown)";
+ char offLineMsg[256]="server temporarily inaccessible";
+ char motd[256]="server temporarily inaccessible";
+ cm_conn_t *connp;
+ AFSFetchVolumeStatus volStat;
+ char *Name;
+ char *OfflineMsg;
+ char *MOTD;
+ struct rx_connection * rxconnp;
+ int sync_done = 0;
+ int scp_locked = 0;
+
+ RDR_InitReq(&req, bWow64);
+
+ osi_Log4(afsd_logp, "RDR_GetVolumeSizeInfo File FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
+ FileId.Cell, FileId.Volume,
+ FileId.Vnode, FileId.Unique);
+
+ Length = sizeof( AFSCommResult) + sizeof(AFSVolumeSizeInfoCB);
+ if (sizeof(AFSVolumeSizeInfoCB) > ResultBufferLength) {
+ *ResultCB = (AFSCommResult *)malloc(sizeof(AFSCommResult) );
+ if (!(*ResultCB))
+ return;
+ memset( *ResultCB, 0, sizeof(AFSCommResult));
+ (*ResultCB)->ResultStatus = STATUS_BUFFER_OVERFLOW;
+ return;
+ }
+
+ *ResultCB = (AFSCommResult *)malloc( Length );
+ if (!(*ResultCB))
+ return;
+ memset( *ResultCB, '\0', Length );
+ (*ResultCB)->ResultBufferLength = sizeof(AFSVolumeSizeInfoCB);
+ pResultCB = (AFSVolumeSizeInfoCB *)(*ResultCB)->ResultData;
+
+ if (FileId.Cell != 0) {
+ cm_SetFid(&Fid, FileId.Cell, FileId.Volume, 1, 1);
+ code = cm_GetSCache(&Fid, NULL, &scp, userp, &req);
+ if (code) {
+ smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
+ (*ResultCB)->ResultStatus = status;
+ (*ResultCB)->ResultBufferLength = 0;
+ osi_Log2(afsd_logp, "RDR_GetVolumeSizeInfo cm_GetSCache FID failure code=0x%x status=0x%x",
+ code, status);
+ return;
+ }
+ } else {
+ (*ResultCB)->ResultStatus = STATUS_OBJECT_NAME_INVALID;
+ osi_Log0(afsd_logp, "RDR_GetVolumeSizeInfo Object Name Invalid - Cell = 0");
return;
}
lock_ObtainWrite(&scp->rw);
+ scp_locked = 1;
- /* start by looking up the file's end */
- code = cm_SyncOp(scp, NULL, userp, &req, 0,
- CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
- if (code) {
- lock_ReleaseWrite(&scp->rw);
- smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
- (*ResultCB)->ResultStatus = status;
- (*ResultCB)->ResultBufferLength = 0;
- osi_Log3(afsd_logp, "RDR_GetVolumeInfo cm_SyncOp failure scp=0x%p code=0x%x status=0x%x",
- scp, code, status);
- return;
- }
-
- /* Fake for now */
pResultCB->SectorsPerAllocationUnit = 1;
pResultCB->BytesPerSector = 1024;
- 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_REPARSE_POINTS;
-
if (scp->fid.cell==AFS_FAKE_ROOT_CELL_ID &&
- scp->fid.volume==AFS_FAKE_ROOT_VOL_ID)
+ scp->fid.volume==AFS_FAKE_ROOT_VOL_ID)
{
pResultCB->TotalAllocationUnits.QuadPart = 100;
- memcpy(&pResultCB->VolumeCreationTime, &ft, sizeof(ft));
-
pResultCB->AvailableAllocationUnits.QuadPart = 0;
- pResultCB->Characteristics |= FILE_READ_ONLY_DEVICE;
-
- pResultCB->VolumeLabelLength = cm_Utf8ToUtf16( "Freelance.Local.Root", -1, pResultCB->VolumeLabel,
- (sizeof(pResultCB->VolumeLabel) / sizeof(WCHAR)) + 1);
- if ( pResultCB->VolumeLabelLength )
- pResultCB->VolumeLabelLength--;
} else {
- memcpy(&pResultCB->VolumeCreationTime, &ft, sizeof(ft));
-
volp = cm_GetVolumeByFID(&scp->fid);
if (!volp) {
code = CM_ERROR_NOSUCHVOLUME;
goto _done;
}
- volstatep = cm_VolumeStateByID(volp, scp->fid.volume);
+
volType = cm_VolumeType(volp, scp->fid.volume);
- pResultCB->Characteristics |= ((volType == ROVOL || volType == BACKVOL) ? FILE_READ_ONLY_DEVICE : 0);
+ code = -1;
+
+ 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)
+ {
+ 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;
- Name = volName;
- OfflineMsg = offLineMsg;
- MOTD = motd;
- lock_ReleaseWrite(&scp->rw);
- 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);
- 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);
- } while (cm_Analyze(connp, userp, &req, &scp->fid, NULL, NULL, NULL, code));
- code = cm_MapRPCError(code, &req);
- if (code == 0) {
- pResultCB->TotalAllocationUnits.QuadPart = volStat.PartMaxBlocks;
- pResultCB->AvailableAllocationUnits.QuadPart = volStat.PartBlocksAvail;
+ 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);
+ }
+ }
+ }
- pResultCB->VolumeLabelLength = cm_Utf8ToUtf16( Name, -1, pResultCB->VolumeLabel,
- (sizeof(pResultCB->VolumeLabel) / sizeof(WCHAR)) + 1);
+ if (code == 0) {
+ 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;
+ pResultCB->AvailableAllocationUnits.QuadPart = volStat.PartBlocksAvail;
+ }
+ }
} else {
+ /*
+ * Lie about the available space. Out of quota errors will need
+ * detected when the file server rejects the store data.
+ */
pResultCB->TotalAllocationUnits.QuadPart = 0x7FFFFFFF;
pResultCB->AvailableAllocationUnits.QuadPart = (volType == ROVOL || volType == BACKVOL) ? 0 : 0x3F000000;
-
- pResultCB->VolumeLabelLength = cm_Utf8ToUtf16( volp->namep, -1, pResultCB->VolumeLabel,
- (sizeof(pResultCB->VolumeLabel) / sizeof(WCHAR)) + 1);
code = 0;
}
- if ( pResultCB->VolumeLabelLength )
- pResultCB->VolumeLabelLength--;
- lock_ObtainWrite(&scp->rw);
+ 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 */
-
- cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
_done:
- lock_ReleaseWrite(&scp->rw);
+ if (scp_locked)
+ lock_ReleaseWrite(&scp->rw);
if (volp)
cm_PutVolume(volp);
cm_ReleaseSCache(scp);
smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
(*ResultCB)->ResultStatus = status;
- osi_Log0(afsd_logp, "RDR_GetVolumeInfo SUCCESS");
+ osi_Log0(afsd_logp, "RDR_GetVolumeSizeInfo SUCCESS");
return;
}
DWORD Length;
cm_req_t req;
- RDR_InitReq(&req);
+ RDR_InitReq(&req, FALSE);
osi_Log1(afsd_logp, "RDR_HoldFid Count=%u", pHoldFidCB->Count);
DWORD Length;
cm_req_t req;
- RDR_InitReq(&req);
+ RDR_InitReq(&req, FALSE);
osi_Log1(afsd_logp, "RDR_ReleaseFid Count=%u", pReleaseFidCB->Count);
cm_req_t req;
DWORD status;
- RDR_InitReq(&req);
- if ( bWow64 )
- req.flags |= CM_REQ_WOW64;
+ RDR_InitReq(&req, bWow64);
*ResultCB = (AFSCommResult *)malloc( sizeof( AFSCommResult) + sizeof(AFSPipeIOResultCB));
if (!(*ResultCB))
cm_req_t req;
DWORD status;
- RDR_InitReq(&req);
- if ( bWow64 )
- req.flags |= CM_REQ_WOW64;
+ RDR_InitReq(&req, bWow64);
*ResultCB = (AFSCommResult *)malloc( sizeof( AFSCommResult) + ResultBufferLength);
if (!(*ResultCB))
cm_req_t req;
DWORD status;
- RDR_InitReq(&req);
- if ( bWow64 )
- req.flags |= CM_REQ_WOW64;
+ RDR_InitReq(&req, bWow64);
*ResultCB = (AFSCommResult *)malloc( sizeof( AFSCommResult));
if (!(*ResultCB))
cm_req_t req;
DWORD status;
- RDR_InitReq(&req);
- if ( bWow64 )
- req.flags |= CM_REQ_WOW64;
+ RDR_InitReq(&req, bWow64);
*ResultCB = (AFSCommResult *)malloc( sizeof( AFSCommResult) + ResultBufferLength);
if (!(*ResultCB))
DWORD status;
DWORD Length = ResultBufferLength + sizeof( AFSCommResult);
- RDR_InitReq(&req);
- if ( bWow64 )
- req.flags |= CM_REQ_WOW64;
+ RDR_InitReq(&req, bWow64);
*ResultCB = (AFSCommResult *)malloc( Length);
if (!(*ResultCB))
(*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;
+}