15 #include <WINNT/afsreg.h>
19 #ifdef AFS_FREELANCE_CLIENT
20 #include "cm_freelance.h"
23 extern void afsi_log(char *pattern, ...);
25 int cm_noLocalMountPoints;
27 int cm_fakeDirCallback=0;
28 int cm_fakeGettingCallback=0;
29 cm_localMountPoint_t* cm_localMountPoints;
30 osi_mutex_t cm_Freelance_Lock;
31 int cm_localMountPointChangeFlag = 0;
32 int cm_freelanceEnabled = 1;
33 time_t FakeFreelanceModTime = 0x3b49f6e2;
35 static int freelance_ShutdownFlag = 0;
37 static HANDLE hFreelanceChangeEvent = 0;
38 static HANDLE hFreelanceSymlinkChangeEvent = 0;
41 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();
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();
136 cm_FreelanceShutdown(void)
138 freelance_ShutdownFlag = 1;
140 if (hFreelanceChangeEvent != 0)
141 thrd_SetEvent(hFreelanceChangeEvent);
142 if (hFreelanceSymlinkChangeEvent != 0)
143 thrd_SetEvent(hFreelanceSymlinkChangeEvent);
147 void cm_InitFreelance() {
153 lock_InitializeMutex(&cm_Freelance_Lock, "Freelance Lock");
155 // make sure we sync the data version to the cached root scache_t
156 if (cm_data.rootSCachep && cm_data.rootSCachep->fid.cell == AFS_FAKE_ROOT_CELL_ID)
157 cm_data.fakeDirVersion = cm_data.rootSCachep->dataVersion;
159 // yj: first we make a call to cm_initLocalMountPoints
160 // to read all the local mount points from the registry
161 cm_InitLocalMountPoints();
163 // then we make a call to InitFakeRootDir to create
164 // a fake root directory based on the local mount points
165 cm_InitFakeRootDir();
166 // --- end of yj code
169 /* Start the registry monitor */
170 phandle = thrd_Create(NULL, 65536, (ThreadFunc) cm_FreelanceChangeNotifier,
171 NULL, 0, &lpid, "cm_FreelanceChangeNotifier");
172 osi_assert(phandle != NULL);
173 thrd_CloseHandle(phandle);
175 phandle = thrd_Create(NULL, 65536, (ThreadFunc) cm_FreelanceSymlinkChangeNotifier,
176 NULL, 0, &lpid, "cm_FreelanceSymlinkChangeNotifier");
177 osi_assert(phandle != NULL);
178 thrd_CloseHandle(phandle);
182 /* yj: Initialization of the fake root directory */
183 /* to be called while holding freelance lock unless during init. */
184 void cm_InitFakeRootDir() {
189 // allocate space for the fake info
190 cm_dirHeader_t fakeDirHeader;
191 cm_dirEntry_t fakeEntry;
192 cm_pageHeader_t fakePageHeader;
194 // i'm going to calculate how much space is needed for
195 // this fake root directory. we have these rules:
196 // 1. there are cm_noLocalMountPoints number of entries
197 // 2. each page is CM_DIR_PAGESIZE in size
198 // 3. the first 13 chunks of the first page are used for
200 // 4. the first chunk of all subsequent pages are used
201 // for page header stuff
202 // 5. a max of CM_DIR_EPP entries are allowed per page
203 // 6. each entry takes 1 or more chunks, depending on
204 // the size of the mount point string, as determined
206 // 7. each chunk is CM_DIR_CHUNKSIZE bytes
208 int CPP = CM_DIR_PAGESIZE / CM_DIR_CHUNKSIZE;
209 int curChunk = 13; // chunks 0 - 12 are used for header stuff
210 // of the first page in the directory
213 int curDirEntryInPage = 0;
217 /* Reserve 2 directory chunks for "." and ".." */
220 while (curDirEntry<cm_noLocalMountPoints) {
221 sizeOfCurEntry = cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0);
222 if ((curChunk + sizeOfCurEntry >= CPP) ||
223 (curDirEntryInPage + 1 >= CM_DIR_EPP)) {
225 curDirEntryInPage = 0;
228 curChunk += sizeOfCurEntry;
233 dirSize = (curPage+1) * CM_DIR_PAGESIZE;
234 cm_FakeRootDir = malloc(dirSize);
235 cm_fakeDirSize = dirSize;
237 // yj: when we get here, we've figured out how much memory we need and
238 // allocated the appropriate space for it. we now prceed to fill
239 // it up with entries.
242 curDirEntryInPage = 0;
245 // fields in the directory entry that are unused.
247 fakeEntry.length = 0;
249 fakeEntry.fid.unique = htonl(1);
251 // the first page is special, it uses fakeDirHeader instead of fakePageHeader
252 // we fill up the page with dirEntries that belong there and we make changes
253 // to the fakeDirHeader.header.freeBitmap along the way. Then when we're done
254 // filling up the dirEntries in this page, we copy the fakeDirHeader into
255 // the top of the page.
257 // init the freeBitmap array
259 fakeDirHeader.header.freeBitmap[i]=0;
261 fakeDirHeader.header.freeBitmap[0] = 0xff;
262 fakeDirHeader.header.freeBitmap[1] = 0x7f;
265 // we start counting at 13 because the 0th to 12th chunks are used for header
268 // stick the first 2 entries "." and ".." in
269 fakeEntry.fid.unique = htonl(1);
270 fakeEntry.fid.vnode = htonl(1);
271 strcpy(fakeEntry.name, ".");
272 currentPos = cm_FakeRootDir + curPage * CM_DIR_PAGESIZE + curChunk * CM_DIR_CHUNKSIZE;
273 memcpy(currentPos, &fakeEntry, CM_DIR_CHUNKSIZE);
274 curChunk++; curDirEntryInPage++;
275 strcpy(fakeEntry.name, "..");
276 currentPos = cm_FakeRootDir + curPage * CM_DIR_PAGESIZE + curChunk * CM_DIR_CHUNKSIZE;
277 memcpy(currentPos, &fakeEntry, CM_DIR_CHUNKSIZE);
278 curChunk++; curDirEntryInPage++;
280 // keep putting stuff into page 0 if
281 // 1. we're not done with all entries
282 // 2. we have less than CM_DIR_EPP entries in page 0
283 // 3. we're not out of chunks in page 0
285 while( (curDirEntry<cm_noLocalMountPoints) &&
286 (curDirEntryInPage < CM_DIR_EPP) &&
287 (curChunk + cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0) <= CPP))
290 noChunks = cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0);
291 fakeEntry.fid.vnode = htonl(curDirEntry + 2);
292 currentPos = cm_FakeRootDir + curPage * CM_DIR_PAGESIZE + curChunk * CM_DIR_CHUNKSIZE;
294 memcpy(currentPos, &fakeEntry, CM_DIR_CHUNKSIZE);
295 strcpy(currentPos + 12, (cm_localMountPoints+curDirEntry)->namep);
298 for (i=0; i<noChunks; i++) {
299 t1 = (curChunk + i) / 8;
300 t2 = curChunk + i - (t1*8);
301 fakeDirHeader.header.freeBitmap[t1] |= (1 << t2);
306 // when we get here, we're done with filling in the entries for page 0
307 // copy in the header info
309 memcpy(cm_FakeRootDir, &fakeDirHeader, 13 * CM_DIR_CHUNKSIZE);
313 // ok, page 0's done. Move on to the next page.
314 while (curDirEntry<cm_noLocalMountPoints) {
316 curChunk = 1; // the zeroth chunk is reserved for page header
317 curDirEntryInPage = 0;
318 for (i=0; i<8; i++) {
319 fakePageHeader.freeBitmap[i]=0;
321 fakePageHeader.freeCount = 0;
322 fakePageHeader.pgcount = 0;
323 fakePageHeader.tag = htons(1234);
325 // while we're on the same page...
326 while ( (curDirEntry<cm_noLocalMountPoints) &&
327 (curDirEntryInPage < CM_DIR_EPP) &&
328 (curChunk + cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0) <= CPP))
330 // add an entry to this page
332 noChunks = cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0);
333 fakeEntry.fid.vnode=htonl(curDirEntry+2);
334 currentPos = cm_FakeRootDir + curPage * CM_DIR_PAGESIZE + curChunk * CM_DIR_CHUNKSIZE;
335 memcpy(currentPos, &fakeEntry, CM_DIR_CHUNKSIZE);
336 strcpy(currentPos + 12, (cm_localMountPoints+curDirEntry)->namep);
339 for (i=0; i<noChunks; i++) {
340 t1 = (curChunk + i) / 8;
341 t2 = curChunk + i - (t1*8);
342 fakePageHeader.freeBitmap[t1] |= (1 << t2);
346 memcpy(cm_FakeRootDir + curPage * CM_DIR_PAGESIZE, &fakePageHeader, sizeof(fakePageHeader));
351 // we know the fakeDir is setup properly, so we claim that we have callback
352 osi_Log0(afsd_logp,"cm_InitFakeRootDir fakeDirCallback=1");
353 cm_fakeDirCallback=1;
355 // when we get here, we've set up everything! done!
358 int cm_FakeRootFid(cm_fid_t *fidp)
360 fidp->cell = AFS_FAKE_ROOT_CELL_ID; /* root cell */
361 fidp->volume = AFS_FAKE_ROOT_VOL_ID; /* root.afs ? */
367 /* called directly from ioctl */
368 /* called while not holding freelance lock */
369 int cm_noteLocalMountPointChange(void) {
370 lock_ObtainMutex(&cm_Freelance_Lock);
371 cm_data.fakeDirVersion++;
372 cm_localMountPointChangeFlag = 1;
373 lock_ReleaseMutex(&cm_Freelance_Lock);
377 int cm_getLocalMountPointChange() {
378 return cm_localMountPointChangeFlag;
381 int cm_clearLocalMountPointChange() {
382 cm_localMountPointChangeFlag = 0;
386 int cm_reInitLocalMountPoints() {
389 cm_scache_t *scp, **lscpp, *tscp;
391 osi_Log0(afsd_logp,"----- freelance reinitialization starts ----- ");
393 // first we invalidate all the SCPs that were created
394 // for the local mount points
396 osi_Log0(afsd_logp,"Invalidating local mount point scp... ");
398 aFid.cell = AFS_FAKE_ROOT_CELL_ID;
399 aFid.volume=AFS_FAKE_ROOT_VOL_ID;
403 lock_ObtainWrite(&cm_scacheLock);
404 lock_ObtainMutex(&cm_Freelance_Lock); /* always scache then freelance lock */
405 for (i=0; i<cm_noLocalMountPoints; i++) {
406 hash = CM_SCACHE_HASH(&aFid);
407 for (scp=cm_data.scacheHashTablep[hash]; scp; scp=scp->nextp) {
408 if (scp->fid.volume == aFid.volume &&
409 scp->fid.vnode == aFid.vnode &&
410 scp->fid.unique == aFid.unique
413 // mark the scp to be reused
414 cm_HoldSCacheNoLock(scp);
415 lock_ReleaseWrite(&cm_scacheLock);
416 lock_ObtainMutex(&scp->mx);
417 cm_DiscardSCache(scp);
418 lock_ReleaseMutex(&scp->mx);
419 cm_CallbackNotifyChange(scp);
420 lock_ObtainWrite(&cm_scacheLock);
421 cm_ReleaseSCacheNoLock(scp);
423 // take the scp out of the hash
424 for (lscpp = &cm_data.scacheHashTablep[hash], tscp = cm_data.scacheHashTablep[hash];
426 lscpp = &tscp->nextp, tscp = tscp->nextp) {
429 lock_ObtainMutex(&scp->mx);
430 scp->flags &= ~CM_SCACHEFLAG_INHASH;
431 lock_ReleaseMutex(&scp->mx);
437 aFid.vnode = aFid.vnode + 1;
439 lock_ReleaseWrite(&cm_scacheLock);
440 osi_Log0(afsd_logp,"\tall old scp cleared!");
442 // we must free the memory that was allocated in the prev
443 // cm_InitLocalMountPoints call
444 osi_Log0(afsd_logp,"Removing old localmountpoints... ");
445 free(cm_localMountPoints);
446 osi_Log0(afsd_logp,"\tall old localmountpoints cleared!");
448 // now re-init the localmountpoints
449 osi_Log0(afsd_logp,"Creating new localmountpoints... ");
450 cm_InitLocalMountPoints();
451 osi_Log0(afsd_logp,"\tcreated new set of localmountpoints!");
453 // now we have to free the memory allocated in cm_initfakerootdir
454 osi_Log0(afsd_logp,"Removing old fakedir... ");
455 free(cm_FakeRootDir);
456 osi_Log0(afsd_logp,"\t\told fakedir removed!");
458 // then we re-create that dir
459 osi_Log0(afsd_logp,"Creating new fakedir... ");
460 cm_InitFakeRootDir();
461 osi_Log0(afsd_logp,"\t\tcreated new fakedir!");
463 lock_ReleaseMutex(&cm_Freelance_Lock);
465 osi_Log0(afsd_logp,"----- freelance reinit complete -----");
470 // yj: open up the registry and read all the local mount
471 // points that are stored there. Part of the initialization
472 // process for the freelance client.
473 /* to be called while holding freelance lock unless during init. */
474 long cm_InitLocalMountPoints() {
479 cm_localMountPoint_t* aLocalMountPoint;
482 char rootCellName[256];
484 HKEY hkFreelance = 0, hkFreelanceSymlinks = 0;
485 DWORD dwType, dwSize;
486 DWORD dwMountPoints = 0;
488 DWORD dwSymlinks = 0;
489 FILETIME ftLastWriteTime;
493 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
494 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance",
496 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
497 &hkFreelance) == ERROR_SUCCESS) {
499 RegQueryInfoKey( hkFreelance,
502 NULL, /* lpReserved */
503 NULL, /* lpcSubKeys */
504 NULL, /* lpcMaxSubKeyLen */
505 NULL, /* lpcMaxClassLen */
506 &dwMountPoints, /* lpcValues */
507 NULL, /* lpcMaxValueNameLen */
508 NULL, /* lpcMaxValueLen */
509 NULL, /* lpcbSecurityDescriptor */
510 &ftLastWriteTime /* lpftLastWriteTime */
513 smb_UnixTimeFromLargeSearchTime(&FakeFreelanceModTime, &ftLastWriteTime);
515 if ( dwMountPoints == 0 ) {
516 rootCellName[0] = '.';
517 code = cm_GetRootCellName(&rootCellName[1]);
519 cm_FreelanceAddMount(&rootCellName[1], &rootCellName[1], "root.cell.", 0, NULL);
520 cm_FreelanceAddMount(rootCellName, &rootCellName[1], "root.cell.", 1, NULL);
521 cm_FreelanceAddMount(".root", &rootCellName[1], "root.afs.", 1, NULL);
526 if (RegCreateKeyEx( HKEY_LOCAL_MACHINE,
527 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance\\Symlinks",
530 REG_OPTION_NON_VOLATILE,
531 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
533 &hkFreelanceSymlinks,
534 NULL) == ERROR_SUCCESS) {
536 RegQueryInfoKey( hkFreelanceSymlinks,
539 NULL, /* lpReserved */
540 NULL, /* lpcSubKeys */
541 NULL, /* lpcMaxSubKeyLen */
542 NULL, /* lpcMaxClassLen */
543 &dwSymlinks, /* lpcValues */
544 NULL, /* lpcMaxValueNameLen */
545 NULL, /* lpcMaxValueLen */
546 NULL, /* lpcbSecurityDescriptor */
547 NULL /* lpftLastWriteTime */
551 // get the number of entries there are from the first line
553 cm_noLocalMountPoints = dwMountPoints + dwSymlinks;
555 // create space to store the local mount points
556 cm_localMountPoints = malloc(sizeof(cm_localMountPoint_t) * cm_noLocalMountPoints);
557 aLocalMountPoint = cm_localMountPoints;
559 // now we read n lines and parse them into local mount points
560 // where n is the number of local mount points there are, as
562 // Each line in the ini file represents 1 local mount point and
563 // is in the format xxx#yyy:zzz, where xxx is the directory
564 // entry name, yyy is the cell name and zzz is the volume name.
565 // #yyy:zzz together make up the mount point.
566 for ( dwIndex = 0 ; dwIndex < dwMountPoints; dwIndex++ ) {
567 TCHAR szValueName[16];
568 DWORD dwValueSize = 16;
569 dwSize = sizeof(line);
570 if (RegEnumValue( hkFreelance, dwIndex, szValueName, &dwValueSize, NULL,
571 &dwType, line, &dwSize))
573 afsi_log("RegEnumValue(hkFreelance) failed");
574 cm_noLocalMountPoints--;
578 afsi_log("Mountpoint[%d] = %s",dwIndex, line);
580 /* find the trailing dot; null terminate after it */
581 t2 = strrchr(line, '.');
585 for ( t=line;*t;t++ ) {
586 if ( !isprint(*t) ) {
587 afsi_log("error occurred while parsing mountpoint entry [%d]: non-printable character", dwIndex);
588 fprintf(stderr, "error occurred while parsing mountpoint entry [%d]: non-printable character", dwIndex);
589 cm_noLocalMountPoints--;
594 // line is not empty, so let's parse it
595 t = strchr(line, '#');
597 t = strchr(line, '%');
598 // make sure that there is a '#' or '%' separator in the line
600 afsi_log("error occurred while parsing mountpoint entry [%d]: no # or %% separator", dwIndex);
601 fprintf(stderr, "error occurred while parsing mountpoint entry [%d]: no # or %% separator", dwIndex);
602 cm_noLocalMountPoints--;
606 aLocalMountPoint->fileType = CM_SCACHETYPE_MOUNTPOINT;
607 aLocalMountPoint->namep=malloc(t-line+1);
608 strncpy(aLocalMountPoint->namep, line, t-line);
609 aLocalMountPoint->namep[t-line] = '\0';
611 /* copy the mount point string */
612 aLocalMountPoint->mountPointStringp=malloc(strlen(t));
613 strncpy(aLocalMountPoint->mountPointStringp, t, strlen(t)-1);
614 aLocalMountPoint->mountPointStringp[strlen(t)-1] = '\0';
616 osi_Log2(afsd_logp,"found mount point: name %s, string %s",
617 osi_LogSaveString(afsd_logp,aLocalMountPoint->namep),
618 osi_LogSaveString(afsd_logp,aLocalMountPoint->mountPointStringp));
623 for ( dwIndex = 0 ; dwIndex < dwSymlinks; dwIndex++ ) {
624 TCHAR szValueName[16];
625 DWORD dwValueSize = 16;
626 dwSize = sizeof(line);
627 if (RegEnumValue( hkFreelanceSymlinks, dwIndex, szValueName, &dwValueSize, NULL,
628 &dwType, line, &dwSize))
630 afsi_log("RegEnumValue(hkFreelanceSymlinks) failed");
631 cm_noLocalMountPoints--;
635 afsi_log("Symlink[%d] = %s",dwIndex, line);
637 /* find the trailing dot; null terminate after it */
638 t2 = strrchr(line, '.');
642 for ( t=line;*t;t++ ) {
643 if ( !isprint(*t) ) {
644 afsi_log("error occurred while parsing symlink entry [%d]: non-printable character", dwIndex);
645 fprintf(stderr, "error occurred while parsing symlink entry [%d]: non-printable character", dwIndex);
646 cm_noLocalMountPoints--;
651 // line is not empty, so let's parse it
652 t = strchr(line, ':');
654 // make sure that there is a ':' separator in the line
656 afsi_log("error occurred while parsing symlink entry [%d]: no ':' separator", dwIndex);
657 fprintf(stderr, "error occurred while parsing symlink entry [%d]: no ':' separator", dwIndex);
658 cm_noLocalMountPoints--;
662 aLocalMountPoint->fileType = CM_SCACHETYPE_SYMLINK;
663 aLocalMountPoint->namep=malloc(t-line+1);
664 strncpy(aLocalMountPoint->namep, line, t-line);
665 aLocalMountPoint->namep[t-line] = '\0';
667 /* copy the symlink string */
668 aLocalMountPoint->mountPointStringp=malloc(strlen(t)-1);
669 strncpy(aLocalMountPoint->mountPointStringp, t+1, strlen(t)-2);
670 aLocalMountPoint->mountPointStringp[strlen(t)-2] = '\0';
672 osi_Log2(afsd_logp,"found symlink: name %s, string %s",
673 osi_LogSaveString(afsd_logp,aLocalMountPoint->namep),
674 osi_LogSaveString(afsd_logp,aLocalMountPoint->mountPointStringp));
679 if ( hkFreelanceSymlinks )
680 RegCloseKey( hkFreelanceSymlinks );
681 RegCloseKey(hkFreelance);
686 /* What follows is the old code to read freelance mount points
687 * out of a text file modified to copy the data into the registry
689 cm_GetConfigDir(hdir);
690 strcat(hdir, AFS_FREELANCE_INI);
691 // open the ini file for reading
692 fp = fopen(hdir, "r");
694 /* look in the Windows directory where we used to store the file */
695 GetWindowsDirectory(hdir, sizeof(hdir));
697 strcat(hdir, AFS_FREELANCE_INI);
698 fp = fopen(hdir, "r");
702 RegCreateKeyEx( HKEY_LOCAL_MACHINE,
703 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance",
706 REG_OPTION_NON_VOLATILE,
716 RegCloseKey(hkFreelance);
718 rootCellName[0] = '.';
719 code = cm_GetRootCellName(&rootCellName[1]);
721 cm_FreelanceAddMount(&rootCellName[1], &rootCellName[1], "root.cell.", 0, NULL);
722 cm_FreelanceAddMount(rootCellName, &rootCellName[1], "root.cell.", 1, NULL);
723 cm_FreelanceAddMount(".root", &rootCellName[1], "root.afs.", 1, NULL);
728 // we successfully opened the file
729 osi_Log0(afsd_logp,"opened afs_freelance.ini");
731 // now we read the first line to see how many entries
733 fgets(line, sizeof(line), fp);
735 // if the line is empty at any point when we're reading
736 // we're screwed. report error and return.
738 afsi_log("error occurred while reading afs_freelance.ini");
739 fprintf(stderr, "error occurred while reading afs_freelance.ini");
743 // get the number of entries there are from the first line
745 cm_noLocalMountPoints = atoi(line);
747 if (cm_noLocalMountPoints > 0) {
748 // create space to store the local mount points
749 cm_localMountPoints = malloc(sizeof(cm_localMountPoint_t) * cm_noLocalMountPoints);
750 aLocalMountPoint = cm_localMountPoints;
753 // now we read n lines and parse them into local mount points
754 // where n is the number of local mount points there are, as
756 // Each line in the ini file represents 1 local mount point and
757 // is in the format xxx#yyy:zzz, where xxx is the directory
758 // entry name, yyy is the cell name and zzz is the volume name.
759 // #yyy:zzz together make up the mount point.
760 for (i=0; i<cm_noLocalMountPoints; i++) {
761 fgets(line, sizeof(line), fp);
762 // check that the line is not empty
764 afsi_log("error occurred while parsing entry in %s: empty line in line %d", AFS_FREELANCE_INI, i);
765 fprintf(stderr, "error occurred while parsing entry in afs_freelance.ini: empty line in line %d", i);
769 /* find the trailing dot; null terminate after it */
770 t2 = strrchr(line, '.');
777 /* we are migrating to the registry */
778 sprintf(szIndex,"%d",dwIndex++);
780 dwSize = (DWORD)strlen(line) + 1;
781 RegSetValueEx( hkFreelance, szIndex, 0, dwType, line, dwSize);
785 // line is not empty, so let's parse it
786 t = strchr(line, '#');
788 t = strchr(line, '%');
789 // make sure that there is a '#' or '%' separator in the line
791 afsi_log("error occurred while parsing entry in %s: no # or %% separator in line %d", AFS_FREELANCE_INI, i);
792 fprintf(stderr, "error occurred while parsing entry in afs_freelance.ini: no # or %% separator in line %d", i);
795 aLocalMountPoint->namep=malloc(t-line+1);
796 memcpy(aLocalMountPoint->namep, line, t-line);
797 *(aLocalMountPoint->namep + (t-line)) = 0;
799 aLocalMountPoint->mountPointStringp=malloc(strlen(line) - (t-line) + 1);
800 memcpy(aLocalMountPoint->mountPointStringp, t, strlen(line)-(t-line)-1);
801 *(aLocalMountPoint->mountPointStringp + (strlen(line)-(t-line)-1)) = 0;
803 osi_Log2(afsd_logp,"found mount point: name %s, string %s",
804 aLocalMountPoint->namep,
805 aLocalMountPoint->mountPointStringp);
812 RegCloseKey(hkFreelance);
819 int cm_getNoLocalMountPoints() {
820 return cm_noLocalMountPoints;
824 long cm_FreelanceMountPointExists(char * filename)
830 HKEY hkFreelance = 0;
831 DWORD dwType, dwSize;
835 lock_ObtainMutex(&cm_Freelance_Lock);
837 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
838 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance",
840 KEY_READ|KEY_QUERY_VALUE,
841 &hkFreelance) == ERROR_SUCCESS)
843 RegQueryInfoKey( hkFreelance,
846 NULL, /* lpReserved */
847 NULL, /* lpcSubKeys */
848 NULL, /* lpcMaxSubKeyLen */
849 NULL, /* lpcMaxClassLen */
850 &dwMountPoints, /* lpcValues */
851 NULL, /* lpcMaxValueNameLen */
852 NULL, /* lpcMaxValueLen */
853 NULL, /* lpcbSecurityDescriptor */
854 NULL /* lpftLastWriteTime */
857 for ( dwIndex = 0; dwIndex < dwMountPoints; dwIndex++ ) {
858 TCHAR szValueName[16];
859 DWORD dwValueSize = 16;
860 dwSize = sizeof(line);
861 RegEnumValue( hkFreelance, dwIndex, szValueName, &dwValueSize, NULL,
862 &dwType, line, &dwSize);
864 cp=strchr(line, '#');
866 cp=strchr(line, '%');
867 memcpy(shortname, line, cp-line);
868 shortname[cp-line]=0;
870 if (!strcmp(shortname, filename)) {
875 for ( dwIndex = 0; dwIndex < dwMountPoints; dwIndex++ ) {
876 TCHAR szValueName[16];
877 DWORD dwValueSize = 16;
878 dwSize = sizeof(line);
879 RegEnumValue( hkFreelance, dwIndex, szValueName, &dwValueSize, NULL,
880 &dwType, line, &dwSize);
882 cp=strchr(line, '#');
884 cp=strchr(line, '%');
885 memcpy(shortname, line, cp-line);
886 shortname[cp-line]=0;
888 if (!stricmp(shortname, filename)) {
893 RegCloseKey(hkFreelance);
896 lock_ReleaseMutex(&cm_Freelance_Lock);
901 long cm_FreelanceSymlinkExists(char * filename)
907 HKEY hkFreelance = 0;
908 DWORD dwType, dwSize;
912 lock_ObtainMutex(&cm_Freelance_Lock);
914 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
915 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance\\Symlinks",
917 KEY_READ|KEY_QUERY_VALUE,
918 &hkFreelance) == ERROR_SUCCESS)
920 RegQueryInfoKey( hkFreelance,
923 NULL, /* lpReserved */
924 NULL, /* lpcSubKeys */
925 NULL, /* lpcMaxSubKeyLen */
926 NULL, /* lpcMaxClassLen */
927 &dwSymlinks, /* lpcValues */
928 NULL, /* lpcMaxValueNameLen */
929 NULL, /* lpcMaxValueLen */
930 NULL, /* lpcbSecurityDescriptor */
931 NULL /* lpftLastWriteTime */
934 for ( dwIndex = 0; dwIndex < dwSymlinks; dwIndex++ ) {
935 TCHAR szValueName[16];
936 DWORD dwValueSize = 16;
937 dwSize = sizeof(line);
938 RegEnumValue( hkFreelance, dwIndex, szValueName, &dwValueSize, NULL,
939 &dwType, line, &dwSize);
941 cp=strchr(line, ':');
942 memcpy(shortname, line, cp-line);
943 shortname[cp-line]=0;
945 if (!strcmp(shortname, filename)) {
950 for ( dwIndex = 0; dwIndex < dwSymlinks; dwIndex++ ) {
951 TCHAR szValueName[16];
952 DWORD dwValueSize = 16;
953 dwSize = sizeof(line);
954 RegEnumValue( hkFreelance, dwIndex, szValueName, &dwValueSize, NULL,
955 &dwType, line, &dwSize);
957 cp=strchr(line, ':');
958 memcpy(shortname, line, cp-line);
959 shortname[cp-line]=0;
961 if (!stricmp(shortname, filename)) {
966 RegCloseKey(hkFreelance);
969 lock_ReleaseMutex(&cm_Freelance_Lock);
975 long cm_FreelanceAddMount(char *filename, char *cellname, char *volume, int rw, cm_fid_t *fidp)
984 HKEY hkFreelance = 0;
985 DWORD dwType, dwSize;
990 /* before adding, verify the cell name; if it is not a valid cell,
991 don't add the mount point.
992 allow partial matches as a means of poor man's alias. */
993 /* major performance issue? */
994 osi_Log4(afsd_logp,"Freelance Add Mount request: filename=%s cellname=%s volume=%s %s",
995 osi_LogSaveString(afsd_logp,filename),
996 osi_LogSaveString(afsd_logp,cellname),
997 osi_LogSaveString(afsd_logp,volume),
1000 if ( filename[0] == '\0' || cellname[0] == '\0' || volume[0] == '\0' )
1003 if (cellname[0] == '.') {
1004 if (!cm_GetCell_Gen(&cellname[1], fullname, CM_FLAG_CREATE))
1007 if (!cm_GetCell_Gen(cellname, fullname, CM_FLAG_CREATE))
1012 if ( cm_FreelanceMountPointExists(filename) ||
1013 cm_FreelanceSymlinkExists(filename) )
1017 osi_Log1(afsd_logp,"Freelance Adding Mount for Cell: %s",
1018 osi_LogSaveString(afsd_logp,cellname));
1020 lock_ObtainMutex(&cm_Freelance_Lock);
1023 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
1024 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance",
1026 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
1027 &hkFreelance) == ERROR_SUCCESS) {
1029 RegQueryInfoKey( hkFreelance,
1031 NULL, /* lpcClass */
1032 NULL, /* lpReserved */
1033 NULL, /* lpcSubKeys */
1034 NULL, /* lpcMaxSubKeyLen */
1035 NULL, /* lpcMaxClassLen */
1036 &dwMountPoints, /* lpcValues */
1037 NULL, /* lpcMaxValueNameLen */
1038 NULL, /* lpcMaxValueLen */
1039 NULL, /* lpcbSecurityDescriptor */
1040 NULL /* lpftLastWriteTime */
1044 sprintf(line, "%s%%%s:%s", filename, fullname, volume);
1046 sprintf(line, "%s#%s:%s", filename, fullname, volume);
1048 /* If we are adding a new value, there must be an unused name
1049 * within the range 0 to dwMountPoints
1051 for ( dwIndex = 0; dwIndex <= dwMountPoints; dwIndex++ ) {
1055 dwSize = sizeof(szMount);
1056 sprintf(szIndex, "%d", dwIndex);
1057 if (RegQueryValueEx( hkFreelance, szIndex, 0, &dwType, szMount, &dwSize) != ERROR_SUCCESS) {
1058 /* found an unused value */
1060 dwSize = (DWORD)strlen(line) + 1;
1061 RegSetValueEx( hkFreelance, szIndex, 0, dwType, line, dwSize);
1064 int len = (int)strlen(filename);
1065 if ( dwType == REG_SZ && !strncmp(filename, szMount, len) &&
1066 (szMount[len] == '%' || szMount[len] == '#')) {
1067 /* Replace the existing value */
1069 dwSize = (DWORD)strlen(line) + 1;
1070 RegSetValueEx( hkFreelance, szIndex, 0, dwType, line, dwSize);
1075 RegCloseKey(hkFreelance);
1079 cm_GetConfigDir(hfile);
1080 strcat(hfile, AFS_FREELANCE_INI);
1081 fp = fopen(hfile, "r+");
1083 return CM_ERROR_INVAL;
1084 fgets(line, sizeof(line), fp);
1087 fseek(fp, 0, SEEK_SET);
1088 fprintf(fp, "%d", n);
1089 fseek(fp, 0, SEEK_END);
1091 fprintf(fp, "%s%%%s:%s\n", filename, fullname, volume);
1093 fprintf(fp, "%s#%s:%s\n", filename, fullname, volume);
1096 lock_ReleaseMutex(&cm_Freelance_Lock);
1098 /* cm_reInitLocalMountPoints(); */
1101 fidp->vnode = cm_noLocalMountPoints + 1; /* vnode value of last mt pt */
1103 cm_noteLocalMountPointChange();
1107 long cm_FreelanceRemoveMount(char *toremove)
1112 char shortname[200];
1113 char hfile[120], hfile2[120];
1117 HKEY hkFreelance = 0;
1118 DWORD dwType, dwSize;
1119 DWORD dwMountPoints;
1123 lock_ObtainMutex(&cm_Freelance_Lock);
1126 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
1127 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance",
1129 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
1130 &hkFreelance) == ERROR_SUCCESS) {
1132 RegQueryInfoKey( hkFreelance,
1134 NULL, /* lpcClass */
1135 NULL, /* lpReserved */
1136 NULL, /* lpcSubKeys */
1137 NULL, /* lpcMaxSubKeyLen */
1138 NULL, /* lpcMaxClassLen */
1139 &dwMountPoints, /* lpcValues */
1140 NULL, /* lpcMaxValueNameLen */
1141 NULL, /* lpcMaxValueLen */
1142 NULL, /* lpcbSecurityDescriptor */
1143 NULL /* lpftLastWriteTime */
1146 for ( dwIndex = 0; dwIndex < dwMountPoints; dwIndex++ ) {
1147 TCHAR szValueName[16];
1148 DWORD dwValueSize = 16;
1149 dwSize = sizeof(line);
1150 RegEnumValue( hkFreelance, dwIndex, szValueName, &dwValueSize, NULL,
1151 &dwType, line, &dwSize);
1153 cp=strchr(line, '#');
1155 cp=strchr(line, '%');
1156 memcpy(shortname, line, cp-line);
1157 shortname[cp-line]=0;
1159 if (!strcmp(shortname, toremove)) {
1160 RegDeleteValue( hkFreelance, szValueName );
1164 RegCloseKey(hkFreelance);
1168 cm_GetConfigDir(hfile);
1169 strcat(hfile, AFS_FREELANCE_INI);
1170 strcpy(hfile2, hfile);
1171 strcat(hfile2, "2");
1172 fp1=fopen(hfile, "r+");
1174 return CM_ERROR_INVAL;
1175 fp2=fopen(hfile2, "w+");
1178 return CM_ERROR_INVAL;
1181 fgets(line, sizeof(line), fp1);
1183 fprintf(fp2, "%d\n", n-1);
1185 for (i=0; i<n; i++) {
1186 fgets(line, sizeof(line), fp1);
1187 cp=strchr(line, '#');
1189 cp=strchr(line, '%');
1190 memcpy(shortname, line, cp-line);
1191 shortname[cp-line]=0;
1193 if (strcmp(shortname, toremove)==0) {
1204 return CM_ERROR_NOSUCHFILE;
1207 rename(hfile2, hfile);
1210 lock_ReleaseMutex(&cm_Freelance_Lock);
1211 cm_noteLocalMountPointChange();
1215 long cm_FreelanceAddSymlink(char *filename, char *destination, cm_fid_t *fidp)
1221 HKEY hkFreelanceSymlinks = 0;
1222 DWORD dwType, dwSize;
1227 /* before adding, verify the filename. If it is already in use, either as
1228 * as mount point or a cellname, do not permit the creation of the symlink.
1230 osi_Log2(afsd_logp,"Freelance Add Symlink request: filename=%s destination=%s",
1231 osi_LogSaveString(afsd_logp,filename),
1232 osi_LogSaveString(afsd_logp,destination));
1234 if ( filename[0] == '\0' || destination[0] == '\0' )
1235 return CM_ERROR_INVAL;
1238 if (filename[0] == '.') {
1239 cm_GetCell_Gen(&filename[1], fullname, CM_FLAG_CREATE);
1240 if (stricmp(&filename[1],fullname) == 0)
1241 return CM_ERROR_EXISTS;
1243 cm_GetCell_Gen(filename, fullname, CM_FLAG_CREATE);
1244 if (stricmp(filename,fullname) == 0)
1245 return CM_ERROR_EXISTS;
1249 if ( cm_FreelanceMountPointExists(filename) ||
1250 cm_FreelanceSymlinkExists(filename) )
1251 return CM_ERROR_EXISTS;
1254 lock_ObtainMutex(&cm_Freelance_Lock);
1257 if (RegCreateKeyEx( HKEY_LOCAL_MACHINE,
1258 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance\\Symlinks",
1261 REG_OPTION_NON_VOLATILE,
1262 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
1264 &hkFreelanceSymlinks,
1265 NULL) == ERROR_SUCCESS) {
1267 RegQueryInfoKey( hkFreelanceSymlinks,
1269 NULL, /* lpcClass */
1270 NULL, /* lpReserved */
1271 NULL, /* lpcSubKeys */
1272 NULL, /* lpcMaxSubKeyLen */
1273 NULL, /* lpcMaxClassLen */
1274 &dwSymlinks, /* lpcValues */
1275 NULL, /* lpcMaxValueNameLen */
1276 NULL, /* lpcMaxValueLen */
1277 NULL, /* lpcbSecurityDescriptor */
1278 NULL /* lpftLastWriteTime */
1281 sprintf(line, "%s:%s.", filename, destination);
1283 /* If we are adding a new value, there must be an unused name
1284 * within the range 0 to dwSymlinks
1286 for ( dwIndex = 0; dwIndex <= dwSymlinks; dwIndex++ ) {
1290 dwSize = sizeof(szLink);
1291 sprintf(szIndex, "%d", dwIndex);
1292 if (RegQueryValueEx( hkFreelanceSymlinks, szIndex, 0, &dwType, szLink, &dwSize) != ERROR_SUCCESS) {
1293 /* found an unused value */
1295 dwSize = (DWORD)strlen(line) + 1;
1296 RegSetValueEx( hkFreelanceSymlinks, szIndex, 0, dwType, line, dwSize);
1299 int len = (int)strlen(filename);
1300 if ( dwType == REG_SZ && !strncmp(filename, szLink, len) && szLink[len] == ':') {
1301 /* Replace the existing value */
1303 dwSize = (DWORD)strlen(line) + 1;
1304 RegSetValueEx( hkFreelanceSymlinks, szIndex, 0, dwType, line, dwSize);
1309 RegCloseKey(hkFreelanceSymlinks);
1312 lock_ReleaseMutex(&cm_Freelance_Lock);
1314 /* cm_reInitLocalMountPoints(); */
1317 fidp->vnode = cm_noLocalMountPoints + 1; /* vnode value of last mt pt */
1319 cm_noteLocalMountPointChange();
1323 long cm_FreelanceRemoveSymlink(char *toremove)
1327 char shortname[200];
1330 HKEY hkFreelanceSymlinks = 0;
1331 DWORD dwType, dwSize;
1336 lock_ObtainMutex(&cm_Freelance_Lock);
1339 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
1340 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance\\Symlinks",
1342 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
1343 &hkFreelanceSymlinks) == ERROR_SUCCESS) {
1345 RegQueryInfoKey( hkFreelanceSymlinks,
1347 NULL, /* lpcClass */
1348 NULL, /* lpReserved */
1349 NULL, /* lpcSubKeys */
1350 NULL, /* lpcMaxSubKeyLen */
1351 NULL, /* lpcMaxClassLen */
1352 &dwSymlinks, /* lpcValues */
1353 NULL, /* lpcMaxValueNameLen */
1354 NULL, /* lpcMaxValueLen */
1355 NULL, /* lpcbSecurityDescriptor */
1356 NULL /* lpftLastWriteTime */
1359 for ( dwIndex = 0; dwIndex < dwSymlinks; dwIndex++ ) {
1360 TCHAR szValueName[16];
1361 DWORD dwValueSize = 16;
1362 dwSize = sizeof(line);
1363 RegEnumValue( hkFreelanceSymlinks, dwIndex, szValueName, &dwValueSize, NULL,
1364 &dwType, line, &dwSize);
1366 cp=strchr(line, ':');
1367 memcpy(shortname, line, cp-line);
1368 shortname[cp-line]=0;
1370 if (!strcmp(shortname, toremove)) {
1371 RegDeleteValue( hkFreelanceSymlinks, szValueName );
1375 RegCloseKey(hkFreelanceSymlinks);
1379 lock_ReleaseMutex(&cm_Freelance_Lock);
1380 cm_noteLocalMountPointChange();
1383 #endif /* AFS_FREELANCE_CLIENT */