STABLE14-windows-links-20040921

FIXES 915
FIXES 15250

  * 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.


(cherry picked from commit e07406e551)
This commit is contained in:
Jeffrey Altman 2004-09-21 15:07:12 +00:00 committed by Jeffrey Altman
parent 0b68a11a93
commit 02368492c4
11 changed files with 2241 additions and 1747 deletions

View File

@ -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"

View File

@ -196,3 +196,18 @@ List of unfunded projects:
afsmap.exe <drive> /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

View File

@ -30,7 +30,8 @@ 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) {
@ -43,13 +44,20 @@ long cm_MapRPCError(long error, cm_req_t *reqp)
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;
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;
@ -63,7 +71,10 @@ long cm_MapRPCError(long error, cm_req_t *reqp)
|| 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 == VNOVNODE)
error = CM_ERROR_BADFD;
else if (error == 21)
return CM_ERROR_ISDIR;
return error;
}

View File

@ -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)
{

View File

@ -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);

View File

@ -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 <afs/param.h>
#include <afs/stds.h>
@ -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 */
@ -215,8 +219,6 @@ char * myCrt_Dispatch(int i)
{
switch (i)
{
default:
return "unknown SMB op";
case 0x00:
return "(00)ReceiveCoreMakeDir";
case 0x01:
@ -301,20 +303,36 @@ char * myCrt_Dispatch(int i)
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)SendCoreBadOp";
return "(C0)OpenPrintFile";
case 0xc1:
return "(c1)SendCoreBadOp";
return "(C1)WritePrintFile";
case 0xc2:
return "(c2)SendCoreBadOp";
return "(C2)ClosePrintFile";
case 0xc3:
return "(c3)SendCoreBadOp";
return "(C3)GetPrintQueue";
case 0xd8:
return "(D8)ReadBulk";
case 0xd9:
return "(D9)WriteBulk";
case 0xda:
return "(DA)WriteBulkData";
default:
return "unknown SMB op";
}
}
@ -351,7 +369,9 @@ char * myCrt_2Dispatch(int i)
case 12:
return "S(0c)_ReceiveTran2FindNotifyNext";
case 13:
return "S(0d)CreateDirectory_ReceiveTran2MKDir";
return "S(0d)_ReceiveTran2CreateDirectory";
case 14:
return "S(0e)_ReceiveTran2SessionSetup";
}
}
@ -1511,7 +1531,7 @@ 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)
{
@ -2196,7 +2216,12 @@ void smb_MapNTError(long code, unsigned long *NTStatusp)
NTStatus = 0xC00000BAL; /* File is a directory */
}
else if (code == CM_ERROR_BADOP) {
#ifdef COMMENT
/* 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 */
@ -2418,6 +2443,7 @@ 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)
{
osi_Log0(smb_logp,"SendCoreBadOp - NOT_SUPPORTED");
return CM_ERROR_BADOP;
}
@ -4373,12 +4399,11 @@ 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;
@ -4394,21 +4419,17 @@ long smb_ReceiveCoreRename(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
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);
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));
spacep = inp->spacep;
smb_StripLastComponent(spacep->data, &oldLastNamep, oldPathp);
userp = smb_GetUser(vcp, inp);
/*
* Changed to use CASEFOLD always. This enables us to rename Foo/baz when
* what actually exists is foo/baz. I don't know why the code used to be
@ -4421,12 +4442,6 @@ 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;
code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp);
if(code) {
cm_ReleaseUser(userp);
return CM_ERROR_NOSUCHPATH;
}
code = cm_NameI(cm_rootSCachep, spacep->data, caseFold,
userp, tidPathp, &req, &oldDscp);
@ -4551,6 +4566,155 @@ long smb_ReceiveCoreRename(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
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;
@ -5982,7 +6146,7 @@ void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
oldGen = sessionGen;
oldTime = GetCurrentTime();
while(inp->inCom != 0xff) {
while (inp->inCom != 0xff) {
dp = &smb_dispatchTable[inp->inCom];
if (outp->flags & SMB_PACKETFLAG_SUSPENDED) {
@ -6032,6 +6196,11 @@ void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
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) {
@ -6054,16 +6223,18 @@ void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
}
else {
/* bad opcode, fail the request, after displaying it */
#ifdef NOTSERVICE
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);
code = (*smb_MBfunc)(NULL, tbuffer, "Cancel: don't show again",
MB_OKCANCEL|MB_SERVICE_NOTIFICATION);
if (code == IDCANCEL) showErrors = 0;
if (code == IDCANCEL)
showErrors = 0;
}
#endif /* DJGPP */
code = CM_ERROR_BADOP;
@ -6087,9 +6258,9 @@ void smb_DispatchPacket(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp,
ReportEvent(h, EVENTLOG_ERROR_TYPE, 0, 1002, NULL,
1, ncbp->ncb_length, ptbuf, smbp);
DeregisterEventSource(h);
#ifdef NOTSERVICE
#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);
@ -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);
@ -7351,6 +7522,11 @@ void smb_Init(osi_log_t *logp, char *snamep, int useV3, int LANadapt,
/* 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;
@ -7407,18 +7583,22 @@ void smb_Init(osi_log_t *logp, char *snamep, int useV3, int LANadapt,
smb_dispatchTable[0x75].flags |= SMB_DISPATCHFLAG_CHAINED;
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[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[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;
@ -7434,7 +7614,10 @@ void smb_Init(osi_log_t *logp, char *snamep, int useV3, int LANadapt,
smb_tran2DispatchTable[10].procp = smb_ReceiveTran2IOCTL;
smb_tran2DispatchTable[11].procp = smb_ReceiveTran2FindNotifyFirst;
smb_tran2DispatchTable[12].procp = smb_ReceiveTran2FindNotifyNext;
smb_tran2DispatchTable[13].procp = smb_ReceiveTran2MKDir;
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));
@ -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)
{

View File

@ -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);

View File

@ -997,7 +997,7 @@ long smb_ReceiveV3TreeConnectX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *o
((smb_t *)outp)->tid = newTid;
((smb_t *)inp)->tid = newTid;
tp = smb_GetSMBData(outp, NULL);
if(!ipc) {
if (!ipc) {
*tp++ = 'A';
*tp++ = ':';
*tp++ = 0;
@ -1018,7 +1018,7 @@ smb_tran2Packet_t *smb_FindTran2Packet(smb_vc_t *vcp, smb_packet_t *inp)
smb_t *smbp;
smbp = (smb_t *) inp->data;
for(tp = smb_tran2AssemblyQueuep; tp; tp = (smb_tran2Packet_t *) osi_QNext(&tp->q)) {
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;
}
@ -2106,7 +2106,7 @@ long smb_ReceiveTran2Open(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
}
code = smb_LookupTIDPath(vcp, p->tid, &tidPathp);
if(code == CM_ERROR_TIDIPC) {
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. */
@ -2136,8 +2136,10 @@ long smb_ReceiveTran2Open(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
* 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) {
@ -2180,7 +2182,8 @@ long smb_ReceiveTran2Open(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
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 */
@ -2234,12 +2237,29 @@ long smb_ReceiveTran2Open(smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op)
}
/* 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);
@ -2299,11 +2319,13 @@ 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;
}
@ -3074,7 +3096,8 @@ long smb_ApplyV3DirListPatches(cm_scache_t *dscp,
}
/* now watch for a symlink */
if (scp->fileType == CM_SCACHETYPE_SYMLINK) {
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) {
@ -4642,14 +4665,13 @@ 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)
{
@ -4659,6 +4681,7 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
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;
@ -4731,7 +4754,8 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
* extended attributes
*/
initialModeBits = 0666;
if (extAttributes & 1) initialModeBits &= ~0222;
if (extAttributes & 1)
initialModeBits &= ~0222;
pathp = smb_GetSMBData(inp, NULL);
/* Sometimes path is not null-terminated, so we make a copy. */
@ -4743,8 +4767,8 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
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
@ -4802,10 +4826,10 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
if (baseFid == 0) {
baseDirp = cm_rootSCachep;
code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp);
if(code == CM_ERROR_TIDIPC) {
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);
@ -4838,7 +4862,9 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
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) {
@ -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,13 +4958,16 @@ 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
} 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);
@ -4968,7 +4997,7 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
return code;
}
if (createDisp == 2) {
if (createDisp == FILE_CREATE) {
/* oops, file shouldn't be there */
if (dscp) cm_ReleaseSCache(dscp);
cm_ReleaseSCache(scp);
@ -4977,17 +5006,33 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
return CM_ERROR_EXISTS;
}
if (createDisp == 4
|| createDisp == 5) {
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 == 1 || createDisp == 4) {
else if (createDisp == FILE_OPEN || createDisp == FILE_OVERWRITE) {
/* don't create if not found */
if (dscp) cm_ReleaseSCache(dscp);
cm_ReleaseUser(userp);
@ -5007,7 +5052,7 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
smb_NotifyChange(FILE_ACTION_ADDED,
FILE_NOTIFY_CHANGE_FILE_NAME,
dscp, lastNamep, NULL, TRUE);
if (code == CM_ERROR_EXISTS && createDisp != 2) {
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
@ -5017,12 +5062,28 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
code = cm_Lookup(dscp, lastNamep, CM_FLAG_CASEFOLD,
userp, &req, &scp);
if (code == 0) {
if (createDisp == 5) {
if (createDisp == FILE_OVERWRITE_IF) {
setAttr.mask = CM_ATTRMASK_LENGTH;
setAttr.length.LowPart = 0;
setAttr.length.HighPart = 0;
code = cm_SetAttr(scp, &setAttr, userp,
&req);
/* 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 */
}
@ -5035,7 +5096,8 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
int isLast = 0;
/* create directory */
if ( !treeCreate ) treeStartp = lastNamep;
if ( !treeCreate )
treeStartp = lastNamep;
osi_assert(dscp != NULL);
osi_Log1(smb_logp, "smb_ReceiveNTCreateX creating directory [%s]",
osi_LogSaveString(smb_logp, treeStartp));
@ -5063,7 +5125,8 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
}
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);
@ -5072,7 +5135,7 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
FILE_NOTIFY_CHANGE_DIR_NAME,
tscp, cp, NULL, TRUE);
if (code == 0 ||
(code == CM_ERROR_EXISTS && createDisp != 2)) {
(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
@ -5091,8 +5154,8 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
}
/*
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.
* 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;
}
@ -5108,12 +5171,31 @@ long smb_ReceiveNTCreateX(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
/* 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);
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);
@ -5194,6 +5276,7 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
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;
@ -5270,8 +5353,8 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
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_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
@ -5290,7 +5373,8 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
* extended attributes
*/
initialModeBits = 0666;
if (extAttributes & 1) initialModeBits &= ~0222;
if (extAttributes & 1)
initialModeBits &= ~0222;
pathp = parmp + (13 * sizeof(ULONG)) + sizeof(UCHAR);
/* Sometimes path is not null-terminated, so we make a copy. */
@ -5328,8 +5412,8 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
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);
@ -5359,7 +5443,9 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
dscp = NULL;
code = 0;
if (createDisp == 2 || createDisp == 4 || createDisp == 5) {
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) {
@ -5383,7 +5469,8 @@ 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)
foundscp = TRUE;
if (code != 0
|| (fidflags & (SMB_FID_OPENDELETE | SMB_FID_OPENWRITE))) {
/* look up parent directory */
@ -5414,13 +5501,14 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
return CM_ERROR_BADNTFILENAME;
if (!foundscp) {
if (createDisp == 2 || createDisp == 4)
if (createDisp == FILE_CREATE || createDisp == FILE_OVERWRITE_IF) {
code = cm_Lookup(dscp, lastNamep,
CM_FLAG_FOLLOW, userp, &req, &scp);
else
} 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);
@ -5453,7 +5541,7 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
return code;
}
if (createDisp == 2) {
if (createDisp == FILE_CREATE) {
/* oops, file shouldn't be there */
if (dscp) cm_ReleaseSCache(dscp);
cm_ReleaseSCache(scp);
@ -5462,17 +5550,34 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
return CM_ERROR_EXISTS;
}
if (createDisp == 4
|| createDisp == 5) {
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 == 1 || createDisp == 4) {
else if (createDisp == FILE_OPEN || createDisp == FILE_OVERWRITE) {
/* don't create if not found */
if (dscp) cm_ReleaseSCache(dscp);
cm_ReleaseUser(userp);
@ -5492,7 +5597,7 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
smb_NotifyChange(FILE_ACTION_ADDED,
FILE_NOTIFY_CHANGE_FILE_NAME,
dscp, lastNamep, NULL, TRUE);
if (code == CM_ERROR_EXISTS && createDisp != 2) {
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
@ -5502,12 +5607,28 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
code = cm_Lookup(dscp, lastNamep, CM_FLAG_CASEFOLD,
userp, &req, &scp);
if (code == 0) {
if (createDisp == 5) {
if (createDisp == FILE_OVERWRITE_IF) {
setAttr.mask = CM_ATTRMASK_LENGTH;
setAttr.length.LowPart = 0;
setAttr.length.HighPart = 0;
code = cm_SetAttr(scp, &setAttr, userp,
&req);
/* 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 */
}
@ -5526,8 +5647,8 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
smb_NotifyChange(FILE_ACTION_ADDED,
FILE_NOTIFY_CHANGE_DIR_NAME,
dscp, lastNamep, NULL, TRUE);
if (code == 0
|| (code == CM_ERROR_EXISTS && createDisp != 2)) {
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
@ -5549,11 +5670,31 @@ long smb_ReceiveNTTranCreate(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *out
/* 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;
}
}
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);
@ -5839,14 +5980,14 @@ long smb_ReceiveNTTransact(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
((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;
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,6 +6244,49 @@ 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");

View File

@ -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();

View File

@ -30,7 +30,7 @@ languages:
# )
$(MAKE) /f NTMakefile /nologo LANG=en_US lang
lang:: $(MSIFILE)
lang:: lang_clean $(MSIFILE)
customactions:
$(CD) custom

View File

@ -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