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_freelanceDiscovery = 1;
35 int cm_freelanceImportCellServDB = 0;
36 time_t FakeFreelanceModTime = 0x3b49f6e2;
38 static int freelance_ShutdownFlag = 0;
39 static HANDLE hFreelanceChangeEvent = 0;
40 static HANDLE hFreelanceSymlinkChangeEvent = 0;
42 void cm_InitFakeRootDir();
44 void cm_FreelanceChangeNotifier(void * parmp) {
47 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
48 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance",
51 &hkFreelance) == ERROR_SUCCESS) {
53 hFreelanceChangeEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
54 if (hFreelanceChangeEvent == NULL) {
55 RegCloseKey(hkFreelance);
61 /* check hFreelanceChangeEvent to see if it is set.
62 * if so, call cm_noteLocalMountPointChange()
64 if (RegNotifyChangeKeyValue( hkFreelance, /* hKey */
65 FALSE, /* bWatchSubtree */
66 REG_NOTIFY_CHANGE_LAST_SET, /* dwNotifyFilter */
67 hFreelanceChangeEvent, /* hEvent */
68 TRUE /* fAsynchronous */
70 RegCloseKey(hkFreelance);
71 CloseHandle(hFreelanceChangeEvent);
72 hFreelanceChangeEvent = 0;
76 if (WaitForSingleObject(hFreelanceChangeEvent, INFINITE) == WAIT_OBJECT_0)
78 if (freelance_ShutdownFlag == 1) {
79 RegCloseKey(hkFreelance);
80 CloseHandle(hFreelanceChangeEvent);
81 hFreelanceChangeEvent = 0;
84 cm_noteLocalMountPointChange(FALSE);
89 void cm_FreelanceSymlinkChangeNotifier(void * parmp) {
92 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
93 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance\\Symlinks",
96 &hkFreelance) == ERROR_SUCCESS) {
98 hFreelanceSymlinkChangeEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
99 if (hFreelanceSymlinkChangeEvent == NULL) {
100 RegCloseKey(hkFreelance);
106 /* check hFreelanceSymlinkChangeEvent to see if it is set.
107 * if so, call cm_noteLocalMountPointSymlinkChange()
109 if (RegNotifyChangeKeyValue( hkFreelance, /* hKey */
110 FALSE, /* bWatchSubtree */
111 REG_NOTIFY_CHANGE_LAST_SET, /* dwNotifyFilter */
112 hFreelanceSymlinkChangeEvent, /* hEvent */
113 TRUE /* fAsynchronous */
114 ) != ERROR_SUCCESS) {
115 RegCloseKey(hkFreelance);
116 CloseHandle(hFreelanceSymlinkChangeEvent);
117 hFreelanceSymlinkChangeEvent = 0;
121 if (WaitForSingleObject(hFreelanceSymlinkChangeEvent, INFINITE) == WAIT_OBJECT_0)
123 if (freelance_ShutdownFlag == 1) {
124 RegCloseKey(hkFreelance);
125 CloseHandle(hFreelanceSymlinkChangeEvent);
126 hFreelanceSymlinkChangeEvent = 0;
129 cm_noteLocalMountPointChange(FALSE);
135 cm_FreelanceShutdown(void)
137 freelance_ShutdownFlag = 1;
138 if (hFreelanceChangeEvent != 0)
139 thrd_SetEvent(hFreelanceChangeEvent);
140 if (hFreelanceSymlinkChangeEvent != 0)
141 thrd_SetEvent(hFreelanceSymlinkChangeEvent);
145 cm_FreelanceAddCSDBMountPoints(void *rockp, char *cellNamep)
147 char szCellName[CELL_MAXNAMELEN+1] = ".";
149 cm_FsStrCpy( &szCellName[1], CELL_MAXNAMELEN, cellNamep);
150 /* create readonly mount point */
151 cm_FreelanceAddMount( cellNamep, cellNamep, "root.cell", 0, NULL);
153 /* create read/write mount point */
154 cm_FreelanceAddMount( szCellName, szCellName, "root.cell", 1, NULL);
160 cm_FreelanceImportCellServDB(void)
162 cm_EnumerateCellRegistry( TRUE, cm_FreelanceAddCSDBMountPoints, NULL);
163 cm_EnumerateCellFile( TRUE, cm_FreelanceAddCSDBMountPoints, NULL);
166 void cm_InitFreelance() {
170 lock_InitializeMutex(&cm_Freelance_Lock, "Freelance Lock", LOCK_HIERARCHY_FREELANCE_GLOBAL);
172 lock_ObtainMutex(&cm_Freelance_Lock);
174 // yj: first we make a call to cm_initLocalMountPoints
175 // to read all the local mount points from the registry
176 cm_InitLocalMountPoints();
178 // then we make a call to InitFakeRootDir to create
179 // a fake root directory based on the local mount points
180 cm_InitFakeRootDir();
182 // increment the fakeDirVersion to force status updates for
183 // all cached Freelance objects
184 cm_data.fakeDirVersion++;
185 // --- end of yj code
186 lock_ReleaseMutex(&cm_Freelance_Lock);
188 /* Start the registry monitor */
189 phandle = thrd_Create(NULL, 65536, (ThreadFunc) cm_FreelanceChangeNotifier,
190 NULL, 0, &lpid, "cm_FreelanceChangeNotifier");
191 osi_assertx(phandle != NULL, "cm_FreelanceChangeNotifier thread create failure");
192 thrd_CloseHandle(phandle);
194 phandle = thrd_Create(NULL, 65536, (ThreadFunc) cm_FreelanceSymlinkChangeNotifier,
195 NULL, 0, &lpid, "cm_FreelanceSymlinkChangeNotifier");
196 osi_assertx(phandle != NULL, "cm_FreelanceSymlinkChangeNotifier thread create failure");
197 thrd_CloseHandle(phandle);
200 /* yj: Initialization of the fake root directory */
201 /* to be called while holding freelance lock. */
202 void cm_InitFakeRootDir() {
207 // allocate space for the fake info
208 cm_dirHeader_t fakeDirHeader;
209 cm_dirEntry_t fakeEntry;
210 cm_pageHeader_t fakePageHeader;
212 // i'm going to calculate how much space is needed for
213 // this fake root directory. we have these rules:
214 // 1. there are cm_noLocalMountPoints number of entries
215 // 2. each page is CM_DIR_PAGESIZE in size
216 // 3. the first 13 chunks of the first page are used for
218 // 4. the first chunk of all subsequent pages are used
219 // for page header stuff
220 // 5. a max of CM_DIR_EPP entries are allowed per page
221 // 6. each entry takes 1 or more chunks, depending on
222 // the size of the mount point string, as determined
224 // 7. each chunk is CM_DIR_CHUNKSIZE bytes
226 int CPP = CM_DIR_PAGESIZE / CM_DIR_CHUNKSIZE;
227 int curChunk = 13; // chunks 0 - 12 are used for header stuff
228 // of the first page in the directory
230 unsigned int curDirEntry = 0;
231 int curDirEntryInPage = 0;
235 /* Increment the fake Uniquifier */
236 cm_data.fakeUnique++;
238 /* Reserve 2 directory chunks for "." and ".." */
241 while (curDirEntry<cm_noLocalMountPoints) {
242 sizeOfCurEntry = cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0);
243 if ((curChunk + sizeOfCurEntry >= CPP) ||
244 (curDirEntryInPage + 1 >= CM_DIR_EPP)) {
246 curDirEntryInPage = 0;
249 curChunk += sizeOfCurEntry;
254 dirSize = (curPage+1) * CM_DIR_PAGESIZE;
255 if (cm_fakeDirSize != dirSize) {
257 free(cm_FakeRootDir);
258 cm_FakeRootDir = calloc(dirSize, 1);
259 cm_fakeDirSize = dirSize;
262 // yj: when we get here, we've figured out how much memory we need and
263 // allocated the appropriate space for it. we now prceed to fill
264 // it up with entries.
267 curDirEntryInPage = 0;
270 // fields in the directory entry that are unused.
272 fakeEntry.length = 0;
274 fakeEntry.fid.unique = htonl(1 + cm_data.fakeUnique);
276 // the first page is special, it uses fakeDirHeader instead of fakePageHeader
277 // we fill up the page with dirEntries that belong there and we make changes
278 // to the fakeDirHeader.header.freeBitmap along the way. Then when we're done
279 // filling up the dirEntries in this page, we copy the fakeDirHeader into
280 // the top of the page.
282 // init the freeBitmap array
284 fakeDirHeader.header.freeBitmap[i]=0;
286 fakeDirHeader.header.freeBitmap[0] = 0xff;
287 fakeDirHeader.header.freeBitmap[1] = 0x7f;
290 // we start counting at 13 because the 0th to 12th chunks are used for header
293 // stick the first 2 entries "." and ".." in
294 fakeEntry.fid.vnode = htonl(1);
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++;
299 strcpy(fakeEntry.name, "..");
300 currentPos = cm_FakeRootDir + curPage * CM_DIR_PAGESIZE + curChunk * CM_DIR_CHUNKSIZE;
301 memcpy(currentPos, &fakeEntry, CM_DIR_CHUNKSIZE);
302 curChunk++; curDirEntryInPage++;
304 // keep putting stuff into page 0 if
305 // 1. we're not done with all entries
306 // 2. we have less than CM_DIR_EPP entries in page 0
307 // 3. we're not out of chunks in page 0
309 while( (curDirEntry<cm_noLocalMountPoints) &&
310 (curDirEntryInPage < CM_DIR_EPP) &&
311 (curChunk + cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0) <= CPP))
314 noChunks = cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0);
315 /* enforce the rule that only directories have odd vnode values */
316 fakeEntry.fid.vnode = htonl((curDirEntry + 1) * 2);
317 fakeEntry.fid.unique = htonl(curDirEntry + 1 + cm_data.fakeUnique);
318 currentPos = cm_FakeRootDir + curPage * CM_DIR_PAGESIZE + curChunk * CM_DIR_CHUNKSIZE;
320 memcpy(currentPos, &fakeEntry, CM_DIR_CHUNKSIZE);
321 strcpy(currentPos + 12, (cm_localMountPoints+curDirEntry)->namep);
324 for (i=0; i<noChunks; i++) {
325 t1 = (curChunk + i) / 8;
326 t2 = curChunk + i - (t1*8);
327 fakeDirHeader.header.freeBitmap[t1] |= (1 << t2);
332 // when we get here, we're done with filling in the entries for page 0
333 // copy in the header info
335 memcpy(cm_FakeRootDir, &fakeDirHeader, 13 * CM_DIR_CHUNKSIZE);
339 // ok, page 0's done. Move on to the next page.
340 while (curDirEntry<cm_noLocalMountPoints) {
342 curChunk = 1; // the zeroth chunk is reserved for page header
343 curDirEntryInPage = 0;
344 for (i=0; i<8; i++) {
345 fakePageHeader.freeBitmap[i]=0;
347 fakePageHeader.freeCount = 0;
348 fakePageHeader.pgcount = 0;
349 fakePageHeader.tag = htons(1234);
351 // while we're on the same page...
352 while ( (curDirEntry<cm_noLocalMountPoints) &&
353 (curDirEntryInPage < CM_DIR_EPP) &&
354 (curChunk + cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0) <= CPP))
356 // add an entry to this page
358 noChunks = cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0);
359 /* enforce the rule that only directories have odd vnode values */
360 fakeEntry.fid.vnode = htonl((curDirEntry + 1) * 2);
361 fakeEntry.fid.unique = htonl(curDirEntry + 1 + cm_data.fakeUnique);
362 currentPos = cm_FakeRootDir + curPage * CM_DIR_PAGESIZE + curChunk * CM_DIR_CHUNKSIZE;
363 memcpy(currentPos, &fakeEntry, CM_DIR_CHUNKSIZE);
364 strcpy(currentPos + 12, (cm_localMountPoints+curDirEntry)->namep);
367 for (i=0; i<noChunks; i++) {
368 t1 = (curChunk + i) / 8;
369 t2 = curChunk + i - (t1*8);
370 fakePageHeader.freeBitmap[t1] |= (1 << t2);
374 memcpy(cm_FakeRootDir + curPage * CM_DIR_PAGESIZE, &fakePageHeader, sizeof(fakePageHeader));
379 // we know the fakeDir is setup properly, so we claim that we have callback
380 osi_Log0(afsd_logp,"cm_InitFakeRootDir completed!");
382 // when we get here, we've set up everything! done!
385 int cm_FakeRootFid(cm_fid_t *fidp)
388 AFS_FAKE_ROOT_CELL_ID, /* root cell */
389 AFS_FAKE_ROOT_VOL_ID, /* root.afs ? */
394 /* called directly from ioctl */
395 /* called while not holding freelance lock */
396 int cm_noteLocalMountPointChange(afs_int32 locked) {
398 lock_ObtainMutex(&cm_Freelance_Lock);
399 cm_data.fakeDirVersion++;
400 cm_localMountPointChangeFlag = 1;
403 lock_ReleaseMutex(&cm_Freelance_Lock);
405 if (RDR_Initialized) {
407 cm_FakeRootFid(&fid);
408 RDR_InvalidateObject( fid.cell, fid.volume, fid.vnode, fid.unique, fid.hash,
409 CM_SCACHETYPE_DIRECTORY,
410 AFS_INVALIDATE_DATA_VERSION);
415 int cm_getLocalMountPointChange() {
416 return cm_localMountPointChangeFlag;
419 int cm_clearLocalMountPointChange() {
420 cm_localMountPointChangeFlag = 0;
424 int cm_reInitLocalMountPoints() {
426 unsigned int i, hash;
427 cm_scache_t *scp, **lscpp, *tscp;
432 osi_Log0(afsd_logp,"----- freelance reinitialization starts ----- ");
434 // first we invalidate all the SCPs that were created
435 // for the local mount points
437 osi_Log0(afsd_logp,"Invalidating local mount point scp... ");
439 lock_ObtainWrite(&cm_scacheLock);
440 lock_ObtainMutex(&cm_Freelance_Lock); /* always scache then freelance lock */
441 for (i=0; i<=cm_noLocalMountPoints; i++) {
443 cm_SetFid(&aFid, AFS_FAKE_ROOT_CELL_ID, AFS_FAKE_ROOT_VOL_ID, 1, 1);
445 cm_SetFid(&aFid, AFS_FAKE_ROOT_CELL_ID, AFS_FAKE_ROOT_VOL_ID, i*2, i);
446 hash = CM_SCACHE_HASH(&aFid);
447 for (scp=cm_data.scacheHashTablep[hash]; scp; scp=scp->nextp) {
448 if (scp != cm_data.rootSCachep && cm_FidCmp(&scp->fid, &aFid) == 0) {
449 // mark the scp to be reused
450 cm_HoldSCacheNoLock(scp);
451 lock_ReleaseMutex(&cm_Freelance_Lock);
452 lock_ReleaseWrite(&cm_scacheLock);
453 lock_ObtainWrite(&scp->rw);
454 cm_DiscardSCache(scp);
456 // take the scp out of the hash
457 lock_ObtainWrite(&cm_scacheLock);
458 for (lscpp = &cm_data.scacheHashTablep[hash], tscp = cm_data.scacheHashTablep[hash];
460 lscpp = &tscp->nextp, tscp = tscp->nextp) {
464 scp->flags &= ~CM_SCACHEFLAG_INHASH;
469 lock_ReleaseWrite(&scp->rw);
470 lock_ReleaseWrite(&cm_scacheLock);
471 cm_CallbackNotifyChange(scp);
474 RDR_InvalidateObject(scp->fid.cell, scp->fid.volume, scp->fid.vnode, scp->fid.unique,
475 scp->fid.hash, scp->fileType, AFS_INVALIDATE_CALLBACK);
477 lock_ObtainWrite(&cm_scacheLock);
478 cm_ReleaseSCacheNoLock(scp);
479 lock_ObtainMutex(&cm_Freelance_Lock);
483 lock_ReleaseWrite(&cm_scacheLock);
484 lock_ReleaseMutex(&cm_Freelance_Lock);
485 osi_Log0(afsd_logp,"\tall old scp cleared!");
487 lock_ObtainWrite(&cm_data.rootSCachep->rw);
488 lock_ObtainMutex(&cm_Freelance_Lock);
489 // we must free the memory that was allocated in the prev
490 // cm_InitLocalMountPoints call
491 osi_Log0(afsd_logp,"Removing old localmountpoints... ");
492 free(cm_localMountPoints);
493 cm_localMountPoints = NULL;
494 cm_noLocalMountPoints = 0;
495 osi_Log0(afsd_logp,"\tall old localmountpoints cleared!");
497 // now re-init the localmountpoints
498 osi_Log0(afsd_logp,"Creating new localmountpoints... ");
499 cm_InitLocalMountPoints();
500 osi_Log0(afsd_logp,"\tcreated new set of localmountpoints!");
502 // then we re-create that dir
503 osi_Log0(afsd_logp,"Creating new fakedir... ");
504 cm_InitFakeRootDir();
505 osi_Log0(afsd_logp,"\t\tcreated new fakedir!");
507 lock_ReleaseMutex(&cm_Freelance_Lock);
509 cm_GetCallback(cm_data.rootSCachep, cm_rootUserp, &req, 0);
510 lock_ReleaseWrite(&cm_data.rootSCachep->rw);
512 osi_Log0(afsd_logp,"----- freelance reinit complete -----");
517 * cm_enforceTrailingDot
519 * return 0 on failure, non-zero on success
523 cm_enforceTrailingDot(char * line, size_t cchLine, DWORD *pdwSize)
526 afsi_log("invalid string");
530 /* trailing white space first. */
531 if (line[(*pdwSize)-1] == '\0') {
532 while (isspace(line[(*pdwSize)-2])) {
533 line[(*pdwSize)-2] = '\0';
537 while (isspace(line[(*pdwSize)-1])) {
538 line[(*pdwSize)-1] = '\0';
543 /* then enforce the trailing dot requirement */
544 if (line[(*pdwSize)-1] == '\0' && line[(*pdwSize)-2] != '.') {
545 if ((*pdwSize) >= cchLine) {
546 afsi_log("no room for trailing dot");
549 line[(*pdwSize)-1] = '.';
550 line[(*pdwSize)] = '\0';
551 } else if (line[(*pdwSize)-1] != '\0' && line[(*pdwSize)-1] != '.') {
552 if ((*pdwSize) >= cchLine) {
553 afsi_log("no room for trailing dot and nul");
556 line[(*pdwSize)] = '.';
557 line[(*pdwSize)+1] = '\0';
558 } else if (line[(*pdwSize)-1] != '\0') {
559 if ((*pdwSize) >= cchLine) {
560 afsi_log("no room for trailing nul");
563 line[(*pdwSize)] = '\0';
569 // yj: open up the registry and read all the local mount
570 // points that are stored there. Part of the initialization
571 // process for the freelance client.
572 /* to be called while holding freelance lock. */
573 long cm_InitLocalMountPoints() {
578 cm_localMountPoint_t* aLocalMountPoint;
581 char rootCellName[256];
582 HKEY hkFreelance = 0, hkFreelanceSymlinks = 0;
583 DWORD dwType, dwSize;
584 DWORD dwMountPoints = 0;
586 DWORD dwSymlinks = 0;
587 FILETIME ftLastWriteTime;
589 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
590 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance",
592 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
593 &hkFreelance) == ERROR_SUCCESS) {
595 RegQueryInfoKey( hkFreelance,
598 NULL, /* lpReserved */
599 NULL, /* lpcSubKeys */
600 NULL, /* lpcMaxSubKeyLen */
601 NULL, /* lpcMaxClassLen */
602 &dwMountPoints, /* lpcValues */
603 NULL, /* lpcMaxValueNameLen */
604 NULL, /* lpcMaxValueLen */
605 NULL, /* lpcbSecurityDescriptor */
606 &ftLastWriteTime /* lpftLastWriteTime */
609 cm_UnixTimeFromLargeSearchTime(&FakeFreelanceModTime, &ftLastWriteTime);
611 if ( dwMountPoints == 0 ) {
612 rootCellName[0] = '.';
613 code = cm_GetRootCellName(&rootCellName[1]);
615 lock_ReleaseMutex(&cm_Freelance_Lock);
616 cm_FreelanceAddMount(&rootCellName[1], &rootCellName[1], "root.cell", 0, NULL);
617 cm_FreelanceAddMount(rootCellName, &rootCellName[1], "root.cell", 1, NULL);
618 cm_FreelanceAddMount(".root", &rootCellName[1], "root.afs", 1, NULL);
619 lock_ObtainMutex(&cm_Freelance_Lock);
624 if (RegCreateKeyEx( HKEY_LOCAL_MACHINE,
625 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance\\Symlinks",
628 REG_OPTION_NON_VOLATILE,
629 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
631 &hkFreelanceSymlinks,
632 NULL) == ERROR_SUCCESS) {
634 RegQueryInfoKey( hkFreelanceSymlinks,
637 NULL, /* lpReserved */
638 NULL, /* lpcSubKeys */
639 NULL, /* lpcMaxSubKeyLen */
640 NULL, /* lpcMaxClassLen */
641 &dwSymlinks, /* lpcValues */
642 NULL, /* lpcMaxValueNameLen */
643 NULL, /* lpcMaxValueLen */
644 NULL, /* lpcbSecurityDescriptor */
645 NULL /* lpftLastWriteTime */
649 // get the number of entries there are from the first line
651 cm_noLocalMountPoints = dwMountPoints + dwSymlinks;
653 // create space to store the local mount points
654 cm_localMountPoints = malloc(sizeof(cm_localMountPoint_t) * cm_noLocalMountPoints);
655 aLocalMountPoint = cm_localMountPoints;
657 // now we read n lines and parse them into local mount points
658 // where n is the number of local mount points there are, as
660 // Each line in the ini file represents 1 local mount point and
661 // is in the format xxx#yyy:zzz, where xxx is the directory
662 // entry name, yyy is the cell name and zzz is the volume name.
663 // #yyy:zzz together make up the mount point.
664 for ( dwIndex = 0 ; dwIndex < dwMountPoints; dwIndex++ ) {
665 TCHAR szValueName[16];
666 DWORD dwValueSize = 16;
667 dwSize = sizeof(line);
668 if (RegEnumValue( hkFreelance, dwIndex, szValueName, &dwValueSize, NULL,
669 &dwType, line, &dwSize))
671 afsi_log("RegEnumValue(hkFreelance) failed");
672 cm_noLocalMountPoints--;
676 /* make sure there is a trailing dot and a nul terminator */
677 if (!cm_enforceTrailingDot(line, sizeof(line), &dwSize)) {
678 cm_noLocalMountPoints--;
682 afsi_log("Mountpoint[%d] = %s", dwIndex, line);
684 for ( t=line;*t;t++ ) {
685 if ( !isprint(*t) ) {
686 afsi_log("error occurred while parsing mountpoint entry [%d]: non-printable character", dwIndex);
687 fprintf(stderr, "error occurred while parsing mountpoint entry [%d]: non-printable character", dwIndex);
688 cm_noLocalMountPoints--;
693 // line is not empty, so let's parse it
694 t = strchr(line, '#');
696 t = strchr(line, '%');
697 // make sure that there is a '#' or '%' separator in the line
699 afsi_log("error occurred while parsing mountpoint entry [%d]: no # or %% separator", dwIndex);
700 fprintf(stderr, "error occurred while parsing mountpoint entry [%d]: no # or %% separator", dwIndex);
701 cm_noLocalMountPoints--;
705 aLocalMountPoint->fileType = CM_SCACHETYPE_MOUNTPOINT;
706 aLocalMountPoint->namep=malloc(t-line+1);
707 strncpy(aLocalMountPoint->namep, line, t-line);
708 aLocalMountPoint->namep[t-line] = '\0';
710 /* copy the mount point string */
711 aLocalMountPoint->mountPointStringp=malloc(strlen(t));
712 strncpy(aLocalMountPoint->mountPointStringp, t, strlen(t)-1);
713 aLocalMountPoint->mountPointStringp[strlen(t)-1] = '\0';
715 osi_Log2(afsd_logp,"found mount point: name %s, string %s",
716 osi_LogSaveString(afsd_logp,aLocalMountPoint->namep),
717 osi_LogSaveString(afsd_logp,aLocalMountPoint->mountPointStringp));
722 for ( dwIndex = 0 ; dwIndex < dwSymlinks; dwIndex++ ) {
723 TCHAR szValueName[16];
724 DWORD dwValueSize = 16;
725 dwSize = sizeof(line);
726 if (RegEnumValue( hkFreelanceSymlinks, dwIndex, szValueName, &dwValueSize, NULL,
727 &dwType, line, &dwSize))
729 afsi_log("RegEnumValue(hkFreelanceSymlinks) failed");
730 cm_noLocalMountPoints--;
734 /* make sure there is a trailing dot and a nul terminator */
735 if (!cm_enforceTrailingDot(line, sizeof(line), &dwSize)) {
736 cm_noLocalMountPoints--;
740 afsi_log("Symlink[%d] = %s", dwIndex, line);
742 for ( t=line;*t;t++ ) {
743 if ( !isprint(*t) ) {
744 afsi_log("error occurred while parsing symlink entry [%d]: non-printable character", dwIndex);
745 fprintf(stderr, "error occurred while parsing symlink entry [%d]: non-printable character", dwIndex);
746 cm_noLocalMountPoints--;
751 // line is not empty, so let's parse it
752 t = strchr(line, ':');
754 // make sure that there is a ':' separator in the line
756 afsi_log("error occurred while parsing symlink entry [%d]: no ':' separator", dwIndex);
757 fprintf(stderr, "error occurred while parsing symlink entry [%d]: no ':' separator", dwIndex);
758 cm_noLocalMountPoints--;
762 aLocalMountPoint->fileType = CM_SCACHETYPE_SYMLINK;
763 aLocalMountPoint->namep=malloc(t-line+1);
764 strncpy(aLocalMountPoint->namep, line, t-line);
765 aLocalMountPoint->namep[t-line] = '\0';
767 /* copy the symlink string */
768 aLocalMountPoint->mountPointStringp=malloc(strlen(t)-1);
769 strncpy(aLocalMountPoint->mountPointStringp, t+1, strlen(t)-2);
770 aLocalMountPoint->mountPointStringp[strlen(t)-2] = '\0';
772 osi_Log2(afsd_logp,"found symlink: name %s, string %s",
773 osi_LogSaveString(afsd_logp,aLocalMountPoint->namep),
774 osi_LogSaveString(afsd_logp,aLocalMountPoint->mountPointStringp));
779 if ( hkFreelanceSymlinks )
780 RegCloseKey( hkFreelanceSymlinks );
781 RegCloseKey(hkFreelance);
785 /* What follows is the old code to read freelance mount points
786 * out of a text file modified to copy the data into the registry
788 cm_GetConfigDir(hdir, sizeof(hdir));
789 strcat(hdir, AFS_FREELANCE_INI);
790 // open the ini file for reading
791 fp = fopen(hdir, "r");
793 /* look in the Windows directory where we used to store the file */
794 GetWindowsDirectory(hdir, sizeof(hdir));
796 strcat(hdir, AFS_FREELANCE_INI);
797 fp = fopen(hdir, "r");
800 RegCreateKeyEx( HKEY_LOCAL_MACHINE,
801 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance",
804 REG_OPTION_NON_VOLATILE,
812 RegCloseKey(hkFreelance);
813 rootCellName[0] = '.';
814 code = cm_GetRootCellName(&rootCellName[1]);
816 lock_ReleaseMutex(&cm_Freelance_Lock);
817 cm_FreelanceAddMount(&rootCellName[1], &rootCellName[1], "root.cell", 0, NULL);
818 cm_FreelanceAddMount(rootCellName, &rootCellName[1], "root.cell", 1, NULL);
819 cm_FreelanceAddMount(".root", &rootCellName[1], "root.afs", 1, NULL);
820 lock_ObtainMutex(&cm_Freelance_Lock);
825 // we successfully opened the file
826 osi_Log0(afsd_logp,"opened afs_freelance.ini");
828 // now we read the first line to see how many entries
830 fgets(line, sizeof(line), fp);
832 // if the line is empty at any point when we're reading
833 // we're screwed. report error and return.
835 afsi_log("error occurred while reading afs_freelance.ini");
836 fprintf(stderr, "error occurred while reading afs_freelance.ini");
840 // get the number of entries there are from the first line
842 cm_noLocalMountPoints = atoi(line);
844 if (cm_noLocalMountPoints > 0) {
845 // create space to store the local mount points
846 cm_localMountPoints = malloc(sizeof(cm_localMountPoint_t) * cm_noLocalMountPoints);
847 aLocalMountPoint = cm_localMountPoints;
850 // now we read n lines and parse them into local mount points
851 // where n is the number of local mount points there are, as
853 // Each line in the ini file represents 1 local mount point and
854 // is in the format xxx#yyy:zzz, where xxx is the directory
855 // entry name, yyy is the cell name and zzz is the volume name.
856 // #yyy:zzz together make up the mount point.
857 for (i=0; i<cm_noLocalMountPoints; i++) {
858 fgets(line, sizeof(line), fp);
859 // check that the line is not empty
861 afsi_log("error occurred while parsing entry in %s: empty line in line %d", AFS_FREELANCE_INI, i);
862 fprintf(stderr, "error occurred while parsing entry in afs_freelance.ini: empty line in line %d", i);
866 /* find the trailing dot; null terminate after it */
867 t2 = strrchr(line, '.');
873 /* we are migrating to the registry */
874 sprintf(szIndex,"%d",dwIndex++);
876 dwSize = (DWORD)strlen(line) + 1;
877 RegSetValueEx( hkFreelance, szIndex, 0, dwType, line, dwSize);
880 // line is not empty, so let's parse it
881 t = strchr(line, '#');
883 t = strchr(line, '%');
884 // make sure that there is a '#' or '%' separator in the line
886 afsi_log("error occurred while parsing entry in %s: no # or %% separator in line %d", AFS_FREELANCE_INI, i);
887 fprintf(stderr, "error occurred while parsing entry in afs_freelance.ini: no # or %% separator in line %d", i);
890 aLocalMountPoint->namep=malloc(t-line+1);
891 memcpy(aLocalMountPoint->namep, line, t-line);
892 *(aLocalMountPoint->namep + (t-line)) = 0;
894 aLocalMountPoint->mountPointStringp=malloc(strlen(line) - (t-line) + 1);
895 memcpy(aLocalMountPoint->mountPointStringp, t, strlen(line)-(t-line)-1);
896 *(aLocalMountPoint->mountPointStringp + (strlen(line)-(t-line)-1)) = 0;
898 osi_Log2(afsd_logp,"found mount point: name %s, string %s",
899 aLocalMountPoint->namep,
900 aLocalMountPoint->mountPointStringp);
906 RegCloseKey(hkFreelance);
912 int cm_getNoLocalMountPoints() {
913 return cm_noLocalMountPoints;
916 long cm_FreelanceMountPointExists(char * filename, int prefix_ok)
922 HKEY hkFreelance = 0;
923 DWORD dwType, dwSize;
927 lock_ObtainMutex(&cm_Freelance_Lock);
929 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
930 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance",
932 KEY_READ|KEY_QUERY_VALUE,
933 &hkFreelance) == ERROR_SUCCESS)
935 RegQueryInfoKey( hkFreelance,
938 NULL, /* lpReserved */
939 NULL, /* lpcSubKeys */
940 NULL, /* lpcMaxSubKeyLen */
941 NULL, /* lpcMaxClassLen */
942 &dwMountPoints, /* lpcValues */
943 NULL, /* lpcMaxValueNameLen */
944 NULL, /* lpcMaxValueLen */
945 NULL, /* lpcbSecurityDescriptor */
946 NULL /* lpftLastWriteTime */
949 for ( dwIndex = 0; dwIndex < dwMountPoints; dwIndex++ ) {
950 TCHAR szValueName[16];
951 DWORD dwValueSize = 16;
952 dwSize = sizeof(line);
953 RegEnumValue( hkFreelance, dwIndex, szValueName, &dwValueSize, NULL,
954 &dwType, line, &dwSize);
956 cp=strchr(line, '#');
958 cp=strchr(line, '%');
959 memcpy(shortname, line, cp-line);
960 shortname[cp-line]=0;
962 if (!strcmp(shortname, filename)) {
967 for ( dwIndex = 0; dwIndex < dwMountPoints; dwIndex++ ) {
968 TCHAR szValueName[16];
969 DWORD dwValueSize = 16;
970 dwSize = sizeof(line);
971 RegEnumValue( hkFreelance, dwIndex, szValueName, &dwValueSize, NULL,
972 &dwType, line, &dwSize);
974 cp=strchr(line, '#');
976 cp=strchr(line, '%');
977 memcpy(shortname, line, cp-line);
978 shortname[cp-line]=0;
980 if (!cm_stricmp_utf8(shortname, filename)) {
985 if (prefix_ok && strlen(shortname) - strlen(filename) == 1 && !strncmp(shortname, filename, strlen(filename))) {
990 RegCloseKey(hkFreelance);
993 lock_ReleaseMutex(&cm_Freelance_Lock);
998 long cm_FreelanceSymlinkExists(char * filename, int prefix_ok)
1002 char shortname[200];
1004 HKEY hkFreelance = 0;
1005 DWORD dwType, dwSize;
1009 lock_ObtainMutex(&cm_Freelance_Lock);
1011 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
1012 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance\\Symlinks",
1014 KEY_READ|KEY_QUERY_VALUE,
1015 &hkFreelance) == ERROR_SUCCESS)
1017 RegQueryInfoKey( hkFreelance,
1019 NULL, /* lpcClass */
1020 NULL, /* lpReserved */
1021 NULL, /* lpcSubKeys */
1022 NULL, /* lpcMaxSubKeyLen */
1023 NULL, /* lpcMaxClassLen */
1024 &dwSymlinks, /* lpcValues */
1025 NULL, /* lpcMaxValueNameLen */
1026 NULL, /* lpcMaxValueLen */
1027 NULL, /* lpcbSecurityDescriptor */
1028 NULL /* lpftLastWriteTime */
1031 for ( dwIndex = 0; dwIndex < dwSymlinks; dwIndex++ ) {
1032 TCHAR szValueName[16];
1033 DWORD dwValueSize = 16;
1034 dwSize = sizeof(line);
1035 RegEnumValue( hkFreelance, dwIndex, szValueName, &dwValueSize, NULL,
1036 &dwType, line, &dwSize);
1038 cp=strchr(line, ':');
1039 memcpy(shortname, line, cp-line);
1040 shortname[cp-line]=0;
1042 if (!strcmp(shortname, filename)) {
1047 if (prefix_ok && strlen(shortname) - strlen(filename) == 1 && !strncmp(shortname, filename, strlen(filename))) {
1052 for ( dwIndex = 0; dwIndex < dwSymlinks; dwIndex++ ) {
1053 TCHAR szValueName[16];
1054 DWORD dwValueSize = 16;
1055 dwSize = sizeof(line);
1056 RegEnumValue( hkFreelance, dwIndex, szValueName, &dwValueSize, NULL,
1057 &dwType, line, &dwSize);
1059 cp=strchr(line, ':');
1060 memcpy(shortname, line, cp-line);
1061 shortname[cp-line]=0;
1063 if (!cm_stricmp_utf8(shortname, filename)) {
1068 RegCloseKey(hkFreelance);
1071 lock_ReleaseMutex(&cm_Freelance_Lock);
1076 long cm_FreelanceAddMount(char *filename, char *cellname, char *volume, int rw, cm_fid_t *fidp)
1081 char fullname[CELL_MAXNAMELEN];
1084 HKEY hkFreelance = 0;
1085 DWORD dwType, dwSize;
1086 DWORD dwMountPoints;
1088 afs_uint32 code = 0;
1090 /* before adding, verify the cell name; if it is not a valid cell,
1091 don't add the mount point.
1092 allow partial matches as a means of poor man's alias. */
1093 /* major performance issue? */
1094 osi_Log4(afsd_logp,"Freelance Add Mount request: filename=%s cellname=%s volume=%s %s",
1095 osi_LogSaveString(afsd_logp,filename),
1096 osi_LogSaveString(afsd_logp,cellname),
1097 osi_LogSaveString(afsd_logp,volume),
1100 if ( filename[0] == '\0' || cellname[0] == '\0' || volume[0] == '\0' )
1101 return CM_ERROR_INVAL;
1103 if ( cm_FreelanceMountPointExists(filename, 0) ||
1104 cm_FreelanceSymlinkExists(filename, 0) ) {
1105 code = CM_ERROR_EXISTS;
1109 if (cellname[0] == '.') {
1110 if (!cm_GetCell_Gen(&cellname[1], fullname, CM_FLAG_CREATE))
1111 return CM_ERROR_INVAL;
1113 if (!cm_GetCell_Gen(cellname, fullname, CM_FLAG_CREATE))
1114 return CM_ERROR_INVAL;
1117 osi_Log1(afsd_logp,"Freelance Adding Mount for Cell: %s",
1118 osi_LogSaveString(afsd_logp,cellname));
1120 lock_ObtainMutex(&cm_Freelance_Lock);
1122 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
1123 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance",
1125 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
1126 &hkFreelance) == ERROR_SUCCESS) {
1128 RegQueryInfoKey( hkFreelance,
1130 NULL, /* lpcClass */
1131 NULL, /* lpReserved */
1132 NULL, /* lpcSubKeys */
1133 NULL, /* lpcMaxSubKeyLen */
1134 NULL, /* lpcMaxClassLen */
1135 &dwMountPoints, /* lpcValues */
1136 NULL, /* lpcMaxValueNameLen */
1137 NULL, /* lpcMaxValueLen */
1138 NULL, /* lpcbSecurityDescriptor */
1139 NULL /* lpftLastWriteTime */
1143 sprintf(line, "%s%%%s:%s.", filename, fullname, volume);
1145 sprintf(line, "%s#%s:%s.", filename, fullname, volume);
1147 /* If we are adding a new value, there must be an unused name
1148 * within the range 0 to dwMountPoints
1150 for ( dwIndex = 0; dwIndex <= dwMountPoints; dwIndex++ ) {
1154 dwSize = sizeof(szMount);
1155 sprintf(szIndex, "%d", dwIndex);
1156 if (RegQueryValueEx( hkFreelance, szIndex, 0, &dwType, szMount, &dwSize) != ERROR_SUCCESS) {
1157 /* found an unused value */
1159 dwSize = (DWORD)strlen(line) + 1;
1160 RegSetValueEx( hkFreelance, szIndex, 0, dwType, line, dwSize);
1163 int len = (int)strlen(filename);
1164 if ( dwType == REG_SZ && !strncmp(filename, szMount, len) &&
1165 (szMount[len] == '%' || szMount[len] == '#')) {
1166 /* Replace the existing value */
1168 dwSize = (DWORD)strlen(line) + 1;
1169 RegSetValueEx( hkFreelance, szIndex, 0, dwType, line, dwSize);
1174 RegCloseKey(hkFreelance);
1177 cm_GetConfigDir(hfile, sizeof(hfile));
1178 strcat(hfile, AFS_FREELANCE_INI);
1179 fp = fopen(hfile, "r+");
1181 return CM_ERROR_INVAL;
1182 fgets(line, sizeof(line), fp);
1185 fseek(fp, 0, SEEK_SET);
1186 fprintf(fp, "%d", n);
1187 fseek(fp, 0, SEEK_END);
1189 fprintf(fp, "%s%%%s:%s.\n", filename, fullname, volume);
1191 fprintf(fp, "%s#%s:%s.\n", filename, fullname, volume);
1195 /* Do this while we are holding the lock */
1196 cm_noteLocalMountPointChange(TRUE);
1197 lock_ReleaseMutex(&cm_Freelance_Lock);
1203 clientchar_t *cpath;
1207 cpath = cm_FsStringToClientStringAlloc(filename, -1, NULL);
1209 return CM_ERROR_NOSUCHPATH;
1211 if (cm_getLocalMountPointChange()) { // check for changes
1212 cm_clearLocalMountPointChange(); // clear the changefile
1213 cm_reInitLocalMountPoints(); // start reinit
1216 code = cm_NameI(cm_RootSCachep(cm_rootUserp, &req), cpath,
1217 CM_FLAG_DIRSEARCH | CM_FLAG_CASEFOLD,
1218 cm_rootUserp, NULL, &req, &scp);
1223 cm_ReleaseSCache(scp);
1229 long cm_FreelanceRemoveMount(char *toremove)
1234 char shortname[200];
1235 char hfile[260], hfile2[260];
1238 HKEY hkFreelance = 0;
1239 DWORD dwType, dwSize;
1240 DWORD dwMountPoints;
1243 lock_ObtainMutex(&cm_Freelance_Lock);
1245 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
1246 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance",
1248 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
1249 &hkFreelance) == ERROR_SUCCESS) {
1251 RegQueryInfoKey( hkFreelance,
1253 NULL, /* lpcClass */
1254 NULL, /* lpReserved */
1255 NULL, /* lpcSubKeys */
1256 NULL, /* lpcMaxSubKeyLen */
1257 NULL, /* lpcMaxClassLen */
1258 &dwMountPoints, /* lpcValues */
1259 NULL, /* lpcMaxValueNameLen */
1260 NULL, /* lpcMaxValueLen */
1261 NULL, /* lpcbSecurityDescriptor */
1262 NULL /* lpftLastWriteTime */
1265 for ( dwIndex = 0; dwIndex < dwMountPoints; dwIndex++ ) {
1266 TCHAR szValueName[16];
1267 DWORD dwValueSize = 16;
1268 dwSize = sizeof(line);
1269 RegEnumValue( hkFreelance, dwIndex, szValueName, &dwValueSize, NULL,
1270 &dwType, line, &dwSize);
1272 cp=strchr(line, '#');
1274 cp=strchr(line, '%');
1275 memcpy(shortname, line, cp-line);
1276 shortname[cp-line]=0;
1278 if (!strcmp(shortname, toremove)) {
1279 RegDeleteValue( hkFreelance, szValueName );
1284 RegCloseKey(hkFreelance);
1287 cm_GetConfigDir(hfile, sizeof(hfile));
1288 strcat(hfile, AFS_FREELANCE_INI);
1289 strcpy(hfile2, hfile);
1290 strcat(hfile2, "2");
1291 fp1=fopen(hfile, "r+");
1293 return CM_ERROR_INVAL;
1294 fp2=fopen(hfile2, "w+");
1297 return CM_ERROR_INVAL;
1300 fgets(line, sizeof(line), fp1);
1302 fprintf(fp2, "%d\n", n-1);
1304 for (i=0; i<n; i++) {
1305 fgets(line, sizeof(line), fp1);
1306 cp=strchr(line, '#');
1308 cp=strchr(line, '%');
1309 memcpy(shortname, line, cp-line);
1310 shortname[cp-line]=0;
1312 if (strcmp(shortname, toremove)==0) {
1324 rename(hfile2, hfile);
1329 /* Do this while we are holding the lock */
1330 cm_noteLocalMountPointChange(TRUE);
1332 lock_ReleaseMutex(&cm_Freelance_Lock);
1333 return (found ? 0 : CM_ERROR_NOSUCHFILE);
1336 long cm_FreelanceAddSymlink(char *filename, char *destination, cm_fid_t *fidp)
1339 char fullname[CELL_MAXNAMELEN] = "";
1341 HKEY hkFreelanceSymlinks = 0;
1342 DWORD dwType, dwSize;
1345 afs_uint32 code = 0;
1348 * before adding, verify the filename. If it is already in use, either as
1349 * as mount point or a cellname, do not permit the creation of the symlink.
1351 osi_Log2(afsd_logp,"Freelance Add Symlink request: filename=%s destination=%s",
1352 osi_LogSaveString(afsd_logp,filename),
1353 osi_LogSaveString(afsd_logp,destination));
1355 if ( filename[0] == '\0' || destination[0] == '\0' )
1356 return CM_ERROR_INVAL;
1358 /* Do not create the symlink if the name ends in a dot */
1359 if ( filename[strlen(filename)-1] == '.')
1360 return CM_ERROR_INVAL;
1362 if ( cm_FreelanceMountPointExists(filename, 0) ||
1363 cm_FreelanceSymlinkExists(filename, 0) ) {
1364 code = CM_ERROR_EXISTS;
1368 if (filename[0] == '.') {
1369 cm_GetCell_Gen(&filename[1], fullname, CM_FLAG_CREATE);
1370 if (cm_stricmp_utf8(&filename[1],fullname) == 0) {
1371 code = CM_ERROR_EXISTS;
1375 cm_GetCell_Gen(filename, fullname, CM_FLAG_CREATE);
1376 if (cm_stricmp_utf8(filename,fullname) == 0) {
1377 code = CM_ERROR_EXISTS;
1382 lock_ObtainMutex(&cm_Freelance_Lock);
1384 if (RegCreateKeyEx( HKEY_LOCAL_MACHINE,
1385 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance\\Symlinks",
1388 REG_OPTION_NON_VOLATILE,
1389 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
1391 &hkFreelanceSymlinks,
1392 NULL) == ERROR_SUCCESS) {
1394 RegQueryInfoKey( hkFreelanceSymlinks,
1396 NULL, /* lpcClass */
1397 NULL, /* lpReserved */
1398 NULL, /* lpcSubKeys */
1399 NULL, /* lpcMaxSubKeyLen */
1400 NULL, /* lpcMaxClassLen */
1401 &dwSymlinks, /* lpcValues */
1402 NULL, /* lpcMaxValueNameLen */
1403 NULL, /* lpcMaxValueLen */
1404 NULL, /* lpcbSecurityDescriptor */
1405 NULL /* lpftLastWriteTime */
1408 sprintf(line, "%s:%s.", filename, destination);
1410 /* If we are adding a new value, there must be an unused name
1411 * within the range 0 to dwSymlinks
1413 for ( dwIndex = 0; dwIndex <= dwSymlinks; dwIndex++ ) {
1417 dwSize = sizeof(szLink);
1418 sprintf(szIndex, "%d", dwIndex);
1419 if (RegQueryValueEx( hkFreelanceSymlinks, szIndex, 0, &dwType, szLink, &dwSize) != ERROR_SUCCESS) {
1420 /* found an unused value */
1422 dwSize = (DWORD)strlen(line) + 1;
1423 RegSetValueEx( hkFreelanceSymlinks, szIndex, 0, dwType, line, dwSize);
1426 int len = (int)strlen(filename);
1427 if ( dwType == REG_SZ && !strncmp(filename, szLink, len) && szLink[len] == ':') {
1428 /* Replace the existing value */
1430 dwSize = (DWORD)strlen(line) + 1;
1431 RegSetValueEx( hkFreelanceSymlinks, szIndex, 0, dwType, line, dwSize);
1436 RegCloseKey(hkFreelanceSymlinks);
1439 /* Do this while we are holding the lock */
1440 cm_noteLocalMountPointChange(TRUE);
1441 lock_ReleaseMutex(&cm_Freelance_Lock);
1447 clientchar_t *cpath;
1451 cpath = cm_FsStringToClientStringAlloc(filename, -1, NULL);
1453 code = CM_ERROR_NOSUCHPATH;
1455 if (cm_getLocalMountPointChange()) { // check for changes
1456 cm_clearLocalMountPointChange(); // clear the changefile
1457 cm_reInitLocalMountPoints(); // start reinit
1460 code = cm_NameI(cm_RootSCachep(cm_rootUserp, &req), cpath,
1461 CM_FLAG_DIRSEARCH | CM_FLAG_CASEFOLD,
1462 cm_rootUserp, NULL, &req, &scp);
1466 cm_ReleaseSCache(scp);
1474 long cm_FreelanceRemoveSymlink(char *toremove)
1478 char shortname[200];
1480 HKEY hkFreelanceSymlinks = 0;
1481 DWORD dwType, dwSize;
1485 lock_ObtainMutex(&cm_Freelance_Lock);
1487 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
1488 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance\\Symlinks",
1490 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
1491 &hkFreelanceSymlinks) == ERROR_SUCCESS) {
1493 RegQueryInfoKey( hkFreelanceSymlinks,
1495 NULL, /* lpcClass */
1496 NULL, /* lpReserved */
1497 NULL, /* lpcSubKeys */
1498 NULL, /* lpcMaxSubKeyLen */
1499 NULL, /* lpcMaxClassLen */
1500 &dwSymlinks, /* lpcValues */
1501 NULL, /* lpcMaxValueNameLen */
1502 NULL, /* lpcMaxValueLen */
1503 NULL, /* lpcbSecurityDescriptor */
1504 NULL /* lpftLastWriteTime */
1507 for ( dwIndex = 0; dwIndex < dwSymlinks; dwIndex++ ) {
1508 TCHAR szValueName[16];
1509 DWORD dwValueSize = 16;
1510 dwSize = sizeof(line);
1511 RegEnumValue( hkFreelanceSymlinks, dwIndex, szValueName, &dwValueSize, NULL,
1512 &dwType, line, &dwSize);
1514 cp=strchr(line, ':');
1515 memcpy(shortname, line, cp-line);
1516 shortname[cp-line]=0;
1518 if (!strcmp(shortname, toremove)) {
1519 RegDeleteValue( hkFreelanceSymlinks, szValueName );
1524 RegCloseKey(hkFreelanceSymlinks);
1528 /* Do this while we are holding the lock */
1529 cm_noteLocalMountPointChange(TRUE);
1531 lock_ReleaseMutex(&cm_Freelance_Lock);
1532 return (found ? 0 : CM_ERROR_NOSUCHFILE);
1536 cm_FreelanceFetchMountPointString(cm_scache_t *scp)
1538 lock_ObtainMutex(&cm_Freelance_Lock);
1539 if (scp->mpDataVersion != scp->dataVersion &&
1540 scp->fid.cell == AFS_FAKE_ROOT_CELL_ID &&
1541 scp->fid.volume == AFS_FAKE_ROOT_VOL_ID &&
1542 (afs_int32)(scp->fid.unique - cm_data.fakeUnique) - 1 >= 0 &&
1543 scp->fid.unique - cm_data.fakeUnique <= cm_noLocalMountPoints) {
1544 strncpy(scp->mountPointStringp, cm_localMountPoints[scp->fid.unique-cm_data.fakeUnique-1].mountPointStringp, MOUNTPOINTLEN);
1545 scp->mountPointStringp[MOUNTPOINTLEN-1] = 0; /* null terminate */
1546 scp->mpDataVersion = scp->dataVersion;
1548 lock_ReleaseMutex(&cm_Freelance_Lock);
1554 cm_FreelanceFetchFileType(cm_scache_t *scp)
1556 lock_ObtainMutex(&cm_Freelance_Lock);
1557 if (scp->fid.cell == AFS_FAKE_ROOT_CELL_ID &&
1558 scp->fid.volume == AFS_FAKE_ROOT_VOL_ID &&
1559 (afs_int32)(scp->fid.unique - cm_data.fakeUnique) - 1 >= 0 &&
1560 scp->fid.unique - cm_data.fakeUnique <= cm_noLocalMountPoints)
1562 scp->fileType = cm_localMountPoints[scp->fid.unique-cm_data.fakeUnique-1].fileType;
1564 if (scp->fileType == CM_SCACHETYPE_SYMLINK &&
1565 !strnicmp(cm_localMountPoints[scp->fid.unique-cm_data.fakeUnique-1].mountPointStringp, "msdfs:", strlen("msdfs:")) )
1567 scp->fileType = CM_SCACHETYPE_DFSLINK;
1570 scp->fileType = CM_SCACHETYPE_INVALID;
1572 lock_ReleaseMutex(&cm_Freelance_Lock);
1576 #endif /* AFS_FREELANCE_CLIENT */