15 #include <WINNT/afsreg.h>
19 #ifdef AFS_FREELANCE_CLIENT
20 #include "cm_freelance.h"
22 #define STRSAFE_NO_DEPRECATE
25 extern void afsi_log(char *pattern, ...);
27 static unsigned int cm_noLocalMountPoints = 0;
28 char * cm_FakeRootDir = NULL;
29 int cm_fakeDirSize = 0;
30 static cm_localMountPoint_t* cm_localMountPoints;
31 osi_mutex_t cm_Freelance_Lock;
32 static int cm_localMountPointChangeFlag = 0;
33 int cm_freelanceEnabled = 1;
34 int cm_freelanceImportCellServDB = 0;
35 time_t FakeFreelanceModTime = 0x3b49f6e2;
37 static int freelance_ShutdownFlag = 0;
38 static HANDLE hFreelanceChangeEvent = 0;
39 static HANDLE hFreelanceSymlinkChangeEvent = 0;
41 void cm_InitFakeRootDir();
43 void cm_FreelanceChangeNotifier(void * parmp) {
46 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
47 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance",
50 &hkFreelance) == ERROR_SUCCESS) {
52 hFreelanceChangeEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
53 if (hFreelanceChangeEvent == NULL) {
54 RegCloseKey(hkFreelance);
60 /* check hFreelanceChangeEvent to see if it is set.
61 * if so, call cm_noteLocalMountPointChange()
63 if (RegNotifyChangeKeyValue( hkFreelance, /* hKey */
64 FALSE, /* bWatchSubtree */
65 REG_NOTIFY_CHANGE_LAST_SET, /* dwNotifyFilter */
66 hFreelanceChangeEvent, /* hEvent */
67 TRUE /* fAsynchronous */
69 RegCloseKey(hkFreelance);
70 CloseHandle(hFreelanceChangeEvent);
71 hFreelanceChangeEvent = 0;
75 if (WaitForSingleObject(hFreelanceChangeEvent, INFINITE) == WAIT_OBJECT_0)
77 if (freelance_ShutdownFlag == 1) {
78 RegCloseKey(hkFreelance);
79 CloseHandle(hFreelanceChangeEvent);
80 hFreelanceChangeEvent = 0;
83 cm_noteLocalMountPointChange(FALSE);
88 void cm_FreelanceSymlinkChangeNotifier(void * parmp) {
91 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
92 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance\\Symlinks",
95 &hkFreelance) == ERROR_SUCCESS) {
97 hFreelanceSymlinkChangeEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
98 if (hFreelanceSymlinkChangeEvent == NULL) {
99 RegCloseKey(hkFreelance);
105 /* check hFreelanceSymlinkChangeEvent to see if it is set.
106 * if so, call cm_noteLocalMountPointSymlinkChange()
108 if (RegNotifyChangeKeyValue( hkFreelance, /* hKey */
109 FALSE, /* bWatchSubtree */
110 REG_NOTIFY_CHANGE_LAST_SET, /* dwNotifyFilter */
111 hFreelanceSymlinkChangeEvent, /* hEvent */
112 TRUE /* fAsynchronous */
113 ) != ERROR_SUCCESS) {
114 RegCloseKey(hkFreelance);
115 CloseHandle(hFreelanceSymlinkChangeEvent);
116 hFreelanceSymlinkChangeEvent = 0;
120 if (WaitForSingleObject(hFreelanceSymlinkChangeEvent, INFINITE) == WAIT_OBJECT_0)
122 if (freelance_ShutdownFlag == 1) {
123 RegCloseKey(hkFreelance);
124 CloseHandle(hFreelanceSymlinkChangeEvent);
125 hFreelanceSymlinkChangeEvent = 0;
128 cm_noteLocalMountPointChange(FALSE);
134 cm_FreelanceShutdown(void)
136 freelance_ShutdownFlag = 1;
137 if (hFreelanceChangeEvent != 0)
138 thrd_SetEvent(hFreelanceChangeEvent);
139 if (hFreelanceSymlinkChangeEvent != 0)
140 thrd_SetEvent(hFreelanceSymlinkChangeEvent);
144 cm_FreelanceAddCSDBMountPoints(void *rockp, char *cellNamep)
146 char szCellName[CELL_MAXNAMELEN+1] = ".";
148 cm_FsStrCpy( &szCellName[1], CELL_MAXNAMELEN, cellNamep);
149 /* create readonly mount point */
150 cm_FreelanceAddMount( cellNamep, cellNamep, "root.cell", 0, NULL);
152 /* create read/write mount point */
153 cm_FreelanceAddMount( szCellName, szCellName, "root.cell", 1, NULL);
159 cm_FreelanceImportCellServDB(void)
161 cm_EnumerateCellRegistry( TRUE, cm_FreelanceAddCSDBMountPoints, NULL);
162 cm_EnumerateCellFile( TRUE, cm_FreelanceAddCSDBMountPoints, NULL);
165 void cm_InitFreelance() {
169 lock_InitializeMutex(&cm_Freelance_Lock, "Freelance Lock", LOCK_HIERARCHY_FREELANCE_GLOBAL);
171 lock_ObtainMutex(&cm_Freelance_Lock);
173 // yj: first we make a call to cm_initLocalMountPoints
174 // to read all the local mount points from the registry
175 cm_InitLocalMountPoints();
177 // then we make a call to InitFakeRootDir to create
178 // a fake root directory based on the local mount points
179 cm_InitFakeRootDir();
181 // increment the fakeDirVersion to force status updates for
182 // all cached Freelance objects
183 cm_data.fakeDirVersion++;
184 // --- end of yj code
185 lock_ReleaseMutex(&cm_Freelance_Lock);
187 /* Start the registry monitor */
188 phandle = thrd_Create(NULL, 65536, (ThreadFunc) cm_FreelanceChangeNotifier,
189 NULL, 0, &lpid, "cm_FreelanceChangeNotifier");
190 osi_assertx(phandle != NULL, "cm_FreelanceChangeNotifier thread create failure");
191 thrd_CloseHandle(phandle);
193 phandle = thrd_Create(NULL, 65536, (ThreadFunc) cm_FreelanceSymlinkChangeNotifier,
194 NULL, 0, &lpid, "cm_FreelanceSymlinkChangeNotifier");
195 osi_assertx(phandle != NULL, "cm_FreelanceSymlinkChangeNotifier thread create failure");
196 thrd_CloseHandle(phandle);
199 /* yj: Initialization of the fake root directory */
200 /* to be called while holding freelance lock. */
201 void cm_InitFakeRootDir() {
206 // allocate space for the fake info
207 cm_dirHeader_t fakeDirHeader;
208 cm_dirEntry_t fakeEntry;
209 cm_pageHeader_t fakePageHeader;
211 // i'm going to calculate how much space is needed for
212 // this fake root directory. we have these rules:
213 // 1. there are cm_noLocalMountPoints number of entries
214 // 2. each page is CM_DIR_PAGESIZE in size
215 // 3. the first 13 chunks of the first page are used for
217 // 4. the first chunk of all subsequent pages are used
218 // for page header stuff
219 // 5. a max of CM_DIR_EPP entries are allowed per page
220 // 6. each entry takes 1 or more chunks, depending on
221 // the size of the mount point string, as determined
223 // 7. each chunk is CM_DIR_CHUNKSIZE bytes
225 int CPP = CM_DIR_PAGESIZE / CM_DIR_CHUNKSIZE;
226 int curChunk = 13; // chunks 0 - 12 are used for header stuff
227 // of the first page in the directory
229 unsigned int curDirEntry = 0;
230 int curDirEntryInPage = 0;
234 /* Increment the fake Uniquifier */
235 cm_data.fakeUnique++;
237 /* Reserve 2 directory chunks for "." and ".." */
240 while (curDirEntry<cm_noLocalMountPoints) {
241 sizeOfCurEntry = cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0);
242 if ((curChunk + sizeOfCurEntry >= CPP) ||
243 (curDirEntryInPage + 1 >= CM_DIR_EPP)) {
245 curDirEntryInPage = 0;
248 curChunk += sizeOfCurEntry;
253 dirSize = (curPage+1) * CM_DIR_PAGESIZE;
254 if (cm_fakeDirSize != dirSize) {
256 free(cm_FakeRootDir);
257 cm_FakeRootDir = calloc(dirSize, 1);
258 cm_fakeDirSize = dirSize;
261 // yj: when we get here, we've figured out how much memory we need and
262 // allocated the appropriate space for it. we now prceed to fill
263 // it up with entries.
266 curDirEntryInPage = 0;
269 // fields in the directory entry that are unused.
271 fakeEntry.length = 0;
273 fakeEntry.fid.unique = htonl(1 + cm_data.fakeUnique);
275 // the first page is special, it uses fakeDirHeader instead of fakePageHeader
276 // we fill up the page with dirEntries that belong there and we make changes
277 // to the fakeDirHeader.header.freeBitmap along the way. Then when we're done
278 // filling up the dirEntries in this page, we copy the fakeDirHeader into
279 // the top of the page.
281 // init the freeBitmap array
283 fakeDirHeader.header.freeBitmap[i]=0;
285 fakeDirHeader.header.freeBitmap[0] = 0xff;
286 fakeDirHeader.header.freeBitmap[1] = 0x7f;
289 // we start counting at 13 because the 0th to 12th chunks are used for header
292 // stick the first 2 entries "." and ".." in
293 fakeEntry.fid.vnode = htonl(1);
294 strcpy(fakeEntry.name, ".");
295 currentPos = cm_FakeRootDir + curPage * CM_DIR_PAGESIZE + curChunk * CM_DIR_CHUNKSIZE;
296 memcpy(currentPos, &fakeEntry, CM_DIR_CHUNKSIZE);
297 curChunk++; curDirEntryInPage++;
298 strcpy(fakeEntry.name, "..");
299 currentPos = cm_FakeRootDir + curPage * CM_DIR_PAGESIZE + curChunk * CM_DIR_CHUNKSIZE;
300 memcpy(currentPos, &fakeEntry, CM_DIR_CHUNKSIZE);
301 curChunk++; curDirEntryInPage++;
303 // keep putting stuff into page 0 if
304 // 1. we're not done with all entries
305 // 2. we have less than CM_DIR_EPP entries in page 0
306 // 3. we're not out of chunks in page 0
308 while( (curDirEntry<cm_noLocalMountPoints) &&
309 (curDirEntryInPage < CM_DIR_EPP) &&
310 (curChunk + cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0) <= CPP))
313 noChunks = cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0);
314 /* enforce the rule that only directories have odd vnode values */
315 fakeEntry.fid.vnode = htonl((curDirEntry + 1) * 2);
316 fakeEntry.fid.unique = htonl(curDirEntry + 1 + cm_data.fakeUnique);
317 currentPos = cm_FakeRootDir + curPage * CM_DIR_PAGESIZE + curChunk * CM_DIR_CHUNKSIZE;
319 memcpy(currentPos, &fakeEntry, CM_DIR_CHUNKSIZE);
320 strcpy(currentPos + 12, (cm_localMountPoints+curDirEntry)->namep);
323 for (i=0; i<noChunks; i++) {
324 t1 = (curChunk + i) / 8;
325 t2 = curChunk + i - (t1*8);
326 fakeDirHeader.header.freeBitmap[t1] |= (1 << t2);
331 // when we get here, we're done with filling in the entries for page 0
332 // copy in the header info
334 memcpy(cm_FakeRootDir, &fakeDirHeader, 13 * CM_DIR_CHUNKSIZE);
338 // ok, page 0's done. Move on to the next page.
339 while (curDirEntry<cm_noLocalMountPoints) {
341 curChunk = 1; // the zeroth chunk is reserved for page header
342 curDirEntryInPage = 0;
343 for (i=0; i<8; i++) {
344 fakePageHeader.freeBitmap[i]=0;
346 fakePageHeader.freeCount = 0;
347 fakePageHeader.pgcount = 0;
348 fakePageHeader.tag = htons(1234);
350 // while we're on the same page...
351 while ( (curDirEntry<cm_noLocalMountPoints) &&
352 (curDirEntryInPage < CM_DIR_EPP) &&
353 (curChunk + cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0) <= CPP))
355 // add an entry to this page
357 noChunks = cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0);
358 /* enforce the rule that only directories have odd vnode values */
359 fakeEntry.fid.vnode = htonl((curDirEntry + 1) * 2);
360 fakeEntry.fid.unique = htonl(curDirEntry + 1 + cm_data.fakeUnique);
361 currentPos = cm_FakeRootDir + curPage * CM_DIR_PAGESIZE + curChunk * CM_DIR_CHUNKSIZE;
362 memcpy(currentPos, &fakeEntry, CM_DIR_CHUNKSIZE);
363 strcpy(currentPos + 12, (cm_localMountPoints+curDirEntry)->namep);
366 for (i=0; i<noChunks; i++) {
367 t1 = (curChunk + i) / 8;
368 t2 = curChunk + i - (t1*8);
369 fakePageHeader.freeBitmap[t1] |= (1 << t2);
373 memcpy(cm_FakeRootDir + curPage * CM_DIR_PAGESIZE, &fakePageHeader, sizeof(fakePageHeader));
378 // we know the fakeDir is setup properly, so we claim that we have callback
379 osi_Log0(afsd_logp,"cm_InitFakeRootDir completed!");
381 // when we get here, we've set up everything! done!
384 int cm_FakeRootFid(cm_fid_t *fidp)
387 AFS_FAKE_ROOT_CELL_ID, /* root cell */
388 AFS_FAKE_ROOT_VOL_ID, /* root.afs ? */
393 /* called directly from ioctl */
394 /* called while not holding freelance lock */
395 int cm_noteLocalMountPointChange(afs_int32 locked) {
397 lock_ObtainMutex(&cm_Freelance_Lock);
398 cm_data.fakeDirVersion++;
399 cm_localMountPointChangeFlag = 1;
402 lock_ReleaseMutex(&cm_Freelance_Lock);
404 if (RDR_Initialized) {
406 cm_FakeRootFid(&fid);
407 RDR_InvalidateObject( fid.cell, fid.volume, fid.vnode, fid.unique, fid.hash,
408 CM_SCACHETYPE_DIRECTORY,
409 AFS_INVALIDATE_DATA_VERSION);
414 int cm_getLocalMountPointChange() {
415 return cm_localMountPointChangeFlag;
418 int cm_clearLocalMountPointChange() {
419 cm_localMountPointChangeFlag = 0;
423 int cm_reInitLocalMountPoints() {
425 unsigned int i, hash;
426 cm_scache_t *scp, **lscpp, *tscp;
431 osi_Log0(afsd_logp,"----- freelance reinitialization starts ----- ");
433 // first we invalidate all the SCPs that were created
434 // for the local mount points
436 osi_Log0(afsd_logp,"Invalidating local mount point scp... ");
438 lock_ObtainWrite(&cm_scacheLock);
439 lock_ObtainMutex(&cm_Freelance_Lock); /* always scache then freelance lock */
440 for (i=0; i<=cm_noLocalMountPoints; i++) {
442 cm_SetFid(&aFid, AFS_FAKE_ROOT_CELL_ID, AFS_FAKE_ROOT_VOL_ID, 1, 1);
444 cm_SetFid(&aFid, AFS_FAKE_ROOT_CELL_ID, AFS_FAKE_ROOT_VOL_ID, i*2, i);
445 hash = CM_SCACHE_HASH(&aFid);
446 for (scp=cm_data.scacheHashTablep[hash]; scp; scp=scp->nextp) {
447 if (scp != cm_data.rootSCachep && cm_FidCmp(&scp->fid, &aFid) == 0) {
448 // mark the scp to be reused
449 cm_HoldSCacheNoLock(scp);
450 lock_ReleaseMutex(&cm_Freelance_Lock);
451 lock_ReleaseWrite(&cm_scacheLock);
452 lock_ObtainWrite(&scp->rw);
453 cm_DiscardSCache(scp);
455 // take the scp out of the hash
456 lock_ObtainWrite(&cm_scacheLock);
457 for (lscpp = &cm_data.scacheHashTablep[hash], tscp = cm_data.scacheHashTablep[hash];
459 lscpp = &tscp->nextp, tscp = tscp->nextp) {
463 scp->flags &= ~CM_SCACHEFLAG_INHASH;
468 lock_ReleaseWrite(&scp->rw);
469 lock_ReleaseWrite(&cm_scacheLock);
470 cm_CallbackNotifyChange(scp);
473 RDR_InvalidateObject(scp->fid.cell, scp->fid.volume, scp->fid.vnode, scp->fid.unique,
474 scp->fid.hash, scp->fileType, AFS_INVALIDATE_CALLBACK);
476 lock_ObtainWrite(&cm_scacheLock);
477 cm_ReleaseSCacheNoLock(scp);
478 lock_ObtainMutex(&cm_Freelance_Lock);
482 lock_ReleaseWrite(&cm_scacheLock);
483 lock_ReleaseMutex(&cm_Freelance_Lock);
484 osi_Log0(afsd_logp,"\tall old scp cleared!");
486 lock_ObtainWrite(&cm_data.rootSCachep->rw);
487 lock_ObtainMutex(&cm_Freelance_Lock);
488 // we must free the memory that was allocated in the prev
489 // cm_InitLocalMountPoints call
490 osi_Log0(afsd_logp,"Removing old localmountpoints... ");
491 free(cm_localMountPoints);
492 cm_localMountPoints = NULL;
493 cm_noLocalMountPoints = 0;
494 osi_Log0(afsd_logp,"\tall old localmountpoints cleared!");
496 // now re-init the localmountpoints
497 osi_Log0(afsd_logp,"Creating new localmountpoints... ");
498 cm_InitLocalMountPoints();
499 osi_Log0(afsd_logp,"\tcreated new set of localmountpoints!");
501 // then we re-create that dir
502 osi_Log0(afsd_logp,"Creating new fakedir... ");
503 cm_InitFakeRootDir();
504 osi_Log0(afsd_logp,"\t\tcreated new fakedir!");
506 lock_ReleaseMutex(&cm_Freelance_Lock);
508 cm_GetCallback(cm_data.rootSCachep, cm_rootUserp, &req, 0);
509 lock_ReleaseWrite(&cm_data.rootSCachep->rw);
511 osi_Log0(afsd_logp,"----- freelance reinit complete -----");
516 * cm_enforceTrailingDot
518 * return 0 on failure, non-zero on success
522 cm_enforceTrailingDot(char * line, size_t cchLine, DWORD *pdwSize)
525 afsi_log("invalid string");
529 /* trailing white space first. */
530 if (line[(*pdwSize)-1] == '\0') {
531 while (isspace(line[(*pdwSize)-2])) {
532 line[(*pdwSize)-2] = '\0';
536 while (isspace(line[(*pdwSize)-1])) {
537 line[(*pdwSize)-1] = '\0';
542 /* then enforce the trailing dot requirement */
543 if (line[(*pdwSize)-1] == '\0' && line[(*pdwSize)-2] != '.') {
544 if ((*pdwSize) >= cchLine) {
545 afsi_log("no room for trailing dot");
548 line[(*pdwSize)-1] = '.';
549 line[(*pdwSize)] = '\0';
550 } else if (line[(*pdwSize)-1] != '\0' && line[(*pdwSize)-1] != '.') {
551 if ((*pdwSize) >= cchLine) {
552 afsi_log("no room for trailing dot and nul");
555 line[(*pdwSize)] = '.';
556 line[(*pdwSize)+1] = '\0';
557 } else if (line[(*pdwSize)-1] != '\0') {
558 if ((*pdwSize) >= cchLine) {
559 afsi_log("no room for trailing nul");
562 line[(*pdwSize)] = '\0';
568 // yj: open up the registry and read all the local mount
569 // points that are stored there. Part of the initialization
570 // process for the freelance client.
571 /* to be called while holding freelance lock. */
572 long cm_InitLocalMountPoints() {
577 cm_localMountPoint_t* aLocalMountPoint;
580 char rootCellName[256];
581 HKEY hkFreelance = 0, hkFreelanceSymlinks = 0;
582 DWORD dwType, dwSize;
583 DWORD dwMountPoints = 0;
585 DWORD dwSymlinks = 0;
586 FILETIME ftLastWriteTime;
588 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
589 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance",
591 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
592 &hkFreelance) == ERROR_SUCCESS) {
594 RegQueryInfoKey( hkFreelance,
597 NULL, /* lpReserved */
598 NULL, /* lpcSubKeys */
599 NULL, /* lpcMaxSubKeyLen */
600 NULL, /* lpcMaxClassLen */
601 &dwMountPoints, /* lpcValues */
602 NULL, /* lpcMaxValueNameLen */
603 NULL, /* lpcMaxValueLen */
604 NULL, /* lpcbSecurityDescriptor */
605 &ftLastWriteTime /* lpftLastWriteTime */
608 cm_UnixTimeFromLargeSearchTime(&FakeFreelanceModTime, &ftLastWriteTime);
610 if ( dwMountPoints == 0 ) {
611 rootCellName[0] = '.';
612 code = cm_GetRootCellName(&rootCellName[1]);
614 lock_ReleaseMutex(&cm_Freelance_Lock);
615 cm_FreelanceAddMount(&rootCellName[1], &rootCellName[1], "root.cell", 0, NULL);
616 cm_FreelanceAddMount(rootCellName, &rootCellName[1], "root.cell", 1, NULL);
617 cm_FreelanceAddMount(".root", &rootCellName[1], "root.afs", 1, NULL);
618 lock_ObtainMutex(&cm_Freelance_Lock);
623 if (RegCreateKeyEx( HKEY_LOCAL_MACHINE,
624 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance\\Symlinks",
627 REG_OPTION_NON_VOLATILE,
628 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
630 &hkFreelanceSymlinks,
631 NULL) == ERROR_SUCCESS) {
633 RegQueryInfoKey( hkFreelanceSymlinks,
636 NULL, /* lpReserved */
637 NULL, /* lpcSubKeys */
638 NULL, /* lpcMaxSubKeyLen */
639 NULL, /* lpcMaxClassLen */
640 &dwSymlinks, /* lpcValues */
641 NULL, /* lpcMaxValueNameLen */
642 NULL, /* lpcMaxValueLen */
643 NULL, /* lpcbSecurityDescriptor */
644 NULL /* lpftLastWriteTime */
648 // get the number of entries there are from the first line
650 cm_noLocalMountPoints = dwMountPoints + dwSymlinks;
652 // create space to store the local mount points
653 cm_localMountPoints = malloc(sizeof(cm_localMountPoint_t) * cm_noLocalMountPoints);
654 aLocalMountPoint = cm_localMountPoints;
656 // now we read n lines and parse them into local mount points
657 // where n is the number of local mount points there are, as
659 // Each line in the ini file represents 1 local mount point and
660 // is in the format xxx#yyy:zzz, where xxx is the directory
661 // entry name, yyy is the cell name and zzz is the volume name.
662 // #yyy:zzz together make up the mount point.
663 for ( dwIndex = 0 ; dwIndex < dwMountPoints; dwIndex++ ) {
664 TCHAR szValueName[16];
665 DWORD dwValueSize = 16;
666 dwSize = sizeof(line);
667 if (RegEnumValue( hkFreelance, dwIndex, szValueName, &dwValueSize, NULL,
668 &dwType, line, &dwSize))
670 afsi_log("RegEnumValue(hkFreelance) failed");
671 cm_noLocalMountPoints--;
675 /* make sure there is a trailing dot and a nul terminator */
676 if (!cm_enforceTrailingDot(line, sizeof(line), &dwSize)) {
677 cm_noLocalMountPoints--;
681 afsi_log("Mountpoint[%d] = %s", dwIndex, line);
683 for ( t=line;*t;t++ ) {
684 if ( !isprint(*t) ) {
685 afsi_log("error occurred while parsing mountpoint entry [%d]: non-printable character", dwIndex);
686 fprintf(stderr, "error occurred while parsing mountpoint entry [%d]: non-printable character", dwIndex);
687 cm_noLocalMountPoints--;
692 // line is not empty, so let's parse it
693 t = strchr(line, '#');
695 t = strchr(line, '%');
696 // make sure that there is a '#' or '%' separator in the line
698 afsi_log("error occurred while parsing mountpoint entry [%d]: no # or %% separator", dwIndex);
699 fprintf(stderr, "error occurred while parsing mountpoint entry [%d]: no # or %% separator", dwIndex);
700 cm_noLocalMountPoints--;
704 aLocalMountPoint->fileType = CM_SCACHETYPE_MOUNTPOINT;
705 aLocalMountPoint->namep=malloc(t-line+1);
706 strncpy(aLocalMountPoint->namep, line, t-line);
707 aLocalMountPoint->namep[t-line] = '\0';
709 /* copy the mount point string */
710 aLocalMountPoint->mountPointStringp=malloc(strlen(t));
711 strncpy(aLocalMountPoint->mountPointStringp, t, strlen(t)-1);
712 aLocalMountPoint->mountPointStringp[strlen(t)-1] = '\0';
714 osi_Log2(afsd_logp,"found mount point: name %s, string %s",
715 osi_LogSaveString(afsd_logp,aLocalMountPoint->namep),
716 osi_LogSaveString(afsd_logp,aLocalMountPoint->mountPointStringp));
721 for ( dwIndex = 0 ; dwIndex < dwSymlinks; dwIndex++ ) {
722 TCHAR szValueName[16];
723 DWORD dwValueSize = 16;
724 dwSize = sizeof(line);
725 if (RegEnumValue( hkFreelanceSymlinks, dwIndex, szValueName, &dwValueSize, NULL,
726 &dwType, line, &dwSize))
728 afsi_log("RegEnumValue(hkFreelanceSymlinks) failed");
729 cm_noLocalMountPoints--;
733 /* make sure there is a trailing dot and a nul terminator */
734 if (!cm_enforceTrailingDot(line, sizeof(line), &dwSize)) {
735 cm_noLocalMountPoints--;
739 afsi_log("Symlink[%d] = %s", dwIndex, line);
741 for ( t=line;*t;t++ ) {
742 if ( !isprint(*t) ) {
743 afsi_log("error occurred while parsing symlink entry [%d]: non-printable character", dwIndex);
744 fprintf(stderr, "error occurred while parsing symlink entry [%d]: non-printable character", dwIndex);
745 cm_noLocalMountPoints--;
750 // line is not empty, so let's parse it
751 t = strchr(line, ':');
753 // make sure that there is a ':' separator in the line
755 afsi_log("error occurred while parsing symlink entry [%d]: no ':' separator", dwIndex);
756 fprintf(stderr, "error occurred while parsing symlink entry [%d]: no ':' separator", dwIndex);
757 cm_noLocalMountPoints--;
761 aLocalMountPoint->fileType = CM_SCACHETYPE_SYMLINK;
762 aLocalMountPoint->namep=malloc(t-line+1);
763 strncpy(aLocalMountPoint->namep, line, t-line);
764 aLocalMountPoint->namep[t-line] = '\0';
766 /* copy the symlink string */
767 aLocalMountPoint->mountPointStringp=malloc(strlen(t)-1);
768 strncpy(aLocalMountPoint->mountPointStringp, t+1, strlen(t)-2);
769 aLocalMountPoint->mountPointStringp[strlen(t)-2] = '\0';
771 osi_Log2(afsd_logp,"found symlink: name %s, string %s",
772 osi_LogSaveString(afsd_logp,aLocalMountPoint->namep),
773 osi_LogSaveString(afsd_logp,aLocalMountPoint->mountPointStringp));
778 if ( hkFreelanceSymlinks )
779 RegCloseKey( hkFreelanceSymlinks );
780 RegCloseKey(hkFreelance);
784 /* What follows is the old code to read freelance mount points
785 * out of a text file modified to copy the data into the registry
787 cm_GetConfigDir(hdir, sizeof(hdir));
788 strcat(hdir, AFS_FREELANCE_INI);
789 // open the ini file for reading
790 fp = fopen(hdir, "r");
792 /* look in the Windows directory where we used to store the file */
793 GetWindowsDirectory(hdir, sizeof(hdir));
795 strcat(hdir, AFS_FREELANCE_INI);
796 fp = fopen(hdir, "r");
799 RegCreateKeyEx( HKEY_LOCAL_MACHINE,
800 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance",
803 REG_OPTION_NON_VOLATILE,
811 RegCloseKey(hkFreelance);
812 rootCellName[0] = '.';
813 code = cm_GetRootCellName(&rootCellName[1]);
815 lock_ReleaseMutex(&cm_Freelance_Lock);
816 cm_FreelanceAddMount(&rootCellName[1], &rootCellName[1], "root.cell", 0, NULL);
817 cm_FreelanceAddMount(rootCellName, &rootCellName[1], "root.cell", 1, NULL);
818 cm_FreelanceAddMount(".root", &rootCellName[1], "root.afs", 1, NULL);
819 lock_ObtainMutex(&cm_Freelance_Lock);
824 // we successfully opened the file
825 osi_Log0(afsd_logp,"opened afs_freelance.ini");
827 // now we read the first line to see how many entries
829 fgets(line, sizeof(line), fp);
831 // if the line is empty at any point when we're reading
832 // we're screwed. report error and return.
834 afsi_log("error occurred while reading afs_freelance.ini");
835 fprintf(stderr, "error occurred while reading afs_freelance.ini");
839 // get the number of entries there are from the first line
841 cm_noLocalMountPoints = atoi(line);
843 if (cm_noLocalMountPoints > 0) {
844 // create space to store the local mount points
845 cm_localMountPoints = malloc(sizeof(cm_localMountPoint_t) * cm_noLocalMountPoints);
846 aLocalMountPoint = cm_localMountPoints;
849 // now we read n lines and parse them into local mount points
850 // where n is the number of local mount points there are, as
852 // Each line in the ini file represents 1 local mount point and
853 // is in the format xxx#yyy:zzz, where xxx is the directory
854 // entry name, yyy is the cell name and zzz is the volume name.
855 // #yyy:zzz together make up the mount point.
856 for (i=0; i<cm_noLocalMountPoints; i++) {
857 fgets(line, sizeof(line), fp);
858 // check that the line is not empty
860 afsi_log("error occurred while parsing entry in %s: empty line in line %d", AFS_FREELANCE_INI, i);
861 fprintf(stderr, "error occurred while parsing entry in afs_freelance.ini: empty line in line %d", i);
865 /* find the trailing dot; null terminate after it */
866 t2 = strrchr(line, '.');
872 /* we are migrating to the registry */
873 sprintf(szIndex,"%d",dwIndex++);
875 dwSize = (DWORD)strlen(line) + 1;
876 RegSetValueEx( hkFreelance, szIndex, 0, dwType, line, dwSize);
879 // line is not empty, so let's parse it
880 t = strchr(line, '#');
882 t = strchr(line, '%');
883 // make sure that there is a '#' or '%' separator in the line
885 afsi_log("error occurred while parsing entry in %s: no # or %% separator in line %d", AFS_FREELANCE_INI, i);
886 fprintf(stderr, "error occurred while parsing entry in afs_freelance.ini: no # or %% separator in line %d", i);
889 aLocalMountPoint->namep=malloc(t-line+1);
890 memcpy(aLocalMountPoint->namep, line, t-line);
891 *(aLocalMountPoint->namep + (t-line)) = 0;
893 aLocalMountPoint->mountPointStringp=malloc(strlen(line) - (t-line) + 1);
894 memcpy(aLocalMountPoint->mountPointStringp, t, strlen(line)-(t-line)-1);
895 *(aLocalMountPoint->mountPointStringp + (strlen(line)-(t-line)-1)) = 0;
897 osi_Log2(afsd_logp,"found mount point: name %s, string %s",
898 aLocalMountPoint->namep,
899 aLocalMountPoint->mountPointStringp);
905 RegCloseKey(hkFreelance);
911 int cm_getNoLocalMountPoints() {
912 return cm_noLocalMountPoints;
915 long cm_FreelanceMountPointExists(char * filename, int prefix_ok)
921 HKEY hkFreelance = 0;
922 DWORD dwType, dwSize;
926 lock_ObtainMutex(&cm_Freelance_Lock);
928 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
929 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance",
931 KEY_READ|KEY_QUERY_VALUE,
932 &hkFreelance) == ERROR_SUCCESS)
934 RegQueryInfoKey( hkFreelance,
937 NULL, /* lpReserved */
938 NULL, /* lpcSubKeys */
939 NULL, /* lpcMaxSubKeyLen */
940 NULL, /* lpcMaxClassLen */
941 &dwMountPoints, /* lpcValues */
942 NULL, /* lpcMaxValueNameLen */
943 NULL, /* lpcMaxValueLen */
944 NULL, /* lpcbSecurityDescriptor */
945 NULL /* lpftLastWriteTime */
948 for ( dwIndex = 0; dwIndex < dwMountPoints; dwIndex++ ) {
949 TCHAR szValueName[16];
950 DWORD dwValueSize = 16;
951 dwSize = sizeof(line);
952 RegEnumValue( hkFreelance, dwIndex, szValueName, &dwValueSize, NULL,
953 &dwType, line, &dwSize);
955 cp=strchr(line, '#');
957 cp=strchr(line, '%');
958 memcpy(shortname, line, cp-line);
959 shortname[cp-line]=0;
961 if (!strcmp(shortname, filename)) {
966 for ( dwIndex = 0; dwIndex < dwMountPoints; dwIndex++ ) {
967 TCHAR szValueName[16];
968 DWORD dwValueSize = 16;
969 dwSize = sizeof(line);
970 RegEnumValue( hkFreelance, dwIndex, szValueName, &dwValueSize, NULL,
971 &dwType, line, &dwSize);
973 cp=strchr(line, '#');
975 cp=strchr(line, '%');
976 memcpy(shortname, line, cp-line);
977 shortname[cp-line]=0;
979 if (!cm_stricmp_utf8(shortname, filename)) {
984 if (prefix_ok && strlen(shortname) - strlen(filename) == 1 && !strncmp(shortname, filename, strlen(filename))) {
989 RegCloseKey(hkFreelance);
992 lock_ReleaseMutex(&cm_Freelance_Lock);
997 long cm_FreelanceSymlinkExists(char * filename, int prefix_ok)
1001 char shortname[200];
1003 HKEY hkFreelance = 0;
1004 DWORD dwType, dwSize;
1008 lock_ObtainMutex(&cm_Freelance_Lock);
1010 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
1011 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance\\Symlinks",
1013 KEY_READ|KEY_QUERY_VALUE,
1014 &hkFreelance) == ERROR_SUCCESS)
1016 RegQueryInfoKey( hkFreelance,
1018 NULL, /* lpcClass */
1019 NULL, /* lpReserved */
1020 NULL, /* lpcSubKeys */
1021 NULL, /* lpcMaxSubKeyLen */
1022 NULL, /* lpcMaxClassLen */
1023 &dwSymlinks, /* lpcValues */
1024 NULL, /* lpcMaxValueNameLen */
1025 NULL, /* lpcMaxValueLen */
1026 NULL, /* lpcbSecurityDescriptor */
1027 NULL /* lpftLastWriteTime */
1030 for ( dwIndex = 0; dwIndex < dwSymlinks; dwIndex++ ) {
1031 TCHAR szValueName[16];
1032 DWORD dwValueSize = 16;
1033 dwSize = sizeof(line);
1034 RegEnumValue( hkFreelance, dwIndex, szValueName, &dwValueSize, NULL,
1035 &dwType, line, &dwSize);
1037 cp=strchr(line, ':');
1038 memcpy(shortname, line, cp-line);
1039 shortname[cp-line]=0;
1041 if (!strcmp(shortname, filename)) {
1046 if (prefix_ok && strlen(shortname) - strlen(filename) == 1 && !strncmp(shortname, filename, strlen(filename))) {
1051 for ( dwIndex = 0; dwIndex < dwSymlinks; dwIndex++ ) {
1052 TCHAR szValueName[16];
1053 DWORD dwValueSize = 16;
1054 dwSize = sizeof(line);
1055 RegEnumValue( hkFreelance, dwIndex, szValueName, &dwValueSize, NULL,
1056 &dwType, line, &dwSize);
1058 cp=strchr(line, ':');
1059 memcpy(shortname, line, cp-line);
1060 shortname[cp-line]=0;
1062 if (!cm_stricmp_utf8(shortname, filename)) {
1067 RegCloseKey(hkFreelance);
1070 lock_ReleaseMutex(&cm_Freelance_Lock);
1075 long cm_FreelanceAddMount(char *filename, char *cellname, char *volume, int rw, cm_fid_t *fidp)
1080 char fullname[CELL_MAXNAMELEN];
1083 HKEY hkFreelance = 0;
1084 DWORD dwType, dwSize;
1085 DWORD dwMountPoints;
1087 afs_uint32 code = 0;
1089 /* before adding, verify the cell name; if it is not a valid cell,
1090 don't add the mount point.
1091 allow partial matches as a means of poor man's alias. */
1092 /* major performance issue? */
1093 osi_Log4(afsd_logp,"Freelance Add Mount request: filename=%s cellname=%s volume=%s %s",
1094 osi_LogSaveString(afsd_logp,filename),
1095 osi_LogSaveString(afsd_logp,cellname),
1096 osi_LogSaveString(afsd_logp,volume),
1099 if ( filename[0] == '\0' || cellname[0] == '\0' || volume[0] == '\0' )
1100 return CM_ERROR_INVAL;
1102 if ( cm_FreelanceMountPointExists(filename, 0) ||
1103 cm_FreelanceSymlinkExists(filename, 0) ) {
1104 code = CM_ERROR_EXISTS;
1108 if (cellname[0] == '.') {
1109 if (!cm_GetCell_Gen(&cellname[1], fullname, CM_FLAG_CREATE))
1110 return CM_ERROR_INVAL;
1112 if (!cm_GetCell_Gen(cellname, fullname, CM_FLAG_CREATE))
1113 return CM_ERROR_INVAL;
1116 osi_Log1(afsd_logp,"Freelance Adding Mount for Cell: %s",
1117 osi_LogSaveString(afsd_logp,cellname));
1119 lock_ObtainMutex(&cm_Freelance_Lock);
1121 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
1122 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance",
1124 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
1125 &hkFreelance) == ERROR_SUCCESS) {
1127 RegQueryInfoKey( hkFreelance,
1129 NULL, /* lpcClass */
1130 NULL, /* lpReserved */
1131 NULL, /* lpcSubKeys */
1132 NULL, /* lpcMaxSubKeyLen */
1133 NULL, /* lpcMaxClassLen */
1134 &dwMountPoints, /* lpcValues */
1135 NULL, /* lpcMaxValueNameLen */
1136 NULL, /* lpcMaxValueLen */
1137 NULL, /* lpcbSecurityDescriptor */
1138 NULL /* lpftLastWriteTime */
1142 sprintf(line, "%s%%%s:%s.", filename, fullname, volume);
1144 sprintf(line, "%s#%s:%s.", filename, fullname, volume);
1146 /* If we are adding a new value, there must be an unused name
1147 * within the range 0 to dwMountPoints
1149 for ( dwIndex = 0; dwIndex <= dwMountPoints; dwIndex++ ) {
1153 dwSize = sizeof(szMount);
1154 sprintf(szIndex, "%d", dwIndex);
1155 if (RegQueryValueEx( hkFreelance, szIndex, 0, &dwType, szMount, &dwSize) != ERROR_SUCCESS) {
1156 /* found an unused value */
1158 dwSize = (DWORD)strlen(line) + 1;
1159 RegSetValueEx( hkFreelance, szIndex, 0, dwType, line, dwSize);
1162 int len = (int)strlen(filename);
1163 if ( dwType == REG_SZ && !strncmp(filename, szMount, len) &&
1164 (szMount[len] == '%' || szMount[len] == '#')) {
1165 /* Replace the existing value */
1167 dwSize = (DWORD)strlen(line) + 1;
1168 RegSetValueEx( hkFreelance, szIndex, 0, dwType, line, dwSize);
1173 RegCloseKey(hkFreelance);
1176 cm_GetConfigDir(hfile, sizeof(hfile));
1177 strcat(hfile, AFS_FREELANCE_INI);
1178 fp = fopen(hfile, "r+");
1180 return CM_ERROR_INVAL;
1181 fgets(line, sizeof(line), fp);
1184 fseek(fp, 0, SEEK_SET);
1185 fprintf(fp, "%d", n);
1186 fseek(fp, 0, SEEK_END);
1188 fprintf(fp, "%s%%%s:%s.\n", filename, fullname, volume);
1190 fprintf(fp, "%s#%s:%s.\n", filename, fullname, volume);
1194 /* Do this while we are holding the lock */
1195 cm_noteLocalMountPointChange(TRUE);
1196 lock_ReleaseMutex(&cm_Freelance_Lock);
1202 clientchar_t *cpath;
1206 cpath = cm_FsStringToClientStringAlloc(filename, -1, NULL);
1208 return CM_ERROR_NOSUCHPATH;
1210 if (cm_getLocalMountPointChange()) { // check for changes
1211 cm_clearLocalMountPointChange(); // clear the changefile
1212 cm_reInitLocalMountPoints(); // start reinit
1215 code = cm_NameI(cm_RootSCachep(cm_rootUserp, &req), cpath,
1216 CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD | CM_FLAG_DFS_REFERRAL,
1217 cm_rootUserp, NULL, &req, &scp);
1222 cm_ReleaseSCache(scp);
1228 long cm_FreelanceRemoveMount(char *toremove)
1233 char shortname[200];
1234 char hfile[260], hfile2[260];
1237 HKEY hkFreelance = 0;
1238 DWORD dwType, dwSize;
1239 DWORD dwMountPoints;
1242 lock_ObtainMutex(&cm_Freelance_Lock);
1244 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
1245 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance",
1247 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
1248 &hkFreelance) == ERROR_SUCCESS) {
1250 RegQueryInfoKey( hkFreelance,
1252 NULL, /* lpcClass */
1253 NULL, /* lpReserved */
1254 NULL, /* lpcSubKeys */
1255 NULL, /* lpcMaxSubKeyLen */
1256 NULL, /* lpcMaxClassLen */
1257 &dwMountPoints, /* lpcValues */
1258 NULL, /* lpcMaxValueNameLen */
1259 NULL, /* lpcMaxValueLen */
1260 NULL, /* lpcbSecurityDescriptor */
1261 NULL /* lpftLastWriteTime */
1264 for ( dwIndex = 0; dwIndex < dwMountPoints; dwIndex++ ) {
1265 TCHAR szValueName[16];
1266 DWORD dwValueSize = 16;
1267 dwSize = sizeof(line);
1268 RegEnumValue( hkFreelance, dwIndex, szValueName, &dwValueSize, NULL,
1269 &dwType, line, &dwSize);
1271 cp=strchr(line, '#');
1273 cp=strchr(line, '%');
1274 memcpy(shortname, line, cp-line);
1275 shortname[cp-line]=0;
1277 if (!strcmp(shortname, toremove)) {
1278 RegDeleteValue( hkFreelance, szValueName );
1283 RegCloseKey(hkFreelance);
1286 cm_GetConfigDir(hfile, sizeof(hfile));
1287 strcat(hfile, AFS_FREELANCE_INI);
1288 strcpy(hfile2, hfile);
1289 strcat(hfile2, "2");
1290 fp1=fopen(hfile, "r+");
1292 return CM_ERROR_INVAL;
1293 fp2=fopen(hfile2, "w+");
1296 return CM_ERROR_INVAL;
1299 fgets(line, sizeof(line), fp1);
1301 fprintf(fp2, "%d\n", n-1);
1303 for (i=0; i<n; i++) {
1304 fgets(line, sizeof(line), fp1);
1305 cp=strchr(line, '#');
1307 cp=strchr(line, '%');
1308 memcpy(shortname, line, cp-line);
1309 shortname[cp-line]=0;
1311 if (strcmp(shortname, toremove)==0) {
1323 rename(hfile2, hfile);
1328 /* Do this while we are holding the lock */
1329 cm_noteLocalMountPointChange(TRUE);
1331 lock_ReleaseMutex(&cm_Freelance_Lock);
1332 return (found ? 0 : CM_ERROR_NOSUCHFILE);
1335 long cm_FreelanceAddSymlink(char *filename, char *destination, cm_fid_t *fidp)
1338 char fullname[CELL_MAXNAMELEN] = "";
1340 HKEY hkFreelanceSymlinks = 0;
1341 DWORD dwType, dwSize;
1344 afs_uint32 code = 0;
1347 * before adding, verify the filename. If it is already in use, either as
1348 * as mount point or a cellname, do not permit the creation of the symlink.
1350 osi_Log2(afsd_logp,"Freelance Add Symlink request: filename=%s destination=%s",
1351 osi_LogSaveString(afsd_logp,filename),
1352 osi_LogSaveString(afsd_logp,destination));
1354 if ( filename[0] == '\0' || destination[0] == '\0' )
1355 return CM_ERROR_INVAL;
1357 /* Do not create the symlink if the name ends in a dot */
1358 if ( filename[strlen(filename)-1] == '.')
1359 return CM_ERROR_INVAL;
1361 if ( cm_FreelanceMountPointExists(filename, 0) ||
1362 cm_FreelanceSymlinkExists(filename, 0) ) {
1363 code = CM_ERROR_EXISTS;
1367 if (filename[0] == '.') {
1368 cm_GetCell_Gen(&filename[1], fullname, CM_FLAG_CREATE);
1369 if (cm_stricmp_utf8(&filename[1],fullname) == 0) {
1370 code = CM_ERROR_EXISTS;
1374 cm_GetCell_Gen(filename, fullname, CM_FLAG_CREATE);
1375 if (cm_stricmp_utf8(filename,fullname) == 0) {
1376 code = CM_ERROR_EXISTS;
1381 lock_ObtainMutex(&cm_Freelance_Lock);
1383 if (RegCreateKeyEx( HKEY_LOCAL_MACHINE,
1384 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance\\Symlinks",
1387 REG_OPTION_NON_VOLATILE,
1388 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
1390 &hkFreelanceSymlinks,
1391 NULL) == ERROR_SUCCESS) {
1393 RegQueryInfoKey( hkFreelanceSymlinks,
1395 NULL, /* lpcClass */
1396 NULL, /* lpReserved */
1397 NULL, /* lpcSubKeys */
1398 NULL, /* lpcMaxSubKeyLen */
1399 NULL, /* lpcMaxClassLen */
1400 &dwSymlinks, /* lpcValues */
1401 NULL, /* lpcMaxValueNameLen */
1402 NULL, /* lpcMaxValueLen */
1403 NULL, /* lpcbSecurityDescriptor */
1404 NULL /* lpftLastWriteTime */
1407 sprintf(line, "%s:%s.", filename, destination);
1409 /* If we are adding a new value, there must be an unused name
1410 * within the range 0 to dwSymlinks
1412 for ( dwIndex = 0; dwIndex <= dwSymlinks; dwIndex++ ) {
1416 dwSize = sizeof(szLink);
1417 sprintf(szIndex, "%d", dwIndex);
1418 if (RegQueryValueEx( hkFreelanceSymlinks, szIndex, 0, &dwType, szLink, &dwSize) != ERROR_SUCCESS) {
1419 /* found an unused value */
1421 dwSize = (DWORD)strlen(line) + 1;
1422 RegSetValueEx( hkFreelanceSymlinks, szIndex, 0, dwType, line, dwSize);
1425 int len = (int)strlen(filename);
1426 if ( dwType == REG_SZ && !strncmp(filename, szLink, len) && szLink[len] == ':') {
1427 /* Replace the existing value */
1429 dwSize = (DWORD)strlen(line) + 1;
1430 RegSetValueEx( hkFreelanceSymlinks, szIndex, 0, dwType, line, dwSize);
1435 RegCloseKey(hkFreelanceSymlinks);
1438 /* Do this while we are holding the lock */
1439 cm_noteLocalMountPointChange(TRUE);
1440 lock_ReleaseMutex(&cm_Freelance_Lock);
1446 clientchar_t *cpath;
1450 cpath = cm_FsStringToClientStringAlloc(filename, -1, NULL);
1452 code = CM_ERROR_NOSUCHPATH;
1454 if (cm_getLocalMountPointChange()) { // check for changes
1455 cm_clearLocalMountPointChange(); // clear the changefile
1456 cm_reInitLocalMountPoints(); // start reinit
1459 code = cm_NameI(cm_RootSCachep(cm_rootUserp, &req), cpath,
1460 CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD | CM_FLAG_DFS_REFERRAL,
1461 cm_rootUserp, NULL, &req, &scp);
1465 cm_ReleaseSCache(scp);
1473 long cm_FreelanceRemoveSymlink(char *toremove)
1477 char shortname[200];
1479 HKEY hkFreelanceSymlinks = 0;
1480 DWORD dwType, dwSize;
1484 lock_ObtainMutex(&cm_Freelance_Lock);
1486 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
1487 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance\\Symlinks",
1489 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
1490 &hkFreelanceSymlinks) == ERROR_SUCCESS) {
1492 RegQueryInfoKey( hkFreelanceSymlinks,
1494 NULL, /* lpcClass */
1495 NULL, /* lpReserved */
1496 NULL, /* lpcSubKeys */
1497 NULL, /* lpcMaxSubKeyLen */
1498 NULL, /* lpcMaxClassLen */
1499 &dwSymlinks, /* lpcValues */
1500 NULL, /* lpcMaxValueNameLen */
1501 NULL, /* lpcMaxValueLen */
1502 NULL, /* lpcbSecurityDescriptor */
1503 NULL /* lpftLastWriteTime */
1506 for ( dwIndex = 0; dwIndex < dwSymlinks; dwIndex++ ) {
1507 TCHAR szValueName[16];
1508 DWORD dwValueSize = 16;
1509 dwSize = sizeof(line);
1510 RegEnumValue( hkFreelanceSymlinks, dwIndex, szValueName, &dwValueSize, NULL,
1511 &dwType, line, &dwSize);
1513 cp=strchr(line, ':');
1514 memcpy(shortname, line, cp-line);
1515 shortname[cp-line]=0;
1517 if (!strcmp(shortname, toremove)) {
1518 RegDeleteValue( hkFreelanceSymlinks, szValueName );
1523 RegCloseKey(hkFreelanceSymlinks);
1527 /* Do this while we are holding the lock */
1528 cm_noteLocalMountPointChange(TRUE);
1530 lock_ReleaseMutex(&cm_Freelance_Lock);
1531 return (found ? 0 : CM_ERROR_NOSUCHFILE);
1535 cm_FreelanceFetchMountPointString(cm_scache_t *scp)
1537 lock_ObtainMutex(&cm_Freelance_Lock);
1538 if (scp->mpDataVersion != scp->dataVersion &&
1539 scp->fid.cell == AFS_FAKE_ROOT_CELL_ID &&
1540 scp->fid.volume == AFS_FAKE_ROOT_VOL_ID &&
1541 (afs_int32)(scp->fid.unique - cm_data.fakeUnique) - 1 >= 0 &&
1542 scp->fid.unique - cm_data.fakeUnique <= cm_noLocalMountPoints) {
1543 strncpy(scp->mountPointStringp, cm_localMountPoints[scp->fid.unique-cm_data.fakeUnique-1].mountPointStringp, MOUNTPOINTLEN);
1544 scp->mountPointStringp[MOUNTPOINTLEN-1] = 0; /* null terminate */
1545 scp->mpDataVersion = scp->dataVersion;
1547 lock_ReleaseMutex(&cm_Freelance_Lock);
1553 cm_FreelanceFetchFileType(cm_scache_t *scp)
1555 lock_ObtainMutex(&cm_Freelance_Lock);
1556 if (scp->fid.cell == AFS_FAKE_ROOT_CELL_ID &&
1557 scp->fid.volume == AFS_FAKE_ROOT_VOL_ID &&
1558 (afs_int32)(scp->fid.unique - cm_data.fakeUnique) - 1 >= 0 &&
1559 scp->fid.unique - cm_data.fakeUnique <= cm_noLocalMountPoints)
1561 scp->fileType = cm_localMountPoints[scp->fid.unique-cm_data.fakeUnique-1].fileType;
1563 if (scp->fileType == CM_SCACHETYPE_SYMLINK &&
1564 !strnicmp(cm_localMountPoints[scp->fid.unique-cm_data.fakeUnique-1].mountPointStringp, "msdfs:", strlen("msdfs:")) )
1566 scp->fileType = CM_SCACHETYPE_DFSLINK;
1569 scp->fileType = CM_SCACHETYPE_INVALID;
1571 lock_ReleaseMutex(&cm_Freelance_Lock);
1575 #endif /* AFS_FREELANCE_CLIENT */