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 int cm_fakeDirCallback=0;
28 int cm_fakeGettingCallback=0;
29 static cm_localMountPoint_t* cm_localMountPoints;
30 osi_mutex_t cm_Freelance_Lock;
31 static int cm_localMountPointChangeFlag = 0;
32 int cm_freelanceEnabled = 1;
33 int cm_freelanceImportCellServDB = 0;
34 time_t FakeFreelanceModTime = 0x3b49f6e2;
36 static int freelance_ShutdownFlag = 0;
37 static HANDLE hFreelanceChangeEvent = 0;
38 static HANDLE hFreelanceSymlinkChangeEvent = 0;
40 void cm_InitFakeRootDir();
42 void cm_FreelanceChangeNotifier(void * parmp) {
45 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
46 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance",
49 &hkFreelance) == ERROR_SUCCESS) {
51 hFreelanceChangeEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
52 if (hFreelanceChangeEvent == NULL) {
53 RegCloseKey(hkFreelance);
59 /* check hFreelanceChangeEvent to see if it is set.
60 * if so, call cm_noteLocalMountPointChange()
62 if (RegNotifyChangeKeyValue( hkFreelance, /* hKey */
63 FALSE, /* bWatchSubtree */
64 REG_NOTIFY_CHANGE_LAST_SET, /* dwNotifyFilter */
65 hFreelanceChangeEvent, /* hEvent */
66 TRUE /* fAsynchronous */
68 RegCloseKey(hkFreelance);
69 CloseHandle(hFreelanceChangeEvent);
70 hFreelanceChangeEvent = 0;
74 if (WaitForSingleObject(hFreelanceChangeEvent, INFINITE) == WAIT_OBJECT_0)
76 if (freelance_ShutdownFlag == 1) {
77 RegCloseKey(hkFreelance);
78 CloseHandle(hFreelanceChangeEvent);
79 hFreelanceChangeEvent = 0;
82 cm_noteLocalMountPointChange(FALSE);
87 void cm_FreelanceSymlinkChangeNotifier(void * parmp) {
90 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
91 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance\\Symlinks",
94 &hkFreelance) == ERROR_SUCCESS) {
96 hFreelanceSymlinkChangeEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
97 if (hFreelanceSymlinkChangeEvent == NULL) {
98 RegCloseKey(hkFreelance);
104 /* check hFreelanceSymlinkChangeEvent to see if it is set.
105 * if so, call cm_noteLocalMountPointSymlinkChange()
107 if (RegNotifyChangeKeyValue( hkFreelance, /* hKey */
108 FALSE, /* bWatchSubtree */
109 REG_NOTIFY_CHANGE_LAST_SET, /* dwNotifyFilter */
110 hFreelanceSymlinkChangeEvent, /* hEvent */
111 TRUE /* fAsynchronous */
112 ) != ERROR_SUCCESS) {
113 RegCloseKey(hkFreelance);
114 CloseHandle(hFreelanceSymlinkChangeEvent);
115 hFreelanceSymlinkChangeEvent = 0;
119 if (WaitForSingleObject(hFreelanceSymlinkChangeEvent, INFINITE) == WAIT_OBJECT_0)
121 if (freelance_ShutdownFlag == 1) {
122 RegCloseKey(hkFreelance);
123 CloseHandle(hFreelanceSymlinkChangeEvent);
124 hFreelanceSymlinkChangeEvent = 0;
127 cm_noteLocalMountPointChange(FALSE);
133 cm_FreelanceShutdown(void)
135 freelance_ShutdownFlag = 1;
136 if (hFreelanceChangeEvent != 0)
137 thrd_SetEvent(hFreelanceChangeEvent);
138 if (hFreelanceSymlinkChangeEvent != 0)
139 thrd_SetEvent(hFreelanceSymlinkChangeEvent);
143 cm_FreelanceAddCSDBMountPoints(void *rockp, char *cellNamep)
145 char szCellName[CELL_MAXNAMELEN+1] = ".";
147 cm_FsStrCpy( &szCellName[1], CELL_MAXNAMELEN, cellNamep);
148 /* create readonly mount point */
149 cm_FreelanceAddMount( cellNamep, cellNamep, "root.cell", 0, NULL);
151 /* create read/write mount point */
152 cm_FreelanceAddMount( szCellName, szCellName, "root.cell", 1, NULL);
158 cm_FreelanceImportCellServDB(void)
160 cm_EnumerateCellRegistry( TRUE, cm_FreelanceAddCSDBMountPoints, NULL);
161 cm_EnumerateCellFile( TRUE, cm_FreelanceAddCSDBMountPoints, NULL);
164 void cm_InitFreelance() {
168 lock_InitializeMutex(&cm_Freelance_Lock, "Freelance Lock", LOCK_HIERARCHY_FREELANCE_GLOBAL);
170 lock_ObtainMutex(&cm_Freelance_Lock);
172 // yj: first we make a call to cm_initLocalMountPoints
173 // to read all the local mount points from the registry
174 cm_InitLocalMountPoints();
176 // then we make a call to InitFakeRootDir to create
177 // a fake root directory based on the local mount points
178 cm_InitFakeRootDir();
179 // --- end of yj code
180 lock_ReleaseMutex(&cm_Freelance_Lock);
182 /* Start the registry monitor */
183 phandle = thrd_Create(NULL, 65536, (ThreadFunc) cm_FreelanceChangeNotifier,
184 NULL, 0, &lpid, "cm_FreelanceChangeNotifier");
185 osi_assertx(phandle != NULL, "cm_FreelanceChangeNotifier thread create failure");
186 thrd_CloseHandle(phandle);
188 phandle = thrd_Create(NULL, 65536, (ThreadFunc) cm_FreelanceSymlinkChangeNotifier,
189 NULL, 0, &lpid, "cm_FreelanceSymlinkChangeNotifier");
190 osi_assertx(phandle != NULL, "cm_FreelanceSymlinkChangeNotifier thread create failure");
191 thrd_CloseHandle(phandle);
194 /* yj: Initialization of the fake root directory */
195 /* to be called while holding freelance lock. */
196 void cm_InitFakeRootDir() {
201 // allocate space for the fake info
202 cm_dirHeader_t fakeDirHeader;
203 cm_dirEntry_t fakeEntry;
204 cm_pageHeader_t fakePageHeader;
206 // i'm going to calculate how much space is needed for
207 // this fake root directory. we have these rules:
208 // 1. there are cm_noLocalMountPoints number of entries
209 // 2. each page is CM_DIR_PAGESIZE in size
210 // 3. the first 13 chunks of the first page are used for
212 // 4. the first chunk of all subsequent pages are used
213 // for page header stuff
214 // 5. a max of CM_DIR_EPP entries are allowed per page
215 // 6. each entry takes 1 or more chunks, depending on
216 // the size of the mount point string, as determined
218 // 7. each chunk is CM_DIR_CHUNKSIZE bytes
220 int CPP = CM_DIR_PAGESIZE / CM_DIR_CHUNKSIZE;
221 int curChunk = 13; // chunks 0 - 12 are used for header stuff
222 // of the first page in the directory
224 unsigned int curDirEntry = 0;
225 int curDirEntryInPage = 0;
229 /* Reserve 2 directory chunks for "." and ".." */
232 while (curDirEntry<cm_noLocalMountPoints) {
233 sizeOfCurEntry = cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0);
234 if ((curChunk + sizeOfCurEntry >= CPP) ||
235 (curDirEntryInPage + 1 >= CM_DIR_EPP)) {
237 curDirEntryInPage = 0;
240 curChunk += sizeOfCurEntry;
245 dirSize = (curPage+1) * CM_DIR_PAGESIZE;
246 if (cm_fakeDirSize != dirSize) {
248 free(cm_FakeRootDir);
249 cm_FakeRootDir = calloc(dirSize, 1);
250 cm_fakeDirSize = dirSize;
253 // yj: when we get here, we've figured out how much memory we need and
254 // allocated the appropriate space for it. we now prceed to fill
255 // it up with entries.
258 curDirEntryInPage = 0;
261 // fields in the directory entry that are unused.
263 fakeEntry.length = 0;
265 fakeEntry.fid.unique = htonl(1);
267 // the first page is special, it uses fakeDirHeader instead of fakePageHeader
268 // we fill up the page with dirEntries that belong there and we make changes
269 // to the fakeDirHeader.header.freeBitmap along the way. Then when we're done
270 // filling up the dirEntries in this page, we copy the fakeDirHeader into
271 // the top of the page.
273 // init the freeBitmap array
275 fakeDirHeader.header.freeBitmap[i]=0;
277 fakeDirHeader.header.freeBitmap[0] = 0xff;
278 fakeDirHeader.header.freeBitmap[1] = 0x7f;
281 // we start counting at 13 because the 0th to 12th chunks are used for header
284 // stick the first 2 entries "." and ".." in
285 fakeEntry.fid.vnode = htonl(1);
286 strcpy(fakeEntry.name, ".");
287 currentPos = cm_FakeRootDir + curPage * CM_DIR_PAGESIZE + curChunk * CM_DIR_CHUNKSIZE;
288 memcpy(currentPos, &fakeEntry, CM_DIR_CHUNKSIZE);
289 curChunk++; curDirEntryInPage++;
290 strcpy(fakeEntry.name, "..");
291 currentPos = cm_FakeRootDir + curPage * CM_DIR_PAGESIZE + curChunk * CM_DIR_CHUNKSIZE;
292 memcpy(currentPos, &fakeEntry, CM_DIR_CHUNKSIZE);
293 curChunk++; curDirEntryInPage++;
295 // keep putting stuff into page 0 if
296 // 1. we're not done with all entries
297 // 2. we have less than CM_DIR_EPP entries in page 0
298 // 3. we're not out of chunks in page 0
300 while( (curDirEntry<cm_noLocalMountPoints) &&
301 (curDirEntryInPage < CM_DIR_EPP) &&
302 (curChunk + cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0) <= CPP))
305 noChunks = cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0);
306 /* enforce the rule that only directories have odd vnode values */
307 fakeEntry.fid.vnode = htonl((curDirEntry + 1) * 2);
308 fakeEntry.fid.unique = htonl(curDirEntry + 1);
309 currentPos = cm_FakeRootDir + curPage * CM_DIR_PAGESIZE + curChunk * CM_DIR_CHUNKSIZE;
311 memcpy(currentPos, &fakeEntry, CM_DIR_CHUNKSIZE);
312 strcpy(currentPos + 12, (cm_localMountPoints+curDirEntry)->namep);
315 for (i=0; i<noChunks; i++) {
316 t1 = (curChunk + i) / 8;
317 t2 = curChunk + i - (t1*8);
318 fakeDirHeader.header.freeBitmap[t1] |= (1 << t2);
323 // when we get here, we're done with filling in the entries for page 0
324 // copy in the header info
326 memcpy(cm_FakeRootDir, &fakeDirHeader, 13 * CM_DIR_CHUNKSIZE);
330 // ok, page 0's done. Move on to the next page.
331 while (curDirEntry<cm_noLocalMountPoints) {
333 curChunk = 1; // the zeroth chunk is reserved for page header
334 curDirEntryInPage = 0;
335 for (i=0; i<8; i++) {
336 fakePageHeader.freeBitmap[i]=0;
338 fakePageHeader.freeCount = 0;
339 fakePageHeader.pgcount = 0;
340 fakePageHeader.tag = htons(1234);
342 // while we're on the same page...
343 while ( (curDirEntry<cm_noLocalMountPoints) &&
344 (curDirEntryInPage < CM_DIR_EPP) &&
345 (curChunk + cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0) <= CPP))
347 // add an entry to this page
349 noChunks = cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0);
350 /* enforce the rule that only directories have odd vnode values */
351 fakeEntry.fid.vnode = htonl((curDirEntry + 1) * 2);
352 fakeEntry.fid.unique = htonl(curDirEntry + 1);
353 currentPos = cm_FakeRootDir + curPage * CM_DIR_PAGESIZE + curChunk * CM_DIR_CHUNKSIZE;
354 memcpy(currentPos, &fakeEntry, CM_DIR_CHUNKSIZE);
355 strcpy(currentPos + 12, (cm_localMountPoints+curDirEntry)->namep);
358 for (i=0; i<noChunks; i++) {
359 t1 = (curChunk + i) / 8;
360 t2 = curChunk + i - (t1*8);
361 fakePageHeader.freeBitmap[t1] |= (1 << t2);
365 memcpy(cm_FakeRootDir + curPage * CM_DIR_PAGESIZE, &fakePageHeader, sizeof(fakePageHeader));
370 // we know the fakeDir is setup properly, so we claim that we have callback
371 osi_Log0(afsd_logp,"cm_InitFakeRootDir fakeDirCallback=1");
372 cm_fakeDirCallback=1;
374 // when we get here, we've set up everything! done!
377 int cm_FakeRootFid(cm_fid_t *fidp)
380 AFS_FAKE_ROOT_CELL_ID, /* root cell */
381 AFS_FAKE_ROOT_VOL_ID, /* root.afs ? */
386 /* called directly from ioctl */
387 /* called while not holding freelance lock */
388 int cm_noteLocalMountPointChange(afs_int32 locked) {
390 lock_ObtainMutex(&cm_Freelance_Lock);
391 cm_data.fakeDirVersion++;
392 cm_localMountPointChangeFlag = 1;
394 lock_ReleaseMutex(&cm_Freelance_Lock);
398 int cm_getLocalMountPointChange() {
399 return cm_localMountPointChangeFlag;
402 int cm_clearLocalMountPointChange() {
403 cm_localMountPointChangeFlag = 0;
407 int cm_reInitLocalMountPoints() {
409 unsigned int i, hash;
410 cm_scache_t *scp, **lscpp, *tscp;
415 osi_Log0(afsd_logp,"----- freelance reinitialization starts ----- ");
417 // first we invalidate all the SCPs that were created
418 // for the local mount points
420 osi_Log0(afsd_logp,"Invalidating local mount point scp... ");
422 lock_ObtainWrite(&cm_scacheLock);
423 lock_ObtainMutex(&cm_Freelance_Lock); /* always scache then freelance lock */
424 for (i=0; i<=cm_noLocalMountPoints; i++) {
426 cm_SetFid(&aFid, AFS_FAKE_ROOT_CELL_ID, AFS_FAKE_ROOT_VOL_ID, 1, 1);
428 cm_SetFid(&aFid, AFS_FAKE_ROOT_CELL_ID, AFS_FAKE_ROOT_VOL_ID, i*2, i);
429 hash = CM_SCACHE_HASH(&aFid);
430 for (scp=cm_data.scacheHashTablep[hash]; scp; scp=scp->nextp) {
431 if (scp != cm_data.rootSCachep && cm_FidCmp(&scp->fid, &aFid) == 0) {
432 // mark the scp to be reused
433 cm_HoldSCacheNoLock(scp);
434 lock_ReleaseMutex(&cm_Freelance_Lock);
435 lock_ReleaseWrite(&cm_scacheLock);
436 lock_ObtainWrite(&scp->rw);
437 cm_DiscardSCache(scp);
439 // take the scp out of the hash
440 lock_ObtainWrite(&cm_scacheLock);
441 for (lscpp = &cm_data.scacheHashTablep[hash], tscp = cm_data.scacheHashTablep[hash];
443 lscpp = &tscp->nextp, tscp = tscp->nextp) {
447 scp->flags &= ~CM_SCACHEFLAG_INHASH;
452 lock_ReleaseWrite(&scp->rw);
453 lock_ReleaseWrite(&cm_scacheLock);
454 cm_CallbackNotifyChange(scp);
455 lock_ObtainWrite(&cm_scacheLock);
456 cm_ReleaseSCacheNoLock(scp);
457 lock_ObtainMutex(&cm_Freelance_Lock);
461 lock_ReleaseWrite(&cm_scacheLock);
462 lock_ReleaseMutex(&cm_Freelance_Lock);
463 osi_Log0(afsd_logp,"\tall old scp cleared!");
465 lock_ObtainWrite(&cm_data.rootSCachep->rw);
466 lock_ObtainMutex(&cm_Freelance_Lock);
467 // we must free the memory that was allocated in the prev
468 // cm_InitLocalMountPoints call
469 osi_Log0(afsd_logp,"Removing old localmountpoints... ");
470 free(cm_localMountPoints);
471 cm_localMountPoints = NULL;
472 cm_noLocalMountPoints = 0;
473 osi_Log0(afsd_logp,"\tall old localmountpoints cleared!");
475 // now re-init the localmountpoints
476 osi_Log0(afsd_logp,"Creating new localmountpoints... ");
477 cm_InitLocalMountPoints();
478 osi_Log0(afsd_logp,"\tcreated new set of localmountpoints!");
480 // then we re-create that dir
481 osi_Log0(afsd_logp,"Creating new fakedir... ");
482 cm_InitFakeRootDir();
483 osi_Log0(afsd_logp,"\t\tcreated new fakedir!");
485 lock_ReleaseMutex(&cm_Freelance_Lock);
487 cm_GetCallback(cm_data.rootSCachep, cm_rootUserp, &req, 0);
488 lock_ReleaseWrite(&cm_data.rootSCachep->rw);
490 osi_Log0(afsd_logp,"----- freelance reinit complete -----");
495 // yj: open up the registry and read all the local mount
496 // points that are stored there. Part of the initialization
497 // process for the freelance client.
498 /* to be called while holding freelance lock. */
499 long cm_InitLocalMountPoints() {
504 cm_localMountPoint_t* aLocalMountPoint;
507 char rootCellName[256];
508 HKEY hkFreelance = 0, hkFreelanceSymlinks = 0;
509 DWORD dwType, dwSize;
510 DWORD dwMountPoints = 0;
512 DWORD dwSymlinks = 0;
513 FILETIME ftLastWriteTime;
515 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
516 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance",
518 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
519 &hkFreelance) == ERROR_SUCCESS) {
521 RegQueryInfoKey( hkFreelance,
524 NULL, /* lpReserved */
525 NULL, /* lpcSubKeys */
526 NULL, /* lpcMaxSubKeyLen */
527 NULL, /* lpcMaxClassLen */
528 &dwMountPoints, /* lpcValues */
529 NULL, /* lpcMaxValueNameLen */
530 NULL, /* lpcMaxValueLen */
531 NULL, /* lpcbSecurityDescriptor */
532 &ftLastWriteTime /* lpftLastWriteTime */
535 cm_UnixTimeFromLargeSearchTime(&FakeFreelanceModTime, &ftLastWriteTime);
537 if ( dwMountPoints == 0 ) {
538 rootCellName[0] = '.';
539 code = cm_GetRootCellName(&rootCellName[1]);
541 lock_ReleaseMutex(&cm_Freelance_Lock);
542 cm_FreelanceAddMount(&rootCellName[1], &rootCellName[1], "root.cell.", 0, NULL);
543 cm_FreelanceAddMount(rootCellName, &rootCellName[1], "root.cell.", 1, NULL);
544 cm_FreelanceAddMount(".root", &rootCellName[1], "root.afs.", 1, NULL);
545 lock_ObtainMutex(&cm_Freelance_Lock);
550 if (RegCreateKeyEx( HKEY_LOCAL_MACHINE,
551 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance\\Symlinks",
554 REG_OPTION_NON_VOLATILE,
555 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
557 &hkFreelanceSymlinks,
558 NULL) == ERROR_SUCCESS) {
560 RegQueryInfoKey( hkFreelanceSymlinks,
563 NULL, /* lpReserved */
564 NULL, /* lpcSubKeys */
565 NULL, /* lpcMaxSubKeyLen */
566 NULL, /* lpcMaxClassLen */
567 &dwSymlinks, /* lpcValues */
568 NULL, /* lpcMaxValueNameLen */
569 NULL, /* lpcMaxValueLen */
570 NULL, /* lpcbSecurityDescriptor */
571 NULL /* lpftLastWriteTime */
575 // get the number of entries there are from the first line
577 cm_noLocalMountPoints = dwMountPoints + dwSymlinks;
579 // create space to store the local mount points
580 cm_localMountPoints = malloc(sizeof(cm_localMountPoint_t) * cm_noLocalMountPoints);
581 aLocalMountPoint = cm_localMountPoints;
583 // now we read n lines and parse them into local mount points
584 // where n is the number of local mount points there are, as
586 // Each line in the ini file represents 1 local mount point and
587 // is in the format xxx#yyy:zzz, where xxx is the directory
588 // entry name, yyy is the cell name and zzz is the volume name.
589 // #yyy:zzz together make up the mount point.
590 for ( dwIndex = 0 ; dwIndex < dwMountPoints; dwIndex++ ) {
591 TCHAR szValueName[16];
592 DWORD dwValueSize = 16;
593 dwSize = sizeof(line);
594 if (RegEnumValue( hkFreelance, dwIndex, szValueName, &dwValueSize, NULL,
595 &dwType, line, &dwSize))
597 afsi_log("RegEnumValue(hkFreelance) failed");
598 cm_noLocalMountPoints--;
602 afsi_log("Mountpoint[%d] = %s",dwIndex, line);
604 /* find the trailing dot; null terminate after it */
605 t2 = strrchr(line, '.');
609 for ( t=line;*t;t++ ) {
610 if ( !isprint(*t) ) {
611 afsi_log("error occurred while parsing mountpoint entry [%d]: non-printable character", dwIndex);
612 fprintf(stderr, "error occurred while parsing mountpoint entry [%d]: non-printable character", dwIndex);
613 cm_noLocalMountPoints--;
618 // line is not empty, so let's parse it
619 t = strchr(line, '#');
621 t = strchr(line, '%');
622 // make sure that there is a '#' or '%' separator in the line
624 afsi_log("error occurred while parsing mountpoint entry [%d]: no # or %% separator", dwIndex);
625 fprintf(stderr, "error occurred while parsing mountpoint entry [%d]: no # or %% separator", dwIndex);
626 cm_noLocalMountPoints--;
630 aLocalMountPoint->fileType = CM_SCACHETYPE_MOUNTPOINT;
631 aLocalMountPoint->namep=malloc(t-line+1);
632 strncpy(aLocalMountPoint->namep, line, t-line);
633 aLocalMountPoint->namep[t-line] = '\0';
635 /* copy the mount point string */
636 aLocalMountPoint->mountPointStringp=malloc(strlen(t));
637 strncpy(aLocalMountPoint->mountPointStringp, t, strlen(t)-1);
638 aLocalMountPoint->mountPointStringp[strlen(t)-1] = '\0';
640 osi_Log2(afsd_logp,"found mount point: name %s, string %s",
641 osi_LogSaveString(afsd_logp,aLocalMountPoint->namep),
642 osi_LogSaveString(afsd_logp,aLocalMountPoint->mountPointStringp));
647 for ( dwIndex = 0 ; dwIndex < dwSymlinks; dwIndex++ ) {
648 TCHAR szValueName[16];
649 DWORD dwValueSize = 16;
650 dwSize = sizeof(line);
651 if (RegEnumValue( hkFreelanceSymlinks, dwIndex, szValueName, &dwValueSize, NULL,
652 &dwType, line, &dwSize))
654 afsi_log("RegEnumValue(hkFreelanceSymlinks) failed");
655 cm_noLocalMountPoints--;
659 afsi_log("Symlink[%d] = %s",dwIndex, line);
661 /* find the trailing dot; null terminate after it */
662 t2 = strrchr(line, '.');
666 for ( t=line;*t;t++ ) {
667 if ( !isprint(*t) ) {
668 afsi_log("error occurred while parsing symlink entry [%d]: non-printable character", dwIndex);
669 fprintf(stderr, "error occurred while parsing symlink entry [%d]: non-printable character", dwIndex);
670 cm_noLocalMountPoints--;
675 // line is not empty, so let's parse it
676 t = strchr(line, ':');
678 // make sure that there is a ':' separator in the line
680 afsi_log("error occurred while parsing symlink entry [%d]: no ':' separator", dwIndex);
681 fprintf(stderr, "error occurred while parsing symlink entry [%d]: no ':' separator", dwIndex);
682 cm_noLocalMountPoints--;
686 aLocalMountPoint->fileType = CM_SCACHETYPE_SYMLINK;
687 aLocalMountPoint->namep=malloc(t-line+1);
688 strncpy(aLocalMountPoint->namep, line, t-line);
689 aLocalMountPoint->namep[t-line] = '\0';
691 /* copy the symlink string */
692 aLocalMountPoint->mountPointStringp=malloc(strlen(t)-1);
693 strncpy(aLocalMountPoint->mountPointStringp, t+1, strlen(t)-2);
694 aLocalMountPoint->mountPointStringp[strlen(t)-2] = '\0';
696 osi_Log2(afsd_logp,"found symlink: name %s, string %s",
697 osi_LogSaveString(afsd_logp,aLocalMountPoint->namep),
698 osi_LogSaveString(afsd_logp,aLocalMountPoint->mountPointStringp));
703 if ( hkFreelanceSymlinks )
704 RegCloseKey( hkFreelanceSymlinks );
705 RegCloseKey(hkFreelance);
709 /* What follows is the old code to read freelance mount points
710 * out of a text file modified to copy the data into the registry
712 cm_GetConfigDir(hdir, sizeof(hdir));
713 strcat(hdir, AFS_FREELANCE_INI);
714 // open the ini file for reading
715 fp = fopen(hdir, "r");
717 /* look in the Windows directory where we used to store the file */
718 GetWindowsDirectory(hdir, sizeof(hdir));
720 strcat(hdir, AFS_FREELANCE_INI);
721 fp = fopen(hdir, "r");
724 RegCreateKeyEx( HKEY_LOCAL_MACHINE,
725 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance",
728 REG_OPTION_NON_VOLATILE,
736 RegCloseKey(hkFreelance);
737 rootCellName[0] = '.';
738 code = cm_GetRootCellName(&rootCellName[1]);
740 lock_ReleaseMutex(&cm_Freelance_Lock);
741 cm_FreelanceAddMount(&rootCellName[1], &rootCellName[1], "root.cell.", 0, NULL);
742 cm_FreelanceAddMount(rootCellName, &rootCellName[1], "root.cell.", 1, NULL);
743 cm_FreelanceAddMount(".root", &rootCellName[1], "root.afs.", 1, NULL);
744 lock_ObtainMutex(&cm_Freelance_Lock);
749 // we successfully opened the file
750 osi_Log0(afsd_logp,"opened afs_freelance.ini");
752 // now we read the first line to see how many entries
754 fgets(line, sizeof(line), fp);
756 // if the line is empty at any point when we're reading
757 // we're screwed. report error and return.
759 afsi_log("error occurred while reading afs_freelance.ini");
760 fprintf(stderr, "error occurred while reading afs_freelance.ini");
764 // get the number of entries there are from the first line
766 cm_noLocalMountPoints = atoi(line);
768 if (cm_noLocalMountPoints > 0) {
769 // create space to store the local mount points
770 cm_localMountPoints = malloc(sizeof(cm_localMountPoint_t) * cm_noLocalMountPoints);
771 aLocalMountPoint = cm_localMountPoints;
774 // now we read n lines and parse them into local mount points
775 // where n is the number of local mount points there are, as
777 // Each line in the ini file represents 1 local mount point and
778 // is in the format xxx#yyy:zzz, where xxx is the directory
779 // entry name, yyy is the cell name and zzz is the volume name.
780 // #yyy:zzz together make up the mount point.
781 for (i=0; i<cm_noLocalMountPoints; i++) {
782 fgets(line, sizeof(line), fp);
783 // check that the line is not empty
785 afsi_log("error occurred while parsing entry in %s: empty line in line %d", AFS_FREELANCE_INI, i);
786 fprintf(stderr, "error occurred while parsing entry in afs_freelance.ini: empty line in line %d", i);
790 /* find the trailing dot; null terminate after it */
791 t2 = strrchr(line, '.');
797 /* we are migrating to the registry */
798 sprintf(szIndex,"%d",dwIndex++);
800 dwSize = (DWORD)strlen(line) + 1;
801 RegSetValueEx( hkFreelance, szIndex, 0, dwType, line, dwSize);
804 // line is not empty, so let's parse it
805 t = strchr(line, '#');
807 t = strchr(line, '%');
808 // make sure that there is a '#' or '%' separator in the line
810 afsi_log("error occurred while parsing entry in %s: no # or %% separator in line %d", AFS_FREELANCE_INI, i);
811 fprintf(stderr, "error occurred while parsing entry in afs_freelance.ini: no # or %% separator in line %d", i);
814 aLocalMountPoint->namep=malloc(t-line+1);
815 memcpy(aLocalMountPoint->namep, line, t-line);
816 *(aLocalMountPoint->namep + (t-line)) = 0;
818 aLocalMountPoint->mountPointStringp=malloc(strlen(line) - (t-line) + 1);
819 memcpy(aLocalMountPoint->mountPointStringp, t, strlen(line)-(t-line)-1);
820 *(aLocalMountPoint->mountPointStringp + (strlen(line)-(t-line)-1)) = 0;
822 osi_Log2(afsd_logp,"found mount point: name %s, string %s",
823 aLocalMountPoint->namep,
824 aLocalMountPoint->mountPointStringp);
830 RegCloseKey(hkFreelance);
836 int cm_getNoLocalMountPoints() {
837 return cm_noLocalMountPoints;
840 long cm_FreelanceMountPointExists(char * filename, int prefix_ok)
846 HKEY hkFreelance = 0;
847 DWORD dwType, dwSize;
851 lock_ObtainMutex(&cm_Freelance_Lock);
853 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
854 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance",
856 KEY_READ|KEY_QUERY_VALUE,
857 &hkFreelance) == ERROR_SUCCESS)
859 RegQueryInfoKey( hkFreelance,
862 NULL, /* lpReserved */
863 NULL, /* lpcSubKeys */
864 NULL, /* lpcMaxSubKeyLen */
865 NULL, /* lpcMaxClassLen */
866 &dwMountPoints, /* lpcValues */
867 NULL, /* lpcMaxValueNameLen */
868 NULL, /* lpcMaxValueLen */
869 NULL, /* lpcbSecurityDescriptor */
870 NULL /* lpftLastWriteTime */
873 for ( dwIndex = 0; dwIndex < dwMountPoints; dwIndex++ ) {
874 TCHAR szValueName[16];
875 DWORD dwValueSize = 16;
876 dwSize = sizeof(line);
877 RegEnumValue( hkFreelance, dwIndex, szValueName, &dwValueSize, NULL,
878 &dwType, line, &dwSize);
880 cp=strchr(line, '#');
882 cp=strchr(line, '%');
883 memcpy(shortname, line, cp-line);
884 shortname[cp-line]=0;
886 if (!strcmp(shortname, filename)) {
891 for ( dwIndex = 0; dwIndex < dwMountPoints; dwIndex++ ) {
892 TCHAR szValueName[16];
893 DWORD dwValueSize = 16;
894 dwSize = sizeof(line);
895 RegEnumValue( hkFreelance, dwIndex, szValueName, &dwValueSize, NULL,
896 &dwType, line, &dwSize);
898 cp=strchr(line, '#');
900 cp=strchr(line, '%');
901 memcpy(shortname, line, cp-line);
902 shortname[cp-line]=0;
904 if (!cm_stricmp_utf8(shortname, filename)) {
909 if (prefix_ok && strlen(shortname) - strlen(filename) == 1 && !strncmp(shortname, filename, strlen(filename))) {
914 RegCloseKey(hkFreelance);
917 lock_ReleaseMutex(&cm_Freelance_Lock);
922 long cm_FreelanceSymlinkExists(char * filename, int prefix_ok)
928 HKEY hkFreelance = 0;
929 DWORD dwType, dwSize;
933 lock_ObtainMutex(&cm_Freelance_Lock);
935 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
936 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance\\Symlinks",
938 KEY_READ|KEY_QUERY_VALUE,
939 &hkFreelance) == ERROR_SUCCESS)
941 RegQueryInfoKey( hkFreelance,
944 NULL, /* lpReserved */
945 NULL, /* lpcSubKeys */
946 NULL, /* lpcMaxSubKeyLen */
947 NULL, /* lpcMaxClassLen */
948 &dwSymlinks, /* lpcValues */
949 NULL, /* lpcMaxValueNameLen */
950 NULL, /* lpcMaxValueLen */
951 NULL, /* lpcbSecurityDescriptor */
952 NULL /* lpftLastWriteTime */
955 for ( dwIndex = 0; dwIndex < dwSymlinks; dwIndex++ ) {
956 TCHAR szValueName[16];
957 DWORD dwValueSize = 16;
958 dwSize = sizeof(line);
959 RegEnumValue( hkFreelance, dwIndex, szValueName, &dwValueSize, NULL,
960 &dwType, line, &dwSize);
962 cp=strchr(line, ':');
963 memcpy(shortname, line, cp-line);
964 shortname[cp-line]=0;
966 if (!strcmp(shortname, filename)) {
971 if (prefix_ok && strlen(shortname) - strlen(filename) == 1 && !strncmp(shortname, filename, strlen(filename))) {
976 for ( dwIndex = 0; dwIndex < dwSymlinks; dwIndex++ ) {
977 TCHAR szValueName[16];
978 DWORD dwValueSize = 16;
979 dwSize = sizeof(line);
980 RegEnumValue( hkFreelance, dwIndex, szValueName, &dwValueSize, NULL,
981 &dwType, line, &dwSize);
983 cp=strchr(line, ':');
984 memcpy(shortname, line, cp-line);
985 shortname[cp-line]=0;
987 if (!cm_stricmp_utf8(shortname, filename)) {
992 RegCloseKey(hkFreelance);
995 lock_ReleaseMutex(&cm_Freelance_Lock);
1000 long cm_FreelanceAddMount(char *filename, char *cellname, char *volume, int rw, cm_fid_t *fidp)
1005 char fullname[CELL_MAXNAMELEN];
1008 HKEY hkFreelance = 0;
1009 DWORD dwType, dwSize;
1010 DWORD dwMountPoints;
1012 afs_uint32 code = 0;
1014 /* before adding, verify the cell name; if it is not a valid cell,
1015 don't add the mount point.
1016 allow partial matches as a means of poor man's alias. */
1017 /* major performance issue? */
1018 osi_Log4(afsd_logp,"Freelance Add Mount request: filename=%s cellname=%s volume=%s %s",
1019 osi_LogSaveString(afsd_logp,filename),
1020 osi_LogSaveString(afsd_logp,cellname),
1021 osi_LogSaveString(afsd_logp,volume),
1024 if ( filename[0] == '\0' || cellname[0] == '\0' || volume[0] == '\0' )
1025 return CM_ERROR_INVAL;
1027 if ( cm_FreelanceMountPointExists(filename, 0) ||
1028 cm_FreelanceSymlinkExists(filename, 0) ) {
1029 code = CM_ERROR_EXISTS;
1033 if (cellname[0] == '.') {
1034 if (!cm_GetCell_Gen(&cellname[1], fullname, CM_FLAG_CREATE))
1035 return CM_ERROR_INVAL;
1037 if (!cm_GetCell_Gen(cellname, fullname, CM_FLAG_CREATE))
1038 return CM_ERROR_INVAL;
1041 osi_Log1(afsd_logp,"Freelance Adding Mount for Cell: %s",
1042 osi_LogSaveString(afsd_logp,cellname));
1044 lock_ObtainMutex(&cm_Freelance_Lock);
1046 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
1047 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance",
1049 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
1050 &hkFreelance) == ERROR_SUCCESS) {
1052 RegQueryInfoKey( hkFreelance,
1054 NULL, /* lpcClass */
1055 NULL, /* lpReserved */
1056 NULL, /* lpcSubKeys */
1057 NULL, /* lpcMaxSubKeyLen */
1058 NULL, /* lpcMaxClassLen */
1059 &dwMountPoints, /* lpcValues */
1060 NULL, /* lpcMaxValueNameLen */
1061 NULL, /* lpcMaxValueLen */
1062 NULL, /* lpcbSecurityDescriptor */
1063 NULL /* lpftLastWriteTime */
1067 sprintf(line, "%s%%%s:%s", filename, fullname, volume);
1069 sprintf(line, "%s#%s:%s", filename, fullname, volume);
1071 /* If we are adding a new value, there must be an unused name
1072 * within the range 0 to dwMountPoints
1074 for ( dwIndex = 0; dwIndex <= dwMountPoints; dwIndex++ ) {
1078 dwSize = sizeof(szMount);
1079 sprintf(szIndex, "%d", dwIndex);
1080 if (RegQueryValueEx( hkFreelance, szIndex, 0, &dwType, szMount, &dwSize) != ERROR_SUCCESS) {
1081 /* found an unused value */
1083 dwSize = (DWORD)strlen(line) + 1;
1084 RegSetValueEx( hkFreelance, szIndex, 0, dwType, line, dwSize);
1087 int len = (int)strlen(filename);
1088 if ( dwType == REG_SZ && !strncmp(filename, szMount, len) &&
1089 (szMount[len] == '%' || szMount[len] == '#')) {
1090 /* Replace the existing value */
1092 dwSize = (DWORD)strlen(line) + 1;
1093 RegSetValueEx( hkFreelance, szIndex, 0, dwType, line, dwSize);
1098 RegCloseKey(hkFreelance);
1101 cm_GetConfigDir(hfile, sizeof(hfile));
1102 strcat(hfile, AFS_FREELANCE_INI);
1103 fp = fopen(hfile, "r+");
1105 return CM_ERROR_INVAL;
1106 fgets(line, sizeof(line), fp);
1109 fseek(fp, 0, SEEK_SET);
1110 fprintf(fp, "%d", n);
1111 fseek(fp, 0, SEEK_END);
1113 fprintf(fp, "%s%%%s:%s\n", filename, fullname, volume);
1115 fprintf(fp, "%s#%s:%s\n", filename, fullname, volume);
1119 /* Do this while we are holding the lock */
1120 cm_noteLocalMountPointChange(TRUE);
1121 lock_ReleaseMutex(&cm_Freelance_Lock);
1127 clientchar_t *cpath;
1131 cpath = cm_FsStringToClientStringAlloc(filename, -1, NULL);
1133 return CM_ERROR_NOSUCHPATH;
1135 if (cm_getLocalMountPointChange()) { // check for changes
1136 cm_clearLocalMountPointChange(); // clear the changefile
1137 cm_reInitLocalMountPoints(); // start reinit
1140 code = cm_NameI(cm_data.rootSCachep, cpath,
1141 CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD | CM_FLAG_DFS_REFERRAL,
1142 cm_rootUserp, NULL, &req, &scp);
1147 cm_ReleaseSCache(scp);
1153 long cm_FreelanceRemoveMount(char *toremove)
1158 char shortname[200];
1159 char hfile[260], hfile2[260];
1162 HKEY hkFreelance = 0;
1163 DWORD dwType, dwSize;
1164 DWORD dwMountPoints;
1167 lock_ObtainMutex(&cm_Freelance_Lock);
1169 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
1170 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance",
1172 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
1173 &hkFreelance) == ERROR_SUCCESS) {
1175 RegQueryInfoKey( hkFreelance,
1177 NULL, /* lpcClass */
1178 NULL, /* lpReserved */
1179 NULL, /* lpcSubKeys */
1180 NULL, /* lpcMaxSubKeyLen */
1181 NULL, /* lpcMaxClassLen */
1182 &dwMountPoints, /* lpcValues */
1183 NULL, /* lpcMaxValueNameLen */
1184 NULL, /* lpcMaxValueLen */
1185 NULL, /* lpcbSecurityDescriptor */
1186 NULL /* lpftLastWriteTime */
1189 for ( dwIndex = 0; dwIndex < dwMountPoints; dwIndex++ ) {
1190 TCHAR szValueName[16];
1191 DWORD dwValueSize = 16;
1192 dwSize = sizeof(line);
1193 RegEnumValue( hkFreelance, dwIndex, szValueName, &dwValueSize, NULL,
1194 &dwType, line, &dwSize);
1196 cp=strchr(line, '#');
1198 cp=strchr(line, '%');
1199 memcpy(shortname, line, cp-line);
1200 shortname[cp-line]=0;
1202 if (!strcmp(shortname, toremove)) {
1203 RegDeleteValue( hkFreelance, szValueName );
1208 RegCloseKey(hkFreelance);
1211 cm_GetConfigDir(hfile, sizeof(hfile));
1212 strcat(hfile, AFS_FREELANCE_INI);
1213 strcpy(hfile2, hfile);
1214 strcat(hfile2, "2");
1215 fp1=fopen(hfile, "r+");
1217 return CM_ERROR_INVAL;
1218 fp2=fopen(hfile2, "w+");
1221 return CM_ERROR_INVAL;
1224 fgets(line, sizeof(line), fp1);
1226 fprintf(fp2, "%d\n", n-1);
1228 for (i=0; i<n; i++) {
1229 fgets(line, sizeof(line), fp1);
1230 cp=strchr(line, '#');
1232 cp=strchr(line, '%');
1233 memcpy(shortname, line, cp-line);
1234 shortname[cp-line]=0;
1236 if (strcmp(shortname, toremove)==0) {
1248 rename(hfile2, hfile);
1253 /* Do this while we are holding the lock */
1254 cm_noteLocalMountPointChange(TRUE);
1256 lock_ReleaseMutex(&cm_Freelance_Lock);
1257 return (found ? 0 : CM_ERROR_NOSUCHFILE);
1260 long cm_FreelanceAddSymlink(char *filename, char *destination, cm_fid_t *fidp)
1263 char fullname[CELL_MAXNAMELEN] = "";
1265 HKEY hkFreelanceSymlinks = 0;
1266 DWORD dwType, dwSize;
1269 afs_uint32 code = 0;
1272 * before adding, verify the filename. If it is already in use, either as
1273 * as mount point or a cellname, do not permit the creation of the symlink.
1275 osi_Log2(afsd_logp,"Freelance Add Symlink request: filename=%s destination=%s",
1276 osi_LogSaveString(afsd_logp,filename),
1277 osi_LogSaveString(afsd_logp,destination));
1279 if ( filename[0] == '\0' || destination[0] == '\0' )
1280 return CM_ERROR_INVAL;
1282 /* Do not create the symlink if the name ends in a dot */
1283 if ( filename[strlen(filename)-1] == '.')
1284 return CM_ERROR_INVAL;
1286 if ( cm_FreelanceMountPointExists(filename, 0) ||
1287 cm_FreelanceSymlinkExists(filename, 0) ) {
1288 code = CM_ERROR_EXISTS;
1292 if (filename[0] == '.') {
1293 cm_GetCell_Gen(&filename[1], fullname, CM_FLAG_CREATE);
1294 if (cm_stricmp_utf8(&filename[1],fullname) == 0) {
1295 code = CM_ERROR_EXISTS;
1299 cm_GetCell_Gen(filename, fullname, CM_FLAG_CREATE);
1300 if (cm_stricmp_utf8(filename,fullname) == 0) {
1301 code = CM_ERROR_EXISTS;
1306 lock_ObtainMutex(&cm_Freelance_Lock);
1308 if (RegCreateKeyEx( HKEY_LOCAL_MACHINE,
1309 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance\\Symlinks",
1312 REG_OPTION_NON_VOLATILE,
1313 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
1315 &hkFreelanceSymlinks,
1316 NULL) == ERROR_SUCCESS) {
1318 RegQueryInfoKey( hkFreelanceSymlinks,
1320 NULL, /* lpcClass */
1321 NULL, /* lpReserved */
1322 NULL, /* lpcSubKeys */
1323 NULL, /* lpcMaxSubKeyLen */
1324 NULL, /* lpcMaxClassLen */
1325 &dwSymlinks, /* lpcValues */
1326 NULL, /* lpcMaxValueNameLen */
1327 NULL, /* lpcMaxValueLen */
1328 NULL, /* lpcbSecurityDescriptor */
1329 NULL /* lpftLastWriteTime */
1332 sprintf(line, "%s:%s.", filename, destination);
1334 /* If we are adding a new value, there must be an unused name
1335 * within the range 0 to dwSymlinks
1337 for ( dwIndex = 0; dwIndex <= dwSymlinks; dwIndex++ ) {
1341 dwSize = sizeof(szLink);
1342 sprintf(szIndex, "%d", dwIndex);
1343 if (RegQueryValueEx( hkFreelanceSymlinks, szIndex, 0, &dwType, szLink, &dwSize) != ERROR_SUCCESS) {
1344 /* found an unused value */
1346 dwSize = (DWORD)strlen(line) + 1;
1347 RegSetValueEx( hkFreelanceSymlinks, szIndex, 0, dwType, line, dwSize);
1350 int len = (int)strlen(filename);
1351 if ( dwType == REG_SZ && !strncmp(filename, szLink, len) && szLink[len] == ':') {
1352 /* Replace the existing value */
1354 dwSize = (DWORD)strlen(line) + 1;
1355 RegSetValueEx( hkFreelanceSymlinks, szIndex, 0, dwType, line, dwSize);
1360 RegCloseKey(hkFreelanceSymlinks);
1363 /* Do this while we are holding the lock */
1364 cm_noteLocalMountPointChange(TRUE);
1365 lock_ReleaseMutex(&cm_Freelance_Lock);
1371 clientchar_t *cpath;
1375 cpath = cm_FsStringToClientStringAlloc(filename, -1, NULL);
1377 code = CM_ERROR_NOSUCHPATH;
1379 if (cm_getLocalMountPointChange()) { // check for changes
1380 cm_clearLocalMountPointChange(); // clear the changefile
1381 cm_reInitLocalMountPoints(); // start reinit
1384 code = cm_NameI(cm_data.rootSCachep, cpath,
1385 CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD | CM_FLAG_DFS_REFERRAL,
1386 cm_rootUserp, NULL, &req, &scp);
1390 cm_ReleaseSCache(scp);
1398 long cm_FreelanceRemoveSymlink(char *toremove)
1402 char shortname[200];
1404 HKEY hkFreelanceSymlinks = 0;
1405 DWORD dwType, dwSize;
1409 lock_ObtainMutex(&cm_Freelance_Lock);
1411 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
1412 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance\\Symlinks",
1414 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
1415 &hkFreelanceSymlinks) == ERROR_SUCCESS) {
1417 RegQueryInfoKey( hkFreelanceSymlinks,
1419 NULL, /* lpcClass */
1420 NULL, /* lpReserved */
1421 NULL, /* lpcSubKeys */
1422 NULL, /* lpcMaxSubKeyLen */
1423 NULL, /* lpcMaxClassLen */
1424 &dwSymlinks, /* lpcValues */
1425 NULL, /* lpcMaxValueNameLen */
1426 NULL, /* lpcMaxValueLen */
1427 NULL, /* lpcbSecurityDescriptor */
1428 NULL /* lpftLastWriteTime */
1431 for ( dwIndex = 0; dwIndex < dwSymlinks; dwIndex++ ) {
1432 TCHAR szValueName[16];
1433 DWORD dwValueSize = 16;
1434 dwSize = sizeof(line);
1435 RegEnumValue( hkFreelanceSymlinks, dwIndex, szValueName, &dwValueSize, NULL,
1436 &dwType, line, &dwSize);
1438 cp=strchr(line, ':');
1439 memcpy(shortname, line, cp-line);
1440 shortname[cp-line]=0;
1442 if (!strcmp(shortname, toremove)) {
1443 RegDeleteValue( hkFreelanceSymlinks, szValueName );
1448 RegCloseKey(hkFreelanceSymlinks);
1452 /* Do this while we are holding the lock */
1453 cm_noteLocalMountPointChange(TRUE);
1455 lock_ReleaseMutex(&cm_Freelance_Lock);
1456 return (found ? 0 : CM_ERROR_NOSUCHFILE);
1460 cm_FreelanceFetchMountPointString(cm_scache_t *scp)
1462 lock_ObtainMutex(&cm_Freelance_Lock);
1463 if (!scp->mountPointStringp[0] &&
1464 scp->fid.cell == AFS_FAKE_ROOT_CELL_ID &&
1465 scp->fid.volume == AFS_FAKE_ROOT_VOL_ID &&
1466 scp->fid.unique <= cm_noLocalMountPoints) {
1467 strncpy(scp->mountPointStringp, cm_localMountPoints[scp->fid.unique-1].mountPointStringp, MOUNTPOINTLEN);
1468 scp->mountPointStringp[MOUNTPOINTLEN-1] = 0; /* null terminate */
1470 lock_ReleaseMutex(&cm_Freelance_Lock);
1476 cm_FreelanceFetchFileType(cm_scache_t *scp)
1478 lock_ObtainMutex(&cm_Freelance_Lock);
1479 if (scp->fid.cell == AFS_FAKE_ROOT_CELL_ID &&
1480 scp->fid.volume == AFS_FAKE_ROOT_VOL_ID &&
1481 scp->fid.unique <= cm_noLocalMountPoints)
1483 scp->fileType = cm_localMountPoints[scp->fid.unique-1].fileType;
1485 if ( scp->fileType == CM_SCACHETYPE_SYMLINK &&
1486 !strnicmp(cm_localMountPoints[scp->fid.unique-1].mountPointStringp, "msdfs:", strlen("msdfs:")) )
1488 scp->fileType = CM_SCACHETYPE_DFSLINK;
1491 scp->fileType = CM_SCACHETYPE_INVALID;
1493 lock_ReleaseMutex(&cm_Freelance_Lock);
1497 #endif /* AFS_FREELANCE_CLIENT */