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 (*ppRedirInitInfo)->GlobalReparsePointPolicy = rdr_ReparsePointPolicy;
218 if (cm_virtualCache || cm_data.bufferSize <= maxMemoryCacheSize) {
219 osi_Log0(afsd_logp, "RDR_SetInitParams Initializing Memory Extent Interface");
220 (*ppRedirInitInfo)->MemoryCacheOffset.QuadPart = (LONGLONG)cm_data.bufDataBaseAddress;
221 (*ppRedirInitInfo)->MemoryCacheLength.QuadPart = cm_data.bufEndOfData - cm_data.bufDataBaseAddress;
222 (*ppRedirInitInfo)->CacheFileNameLength = 0;
223 RDR_extentBaseAddress = cm_data.bufDataBaseAddress;
225 (*ppRedirInitInfo)->MemoryCacheOffset.QuadPart = 0;
226 (*ppRedirInitInfo)->MemoryCacheLength.QuadPart = 0;
227 (*ppRedirInitInfo)->CacheFileNameLength = (ULONG) (CachePathLen * sizeof(WCHAR));
228 err = mbstowcs((*ppRedirInitInfo)->CacheFileName, FullCachePath, (CachePathLen + 1) *sizeof(WCHAR));
230 free(*ppRedirInitInfo);
231 osi_Log0(afsd_logp, "RDR_SetInitParams Invalid Object Name");
232 return STATUS_OBJECT_NAME_INVALID;
234 RDR_extentBaseAddress = cm_data.baseAddress;
236 (*ppRedirInitInfo)->DumpFileLocationOffset = FIELD_OFFSET(AFSRedirectorInitInfo, CacheFileName) + (*ppRedirInitInfo)->CacheFileNameLength;
237 (*ppRedirInitInfo)->DumpFileLocationLength = (TempPathLen - 1) * sizeof(WCHAR);
239 err = mbstowcs((((PBYTE)(*ppRedirInitInfo)) + (*ppRedirInitInfo)->DumpFileLocationOffset),
240 FullTempPath, (TempPathLen + 1) *sizeof(WCHAR));
242 free(*ppRedirInitInfo);
243 osi_Log0(afsd_logp, "RDR_SetInitParams Invalid Object Name");
244 return STATUS_OBJECT_NAME_INVALID;
247 osi_Log0(afsd_logp,"RDR_SetInitParams Success");
251 static wchar_t cname[MAX_COMPUTERNAME_LENGTH+1] = L"";
254 RDR_GetLocalSystemUser( void)
257 cm_user_t *userp = NULL;
259 if ( cname[0] == '\0') {
260 int len = MAX_COMPUTERNAME_LENGTH+1;
261 GetComputerNameW(cname, &len);
264 unp = smb_FindUserByName(NTSID_LOCAL_SYSTEM, cname, SMB_FLAG_CREATE);
265 lock_ObtainMutex(&unp->mx);
267 unp->userp = cm_NewUser();
268 unp->flags |= SMB_USERNAMEFLAG_SID;
269 lock_ReleaseMutex(&unp->mx);
272 smb_ReleaseUsername(unp);
275 userp = cm_rootUserp;
283 RDR_UserFromCommRequest( IN AFSCommRequest *RequestBuffer)
286 return RDR_UserFromAuthGroup( &RequestBuffer->AuthGroup);
290 RDR_UserFromAuthGroup( IN GUID *pGuid)
293 cm_user_t * userp = NULL;
294 RPC_WSTR UuidString = NULL;
296 if (UuidToStringW((UUID *)pGuid, &UuidString) != RPC_S_OK)
299 if ( cname[0] == '\0') {
300 int len = MAX_COMPUTERNAME_LENGTH+1;
301 GetComputerNameW(cname, &len);
305 unp = smb_FindUserByName(UuidString, cname, SMB_FLAG_CREATE);
306 lock_ObtainMutex(&unp->mx);
308 unp->userp = cm_NewUser();
309 memcpy(&unp->userp->authgroup, pGuid, sizeof(GUID));
311 unp->flags |= SMB_USERNAMEFLAG_SID;
312 lock_ReleaseMutex(&unp->mx);
315 smb_ReleaseUsername(unp);
319 userp = cm_rootUserp;
323 osi_Log2(afsd_logp, "RDR_UserFromCommRequest Guid %S userp = 0x%p",
324 osi_LogSaveStringW(afsd_logp, UuidString),
328 RpcStringFreeW(&UuidString);
334 RDR_ReleaseUser( IN cm_user_t *userp )
336 osi_Log1(afsd_logp, "RDR_ReleaseUser userp = 0x%p", userp);
337 cm_ReleaseUser(userp);
342 * RDR_FlagScpInUse flags the scp with CM_SCACHEFLAG_RDR_IN_USE
345 RDR_FlagScpInUse( IN cm_scache_t *scp, IN BOOL bLocked )
348 lock_ObtainWrite(&scp->rw);
350 lock_AssertWrite(&scp->rw);
351 scp->flags |= CM_SCACHEFLAG_RDR_IN_USE;
354 lock_ReleaseWrite(&scp->rw);
358 * Obtain the status information for the specified object using
359 * an inline bulk status rpc. cm_BPlusDirEnumBulkStatOne() will
360 * obtain current status for the directory object, the object
361 * which is the focus of the inquiry and as many other objects
362 * in the directory for which there are not callbacks registered
363 * since we are likely to be asked for other objects in the directory.
366 RDR_BulkStatLookup( cm_scache_t *dscp,
371 cm_direnum_t * enump = NULL;
375 code = cm_BeginDirOp(dscp, userp, reqp, CM_DIRLOCK_READ, CM_DIROP_FLAG_NONE, &dirop);
377 code = cm_BPlusDirEnumerate(dscp, userp, reqp, TRUE, NULL, TRUE, &enump);
379 osi_Log1(afsd_logp, "RDR_BulkStatLookup cm_BPlusDirEnumerate failure code=0x%x",
384 osi_Log1(afsd_logp, "RDR_BulkStatLookup cm_BeginDirOp failure code=0x%x",
390 code = cm_BPlusDirEnumBulkStatOne(enump, scp);
392 osi_Log1(afsd_logp, "RDR_BulkStatLookup cm_BPlusDirEnumBulkStatOne failure code=0x%x",
395 cm_BPlusDirFreeEnumeration(enump);
402 #define RDR_POP_FOLLOW_MOUNTPOINTS 0x01
403 #define RDR_POP_EVALUATE_SYMLINKS 0x02
404 #define RDR_POP_WOW64 0x04
405 #define RDR_POP_NO_GETSTATUS 0x08
408 RDR_PopulateCurrentEntry( IN AFSDirEnumEntry * pCurrentEntry,
409 IN DWORD dwMaxEntryLength,
410 IN cm_scache_t * dscp,
411 IN cm_scache_t * scp,
412 IN cm_user_t * userp,
415 IN wchar_t * shortName,
417 IN afs_uint32 cmError,
418 OUT AFSDirEnumEntry **ppNextEntry,
419 OUT DWORD * pdwRemainingLength)
422 WCHAR * wname, *wtarget;
425 afs_uint32 code = 0, code2 = 0;
426 BOOL bMustFake = FALSE;
428 osi_Log5(afsd_logp, "RDR_PopulateCurrentEntry dscp=0x%p scp=0x%p name=%S short=%S flags=0x%x",
429 dscp, scp, osi_LogSaveStringW(afsd_logp, name),
430 osi_LogSaveStringW(afsd_logp, shortName), dwFlags);
431 osi_Log1(afsd_logp, "... maxLength=%d", dwMaxEntryLength);
433 if (dwMaxEntryLength < sizeof(AFSDirEnumEntry) + (MAX_PATH + MOUNTPOINTLEN) * sizeof(wchar_t)) {
435 *ppNextEntry = pCurrentEntry;
436 if (pdwRemainingLength)
437 *pdwRemainingLength = dwMaxEntryLength;
438 osi_Log2(afsd_logp, "RDR_PopulateCurrentEntry Not Enough Room for Entry %d < %d",
439 dwMaxEntryLength, sizeof(AFSDirEnumEntry) + (MAX_PATH + MOUNTPOINTLEN) * sizeof(wchar_t));
440 return CM_ERROR_TOOBIG;
448 dwEntryLength = sizeof(AFSDirEnumEntry);
450 lock_ObtainWrite(&scp->rw);
451 if (dwFlags & RDR_POP_NO_GETSTATUS) {
452 if (!cm_HaveCallback(scp))
455 #ifdef AFS_FREELANCE_CLIENT
456 if (scp->fid.cell == AFS_FAKE_ROOT_CELL_ID && scp->fid.volume == AFS_FAKE_ROOT_VOL_ID) {
458 * If the FID is from the Freelance Local Root always perform
459 * a single item status check.
461 code = cm_SyncOp( scp, NULL, userp, reqp, 0,
462 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
464 lock_ReleaseWrite(&scp->rw);
465 osi_Log2(afsd_logp, "RDR_PopulateCurrentEntry cm_SyncOp failed for scp=0x%p code=0x%x",
473 * For non-Freelance objects, check to see if we have current
474 * status information. If not, perform a bulk status lookup of multiple
475 * entries in order to reduce the number of RPCs issued to the file server.
477 if (cm_EAccesFindEntry(userp, &scp->fid))
479 else if (!cm_HaveCallback(scp)) {
480 lock_ReleaseWrite(&scp->rw);
481 code = RDR_BulkStatLookup(dscp, scp, userp, reqp);
483 osi_Log2(afsd_logp, "RDR_PopulateCurrentEntry RDR_BulkStatLookup failed for scp=0x%p code=0x%x",
487 lock_ObtainWrite(&scp->rw);
489 * RDR_BulkStatLookup can succeed but it may be the case that there
490 * still is not valid status info. If we get this far, generate fake
493 if (!cm_HaveCallback(scp))
499 /* Populate the error code */
500 smb_MapNTError(cmError, &pCurrentEntry->NTStatus, TRUE);
502 /* Populate the real or fake data */
503 pCurrentEntry->FileId.Cell = scp->fid.cell;
504 pCurrentEntry->FileId.Volume = scp->fid.volume;
505 pCurrentEntry->FileId.Vnode = scp->fid.vnode;
506 pCurrentEntry->FileId.Unique = scp->fid.unique;
507 pCurrentEntry->FileId.Hash = scp->fid.hash;
509 pCurrentEntry->FileType = scp->fileType;
511 pCurrentEntry->DataVersion.QuadPart = scp->dataVersion;
513 if (scp->fid.cell==AFS_FAKE_ROOT_CELL_ID &&
514 scp->fid.volume==AFS_FAKE_ROOT_VOL_ID) {
515 cm_LargeSearchTimeFromUnixTime(&ft, MAX_AFS_UINT32);
517 cm_LargeSearchTimeFromUnixTime(&ft, scp->cbExpires);
519 pCurrentEntry->Expiration.LowPart = ft.dwLowDateTime;
520 pCurrentEntry->Expiration.HighPart = ft.dwHighDateTime;
523 /* 1969-12-31 23:59:59 +00 */
524 ft.dwHighDateTime = 0x19DB200;
525 ft.dwLowDateTime = 0x5BB78980;
527 cm_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime);
528 pCurrentEntry->CreationTime.LowPart = ft.dwLowDateTime;
529 pCurrentEntry->CreationTime.HighPart = ft.dwHighDateTime;
530 pCurrentEntry->LastAccessTime = pCurrentEntry->CreationTime;
531 pCurrentEntry->LastWriteTime = pCurrentEntry->CreationTime;
532 pCurrentEntry->ChangeTime = pCurrentEntry->CreationTime;
534 pCurrentEntry->EndOfFile = scp->length;
535 pCurrentEntry->AllocationSize = scp->length;
538 switch (scp->fileType) {
539 case CM_SCACHETYPE_DIRECTORY:
540 pCurrentEntry->FileAttributes = SMB_ATTR_DIRECTORY;
542 case CM_SCACHETYPE_MOUNTPOINT:
543 case CM_SCACHETYPE_INVALID:
544 case CM_SCACHETYPE_DFSLINK:
545 pCurrentEntry->FileAttributes = SMB_ATTR_DIRECTORY | SMB_ATTR_REPARSE_POINT;
547 case CM_SCACHETYPE_SYMLINK:
548 if (cm_TargetPerceivedAsDirectory(scp->mountPointStringp))
549 pCurrentEntry->FileAttributes = SMB_ATTR_DIRECTORY | SMB_ATTR_REPARSE_POINT;
551 pCurrentEntry->FileAttributes = SMB_ATTR_REPARSE_POINT;
554 /* if we get here we either have a normal file
555 * or we have a file for which we have never
556 * received status info. In this case, we can
557 * check the even/odd value of the entry's vnode.
558 * odd means it is to be treated as a directory
559 * and even means it is to be treated as a file.
561 if (scp->fid.vnode & 0x1)
562 pCurrentEntry->FileAttributes = SMB_ATTR_DIRECTORY;
564 pCurrentEntry->FileAttributes = SMB_ATTR_NORMAL;
567 pCurrentEntry->FileAttributes = RDR_ExtAttributes(scp);
568 pCurrentEntry->EaSize = 0;
569 pCurrentEntry->Links = scp->linkCount;
571 len = wcslen(shortName);
572 wcsncpy(pCurrentEntry->ShortName, shortName, len);
573 pCurrentEntry->ShortNameLength = (CCHAR)(len * sizeof(WCHAR));
575 pCurrentEntry->FileNameOffset = sizeof(AFSDirEnumEntry);
577 wname = (WCHAR *)((PBYTE)pCurrentEntry + pCurrentEntry->FileNameOffset);
578 wcsncpy(wname, name, len);
579 pCurrentEntry->FileNameLength = (ULONG)(sizeof(WCHAR) * len);
581 osi_Log3(afsd_logp, "RDR_PopulateCurrentEntry scp=0x%p fileType=%d dv=%u",
582 scp, scp->fileType, (afs_uint32)scp->dataVersion);
584 if (!(dwFlags & RDR_POP_NO_GETSTATUS))
585 cm_SyncOpDone( scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
587 pCurrentEntry->TargetNameOffset = 0;
588 pCurrentEntry->TargetNameLength = 0;
589 if (!(dwFlags & RDR_POP_NO_GETSTATUS) && cm_HaveCallback(scp)) {
590 switch (scp->fileType) {
591 case CM_SCACHETYPE_MOUNTPOINT:
593 if ((code2 = cm_ReadMountPoint(scp, userp, reqp)) == 0) {
594 cm_scache_t *targetScp = NULL;
596 pCurrentEntry->TargetNameOffset = pCurrentEntry->FileNameOffset + pCurrentEntry->FileNameLength;
597 len = strlen(scp->mountPointStringp);
598 wtarget = (WCHAR *)((PBYTE)pCurrentEntry + pCurrentEntry->TargetNameOffset);
601 cch = MultiByteToWideChar( CP_UTF8, 0, scp->mountPointStringp,
604 len * sizeof(WCHAR));
606 mbstowcs(wtarget, scp->mountPointStringp, len);
608 pCurrentEntry->TargetNameLength = (ULONG)(sizeof(WCHAR) * len);
610 if (dwFlags & RDR_POP_FOLLOW_MOUNTPOINTS) {
611 code2 = cm_FollowMountPoint(scp, dscp, userp, reqp, &targetScp);
613 pCurrentEntry->TargetFileId.Cell = targetScp->fid.cell;
614 pCurrentEntry->TargetFileId.Volume = targetScp->fid.volume;
615 pCurrentEntry->TargetFileId.Vnode = targetScp->fid.vnode;
616 pCurrentEntry->TargetFileId.Unique = targetScp->fid.unique;
617 pCurrentEntry->TargetFileId.Hash = targetScp->fid.hash;
619 osi_Log4(afsd_logp, "RDR_PopulateCurrentEntry target FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
620 pCurrentEntry->TargetFileId.Cell, pCurrentEntry->TargetFileId.Volume,
621 pCurrentEntry->TargetFileId.Vnode, pCurrentEntry->TargetFileId.Unique);
623 cm_ReleaseSCache(targetScp);
625 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 if (scp->mountPointStringp[0]) {
649 size_t wtarget_len = 0;
651 len = strlen(scp->mountPointStringp) + 1;
652 mp = strdup(scp->mountPointStringp);
654 for (s=mp; *s; s++) {
659 if (strncmp("msdfs:", mp, 6) == 0) {
664 if ( mp[offset + 1] == ':' && mp[offset] != '\\') {
665 /* Local drive letter. Must return <drive>:\<path> */
666 pCurrentEntry->FileType = CM_SCACHETYPE_DFSLINK;
667 wtarget_len = len - offset;
669 cch = MultiByteToWideChar( CP_UTF8, 0, &mp[offset],
670 wtarget_len * sizeof(char),
672 wtarget_len * sizeof(WCHAR));
674 mbstowcs(wtarget, &mp[offset], wtarget_len);
676 } else if (mp[offset] == '\\') {
677 size_t nbNameLen = strlen(cm_NetbiosName);
679 if ( strnicmp(&mp[offset + 1], cm_NetbiosName, nbNameLen) == 0 &&
680 mp[offset + nbNameLen + 1] == '\\')
683 pCurrentEntry->FileType = CM_SCACHETYPE_SYMLINK;
684 wtarget_len = len - offset;
686 cch = MultiByteToWideChar( CP_UTF8, 0, &mp[offset],
687 wtarget_len * sizeof(char),
689 wtarget_len * sizeof(WCHAR));
691 mbstowcs(wtarget, &mp[offset], wtarget_len);
693 } else if ( mp[offset + 1] == '\\' &&
694 strnicmp(&mp[offset + 2], cm_NetbiosName, strlen(cm_NetbiosName)) == 0 &&
695 mp[offset + nbNameLen + 2] == '\\')
698 pCurrentEntry->FileType = CM_SCACHETYPE_SYMLINK;
699 wtarget_len = len - offset - 1;
701 cch = MultiByteToWideChar( CP_UTF8, 0, &mp[offset + 1],
702 wtarget_len * sizeof(char),
704 wtarget_len * sizeof(WCHAR));
706 mbstowcs(wtarget, &mp[offset + 1], wtarget_len);
710 * treat as a UNC path. Needs to be \<server>\<share\<path>
712 pCurrentEntry->FileType = CM_SCACHETYPE_DFSLINK;
714 if ( mp[offset] == '\\' && mp[offset + 1] == '\\')
717 wtarget_len = len - offset;
719 cch = MultiByteToWideChar( CP_UTF8, 0, &mp[offset],
720 wtarget_len * sizeof(char),
722 wtarget_len * sizeof(WCHAR));
724 mbstowcs(wtarget, &mp[offset], wtarget_len);
728 /* Relative AFS Symlink */
729 pCurrentEntry->FileType = CM_SCACHETYPE_SYMLINK;
730 wtarget_len = len - offset;
732 cch = MultiByteToWideChar( CP_UTF8, 0, &mp[offset],
733 wtarget_len * sizeof(char),
735 wtarget_len * sizeof(WCHAR));
737 mbstowcs(wtarget, &mp[offset], wtarget_len);
743 pCurrentEntry->TargetNameLength = (ULONG)(sizeof(WCHAR) * (wtarget_len - 1));
746 osi_Log2(afsd_logp, "RDR_PopulateCurrentEntry cm_HandleLink failed scp=0x%p code=0x%x",
755 pCurrentEntry->TargetNameOffset = 0;
756 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) |
1046 RDR_POP_EVALUATE_SYMLINKS,
1048 &pCurrentEntry, &dwMaxEntryLength);
1049 cm_ReleaseSCache(scp);
1051 code = RDR_PopulateCurrentEntryNoScp( pCurrentEntry, dwMaxEntryLength,
1052 dscp, &entryp->fid, userp, &req,
1054 cm_shortNames && cm_Is8Dot3(entryp->name) ? NULL : entryp->shortName,
1055 (bWow64 ? RDR_POP_WOW64 : 0),
1057 &pCurrentEntry, &dwMaxEntryLength);
1068 if (code || enump->next == enump->count || ResultBufferLength == 0) {
1069 cm_BPlusDirFreeEnumeration(enump);
1070 enump = (cm_direnum_t *)(ULONG_PTR)-1;
1073 if (code == 0 || code == CM_ERROR_STOPNOW) {
1074 (*ResultCB)->ResultStatus = STATUS_SUCCESS;
1075 osi_Log0(afsd_logp, "RDR_EnumerateDirectory SUCCESS");
1077 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1078 (*ResultCB)->ResultStatus = status;
1079 osi_Log2(afsd_logp, "RDR_EnumerateDirectory Failure code=0x%x status=0x%x",
1083 if (ResultBufferLength) {
1084 (*ResultCB)->ResultBufferLength = ResultBufferLength - dwMaxEntryLength;
1086 pDirEnumResp->EnumHandle = (ULONG_PTR) enump;
1087 pDirEnumResp->CurrentDataVersion.QuadPart = dscp->dataVersion;
1091 cm_ReleaseSCache(dscp);
1097 RDR_EvaluateNodeByName( IN cm_user_t *userp,
1098 IN AFSFileID ParentID,
1099 IN WCHAR *FileNameCounted,
1100 IN DWORD FileNameLength,
1101 IN BOOL CaseSensitive,
1102 IN BOOL LastComponent,
1106 IN DWORD ResultBufferLength,
1107 IN OUT AFSCommResult **ResultCB)
1109 AFSFileEvalResultCB *pEvalResultCB = NULL;
1110 AFSDirEnumEntry * pCurrentEntry;
1111 size_t size = ResultBufferLength ? sizeof(AFSCommResult) + ResultBufferLength - 1 : sizeof(AFSCommResult);
1112 afs_uint32 code = 0;
1113 cm_scache_t * scp = NULL;
1114 cm_scache_t * dscp = NULL;
1119 WCHAR * wszName = NULL;
1122 wchar_t FileName[260];
1123 afs_uint32 lookupFlags;
1125 StringCchCopyNW(FileName, 260, FileNameCounted, FileNameLength / sizeof(WCHAR));
1127 RDR_InitReq(&req, bWow64);
1129 osi_Log4(afsd_logp, "RDR_EvaluateNodeByName parent FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
1130 ParentID.Cell, ParentID.Volume, ParentID.Vnode, ParentID.Unique);
1132 /* Allocate enough room to add a volume prefix if necessary */
1133 cbName = FileNameLength + (CM_PREFIX_VOL_CCH + 64) * sizeof(WCHAR);
1134 wszName = malloc(cbName);
1136 osi_Log0(afsd_logp, "RDR_EvaluateNodeByName Out of Memory");
1139 StringCbCopyNW(wszName, cbName, FileName, FileNameLength);
1140 osi_Log1(afsd_logp, "... name=%S", osi_LogSaveStringW(afsd_logp, wszName));
1142 *ResultCB = (AFSCommResult *)malloc(size);
1144 osi_Log0(afsd_logp, "RDR_EvaluateNodeByName Out of Memory");
1149 memset(*ResultCB, 0, size);
1150 (*ResultCB)->ResultBufferLength = 0;
1151 dwRemaining = ResultBufferLength;
1152 if (ResultBufferLength >= sizeof( AFSFileEvalResultCB)) {
1153 pEvalResultCB = (AFSFileEvalResultCB *)&(*ResultCB)->ResultData;
1154 pCurrentEntry = &pEvalResultCB->DirEnum;
1155 dwRemaining -= (sizeof( AFSFileEvalResultCB) - sizeof( AFSDirEnumEntry));
1158 if (ParentID.Cell != 0) {
1159 parentFid.cell = ParentID.Cell;
1160 parentFid.volume = ParentID.Volume;
1161 parentFid.vnode = ParentID.Vnode;
1162 parentFid.unique = ParentID.Unique;
1163 parentFid.hash = ParentID.Hash;
1165 code = cm_GetSCache(&parentFid, NULL, &dscp, userp, &req);
1167 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1168 (*ResultCB)->ResultStatus = status;
1169 if ( status == STATUS_INVALID_HANDLE)
1170 status = STATUS_OBJECT_PATH_INVALID;
1171 osi_Log2(afsd_logp, "RDR_EvaluateNodeByName cm_GetSCache parentFID failure code=0x%x status=0x%x",
1177 (*ResultCB)->ResultStatus = STATUS_OBJECT_NAME_INVALID;
1178 osi_Log0(afsd_logp, "RDR_EvaluateNodeByName Object Name Invalid - Cell = 0");
1182 /* get the directory size */
1183 lock_ObtainWrite(&dscp->rw);
1184 code = cm_SyncOp(dscp, NULL, userp, &req, 0,
1185 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1187 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1188 (*ResultCB)->ResultStatus = status;
1189 lock_ReleaseWrite(&dscp->rw);
1190 cm_ReleaseSCache(dscp);
1191 osi_Log3(afsd_logp, "RDR_EvaluateNodeByName cm_SyncOp failure dscp=0x%p code=0x%x status=0x%x",
1192 dscp, code, status);
1196 cm_SyncOpDone(dscp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1197 lock_ReleaseWrite(&dscp->rw);
1199 if (dscp->fileType != CM_SCACHETYPE_DIRECTORY) {
1200 (*ResultCB)->ResultStatus = STATUS_NOT_A_DIRECTORY;
1201 cm_ReleaseSCache(dscp);
1202 osi_Log1(afsd_logp, "RDR_EvaluateNodeByName Not a Directory dscp=0x%p",
1208 lookupFlags = CM_FLAG_NOMOUNTCHASE;
1210 if ( !LastComponent )
1211 lookupFlags |= CM_FLAG_CHECKPATH;
1212 code = cm_Lookup(dscp, wszName, lookupFlags, userp, &req, &scp);
1214 if (!CaseSensitive &&
1215 (code == CM_ERROR_NOSUCHPATH || code == CM_ERROR_NOSUCHFILE || code == CM_ERROR_BPLUS_NOMATCH)) {
1216 lookupFlags |= CM_FLAG_CASEFOLD;
1217 code = cm_Lookup(dscp, wszName, lookupFlags, userp, &req, &scp);
1220 if ((code == CM_ERROR_NOSUCHPATH || code == CM_ERROR_NOSUCHFILE || code == CM_ERROR_BPLUS_NOMATCH) &&
1221 dscp == cm_data.rootSCachep) {
1223 if (wcschr(wszName, '%') != NULL || wcschr(wszName, '#') != NULL) {
1225 * A volume reference: <cell>{%,#}<volume> -> @vol:<cell>{%,#}<volume>
1227 StringCchCopyNW(wszName, cbName, _C(CM_PREFIX_VOL), CM_PREFIX_VOL_CCH);
1228 StringCbCatNW(wszName, cbName, FileName, FileNameLength);
1231 code = cm_EvaluateVolumeReference(wszName, CM_FLAG_CHECKPATH, userp, &req, &scp);
1233 #ifdef AFS_FREELANCE_CLIENT
1234 else if (dscp->fid.cell == AFS_FAKE_ROOT_CELL_ID && dscp->fid.volume == AFS_FAKE_ROOT_VOL_ID &&
1235 dscp->fid.vnode == 1 && dscp->fid.unique == 1) {
1237 * If this is the Freelance volume root directory then treat unrecognized
1238 * names as cell names and attempt to find the appropriate "root.cell".
1240 StringCchCopyNW(wszName, cbName, _C(CM_PREFIX_VOL), CM_PREFIX_VOL_CCH);
1241 if (FileName[0] == L'.') {
1242 StringCbCatNW(wszName, cbName, &FileName[1], FileNameLength);
1243 StringCbCatNW(wszName, cbName, L"%", sizeof(WCHAR));
1245 StringCbCatNW(wszName, cbName, FileName, FileNameLength);
1246 StringCbCatNW(wszName, cbName, L"#", sizeof(WCHAR));
1248 StringCbCatNW(wszName, cbName, L"root.cell", 9 * sizeof(WCHAR));
1251 code = cm_EvaluateVolumeReference(wszName, CM_FLAG_CHECKPATH, userp, &req, &scp);
1256 if (code == 0 && scp) {
1257 wchar_t shortName[13]=L"";
1259 if (!cm_shortNames) {
1260 shortName[0] = L'\0';
1262 cm_Gen8Dot3VolNameW(scp->fid.cell, scp->fid.volume, shortName, NULL);
1263 } else if (!cm_Is8Dot3(wszName)) {
1266 dfid.vnode = htonl(scp->fid.vnode);
1267 dfid.unique = htonl(scp->fid.unique);
1269 cm_Gen8Dot3NameIntW(FileName, &dfid, shortName, NULL);
1271 shortName[0] = L'\0';
1274 code = RDR_PopulateCurrentEntry(pCurrentEntry, dwRemaining,
1275 dscp, scp, userp, &req,
1276 FileName, shortName,
1277 (bWow64 ? RDR_POP_WOW64 : 0) |
1278 (bNoFollow ? 0 : RDR_POP_FOLLOW_MOUNTPOINTS) |
1279 RDR_POP_EVALUATE_SYMLINKS,
1280 0, NULL, &dwRemaining);
1282 RDR_FlagScpInUse( scp, FALSE );
1283 cm_ReleaseSCache(scp);
1286 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1287 (*ResultCB)->ResultStatus = status;
1288 osi_Log2(afsd_logp, "RDR_EvaluateNodeByName FAILURE code=0x%x status=0x%x",
1291 pEvalResultCB->ParentDataVersion.QuadPart = dscp->dataVersion;
1292 (*ResultCB)->ResultStatus = STATUS_SUCCESS;
1293 (*ResultCB)->ResultBufferLength = ResultBufferLength - dwRemaining;
1294 osi_Log0(afsd_logp, "RDR_EvaluateNodeByName SUCCESS");
1297 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1298 (*ResultCB)->ResultStatus = status;
1299 osi_Log2(afsd_logp, "RDR_EvaluateNodeByName FAILURE code=0x%x status=0x%x",
1302 (*ResultCB)->ResultStatus = STATUS_NO_SUCH_FILE;
1303 osi_Log0(afsd_logp, "RDR_EvaluateNodeByName No Such File");
1305 cm_ReleaseSCache(dscp);
1312 RDR_EvaluateNodeByID( IN cm_user_t *userp,
1313 IN AFSFileID ParentID, /* not used */
1314 IN AFSFileID SourceID,
1318 IN DWORD ResultBufferLength,
1319 IN OUT AFSCommResult **ResultCB)
1321 AFSFileEvalResultCB *pEvalResultCB = NULL;
1322 AFSDirEnumEntry * pCurrentEntry = NULL;
1323 size_t size = ResultBufferLength ? sizeof(AFSCommResult) + ResultBufferLength - 1 : sizeof(AFSCommResult);
1324 afs_uint32 code = 0;
1325 cm_scache_t * scp = NULL;
1326 cm_scache_t * dscp = NULL;
1333 osi_Log4(afsd_logp, "RDR_EvaluateNodeByID source FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
1334 SourceID.Cell, SourceID.Volume, SourceID.Vnode, SourceID.Unique);
1335 osi_Log4(afsd_logp, "... parent FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
1336 ParentID.Cell, ParentID.Volume, ParentID.Vnode, ParentID.Unique);
1338 *ResultCB = (AFSCommResult *)malloc(size);
1340 osi_Log0(afsd_logp, "RDR_EvaluateNodeByID Out of Memory");
1344 memset(*ResultCB, 0, size);
1345 (*ResultCB)->ResultBufferLength = 0;
1346 dwRemaining = ResultBufferLength;
1347 if (ResultBufferLength >= sizeof( AFSFileEvalResultCB)) {
1348 pEvalResultCB = (AFSFileEvalResultCB *)&(*ResultCB)->ResultData;
1349 pCurrentEntry = &pEvalResultCB->DirEnum;
1350 dwRemaining -= (sizeof( AFSFileEvalResultCB) - sizeof( AFSDirEnumEntry));
1353 RDR_InitReq(&req, bWow64);
1355 if (SourceID.Cell != 0) {
1356 cm_SetFid(&Fid, SourceID.Cell, SourceID.Volume, SourceID.Vnode, SourceID.Unique);
1357 code = cm_GetSCache(&Fid, NULL, &scp, userp, &req);
1359 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1360 (*ResultCB)->ResultStatus = status;
1361 osi_Log2(afsd_logp, "RDR_EvaluateNodeByID cm_GetSCache SourceFID failure code=0x%x status=0x%x",
1366 (*ResultCB)->ResultStatus = STATUS_OBJECT_NAME_INVALID;
1367 osi_Log0(afsd_logp, "RDR_EvaluateNodeByID Object Name Invalid - Cell = 0");
1371 if (ParentID.Cell != 0) {
1372 cm_SetFid(&parentFid, ParentID.Cell, ParentID.Volume, ParentID.Vnode, ParentID.Unique);
1373 code = cm_GetSCache(&parentFid, NULL, &dscp, userp, &req);
1375 cm_ReleaseSCache(scp);
1376 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1377 if ( status == STATUS_INVALID_HANDLE)
1378 status = STATUS_OBJECT_PATH_INVALID;
1379 (*ResultCB)->ResultStatus = status;
1380 osi_Log2(afsd_logp, "RDR_EvaluateNodeByID cm_GetSCache parentFID failure code=0x%x status=0x%x",
1384 } else if (SourceID.Vnode == 1) {
1386 cm_HoldSCache(dscp);
1387 } else if (scp->parentVnode) {
1388 cm_SetFid(&parentFid, SourceID.Cell, SourceID.Volume, scp->parentVnode, scp->parentUnique);
1389 code = cm_GetSCache(&parentFid, NULL, &dscp, userp, &req);
1391 cm_ReleaseSCache(scp);
1392 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1393 if ( status == STATUS_INVALID_HANDLE)
1394 status = STATUS_OBJECT_PATH_INVALID;
1395 (*ResultCB)->ResultStatus = status;
1396 osi_Log2(afsd_logp, "RDR_EvaluateNodeByID cm_GetSCache parentFID failure code=0x%x status=0x%x",
1401 (*ResultCB)->ResultStatus = STATUS_OBJECT_PATH_INVALID;
1402 osi_Log0(afsd_logp, "RDR_EvaluateNodeByID Object Path Invalid - Unknown Parent");
1406 /* Make sure the directory is current */
1407 lock_ObtainWrite(&dscp->rw);
1408 code = cm_SyncOp(dscp, NULL, userp, &req, 0,
1409 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1411 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1412 (*ResultCB)->ResultStatus = status;
1413 lock_ReleaseWrite(&dscp->rw);
1414 cm_ReleaseSCache(dscp);
1415 cm_ReleaseSCache(scp);
1416 osi_Log3(afsd_logp, "RDR_EvaluateNodeByID cm_SyncOp failure dscp=0x%p code=0x%x status=0x%x",
1417 dscp, code, status);
1421 cm_SyncOpDone(dscp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1422 lock_ReleaseWrite(&dscp->rw);
1424 if (dscp->fileType != CM_SCACHETYPE_DIRECTORY) {
1425 (*ResultCB)->ResultStatus = STATUS_NOT_A_DIRECTORY;
1426 cm_ReleaseSCache(dscp);
1427 cm_ReleaseSCache(scp);
1428 osi_Log1(afsd_logp, "RDR_EvaluateNodeByID Not a Directory dscp=0x%p", dscp);
1432 code = RDR_PopulateCurrentEntry(pCurrentEntry, dwRemaining,
1433 dscp, scp, userp, &req, NULL, NULL,
1434 (bWow64 ? RDR_POP_WOW64 : 0) |
1435 (bNoFollow ? 0 : RDR_POP_FOLLOW_MOUNTPOINTS) |
1436 RDR_POP_EVALUATE_SYMLINKS,
1437 0, NULL, &dwRemaining);
1440 RDR_FlagScpInUse( scp, FALSE );
1441 cm_ReleaseSCache(scp);
1442 cm_ReleaseSCache(dscp);
1445 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1446 (*ResultCB)->ResultStatus = status;
1447 osi_Log2(afsd_logp, "RDR_EvaluateNodeByID FAILURE code=0x%x status=0x%x",
1450 pEvalResultCB->ParentDataVersion.QuadPart = dscp->dataVersion;
1452 (*ResultCB)->ResultStatus = STATUS_SUCCESS;
1453 (*ResultCB)->ResultBufferLength = ResultBufferLength - dwRemaining;
1454 osi_Log0(afsd_logp, "RDR_EvaluateNodeByID SUCCESS");
1460 RDR_CreateFileEntry( IN cm_user_t *userp,
1461 IN WCHAR *FileNameCounted,
1462 IN DWORD FileNameLength,
1463 IN AFSFileCreateCB *CreateCB,
1466 IN DWORD ResultBufferLength,
1467 IN OUT AFSCommResult **ResultCB)
1469 AFSFileCreateResultCB *pResultCB = NULL;
1470 size_t size = sizeof(AFSCommResult) + ResultBufferLength - 1;
1473 cm_scache_t * dscp = NULL;
1474 afs_uint32 flags = 0;
1476 cm_scache_t * scp = NULL;
1479 wchar_t FileName[260];
1481 StringCchCopyNW(FileName, 260, FileNameCounted, FileNameLength / sizeof(WCHAR));
1483 osi_Log4(afsd_logp, "RDR_CreateFileEntry parent FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
1484 CreateCB->ParentId.Cell, CreateCB->ParentId.Volume,
1485 CreateCB->ParentId.Vnode, CreateCB->ParentId.Unique);
1486 osi_Log1(afsd_logp, "... name=%S", osi_LogSaveStringW(afsd_logp, FileName));
1488 RDR_InitReq(&req, bWow64);
1489 memset(&setAttr, 0, sizeof(cm_attr_t));
1491 *ResultCB = (AFSCommResult *)malloc(size);
1493 osi_Log0(afsd_logp, "RDR_CreateFileEntry out of memory");
1501 parentFid.cell = CreateCB->ParentId.Cell;
1502 parentFid.volume = CreateCB->ParentId.Volume;
1503 parentFid.vnode = CreateCB->ParentId.Vnode;
1504 parentFid.unique = CreateCB->ParentId.Unique;
1505 parentFid.hash = CreateCB->ParentId.Hash;
1507 code = cm_GetSCache(&parentFid, NULL, &dscp, userp, &req);
1509 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1510 (*ResultCB)->ResultStatus = status;
1511 if ( status == STATUS_INVALID_HANDLE)
1512 status = STATUS_OBJECT_PATH_INVALID;
1513 osi_Log2(afsd_logp, "RDR_CreateFileEntry cm_GetSCache ParentFID failure code=0x%x status=0x%x",
1518 lock_ObtainWrite(&dscp->rw);
1519 code = cm_SyncOp(dscp, NULL, userp, &req, 0,
1520 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1522 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1523 (*ResultCB)->ResultStatus = status;
1524 lock_ReleaseWrite(&dscp->rw);
1525 cm_ReleaseSCache(dscp);
1526 osi_Log3(afsd_logp, "RDR_CreateFileEntry cm_SyncOp failure (1) dscp=0x%p code=0x%x status=0x%x",
1527 dscp, code, status);
1531 cm_SyncOpDone(dscp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1532 lock_ReleaseWrite(&dscp->rw);
1534 if (dscp->fileType != CM_SCACHETYPE_DIRECTORY) {
1535 (*ResultCB)->ResultStatus = STATUS_NOT_A_DIRECTORY;
1536 cm_ReleaseSCache(dscp);
1537 osi_Log1(afsd_logp, "RDR_CreateFileEntry Not a Directory dscp=0x%p",
1542 /* Use current time */
1543 setAttr.mask = CM_ATTRMASK_CLIENTMODTIME;
1544 setAttr.clientModTime = time(NULL);
1546 if (CreateCB->FileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
1547 if (smb_unixModeDefaultDir) {
1548 setAttr.mask |= CM_ATTRMASK_UNIXMODEBITS;
1549 setAttr.unixModeBits = smb_unixModeDefaultDir;
1550 if (CreateCB->FileAttributes & FILE_ATTRIBUTE_READONLY)
1551 setAttr.unixModeBits &= ~0222; /* disable the write bits */
1554 code = cm_MakeDir(dscp, FileName, flags, &setAttr, userp, &req, &scp);
1556 if (smb_unixModeDefaultFile) {
1557 setAttr.mask |= CM_ATTRMASK_UNIXMODEBITS;
1558 setAttr.unixModeBits = smb_unixModeDefaultFile;
1559 if (CreateCB->FileAttributes & FILE_ATTRIBUTE_READONLY)
1560 setAttr.unixModeBits &= ~0222; /* disable the write bits */
1563 setAttr.mask |= CM_ATTRMASK_LENGTH;
1564 setAttr.length.LowPart = CreateCB->AllocationSize.LowPart;
1565 setAttr.length.HighPart = CreateCB->AllocationSize.HighPart;
1566 code = cm_Create(dscp, FileName, flags, &setAttr, &scp, userp, &req);
1569 wchar_t shortName[13]=L"";
1573 (*ResultCB)->ResultStatus = 0; // We will be able to fit all the data in here
1575 (*ResultCB)->ResultBufferLength = sizeof( AFSFileCreateResultCB);
1577 pResultCB = (AFSFileCreateResultCB *)(*ResultCB)->ResultData;
1579 dwRemaining = ResultBufferLength - sizeof( AFSFileCreateResultCB) + sizeof( AFSDirEnumEntry);
1581 lock_ObtainWrite(&dscp->rw);
1582 code = cm_SyncOp(dscp, NULL, userp, &req, 0,
1583 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1585 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1586 (*ResultCB)->ResultStatus = status;
1587 lock_ReleaseWrite(&dscp->rw);
1588 cm_ReleaseSCache(dscp);
1589 cm_ReleaseSCache(scp);
1590 osi_Log3(afsd_logp, "RDR_CreateFileEntry cm_SyncOp failure (2) dscp=0x%p code=0x%x status=0x%x",
1591 dscp, code, status);
1595 pResultCB->ParentDataVersion.QuadPart = dscp->dataVersion;
1597 cm_SyncOpDone(dscp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1598 lock_ReleaseWrite(&dscp->rw);
1600 if (cm_shortNames) {
1601 dfid.vnode = htonl(scp->fid.vnode);
1602 dfid.unique = htonl(scp->fid.unique);
1604 if (!cm_Is8Dot3(FileName))
1605 cm_Gen8Dot3NameIntW(FileName, &dfid, shortName, NULL);
1607 shortName[0] = '\0';
1610 code = RDR_PopulateCurrentEntry(&pResultCB->DirEnum, dwRemaining,
1611 dscp, scp, userp, &req, FileName, shortName,
1612 RDR_POP_FOLLOW_MOUNTPOINTS | RDR_POP_EVALUATE_SYMLINKS,
1613 0, NULL, &dwRemaining);
1616 RDR_FlagScpInUse( scp, FALSE );
1617 cm_ReleaseSCache(scp);
1618 (*ResultCB)->ResultBufferLength = ResultBufferLength - dwRemaining;
1619 osi_Log0(afsd_logp, "RDR_CreateFileEntry SUCCESS");
1621 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1622 (*ResultCB)->ResultStatus = status;
1623 (*ResultCB)->ResultBufferLength = 0;
1624 osi_Log2(afsd_logp, "RDR_CreateFileEntry FAILURE code=0x%x status=0x%x",
1628 cm_ReleaseSCache(dscp);
1634 RDR_UpdateFileEntry( IN cm_user_t *userp,
1635 IN AFSFileID FileId,
1636 IN AFSFileUpdateCB *UpdateCB,
1638 IN DWORD ResultBufferLength,
1639 IN OUT AFSCommResult **ResultCB)
1641 AFSFileUpdateResultCB *pResultCB = NULL;
1642 size_t size = sizeof(AFSCommResult) + ResultBufferLength - 1;
1646 afs_uint32 flags = 0;
1648 cm_scache_t * scp = NULL;
1649 cm_scache_t * dscp = NULL;
1651 time_t clientModTime;
1654 BOOL bScpLocked = FALSE;
1656 RDR_InitReq(&req, bWow64);
1657 memset(&setAttr, 0, sizeof(cm_attr_t));
1659 osi_Log4(afsd_logp, "RDR_UpdateFileEntry parent FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
1660 UpdateCB->ParentId.Cell, UpdateCB->ParentId.Volume,
1661 UpdateCB->ParentId.Vnode, UpdateCB->ParentId.Unique);
1662 osi_Log4(afsd_logp, "... object FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
1663 FileId.Cell, FileId.Volume,
1664 FileId.Vnode, FileId.Unique);
1666 *ResultCB = (AFSCommResult *)malloc( size);
1668 osi_Log0(afsd_logp, "RDR_UpdateFileEntry Out of Memory");
1676 parentFid.cell = UpdateCB->ParentId.Cell;
1677 parentFid.volume = UpdateCB->ParentId.Volume;
1678 parentFid.vnode = UpdateCB->ParentId.Vnode;
1679 parentFid.unique = UpdateCB->ParentId.Unique;
1680 parentFid.hash = UpdateCB->ParentId.Hash;
1682 code = cm_GetSCache(&parentFid, NULL, &dscp, userp, &req);
1684 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1685 (*ResultCB)->ResultStatus = status;
1686 if ( status == STATUS_INVALID_HANDLE)
1687 status = STATUS_OBJECT_PATH_INVALID;
1688 osi_Log2(afsd_logp, "RDR_UpdateFileEntry cm_GetSCache ParentFID failure code=0x%x status=0x%x",
1693 lock_ObtainWrite(&dscp->rw);
1694 code = cm_SyncOp(dscp, NULL, userp, &req, 0,
1695 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1697 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1698 (*ResultCB)->ResultStatus = status;
1699 lock_ReleaseWrite(&dscp->rw);
1700 cm_ReleaseSCache(dscp);
1701 osi_Log3(afsd_logp, "RDR_UpdateFileEntry cm_SyncOp failure dscp=0x%p code=0x%x status=0x%x",
1702 dscp, code, status);
1706 cm_SyncOpDone(dscp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1707 lock_ReleaseWrite(&dscp->rw);
1709 if (dscp->fileType != CM_SCACHETYPE_DIRECTORY) {
1710 (*ResultCB)->ResultStatus = STATUS_NOT_A_DIRECTORY;
1711 cm_ReleaseSCache(dscp);
1712 osi_Log1(afsd_logp, "RDR_UpdateFileEntry Not a Directory dscp=0x%p",
1717 Fid.cell = FileId.Cell;
1718 Fid.volume = FileId.Volume;
1719 Fid.vnode = FileId.Vnode;
1720 Fid.unique = FileId.Unique;
1721 Fid.hash = FileId.Hash;
1723 code = cm_GetSCache(&Fid, &dscp->fid, &scp, userp, &req);
1725 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1726 (*ResultCB)->ResultStatus = status;
1727 cm_ReleaseSCache(dscp);
1728 osi_Log2(afsd_logp, "RDR_UpdateFileEntry cm_GetSCache object FID failure code=0x%x status=0x%x",
1733 lock_ObtainWrite(&scp->rw);
1735 code = cm_SyncOp(scp, NULL, userp, &req, 0,
1736 CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_NEEDCALLBACK);
1738 lock_ReleaseWrite(&scp->rw);
1739 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1740 (*ResultCB)->ResultStatus = status;
1741 (*ResultCB)->ResultBufferLength = 0;
1742 cm_ReleaseSCache(dscp);
1743 cm_ReleaseSCache(scp);
1744 osi_Log3(afsd_logp, "RDR_UpdateFileEntry cm_SyncOp failure scp=0x%p code=0x%x status=0x%x",
1748 cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1750 if (UpdateCB->ChangeTime.QuadPart) {
1752 if (scp->fileType == CM_SCACHETYPE_FILE) {
1753 /* Do not set length and other attributes at the same time */
1754 if (scp->length.QuadPart != UpdateCB->AllocationSize.QuadPart) {
1755 osi_Log2(afsd_logp, "RDR_UpdateFileEntry Length Change 0x%x -> 0x%x",
1756 (afs_uint32)scp->length.QuadPart, (afs_uint32)UpdateCB->AllocationSize.QuadPart);
1757 setAttr.mask |= CM_ATTRMASK_LENGTH;
1758 setAttr.length.LowPart = UpdateCB->AllocationSize.LowPart;
1759 setAttr.length.HighPart = UpdateCB->AllocationSize.HighPart;
1760 lock_ReleaseWrite(&scp->rw);
1762 code = cm_SetAttr(scp, &setAttr, userp, &req);
1770 lock_ObtainWrite(&scp->rw);
1773 if ((scp->unixModeBits & 0200) && (UpdateCB->FileAttributes & FILE_ATTRIBUTE_READONLY)) {
1774 setAttr.mask |= CM_ATTRMASK_UNIXMODEBITS;
1775 setAttr.unixModeBits = scp->unixModeBits & ~0222;
1776 } else if (!(scp->unixModeBits & 0200) && !(UpdateCB->FileAttributes & FILE_ATTRIBUTE_READONLY)) {
1777 setAttr.mask |= CM_ATTRMASK_UNIXMODEBITS;
1778 setAttr.unixModeBits = scp->unixModeBits | 0222;
1782 if (UpdateCB->LastWriteTime.QuadPart) {
1783 ft.dwLowDateTime = UpdateCB->LastWriteTime.LowPart;
1784 ft.dwHighDateTime = UpdateCB->LastWriteTime.HighPart;
1786 cm_UnixTimeFromLargeSearchTime(& clientModTime, &ft);
1789 lock_ObtainWrite(&scp->rw);
1792 if (scp->clientModTime != clientModTime) {
1793 setAttr.mask |= CM_ATTRMASK_CLIENTMODTIME;
1794 setAttr.clientModTime = clientModTime;
1799 lock_ReleaseWrite(&scp->rw);
1801 code = cm_SetAttr(scp, &setAttr, userp, &req);
1808 lock_ReleaseWrite(&scp->rw);
1812 DWORD dwRemaining = ResultBufferLength - sizeof( AFSFileUpdateResultCB) + sizeof( AFSDirEnumEntry);
1814 pResultCB = (AFSFileUpdateResultCB *)(*ResultCB)->ResultData;
1816 pResultCB->ParentDataVersion.QuadPart = dscp->dataVersion;
1818 code = RDR_PopulateCurrentEntry(&pResultCB->DirEnum, dwRemaining,
1819 dscp, scp, userp, &req, NULL, NULL,
1820 RDR_POP_FOLLOW_MOUNTPOINTS | RDR_POP_EVALUATE_SYMLINKS,
1821 0, NULL, &dwRemaining);
1822 (*ResultCB)->ResultBufferLength = ResultBufferLength - dwRemaining;
1823 osi_Log0(afsd_logp, "RDR_UpdateFileEntry SUCCESS");
1825 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1826 (*ResultCB)->ResultStatus = status;
1827 (*ResultCB)->ResultBufferLength = 0;
1828 osi_Log2(afsd_logp, "RDR_UpdateFileEntry FAILURE code=0x%x status=0x%x",
1831 cm_ReleaseSCache(scp);
1832 cm_ReleaseSCache(dscp);
1838 RDR_CleanupFileEntry( IN cm_user_t *userp,
1839 IN AFSFileID FileId,
1840 IN WCHAR *FileNameCounted,
1841 IN DWORD FileNameLength,
1842 IN AFSFileCleanupCB *CleanupCB,
1844 IN BOOL bLastHandle,
1845 IN BOOL bDeleteFile,
1846 IN BOOL bUnlockFile,
1847 IN DWORD ResultBufferLength,
1848 IN OUT AFSCommResult **ResultCB)
1850 AFSFileCleanupResultCB *pResultCB = NULL;
1851 size_t size = sizeof(AFSCommResult) + ResultBufferLength - 1;
1854 afs_uint32 code = 0;
1855 afs_uint32 flags = 0;
1857 cm_scache_t * scp = NULL;
1858 cm_scache_t * dscp = NULL;
1860 time_t clientModTime;
1863 BOOL bScpLocked = FALSE;
1864 BOOL bDscpLocked = FALSE;
1865 BOOL bFlushFile = FALSE;
1868 RDR_InitReq(&req, bWow64);
1869 memset(&setAttr, 0, sizeof(cm_attr_t));
1871 osi_Log4(afsd_logp, "RDR_CleanupFileEntry parent FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
1872 CleanupCB->ParentId.Cell, CleanupCB->ParentId.Volume,
1873 CleanupCB->ParentId.Vnode, CleanupCB->ParentId.Unique);
1874 osi_Log4(afsd_logp, "... object FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
1875 FileId.Cell, FileId.Volume,
1876 FileId.Vnode, FileId.Unique);
1878 *ResultCB = (AFSCommResult *)malloc( size);
1880 osi_Log0(afsd_logp, "RDR_CleanupFileEntry Out of Memory");
1888 parentFid.cell = CleanupCB->ParentId.Cell;
1889 parentFid.volume = CleanupCB->ParentId.Volume;
1890 parentFid.vnode = CleanupCB->ParentId.Vnode;
1891 parentFid.unique = CleanupCB->ParentId.Unique;
1892 parentFid.hash = CleanupCB->ParentId.Hash;
1894 if (parentFid.cell) {
1895 code = cm_GetSCache(&parentFid, NULL, &dscp, userp, &req);
1897 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
1898 if ( status == STATUS_INVALID_HANDLE)
1899 status = STATUS_OBJECT_PATH_INVALID;
1900 (*ResultCB)->ResultStatus = status;
1901 osi_Log2(afsd_logp, "RDR_CleanupFileEntry cm_GetSCache ParentFID failure code=0x%x status=0x%x",
1906 lock_ObtainWrite(&dscp->rw);
1908 code = cm_SyncOp(dscp, NULL, userp, &req, 0,
1909 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1911 osi_Log2(afsd_logp, "RDR_CleanupFileEntry cm_SyncOp failure dscp=0x%p code=0x%x",
1917 cm_SyncOpDone(dscp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1918 lock_ReleaseWrite(&dscp->rw);
1919 bDscpLocked = FALSE;
1921 if (dscp->fileType != CM_SCACHETYPE_DIRECTORY) {
1922 (*ResultCB)->ResultStatus = STATUS_NOT_A_DIRECTORY;
1923 cm_ReleaseSCache(dscp);
1924 osi_Log1(afsd_logp, "RDR_CleanupFileEntry Not a Directory dscp=0x%p",
1931 Fid.cell = FileId.Cell;
1932 Fid.volume = FileId.Volume;
1933 Fid.vnode = FileId.Vnode;
1934 Fid.unique = FileId.Unique;
1935 Fid.hash = FileId.Hash;
1937 code = cm_GetSCache(&Fid, dscp ? &dscp->fid : NULL, &scp, userp, &req);
1939 osi_Log1(afsd_logp, "RDR_CleanupFileEntry cm_GetSCache object FID failure code=0x%x",
1944 lock_ObtainWrite(&scp->rw);
1946 code = cm_SyncOp(scp, NULL, userp, &req, 0,
1947 CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_NEEDCALLBACK);
1949 osi_Log2(afsd_logp, "RDR_CleanupFileEntry cm_SyncOp failure scp=0x%p code=0x%x",
1953 cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
1955 if (bLastHandle && (scp->fileType == CM_SCACHETYPE_FILE) &&
1956 scp->redirBufCount > 0)
1958 LARGE_INTEGER heldExtents;
1959 AFSFileExtentCB extentList[1024];
1960 DWORD extentCount = 0;
1965 heldExtents.QuadPart = 0;
1967 for ( srbp = redirq_to_cm_buf_t(scp->redirQueueT);
1969 srbp = redirq_to_cm_buf_t(osi_QPrev(&srbp->redirq)))
1971 extentList[extentCount].Flags = 0;
1972 extentList[extentCount].Length = cm_data.blockSize;
1973 extentList[extentCount].FileOffset.QuadPart = srbp->offset.QuadPart;
1974 extentList[extentCount].CacheOffset.QuadPart = srbp->datap - RDR_extentBaseAddress;
1975 lock_ObtainWrite(&buf_globalLock);
1976 srbp->redirReleaseRequested = now;
1977 lock_ReleaseWrite(&buf_globalLock);
1980 if (extentCount == 1024) {
1981 lock_ReleaseWrite(&scp->rw);
1982 code = RDR_RequestExtentRelease(&scp->fid, heldExtents, extentCount, extentList);
1984 if (code == CM_ERROR_RETRY) {
1986 * The redirector either is not holding the extents or cannot let them
1987 * go because they are otherwise in use. At the moment, do nothing.
1994 lock_ObtainWrite(&scp->rw);
1998 if (code == 0 && extentCount > 0) {
2000 lock_ReleaseWrite(&scp->rw);
2003 code = RDR_RequestExtentRelease(&scp->fid, heldExtents, extentCount, extentList);
2008 /* No longer in use by redirector */
2010 lock_ObtainWrite(&scp->rw);
2015 lock_AssertWrite(&scp->rw);
2016 scp->flags &= ~CM_SCACHEFLAG_RDR_IN_USE;
2019 /* If not a readonly object, flush dirty data and update metadata */
2020 if (!(scp->flags & CM_SCACHEFLAG_RO)) {
2021 if ((scp->fileType == CM_SCACHETYPE_FILE) && (bLastHandle || bFlushFile)) {
2022 /* Serialize with any outstanding AsyncStore operation */
2023 code = cm_SyncOp(scp, NULL, userp, &req, 0, CM_SCACHESYNC_ASYNCSTORE);
2025 cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_ASYNCSTORE);
2027 code = cm_SyncOp(scp, NULL, userp, &req, PRSFS_WRITE,
2028 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2030 * If we only have 'i' bits, then we should still be able to
2031 * set flush the file.
2033 if (code == CM_ERROR_NOACCESS && scp->creator == userp) {
2034 code = cm_SyncOp(scp, NULL, userp, &req, PRSFS_INSERT,
2035 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2039 lock_ReleaseWrite(&scp->rw);
2043 code = cm_FSync(scp, userp, &req, bScpLocked);
2046 if (bLastHandle && code)
2050 if (CleanupCB->ChangeTime.QuadPart) {
2052 if (scp->fileType == CM_SCACHETYPE_FILE) {
2053 /* Do not set length and other attributes at the same time */
2054 if (scp->length.QuadPart != CleanupCB->AllocationSize.QuadPart) {
2055 osi_Log2(afsd_logp, "RDR_CleanupFileEntry Length Change 0x%x -> 0x%x",
2056 (afs_uint32)scp->length.QuadPart, (afs_uint32)CleanupCB->AllocationSize.QuadPart);
2057 setAttr.mask |= CM_ATTRMASK_LENGTH;
2058 setAttr.length.LowPart = CleanupCB->AllocationSize.LowPart;
2059 setAttr.length.HighPart = CleanupCB->AllocationSize.HighPart;
2062 lock_ReleaseWrite(&scp->rw);
2065 code = cm_SetAttr(scp, &setAttr, userp, &req);
2073 lock_ObtainWrite(&scp->rw);
2077 if ((scp->unixModeBits & 0200) && (CleanupCB->FileAttributes & FILE_ATTRIBUTE_READONLY)) {
2078 setAttr.mask |= CM_ATTRMASK_UNIXMODEBITS;
2079 setAttr.unixModeBits = scp->unixModeBits & ~0222;
2080 } else if (!(scp->unixModeBits & 0200) && !(CleanupCB->FileAttributes & FILE_ATTRIBUTE_READONLY)) {
2081 setAttr.mask |= CM_ATTRMASK_UNIXMODEBITS;
2082 setAttr.unixModeBits = scp->unixModeBits | 0222;
2086 if (CleanupCB->LastWriteTime.QuadPart) {
2087 ft.dwLowDateTime = CleanupCB->LastWriteTime.LowPart;
2088 ft.dwHighDateTime = CleanupCB->LastWriteTime.HighPart;
2090 cm_UnixTimeFromLargeSearchTime(&clientModTime, &ft);
2091 if (scp->clientModTime != clientModTime) {
2092 setAttr.mask |= CM_ATTRMASK_CLIENTMODTIME;
2093 setAttr.clientModTime = clientModTime;
2100 lock_ReleaseWrite(&scp->rw);
2103 code = cm_SetAttr(scp, &setAttr, userp, &req);
2109 /* Now drop the lock enforcing the share access */
2110 if ( CleanupCB->FileAccess != AFS_FILE_ACCESS_NOLOCK) {
2111 unsigned int sLockType;
2112 LARGE_INTEGER LOffset, LLength;
2114 if (CleanupCB->FileAccess == AFS_FILE_ACCESS_SHARED)
2115 sLockType = LOCKING_ANDX_SHARED_LOCK;
2119 key = cm_GenerateKey(CM_SESSION_IFS, SMB_FID_QLOCK_PID, CleanupCB->Identifier);
2121 LOffset.HighPart = SMB_FID_QLOCK_HIGH;
2122 LOffset.LowPart = SMB_FID_QLOCK_LOW;
2123 LLength.HighPart = 0;
2124 LLength.LowPart = SMB_FID_QLOCK_LENGTH;
2127 lock_ObtainWrite(&scp->rw);
2131 code = cm_SyncOp(scp, NULL, userp, &req, 0, CM_SCACHESYNC_LOCK);
2134 code = cm_Unlock(scp, sLockType, LOffset, LLength, key, 0, userp, &req);
2136 cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_LOCK);
2138 if (code == CM_ERROR_RANGE_NOT_LOCKED)
2140 osi_Log3(afsd_logp, "RDR_CleanupFileEntry Range Not Locked -- FileAccess 0x%x ProcessId 0x%x HandleId 0x%x",
2141 CleanupCB->FileAccess, CleanupCB->ProcessId, CleanupCB->Identifier);
2147 if (bUnlockFile || bDeleteFile) {
2149 lock_ObtainWrite(&scp->rw);
2152 code = cm_SyncOp(scp, NULL, userp, &req, 0,
2153 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_LOCK);
2155 osi_Log2(afsd_logp, "RDR_CleanupFileEntry cm_SyncOp (2) failure scp=0x%p code=0x%x",
2160 key = cm_GenerateKey(CM_SESSION_IFS, CleanupCB->ProcessId, 0);
2162 /* the scp is now locked and current */
2163 code = cm_UnlockByKey(scp, key,
2164 bDeleteFile ? CM_UNLOCK_FLAG_BY_FID : 0,
2167 cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_LOCK);
2175 lock_ReleaseWrite(&dscp->rw);
2177 lock_ReleaseWrite(&scp->rw);
2179 if (code == 0 && dscp && bDeleteFile) {
2180 WCHAR FileName[260];
2182 StringCchCopyNW(FileName, 260, FileNameCounted, FileNameLength / sizeof(WCHAR));
2184 if (scp->fileType == CM_SCACHETYPE_DIRECTORY)
2185 code = cm_RemoveDir(dscp, NULL, FileName, userp, &req);
2187 code = cm_Unlink(dscp, NULL, FileName, userp, &req);
2191 if ( ResultBufferLength >= sizeof( AFSFileCleanupResultCB))
2193 (*ResultCB)->ResultBufferLength = sizeof( AFSFileCleanupResultCB);
2194 pResultCB = (AFSFileCleanupResultCB *)&(*ResultCB)->ResultData;
2195 pResultCB->ParentDataVersion.QuadPart = dscp ? dscp->dataVersion : 0;
2197 (*ResultCB)->ResultBufferLength = 0;
2200 (*ResultCB)->ResultStatus = 0;
2201 osi_Log0(afsd_logp, "RDR_CleanupFileEntry SUCCESS");
2203 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2204 (*ResultCB)->ResultStatus = status;
2205 osi_Log2(afsd_logp, "RDR_CleanupFileEntry FAILURE code=0x%x status=0x%x",
2210 cm_ReleaseSCache(scp);
2212 cm_ReleaseSCache(dscp);
2218 RDR_DeleteFileEntry( IN cm_user_t *userp,
2219 IN AFSFileID ParentId,
2220 IN ULONGLONG ProcessId,
2221 IN WCHAR *FileNameCounted,
2222 IN DWORD FileNameLength,
2225 IN DWORD ResultBufferLength,
2226 IN OUT AFSCommResult **ResultCB)
2229 AFSFileDeleteResultCB *pResultCB = NULL;
2230 size_t size = sizeof(AFSCommResult) + ResultBufferLength - 1;
2233 cm_scache_t * dscp = NULL;
2234 cm_scache_t * scp = NULL;
2235 afs_uint32 flags = 0;
2239 wchar_t FileName[260];
2242 StringCchCopyNW(FileName, 260, FileNameCounted, FileNameLength / sizeof(WCHAR));
2244 osi_Log4(afsd_logp, "RDR_DeleteFileEntry parent FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
2245 ParentId.Cell, ParentId.Volume,
2246 ParentId.Vnode, ParentId.Unique);
2247 osi_Log2(afsd_logp, "... name=%S checkOnly=%x",
2248 osi_LogSaveStringW(afsd_logp, FileName),
2251 RDR_InitReq(&req, bWow64);
2252 memset(&setAttr, 0, sizeof(cm_attr_t));
2254 *ResultCB = (AFSCommResult *)malloc( size);
2256 osi_Log0(afsd_logp, "RDR_DeleteFileEntry out of memory");
2264 parentFid.cell = ParentId.Cell;
2265 parentFid.volume = ParentId.Volume;
2266 parentFid.vnode = ParentId.Vnode;
2267 parentFid.unique = ParentId.Unique;
2268 parentFid.hash = ParentId.Hash;
2270 code = cm_GetSCache(&parentFid, NULL, &dscp, userp, &req);
2272 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2273 if ( status == STATUS_INVALID_HANDLE)
2274 status = STATUS_OBJECT_PATH_INVALID;
2275 (*ResultCB)->ResultStatus = status;
2276 osi_Log2(afsd_logp, "RDR_DeleteFileEntry cm_GetSCache ParentFID failure code=0x%x status=0x%x",
2281 lock_ObtainWrite(&dscp->rw);
2283 code = cm_SyncOp(dscp, NULL, userp, &req, 0,
2284 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2286 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2287 (*ResultCB)->ResultStatus = status;
2288 (*ResultCB)->ResultBufferLength = 0;
2289 lock_ReleaseWrite(&dscp->rw);
2290 cm_ReleaseSCache(dscp);
2291 osi_Log3(afsd_logp, "RDR_DeleteFileEntry cm_SyncOp failure dscp=0x%p code=0x%x status=0x%x",
2292 dscp, code, status);
2296 cm_SyncOpDone(dscp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2297 lock_ReleaseWrite(&dscp->rw);
2299 if (dscp->fileType != CM_SCACHETYPE_DIRECTORY) {
2300 (*ResultCB)->ResultStatus = STATUS_NOT_A_DIRECTORY;
2301 cm_ReleaseSCache(dscp);
2302 osi_Log1(afsd_logp, "RDR_DeleteFileEntry Not a Directory dscp=0x%p",
2307 code = cm_Lookup(dscp, FileName, 0, userp, &req, &scp);
2309 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2310 (*ResultCB)->ResultStatus = status;
2311 (*ResultCB)->ResultBufferLength = 0;
2312 cm_ReleaseSCache(dscp);
2313 osi_Log2(afsd_logp, "RDR_DeleteFileEntry cm_Lookup failure code=0x%x status=0x%x",
2318 lock_ObtainWrite(&scp->rw);
2319 code = cm_SyncOp(scp, NULL, userp, &req, PRSFS_DELETE,
2320 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2322 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2323 (*ResultCB)->ResultStatus = status;
2324 (*ResultCB)->ResultBufferLength = 0;
2325 lock_ReleaseWrite(&scp->rw);
2326 cm_ReleaseSCache(scp);
2327 cm_ReleaseSCache(dscp);
2328 osi_Log3(afsd_logp, "RDR_DeleteFileEntry cm_SyncOp failure scp=0x%p code=0x%x status=0x%x",
2333 if (scp->fileType == CM_SCACHETYPE_DIRECTORY) {
2336 lock_ReleaseWrite(&scp->rw);
2338 code = cm_BeginDirOp(scp, userp, &req, CM_DIRLOCK_READ,
2339 CM_DIROP_FLAG_NONE, &dirop);
2341 /* is the directory empty? if not, CM_ERROR_NOTEMPTY */
2344 code = cm_BPlusDirIsEmpty(&dirop, &bEmpty);
2345 if (code == 0 && !bEmpty)
2346 code = CM_ERROR_NOTEMPTY;
2348 cm_EndDirOp(&dirop);
2352 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2353 (*ResultCB)->ResultStatus = status;
2354 (*ResultCB)->ResultBufferLength = 0;
2355 cm_ReleaseSCache(scp);
2356 cm_ReleaseSCache(dscp);
2357 osi_Log3(afsd_logp, "RDR_DeleteFileEntry cm_SyncOp failure scp=0x%p code=0x%x status=0x%x",
2361 lock_ObtainWrite(&scp->rw);
2365 /* Drop all locks since the file is being deleted */
2366 code = cm_SyncOp(scp, NULL, userp, &req, 0,
2367 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_LOCK);
2369 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2370 (*ResultCB)->ResultStatus = status;
2371 (*ResultCB)->ResultBufferLength = 0;
2372 lock_ReleaseWrite(&scp->rw);
2373 cm_ReleaseSCache(scp);
2374 cm_ReleaseSCache(dscp);
2375 osi_Log3(afsd_logp, "RDR_DeleteFileEntry cm_SyncOp Lock failure scp=0x%p code=0x%x status=0x%x",
2379 /* the scp is now locked and current */
2380 key = cm_GenerateKey(CM_SESSION_IFS, ProcessId, 0);
2382 code = cm_UnlockByKey(scp, key,
2383 CM_UNLOCK_FLAG_BY_FID,
2386 cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_LOCK);
2387 lock_ReleaseWrite(&scp->rw);
2389 if (scp->fileType == CM_SCACHETYPE_DIRECTORY)
2390 code = cm_RemoveDir(dscp, NULL, FileName, userp, &req);
2392 code = cm_Unlink(dscp, NULL, FileName, userp, &req);
2394 lock_ReleaseWrite(&scp->rw);
2398 (*ResultCB)->ResultStatus = 0; // We will be able to fit all the data in here
2400 (*ResultCB)->ResultBufferLength = sizeof( AFSFileDeleteResultCB);
2402 pResultCB = (AFSFileDeleteResultCB *)(*ResultCB)->ResultData;
2404 pResultCB->ParentDataVersion.QuadPart = dscp->dataVersion;
2405 osi_Log0(afsd_logp, "RDR_DeleteFileEntry SUCCESS");
2407 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2408 (*ResultCB)->ResultStatus = status;
2409 (*ResultCB)->ResultBufferLength = 0;
2410 osi_Log2(afsd_logp, "RDR_DeleteFileEntry FAILURE code=0x%x status=0x%x",
2414 cm_ReleaseSCache(dscp);
2415 cm_ReleaseSCache(scp);
2421 RDR_RenameFileEntry( IN cm_user_t *userp,
2422 IN WCHAR *SourceFileNameCounted,
2423 IN DWORD SourceFileNameLength,
2424 IN AFSFileID SourceFileId,
2425 IN AFSFileRenameCB *pRenameCB,
2427 IN DWORD ResultBufferLength,
2428 IN OUT AFSCommResult **ResultCB)
2431 AFSFileRenameResultCB *pResultCB = NULL;
2432 size_t size = sizeof(AFSCommResult) + ResultBufferLength - 1;
2433 AFSFileID SourceParentId = pRenameCB->SourceParentId;
2434 AFSFileID TargetParentId = pRenameCB->TargetParentId;
2435 WCHAR * TargetFileNameCounted = pRenameCB->TargetName;
2436 DWORD TargetFileNameLength = pRenameCB->TargetNameLength;
2437 cm_fid_t SourceParentFid;
2438 cm_fid_t TargetParentFid;
2440 cm_fid_t OrigTargetFid = {0,0,0,0,0};
2442 cm_scache_t * oldDscp;
2443 cm_scache_t * newDscp;
2445 wchar_t shortName[13];
2446 wchar_t SourceFileName[260];
2447 wchar_t TargetFileName[260];
2453 RDR_InitReq(&req, bWow64);
2455 StringCchCopyNW(SourceFileName, 260, SourceFileNameCounted, SourceFileNameLength / sizeof(WCHAR));
2456 StringCchCopyNW(TargetFileName, 260, TargetFileNameCounted, TargetFileNameLength / sizeof(WCHAR));
2458 osi_Log4(afsd_logp, "RDR_RenameFileEntry Source Parent FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
2459 SourceParentId.Cell, SourceParentId.Volume,
2460 SourceParentId.Vnode, SourceParentId.Unique);
2461 osi_Log2(afsd_logp, "... Source Name=%S Length %u", osi_LogSaveStringW(afsd_logp, SourceFileName), SourceFileNameLength);
2462 osi_Log4(afsd_logp, "... Target Parent FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
2463 TargetParentId.Cell, TargetParentId.Volume,
2464 TargetParentId.Vnode, TargetParentId.Unique);
2465 osi_Log2(afsd_logp, "... Target Name=%S Length %u", osi_LogSaveStringW(afsd_logp, TargetFileName), TargetFileNameLength);
2467 *ResultCB = (AFSCommResult *)malloc( size);
2475 pResultCB = (AFSFileRenameResultCB *)(*ResultCB)->ResultData;
2477 if (SourceFileNameLength == 0 || TargetFileNameLength == 0)
2479 osi_Log2(afsd_logp, "RDR_RenameFileEntry Invalid Name Length: src %u target %u",
2480 SourceFileNameLength, TargetFileNameLength);
2481 (*ResultCB)->ResultStatus = STATUS_INVALID_PARAMETER;
2485 SourceParentFid.cell = SourceParentId.Cell;
2486 SourceParentFid.volume = SourceParentId.Volume;
2487 SourceParentFid.vnode = SourceParentId.Vnode;
2488 SourceParentFid.unique = SourceParentId.Unique;
2489 SourceParentFid.hash = SourceParentId.Hash;
2491 TargetParentFid.cell = TargetParentId.Cell;
2492 TargetParentFid.volume = TargetParentId.Volume;
2493 TargetParentFid.vnode = TargetParentId.Vnode;
2494 TargetParentFid.unique = TargetParentId.Unique;
2495 TargetParentFid.hash = TargetParentId.Hash;
2497 code = cm_GetSCache(&SourceParentFid, NULL, &oldDscp, userp, &req);
2499 osi_Log1(afsd_logp, "RDR_RenameFileEntry cm_GetSCache source parent failed code 0x%x", code);
2500 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2501 if ( status == STATUS_INVALID_HANDLE)
2502 status = STATUS_OBJECT_PATH_INVALID;
2503 (*ResultCB)->ResultStatus = status;
2507 lock_ObtainWrite(&oldDscp->rw);
2508 code = cm_SyncOp(oldDscp, NULL, userp, &req, 0,
2509 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2511 osi_Log2(afsd_logp, "RDR_RenameFileEntry cm_SyncOp oldDscp 0x%p failed code 0x%x", oldDscp, code);
2512 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2513 if ( status == STATUS_INVALID_HANDLE)
2514 status = STATUS_OBJECT_PATH_INVALID;
2515 (*ResultCB)->ResultStatus = status;
2516 lock_ReleaseWrite(&oldDscp->rw);
2517 cm_ReleaseSCache(oldDscp);
2521 cm_SyncOpDone(oldDscp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2522 lock_ReleaseWrite(&oldDscp->rw);
2525 if (oldDscp->fileType != CM_SCACHETYPE_DIRECTORY) {
2526 osi_Log1(afsd_logp, "RDR_RenameFileEntry oldDscp 0x%p not a directory", oldDscp);
2527 (*ResultCB)->ResultStatus = STATUS_NOT_A_DIRECTORY;
2528 cm_ReleaseSCache(oldDscp);
2532 code = cm_GetSCache(&TargetParentFid, NULL, &newDscp, userp, &req);
2534 osi_Log1(afsd_logp, "RDR_RenameFileEntry cm_GetSCache target parent failed code 0x%x", code);
2535 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2536 (*ResultCB)->ResultStatus = status;
2537 cm_ReleaseSCache(oldDscp);
2541 lock_ObtainWrite(&newDscp->rw);
2542 code = cm_SyncOp(newDscp, NULL, userp, &req, 0,
2543 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2545 osi_Log2(afsd_logp, "RDR_RenameFileEntry cm_SyncOp newDscp 0x%p failed code 0x%x", newDscp, code);
2546 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2547 (*ResultCB)->ResultStatus = status;
2548 lock_ReleaseWrite(&newDscp->rw);
2549 cm_ReleaseSCache(oldDscp);
2550 cm_ReleaseSCache(newDscp);
2554 cm_SyncOpDone(newDscp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2555 lock_ReleaseWrite(&newDscp->rw);
2558 if (newDscp->fileType != CM_SCACHETYPE_DIRECTORY) {
2559 osi_Log1(afsd_logp, "RDR_RenameFileEntry newDscp 0x%p not a directory", newDscp);
2560 (*ResultCB)->ResultStatus = STATUS_NOT_A_DIRECTORY;
2561 cm_ReleaseSCache(oldDscp);
2562 cm_ReleaseSCache(newDscp);
2566 /* Obtain the original FID just for debugging purposes */
2567 code = cm_BeginDirOp( oldDscp, userp, &req, CM_DIRLOCK_READ, CM_DIROP_FLAG_NONE, &dirop);
2569 code = cm_BPlusDirLookup(&dirop, SourceFileName, &SourceFid);
2570 code = cm_BPlusDirLookup(&dirop, TargetFileName, &OrigTargetFid);
2571 cm_EndDirOp(&dirop);
2574 code = cm_Rename( oldDscp, NULL, SourceFileName,
2575 newDscp, TargetFileName, userp, &req);
2577 cm_scache_t *scp = 0;
2580 (*ResultCB)->ResultBufferLength = ResultBufferLength;
2581 dwRemaining = ResultBufferLength - sizeof( AFSFileRenameResultCB) + sizeof( AFSDirEnumEntry);
2582 (*ResultCB)->ResultStatus = 0;
2584 pResultCB->SourceParentDataVersion.QuadPart = oldDscp->dataVersion;
2585 pResultCB->TargetParentDataVersion.QuadPart = newDscp->dataVersion;
2587 osi_Log2(afsd_logp, "RDR_RenameFileEntry cm_Rename oldDscp 0x%p newDscp 0x%p SUCCESS",
2590 code = cm_BeginDirOp( newDscp, userp, &req, CM_DIRLOCK_READ, CM_DIROP_FLAG_NONE, &dirop);
2592 code = cm_BPlusDirLookup(&dirop, TargetFileName, &TargetFid);
2593 cm_EndDirOp(&dirop);
2597 osi_Log1(afsd_logp, "RDR_RenameFileEntry cm_BPlusDirLookup failed code 0x%x",
2599 (*ResultCB)->ResultStatus = STATUS_OBJECT_PATH_INVALID;
2600 cm_ReleaseSCache(oldDscp);
2601 cm_ReleaseSCache(newDscp);
2605 osi_Log4(afsd_logp, "RDR_RenameFileEntry Target FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
2606 TargetFid.cell, TargetFid.volume,
2607 TargetFid.vnode, TargetFid.unique);
2609 code = cm_GetSCache(&TargetFid, &newDscp->fid, &scp, userp, &req);
2611 osi_Log1(afsd_logp, "RDR_RenameFileEntry cm_GetSCache target failed code 0x%x", code);
2612 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2613 (*ResultCB)->ResultStatus = status;
2614 cm_ReleaseSCache(oldDscp);
2615 cm_ReleaseSCache(newDscp);
2619 /* Make sure the source vnode is current */
2620 lock_ObtainWrite(&scp->rw);
2621 code = cm_SyncOp(scp, NULL, userp, &req, 0,
2622 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2624 osi_Log2(afsd_logp, "RDR_RenameFileEntry cm_SyncOp scp 0x%p failed code 0x%x", scp, code);
2625 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2626 (*ResultCB)->ResultStatus = status;
2627 lock_ReleaseWrite(&scp->rw);
2628 cm_ReleaseSCache(oldDscp);
2629 cm_ReleaseSCache(newDscp);
2630 cm_ReleaseSCache(scp);
2634 cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2635 lock_ReleaseWrite(&scp->rw);
2637 if (cm_shortNames) {
2638 dfid.vnode = htonl(scp->fid.vnode);
2639 dfid.unique = htonl(scp->fid.unique);
2641 if (!cm_Is8Dot3(TargetFileName))
2642 cm_Gen8Dot3NameIntW(TargetFileName, &dfid, shortName, NULL);
2644 shortName[0] = '\0';
2647 RDR_PopulateCurrentEntry(&pResultCB->DirEnum, dwRemaining,
2648 newDscp, scp, userp, &req, TargetFileName, shortName,
2649 RDR_POP_FOLLOW_MOUNTPOINTS | RDR_POP_EVALUATE_SYMLINKS,
2650 0, NULL, &dwRemaining);
2651 (*ResultCB)->ResultBufferLength = ResultBufferLength - dwRemaining;
2652 cm_ReleaseSCache(scp);
2654 osi_Log0(afsd_logp, "RDR_RenameFileEntry SUCCESS");
2656 osi_Log3(afsd_logp, "RDR_RenameFileEntry cm_Rename oldDscp 0x%p newDscp 0x%p failed code 0x%x",
2657 oldDscp, newDscp, code);
2658 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2659 (*ResultCB)->ResultStatus = status;
2660 (*ResultCB)->ResultBufferLength = 0;
2663 cm_ReleaseSCache(oldDscp);
2664 cm_ReleaseSCache(newDscp);
2669 * AFS does not support cross-directory hard links but RDR_HardLinkFileEntry
2670 * is written as if AFS does. The check for cross-directory links is
2671 * implemented in cm_Link().
2673 * Windows supports optional ReplaceIfExists functionality. The AFS file
2674 * server does not. If the target name already exists and bReplaceIfExists
2675 * is true, check to see if the user has insert permission before calling
2676 * cm_Unlink() on the existing object. If the user does not have insert
2677 * permission return STATUS_ACCESS_DENIED.
2681 RDR_HardLinkFileEntry( IN cm_user_t *userp,
2682 IN WCHAR *SourceFileNameCounted,
2683 IN DWORD SourceFileNameLength,
2684 IN AFSFileID SourceFileId,
2685 IN AFSFileHardLinkCB *pHardLinkCB,
2687 IN DWORD ResultBufferLength,
2688 IN OUT AFSCommResult **ResultCB)
2691 AFSFileHardLinkResultCB *pResultCB = NULL;
2692 size_t size = sizeof(AFSCommResult) + ResultBufferLength - 1;
2693 AFSFileID SourceParentId = pHardLinkCB->SourceParentId;
2694 AFSFileID TargetParentId = pHardLinkCB->TargetParentId;
2695 WCHAR * TargetFileNameCounted = pHardLinkCB->TargetName;
2696 DWORD TargetFileNameLength = pHardLinkCB->TargetNameLength;
2697 cm_fid_t SourceParentFid;
2698 cm_fid_t TargetParentFid;
2700 cm_fid_t OrigTargetFid = {0,0,0,0,0};
2701 cm_scache_t * srcDscp = NULL;
2702 cm_scache_t * targetDscp = NULL;
2703 cm_scache_t * srcScp = NULL;
2705 wchar_t shortName[13];
2706 wchar_t SourceFileName[260];
2707 wchar_t TargetFileName[260];
2713 RDR_InitReq(&req, bWow64);
2715 StringCchCopyNW(SourceFileName, 260, SourceFileNameCounted, SourceFileNameLength / sizeof(WCHAR));
2716 StringCchCopyNW(TargetFileName, 260, TargetFileNameCounted, TargetFileNameLength / sizeof(WCHAR));
2718 osi_Log4(afsd_logp, "RDR_HardLinkFileEntry Source Parent FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
2719 SourceParentId.Cell, SourceParentId.Volume,
2720 SourceParentId.Vnode, SourceParentId.Unique);
2721 osi_Log2(afsd_logp, "... Source Name=%S Length %u", osi_LogSaveStringW(afsd_logp, SourceFileName), SourceFileNameLength);
2722 osi_Log4(afsd_logp, "... Target Parent FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
2723 TargetParentId.Cell, TargetParentId.Volume,
2724 TargetParentId.Vnode, TargetParentId.Unique);
2725 osi_Log2(afsd_logp, "... Target Name=%S Length %u", osi_LogSaveStringW(afsd_logp, TargetFileName), TargetFileNameLength);
2727 *ResultCB = (AFSCommResult *)malloc( size);
2735 pResultCB = (AFSFileHardLinkResultCB *)(*ResultCB)->ResultData;
2737 if (SourceFileNameLength == 0 || TargetFileNameLength == 0)
2739 osi_Log2(afsd_logp, "RDR_HardLinkFileEntry Invalid Name Length: src %u target %u",
2740 SourceFileNameLength, TargetFileNameLength);
2741 (*ResultCB)->ResultStatus = STATUS_INVALID_PARAMETER;
2745 SourceFid.cell = SourceFileId.Cell;
2746 SourceFid.volume = SourceFileId.Volume;
2747 SourceFid.vnode = SourceFileId.Vnode;
2748 SourceFid.unique = SourceFileId.Unique;
2749 SourceFid.hash = SourceFileId.Hash;
2751 SourceParentFid.cell = SourceParentId.Cell;
2752 SourceParentFid.volume = SourceParentId.Volume;
2753 SourceParentFid.vnode = SourceParentId.Vnode;
2754 SourceParentFid.unique = SourceParentId.Unique;
2755 SourceParentFid.hash = SourceParentId.Hash;
2757 TargetParentFid.cell = TargetParentId.Cell;
2758 TargetParentFid.volume = TargetParentId.Volume;
2759 TargetParentFid.vnode = TargetParentId.Vnode;
2760 TargetParentFid.unique = TargetParentId.Unique;
2761 TargetParentFid.hash = TargetParentId.Hash;
2763 code = cm_GetSCache(&SourceFid, NULL, &srcScp, userp, &req);
2765 osi_Log1(afsd_logp, "RDR_HardLinkFileEntry cm_GetSCache source failed code 0x%x", code);
2766 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2767 (*ResultCB)->ResultStatus = status;
2771 code = cm_GetSCache(&TargetParentFid, NULL, &targetDscp, userp, &req);
2773 osi_Log1(afsd_logp, "RDR_HardLinkFileEntry cm_GetSCache target parent failed code 0x%x", code);
2774 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2775 (*ResultCB)->ResultStatus = status;
2776 cm_ReleaseSCache(srcScp);
2780 lock_ObtainWrite(&targetDscp->rw);
2781 code = cm_SyncOp(targetDscp, NULL, userp, &req, PRSFS_INSERT,
2782 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2784 osi_Log2(afsd_logp, "RDR_HardLinkFileEntry cm_SyncOp targetDscp 0x%p failed code 0x%x", targetDscp, code);
2785 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2786 (*ResultCB)->ResultStatus = status;
2787 lock_ReleaseWrite(&targetDscp->rw);
2788 cm_ReleaseSCache(srcScp);
2789 cm_ReleaseSCache(targetDscp);
2793 cm_SyncOpDone(targetDscp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2794 lock_ReleaseWrite(&targetDscp->rw);
2796 if (targetDscp->fileType != CM_SCACHETYPE_DIRECTORY) {
2797 osi_Log1(afsd_logp, "RDR_HardLinkFileEntry targetDscp 0x%p not a directory", targetDscp);
2798 (*ResultCB)->ResultStatus = STATUS_NOT_A_DIRECTORY;
2799 cm_ReleaseSCache(srcScp);
2800 cm_ReleaseSCache(targetDscp);
2804 if ( cm_FidCmp(&SourceParentFid, &TargetParentFid) ) {
2805 code = cm_GetSCache(&SourceParentFid, NULL, &srcDscp, userp, &req);
2807 osi_Log1(afsd_logp, "RDR_HardLinkFileEntry cm_GetSCache source parent failed code 0x%x", code);
2808 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2809 if ( status == STATUS_INVALID_HANDLE)
2810 status = STATUS_OBJECT_PATH_INVALID;
2811 (*ResultCB)->ResultStatus = status;
2812 cm_ReleaseSCache(srcScp);
2813 cm_ReleaseSCache(targetDscp);
2817 lock_ObtainWrite(&srcDscp->rw);
2818 code = cm_SyncOp(srcDscp, NULL, userp, &req, 0,
2819 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2821 osi_Log2(afsd_logp, "RDR_HardLinkFileEntry cm_SyncOp srcDscp 0x%p failed code 0x%x", srcDscp, code);
2822 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2823 if ( status == STATUS_INVALID_HANDLE)
2824 status = STATUS_OBJECT_PATH_INVALID;
2825 (*ResultCB)->ResultStatus = status;
2826 lock_ReleaseWrite(&srcDscp->rw);
2827 if (srcDscp != targetDscp)
2828 cm_ReleaseSCache(srcDscp);
2829 cm_ReleaseSCache(targetDscp);
2830 cm_ReleaseSCache(srcScp);
2834 cm_SyncOpDone(srcDscp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2835 lock_ReleaseWrite(&srcDscp->rw);
2837 if (srcDscp->fileType != CM_SCACHETYPE_DIRECTORY) {
2838 osi_Log1(afsd_logp, "RDR_HardLinkFileEntry srcDscp 0x%p not a directory", srcDscp);
2839 (*ResultCB)->ResultStatus = STATUS_NOT_A_DIRECTORY;
2840 if (srcDscp != targetDscp)
2841 cm_ReleaseSCache(srcDscp);
2842 cm_ReleaseSCache(targetDscp);
2843 cm_ReleaseSCache(srcScp);
2847 srcDscp = targetDscp;
2850 /* Obtain the target FID if it exists */
2851 code = cm_BeginDirOp( targetDscp, userp, &req, CM_DIRLOCK_READ, CM_DIROP_FLAG_NONE, &dirop);
2853 code = cm_BPlusDirLookup(&dirop, TargetFileName, &OrigTargetFid);
2854 cm_EndDirOp(&dirop);
2857 if (OrigTargetFid.vnode) {
2859 /* An object exists with the target name */
2860 if (!pHardLinkCB->bReplaceIfExists) {
2861 osi_Log0(afsd_logp, "RDR_HardLinkFileEntry target name collision and !ReplaceIfExists");
2862 (*ResultCB)->ResultStatus = STATUS_OBJECT_NAME_COLLISION;
2863 if (srcDscp != targetDscp)
2864 cm_ReleaseSCache(srcDscp);
2865 cm_ReleaseSCache(targetDscp);
2866 cm_ReleaseSCache(srcScp);
2870 lock_ObtainWrite(&targetDscp->rw);
2871 code = cm_SyncOp(targetDscp, NULL, userp, &req, PRSFS_INSERT | PRSFS_DELETE,
2872 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2874 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2875 (*ResultCB)->ResultStatus = status;
2876 lock_ReleaseWrite(&srcDscp->rw);
2877 if (srcDscp != targetDscp)
2878 cm_ReleaseSCache(srcDscp);
2879 cm_ReleaseSCache(targetDscp);
2880 cm_ReleaseSCache(srcScp);
2883 cm_SyncOpDone(targetDscp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2884 lock_ReleaseWrite(&targetDscp->rw);
2886 code = cm_Unlink(targetDscp, NULL, TargetFileName, userp, &req);
2888 osi_Log1(afsd_logp, "RDR_HardLinkFileEntry cm_Unlink code 0x%x", code);
2889 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2890 (*ResultCB)->ResultStatus = status;
2891 lock_ReleaseWrite(&srcDscp->rw);
2892 if (srcDscp != targetDscp)
2893 cm_ReleaseSCache(srcDscp);
2894 cm_ReleaseSCache(targetDscp);
2895 cm_ReleaseSCache(srcScp);
2900 code = cm_Link( targetDscp, TargetFileName, srcScp, 0, userp, &req);
2903 cm_scache_t *targetScp = 0;
2906 (*ResultCB)->ResultBufferLength = ResultBufferLength;
2907 dwRemaining = ResultBufferLength - sizeof( AFSFileHardLinkResultCB) + sizeof( AFSDirEnumEntry);
2908 (*ResultCB)->ResultStatus = 0;
2910 pResultCB->SourceParentDataVersion.QuadPart = srcDscp->dataVersion;
2911 pResultCB->TargetParentDataVersion.QuadPart = targetDscp->dataVersion;
2913 osi_Log2(afsd_logp, "RDR_HardLinkFileEntry cm_Link srcDscp 0x%p targetDscp 0x%p SUCCESS",
2914 srcDscp, targetDscp);
2916 code = cm_BeginDirOp( targetDscp, userp, &req, CM_DIRLOCK_READ, CM_DIROP_FLAG_NONE, &dirop);
2918 code = cm_BPlusDirLookup(&dirop, TargetFileName, &TargetFid);
2919 cm_EndDirOp(&dirop);
2923 osi_Log1(afsd_logp, "RDR_HardLinkFileEntry cm_BPlusDirLookup failed code 0x%x",
2925 (*ResultCB)->ResultStatus = STATUS_OBJECT_PATH_INVALID;
2926 if (srcDscp != targetDscp)
2927 cm_ReleaseSCache(srcDscp);
2928 cm_ReleaseSCache(srcScp);
2929 cm_ReleaseSCache(targetDscp);
2933 osi_Log4(afsd_logp, "RDR_HardLinkFileEntry Target FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
2934 TargetFid.cell, TargetFid.volume,
2935 TargetFid.vnode, TargetFid.unique);
2937 code = cm_GetSCache(&TargetFid, &targetDscp->fid, &targetScp, userp, &req);
2939 osi_Log1(afsd_logp, "RDR_HardLinkFileEntry cm_GetSCache target failed code 0x%x", code);
2940 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2941 (*ResultCB)->ResultStatus = status;
2942 if (srcDscp != targetDscp)
2943 cm_ReleaseSCache(srcDscp);
2944 cm_ReleaseSCache(srcScp);
2945 cm_ReleaseSCache(targetDscp);
2949 /* Make sure the source vnode is current */
2950 lock_ObtainWrite(&targetScp->rw);
2951 code = cm_SyncOp(targetScp, NULL, userp, &req, 0,
2952 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2954 osi_Log2(afsd_logp, "RDR_HardLinkFileEntry cm_SyncOp scp 0x%p failed code 0x%x",
2956 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2957 (*ResultCB)->ResultStatus = status;
2958 lock_ReleaseWrite(&targetScp->rw);
2959 cm_ReleaseSCache(targetScp);
2960 if (srcDscp != targetDscp)
2961 cm_ReleaseSCache(srcDscp);
2962 cm_ReleaseSCache(srcScp);
2963 cm_ReleaseSCache(targetDscp);
2967 cm_SyncOpDone(targetScp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
2968 lock_ReleaseWrite(&targetScp->rw);
2970 if (cm_shortNames) {
2971 dfid.vnode = htonl(targetScp->fid.vnode);
2972 dfid.unique = htonl(targetScp->fid.unique);
2974 if (!cm_Is8Dot3(TargetFileName))
2975 cm_Gen8Dot3NameIntW(TargetFileName, &dfid, shortName, NULL);
2977 shortName[0] = '\0';
2980 RDR_PopulateCurrentEntry(&pResultCB->DirEnum, dwRemaining,
2981 targetDscp, targetScp, userp, &req, TargetFileName, shortName,
2982 RDR_POP_FOLLOW_MOUNTPOINTS | RDR_POP_EVALUATE_SYMLINKS,
2983 0, NULL, &dwRemaining);
2984 (*ResultCB)->ResultBufferLength = ResultBufferLength - dwRemaining;
2985 cm_ReleaseSCache(targetScp);
2987 osi_Log0(afsd_logp, "RDR_HardLinkFileEntry SUCCESS");
2989 osi_Log3(afsd_logp, "RDR_HardLinkFileEntry cm_Link srcDscp 0x%p targetDscp 0x%p failed code 0x%x",
2990 srcDscp, targetDscp, code);
2991 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
2992 (*ResultCB)->ResultStatus = status;
2993 (*ResultCB)->ResultBufferLength = 0;
2996 cm_ReleaseSCache(srcScp);
2997 if (srcDscp != targetDscp)
2998 cm_ReleaseSCache(srcDscp);
2999 cm_ReleaseSCache(targetDscp);
3005 RDR_CreateSymlinkEntry( IN cm_user_t *userp,
3006 IN AFSFileID FileId,
3007 IN WCHAR *FileNameCounted,
3008 IN DWORD FileNameLength,
3009 IN AFSCreateSymlinkCB *SymlinkCB,
3011 IN DWORD ResultBufferLength,
3012 IN OUT AFSCommResult **ResultCB)
3014 AFSCreateSymlinkResultCB *pResultCB = NULL;
3015 size_t size = sizeof(AFSCommResult) + ResultBufferLength - 1;
3019 cm_scache_t * dscp = NULL;
3020 afs_uint32 flags = 0;
3022 cm_scache_t * scp = NULL;
3025 wchar_t FileName[260];
3026 char *TargetPath = NULL;
3028 StringCchCopyNW(FileName, 260, FileNameCounted, FileNameLength / sizeof(WCHAR));
3029 TargetPath = cm_Utf16ToUtf8Alloc( SymlinkCB->TargetName, SymlinkCB->TargetNameLength / sizeof(WCHAR), NULL);
3031 osi_Log4( afsd_logp, "RDR_CreateSymlinkEntry parent FID cell=0x%x vol=0x%x vn=0x%x uniq=0x%x",
3032 SymlinkCB->ParentId.Cell, SymlinkCB->ParentId.Volume,
3033 SymlinkCB->ParentId.Vnode, SymlinkCB->ParentId.Unique);
3034 osi_Log1(afsd_logp, "... name=%S", osi_LogSaveStringW(afsd_logp, FileName));
3036 RDR_InitReq(&req, bWow64);
3037 memset(&setAttr, 0, sizeof(cm_attr_t));
3039 *ResultCB = (AFSCommResult *)malloc(size);
3041 osi_Log0(afsd_logp, "RDR_CreateSymlinkEntry out of memory");
3050 parentFid.cell = SymlinkCB->ParentId.Cell;
3051 parentFid.volume = SymlinkCB->ParentId.Volume;
3052 parentFid.vnode = SymlinkCB->ParentId.Vnode;
3053 parentFid.unique = SymlinkCB->ParentId.Unique;
3054 parentFid.hash = SymlinkCB->ParentId.Hash;
3056 code = cm_GetSCache(&parentFid, NULL, &dscp, userp, &req);
3058 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
3059 (*ResultCB)->ResultStatus = status;
3060 if ( status == STATUS_INVALID_HANDLE)
3061 status = STATUS_OBJECT_PATH_INVALID;
3062 osi_Log2(afsd_logp, "RDR_CreateSymlinkEntry cm_GetSCache ParentFID failure code=0x%x status=0x%x",
3068 lock_ObtainWrite(&dscp->rw);
3069 code = cm_SyncOp(dscp, NULL, userp, &req, 0,
3070 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
3072 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
3073 (*ResultCB)->ResultStatus = status;
3074 lock_ReleaseWrite(&dscp->rw);
3075 cm_ReleaseSCache(dscp);
3076 osi_Log3(afsd_logp, "RDR_CreateSymlinkEntry cm_SyncOp failure (1) dscp=0x%p code=0x%x status=0x%x",
3077 dscp, code, status);
3082 cm_SyncOpDone(dscp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
3083 lock_ReleaseWrite(&dscp->rw);
3085 if (dscp->fileType != CM_SCACHETYPE_DIRECTORY) {
3086 (*ResultCB)->ResultStatus = STATUS_NOT_A_DIRECTORY;
3087 cm_ReleaseSCache(dscp);
3088 osi_Log1(afsd_logp, "RDR_CreateSymlinkEntry Not a Directory dscp=0x%p",
3094 Fid.cell = FileId.Cell;
3095 Fid.volume = FileId.Volume;
3096 Fid.vnode = FileId.Vnode;
3097 Fid.unique = FileId.Unique;
3098 Fid.hash = FileId.Hash;
3100 code = cm_GetSCache(&Fid, NULL, &scp, userp, &req);
3102 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
3103 (*ResultCB)->ResultStatus = status;
3104 if ( status == STATUS_INVALID_HANDLE)
3105 status = STATUS_OBJECT_PATH_INVALID;
3106 osi_Log2(afsd_logp, "RDR_CreateSymlinkEntry cm_GetSCache FID failure code=0x%x status=0x%x",
3112 lock_ObtainWrite(&scp->rw);
3113 code = cm_SyncOp(scp, NULL, userp, &req, 0,
3114 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
3116 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
3117 (*ResultCB)->ResultStatus = status;
3118 lock_ReleaseWrite(&scp->rw);
3119 cm_ReleaseSCache(scp);
3120 osi_Log3(afsd_logp, "RDR_CreateSymlinkEntry cm_SyncOp failure (1) scp=0x%p code=0x%x status=0x%x",
3126 cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
3127 lock_ReleaseWrite(&scp->rw);
3129 /* Remove the temporary object */
3130 if (scp->fileType == CM_SCACHETYPE_DIRECTORY)
3131 code = cm_RemoveDir(dscp, NULL, FileName, userp, &req);
3133 code = cm_Unlink(dscp, NULL, FileName, userp, &req);
3134 cm_ReleaseSCache(scp);
3136 if (code && code != CM_ERROR_NOSUCHFILE) {
3137 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
3138 (*ResultCB)->ResultStatus = status;
3139 cm_ReleaseSCache(dscp);
3140 osi_Log2(afsd_logp, "RDR_CreateSymlinkEntry Unable to delete file dscp=0x%p code=0x%x",
3147 * The target path is going to be provided by the redirector in one of the following forms:
3150 * 2. Absolute path prefaced as \??\UNC\<server>\<share>\<path>
3151 * 3. Absolute path prefaced as \??\<drive-letter>:\<path>
3153 * Relative paths can be used with just slash conversion. Absolute paths must be converted.
3154 * UNC paths with a server name that matches cm_NetbiosName then the path is an AFS path and
3155 * it must be converted to /<server>/<share>/<path>. Other UNC paths must be converted to
3156 * msdfs:\\<server>\<share>\<path>. Local disk paths should be converted to
3157 * msdfs:<drive-letter>:<path>.
3160 if ( TargetPath[0] == '\\' ) {
3161 size_t nbNameLen = strlen(cm_NetbiosName);
3165 if ( strncmp(TargetPath, "\\??\\UNC\\", 8) == 0) {
3167 if (strncmp(&TargetPath[8], cm_NetbiosName, nbNameLen) == 0 &&
3168 TargetPath[8 + nbNameLen] == '\\')
3171 s = strdup(&TargetPath[8 + nbNameLen]);
3180 * non-AFS UNC path (msdfs:\\server\share\path)
3181 * strlen("msdfs:\\") == 7 + 1 for the NUL
3183 len = 8 + strlen(&TargetPath[7]);
3184 s = malloc(8 + strlen(&TargetPath[7]));
3185 StringCbCopy(s, len, "msdfs:\\");
3186 StringCbCat(s, len, &TargetPath[7]);
3191 /* non-UNC path (msdfs:<drive>:\<path> */
3192 s = strdup(&TargetPath[4]);
3198 /* relative paths require slash conversion */
3199 char *s = TargetPath;
3206 /* Use current time */
3207 setAttr.mask = CM_ATTRMASK_UNIXMODEBITS | CM_ATTRMASK_CLIENTMODTIME;
3208 setAttr.unixModeBits = 0755;
3209 setAttr.clientModTime = time(NULL);
3211 code = cm_SymLink(dscp, FileName, TargetPath, flags, &setAttr, userp, &req, &scp);
3215 wchar_t shortName[13]=L"";
3219 if (dscp->flags & CM_SCACHEFLAG_ANYWATCH) {
3220 smb_NotifyChange(FILE_ACTION_ADDED,
3221 FILE_NOTIFY_CHANGE_DIR_NAME,
3222 dscp, FileName, NULL, TRUE);
3225 (*ResultCB)->ResultStatus = 0; // We will be able to fit all the data in here
3227 (*ResultCB)->ResultBufferLength = sizeof( AFSCreateSymlinkResultCB);
3229 pResultCB = (AFSCreateSymlinkResultCB *)(*ResultCB)->ResultData;
3231 dwRemaining = ResultBufferLength - sizeof( AFSCreateSymlinkResultCB) + sizeof( AFSDirEnumEntry);
3233 lock_ObtainWrite(&dscp->rw);
3234 code = cm_SyncOp(dscp, NULL, userp, &req, 0,
3235 CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
3237 smb_MapNTError(cm_MapRPCError(code, &req), &status, TRUE);
3238 (*ResultCB)->ResultStatus = status;
3239 lock_ReleaseWrite(&dscp->rw);
3240 cm_ReleaseSCache(dscp);
3241 cm_ReleaseSCache(scp);
3242 osi_Log3(afsd_logp, "RDR_CreateSymlinkEntry cm_SyncOp failure (2) dscp=0x%p code=0x%x status=0x%x",
3243 dscp, code, status);
3247 pResultCB->ParentDataVersion.QuadPart = dscp->dataVersion;
3249 cm_SyncOpDone(dscp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS);
3250 lock_ReleaseWrite(&dscp->rw);
3252 if (cm_shortNames) {
3253 dfid.vnode = htonl(scp->fid.vnode);
3254 dfid.unique = htonl(scp->fid.unique);
3256 if (!cm_Is8Dot3(FileName))
3257 cm_Gen8Dot3NameIntW(FileName, &dfid, shortName, NULL);
3259 shortName[0] = '\0';
3262 code = RDR_PopulateCurrentEntry(&pResultCB->DirEnum, dwRemaining,
3263 dscp, scp, userp, &req, FileName, shortName,
3264 RDR_POP_FOLLOW_MOUNTPOINTS | RDR_POP_EVALUATE_SYMLINKS,
3265 0, NULL, &dwRemaining);
3266 cm_ReleaseSCache(scp);
3267 (*ResultCB)->ResultBufferLength = ResultBufferLength - dwRemaining;
3268 osi_Log0(afsd_logp, "RDR_CreateSymlinkEntry SUCCESS");
3270 (*ResultCB)->ResultStatus = STATUS_FILE_DELETED;
3271 (*ResultCB)->ResultBufferLength = 0;
3272 osi_Log2(afsd_logp, "RDR_CreateSymlinkEntry FAILURE code=0x%x status=0x%x",
3273 code, STATUS_FILE_DELETED);
3276 cm_ReleaseSCache(dscp);
3283 RDR_FlushFileEntry( IN cm_user_t *userp,
3284 IN AFSFileID FileId,