#define CM_ERROR_EXISTS (CM_ERROR_BASE+11)
#define CM_ERROR_CROSSDEVLINK (CM_ERROR_BASE+12)
#define CM_ERROR_BADOP (CM_ERROR_BASE+13)
-#define CM_ERROR_BADSMB (CM_ERROR_BASE+32)
/* CM_ERROR_BADPASSWORD used to be here */
#define CM_ERROR_NOTDIR (CM_ERROR_BASE+15)
#define CM_ERROR_ISDIR (CM_ERROR_BASE+16)
#define CM_ERROR_REMOTECONN (CM_ERROR_BASE+27)
#define CM_ERROR_ATSYS (CM_ERROR_BASE+28)
#define CM_ERROR_NOSUCHPATH (CM_ERROR_BASE+29)
-
#define CM_ERROR_CLOCKSKEW (CM_ERROR_BASE+31)
-
+#define CM_ERROR_BADSMB (CM_ERROR_BASE+32)
#define CM_ERROR_ALLBUSY (CM_ERROR_BASE+33)
#define CM_ERROR_NOFILES (CM_ERROR_BASE+34)
#define CM_ERROR_PARTIALWRITE (CM_ERROR_BASE+35)
#define CM_ERROR_BUFFERTOOSMALL (CM_ERROR_BASE+38)
#define CM_ERROR_RENAME_IDENTICAL (CM_ERROR_BASE+39)
#define CM_ERROR_ALLOFFLINE (CM_ERROR_BASE+40)
-
+#define CM_ERROR_AMBIGUOUS_FILENAME (CM_ERROR_BASE+41)
#endif /* __CM_H_ENV__ */
dnlcstats.enters++;
for (tnc = nameHash[skey], safety=0; tnc; tnc = tnc->next, safety++ )
- if ((tnc->dirp == adp) && (!cm_stricmp(tnc->name, aname)))
+ if ((tnc->dirp == adp) && (!strcmp(tnc->name, aname)))
break; /* preexisting entry */
else if ( tnc->next == nameHash[skey]) /* end of list */
{
lock_ObtainRead(&cm_dnlcLock);
dnlcstats.lookups++; /* Is a dnlcread lock sufficient? */
+ ts = 0;
tnc_begin = nameHash[skey];
for ( tvc = (cm_scache_t *) 0, tnc = tnc_begin, safety=0;
tnc; tnc = tnc->next, safety++ )
{
if (tnc->dirp == adp)
{
+ if( cm_debugDnlc )
+ osi_Log1(afsd_logp,"Looking at [%s]",
+ osi_LogSaveString(afsd_logp,tnc->name));
+
if ( sp->caseFold ) /* case insensitive */
{
- match = cm_stricmp(tnc->name, aname);
- if ( !match ) /* something matches */
- {
- /* determine what type of match it is */
- if ( !strcmp(tnc->name, aname))
- {
- /* exact match, do nothing */
- }
- else if ( cm_NoneUpper(tnc->name))
- sp->LCfound = 1;
- else if ( cm_NoneLower(tnc->name))
- sp->UCfound = 1;
- else sp->NCfound = 1;
- tvc = tnc->vp;
- break;
- }
+ match = cm_stricmp(tnc->name, aname);
+ if ( !match ) /* something matches */
+ {
+ tvc = tnc->vp;
+ ts = tnc->name;
+
+ /* determine what type of match it is */
+ if ( !strcmp(tnc->name, aname))
+ {
+ /* exact match. */
+ sp->ExactFound = 1;
+
+ if( cm_debugDnlc )
+ osi_Log1(afsd_logp,"DNLC found exact match [%s]",
+ osi_LogSaveString(afsd_logp,tnc->name));
+ break;
+ }
+ else if ( cm_NoneUpper(tnc->name))
+ sp->LCfound = 1;
+ else if ( cm_NoneLower(tnc->name))
+ sp->UCfound = 1;
+ else
+ sp->NCfound = 1;
+ /* Don't break here. We might find an exact match yet */
+ }
}
else /* case sensitive */
{
- match = strcmp(tnc->name, aname);
- if ( !match ) /* found a match */
- {
- tvc = tnc->vp;
- break;
- }
+ match = strcmp(tnc->name, aname);
+ if ( !match ) /* found a match */
+ {
+ sp->ExactFound = 1;
+ tvc = tnc->vp;
+ ts = tnc->name;
+ break;
+ }
}
}
if (tnc->next == nameHash[skey])
}
}
+ if(cm_debugDnlc && ts) {
+ osi_Log3(afsd_logp, "DNLC matched [%s] for [%s] with vnode[%ld]",
+ osi_LogSaveString(afsd_logp,ts),
+ osi_LogSaveString(afsd_logp,aname),
+ (long) tvc->fid.vnode);
+ }
+
if (!tvc)
- dnlcstats.misses++; /* Is a dnlcread lock sufficient? */
+ dnlcstats.misses++; /* Is a dnlcread lock sufficient? */
else
{
- sp->found = 1;
- sp->fid.vnode = tvc->fid.vnode;
- sp->fid.unique = tvc->fid.unique;
+ sp->found = 1;
+ sp->fid.vnode = tvc->fid.vnode;
+ sp->fid.unique = tvc->fid.unique;
}
lock_ReleaseRead(&cm_dnlcLock);
if (tvc) {
- lock_ObtainWrite(&cm_scacheLock);
- tvc->refCount++; /* scache entry held */
- lock_ReleaseWrite(&cm_scacheLock);
+ lock_ObtainWrite(&cm_scacheLock);
+ tvc->refCount++; /* scache entry held */
+ lock_ReleaseWrite(&cm_scacheLock);
}
if ( cm_debugDnlc && tvc )
- osi_Log1(afsd_logp, "cm_dnlcLookup found %x", tvc);
+ osi_Log1(afsd_logp, "cm_dnlcLookup found %x", tvc);
return tvc;
}
for (tnc = nameHash[skey], safety=0; tnc; safety++)
{
if ( (tnc->dirp == adp) && (tnc->key == key)
- && !cm_stricmp(tnc->name,aname) )
+ && !strcmp(tnc->name,aname) )
{
tnc->dirp = (cm_scache_t *) 0; /* now it won't match anything */
tmp = tnc->next;
if ( retscp ) /* if this is a lookup call */
{
cm_lookupSearch_t* sp = parmp;
+ int casefold = sp->caseFold;
+
+ sp->caseFold = 0; /* we have a strong preference for exact matches */
if ( *retscp = cm_dnlcLookup(scp, sp)) /* dnlc hit */
{
+ sp->caseFold = casefold;
lock_ReleaseMutex(&scp->mx);
return 0;
}
+
+ sp->caseFold = casefold;
}
/*
osi_hyper_t *offp)
{
cm_lookupSearch_t *sp;
- int match;
+ int match;
char shortName[13];
char *matchName;
- sp = rockp;
+ sp = (cm_lookupSearch_t *) rockp;
matchName = dep->name;
if (sp->caseFold)
return 0;
sp->found = 1;
+ if(!sp->caseFold) sp->ExactFound = 1;
if (!sp->caseFold || matchName == shortName) {
sp->fid.vnode = ntohl(dep->fid.vnode);
sp->fid.unique = ntohl(dep->fid.unique);
- return CM_ERROR_STOPNOW;
- }
+ return CM_ERROR_STOPNOW;
+ }
/*
* If we get here, we are doing a case-insensitive search, and we
/* Exact matches are the best. */
match = strcmp(matchName, sp->searchNamep);
if (match == 0) {
+ sp->ExactFound = 1;
sp->fid.vnode = ntohl(dep->fid.vnode);
sp->fid.unique = ntohl(dep->fid.unique);
- return CM_ERROR_STOPNOW;
- }
+ return CM_ERROR_STOPNOW;
+ }
/* Lower-case matches are next. */
if (sp->LCfound)
*outpScpp = tscp;
/* insert scache in dnlc */
- if ( !dnlcHit && !(flags & CM_FLAG_NOMOUNTCHASE) ) {
+ if ( !dnlcHit && !(flags & CM_FLAG_NOMOUNTCHASE) && rock.ExactFound ) {
/* lock the directory entry to prevent racing callback revokes */
lock_ObtainMutex(&dscp->mx);
if ( dscp->cbServerp && dscp->cbExpires )
cm_fid_t fid;
char *searchNamep;
int found;
- int LCfound, UCfound, NCfound;
+ int LCfound, UCfound, NCfound, ExactFound;
int caseFold;
int hasTilde;
} cm_lookupSearch_t;
char *smb_RawBufs;
#endif /* DJGPP */
+#define SMB_MASKFLAG_TILDE 1
+#define SMB_MASKFLAG_CASEFOLD 2
+
#define RAWTIMEOUT INFINITE
/* for raw write */
else if (code == CM_ERROR_BUFFERTOOSMALL) {
NTStatus = 0xC0000023L; /* Buffer too small */
}
+ else if (code == CM_ERROR_AMBIGUOUS_FILENAME) {
+ NTStatus = 0xC000049CL; /* Potential file found */
+ }
else {
NTStatus = 0xC0982001L; /* SMB non-specific error */
}
cm_req_t *reqp;
smb_vc_t *vcp;
char *maskp; /* pointer to the star pattern */
- int hasTilde;
+ int flags;
int any;
} smb_unlinkRock_t;
rockp = vrockp;
- if (rockp->vcp->flags & SMB_VCFLAG_USEV3)
- caseFold = CM_FLAG_CASEFOLD;
- else
- caseFold = CM_FLAG_CASEFOLD | CM_FLAG_8DOT3;
+ caseFold = ((rockp->flags & SMB_MASKFLAG_CASEFOLD)? CM_FLAG_CASEFOLD : 0);
+ if (!(rockp->vcp->flags & SMB_VCFLAG_USEV3))
+ caseFold |= CM_FLAG_8DOT3;
matchName = dep->name;
match = smb_V3MatchMask(matchName, rockp->maskp, caseFold);
if (!match
- && rockp->hasTilde
+ && (rockp->flags & SMB_MASKFLAG_TILDE)
&& !cm_Is8Dot3(dep->name)) {
cm_Gen8Dot3Name(dep, shortName, NULL);
matchName = shortName;
- match = smb_V3MatchMask(matchName, rockp->maskp, caseFold);
+ /* 8.3 matches are always case insensitive */
+ match = smb_V3MatchMask(matchName, rockp->maskp, caseFold | CM_FLAG_CASEFOLD);
}
if (match) {
osi_Log1(smb_logp, "Unlinking %s",
smb_NotifyChange(FILE_ACTION_REMOVED,
FILE_NOTIFY_CHANGE_FILE_NAME,
dscp, dep->name, NULL, TRUE);
- if (code == 0)
+ if (code == 0) {
rockp->any = 1;
+ /* If we made a case sensitive exact match, we might as well quit now. */
+ if(!(rockp->flags & SMB_MASKFLAG_CASEFOLD) && !strcmp(matchName, rockp->maskp))
+ code = CM_ERROR_STOPNOW;
+ }
}
else code = 0;
rock.any = 0;
rock.maskp = smb_FindMask(pathp);
- rock.hasTilde = ((strchr(rock.maskp, '~') != NULL) ? 1 : 0);
+ rock.flags = ((strchr(rock.maskp, '~') != NULL) ? SMB_MASKFLAG_TILDE : 0);
thyper.LowPart = 0;
thyper.HighPart = 0;
rock.reqp = &req;
rock.dscp = dscp;
rock.vcp = vcp;
- code = cm_ApplyDir(dscp, smb_UnlinkProc, &rock, &thyper, userp, &req, NULL);
+
+ /* Now, if we aren't dealing with a wildcard match, we first try an exact
+ * match. If that fails, we do a case insensitve match.
+ */
+ if (!(rock.flags & SMB_MASKFLAG_TILDE) &&
+ !smb_IsStarMask(rock.maskp)) {
+ code = cm_ApplyDir(dscp, smb_UnlinkProc, &rock, &thyper, userp, &req, NULL);
+ if(!rock.any) {
+ thyper.LowPart = 0;
+ thyper.HighPart = 0;
+ rock.flags |= SMB_MASKFLAG_CASEFOLD;
+ }
+ }
+
+ if (!rock.any)
+ code = cm_ApplyDir(dscp, smb_UnlinkProc, &rock, &thyper, userp, &req, NULL);
+
+ if (code == CM_ERROR_STOPNOW)
+ code = 0;
cm_ReleaseUser(userp);
cm_req_t *reqp; /* request struct */
smb_vc_t *vcp; /* virtual circuit */
char *maskp; /* pointer to star pattern of old file name */
- int hasTilde; /* star pattern might be shortname? */
+ int flags; /* tilde, casefold, etc */
char *newNamep; /* ptr to the new file's name */
} smb_renameRock_t;
rockp = (smb_renameRock_t *) vrockp;
- if (rockp->vcp->flags & SMB_VCFLAG_USEV3)
- caseFold = CM_FLAG_CASEFOLD;
- else
- caseFold = CM_FLAG_CASEFOLD | CM_FLAG_8DOT3;
+ caseFold = ((rockp->flags & SMB_MASKFLAG_CASEFOLD)? CM_FLAG_CASEFOLD : 0);
+ if (!(rockp->vcp->flags & SMB_VCFLAG_USEV3))
+ caseFold |= CM_FLAG_8DOT3;
match = smb_V3MatchMask(dep->name, rockp->maskp, caseFold);
if (!match
- && rockp->hasTilde
+ && (rockp->flags & SMB_MASKFLAG_TILDE)
&& !cm_Is8Dot3(dep->name)) {
cm_Gen8Dot3Name(dep, shortName, NULL);
match = smb_V3MatchMask(shortName, rockp->maskp, caseFold);
char *oldPathp;
char *newPathp;
char *tp;
- cm_space_t *spacep;
+ cm_space_t *spacep = NULL;
smb_renameRock_t rock;
- cm_scache_t *oldDscp;
- cm_scache_t *newDscp;
- cm_scache_t *tmpscp;
+ 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;
oldPathp = smb_ParseASCIIBlock(tp, &tp);
newPathp = smb_ParseASCIIBlock(tp, &tp);
- osi_Log2(smb_logp, "smb rename %s to %s",
+ osi_Log2(smb_logp, "smb rename [%s] to [%s]",
osi_LogSaveString(smb_logp, oldPathp),
osi_LogSaveString(smb_logp, newPathp));
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.reqp = &req;
rock.vcp = vcp;
rock.maskp = oldLastNamep;
- rock.hasTilde = ((strchr(oldLastNamep, '~') != NULL) ? 1 : 0);
+ 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) ) {
- cm_ReleaseSCache(newDscp);
- cm_ReleaseSCache(oldDscp);
- cm_ReleaseUser(userp);
- if (!code)
- cm_ReleaseSCache(tmpscp);
+ if ((code != CM_ERROR_NOSUCHFILE) && (code != CM_ERROR_NOSUCHPATH) && (code != CM_ERROR_NOSUCHVOLUME) ) {
+ osi_Log2(afsd_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
*/
- if(oldDscp == newDscp && !stricmp(oldLastNamep, newLastNamep)) {
- osi_Log0(afsd_logp, "Rename: Old and new names are the same");
- code = 0;
+ if (!code && oldDscp == newDscp && !stricmp(oldLastNamep, newLastNamep)) {
+
+ /* This would be a success only if the old file is *as same as* the new file */
+ code = cm_Lookup(oldDscp, oldLastNamep, CM_FLAG_CHECKPATH, userp, &req, &tmpscp2);
+ if (!code) {
+ if (tmpscp == tmpscp2)
+ code = 0;
+ else
+ code = CM_ERROR_EXISTS;
+ cm_ReleaseSCache(tmpscp2);
+ tmpscp2 = NULL;
+ } else {
+ code = CM_ERROR_NOSUCHFILE;
+ }
} else {
/* file exist, do not rename, also fixes move */
osi_Log0(afsd_logp, "Can't rename. Target already exists");
code = CM_ERROR_EXISTS;
}
+
+ if(tmpscp != NULL)
+ cm_ReleaseSCache(tmpscp);
+ cm_ReleaseSCache(newDscp);
+ cm_ReleaseSCache(oldDscp);
+ cm_ReleaseUser(userp);
return code;
}
NULL, TRUE);
}
- cm_ReleaseUser(userp);
+ if(tmpscp != NULL)
+ cm_ReleaseSCache(tmpscp);
+ cm_ReleaseUser(userp);
cm_ReleaseSCache(oldDscp);
cm_ReleaseSCache(newDscp);
return code;
cm_user_t *userp;
cm_req_t *reqp;
char *maskp; /* pointer to the star pattern */
- int hasTilde;
+ int flags;
int any;
} smb_rmdirRock_t;
char shortName[13];
char *matchName;
- rockp = vrockp;
+ rockp = (smb_rmdirRock_t *) vrockp;
matchName = dep->name;
- match = (cm_stricmp(matchName, rockp->maskp) == 0);
+ if (rockp->flags & SMB_MASKFLAG_CASEFOLD)
+ match = (cm_stricmp(matchName, rockp->maskp) == 0);
+ else
+ match = (strcmp(matchName, rockp->maskp) == 0);
if (!match
- && rockp->hasTilde
+ && (rockp->flags & SMB_MASKFLAG_TILDE)
&& !cm_Is8Dot3(dep->name)) {
cm_Gen8Dot3Name(dep, shortName, NULL);
matchName = shortName;
rock.any = 0;
rock.maskp = lastNamep;
- rock.hasTilde = ((strchr(rock.maskp, '~') != NULL) ? 1 : 0);
+ rock.flags = ((strchr(rock.maskp, '~') != NULL) ? SMB_MASKFLAG_TILDE : 0);
thyper.LowPart = 0;
thyper.HighPart = 0;
rock.userp = userp;
rock.reqp = &req;
rock.dscp = dscp;
- code = cm_ApplyDir(dscp, smb_RmdirProc, &rock, &thyper, userp, &req, NULL);
+ /* First do a case sensitive match, and if that fails, do a case insensitive match */
+ code = cm_ApplyDir(dscp, smb_RmdirProc, &rock, &thyper, userp, &req, NULL);
+ if (code == 0 && !rock.any) {
+ thyper.LowPart = 0;
+ thyper.HighPart = 0;
+ rock.flags |= SMB_MASKFLAG_CASEFOLD;
+ code = cm_ApplyDir(dscp, smb_RmdirProc, &rock, &thyper, userp, &req, NULL);
+ }
cm_ReleaseUser(userp);
char shortName[13];
struct smb_FullNameRock *vrockp;
- vrockp = rockp;
+ vrockp = (struct smb_FullNameRock *)rockp;
if (!cm_Is8Dot3(dep->name)) {
cm_Gen8Dot3Name(dep, shortName, NULL);
- if (strcmp(shortName, vrockp->name) == 0) {
+ if (cm_stricmp(shortName, vrockp->name) == 0) {
vrockp->fullName = strdup(dep->name);
return CM_ERROR_STOPNOW;
}
}
- if (stricmp(dep->name, vrockp->name) == 0
+ if (cm_stricmp(dep->name, vrockp->name) == 0
&& ntohl(dep->fid.vnode) == vrockp->vnode->fid.vnode
&& ntohl(dep->fid.unique) == vrockp->vnode->fid.unique) {
vrockp->fullName = strdup(dep->name);
lastNamep = pathp;
else
lastNamep++;
- code = cm_Lookup(dscp, lastNamep, caseFold, userp, &req, &scp);
+ code = cm_Lookup(dscp, lastNamep, 0, userp, &req, &scp);
if (scp) cm_ReleaseSCache(scp);
if (code != CM_ERROR_NOSUCHFILE) {
if (code == 0) code = CM_ERROR_EXISTS;
}
#endif
- code = cm_Lookup(dscp, lastNamep, caseFold, userp, &req, &scp);
+ code = cm_Lookup(dscp, lastNamep, 0, userp, &req, &scp);
if (code && code != CM_ERROR_NOSUCHFILE) {
cm_ReleaseSCache(dscp);
cm_ReleaseUser(userp);
/* compare both names and vnodes, though probably just comparing vnodes
* would be safe enough.
*/
- if (stricmp(dep->name, rockp->maskp) != 0)
+ if (cm_stricmp(dep->name, rockp->maskp) != 0)
return 0;
if (ntohl(dep->fid.vnode) != rockp->vnode)
return 0;
int sawDot = 0, sawStar = 0, req8dot3 = 0;
char *starNamep, *starMaskp;
static char nullCharp[] = {0};
+ int casefold = flags & CM_FLAG_CASEFOLD;
/* make sure we only match 8.3 names, if requested */
req8dot3 = (flags & CM_FLAG_8DOT3);
tcp2 = *maskp++;
/* skip over characters that don't match tcp2 */
- while (req8dot3 && tcn1 != '.' && tcn1 != 0
- && cm_foldUpper[tcn1] != cm_foldUpper[tcp2])
+ while (req8dot3 && tcn1 != '.' && tcn1 != 0 &&
+ ((casefold && cm_foldUpper[tcn1] != cm_foldUpper[tcp2]) ||
+ (!casefold && tcn1 != tcp2)))
tcn1 = *++namep;
/* No match */
}
else {
/* tcp1 is not a wildcard */
- if (cm_foldUpper[tcn1] == cm_foldUpper[tcp1]) {
+ if ((casefold && cm_foldUpper[tcn1] == cm_foldUpper[tcp1]) ||
+ (!casefold && tcn1 == tcp1)) {
/* they match */
namep++;
continue;
int align;
char shortName[13]; /* 8.3 name if needed */
int NeedShortName;
+ int foundInexact;
char *shortNameEnd;
int fileType;
cm_fid_t fid;
return code;
}
+ startsearch:
dirLength = scp->length;
bufferp = NULL;
bufferOffset.LowPart = bufferOffset.HighPart = 0;
curOffset.LowPart = nextCookie;
origOp = outp->datap;
+ foundInexact = 0;
code = 0;
returnedNames = 0;
bytesInBuffer = 0;
NeedShortName = 1;
}
- if (dep->fid.vnode != 0
- && (smb_V3MatchMask(dep->name, maskp, CM_FLAG_CASEFOLD)
- || (NeedShortName
- && smb_V3MatchMask(shortName, maskp,
- CM_FLAG_CASEFOLD)))) {
+ /* When matching, we are using doing a case fold if we have a wildcard mask.
+ * If we get a non-wildcard match, it's a lookup for a specific file.
+ */
+ if (dep->fid.vnode != 0 &&
+ (smb_V3MatchMask(dep->name, maskp, (starPattern? CM_FLAG_CASEFOLD : 0))
+ || (NeedShortName
+ && smb_V3MatchMask(shortName, maskp, CM_FLAG_CASEFOLD)))) {
/* Eliminate entries that don't match requested attributes */
if (smb_hideDotFiles && !(dsp->attribute & SMB_ATTR_HIDDEN) &&
}
} /* if we're including this name */
+ else if(!NeedShortName &&
+ !starPattern &&
+ !foundInexact &&
+ dep->fid.vnode != 0 &&
+ smb_V3MatchMask(dep->name, maskp, CM_FLAG_CASEFOLD)) {
+ /* We were looking for exact matches, but here's an inexact one*/
+ foundInexact = 1;
+ }
nextEntry:
/* and adjust curOffset to be where the new cookie is */
curOffset = LargeIntegerAdd(thyper, curOffset);
} /* while copying data for dir listing */
+ /* If we didn't get a star pattern, we did an exact match during the first pass.
+ * If there were no exact matches found, we fail over to inexact matches by
+ * marking the query as a star pattern (matches all case permutations), and
+ * re-running the query.
+ */
+ if (returnedNames == 0 && !starPattern && foundInexact) {
+ osi_Log0(afsd_logp,"T2 Search: No exact matches. Re-running for inexact matches");
+ starPattern = 1;
+ goto startsearch;
+ }
+
/* release the mutex */
lock_ReleaseMutex(&scp->mx);
if (bufferp) buf_Release(bufferp);
dscp = NULL;
code = 0;
- code = cm_NameI(baseDirp, realPathp, CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
- userp, tidPathp, &req, &scp);
- if (code == 0) foundscp = TRUE;
+ /* For an exclusive create, we want to do a case sensitive match for the last component. */
+ if (createDisp == 2 || createDisp == 4) {
+ code = cm_NameI(baseDirp, spacep->data, CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
+ userp, tidPathp, &req, &dscp);
+ if(code == 0) {
+ code = cm_Lookup(dscp, (lastNamep)?(lastNamep+1):realPathp, CM_FLAG_FOLLOW,
+ userp, tidPathp, &req, &scp);
+ } else
+ dscp = NULL;
+ } else {
+ code = cm_NameI(baseDirp, realPathp, CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
+ userp, tidPathp, &req, &scp);
+ }
+
+ if (code == 0) foundscp = TRUE;
if (code != 0
|| (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.
- */
+ * the immediate parent. We have to work our way up realPathp until we hit something that we
+ * recognize.
+ */
+ if ( !dscp ) {
while(1) {
char *tp;
else
break;
}
+ } else
+ code = 0;
if (baseFid != 0) smb_ReleaseFID(baseFidp);
}
if (!foundscp && !treeCreate) {
- code = cm_Lookup(dscp, lastNamep,
- CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
- userp, &req, &scp);
+ if(createDisp == 2 || createDisp == 4)
+ 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);
dscp = NULL;
code = 0;
- code = cm_NameI(baseDirp, realPathp, CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
- userp, tidPathp, &req, &scp);
+ if (createDisp == 2 || createDisp == 4) {
+ code = cm_NameI(baseDirp, spacep->data, CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
+ userp, tidPathp, &req, &dscp);
+ if (code == 0) {
+ code = cm_Lookup(dscp, (lastNamep)?(lastNamep+1):realPathp, CM_FLAG_FOLLOW,
+ userp, tidPathp, &req, &scp);
+ } else
+ dscp = NULL;
+ } else {
+ code = cm_NameI(baseDirp, realPathp, CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
+ userp, tidPathp, &req, &scp);
+ }
+
if (code == 0) foundscp = TRUE;
if (code != 0
|| (fidflags & (SMB_FID_OPENDELETE | SMB_FID_OPENWRITE))) {
/* look up parent directory */
- code = cm_NameI(baseDirp, spacep->data,
- CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
- userp, tidPathp, &req, &dscp);
- cm_FreeSpace(spacep);
+ if ( !dscp ) {
+ code = cm_NameI(baseDirp, spacep->data,
+ CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
+ userp, tidPathp, &req, &dscp);
+ } else
+ code = 0;
+
+ cm_FreeSpace(spacep);
if (baseFid != 0) {
smb_ReleaseFID(baseFidp);
return CM_ERROR_BADNTFILENAME;
if (!foundscp) {
- code = cm_Lookup(dscp, lastNamep,
- CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD,
- userp, &req, &scp);
+ if (createDisp == 2 || createDisp == 4)
+ 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);