diff --git a/doc/txt/winnotes/afs-changes-since-1.2.txt b/doc/txt/winnotes/afs-changes-since-1.2.txt index 82c39b9721..2dff4e8bee 100644 --- a/doc/txt/winnotes/afs-changes-since-1.2.txt +++ b/doc/txt/winnotes/afs-changes-since-1.2.txt @@ -1,3 +1,32 @@ +Since 1.3.71: + * smb_ReceiveCoreRename() was factored to produce smb_Rename() + which is used by both the original function and the new + smb_ReceiveNTRename(). smb_ReceiveNTRename() supports the + creation of HardLinks in addition to Renaming. smb_Link() + is a new function which creates HardLinks via cm_Link(). + cm_Link() is a new vnodeops function which creates links + using RXAFS_Link(). + + smb_ReceiveNTRename() does not support the File Copy and + Move Cluster Information operations described in its interface. + ReceiveNTRename is under documented in CIFS-TR-1p00_FINAL.pdf. + + * When opening files via symlinks, we should follow the symlinks + until we reach the actual file stat cache entry. The stat cache + entry of the file should then be stored in the FID instead of + stat scache entry of the symlink. + + * return bad operation errors for all unimplemented functions + even if we do not know the functions exist. + + * Log bad packets and unknown operation packets to the trace log + + * Map CM_ERROR_BADOP to STATUS_NOT_SUPPORTED instead of + 0xC09820FF + + * Update list of known CIFS operations to include all those listed + in CIFS-TR-1p00_FINAL.pdf. + Since 1.3.70: * A new Windows authorization group "AFS Client Admins" is now created and populated with the members of the "Administrators" diff --git a/doc/txt/winnotes/afs-issues.txt b/doc/txt/winnotes/afs-issues.txt index 741e748bc9..44ce41ffd6 100644 --- a/doc/txt/winnotes/afs-issues.txt +++ b/doc/txt/winnotes/afs-issues.txt @@ -196,3 +196,18 @@ List of unfunded projects: afsmap.exe /DELETE 22. Write-through caching appears to be unsupported. Files copied to AFS do not end up in the local cache. + 23. The Win32 API CreateHardLink() is not properly supported by the SMB/CIFS + server. It neither returns a valid error nor does it perform the + operation. + 24. Missing SMB/CIFS functions: + Find + FindUnique + FindClose + ReadBulk + WriteBulk + WriteBulkData + Tran2::SessionSetup + + + + diff --git a/src/WINNT/afsd/cm_utils.c b/src/WINNT/afsd/cm_utils.c index f7e3284c09..edceef032c 100644 --- a/src/WINNT/afsd/cm_utils.c +++ b/src/WINNT/afsd/cm_utils.c @@ -30,41 +30,52 @@ cm_space_t *cm_spaceListp; long cm_MapRPCError(long error, cm_req_t *reqp) { - if (error == 0) return 0; + if (error == 0) + return 0; - /* If we had to stop retrying, report our saved error code. */ - if (reqp && error == CM_ERROR_TIMEDOUT) { - if (reqp->accessError) - return reqp->accessError; - if (reqp->volumeError) - return reqp->volumeError; - if (reqp->rpcError) - return reqp->rpcError; - return error; - } - - if (error < 0) error = CM_ERROR_TIMEDOUT; - else if (error == 30) error = CM_ERROR_READONLY; - else if (error == 13) error = CM_ERROR_NOACCESS; - else if (error == 18) error = CM_ERROR_CROSSDEVLINK; - else if (error == 17) error = CM_ERROR_EXISTS; - else if (error == 20) error = CM_ERROR_NOTDIR; - else if (error == 2) error = CM_ERROR_NOSUCHFILE; - else if (error == 11 /* EAGAIN, most servers */ - || error == 35) /* EAGAIN, Digital UNIX */ - error = CM_ERROR_WOULDBLOCK; - else if (error == VDISKFULL - || error == 28) /* ENOSPC */ - error = CM_ERROR_SPACE; - else if (error == VOVERQUOTA - || error == 49 /* EDQUOT on Solaris */ - || error == 88 /* EDQUOT on AIX */ - || error == 69 /* EDQUOT on Digital UNIX and HPUX */ - || error == 122 /* EDQUOT on Linux */ - || error == 1133) /* EDQUOT on Irix */ - error = CM_ERROR_QUOTA; - else if (error == VNOVNODE) error = CM_ERROR_BADFD; + /* If we had to stop retrying, report our saved error code. */ + if (reqp && error == CM_ERROR_TIMEDOUT) { + if (reqp->accessError) + return reqp->accessError; + if (reqp->volumeError) + return reqp->volumeError; + if (reqp->rpcError) + return reqp->rpcError; return error; + } + + if (error < 0) + error = CM_ERROR_TIMEDOUT; + else if (error == 30) + error = CM_ERROR_READONLY; + else if (error == 13) + error = CM_ERROR_NOACCESS; + else if (error == 18) + error = CM_ERROR_CROSSDEVLINK; + else if (error == 17) + error = CM_ERROR_EXISTS; + else if (error == 20) + error = CM_ERROR_NOTDIR; + else if (error == 2) + error = CM_ERROR_NOSUCHFILE; + else if (error == 11 /* EAGAIN, most servers */ + || error == 35) /* EAGAIN, Digital UNIX */ + error = CM_ERROR_WOULDBLOCK; + else if (error == VDISKFULL + || error == 28) /* ENOSPC */ + error = CM_ERROR_SPACE; + else if (error == VOVERQUOTA + || error == 49 /* EDQUOT on Solaris */ + || error == 88 /* EDQUOT on AIX */ + || error == 69 /* EDQUOT on Digital UNIX and HPUX */ + || error == 122 /* EDQUOT on Linux */ + || error == 1133) /* EDQUOT on Irix */ + error = CM_ERROR_QUOTA; + else if (error == VNOVNODE) + error = CM_ERROR_BADFD; + else if (error == 21) + return CM_ERROR_ISDIR; + return error; } long cm_MapRPCErrorRmdir(long error, cm_req_t *reqp) diff --git a/src/WINNT/afsd/cm_vnodeops.c b/src/WINNT/afsd/cm_vnodeops.c index 26b90fb162..59b07fab25 100644 --- a/src/WINNT/afsd/cm_vnodeops.c +++ b/src/WINNT/afsd/cm_vnodeops.c @@ -2082,6 +2082,60 @@ long cm_MakeDir(cm_scache_t *dscp, char *namep, long flags, cm_attr_t *attrp, return code; } +long cm_Link(cm_scache_t *dscp, char *namep, cm_scache_t *sscp, long flags, + cm_user_t *userp, cm_req_t *reqp) +{ + cm_conn_t *connp; + long code = 0; + AFSFid dirAFSFid; + AFSFid existingAFSFid; + AFSFetchStatus updatedDirStatus; + AFSFetchStatus newLinkStatus; + AFSVolSync volSync; + + if (dscp->fid.cell != sscp->fid.cell || + dscp->fid.volume != sscp->fid.volume) { + return CM_ERROR_CROSSDEVLINK; + } + + lock_ObtainMutex(&dscp->mx); + code = cm_SyncOp(dscp, NULL, userp, reqp, 0, CM_SCACHESYNC_STOREDATA); + lock_ReleaseMutex(&dscp->mx); + + if (code) + return code; + + do { + code = cm_Conn(&dscp->fid, userp, reqp, &connp); + if (code) continue; + + dirAFSFid.Volume = dscp->fid.volume; + dirAFSFid.Vnode = dscp->fid.vnode; + dirAFSFid.Unique = dscp->fid.unique; + + existingAFSFid.Volume = sscp->fid.volume; + existingAFSFid.Vnode = sscp->fid.vnode; + existingAFSFid.Unique = sscp->fid.unique; + + code = RXAFS_Link(connp->callp, &dirAFSFid, namep, &existingAFSFid, + &newLinkStatus, &updatedDirStatus, &volSync); + + osi_Log1(smb_logp," RXAFS_Link returns %d", code); + } while (cm_Analyze(connp, userp, reqp, + &dscp->fid, &volSync, NULL, NULL, code)); + + code = cm_MapRPCError(code, reqp); + + lock_ObtainMutex(&dscp->mx); + cm_SyncOpDone(dscp, NULL, CM_SCACHESYNC_STOREDATA); + if (code == 0) { + cm_MergeStatus(dscp, &updatedDirStatus, &volSync, userp, 0); + } + lock_ReleaseMutex(&dscp->mx); + + return code; +} + long cm_SymLink(cm_scache_t *dscp, char *namep, char *contentsp, long flags, cm_attr_t *attrp, cm_user_t *userp, cm_req_t *reqp) { diff --git a/src/WINNT/afsd/cm_vnodeops.h b/src/WINNT/afsd/cm_vnodeops.h index ce45999f18..28664916bd 100644 --- a/src/WINNT/afsd/cm_vnodeops.h +++ b/src/WINNT/afsd/cm_vnodeops.h @@ -104,6 +104,9 @@ extern long cm_Rename(cm_scache_t *oldDscp, char *oldLastNamep, extern long cm_HandleLink(cm_scache_t *linkScp, struct cm_user *userp, cm_req_t *reqp); +extern long cm_Link(cm_scache_t *dscp, char *namep, cm_scache_t *sscp, + long flags, cm_user_t *userp, cm_req_t *reqp); + extern long cm_SymLink(cm_scache_t *dscp, char *namep, char *contentsp, long flags, cm_attr_t *attrp, cm_user_t *userp, cm_req_t *reqp); diff --git a/src/WINNT/afsd/smb.c b/src/WINNT/afsd/smb.c index 7d0f37d2ce..390df160bc 100644 --- a/src/WINNT/afsd/smb.c +++ b/src/WINNT/afsd/smb.c @@ -7,7 +7,8 @@ * directory or online at http://www.openafs.org/dl/license10.html */ -//#define NOSERVICE 1 +//#define NOTSERVICE 1 +#define LOG_PACKET 1 #include #include @@ -189,6 +190,9 @@ extern char cm_confDir[]; *(sizep) = strlen(cm_HostName) #endif /* DJGPP */ +#ifdef LOG_PACKET +void smb_LogPacket(smb_packet_t *packet); +#endif /* LOG_PACKET */ extern char AFSConfigKeyName[]; char smb_ServerDomainName[MAX_COMPUTERNAME_LENGTH + 1] = ""; /* domain name */ @@ -213,164 +217,180 @@ GUID smb_ServerGUID = { 0x40015cb8, 0x058a, 0x44fc, { 0xae, 0x7e, 0xbb, 0x29, 0x char * myCrt_Dispatch(int i) { - switch (i) - { - default: - return "unknown SMB op"; - case 0x00: - return "(00)ReceiveCoreMakeDir"; - case 0x01: - return "(01)ReceiveCoreRemoveDir"; - case 0x02: - return "(02)ReceiveCoreOpen"; - case 0x03: - return "(03)ReceiveCoreCreate"; - case 0x04: - return "(04)ReceiveCoreClose"; - case 0x05: - return "(05)ReceiveCoreFlush"; - case 0x06: - return "(06)ReceiveCoreUnlink"; - case 0x07: - return "(07)ReceiveCoreRename"; - case 0x08: - return "(08)ReceiveCoreGetFileAttributes"; - case 0x09: - return "(09)ReceiveCoreSetFileAttributes"; - case 0x0a: - return "(0a)ReceiveCoreRead"; - case 0x0b: - return "(0b)ReceiveCoreWrite"; - case 0x0c: - return "(0c)ReceiveCoreLockRecord"; - case 0x0d: - return "(0d)ReceiveCoreUnlockRecord"; - case 0x0e: - return "(0e)SendCoreBadOp"; - case 0x0f: - return "(0f)ReceiveCoreCreate"; - case 0x10: - return "(10)ReceiveCoreCheckPath"; - case 0x11: - return "(11)SendCoreBadOp"; - case 0x12: - return "(12)ReceiveCoreSeek"; - case 0x1a: - return "(1a)ReceiveCoreReadRaw"; - case 0x1d: - return "(1d)ReceiveCoreWriteRawDummy"; - case 0x22: - return "(22)ReceiveV3SetAttributes"; - case 0x23: - return "(23)ReceiveV3GetAttributes"; - case 0x24: - return "(24)ReceiveV3LockingX"; - case 0x25: - return "(25)ReceiveV3Trans"; - case 0x26: - return "(26)ReceiveV3Trans[aux]"; - case 0x29: - return "(29)SendCoreBadOp"; - case 0x2b: - return "(2b)ReceiveCoreEcho"; - case 0x2d: - return "(2d)ReceiveV3OpenX"; - case 0x2e: - return "(2e)ReceiveV3ReadX"; - case 0x32: - return "(32)ReceiveV3Tran2A"; - case 0x33: - return "(33)ReceiveV3Tran2A[aux]"; - case 0x34: - return "(34)ReceiveV3FindClose"; - case 0x35: - return "(35)ReceiveV3FindNotifyClose"; - case 0x70: - return "(70)ReceiveCoreTreeConnect"; - case 0x71: - return "(71)ReceiveCoreTreeDisconnect"; - case 0x72: - return "(72)ReceiveNegotiate"; - case 0x73: - return "(73)ReceiveV3SessionSetupX"; - case 0x74: - return "(74)ReceiveV3UserLogoffX"; - case 0x75: - return "(75)ReceiveV3TreeConnectX"; - case 0x80: - return "(80)ReceiveCoreGetDiskAttributes"; - case 0x81: - return "(81)ReceiveCoreSearchDir"; - case 0xA0: - return "(A0)ReceiveNTTransact"; - case 0xA2: - return "(A2)ReceiveNTCreateX"; - case 0xA4: - return "(A4)ReceiveNTCancel"; - case 0xc0: - return "(c0)SendCoreBadOp"; - case 0xc1: - return "(c1)SendCoreBadOp"; - case 0xc2: - return "(c2)SendCoreBadOp"; - case 0xc3: - return "(c3)SendCoreBadOp"; - } -} + switch (i) + { + case 0x00: + return "(00)ReceiveCoreMakeDir"; + case 0x01: + return "(01)ReceiveCoreRemoveDir"; + case 0x02: + return "(02)ReceiveCoreOpen"; + case 0x03: + return "(03)ReceiveCoreCreate"; + case 0x04: + return "(04)ReceiveCoreClose"; + case 0x05: + return "(05)ReceiveCoreFlush"; + case 0x06: + return "(06)ReceiveCoreUnlink"; + case 0x07: + return "(07)ReceiveCoreRename"; + case 0x08: + return "(08)ReceiveCoreGetFileAttributes"; + case 0x09: + return "(09)ReceiveCoreSetFileAttributes"; + case 0x0a: + return "(0a)ReceiveCoreRead"; + case 0x0b: + return "(0b)ReceiveCoreWrite"; + case 0x0c: + return "(0c)ReceiveCoreLockRecord"; + case 0x0d: + return "(0d)ReceiveCoreUnlockRecord"; + case 0x0e: + return "(0e)SendCoreBadOp"; + case 0x0f: + return "(0f)ReceiveCoreCreate"; + case 0x10: + return "(10)ReceiveCoreCheckPath"; + case 0x11: + return "(11)SendCoreBadOp"; + case 0x12: + return "(12)ReceiveCoreSeek"; + case 0x1a: + return "(1a)ReceiveCoreReadRaw"; + case 0x1d: + return "(1d)ReceiveCoreWriteRawDummy"; + case 0x22: + return "(22)ReceiveV3SetAttributes"; + case 0x23: + return "(23)ReceiveV3GetAttributes"; + case 0x24: + return "(24)ReceiveV3LockingX"; + case 0x25: + return "(25)ReceiveV3Trans"; + case 0x26: + return "(26)ReceiveV3Trans[aux]"; + case 0x29: + return "(29)SendCoreBadOp"; + case 0x2b: + return "(2b)ReceiveCoreEcho"; + case 0x2d: + return "(2d)ReceiveV3OpenX"; + case 0x2e: + return "(2e)ReceiveV3ReadX"; + case 0x32: + return "(32)ReceiveV3Tran2A"; + case 0x33: + return "(33)ReceiveV3Tran2A[aux]"; + case 0x34: + return "(34)ReceiveV3FindClose"; + case 0x35: + return "(35)ReceiveV3FindNotifyClose"; + case 0x70: + return "(70)ReceiveCoreTreeConnect"; + case 0x71: + return "(71)ReceiveCoreTreeDisconnect"; + case 0x72: + return "(72)ReceiveNegotiate"; + case 0x73: + return "(73)ReceiveV3SessionSetupX"; + case 0x74: + return "(74)ReceiveV3UserLogoffX"; + case 0x75: + return "(75)ReceiveV3TreeConnectX"; + case 0x80: + return "(80)ReceiveCoreGetDiskAttributes"; + case 0x81: + return "(81)ReceiveCoreSearchDir"; + case 0x82: + return "(82)Find"; + case 0x83: + return "(83)FindUnique"; + case 0x84: + return "(84)FindClose"; + case 0xA0: + return "(A0)ReceiveNTTransact"; + case 0xA2: + return "(A2)ReceiveNTCreateX"; + case 0xA4: + return "(A4)ReceiveNTCancel"; + case 0xA5: + return "(A5)ReceiveNTRename"; + case 0xc0: + return "(C0)OpenPrintFile"; + case 0xc1: + return "(C1)WritePrintFile"; + case 0xc2: + return "(C2)ClosePrintFile"; + case 0xc3: + return "(C3)GetPrintQueue"; + case 0xd8: + return "(D8)ReadBulk"; + case 0xd9: + return "(D9)WriteBulk"; + case 0xda: + return "(DA)WriteBulkData"; + default: + return "unknown SMB op"; + } +} char * myCrt_2Dispatch(int i) { - switch (i) - { - default: - return "unknown SMB op-2"; - case 0: - return "S(00)CreateFile"; - case 1: - return "S(01)FindFirst"; - case 2: - return "S(02)FindNext"; /* FindNext */ - case 3: - return "S(03)QueryFileSystem_ReceiveTran2QFSInfo"; - case 4: - return "S(04)??"; - case 5: - return "S(05)QueryFileInfo_ReceiveTran2QPathInfo"; - case 6: - return "S(06)SetFileInfo_ReceiveTran2SetPathInfo"; - case 7: - return "S(07)SetInfoHandle_ReceiveTran2QFileInfo"; - case 8: - return "S(08)??_ReceiveTran2SetFileInfo"; - case 9: - return "S(09)??_ReceiveTran2FSCTL"; - case 10: - return "S(0a)_ReceiveTran2IOCTL"; - case 11: - return "S(0b)_ReceiveTran2FindNotifyFirst"; - case 12: - return "S(0c)_ReceiveTran2FindNotifyNext"; - case 13: - return "S(0d)CreateDirectory_ReceiveTran2MKDir"; - } -} + switch (i) + { + default: + return "unknown SMB op-2"; + case 0: + return "S(00)CreateFile"; + case 1: + return "S(01)FindFirst"; + case 2: + return "S(02)FindNext"; /* FindNext */ + case 3: + return "S(03)QueryFileSystem_ReceiveTran2QFSInfo"; + case 4: + return "S(04)??"; + case 5: + return "S(05)QueryFileInfo_ReceiveTran2QPathInfo"; + case 6: + return "S(06)SetFileInfo_ReceiveTran2SetPathInfo"; + case 7: + return "S(07)SetInfoHandle_ReceiveTran2QFileInfo"; + case 8: + return "S(08)??_ReceiveTran2SetFileInfo"; + case 9: + return "S(09)??_ReceiveTran2FSCTL"; + case 10: + return "S(0a)_ReceiveTran2IOCTL"; + case 11: + return "S(0b)_ReceiveTran2FindNotifyFirst"; + case 12: + return "S(0c)_ReceiveTran2FindNotifyNext"; + case 13: + return "S(0d)_ReceiveTran2CreateDirectory"; + case 14: + return "S(0e)_ReceiveTran2SessionSetup"; + } +} char * myCrt_RapDispatch(int i) { - switch(i) - { - default: - return "unknown RAP OP"; - case 0: - return "RAP(0)NetShareEnum"; - case 1: - return "RAP(1)NetShareGetInfo"; - case 13: - return "RAP(13)NetServerGetInfo"; - case 63: - return "RAP(63)NetWkStaGetInfo"; - } -} + switch(i) + { + default: + return "unknown RAP OP"; + case 0: + return "RAP(0)NetShareEnum"; + case 1: + return "RAP(1)NetShareGetInfo"; + case 13: + return "RAP(13)NetServerGetInfo"; + case 63: + return "RAP(63)NetWkStaGetInfo"; + } +} /* scache must be locked */ unsigned int smb_Attributes(cm_scache_t *scp) @@ -1492,8 +1512,8 @@ int smb_FindShare(smb_vc_t *vcp, smb_user_t *uidp, char *shareName, int smb_FindShareCSCPolicy(char *shareName) { - DWORD len; - char policy[1024]; + DWORD len; + char policy[1024]; DWORD dwType; HKEY hkCSCPolicy; int retval = CSC_POLICY_MANUAL; @@ -1511,20 +1531,20 @@ int smb_FindShareCSCPolicy(char *shareName) len = sizeof(policy); if ( RegQueryValueEx( hkCSCPolicy, shareName, 0, &dwType, policy, &len ) || len == 0) { - retval = CSC_POLICY_MANUAL; + retval = stricmp("all",shareName) ? CSC_POLICY_MANUAL : CSC_POLICY_DISABLE; + } + else if (stricmp(policy, "documents") == 0) + { + retval = CSC_POLICY_DOCUMENTS; + } + else if (stricmp(policy, "programs") == 0) + { + retval = CSC_POLICY_PROGRAMS; + } + else if (stricmp(policy, "disable") == 0) + { + retval = CSC_POLICY_DISABLE; } - else if (stricmp(policy, "documents") == 0) - { - retval = CSC_POLICY_DOCUMENTS; - } - else if (stricmp(policy, "programs") == 0) - { - retval = CSC_POLICY_PROGRAMS; - } - else if (stricmp(policy, "disable") == 0) - { - retval = CSC_POLICY_DISABLE; - } RegCloseKey(hkCSCPolicy); return retval; @@ -2132,131 +2152,136 @@ void smb_SendPacket(smb_vc_t *vcp, smb_packet_t *inp) #endif /* !DJGPP */ if (code != 0) - osi_Log1(smb_logp, "SendPacket failure code %d", code); + osi_Log1(smb_logp, "SendPacket failure code %d", code); if (localNCB) - FreeNCB(ncbp); + FreeNCB(ncbp); } void smb_MapNTError(long code, unsigned long *NTStatusp) { - unsigned long NTStatus; + unsigned long NTStatus; - /* map CM_ERROR_* errors to NT 32-bit status codes */ + /* map CM_ERROR_* errors to NT 32-bit status codes */ /* NT Status codes are listed in ntstatus.h not winerror.h */ - if (code == CM_ERROR_NOSUCHCELL) { - NTStatus = 0xC000000FL; /* No such file */ - } - else if (code == CM_ERROR_NOSUCHVOLUME) { - NTStatus = 0xC000000FL; /* No such file */ - } - else if (code == CM_ERROR_TIMEDOUT) { - NTStatus = 0xC00000CFL; /* Sharing Paused */ - } - else if (code == CM_ERROR_RETRY) { - NTStatus = 0xC000022DL; /* Retry */ - } - else if (code == CM_ERROR_NOACCESS) { - NTStatus = 0xC0000022L; /* Access denied */ - } - else if (code == CM_ERROR_READONLY) { - NTStatus = 0xC00000A2L; /* Write protected */ - } - else if (code == CM_ERROR_NOSUCHFILE) { - NTStatus = 0xC000000FL; /* No such file */ - } - else if (code == CM_ERROR_NOSUCHPATH) { - NTStatus = 0xC000003AL; /* Object path not found */ - } - else if (code == CM_ERROR_TOOBIG) { - NTStatus = 0xC000007BL; /* Invalid image format */ - } - else if (code == CM_ERROR_INVAL) { - NTStatus = 0xC000000DL; /* Invalid parameter */ - } - else if (code == CM_ERROR_BADFD) { - NTStatus = 0xC0000008L; /* Invalid handle */ - } - else if (code == CM_ERROR_BADFDOP) { - NTStatus = 0xC0000022L; /* Access denied */ - } - else if (code == CM_ERROR_EXISTS) { - NTStatus = 0xC0000035L; /* Object name collision */ - } - else if (code == CM_ERROR_NOTEMPTY) { - NTStatus = 0xC0000101L; /* Directory not empty */ - } - else if (code == CM_ERROR_CROSSDEVLINK) { - NTStatus = 0xC00000D4L; /* Not same device */ - } - else if (code == CM_ERROR_NOTDIR) { - NTStatus = 0xC0000103L; /* Not a directory */ - } - else if (code == CM_ERROR_ISDIR) { - NTStatus = 0xC00000BAL; /* File is a directory */ - } - else if (code == CM_ERROR_BADOP) { - NTStatus = 0xC09820FFL; /* SMB no support */ - } - else if (code == CM_ERROR_BADSHARENAME) { - NTStatus = 0xC00000CCL; /* Bad network name */ - } - else if (code == CM_ERROR_NOIPC) { + if (code == CM_ERROR_NOSUCHCELL) { + NTStatus = 0xC000000FL; /* No such file */ + } + else if (code == CM_ERROR_NOSUCHVOLUME) { + NTStatus = 0xC000000FL; /* No such file */ + } + else if (code == CM_ERROR_TIMEDOUT) { + NTStatus = 0xC00000CFL; /* Sharing Paused */ + } + else if (code == CM_ERROR_RETRY) { + NTStatus = 0xC000022DL; /* Retry */ + } + else if (code == CM_ERROR_NOACCESS) { + NTStatus = 0xC0000022L; /* Access denied */ + } + else if (code == CM_ERROR_READONLY) { + NTStatus = 0xC00000A2L; /* Write protected */ + } + else if (code == CM_ERROR_NOSUCHFILE) { + NTStatus = 0xC000000FL; /* No such file */ + } + else if (code == CM_ERROR_NOSUCHPATH) { + NTStatus = 0xC000003AL; /* Object path not found */ + } + else if (code == CM_ERROR_TOOBIG) { + NTStatus = 0xC000007BL; /* Invalid image format */ + } + else if (code == CM_ERROR_INVAL) { + NTStatus = 0xC000000DL; /* Invalid parameter */ + } + else if (code == CM_ERROR_BADFD) { + NTStatus = 0xC0000008L; /* Invalid handle */ + } + else if (code == CM_ERROR_BADFDOP) { + NTStatus = 0xC0000022L; /* Access denied */ + } + else if (code == CM_ERROR_EXISTS) { + NTStatus = 0xC0000035L; /* Object name collision */ + } + else if (code == CM_ERROR_NOTEMPTY) { + NTStatus = 0xC0000101L; /* Directory not empty */ + } + else if (code == CM_ERROR_CROSSDEVLINK) { + NTStatus = 0xC00000D4L; /* Not same device */ + } + else if (code == CM_ERROR_NOTDIR) { + NTStatus = 0xC0000103L; /* Not a directory */ + } + else if (code == CM_ERROR_ISDIR) { + NTStatus = 0xC00000BAL; /* File is a directory */ + } + else if (code == CM_ERROR_BADOP) { #ifdef COMMENT - NTStatus = 0xC0000022L; /* Access Denied */ + /* I have no idea where this comes from */ + NTStatus = 0xC09820FFL; /* SMB no support */ #else + NTStatus = 0xC00000BBL; /* Not supported */ +#endif /* COMMENT */ + } + else if (code == CM_ERROR_BADSHARENAME) { + NTStatus = 0xC00000CCL; /* Bad network name */ + } + else if (code == CM_ERROR_NOIPC) { +#ifdef COMMENT + NTStatus = 0xC0000022L; /* Access Denied */ +#else NTStatus = 0xC000013DL; /* Remote Resources */ #endif - } - else if (code == CM_ERROR_CLOCKSKEW) { - NTStatus = 0xC0000133L; /* Time difference at DC */ - } - else if (code == CM_ERROR_BADTID) { - NTStatus = 0xC0982005L; /* SMB bad TID */ - } - else if (code == CM_ERROR_USESTD) { - NTStatus = 0xC09820FBL; /* SMB use standard */ - } - else if (code == CM_ERROR_QUOTA) { - NTStatus = 0xC0000044L; /* Quota exceeded */ - } - else if (code == CM_ERROR_SPACE) { - NTStatus = 0xC000007FL; /* Disk full */ - } - else if (code == CM_ERROR_ATSYS) { - NTStatus = 0xC0000033L; /* Object name invalid */ - } - else if (code == CM_ERROR_BADNTFILENAME) { - NTStatus = 0xC0000033L; /* Object name invalid */ - } - else if (code == CM_ERROR_WOULDBLOCK) { - NTStatus = 0xC0000055L; /* Lock not granted */ - } - else if (code == CM_ERROR_PARTIALWRITE) { - NTStatus = 0xC000007FL; /* Disk full */ - } - else if (code == CM_ERROR_BUFFERTOOSMALL) { - NTStatus = 0xC0000023L; /* Buffer too small */ - } - else if (code == CM_ERROR_AMBIGUOUS_FILENAME) { - NTStatus = 0xC0000035L; /* Object name collision */ } - else if (code == CM_ERROR_BADPASSWORD) { - NTStatus = 0xC000006DL; /* unknown username or bad password */ - } - else if (code == CM_ERROR_BADLOGONTYPE) { - NTStatus = 0xC000015BL; /* logon type not granted */ - } - else if (code == CM_ERROR_GSSCONTINUE) { - NTStatus = 0xC0000016L; /* more processing required */ - } - else { - NTStatus = 0xC0982001L; /* SMB non-specific error */ - } + else if (code == CM_ERROR_CLOCKSKEW) { + NTStatus = 0xC0000133L; /* Time difference at DC */ + } + else if (code == CM_ERROR_BADTID) { + NTStatus = 0xC0982005L; /* SMB bad TID */ + } + else if (code == CM_ERROR_USESTD) { + NTStatus = 0xC09820FBL; /* SMB use standard */ + } + else if (code == CM_ERROR_QUOTA) { + NTStatus = 0xC0000044L; /* Quota exceeded */ + } + else if (code == CM_ERROR_SPACE) { + NTStatus = 0xC000007FL; /* Disk full */ + } + else if (code == CM_ERROR_ATSYS) { + NTStatus = 0xC0000033L; /* Object name invalid */ + } + else if (code == CM_ERROR_BADNTFILENAME) { + NTStatus = 0xC0000033L; /* Object name invalid */ + } + else if (code == CM_ERROR_WOULDBLOCK) { + NTStatus = 0xC0000055L; /* Lock not granted */ + } + else if (code == CM_ERROR_PARTIALWRITE) { + NTStatus = 0xC000007FL; /* Disk full */ + } + else if (code == CM_ERROR_BUFFERTOOSMALL) { + NTStatus = 0xC0000023L; /* Buffer too small */ + } + else if (code == CM_ERROR_AMBIGUOUS_FILENAME) { + NTStatus = 0xC0000035L; /* Object name collision */ + } + else if (code == CM_ERROR_BADPASSWORD) { + NTStatus = 0xC000006DL; /* unknown username or bad password */ + } + else if (code == CM_ERROR_BADLOGONTYPE) { + NTStatus = 0xC000015BL; /* logon type not granted */ + } + else if (code == CM_ERROR_GSSCONTINUE) { + NTStatus = 0xC0000016L; /* more processing required */ + } + else { + NTStatus = 0xC0982001L; /* SMB non-specific error */ + } - *NTStatusp = NTStatus; - osi_Log2(smb_logp, "SMB SEND code %lX as NT %lX", code, NTStatus); -} + *NTStatusp = NTStatus; + osi_Log2(smb_logp, "SMB SEND code %lX as NT %lX", code, NTStatus); +} void smb_MapCoreError(long code, smb_vc_t *vcp, unsigned short *scodep, unsigned char *classp) @@ -2418,7 +2443,8 @@ void smb_MapCoreError(long code, smb_vc_t *vcp, unsigned short *scodep, long smb_SendCoreBadOp(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) { - return CM_ERROR_BADOP; + osi_Log0(smb_logp,"SendCoreBadOp - NOT_SUPPORTED"); + return CM_ERROR_BADOP; } long smb_ReceiveCoreEcho(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) @@ -4373,41 +4399,36 @@ int smb_RenameProc(cm_scache_t *dscp, cm_dirEntry_t *dep, void *vrockp, osi_hype return code; } -long smb_ReceiveCoreRename(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) + +long +smb_Rename(smb_vc_t *vcp, smb_packet_t *inp, char * oldPathp, char * newPathp, int attrs) { - long code = 0; - char *oldPathp; - char *newPathp; - char *tp; - cm_space_t *spacep = NULL; - smb_renameRock_t rock; - cm_scache_t *oldDscp = NULL; - cm_scache_t *newDscp = NULL; - cm_scache_t *tmpscp= NULL; - cm_scache_t *tmpscp2 = NULL; - char *oldLastNamep; - char *newLastNamep; - osi_hyper_t thyper; - cm_user_t *userp; - int caseFold; - char *tidPathp; - DWORD filter; - cm_req_t req; + long code = 0; + cm_space_t *spacep = NULL; + smb_renameRock_t rock; + cm_scache_t *oldDscp = NULL; + cm_scache_t *newDscp = NULL; + cm_scache_t *tmpscp= NULL; + cm_scache_t *tmpscp2 = NULL; + char *oldLastNamep; + char *newLastNamep; + osi_hyper_t thyper; + cm_user_t *userp; + int caseFold; + char *tidPathp; + DWORD filter; + cm_req_t req; - cm_InitReq(&req); - - tp = smb_GetSMBData(inp, NULL); - oldPathp = smb_ParseASCIIBlock(tp, &tp); - newPathp = smb_ParseASCIIBlock(tp, &tp); + userp = smb_GetUser(vcp, inp); + code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp); + if (code) { + cm_ReleaseUser(userp); + return CM_ERROR_NOSUCHPATH; + } - osi_Log2(smb_logp, "smb rename [%s] to [%s]", - osi_LogSaveString(smb_logp, oldPathp), - osi_LogSaveString(smb_logp, newPathp)); - - spacep = inp->spacep; - smb_StripLastComponent(spacep->data, &oldLastNamep, oldPathp); - - userp = smb_GetUser(vcp, inp); + cm_InitReq(&req); + spacep = inp->spacep; + smb_StripLastComponent(spacep->data, &oldLastNamep, oldPathp); /* * Changed to use CASEFOLD always. This enables us to rename Foo/baz when @@ -4420,65 +4441,59 @@ long smb_ReceiveCoreRename(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) * * caseFold = CM_FLAG_CASEFOLD; */ - caseFold = CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD; + caseFold = CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD; + code = cm_NameI(cm_rootSCachep, spacep->data, caseFold, + userp, tidPathp, &req, &oldDscp); - code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp); - if(code) { + if (code) { cm_ReleaseUser(userp); - return CM_ERROR_NOSUCHPATH; + return code; } - code = cm_NameI(cm_rootSCachep, spacep->data, caseFold, - userp, tidPathp, &req, &oldDscp); - - if (code) { - cm_ReleaseUser(userp); - return code; - } - smb_StripLastComponent(spacep->data, &newLastNamep, newPathp); - code = cm_NameI(cm_rootSCachep, spacep->data, caseFold, - userp, tidPathp, &req, &newDscp); + smb_StripLastComponent(spacep->data, &newLastNamep, newPathp); + code = cm_NameI(cm_rootSCachep, spacep->data, caseFold, + userp, tidPathp, &req, &newDscp); - if (code) { - cm_ReleaseSCache(oldDscp); - cm_ReleaseUser(userp); - return code; - } + if (code) { + cm_ReleaseSCache(oldDscp); + cm_ReleaseUser(userp); + return code; + } - /* otherwise, oldDscp and newDscp point to the corresponding directories. - * next, get the component names, and lower case them. - */ + /* otherwise, oldDscp and newDscp point to the corresponding directories. + * next, get the component names, and lower case them. + */ - /* handle the old name first */ - if (!oldLastNamep) - oldLastNamep = oldPathp; - else - oldLastNamep++; + /* handle the old name first */ + if (!oldLastNamep) + oldLastNamep = oldPathp; + else + oldLastNamep++; - /* and handle the new name, too */ - if (!newLastNamep) - newLastNamep = newPathp; - else - newLastNamep++; + /* and handle the new name, too */ + if (!newLastNamep) + newLastNamep = newPathp; + else + newLastNamep++; /* TODO: The old name could be a wildcard. The new name must not be */ - - /* do the vnode call */ - rock.odscp = oldDscp; - rock.ndscp = newDscp; - rock.userp = userp; - rock.reqp = &req; - rock.vcp = vcp; - rock.maskp = oldLastNamep; - rock.flags = ((strchr(oldLastNamep, '~') != NULL) ? SMB_MASKFLAG_TILDE : 0); - rock.newNamep = newLastNamep; + + /* do the vnode call */ + rock.odscp = oldDscp; + rock.ndscp = newDscp; + rock.userp = userp; + rock.reqp = &req; + rock.vcp = vcp; + rock.maskp = oldLastNamep; + rock.flags = ((strchr(oldLastNamep, '~') != NULL) ? SMB_MASKFLAG_TILDE : 0); + rock.newNamep = newLastNamep; /* Check if the file already exists; if so return error */ - code = cm_Lookup(newDscp,newLastNamep,CM_FLAG_CHECKPATH,userp,&req,&tmpscp); - if ((code != CM_ERROR_NOSUCHFILE) && (code != CM_ERROR_NOSUCHPATH) && (code != CM_ERROR_NOSUCHVOLUME) ) { + code = cm_Lookup(newDscp,newLastNamep,CM_FLAG_CHECKPATH,userp,&req,&tmpscp); + if ((code != CM_ERROR_NOSUCHFILE) && (code != CM_ERROR_NOSUCHPATH) && (code != CM_ERROR_NOSUCHVOLUME) ) { osi_Log2(smb_logp, " lookup returns %ld for [%s]", code, osi_LogSaveString(afsd_logp, newLastNamep)); - + /* Check if the old and the new names differ only in case. If so return * success, else return CM_ERROR_EXISTS */ @@ -4502,55 +4517,204 @@ long smb_ReceiveCoreRename(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) code = CM_ERROR_EXISTS; } - if(tmpscp != NULL) + if(tmpscp != NULL) cm_ReleaseSCache(tmpscp); cm_ReleaseSCache(newDscp); cm_ReleaseSCache(oldDscp); cm_ReleaseUser(userp); - return code; - } + return code; + } /* Now search the directory for the pattern, and do the appropriate rename when found */ - thyper.LowPart = 0; /* search dir from here */ + thyper.LowPart = 0; /* search dir from here */ thyper.HighPart = 0; code = cm_ApplyDir(oldDscp, smb_RenameProc, &rock, &thyper, userp, &req, NULL); if (code == CM_ERROR_STOPNOW) - code = 0; - else if (code == 0) - code = CM_ERROR_NOSUCHFILE; + code = 0; + else if (code == 0) + code = CM_ERROR_NOSUCHFILE; - /* Handle Change Notification */ - /* - * Being lazy, not distinguishing between files and dirs in this - * filter, since we'd have to do a lookup. - */ - filter = FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME; - if (oldDscp == newDscp) { - if (oldDscp->flags & CM_SCACHEFLAG_ANYWATCH) - smb_NotifyChange(FILE_ACTION_RENAMED_OLD_NAME, - filter, oldDscp, oldLastNamep, - newLastNamep, TRUE); - } else { - if (oldDscp->flags & CM_SCACHEFLAG_ANYWATCH) - smb_NotifyChange(FILE_ACTION_RENAMED_OLD_NAME, - filter, oldDscp, oldLastNamep, - NULL, TRUE); - if (newDscp->flags & CM_SCACHEFLAG_ANYWATCH) - smb_NotifyChange(FILE_ACTION_RENAMED_NEW_NAME, - filter, newDscp, newLastNamep, - NULL, TRUE); - } + /* Handle Change Notification */ + /* + * Being lazy, not distinguishing between files and dirs in this + * filter, since we'd have to do a lookup. + */ + filter = FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME; + if (oldDscp == newDscp) { + if (oldDscp->flags & CM_SCACHEFLAG_ANYWATCH) + smb_NotifyChange(FILE_ACTION_RENAMED_OLD_NAME, + filter, oldDscp, oldLastNamep, + newLastNamep, TRUE); + } else { + if (oldDscp->flags & CM_SCACHEFLAG_ANYWATCH) + smb_NotifyChange(FILE_ACTION_RENAMED_OLD_NAME, + filter, oldDscp, oldLastNamep, + NULL, TRUE); + if (newDscp->flags & CM_SCACHEFLAG_ANYWATCH) + smb_NotifyChange(FILE_ACTION_RENAMED_NEW_NAME, + filter, newDscp, newLastNamep, + NULL, TRUE); + } if(tmpscp != NULL) cm_ReleaseSCache(tmpscp); cm_ReleaseUser(userp); - cm_ReleaseSCache(oldDscp); - cm_ReleaseSCache(newDscp); - return code; + cm_ReleaseSCache(oldDscp); + cm_ReleaseSCache(newDscp); + return code; } +long +smb_Link(smb_vc_t *vcp, smb_packet_t *inp, char * oldPathp, char * newPathp) +{ + long code = 0; + cm_space_t *spacep = NULL; + cm_scache_t *oldDscp = NULL; + cm_scache_t *newDscp = NULL; + cm_scache_t *tmpscp= NULL; + cm_scache_t *tmpscp2 = NULL; + cm_scache_t *sscp = NULL; + char *oldLastNamep; + char *newLastNamep; + cm_user_t *userp; + int caseFold; + char *tidPathp; + DWORD filter; + cm_req_t req; + + userp = smb_GetUser(vcp, inp); + + code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp); + if (code) { + cm_ReleaseUser(userp); + return CM_ERROR_NOSUCHPATH; + } + + cm_InitReq(&req); + + caseFold = CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD; + + spacep = inp->spacep; + smb_StripLastComponent(spacep->data, &oldLastNamep, oldPathp); + + code = cm_NameI(cm_rootSCachep, spacep->data, caseFold, + userp, tidPathp, &req, &oldDscp); + if (code) { + cm_ReleaseUser(userp); + return code; + } + + smb_StripLastComponent(spacep->data, &newLastNamep, newPathp); + code = cm_NameI(cm_rootSCachep, spacep->data, caseFold, + userp, tidPathp, &req, &newDscp); + if (code) { + cm_ReleaseSCache(oldDscp); + cm_ReleaseUser(userp); + return code; + } + + /* Now, although we did two lookups for the two directories (because the same + * directory can be referenced through different paths), we only allow hard links + * within the same directory. */ + if (oldDscp != newDscp) { + cm_ReleaseSCache(oldDscp); + cm_ReleaseSCache(newDscp); + cm_ReleaseUser(userp); + return CM_ERROR_CROSSDEVLINK; + } + + /* handle the old name first */ + if (!oldLastNamep) + oldLastNamep = oldPathp; + else + oldLastNamep++; + + /* and handle the new name, too */ + if (!newLastNamep) + newLastNamep = newPathp; + else + newLastNamep++; + + /* now lookup the old name */ + osi_Log1(smb_logp," looking up [%s]", osi_LogSaveString(smb_logp,oldLastNamep)); + code = cm_Lookup(oldDscp, oldLastNamep, CM_FLAG_CHECKPATH | CM_FLAG_CASEFOLD, userp, &req, &sscp); + if (code) { + cm_ReleaseSCache(oldDscp); + cm_ReleaseSCache(newDscp); + cm_ReleaseUser(userp); + return code; + } + + /* Check if the file already exists; if so return error */ + code = cm_Lookup(newDscp,newLastNamep,CM_FLAG_CHECKPATH,userp,&req,&tmpscp); + if ((code != CM_ERROR_NOSUCHFILE) && (code != CM_ERROR_NOSUCHPATH) && (code != CM_ERROR_NOSUCHVOLUME) ) { + osi_Log2(smb_logp, " lookup returns %ld for [%s]", code, + osi_LogSaveString(afsd_logp, newLastNamep)); + + /* if the existing link is to the same file, then we return success */ + if (!code) { + if(sscp == tmpscp) { + code = 0; + } else { + osi_Log0(smb_logp, "Can't create hardlink. Target already exists"); + code = CM_ERROR_EXISTS; + } + } + + if (tmpscp != NULL) + cm_ReleaseSCache(tmpscp); + cm_ReleaseSCache(sscp); + cm_ReleaseSCache(newDscp); + cm_ReleaseSCache(oldDscp); + cm_ReleaseUser(userp); + return code; + } + + /* now create the hardlink */ + osi_Log1(smb_logp," Attempting to create new link [%s]", osi_LogSaveString(smb_logp, newLastNamep)); + code = cm_Link(newDscp, newLastNamep, sscp, 0, userp, &req); + osi_Log1(smb_logp," Link returns %d", code); + + /* Handle Change Notification */ + if (code == 0) { + filter = (sscp->fileType == CM_SCACHETYPE_FILE)? FILE_NOTIFY_CHANGE_FILE_NAME : FILE_NOTIFY_CHANGE_DIR_NAME; + if (newDscp->flags & CM_SCACHEFLAG_ANYWATCH) + smb_NotifyChange(FILE_ACTION_ADDED, + filter, newDscp, newLastNamep, + NULL, TRUE); + } + + if (tmpscp != NULL) + cm_ReleaseSCache(tmpscp); + cm_ReleaseUser(userp); + cm_ReleaseSCache(sscp); + cm_ReleaseSCache(oldDscp); + cm_ReleaseSCache(newDscp); + return code; +} + +long +smb_ReceiveCoreRename(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) +{ + char *oldPathp; + char *newPathp; + char *tp; + + tp = smb_GetSMBData(inp, NULL); + oldPathp = smb_ParseASCIIBlock(tp, &tp); + newPathp = smb_ParseASCIIBlock(tp, &tp); + + osi_Log2(smb_logp, "smb rename [%s] to [%s]", + osi_LogSaveString(smb_logp, oldPathp), + osi_LogSaveString(smb_logp, newPathp)); + + return smb_Rename(vcp,inp,oldPathp,newPathp,0); +} + + + typedef struct smb_rmdirRock { cm_scache_t *dscp; cm_user_t *userp; @@ -5933,225 +6097,232 @@ void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp, int temp; unsigned char *tp; unsigned short errCode; - unsigned long NTStatus; + unsigned long NTStatus; int noSend; unsigned char errClass; - unsigned int oldGen; - DWORD oldTime, newTime; + unsigned int oldGen; + DWORD oldTime, newTime; - /* get easy pointer to the data */ - smbp = (smb_t *) inp->data; + /* get easy pointer to the data */ + smbp = (smb_t *) inp->data; - if (!(outp->flags & SMB_PACKETFLAG_SUSPENDED)) { + if (!(outp->flags & SMB_PACKETFLAG_SUSPENDED)) { /* setup the basic parms for the initial request in the packet */ - inp->inCom = smbp->com; + inp->inCom = smbp->com; inp->wctp = &smbp->wct; inp->inCount = 0; - inp->ncb_length = ncbp->ncb_length; - } + inp->ncb_length = ncbp->ncb_length; + } noSend = 0; - /* Sanity check */ - if (ncbp->ncb_length < offsetof(struct smb, vdata)) { - /* log it and discard it */ + /* Sanity check */ + if (ncbp->ncb_length < offsetof(struct smb, vdata)) { + /* log it and discard it */ #ifndef DJGPP - HANDLE h; - char *ptbuf[1]; - char s[100]; - h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME); - sprintf(s, "SMB message too short, len %d", ncbp->ncb_length); - ptbuf[0] = s; - ReportEvent(h, EVENTLOG_WARNING_TYPE, 0, 1007, NULL, - 1, ncbp->ncb_length, ptbuf, inp); - DeregisterEventSource(h); + HANDLE h; + char *ptbuf[1]; + char s[100]; + h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME); + sprintf(s, "SMB message too short, len %d", ncbp->ncb_length); + ptbuf[0] = s; + ReportEvent(h, EVENTLOG_WARNING_TYPE, 0, 1007, NULL, + 1, ncbp->ncb_length, ptbuf, inp); + DeregisterEventSource(h); #else /* DJGPP */ osi_Log1(smb_logp, "SMB message too short, len %d", ncbp->ncb_length); #endif /* !DJGPP */ - return; - } + return; + } - /* We are an ongoing op */ - thrd_Increment(&ongoingOps); + /* We are an ongoing op */ + thrd_Increment(&ongoingOps); /* set up response packet for receiving output */ - if (!(outp->flags & SMB_PACKETFLAG_SUSPENDED)) + if (!(outp->flags & SMB_PACKETFLAG_SUSPENDED)) smb_FormatResponsePacket(vcp, inp, outp); outWctp = outp->wctp; - /* Remember session generation number and time */ - oldGen = sessionGen; - oldTime = GetCurrentTime(); + /* Remember session generation number and time */ + oldGen = sessionGen; + oldTime = GetCurrentTime(); - while(inp->inCom != 0xff) { + while (inp->inCom != 0xff) { dp = &smb_dispatchTable[inp->inCom]; - if (outp->flags & SMB_PACKETFLAG_SUSPENDED) { - outp->flags &= ~SMB_PACKETFLAG_SUSPENDED; - code = outp->resumeCode; - goto resume; - } + if (outp->flags & SMB_PACKETFLAG_SUSPENDED) { + outp->flags &= ~SMB_PACKETFLAG_SUSPENDED; + code = outp->resumeCode; + goto resume; + } /* process each request in the packet; inCom, wctp and inCount * are already set up. */ - osi_Log2(smb_logp, "SMB received op 0x%x lsn %d", inp->inCom, - ncbp->ncb_lsn); + osi_Log2(smb_logp, "SMB received op 0x%x lsn %d", inp->inCom, + ncbp->ncb_lsn); - /* now do the dispatch */ - /* start by formatting the response record a little, as a default */ + /* now do the dispatch */ + /* start by formatting the response record a little, as a default */ if (dp->flags & SMB_DISPATCHFLAG_CHAINED) { - outWctp[0] = 2; + outWctp[0] = 2; outWctp[1] = 0xff; /* no operation */ outWctp[2] = 0; /* padding */ outWctp[3] = 0; outWctp[4] = 0; } - else { - /* not a chained request, this is a more reasonable default */ + else { + /* not a chained request, this is a more reasonable default */ outWctp[0] = 0; /* wct of zero */ outWctp[1] = 0; /* and bcc (word) of zero */ outWctp[2] = 0; - } + } - /* once set, stays set. Doesn't matter, since we never chain + /* once set, stays set. Doesn't matter, since we never chain * "no response" calls. */ - if (dp->flags & SMB_DISPATCHFLAG_NORESPONSE) + if (dp->flags & SMB_DISPATCHFLAG_NORESPONSE) noSend = 1; if (dp->procp) { - /* we have a recognized operation */ + /* we have a recognized operation */ - if (inp->inCom == 0x1d) - /* Raw Write */ - code = smb_ReceiveCoreWriteRaw (vcp, inp, outp, - rwcp); - else { - osi_LogEvent("AFS Dispatch %s",(myCrt_Dispatch(inp->inCom)),"vcp[%x] lana[%d] lsn[%d]",(int)vcp,vcp->lana,vcp->lsn); - osi_Log4(smb_logp,"Dispatch %s vcp[%x] lana[%d] lsn[%d]",(myCrt_Dispatch(inp->inCom)),vcp,vcp->lana,vcp->lsn); - code = (*(dp->procp)) (vcp, inp, outp); - osi_LogEvent("AFS Dispatch return",NULL,"Code[%d]",(code==0)?0:code-CM_ERROR_BASE); - osi_Log1(smb_logp,"Dispatch return code[%d]",(code==0)?0:code-CM_ERROR_BASE); - } + if (inp->inCom == 0x1d) + /* Raw Write */ + code = smb_ReceiveCoreWriteRaw (vcp, inp, outp, + rwcp); + else { + osi_LogEvent("AFS Dispatch %s",(myCrt_Dispatch(inp->inCom)),"vcp[%x] lana[%d] lsn[%d]",(int)vcp,vcp->lana,vcp->lsn); + osi_Log4(smb_logp,"Dispatch %s vcp[%x] lana[%d] lsn[%d]",(myCrt_Dispatch(inp->inCom)),vcp,vcp->lana,vcp->lsn); + code = (*(dp->procp)) (vcp, inp, outp); + osi_LogEvent("AFS Dispatch return",NULL,"Code[%d]",(code==0)?0:code-CM_ERROR_BASE); + osi_Log1(smb_logp,"Dispatch return code[%d]",(code==0)?0:code-CM_ERROR_BASE); +#ifdef LOG_PACKET + if ( code == CM_ERROR_BADSMB || + code == CM_ERROR_BADOP ) + smb_LogPacket(inp); +#endif /* LOG_PACKET */ + } - if (oldGen != sessionGen) { + if (oldGen != sessionGen) { #ifndef DJGPP - HANDLE h; - char *ptbuf[1]; - char s[100]; - newTime = GetCurrentTime(); - h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME); - sprintf(s, "Pkt straddled session startup, took %d ms, ncb length %d", - newTime - oldTime, ncbp->ncb_length); - ptbuf[0] = s; - ReportEvent(h, EVENTLOG_WARNING_TYPE, 0, - 1005, NULL, 1, ncbp->ncb_length, ptbuf, smbp); - DeregisterEventSource(h); + HANDLE h; + char *ptbuf[1]; + char s[100]; + newTime = GetCurrentTime(); + h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME); + sprintf(s, "Pkt straddled session startup, took %d ms, ncb length %d", + newTime - oldTime, ncbp->ncb_length); + ptbuf[0] = s; + ReportEvent(h, EVENTLOG_WARNING_TYPE, 0, + 1005, NULL, 1, ncbp->ncb_length, ptbuf, smbp); + DeregisterEventSource(h); #endif /* !DJGPP */ - osi_Log1(smb_logp, "Pkt straddled session startup, " - "ncb length %d", ncbp->ncb_length); - } + osi_Log1(smb_logp, "Pkt straddled session startup, " + "ncb length %d", ncbp->ncb_length); + } } else { - /* bad opcode, fail the request, after displaying it */ -#ifdef NOTSERVICE + /* bad opcode, fail the request, after displaying it */ + osi_Log1(smb_logp, "Received bad SMB req 0x%X", inp->inCom); +#ifdef LOG_PACKET smb_LogPacket(inp); -#endif /* NOTSERVICE */ +#endif /* LOG_PACKET */ #ifndef DJGPP - if (showErrors) { - sprintf(tbuffer, "Received bad SMB req 0x%x", inp->inCom); + if (showErrors) { + sprintf(tbuffer, "Received bad SMB req 0x%x", inp->inCom); code = (*smb_MBfunc)(NULL, tbuffer, "Cancel: don't show again", - MB_OKCANCEL|MB_SERVICE_NOTIFICATION); - if (code == IDCANCEL) showErrors = 0; - } + MB_OKCANCEL|MB_SERVICE_NOTIFICATION); + if (code == IDCANCEL) + showErrors = 0; + } #endif /* DJGPP */ code = CM_ERROR_BADOP; } - /* catastrophic failure: log as much as possible */ - if (code == CM_ERROR_BADSMB) { + /* catastrophic failure: log as much as possible */ + if (code == CM_ERROR_BADSMB) { #ifndef DJGPP - HANDLE h; - char *ptbuf[1]; - char s[100]; + HANDLE h; + char *ptbuf[1]; + char s[100]; - osi_Log1(smb_logp, + osi_Log1(smb_logp, "Invalid SMB, ncb_length %d", ncbp->ncb_length); - h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME); - sprintf(s, "Invalid SMB message, length %d", + h = RegisterEventSource(NULL, AFS_DAEMON_EVENT_NAME); + sprintf(s, "Invalid SMB message, length %d", ncbp->ncb_length); - ptbuf[0] = s; - ReportEvent(h, EVENTLOG_ERROR_TYPE, 0, 1002, NULL, + ptbuf[0] = s; + ReportEvent(h, EVENTLOG_ERROR_TYPE, 0, 1002, NULL, 1, ncbp->ncb_length, ptbuf, smbp); - DeregisterEventSource(h); -#ifdef NOTSERVICE + DeregisterEventSource(h); +#ifdef LOG_PACKET smb_LogPacket(inp); -#endif /* NOTSERVICE */ +#endif /* LOG_PACKET */ #endif /* !DJGPP */ osi_Log1(smb_logp, "Invalid SMB message, length %d", ncbp->ncb_length); - code = CM_ERROR_INVAL; - } + code = CM_ERROR_INVAL; + } - if (outp->flags & SMB_PACKETFLAG_NOSEND) { - thrd_Decrement(&ongoingOps); - return; - } + if (outp->flags & SMB_PACKETFLAG_NOSEND) { + thrd_Decrement(&ongoingOps); + return; + } resume: - /* now, if we failed, turn the current response into an empty + /* now, if we failed, turn the current response into an empty * one, and fill in the response packet's error code. */ - if (code) { - if (vcp->flags & SMB_VCFLAG_STATUS32) { - smb_MapNTError(code, &NTStatus); - outWctp = outp->wctp; - smbp = (smb_t *) &outp->data; - if (code != CM_ERROR_PARTIALWRITE - && code != CM_ERROR_BUFFERTOOSMALL - && code != CM_ERROR_GSSCONTINUE) { - /* nuke wct and bcc. For a partial - * write or an in-process authentication handshake, + if (code) { + if (vcp->flags & SMB_VCFLAG_STATUS32) { + smb_MapNTError(code, &NTStatus); + outWctp = outp->wctp; + smbp = (smb_t *) &outp->data; + if (code != CM_ERROR_PARTIALWRITE + && code != CM_ERROR_BUFFERTOOSMALL + && code != CM_ERROR_GSSCONTINUE) { + /* nuke wct and bcc. For a partial + * write or an in-process authentication handshake, * assume they're OK. - */ - *outWctp++ = 0; - *outWctp++ = 0; - *outWctp++ = 0; - } - smbp->rcls = (unsigned char) (NTStatus & 0xff); - smbp->reh = (unsigned char) ((NTStatus >> 8) & 0xff); - smbp->errLow = (unsigned char) ((NTStatus >> 16) & 0xff); - smbp->errHigh = (unsigned char) ((NTStatus >> 24) & 0xff); - smbp->flg2 |= 0x4000; - break; - } - else { + */ + *outWctp++ = 0; + *outWctp++ = 0; + *outWctp++ = 0; + } + smbp->rcls = (unsigned char) (NTStatus & 0xff); + smbp->reh = (unsigned char) ((NTStatus >> 8) & 0xff); + smbp->errLow = (unsigned char) ((NTStatus >> 16) & 0xff); + smbp->errHigh = (unsigned char) ((NTStatus >> 24) & 0xff); + smbp->flg2 |= 0x4000; + break; + } + else { smb_MapCoreError(code, vcp, &errCode, &errClass); - outWctp = outp->wctp; - smbp = (smb_t *) &outp->data; - if (code != CM_ERROR_PARTIALWRITE) { - /* nuke wct and bcc. For a partial - * write, assume they're OK. - */ - *outWctp++ = 0; - *outWctp++ = 0; - *outWctp++ = 0; - } - smbp->errLow = (unsigned char) (errCode & 0xff); - smbp->errHigh = (unsigned char) ((errCode >> 8) & 0xff); + outWctp = outp->wctp; + smbp = (smb_t *) &outp->data; + if (code != CM_ERROR_PARTIALWRITE) { + /* nuke wct and bcc. For a partial + * write, assume they're OK. + */ + *outWctp++ = 0; + *outWctp++ = 0; + *outWctp++ = 0; + } + smbp->errLow = (unsigned char) (errCode & 0xff); + smbp->errHigh = (unsigned char) ((errCode >> 8) & 0xff); smbp->rcls = errClass; - break; - } - } /* error occurred */ - + break; + } + } /* error occurred */ + /* if we're here, we've finished one request. Look to see if - * this is a chained opcode. If it is, setup things to process - * the chained request, and setup the output buffer to hold the - * chained response. Start by finding the next input record. + * this is a chained opcode. If it is, setup things to process + * the chained request, and setup the output buffer to hold the + * chained response. Start by finding the next input record. */ if (!(dp->flags & SMB_DISPATCHFLAG_CHAINED)) break; /* not a chained req */ @@ -6168,7 +6339,7 @@ void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp, /* and now append the next output request to the end of this * last request. Begin by finding out where the last response - * ends, since that's where we'll put our new response. + * ends, since that's where we'll put our new response. */ outWctp = outp->wctp; /* ptr to out parameters */ osi_assert (outWctp[0] >= 2); /* need this for all chained requests */ @@ -6176,35 +6347,35 @@ void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp, tp = outWctp + nparms + 1; /* now points to bcc field */ nbytes = tp[0] + (tp[1] << 8); /* # of data bytes */ tp += 2 /* for the count itself */ + nbytes; - /* tp now points to the new output record; go back and patch the + /* tp now points to the new output record; go back and patch the * second parameter (off2) to point to the new record. */ - temp = (unsigned int)tp - ((unsigned int) outp->data); + temp = (unsigned int)tp - ((unsigned int) outp->data); outWctp[3] = (unsigned char) (temp & 0xff); outWctp[4] = (unsigned char) ((temp >> 8) & 0xff); outWctp[2] = 0; /* padding */ outWctp[1] = inp->inCom; /* next opcode */ - /* finally, setup for the next iteration */ + /* finally, setup for the next iteration */ outp->wctp = tp; - outWctp = tp; - } /* while loop over all requests in the packet */ + outWctp = tp; + } /* while loop over all requests in the packet */ - /* done logging out, turn off logging-out flag */ - if (!(inp->flags & SMB_PACKETFLAG_PROFILE_UPDATE_OK)) { - vcp->justLoggedOut = NULL; - if (loggedOut) { - loggedOut = 0; - free(loggedOutName); - loggedOutName = NULL; - smb_ReleaseUID(loggedOutUserp); - loggedOutUserp = NULL; - } - } + /* done logging out, turn off logging-out flag */ + if (!(inp->flags & SMB_PACKETFLAG_PROFILE_UPDATE_OK)) { + vcp->justLoggedOut = NULL; + if (loggedOut) { + loggedOut = 0; + free(loggedOutName); + loggedOutName = NULL; + smb_ReleaseUID(loggedOutUserp); + loggedOutUserp = NULL; + } + } /* now send the output packet, and return */ if (!noSend) - smb_SendPacket(vcp, outp); + smb_SendPacket(vcp, outp); thrd_Decrement(&ongoingOps); if (!(vcp->flags & SMB_VCFLAG_ALREADYDEAD)) { @@ -6214,12 +6385,12 @@ void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp, "Replacing active_vcp %x with %x", active_vcp, vcp); } smb_HoldVC(vcp); - active_vcp = vcp; - last_msg_time = GetCurrentTime(); - } + active_vcp = vcp; + last_msg_time = GetCurrentTime(); + } else if (active_vcp == vcp) { - smb_ReleaseVC(active_vcp); - active_vcp = NULL; + smb_ReleaseVC(active_vcp); + active_vcp = NULL; } return; @@ -6929,7 +7100,7 @@ void smb_Listener(void *parmp) fprintf(stderr, "New session(ncb_lsn,ncb_lana_num) %d,%d starting from host " "%s\n", ncbp->ncb_lsn,ncbp->ncb_lana_num, rname); -#endif +#endif /* NOTSERVICE */ osi_Log4(smb_logp, "New session(ncb_lsn,ncb_lana_num) (%d,%d) starting from host %s, %d ongoing ops", ncbp->ncb_lsn,ncbp->ncb_lana_num, osi_LogSaveString(smb_logp, rname), ongoingOps); @@ -7341,100 +7512,112 @@ void smb_Init(osi_log_t *logp, char *snamep, int useV3, int LANadapt, retHandle = thrd_CreateEvent(NULL, FALSE, FALSE, eventName); if ( GetLastError() == ERROR_ALREADY_EXISTS ) afsi_log("Event Object Already Exists: %s", eventName); - for (i = 0; i < smb_NumServerThreads; i++) { - NCBreturns[i] = malloc(NCBmax * sizeof(EVENT_HANDLE)); - NCBreturns[i][0] = retHandle; - } - for (i = 1; i <= nThreads; i++) - InitNCBslot(i); - numNCBs = nThreads + 1; + for (i = 0; i < smb_NumServerThreads; i++) { + NCBreturns[i] = malloc(NCBmax * sizeof(EVENT_HANDLE)); + NCBreturns[i][0] = retHandle; + } + for (i = 1; i <= nThreads; i++) + InitNCBslot(i); + numNCBs = nThreads + 1; - /* Initialize dispatch table */ - memset(&smb_dispatchTable, 0, sizeof(smb_dispatchTable)); - smb_dispatchTable[0x00].procp = smb_ReceiveCoreMakeDir; - smb_dispatchTable[0x01].procp = smb_ReceiveCoreRemoveDir; - smb_dispatchTable[0x02].procp = smb_ReceiveCoreOpen; - smb_dispatchTable[0x03].procp = smb_ReceiveCoreCreate; - smb_dispatchTable[0x04].procp = smb_ReceiveCoreClose; - smb_dispatchTable[0x05].procp = smb_ReceiveCoreFlush; - smb_dispatchTable[0x06].procp = smb_ReceiveCoreUnlink; - smb_dispatchTable[0x07].procp = smb_ReceiveCoreRename; - smb_dispatchTable[0x08].procp = smb_ReceiveCoreGetFileAttributes; - smb_dispatchTable[0x09].procp = smb_ReceiveCoreSetFileAttributes; - smb_dispatchTable[0x0a].procp = smb_ReceiveCoreRead; - smb_dispatchTable[0x0b].procp = smb_ReceiveCoreWrite; - smb_dispatchTable[0x0c].procp = smb_ReceiveCoreLockRecord; - smb_dispatchTable[0x0d].procp = smb_ReceiveCoreUnlockRecord; - smb_dispatchTable[0x0e].procp = smb_SendCoreBadOp; /* create temporary */ - smb_dispatchTable[0x0f].procp = smb_ReceiveCoreCreate; - smb_dispatchTable[0x10].procp = smb_ReceiveCoreCheckPath; - smb_dispatchTable[0x11].procp = smb_SendCoreBadOp; /* process exit */ - smb_dispatchTable[0x12].procp = smb_ReceiveCoreSeek; - smb_dispatchTable[0x1a].procp = smb_ReceiveCoreReadRaw; - /* Set NORESPONSE because smb_ReceiveCoreReadRaw() does the responses itself */ - smb_dispatchTable[0x1a].flags |= SMB_DISPATCHFLAG_NORESPONSE; - smb_dispatchTable[0x1d].procp = smb_ReceiveCoreWriteRawDummy; - smb_dispatchTable[0x22].procp = smb_ReceiveV3SetAttributes; - smb_dispatchTable[0x23].procp = smb_ReceiveV3GetAttributes; - smb_dispatchTable[0x24].procp = smb_ReceiveV3LockingX; - smb_dispatchTable[0x24].flags |= SMB_DISPATCHFLAG_CHAINED; - smb_dispatchTable[0x25].procp = smb_ReceiveV3Trans; - smb_dispatchTable[0x25].flags |= SMB_DISPATCHFLAG_NORESPONSE; - smb_dispatchTable[0x26].procp = smb_ReceiveV3Trans; - smb_dispatchTable[0x26].flags |= SMB_DISPATCHFLAG_NORESPONSE; - smb_dispatchTable[0x29].procp = smb_SendCoreBadOp; /* copy file */ - smb_dispatchTable[0x2b].procp = smb_ReceiveCoreEcho; - /* Set NORESPONSE because smb_ReceiveCoreEcho() does the responses itself */ - smb_dispatchTable[0x2b].flags |= SMB_DISPATCHFLAG_NORESPONSE; + /* Initialize dispatch table */ + memset(&smb_dispatchTable, 0, sizeof(smb_dispatchTable)); + /* Prepare the table for unknown operations */ + for(i=0; i<= SMB_NOPCODES; i++) { + smb_dispatchTable[i].procp = smb_SendCoreBadOp; + } + /* Fill in the ones we do know */ + smb_dispatchTable[0x00].procp = smb_ReceiveCoreMakeDir; + smb_dispatchTable[0x01].procp = smb_ReceiveCoreRemoveDir; + smb_dispatchTable[0x02].procp = smb_ReceiveCoreOpen; + smb_dispatchTable[0x03].procp = smb_ReceiveCoreCreate; + smb_dispatchTable[0x04].procp = smb_ReceiveCoreClose; + smb_dispatchTable[0x05].procp = smb_ReceiveCoreFlush; + smb_dispatchTable[0x06].procp = smb_ReceiveCoreUnlink; + smb_dispatchTable[0x07].procp = smb_ReceiveCoreRename; + smb_dispatchTable[0x08].procp = smb_ReceiveCoreGetFileAttributes; + smb_dispatchTable[0x09].procp = smb_ReceiveCoreSetFileAttributes; + smb_dispatchTable[0x0a].procp = smb_ReceiveCoreRead; + smb_dispatchTable[0x0b].procp = smb_ReceiveCoreWrite; + smb_dispatchTable[0x0c].procp = smb_ReceiveCoreLockRecord; + smb_dispatchTable[0x0d].procp = smb_ReceiveCoreUnlockRecord; + smb_dispatchTable[0x0e].procp = smb_SendCoreBadOp; /* create temporary */ + smb_dispatchTable[0x0f].procp = smb_ReceiveCoreCreate; + smb_dispatchTable[0x10].procp = smb_ReceiveCoreCheckPath; + smb_dispatchTable[0x11].procp = smb_SendCoreBadOp; /* process exit */ + smb_dispatchTable[0x12].procp = smb_ReceiveCoreSeek; + smb_dispatchTable[0x1a].procp = smb_ReceiveCoreReadRaw; + /* Set NORESPONSE because smb_ReceiveCoreReadRaw() does the responses itself */ + smb_dispatchTable[0x1a].flags |= SMB_DISPATCHFLAG_NORESPONSE; + smb_dispatchTable[0x1d].procp = smb_ReceiveCoreWriteRawDummy; + smb_dispatchTable[0x22].procp = smb_ReceiveV3SetAttributes; + smb_dispatchTable[0x23].procp = smb_ReceiveV3GetAttributes; + smb_dispatchTable[0x24].procp = smb_ReceiveV3LockingX; + smb_dispatchTable[0x24].flags |= SMB_DISPATCHFLAG_CHAINED; + smb_dispatchTable[0x25].procp = smb_ReceiveV3Trans; + smb_dispatchTable[0x25].flags |= SMB_DISPATCHFLAG_NORESPONSE; + smb_dispatchTable[0x26].procp = smb_ReceiveV3Trans; + smb_dispatchTable[0x26].flags |= SMB_DISPATCHFLAG_NORESPONSE; + smb_dispatchTable[0x29].procp = smb_SendCoreBadOp; /* copy file */ + smb_dispatchTable[0x2b].procp = smb_ReceiveCoreEcho; + /* Set NORESPONSE because smb_ReceiveCoreEcho() does the responses itself */ + smb_dispatchTable[0x2b].flags |= SMB_DISPATCHFLAG_NORESPONSE; smb_dispatchTable[0x2d].procp = smb_ReceiveV3OpenX; smb_dispatchTable[0x2d].flags |= SMB_DISPATCHFLAG_CHAINED; smb_dispatchTable[0x2e].procp = smb_ReceiveV3ReadX; smb_dispatchTable[0x2e].flags |= SMB_DISPATCHFLAG_CHAINED; - smb_dispatchTable[0x32].procp = smb_ReceiveV3Tran2A; /* both are same */ + smb_dispatchTable[0x32].procp = smb_ReceiveV3Tran2A; /* both are same */ smb_dispatchTable[0x32].flags |= SMB_DISPATCHFLAG_NORESPONSE; smb_dispatchTable[0x33].procp = smb_ReceiveV3Tran2A; smb_dispatchTable[0x33].flags |= SMB_DISPATCHFLAG_NORESPONSE; smb_dispatchTable[0x34].procp = smb_ReceiveV3FindClose; smb_dispatchTable[0x35].procp = smb_ReceiveV3FindNotifyClose; - smb_dispatchTable[0x70].procp = smb_ReceiveCoreTreeConnect; - smb_dispatchTable[0x71].procp = smb_ReceiveCoreTreeDisconnect; - smb_dispatchTable[0x72].procp = smb_ReceiveNegotiate; - smb_dispatchTable[0x73].procp = smb_ReceiveV3SessionSetupX; + smb_dispatchTable[0x70].procp = smb_ReceiveCoreTreeConnect; + smb_dispatchTable[0x71].procp = smb_ReceiveCoreTreeDisconnect; + smb_dispatchTable[0x72].procp = smb_ReceiveNegotiate; + smb_dispatchTable[0x73].procp = smb_ReceiveV3SessionSetupX; smb_dispatchTable[0x73].flags |= SMB_DISPATCHFLAG_CHAINED; smb_dispatchTable[0x74].procp = smb_ReceiveV3UserLogoffX; smb_dispatchTable[0x74].flags |= SMB_DISPATCHFLAG_CHAINED; smb_dispatchTable[0x75].procp = smb_ReceiveV3TreeConnectX; smb_dispatchTable[0x75].flags |= SMB_DISPATCHFLAG_CHAINED; - smb_dispatchTable[0x80].procp = smb_ReceiveCoreGetDiskAttributes; - smb_dispatchTable[0x81].procp = smb_ReceiveCoreSearchDir; - smb_dispatchTable[0xA0].procp = smb_ReceiveNTTransact; - smb_dispatchTable[0xA2].procp = smb_ReceiveNTCreateX; - smb_dispatchTable[0xA2].flags |= SMB_DISPATCHFLAG_CHAINED; - smb_dispatchTable[0xA4].procp = smb_ReceiveNTCancel; - smb_dispatchTable[0xA4].flags |= SMB_DISPATCHFLAG_NORESPONSE; - smb_dispatchTable[0xc0].procp = smb_SendCoreBadOp; - smb_dispatchTable[0xc1].procp = smb_SendCoreBadOp; - smb_dispatchTable[0xc2].procp = smb_SendCoreBadOp; - smb_dispatchTable[0xc3].procp = smb_SendCoreBadOp; - for(i=0xd0; i<= 0xd7; i++) { - smb_dispatchTable[i].procp = smb_SendCoreBadOp; - } + smb_dispatchTable[0x80].procp = smb_ReceiveCoreGetDiskAttributes; + smb_dispatchTable[0x81].procp = smb_ReceiveCoreSearchDir; + smb_dispatchTable[0x82].procp = smb_SendCoreBadOp; /* Find */ + smb_dispatchTable[0x83].procp = smb_SendCoreBadOp; /* Find Unique */ + smb_dispatchTable[0x84].procp = smb_SendCoreBadOp; /* Find Close */ + smb_dispatchTable[0xA0].procp = smb_ReceiveNTTransact; + smb_dispatchTable[0xA2].procp = smb_ReceiveNTCreateX; + smb_dispatchTable[0xA2].flags |= SMB_DISPATCHFLAG_CHAINED; + smb_dispatchTable[0xA4].procp = smb_ReceiveNTCancel; + smb_dispatchTable[0xA4].flags |= SMB_DISPATCHFLAG_NORESPONSE; + smb_dispatchTable[0xA5].procp = smb_ReceiveNTRename; + smb_dispatchTable[0xc0].procp = smb_SendCoreBadOp; /* Open Print File */ + smb_dispatchTable[0xc1].procp = smb_SendCoreBadOp; /* Write Print File */ + smb_dispatchTable[0xc2].procp = smb_SendCoreBadOp; /* Close Print File */ + smb_dispatchTable[0xc3].procp = smb_SendCoreBadOp; /* Get Print Queue */ + smb_dispatchTable[0xD8].procp = smb_SendCoreBadOp; /* Read Bulk */ + smb_dispatchTable[0xD9].procp = smb_SendCoreBadOp; /* Write Bulk */ + smb_dispatchTable[0xDA].procp = smb_SendCoreBadOp; /* Write Bulk Data */ - /* setup tran 2 dispatch table */ - smb_tran2DispatchTable[0].procp = smb_ReceiveTran2Open; - smb_tran2DispatchTable[1].procp = smb_ReceiveTran2SearchDir; /* FindFirst */ - smb_tran2DispatchTable[2].procp = smb_ReceiveTran2SearchDir; /* FindNext */ - smb_tran2DispatchTable[3].procp = smb_ReceiveTran2QFSInfo; - smb_tran2DispatchTable[4].procp = smb_ReceiveTran2SetFSInfo; - smb_tran2DispatchTable[5].procp = smb_ReceiveTran2QPathInfo; - smb_tran2DispatchTable[6].procp = smb_ReceiveTran2SetPathInfo; - smb_tran2DispatchTable[7].procp = smb_ReceiveTran2QFileInfo; - smb_tran2DispatchTable[8].procp = smb_ReceiveTran2SetFileInfo; - smb_tran2DispatchTable[9].procp = smb_ReceiveTran2FSCTL; - smb_tran2DispatchTable[10].procp = smb_ReceiveTran2IOCTL; - smb_tran2DispatchTable[11].procp = smb_ReceiveTran2FindNotifyFirst; - smb_tran2DispatchTable[12].procp = smb_ReceiveTran2FindNotifyNext; - smb_tran2DispatchTable[13].procp = smb_ReceiveTran2MKDir; + /* setup tran 2 dispatch table */ + smb_tran2DispatchTable[0].procp = smb_ReceiveTran2Open; + smb_tran2DispatchTable[1].procp = smb_ReceiveTran2SearchDir; /* FindFirst */ + smb_tran2DispatchTable[2].procp = smb_ReceiveTran2SearchDir; /* FindNext */ + smb_tran2DispatchTable[3].procp = smb_ReceiveTran2QFSInfo; + smb_tran2DispatchTable[4].procp = smb_ReceiveTran2SetFSInfo; + smb_tran2DispatchTable[5].procp = smb_ReceiveTran2QPathInfo; + smb_tran2DispatchTable[6].procp = smb_ReceiveTran2SetPathInfo; + smb_tran2DispatchTable[7].procp = smb_ReceiveTran2QFileInfo; + smb_tran2DispatchTable[8].procp = smb_ReceiveTran2SetFileInfo; + smb_tran2DispatchTable[9].procp = smb_ReceiveTran2FSCTL; + smb_tran2DispatchTable[10].procp = smb_ReceiveTran2IOCTL; + smb_tran2DispatchTable[11].procp = smb_ReceiveTran2FindNotifyFirst; + smb_tran2DispatchTable[12].procp = smb_ReceiveTran2FindNotifyNext; + smb_tran2DispatchTable[13].procp = smb_ReceiveTran2CreateDirectory; + smb_tran2DispatchTable[14].procp = smb_ReceiveTran2SessionSetup; + smb_tran2DispatchTable[14].procp = smb_ReceiveTran2GetDFSReferral; + smb_tran2DispatchTable[14].procp = smb_ReceiveTran2ReportDFSInconsistency; /* setup the rap dispatch table */ memset(smb_rapDispatchTable, 0, sizeof(smb_rapDispatchTable)); @@ -7443,45 +7626,45 @@ void smb_Init(osi_log_t *logp, char *snamep, int useV3, int LANadapt, smb_rapDispatchTable[63].procp = smb_ReceiveRAPNetWkstaGetInfo; smb_rapDispatchTable[13].procp = smb_ReceiveRAPNetServerGetInfo; - smb3_Init(); + smb3_Init(); - /* if we are doing SMB authentication we have register outselves as a logon process */ - if (smb_authType != SMB_AUTH_NONE) { + /* if we are doing SMB authentication we have register outselves as a logon process */ + if (smb_authType != SMB_AUTH_NONE) { NTSTATUS nts; - LSA_STRING afsProcessName; - LSA_OPERATIONAL_MODE dummy; /*junk*/ + LSA_STRING afsProcessName; + LSA_OPERATIONAL_MODE dummy; /*junk*/ - afsProcessName.Buffer = "OpenAFSClientDaemon"; - afsProcessName.Length = strlen(afsProcessName.Buffer); - afsProcessName.MaximumLength = afsProcessName.Length + 1; + afsProcessName.Buffer = "OpenAFSClientDaemon"; + afsProcessName.Length = strlen(afsProcessName.Buffer); + afsProcessName.MaximumLength = afsProcessName.Length + 1; - nts = LsaRegisterLogonProcess(&afsProcessName, &smb_lsaHandle, &dummy); + nts = LsaRegisterLogonProcess(&afsProcessName, &smb_lsaHandle, &dummy); - if (nts == STATUS_SUCCESS) { - LSA_STRING packageName; - /* we are registered. Find out the security package id */ - packageName.Buffer = MSV1_0_PACKAGE_NAME; - packageName.Length = strlen(packageName.Buffer); - packageName.MaximumLength = packageName.Length + 1; - nts = LsaLookupAuthenticationPackage(smb_lsaHandle, &packageName , &smb_lsaSecPackage); - if (nts == STATUS_SUCCESS) { - smb_lsaLogonOrigin.Buffer = "OpenAFS"; - smb_lsaLogonOrigin.Length = strlen(smb_lsaLogonOrigin.Buffer); - smb_lsaLogonOrigin.MaximumLength = smb_lsaLogonOrigin.Length + 1; - } else { - afsi_log("Can't determine security package name for NTLM!! NTSTATUS=[%l]",nts); - } - } else { - afsi_log("Can't register logon process!! NTSTATUS=[%l]",nts); - } + if (nts == STATUS_SUCCESS) { + LSA_STRING packageName; + /* we are registered. Find out the security package id */ + packageName.Buffer = MSV1_0_PACKAGE_NAME; + packageName.Length = strlen(packageName.Buffer); + packageName.MaximumLength = packageName.Length + 1; + nts = LsaLookupAuthenticationPackage(smb_lsaHandle, &packageName , &smb_lsaSecPackage); + if (nts == STATUS_SUCCESS) { + smb_lsaLogonOrigin.Buffer = "OpenAFS"; + smb_lsaLogonOrigin.Length = strlen(smb_lsaLogonOrigin.Buffer); + smb_lsaLogonOrigin.MaximumLength = smb_lsaLogonOrigin.Length + 1; + } else { + afsi_log("Can't determine security package name for NTLM!! NTSTATUS=[%l]",nts); + } + } else { + afsi_log("Can't register logon process!! NTSTATUS=[%l]",nts); + } - if (nts != STATUS_SUCCESS) { - /* something went wrong. We report the error and revert back to no authentication - because we can't perform any auth requests without a successful lsa handle - or sec package id. */ - afsi_log("Reverting to NO SMB AUTH"); - smb_authType = SMB_AUTH_NONE; - } + if (nts != STATUS_SUCCESS) { + /* something went wrong. We report the error and revert back to no authentication + because we can't perform any auth requests without a successful lsa handle + or sec package id. */ + afsi_log("Reverting to NO SMB AUTH"); + smb_authType = SMB_AUTH_NONE; + } #ifdef COMMENT /* Don't fallback to SMB_AUTH_NTLM. Apparently, allowing SPNEGO to be used each * time prevents the failure of authentication when logged into Windows with an @@ -7645,8 +7828,8 @@ char *smb_GetSharename() return name; } -#ifdef NOTSERVICE +#ifdef LOG_PACKET void smb_LogPacket(smb_packet_t *packet) { BYTE *vp, *cp; @@ -7701,14 +7884,14 @@ void smb_LogPacket(smb_packet_t *packet) *cp = 0; - osi_Log0( smb_logp, buf ); + osi_Log0( smb_logp, osi_LogSaveString(smb_logp, buf)); } osi_Log0(smb_logp, "*** End SMB packet dump ***"); } +#endif /* LOG_PACKET */ -#endif /* NOTSERVICE */ int smb_DumpVCP(FILE *outputFile, char *cookie) { diff --git a/src/WINNT/afsd/smb.h b/src/WINNT/afsd/smb.h index 4f9bd33fd4..4e83730fa1 100644 --- a/src/WINNT/afsd/smb.h +++ b/src/WINNT/afsd/smb.h @@ -561,6 +561,10 @@ extern long smb_ReadData(smb_fid_t *fidp, osi_hyper_t *offsetp, long count, char *op, cm_user_t *userp, long *readp, int dosflag); #endif /* !DJGPP */ +extern long smb_Rename(smb_vc_t *vcp, smb_packet_t *inp, char *oldPathp, char *newPathp, int attrs); + +extern long smb_Link(smb_vc_t *vcp, smb_packet_t *inp, char *oldPathp, char *newPathp); + extern BOOL smb_IsLegalFilename(char *filename); extern char *smb_GetSharename(void); diff --git a/src/WINNT/afsd/smb3.c b/src/WINNT/afsd/smb3.c index 5b43ef969c..117b729479 100644 --- a/src/WINNT/afsd/smb3.c +++ b/src/WINNT/afsd/smb3.c @@ -800,8 +800,8 @@ long smb_ReceiveV3SessionSetupX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t * unp = uidp->unp; userp = unp->userp; newUid = (unsigned short)uidp->userID; /* For some reason these are different types!*/ - osi_LogEvent("AFS smb_ReceiveV3SessionSetupX",NULL,"FindUserByName:Lana[%d],lsn[%d],userid[%d],name[%s]",vcp->lana,vcp->lsn,newUid,osi_LogSaveString(smb_logp, usern)); - osi_Log3(smb_logp,"smb_ReceiveV3SessionSetupX FindUserByName:Lana[%d],lsn[%d],userid[%d]",vcp->lana,vcp->lsn,newUid); + osi_LogEvent("AFS smb_ReceiveV3SessionSetupX",NULL,"FindUserByName:Lana[%d],lsn[%d],userid[%d],name[%s]",vcp->lana,vcp->lsn,newUid,osi_LogSaveString(smb_logp, usern)); + osi_Log3(smb_logp,"smb_ReceiveV3SessionSetupX FindUserByName:Lana[%d],lsn[%d],userid[%d]",vcp->lana,vcp->lsn,newUid); smb_ReleaseUID(uidp); } else { @@ -826,8 +826,8 @@ long smb_ReceiveV3SessionSetupX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t * uidp = smb_FindUID(vcp, newUid, SMB_FLAG_CREATE); lock_ObtainMutex(&uidp->mx); uidp->unp = unp; - osi_LogEvent("AFS smb_ReceiveV3SessionSetupX",NULL,"MakeNewUser:VCP[%x],Lana[%d],lsn[%d],userid[%d],TicketKTCName[%s]",(int)vcp,vcp->lana,vcp->lsn,newUid,osi_LogSaveString(smb_logp, usern)); - osi_Log4(smb_logp,"smb_ReceiveV3SessionSetupX MakeNewUser:VCP[%x],Lana[%d],lsn[%d],userid[%d]",vcp,vcp->lana,vcp->lsn,newUid); + osi_LogEvent("AFS smb_ReceiveV3SessionSetupX",NULL,"MakeNewUser:VCP[%x],Lana[%d],lsn[%d],userid[%d],TicketKTCName[%s]",(int)vcp,vcp->lana,vcp->lsn,newUid,osi_LogSaveString(smb_logp, usern)); + osi_Log4(smb_logp,"smb_ReceiveV3SessionSetupX MakeNewUser:VCP[%x],Lana[%d],lsn[%d],userid[%d]",vcp,vcp->lana,vcp->lsn,newUid); lock_ReleaseMutex(&uidp->mx); smb_ReleaseUID(uidp); } @@ -881,35 +881,35 @@ long smb_ReceiveV3SessionSetupX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t * long smb_ReceiveV3UserLogoffX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) { - smb_user_t *uidp; + smb_user_t *uidp; - /* don't get tokens from this VC */ - vcp->flags |= SMB_VCFLAG_ALREADYDEAD; + /* don't get tokens from this VC */ + vcp->flags |= SMB_VCFLAG_ALREADYDEAD; - inp->flags |= SMB_PACKETFLAG_PROFILE_UPDATE_OK; + inp->flags |= SMB_PACKETFLAG_PROFILE_UPDATE_OK; - /* find the tree and free it */ + /* find the tree and free it */ uidp = smb_FindUID(vcp, ((smb_t *)inp)->uid, 0); /* TODO: smb_ReleaseUID() ? */ if (uidp) { - char *s1 = NULL, *s2 = NULL; + char *s1 = NULL, *s2 = NULL; - if (s2 == NULL) s2 = " "; - if (s1 == NULL) {s1 = s2; s2 = " ";} + if (s2 == NULL) s2 = " "; + if (s1 == NULL) {s1 = s2; s2 = " ";} - osi_Log4(smb_logp, "SMB3 user logoffX uid %d name %s%s%s", uidp->userID, - osi_LogSaveString(smb_logp, (uidp->unp) ? uidp->unp->name: " "), s1, s2); + osi_Log4(smb_logp, "SMB3 user logoffX uid %d name %s%s%s", uidp->userID, + osi_LogSaveString(smb_logp, (uidp->unp) ? uidp->unp->name: " "), s1, s2); - lock_ObtainMutex(&uidp->mx); - uidp->flags |= SMB_USERFLAG_DELETE; - /* - * it doesn't get deleted right away - * because the vcp points to it - */ + lock_ObtainMutex(&uidp->mx); + uidp->flags |= SMB_USERFLAG_DELETE; + /* + * it doesn't get deleted right away + * because the vcp points to it + */ lock_ReleaseMutex(&uidp->mx); } - else - osi_Log0(smb_logp, "SMB3 user logoffX"); + else + osi_Log0(smb_logp, "SMB3 user logoffX"); smb_SetSMBDataLength(outp, 0); return 0; @@ -923,89 +923,89 @@ long smb_ReceiveV3TreeConnectX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *o smb_user_t *uidp; unsigned short newTid; char shareName[256]; - char *sharePath; - int shareFound; + char *sharePath; + int shareFound; char *tp; char *pathp; char *passwordp; - char *servicep; + char *servicep; cm_user_t *userp; - int ipc = 0; + int ipc = 0; - osi_Log0(smb_logp, "SMB3 receive tree connect"); + osi_Log0(smb_logp, "SMB3 receive tree connect"); - /* parse input parameters */ - tp = smb_GetSMBData(inp, NULL); + /* parse input parameters */ + tp = smb_GetSMBData(inp, NULL); passwordp = smb_ParseString(tp, &tp); - pathp = smb_ParseString(tp, &tp); - servicep = smb_ParseString(tp, &tp); + pathp = smb_ParseString(tp, &tp); + servicep = smb_ParseString(tp, &tp); - tp = strrchr(pathp, '\\'); + tp = strrchr(pathp, '\\'); if (!tp) { return CM_ERROR_BADSMB; } strcpy(shareName, tp+1); osi_Log2(smb_logp, "Tree connect pathp[%s] shareName[%s]", - osi_LogSaveString(smb_logp, pathp), - osi_LogSaveString(smb_logp, shareName)); + osi_LogSaveString(smb_logp, pathp), + osi_LogSaveString(smb_logp, shareName)); - if (strcmp(servicep, "IPC") == 0 || strcmp(shareName, "IPC$") == 0) { + if (strcmp(servicep, "IPC") == 0 || strcmp(shareName, "IPC$") == 0) { #ifndef NO_IPC - osi_Log0(smb_logp, "TreeConnectX connecting to IPC$"); - ipc = 1; + osi_Log0(smb_logp, "TreeConnectX connecting to IPC$"); + ipc = 1; #else - return CM_ERROR_NOIPC; + return CM_ERROR_NOIPC; #endif - } + } userp = smb_GetUser(vcp, inp); - lock_ObtainMutex(&vcp->mx); + lock_ObtainMutex(&vcp->mx); newTid = vcp->tidCounter++; - lock_ReleaseMutex(&vcp->mx); + lock_ReleaseMutex(&vcp->mx); - tidp = smb_FindTID(vcp, newTid, SMB_FLAG_CREATE); + tidp = smb_FindTID(vcp, newTid, SMB_FLAG_CREATE); - if(!ipc) { - uidp = smb_FindUID(vcp, ((smb_t *)inp)->uid, 0); + if(!ipc) { + uidp = smb_FindUID(vcp, ((smb_t *)inp)->uid, 0); shareFound = smb_FindShare(vcp, uidp, shareName, &sharePath); - if (uidp) - smb_ReleaseUID(uidp); + if (uidp) + smb_ReleaseUID(uidp); if (!shareFound) { - smb_ReleaseTID(tidp); - return CM_ERROR_BADSHARENAME; + smb_ReleaseTID(tidp); + return CM_ERROR_BADSHARENAME; } if (vcp->flags & SMB_VCFLAG_USENT) - { - int policy = smb_FindShareCSCPolicy(shareName); - smb_SetSMBParm(outp, 2, SMB_SUPPORT_SEARCH_BITS | (policy << 2)); + { + int policy = smb_FindShareCSCPolicy(shareName); + smb_SetSMBParm(outp, 2, SMB_SUPPORT_SEARCH_BITS | (policy << 2)); + } + } else { + smb_SetSMBParm(outp, 2, 0); + sharePath = NULL; } - } else { - smb_SetSMBParm(outp, 2, 0); - sharePath = NULL; - } lock_ObtainMutex(&tidp->mx); tidp->userp = userp; - tidp->pathname = sharePath; - if(ipc) tidp->flags |= SMB_TIDFLAG_IPC; + tidp->pathname = sharePath; + if(ipc) tidp->flags |= SMB_TIDFLAG_IPC; lock_ReleaseMutex(&tidp->mx); smb_ReleaseTID(tidp); - ((smb_t *)outp)->tid = newTid; - ((smb_t *)inp)->tid = newTid; - tp = smb_GetSMBData(outp, NULL); - if(!ipc) { - *tp++ = 'A'; - *tp++ = ':'; - *tp++ = 0; - smb_SetSMBDataLength(outp, 3); - } else { - strcpy(tp, "IPC"); - smb_SetSMBDataLength(outp, 4); - } + ((smb_t *)outp)->tid = newTid; + ((smb_t *)inp)->tid = newTid; + tp = smb_GetSMBData(outp, NULL); + if (!ipc) { + *tp++ = 'A'; + *tp++ = ':'; + *tp++ = 0; + smb_SetSMBDataLength(outp, 3); + } else { + strcpy(tp, "IPC"); + smb_SetSMBDataLength(outp, 4); + } osi_Log1(smb_logp, "SMB3 tree connect created ID %d", newTid); return 0; @@ -1014,12 +1014,12 @@ long smb_ReceiveV3TreeConnectX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *o /* must be called with global tran lock held */ smb_tran2Packet_t *smb_FindTran2Packet(smb_vc_t *vcp, smb_packet_t *inp) { - smb_tran2Packet_t *tp; + smb_tran2Packet_t *tp; smb_t *smbp; smbp = (smb_t *) inp->data; - for(tp = smb_tran2AssemblyQueuep; tp; tp = (smb_tran2Packet_t *) osi_QNext(&tp->q)) { - if (tp->vcp == vcp && tp->mid == smbp->mid && tp->tid == smbp->tid) + for (tp = smb_tran2AssemblyQueuep; tp; tp = (smb_tran2Packet_t *) osi_QNext(&tp->q)) { + if (tp->vcp == vcp && tp->mid == smbp->mid && tp->tid == smbp->tid) return tp; } return NULL; @@ -1028,11 +1028,11 @@ smb_tran2Packet_t *smb_FindTran2Packet(smb_vc_t *vcp, smb_packet_t *inp) smb_tran2Packet_t *smb_NewTran2Packet(smb_vc_t *vcp, smb_packet_t *inp, int totalParms, int totalData) { - smb_tran2Packet_t *tp; + smb_tran2Packet_t *tp; smb_t *smbp; smbp = (smb_t *) inp->data; - tp = malloc(sizeof(*tp)); + tp = malloc(sizeof(*tp)); memset(tp, 0, sizeof(*tp)); tp->vcp = vcp; smb_HoldVC(vcp); @@ -1043,63 +1043,63 @@ smb_tran2Packet_t *smb_NewTran2Packet(smb_vc_t *vcp, smb_packet_t *inp, tp->mid = smbp->mid; tp->uid = smbp->uid; tp->pid = smbp->pid; - tp->res[0] = smbp->res[0]; - osi_QAdd((osi_queue_t **)&smb_tran2AssemblyQueuep, &tp->q); - if (totalParms != 0) + tp->res[0] = smbp->res[0]; + osi_QAdd((osi_queue_t **)&smb_tran2AssemblyQueuep, &tp->q); + if (totalParms != 0) tp->parmsp = malloc(totalParms); - if (totalData != 0) + if (totalData != 0) tp->datap = malloc(totalData); - if (smbp->com == 0x25 || smbp->com == 0x26) - tp->com = 0x25; - else { - tp->opcode = smb_GetSMBParm(inp, 14); - tp->com = 0x32; - } - tp->flags |= SMB_TRAN2PFLAG_ALLOC; + if (smbp->com == 0x25 || smbp->com == 0x26) + tp->com = 0x25; + else { + tp->opcode = smb_GetSMBParm(inp, 14); + tp->com = 0x32; + } + tp->flags |= SMB_TRAN2PFLAG_ALLOC; return tp; } smb_tran2Packet_t *smb_GetTran2ResponsePacket(smb_vc_t *vcp, - smb_tran2Packet_t *inp, smb_packet_t *outp, - int totalParms, int totalData) + smb_tran2Packet_t *inp, smb_packet_t *outp, + int totalParms, int totalData) { - smb_tran2Packet_t *tp; - unsigned short parmOffset; - unsigned short dataOffset; - unsigned short dataAlign; + smb_tran2Packet_t *tp; + unsigned short parmOffset; + unsigned short dataOffset; + unsigned short dataAlign; - tp = malloc(sizeof(*tp)); + tp = malloc(sizeof(*tp)); memset(tp, 0, sizeof(*tp)); tp->vcp = NULL; tp->curData = tp->curParms = 0; tp->totalData = totalData; tp->totalParms = totalParms; - tp->oldTotalParms = totalParms; + tp->oldTotalParms = totalParms; tp->tid = inp->tid; tp->mid = inp->mid; tp->uid = inp->uid; tp->pid = inp->pid; - tp->res[0] = inp->res[0]; + tp->res[0] = inp->res[0]; tp->opcode = inp->opcode; - tp->com = inp->com; + tp->com = inp->com; - /* - * We calculate where the parameters and data will start. - * This calculation must parallel the calculation in - * smb_SendTran2Packet. - */ + /* + * We calculate where the parameters and data will start. + * This calculation must parallel the calculation in + * smb_SendTran2Packet. + */ - parmOffset = 10*2 + 35; - parmOffset++; /* round to even */ - tp->parmsp = (unsigned short *) (outp->data + parmOffset); + parmOffset = 10*2 + 35; + parmOffset++; /* round to even */ + tp->parmsp = (unsigned short *) (outp->data + parmOffset); - dataOffset = parmOffset + totalParms; - dataAlign = dataOffset & 2; /* quad-align */ - dataOffset += dataAlign; - tp->datap = outp->data + dataOffset; + dataOffset = parmOffset + totalParms; + dataAlign = dataOffset & 2; /* quad-align */ + dataOffset += dataAlign; + tp->datap = outp->data + dataOffset; return tp; -} +} /* free a tran2 packet; must be called with smb_globalLock held */ void smb_FreeTran2Packet(smb_tran2Packet_t *t2p) @@ -1328,7 +1328,7 @@ long smb_ReceiveV3Trans(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) code = CM_ERROR_BADOP; } - /* if an error is returned, we're supposed to send an error packet, + /* if an error is returned, we're supposed to send an error packet, * otherwise the dispatched function already did the data sending. * We give dispatched proc the responsibility since it knows how much * space to allocate. @@ -1337,20 +1337,20 @@ long smb_ReceiveV3Trans(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) smb_SendTran2Error(vcp, asp, outp, code); } - /* free the input tran 2 packet */ - lock_ObtainWrite(&smb_globalLock); + /* free the input tran 2 packet */ + lock_ObtainWrite(&smb_globalLock); smb_FreeTran2Packet(asp); - lock_ReleaseWrite(&smb_globalLock); + lock_ReleaseWrite(&smb_globalLock); } else if (firstPacket) { - /* the first packet in a multi-packet request, we need to send an + /* the first packet in a multi-packet request, we need to send an * ack to get more data. */ smb_SetSMBDataLength(outp, 0); smb_SendPacket(vcp, outp); } - return 0; + return 0; } /* ANSI versions. The unicode versions support arbitrary length @@ -1993,10 +1993,10 @@ long smb_ReceiveV3Tran2A(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) long smb_ReceiveTran2Open(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op) { - char *pathp; + char *pathp; smb_tran2Packet_t *outp; long code = 0; - cm_space_t *spacep; + cm_space_t *spacep; int excl; cm_user_t *userp; cm_scache_t *dscp; /* dir we're dealing with */ @@ -2014,26 +2014,26 @@ long smb_ReceiveTran2Open(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op) int openAction; int parmSlot; /* which parm we're dealing with */ long returnEALength; - char *tidPathp; - cm_req_t req; + char *tidPathp; + cm_req_t req; - cm_InitReq(&req); + cm_InitReq(&req); scp = NULL; - extraInfo = (p->parmsp[0] & 1); /* return extra info */ + extraInfo = (p->parmsp[0] & 1); /* return extra info */ returnEALength = (p->parmsp[0] & 8); /* return extended attr length */ - openFun = p->parmsp[6]; /* open function */ + openFun = p->parmsp[6]; /* open function */ excl = ((openFun & 3) == 0); trunc = ((openFun & 3) == 2); /* truncate it */ - openMode = (p->parmsp[1] & 0x7); + openMode = (p->parmsp[1] & 0x7); openAction = 0; /* tracks what we did */ attributes = p->parmsp[3]; dosTime = p->parmsp[4] | (p->parmsp[5] << 16); - /* compute initial mode bits based on read-only flag in attributes */ + /* compute initial mode bits based on read-only flag in attributes */ initialModeBits = 0666; if (attributes & 1) initialModeBits &= ~0222; @@ -2041,20 +2041,20 @@ long smb_ReceiveTran2Open(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op) outp = smb_GetTran2ResponsePacket(vcp, p, op, 40, 0); - spacep = cm_GetSpace(); + spacep = cm_GetSpace(); smb_StripLastComponent(spacep->data, &lastNamep, pathp); - if (lastNamep && strcmp(lastNamep, SMB_IOCTL_FILENAME) == 0) { - /* special case magic file name for receiving IOCTL requests + if (lastNamep && strcmp(lastNamep, SMB_IOCTL_FILENAME) == 0) { + /* special case magic file name for receiving IOCTL requests * (since IOCTL calls themselves aren't getting through). */ fidp = smb_FindFID(vcp, 0, SMB_FLAG_CREATE); smb_SetupIoctlFid(fidp, spacep); /* copy out remainder of the parms */ - parmSlot = 0; - outp->parmsp[parmSlot] = fidp->fid; parmSlot++; - if (extraInfo) { + parmSlot = 0; + outp->parmsp[parmSlot] = fidp->fid; parmSlot++; + if (extraInfo) { outp->parmsp[parmSlot] = /* attrs */ 0; parmSlot++; outp->parmsp[parmSlot] = 0; parmSlot++; /* mod time */ outp->parmsp[parmSlot] = 0; parmSlot++; @@ -2063,17 +2063,17 @@ long smb_ReceiveTran2Open(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op) outp->parmsp[parmSlot] = openMode; parmSlot++; outp->parmsp[parmSlot] = 0; parmSlot++; /* file type 0 ==> normal file or dir */ outp->parmsp[parmSlot] = 0; parmSlot++; /* IPC junk */ - } - /* and the final "always present" stuff */ + } + /* and the final "always present" stuff */ outp->parmsp[parmSlot] = /* openAction found existing file */ 1; parmSlot++; - /* next write out the "unique" ID */ - outp->parmsp[parmSlot] = 0x1234; parmSlot++; - outp->parmsp[parmSlot] = 0x5678; parmSlot++; + /* next write out the "unique" ID */ + outp->parmsp[parmSlot] = 0x1234; parmSlot++; + outp->parmsp[parmSlot] = 0x5678; parmSlot++; outp->parmsp[parmSlot] = 0; parmSlot++; - if (returnEALength) { - outp->parmsp[parmSlot] = 0; parmSlot++; - outp->parmsp[parmSlot] = 0; parmSlot++; - } + if (returnEALength) { + outp->parmsp[parmSlot] = 0; parmSlot++; + outp->parmsp[parmSlot] = 0; parmSlot++; + } outp->totalData = 0; outp->totalParms = parmSlot * 2; @@ -2082,22 +2082,22 @@ long smb_ReceiveTran2Open(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op) smb_FreeTran2Packet(outp); - /* and clean up fid reference */ + /* and clean up fid reference */ smb_ReleaseFID(fidp); return 0; } #ifdef DEBUG_VERBOSE - { - char *hexp, *asciip; - asciip = (lastNamep ? lastNamep : pathp); - hexp = osi_HexifyString( asciip ); - DEBUG_EVENT2("AFS","T2Open H[%s] A[%s]", hexp, asciip); - free(hexp); - } + { + char *hexp, *asciip; + asciip = (lastNamep ? lastNamep : pathp); + hexp = osi_HexifyString( asciip ); + DEBUG_EVENT2("AFS","T2Open H[%s] A[%s]", hexp, asciip); + free(hexp); + } #endif - userp = smb_GetTran2User(vcp, p); + userp = smb_GetTran2User(vcp, p); /* In the off chance that userp is NULL, we log and abandon */ if (!userp) { osi_Log1(smb_logp, "ReceiveTran2Open user [%d] not resolvable", p->uid); @@ -2105,8 +2105,8 @@ long smb_ReceiveTran2Open(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op) return CM_ERROR_BADSMB; } - code = smb_LookupTIDPath(vcp, p->tid, &tidPathp); - if(code == CM_ERROR_TIDIPC) { + code = smb_LookupTIDPath(vcp, p->tid, &tidPathp); + if (code == CM_ERROR_TIDIPC) { /* Attempt to use TID allocated for IPC. The client is probably trying to locate DCE RPC end points, which we don't support. */ @@ -2116,154 +2116,174 @@ long smb_ReceiveTran2Open(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op) return CM_ERROR_NOSUCHPATH; } - dscp = NULL; - code = cm_NameI(cm_rootSCachep, pathp, - CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD, - userp, tidPathp, &req, &scp); - if (code != 0) { - code = cm_NameI(cm_rootSCachep, spacep->data, - CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD, - userp, tidPathp, &req, &dscp); - cm_FreeSpace(spacep); + dscp = NULL; + code = cm_NameI(cm_rootSCachep, pathp, + CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD, + userp, tidPathp, &req, &scp); + if (code != 0) { + code = cm_NameI(cm_rootSCachep, spacep->data, + CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD, + userp, tidPathp, &req, &dscp); + cm_FreeSpace(spacep); if (code) { cm_ReleaseUser(userp); - smb_FreeTran2Packet(outp); + smb_FreeTran2Packet(outp); return code; } /* otherwise, scp points to the parent directory. Do a lookup, - * and truncate the file if we find it, otherwise we create the - * file. + * and truncate the file if we find it, otherwise we create the + * file. */ - if (!lastNamep) lastNamep = pathp; - else lastNamep++; + if (!lastNamep) + lastNamep = pathp; + else + lastNamep++; code = cm_Lookup(dscp, lastNamep, CM_FLAG_CASEFOLD, userp, &req, &scp); if (code && code != CM_ERROR_NOSUCHFILE) { - cm_ReleaseSCache(dscp); + cm_ReleaseSCache(dscp); cm_ReleaseUser(userp); - smb_FreeTran2Packet(outp); + smb_FreeTran2Packet(outp); return code; } - } + } else { cm_FreeSpace(spacep); - } + } /* if we get here, if code is 0, the file exists and is represented by * scp. Otherwise, we have to create it. */ - if (code == 0) { + if (code == 0) { code = cm_CheckOpen(scp, openMode, trunc, userp, &req); if (code) { if (dscp) cm_ReleaseSCache(dscp); cm_ReleaseSCache(scp); cm_ReleaseUser(userp); - smb_FreeTran2Packet(outp); + smb_FreeTran2Packet(outp); return code; } - if (excl) { - /* oops, file shouldn't be there */ + if (excl) { + /* oops, file shouldn't be there */ if (dscp) cm_ReleaseSCache(dscp); cm_ReleaseSCache(scp); cm_ReleaseUser(userp); - smb_FreeTran2Packet(outp); + smb_FreeTran2Packet(outp); return CM_ERROR_EXISTS; } - if (trunc) { - setAttr.mask = CM_ATTRMASK_LENGTH; + if (trunc) { + setAttr.mask = CM_ATTRMASK_LENGTH; setAttr.length.LowPart = 0; setAttr.length.HighPart = 0; - code = cm_SetAttr(scp, &setAttr, userp, &req); + code = cm_SetAttr(scp, &setAttr, userp, &req); openAction = 3; /* truncated existing file */ - } - else openAction = 1; /* found existing file */ + } + else + openAction = 1; /* found existing file */ } - else if (!(openFun & SMB_ATTR_DIRECTORY)) { - /* don't create if not found */ + else if (!(openFun & SMB_ATTR_DIRECTORY)) { + /* don't create if not found */ if (dscp) cm_ReleaseSCache(dscp); osi_assert(scp == NULL); cm_ReleaseUser(userp); - smb_FreeTran2Packet(outp); + smb_FreeTran2Packet(outp); return CM_ERROR_NOSUCHFILE; } else { - osi_assert(dscp != NULL && scp == NULL); - openAction = 2; /* created file */ - setAttr.mask = CM_ATTRMASK_CLIENTMODTIME; - smb_UnixTimeFromSearchTime(&setAttr.clientModTime, dosTime); + osi_assert(dscp != NULL && scp == NULL); + openAction = 2; /* created file */ + setAttr.mask = CM_ATTRMASK_CLIENTMODTIME; + smb_UnixTimeFromSearchTime(&setAttr.clientModTime, dosTime); code = cm_Create(dscp, lastNamep, 0, &setAttr, &scp, userp, - &req); - if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH)) - smb_NotifyChange(FILE_ACTION_ADDED, + &req); + if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH)) + smb_NotifyChange(FILE_ACTION_ADDED, FILE_NOTIFY_CHANGE_FILE_NAME, dscp, lastNamep, NULL, TRUE); if (!excl && code == CM_ERROR_EXISTS) { - /* not an exclusive create, and someone else tried - * creating it already, then we open it anyway. We - * don't bother retrying after this, since if this next - * fails, that means that the file was deleted after we - * started this call. + /* not an exclusive create, and someone else tried + * creating it already, then we open it anyway. We + * don't bother retrying after this, since if this next + * fails, that means that the file was deleted after we + * started this call. */ code = cm_Lookup(dscp, lastNamep, CM_FLAG_CASEFOLD, - userp, &req, &scp); + userp, &req, &scp); if (code == 0) { if (trunc) { - setAttr.mask = CM_ATTRMASK_LENGTH; + setAttr.mask = CM_ATTRMASK_LENGTH; setAttr.length.LowPart = 0; setAttr.length.HighPart = 0; code = cm_SetAttr(scp, &setAttr, userp, - &req); + &req); } - } /* lookup succeeded */ + } /* lookup succeeded */ } } - /* we don't need this any longer */ - if (dscp) cm_ReleaseSCache(dscp); + /* we don't need this any longer */ + if (dscp) cm_ReleaseSCache(dscp); if (code) { - /* something went wrong creating or truncating the file */ + /* something went wrong creating or truncating the file */ if (scp) cm_ReleaseSCache(scp); cm_ReleaseUser(userp); - smb_FreeTran2Packet(outp); + smb_FreeTran2Packet(outp); return code; } - /* make sure we're about to open a file */ - if (scp->fileType != CM_SCACHETYPE_FILE) { - cm_ReleaseSCache(scp); - cm_ReleaseUser(userp); - smb_FreeTran2Packet(outp); - return CM_ERROR_ISDIR; - } + /* make sure we're about to open a file */ + if (scp->fileType != CM_SCACHETYPE_FILE) { + code = 0; + while (code == 0 && scp->fileType == CM_SCACHETYPE_SYMLINK) { + cm_scache_t * targetScp = 0; + code = cm_EvaluateSymLink(dscp, scp, &targetScp, userp, &req); + if (code == 0) { + /* we have a more accurate file to use (the + * target of the symbolic link). Otherwise, + * we'll just use the symlink anyway. + */ + osi_Log2(smb_logp, "symlink vp %x to vp %x", + scp, targetScp); + cm_ReleaseSCache(scp); + scp = targetScp; + } + } + if (scp->fileType != CM_SCACHETYPE_FILE) { + cm_ReleaseSCache(scp); + cm_ReleaseUser(userp); + smb_FreeTran2Packet(outp); + return CM_ERROR_ISDIR; + } + } /* now all we have to do is open the file itself */ fidp = smb_FindFID(vcp, 0, SMB_FLAG_CREATE); osi_assert(fidp); - /* save a pointer to the vnode */ + /* save a pointer to the vnode */ fidp->scp = scp; - /* compute open mode */ + /* compute open mode */ if (openMode != 1) fidp->flags |= SMB_FID_OPENREAD; if (openMode == 1 || openMode == 2) fidp->flags |= SMB_FID_OPENWRITE; - smb_ReleaseFID(fidp); + smb_ReleaseFID(fidp); - cm_Open(scp, 0, userp); + cm_Open(scp, 0, userp); /* copy out remainder of the parms */ - parmSlot = 0; - outp->parmsp[parmSlot] = fidp->fid; parmSlot++; - lock_ObtainMutex(&scp->mx); - if (extraInfo) { + parmSlot = 0; + outp->parmsp[parmSlot] = fidp->fid; parmSlot++; + lock_ObtainMutex(&scp->mx); + if (extraInfo) { outp->parmsp[parmSlot] = smb_Attributes(scp); parmSlot++; - smb_SearchTimeFromUnixTime(&dosTime, scp->clientModTime); + smb_SearchTimeFromUnixTime(&dosTime, scp->clientModTime); outp->parmsp[parmSlot] = (unsigned short)(dosTime & 0xffff); parmSlot++; outp->parmsp[parmSlot] = (unsigned short)((dosTime>>16) & 0xffff); parmSlot++; outp->parmsp[parmSlot] = (unsigned short) (scp->length.LowPart & 0xffff); @@ -2273,23 +2293,23 @@ long smb_ReceiveTran2Open(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op) outp->parmsp[parmSlot] = openMode; parmSlot++; outp->parmsp[parmSlot] = 0; parmSlot++; /* file type 0 ==> normal file or dir */ outp->parmsp[parmSlot] = 0; parmSlot++; /* IPC junk */ - } - /* and the final "always present" stuff */ + } + /* and the final "always present" stuff */ outp->parmsp[parmSlot] = openAction; parmSlot++; - /* next write out the "unique" ID */ - outp->parmsp[parmSlot] = (unsigned short) (scp->fid.vnode & 0xffff); parmSlot++; - outp->parmsp[parmSlot] = (unsigned short) (scp->fid.volume & 0xffff); parmSlot++; + /* next write out the "unique" ID */ + outp->parmsp[parmSlot] = (unsigned short) (scp->fid.vnode & 0xffff); parmSlot++; + outp->parmsp[parmSlot] = (unsigned short) (scp->fid.volume & 0xffff); parmSlot++; outp->parmsp[parmSlot] = 0; parmSlot++; if (returnEALength) { - outp->parmsp[parmSlot] = 0; parmSlot++; - outp->parmsp[parmSlot] = 0; parmSlot++; - } - lock_ReleaseMutex(&scp->mx); - outp->totalData = 0; /* total # of data bytes */ + outp->parmsp[parmSlot] = 0; parmSlot++; + outp->parmsp[parmSlot] = 0; parmSlot++; + } + lock_ReleaseMutex(&scp->mx); + outp->totalData = 0; /* total # of data bytes */ outp->totalParms = parmSlot * 2; /* shorts are two bytes */ - smb_SendTran2Packet(vcp, outp, op); - + smb_SendTran2Packet(vcp, outp, op); + smb_FreeTran2Packet(outp); cm_ReleaseUser(userp); @@ -2299,103 +2319,105 @@ long smb_ReceiveTran2Open(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op) long smb_ReceiveTran2FindFirst(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *outp) { + osi_Log0(smb_logp,"ReceiveTran2FindFirst - NOT_SUPPORTED"); return CM_ERROR_BADOP; } long smb_ReceiveTran2FindNext(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *outp) { + osi_Log0(smb_logp,"ReceiveTran2FindNext - NOT_SUPPORTED"); return CM_ERROR_BADOP; } long smb_ReceiveTran2QFSInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op) { - smb_tran2Packet_t *outp; + smb_tran2Packet_t *outp; smb_tran2QFSInfo_t qi; - int responseSize; - osi_hyper_t temp; - static char FSname[6] = {'A', 0, 'F', 0, 'S', 0}; + int responseSize; + osi_hyper_t temp; + static char FSname[6] = {'A', 0, 'F', 0, 'S', 0}; - osi_Log1(smb_logp, "T2 QFSInfo type 0x%x", p->parmsp[0]); + osi_Log1(smb_logp, "T2 QFSInfo type 0x%x", p->parmsp[0]); - switch (p->parmsp[0]) { - case 1: responseSize = sizeof(qi.u.allocInfo); break; - case 2: responseSize = sizeof(qi.u.volumeInfo); break; - case 0x102: responseSize = sizeof(qi.u.FSvolumeInfo); break; - case 0x103: responseSize = sizeof(qi.u.FSsizeInfo); break; - case 0x104: responseSize = sizeof(qi.u.FSdeviceInfo); break; - case 0x105: responseSize = sizeof(qi.u.FSattributeInfo); break; - default: return CM_ERROR_INVAL; - } + switch (p->parmsp[0]) { + case 1: responseSize = sizeof(qi.u.allocInfo); break; + case 2: responseSize = sizeof(qi.u.volumeInfo); break; + case 0x102: responseSize = sizeof(qi.u.FSvolumeInfo); break; + case 0x103: responseSize = sizeof(qi.u.FSsizeInfo); break; + case 0x104: responseSize = sizeof(qi.u.FSdeviceInfo); break; + case 0x105: responseSize = sizeof(qi.u.FSattributeInfo); break; + default: return CM_ERROR_INVAL; + } outp = smb_GetTran2ResponsePacket(vcp, p, op, 0, responseSize); - switch (p->parmsp[0]) { - case 1: - /* alloc info */ + switch (p->parmsp[0]) { + case 1: + /* alloc info */ qi.u.allocInfo.FSID = 0; qi.u.allocInfo.sectorsPerAllocUnit = 1; qi.u.allocInfo.totalAllocUnits = 0x7fffffff; qi.u.allocInfo.availAllocUnits = 0x3fffffff; qi.u.allocInfo.bytesPerSector = 1024; - break; + break; case 2: - /* volume info */ + /* volume info */ qi.u.volumeInfo.vsn = 1234; qi.u.volumeInfo.vnCount = 4; - /* we're supposed to pad it out with zeroes to the end */ - memset(&qi.u.volumeInfo.label, 0, sizeof(qi.u.volumeInfo.label)); + /* we're supposed to pad it out with zeroes to the end */ + memset(&qi.u.volumeInfo.label, 0, sizeof(qi.u.volumeInfo.label)); memcpy(qi.u.volumeInfo.label, "AFS", 4); - break; + break; - case 0x102: - /* FS volume info */ - memset((char *)&qi.u.FSvolumeInfo.vct, 0, sizeof(FILETIME)); - qi.u.FSvolumeInfo.vsn = 1234; - qi.u.FSvolumeInfo.vnCount = 8; - memcpy(qi.u.FSvolumeInfo.label, "A\0F\0S\0\0", 8); - break; + case 0x102: + /* FS volume info */ + memset((char *)&qi.u.FSvolumeInfo.vct, 0, sizeof(FILETIME)); + qi.u.FSvolumeInfo.vsn = 1234; + qi.u.FSvolumeInfo.vnCount = 8; + memcpy(qi.u.FSvolumeInfo.label, "A\0F\0S\0\0", 8); + break; - case 0x103: - /* FS size info */ - temp.HighPart = 0; - temp.LowPart = 0x7fffffff; - qi.u.FSsizeInfo.totalAllocUnits = temp; - temp.LowPart = 0x3fffffff; - qi.u.FSsizeInfo.availAllocUnits = temp; - qi.u.FSsizeInfo.sectorsPerAllocUnit = 1; - qi.u.FSsizeInfo.bytesPerSector = 1024; - break; + case 0x103: + /* FS size info */ + temp.HighPart = 0; + temp.LowPart = 0x7fffffff; + qi.u.FSsizeInfo.totalAllocUnits = temp; + temp.LowPart = 0x3fffffff; + qi.u.FSsizeInfo.availAllocUnits = temp; + qi.u.FSsizeInfo.sectorsPerAllocUnit = 1; + qi.u.FSsizeInfo.bytesPerSector = 1024; + break; - case 0x104: - /* FS device info */ - qi.u.FSdeviceInfo.devType = 0; /* don't have a number */ - qi.u.FSdeviceInfo.characteristics = 0x50; /* remote, virtual */ - break; + case 0x104: + /* FS device info */ + qi.u.FSdeviceInfo.devType = 0; /* don't have a number */ + qi.u.FSdeviceInfo.characteristics = 0x50; /* remote, virtual */ + break; case 0x105: - /* FS attribute info */ - /* attributes, defined in WINNT.H: - * FILE_CASE_SENSITIVE_SEARCH 0x1 - * FILE_CASE_PRESERVED_NAMES 0x2 - * 0x4000 - * If bit 0x4000 is not set, Windows 95 thinks - * we can't handle long (non-8.3) names, - * despite our protestations to the contrary. - */ - qi.u.FSattributeInfo.attributes = 0x4003; - qi.u.FSattributeInfo.maxCompLength = 255; - qi.u.FSattributeInfo.FSnameLength = 6; - memcpy(qi.u.FSattributeInfo.FSname, FSname, 6); - break; - } + /* FS attribute info */ + /* attributes, defined in WINNT.H: + * FILE_CASE_SENSITIVE_SEARCH 0x1 + * FILE_CASE_PRESERVED_NAMES 0x2 + * 0x4000 + * If bit 0x4000 is not set, Windows 95 thinks + * we can't handle long (non-8.3) names, + * despite our protestations to the contrary. + */ + qi.u.FSattributeInfo.attributes = 0x4003; + qi.u.FSattributeInfo.maxCompLength = 255; + qi.u.FSattributeInfo.FSnameLength = 6; + memcpy(qi.u.FSattributeInfo.FSname, FSname, 6); + break; + } - /* copy out return data, and set corresponding sizes */ - outp->totalParms = 0; + /* copy out return data, and set corresponding sizes */ + outp->totalParms = 0; outp->totalData = responseSize; memcpy(outp->datap, &qi, responseSize); - /* send and free the packets */ - smb_SendTran2Packet(vcp, outp, op); + /* send and free the packets */ + smb_SendTran2Packet(vcp, outp, op); smb_FreeTran2Packet(outp); return 0; @@ -2537,7 +2559,7 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t return CM_ERROR_BADSMB; } - code = smb_LookupTIDPath(vcp, p->tid, &tidPathp); + code = smb_LookupTIDPath(vcp, p->tid, &tidPathp); if(code) { cm_ReleaseUser(userp); smb_SendTran2Error(vcp, p, opx, CM_ERROR_NOSUCHPATH); @@ -2545,32 +2567,32 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t return 0; } - /* - * XXX Strange hack XXX - * - * As of Patch 7 (13 January 98), we are having the following problem: - * In NT Explorer 4.0, whenever we click on a directory, AFS gets - * requests to look up "desktop.ini" in all the subdirectories. - * This can cause zillions of timeouts looking up non-existent cells - * and volumes, especially in the top-level directory. - * - * We have not found any way to avoid this or work around it except - * to explicitly ignore the requests for mount points that haven't - * yet been evaluated and for directories that haven't yet been - * fetched. - */ - if (infoLevel == 0x101) { - spacep = cm_GetSpace(); - smb_StripLastComponent(spacep->data, &lastComp, - (char *)(&p->parmsp[3])); - /* Make sure that lastComp is not NULL */ - if (lastComp) { - if (strcmp(lastComp, "\\desktop.ini") == 0) { + /* + * XXX Strange hack XXX + * + * As of Patch 7 (13 January 98), we are having the following problem: + * In NT Explorer 4.0, whenever we click on a directory, AFS gets + * requests to look up "desktop.ini" in all the subdirectories. + * This can cause zillions of timeouts looking up non-existent cells + * and volumes, especially in the top-level directory. + * + * We have not found any way to avoid this or work around it except + * to explicitly ignore the requests for mount points that haven't + * yet been evaluated and for directories that haven't yet been + * fetched. + */ + if (infoLevel == 0x101) { + spacep = cm_GetSpace(); + smb_StripLastComponent(spacep->data, &lastComp, + (char *)(&p->parmsp[3])); + /* Make sure that lastComp is not NULL */ + if (lastComp) { + if (strcmp(lastComp, "\\desktop.ini") == 0) { code = cm_NameI(cm_rootSCachep, spacep->data, - CM_FLAG_CASEFOLD - | CM_FLAG_DIRSEARCH - | CM_FLAG_FOLLOW, - userp, tidPathp, &req, &dscp); + CM_FLAG_CASEFOLD + | CM_FLAG_DIRSEARCH + | CM_FLAG_FOLLOW, + userp, tidPathp, &req, &dscp); if (code == 0) { if (dscp->fileType == CM_SCACHETYPE_MOUNTPOINT && !dscp->mountRootFidp) @@ -2593,90 +2615,90 @@ long smb_ReceiveTran2QPathInfo(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t } } } - cm_FreeSpace(spacep); - } + cm_FreeSpace(spacep); + } - /* now do namei and stat, and copy out the info */ + /* now do namei and stat, and copy out the info */ code = cm_NameI(cm_rootSCachep, (char *)(&p->parmsp[3]), - CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD, userp, tidPathp, &req, &scp); + CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD, userp, tidPathp, &req, &scp); - if (code) { - cm_ReleaseUser(userp); + if (code) { + cm_ReleaseUser(userp); smb_SendTran2Error(vcp, p, opx, code); smb_FreeTran2Packet(outp); return 0; } lock_ObtainMutex(&scp->mx); - code = cm_SyncOp(scp, NULL, userp, &req, 0, - CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS); - if (code) goto done; + code = cm_SyncOp(scp, NULL, userp, &req, 0, + CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS); + if (code) goto done; /* now we have the status in the cache entry, and everything is locked. - * Marshall the output data. + * Marshall the output data. */ - op = outp->datap; - /* for info level 108, figure out short name */ - if (infoLevel == 0x108) { - code = cm_GetShortName((char *)(&p->parmsp[3]), userp, &req, + op = outp->datap; + /* for info level 108, figure out short name */ + if (infoLevel == 0x108) { + code = cm_GetShortName((char *)(&p->parmsp[3]), userp, &req, tidPathp, scp->fid.vnode, shortName, (size_t *) &len); - if (code) { - goto done; - } + if (code) { + goto done; + } - op = outp->datap; - *((u_long *)op) = len * 2; op += 4; - mbstowcs((unsigned short *)op, shortName, len); - op += (len * 2); + op = outp->datap; + *((u_long *)op) = len * 2; op += 4; + mbstowcs((unsigned short *)op, shortName, len); + op += (len * 2); - goto done; - } - if (infoLevel == 1 || infoLevel == 2) { - smb_SearchTimeFromUnixTime(&dosTime, scp->clientModTime); + goto done; + } + if (infoLevel == 1 || infoLevel == 2) { + smb_SearchTimeFromUnixTime(&dosTime, scp->clientModTime); *((u_long *)op) = dosTime; op += 4; /* creation time */ *((u_long *)op) = dosTime; op += 4; /* access time */ *((u_long *)op) = dosTime; op += 4; /* write time */ *((u_long *)op) = scp->length.LowPart; op += 4; /* length */ *((u_long *)op) = scp->length.LowPart; op += 4; /* alloc size */ - attributes = smb_Attributes(scp); - *((u_short *)op) = attributes; op += 2; /* attributes */ - } - else if (infoLevel == 0x101) { - smb_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime); - *((FILETIME *)op) = ft; op += 8; /* creation time */ - *((FILETIME *)op) = ft; op += 8; /* last access time */ - *((FILETIME *)op) = ft; op += 8; /* last write time */ - *((FILETIME *)op) = ft; op += 8; /* last change time */ - extAttributes = smb_ExtAttributes(scp); - *((u_long *)op) = extAttributes; op += 4; /* extended attribs */ - *((u_long *)op) = 0; op += 4; /* don't know what this is */ - } - else if (infoLevel == 0x102) { - *((LARGE_INTEGER *)op) = scp->length; op += 8; /* alloc size */ - *((LARGE_INTEGER *)op) = scp->length; op += 8; /* EOF */ - *((u_long *)op) = scp->linkCount; op += 4; - *op++ = 0; - *op++ = 0; - *op++ = (scp->fileType == CM_SCACHETYPE_DIRECTORY ? 1 : 0); - *op++ = 0; - } - else if (infoLevel == 0x103) { - memset(op, 0, 4); op += 4; /* EA size */ - } + attributes = smb_Attributes(scp); + *((u_short *)op) = attributes; op += 2; /* attributes */ + } + else if (infoLevel == 0x101) { + smb_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime); + *((FILETIME *)op) = ft; op += 8; /* creation time */ + *((FILETIME *)op) = ft; op += 8; /* last access time */ + *((FILETIME *)op) = ft; op += 8; /* last write time */ + *((FILETIME *)op) = ft; op += 8; /* last change time */ + extAttributes = smb_ExtAttributes(scp); + *((u_long *)op) = extAttributes; op += 4; /* extended attribs */ + *((u_long *)op) = 0; op += 4; /* don't know what this is */ + } + else if (infoLevel == 0x102) { + *((LARGE_INTEGER *)op) = scp->length; op += 8; /* alloc size */ + *((LARGE_INTEGER *)op) = scp->length; op += 8; /* EOF */ + *((u_long *)op) = scp->linkCount; op += 4; + *op++ = 0; + *op++ = 0; + *op++ = (scp->fileType == CM_SCACHETYPE_DIRECTORY ? 1 : 0); + *op++ = 0; + } + else if (infoLevel == 0x103) { + memset(op, 0, 4); op += 4; /* EA size */ + } - /* now, if we are being asked about extended attrs, return a 0 size */ - if (infoLevel == 2) { - *((u_long *)op) = 0; op += 4; - } - + /* now, if we are being asked about extended attrs, return a 0 size */ + if (infoLevel == 2) { + *((u_long *)op) = 0; op += 4; + } - /* send and free the packets */ + + /* send and free the packets */ done: - lock_ReleaseMutex(&scp->mx); + lock_ReleaseMutex(&scp->mx); cm_ReleaseSCache(scp); cm_ReleaseUser(userp); - if (code == 0) + if (code == 0) smb_SendTran2Packet(vcp, outp, opx); else smb_SendTran2Error(vcp, p, opx, code); @@ -3074,17 +3096,18 @@ long smb_ApplyV3DirListPatches(cm_scache_t *dscp, } /* now watch for a symlink */ - if (scp->fileType == CM_SCACHETYPE_SYMLINK) { - lock_ReleaseMutex(&scp->mx); + code = 0; + while (code == 0 && scp->fileType == CM_SCACHETYPE_SYMLINK) { + lock_ReleaseMutex(&scp->mx); code = cm_EvaluateSymLink(dscp, scp, &targetScp, userp, reqp); if (code == 0) { - /* we have a more accurate file to use (the - * target of the symbolic link). Otherwise, - * we'll just use the symlink anyway. + /* we have a more accurate file to use (the + * target of the symbolic link). Otherwise, + * we'll just use the symlink anyway. */ - osi_Log2(smb_logp, "symlink vp %x to vp %x", - scp, targetScp); - cm_ReleaseSCache(scp); + osi_Log2(smb_logp, "symlink vp %x to vp %x", + scp, targetScp); + cm_ReleaseSCache(scp); scp = targetScp; } lock_ObtainMutex(&scp->mx); @@ -4267,9 +4290,9 @@ long smb_ReceiveV3OpenX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) /* make sure we're about to open a file */ if (scp->fileType != CM_SCACHETYPE_FILE) { - cm_ReleaseSCache(scp); - cm_ReleaseUser(userp); - return CM_ERROR_ISDIR; + cm_ReleaseSCache(scp); + cm_ReleaseUser(userp); + return CM_ERROR_ISDIR; } /* now all we have to do is open the file itself */ @@ -4642,146 +4665,147 @@ long smb_ReceiveV3ReadX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) /* * Values for createDisp, copied from NTDDK.H - * - * FILE_SUPERSEDE 0 (???) - * FILE_OPEN 1 (open) - * FILE_CREATE 2 (exclusive) - * FILE_OPEN_IF 3 (non-exclusive) - * FILE_OVERWRITE 4 (open & truncate, but do not create) - * FILE_OVERWRITE_IF 5 (open & truncate, or create) */ +#define FILE_SUPERSEDE 0 // (???) +#define FILE_OPEN 1 // (open) +#define FILE_CREATE 2 // (exclusive) +#define FILE_OPEN_IF 3 // (non-exclusive) +#define FILE_OVERWRITE 4 // (open & truncate, but do not create) +#define FILE_OVERWRITE_IF 5 // (open & truncate, or create) long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) { - char *pathp, *realPathp; - long code = 0; - cm_space_t *spacep; - cm_user_t *userp; - cm_scache_t *dscp; /* parent dir */ - cm_scache_t *scp; /* file to create or open */ - cm_attr_t setAttr; - char *lastNamep; + char *pathp, *realPathp; + long code = 0; + cm_space_t *spacep; + cm_user_t *userp; + cm_scache_t *dscp; /* parent dir */ + cm_scache_t *scp; /* file to create or open */ + cm_scache_t *targetScp; /* if scp is a symlink */ + cm_attr_t setAttr; + char *lastNamep; char *treeStartp; - unsigned short nameLength; - unsigned int flags; - unsigned int requestOpLock; - unsigned int requestBatchOpLock; - unsigned int mustBeDir; + unsigned short nameLength; + unsigned int flags; + unsigned int requestOpLock; + unsigned int requestBatchOpLock; + unsigned int mustBeDir; unsigned int treeCreate; - int realDirFlag; - unsigned int desiredAccess; - unsigned int extAttributes; - unsigned int createDisp; - unsigned int createOptions; - int initialModeBits; - unsigned short baseFid; - smb_fid_t *baseFidp; - smb_fid_t *fidp; - cm_scache_t *baseDirp; - unsigned short openAction; - int parmSlot; - long fidflags; - FILETIME ft; - LARGE_INTEGER sz; - char *tidPathp; - BOOL foundscp; - cm_req_t req; + int realDirFlag; + unsigned int desiredAccess; + unsigned int extAttributes; + unsigned int createDisp; + unsigned int createOptions; + int initialModeBits; + unsigned short baseFid; + smb_fid_t *baseFidp; + smb_fid_t *fidp; + cm_scache_t *baseDirp; + unsigned short openAction; + int parmSlot; + long fidflags; + FILETIME ft; + LARGE_INTEGER sz; + char *tidPathp; + BOOL foundscp; + cm_req_t req; - cm_InitReq(&req); + cm_InitReq(&req); treeCreate = FALSE; - foundscp = FALSE; - scp = NULL; + foundscp = FALSE; + scp = NULL; - nameLength = smb_GetSMBOffsetParm(inp, 2, 1); - flags = smb_GetSMBOffsetParm(inp, 3, 1) - | (smb_GetSMBOffsetParm(inp, 4, 1) << 16); - requestOpLock = flags & 0x02; - requestBatchOpLock = flags & 0x04; - mustBeDir = flags & 0x08; + nameLength = smb_GetSMBOffsetParm(inp, 2, 1); + flags = smb_GetSMBOffsetParm(inp, 3, 1) + | (smb_GetSMBOffsetParm(inp, 4, 1) << 16); + requestOpLock = flags & 0x02; + requestBatchOpLock = flags & 0x04; + mustBeDir = flags & 0x08; - /* - * Why all of a sudden 32-bit FID? - * We will reject all bits higher than 16. - */ - if (smb_GetSMBOffsetParm(inp, 6, 1) != 0) - return CM_ERROR_INVAL; - baseFid = smb_GetSMBOffsetParm(inp, 5, 1); - desiredAccess = smb_GetSMBOffsetParm(inp, 7, 1) - | (smb_GetSMBOffsetParm(inp, 8, 1) << 16); - extAttributes = smb_GetSMBOffsetParm(inp, 13, 1) - | (smb_GetSMBOffsetParm(inp, 14, 1) << 16); - createDisp = smb_GetSMBOffsetParm(inp, 17, 1) - | (smb_GetSMBOffsetParm(inp, 18, 1) << 16); - createOptions = smb_GetSMBOffsetParm(inp, 19, 1) - | (smb_GetSMBOffsetParm(inp, 20, 1) << 16); + /* + * Why all of a sudden 32-bit FID? + * We will reject all bits higher than 16. + */ + if (smb_GetSMBOffsetParm(inp, 6, 1) != 0) + return CM_ERROR_INVAL; + baseFid = smb_GetSMBOffsetParm(inp, 5, 1); + desiredAccess = smb_GetSMBOffsetParm(inp, 7, 1) + | (smb_GetSMBOffsetParm(inp, 8, 1) << 16); + extAttributes = smb_GetSMBOffsetParm(inp, 13, 1) + | (smb_GetSMBOffsetParm(inp, 14, 1) << 16); + createDisp = smb_GetSMBOffsetParm(inp, 17, 1) + | (smb_GetSMBOffsetParm(inp, 18, 1) << 16); + createOptions = smb_GetSMBOffsetParm(inp, 19, 1) + | (smb_GetSMBOffsetParm(inp, 20, 1) << 16); - /* mustBeDir is never set; createOptions directory bit seems to be + /* mustBeDir is never set; createOptions directory bit seems to be * more important - */ - if (createOptions & 1) - realDirFlag = 1; - else if (createOptions & 0x40) - realDirFlag = 0; - else - realDirFlag = -1; + */ + if (createOptions & 1) + realDirFlag = 1; + else if (createOptions & 0x40) + realDirFlag = 0; + else + realDirFlag = -1; - /* - * compute initial mode bits based on read-only flag in - * extended attributes - */ - initialModeBits = 0666; - if (extAttributes & 1) initialModeBits &= ~0222; + /* + * compute initial mode bits based on read-only flag in + * extended attributes + */ + initialModeBits = 0666; + if (extAttributes & 1) + initialModeBits &= ~0222; - pathp = smb_GetSMBData(inp, NULL); - /* Sometimes path is not null-terminated, so we make a copy. */ - realPathp = malloc(nameLength+1); - memcpy(realPathp, pathp, nameLength); - realPathp[nameLength] = 0; + pathp = smb_GetSMBData(inp, NULL); + /* Sometimes path is not null-terminated, so we make a copy. */ + realPathp = malloc(nameLength+1); + memcpy(realPathp, pathp, nameLength); + realPathp[nameLength] = 0; - spacep = inp->spacep; - smb_StripLastComponent(spacep->data, &lastNamep, realPathp); + spacep = inp->spacep; + smb_StripLastComponent(spacep->data, &lastNamep, realPathp); osi_Log1(smb_logp,"NTCreateX for [%s]",osi_LogSaveString(smb_logp,realPathp)); - osi_Log4(smb_logp,"NTCreateX da=[%x] ea=[%x] cd=[%x] co=[%x]", desiredAccess, extAttributes, createDisp, createOptions); - osi_Log1(smb_logp,"NTCreateX lastNamep=[%s]",osi_LogSaveString(smb_logp,(lastNamep?lastNamep:"null"))); + osi_Log4(smb_logp,"... da=[%x] ea=[%x] cd=[%x] co=[%x]", desiredAccess, extAttributes, createDisp, createOptions); + osi_Log2(smb_logp,"... flags=[%x] lastNamep=[%s]", flags, osi_LogSaveString(smb_logp,(lastNamep?lastNamep:"null"))); - if (lastNamep && strcmp(lastNamep, SMB_IOCTL_FILENAME) == 0) { - /* special case magic file name for receiving IOCTL requests - * (since IOCTL calls themselves aren't getting through). - */ - fidp = smb_FindFID(vcp, 0, SMB_FLAG_CREATE); - smb_SetupIoctlFid(fidp, spacep); - osi_Log1(smb_logp,"NTCreateX Setting up IOCTL on fid[%d]",fidp->fid); + if (lastNamep && strcmp(lastNamep, SMB_IOCTL_FILENAME) == 0) { + /* special case magic file name for receiving IOCTL requests + * (since IOCTL calls themselves aren't getting through). + */ + fidp = smb_FindFID(vcp, 0, SMB_FLAG_CREATE); + smb_SetupIoctlFid(fidp, spacep); + osi_Log1(smb_logp,"NTCreateX Setting up IOCTL on fid[%d]",fidp->fid); - /* set inp->fid so that later read calls in same msg can find fid */ - inp->fid = fidp->fid; + /* set inp->fid so that later read calls in same msg can find fid */ + inp->fid = fidp->fid; - /* out parms */ - parmSlot = 2; - smb_SetSMBParmByte(outp, parmSlot, 0); /* oplock */ - smb_SetSMBParm(outp, parmSlot, fidp->fid); parmSlot++; - smb_SetSMBParmLong(outp, parmSlot, 1); parmSlot += 2; /* Action */ - /* times */ - memset(&ft, 0, sizeof(ft)); - smb_SetSMBParmDouble(outp, parmSlot, (char *)&ft); parmSlot += 4; - smb_SetSMBParmDouble(outp, parmSlot, (char *)&ft); parmSlot += 4; - smb_SetSMBParmDouble(outp, parmSlot, (char *)&ft); parmSlot += 4; - smb_SetSMBParmDouble(outp, parmSlot, (char *)&ft); parmSlot += 4; - smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2; /* attr */ - sz.HighPart = 0x7fff; sz.LowPart = 0; - smb_SetSMBParmDouble(outp, parmSlot, (char *)&sz); parmSlot += 4; /* alen */ - smb_SetSMBParmDouble(outp, parmSlot, (char *)&sz); parmSlot += 4; /* len */ - smb_SetSMBParm(outp, parmSlot, 0); parmSlot++; /* filetype */ - smb_SetSMBParm(outp, parmSlot, 0); parmSlot++; /* dev state */ - smb_SetSMBParmByte(outp, parmSlot, 0); /* is a dir? */ - smb_SetSMBDataLength(outp, 0); + /* out parms */ + parmSlot = 2; + smb_SetSMBParmByte(outp, parmSlot, 0); /* oplock */ + smb_SetSMBParm(outp, parmSlot, fidp->fid); parmSlot++; + smb_SetSMBParmLong(outp, parmSlot, 1); parmSlot += 2; /* Action */ + /* times */ + memset(&ft, 0, sizeof(ft)); + smb_SetSMBParmDouble(outp, parmSlot, (char *)&ft); parmSlot += 4; + smb_SetSMBParmDouble(outp, parmSlot, (char *)&ft); parmSlot += 4; + smb_SetSMBParmDouble(outp, parmSlot, (char *)&ft); parmSlot += 4; + smb_SetSMBParmDouble(outp, parmSlot, (char *)&ft); parmSlot += 4; + smb_SetSMBParmLong(outp, parmSlot, 0); parmSlot += 2; /* attr */ + sz.HighPart = 0x7fff; sz.LowPart = 0; + smb_SetSMBParmDouble(outp, parmSlot, (char *)&sz); parmSlot += 4; /* alen */ + smb_SetSMBParmDouble(outp, parmSlot, (char *)&sz); parmSlot += 4; /* len */ + smb_SetSMBParm(outp, parmSlot, 0); parmSlot++; /* filetype */ + smb_SetSMBParm(outp, parmSlot, 0); parmSlot++; /* dev state */ + smb_SetSMBParmByte(outp, parmSlot, 0); /* is a dir? */ + smb_SetSMBDataLength(outp, 0); - /* clean up fid reference */ - smb_ReleaseFID(fidp); - free(realPathp); - return 0; - } + /* clean up fid reference */ + smb_ReleaseFID(fidp); + free(realPathp); + return 0; + } #ifdef DEBUG_VERBOSE { @@ -4799,46 +4823,48 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) return CM_ERROR_INVAL; } - if (baseFid == 0) { - baseDirp = cm_rootSCachep; - code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp); - if(code == CM_ERROR_TIDIPC) { + if (baseFid == 0) { + baseDirp = cm_rootSCachep; + code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp); + if (code == CM_ERROR_TIDIPC) { /* Attempt to use a TID allocated for IPC. The client - is probably looking for DCE RPC end points which we - don't support. */ + * is probably looking for DCE RPC end points which we + * don't support. */ osi_Log0(smb_logp, "NTCreateX received IPC TID"); free(realPathp); cm_ReleaseUser(userp); return CM_ERROR_NOSUCHFILE; } - } - else { + } + else { baseFidp = smb_FindFID(vcp, baseFid, 0); if (!baseFidp) { - osi_Log1(smb_logp, "NTCreateX Invalid base fid [%d]", baseFid); - free(realPathp); - cm_ReleaseUser(userp); - return CM_ERROR_INVAL; - } - baseDirp = baseFidp->scp; - tidPathp = NULL; - } + osi_Log1(smb_logp, "NTCreateX Invalid base fid [%d]", baseFid); + free(realPathp); + cm_ReleaseUser(userp); + return CM_ERROR_INVAL; + } + baseDirp = baseFidp->scp; + tidPathp = NULL; + } osi_Log1(smb_logp, "NTCreateX tidPathp=[%s]", (tidPathp==NULL)?"null": osi_LogSaveString(smb_logp,tidPathp)); - - /* compute open mode */ - fidflags = 0; - if (desiredAccess & DELETE) - fidflags |= SMB_FID_OPENDELETE; - if (desiredAccess & AFS_ACCESS_READ) - fidflags |= SMB_FID_OPENREAD; - if (desiredAccess & AFS_ACCESS_WRITE) - fidflags |= SMB_FID_OPENWRITE; - dscp = NULL; - code = 0; + /* compute open mode */ + fidflags = 0; + if (desiredAccess & DELETE) + fidflags |= SMB_FID_OPENDELETE; + if (desiredAccess & AFS_ACCESS_READ) + fidflags |= SMB_FID_OPENREAD; + if (desiredAccess & AFS_ACCESS_WRITE) + fidflags |= SMB_FID_OPENWRITE; + + dscp = NULL; + code = 0; /* For an exclusive create, we want to do a case sensitive match for the last component. */ - if (createDisp == 2 || createDisp == 4 || createDisp == 5) { + if ( createDisp == FILE_CREATE || + createDisp == FILE_OVERWRITE || + createDisp == FILE_OVERWRITE_IF) { code = cm_NameI(baseDirp, spacep->data, CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD, userp, tidPathp, &req, &dscp); if (code == 0) { @@ -4848,7 +4874,7 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) code = cm_Lookup(dscp, (lastNamep)?(lastNamep+1):realPathp, CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD, userp, &req, &scp); if (code == 0 && realDirFlag == 1) { - cm_ReleaseSCache(scp); + cm_ReleaseSCache(scp); cm_ReleaseSCache(dscp); cm_ReleaseUser(userp); free(realPathp); @@ -4862,10 +4888,10 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) userp, tidPathp, &req, &scp); } if (code == 0) - foundscp = TRUE; + foundscp = TRUE; - if (!foundscp || (fidflags & (SMB_FID_OPENDELETE | SMB_FID_OPENWRITE))) { - /* look up parent directory */ + if (!foundscp || (fidflags & (SMB_FID_OPENDELETE | SMB_FID_OPENWRITE))) { + /* look up parent directory */ /* If we are trying to create a path (i.e. multiple nested directories), then we don't *need* * the immediate parent. We have to work our way up realPathp until we hit something that we * recognize. @@ -4881,7 +4907,7 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) if (code && (tp = strrchr(spacep->data,'\\')) && - (createDisp == 2) && + (createDisp == FILE_CREATE) && (realDirFlag == 1)) { *tp++ = 0; treeCreate = TRUE; @@ -4932,25 +4958,28 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) } if (!foundscp && !treeCreate) { - if (createDisp == 2 || createDisp == 4) + if ( createDisp == FILE_CREATE || + createDisp == FILE_OVERWRITE || + createDisp == FILE_OVERWRITE_IF) { code = cm_Lookup(dscp, lastNamep, CM_FLAG_FOLLOW, userp, &req, &scp); - else - code = cm_Lookup(dscp, lastNamep, - CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD, - userp, &req, &scp); - if (code && code != CM_ERROR_NOSUCHFILE) { - cm_ReleaseSCache(dscp); - cm_ReleaseUser(userp); - free(realPathp); - return code; - } - } - } - else { - if (baseFid != 0) - smb_ReleaseFID(baseFidp); - } + } else { + code = cm_Lookup(dscp, lastNamep, + CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD, + userp, &req, &scp); + } + if (code && code != CM_ERROR_NOSUCHFILE) { + cm_ReleaseSCache(dscp); + cm_ReleaseUser(userp); + free(realPathp); + return code; + } + } + } + else { + if (baseFid != 0) + smb_ReleaseFID(baseFidp); + } /* if we get here, if code is 0, the file exists and is represented by * scp. Otherwise, we have to create it. The dir may be represented @@ -4958,229 +4987,282 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) * scp is NULL. */ if (code == 0 && !treeCreate) { - code = cm_CheckNTOpen(scp, desiredAccess, createDisp, userp, - &req); - if (code) { - if (dscp) cm_ReleaseSCache(dscp); - cm_ReleaseSCache(scp); - cm_ReleaseUser(userp); - free(realPathp); - return code; - } + code = cm_CheckNTOpen(scp, desiredAccess, createDisp, userp, + &req); + if (code) { + if (dscp) cm_ReleaseSCache(dscp); + cm_ReleaseSCache(scp); + cm_ReleaseUser(userp); + free(realPathp); + return code; + } - if (createDisp == 2) { - /* oops, file shouldn't be there */ - if (dscp) cm_ReleaseSCache(dscp); - cm_ReleaseSCache(scp); - cm_ReleaseUser(userp); - free(realPathp); - return CM_ERROR_EXISTS; - } + if (createDisp == FILE_CREATE) { + /* oops, file shouldn't be there */ + if (dscp) cm_ReleaseSCache(dscp); + cm_ReleaseSCache(scp); + cm_ReleaseUser(userp); + free(realPathp); + return CM_ERROR_EXISTS; + } - if (createDisp == 4 - || createDisp == 5) { - setAttr.mask = CM_ATTRMASK_LENGTH; - setAttr.length.LowPart = 0; - setAttr.length.HighPart = 0; - code = cm_SetAttr(scp, &setAttr, userp, &req); - openAction = 3; /* truncated existing file */ - } - else openAction = 1; /* found existing file */ - } - else if (createDisp == 1 || createDisp == 4) { - /* don't create if not found */ - if (dscp) cm_ReleaseSCache(dscp); - cm_ReleaseUser(userp); - free(realPathp); - return CM_ERROR_NOSUCHFILE; - } + if ( createDisp == FILE_OVERWRITE || + createDisp == FILE_OVERWRITE_IF) { + setAttr.mask = CM_ATTRMASK_LENGTH; + setAttr.length.LowPart = 0; + setAttr.length.HighPart = 0; + /* now watch for a symlink */ + code = 0; + while (code == 0 && scp->fileType == CM_SCACHETYPE_SYMLINK) { + targetScp = 0; + code = cm_EvaluateSymLink(dscp, scp, &targetScp, userp, &req); + if (code == 0) { + /* we have a more accurate file to use (the + * target of the symbolic link). Otherwise, + * we'll just use the symlink anyway. + */ + osi_Log2(smb_logp, "symlink vp %x to vp %x", + scp, targetScp); + cm_ReleaseSCache(scp); + scp = targetScp; + } + } + code = cm_SetAttr(scp, &setAttr, userp, &req); + openAction = 3; /* truncated existing file */ + } + else openAction = 1; /* found existing file */ + } + else if (createDisp == FILE_OPEN || createDisp == FILE_OVERWRITE) { + /* don't create if not found */ + if (dscp) cm_ReleaseSCache(dscp); + cm_ReleaseUser(userp); + free(realPathp); + return CM_ERROR_NOSUCHFILE; + } else if (realDirFlag == 0 || realDirFlag == -1) { - osi_assert(dscp != NULL); - osi_Log1(smb_logp, "smb_ReceiveNTCreateX creating file %s", - osi_LogSaveString(smb_logp, lastNamep)); - openAction = 2; /* created file */ - setAttr.mask = CM_ATTRMASK_CLIENTMODTIME; - setAttr.clientModTime = time(NULL); - code = cm_Create(dscp, lastNamep, 0, &setAttr, &scp, userp, - &req); - if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH)) - smb_NotifyChange(FILE_ACTION_ADDED, - FILE_NOTIFY_CHANGE_FILE_NAME, - dscp, lastNamep, NULL, TRUE); - if (code == CM_ERROR_EXISTS && createDisp != 2) { - /* Not an exclusive create, and someone else tried - * creating it already, then we open it anyway. We - * don't bother retrying after this, since if this next - * fails, that means that the file was deleted after we - * started this call. - */ - code = cm_Lookup(dscp, lastNamep, CM_FLAG_CASEFOLD, - userp, &req, &scp); - if (code == 0) { - if (createDisp == 5) { - setAttr.mask = CM_ATTRMASK_LENGTH; - setAttr.length.LowPart = 0; - setAttr.length.HighPart = 0; - code = cm_SetAttr(scp, &setAttr, userp, - &req); - } - } /* lookup succeeded */ - } - } + osi_assert(dscp != NULL); + osi_Log1(smb_logp, "smb_ReceiveNTCreateX creating file %s", + osi_LogSaveString(smb_logp, lastNamep)); + openAction = 2; /* created file */ + setAttr.mask = CM_ATTRMASK_CLIENTMODTIME; + setAttr.clientModTime = time(NULL); + code = cm_Create(dscp, lastNamep, 0, &setAttr, &scp, userp, + &req); + if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH)) + smb_NotifyChange(FILE_ACTION_ADDED, + FILE_NOTIFY_CHANGE_FILE_NAME, + dscp, lastNamep, NULL, TRUE); + if (code == CM_ERROR_EXISTS && createDisp != FILE_CREATE) { + /* Not an exclusive create, and someone else tried + * creating it already, then we open it anyway. We + * don't bother retrying after this, since if this next + * fails, that means that the file was deleted after we + * started this call. + */ + code = cm_Lookup(dscp, lastNamep, CM_FLAG_CASEFOLD, + userp, &req, &scp); + if (code == 0) { + if (createDisp == FILE_OVERWRITE_IF) { + setAttr.mask = CM_ATTRMASK_LENGTH; + setAttr.length.LowPart = 0; + setAttr.length.HighPart = 0; + + /* now watch for a symlink */ + code = 0; + while (code == 0 && scp->fileType == CM_SCACHETYPE_SYMLINK) { + targetScp = 0; + code = cm_EvaluateSymLink(dscp, scp, &targetScp, userp, &req); + if (code == 0) { + /* we have a more accurate file to use (the + * target of the symbolic link). Otherwise, + * we'll just use the symlink anyway. + */ + osi_Log2(smb_logp, "symlink vp %x to vp %x", + scp, targetScp); + cm_ReleaseSCache(scp); + scp = targetScp; + } + } + code = cm_SetAttr(scp, &setAttr, userp, &req); + } + } /* lookup succeeded */ + } + } else { - char *tp, *pp; - char *cp; /* This component */ - int clen = 0; /* length of component */ - cm_scache_t *tscp; - int isLast = 0; + char *tp, *pp; + char *cp; /* This component */ + int clen = 0; /* length of component */ + cm_scache_t *tscp; + int isLast = 0; - /* create directory */ - if ( !treeCreate ) treeStartp = lastNamep; - osi_assert(dscp != NULL); - osi_Log1(smb_logp, "smb_ReceiveNTCreateX creating directory [%s]", - osi_LogSaveString(smb_logp, treeStartp)); - openAction = 2; /* created directory */ + /* create directory */ + if ( !treeCreate ) + treeStartp = lastNamep; + osi_assert(dscp != NULL); + osi_Log1(smb_logp, "smb_ReceiveNTCreateX creating directory [%s]", + osi_LogSaveString(smb_logp, treeStartp)); + openAction = 2; /* created directory */ - setAttr.mask = CM_ATTRMASK_CLIENTMODTIME; - setAttr.clientModTime = time(NULL); + setAttr.mask = CM_ATTRMASK_CLIENTMODTIME; + setAttr.clientModTime = time(NULL); - pp = treeStartp; - cp = spacep->data; - tscp = dscp; + pp = treeStartp; + cp = spacep->data; + tscp = dscp; - while (pp && *pp) { - tp = strchr(pp, '\\'); - if (!tp) { - strcpy(cp,pp); - clen = strlen(cp); - isLast = 1; /* indicate last component. the supplied path never ends in a slash */ - } - else { - clen = tp - pp; - strncpy(cp,pp,clen); - *(cp + clen) = 0; - tp++; - } - pp = tp; + while (pp && *pp) { + tp = strchr(pp, '\\'); + if (!tp) { + strcpy(cp,pp); + clen = strlen(cp); + isLast = 1; /* indicate last component. the supplied path never ends in a slash */ + } + else { + clen = tp - pp; + strncpy(cp,pp,clen); + *(cp + clen) = 0; + tp++; + } + pp = tp; - if (clen == 0) continue; /* the supplied path can't have consecutive slashes either , but */ + if (clen == 0) + continue; /* the supplied path can't have consecutive slashes either , but */ - /* cp is the next component to be created. */ - code = cm_MakeDir(tscp, cp, 0, &setAttr, userp, &req); - if (code == 0 && (tscp->flags & CM_SCACHEFLAG_ANYWATCH)) - smb_NotifyChange(FILE_ACTION_ADDED, - FILE_NOTIFY_CHANGE_DIR_NAME, - tscp, cp, NULL, TRUE); - if (code == 0 || - (code == CM_ERROR_EXISTS && createDisp != 2)) { - /* Not an exclusive create, and someone else tried - * creating it already, then we open it anyway. We - * don't bother retrying after this, since if this next - * fails, that means that the file was deleted after we - * started this call. - */ - code = cm_Lookup(tscp, cp, CM_FLAG_CASEFOLD, - userp, &req, &scp); - } - if (code) break; + /* cp is the next component to be created. */ + code = cm_MakeDir(tscp, cp, 0, &setAttr, userp, &req); + if (code == 0 && (tscp->flags & CM_SCACHEFLAG_ANYWATCH)) + smb_NotifyChange(FILE_ACTION_ADDED, + FILE_NOTIFY_CHANGE_DIR_NAME, + tscp, cp, NULL, TRUE); + if (code == 0 || + (code == CM_ERROR_EXISTS && createDisp != FILE_CREATE)) { + /* Not an exclusive create, and someone else tried + * creating it already, then we open it anyway. We + * don't bother retrying after this, since if this next + * fails, that means that the file was deleted after we + * started this call. + */ + code = cm_Lookup(tscp, cp, CM_FLAG_CASEFOLD, + userp, &req, &scp); + } + if (code) break; - if (!isLast) { /* for anything other than dscp, release it unless it's the last one */ - cm_ReleaseSCache(tscp); - tscp = scp; /* Newly created directory will be next parent */ - } - } + if (!isLast) { /* for anything other than dscp, release it unless it's the last one */ + cm_ReleaseSCache(tscp); + tscp = scp; /* Newly created directory will be next parent */ + } + } - /* - if we get here and code == 0, then scp is the last directory created, and tscp is the - parent of scp. dscp got released if dscp != tscp. both tscp and scp are held. - */ - dscp = tscp; + /* + * if we get here and code == 0, then scp is the last directory created, and tscp is the + * parent of scp. dscp got released if dscp != tscp. both tscp and scp are held. + */ + dscp = tscp; } - if (code) { - /* something went wrong creating or truncating the file */ - if (scp) cm_ReleaseSCache(scp); + if (code) { + /* something went wrong creating or truncating the file */ + if (scp) cm_ReleaseSCache(scp); if (dscp) cm_ReleaseSCache(dscp); - cm_ReleaseUser(userp); - free(realPathp); - return code; - } + cm_ReleaseUser(userp); + free(realPathp); + return code; + } + + /* make sure we have file vs. dir right (only applies for single component case) */ + if (realDirFlag == 0 && scp->fileType != CM_SCACHETYPE_FILE) { + /* now watch for a symlink */ + code = 0; + while (code == 0 && scp->fileType == CM_SCACHETYPE_SYMLINK) { + cm_scache_t * targetScp = 0; + code = cm_EvaluateSymLink(dscp, scp, &targetScp, userp, &req); + if (code == 0) { + /* we have a more accurate file to use (the + * target of the symbolic link). Otherwise, + * we'll just use the symlink anyway. + */ + osi_Log2(smb_logp, "symlink vp %x to vp %x", + scp, targetScp); + cm_ReleaseSCache(scp); + scp = targetScp; + } + } + + if (scp->fileType != CM_SCACHETYPE_FILE) { + cm_ReleaseSCache(scp); + cm_ReleaseUser(userp); + free(realPathp); + return CM_ERROR_ISDIR; + } + } - /* make sure we have file vs. dir right (only applies for single component case) */ - if (realDirFlag == 0 && scp->fileType != CM_SCACHETYPE_FILE) { - cm_ReleaseSCache(scp); - if (dscp) cm_ReleaseSCache(dscp); - cm_ReleaseUser(userp); - free(realPathp); - return CM_ERROR_ISDIR; - } /* (only applies to single component case) */ - if (realDirFlag == 1 && scp->fileType == CM_SCACHETYPE_FILE) { - cm_ReleaseSCache(scp); + if (realDirFlag == 1 && scp->fileType == CM_SCACHETYPE_FILE) { + cm_ReleaseSCache(scp); if (dscp) cm_ReleaseSCache(dscp); - cm_ReleaseUser(userp); - free(realPathp); - return CM_ERROR_NOTDIR; - } + cm_ReleaseUser(userp); + free(realPathp); + return CM_ERROR_NOTDIR; + } - /* open the file itself */ - fidp = smb_FindFID(vcp, 0, SMB_FLAG_CREATE); - osi_assert(fidp); - /* save a pointer to the vnode */ - fidp->scp = scp; + /* open the file itself */ + fidp = smb_FindFID(vcp, 0, SMB_FLAG_CREATE); + osi_assert(fidp); + /* save a pointer to the vnode */ + fidp->scp = scp; - fidp->flags = fidflags; + fidp->flags = fidflags; - /* save parent dir and pathname for delete or change notification */ - if (fidflags & (SMB_FID_OPENDELETE | SMB_FID_OPENWRITE)) { - fidp->flags |= SMB_FID_NTOPEN; - fidp->NTopen_dscp = dscp; - cm_HoldSCache(dscp); - fidp->NTopen_pathp = strdup(lastNamep); - } - fidp->NTopen_wholepathp = realPathp; + /* save parent dir and pathname for delete or change notification */ + if (fidflags & (SMB_FID_OPENDELETE | SMB_FID_OPENWRITE)) { + fidp->flags |= SMB_FID_NTOPEN; + fidp->NTopen_dscp = dscp; + cm_HoldSCache(dscp); + fidp->NTopen_pathp = strdup(lastNamep); + } + fidp->NTopen_wholepathp = realPathp; - /* we don't need this any longer */ - if (dscp) cm_ReleaseSCache(dscp); - cm_Open(scp, 0, userp); + /* we don't need this any longer */ + if (dscp) cm_ReleaseSCache(dscp); + cm_Open(scp, 0, userp); - /* set inp->fid so that later read calls in same msg can find fid */ - inp->fid = fidp->fid; + /* set inp->fid so that later read calls in same msg can find fid */ + inp->fid = fidp->fid; - /* out parms */ - parmSlot = 2; - lock_ObtainMutex(&scp->mx); - smb_SetSMBParmByte(outp, parmSlot, 0); /* oplock */ - smb_SetSMBParm(outp, parmSlot, fidp->fid); parmSlot++; - smb_SetSMBParmLong(outp, parmSlot, openAction); parmSlot += 2; - smb_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime); - smb_SetSMBParmDouble(outp, parmSlot, (char *)&ft); parmSlot += 4; - smb_SetSMBParmDouble(outp, parmSlot, (char *)&ft); parmSlot += 4; - smb_SetSMBParmDouble(outp, parmSlot, (char *)&ft); parmSlot += 4; - smb_SetSMBParmDouble(outp, parmSlot, (char *)&ft); parmSlot += 4; - smb_SetSMBParmLong(outp, parmSlot, smb_ExtAttributes(scp)); - parmSlot += 2; - smb_SetSMBParmDouble(outp, parmSlot, (char *)&scp->length); parmSlot += 4; - smb_SetSMBParmDouble(outp, parmSlot, (char *)&scp->length); parmSlot += 4; - smb_SetSMBParm(outp, parmSlot, 0); parmSlot++; /* filetype */ - smb_SetSMBParm(outp, parmSlot, 0); parmSlot++; /* dev state */ - smb_SetSMBParmByte(outp, parmSlot, - scp->fileType == CM_SCACHETYPE_DIRECTORY); /* is a dir? */ - lock_ReleaseMutex(&scp->mx); - smb_SetSMBDataLength(outp, 0); + /* out parms */ + parmSlot = 2; + lock_ObtainMutex(&scp->mx); + smb_SetSMBParmByte(outp, parmSlot, 0); /* oplock */ + smb_SetSMBParm(outp, parmSlot, fidp->fid); parmSlot++; + smb_SetSMBParmLong(outp, parmSlot, openAction); parmSlot += 2; + smb_LargeSearchTimeFromUnixTime(&ft, scp->clientModTime); + smb_SetSMBParmDouble(outp, parmSlot, (char *)&ft); parmSlot += 4; + smb_SetSMBParmDouble(outp, parmSlot, (char *)&ft); parmSlot += 4; + smb_SetSMBParmDouble(outp, parmSlot, (char *)&ft); parmSlot += 4; + smb_SetSMBParmDouble(outp, parmSlot, (char *)&ft); parmSlot += 4; + smb_SetSMBParmLong(outp, parmSlot, smb_ExtAttributes(scp)); + parmSlot += 2; + smb_SetSMBParmDouble(outp, parmSlot, (char *)&scp->length); parmSlot += 4; + smb_SetSMBParmDouble(outp, parmSlot, (char *)&scp->length); parmSlot += 4; + smb_SetSMBParm(outp, parmSlot, 0); parmSlot++; /* filetype */ + smb_SetSMBParm(outp, parmSlot, 0); parmSlot++; /* dev state */ + smb_SetSMBParmByte(outp, parmSlot, + scp->fileType == CM_SCACHETYPE_DIRECTORY); /* is a dir? */ + lock_ReleaseMutex(&scp->mx); + smb_SetSMBDataLength(outp, 0); - osi_Log2(smb_logp, "SMB NT CreateX opening fid %d path %s", fidp->fid, - osi_LogSaveString(smb_logp, realPathp)); + osi_Log2(smb_logp, "SMB NT CreateX opening fid %d path %s", fidp->fid, + osi_LogSaveString(smb_logp, realPathp)); - smb_ReleaseFID(fidp); + smb_ReleaseFID(fidp); - cm_ReleaseUser(userp); + cm_ReleaseUser(userp); /* Can't free realPathp if we get here since fidp->NTopen_wholepathp is pointing there */ - /* leave scp held since we put it in fidp->scp */ - return 0; -} + /* leave scp held since we put it in fidp->scp */ + return 0; +} /* * A lot of stuff copied verbatim from NT Create&X to NT Tran Create. @@ -5188,165 +5270,167 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) */ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) { - char *pathp, *realPathp; - long code = 0; - cm_space_t *spacep; - cm_user_t *userp; - cm_scache_t *dscp; /* parent dir */ - cm_scache_t *scp; /* file to create or open */ - cm_attr_t setAttr; - char *lastNamep; - unsigned long nameLength; - unsigned int flags; - unsigned int requestOpLock; - unsigned int requestBatchOpLock; - unsigned int mustBeDir; + char *pathp, *realPathp; + long code = 0; + cm_space_t *spacep; + cm_user_t *userp; + cm_scache_t *dscp; /* parent dir */ + cm_scache_t *scp; /* file to create or open */ + cm_scache_t *targetScp; /* if scp is a symlink */ + cm_attr_t setAttr; + char *lastNamep; + unsigned long nameLength; + unsigned int flags; + unsigned int requestOpLock; + unsigned int requestBatchOpLock; + unsigned int mustBeDir; unsigned int extendedRespRequired; - int realDirFlag; - unsigned int desiredAccess; + int realDirFlag; + unsigned int desiredAccess; #ifdef DEBUG_VERBOSE unsigned int allocSize; unsigned int shareAccess; #endif - unsigned int extAttributes; - unsigned int createDisp; + unsigned int extAttributes; + unsigned int createDisp; #ifdef DEBUG_VERBOSE unsigned int sdLen; #endif - unsigned int createOptions; - int initialModeBits; - unsigned short baseFid; - smb_fid_t *baseFidp; - smb_fid_t *fidp; - cm_scache_t *baseDirp; - unsigned short openAction; - int parmSlot; - long fidflags; - FILETIME ft; - char *tidPathp; - BOOL foundscp; - int parmOffset, dataOffset; - char *parmp; - ULONG *lparmp; - char *outData; - cm_req_t req; + unsigned int createOptions; + int initialModeBits; + unsigned short baseFid; + smb_fid_t *baseFidp; + smb_fid_t *fidp; + cm_scache_t *baseDirp; + unsigned short openAction; + int parmSlot; + long fidflags; + FILETIME ft; + char *tidPathp; + BOOL foundscp; + int parmOffset, dataOffset; + char *parmp; + ULONG *lparmp; + char *outData; + cm_req_t req; - cm_InitReq(&req); + cm_InitReq(&req); - foundscp = FALSE; - scp = NULL; + foundscp = FALSE; + scp = NULL; - parmOffset = smb_GetSMBOffsetParm(inp, 11, 1) - | (smb_GetSMBOffsetParm(inp, 12, 1) << 16); - parmp = inp->data + parmOffset; - lparmp = (ULONG *) parmp; + parmOffset = smb_GetSMBOffsetParm(inp, 11, 1) + | (smb_GetSMBOffsetParm(inp, 12, 1) << 16); + parmp = inp->data + parmOffset; + lparmp = (ULONG *) parmp; - flags = lparmp[0]; - requestOpLock = flags & 0x02; - requestBatchOpLock = flags & 0x04; - mustBeDir = flags & 0x08; + flags = lparmp[0]; + requestOpLock = flags & 0x02; + requestBatchOpLock = flags & 0x04; + mustBeDir = flags & 0x08; extendedRespRequired = flags & 0x10; - /* - * Why all of a sudden 32-bit FID? - * We will reject all bits higher than 16. - */ - if (lparmp[1] & 0xFFFF0000) - return CM_ERROR_INVAL; - baseFid = (unsigned short)lparmp[1]; - desiredAccess = lparmp[2]; + /* + * Why all of a sudden 32-bit FID? + * We will reject all bits higher than 16. + */ + if (lparmp[1] & 0xFFFF0000) + return CM_ERROR_INVAL; + baseFid = (unsigned short)lparmp[1]; + desiredAccess = lparmp[2]; #ifdef DEBUG_VERBOSE allocSize = lparmp[3]; #endif /* DEBUG_VERSOSE */ - extAttributes = lparmp[5]; + extAttributes = lparmp[5]; #ifdef DEBUG_VEROSE shareAccess = lparmp[6]; #endif - createDisp = lparmp[7]; - createOptions = lparmp[8]; + createDisp = lparmp[7]; + createOptions = lparmp[8]; #ifdef DEBUG_VERBOSE sdLen = lparmp[9]; #endif - nameLength = lparmp[11]; + nameLength = lparmp[11]; #ifdef DEBUG_VERBOSE - osi_Log4(smb_logp,"NTTransCreate with da[%x],ea[%x],sa[%x],cd[%x]",desiredAccess,extAttributes,shareAccess,createDisp); - osi_Log2(smb_logp,"... co[%x],sdl[%x],as[%x]",createOptions,sdLen,allocSize); - osi_Log1(smb_logp,"... flags[%x]",flags); + osi_Log4(smb_logp,"NTTranCreate with da[%x],ea[%x],sa[%x],cd[%x]",desiredAccess,extAttributes,shareAccess,createDisp); + osi_Log3(smb_logp,"... co[%x],sdl[%x],as[%x]",createOptions,sdLen,allocSize); + osi_Log1(smb_logp,"... flags[%x]",flags); #endif - /* mustBeDir is never set; createOptions directory bit seems to be - * more important - */ - if (createOptions & 1) - realDirFlag = 1; - else if (createOptions & 0x40) - realDirFlag = 0; - else - realDirFlag = -1; + /* mustBeDir is never set; createOptions directory bit seems to be + * more important + */ + if (createOptions & 1) + realDirFlag = 1; + else if (createOptions & 0x40) + realDirFlag = 0; + else + realDirFlag = -1; - /* - * compute initial mode bits based on read-only flag in - * extended attributes - */ - initialModeBits = 0666; - if (extAttributes & 1) initialModeBits &= ~0222; + /* + * compute initial mode bits based on read-only flag in + * extended attributes + */ + initialModeBits = 0666; + if (extAttributes & 1) + initialModeBits &= ~0222; - pathp = parmp + (13 * sizeof(ULONG)) + sizeof(UCHAR); - /* Sometimes path is not null-terminated, so we make a copy. */ - realPathp = malloc(nameLength+1); - memcpy(realPathp, pathp, nameLength); - realPathp[nameLength] = 0; + pathp = parmp + (13 * sizeof(ULONG)) + sizeof(UCHAR); + /* Sometimes path is not null-terminated, so we make a copy. */ + realPathp = malloc(nameLength+1); + memcpy(realPathp, pathp, nameLength); + realPathp[nameLength] = 0; - spacep = cm_GetSpace(); - smb_StripLastComponent(spacep->data, &lastNamep, realPathp); + spacep = cm_GetSpace(); + smb_StripLastComponent(spacep->data, &lastNamep, realPathp); - /* - * Nothing here to handle SMB_IOCTL_FILENAME. - * Will add it if necessary. - */ + /* + * Nothing here to handle SMB_IOCTL_FILENAME. + * Will add it if necessary. + */ #ifdef DEBUG_VERBOSE - { - char *hexp, *asciip; - asciip = (lastNamep? lastNamep : realPathp); - hexp = osi_HexifyString( asciip ); - DEBUG_EVENT2("AFS", "NTTranCreate H[%s] A[%s]", hexp, asciip); - free(hexp); - } + { + char *hexp, *asciip; + asciip = (lastNamep? lastNamep : realPathp); + hexp = osi_HexifyString( asciip ); + DEBUG_EVENT2("AFS", "NTTranCreate H[%s] A[%s]", hexp, asciip); + free(hexp); + } #endif - userp = smb_GetUser(vcp, inp); + userp = smb_GetUser(vcp, inp); if (!userp) { osi_Log1(smb_logp, "NTTranCreate invalid user [%d]", ((smb_t *) inp)->uid); free(realPathp); return CM_ERROR_INVAL; } - if (baseFid == 0) { - baseDirp = cm_rootSCachep; - code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp); + if (baseFid == 0) { + baseDirp = cm_rootSCachep; + code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp); if(code == CM_ERROR_TIDIPC) { /* Attempt to use TID allocated for IPC. The client is - probably trying to locate DCE RPC endpoints, which we - don't support. */ + * probably trying to locate DCE RPC endpoints, which we + * don't support. */ osi_Log0(smb_logp, "NTTranCreate received IPC TID"); free(realPathp); cm_ReleaseUser(userp); return CM_ERROR_NOSUCHPATH; } - } - else { + } + else { baseFidp = smb_FindFID(vcp, baseFid, 0); if (!baseFidp) { osi_Log1(smb_logp, "NTTranCreate Invalid fid [%d]", baseFid); - free(realPathp); - cm_ReleaseUser(userp); - return CM_ERROR_INVAL; - } - baseDirp = baseFidp->scp; - tidPathp = NULL; - } + free(realPathp); + cm_ReleaseUser(userp); + return CM_ERROR_INVAL; + } + baseDirp = baseFidp->scp; + tidPathp = NULL; + } /* compute open mode */ fidflags = 0; @@ -5357,9 +5441,11 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out if (desiredAccess & AFS_ACCESS_WRITE) fidflags |= SMB_FID_OPENWRITE; - dscp = NULL; - code = 0; - if (createDisp == 2 || createDisp == 4 || createDisp == 5) { + dscp = NULL; + code = 0; + if ( createDisp == FILE_OPEN || + createDisp == FILE_OVERWRITE || + createDisp == FILE_OVERWRITE_IF) { code = cm_NameI(baseDirp, spacep->data, CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD, userp, tidPathp, &req, &dscp); if (code == 0) { @@ -5369,7 +5455,7 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out code = cm_Lookup(dscp, (lastNamep)?(lastNamep+1):realPathp, CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD, userp, &req, &scp); if (code == 0 && realDirFlag == 1) { - cm_ReleaseSCache(scp); + cm_ReleaseSCache(scp); cm_ReleaseSCache(dscp); cm_ReleaseUser(userp); free(realPathp); @@ -5383,10 +5469,11 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out userp, tidPathp, &req, &scp); } - if (code == 0) foundscp = TRUE; - if (code != 0 - || (fidflags & (SMB_FID_OPENDELETE | SMB_FID_OPENWRITE))) { - /* look up parent directory */ + if (code == 0) + foundscp = TRUE; + if (code != 0 + || (fidflags & (SMB_FID_OPENDELETE | SMB_FID_OPENWRITE))) { + /* look up parent directory */ if ( !dscp ) { code = cm_NameI(baseDirp, spacep->data, CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD, @@ -5396,179 +5483,233 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out cm_FreeSpace(spacep); - if (baseFid != 0) { - smb_ReleaseFID(baseFidp); - baseFidp = 0; + if (baseFid != 0) { + smb_ReleaseFID(baseFidp); + baseFidp = 0; } - if (code) { - cm_ReleaseUser(userp); - free(realPathp); - return code; - } + if (code) { + cm_ReleaseUser(userp); + free(realPathp); + return code; + } - if (!lastNamep) lastNamep = realPathp; - else lastNamep++; + if (!lastNamep) lastNamep = realPathp; + else lastNamep++; if (!smb_IsLegalFilename(lastNamep)) return CM_ERROR_BADNTFILENAME; - if (!foundscp) { - if (createDisp == 2 || createDisp == 4) + if (!foundscp) { + if (createDisp == FILE_CREATE || createDisp == FILE_OVERWRITE_IF) { code = cm_Lookup(dscp, lastNamep, - CM_FLAG_FOLLOW, userp, &req, &scp); - else + CM_FLAG_FOLLOW, userp, &req, &scp); + } else { code = cm_Lookup(dscp, lastNamep, CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD, userp, &req, &scp); - if (code && code != CM_ERROR_NOSUCHFILE) { - cm_ReleaseSCache(dscp); - cm_ReleaseUser(userp); - free(realPathp); - return code; - } - } - } - else { - if (baseFid != 0) { + } + if (code && code != CM_ERROR_NOSUCHFILE) { + cm_ReleaseSCache(dscp); + cm_ReleaseUser(userp); + free(realPathp); + return code; + } + } + } + else { + if (baseFid != 0) { smb_ReleaseFID(baseFidp); baseFidp = 0; } - cm_FreeSpace(spacep); - } + cm_FreeSpace(spacep); + } - /* if we get here, if code is 0, the file exists and is represented by - * scp. Otherwise, we have to create it. The dir may be represented - * by dscp, or we may have found the file directly. If code is non-zero, - * scp is NULL. - */ - if (code == 0) { - code = cm_CheckNTOpen(scp, desiredAccess, createDisp, userp, - &req); - if (code) { - if (dscp) cm_ReleaseSCache(dscp); - cm_ReleaseSCache(scp); - cm_ReleaseUser(userp); - free(realPathp); - return code; - } + /* if we get here, if code is 0, the file exists and is represented by + * scp. Otherwise, we have to create it. The dir may be represented + * by dscp, or we may have found the file directly. If code is non-zero, + * scp is NULL. + */ + if (code == 0) { + code = cm_CheckNTOpen(scp, desiredAccess, createDisp, userp, + &req); + if (code) { + if (dscp) cm_ReleaseSCache(dscp); + cm_ReleaseSCache(scp); + cm_ReleaseUser(userp); + free(realPathp); + return code; + } - if (createDisp == 2) { - /* oops, file shouldn't be there */ - if (dscp) cm_ReleaseSCache(dscp); - cm_ReleaseSCache(scp); - cm_ReleaseUser(userp); - free(realPathp); - return CM_ERROR_EXISTS; - } + if (createDisp == FILE_CREATE) { + /* oops, file shouldn't be there */ + if (dscp) cm_ReleaseSCache(dscp); + cm_ReleaseSCache(scp); + cm_ReleaseUser(userp); + free(realPathp); + return CM_ERROR_EXISTS; + } - if (createDisp == 4 - || createDisp == 5) { - setAttr.mask = CM_ATTRMASK_LENGTH; - setAttr.length.LowPart = 0; - setAttr.length.HighPart = 0; - code = cm_SetAttr(scp, &setAttr, userp, &req); - openAction = 3; /* truncated existing file */ - } - else openAction = 1; /* found existing file */ - } - else if (createDisp == 1 || createDisp == 4) { - /* don't create if not found */ - if (dscp) cm_ReleaseSCache(dscp); - cm_ReleaseUser(userp); - free(realPathp); - return CM_ERROR_NOSUCHFILE; - } - else if (realDirFlag == 0 || realDirFlag == -1) { - osi_assert(dscp != NULL); - osi_Log1(smb_logp, "smb_ReceiveNTTranCreate creating file %s", - osi_LogSaveString(smb_logp, lastNamep)); - openAction = 2; /* created file */ - setAttr.mask = CM_ATTRMASK_CLIENTMODTIME; - setAttr.clientModTime = time(NULL); - code = cm_Create(dscp, lastNamep, 0, &setAttr, &scp, userp, - &req); - if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH)) - smb_NotifyChange(FILE_ACTION_ADDED, - FILE_NOTIFY_CHANGE_FILE_NAME, - dscp, lastNamep, NULL, TRUE); - if (code == CM_ERROR_EXISTS && createDisp != 2) { - /* Not an exclusive create, and someone else tried - * creating it already, then we open it anyway. We - * don't bother retrying after this, since if this next - * fails, that means that the file was deleted after we - * started this call. - */ - code = cm_Lookup(dscp, lastNamep, CM_FLAG_CASEFOLD, - userp, &req, &scp); - if (code == 0) { - if (createDisp == 5) { - setAttr.mask = CM_ATTRMASK_LENGTH; - setAttr.length.LowPart = 0; - setAttr.length.HighPart = 0; - code = cm_SetAttr(scp, &setAttr, userp, - &req); - } - } /* lookup succeeded */ - } - } - else { - /* create directory */ - osi_assert(dscp != NULL); - osi_Log1(smb_logp, - "smb_ReceiveNTTranCreate creating directory %s", - osi_LogSaveString(smb_logp, lastNamep)); - openAction = 2; /* created directory */ - setAttr.mask = CM_ATTRMASK_CLIENTMODTIME; - setAttr.clientModTime = time(NULL); - code = cm_MakeDir(dscp, lastNamep, 0, &setAttr, userp, &req); - if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH)) - smb_NotifyChange(FILE_ACTION_ADDED, - FILE_NOTIFY_CHANGE_DIR_NAME, - dscp, lastNamep, NULL, TRUE); - if (code == 0 - || (code == CM_ERROR_EXISTS && createDisp != 2)) { - /* Not an exclusive create, and someone else tried - * creating it already, then we open it anyway. We - * don't bother retrying after this, since if this next - * fails, that means that the file was deleted after we - * started this call. - */ - code = cm_Lookup(dscp, lastNamep, CM_FLAG_CASEFOLD, - userp, &req, &scp); - } - } + if (createDisp == FILE_OVERWRITE || + createDisp == FILE_OVERWRITE_IF) { + setAttr.mask = CM_ATTRMASK_LENGTH; + setAttr.length.LowPart = 0; + setAttr.length.HighPart = 0; - if (code) { - /* something went wrong creating or truncating the file */ - if (scp) cm_ReleaseSCache(scp); - cm_ReleaseUser(userp); - free(realPathp); - return code; - } + /* now watch for a symlink */ + code = 0; + while (code == 0 && scp->fileType == CM_SCACHETYPE_SYMLINK) { + targetScp = 0; + code = cm_EvaluateSymLink(dscp, scp, &targetScp, userp, &req); + if (code == 0) { + /* we have a more accurate file to use (the + * target of the symbolic link). Otherwise, + * we'll just use the symlink anyway. + */ + osi_Log2(smb_logp, "symlink vp %x to vp %x", + scp, targetScp); + cm_ReleaseSCache(scp); + scp = targetScp; + } + } + code = cm_SetAttr(scp, &setAttr, userp, &req); + openAction = 3; /* truncated existing file */ + } + else openAction = 1; /* found existing file */ + } + else if (createDisp == FILE_OPEN || createDisp == FILE_OVERWRITE) { + /* don't create if not found */ + if (dscp) cm_ReleaseSCache(dscp); + cm_ReleaseUser(userp); + free(realPathp); + return CM_ERROR_NOSUCHFILE; + } + else if (realDirFlag == 0 || realDirFlag == -1) { + osi_assert(dscp != NULL); + osi_Log1(smb_logp, "smb_ReceiveNTTranCreate creating file %s", + osi_LogSaveString(smb_logp, lastNamep)); + openAction = 2; /* created file */ + setAttr.mask = CM_ATTRMASK_CLIENTMODTIME; + setAttr.clientModTime = time(NULL); + code = cm_Create(dscp, lastNamep, 0, &setAttr, &scp, userp, + &req); + if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH)) + smb_NotifyChange(FILE_ACTION_ADDED, + FILE_NOTIFY_CHANGE_FILE_NAME, + dscp, lastNamep, NULL, TRUE); + if (code == CM_ERROR_EXISTS && createDisp != FILE_CREATE) { + /* Not an exclusive create, and someone else tried + * creating it already, then we open it anyway. We + * don't bother retrying after this, since if this next + * fails, that means that the file was deleted after we + * started this call. + */ + code = cm_Lookup(dscp, lastNamep, CM_FLAG_CASEFOLD, + userp, &req, &scp); + if (code == 0) { + if (createDisp == FILE_OVERWRITE_IF) { + setAttr.mask = CM_ATTRMASK_LENGTH; + setAttr.length.LowPart = 0; + setAttr.length.HighPart = 0; - /* make sure we have file vs. dir right */ - if (realDirFlag == 0 && scp->fileType != CM_SCACHETYPE_FILE) { - cm_ReleaseSCache(scp); - cm_ReleaseUser(userp); - free(realPathp); - return CM_ERROR_ISDIR; - } - if (realDirFlag == 1 && scp->fileType == CM_SCACHETYPE_FILE) { - cm_ReleaseSCache(scp); - cm_ReleaseUser(userp); - free(realPathp); - return CM_ERROR_NOTDIR; - } + /* now watch for a symlink */ + code = 0; + while (code == 0 && scp->fileType == CM_SCACHETYPE_SYMLINK) { + targetScp = 0; + code = cm_EvaluateSymLink(dscp, scp, &targetScp, userp, &req); + if (code == 0) { + /* we have a more accurate file to use (the + * target of the symbolic link). Otherwise, + * we'll just use the symlink anyway. + */ + osi_Log2(smb_logp, "symlink vp %x to vp %x", + scp, targetScp); + cm_ReleaseSCache(scp); + scp = targetScp; + } + } + code = cm_SetAttr(scp, &setAttr, userp, &req); + } + } /* lookup succeeded */ + } + } + else { + /* create directory */ + osi_assert(dscp != NULL); + osi_Log1(smb_logp, + "smb_ReceiveNTTranCreate creating directory %s", + osi_LogSaveString(smb_logp, lastNamep)); + openAction = 2; /* created directory */ + setAttr.mask = CM_ATTRMASK_CLIENTMODTIME; + setAttr.clientModTime = time(NULL); + code = cm_MakeDir(dscp, lastNamep, 0, &setAttr, userp, &req); + if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH)) + smb_NotifyChange(FILE_ACTION_ADDED, + FILE_NOTIFY_CHANGE_DIR_NAME, + dscp, lastNamep, NULL, TRUE); + if (code == 0 || + (code == CM_ERROR_EXISTS && createDisp != FILE_CREATE)) { + /* Not an exclusive create, and someone else tried + * creating it already, then we open it anyway. We + * don't bother retrying after this, since if this next + * fails, that means that the file was deleted after we + * started this call. + */ + code = cm_Lookup(dscp, lastNamep, CM_FLAG_CASEFOLD, + userp, &req, &scp); + } + } - /* open the file itself */ - fidp = smb_FindFID(vcp, 0, SMB_FLAG_CREATE); - osi_assert(fidp); + if (code) { + /* something went wrong creating or truncating the file */ + if (scp) cm_ReleaseSCache(scp); + cm_ReleaseUser(userp); + free(realPathp); + return code; + } - /* save a pointer to the vnode */ - fidp->scp = scp; + /* make sure we have file vs. dir right */ + if (realDirFlag == 0 && scp->fileType != CM_SCACHETYPE_FILE) { + /* now watch for a symlink */ + code = 0; + while (code == 0 && scp->fileType == CM_SCACHETYPE_SYMLINK) { + targetScp = 0; + code = cm_EvaluateSymLink(dscp, scp, &targetScp, userp, &req); + if (code == 0) { + /* we have a more accurate file to use (the + * target of the symbolic link). Otherwise, + * we'll just use the symlink anyway. + */ + osi_Log2(smb_logp, "symlink vp %x to vp %x", + scp, targetScp); + cm_ReleaseSCache(scp); + scp = targetScp; + } + } - fidp->flags = fidflags; + if (scp->fileType != CM_SCACHETYPE_FILE) { + cm_ReleaseSCache(scp); + cm_ReleaseUser(userp); + free(realPathp); + return CM_ERROR_ISDIR; + } + } + + if (realDirFlag == 1 && scp->fileType == CM_SCACHETYPE_FILE) { + cm_ReleaseSCache(scp); + cm_ReleaseUser(userp); + free(realPathp); + return CM_ERROR_NOTDIR; + } + + /* open the file itself */ + fidp = smb_FindFID(vcp, 0, SMB_FLAG_CREATE); + osi_assert(fidp); + + /* save a pointer to the vnode */ + fidp->scp = scp; + + fidp->flags = fidflags; /* save parent dir and pathname for deletion or change notification */ if (fidflags & (SMB_FID_OPENDELETE | SMB_FID_OPENWRITE)) { @@ -5577,15 +5718,15 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out cm_HoldSCache(dscp); fidp->NTopen_pathp = strdup(lastNamep); } - fidp->NTopen_wholepathp = realPathp; + fidp->NTopen_wholepathp = realPathp; - /* we don't need this any longer */ - if (dscp) cm_ReleaseSCache(dscp); + /* we don't need this any longer */ + if (dscp) cm_ReleaseSCache(dscp); - cm_Open(scp, 0, userp); + cm_Open(scp, 0, userp); - /* set inp->fid so that later read calls in same msg can find fid */ - inp->fid = fidp->fid; + /* set inp->fid so that later read calls in same msg can find fid */ + inp->fid = fidp->fid; /* check whether we are required to send an extended response */ if (!extendedRespRequired) { @@ -5689,15 +5830,15 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out lock_ReleaseMutex(&scp->mx); } - osi_Log1(smb_logp, "SMB NTTranCreate opening fid %d", fidp->fid); + osi_Log1(smb_logp, "SMB NTTranCreate opening fid %d", fidp->fid); - smb_ReleaseFID(fidp); + smb_ReleaseFID(fidp); - cm_ReleaseUser(userp); + cm_ReleaseUser(userp); - /* free(realPathp); Can't free realPathp here because fidp->NTopen_wholepathp points there */ - /* leave scp held since we put it in fidp->scp */ - return 0; + /* free(realPathp); Can't free realPathp here because fidp->NTopen_wholepathp points there */ + /* leave scp held since we put it in fidp->scp */ + return 0; } long smb_ReceiveNTTranNotifyChange(smb_vc_t *vcp, smb_packet_t *inp, @@ -5828,26 +5969,26 @@ long smb_ReceiveNTTranQuerySecurityDesc(smb_vc_t *vcp, smb_packet_t *inp, smb_pa long smb_ReceiveNTTransact(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) { - unsigned short function; + unsigned short function; - function = smb_GetSMBParm(inp, 18); + function = smb_GetSMBParm(inp, 18); - osi_Log1(smb_logp, "SMB NT Transact function %d", function); + osi_Log1(smb_logp, "SMB NT Transact function %d", function); - /* We can handle long names */ - if (vcp->flags & SMB_VCFLAG_USENT) - ((smb_t *)outp)->flg2 |= 0x40; /* IS_LONG_NAME */ + /* We can handle long names */ + if (vcp->flags & SMB_VCFLAG_USENT) + ((smb_t *)outp)->flg2 |= 0x40; /* IS_LONG_NAME */ - switch (function) { - - case 6: return smb_ReceiveNTTranQuerySecurityDesc(vcp, inp, outp); - - case 4: return smb_ReceiveNTTranNotifyChange(vcp, inp, outp); - - case 1: return smb_ReceiveNTTranCreate(vcp, inp, outp); - - default: return CM_ERROR_INVAL; - } + switch (function) { + case 6: + return smb_ReceiveNTTranQuerySecurityDesc(vcp, inp, outp); + case 4: + return smb_ReceiveNTTranNotifyChange(vcp, inp, outp); + case 1: + return smb_ReceiveNTTranCreate(vcp, inp, outp); + default: + return CM_ERROR_INVAL; + } } /* @@ -6103,9 +6244,52 @@ long smb_ReceiveNTCancel(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) return 0; } +/* + * NT rename also does hard links. + */ + +#define RENAME_FLAG_MOVE_CLUSTER_INFORMATION 0x102 +#define RENAME_FLAG_HARD_LINK 0x103 +#define RENAME_FLAG_RENAME 0x104 +#define RENAME_FLAG_COPY 0x105 + +long smb_ReceiveNTRename(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) +{ + char *oldname, *newname; + long code = 0; + cm_user_t *userp; + char * tp; + int attrs; + int rename_type; + + attrs = smb_GetSMBParm(inp, 0); + rename_type = smb_GetSMBParm(inp, 1); + + if (rename_type != RENAME_FLAG_RENAME && rename_type != RENAME_FLAG_HARD_LINK) { + osi_Log1(smb_logp, "NTRename invalid infolevel [%x]", rename_type); + return CM_ERROR_NOACCESS; + } + + tp = smb_GetSMBData(inp, NULL); + oldname = smb_ParseASCIIBlock(tp, &tp); + newname = smb_ParseASCIIBlock(tp, &tp); + + osi_Log3(smb_logp, "NTRename for [%s]->[%s] type [%s]", + osi_LogSaveString(smb_logp, oldname), + osi_LogSaveString(smb_logp, newname), + ((rename_type==RENAME_FLAG_RENAME)?"rename":"hardlink")); + + if (rename_type == RENAME_FLAG_RENAME) { + code = smb_Rename(vcp,inp,oldname,newname,attrs); + } else { /* RENAME_FLAG_HARD_LINK */ + code = smb_Link(vcp,inp,oldname,newname); + } + return code; +} + void smb3_Init() { - lock_InitializeMutex(&smb_Dir_Watch_Lock, "Directory Watch List Lock"); + lock_InitializeMutex(&smb_Dir_Watch_Lock, "Directory Watch List Lock"); } cm_user_t *smb_FindCMUserByName(/*smb_vc_t *vcp,*/ char *usern, char *machine) diff --git a/src/WINNT/afsd/smb3.h b/src/WINNT/afsd/smb3.h index 03f3a5aa9f..99f5ca5802 100644 --- a/src/WINNT/afsd/smb3.h +++ b/src/WINNT/afsd/smb3.h @@ -149,7 +149,16 @@ extern long smb_ReceiveTran2FindNotifyFirst(smb_vc_t *vcp, smb_tran2Packet_t *p, extern long smb_ReceiveTran2FindNotifyNext(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *outp); -extern long smb_ReceiveTran2MKDir(smb_vc_t *vcp, smb_tran2Packet_t *p, +extern long smb_ReceiveTran2CreateDirectory(smb_vc_t *vcp, smb_tran2Packet_t *p, + smb_packet_t *outp); + +extern long smb_ReceiveTran2SessionSetup(smb_vc_t *vcp, smb_tran2Packet_t *p, + smb_packet_t *outp); + +extern long smb_ReceiveTran2GetDFSReferral(smb_vc_t *vcp, smb_tran2Packet_t *p, + smb_packet_t *outp); + +extern long smb_ReceiveTran2ReportDFSInconsistency(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *outp); extern long smb_ReceiveV3FindClose(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp); @@ -178,6 +187,8 @@ extern void smb_NotifyChange(DWORD action, DWORD notifyFilter, extern long smb_ReceiveNTCancel(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp); +extern long smb_ReceiveNTRename(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp); + extern int smb_V3MatchMask(char *namep, char *maskp, int flags); extern void smb3_Init(); diff --git a/src/WINNT/install/wix/NTMakefile b/src/WINNT/install/wix/NTMakefile index 0dff735c0c..8ea9570bf3 100644 --- a/src/WINNT/install/wix/NTMakefile +++ b/src/WINNT/install/wix/NTMakefile @@ -30,7 +30,7 @@ languages: # ) $(MAKE) /f NTMakefile /nologo LANG=en_US lang -lang:: $(MSIFILE) +lang:: lang_clean $(MSIFILE) customactions: $(CD) custom diff --git a/src/config/NTMakefile.i386_nt40 b/src/config/NTMakefile.i386_nt40 index 9bf0a49219..229efba09a 100644 --- a/src/config/NTMakefile.i386_nt40 +++ b/src/config/NTMakefile.i386_nt40 @@ -80,7 +80,7 @@ LIB = $(AFSDEV_LIB) #define used in WinNT/2000 installation and program version display AFSPRODUCT_VER_MAJOR=1 AFSPRODUCT_VER_MINOR=3 -AFSPRODUCT_VER_PATCH=7100 +AFSPRODUCT_VER_PATCH=7101 AFSPRODUCT_VER_BUILD=0 # For MSI installer, each major release should have a different GUID