12 #include <WINNT/afsreg.h>
16 #ifdef AFS_FREELANCE_CLIENT
17 #include "cm_freelance.h"
19 #define STRSAFE_NO_DEPRECATE
22 extern void afsi_log(char *pattern, ...);
24 static unsigned int cm_noLocalMountPoints = 0;
25 char * cm_FakeRootDir = NULL;
26 int cm_fakeDirSize = 0;
27 static cm_localMountPoint_t* cm_localMountPoints;
28 osi_mutex_t cm_Freelance_Lock;
29 static int cm_localMountPointChangeFlag = 0;
30 int cm_freelanceEnabled = 1;
31 int cm_freelanceImportCellServDB = 0;
32 time_t FakeFreelanceModTime = 0x3b49f6e2;
34 static int freelance_ShutdownFlag = 0;
35 static HANDLE hFreelanceChangeEvent = 0;
36 static HANDLE hFreelanceSymlinkChangeEvent = 0;
38 void cm_InitFakeRootDir();
40 void cm_FreelanceChangeNotifier(void * parmp) {
43 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
44 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance",
47 &hkFreelance) == ERROR_SUCCESS) {
49 hFreelanceChangeEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
50 if (hFreelanceChangeEvent == NULL) {
51 RegCloseKey(hkFreelance);
57 /* check hFreelanceChangeEvent to see if it is set.
58 * if so, call cm_noteLocalMountPointChange()
60 if (RegNotifyChangeKeyValue( hkFreelance, /* hKey */
61 FALSE, /* bWatchSubtree */
62 REG_NOTIFY_CHANGE_LAST_SET, /* dwNotifyFilter */
63 hFreelanceChangeEvent, /* hEvent */
64 TRUE /* fAsynchronous */
66 RegCloseKey(hkFreelance);
67 CloseHandle(hFreelanceChangeEvent);
68 hFreelanceChangeEvent = 0;
72 if (WaitForSingleObject(hFreelanceChangeEvent, INFINITE) == WAIT_OBJECT_0)
74 if (freelance_ShutdownFlag == 1) {
75 RegCloseKey(hkFreelance);
76 CloseHandle(hFreelanceChangeEvent);
77 hFreelanceChangeEvent = 0;
80 cm_noteLocalMountPointChange(FALSE);
85 void cm_FreelanceSymlinkChangeNotifier(void * parmp) {
88 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
89 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance\\Symlinks",
92 &hkFreelance) == ERROR_SUCCESS) {
94 hFreelanceSymlinkChangeEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
95 if (hFreelanceSymlinkChangeEvent == NULL) {
96 RegCloseKey(hkFreelance);
102 /* check hFreelanceSymlinkChangeEvent to see if it is set.
103 * if so, call cm_noteLocalMountPointSymlinkChange()
105 if (RegNotifyChangeKeyValue( hkFreelance, /* hKey */
106 FALSE, /* bWatchSubtree */
107 REG_NOTIFY_CHANGE_LAST_SET, /* dwNotifyFilter */
108 hFreelanceSymlinkChangeEvent, /* hEvent */
109 TRUE /* fAsynchronous */
110 ) != ERROR_SUCCESS) {
111 RegCloseKey(hkFreelance);
112 CloseHandle(hFreelanceSymlinkChangeEvent);
113 hFreelanceSymlinkChangeEvent = 0;
117 if (WaitForSingleObject(hFreelanceSymlinkChangeEvent, INFINITE) == WAIT_OBJECT_0)
119 if (freelance_ShutdownFlag == 1) {
120 RegCloseKey(hkFreelance);
121 CloseHandle(hFreelanceSymlinkChangeEvent);
122 hFreelanceSymlinkChangeEvent = 0;
125 cm_noteLocalMountPointChange(FALSE);
131 cm_FreelanceShutdown(void)
133 freelance_ShutdownFlag = 1;
134 if (hFreelanceChangeEvent != 0)
135 thrd_SetEvent(hFreelanceChangeEvent);
136 if (hFreelanceSymlinkChangeEvent != 0)
137 thrd_SetEvent(hFreelanceSymlinkChangeEvent);
141 cm_FreelanceAddCSDBMountPoints(void *rockp, char *cellNamep)
143 char szCellName[CELL_MAXNAMELEN+1] = ".";
145 cm_FsStrCpy( &szCellName[1], CELL_MAXNAMELEN, cellNamep);
146 /* create readonly mount point */
147 cm_FreelanceAddMount( cellNamep, cellNamep, "root.cell", 0, NULL);
149 /* create read/write mount point */
150 cm_FreelanceAddMount( szCellName, szCellName, "root.cell", 1, NULL);
156 cm_FreelanceImportCellServDB(void)
158 cm_EnumerateCellRegistry( TRUE, cm_FreelanceAddCSDBMountPoints, NULL);
159 cm_EnumerateCellFile( TRUE, cm_FreelanceAddCSDBMountPoints, NULL);
162 void cm_InitFreelance() {
166 lock_InitializeMutex(&cm_Freelance_Lock, "Freelance Lock", LOCK_HIERARCHY_FREELANCE_GLOBAL);
168 lock_ObtainMutex(&cm_Freelance_Lock);
170 // yj: first we make a call to cm_initLocalMountPoints
171 // to read all the local mount points from the registry
172 cm_InitLocalMountPoints();
174 // then we make a call to InitFakeRootDir to create
175 // a fake root directory based on the local mount points
176 cm_InitFakeRootDir();
178 // increment the fakeDirVersion to force status updates for
179 // all cached Freelance objects
180 cm_data.fakeDirVersion++;
181 // --- end of yj code
182 lock_ReleaseMutex(&cm_Freelance_Lock);
184 /* Start the registry monitor */
185 phandle = thrd_Create(NULL, 65536, (ThreadFunc) cm_FreelanceChangeNotifier,
186 NULL, 0, &lpid, "cm_FreelanceChangeNotifier");
187 osi_assertx(phandle != NULL, "cm_FreelanceChangeNotifier thread create failure");
188 thrd_CloseHandle(phandle);
190 phandle = thrd_Create(NULL, 65536, (ThreadFunc) cm_FreelanceSymlinkChangeNotifier,
191 NULL, 0, &lpid, "cm_FreelanceSymlinkChangeNotifier");
192 osi_assertx(phandle != NULL, "cm_FreelanceSymlinkChangeNotifier thread create failure");
193 thrd_CloseHandle(phandle);
196 /* yj: Initialization of the fake root directory */
197 /* to be called while holding freelance lock. */
198 void cm_InitFakeRootDir() {
203 // allocate space for the fake info
204 cm_dirHeader_t fakeDirHeader;
205 cm_dirEntry_t fakeEntry;
206 cm_pageHeader_t fakePageHeader;
208 // i'm going to calculate how much space is needed for
209 // this fake root directory. we have these rules:
210 // 1. there are cm_noLocalMountPoints number of entries
211 // 2. each page is CM_DIR_PAGESIZE in size
212 // 3. the first 13 chunks of the first page are used for
214 // 4. the first chunk of all subsequent pages are used
215 // for page header stuff
216 // 5. a max of CM_DIR_EPP entries are allowed per page
217 // 6. each entry takes 1 or more chunks, depending on
218 // the size of the mount point string, as determined
220 // 7. each chunk is CM_DIR_CHUNKSIZE bytes
222 int CPP = CM_DIR_PAGESIZE / CM_DIR_CHUNKSIZE;
223 int curChunk = 13; // chunks 0 - 12 are used for header stuff
224 // of the first page in the directory
226 unsigned int curDirEntry = 0;
227 int curDirEntryInPage = 0;
231 /* Reserve 2 directory chunks for "." and ".." */
234 while (curDirEntry<cm_noLocalMountPoints) {
235 sizeOfCurEntry = cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0);
236 if ((curChunk + sizeOfCurEntry >= CPP) ||
237 (curDirEntryInPage + 1 >= CM_DIR_EPP)) {
239 curDirEntryInPage = 0;
242 curChunk += sizeOfCurEntry;
247 dirSize = (curPage+1) * CM_DIR_PAGESIZE;
248 if (cm_fakeDirSize != dirSize) {
250 free(cm_FakeRootDir);
251 cm_FakeRootDir = calloc(dirSize, 1);
252 cm_fakeDirSize = dirSize;
255 // yj: when we get here, we've figured out how much memory we need and
256 // allocated the appropriate space for it. we now prceed to fill
257 // it up with entries.
260 curDirEntryInPage = 0;
263 // fields in the directory entry that are unused.
265 fakeEntry.length = 0;
267 fakeEntry.fid.unique = htonl(1);
269 // the first page is special, it uses fakeDirHeader instead of fakePageHeader
270 // we fill up the page with dirEntries that belong there and we make changes
271 // to the fakeDirHeader.header.freeBitmap along the way. Then when we're done
272 // filling up the dirEntries in this page, we copy the fakeDirHeader into
273 // the top of the page.
275 // init the freeBitmap array
277 fakeDirHeader.header.freeBitmap[i]=0;
279 fakeDirHeader.header.freeBitmap[0] = 0xff;
280 fakeDirHeader.header.freeBitmap[1] = 0x7f;
283 // we start counting at 13 because the 0th to 12th chunks are used for header
286 // stick the first 2 entries "." and ".." in
287 fakeEntry.fid.vnode = htonl(1);
288 strcpy(fakeEntry.name, ".");
289 currentPos = cm_FakeRootDir + curPage * CM_DIR_PAGESIZE + curChunk * CM_DIR_CHUNKSIZE;
290 memcpy(currentPos, &fakeEntry, CM_DIR_CHUNKSIZE);
291 curChunk++; curDirEntryInPage++;
292 strcpy(fakeEntry.name, "..");
293 currentPos = cm_FakeRootDir + curPage * CM_DIR_PAGESIZE + curChunk * CM_DIR_CHUNKSIZE;
294 memcpy(currentPos, &fakeEntry, CM_DIR_CHUNKSIZE);
295 curChunk++; curDirEntryInPage++;
297 // keep putting stuff into page 0 if
298 // 1. we're not done with all entries
299 // 2. we have less than CM_DIR_EPP entries in page 0
300 // 3. we're not out of chunks in page 0
302 while( (curDirEntry<cm_noLocalMountPoints) &&
303 (curDirEntryInPage < CM_DIR_EPP) &&
304 (curChunk + cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0) <= CPP))
307 noChunks = cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0);
308 /* enforce the rule that only directories have odd vnode values */
309 fakeEntry.fid.vnode = htonl((curDirEntry + 1) * 2);
310 fakeEntry.fid.unique = htonl(curDirEntry + 1);
311 currentPos = cm_FakeRootDir + curPage * CM_DIR_PAGESIZE + curChunk * CM_DIR_CHUNKSIZE;
313 memcpy(currentPos, &fakeEntry, CM_DIR_CHUNKSIZE);
314 strcpy(currentPos + 12, (cm_localMountPoints+curDirEntry)->namep);
317 for (i=0; i<noChunks; i++) {
318 t1 = (curChunk + i) / 8;
319 t2 = curChunk + i - (t1*8);
320 fakeDirHeader.header.freeBitmap[t1] |= (1 << t2);
325 // when we get here, we're done with filling in the entries for page 0
326 // copy in the header info
328 memcpy(cm_FakeRootDir, &fakeDirHeader, 13 * CM_DIR_CHUNKSIZE);
332 // ok, page 0's done. Move on to the next page.
333 while (curDirEntry<cm_noLocalMountPoints) {
335 curChunk = 1; // the zeroth chunk is reserved for page header
336 curDirEntryInPage = 0;
337 for (i=0; i<8; i++) {
338 fakePageHeader.freeBitmap[i]=0;
340 fakePageHeader.freeCount = 0;
341 fakePageHeader.pgcount = 0;
342 fakePageHeader.tag = htons(1234);
344 // while we're on the same page...
345 while ( (curDirEntry<cm_noLocalMountPoints) &&
346 (curDirEntryInPage < CM_DIR_EPP) &&
347 (curChunk + cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0) <= CPP))
349 // add an entry to this page
351 noChunks = cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0);
352 /* enforce the rule that only directories have odd vnode values */
353 fakeEntry.fid.vnode = htonl((curDirEntry + 1) * 2);
354 fakeEntry.fid.unique = htonl(curDirEntry + 1);
355 currentPos = cm_FakeRootDir + curPage * CM_DIR_PAGESIZE + curChunk * CM_DIR_CHUNKSIZE;
356 memcpy(currentPos, &fakeEntry, CM_DIR_CHUNKSIZE);
357 strcpy(currentPos + 12, (cm_localMountPoints+curDirEntry)->namep);
360 for (i=0; i<noChunks; i++) {
361 t1 = (curChunk + i) / 8;
362 t2 = curChunk + i - (t1*8);
363 fakePageHeader.freeBitmap[t1] |= (1 << t2);
367 memcpy(cm_FakeRootDir + curPage * CM_DIR_PAGESIZE, &fakePageHeader, sizeof(fakePageHeader));
372 // we know the fakeDir is setup properly, so we claim that we have callback
373 osi_Log0(afsd_logp,"cm_InitFakeRootDir completed!");
375 // when we get here, we've set up everything! done!
378 int cm_FakeRootFid(cm_fid_t *fidp)
381 AFS_FAKE_ROOT_CELL_ID, /* root cell */
382 AFS_FAKE_ROOT_VOL_ID, /* root.afs ? */
387 /* called directly from ioctl */
388 /* called while not holding freelance lock */
389 int cm_noteLocalMountPointChange(afs_int32 locked) {
391 lock_ObtainMutex(&cm_Freelance_Lock);
392 cm_data.fakeDirVersion++;
393 cm_localMountPointChangeFlag = 1;
395 lock_ReleaseMutex(&cm_Freelance_Lock);
399 int cm_getLocalMountPointChange() {
400 return cm_localMountPointChangeFlag;
403 int cm_clearLocalMountPointChange() {
404 cm_localMountPointChangeFlag = 0;
408 int cm_reInitLocalMountPoints() {
410 unsigned int i, hash;
411 cm_scache_t *scp, **lscpp, *tscp;
416 osi_Log0(afsd_logp,"----- freelance reinitialization starts ----- ");
418 // first we invalidate all the SCPs that were created
419 // for the local mount points
421 osi_Log0(afsd_logp,"Invalidating local mount point scp... ");
423 lock_ObtainWrite(&cm_scacheLock);
424 lock_ObtainMutex(&cm_Freelance_Lock); /* always scache then freelance lock */
425 for (i=0; i<=cm_noLocalMountPoints; i++) {
427 cm_SetFid(&aFid, AFS_FAKE_ROOT_CELL_ID, AFS_FAKE_ROOT_VOL_ID, 1, 1);
429 cm_SetFid(&aFid, AFS_FAKE_ROOT_CELL_ID, AFS_FAKE_ROOT_VOL_ID, i*2, i);
430 hash = CM_SCACHE_HASH(&aFid);
431 for (scp=cm_data.scacheHashTablep[hash]; scp; scp=scp->nextp) {
432 if (scp != cm_data.rootSCachep && cm_FidCmp(&scp->fid, &aFid) == 0) {
433 // mark the scp to be reused
434 cm_HoldSCacheNoLock(scp);
435 lock_ReleaseMutex(&cm_Freelance_Lock);
436 lock_ReleaseWrite(&cm_scacheLock);
437 lock_ObtainWrite(&scp->rw);
438 cm_DiscardSCache(scp);
440 // take the scp out of the hash
441 lock_ObtainWrite(&cm_scacheLock);
442 for (lscpp = &cm_data.scacheHashTablep[hash], tscp = cm_data.scacheHashTablep[hash];
444 lscpp = &tscp->nextp, tscp = tscp->nextp) {
448 scp->flags &= ~CM_SCACHEFLAG_INHASH;
453 lock_ReleaseWrite(&scp->rw);
454 lock_ReleaseWrite(&cm_scacheLock);
455 cm_CallbackNotifyChange(scp);
456 lock_ObtainWrite(&cm_scacheLock);
457 cm_ReleaseSCacheNoLock(scp);
458 lock_ObtainMutex(&cm_Freelance_Lock);
462 lock_ReleaseWrite(&cm_scacheLock);
463 lock_ReleaseMutex(&cm_Freelance_Lock);
464 osi_Log0(afsd_logp,"\tall old scp cleared!");
466 lock_ObtainWrite(&cm_data.rootSCachep->rw);
467 lock_ObtainMutex(&cm_Freelance_Lock);
468 // we must free the memory that was allocated in the prev
469 // cm_InitLocalMountPoints call
470 osi_Log0(afsd_logp,"Removing old localmountpoints... ");
471 free(cm_localMountPoints);
472 cm_localMountPoints = NULL;
473 cm_noLocalMountPoints = 0;
474 osi_Log0(afsd_logp,"\tall old localmountpoints cleared!");
476 // now re-init the localmountpoints
477 osi_Log0(afsd_logp,"Creating new localmountpoints... ");
478 cm_InitLocalMountPoints();
479 osi_Log0(afsd_logp,"\tcreated new set of localmountpoints!");
481 // then we re-create that dir
482 osi_Log0(afsd_logp,"Creating new fakedir... ");
483 cm_InitFakeRootDir();
484 osi_Log0(afsd_logp,"\t\tcreated new fakedir!");
486 lock_ReleaseMutex(&cm_Freelance_Lock);
488 cm_GetCallback(cm_data.rootSCachep, cm_rootUserp, &req, 0);
489 lock_ReleaseWrite(&cm_data.rootSCachep->rw);
491 osi_Log0(afsd_logp,"----- freelance reinit complete -----");
496 * cm_enforceTrailingDot
498 * return 0 on failure, non-zero on success
502 cm_enforceTrailingDot(char * line, size_t cchLine, DWORD *pdwSize)
504 /* trailing white space first. */
505 if (line[(*pdwSize)-1] == '\0') {
506 while (isspace(line[(*pdwSize)-2])) {
507 line[(*pdwSize)-2] = '\0';
511 while (isspace(line[(*pdwSize)-1])) {
512 line[(*pdwSize)-1] = '\0';
517 /* then enforce the trailing dot requirement */
518 if (line[(*pdwSize)-1] == '\0' && line[(*pdwSize)-2] != '.') {
519 if ((*pdwSize) >= cchLine) {
520 afsi_log("no room for trailing dot");
523 line[(*pdwSize)-1] = '.';
524 line[(*pdwSize)] = '\0';
525 } else if (line[(*pdwSize)-1] != '\0' && line[(*pdwSize)-1] != '.') {
526 if ((*pdwSize) >= cchLine) {
527 afsi_log("no room for trailing dot and nul");
530 line[(*pdwSize)] = '.';
531 line[(*pdwSize)+1] = '\0';
532 } else if (line[(*pdwSize)-1] != '\0') {
533 if ((*pdwSize) >= cchLine) {
534 afsi_log("no room for trailing nul");
537 line[(*pdwSize)] = '\0';
543 // yj: open up the registry and read all the local mount
544 // points that are stored there. Part of the initialization
545 // process for the freelance client.
546 /* to be called while holding freelance lock. */
547 long cm_InitLocalMountPoints() {
552 cm_localMountPoint_t* aLocalMountPoint;
555 char rootCellName[256];
556 HKEY hkFreelance = 0, hkFreelanceSymlinks = 0;
557 DWORD dwType, dwSize;
558 DWORD dwMountPoints = 0;
560 DWORD dwSymlinks = 0;
561 FILETIME ftLastWriteTime;
563 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
564 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance",
566 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
567 &hkFreelance) == ERROR_SUCCESS) {
569 RegQueryInfoKey( hkFreelance,
572 NULL, /* lpReserved */
573 NULL, /* lpcSubKeys */
574 NULL, /* lpcMaxSubKeyLen */
575 NULL, /* lpcMaxClassLen */
576 &dwMountPoints, /* lpcValues */
577 NULL, /* lpcMaxValueNameLen */
578 NULL, /* lpcMaxValueLen */
579 NULL, /* lpcbSecurityDescriptor */
580 &ftLastWriteTime /* lpftLastWriteTime */
583 cm_UnixTimeFromLargeSearchTime(&FakeFreelanceModTime, &ftLastWriteTime);
585 if ( dwMountPoints == 0 ) {
586 rootCellName[0] = '.';
587 code = cm_GetRootCellName(&rootCellName[1]);
589 lock_ReleaseMutex(&cm_Freelance_Lock);
590 cm_FreelanceAddMount(&rootCellName[1], &rootCellName[1], "root.cell.", 0, NULL);
591 cm_FreelanceAddMount(rootCellName, &rootCellName[1], "root.cell.", 1, NULL);
592 cm_FreelanceAddMount(".root", &rootCellName[1], "root.afs.", 1, NULL);
593 lock_ObtainMutex(&cm_Freelance_Lock);
598 if (RegCreateKeyEx( HKEY_LOCAL_MACHINE,
599 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance\\Symlinks",
602 REG_OPTION_NON_VOLATILE,
603 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
605 &hkFreelanceSymlinks,
606 NULL) == ERROR_SUCCESS) {
608 RegQueryInfoKey( hkFreelanceSymlinks,
611 NULL, /* lpReserved */
612 NULL, /* lpcSubKeys */
613 NULL, /* lpcMaxSubKeyLen */
614 NULL, /* lpcMaxClassLen */
615 &dwSymlinks, /* lpcValues */
616 NULL, /* lpcMaxValueNameLen */
617 NULL, /* lpcMaxValueLen */
618 NULL, /* lpcbSecurityDescriptor */
619 NULL /* lpftLastWriteTime */
623 // get the number of entries there are from the first line
625 cm_noLocalMountPoints = dwMountPoints + dwSymlinks;
627 // create space to store the local mount points
628 cm_localMountPoints = malloc(sizeof(cm_localMountPoint_t) * cm_noLocalMountPoints);
629 aLocalMountPoint = cm_localMountPoints;
631 // now we read n lines and parse them into local mount points
632 // where n is the number of local mount points there are, as
634 // Each line in the ini file represents 1 local mount point and
635 // is in the format xxx#yyy:zzz, where xxx is the directory
636 // entry name, yyy is the cell name and zzz is the volume name.
637 // #yyy:zzz together make up the mount point.
638 for ( dwIndex = 0 ; dwIndex < dwMountPoints; dwIndex++ ) {
639 TCHAR szValueName[16];
640 DWORD dwValueSize = 16;
641 dwSize = sizeof(line);
642 if (RegEnumValue( hkFreelance, dwIndex, szValueName, &dwValueSize, NULL,
643 &dwType, line, &dwSize))
645 afsi_log("RegEnumValue(hkFreelance) failed");
646 cm_noLocalMountPoints--;
650 /* make sure there is a trailing dot and a nul terminator */
651 if (!cm_enforceTrailingDot(line, sizeof(line), &dwSize)) {
652 cm_noLocalMountPoints--;
656 afsi_log("Mountpoint[%d] = %s", dwIndex, line);
658 for ( t=line;*t;t++ ) {
659 if ( !isprint(*t) ) {
660 afsi_log("error occurred while parsing mountpoint entry [%d]: non-printable character", dwIndex);
661 fprintf(stderr, "error occurred while parsing mountpoint entry [%d]: non-printable character", dwIndex);
662 cm_noLocalMountPoints--;
667 // line is not empty, so let's parse it
668 t = strchr(line, '#');
670 t = strchr(line, '%');
671 // make sure that there is a '#' or '%' separator in the line
673 afsi_log("error occurred while parsing mountpoint entry [%d]: no # or %% separator", dwIndex);
674 fprintf(stderr, "error occurred while parsing mountpoint entry [%d]: no # or %% separator", dwIndex);
675 cm_noLocalMountPoints--;
679 aLocalMountPoint->fileType = CM_SCACHETYPE_MOUNTPOINT;
680 aLocalMountPoint->namep=malloc(t-line+1);
681 strncpy(aLocalMountPoint->namep, line, t-line);
682 aLocalMountPoint->namep[t-line] = '\0';
684 /* copy the mount point string */
685 aLocalMountPoint->mountPointStringp=malloc(strlen(t));
686 strncpy(aLocalMountPoint->mountPointStringp, t, strlen(t)-1);
687 aLocalMountPoint->mountPointStringp[strlen(t)-1] = '\0';
689 osi_Log2(afsd_logp,"found mount point: name %s, string %s",
690 osi_LogSaveString(afsd_logp,aLocalMountPoint->namep),
691 osi_LogSaveString(afsd_logp,aLocalMountPoint->mountPointStringp));
696 for ( dwIndex = 0 ; dwIndex < dwSymlinks; dwIndex++ ) {
697 TCHAR szValueName[16];
698 DWORD dwValueSize = 16;
699 dwSize = sizeof(line);
700 if (RegEnumValue( hkFreelanceSymlinks, dwIndex, szValueName, &dwValueSize, NULL,
701 &dwType, line, &dwSize))
703 afsi_log("RegEnumValue(hkFreelanceSymlinks) failed");
704 cm_noLocalMountPoints--;
708 /* make sure there is a trailing dot and a nul terminator */
709 if (!cm_enforceTrailingDot(line, sizeof(line), &dwSize)) {
710 cm_noLocalMountPoints--;
714 afsi_log("Symlink[%d] = %s", dwIndex, line);
716 for ( t=line;*t;t++ ) {
717 if ( !isprint(*t) ) {
718 afsi_log("error occurred while parsing symlink entry [%d]: non-printable character", dwIndex);
719 fprintf(stderr, "error occurred while parsing symlink entry [%d]: non-printable character", dwIndex);
720 cm_noLocalMountPoints--;
725 // line is not empty, so let's parse it
726 t = strchr(line, ':');
728 // make sure that there is a ':' separator in the line
730 afsi_log("error occurred while parsing symlink entry [%d]: no ':' separator", dwIndex);
731 fprintf(stderr, "error occurred while parsing symlink entry [%d]: no ':' separator", dwIndex);
732 cm_noLocalMountPoints--;
736 aLocalMountPoint->fileType = CM_SCACHETYPE_SYMLINK;
737 aLocalMountPoint->namep=malloc(t-line+1);
738 strncpy(aLocalMountPoint->namep, line, t-line);
739 aLocalMountPoint->namep[t-line] = '\0';
741 /* copy the symlink string */
742 aLocalMountPoint->mountPointStringp=malloc(strlen(t)-1);
743 strncpy(aLocalMountPoint->mountPointStringp, t+1, strlen(t)-2);
744 aLocalMountPoint->mountPointStringp[strlen(t)-2] = '\0';
746 osi_Log2(afsd_logp,"found symlink: name %s, string %s",
747 osi_LogSaveString(afsd_logp,aLocalMountPoint->namep),
748 osi_LogSaveString(afsd_logp,aLocalMountPoint->mountPointStringp));
753 if ( hkFreelanceSymlinks )
754 RegCloseKey( hkFreelanceSymlinks );
755 RegCloseKey(hkFreelance);
759 /* What follows is the old code to read freelance mount points
760 * out of a text file modified to copy the data into the registry
762 cm_GetConfigDir(hdir, sizeof(hdir));
763 strcat(hdir, AFS_FREELANCE_INI);
764 // open the ini file for reading
765 fp = fopen(hdir, "r");
767 /* look in the Windows directory where we used to store the file */
768 GetWindowsDirectory(hdir, sizeof(hdir));
770 strcat(hdir, AFS_FREELANCE_INI);
771 fp = fopen(hdir, "r");
774 RegCreateKeyEx( HKEY_LOCAL_MACHINE,
775 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance",
778 REG_OPTION_NON_VOLATILE,
786 RegCloseKey(hkFreelance);
787 rootCellName[0] = '.';
788 code = cm_GetRootCellName(&rootCellName[1]);
790 lock_ReleaseMutex(&cm_Freelance_Lock);
791 cm_FreelanceAddMount(&rootCellName[1], &rootCellName[1], "root.cell.", 0, NULL);
792 cm_FreelanceAddMount(rootCellName, &rootCellName[1], "root.cell.", 1, NULL);
793 cm_FreelanceAddMount(".root", &rootCellName[1], "root.afs.", 1, NULL);
794 lock_ObtainMutex(&cm_Freelance_Lock);
799 // we successfully opened the file
800 osi_Log0(afsd_logp,"opened afs_freelance.ini");
802 // now we read the first line to see how many entries
804 fgets(line, sizeof(line), fp);
806 // if the line is empty at any point when we're reading
807 // we're screwed. report error and return.
809 afsi_log("error occurred while reading afs_freelance.ini");
810 fprintf(stderr, "error occurred while reading afs_freelance.ini");
814 // get the number of entries there are from the first line
816 cm_noLocalMountPoints = atoi(line);
818 if (cm_noLocalMountPoints > 0) {
819 // create space to store the local mount points
820 cm_localMountPoints = malloc(sizeof(cm_localMountPoint_t) * cm_noLocalMountPoints);
821 aLocalMountPoint = cm_localMountPoints;
824 // now we read n lines and parse them into local mount points
825 // where n is the number of local mount points there are, as
827 // Each line in the ini file represents 1 local mount point and
828 // is in the format xxx#yyy:zzz, where xxx is the directory
829 // entry name, yyy is the cell name and zzz is the volume name.
830 // #yyy:zzz together make up the mount point.
831 for (i=0; i<cm_noLocalMountPoints; i++) {
832 fgets(line, sizeof(line), fp);
833 // check that the line is not empty
835 afsi_log("error occurred while parsing entry in %s: empty line in line %d", AFS_FREELANCE_INI, i);
836 fprintf(stderr, "error occurred while parsing entry in afs_freelance.ini: empty line in line %d", i);
840 /* find the trailing dot; null terminate after it */
841 t2 = strrchr(line, '.');
847 /* we are migrating to the registry */
848 sprintf(szIndex,"%d",dwIndex++);
850 dwSize = (DWORD)strlen(line) + 1;
851 RegSetValueEx( hkFreelance, szIndex, 0, dwType, line, dwSize);
854 // line is not empty, so let's parse it
855 t = strchr(line, '#');
857 t = strchr(line, '%');
858 // make sure that there is a '#' or '%' separator in the line
860 afsi_log("error occurred while parsing entry in %s: no # or %% separator in line %d", AFS_FREELANCE_INI, i);
861 fprintf(stderr, "error occurred while parsing entry in afs_freelance.ini: no # or %% separator in line %d", i);
864 aLocalMountPoint->namep=malloc(t-line+1);
865 memcpy(aLocalMountPoint->namep, line, t-line);
866 *(aLocalMountPoint->namep + (t-line)) = 0;
868 aLocalMountPoint->mountPointStringp=malloc(strlen(line) - (t-line) + 1);
869 memcpy(aLocalMountPoint->mountPointStringp, t, strlen(line)-(t-line)-1);
870 *(aLocalMountPoint->mountPointStringp + (strlen(line)-(t-line)-1)) = 0;
872 osi_Log2(afsd_logp,"found mount point: name %s, string %s",
873 aLocalMountPoint->namep,
874 aLocalMountPoint->mountPointStringp);
880 RegCloseKey(hkFreelance);
886 int cm_getNoLocalMountPoints() {
887 return cm_noLocalMountPoints;
890 long cm_FreelanceMountPointExists(char * filename, int prefix_ok)
896 HKEY hkFreelance = 0;
897 DWORD dwType, dwSize;
901 lock_ObtainMutex(&cm_Freelance_Lock);
903 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
904 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance",
906 KEY_READ|KEY_QUERY_VALUE,
907 &hkFreelance) == ERROR_SUCCESS)
909 RegQueryInfoKey( hkFreelance,
912 NULL, /* lpReserved */
913 NULL, /* lpcSubKeys */
914 NULL, /* lpcMaxSubKeyLen */
915 NULL, /* lpcMaxClassLen */
916 &dwMountPoints, /* lpcValues */
917 NULL, /* lpcMaxValueNameLen */
918 NULL, /* lpcMaxValueLen */
919 NULL, /* lpcbSecurityDescriptor */
920 NULL /* lpftLastWriteTime */
923 for ( dwIndex = 0; dwIndex < dwMountPoints; dwIndex++ ) {
924 TCHAR szValueName[16];
925 DWORD dwValueSize = 16;
926 dwSize = sizeof(line);
927 RegEnumValue( hkFreelance, dwIndex, szValueName, &dwValueSize, NULL,
928 &dwType, line, &dwSize);
930 cp=strchr(line, '#');
932 cp=strchr(line, '%');
933 memcpy(shortname, line, cp-line);
934 shortname[cp-line]=0;
936 if (!strcmp(shortname, filename)) {
941 for ( dwIndex = 0; dwIndex < dwMountPoints; dwIndex++ ) {
942 TCHAR szValueName[16];
943 DWORD dwValueSize = 16;
944 dwSize = sizeof(line);
945 RegEnumValue( hkFreelance, dwIndex, szValueName, &dwValueSize, NULL,
946 &dwType, line, &dwSize);
948 cp=strchr(line, '#');
950 cp=strchr(line, '%');
951 memcpy(shortname, line, cp-line);
952 shortname[cp-line]=0;
954 if (!cm_stricmp_utf8(shortname, filename)) {
959 if (prefix_ok && strlen(shortname) - strlen(filename) == 1 && !strncmp(shortname, filename, strlen(filename))) {
964 RegCloseKey(hkFreelance);
967 lock_ReleaseMutex(&cm_Freelance_Lock);
972 long cm_FreelanceSymlinkExists(char * filename, int prefix_ok)
978 HKEY hkFreelance = 0;
979 DWORD dwType, dwSize;
983 lock_ObtainMutex(&cm_Freelance_Lock);
985 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
986 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance\\Symlinks",
988 KEY_READ|KEY_QUERY_VALUE,
989 &hkFreelance) == ERROR_SUCCESS)
991 RegQueryInfoKey( hkFreelance,
994 NULL, /* lpReserved */
995 NULL, /* lpcSubKeys */
996 NULL, /* lpcMaxSubKeyLen */
997 NULL, /* lpcMaxClassLen */
998 &dwSymlinks, /* lpcValues */
999 NULL, /* lpcMaxValueNameLen */
1000 NULL, /* lpcMaxValueLen */
1001 NULL, /* lpcbSecurityDescriptor */
1002 NULL /* lpftLastWriteTime */
1005 for ( dwIndex = 0; dwIndex < dwSymlinks; dwIndex++ ) {
1006 TCHAR szValueName[16];
1007 DWORD dwValueSize = 16;
1008 dwSize = sizeof(line);
1009 RegEnumValue( hkFreelance, dwIndex, szValueName, &dwValueSize, NULL,
1010 &dwType, line, &dwSize);
1012 cp=strchr(line, ':');
1013 memcpy(shortname, line, cp-line);
1014 shortname[cp-line]=0;
1016 if (!strcmp(shortname, filename)) {
1021 if (prefix_ok && strlen(shortname) - strlen(filename) == 1 && !strncmp(shortname, filename, strlen(filename))) {
1026 for ( dwIndex = 0; dwIndex < dwSymlinks; dwIndex++ ) {
1027 TCHAR szValueName[16];
1028 DWORD dwValueSize = 16;
1029 dwSize = sizeof(line);
1030 RegEnumValue( hkFreelance, dwIndex, szValueName, &dwValueSize, NULL,
1031 &dwType, line, &dwSize);
1033 cp=strchr(line, ':');
1034 memcpy(shortname, line, cp-line);
1035 shortname[cp-line]=0;
1037 if (!cm_stricmp_utf8(shortname, filename)) {
1042 RegCloseKey(hkFreelance);
1045 lock_ReleaseMutex(&cm_Freelance_Lock);
1050 long cm_FreelanceAddMount(char *filename, char *cellname, char *volume, int rw, cm_fid_t *fidp)
1055 char fullname[CELL_MAXNAMELEN];
1058 HKEY hkFreelance = 0;
1059 DWORD dwType, dwSize;
1060 DWORD dwMountPoints;
1062 afs_uint32 code = 0;
1064 /* before adding, verify the cell name; if it is not a valid cell,
1065 don't add the mount point.
1066 allow partial matches as a means of poor man's alias. */
1067 /* major performance issue? */
1068 osi_Log4(afsd_logp,"Freelance Add Mount request: filename=%s cellname=%s volume=%s %s",
1069 osi_LogSaveString(afsd_logp,filename),
1070 osi_LogSaveString(afsd_logp,cellname),
1071 osi_LogSaveString(afsd_logp,volume),
1074 if ( filename[0] == '\0' || cellname[0] == '\0' || volume[0] == '\0' )
1075 return CM_ERROR_INVAL;
1077 if ( cm_FreelanceMountPointExists(filename, 0) ||
1078 cm_FreelanceSymlinkExists(filename, 0) ) {
1079 code = CM_ERROR_EXISTS;
1083 if (cellname[0] == '.') {
1084 if (!cm_GetCell_Gen(&cellname[1], fullname, CM_FLAG_CREATE))
1085 return CM_ERROR_INVAL;
1087 if (!cm_GetCell_Gen(cellname, fullname, CM_FLAG_CREATE))
1088 return CM_ERROR_INVAL;
1091 osi_Log1(afsd_logp,"Freelance Adding Mount for Cell: %s",
1092 osi_LogSaveString(afsd_logp,cellname));
1094 lock_ObtainMutex(&cm_Freelance_Lock);
1096 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
1097 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance",
1099 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
1100 &hkFreelance) == ERROR_SUCCESS) {
1102 RegQueryInfoKey( hkFreelance,
1104 NULL, /* lpcClass */
1105 NULL, /* lpReserved */
1106 NULL, /* lpcSubKeys */
1107 NULL, /* lpcMaxSubKeyLen */
1108 NULL, /* lpcMaxClassLen */
1109 &dwMountPoints, /* lpcValues */
1110 NULL, /* lpcMaxValueNameLen */
1111 NULL, /* lpcMaxValueLen */
1112 NULL, /* lpcbSecurityDescriptor */
1113 NULL /* lpftLastWriteTime */
1117 sprintf(line, "%s%%%s:%s", filename, fullname, volume);
1119 sprintf(line, "%s#%s:%s", filename, fullname, volume);
1121 /* If we are adding a new value, there must be an unused name
1122 * within the range 0 to dwMountPoints
1124 for ( dwIndex = 0; dwIndex <= dwMountPoints; dwIndex++ ) {
1128 dwSize = sizeof(szMount);
1129 sprintf(szIndex, "%d", dwIndex);
1130 if (RegQueryValueEx( hkFreelance, szIndex, 0, &dwType, szMount, &dwSize) != ERROR_SUCCESS) {
1131 /* found an unused value */
1133 dwSize = (DWORD)strlen(line) + 1;
1134 RegSetValueEx( hkFreelance, szIndex, 0, dwType, line, dwSize);
1137 int len = (int)strlen(filename);
1138 if ( dwType == REG_SZ && !strncmp(filename, szMount, len) &&
1139 (szMount[len] == '%' || szMount[len] == '#')) {
1140 /* Replace the existing value */
1142 dwSize = (DWORD)strlen(line) + 1;
1143 RegSetValueEx( hkFreelance, szIndex, 0, dwType, line, dwSize);
1148 RegCloseKey(hkFreelance);
1151 cm_GetConfigDir(hfile, sizeof(hfile));
1152 strcat(hfile, AFS_FREELANCE_INI);
1153 fp = fopen(hfile, "r+");
1155 return CM_ERROR_INVAL;
1156 fgets(line, sizeof(line), fp);
1159 fseek(fp, 0, SEEK_SET);
1160 fprintf(fp, "%d", n);
1161 fseek(fp, 0, SEEK_END);
1163 fprintf(fp, "%s%%%s:%s\n", filename, fullname, volume);
1165 fprintf(fp, "%s#%s:%s\n", filename, fullname, volume);
1169 /* Do this while we are holding the lock */
1170 cm_noteLocalMountPointChange(TRUE);
1171 lock_ReleaseMutex(&cm_Freelance_Lock);
1177 clientchar_t *cpath;
1181 cpath = cm_FsStringToClientStringAlloc(filename, -1, NULL);
1183 return CM_ERROR_NOSUCHPATH;
1185 if (cm_getLocalMountPointChange()) { // check for changes
1186 cm_clearLocalMountPointChange(); // clear the changefile
1187 cm_reInitLocalMountPoints(); // start reinit
1190 code = cm_NameI(cm_RootSCachep(cm_rootUserp, &req), cpath,
1191 CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD | CM_FLAG_DFS_REFERRAL,
1192 cm_rootUserp, NULL, &req, &scp);
1197 cm_ReleaseSCache(scp);
1203 long cm_FreelanceRemoveMount(char *toremove)
1208 char shortname[200];
1209 char hfile[260], hfile2[260];
1212 HKEY hkFreelance = 0;
1213 DWORD dwType, dwSize;
1214 DWORD dwMountPoints;
1217 lock_ObtainMutex(&cm_Freelance_Lock);
1219 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
1220 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance",
1222 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
1223 &hkFreelance) == ERROR_SUCCESS) {
1225 RegQueryInfoKey( hkFreelance,
1227 NULL, /* lpcClass */
1228 NULL, /* lpReserved */
1229 NULL, /* lpcSubKeys */
1230 NULL, /* lpcMaxSubKeyLen */
1231 NULL, /* lpcMaxClassLen */
1232 &dwMountPoints, /* lpcValues */
1233 NULL, /* lpcMaxValueNameLen */
1234 NULL, /* lpcMaxValueLen */
1235 NULL, /* lpcbSecurityDescriptor */
1236 NULL /* lpftLastWriteTime */
1239 for ( dwIndex = 0; dwIndex < dwMountPoints; dwIndex++ ) {
1240 TCHAR szValueName[16];
1241 DWORD dwValueSize = 16;
1242 dwSize = sizeof(line);
1243 RegEnumValue( hkFreelance, dwIndex, szValueName, &dwValueSize, NULL,
1244 &dwType, line, &dwSize);
1246 cp=strchr(line, '#');
1248 cp=strchr(line, '%');
1249 memcpy(shortname, line, cp-line);
1250 shortname[cp-line]=0;
1252 if (!strcmp(shortname, toremove)) {
1253 RegDeleteValue( hkFreelance, szValueName );
1258 RegCloseKey(hkFreelance);
1261 cm_GetConfigDir(hfile, sizeof(hfile));
1262 strcat(hfile, AFS_FREELANCE_INI);
1263 strcpy(hfile2, hfile);
1264 strcat(hfile2, "2");
1265 fp1=fopen(hfile, "r+");
1267 return CM_ERROR_INVAL;
1268 fp2=fopen(hfile2, "w+");
1271 return CM_ERROR_INVAL;
1274 fgets(line, sizeof(line), fp1);
1276 fprintf(fp2, "%d\n", n-1);
1278 for (i=0; i<n; i++) {
1279 fgets(line, sizeof(line), fp1);
1280 cp=strchr(line, '#');
1282 cp=strchr(line, '%');
1283 memcpy(shortname, line, cp-line);
1284 shortname[cp-line]=0;
1286 if (strcmp(shortname, toremove)==0) {
1298 rename(hfile2, hfile);
1303 /* Do this while we are holding the lock */
1304 cm_noteLocalMountPointChange(TRUE);
1306 lock_ReleaseMutex(&cm_Freelance_Lock);
1307 return (found ? 0 : CM_ERROR_NOSUCHFILE);
1310 long cm_FreelanceAddSymlink(char *filename, char *destination, cm_fid_t *fidp)
1313 char fullname[CELL_MAXNAMELEN] = "";
1315 HKEY hkFreelanceSymlinks = 0;
1316 DWORD dwType, dwSize;
1319 afs_uint32 code = 0;
1322 * before adding, verify the filename. If it is already in use, either as
1323 * as mount point or a cellname, do not permit the creation of the symlink.
1325 osi_Log2(afsd_logp,"Freelance Add Symlink request: filename=%s destination=%s",
1326 osi_LogSaveString(afsd_logp,filename),
1327 osi_LogSaveString(afsd_logp,destination));
1329 if ( filename[0] == '\0' || destination[0] == '\0' )
1330 return CM_ERROR_INVAL;
1332 /* Do not create the symlink if the name ends in a dot */
1333 if ( filename[strlen(filename)-1] == '.')
1334 return CM_ERROR_INVAL;
1336 if ( cm_FreelanceMountPointExists(filename, 0) ||
1337 cm_FreelanceSymlinkExists(filename, 0) ) {
1338 code = CM_ERROR_EXISTS;
1342 if (filename[0] == '.') {
1343 cm_GetCell_Gen(&filename[1], fullname, CM_FLAG_CREATE);
1344 if (cm_stricmp_utf8(&filename[1],fullname) == 0) {
1345 code = CM_ERROR_EXISTS;
1349 cm_GetCell_Gen(filename, fullname, CM_FLAG_CREATE);
1350 if (cm_stricmp_utf8(filename,fullname) == 0) {
1351 code = CM_ERROR_EXISTS;
1356 lock_ObtainMutex(&cm_Freelance_Lock);
1358 if (RegCreateKeyEx( HKEY_LOCAL_MACHINE,
1359 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance\\Symlinks",
1362 REG_OPTION_NON_VOLATILE,
1363 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
1365 &hkFreelanceSymlinks,
1366 NULL) == ERROR_SUCCESS) {
1368 RegQueryInfoKey( hkFreelanceSymlinks,
1370 NULL, /* lpcClass */
1371 NULL, /* lpReserved */
1372 NULL, /* lpcSubKeys */
1373 NULL, /* lpcMaxSubKeyLen */
1374 NULL, /* lpcMaxClassLen */
1375 &dwSymlinks, /* lpcValues */
1376 NULL, /* lpcMaxValueNameLen */
1377 NULL, /* lpcMaxValueLen */
1378 NULL, /* lpcbSecurityDescriptor */
1379 NULL /* lpftLastWriteTime */
1382 sprintf(line, "%s:%s.", filename, destination);
1384 /* If we are adding a new value, there must be an unused name
1385 * within the range 0 to dwSymlinks
1387 for ( dwIndex = 0; dwIndex <= dwSymlinks; dwIndex++ ) {
1391 dwSize = sizeof(szLink);
1392 sprintf(szIndex, "%d", dwIndex);
1393 if (RegQueryValueEx( hkFreelanceSymlinks, szIndex, 0, &dwType, szLink, &dwSize) != ERROR_SUCCESS) {
1394 /* found an unused value */
1396 dwSize = (DWORD)strlen(line) + 1;
1397 RegSetValueEx( hkFreelanceSymlinks, szIndex, 0, dwType, line, dwSize);
1400 int len = (int)strlen(filename);
1401 if ( dwType == REG_SZ && !strncmp(filename, szLink, len) && szLink[len] == ':') {
1402 /* Replace the existing value */
1404 dwSize = (DWORD)strlen(line) + 1;
1405 RegSetValueEx( hkFreelanceSymlinks, szIndex, 0, dwType, line, dwSize);
1410 RegCloseKey(hkFreelanceSymlinks);
1413 /* Do this while we are holding the lock */
1414 cm_noteLocalMountPointChange(TRUE);
1415 lock_ReleaseMutex(&cm_Freelance_Lock);
1421 clientchar_t *cpath;
1425 cpath = cm_FsStringToClientStringAlloc(filename, -1, NULL);
1427 code = CM_ERROR_NOSUCHPATH;
1429 if (cm_getLocalMountPointChange()) { // check for changes
1430 cm_clearLocalMountPointChange(); // clear the changefile
1431 cm_reInitLocalMountPoints(); // start reinit
1434 code = cm_NameI(cm_RootSCachep(cm_rootUserp, &req), cpath,
1435 CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD | CM_FLAG_DFS_REFERRAL,
1436 cm_rootUserp, NULL, &req, &scp);
1440 cm_ReleaseSCache(scp);
1448 long cm_FreelanceRemoveSymlink(char *toremove)
1452 char shortname[200];
1454 HKEY hkFreelanceSymlinks = 0;
1455 DWORD dwType, dwSize;
1459 lock_ObtainMutex(&cm_Freelance_Lock);
1461 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
1462 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance\\Symlinks",
1464 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
1465 &hkFreelanceSymlinks) == ERROR_SUCCESS) {
1467 RegQueryInfoKey( hkFreelanceSymlinks,
1469 NULL, /* lpcClass */
1470 NULL, /* lpReserved */
1471 NULL, /* lpcSubKeys */
1472 NULL, /* lpcMaxSubKeyLen */
1473 NULL, /* lpcMaxClassLen */
1474 &dwSymlinks, /* lpcValues */
1475 NULL, /* lpcMaxValueNameLen */
1476 NULL, /* lpcMaxValueLen */
1477 NULL, /* lpcbSecurityDescriptor */
1478 NULL /* lpftLastWriteTime */
1481 for ( dwIndex = 0; dwIndex < dwSymlinks; dwIndex++ ) {
1482 TCHAR szValueName[16];
1483 DWORD dwValueSize = 16;
1484 dwSize = sizeof(line);
1485 RegEnumValue( hkFreelanceSymlinks, dwIndex, szValueName, &dwValueSize, NULL,
1486 &dwType, line, &dwSize);
1488 cp=strchr(line, ':');
1489 memcpy(shortname, line, cp-line);
1490 shortname[cp-line]=0;
1492 if (!strcmp(shortname, toremove)) {
1493 RegDeleteValue( hkFreelanceSymlinks, szValueName );
1498 RegCloseKey(hkFreelanceSymlinks);
1502 /* Do this while we are holding the lock */
1503 cm_noteLocalMountPointChange(TRUE);
1505 lock_ReleaseMutex(&cm_Freelance_Lock);
1506 return (found ? 0 : CM_ERROR_NOSUCHFILE);
1510 cm_FreelanceFetchMountPointString(cm_scache_t *scp)
1512 lock_ObtainMutex(&cm_Freelance_Lock);
1513 if (!scp->mountPointStringp[0] &&
1514 scp->fid.cell == AFS_FAKE_ROOT_CELL_ID &&
1515 scp->fid.volume == AFS_FAKE_ROOT_VOL_ID &&
1516 scp->fid.unique <= cm_noLocalMountPoints) {
1517 strncpy(scp->mountPointStringp, cm_localMountPoints[scp->fid.unique-1].mountPointStringp, MOUNTPOINTLEN);
1518 scp->mountPointStringp[MOUNTPOINTLEN-1] = 0; /* null terminate */
1520 lock_ReleaseMutex(&cm_Freelance_Lock);
1526 cm_FreelanceFetchFileType(cm_scache_t *scp)
1528 lock_ObtainMutex(&cm_Freelance_Lock);
1529 if (scp->fid.cell == AFS_FAKE_ROOT_CELL_ID &&
1530 scp->fid.volume == AFS_FAKE_ROOT_VOL_ID &&
1531 scp->fid.unique <= cm_noLocalMountPoints)
1533 scp->fileType = cm_localMountPoints[scp->fid.unique-1].fileType;
1535 if ( scp->fileType == CM_SCACHETYPE_SYMLINK &&
1536 !strnicmp(cm_localMountPoints[scp->fid.unique-1].mountPointStringp, "msdfs:", strlen("msdfs:")) )
1538 scp->fileType = CM_SCACHETYPE_DFSLINK;
1541 scp->fileType = CM_SCACHETYPE_INVALID;
1543 lock_ReleaseMutex(&cm_Freelance_Lock);
1547 #endif /* AFS_FREELANCE_CLIENT */