+#include <afsconfig.h>
#include <afs/param.h>
+#include <roken.h>
+
#include <afs/stds.h>
#include <windows.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
+#include <cm_nls.h>
#include <WINNT/afsreg.h>
#include "afsd.h"
#ifdef AFS_FREELANCE_CLIENT
#include "cm_freelance.h"
-#include "stdio.h"
+#include <stdio.h>
+#define STRSAFE_NO_DEPRECATE
+#include <strsafe.h>
extern void afsi_log(char *pattern, ...);
-int cm_noLocalMountPoints;
+static unsigned int cm_noLocalMountPoints = 0;
char * cm_FakeRootDir = NULL;
int cm_fakeDirSize = 0;
-int cm_fakeDirCallback=0;
-int cm_fakeGettingCallback=0;
-cm_localMountPoint_t* cm_localMountPoints;
+static cm_localMountPoint_t* cm_localMountPoints;
osi_mutex_t cm_Freelance_Lock;
-int cm_localMountPointChangeFlag = 0;
+static int cm_localMountPointChangeFlag = 0;
int cm_freelanceEnabled = 1;
+int cm_freelanceImportCellServDB = 0;
time_t FakeFreelanceModTime = 0x3b49f6e2;
static int freelance_ShutdownFlag = 0;
hFreelanceChangeEvent = 0;
return;
}
- cm_noteLocalMountPointChange();
+ cm_noteLocalMountPointChange(FALSE);
}
}
}
hFreelanceSymlinkChangeEvent = 0;
return;
}
- cm_noteLocalMountPointChange();
+ cm_noteLocalMountPointChange(FALSE);
}
}
}
thrd_SetEvent(hFreelanceChangeEvent);
if (hFreelanceSymlinkChangeEvent != 0)
thrd_SetEvent(hFreelanceSymlinkChangeEvent);
-}
+}
+
+static long
+cm_FreelanceAddCSDBMountPoints(void *rockp, char *cellNamep)
+{
+ char szCellName[CELL_MAXNAMELEN+1] = ".";
+
+ cm_FsStrCpy( &szCellName[1], CELL_MAXNAMELEN, cellNamep);
+ /* create readonly mount point */
+ cm_FreelanceAddMount( cellNamep, cellNamep, "root.cell", 0, NULL);
+
+ /* create read/write mount point */
+ cm_FreelanceAddMount( szCellName, szCellName, "root.cell", 1, NULL);
+
+ return 0;
+}
+
+void
+cm_FreelanceImportCellServDB(void)
+{
+ cm_EnumerateCellRegistry( TRUE, cm_FreelanceAddCSDBMountPoints, NULL);
+ cm_EnumerateCellFile( TRUE, cm_FreelanceAddCSDBMountPoints, NULL);
+}
void cm_InitFreelance() {
thread_t phandle;
int lpid;
- lock_InitializeMutex(&cm_Freelance_Lock, "Freelance Lock");
+ lock_InitializeMutex(&cm_Freelance_Lock, "Freelance Lock", LOCK_HIERARCHY_FREELANCE_GLOBAL);
+
+ lock_ObtainMutex(&cm_Freelance_Lock);
// yj: first we make a call to cm_initLocalMountPoints
// to read all the local mount points from the registry
// then we make a call to InitFakeRootDir to create
// a fake root directory based on the local mount points
cm_InitFakeRootDir();
+
+ // increment the fakeDirVersion to force status updates for
+ // all cached Freelance objects
+ cm_data.fakeDirVersion++;
// --- end of yj code
+ lock_ReleaseMutex(&cm_Freelance_Lock);
/* Start the registry monitor */
phandle = thrd_Create(NULL, 65536, (ThreadFunc) cm_FreelanceChangeNotifier,
}
/* yj: Initialization of the fake root directory */
-/* to be called while holding freelance lock unless during init. */
+/* to be called while holding freelance lock. */
void cm_InitFakeRootDir() {
int i, t1, t2;
char* currentPos;
int curChunk = 13; // chunks 0 - 12 are used for header stuff
// of the first page in the directory
int curPage = 0;
- int curDirEntry = 0;
+ unsigned int curDirEntry = 0;
int curDirEntryInPage = 0;
int sizeOfCurEntry;
int dirSize;
if (cm_fakeDirSize != dirSize) {
if (cm_FakeRootDir)
free(cm_FakeRootDir);
- cm_FakeRootDir = malloc(dirSize);
+ cm_FakeRootDir = calloc(dirSize, 1);
cm_fakeDirSize = dirSize;
}
{
noChunks = cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0);
- fakeEntry.fid.vnode = htonl(curDirEntry + 2);
+ /* enforce the rule that only directories have odd vnode values */
+ fakeEntry.fid.vnode = htonl((curDirEntry + 1) * 2);
+ fakeEntry.fid.unique = htonl(curDirEntry + 1);
currentPos = cm_FakeRootDir + curPage * CM_DIR_PAGESIZE + curChunk * CM_DIR_CHUNKSIZE;
memcpy(currentPos, &fakeEntry, CM_DIR_CHUNKSIZE);
// add an entry to this page
noChunks = cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0);
- fakeEntry.fid.vnode=htonl(curDirEntry+2);
+ /* enforce the rule that only directories have odd vnode values */
+ fakeEntry.fid.vnode = htonl((curDirEntry + 1) * 2);
+ fakeEntry.fid.unique = htonl(curDirEntry + 1);
currentPos = cm_FakeRootDir + curPage * CM_DIR_PAGESIZE + curChunk * CM_DIR_CHUNKSIZE;
memcpy(currentPos, &fakeEntry, CM_DIR_CHUNKSIZE);
strcpy(currentPos + 12, (cm_localMountPoints+curDirEntry)->namep);
}
// we know the fakeDir is setup properly, so we claim that we have callback
- osi_Log0(afsd_logp,"cm_InitFakeRootDir fakeDirCallback=1");
- cm_fakeDirCallback=1;
+ osi_Log0(afsd_logp,"cm_InitFakeRootDir completed!");
// when we get here, we've set up everything! done!
}
/* called directly from ioctl */
/* called while not holding freelance lock */
-int cm_noteLocalMountPointChange(void) {
- lock_ObtainMutex(&cm_Freelance_Lock);
+int cm_noteLocalMountPointChange(afs_int32 locked) {
+ if (!locked)
+ lock_ObtainMutex(&cm_Freelance_Lock);
cm_data.fakeDirVersion++;
cm_localMountPointChangeFlag = 1;
- lock_ReleaseMutex(&cm_Freelance_Lock);
+ if (!locked)
+ lock_ReleaseMutex(&cm_Freelance_Lock);
return 1;
}
int cm_reInitLocalMountPoints() {
cm_fid_t aFid;
- int i, hash;
+ unsigned int i, hash;
cm_scache_t *scp, **lscpp, *tscp;
+ cm_req_t req;
+
+ cm_InitReq(&req);
osi_Log0(afsd_logp,"----- freelance reinitialization starts ----- ");
osi_Log0(afsd_logp,"Invalidating local mount point scp... ");
- cm_SetFid(&aFid, AFS_FAKE_ROOT_CELL_ID, AFS_FAKE_ROOT_VOL_ID, 1, 1);
-
lock_ObtainWrite(&cm_scacheLock);
lock_ObtainMutex(&cm_Freelance_Lock); /* always scache then freelance lock */
- for (i=0; i<cm_noLocalMountPoints; i++) {
+ for (i=0; i<=cm_noLocalMountPoints; i++) {
+ if (i == 0)
+ cm_SetFid(&aFid, AFS_FAKE_ROOT_CELL_ID, AFS_FAKE_ROOT_VOL_ID, 1, 1);
+ else
+ cm_SetFid(&aFid, AFS_FAKE_ROOT_CELL_ID, AFS_FAKE_ROOT_VOL_ID, i*2, i);
hash = CM_SCACHE_HASH(&aFid);
for (scp=cm_data.scacheHashTablep[hash]; scp; scp=scp->nextp) {
if (scp != cm_data.rootSCachep && cm_FidCmp(&scp->fid, &aFid) == 0) {
// mark the scp to be reused
cm_HoldSCacheNoLock(scp);
+ lock_ReleaseMutex(&cm_Freelance_Lock);
lock_ReleaseWrite(&cm_scacheLock);
lock_ObtainWrite(&scp->rw);
cm_DiscardSCache(scp);
- lock_ReleaseWrite(&scp->rw);
- cm_CallbackNotifyChange(scp);
- lock_ObtainWrite(&cm_scacheLock);
- cm_ReleaseSCacheNoLock(scp);
// take the scp out of the hash
+ lock_ObtainWrite(&cm_scacheLock);
for (lscpp = &cm_data.scacheHashTablep[hash], tscp = cm_data.scacheHashTablep[hash];
tscp;
lscpp = &tscp->nextp, tscp = tscp->nextp) {
if (tscp == scp) {
*lscpp = scp->nextp;
- lock_ObtainWrite(&scp->rw);
+ scp->nextp = NULL;
scp->flags &= ~CM_SCACHEFLAG_INHASH;
- lock_ReleaseWrite(&scp->rw);
break;
}
}
+
+ lock_ReleaseWrite(&scp->rw);
+ lock_ReleaseWrite(&cm_scacheLock);
+ cm_CallbackNotifyChange(scp);
+ lock_ObtainWrite(&cm_scacheLock);
+ cm_ReleaseSCacheNoLock(scp);
+ lock_ObtainMutex(&cm_Freelance_Lock);
}
}
- cm_SetFid(&aFid, AFS_FAKE_ROOT_CELL_ID, AFS_FAKE_ROOT_VOL_ID, aFid.vnode + 1, 1);
}
lock_ReleaseWrite(&cm_scacheLock);
+ lock_ReleaseMutex(&cm_Freelance_Lock);
osi_Log0(afsd_logp,"\tall old scp cleared!");
+ lock_ObtainWrite(&cm_data.rootSCachep->rw);
+ lock_ObtainMutex(&cm_Freelance_Lock);
// we must free the memory that was allocated in the prev
// cm_InitLocalMountPoints call
osi_Log0(afsd_logp,"Removing old localmountpoints... ");
free(cm_localMountPoints);
+ cm_localMountPoints = NULL;
+ cm_noLocalMountPoints = 0;
osi_Log0(afsd_logp,"\tall old localmountpoints cleared!");
// now re-init the localmountpoints
lock_ReleaseMutex(&cm_Freelance_Lock);
+ cm_GetCallback(cm_data.rootSCachep, cm_rootUserp, &req, 0);
+ lock_ReleaseWrite(&cm_data.rootSCachep->rw);
+
osi_Log0(afsd_logp,"----- freelance reinit complete -----");
return 0;
}
+/*
+ * cm_enforceTrailingDot
+ *
+ * return 0 on failure, non-zero on success
+ *
+ */
+static int
+cm_enforceTrailingDot(char * line, size_t cchLine, DWORD *pdwSize)
+{
+ /* trailing white space first. */
+ if (line[(*pdwSize)-1] == '\0') {
+ while (isspace(line[(*pdwSize)-2])) {
+ line[(*pdwSize)-2] = '\0';
+ (*pdwSize)--;
+ }
+ } else {
+ while (isspace(line[(*pdwSize)-1])) {
+ line[(*pdwSize)-1] = '\0';
+ (*pdwSize)--;
+ }
+ }
+
+ /* then enforce the trailing dot requirement */
+ if (line[(*pdwSize)-1] == '\0' && line[(*pdwSize)-2] != '.') {
+ if ((*pdwSize) >= cchLine) {
+ afsi_log("no room for trailing dot");
+ return 0;
+ }
+ line[(*pdwSize)-1] = '.';
+ line[(*pdwSize)] = '\0';
+ } else if (line[(*pdwSize)-1] != '\0' && line[(*pdwSize)-1] != '.') {
+ if ((*pdwSize) >= cchLine) {
+ afsi_log("no room for trailing dot and nul");
+ return 0;
+ }
+ line[(*pdwSize)] = '.';
+ line[(*pdwSize)+1] = '\0';
+ } else if (line[(*pdwSize)-1] != '\0') {
+ if ((*pdwSize) >= cchLine) {
+ afsi_log("no room for trailing nul");
+ return 0;
+ }
+ line[(*pdwSize)] = '\0';
+ }
+ return 1;
+}
+
// yj: open up the registry and read all the local mount
// points that are stored there. Part of the initialization
// process for the freelance client.
-/* to be called while holding freelance lock unless during init. */
+/* to be called while holding freelance lock. */
long cm_InitLocalMountPoints() {
FILE *fp;
- int i;
+ unsigned int i;
char line[512];
char*t, *t2;
cm_localMountPoint_t* aLocalMountPoint;
&ftLastWriteTime /* lpftLastWriteTime */
);
- smb_UnixTimeFromLargeSearchTime(&FakeFreelanceModTime, &ftLastWriteTime);
+ cm_UnixTimeFromLargeSearchTime(&FakeFreelanceModTime, &ftLastWriteTime);
if ( dwMountPoints == 0 ) {
rootCellName[0] = '.';
code = cm_GetRootCellName(&rootCellName[1]);
if (code == 0) {
- cm_FreelanceAddMount(&rootCellName[1], &rootCellName[1], "root.cell.", 0, NULL);
- cm_FreelanceAddMount(rootCellName, &rootCellName[1], "root.cell.", 1, NULL);
- cm_FreelanceAddMount(".root", &rootCellName[1], "root.afs.", 1, NULL);
+ lock_ReleaseMutex(&cm_Freelance_Lock);
+ cm_FreelanceAddMount(&rootCellName[1], &rootCellName[1], "root.cell", 0, NULL);
+ cm_FreelanceAddMount(rootCellName, &rootCellName[1], "root.cell", 1, NULL);
+ cm_FreelanceAddMount(".root", &rootCellName[1], "root.afs", 1, NULL);
+ lock_ObtainMutex(&cm_Freelance_Lock);
dwMountPoints = 3;
}
}
continue;
}
- afsi_log("Mountpoint[%d] = %s",dwIndex, line);
+ /* make sure there is a trailing dot and a nul terminator */
+ if (!cm_enforceTrailingDot(line, sizeof(line), &dwSize)) {
+ cm_noLocalMountPoints--;
+ continue;
+ }
- /* find the trailing dot; null terminate after it */
- t2 = strrchr(line, '.');
- if (t2)
- *(t2+1) = '\0';
+ afsi_log("Mountpoint[%d] = %s", dwIndex, line);
for ( t=line;*t;t++ ) {
if ( !isprint(*t) ) {
continue;
}
- afsi_log("Symlink[%d] = %s",dwIndex, line);
+ /* make sure there is a trailing dot and a nul terminator */
+ if (!cm_enforceTrailingDot(line, sizeof(line), &dwSize)) {
+ cm_noLocalMountPoints--;
+ continue;
+ }
- /* find the trailing dot; null terminate after it */
- t2 = strrchr(line, '.');
- if (t2)
- *(t2+1) = '\0';
+ afsi_log("Symlink[%d] = %s", dwIndex, line);
for ( t=line;*t;t++ ) {
if ( !isprint(*t) ) {
rootCellName[0] = '.';
code = cm_GetRootCellName(&rootCellName[1]);
if (code == 0) {
- cm_FreelanceAddMount(&rootCellName[1], &rootCellName[1], "root.cell.", 0, NULL);
- cm_FreelanceAddMount(rootCellName, &rootCellName[1], "root.cell.", 1, NULL);
- cm_FreelanceAddMount(".root", &rootCellName[1], "root.afs.", 1, NULL);
+ lock_ReleaseMutex(&cm_Freelance_Lock);
+ cm_FreelanceAddMount(&rootCellName[1], &rootCellName[1], "root.cell", 0, NULL);
+ cm_FreelanceAddMount(rootCellName, &rootCellName[1], "root.cell", 1, NULL);
+ cm_FreelanceAddMount(".root", &rootCellName[1], "root.afs", 1, NULL);
+ lock_ObtainMutex(&cm_Freelance_Lock);
}
return 0;
}
memcpy(shortname, line, cp-line);
shortname[cp-line]=0;
- if (!stricmp(shortname, filename)) {
+ if (!cm_stricmp_utf8(shortname, filename)) {
found = 1;
break;
}
memcpy(shortname, line, cp-line);
shortname[cp-line]=0;
- if (!stricmp(shortname, filename)) {
+ if (!cm_stricmp_utf8(shortname, filename)) {
found = 1;
break;
}
FILE *fp;
char hfile[260];
char line[512];
- char fullname[200];
+ char fullname[CELL_MAXNAMELEN];
int n;
int alias = 0;
HKEY hkFreelance = 0;
DWORD dwType, dwSize;
DWORD dwMountPoints;
DWORD dwIndex;
+ afs_uint32 code = 0;
/* before adding, verify the cell name; if it is not a valid cell,
don't add the mount point.
rw ? "rw" : "ro");
if ( filename[0] == '\0' || cellname[0] == '\0' || volume[0] == '\0' )
- return -1;
+ return CM_ERROR_INVAL;
+
+ if ( cm_FreelanceMountPointExists(filename, 0) ||
+ cm_FreelanceSymlinkExists(filename, 0) ) {
+ code = CM_ERROR_EXISTS;
+ goto done;
+ }
if (cellname[0] == '.') {
if (!cm_GetCell_Gen(&cellname[1], fullname, CM_FLAG_CREATE))
- return -1;
+ return CM_ERROR_INVAL;
} else {
if (!cm_GetCell_Gen(cellname, fullname, CM_FLAG_CREATE))
- return -1;
+ return CM_ERROR_INVAL;
}
- if ( cm_FreelanceMountPointExists(filename, 0) ||
- cm_FreelanceSymlinkExists(filename, 0) )
- return -1;
-
osi_Log1(afsd_logp,"Freelance Adding Mount for Cell: %s",
osi_LogSaveString(afsd_logp,cellname));
);
if (rw)
- sprintf(line, "%s%%%s:%s", filename, fullname, volume);
+ sprintf(line, "%s%%%s:%s.", filename, fullname, volume);
else
- sprintf(line, "%s#%s:%s", filename, fullname, volume);
+ sprintf(line, "%s#%s:%s.", filename, fullname, volume);
/* If we are adding a new value, there must be an unused name
* within the range 0 to dwMountPoints
fprintf(fp, "%d", n);
fseek(fp, 0, SEEK_END);
if (rw)
- fprintf(fp, "%s%%%s:%s\n", filename, fullname, volume);
+ fprintf(fp, "%s%%%s:%s.\n", filename, fullname, volume);
else
- fprintf(fp, "%s#%s:%s\n", filename, fullname, volume);
+ fprintf(fp, "%s#%s:%s.\n", filename, fullname, volume);
fclose(fp);
}
+
+ /* Do this while we are holding the lock */
+ cm_noteLocalMountPointChange(TRUE);
lock_ReleaseMutex(&cm_Freelance_Lock);
- /* cm_reInitLocalMountPoints(); */
- if (fidp)
- cm_SetFid(fidp, fidp->cell, fidp->volume, ++cm_noLocalMountPoints, 1);
- cm_noteLocalMountPointChange();
- return 0;
+ done:
+ if (fidp) {
+ cm_req_t req;
+ cm_scache_t *scp;
+ clientchar_t *cpath;
+
+ cm_InitReq(&req);
+
+ cpath = cm_FsStringToClientStringAlloc(filename, -1, NULL);
+ if (!cpath)
+ return CM_ERROR_NOSUCHPATH;
+
+ if (cm_getLocalMountPointChange()) { // check for changes
+ cm_clearLocalMountPointChange(); // clear the changefile
+ cm_reInitLocalMountPoints(); // start reinit
+ }
+
+ code = cm_NameI(cm_RootSCachep(cm_rootUserp, &req), cpath,
+ CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD | CM_FLAG_DFS_REFERRAL,
+ cm_rootUserp, NULL, &req, &scp);
+ free(cpath);
+ if (code)
+ return code;
+ *fidp = scp->fid;
+ cm_ReleaseSCache(scp);
+ }
+
+ return code;
}
long cm_FreelanceRemoveMount(char *toremove)
rename(hfile2, hfile);
}
}
-
- lock_ReleaseMutex(&cm_Freelance_Lock);
+
if (found) {
- cm_noteLocalMountPointChange();
- return 0;
- } else
- return CM_ERROR_NOSUCHFILE;
+ /* Do this while we are holding the lock */
+ cm_noteLocalMountPointChange(TRUE);
+ }
+ lock_ReleaseMutex(&cm_Freelance_Lock);
+ return (found ? 0 : CM_ERROR_NOSUCHFILE);
}
long cm_FreelanceAddSymlink(char *filename, char *destination, cm_fid_t *fidp)
{
char line[512];
- char fullname[200];
+ char fullname[CELL_MAXNAMELEN] = "";
int alias = 0;
HKEY hkFreelanceSymlinks = 0;
DWORD dwType, dwSize;
DWORD dwSymlinks;
DWORD dwIndex;
+ afs_uint32 code = 0;
- /* before adding, verify the filename. If it is already in use, either as
+ /*
+ * before adding, verify the filename. If it is already in use, either as
* as mount point or a cellname, do not permit the creation of the symlink.
*/
osi_Log2(afsd_logp,"Freelance Add Symlink request: filename=%s destination=%s",
if ( filename[0] == '\0' || destination[0] == '\0' )
return CM_ERROR_INVAL;
- fullname[0] = '\0';
+ /* Do not create the symlink if the name ends in a dot */
+ if ( filename[strlen(filename)-1] == '.')
+ return CM_ERROR_INVAL;
+
+ if ( cm_FreelanceMountPointExists(filename, 0) ||
+ cm_FreelanceSymlinkExists(filename, 0) ) {
+ code = CM_ERROR_EXISTS;
+ goto done;
+ }
+
if (filename[0] == '.') {
cm_GetCell_Gen(&filename[1], fullname, CM_FLAG_CREATE);
- if (stricmp(&filename[1],fullname) == 0)
- return CM_ERROR_EXISTS;
+ if (cm_stricmp_utf8(&filename[1],fullname) == 0) {
+ code = CM_ERROR_EXISTS;
+ goto done;
+ }
} else {
cm_GetCell_Gen(filename, fullname, CM_FLAG_CREATE);
- if (stricmp(filename,fullname) == 0)
- return CM_ERROR_EXISTS;
+ if (cm_stricmp_utf8(filename,fullname) == 0) {
+ code = CM_ERROR_EXISTS;
+ goto done;
+ }
}
- if ( cm_FreelanceMountPointExists(filename, 0) ||
- cm_FreelanceSymlinkExists(filename, 0) )
- return CM_ERROR_EXISTS;
-
lock_ObtainMutex(&cm_Freelance_Lock);
if (RegCreateKeyEx( HKEY_LOCAL_MACHINE,
}
RegCloseKey(hkFreelanceSymlinks);
}
+
+ /* Do this while we are holding the lock */
+ cm_noteLocalMountPointChange(TRUE);
lock_ReleaseMutex(&cm_Freelance_Lock);
- /* cm_reInitLocalMountPoints(); */
- if (fidp)
- cm_SetFid(fidp, fidp->cell, fidp->volume, ++cm_noLocalMountPoints, 1);
- cm_noteLocalMountPointChange();
- return 0;
+ done:
+ if (fidp) {
+ cm_req_t req;
+ cm_scache_t *scp;
+ clientchar_t *cpath;
+
+ cm_InitReq(&req);
+
+ cpath = cm_FsStringToClientStringAlloc(filename, -1, NULL);
+ if (!cpath) {
+ code = CM_ERROR_NOSUCHPATH;
+ } else {
+ if (cm_getLocalMountPointChange()) { // check for changes
+ cm_clearLocalMountPointChange(); // clear the changefile
+ cm_reInitLocalMountPoints(); // start reinit
+ }
+
+ code = cm_NameI(cm_RootSCachep(cm_rootUserp, &req), cpath,
+ CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD | CM_FLAG_DFS_REFERRAL,
+ cm_rootUserp, NULL, &req, &scp);
+ free(cpath);
+ if (code == 0) {
+ *fidp = scp->fid;
+ cm_ReleaseSCache(scp);
+ }
+ }
+ }
+
+ return code;
}
long cm_FreelanceRemoveSymlink(char *toremove)
RegCloseKey(hkFreelanceSymlinks);
}
- lock_ReleaseMutex(&cm_Freelance_Lock);
if (found) {
- cm_noteLocalMountPointChange();
- return 0;
- } else
- return CM_ERROR_NOSUCHFILE;
+ /* Do this while we are holding the lock */
+ cm_noteLocalMountPointChange(TRUE);
+ }
+ lock_ReleaseMutex(&cm_Freelance_Lock);
+ return (found ? 0 : CM_ERROR_NOSUCHFILE);
+}
+
+long
+cm_FreelanceFetchMountPointString(cm_scache_t *scp)
+{
+ lock_ObtainMutex(&cm_Freelance_Lock);
+ if (!scp->mountPointStringp[0] &&
+ scp->fid.cell == AFS_FAKE_ROOT_CELL_ID &&
+ scp->fid.volume == AFS_FAKE_ROOT_VOL_ID &&
+ scp->fid.unique <= cm_noLocalMountPoints) {
+ strncpy(scp->mountPointStringp, cm_localMountPoints[scp->fid.unique-1].mountPointStringp, MOUNTPOINTLEN);
+ scp->mountPointStringp[MOUNTPOINTLEN-1] = 0; /* null terminate */
+ }
+ lock_ReleaseMutex(&cm_Freelance_Lock);
+
+ return 0;
+}
+
+long
+cm_FreelanceFetchFileType(cm_scache_t *scp)
+{
+ lock_ObtainMutex(&cm_Freelance_Lock);
+ if (scp->fid.cell == AFS_FAKE_ROOT_CELL_ID &&
+ scp->fid.volume == AFS_FAKE_ROOT_VOL_ID &&
+ scp->fid.unique <= cm_noLocalMountPoints)
+ {
+ scp->fileType = cm_localMountPoints[scp->fid.unique-1].fileType;
+
+ if ( scp->fileType == CM_SCACHETYPE_SYMLINK &&
+ !strnicmp(cm_localMountPoints[scp->fid.unique-1].mountPointStringp, "msdfs:", strlen("msdfs:")) )
+ {
+ scp->fileType = CM_SCACHETYPE_DFSLINK;
+ }
+ } else {
+ scp->fileType = CM_SCACHETYPE_INVALID;
+ }
+ lock_ReleaseMutex(&cm_Freelance_Lock);
+
+ return 0;
}
#endif /* AFS_FREELANCE_CLIENT */