#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)
-#define CM_ERROR_BADLOGONTYPE (CM_ERROR_BASE+42)
-#define CM_ERROR_GSSCONTINUE (CM_ERROR_BASE+43)
-#define CM_ERROR_TIDIPC (CM_ERROR_BASE+44)
+#define CM_ERROR_AMBIGUOUS_FILENAME (CM_ERROR_BASE+41)
+#define CM_ERROR_BADLOGONTYPE (CM_ERROR_BASE+42)
+#define CM_ERROR_GSSCONTINUE (CM_ERROR_BASE+43)
+#define CM_ERROR_TIDIPC (CM_ERROR_BASE+44)
+#define CM_ERROR_TOO_MANY_SYMLINKS (CM_ERROR_BASE+45)
#endif /* __CM_H_ENV__ */
long cm_ConnByMServers(cm_serverRef_t *serversp, cm_user_t *usersp,
cm_req_t *reqp, cm_conn_t **connpp)
{
- long code;
- cm_serverRef_t *tsrp;
+ long code;
+ cm_serverRef_t *tsrp;
cm_server_t *tsp;
long firstError = 0;
- int someBusy = 0, someOffline = 0, allBusy = 1, allDown = 1;
- long timeUsed, timeLeft, hardTimeLeft;
+ int someBusy = 0, someOffline = 0, allBusy = 1, allDown = 1;
+ long timeUsed, timeLeft, hardTimeLeft;
#ifdef DJGPP
struct timeval now;
#endif /* DJGPP */
*connpp = NULL;
#ifndef DJGPP
- timeUsed = (GetCurrentTime() - reqp->startTime) / 1000;
+ timeUsed = (GetCurrentTime() - reqp->startTime) / 1000;
#else
gettimeofday(&now, NULL);
timeUsed = sub_time(now, reqp->startTime) / 1000;
#endif
- /* leave 5 seconds margin of safety */
- timeLeft = ConnDeadtimeout - timeUsed - 5;
- hardTimeLeft = HardDeadtimeout - timeUsed - 5;
+ /* leave 5 seconds margin of safety */
+ timeLeft = ConnDeadtimeout - timeUsed - 5;
+ hardTimeLeft = HardDeadtimeout - timeUsed - 5;
- lock_ObtainWrite(&cm_serverLock);
+ lock_ObtainWrite(&cm_serverLock);
for (tsrp = serversp; tsrp; tsrp=tsrp->next) {
tsp = tsrp->server;
cm_GetServerNoLock(tsp);
else if (tsrp->status == offline)
someOffline = 1;
else {
- allBusy = 0;
+ allBusy = 0;
code = cm_ConnByServer(tsp, usersp, connpp);
if (code == 0) {
cm_PutServer(tsp);
if (firstError == 0)
firstError = code;
}
- }
+ }
lock_ObtainWrite(&cm_serverLock);
cm_PutServerNoLock(tsp);
}
- lock_ReleaseWrite(&cm_serverLock);
- if (firstError == 0) {
+ lock_ReleaseWrite(&cm_serverLock);
+ if (firstError == 0) {
if (serversp == NULL)
- firstError = CM_ERROR_NOSUCHVOLUME;
+ firstError = CM_ERROR_NOSUCHVOLUME;
else if (allDown)
- firstError = CM_ERROR_ALLOFFLINE;
- else if (allBusy)
- firstError = CM_ERROR_ALLBUSY;
- else
- firstError = CM_ERROR_TIMEDOUT;
- }
+ firstError = CM_ERROR_ALLOFFLINE;
+ else if (allBusy)
+ firstError = CM_ERROR_ALLBUSY;
+ else
+ firstError = CM_ERROR_TIMEDOUT;
+ }
- osi_Log1(afsd_logp, "cm_ConnByMServers returning %x", firstError);
+ osi_Log1(afsd_logp, "cm_ConnByMServers returning %x", firstError);
return firstError;
}
#if !defined(DJGPP)
if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
- "SOFTWARE\\OpenAFS\\Client\\Freelance\\Symlinks",
+ "SOFTWARE\\OpenAFS\\Client\\Freelance",
0,
KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
&hkFreelance) == ERROR_SUCCESS) {
}
}
/* locked, has callback, has valid data in buffer */
- if ((tlen = scp->length.LowPart) > 1000) return CM_ERROR_TOOBIG;
+ if ((tlen = scp->length.LowPart) > 1000)
+ return CM_ERROR_TOOBIG;
if (tlen <= 0) {
code = CM_ERROR_INVAL;
goto done;
*outpScpp = scp;
return 0;
}
- if (scp) {
- cm_ReleaseSCache(scp);
- scp = 0;
- }
+ if (scp) {
+ cm_ReleaseSCache(scp);
+ scp = 0;
+ }
} else {
return cm_LookupInternal(dscp, namep, flags, userp, reqp, outpScpp);
}
if (tscp->fileType == CM_SCACHETYPE_SYMLINK) {
/* this is a symlink; assemble a new buffer */
lock_ReleaseMutex(&tscp->mx);
- if (symlinkCount++ >= 16) {
+ if (symlinkCount++ >= MAX_SYMLINK_COUNT) {
cm_ReleaseSCache(tscp);
cm_ReleaseSCache(dirScp);
if (psp)
cm_FreeSpace(psp);
- return CM_ERROR_TOOBIG;
+ return CM_ERROR_TOO_MANY_SYMLINKS;
}
if (tc == 0)
restp = "";
bb.counter = 0;
bb.bufOffset = *offsetp;
+ lock_ReleaseMutex(&dscp->mx);
/* first, assemble the file IDs we need to stat */
code = cm_ApplyDir(dscp, cm_TryBulkProc, (void *) &bb, offsetp, userp,
reqp, NULL);
+ lock_ObtainMutex(&dscp->mx);
/* if we failed, bail out early */
if (code && code != CM_ERROR_STOPNOW) return;
* time.
*/
filex = 0;
- while(filex < bb.counter) {
+ while (filex < bb.counter) {
filesThisCall = bb.counter - filex;
if (filesThisCall > AFSCBMAX) filesThisCall = AFSCBMAX;
extern long cm_RetryLock(cm_file_lock_t *oldFileLock, int vcp_is_dead);
+#define MAX_SYMLINK_COUNT 16
#endif /* __CM_VNODEOPS_H_ENV__ */
{
unsigned int attrs;
- if (scp->fileType == CM_SCACHETYPE_DIRECTORY
- || scp->fileType == CM_SCACHETYPE_MOUNTPOINT)
+ if ( scp->fileType == CM_SCACHETYPE_DIRECTORY ||
+ scp->fileType == CM_SCACHETYPE_MOUNTPOINT)
+ {
attrs = SMB_ATTR_DIRECTORY;
- else
+#ifdef SPECIAL_FOLDERS
+#ifdef AFS_FREELANCE_CLIENT
+ if ( cm_freelanceEnabled &&
+ scp->fid.cell==AFS_FAKE_ROOT_CELL_ID &&
+ scp->fid.volume==AFS_FAKE_ROOT_VOL_ID &&
+ scp->fid.vnode==0x1 && scp->fid.unique==0x1) {
+ attrs |= SMB_ATTR_SYSTEM; /* FILE_ATTRIBUTE_SYSTEM */
+ }
+#endif /* AFS_FREELANCE_CLIENT */
+#endif /* SPECIAL_FOLDERS */
+ } else
attrs = 0;
/*
/* find a dir search structure by cookie value, and return it held.
* Must be called with smb_globalLock held.
*/
-smb_dirSearch_t *smb_FindDirSearchNL(long cookie)
+smb_dirSearch_t *smb_FindDirSearchNoLock(long cookie)
{
smb_dirSearch_t *dsp;
- for(dsp = smb_firstDirSearchp; dsp; dsp = (smb_dirSearch_t *) osi_QNext(&dsp->q)) {
+ for (dsp = smb_firstDirSearchp; dsp; dsp = (smb_dirSearch_t *) osi_QNext(&dsp->q)) {
if (dsp->cookie == cookie) {
if (dsp != smb_firstDirSearchp) {
/* move to head of LRU queue, too, if we're not already there */
if (!smb_lastDirSearchp)
smb_lastDirSearchp = (smb_dirSearch_t *) &dsp->q;
}
+ lock_ObtainMutex(&dsp->mx);
dsp->refCount++;
+ lock_ReleaseMutex(&dsp->mx);
break;
}
}
void smb_DeleteDirSearch(smb_dirSearch_t *dsp)
{
lock_ObtainWrite(&smb_globalLock);
- dsp->flags |= SMB_DIRSEARCH_DELETE;
- lock_ReleaseWrite(&smb_globalLock);
lock_ObtainMutex(&dsp->mx);
- if(dsp->scp != NULL) {
+ dsp->flags |= SMB_DIRSEARCH_DELETE;
+ if (dsp->scp != NULL) {
lock_ObtainMutex(&dsp->scp->mx);
if (dsp->flags & SMB_DIRSEARCH_BULKST) {
dsp->flags &= ~SMB_DIRSEARCH_BULKST;
lock_ReleaseMutex(&dsp->scp->mx);
}
lock_ReleaseMutex(&dsp->mx);
+ lock_ReleaseWrite(&smb_globalLock);
}
-void smb_ReleaseDirSearch(smb_dirSearch_t *dsp)
+/* Must be called with the smb_globalLock held */
+void smb_ReleaseDirSearchNoLock(smb_dirSearch_t *dsp)
{
cm_scache_t *scp;
scp = NULL;
- lock_ObtainWrite(&smb_globalLock);
+ lock_ObtainMutex(&dsp->mx);
osi_assert(dsp->refCount-- > 0);
if (dsp->refCount == 0 && (dsp->flags & SMB_DIRSEARCH_DELETE)) {
if (&dsp->q == (osi_queue_t *) smb_lastDirSearchp)
smb_lastDirSearchp = (smb_dirSearch_t *) osi_QPrev(&smb_lastDirSearchp->q);
osi_QRemove((osi_queue_t **) &smb_firstDirSearchp, &dsp->q);
+ lock_ReleaseMutex(&dsp->mx);
lock_FinalizeMutex(&dsp->mx);
scp = dsp->scp;
free(dsp);
+ } else {
+ lock_ReleaseMutex(&dsp->mx);
}
- lock_ReleaseWrite(&smb_globalLock);
-
/* do this now to avoid spurious locking hierarchy creation */
if (scp) cm_ReleaseSCache(scp);
}
+void smb_ReleaseDirSearch(smb_dirSearch_t *dsp)
+{
+ lock_ObtainWrite(&smb_globalLock);
+ smb_ReleaseDirSearchNoLock(dsp);
+ lock_ReleaseWrite(&smb_globalLock);
+}
+
/* find a dir search structure by cookie value, and return it held */
smb_dirSearch_t *smb_FindDirSearch(long cookie)
{
smb_dirSearch_t *dsp;
lock_ObtainWrite(&smb_globalLock);
- dsp = smb_FindDirSearchNL(cookie);
+ dsp = smb_FindDirSearchNoLock(cookie);
lock_ReleaseWrite(&smb_globalLock);
return dsp;
}
}
/* don't do more than this */
- if (victimCount >= SMB_DIRSEARCH_GCMAX) break;
+ if (victimCount >= SMB_DIRSEARCH_GCMAX)
+ break;
}
/* now release them */
- lock_ReleaseWrite(&smb_globalLock);
- for(i = 0; i < victimCount; i++) {
- smb_ReleaseDirSearch(victimsp[i]);
+ for (i = 0; i < victimCount; i++) {
+ smb_ReleaseDirSearchNoLock(victimsp[i]);
}
- lock_ObtainWrite(&smb_globalLock);
}
/* function for allocating a dir search entry. We need these to remember enough context
counter = 0;
/* what's the biggest ID allowed in this version of the protocol */
- if (isV3) maxAllowed = 65535;
- else maxAllowed = 255;
+ maxAllowed = isV3 ? 65535 : 255;
- while(1) {
+ while (1) {
/* twice so we have enough tries to find guys we GC after one pass;
* 10 extra is just in case I mis-counted.
*/
- if (++counter > 2*maxAllowed+10) osi_panic("afsd: dir search cookie leak",
- __FILE__, __LINE__);
+ if (++counter > 2*maxAllowed+10)
+ osi_panic("afsd: dir search cookie leak", __FILE__, __LINE__);
+
if (smb_dirSearchCounter > maxAllowed) {
smb_dirSearchCounter = 1;
- smb_GCDirSearches(isV3); /* GC some (drops global lock) */
+ smb_GCDirSearches(isV3); /* GC some */
}
- dsp = smb_FindDirSearchNL(smb_dirSearchCounter);
+ dsp = smb_FindDirSearchNoLock(smb_dirSearchCounter);
if (dsp) {
/* don't need to watch for refcount zero and deleted, since
* we haven't dropped the global lock.
*/
+ lock_ObtainMutex(&dsp->mx);
dsp->refCount--;
+ lock_ReleaseMutex(&dsp->mx);
++smb_dirSearchCounter;
continue;
}
dsp = malloc(sizeof(*dsp));
memset(dsp, 0, sizeof(*dsp));
osi_QAdd((osi_queue_t **) &smb_firstDirSearchp, &dsp->q);
- if (!smb_lastDirSearchp) smb_lastDirSearchp = (smb_dirSearch_t *) &dsp->q;
+ if (!smb_lastDirSearchp)
+ smb_lastDirSearchp = (smb_dirSearch_t *) &dsp->q;
dsp->cookie = smb_dirSearchCounter;
++smb_dirSearchCounter;
dsp->refCount = 1;
else if (code == CM_ERROR_GSSCONTINUE) {
NTStatus = 0xC0000016L; /* more processing required */
}
+ else if (code == CM_ERROR_TOO_MANY_SYMLINKS) {
+#ifdef COMMENT
+ NTStatus = 0xC0000280L; /* reparse point not resolved */
+#else
+ NTStatus = 0xC0000022L; /* Access Denied */
+#endif
+ }
else {
NTStatus = 0xC0982001L; /* SMB non-specific error */
}
else {
spacep = inp->spacep;
smb_StripLastComponent(spacep->data, NULL, pathp);
- lock_ReleaseMutex(&dsp->mx);
code = smb_LookupTIDPath(vcp, ((smb_t *)inp)->tid, &tidPathp);
if (code) {
lock_ReleaseMutex(&dsp->mx);
}
code = cm_NameI(cm_rootSCachep, spacep->data,
caseFold | CM_FLAG_FOLLOW, userp, tidPathp, &req, &scp);
- lock_ObtainMutex(&dsp->mx);
if (code == 0) {
- if (dsp->scp != 0) cm_ReleaseSCache(dsp->scp);
+ if (dsp->scp != 0)
+ cm_ReleaseSCache(dsp->scp);
dsp->scp = scp;
/* we need one hold for the entry we just stored into,
* and one for our own processing. When we're done with this
lock_ObtainRead(&scp->bufCreateLock);
code = buf_Get(scp, &thyper, &bufferp);
lock_ReleaseRead(&scp->bufCreateLock);
+ lock_ObtainMutex(&dsp->mx);
/* now, if we're doing a star match, do bulk fetching of all of
* the status info for files in the dir.
*/
if (starPattern) {
- smb_ApplyDirListPatches(&dirListPatchesp, userp,
- &req);
+ smb_ApplyDirListPatches(&dirListPatchesp, userp, &req);
+ lock_ObtainMutex(&scp->mx);
if ((dsp->flags & SMB_DIRSEARCH_BULKST) &&
LargeIntegerGreaterThanOrEqualTo(thyper,
scp->bulkStatProgress)) {
} else
cm_TryBulkStat(scp, &thyper, userp, &req);
}
+ } else {
+ lock_ObtainMutex(&scp->mx);
}
-
- lock_ObtainMutex(&scp->mx);
+ lock_ReleaseMutex(&dsp->mx);
if (code)
break;
+
bufferOffset = thyper;
/* now get the data in the cache */
unsigned long attrs;
if (scp->fileType == CM_SCACHETYPE_DIRECTORY ||
- scp->fileType == CM_SCACHETYPE_MOUNTPOINT)
+ scp->fileType == CM_SCACHETYPE_MOUNTPOINT)
+ {
attrs = SMB_ATTR_DIRECTORY;
- else
+#ifdef SPECIAL_FOLDERS
+#ifdef AFS_FREELANCE_CLIENT
+ if ( cm_freelanceEnabled &&
+ scp->fid.cell==AFS_FAKE_ROOT_CELL_ID &&
+ scp->fid.volume==AFS_FAKE_ROOT_VOL_ID &&
+ scp->fid.vnode==0x1 && scp->fid.unique==0x1) {
+ attrs |= SMB_ATTR_SYSTEM; /* FILE_ATTRIBUTE_SYSTEM */
+ }
+#endif /* AFS_FREELANCE_CLIENT */
+#endif /* SPECIAL_FOLDERS */
+ } else
attrs = 0;
/*
* We used to mark a file RO if it was in an RO volume, but that
pathp = ((char *) p->parmsp) + 12; /* points to path */
nextCookie = 0;
maskp = strrchr(pathp, '\\');
- if (maskp == NULL) maskp = pathp;
- else maskp++; /* skip over backslash */
+ if (maskp == NULL)
+ maskp = pathp;
+ else
+ maskp++; /* skip over backslash */
strcpy(dsp->mask, maskp); /* and save mask */
/* track if this is likely to match a lot of entries */
starPattern = smb_V3IsStarMask(maskp);
osi_assert(p->opcode == 2);
/* find next; obtain basic parameters from request or open dir file */
dsp = smb_FindDirSearch(p->parmsp[0]);
- if (!dsp) return CM_ERROR_BADFD;
+ if (!dsp)
+ return CM_ERROR_BADFD;
attribute = dsp->attribute;
maxCount = p->parmsp[1];
infoLevel = p->parmsp[2];
else {
spacep = cm_GetSpace();
smb_StripLastComponent(spacep->data, NULL, pathp);
- lock_ReleaseMutex(&dsp->mx);
-
code = smb_LookupTIDPath(vcp, p->tid, &tidPathp);
if (code) {
+ lock_ReleaseMutex(&dsp->mx);
cm_ReleaseUser(userp);
smb_SendTran2Error(vcp, p, opx, CM_ERROR_NOFILES);
smb_FreeTran2Packet(outp);
userp, tidPathp, &req, &scp);
cm_FreeSpace(spacep);
- lock_ObtainMutex(&dsp->mx);
if (code == 0) {
- if (dsp->scp != 0) cm_ReleaseSCache(dsp->scp);
+ if (dsp->scp != 0)
+ cm_ReleaseSCache(dsp->scp);
dsp->scp = scp;
/* we need one hold for the entry we just stored into,
* and one for our own processing. When we're done
lock_ObtainRead(&scp->bufCreateLock);
code = buf_Get(scp, &thyper, &bufferp);
lock_ReleaseRead(&scp->bufCreateLock);
+ lock_ObtainMutex(&dsp->mx);
/* now, if we're doing a star match, do bulk fetching
* of all of the status info for files in the dir.
smb_ApplyV3DirListPatches(scp, &dirListPatchesp,
infoLevel, userp,
&req);
+ lock_ObtainMutex(&scp->mx);
if ((dsp->flags & SMB_DIRSEARCH_BULKST) &&
LargeIntegerGreaterThanOrEqualTo(thyper, scp->bulkStatProgress)) {
/* Don't bulk stat if risking timeout */
} else
cm_TryBulkStat(scp, &thyper, userp, &req);
}
+ } else {
+ lock_ObtainMutex(&scp->mx);
}
+ lock_ReleaseMutex(&dsp->mx);
+ if (code)
+ break;
- lock_ObtainMutex(&scp->mx);
- if (code) break;
bufferOffset = thyper;
/* now get the data in the cache */