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 /* Reserve 2 directory chunks for "." and ".." */
237 while (curDirEntry<cm_noLocalMountPoints) {
238 sizeOfCurEntry = cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0);
239 if ((curChunk + sizeOfCurEntry >= CPP) ||
240 (curDirEntryInPage + 1 >= CM_DIR_EPP)) {
242 curDirEntryInPage = 0;
245 curChunk += sizeOfCurEntry;
250 dirSize = (curPage+1) * CM_DIR_PAGESIZE;
251 if (cm_fakeDirSize != dirSize) {
253 free(cm_FakeRootDir);
254 cm_FakeRootDir = calloc(dirSize, 1);
255 cm_fakeDirSize = dirSize;
258 // yj: when we get here, we've figured out how much memory we need and
259 // allocated the appropriate space for it. we now prceed to fill
260 // it up with entries.
263 curDirEntryInPage = 0;
266 // fields in the directory entry that are unused.
268 fakeEntry.length = 0;
270 fakeEntry.fid.unique = htonl(1);
272 // the first page is special, it uses fakeDirHeader instead of fakePageHeader
273 // we fill up the page with dirEntries that belong there and we make changes
274 // to the fakeDirHeader.header.freeBitmap along the way. Then when we're done
275 // filling up the dirEntries in this page, we copy the fakeDirHeader into
276 // the top of the page.
278 // init the freeBitmap array
280 fakeDirHeader.header.freeBitmap[i]=0;
282 fakeDirHeader.header.freeBitmap[0] = 0xff;
283 fakeDirHeader.header.freeBitmap[1] = 0x7f;
286 // we start counting at 13 because the 0th to 12th chunks are used for header
289 // stick the first 2 entries "." and ".." in
290 fakeEntry.fid.vnode = htonl(1);
291 strcpy(fakeEntry.name, ".");
292 currentPos = cm_FakeRootDir + curPage * CM_DIR_PAGESIZE + curChunk * CM_DIR_CHUNKSIZE;
293 memcpy(currentPos, &fakeEntry, CM_DIR_CHUNKSIZE);
294 curChunk++; curDirEntryInPage++;
295 strcpy(fakeEntry.name, "..");
296 currentPos = cm_FakeRootDir + curPage * CM_DIR_PAGESIZE + curChunk * CM_DIR_CHUNKSIZE;
297 memcpy(currentPos, &fakeEntry, CM_DIR_CHUNKSIZE);
298 curChunk++; curDirEntryInPage++;
300 // keep putting stuff into page 0 if
301 // 1. we're not done with all entries
302 // 2. we have less than CM_DIR_EPP entries in page 0
303 // 3. we're not out of chunks in page 0
305 while( (curDirEntry<cm_noLocalMountPoints) &&
306 (curDirEntryInPage < CM_DIR_EPP) &&
307 (curChunk + cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0) <= CPP))
310 noChunks = cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0);
311 /* enforce the rule that only directories have odd vnode values */
312 fakeEntry.fid.vnode = htonl((curDirEntry + 1) * 2);
313 fakeEntry.fid.unique = htonl(curDirEntry + 1);
314 currentPos = cm_FakeRootDir + curPage * CM_DIR_PAGESIZE + curChunk * CM_DIR_CHUNKSIZE;
316 memcpy(currentPos, &fakeEntry, CM_DIR_CHUNKSIZE);
317 strcpy(currentPos + 12, (cm_localMountPoints+curDirEntry)->namep);
320 for (i=0; i<noChunks; i++) {
321 t1 = (curChunk + i) / 8;
322 t2 = curChunk + i - (t1*8);
323 fakeDirHeader.header.freeBitmap[t1] |= (1 << t2);
328 // when we get here, we're done with filling in the entries for page 0
329 // copy in the header info
331 memcpy(cm_FakeRootDir, &fakeDirHeader, 13 * CM_DIR_CHUNKSIZE);
335 // ok, page 0's done. Move on to the next page.
336 while (curDirEntry<cm_noLocalMountPoints) {
338 curChunk = 1; // the zeroth chunk is reserved for page header
339 curDirEntryInPage = 0;
340 for (i=0; i<8; i++) {
341 fakePageHeader.freeBitmap[i]=0;
343 fakePageHeader.freeCount = 0;
344 fakePageHeader.pgcount = 0;
345 fakePageHeader.tag = htons(1234);
347 // while we're on the same page...
348 while ( (curDirEntry<cm_noLocalMountPoints) &&
349 (curDirEntryInPage < CM_DIR_EPP) &&
350 (curChunk + cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0) <= CPP))
352 // add an entry to this page
354 noChunks = cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0);
355 /* enforce the rule that only directories have odd vnode values */
356 fakeEntry.fid.vnode = htonl((curDirEntry + 1) * 2);
357 fakeEntry.fid.unique = htonl(curDirEntry + 1);
358 currentPos = cm_FakeRootDir + curPage * CM_DIR_PAGESIZE + curChunk * CM_DIR_CHUNKSIZE;
359 memcpy(currentPos, &fakeEntry, CM_DIR_CHUNKSIZE);
360 strcpy(currentPos + 12, (cm_localMountPoints+curDirEntry)->namep);
363 for (i=0; i<noChunks; i++) {
364 t1 = (curChunk + i) / 8;
365 t2 = curChunk + i - (t1*8);
366 fakePageHeader.freeBitmap[t1] |= (1 << t2);
370 memcpy(cm_FakeRootDir + curPage * CM_DIR_PAGESIZE, &fakePageHeader, sizeof(fakePageHeader));
375 // we know the fakeDir is setup properly, so we claim that we have callback
376 osi_Log0(afsd_logp,"cm_InitFakeRootDir completed!");
378 // when we get here, we've set up everything! done!
381 int cm_FakeRootFid(cm_fid_t *fidp)
384 AFS_FAKE_ROOT_CELL_ID, /* root cell */
385 AFS_FAKE_ROOT_VOL_ID, /* root.afs ? */
390 /* called directly from ioctl */
391 /* called while not holding freelance lock */
392 int cm_noteLocalMountPointChange(afs_int32 locked) {
394 lock_ObtainMutex(&cm_Freelance_Lock);
395 cm_data.fakeDirVersion++;
396 cm_localMountPointChangeFlag = 1;
398 lock_ReleaseMutex(&cm_Freelance_Lock);
402 int cm_getLocalMountPointChange() {
403 return cm_localMountPointChangeFlag;
406 int cm_clearLocalMountPointChange() {
407 cm_localMountPointChangeFlag = 0;
411 int cm_reInitLocalMountPoints() {
413 unsigned int i, hash;
414 cm_scache_t *scp, **lscpp, *tscp;
419 osi_Log0(afsd_logp,"----- freelance reinitialization starts ----- ");
421 // first we invalidate all the SCPs that were created
422 // for the local mount points
424 osi_Log0(afsd_logp,"Invalidating local mount point scp... ");
426 lock_ObtainWrite(&cm_scacheLock);
427 lock_ObtainMutex(&cm_Freelance_Lock); /* always scache then freelance lock */
428 for (i=0; i<=cm_noLocalMountPoints; i++) {
430 cm_SetFid(&aFid, AFS_FAKE_ROOT_CELL_ID, AFS_FAKE_ROOT_VOL_ID, 1, 1);
432 cm_SetFid(&aFid, AFS_FAKE_ROOT_CELL_ID, AFS_FAKE_ROOT_VOL_ID, i*2, i);
433 hash = CM_SCACHE_HASH(&aFid);
434 for (scp=cm_data.scacheHashTablep[hash]; scp; scp=scp->nextp) {
435 if (scp != cm_data.rootSCachep && cm_FidCmp(&scp->fid, &aFid) == 0) {
436 // mark the scp to be reused
437 cm_HoldSCacheNoLock(scp);
438 lock_ReleaseMutex(&cm_Freelance_Lock);
439 lock_ReleaseWrite(&cm_scacheLock);
440 lock_ObtainWrite(&scp->rw);
441 cm_DiscardSCache(scp);
443 // take the scp out of the hash
444 lock_ObtainWrite(&cm_scacheLock);
445 for (lscpp = &cm_data.scacheHashTablep[hash], tscp = cm_data.scacheHashTablep[hash];
447 lscpp = &tscp->nextp, tscp = tscp->nextp) {
451 scp->flags &= ~CM_SCACHEFLAG_INHASH;
456 lock_ReleaseWrite(&scp->rw);
457 lock_ReleaseWrite(&cm_scacheLock);
458 cm_CallbackNotifyChange(scp);
459 lock_ObtainWrite(&cm_scacheLock);
460 cm_ReleaseSCacheNoLock(scp);
461 lock_ObtainMutex(&cm_Freelance_Lock);
465 lock_ReleaseWrite(&cm_scacheLock);
466 lock_ReleaseMutex(&cm_Freelance_Lock);
467 osi_Log0(afsd_logp,"\tall old scp cleared!");
469 lock_ObtainWrite(&cm_data.rootSCachep->rw);
470 lock_ObtainMutex(&cm_Freelance_Lock);
471 // we must free the memory that was allocated in the prev
472 // cm_InitLocalMountPoints call
473 osi_Log0(afsd_logp,"Removing old localmountpoints... ");
474 free(cm_localMountPoints);
475 cm_localMountPoints = NULL;
476 cm_noLocalMountPoints = 0;
477 osi_Log0(afsd_logp,"\tall old localmountpoints cleared!");
479 // now re-init the localmountpoints
480 osi_Log0(afsd_logp,"Creating new localmountpoints... ");
481 cm_InitLocalMountPoints();
482 osi_Log0(afsd_logp,"\tcreated new set of localmountpoints!");
484 // then we re-create that dir
485 osi_Log0(afsd_logp,"Creating new fakedir... ");
486 cm_InitFakeRootDir();
487 osi_Log0(afsd_logp,"\t\tcreated new fakedir!");
489 lock_ReleaseMutex(&cm_Freelance_Lock);
491 cm_GetCallback(cm_data.rootSCachep, cm_rootUserp, &req, 0);
492 lock_ReleaseWrite(&cm_data.rootSCachep->rw);
494 osi_Log0(afsd_logp,"----- freelance reinit complete -----");
499 * cm_enforceTrailingDot
501 * return 0 on failure, non-zero on success
505 cm_enforceTrailingDot(char * line, size_t cchLine, DWORD *pdwSize)
507 /* trailing white space first. */
508 if (line[(*pdwSize)-1] == '\0') {
509 while (isspace(line[(*pdwSize)-2])) {
510 line[(*pdwSize)-2] = '\0';
514 while (isspace(line[(*pdwSize)-1])) {
515 line[(*pdwSize)-1] = '\0';
520 /* then enforce the trailing dot requirement */
521 if (line[(*pdwSize)-1] == '\0' && line[(*pdwSize)-2] != '.') {
522 if ((*pdwSize) >= cchLine) {
523 afsi_log("no room for trailing dot");
526 line[(*pdwSize)-1] = '.';
527 line[(*pdwSize)] = '\0';
528 } else if (line[(*pdwSize)-1] != '\0' && line[(*pdwSize)-1] != '.') {
529 if ((*pdwSize) >= cchLine) {
530 afsi_log("no room for trailing dot and nul");
533 line[(*pdwSize)] = '.';
534 line[(*pdwSize)+1] = '\0';
535 } else if (line[(*pdwSize)-1] != '\0') {
536 if ((*pdwSize) >= cchLine) {
537 afsi_log("no room for trailing nul");
540 line[(*pdwSize)] = '\0';
546 // yj: open up the registry and read all the local mount
547 // points that are stored there. Part of the initialization
548 // process for the freelance client.
549 /* to be called while holding freelance lock. */
550 long cm_InitLocalMountPoints() {
555 cm_localMountPoint_t* aLocalMountPoint;
558 char rootCellName[256];
559 HKEY hkFreelance = 0, hkFreelanceSymlinks = 0;
560 DWORD dwType, dwSize;
561 DWORD dwMountPoints = 0;
563 DWORD dwSymlinks = 0;
564 FILETIME ftLastWriteTime;
566 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
567 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance",
569 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
570 &hkFreelance) == ERROR_SUCCESS) {
572 RegQueryInfoKey( hkFreelance,
575 NULL, /* lpReserved */
576 NULL, /* lpcSubKeys */
577 NULL, /* lpcMaxSubKeyLen */
578 NULL, /* lpcMaxClassLen */
579 &dwMountPoints, /* lpcValues */
580 NULL, /* lpcMaxValueNameLen */
581 NULL, /* lpcMaxValueLen */
582 NULL, /* lpcbSecurityDescriptor */
583 &ftLastWriteTime /* lpftLastWriteTime */
586 cm_UnixTimeFromLargeSearchTime(&FakeFreelanceModTime, &ftLastWriteTime);
588 if ( dwMountPoints == 0 ) {
589 rootCellName[0] = '.';
590 code = cm_GetRootCellName(&rootCellName[1]);
592 lock_ReleaseMutex(&cm_Freelance_Lock);
593 cm_FreelanceAddMount(&rootCellName[1], &rootCellName[1], "root.cell", 0, NULL);
594 cm_FreelanceAddMount(rootCellName, &rootCellName[1], "root.cell", 1, NULL);
595 cm_FreelanceAddMount(".root", &rootCellName[1], "root.afs", 1, NULL);
596 lock_ObtainMutex(&cm_Freelance_Lock);
601 if (RegCreateKeyEx( HKEY_LOCAL_MACHINE,
602 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance\\Symlinks",
605 REG_OPTION_NON_VOLATILE,
606 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
608 &hkFreelanceSymlinks,
609 NULL) == ERROR_SUCCESS) {
611 RegQueryInfoKey( hkFreelanceSymlinks,
614 NULL, /* lpReserved */
615 NULL, /* lpcSubKeys */
616 NULL, /* lpcMaxSubKeyLen */
617 NULL, /* lpcMaxClassLen */
618 &dwSymlinks, /* lpcValues */
619 NULL, /* lpcMaxValueNameLen */
620 NULL, /* lpcMaxValueLen */
621 NULL, /* lpcbSecurityDescriptor */
622 NULL /* lpftLastWriteTime */
626 // get the number of entries there are from the first line
628 cm_noLocalMountPoints = dwMountPoints + dwSymlinks;
630 // create space to store the local mount points
631 cm_localMountPoints = malloc(sizeof(cm_localMountPoint_t) * cm_noLocalMountPoints);
632 aLocalMountPoint = cm_localMountPoints;
634 // now we read n lines and parse them into local mount points
635 // where n is the number of local mount points there are, as
637 // Each line in the ini file represents 1 local mount point and
638 // is in the format xxx#yyy:zzz, where xxx is the directory
639 // entry name, yyy is the cell name and zzz is the volume name.
640 // #yyy:zzz together make up the mount point.
641 for ( dwIndex = 0 ; dwIndex < dwMountPoints; dwIndex++ ) {
642 TCHAR szValueName[16];
643 DWORD dwValueSize = 16;
644 dwSize = sizeof(line);
645 if (RegEnumValue( hkFreelance, dwIndex, szValueName, &dwValueSize, NULL,
646 &dwType, line, &dwSize))
648 afsi_log("RegEnumValue(hkFreelance) failed");
649 cm_noLocalMountPoints--;
653 /* make sure there is a trailing dot and a nul terminator */
654 if (!cm_enforceTrailingDot(line, sizeof(line), &dwSize)) {
655 cm_noLocalMountPoints--;
659 afsi_log("Mountpoint[%d] = %s", dwIndex, line);
661 for ( t=line;*t;t++ ) {
662 if ( !isprint(*t) ) {
663 afsi_log("error occurred while parsing mountpoint entry [%d]: non-printable character", dwIndex);
664 fprintf(stderr, "error occurred while parsing mountpoint entry [%d]: non-printable character", dwIndex);
665 cm_noLocalMountPoints--;
670 // line is not empty, so let's parse it
671 t = strchr(line, '#');
673 t = strchr(line, '%');
674 // make sure that there is a '#' or '%' separator in the line
676 afsi_log("error occurred while parsing mountpoint entry [%d]: no # or %% separator", dwIndex);
677 fprintf(stderr, "error occurred while parsing mountpoint entry [%d]: no # or %% separator", dwIndex);
678 cm_noLocalMountPoints--;
682 aLocalMountPoint->fileType = CM_SCACHETYPE_MOUNTPOINT;
683 aLocalMountPoint->namep=malloc(t-line+1);
684 strncpy(aLocalMountPoint->namep, line, t-line);
685 aLocalMountPoint->namep[t-line] = '\0';
687 /* copy the mount point string */
688 aLocalMountPoint->mountPointStringp=malloc(strlen(t));
689 strncpy(aLocalMountPoint->mountPointStringp, t, strlen(t)-1);
690 aLocalMountPoint->mountPointStringp[strlen(t)-1] = '\0';
692 osi_Log2(afsd_logp,"found mount point: name %s, string %s",
693 osi_LogSaveString(afsd_logp,aLocalMountPoint->namep),
694 osi_LogSaveString(afsd_logp,aLocalMountPoint->mountPointStringp));
699 for ( dwIndex = 0 ; dwIndex < dwSymlinks; dwIndex++ ) {
700 TCHAR szValueName[16];
701 DWORD dwValueSize = 16;
702 dwSize = sizeof(line);
703 if (RegEnumValue( hkFreelanceSymlinks, dwIndex, szValueName, &dwValueSize, NULL,
704 &dwType, line, &dwSize))
706 afsi_log("RegEnumValue(hkFreelanceSymlinks) failed");
707 cm_noLocalMountPoints--;
711 /* make sure there is a trailing dot and a nul terminator */
712 if (!cm_enforceTrailingDot(line, sizeof(line), &dwSize)) {
713 cm_noLocalMountPoints--;
717 afsi_log("Symlink[%d] = %s", dwIndex, line);
719 for ( t=line;*t;t++ ) {
720 if ( !isprint(*t) ) {
721 afsi_log("error occurred while parsing symlink entry [%d]: non-printable character", dwIndex);
722 fprintf(stderr, "error occurred while parsing symlink entry [%d]: non-printable character", dwIndex);
723 cm_noLocalMountPoints--;
728 // line is not empty, so let's parse it
729 t = strchr(line, ':');
731 // make sure that there is a ':' separator in the line
733 afsi_log("error occurred while parsing symlink entry [%d]: no ':' separator", dwIndex);
734 fprintf(stderr, "error occurred while parsing symlink entry [%d]: no ':' separator", dwIndex);
735 cm_noLocalMountPoints--;
739 aLocalMountPoint->fileType = CM_SCACHETYPE_SYMLINK;
740 aLocalMountPoint->namep=malloc(t-line+1);
741 strncpy(aLocalMountPoint->namep, line, t-line);
742 aLocalMountPoint->namep[t-line] = '\0';
744 /* copy the symlink string */
745 aLocalMountPoint->mountPointStringp=malloc(strlen(t)-1);
746 strncpy(aLocalMountPoint->mountPointStringp, t+1, strlen(t)-2);
747 aLocalMountPoint->mountPointStringp[strlen(t)-2] = '\0';
749 osi_Log2(afsd_logp,"found symlink: name %s, string %s",
750 osi_LogSaveString(afsd_logp,aLocalMountPoint->namep),
751 osi_LogSaveString(afsd_logp,aLocalMountPoint->mountPointStringp));
756 if ( hkFreelanceSymlinks )
757 RegCloseKey( hkFreelanceSymlinks );
758 RegCloseKey(hkFreelance);
762 /* What follows is the old code to read freelance mount points
763 * out of a text file modified to copy the data into the registry
765 cm_GetConfigDir(hdir, sizeof(hdir));
766 strcat(hdir, AFS_FREELANCE_INI);
767 // open the ini file for reading
768 fp = fopen(hdir, "r");
770 /* look in the Windows directory where we used to store the file */
771 GetWindowsDirectory(hdir, sizeof(hdir));
773 strcat(hdir, AFS_FREELANCE_INI);
774 fp = fopen(hdir, "r");
777 RegCreateKeyEx( HKEY_LOCAL_MACHINE,
778 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance",
781 REG_OPTION_NON_VOLATILE,
789 RegCloseKey(hkFreelance);
790 rootCellName[0] = '.';
791 code = cm_GetRootCellName(&rootCellName[1]);
793 lock_ReleaseMutex(&cm_Freelance_Lock);
794 cm_FreelanceAddMount(&rootCellName[1], &rootCellName[1], "root.cell", 0, NULL);
795 cm_FreelanceAddMount(rootCellName, &rootCellName[1], "root.cell", 1, NULL);
796 cm_FreelanceAddMount(".root", &rootCellName[1], "root.afs", 1, NULL);
797 lock_ObtainMutex(&cm_Freelance_Lock);
802 // we successfully opened the file
803 osi_Log0(afsd_logp,"opened afs_freelance.ini");
805 // now we read the first line to see how many entries
807 fgets(line, sizeof(line), fp);
809 // if the line is empty at any point when we're reading
810 // we're screwed. report error and return.
812 afsi_log("error occurred while reading afs_freelance.ini");
813 fprintf(stderr, "error occurred while reading afs_freelance.ini");
817 // get the number of entries there are from the first line
819 cm_noLocalMountPoints = atoi(line);
821 if (cm_noLocalMountPoints > 0) {
822 // create space to store the local mount points
823 cm_localMountPoints = malloc(sizeof(cm_localMountPoint_t) * cm_noLocalMountPoints);
824 aLocalMountPoint = cm_localMountPoints;
827 // now we read n lines and parse them into local mount points
828 // where n is the number of local mount points there are, as
830 // Each line in the ini file represents 1 local mount point and
831 // is in the format xxx#yyy:zzz, where xxx is the directory
832 // entry name, yyy is the cell name and zzz is the volume name.
833 // #yyy:zzz together make up the mount point.
834 for (i=0; i<cm_noLocalMountPoints; i++) {
835 fgets(line, sizeof(line), fp);
836 // check that the line is not empty
838 afsi_log("error occurred while parsing entry in %s: empty line in line %d", AFS_FREELANCE_INI, i);
839 fprintf(stderr, "error occurred while parsing entry in afs_freelance.ini: empty line in line %d", i);
843 /* find the trailing dot; null terminate after it */
844 t2 = strrchr(line, '.');
850 /* we are migrating to the registry */
851 sprintf(szIndex,"%d",dwIndex++);
853 dwSize = (DWORD)strlen(line) + 1;
854 RegSetValueEx( hkFreelance, szIndex, 0, dwType, line, dwSize);
857 // line is not empty, so let's parse it
858 t = strchr(line, '#');
860 t = strchr(line, '%');
861 // make sure that there is a '#' or '%' separator in the line
863 afsi_log("error occurred while parsing entry in %s: no # or %% separator in line %d", AFS_FREELANCE_INI, i);
864 fprintf(stderr, "error occurred while parsing entry in afs_freelance.ini: no # or %% separator in line %d", i);
867 aLocalMountPoint->namep=malloc(t-line+1);
868 memcpy(aLocalMountPoint->namep, line, t-line);
869 *(aLocalMountPoint->namep + (t-line)) = 0;
871 aLocalMountPoint->mountPointStringp=malloc(strlen(line) - (t-line) + 1);
872 memcpy(aLocalMountPoint->mountPointStringp, t, strlen(line)-(t-line)-1);
873 *(aLocalMountPoint->mountPointStringp + (strlen(line)-(t-line)-1)) = 0;
875 osi_Log2(afsd_logp,"found mount point: name %s, string %s",
876 aLocalMountPoint->namep,
877 aLocalMountPoint->mountPointStringp);
883 RegCloseKey(hkFreelance);
889 int cm_getNoLocalMountPoints() {
890 return cm_noLocalMountPoints;
893 long cm_FreelanceMountPointExists(char * filename, int prefix_ok)
899 HKEY hkFreelance = 0;
900 DWORD dwType, dwSize;
904 lock_ObtainMutex(&cm_Freelance_Lock);
906 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
907 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance",
909 KEY_READ|KEY_QUERY_VALUE,
910 &hkFreelance) == ERROR_SUCCESS)
912 RegQueryInfoKey( hkFreelance,
915 NULL, /* lpReserved */
916 NULL, /* lpcSubKeys */
917 NULL, /* lpcMaxSubKeyLen */
918 NULL, /* lpcMaxClassLen */
919 &dwMountPoints, /* lpcValues */
920 NULL, /* lpcMaxValueNameLen */
921 NULL, /* lpcMaxValueLen */
922 NULL, /* lpcbSecurityDescriptor */
923 NULL /* lpftLastWriteTime */
926 for ( dwIndex = 0; dwIndex < dwMountPoints; dwIndex++ ) {
927 TCHAR szValueName[16];
928 DWORD dwValueSize = 16;
929 dwSize = sizeof(line);
930 RegEnumValue( hkFreelance, dwIndex, szValueName, &dwValueSize, NULL,
931 &dwType, line, &dwSize);
933 cp=strchr(line, '#');
935 cp=strchr(line, '%');
936 memcpy(shortname, line, cp-line);
937 shortname[cp-line]=0;
939 if (!strcmp(shortname, filename)) {
944 for ( dwIndex = 0; dwIndex < dwMountPoints; dwIndex++ ) {
945 TCHAR szValueName[16];
946 DWORD dwValueSize = 16;
947 dwSize = sizeof(line);
948 RegEnumValue( hkFreelance, dwIndex, szValueName, &dwValueSize, NULL,
949 &dwType, line, &dwSize);
951 cp=strchr(line, '#');
953 cp=strchr(line, '%');
954 memcpy(shortname, line, cp-line);
955 shortname[cp-line]=0;
957 if (!cm_stricmp_utf8(shortname, filename)) {
962 if (prefix_ok && strlen(shortname) - strlen(filename) == 1 && !strncmp(shortname, filename, strlen(filename))) {
967 RegCloseKey(hkFreelance);
970 lock_ReleaseMutex(&cm_Freelance_Lock);
975 long cm_FreelanceSymlinkExists(char * filename, int prefix_ok)
981 HKEY hkFreelance = 0;
982 DWORD dwType, dwSize;
986 lock_ObtainMutex(&cm_Freelance_Lock);
988 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
989 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance\\Symlinks",
991 KEY_READ|KEY_QUERY_VALUE,
992 &hkFreelance) == ERROR_SUCCESS)
994 RegQueryInfoKey( hkFreelance,
997 NULL, /* lpReserved */
998 NULL, /* lpcSubKeys */
999 NULL, /* lpcMaxSubKeyLen */
1000 NULL, /* lpcMaxClassLen */
1001 &dwSymlinks, /* lpcValues */
1002 NULL, /* lpcMaxValueNameLen */
1003 NULL, /* lpcMaxValueLen */
1004 NULL, /* lpcbSecurityDescriptor */
1005 NULL /* lpftLastWriteTime */
1008 for ( dwIndex = 0; dwIndex < dwSymlinks; dwIndex++ ) {
1009 TCHAR szValueName[16];
1010 DWORD dwValueSize = 16;
1011 dwSize = sizeof(line);
1012 RegEnumValue( hkFreelance, dwIndex, szValueName, &dwValueSize, NULL,
1013 &dwType, line, &dwSize);
1015 cp=strchr(line, ':');
1016 memcpy(shortname, line, cp-line);
1017 shortname[cp-line]=0;
1019 if (!strcmp(shortname, filename)) {
1024 if (prefix_ok && strlen(shortname) - strlen(filename) == 1 && !strncmp(shortname, filename, strlen(filename))) {
1029 for ( dwIndex = 0; dwIndex < dwSymlinks; dwIndex++ ) {
1030 TCHAR szValueName[16];
1031 DWORD dwValueSize = 16;
1032 dwSize = sizeof(line);
1033 RegEnumValue( hkFreelance, dwIndex, szValueName, &dwValueSize, NULL,
1034 &dwType, line, &dwSize);
1036 cp=strchr(line, ':');
1037 memcpy(shortname, line, cp-line);
1038 shortname[cp-line]=0;
1040 if (!cm_stricmp_utf8(shortname, filename)) {
1045 RegCloseKey(hkFreelance);
1048 lock_ReleaseMutex(&cm_Freelance_Lock);
1053 long cm_FreelanceAddMount(char *filename, char *cellname, char *volume, int rw, cm_fid_t *fidp)
1058 char fullname[CELL_MAXNAMELEN];
1061 HKEY hkFreelance = 0;
1062 DWORD dwType, dwSize;
1063 DWORD dwMountPoints;
1065 afs_uint32 code = 0;
1067 /* before adding, verify the cell name; if it is not a valid cell,
1068 don't add the mount point.
1069 allow partial matches as a means of poor man's alias. */
1070 /* major performance issue? */
1071 osi_Log4(afsd_logp,"Freelance Add Mount request: filename=%s cellname=%s volume=%s %s",
1072 osi_LogSaveString(afsd_logp,filename),
1073 osi_LogSaveString(afsd_logp,cellname),
1074 osi_LogSaveString(afsd_logp,volume),
1077 if ( filename[0] == '\0' || cellname[0] == '\0' || volume[0] == '\0' )
1078 return CM_ERROR_INVAL;
1080 if ( cm_FreelanceMountPointExists(filename, 0) ||
1081 cm_FreelanceSymlinkExists(filename, 0) ) {
1082 code = CM_ERROR_EXISTS;
1086 if (cellname[0] == '.') {
1087 if (!cm_GetCell_Gen(&cellname[1], fullname, CM_FLAG_CREATE))
1088 return CM_ERROR_INVAL;
1090 if (!cm_GetCell_Gen(cellname, fullname, CM_FLAG_CREATE))
1091 return CM_ERROR_INVAL;
1094 osi_Log1(afsd_logp,"Freelance Adding Mount for Cell: %s",
1095 osi_LogSaveString(afsd_logp,cellname));
1097 lock_ObtainMutex(&cm_Freelance_Lock);
1099 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
1100 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance",
1102 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
1103 &hkFreelance) == ERROR_SUCCESS) {
1105 RegQueryInfoKey( hkFreelance,
1107 NULL, /* lpcClass */
1108 NULL, /* lpReserved */
1109 NULL, /* lpcSubKeys */
1110 NULL, /* lpcMaxSubKeyLen */
1111 NULL, /* lpcMaxClassLen */
1112 &dwMountPoints, /* lpcValues */
1113 NULL, /* lpcMaxValueNameLen */
1114 NULL, /* lpcMaxValueLen */
1115 NULL, /* lpcbSecurityDescriptor */
1116 NULL /* lpftLastWriteTime */
1120 sprintf(line, "%s%%%s:%s.", filename, fullname, volume);
1122 sprintf(line, "%s#%s:%s.", filename, fullname, volume);
1124 /* If we are adding a new value, there must be an unused name
1125 * within the range 0 to dwMountPoints
1127 for ( dwIndex = 0; dwIndex <= dwMountPoints; dwIndex++ ) {
1131 dwSize = sizeof(szMount);
1132 sprintf(szIndex, "%d", dwIndex);
1133 if (RegQueryValueEx( hkFreelance, szIndex, 0, &dwType, szMount, &dwSize) != ERROR_SUCCESS) {
1134 /* found an unused value */
1136 dwSize = (DWORD)strlen(line) + 1;
1137 RegSetValueEx( hkFreelance, szIndex, 0, dwType, line, dwSize);
1140 int len = (int)strlen(filename);
1141 if ( dwType == REG_SZ && !strncmp(filename, szMount, len) &&
1142 (szMount[len] == '%' || szMount[len] == '#')) {
1143 /* Replace the existing value */
1145 dwSize = (DWORD)strlen(line) + 1;
1146 RegSetValueEx( hkFreelance, szIndex, 0, dwType, line, dwSize);
1151 RegCloseKey(hkFreelance);
1154 cm_GetConfigDir(hfile, sizeof(hfile));
1155 strcat(hfile, AFS_FREELANCE_INI);
1156 fp = fopen(hfile, "r+");
1158 return CM_ERROR_INVAL;
1159 fgets(line, sizeof(line), fp);
1162 fseek(fp, 0, SEEK_SET);
1163 fprintf(fp, "%d", n);
1164 fseek(fp, 0, SEEK_END);
1166 fprintf(fp, "%s%%%s:%s.\n", filename, fullname, volume);
1168 fprintf(fp, "%s#%s:%s.\n", filename, fullname, volume);
1172 /* Do this while we are holding the lock */
1173 cm_noteLocalMountPointChange(TRUE);
1174 lock_ReleaseMutex(&cm_Freelance_Lock);
1180 clientchar_t *cpath;
1184 cpath = cm_FsStringToClientStringAlloc(filename, -1, NULL);
1186 return CM_ERROR_NOSUCHPATH;
1188 if (cm_getLocalMountPointChange()) { // check for changes
1189 cm_clearLocalMountPointChange(); // clear the changefile
1190 cm_reInitLocalMountPoints(); // start reinit
1193 code = cm_NameI(cm_RootSCachep(cm_rootUserp, &req), cpath,
1194 CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD | CM_FLAG_DFS_REFERRAL,
1195 cm_rootUserp, NULL, &req, &scp);
1200 cm_ReleaseSCache(scp);
1206 long cm_FreelanceRemoveMount(char *toremove)
1211 char shortname[200];
1212 char hfile[260], hfile2[260];
1215 HKEY hkFreelance = 0;
1216 DWORD dwType, dwSize;
1217 DWORD dwMountPoints;
1220 lock_ObtainMutex(&cm_Freelance_Lock);
1222 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
1223 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance",
1225 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
1226 &hkFreelance) == ERROR_SUCCESS) {
1228 RegQueryInfoKey( hkFreelance,
1230 NULL, /* lpcClass */
1231 NULL, /* lpReserved */
1232 NULL, /* lpcSubKeys */
1233 NULL, /* lpcMaxSubKeyLen */
1234 NULL, /* lpcMaxClassLen */
1235 &dwMountPoints, /* lpcValues */
1236 NULL, /* lpcMaxValueNameLen */
1237 NULL, /* lpcMaxValueLen */
1238 NULL, /* lpcbSecurityDescriptor */
1239 NULL /* lpftLastWriteTime */
1242 for ( dwIndex = 0; dwIndex < dwMountPoints; dwIndex++ ) {
1243 TCHAR szValueName[16];
1244 DWORD dwValueSize = 16;
1245 dwSize = sizeof(line);
1246 RegEnumValue( hkFreelance, dwIndex, szValueName, &dwValueSize, NULL,
1247 &dwType, line, &dwSize);
1249 cp=strchr(line, '#');
1251 cp=strchr(line, '%');
1252 memcpy(shortname, line, cp-line);
1253 shortname[cp-line]=0;
1255 if (!strcmp(shortname, toremove)) {
1256 RegDeleteValue( hkFreelance, szValueName );
1261 RegCloseKey(hkFreelance);
1264 cm_GetConfigDir(hfile, sizeof(hfile));
1265 strcat(hfile, AFS_FREELANCE_INI);
1266 strcpy(hfile2, hfile);
1267 strcat(hfile2, "2");
1268 fp1=fopen(hfile, "r+");
1270 return CM_ERROR_INVAL;
1271 fp2=fopen(hfile2, "w+");
1274 return CM_ERROR_INVAL;
1277 fgets(line, sizeof(line), fp1);
1279 fprintf(fp2, "%d\n", n-1);
1281 for (i=0; i<n; i++) {
1282 fgets(line, sizeof(line), fp1);
1283 cp=strchr(line, '#');
1285 cp=strchr(line, '%');
1286 memcpy(shortname, line, cp-line);
1287 shortname[cp-line]=0;
1289 if (strcmp(shortname, toremove)==0) {
1301 rename(hfile2, hfile);
1306 /* Do this while we are holding the lock */
1307 cm_noteLocalMountPointChange(TRUE);
1309 lock_ReleaseMutex(&cm_Freelance_Lock);
1310 return (found ? 0 : CM_ERROR_NOSUCHFILE);
1313 long cm_FreelanceAddSymlink(char *filename, char *destination, cm_fid_t *fidp)
1316 char fullname[CELL_MAXNAMELEN] = "";
1318 HKEY hkFreelanceSymlinks = 0;
1319 DWORD dwType, dwSize;
1322 afs_uint32 code = 0;
1325 * before adding, verify the filename. If it is already in use, either as
1326 * as mount point or a cellname, do not permit the creation of the symlink.
1328 osi_Log2(afsd_logp,"Freelance Add Symlink request: filename=%s destination=%s",
1329 osi_LogSaveString(afsd_logp,filename),
1330 osi_LogSaveString(afsd_logp,destination));
1332 if ( filename[0] == '\0' || destination[0] == '\0' )
1333 return CM_ERROR_INVAL;
1335 /* Do not create the symlink if the name ends in a dot */
1336 if ( filename[strlen(filename)-1] == '.')
1337 return CM_ERROR_INVAL;
1339 if ( cm_FreelanceMountPointExists(filename, 0) ||
1340 cm_FreelanceSymlinkExists(filename, 0) ) {
1341 code = CM_ERROR_EXISTS;
1345 if (filename[0] == '.') {
1346 cm_GetCell_Gen(&filename[1], fullname, CM_FLAG_CREATE);
1347 if (cm_stricmp_utf8(&filename[1],fullname) == 0) {
1348 code = CM_ERROR_EXISTS;
1352 cm_GetCell_Gen(filename, fullname, CM_FLAG_CREATE);
1353 if (cm_stricmp_utf8(filename,fullname) == 0) {
1354 code = CM_ERROR_EXISTS;
1359 lock_ObtainMutex(&cm_Freelance_Lock);
1361 if (RegCreateKeyEx( HKEY_LOCAL_MACHINE,
1362 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance\\Symlinks",
1365 REG_OPTION_NON_VOLATILE,
1366 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
1368 &hkFreelanceSymlinks,
1369 NULL) == ERROR_SUCCESS) {
1371 RegQueryInfoKey( hkFreelanceSymlinks,
1373 NULL, /* lpcClass */
1374 NULL, /* lpReserved */
1375 NULL, /* lpcSubKeys */
1376 NULL, /* lpcMaxSubKeyLen */
1377 NULL, /* lpcMaxClassLen */
1378 &dwSymlinks, /* lpcValues */
1379 NULL, /* lpcMaxValueNameLen */
1380 NULL, /* lpcMaxValueLen */
1381 NULL, /* lpcbSecurityDescriptor */
1382 NULL /* lpftLastWriteTime */
1385 sprintf(line, "%s:%s.", filename, destination);
1387 /* If we are adding a new value, there must be an unused name
1388 * within the range 0 to dwSymlinks
1390 for ( dwIndex = 0; dwIndex <= dwSymlinks; dwIndex++ ) {
1394 dwSize = sizeof(szLink);
1395 sprintf(szIndex, "%d", dwIndex);
1396 if (RegQueryValueEx( hkFreelanceSymlinks, szIndex, 0, &dwType, szLink, &dwSize) != ERROR_SUCCESS) {
1397 /* found an unused value */
1399 dwSize = (DWORD)strlen(line) + 1;
1400 RegSetValueEx( hkFreelanceSymlinks, szIndex, 0, dwType, line, dwSize);
1403 int len = (int)strlen(filename);
1404 if ( dwType == REG_SZ && !strncmp(filename, szLink, len) && szLink[len] == ':') {
1405 /* Replace the existing value */
1407 dwSize = (DWORD)strlen(line) + 1;
1408 RegSetValueEx( hkFreelanceSymlinks, szIndex, 0, dwType, line, dwSize);
1413 RegCloseKey(hkFreelanceSymlinks);
1416 /* Do this while we are holding the lock */
1417 cm_noteLocalMountPointChange(TRUE);
1418 lock_ReleaseMutex(&cm_Freelance_Lock);
1424 clientchar_t *cpath;
1428 cpath = cm_FsStringToClientStringAlloc(filename, -1, NULL);
1430 code = CM_ERROR_NOSUCHPATH;
1432 if (cm_getLocalMountPointChange()) { // check for changes
1433 cm_clearLocalMountPointChange(); // clear the changefile
1434 cm_reInitLocalMountPoints(); // start reinit
1437 code = cm_NameI(cm_RootSCachep(cm_rootUserp, &req), cpath,
1438 CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD | CM_FLAG_DFS_REFERRAL,
1439 cm_rootUserp, NULL, &req, &scp);
1443 cm_ReleaseSCache(scp);
1451 long cm_FreelanceRemoveSymlink(char *toremove)
1455 char shortname[200];
1457 HKEY hkFreelanceSymlinks = 0;
1458 DWORD dwType, dwSize;
1462 lock_ObtainMutex(&cm_Freelance_Lock);
1464 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
1465 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance\\Symlinks",
1467 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
1468 &hkFreelanceSymlinks) == ERROR_SUCCESS) {
1470 RegQueryInfoKey( hkFreelanceSymlinks,
1472 NULL, /* lpcClass */
1473 NULL, /* lpReserved */
1474 NULL, /* lpcSubKeys */
1475 NULL, /* lpcMaxSubKeyLen */
1476 NULL, /* lpcMaxClassLen */
1477 &dwSymlinks, /* lpcValues */
1478 NULL, /* lpcMaxValueNameLen */
1479 NULL, /* lpcMaxValueLen */
1480 NULL, /* lpcbSecurityDescriptor */
1481 NULL /* lpftLastWriteTime */
1484 for ( dwIndex = 0; dwIndex < dwSymlinks; dwIndex++ ) {
1485 TCHAR szValueName[16];
1486 DWORD dwValueSize = 16;
1487 dwSize = sizeof(line);
1488 RegEnumValue( hkFreelanceSymlinks, dwIndex, szValueName, &dwValueSize, NULL,
1489 &dwType, line, &dwSize);
1491 cp=strchr(line, ':');
1492 memcpy(shortname, line, cp-line);
1493 shortname[cp-line]=0;
1495 if (!strcmp(shortname, toremove)) {
1496 RegDeleteValue( hkFreelanceSymlinks, szValueName );
1501 RegCloseKey(hkFreelanceSymlinks);
1505 /* Do this while we are holding the lock */
1506 cm_noteLocalMountPointChange(TRUE);
1508 lock_ReleaseMutex(&cm_Freelance_Lock);
1509 return (found ? 0 : CM_ERROR_NOSUCHFILE);
1513 cm_FreelanceFetchMountPointString(cm_scache_t *scp)
1515 lock_ObtainMutex(&cm_Freelance_Lock);
1516 if (!scp->mountPointStringp[0] &&
1517 scp->fid.cell == AFS_FAKE_ROOT_CELL_ID &&
1518 scp->fid.volume == AFS_FAKE_ROOT_VOL_ID &&
1519 scp->fid.unique <= cm_noLocalMountPoints) {
1520 strncpy(scp->mountPointStringp, cm_localMountPoints[scp->fid.unique-1].mountPointStringp, MOUNTPOINTLEN);
1521 scp->mountPointStringp[MOUNTPOINTLEN-1] = 0; /* null terminate */
1523 lock_ReleaseMutex(&cm_Freelance_Lock);
1529 cm_FreelanceFetchFileType(cm_scache_t *scp)
1531 lock_ObtainMutex(&cm_Freelance_Lock);
1532 if (scp->fid.cell == AFS_FAKE_ROOT_CELL_ID &&
1533 scp->fid.volume == AFS_FAKE_ROOT_VOL_ID &&
1534 scp->fid.unique <= cm_noLocalMountPoints)
1536 scp->fileType = cm_localMountPoints[scp->fid.unique-1].fileType;
1538 if ( scp->fileType == CM_SCACHETYPE_SYMLINK &&
1539 !strnicmp(cm_localMountPoints[scp->fid.unique-1].mountPointStringp, "msdfs:", strlen("msdfs:")) )
1541 scp->fileType = CM_SCACHETYPE_DFSLINK;
1544 scp->fileType = CM_SCACHETYPE_INVALID;
1546 lock_ReleaseMutex(&cm_Freelance_Lock);
1550 #endif /* AFS_FREELANCE_CLIENT */