2 * Copyright (c) 2008 Secure Endpoints, Inc.
3 * Copyright (c) 2009-2013 Your File System, Inc.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
9 * - Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 * - Neither the name of Secure Endpoints Inc. nor the names of its contributors
15 * may be used to endorse or promote products derived from this software without
16 * specific prior written permission from Secure Endpoints, Inc. and
17 * Your File System, Inc.
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
22 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
23 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 #include <afsconfig.h>
33 #include <afs/param.h>
36 #define _WIN32_WINNT 0x0500
38 #define _CRT_SECURE_NO_DEPRECATE
39 #define _CRT_NON_CONFORMING_SWPRINTFS
40 #define INITGUID /* define AFS_AUTH_GUID_NO_PAG */
43 #define WIN32_NO_STATUS
53 #pragma warning(disable: 4005)
57 #include "..\\Common\\AFSUserDefines.h"
58 #include "..\\Common\\AFSUserStructs.h"
76 #include <RDRPrototypes.h>
80 static CHAR * RDR_extentBaseAddress = NULL;
83 RDR_InitReq(cm_req_t *reqp, BOOL bWow64)
86 reqp->flags |= CM_REQ_SOURCE_REDIR;
88 reqp->flags |= CM_REQ_WOW64;
92 RDR_fid2FID( cm_fid_t *fid, AFSFileID *FileId)
94 FileId->Cell = fid->cell;
95 FileId->Volume = fid->volume;
96 FileId->Vnode = fid->vnode;
97 FileId->Unique = fid->unique;
98 FileId->Hash = fid->hash;
102 RDR_FID2fid( AFSFileID *FileId, cm_fid_t *fid)
104 fid->cell = FileId->Cell;
105 fid->volume = FileId->Volume;
106 fid->vnode = FileId->Vnode;
107 fid->unique = FileId->Unique;
108 fid->hash = FileId->Hash;
112 RDR_ExtAttributes(cm_scache_t *scp)
116 if (scp->fileType == CM_SCACHETYPE_DIRECTORY ||
117 scp->fid.vnode & 0x1)
119 attrs = SMB_ATTR_DIRECTORY;
120 #ifdef SPECIAL_FOLDERS
121 attrs |= SMB_ATTR_SYSTEM; /* FILE_ATTRIBUTE_SYSTEM */
122 #endif /* SPECIAL_FOLDERS */
123 } else if ( scp->fileType == CM_SCACHETYPE_MOUNTPOINT ||
124 scp->fileType == CM_SCACHETYPE_DFSLINK ||
125 scp->fileType == CM_SCACHETYPE_INVALID)
127 attrs = SMB_ATTR_DIRECTORY | SMB_ATTR_REPARSE_POINT;
128 } else if ( scp->fileType == CM_SCACHETYPE_SYMLINK) {
129 attrs = SMB_ATTR_REPARSE_POINT;
134 if ((scp->unixModeBits & 0200) == 0)
135 attrs |= SMB_ATTR_READONLY; /* Read-only */
138 attrs = SMB_ATTR_NORMAL; /* FILE_ATTRIBUTE_NORMAL */
144 RDR_SetInitParams( OUT AFSRedirectorInitInfo **ppRedirInitInfo, OUT DWORD * pRedirInitInfoLen )
146 extern char cm_CachePath[];
147 extern cm_config_data_t cm_data;
148 extern int smb_hideDotFiles;
152 MEMORYSTATUSEX memStatus;
153 DWORD maxMemoryCacheSize;
154 char FullCachePath[MAX_PATH];
155 char TempPath[MAX_PATH];
156 char FullTempPath[MAX_PATH];
159 * The %TEMP% environment variable may be relative instead
160 * of absolute which can result in the redirector referring
161 * to a different directory than the service. The full path
162 * must therefore be obtained first.
165 CachePathLen = GetFullPathNameA(cm_CachePath, MAX_PATH, FullCachePath, NULL);
166 if (CachePathLen == 0) {
167 osi_Log0(afsd_logp, "RDR_SetInitParams Unable to obtain Full Cache Path");
168 return STATUS_OBJECT_NAME_NOT_FOUND;
171 TempPathLen = ExpandEnvironmentStringsA("%TEMP%", TempPath, MAX_PATH);
172 if (TempPathLen == 0) {
173 osi_Log0(afsd_logp, "RDR_SetInitParams Unable to expand %%TEMP%%");
174 return STATUS_OBJECT_NAME_NOT_FOUND;
177 TempPathLen = GetFullPathNameA(TempPath, MAX_PATH, FullTempPath, NULL);
178 if (TempPathLen == 0) {
179 osi_Log0(afsd_logp, "RDR_SetInitParams Unable to obtain Full Temp Path");
180 return STATUS_OBJECT_NAME_NOT_FOUND;
183 memStatus.dwLength = sizeof(memStatus);
184 if (GlobalMemoryStatusEx(&memStatus)) {
186 * Use the memory extent interface in the afs redirector
187 * whenever the cache size is less than equal to 10% of
188 * physical memory. Do not use too much because this memory
189 * will be locked by the redirector so it can't be swapped
192 maxMemoryCacheSize = (DWORD)(memStatus.ullTotalPhys / 1024 / 10);
195 * If we can't determine the amount of physical memory
196 * in the system, be conservative and limit the use of
197 * memory extent interface to 64MB data caches.
199 maxMemoryCacheSize = 65536;
202 *pRedirInitInfoLen = (DWORD) (sizeof(AFSRedirectorInitInfo) + (CachePathLen + TempPathLen) * sizeof(WCHAR));
203 *ppRedirInitInfo = (AFSRedirectorInitInfo *)malloc(*pRedirInitInfoLen);
204 (*ppRedirInitInfo)->Flags = smb_hideDotFiles ? AFS_REDIR_INIT_FLAG_HIDE_DOT_FILES : 0;
205 (*ppRedirInitInfo)->Flags |= cm_shortNames ? 0 : AFS_REDIR_INIT_FLAG_DISABLE_SHORTNAMES;
206 (*ppRedirInitInfo)->Flags |= cm_directIO ? AFS_REDIR_INIT_PERFORM_SERVICE_IO : 0;
207 (*ppRedirInitInfo)->MaximumChunkLength = cm_data.chunkSize;
208 (*ppRedirInitInfo)->GlobalFileId.Cell = cm_data.rootFid.cell;
209 (*ppRedirInitInfo)->GlobalFileId.Volume = cm_data.rootFid.volume;
210 (*ppRedirInitInfo)->GlobalFileId.Vnode = cm_data.rootFid.vnode;
211 (*ppRedirInitInfo)->GlobalFileId.Unique = cm_data.rootFid.unique;
212 (*ppRedirInitInfo)->GlobalFileId.Hash = cm_data.rootFid.hash;
213 (*ppRedirInitInfo)->ExtentCount.QuadPart = cm_data.buf_nbuffers;
214 (*ppRedirInitInfo)->CacheBlockSize = cm_data.blockSize;
215 (*ppRedirInitInfo)->MaxPathLinkCount = MAX_FID_COUNT;
216 (*ppRedirInitInfo)->NameArrayLength = MAX_FID_COUNT;
217 if (cm_virtualCache || cm_data.bufferSize <= maxMemoryCacheSize) {
218 osi_Log0(afsd_logp, "RDR_SetInitParams Initializing Memory Extent Interface");
219 (*ppRedirInitInfo)->MemoryCacheOffset.QuadPart = (LONGLONG)cm_data.bufDataBaseAddress;
220 (*ppRedirInitInfo)->MemoryCacheLength.QuadPart = cm_data.bufEndOfData - cm_data.bufDataBaseAddress;
221 (*ppRedirInitInfo)->CacheFileNameLength = 0;
222 RDR_extentBaseAddress = cm_data.bufDataBaseAddress;
224 (*ppRedirInitInfo)->MemoryCacheOffset.QuadPart = 0;
225 (*ppRedirInitInfo)->MemoryCacheLength.QuadPart = 0;
226 (*ppRedirInitInfo)->CacheFileNameLength = (ULONG) (CachePathLen * sizeof(WCHAR));
227 err = mbstowcs((*ppRedirInitInfo)->CacheFileName, FullCachePath, (CachePathLen + 1) *sizeof(WCHAR));
229 free(*ppRedirInitInfo);
230 osi_Log0(afsd_logp, "RDR_SetInitParams Invalid Object Name");
231 return STATUS_OBJECT_NAME_INVALID;
233 RDR_extentBaseAddress = cm_data.baseAddress;
235 (*ppRedirInitInfo)->DumpFileLocationOffset = FIELD_OFFSET(AFSRedirectorInitInfo, CacheFileName) + (*ppRedirInitInfo)->CacheFileNameLength;
236 (*ppRedirInitInfo)->DumpFileLocationLength = (TempPathLen - 1) * sizeof(WCHAR);
238 err = mbstowcs((((PBYTE)(*ppRedirInitInfo)) + (*ppRedirInitInfo)->DumpFileLocationOffset),
239 FullTempPath, (TempPathLen + 1) *sizeof(WCHAR));
241 free(*ppRedirInitInfo);
242 osi_Log0(afsd_logp, "RDR_SetInitParams Invalid Object Name");
243 return STATUS_OBJECT_NAME_INVALID;
246 osi_Log0(afsd_logp,"RDR_SetInitParams Success");
250 static wchar_t cname[MAX_COMPUTERNAME_LENGTH+1] = L"";
253 RDR_GetLocalSystemUser( void)
256 cm_user_t *userp = NULL;
258 if ( cname[0] == '\0') {
259 int len = MAX_COMPUTERNAME_LENGTH+1;
260 GetComputerNameW(cname, &len);
263 unp = smb_FindUserByName(NTSID_LOCAL_SYSTEM, cname, SMB_FLAG_CREATE);
264 lock_ObtainMutex(&unp->mx);
266 unp->userp = cm_NewUser();
267 unp->flags |= SMB_USERNAMEFLAG_SID;
268 lock_ReleaseMutex(&unp->mx);
271 smb_ReleaseUsername(unp);
274 userp = cm_rootUserp;
282 RDR_UserFromCommRequest( IN AFSCommRequest *RequestBuffer)
285 return RDR_UserFromAuthGroup( &RequestBuffer->AuthGroup);
289 RDR_UserFromAuthGroup( IN GUID *pGuid)
292 cm_user_t * userp = NULL;
293 RPC_WSTR UuidString = NULL;
295 if (UuidToStringW((UUID *)pGuid, &UuidString) != RPC_S_OK)
298 if ( cname[0] == '\0') {
299 int len = MAX_COMPUTERNAME_LENGTH+1;
300 GetComputerNameW(cname, &len);
304 unp = smb_FindUserByName(UuidString, cname, SMB_FLAG_CREATE);
305 lock_ObtainMutex(&unp->mx);
307 unp->userp = cm_NewUser();
308 memcpy(&unp->userp->authgroup, pGuid, sizeof(GUID));
310 unp->flags |= SMB_USERNAMEFLAG_SID;
311 lock_ReleaseMutex(&unp->mx);
314 smb_ReleaseUsername(unp);
318 userp = cm_rootUserp;
322 osi_Log2(afsd_logp, "RDR_UserFromCommRequest Guid %S userp = 0x%p",
323 osi_LogSaveStringW(afsd_logp, UuidString),
327 RpcStringFreeW(&UuidString);
333 RDR_ReleaseUser( IN cm_user_t *userp )
335 osi_Log1(afsd_logp, "RDR_ReleaseUser userp = 0x%p", userp);
336 cm_ReleaseUser(userp);
341 * RDR_FlagScpInUse flags the scp with CM_SCACHEFLAG_RDR_IN_USE
344 RDR_FlagScpInUse( IN cm_scache_t *scp, IN BOOL bLocked )
347 lock_ObtainWrite(&scp->rw);
349 lock_AssertWrite(&scp->rw);
350 scp->flags |= CM_SCACHEFLAG_RDR_IN_USE;
353 lock_ReleaseWrite(&scp->rw);
357 * Obtain the status information for the specified object using
358 * an inline bulk status rpc. cm_BPlusDirEnumBulkStatOne() will
359 * obtain current status for the directory object, the object
360 * which is the focus of the inquiry and as many other objects
361 * in the directory for which there are not callbacks registered
362 * since we are likely to be asked for other objects in the directory.
365 RDR_BulkStatLookup( cm_scache_t *dscp,
370 cm_direnum_t * enump = NULL;
374 code = cm_BeginDirOp(dscp, userp, reqp, CM_DIRLOCK_READ, CM_DIROP_FLAG_NONE, &dirop);
376 code = cm_BPlusDirEnumerate(dscp, userp, reqp, TRUE, NULL, TRUE, &enump);
378 osi_Log1(afsd_logp, "RDR_BulkStatLookup cm_BPlusDirEnumerate failure code=0x%x",
383 osi_Log1(afsd_logp, "RDR_BulkStatLookup cm_BeginDirOp failure code=0x%x",
389 code = cm_BPlusDirEnumBulkStatOne(enump, scp);
391 osi_Log1(afsd_logp, "RDR_BulkStatLookup cm_BPlusDirEnumBulkStatOne failure code=0x%x",
394 cm_BPlusDirFreeEnumeration(enump);
401 #define RDR_POP_FOLLOW_MOUNTPOINTS 0x01
402 #define RDR_POP_EVALUATE_SYMLINKS 0x02
403 #define RDR_POP_WOW64 0x04
404 #define RDR_POP_NO_GETSTATUS 0x08
407 RDR_PopulateCurrentEntry( IN AFSDirEnumEntry * pCurrentEntry,
408 IN DWORD dwMaxEntryLength,
409 IN cm_scache_t * dscp,
410 IN cm_scache_t * scp,
411 IN cm_user_t * userp,
414 IN wchar_t * shortName,
416 IN afs_uint32 cmError,
417 OUT AFSDirEnumEntry **ppNextEntry,
418 OUT DWORD * pdwRemainingLength)
421 WCHAR * wname, *wtarget;
424 afs_uint32 code = 0, code2 = 0;
425 BOOL bMustFake = FALSE;
427 osi_Log5(afsd_logp, "RDR_PopulateCurrentEntry dscp=0x%p scp=0x%p name=%S short=%S flags=0x%x",
428 dscp, scp, osi_LogSaveStringW(afsd_logp, name),
429 osi_LogSaveStringW(afsd_logp, shortName), dwFlags);
430 osi_Log1(afsd_logp, "... maxLength=%d", dwMaxEntryLength);
432 if (dwMaxEntryLength < sizeof(AFSDirEnumEntry) + (MAX_PATH + MOUNTPOINTLEN) * sizeof(wchar_t)) {
434 *ppNextEntry = pCurrentEntry;
435 if (pdwRemainingLength)
436 *pdwRemainingLength = dwMaxEntryLength;
437 osi_Log2(afsd_logp, "RDR_PopulateCurrentEntry Not Enough Room for Entry %d < %d",
438 dwMaxEntryLength, sizeof(AFSDirEnumEntry) + (MAX_PATH + MOUNTPOINTLEN) * sizeof(wchar_t));
439 return CM_ERROR_TOOBIG;
447 dwEntryLength = sizeof(AFSDirEnumEntry);
449 lock_ObtainWrite(&scp->rw);
450 if (dwFlags & RDR_POP_NO_GETSTATUS) {
451 if (!cm_HaveCallback(scp))
454 #ifdef AFS_FREELANCE_CLIENT
455 if (scp->fid.cell == AFS_FAKE_ROOT_CELL_ID && scp->fid.volume == AFS_FAKE_ROOT_VOL_ID) {
457 * If the FID is from the Freelance Local Root always perform
458 * a single item status check.
460 code = cm_SyncOp( scp, NULL, userp, reqp, 0,
461 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
463 lock_ReleaseWrite(&scp->rw);
464 osi_Log2(afsd_logp, "RDR_PopulateCurrentEntry cm_SyncOp failed for scp=0x%p code=0x%x",
472 * For non-Freelance objects, check to see if we have current
473 * status information. If not, perform a bulk status lookup of multiple
474 * entries in order to reduce the number of RPCs issued to the file server.
476 if (cm_EAccesFindEntry(userp, &scp->fid))
478 else if (!cm_HaveCallback(scp)) {
479 lock_ReleaseWrite(&scp->rw);
480 code = RDR_BulkStatLookup(dscp, scp, userp, reqp);
482 osi_Log2(afsd_logp, "RDR_PopulateCurrentEntry RDR_BulkStatLookup failed for scp=0x%p code=0x%x",
486 lock_ObtainWrite(&scp->rw);
488 * RDR_BulkStatLookup can succeed but it may be the case that there
489 * still is not valid status info. If we get this far, generate fake
492 if (!cm_HaveCallback(scp))
498 /* Populate the error code */
499 smb_MapNTError(cmError, &pCurrentEntry->NTStatus, TRUE);
501 /* Populate the real or fake data */
502 pCurrentEntry->FileId.Cell = scp->fid.cell;
503 pCurrentEntry->FileId.Volume = scp->fid.volume;
504 pCurrentEntry->FileId.Vnode = scp->fid.vnode;
505 pCurrentEntry->FileId.Unique = scp->fid.unique;
506 pCurrentEntry->FileId.Hash = scp->fid.hash;
508 pCurrentEntry->FileType = scp->fileType;
510 pCurrentEntry->DataVersion.QuadPart = scp->dataVersion;
512 if (scp->fid.cell==AFS_FAKE_ROOT_CELL_ID &&
513 scp->fid.volume==AFS_FAKE_ROOT_VOL_ID) {
514 cm_LargeSearchTimeFromUnixTime(&ft, MAX_AFS_UINT32);
516 cm_LargeSearchTimeFromUnixTime(&ft, scp->cbExpires);
518 pCurrentEntry->Expiration.LowPart = ft.dwLowDateTime;
519 pCurrentEntry->Expiration.HighPart = ft.dwHighDateTime;
522 /* 1969-12-31 23:59:59 +00 */
523 ft.dwHighDateTime = 0x19DB200;
524 ft.dwLowDateTime = 0x5BB78980;
526 cm_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
527 pCurrentEntry->CreationTime.LowPart = ft.dwLowDateTime;
528 pCurrentEntry->CreationTime.HighPart = ft.dwHighDateTime;
529 pCurrentEntry->LastAccessTime = pCurrentEntry->CreationTime;
530 pCurrentEntry->LastWriteTime = pCurrentEntry->CreationTime;
531 pCurrentEntry->ChangeTime = pCurrentEntry->CreationTime;
533 pCurrentEntry->EndOfFile = scp->length;
534 pCurrentEntry->AllocationSize = scp->length;
537 switch (scp->fileType) {
538 case CM_SCACHETYPE_DIRECTORY:
539 pCurrentEntry->FileAttributes = SMB_ATTR_DIRECTORY;
541 case CM_SCACHETYPE_MOUNTPOINT:
542 case CM_SCACHETYPE_INVALID:
543 case CM_SCACHETYPE_DFSLINK:
544 pCurrentEntry->FileAttributes = SMB_ATTR_DIRECTORY | SMB_ATTR_REPARSE_POINT;
546 case CM_SCACHETYPE_SYMLINK:
547 if (cm_TargetPerceivedAsDirectory(scp->mountPointStringp))
548 pCurrentEntry->FileAttributes = SMB_ATTR_DIRECTORY | SMB_ATTR_REPARSE_POINT;
550 pCurrentEntry->FileAttributes = SMB_ATTR_REPARSE_POINT;
553 /* if we get here we either have a normal file
554 * or we have a file for which we have never
555 * received status info. In this case, we can
556 * check the even/odd value of the entry's vnode.
557 * odd means it is to be treated as a directory
558 * and even means it is to be treated as a file.
560 if (scp->fid.vnode & 0x1)
561 pCurrentEntry->FileAttributes = SMB_ATTR_DIRECTORY;
563 pCurrentEntry->FileAttributes = SMB_ATTR_NORMAL;
566 pCurrentEntry->FileAttributes = RDR_ExtAttributes(scp);
567 pCurrentEntry->EaSize = 0;
568 pCurrentEntry->Links = scp->linkCount;
570 len = wcslen(shortName);
571 wcsncpy(pCurrentEntry->ShortName, shortName, len);
572 pCurrentEntry->ShortNameLength = (CCHAR)(len * sizeof(WCHAR));
574 pCurrentEntry->FileNameOffset = sizeof(AFSDirEnumEntry);
576 wname = (WCHAR *)((PBYTE)pCurrentEntry + pCurrentEntry->FileNameOffset);
577 wcsncpy(wname, name, len);
578 pCurrentEntry->FileNameLength = (ULONG)(sizeof(WCHAR) * len);
580 osi_Log3(afsd_logp, "RDR_PopulateCurrentEntry scp=0x%p fileType=%d dv=%u",
581 scp, scp->fileType, (afs_uint32)scp->dataVersion);
583 if (!(dwFlags & RDR_POP_NO_GETSTATUS))
584 cm_SyncOpDone( scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
586 if ((dwFlags & RDR_POP_NO_GETSTATUS) || !cm_HaveCallback(scp)) {
587 pCurrentEntry->TargetNameOffset = 0;
588 pCurrentEntry->TargetNameLength = 0;
591 switch (scp->fileType) {
592 case CM_SCACHETYPE_MOUNTPOINT:
593 if (dwFlags & RDR_POP_FOLLOW_MOUNTPOINTS) {
594 if ((code2 = cm_ReadMountPoint(scp, userp, reqp)) == 0) {
595 cm_scache_t *targetScp = NULL;
597 pCurrentEntry->TargetNameOffset = pCurrentEntry->FileNameOffset + pCurrentEntry->FileNameLength;
598 len = strlen(scp->mountPointStringp);
599 wtarget = (WCHAR *)((PBYTE)pCurrentEntry + pCurrentEntry->TargetNameOffset);
602 cch = MultiByteToWideChar( CP_UTF8, 0, scp->mountPointStringp,
605 len * sizeof(WCHAR));
607 mbstowcs(wtarget, scp->mountPointStringp, len);
609 pCurrentEntry->TargetNameLength = (ULONG)(sizeof(WCHAR) * len);
611 code2 = cm_FollowMountPoint(scp, dscp, userp, reqp, &targetScp);
614 pCurrentEntry->TargetFileId.Cell = targetScp->fid.cell;
615 pCurrentEntry->TargetFileId.Volume = targetScp->fid.volume;
616 pCurrentEntry->TargetFileId.Vnode = targetScp->fid.vnode;
617 pCurrentEntry->TargetFileId.Unique = targetScp->fid.unique;
618 pCurrentEntry->TargetFileId.Hash = targetScp->fid.hash;
620 osi_Log4(afsd_logp, "RDR_PopulateCurrentEntry target FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
621 pCurrentEntry->TargetFileId.Cell, pCurrentEntry->TargetFileId.Volume,
622 pCurrentEntry->TargetFileId.Vnode, pCurrentEntry->TargetFileId.Unique);
624 cm_ReleaseSCache(targetScp);
626 osi_Log2(afsd_logp, "RDR_PopulateCurrentEntry cm_FollowMountPoint failed scp=0x%p code=0x%x",
630 osi_Log2(afsd_logp, "RDR_PopulateCurrentEntry cm_ReadMountPoint failed scp=0x%p code=0x%x",
635 case CM_SCACHETYPE_SYMLINK:
636 case CM_SCACHETYPE_DFSLINK:
638 pCurrentEntry->TargetNameOffset = pCurrentEntry->FileNameOffset + pCurrentEntry->FileNameLength;
639 wtarget = (WCHAR *)((PBYTE)pCurrentEntry + pCurrentEntry->TargetNameOffset);
641 if (dwFlags & RDR_POP_EVALUATE_SYMLINKS) {
643 code2 = cm_HandleLink(scp, userp, reqp);
645 size_t wtarget_len = 0;
647 if (scp->mountPointStringp[0]) {
652 len = strlen(scp->mountPointStringp) + 1;
653 mp = strdup(scp->mountPointStringp);
655 for (s=mp; *s; s++) {
660 if (strncmp("msdfs:", mp, 6) == 0) {
665 if ( mp[offset + 1] == ':' && mp[offset] != '\\') {
666 /* Local drive letter. Must return <drive>:\<path> */
667 pCurrentEntry->FileType = CM_SCACHETYPE_DFSLINK;
668 wtarget_len = len - offset;
670 cch = MultiByteToWideChar( CP_UTF8, 0, &mp[offset],
671 wtarget_len * sizeof(char),
673 wtarget_len * sizeof(WCHAR));
675 mbstowcs(wtarget, &mp[offset], wtarget_len);
677 } else if (mp[offset] == '\\') {
678 size_t nbNameLen = strlen(cm_NetbiosName);
680 if ( strnicmp(&mp[offset + 1], cm_NetbiosName, nbNameLen) == 0 &&
681 mp[offset + nbNameLen + 1] == '\\')
684 pCurrentEntry->FileType = CM_SCACHETYPE_SYMLINK;
685 wtarget_len = len - offset;
687 cch = MultiByteToWideChar( CP_UTF8, 0, &mp[offset],
688 wtarget_len * sizeof(char),
690 wtarget_len * sizeof(WCHAR));
692 mbstowcs(wtarget, &mp[offset], wtarget_len);
694 } else if ( mp[offset + 1] == '\\' &&
695 strnicmp(&mp[offset + 2], cm_NetbiosName, strlen(cm_NetbiosName)) == 0 &&
696 mp[offset + nbNameLen + 2] == '\\')
699 pCurrentEntry->FileType = CM_SCACHETYPE_SYMLINK;
700 wtarget_len = len - offset - 1;
702 cch = MultiByteToWideChar( CP_UTF8, 0, &mp[offset + 1],
703 wtarget_len * sizeof(char),
705 wtarget_len * sizeof(WCHAR));
707 mbstowcs(wtarget, &mp[offset + 1], wtarget_len);
711 * treat as a UNC path. Needs to be \<server>\<share\<path>
713 pCurrentEntry->FileType = CM_SCACHETYPE_DFSLINK;
715 if ( mp[offset] == '\\' && mp[offset + 1] == '\\')
718 wtarget_len = len - offset;
720 cch = MultiByteToWideChar( CP_UTF8, 0, &mp[offset],
721 wtarget_len * sizeof(char),
723 wtarget_len * sizeof(WCHAR));
725 mbstowcs(wtarget, &mp[offset], wtarget_len);
729 /* Relative AFS Symlink */
730 pCurrentEntry->FileType = CM_SCACHETYPE_SYMLINK;
731 wtarget_len = len - offset;
733 cch = MultiByteToWideChar( CP_UTF8, 0, &mp[offset],
734 wtarget_len * sizeof(char),
736 wtarget_len * sizeof(WCHAR));
738 mbstowcs(wtarget, &mp[offset], wtarget_len);
745 pCurrentEntry->TargetNameLength = (ULONG)(sizeof(WCHAR) * (wtarget_len - 1));
747 osi_Log2(afsd_logp, "RDR_PopulateCurrentEntry cm_HandleLink failed scp=0x%p code=0x%x",
756 pCurrentEntry->TargetNameOffset = 0;
757 pCurrentEntry->TargetNameLength = 0;
759 lock_ReleaseWrite(&scp->rw);
761 dwEntryLength += pCurrentEntry->FileNameLength + pCurrentEntry->TargetNameLength;
762 dwEntryLength += (dwEntryLength % 8) ? 8 - (dwEntryLength % 8) : 0; /* quad align */
764 *ppNextEntry = (AFSDirEnumEntry *)((PBYTE)pCurrentEntry + dwEntryLength);
765 if (pdwRemainingLength)
766 *pdwRemainingLength = dwMaxEntryLength - dwEntryLength;
768 osi_Log3(afsd_logp, "RDR_PopulateCurrentEntry Success FileNameLength=%d TargetNameLength=%d RemainingLength=%d",
769 pCurrentEntry->FileNameLength, pCurrentEntry->TargetNameLength, *pdwRemainingLength);
775 RDR_PopulateCurrentEntryNoScp( IN AFSDirEnumEntry * pCurrentEntry,
776 IN DWORD dwMaxEntryLength,
777 IN cm_scache_t * dscp,
779 IN cm_user_t * userp,
782 IN wchar_t * shortName,
784 IN afs_uint32 cmError,
785 OUT AFSDirEnumEntry **ppNextEntry,
786 OUT DWORD * pdwRemainingLength)
792 afs_uint32 code = 0, code2 = 0;
794 osi_Log4(afsd_logp, "RDR_PopulateCurrentEntryNoEntry dscp=0x%p name=%S short=%S flags=0x%x",
795 dscp, osi_LogSaveStringW(afsd_logp, name),
796 osi_LogSaveStringW(afsd_logp, shortName), dwFlags);
797 osi_Log1(afsd_logp, "... maxLength=%d", dwMaxEntryLength);
799 if (dwMaxEntryLength < sizeof(AFSDirEnumEntry) + (MAX_PATH + MOUNTPOINTLEN) * sizeof(wchar_t)) {
801 *ppNextEntry = pCurrentEntry;
802 if (pdwRemainingLength)
803 *pdwRemainingLength = dwMaxEntryLength;
804 osi_Log2(afsd_logp, "RDR_PopulateCurrentEntryNoEntry Not Enough Room for Entry %d < %d",
805 dwMaxEntryLength, sizeof(AFSDirEnumEntry) + (MAX_PATH + MOUNTPOINTLEN) * sizeof(wchar_t));
806 return CM_ERROR_TOOBIG;
814 dwEntryLength = sizeof(AFSDirEnumEntry);
816 /* Populate the error code */
817 smb_MapNTError(cmError, &pCurrentEntry->NTStatus, TRUE);
819 /* Populate the fake data */
820 pCurrentEntry->FileId.Cell = fidp->cell;
821 pCurrentEntry->FileId.Volume = fidp->volume;
822 pCurrentEntry->FileId.Vnode = fidp->vnode;
823 pCurrentEntry->FileId.Unique = fidp->unique;
824 pCurrentEntry->FileId.Hash = fidp->hash;
826 pCurrentEntry->DataVersion.QuadPart = CM_SCACHE_VERSION_BAD;
828 cm_LargeSearchTimeFromUnixTime(&ft, 0);
829 pCurrentEntry->Expiration.LowPart = ft.dwLowDateTime;
830 pCurrentEntry->Expiration.HighPart = ft.dwHighDateTime;
832 cm_LargeSearchTimeFromUnixTime(&ft, 0);
833 pCurrentEntry->CreationTime.LowPart = ft.dwLowDateTime;
834 pCurrentEntry->CreationTime.HighPart = ft.dwHighDateTime;
835 pCurrentEntry->LastAccessTime = pCurrentEntry->CreationTime;
836 pCurrentEntry->LastWriteTime = pCurrentEntry->CreationTime;
837 pCurrentEntry->ChangeTime = pCurrentEntry->CreationTime;
839 pCurrentEntry->EndOfFile.QuadPart = 0;
840 pCurrentEntry->AllocationSize.QuadPart = 0;
841 if (fidp->vnode & 0x1) {
842 pCurrentEntry->FileType = CM_SCACHETYPE_DIRECTORY;
843 pCurrentEntry->FileAttributes = SMB_ATTR_DIRECTORY;
845 pCurrentEntry->FileType = CM_SCACHETYPE_UNKNOWN;
846 pCurrentEntry->FileAttributes = SMB_ATTR_NORMAL;
847 pCurrentEntry->EaSize = 0;
849 pCurrentEntry->Links = 0;
851 len = wcslen(shortName);
852 wcsncpy(pCurrentEntry->ShortName, shortName, len);
853 pCurrentEntry->ShortNameLength = (CCHAR)(len * sizeof(WCHAR));
855 pCurrentEntry->FileNameOffset = sizeof(AFSDirEnumEntry);
857 wname = (WCHAR *)((PBYTE)pCurrentEntry + pCurrentEntry->FileNameOffset);
858 wcsncpy(wname, name, len);
859 pCurrentEntry->FileNameLength = (ULONG)(sizeof(WCHAR) * len);
861 pCurrentEntry->TargetNameOffset = 0;
862 pCurrentEntry->TargetNameLength = 0;
864 dwEntryLength += pCurrentEntry->FileNameLength + pCurrentEntry->TargetNameLength;
865 dwEntryLength += (dwEntryLength % 8) ? 8 - (dwEntryLength % 8) : 0; /* quad align */
867 *ppNextEntry = (AFSDirEnumEntry *)((PBYTE)pCurrentEntry + dwEntryLength);
868 if (pdwRemainingLength)
869 *pdwRemainingLength = dwMaxEntryLength - dwEntryLength;
871 osi_Log3(afsd_logp, "RDR_PopulateCurrentEntryNoScp Success FileNameLength=%d TargetNameLength=%d RemainingLength=%d",
872 pCurrentEntry->FileNameLength, pCurrentEntry->TargetNameLength, *pdwRemainingLength);
878 RDR_EnumerateDirectory( IN cm_user_t *userp,
880 IN AFSDirQueryCB *QueryCB,
883 IN DWORD ResultBufferLength,
884 IN OUT AFSCommResult **ResultCB)
887 cm_direnum_t * enump = NULL;
888 AFSDirEnumResp * pDirEnumResp;
889 AFSDirEnumEntry * pCurrentEntry;
890 size_t size = ResultBufferLength ? sizeof(AFSCommResult) + ResultBufferLength - 1 : sizeof(AFSCommResult);
891 DWORD dwMaxEntryLength;
894 cm_scache_t * dscp = NULL;
897 RDR_InitReq(&req, bWow64);
899 osi_Log4(afsd_logp, "RDR_EnumerateDirectory FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
900 DirID.Cell, DirID.Volume, DirID.Vnode, DirID.Unique);
902 *ResultCB = (AFSCommResult *)malloc(size);
904 osi_Log0(afsd_logp, "RDR_EnumerateDirectory Out of Memory");
908 memset(*ResultCB, 0, size);
910 if (QueryCB->EnumHandle == (ULONG_PTR)-1) {
911 osi_Log0(afsd_logp, "RDR_EnumerateDirectory No More Entries");
912 (*ResultCB)->ResultStatus = STATUS_NO_MORE_ENTRIES;
913 (*ResultCB)->ResultBufferLength = 0;
917 (*ResultCB)->ResultBufferLength = dwMaxEntryLength = ResultBufferLength;
918 if (ResultBufferLength) {
919 pDirEnumResp = (AFSDirEnumResp *)&(*ResultCB)->ResultData;
920 pCurrentEntry = (AFSDirEnumEntry *)&pDirEnumResp->Entry;
921 dwMaxEntryLength -= FIELD_OFFSET( AFSDirEnumResp, Entry); /* AFSDirEnumResp */
924 if (DirID.Cell != 0) {
925 fid.cell = DirID.Cell;
926 fid.volume = DirID.Volume;
927 fid.vnode = DirID.Vnode;
928 fid.unique = DirID.Unique;
929 fid.hash = DirID.Hash;
931 code = cm_GetSCache(&fid, NULL, &dscp, userp, &req);
933 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
934 (*ResultCB)->ResultStatus = status;
935 osi_Log2(afsd_logp, "RDR_EnumerateDirectory cm_GetSCache failure code=0x%x status=0x%x",
940 (*ResultCB)->ResultStatus = STATUS_OBJECT_NAME_INVALID;
941 osi_Log0(afsd_logp, "RDR_EnumerateDirectory Object Name Invalid - Cell = 0");
945 /* get the directory size */
946 lock_ObtainWrite(&dscp->rw);
947 code = cm_SyncOp(dscp, NULL, userp, &req, PRSFS_LOOKUP,
948 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
950 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
951 (*ResultCB)->ResultStatus = status;
952 lock_ReleaseWrite(&dscp->rw);
953 cm_ReleaseSCache(dscp);
954 osi_Log2(afsd_logp, "RDR_EnumerateDirectory cm_SyncOp failure code=0x%x status=0x%x",
959 cm_SyncOpDone(dscp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
960 lock_ReleaseWrite(&dscp->rw);
962 if (dscp->fileType != CM_SCACHETYPE_DIRECTORY) {
963 (*ResultCB)->ResultStatus = STATUS_NOT_A_DIRECTORY;
964 cm_ReleaseSCache(dscp);
965 osi_Log1(afsd_logp, "RDR_EnumerateDirectory Not a Directory dscp=0x%p",
970 osi_Log1(afsd_logp, "RDR_EnumerateDirectory dv=%u", (afs_uint32)dscp->dataVersion);
973 * If there is no enumeration handle, then this is a new query
974 * and we must perform an enumeration for the specified object.
976 if (QueryCB->EnumHandle == (ULONG_PTR)NULL) {
979 code = cm_BeginDirOp(dscp, userp, &req, CM_DIRLOCK_READ, CM_DIROP_FLAG_NONE, &dirop);
981 code = cm_BPlusDirEnumerate(dscp, userp, &req,
982 TRUE /* dir locked */, NULL /* no mask */,
983 TRUE /* fetch status? */, &enump);
985 osi_Log1(afsd_logp, "RDR_EnumerateDirectory cm_BPlusDirEnumerate failure code=0x%x",
990 osi_Log1(afsd_logp, "RDR_EnumerateDirectory cm_BeginDirOp failure code=0x%x",
994 enump = (cm_direnum_t *)QueryCB->EnumHandle;
998 if (ResultBufferLength == 0) {
999 code = cm_BPlusDirEnumBulkStat(enump);
1001 osi_Log1(afsd_logp, "RDR_EnumerateDirectory cm_BPlusDirEnumBulkStat failure code=0x%x",
1005 cm_direnum_entry_t * entryp = NULL;
1007 pDirEnumResp->SnapshotDataVersion.QuadPart = enump->dataVersion;
1010 if (dwMaxEntryLength < sizeof(AFSDirEnumEntry) + (MAX_PATH + MOUNTPOINTLEN) * sizeof(wchar_t)) {
1011 osi_Log0(afsd_logp, "RDR_EnumerateDirectory out of space, returning");
1015 code = cm_BPlusDirNextEnumEntry(enump, &entryp);
1017 if ((code == 0 || code == CM_ERROR_STOPNOW) && entryp) {
1018 cm_scache_t *scp = NULL;
1019 int stopnow = (code == CM_ERROR_STOPNOW);
1021 if ( !wcscmp(L".", entryp->name) || !wcscmp(L"..", entryp->name) ) {
1022 osi_Log0(afsd_logp, "RDR_EnumerateDirectory skipping . or ..");
1029 code = cm_GetSCache(&entryp->fid, &dscp->fid, &scp, userp, &req);
1031 osi_Log5(afsd_logp, "RDR_EnumerateDirectory cm_GetSCache failure cell %u vol %u vnode %u uniq %u code=0x%x",
1032 entryp->fid.cell, entryp->fid.volume, entryp->fid.vnode, entryp->fid.unique, code);
1035 code = entryp->errorCode;
1036 scp = code ? NULL : cm_FindSCache(&entryp->fid);
1040 code = RDR_PopulateCurrentEntry( pCurrentEntry, dwMaxEntryLength,
1041 dscp, scp, userp, &req,
1043 cm_shortNames && cm_Is8Dot3(entryp->name) ? NULL : entryp->shortName,
1044 (bWow64 ? RDR_POP_WOW64 : 0) |
1045 (bSkipStatus ? RDR_POP_NO_GETSTATUS : 0),
1047 &pCurrentEntry, &dwMaxEntryLength);
1048 cm_ReleaseSCache(scp);
1050 code = RDR_PopulateCurrentEntryNoScp( pCurrentEntry, dwMaxEntryLength,
1051 dscp, &entryp->fid, userp, &req,
1053 cm_shortNames && cm_Is8Dot3(entryp->name) ? NULL : entryp->shortName,
1054 (bWow64 ? RDR_POP_WOW64 : 0),
1056 &pCurrentEntry, &dwMaxEntryLength);
1067 if (code || enump->next == enump->count || ResultBufferLength == 0) {
1068 cm_BPlusDirFreeEnumeration(enump);
1069 enump = (cm_direnum_t *)(ULONG_PTR)-1;
1072 if (code == 0 || code == CM_ERROR_STOPNOW) {
1073 (*ResultCB)->ResultStatus = STATUS_SUCCESS;
1074 osi_Log0(afsd_logp, "RDR_EnumerateDirectory SUCCESS");
1076 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1077 (*ResultCB)->ResultStatus = status;
1078 osi_Log2(afsd_logp, "RDR_EnumerateDirectory Failure code=0x%x status=0x%x",
1082 if (ResultBufferLength) {
1083 (*ResultCB)->ResultBufferLength = ResultBufferLength - dwMaxEntryLength;
1085 pDirEnumResp->EnumHandle = (ULONG_PTR) enump;
1086 pDirEnumResp->CurrentDataVersion.QuadPart = dscp->dataVersion;
1090 cm_ReleaseSCache(dscp);
1096 RDR_EvaluateNodeByName( IN cm_user_t *userp,
1097 IN AFSFileID ParentID,
1098 IN WCHAR *FileNameCounted,
1099 IN DWORD FileNameLength,
1100 IN BOOL CaseSensitive,
1101 IN BOOL LastComponent,
1105 IN DWORD ResultBufferLength,
1106 IN OUT AFSCommResult **ResultCB)
1108 AFSFileEvalResultCB *pEvalResultCB = NULL;
1109 AFSDirEnumEntry * pCurrentEntry;
1110 size_t size = ResultBufferLength ? sizeof(AFSCommResult) + ResultBufferLength - 1 : sizeof(AFSCommResult);
1111 afs_uint32 code = 0;
1112 cm_scache_t * scp = NULL;
1113 cm_scache_t * dscp = NULL;
1118 WCHAR * wszName = NULL;
1121 wchar_t FileName[260];
1122 afs_uint32 lookupFlags;
1124 StringCchCopyNW(FileName, 260, FileNameCounted, FileNameLength / sizeof(WCHAR));
1126 RDR_InitReq(&req, bWow64);
1128 osi_Log4(afsd_logp, "RDR_EvaluateNodeByName parent FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
1129 ParentID.Cell, ParentID.Volume, ParentID.Vnode, ParentID.Unique);
1131 /* Allocate enough room to add a volume prefix if necessary */
1132 cbName = FileNameLength + (CM_PREFIX_VOL_CCH + 64) * sizeof(WCHAR);
1133 wszName = malloc(cbName);
1135 osi_Log0(afsd_logp, "RDR_EvaluateNodeByName Out of Memory");
1138 StringCbCopyNW(wszName, cbName, FileName, FileNameLength);
1139 osi_Log1(afsd_logp, "... name=%S", osi_LogSaveStringW(afsd_logp, wszName));
1141 *ResultCB = (AFSCommResult *)malloc(size);
1143 osi_Log0(afsd_logp, "RDR_EvaluateNodeByName Out of Memory");
1148 memset(*ResultCB, 0, size);
1149 (*ResultCB)->ResultBufferLength = 0;
1150 dwRemaining = ResultBufferLength;
1151 if (ResultBufferLength >= sizeof( AFSFileEvalResultCB)) {
1152 pEvalResultCB = (AFSFileEvalResultCB *)&(*ResultCB)->ResultData;
1153 pCurrentEntry = &pEvalResultCB->DirEnum;
1154 dwRemaining -= (sizeof( AFSFileEvalResultCB) - sizeof( AFSDirEnumEntry));
1157 if (ParentID.Cell != 0) {
1158 parentFid.cell = ParentID.Cell;
1159 parentFid.volume = ParentID.Volume;
1160 parentFid.vnode = ParentID.Vnode;
1161 parentFid.unique = ParentID.Unique;
1162 parentFid.hash = ParentID.Hash;
1164 code = cm_GetSCache(&parentFid, NULL, &dscp, userp, &req);
1166 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1167 (*ResultCB)->ResultStatus = status;
1168 if ( status == STATUS_INVALID_HANDLE)
1169 status = STATUS_OBJECT_PATH_INVALID;
1170 osi_Log2(afsd_logp, "RDR_EvaluateNodeByName cm_GetSCache parentFID failure code=0x%x status=0x%x",
1176 (*ResultCB)->ResultStatus = STATUS_OBJECT_NAME_INVALID;
1177 osi_Log0(afsd_logp, "RDR_EvaluateNodeByName Object Name Invalid - Cell = 0");
1181 /* get the directory size */
1182 lock_ObtainWrite(&dscp->rw);
1183 code = cm_SyncOp(dscp, NULL, userp, &req, 0,
1184 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1186 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1187 (*ResultCB)->ResultStatus = status;
1188 lock_ReleaseWrite(&dscp->rw);
1189 cm_ReleaseSCache(dscp);
1190 osi_Log3(afsd_logp, "RDR_EvaluateNodeByName cm_SyncOp failure dscp=0x%p code=0x%x status=0x%x",
1191 dscp, code, status);
1195 cm_SyncOpDone(dscp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1196 lock_ReleaseWrite(&dscp->rw);
1198 if (dscp->fileType != CM_SCACHETYPE_DIRECTORY) {
1199 (*ResultCB)->ResultStatus = STATUS_NOT_A_DIRECTORY;
1200 cm_ReleaseSCache(dscp);
1201 osi_Log1(afsd_logp, "RDR_EvaluateNodeByName Not a Directory dscp=0x%p",
1207 lookupFlags = CM_FLAG_NOMOUNTCHASE;
1209 if ( !LastComponent )
1210 lookupFlags |= CM_FLAG_CHECKPATH;
1211 code = cm_Lookup(dscp, wszName, lookupFlags, userp, &req, &scp);
1213 if (!CaseSensitive &&
1214 (code == CM_ERROR_NOSUCHPATH || code == CM_ERROR_NOSUCHFILE || code == CM_ERROR_BPLUS_NOMATCH)) {
1215 lookupFlags |= CM_FLAG_CASEFOLD;
1216 code = cm_Lookup(dscp, wszName, lookupFlags, userp, &req, &scp);
1219 if ((code == CM_ERROR_NOSUCHPATH || code == CM_ERROR_NOSUCHFILE || code == CM_ERROR_BPLUS_NOMATCH) &&
1220 dscp == cm_data.rootSCachep) {
1222 if (wcschr(wszName, '%') != NULL || wcschr(wszName, '#') != NULL) {
1224 * A volume reference: <cell>{%,#}<volume> -> @vol:<cell>{%,#}<volume>
1226 StringCchCopyNW(wszName, cbName, _C(CM_PREFIX_VOL), CM_PREFIX_VOL_CCH);
1227 StringCbCatNW(wszName, cbName, FileName, FileNameLength);
1230 code = cm_EvaluateVolumeReference(wszName, CM_FLAG_CHECKPATH, userp, &req, &scp);
1232 #ifdef AFS_FREELANCE_CLIENT
1233 else if (dscp->fid.cell == AFS_FAKE_ROOT_CELL_ID && dscp->fid.volume == AFS_FAKE_ROOT_VOL_ID &&
1234 dscp->fid.vnode == 1 && dscp->fid.unique == 1) {
1236 * If this is the Freelance volume root directory then treat unrecognized
1237 * names as cell names and attempt to find the appropriate "root.cell".
1239 StringCchCopyNW(wszName, cbName, _C(CM_PREFIX_VOL), CM_PREFIX_VOL_CCH);
1240 if (FileName[0] == L'.') {
1241 StringCbCatNW(wszName, cbName, &FileName[1], FileNameLength);
1242 StringCbCatNW(wszName, cbName, L"%", sizeof(WCHAR));
1244 StringCbCatNW(wszName, cbName, FileName, FileNameLength);
1245 StringCbCatNW(wszName, cbName, L"#", sizeof(WCHAR));
1247 StringCbCatNW(wszName, cbName, L"root.cell", 9 * sizeof(WCHAR));
1250 code = cm_EvaluateVolumeReference(wszName, CM_FLAG_CHECKPATH, userp, &req, &scp);
1255 if (code == 0 && scp) {
1256 wchar_t shortName[13]=L"";
1258 if (!cm_shortNames) {
1259 shortName[0] = L'\0';
1261 cm_Gen8Dot3VolNameW(scp->fid.cell, scp->fid.volume, shortName, NULL);
1262 } else if (!cm_Is8Dot3(wszName)) {
1265 dfid.vnode = htonl(scp->fid.vnode);
1266 dfid.unique = htonl(scp->fid.unique);
1268 cm_Gen8Dot3NameIntW(FileName, &dfid, shortName, NULL);
1270 shortName[0] = L'\0';
1273 code = RDR_PopulateCurrentEntry(pCurrentEntry, dwRemaining,
1274 dscp, scp, userp, &req,
1275 FileName, shortName,
1276 (bWow64 ? RDR_POP_WOW64 : 0) |
1277 (bNoFollow ? 0 : (RDR_POP_FOLLOW_MOUNTPOINTS | RDR_POP_EVALUATE_SYMLINKS)),
1278 0, NULL, &dwRemaining);
1280 RDR_FlagScpInUse( scp, FALSE );
1281 cm_ReleaseSCache(scp);
1284 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1285 (*ResultCB)->ResultStatus = status;
1286 osi_Log2(afsd_logp, "RDR_EvaluateNodeByName FAILURE code=0x%x status=0x%x",
1289 pEvalResultCB->ParentDataVersion.QuadPart = dscp->dataVersion;
1290 (*ResultCB)->ResultStatus = STATUS_SUCCESS;
1291 (*ResultCB)->ResultBufferLength = ResultBufferLength - dwRemaining;
1292 osi_Log0(afsd_logp, "RDR_EvaluateNodeByName SUCCESS");
1295 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1296 (*ResultCB)->ResultStatus = status;
1297 osi_Log2(afsd_logp, "RDR_EvaluateNodeByName FAILURE code=0x%x status=0x%x",
1300 (*ResultCB)->ResultStatus = STATUS_NO_SUCH_FILE;
1301 osi_Log0(afsd_logp, "RDR_EvaluateNodeByName No Such File");
1303 cm_ReleaseSCache(dscp);
1310 RDR_EvaluateNodeByID( IN cm_user_t *userp,
1311 IN AFSFileID ParentID, /* not used */
1312 IN AFSFileID SourceID,
1316 IN DWORD ResultBufferLength,
1317 IN OUT AFSCommResult **ResultCB)
1319 AFSFileEvalResultCB *pEvalResultCB = NULL;
1320 AFSDirEnumEntry * pCurrentEntry = NULL;
1321 size_t size = ResultBufferLength ? sizeof(AFSCommResult) + ResultBufferLength - 1 : sizeof(AFSCommResult);
1322 afs_uint32 code = 0;
1323 cm_scache_t * scp = NULL;
1324 cm_scache_t * dscp = NULL;
1331 osi_Log4(afsd_logp, "RDR_EvaluateNodeByID source FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
1332 SourceID.Cell, SourceID.Volume, SourceID.Vnode, SourceID.Unique);
1333 osi_Log4(afsd_logp, "... parent FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
1334 ParentID.Cell, ParentID.Volume, ParentID.Vnode, ParentID.Unique);
1336 *ResultCB = (AFSCommResult *)malloc(size);
1338 osi_Log0(afsd_logp, "RDR_EvaluateNodeByID Out of Memory");
1342 memset(*ResultCB, 0, size);
1343 (*ResultCB)->ResultBufferLength = 0;
1344 dwRemaining = ResultBufferLength;
1345 if (ResultBufferLength >= sizeof( AFSFileEvalResultCB)) {
1346 pEvalResultCB = (AFSFileEvalResultCB *)&(*ResultCB)->ResultData;
1347 pCurrentEntry = &pEvalResultCB->DirEnum;
1348 dwRemaining -= (sizeof( AFSFileEvalResultCB) - sizeof( AFSDirEnumEntry));
1351 RDR_InitReq(&req, bWow64);
1353 if (SourceID.Cell != 0) {
1354 cm_SetFid(&Fid, SourceID.Cell, SourceID.Volume, SourceID.Vnode, SourceID.Unique);
1355 code = cm_GetSCache(&Fid, NULL, &scp, userp, &req);
1357 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1358 (*ResultCB)->ResultStatus = status;
1359 osi_Log2(afsd_logp, "RDR_EvaluateNodeByID cm_GetSCache SourceFID failure code=0x%x status=0x%x",
1364 (*ResultCB)->ResultStatus = STATUS_OBJECT_NAME_INVALID;
1365 osi_Log0(afsd_logp, "RDR_EvaluateNodeByID Object Name Invalid - Cell = 0");
1369 if (ParentID.Cell != 0) {
1370 cm_SetFid(&parentFid, ParentID.Cell, ParentID.Volume, ParentID.Vnode, ParentID.Unique);
1371 code = cm_GetSCache(&parentFid, NULL, &dscp, userp, &req);
1373 cm_ReleaseSCache(scp);
1374 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1375 if ( status == STATUS_INVALID_HANDLE)
1376 status = STATUS_OBJECT_PATH_INVALID;
1377 (*ResultCB)->ResultStatus = status;
1378 osi_Log2(afsd_logp, "RDR_EvaluateNodeByID cm_GetSCache parentFID failure code=0x%x status=0x%x",
1382 } else if (SourceID.Vnode == 1) {
1384 cm_HoldSCache(dscp);
1385 } else if (scp->parentVnode) {
1386 cm_SetFid(&parentFid, SourceID.Cell, SourceID.Volume, scp->parentVnode, scp->parentUnique);
1387 code = cm_GetSCache(&parentFid, NULL, &dscp, userp, &req);
1389 cm_ReleaseSCache(scp);
1390 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1391 if ( status == STATUS_INVALID_HANDLE)
1392 status = STATUS_OBJECT_PATH_INVALID;
1393 (*ResultCB)->ResultStatus = status;
1394 osi_Log2(afsd_logp, "RDR_EvaluateNodeByID cm_GetSCache parentFID failure code=0x%x status=0x%x",
1399 (*ResultCB)->ResultStatus = STATUS_OBJECT_PATH_INVALID;
1400 osi_Log0(afsd_logp, "RDR_EvaluateNodeByID Object Path Invalid - Unknown Parent");
1404 /* Make sure the directory is current */
1405 lock_ObtainWrite(&dscp->rw);
1406 code = cm_SyncOp(dscp, NULL, userp, &req, 0,
1407 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1409 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1410 (*ResultCB)->ResultStatus = status;
1411 lock_ReleaseWrite(&dscp->rw);
1412 cm_ReleaseSCache(dscp);
1413 cm_ReleaseSCache(scp);
1414 osi_Log3(afsd_logp, "RDR_EvaluateNodeByID cm_SyncOp failure dscp=0x%p code=0x%x status=0x%x",
1415 dscp, code, status);
1419 cm_SyncOpDone(dscp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1420 lock_ReleaseWrite(&dscp->rw);
1422 if (dscp->fileType != CM_SCACHETYPE_DIRECTORY) {
1423 (*ResultCB)->ResultStatus = STATUS_NOT_A_DIRECTORY;
1424 cm_ReleaseSCache(dscp);
1425 cm_ReleaseSCache(scp);
1426 osi_Log1(afsd_logp, "RDR_EvaluateNodeByID Not a Directory dscp=0x%p", dscp);
1430 code = RDR_PopulateCurrentEntry(pCurrentEntry, dwRemaining,
1431 dscp, scp, userp, &req, NULL, NULL,
1432 (bWow64 ? RDR_POP_WOW64 : 0) |
1433 (bNoFollow ? 0 : (RDR_POP_FOLLOW_MOUNTPOINTS | RDR_POP_EVALUATE_SYMLINKS)),
1434 0, NULL, &dwRemaining);
1437 RDR_FlagScpInUse( scp, FALSE );
1438 cm_ReleaseSCache(scp);
1439 cm_ReleaseSCache(dscp);
1442 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1443 (*ResultCB)->ResultStatus = status;
1444 osi_Log2(afsd_logp, "RDR_EvaluateNodeByID FAILURE code=0x%x status=0x%x",
1447 pEvalResultCB->ParentDataVersion.QuadPart = dscp->dataVersion;
1449 (*ResultCB)->ResultStatus = STATUS_SUCCESS;
1450 (*ResultCB)->ResultBufferLength = ResultBufferLength - dwRemaining;
1451 osi_Log0(afsd_logp, "RDR_EvaluateNodeByID SUCCESS");
1457 RDR_CreateFileEntry( IN cm_user_t *userp,
1458 IN WCHAR *FileNameCounted,
1459 IN DWORD FileNameLength,
1460 IN AFSFileCreateCB *CreateCB,
1463 IN DWORD ResultBufferLength,
1464 IN OUT AFSCommResult **ResultCB)
1466 AFSFileCreateResultCB *pResultCB = NULL;
1467 size_t size = sizeof(AFSCommResult) + ResultBufferLength - 1;
1470 cm_scache_t * dscp = NULL;
1471 afs_uint32 flags = 0;
1473 cm_scache_t * scp = NULL;
1476 wchar_t FileName[260];
1478 StringCchCopyNW(FileName, 260, FileNameCounted, FileNameLength / sizeof(WCHAR));
1480 osi_Log4(afsd_logp, "RDR_CreateFileEntry parent FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
1481 CreateCB->ParentId.Cell, CreateCB->ParentId.Volume,
1482 CreateCB->ParentId.Vnode, CreateCB->ParentId.Unique);
1483 osi_Log1(afsd_logp, "... name=%S", osi_LogSaveStringW(afsd_logp, FileName));
1485 RDR_InitReq(&req, bWow64);
1486 memset(&setAttr, 0, sizeof(cm_attr_t));
1488 *ResultCB = (AFSCommResult *)malloc(size);
1490 osi_Log0(afsd_logp, "RDR_CreateFileEntry out of memory");
1498 parentFid.cell = CreateCB->ParentId.Cell;
1499 parentFid.volume = CreateCB->ParentId.Volume;
1500 parentFid.vnode = CreateCB->ParentId.Vnode;
1501 parentFid.unique = CreateCB->ParentId.Unique;
1502 parentFid.hash = CreateCB->ParentId.Hash;
1504 code = cm_GetSCache(&parentFid, NULL, &dscp, userp, &req);
1506 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1507 (*ResultCB)->ResultStatus = status;
1508 if ( status == STATUS_INVALID_HANDLE)
1509 status = STATUS_OBJECT_PATH_INVALID;
1510 osi_Log2(afsd_logp, "RDR_CreateFileEntry cm_GetSCache ParentFID failure code=0x%x status=0x%x",
1515 lock_ObtainWrite(&dscp->rw);
1516 code = cm_SyncOp(dscp, NULL, userp, &req, 0,
1517 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1519 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1520 (*ResultCB)->ResultStatus = status;
1521 lock_ReleaseWrite(&dscp->rw);
1522 cm_ReleaseSCache(dscp);
1523 osi_Log3(afsd_logp, "RDR_CreateFileEntry cm_SyncOp failure (1) dscp=0x%p code=0x%x status=0x%x",
1524 dscp, code, status);
1528 cm_SyncOpDone(dscp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1529 lock_ReleaseWrite(&dscp->rw);
1531 if (dscp->fileType != CM_SCACHETYPE_DIRECTORY) {
1532 (*ResultCB)->ResultStatus = STATUS_NOT_A_DIRECTORY;
1533 cm_ReleaseSCache(dscp);
1534 osi_Log1(afsd_logp, "RDR_CreateFileEntry Not a Directory dscp=0x%p",
1539 /* Use current time */
1540 setAttr.mask = CM_ATTRMASK_CLIENTMODTIME;
1541 setAttr.clientModTime = time(NULL);
1543 if (CreateCB->FileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
1544 if (smb_unixModeDefaultDir) {
1545 setAttr.mask |= CM_ATTRMASK_UNIXMODEBITS;
1546 setAttr.unixModeBits = smb_unixModeDefaultDir;
1547 if (CreateCB->FileAttributes & FILE_ATTRIBUTE_READONLY)
1548 setAttr.unixModeBits &= ~0222; /* disable the write bits */
1551 code = cm_MakeDir(dscp, FileName, flags, &setAttr, userp, &req, &scp);
1553 if (smb_unixModeDefaultFile) {
1554 setAttr.mask |= CM_ATTRMASK_UNIXMODEBITS;
1555 setAttr.unixModeBits = smb_unixModeDefaultFile;
1556 if (CreateCB->FileAttributes & FILE_ATTRIBUTE_READONLY)
1557 setAttr.unixModeBits &= ~0222; /* disable the write bits */
1560 setAttr.mask |= CM_ATTRMASK_LENGTH;
1561 setAttr.length.LowPart = CreateCB->AllocationSize.LowPart;
1562 setAttr.length.HighPart = CreateCB->AllocationSize.HighPart;
1563 code = cm_Create(dscp, FileName, flags, &setAttr, &scp, userp, &req);
1566 wchar_t shortName[13]=L"";
1570 (*ResultCB)->ResultStatus = 0; // We will be able to fit all the data in here
1572 (*ResultCB)->ResultBufferLength = sizeof( AFSFileCreateResultCB);
1574 pResultCB = (AFSFileCreateResultCB *)(*ResultCB)->ResultData;
1576 dwRemaining = ResultBufferLength - sizeof( AFSFileCreateResultCB) + sizeof( AFSDirEnumEntry);
1578 lock_ObtainWrite(&dscp->rw);
1579 code = cm_SyncOp(dscp, NULL, userp, &req, 0,
1580 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1582 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1583 (*ResultCB)->ResultStatus = status;
1584 lock_ReleaseWrite(&dscp->rw);
1585 cm_ReleaseSCache(dscp);
1586 cm_ReleaseSCache(scp);
1587 osi_Log3(afsd_logp, "RDR_CreateFileEntry cm_SyncOp failure (2) dscp=0x%p code=0x%x status=0x%x",
1588 dscp, code, status);
1592 pResultCB->ParentDataVersion.QuadPart = dscp->dataVersion;
1594 cm_SyncOpDone(dscp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1595 lock_ReleaseWrite(&dscp->rw);
1597 if (cm_shortNames) {
1598 dfid.vnode = htonl(scp->fid.vnode);
1599 dfid.unique = htonl(scp->fid.unique);
1601 if (!cm_Is8Dot3(FileName))
1602 cm_Gen8Dot3NameIntW(FileName, &dfid, shortName, NULL);
1604 shortName[0] = '\0';
1607 code = RDR_PopulateCurrentEntry(&pResultCB->DirEnum, dwRemaining,
1608 dscp, scp, userp, &req, FileName, shortName,
1609 RDR_POP_FOLLOW_MOUNTPOINTS | RDR_POP_EVALUATE_SYMLINKS,
1610 0, NULL, &dwRemaining);
1613 RDR_FlagScpInUse( scp, FALSE );
1614 cm_ReleaseSCache(scp);
1615 (*ResultCB)->ResultBufferLength = ResultBufferLength - dwRemaining;
1616 osi_Log0(afsd_logp, "RDR_CreateFileEntry SUCCESS");
1618 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1619 (*ResultCB)->ResultStatus = status;
1620 (*ResultCB)->ResultBufferLength = 0;
1621 osi_Log2(afsd_logp, "RDR_CreateFileEntry FAILURE code=0x%x status=0x%x",
1625 cm_ReleaseSCache(dscp);
1631 RDR_UpdateFileEntry( IN cm_user_t *userp,
1632 IN AFSFileID FileId,
1633 IN AFSFileUpdateCB *UpdateCB,
1635 IN DWORD ResultBufferLength,
1636 IN OUT AFSCommResult **ResultCB)
1638 AFSFileUpdateResultCB *pResultCB = NULL;
1639 size_t size = sizeof(AFSCommResult) + ResultBufferLength - 1;
1643 afs_uint32 flags = 0;
1645 cm_scache_t * scp = NULL;
1646 cm_scache_t * dscp = NULL;
1648 time_t clientModTime;
1651 BOOL bScpLocked = FALSE;
1653 RDR_InitReq(&req, bWow64);
1654 memset(&setAttr, 0, sizeof(cm_attr_t));
1656 osi_Log4(afsd_logp, "RDR_UpdateFileEntry parent FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
1657 UpdateCB->ParentId.Cell, UpdateCB->ParentId.Volume,
1658 UpdateCB->ParentId.Vnode, UpdateCB->ParentId.Unique);
1659 osi_Log4(afsd_logp, "... object FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
1660 FileId.Cell, FileId.Volume,
1661 FileId.Vnode, FileId.Unique);
1663 *ResultCB = (AFSCommResult *)malloc( size);
1665 osi_Log0(afsd_logp, "RDR_UpdateFileEntry Out of Memory");
1673 parentFid.cell = UpdateCB->ParentId.Cell;
1674 parentFid.volume = UpdateCB->ParentId.Volume;
1675 parentFid.vnode = UpdateCB->ParentId.Vnode;
1676 parentFid.unique = UpdateCB->ParentId.Unique;
1677 parentFid.hash = UpdateCB->ParentId.Hash;
1679 code = cm_GetSCache(&parentFid, NULL, &dscp, userp, &req);
1681 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1682 (*ResultCB)->ResultStatus = status;
1683 if ( status == STATUS_INVALID_HANDLE)
1684 status = STATUS_OBJECT_PATH_INVALID;
1685 osi_Log2(afsd_logp, "RDR_UpdateFileEntry cm_GetSCache ParentFID failure code=0x%x status=0x%x",
1690 lock_ObtainWrite(&dscp->rw);
1691 code = cm_SyncOp(dscp, NULL, userp, &req, 0,
1692 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1694 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1695 (*ResultCB)->ResultStatus = status;
1696 lock_ReleaseWrite(&dscp->rw);
1697 cm_ReleaseSCache(dscp);
1698 osi_Log3(afsd_logp, "RDR_UpdateFileEntry cm_SyncOp failure dscp=0x%p code=0x%x status=0x%x",
1699 dscp, code, status);
1703 cm_SyncOpDone(dscp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1704 lock_ReleaseWrite(&dscp->rw);
1706 if (dscp->fileType != CM_SCACHETYPE_DIRECTORY) {
1707 (*ResultCB)->ResultStatus = STATUS_NOT_A_DIRECTORY;
1708 cm_ReleaseSCache(dscp);
1709 osi_Log1(afsd_logp, "RDR_UpdateFileEntry Not a Directory dscp=0x%p",
1714 Fid.cell = FileId.Cell;
1715 Fid.volume = FileId.Volume;
1716 Fid.vnode = FileId.Vnode;
1717 Fid.unique = FileId.Unique;
1718 Fid.hash = FileId.Hash;
1720 code = cm_GetSCache(&Fid, &dscp->fid, &scp, userp, &req);
1722 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1723 (*ResultCB)->ResultStatus = status;
1724 cm_ReleaseSCache(dscp);
1725 osi_Log2(afsd_logp, "RDR_UpdateFileEntry cm_GetSCache object FID failure code=0x%x status=0x%x",
1730 lock_ObtainWrite(&scp->rw);
1732 code = cm_SyncOp(scp, NULL, userp, &req, 0,
1733 CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_NEEDCALLBACK);
1735 lock_ReleaseWrite(&scp->rw);
1736 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1737 (*ResultCB)->ResultStatus = status;
1738 (*ResultCB)->ResultBufferLength = 0;
1739 cm_ReleaseSCache(dscp);
1740 cm_ReleaseSCache(scp);
1741 osi_Log3(afsd_logp, "RDR_UpdateFileEntry cm_SyncOp failure scp=0x%p code=0x%x status=0x%x",
1745 cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1747 if (UpdateCB->ChangeTime.QuadPart) {
1749 if (scp->fileType == CM_SCACHETYPE_FILE) {
1750 /* Do not set length and other attributes at the same time */
1751 if (scp->length.QuadPart != UpdateCB->AllocationSize.QuadPart) {
1752 osi_Log2(afsd_logp, "RDR_UpdateFileEntry Length Change 0x%x -> 0x%x",
1753 (afs_uint32)scp->length.QuadPart, (afs_uint32)UpdateCB->AllocationSize.QuadPart);
1754 setAttr.mask |= CM_ATTRMASK_LENGTH;
1755 setAttr.length.LowPart = UpdateCB->AllocationSize.LowPart;
1756 setAttr.length.HighPart = UpdateCB->AllocationSize.HighPart;
1757 lock_ReleaseWrite(&scp->rw);
1759 code = cm_SetAttr(scp, &setAttr, userp, &req);
1767 lock_ObtainWrite(&scp->rw);
1770 if ((scp->unixModeBits & 0200) && (UpdateCB->FileAttributes & FILE_ATTRIBUTE_READONLY)) {
1771 setAttr.mask |= CM_ATTRMASK_UNIXMODEBITS;
1772 setAttr.unixModeBits = scp->unixModeBits & ~0222;
1773 } else if (!(scp->unixModeBits & 0200) && !(UpdateCB->FileAttributes & FILE_ATTRIBUTE_READONLY)) {
1774 setAttr.mask |= CM_ATTRMASK_UNIXMODEBITS;
1775 setAttr.unixModeBits = scp->unixModeBits | 0222;
1779 if (UpdateCB->LastWriteTime.QuadPart) {
1780 ft.dwLowDateTime = UpdateCB->LastWriteTime.LowPart;
1781 ft.dwHighDateTime = UpdateCB->LastWriteTime.HighPart;
1783 cm_UnixTimeFromLargeSearchTime(& clientModTime, &ft);
1786 lock_ObtainWrite(&scp->rw);
1789 if (scp->clientModTime != clientModTime) {
1790 setAttr.mask |= CM_ATTRMASK_CLIENTMODTIME;
1791 setAttr.clientModTime = clientModTime;
1796 lock_ReleaseWrite(&scp->rw);
1798 code = cm_SetAttr(scp, &setAttr, userp, &req);
1805 lock_ReleaseWrite(&scp->rw);
1809 DWORD dwRemaining = ResultBufferLength - sizeof( AFSFileUpdateResultCB) + sizeof( AFSDirEnumEntry);
1811 pResultCB = (AFSFileUpdateResultCB *)(*ResultCB)->ResultData;
1813 pResultCB->ParentDataVersion.QuadPart = dscp->dataVersion;
1815 code = RDR_PopulateCurrentEntry(&pResultCB->DirEnum, dwRemaining,
1816 dscp, scp, userp, &req, NULL, NULL,
1817 RDR_POP_FOLLOW_MOUNTPOINTS | RDR_POP_EVALUATE_SYMLINKS,
1818 0, NULL, &dwRemaining);
1819 (*ResultCB)->ResultBufferLength = ResultBufferLength - dwRemaining;
1820 osi_Log0(afsd_logp, "RDR_UpdateFileEntry SUCCESS");
1822 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1823 (*ResultCB)->ResultStatus = status;
1824 (*ResultCB)->ResultBufferLength = 0;
1825 osi_Log2(afsd_logp, "RDR_UpdateFileEntry FAILURE code=0x%x status=0x%x",
1828 cm_ReleaseSCache(scp);
1829 cm_ReleaseSCache(dscp);
1835 RDR_CleanupFileEntry( IN cm_user_t *userp,
1836 IN AFSFileID FileId,
1837 IN WCHAR *FileNameCounted,
1838 IN DWORD FileNameLength,
1839 IN AFSFileCleanupCB *CleanupCB,
1841 IN BOOL bLastHandle,
1842 IN BOOL bDeleteFile,
1843 IN BOOL bUnlockFile,
1844 IN DWORD ResultBufferLength,
1845 IN OUT AFSCommResult **ResultCB)
1847 AFSFileCleanupResultCB *pResultCB = NULL;
1848 size_t size = sizeof(AFSCommResult) + ResultBufferLength - 1;
1851 afs_uint32 code = 0;
1852 afs_uint32 flags = 0;
1854 cm_scache_t * scp = NULL;
1855 cm_scache_t * dscp = NULL;
1857 time_t clientModTime;
1860 BOOL bScpLocked = FALSE;
1861 BOOL bDscpLocked = FALSE;
1862 BOOL bFlushFile = FALSE;
1865 RDR_InitReq(&req, bWow64);
1866 memset(&setAttr, 0, sizeof(cm_attr_t));
1868 osi_Log4(afsd_logp, "RDR_CleanupFileEntry parent FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
1869 CleanupCB->ParentId.Cell, CleanupCB->ParentId.Volume,
1870 CleanupCB->ParentId.Vnode, CleanupCB->ParentId.Unique);
1871 osi_Log4(afsd_logp, "... object FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
1872 FileId.Cell, FileId.Volume,
1873 FileId.Vnode, FileId.Unique);
1875 *ResultCB = (AFSCommResult *)malloc( size);
1877 osi_Log0(afsd_logp, "RDR_CleanupFileEntry Out of Memory");
1885 parentFid.cell = CleanupCB->ParentId.Cell;
1886 parentFid.volume = CleanupCB->ParentId.Volume;
1887 parentFid.vnode = CleanupCB->ParentId.Vnode;
1888 parentFid.unique = CleanupCB->ParentId.Unique;
1889 parentFid.hash = CleanupCB->ParentId.Hash;
1891 if (parentFid.cell) {
1892 code = cm_GetSCache(&parentFid, NULL, &dscp, userp, &req);
1894 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1895 if ( status == STATUS_INVALID_HANDLE)
1896 status = STATUS_OBJECT_PATH_INVALID;
1897 (*ResultCB)->ResultStatus = status;
1898 osi_Log2(afsd_logp, "RDR_CleanupFileEntry cm_GetSCache ParentFID failure code=0x%x status=0x%x",
1903 lock_ObtainWrite(&dscp->rw);
1905 code = cm_SyncOp(dscp, NULL, userp, &req, 0,
1906 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1908 osi_Log2(afsd_logp, "RDR_CleanupFileEntry cm_SyncOp failure dscp=0x%p code=0x%x",
1914 cm_SyncOpDone(dscp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1915 lock_ReleaseWrite(&dscp->rw);
1916 bDscpLocked = FALSE;
1918 if (dscp->fileType != CM_SCACHETYPE_DIRECTORY) {
1919 (*ResultCB)->ResultStatus = STATUS_NOT_A_DIRECTORY;
1920 cm_ReleaseSCache(dscp);
1921 osi_Log1(afsd_logp, "RDR_CleanupFileEntry Not a Directory dscp=0x%p",
1928 Fid.cell = FileId.Cell;
1929 Fid.volume = FileId.Volume;
1930 Fid.vnode = FileId.Vnode;
1931 Fid.unique = FileId.Unique;
1932 Fid.hash = FileId.Hash;
1934 code = cm_GetSCache(&Fid, dscp ? &dscp->fid : NULL, &scp, userp, &req);
1936 osi_Log1(afsd_logp, "RDR_CleanupFileEntry cm_GetSCache object FID failure code=0x%x",
1941 lock_ObtainWrite(&scp->rw);
1943 code = cm_SyncOp(scp, NULL, userp, &req, 0,
1944 CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_NEEDCALLBACK);
1946 osi_Log2(afsd_logp, "RDR_CleanupFileEntry cm_SyncOp failure scp=0x%p code=0x%x",
1950 cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1952 if (bLastHandle && (scp->fileType == CM_SCACHETYPE_FILE) &&
1953 scp->redirBufCount > 0)
1955 LARGE_INTEGER heldExtents;
1956 AFSFileExtentCB extentList[1024];
1957 DWORD extentCount = 0;
1962 heldExtents.QuadPart = 0;
1964 for ( srbp = redirq_to_cm_buf_t(scp->redirQueueT);
1966 srbp = redirq_to_cm_buf_t(osi_QPrev(&srbp->redirq)))
1968 extentList[extentCount].Flags = 0;
1969 extentList[extentCount].Length = cm_data.blockSize;
1970 extentList[extentCount].FileOffset.QuadPart = srbp->offset.QuadPart;
1971 extentList[extentCount].CacheOffset.QuadPart = srbp->datap - RDR_extentBaseAddress;
1972 lock_ObtainWrite(&buf_globalLock);
1973 srbp->redirReleaseRequested = now;
1974 lock_ReleaseWrite(&buf_globalLock);
1977 if (extentCount == 1024) {
1978 lock_ReleaseWrite(&scp->rw);
1979 code = RDR_RequestExtentRelease(&scp->fid, heldExtents, extentCount, extentList);
1981 if (code == CM_ERROR_RETRY) {
1983 * The redirector either is not holding the extents or cannot let them
1984 * go because they are otherwise in use. At the moment, do nothing.
1991 lock_ObtainWrite(&scp->rw);
1995 if (code == 0 && extentCount > 0) {
1997 lock_ReleaseWrite(&scp->rw);
2000 code = RDR_RequestExtentRelease(&scp->fid, heldExtents, extentCount, extentList);
2005 /* No longer in use by redirector */
2007 lock_ObtainWrite(&scp->rw);
2012 lock_AssertWrite(&scp->rw);
2013 scp->flags &= ~CM_SCACHEFLAG_RDR_IN_USE;
2016 /* If not a readonly object, flush dirty data and update metadata */
2017 if (!(scp->flags & CM_SCACHEFLAG_RO)) {
2018 if ((scp->fileType == CM_SCACHETYPE_FILE) && (bLastHandle || bFlushFile)) {
2019 /* Serialize with any outstanding AsyncStore operation */
2020 code = cm_SyncOp(scp, NULL, userp, &req, 0, CM_SCACHESYNC_ASYNCSTORE);
2022 cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_ASYNCSTORE);
2024 code = cm_SyncOp(scp, NULL, userp, &req, PRSFS_WRITE,
2025 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2027 * If we only have 'i' bits, then we should still be able to
2028 * set flush the file.
2030 if (code == CM_ERROR_NOACCESS && scp->creator == userp) {
2031 code = cm_SyncOp(scp, NULL, userp, &req, PRSFS_INSERT,
2032 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2036 lock_ReleaseWrite(&scp->rw);
2040 code = cm_FSync(scp, userp, &req, bScpLocked);
2043 if (bLastHandle && code)
2047 if (CleanupCB->ChangeTime.QuadPart) {
2049 if (scp->fileType == CM_SCACHETYPE_FILE) {
2050 /* Do not set length and other attributes at the same time */
2051 if (scp->length.QuadPart != CleanupCB->AllocationSize.QuadPart) {
2052 osi_Log2(afsd_logp, "RDR_CleanupFileEntry Length Change 0x%x -> 0x%x",
2053 (afs_uint32)scp->length.QuadPart, (afs_uint32)CleanupCB->AllocationSize.QuadPart);
2054 setAttr.mask |= CM_ATTRMASK_LENGTH;
2055 setAttr.length.LowPart = CleanupCB->AllocationSize.LowPart;
2056 setAttr.length.HighPart = CleanupCB->AllocationSize.HighPart;
2059 lock_ReleaseWrite(&scp->rw);
2062 code = cm_SetAttr(scp, &setAttr, userp, &req);
2070 lock_ObtainWrite(&scp->rw);
2074 if ((scp->unixModeBits & 0200) && (CleanupCB->FileAttributes & FILE_ATTRIBUTE_READONLY)) {
2075 setAttr.mask |= CM_ATTRMASK_UNIXMODEBITS;
2076 setAttr.unixModeBits = scp->unixModeBits & ~0222;
2077 } else if (!(scp->unixModeBits & 0200) && !(CleanupCB->FileAttributes & FILE_ATTRIBUTE_READONLY)) {
2078 setAttr.mask |= CM_ATTRMASK_UNIXMODEBITS;
2079 setAttr.unixModeBits = scp->unixModeBits | 0222;
2083 if (CleanupCB->LastWriteTime.QuadPart) {
2084 ft.dwLowDateTime = CleanupCB->LastWriteTime.LowPart;
2085 ft.dwHighDateTime = CleanupCB->LastWriteTime.HighPart;
2087 cm_UnixTimeFromLargeSearchTime(&clientModTime, &ft);
2088 if (scp->clientModTime != clientModTime) {
2089 setAttr.mask |= CM_ATTRMASK_CLIENTMODTIME;
2090 setAttr.clientModTime = clientModTime;
2097 lock_ReleaseWrite(&scp->rw);
2100 code = cm_SetAttr(scp, &setAttr, userp, &req);
2106 /* Now drop the lock enforcing the share access */
2107 if ( CleanupCB->FileAccess != AFS_FILE_ACCESS_NOLOCK) {
2108 unsigned int sLockType;
2109 LARGE_INTEGER LOffset, LLength;
2111 if (CleanupCB->FileAccess == AFS_FILE_ACCESS_SHARED)
2112 sLockType = LOCKING_ANDX_SHARED_LOCK;
2116 key = cm_GenerateKey(CM_SESSION_IFS, SMB_FID_QLOCK_PID, CleanupCB->Identifier);
2118 LOffset.HighPart = SMB_FID_QLOCK_HIGH;
2119 LOffset.LowPart = SMB_FID_QLOCK_LOW;
2120 LLength.HighPart = 0;
2121 LLength.LowPart = SMB_FID_QLOCK_LENGTH;
2124 lock_ObtainWrite(&scp->rw);
2128 code = cm_SyncOp(scp, NULL, userp, &req, 0, CM_SCACHESYNC_LOCK);
2131 code = cm_Unlock(scp, sLockType, LOffset, LLength, key, 0, userp, &req);
2133 cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_LOCK);
2135 if (code == CM_ERROR_RANGE_NOT_LOCKED)
2137 osi_Log3(afsd_logp, "RDR_CleanupFileEntry Range Not Locked -- FileAccess 0x%x ProcessId 0x%x HandleId 0x%x",
2138 CleanupCB->FileAccess, CleanupCB->ProcessId, CleanupCB->Identifier);
2144 if (bUnlockFile || bDeleteFile) {
2146 lock_ObtainWrite(&scp->rw);
2149 code = cm_SyncOp(scp, NULL, userp, &req, 0,
2150 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_LOCK);
2152 osi_Log2(afsd_logp, "RDR_CleanupFileEntry cm_SyncOp (2) failure scp=0x%p code=0x%x",
2157 key = cm_GenerateKey(CM_SESSION_IFS, CleanupCB->ProcessId, 0);
2159 /* the scp is now locked and current */
2160 code = cm_UnlockByKey(scp, key,
2161 bDeleteFile ? CM_UNLOCK_FLAG_BY_FID : 0,
2164 cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_LOCK);
2172 lock_ReleaseWrite(&dscp->rw);
2174 lock_ReleaseWrite(&scp->rw);
2176 if (code == 0 && dscp && bDeleteFile) {
2177 WCHAR FileName[260];
2179 StringCchCopyNW(FileName, 260, FileNameCounted, FileNameLength / sizeof(WCHAR));
2181 if (scp->fileType == CM_SCACHETYPE_DIRECTORY)
2182 code = cm_RemoveDir(dscp, NULL, FileName, userp, &req);
2184 code = cm_Unlink(dscp, NULL, FileName, userp, &req);
2188 if ( ResultBufferLength >= sizeof( AFSFileCleanupResultCB))
2190 (*ResultCB)->ResultBufferLength = sizeof( AFSFileCleanupResultCB);
2191 pResultCB = (AFSFileCleanupResultCB *)&(*ResultCB)->ResultData;
2192 pResultCB->ParentDataVersion.QuadPart = dscp ? dscp->dataVersion : 0;
2194 (*ResultCB)->ResultBufferLength = 0;
2197 (*ResultCB)->ResultStatus = 0;
2198 osi_Log0(afsd_logp, "RDR_CleanupFileEntry SUCCESS");
2200 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2201 (*ResultCB)->ResultStatus = status;
2202 osi_Log2(afsd_logp, "RDR_CleanupFileEntry FAILURE code=0x%x status=0x%x",
2207 cm_ReleaseSCache(scp);
2209 cm_ReleaseSCache(dscp);
2215 RDR_DeleteFileEntry( IN cm_user_t *userp,
2216 IN AFSFileID ParentId,
2217 IN ULONGLONG ProcessId,
2218 IN WCHAR *FileNameCounted,
2219 IN DWORD FileNameLength,
2222 IN DWORD ResultBufferLength,
2223 IN OUT AFSCommResult **ResultCB)
2226 AFSFileDeleteResultCB *pResultCB = NULL;
2227 size_t size = sizeof(AFSCommResult) + ResultBufferLength - 1;
2230 cm_scache_t * dscp = NULL;
2231 cm_scache_t * scp = NULL;
2232 afs_uint32 flags = 0;
2236 wchar_t FileName[260];
2239 StringCchCopyNW(FileName, 260, FileNameCounted, FileNameLength / sizeof(WCHAR));
2241 osi_Log4(afsd_logp, "RDR_DeleteFileEntry parent FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
2242 ParentId.Cell, ParentId.Volume,
2243 ParentId.Vnode, ParentId.Unique);
2244 osi_Log2(afsd_logp, "... name=%S checkOnly=%x",
2245 osi_LogSaveStringW(afsd_logp, FileName),
2248 RDR_InitReq(&req, bWow64);
2249 memset(&setAttr, 0, sizeof(cm_attr_t));
2251 *ResultCB = (AFSCommResult *)malloc( size);
2253 osi_Log0(afsd_logp, "RDR_DeleteFileEntry out of memory");
2261 parentFid.cell = ParentId.Cell;
2262 parentFid.volume = ParentId.Volume;
2263 parentFid.vnode = ParentId.Vnode;
2264 parentFid.unique = ParentId.Unique;
2265 parentFid.hash = ParentId.Hash;
2267 code = cm_GetSCache(&parentFid, NULL, &dscp, userp, &req);
2269 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2270 if ( status == STATUS_INVALID_HANDLE)
2271 status = STATUS_OBJECT_PATH_INVALID;
2272 (*ResultCB)->ResultStatus = status;
2273 osi_Log2(afsd_logp, "RDR_DeleteFileEntry cm_GetSCache ParentFID failure code=0x%x status=0x%x",
2278 lock_ObtainWrite(&dscp->rw);
2280 code = cm_SyncOp(dscp, NULL, userp, &req, 0,
2281 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2283 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2284 (*ResultCB)->ResultStatus = status;
2285 (*ResultCB)->ResultBufferLength = 0;
2286 lock_ReleaseWrite(&dscp->rw);
2287 cm_ReleaseSCache(dscp);
2288 osi_Log3(afsd_logp, "RDR_DeleteFileEntry cm_SyncOp failure dscp=0x%p code=0x%x status=0x%x",
2289 dscp, code, status);
2293 cm_SyncOpDone(dscp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2294 lock_ReleaseWrite(&dscp->rw);
2296 if (dscp->fileType != CM_SCACHETYPE_DIRECTORY) {
2297 (*ResultCB)->ResultStatus = STATUS_NOT_A_DIRECTORY;
2298 cm_ReleaseSCache(dscp);
2299 osi_Log1(afsd_logp, "RDR_DeleteFileEntry Not a Directory dscp=0x%p",
2304 code = cm_Lookup(dscp, FileName, 0, userp, &req, &scp);
2306 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2307 (*ResultCB)->ResultStatus = status;
2308 (*ResultCB)->ResultBufferLength = 0;
2309 cm_ReleaseSCache(dscp);
2310 osi_Log2(afsd_logp, "RDR_DeleteFileEntry cm_Lookup failure code=0x%x status=0x%x",
2315 lock_ObtainWrite(&scp->rw);
2316 code = cm_SyncOp(scp, NULL, userp, &req, PRSFS_DELETE,
2317 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2319 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2320 (*ResultCB)->ResultStatus = status;
2321 (*ResultCB)->ResultBufferLength = 0;
2322 lock_ReleaseWrite(&scp->rw);
2323 cm_ReleaseSCache(scp);
2324 cm_ReleaseSCache(dscp);
2325 osi_Log3(afsd_logp, "RDR_DeleteFileEntry cm_SyncOp failure scp=0x%p code=0x%x status=0x%x",
2330 if (scp->fileType == CM_SCACHETYPE_DIRECTORY) {
2333 lock_ReleaseWrite(&scp->rw);
2335 code = cm_BeginDirOp(scp, userp, &req, CM_DIRLOCK_READ,
2336 CM_DIROP_FLAG_NONE, &dirop);
2338 /* is the directory empty? if not, CM_ERROR_NOTEMPTY */
2341 code = cm_BPlusDirIsEmpty(&dirop, &bEmpty);
2342 if (code == 0 && !bEmpty)
2343 code = CM_ERROR_NOTEMPTY;
2345 cm_EndDirOp(&dirop);
2349 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2350 (*ResultCB)->ResultStatus = status;
2351 (*ResultCB)->ResultBufferLength = 0;
2352 cm_ReleaseSCache(scp);
2353 cm_ReleaseSCache(dscp);
2354 osi_Log3(afsd_logp, "RDR_DeleteFileEntry cm_SyncOp failure scp=0x%p code=0x%x status=0x%x",
2358 lock_ObtainWrite(&scp->rw);
2362 /* Drop all locks since the file is being deleted */
2363 code = cm_SyncOp(scp, NULL, userp, &req, 0,
2364 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_LOCK);
2366 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2367 (*ResultCB)->ResultStatus = status;
2368 (*ResultCB)->ResultBufferLength = 0;
2369 lock_ReleaseWrite(&scp->rw);
2370 cm_ReleaseSCache(scp);
2371 cm_ReleaseSCache(dscp);
2372 osi_Log3(afsd_logp, "RDR_DeleteFileEntry cm_SyncOp Lock failure scp=0x%p code=0x%x status=0x%x",
2376 /* the scp is now locked and current */
2377 key = cm_GenerateKey(CM_SESSION_IFS, ProcessId, 0);
2379 code = cm_UnlockByKey(scp, key,
2380 CM_UNLOCK_FLAG_BY_FID,
2383 cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_LOCK);
2384 lock_ReleaseWrite(&scp->rw);
2386 if (scp->fileType == CM_SCACHETYPE_DIRECTORY)
2387 code = cm_RemoveDir(dscp, NULL, FileName, userp, &req);
2389 code = cm_Unlink(dscp, NULL, FileName, userp, &req);
2391 lock_ReleaseWrite(&scp->rw);
2395 (*ResultCB)->ResultStatus = 0; // We will be able to fit all the data in here
2397 (*ResultCB)->ResultBufferLength = sizeof( AFSFileDeleteResultCB);
2399 pResultCB = (AFSFileDeleteResultCB *)(*ResultCB)->ResultData;
2401 pResultCB->ParentDataVersion.QuadPart = dscp->dataVersion;
2402 osi_Log0(afsd_logp, "RDR_DeleteFileEntry SUCCESS");
2404 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2405 (*ResultCB)->ResultStatus = status;
2406 (*ResultCB)->ResultBufferLength = 0;
2407 osi_Log2(afsd_logp, "RDR_DeleteFileEntry FAILURE code=0x%x status=0x%x",
2411 cm_ReleaseSCache(dscp);
2412 cm_ReleaseSCache(scp);
2418 RDR_RenameFileEntry( IN cm_user_t *userp,
2419 IN WCHAR *SourceFileNameCounted,
2420 IN DWORD SourceFileNameLength,
2421 IN AFSFileID SourceFileId,
2422 IN AFSFileRenameCB *pRenameCB,
2424 IN DWORD ResultBufferLength,
2425 IN OUT AFSCommResult **ResultCB)
2428 AFSFileRenameResultCB *pResultCB = NULL;
2429 size_t size = sizeof(AFSCommResult) + ResultBufferLength - 1;
2430 AFSFileID SourceParentId = pRenameCB->SourceParentId;
2431 AFSFileID TargetParentId = pRenameCB->TargetParentId;
2432 WCHAR * TargetFileNameCounted = pRenameCB->TargetName;
2433 DWORD TargetFileNameLength = pRenameCB->TargetNameLength;
2434 cm_fid_t SourceParentFid;
2435 cm_fid_t TargetParentFid;
2437 cm_fid_t OrigTargetFid = {0,0,0,0,0};
2439 cm_scache_t * oldDscp;
2440 cm_scache_t * newDscp;
2442 wchar_t shortName[13];
2443 wchar_t SourceFileName[260];
2444 wchar_t TargetFileName[260];
2450 RDR_InitReq(&req, bWow64);
2452 StringCchCopyNW(SourceFileName, 260, SourceFileNameCounted, SourceFileNameLength / sizeof(WCHAR));
2453 StringCchCopyNW(TargetFileName, 260, TargetFileNameCounted, TargetFileNameLength / sizeof(WCHAR));
2455 osi_Log4(afsd_logp, "RDR_RenameFileEntry Source Parent FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
2456 SourceParentId.Cell, SourceParentId.Volume,
2457 SourceParentId.Vnode, SourceParentId.Unique);
2458 osi_Log2(afsd_logp, "... Source Name=%S Length %u", osi_LogSaveStringW(afsd_logp, SourceFileName), SourceFileNameLength);
2459 osi_Log4(afsd_logp, "... Target Parent FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
2460 TargetParentId.Cell, TargetParentId.Volume,
2461 TargetParentId.Vnode, TargetParentId.Unique);
2462 osi_Log2(afsd_logp, "... Target Name=%S Length %u", osi_LogSaveStringW(afsd_logp, TargetFileName), TargetFileNameLength);
2464 *ResultCB = (AFSCommResult *)malloc( size);
2472 pResultCB = (AFSFileRenameResultCB *)(*ResultCB)->ResultData;
2474 if (SourceFileNameLength == 0 || TargetFileNameLength == 0)
2476 osi_Log2(afsd_logp, "RDR_RenameFileEntry Invalid Name Length: src %u target %u",
2477 SourceFileNameLength, TargetFileNameLength);
2478 (*ResultCB)->ResultStatus = STATUS_INVALID_PARAMETER;
2482 SourceParentFid.cell = SourceParentId.Cell;
2483 SourceParentFid.volume = SourceParentId.Volume;
2484 SourceParentFid.vnode = SourceParentId.Vnode;
2485 SourceParentFid.unique = SourceParentId.Unique;
2486 SourceParentFid.hash = SourceParentId.Hash;
2488 TargetParentFid.cell = TargetParentId.Cell;
2489 TargetParentFid.volume = TargetParentId.Volume;
2490 TargetParentFid.vnode = TargetParentId.Vnode;
2491 TargetParentFid.unique = TargetParentId.Unique;
2492 TargetParentFid.hash = TargetParentId.Hash;
2494 code = cm_GetSCache(&SourceParentFid, NULL, &oldDscp, userp, &req);
2496 osi_Log1(afsd_logp, "RDR_RenameFileEntry cm_GetSCache source parent failed code 0x%x", code);
2497 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2498 if ( status == STATUS_INVALID_HANDLE)
2499 status = STATUS_OBJECT_PATH_INVALID;
2500 (*ResultCB)->ResultStatus = status;
2504 lock_ObtainWrite(&oldDscp->rw);
2505 code = cm_SyncOp(oldDscp, NULL, userp, &req, 0,
2506 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2508 osi_Log2(afsd_logp, "RDR_RenameFileEntry cm_SyncOp oldDscp 0x%p failed code 0x%x", oldDscp, code);
2509 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2510 if ( status == STATUS_INVALID_HANDLE)
2511 status = STATUS_OBJECT_PATH_INVALID;
2512 (*ResultCB)->ResultStatus = status;
2513 lock_ReleaseWrite(&oldDscp->rw);
2514 cm_ReleaseSCache(oldDscp);
2518 cm_SyncOpDone(oldDscp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2519 lock_ReleaseWrite(&oldDscp->rw);
2522 if (oldDscp->fileType != CM_SCACHETYPE_DIRECTORY) {
2523 osi_Log1(afsd_logp, "RDR_RenameFileEntry oldDscp 0x%p not a directory", oldDscp);
2524 (*ResultCB)->ResultStatus = STATUS_NOT_A_DIRECTORY;
2525 cm_ReleaseSCache(oldDscp);
2529 code = cm_GetSCache(&TargetParentFid, NULL, &newDscp, userp, &req);
2531 osi_Log1(afsd_logp, "RDR_RenameFileEntry cm_GetSCache target parent failed code 0x%x", code);
2532 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2533 (*ResultCB)->ResultStatus = status;
2534 cm_ReleaseSCache(oldDscp);
2538 lock_ObtainWrite(&newDscp->rw);
2539 code = cm_SyncOp(newDscp, NULL, userp, &req, 0,
2540 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2542 osi_Log2(afsd_logp, "RDR_RenameFileEntry cm_SyncOp newDscp 0x%p failed code 0x%x", newDscp, code);
2543 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2544 (*ResultCB)->ResultStatus = status;
2545 lock_ReleaseWrite(&newDscp->rw);
2546 cm_ReleaseSCache(oldDscp);
2547 cm_ReleaseSCache(newDscp);
2551 cm_SyncOpDone(newDscp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2552 lock_ReleaseWrite(&newDscp->rw);
2555 if (newDscp->fileType != CM_SCACHETYPE_DIRECTORY) {
2556 osi_Log1(afsd_logp, "RDR_RenameFileEntry newDscp 0x%p not a directory", newDscp);
2557 (*ResultCB)->ResultStatus = STATUS_NOT_A_DIRECTORY;
2558 cm_ReleaseSCache(oldDscp);
2559 cm_ReleaseSCache(newDscp);
2563 /* Obtain the original FID just for debugging purposes */
2564 code = cm_BeginDirOp( oldDscp, userp, &req, CM_DIRLOCK_READ, CM_DIROP_FLAG_NONE, &dirop);
2566 code = cm_BPlusDirLookup(&dirop, SourceFileName, &SourceFid);
2567 code = cm_BPlusDirLookup(&dirop, TargetFileName, &OrigTargetFid);
2568 cm_EndDirOp(&dirop);
2571 code = cm_Rename( oldDscp, NULL, SourceFileName,
2572 newDscp, TargetFileName, userp, &req);
2574 cm_scache_t *scp = 0;
2577 (*ResultCB)->ResultBufferLength = ResultBufferLength;
2578 dwRemaining = ResultBufferLength - sizeof( AFSFileRenameResultCB) + sizeof( AFSDirEnumEntry);
2579 (*ResultCB)->ResultStatus = 0;
2581 pResultCB->SourceParentDataVersion.QuadPart = oldDscp->dataVersion;
2582 pResultCB->TargetParentDataVersion.QuadPart = newDscp->dataVersion;
2584 osi_Log2(afsd_logp, "RDR_RenameFileEntry cm_Rename oldDscp 0x%p newDscp 0x%p SUCCESS",
2587 code = cm_BeginDirOp( newDscp, userp, &req, CM_DIRLOCK_READ, CM_DIROP_FLAG_NONE, &dirop);
2589 code = cm_BPlusDirLookup(&dirop, TargetFileName, &TargetFid);
2590 cm_EndDirOp(&dirop);
2594 osi_Log1(afsd_logp, "RDR_RenameFileEntry cm_BPlusDirLookup failed code 0x%x",
2596 (*ResultCB)->ResultStatus = STATUS_OBJECT_PATH_INVALID;
2597 cm_ReleaseSCache(oldDscp);
2598 cm_ReleaseSCache(newDscp);
2602 osi_Log4(afsd_logp, "RDR_RenameFileEntry Target FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
2603 TargetFid.cell, TargetFid.volume,
2604 TargetFid.vnode, TargetFid.unique);
2606 code = cm_GetSCache(&TargetFid, &newDscp->fid, &scp, userp, &req);
2608 osi_Log1(afsd_logp, "RDR_RenameFileEntry cm_GetSCache target failed code 0x%x", code);
2609 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2610 (*ResultCB)->ResultStatus = status;
2611 cm_ReleaseSCache(oldDscp);
2612 cm_ReleaseSCache(newDscp);
2616 /* Make sure the source vnode is current */
2617 lock_ObtainWrite(&scp->rw);
2618 code = cm_SyncOp(scp, NULL, userp, &req, 0,
2619 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2621 osi_Log2(afsd_logp, "RDR_RenameFileEntry cm_SyncOp scp 0x%p failed code 0x%x", scp, code);
2622 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2623 (*ResultCB)->ResultStatus = status;
2624 lock_ReleaseWrite(&scp->rw);
2625 cm_ReleaseSCache(oldDscp);
2626 cm_ReleaseSCache(newDscp);
2627 cm_ReleaseSCache(scp);
2631 cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2632 lock_ReleaseWrite(&scp->rw);
2634 if (cm_shortNames) {
2635 dfid.vnode = htonl(scp->fid.vnode);
2636 dfid.unique = htonl(scp->fid.unique);
2638 if (!cm_Is8Dot3(TargetFileName))
2639 cm_Gen8Dot3NameIntW(TargetFileName, &dfid, shortName, NULL);
2641 shortName[0] = '\0';
2644 RDR_PopulateCurrentEntry(&pResultCB->DirEnum, dwRemaining,
2645 newDscp, scp, userp, &req, TargetFileName, shortName,
2646 RDR_POP_FOLLOW_MOUNTPOINTS | RDR_POP_EVALUATE_SYMLINKS,
2647 0, NULL, &dwRemaining);
2648 (*ResultCB)->ResultBufferLength = ResultBufferLength - dwRemaining;
2649 cm_ReleaseSCache(scp);
2651 osi_Log0(afsd_logp, "RDR_RenameFileEntry SUCCESS");
2653 osi_Log3(afsd_logp, "RDR_RenameFileEntry cm_Rename oldDscp 0x%p newDscp 0x%p failed code 0x%x",
2654 oldDscp, newDscp, code);
2655 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2656 (*ResultCB)->ResultStatus = status;
2657 (*ResultCB)->ResultBufferLength = 0;
2660 cm_ReleaseSCache(oldDscp);
2661 cm_ReleaseSCache(newDscp);
2666 * AFS does not support cross-directory hard links but RDR_HardLinkFileEntry
2667 * is written as if AFS does. The check for cross-directory links is
2668 * implemented in cm_Link().
2670 * Windows supports optional ReplaceIfExists functionality. The AFS file
2671 * server does not. If the target name already exists and bReplaceIfExists
2672 * is true, check to see if the user has insert permission before calling
2673 * cm_Unlink() on the existing object. If the user does not have insert
2674 * permission return STATUS_ACCESS_DENIED.
2678 RDR_HardLinkFileEntry( IN cm_user_t *userp,
2679 IN WCHAR *SourceFileNameCounted,
2680 IN DWORD SourceFileNameLength,
2681 IN AFSFileID SourceFileId,
2682 IN AFSFileHardLinkCB *pHardLinkCB,
2684 IN DWORD ResultBufferLength,
2685 IN OUT AFSCommResult **ResultCB)
2688 AFSFileHardLinkResultCB *pResultCB = NULL;
2689 size_t size = sizeof(AFSCommResult) + ResultBufferLength - 1;
2690 AFSFileID SourceParentId = pHardLinkCB->SourceParentId;
2691 AFSFileID TargetParentId = pHardLinkCB->TargetParentId;
2692 WCHAR * TargetFileNameCounted = pHardLinkCB->TargetName;
2693 DWORD TargetFileNameLength = pHardLinkCB->TargetNameLength;
2694 cm_fid_t SourceParentFid;
2695 cm_fid_t TargetParentFid;
2697 cm_fid_t OrigTargetFid = {0,0,0,0,0};
2698 cm_scache_t * srcDscp = NULL;
2699 cm_scache_t * targetDscp = NULL;
2700 cm_scache_t * srcScp = NULL;
2702 wchar_t shortName[13];
2703 wchar_t SourceFileName[260];
2704 wchar_t TargetFileName[260];
2710 RDR_InitReq(&req, bWow64);
2712 StringCchCopyNW(SourceFileName, 260, SourceFileNameCounted, SourceFileNameLength / sizeof(WCHAR));
2713 StringCchCopyNW(TargetFileName, 260, TargetFileNameCounted, TargetFileNameLength / sizeof(WCHAR));
2715 osi_Log4(afsd_logp, "RDR_HardLinkFileEntry Source Parent FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
2716 SourceParentId.Cell, SourceParentId.Volume,
2717 SourceParentId.Vnode, SourceParentId.Unique);
2718 osi_Log2(afsd_logp, "... Source Name=%S Length %u", osi_LogSaveStringW(afsd_logp, SourceFileName), SourceFileNameLength);
2719 osi_Log4(afsd_logp, "... Target Parent FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
2720 TargetParentId.Cell, TargetParentId.Volume,
2721 TargetParentId.Vnode, TargetParentId.Unique);
2722 osi_Log2(afsd_logp, "... Target Name=%S Length %u", osi_LogSaveStringW(afsd_logp, TargetFileName), TargetFileNameLength);
2724 *ResultCB = (AFSCommResult *)malloc( size);
2732 pResultCB = (AFSFileHardLinkResultCB *)(*ResultCB)->ResultData;
2734 if (SourceFileNameLength == 0 || TargetFileNameLength == 0)
2736 osi_Log2(afsd_logp, "RDR_HardLinkFileEntry Invalid Name Length: src %u target %u",
2737 SourceFileNameLength, TargetFileNameLength);
2738 (*ResultCB)->ResultStatus = STATUS_INVALID_PARAMETER;
2742 SourceFid.cell = SourceFileId.Cell;
2743 SourceFid.volume = SourceFileId.Volume;
2744 SourceFid.vnode = SourceFileId.Vnode;
2745 SourceFid.unique = SourceFileId.Unique;
2746 SourceFid.hash = SourceFileId.Hash;
2748 SourceParentFid.cell = SourceParentId.Cell;
2749 SourceParentFid.volume = SourceParentId.Volume;
2750 SourceParentFid.vnode = SourceParentId.Vnode;
2751 SourceParentFid.unique = SourceParentId.Unique;
2752 SourceParentFid.hash = SourceParentId.Hash;
2754 TargetParentFid.cell = TargetParentId.Cell;
2755 TargetParentFid.volume = TargetParentId.Volume;
2756 TargetParentFid.vnode = TargetParentId.Vnode;
2757 TargetParentFid.unique = TargetParentId.Unique;
2758 TargetParentFid.hash = TargetParentId.Hash;
2760 code = cm_GetSCache(&SourceFid, NULL, &srcScp, userp, &req);
2762 osi_Log1(afsd_logp, "RDR_HardLinkFileEntry cm_GetSCache source failed code 0x%x", code);
2763 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2764 (*ResultCB)->ResultStatus = status;
2768 code = cm_GetSCache(&TargetParentFid, NULL, &targetDscp, userp, &req);
2770 osi_Log1(afsd_logp, "RDR_HardLinkFileEntry cm_GetSCache target parent failed code 0x%x", code);
2771 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2772 (*ResultCB)->ResultStatus = status;
2773 cm_ReleaseSCache(srcScp);
2777 lock_ObtainWrite(&targetDscp->rw);
2778 code = cm_SyncOp(targetDscp, NULL, userp, &req, PRSFS_INSERT,
2779 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2781 osi_Log2(afsd_logp, "RDR_HardLinkFileEntry cm_SyncOp targetDscp 0x%p failed code 0x%x", targetDscp, code);
2782 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2783 (*ResultCB)->ResultStatus = status;
2784 lock_ReleaseWrite(&targetDscp->rw);
2785 cm_ReleaseSCache(srcScp);
2786 cm_ReleaseSCache(targetDscp);
2790 cm_SyncOpDone(targetDscp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2791 lock_ReleaseWrite(&targetDscp->rw);
2793 if (targetDscp->fileType != CM_SCACHETYPE_DIRECTORY) {
2794 osi_Log1(afsd_logp, "RDR_HardLinkFileEntry targetDscp 0x%p not a directory", targetDscp);
2795 (*ResultCB)->ResultStatus = STATUS_NOT_A_DIRECTORY;
2796 cm_ReleaseSCache(srcScp);
2797 cm_ReleaseSCache(targetDscp);
2801 if ( cm_FidCmp(&SourceParentFid, &TargetParentFid) ) {
2802 code = cm_GetSCache(&SourceParentFid, NULL, &srcDscp, userp, &req);
2804 osi_Log1(afsd_logp, "RDR_HardLinkFileEntry cm_GetSCache source parent failed code 0x%x", code);
2805 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2806 if ( status == STATUS_INVALID_HANDLE)
2807 status = STATUS_OBJECT_PATH_INVALID;
2808 (*ResultCB)->ResultStatus = status;
2809 cm_ReleaseSCache(srcScp);
2810 cm_ReleaseSCache(targetDscp);
2814 lock_ObtainWrite(&srcDscp->rw);
2815 code = cm_SyncOp(srcDscp, NULL, userp, &req, 0,
2816 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2818 osi_Log2(afsd_logp, "RDR_HardLinkFileEntry cm_SyncOp srcDscp 0x%p failed code 0x%x", srcDscp, code);
2819 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2820 if ( status == STATUS_INVALID_HANDLE)
2821 status = STATUS_OBJECT_PATH_INVALID;
2822 (*ResultCB)->ResultStatus = status;
2823 lock_ReleaseWrite(&srcDscp->rw);
2824 if (srcDscp != targetDscp)
2825 cm_ReleaseSCache(srcDscp);
2826 cm_ReleaseSCache(targetDscp);
2827 cm_ReleaseSCache(srcScp);
2831 cm_SyncOpDone(srcDscp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2832 lock_ReleaseWrite(&srcDscp->rw);
2834 if (srcDscp->fileType != CM_SCACHETYPE_DIRECTORY) {
2835 osi_Log1(afsd_logp, "RDR_HardLinkFileEntry srcDscp 0x%p not a directory", srcDscp);
2836 (*ResultCB)->ResultStatus = STATUS_NOT_A_DIRECTORY;
2837 if (srcDscp != targetDscp)
2838 cm_ReleaseSCache(srcDscp);
2839 cm_ReleaseSCache(targetDscp);
2840 cm_ReleaseSCache(srcScp);
2844 srcDscp = targetDscp;
2847 /* Obtain the target FID if it exists */
2848 code = cm_BeginDirOp( targetDscp, userp, &req, CM_DIRLOCK_READ, CM_DIROP_FLAG_NONE, &dirop);
2850 code = cm_BPlusDirLookup(&dirop, TargetFileName, &OrigTargetFid);
2851 cm_EndDirOp(&dirop);
2854 if (OrigTargetFid.vnode) {
2856 /* An object exists with the target name */
2857 if (!pHardLinkCB->bReplaceIfExists) {
2858 osi_Log0(afsd_logp, "RDR_HardLinkFileEntry target name collision and !ReplaceIfExists");
2859 (*ResultCB)->ResultStatus = STATUS_OBJECT_NAME_COLLISION;
2860 if (srcDscp != targetDscp)
2861 cm_ReleaseSCache(srcDscp);
2862 cm_ReleaseSCache(targetDscp);
2863 cm_ReleaseSCache(srcScp);
2867 lock_ObtainWrite(&targetDscp->rw);
2868 code = cm_SyncOp(targetDscp, NULL, userp, &req, PRSFS_INSERT | PRSFS_DELETE,
2869 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2871 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2872 (*ResultCB)->ResultStatus = status;
2873 lock_ReleaseWrite(&srcDscp->rw);
2874 if (srcDscp != targetDscp)
2875 cm_ReleaseSCache(srcDscp);
2876 cm_ReleaseSCache(targetDscp);
2877 cm_ReleaseSCache(srcScp);
2880 cm_SyncOpDone(targetDscp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2881 lock_ReleaseWrite(&targetDscp->rw);
2883 code = cm_Unlink(targetDscp, NULL, TargetFileName, userp, &req);
2885 osi_Log1(afsd_logp, "RDR_HardLinkFileEntry cm_Unlink code 0x%x", code);
2886 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2887 (*ResultCB)->ResultStatus = status;
2888 lock_ReleaseWrite(&srcDscp->rw);
2889 if (srcDscp != targetDscp)
2890 cm_ReleaseSCache(srcDscp);
2891 cm_ReleaseSCache(targetDscp);
2892 cm_ReleaseSCache(srcScp);
2897 code = cm_Link( targetDscp, TargetFileName, srcScp, 0, userp, &req);
2900 cm_scache_t *targetScp = 0;
2903 (*ResultCB)->ResultBufferLength = ResultBufferLength;
2904 dwRemaining = ResultBufferLength - sizeof( AFSFileHardLinkResultCB) + sizeof( AFSDirEnumEntry);
2905 (*ResultCB)->ResultStatus = 0;
2907 pResultCB->SourceParentDataVersion.QuadPart = srcDscp->dataVersion;
2908 pResultCB->TargetParentDataVersion.QuadPart = targetDscp->dataVersion;
2910 osi_Log2(afsd_logp, "RDR_HardLinkFileEntry cm_Link srcDscp 0x%p targetDscp 0x%p SUCCESS",
2911 srcDscp, targetDscp);
2913 code = cm_BeginDirOp( targetDscp, userp, &req, CM_DIRLOCK_READ, CM_DIROP_FLAG_NONE, &dirop);
2915 code = cm_BPlusDirLookup(&dirop, TargetFileName, &TargetFid);
2916 cm_EndDirOp(&dirop);
2920 osi_Log1(afsd_logp, "RDR_HardLinkFileEntry cm_BPlusDirLookup failed code 0x%x",
2922 (*ResultCB)->ResultStatus = STATUS_OBJECT_PATH_INVALID;
2923 if (srcDscp != targetDscp)
2924 cm_ReleaseSCache(srcDscp);
2925 cm_ReleaseSCache(srcScp);
2926 cm_ReleaseSCache(targetDscp);
2930 osi_Log4(afsd_logp, "RDR_HardLinkFileEntry Target FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
2931 TargetFid.cell, TargetFid.volume,
2932 TargetFid.vnode, TargetFid.unique);
2934 code = cm_GetSCache(&TargetFid, &targetDscp->fid, &targetScp, userp, &req);
2936 osi_Log1(afsd_logp, "RDR_HardLinkFileEntry cm_GetSCache target failed code 0x%x", code);
2937 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2938 (*ResultCB)->ResultStatus = status;
2939 if (srcDscp != targetDscp)
2940 cm_ReleaseSCache(srcDscp);
2941 cm_ReleaseSCache(srcScp);
2942 cm_ReleaseSCache(targetDscp);
2946 /* Make sure the source vnode is current */
2947 lock_ObtainWrite(&targetScp->rw);
2948 code = cm_SyncOp(targetScp, NULL, userp, &req, 0,
2949 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2951 osi_Log2(afsd_logp, "RDR_HardLinkFileEntry cm_SyncOp scp 0x%p failed code 0x%x",
2953 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2954 (*ResultCB)->ResultStatus = status;
2955 lock_ReleaseWrite(&targetScp->rw);
2956 cm_ReleaseSCache(targetScp);
2957 if (srcDscp != targetDscp)
2958 cm_ReleaseSCache(srcDscp);
2959 cm_ReleaseSCache(srcScp);
2960 cm_ReleaseSCache(targetDscp);
2964 cm_SyncOpDone(targetScp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2965 lock_ReleaseWrite(&targetScp->rw);
2967 if (cm_shortNames) {
2968 dfid.vnode = htonl(targetScp->fid.vnode);
2969 dfid.unique = htonl(targetScp->fid.unique);
2971 if (!cm_Is8Dot3(TargetFileName))
2972 cm_Gen8Dot3NameIntW(TargetFileName, &dfid, shortName, NULL);
2974 shortName[0] = '\0';
2977 RDR_PopulateCurrentEntry(&pResultCB->DirEnum, dwRemaining,
2978 targetDscp, targetScp, userp, &req, TargetFileName, shortName,
2979 RDR_POP_FOLLOW_MOUNTPOINTS | RDR_POP_EVALUATE_SYMLINKS,
2980 0, NULL, &dwRemaining);
2981 (*ResultCB)->ResultBufferLength = ResultBufferLength - dwRemaining;
2982 cm_ReleaseSCache(targetScp);
2984 osi_Log0(afsd_logp, "RDR_HardLinkFileEntry SUCCESS");
2986 osi_Log3(afsd_logp, "RDR_HardLinkFileEntry cm_Link srcDscp 0x%p targetDscp 0x%p failed code 0x%x",
2987 srcDscp, targetDscp, code);
2988 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2989 (*ResultCB)->ResultStatus = status;
2990 (*ResultCB)->ResultBufferLength = 0;
2993 cm_ReleaseSCache(srcScp);
2994 if (srcDscp != targetDscp)
2995 cm_ReleaseSCache(srcDscp);
2996 cm_ReleaseSCache(targetDscp);
3002 RDR_CreateSymlinkEntry( IN cm_user_t *userp,
3003 IN AFSFileID FileId,
3004 IN WCHAR *FileNameCounted,
3005 IN DWORD FileNameLength,
3006 IN AFSCreateSymlinkCB *SymlinkCB,
3008 IN DWORD ResultBufferLength,
3009 IN OUT AFSCommResult **ResultCB)
3011 AFSCreateSymlinkResultCB *pResultCB = NULL;
3012 size_t size = sizeof(AFSCommResult) + ResultBufferLength - 1;
3016 cm_scache_t * dscp = NULL;
3017 afs_uint32 flags = 0;
3019 cm_scache_t * scp = NULL;
3022 wchar_t FileName[260];
3023 char *TargetPath = NULL;
3025 StringCchCopyNW(FileName, 260, FileNameCounted, FileNameLength / sizeof(WCHAR));
3026 TargetPath = cm_Utf16ToUtf8Alloc( SymlinkCB->TargetName, SymlinkCB->TargetNameLength / sizeof(WCHAR), NULL);
3028 osi_Log4( afsd_logp, "RDR_CreateSymlinkEntry parent FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
3029 SymlinkCB->ParentId.Cell, SymlinkCB->ParentId.Volume,
3030 SymlinkCB->ParentId.Vnode, SymlinkCB->ParentId.Unique);
3031 osi_Log1(afsd_logp, "... name=%S", osi_LogSaveStringW(afsd_logp, FileName));
3033 RDR_InitReq(&req, bWow64);
3034 memset(&setAttr, 0, sizeof(cm_attr_t));
3036 *ResultCB = (AFSCommResult *)malloc(size);
3038 osi_Log0(afsd_logp, "RDR_CreateSymlinkEntry out of memory");
3047 parentFid.cell = SymlinkCB->ParentId.Cell;
3048 parentFid.volume = SymlinkCB->ParentId.Volume;
3049 parentFid.vnode = SymlinkCB->ParentId.Vnode;
3050 parentFid.unique = SymlinkCB->ParentId.Unique;
3051 parentFid.hash = SymlinkCB->ParentId.Hash;
3053 code = cm_GetSCache(&parentFid, NULL, &dscp, userp, &req);
3055 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
3056 (*ResultCB)->ResultStatus = status;
3057 if ( status == STATUS_INVALID_HANDLE)
3058 status = STATUS_OBJECT_PATH_INVALID;
3059 osi_Log2(afsd_logp, "RDR_CreateSymlinkEntry cm_GetSCache ParentFID failure code=0x%x status=0x%x",
3065 lock_ObtainWrite(&dscp->rw);
3066 code = cm_SyncOp(dscp, NULL, userp, &req, 0,
3067 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
3069 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
3070 (*ResultCB)->ResultStatus = status;
3071 lock_ReleaseWrite(&dscp->rw);
3072 cm_ReleaseSCache(dscp);
3073 osi_Log3(afsd_logp, "RDR_CreateSymlinkEntry cm_SyncOp failure (1) dscp=0x%p code=0x%x status=0x%x",
3074 dscp, code, status);
3079 cm_SyncOpDone(dscp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
3080 lock_ReleaseWrite(&dscp->rw);
3082 if (dscp->fileType != CM_SCACHETYPE_DIRECTORY) {
3083 (*ResultCB)->ResultStatus = STATUS_NOT_A_DIRECTORY;
3084 cm_ReleaseSCache(dscp);
3085 osi_Log1(afsd_logp, "RDR_CreateSymlinkEntry Not a Directory dscp=0x%p",
3091 Fid.cell = FileId.Cell;
3092 Fid.volume = FileId.Volume;
3093 Fid.vnode = FileId.Vnode;
3094 Fid.unique = FileId.Unique;
3095 Fid.hash = FileId.Hash;
3097 code = cm_GetSCache(&Fid, NULL, &scp, userp, &req);
3099 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
3100 (*ResultCB)->ResultStatus = status;
3101 if ( status == STATUS_INVALID_HANDLE)
3102 status = STATUS_OBJECT_PATH_INVALID;
3103 osi_Log2(afsd_logp, "RDR_CreateSymlinkEntry cm_GetSCache FID failure code=0x%x status=0x%x",
3109 lock_ObtainWrite(&scp->rw);
3110 code = cm_SyncOp(scp, NULL, userp, &req, 0,
3111 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
3113 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
3114 (*ResultCB)->ResultStatus = status;
3115 lock_ReleaseWrite(&scp->rw);
3116 cm_ReleaseSCache(scp);
3117 osi_Log3(afsd_logp, "RDR_CreateSymlinkEntry cm_SyncOp failure (1) scp=0x%p code=0x%x status=0x%x",
3123 cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
3124 lock_ReleaseWrite(&scp->rw);
3126 /* Remove the temporary object */
3127 if (scp->fileType == CM_SCACHETYPE_DIRECTORY)
3128 code = cm_RemoveDir(dscp, NULL, FileName, userp, &req);
3130 code = cm_Unlink(dscp, NULL, FileName, userp, &req);
3131 cm_ReleaseSCache(scp);
3133 if (code && code != CM_ERROR_NOSUCHFILE) {
3134 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
3135 (*ResultCB)->ResultStatus = status;
3136 cm_ReleaseSCache(dscp);
3137 osi_Log2(afsd_logp, "RDR_CreateSymlinkEntry Unable to delete file dscp=0x%p code=0x%x",
3144 * The target path is going to be provided by the redirector in one of the following forms:
3147 * 2. Absolute path prefaced as \??\UNC\<server>\<share>\<path>
3148 * 3. Absolute path prefaced as \??\<drive-letter>:\<path>
3150 * Relative paths can be used with just slash conversion. Absolute paths must be converted.
3151 * UNC paths with a server name that matches cm_NetbiosName then the path is an AFS path and
3152 * it must be converted to /<server>/<share>/<path>. Other UNC paths must be converted to
3153 * msdfs:\\<server>\<share>\<path>. Local disk paths should be converted to
3154 * msdfs:<drive-letter>:<path>.
3157 if ( TargetPath[0] == '\\' ) {
3158 size_t nbNameLen = strlen(cm_NetbiosName);
3162 if ( strncmp(TargetPath, "\\??\\UNC\\", 8) == 0) {
3164 if (strncmp(&TargetPath[8], cm_NetbiosName, nbNameLen) == 0 &&
3165 TargetPath[8 + nbNameLen] == '\\')
3168 s = strdup(&TargetPath[8 + nbNameLen]);
3177 * non-AFS UNC path (msdfs:\\server\share\path)
3178 * strlen("msdfs:\\") == 7 + 1 for the NUL
3180 len = 8 + strlen(&TargetPath[7]);
3181 s = malloc(8 + strlen(&TargetPath[7]));
3182 StringCbCopy(s, len, "msdfs:\\");
3183 StringCbCat(s, len, &TargetPath[7]);
3188 /* non-UNC path (msdfs:<drive>:\<path> */
3189 s = strdup(&TargetPath[4]);
3195 /* relative paths require slash conversion */
3196 char *s = TargetPath;
3203 /* Use current time */
3204 setAttr.mask = CM_ATTRMASK_UNIXMODEBITS | CM_ATTRMASK_CLIENTMODTIME;
3205 setAttr.unixModeBits = 0755;
3206 setAttr.clientModTime = time(NULL);
3208 code = cm_SymLink(dscp, FileName, TargetPath, flags, &setAttr, userp, &req, &scp);
3212 wchar_t shortName[13]=L"";
3216 if (dscp->flags & CM_SCACHEFLAG_ANYWATCH) {
3217 smb_NotifyChange(FILE_ACTION_ADDED,
3218 FILE_NOTIFY_CHANGE_DIR_NAME,
3219 dscp, FileName, NULL, TRUE);
3222 (*ResultCB)->ResultStatus = 0; // We will be able to fit all the data in here
3224 (*ResultCB)->ResultBufferLength = sizeof( AFSCreateSymlinkResultCB);
3226 pResultCB = (AFSCreateSymlinkResultCB *)(*ResultCB)->ResultData;
3228 dwRemaining = ResultBufferLength - sizeof( AFSCreateSymlinkResultCB) + sizeof( AFSDirEnumEntry);
3230 lock_ObtainWrite(&dscp->rw);
3231 code = cm_SyncOp(dscp, NULL, userp, &req, 0,
3232 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
3234 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
3235 (*ResultCB)->ResultStatus = status;
3236 lock_ReleaseWrite(&dscp->rw);
3237 cm_ReleaseSCache(dscp);
3238 cm_ReleaseSCache(scp);
3239 osi_Log3(afsd_logp, "RDR_CreateSymlinkEntry cm_SyncOp failure (2) dscp=0x%p code=0x%x status=0x%x",
3240 dscp, code, status);
3244 pResultCB->ParentDataVersion.QuadPart = dscp->dataVersion;
3246 cm_SyncOpDone(dscp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
3247 lock_ReleaseWrite(&dscp->rw);
3249 if (cm_shortNames) {
3250 dfid.vnode = htonl(scp->fid.vnode);
3251 dfid.unique = htonl(scp->fid.unique);
3253 if (!cm_Is8Dot3(FileName))
3254 cm_Gen8Dot3NameIntW(FileName, &dfid, shortName, NULL);
3256 shortName[0] = '\0';
3259 code = RDR_PopulateCurrentEntry(&pResultCB->DirEnum, dwRemaining,
3260 dscp, scp, userp, &req, FileName, shortName,
3261 RDR_POP_FOLLOW_MOUNTPOINTS | RDR_POP_EVALUATE_SYMLINKS,
3262 0, NULL, &dwRemaining);
3263 cm_ReleaseSCache(scp);
3264 (*ResultCB)->ResultBufferLength = ResultBufferLength - dwRemaining;
3265 osi_Log0(afsd_logp, "RDR_CreateSymlinkEntry SUCCESS");
3267 (*ResultCB)->ResultStatus = STATUS_FILE_DELETED;
3268 (*ResultCB)->ResultBufferLength = 0;
3269 osi_Log2(afsd_logp, "RDR_CreateSymlinkEntry FAILURE code=0x%x status=0x%x",
3270 code, STATUS_FILE_DELETED);
3273 cm_ReleaseSCache(dscp);
3280 RDR_FlushFileEntry( IN cm_user_t *userp,
3281 IN AFSFileID FileId,
3283 IN DWORD ResultBufferLength,
3284 IN OUT AFSCommResult **ResultCB)
3286 cm_scache_t *scp = NULL;