11 #include <WINNT/afsreg.h>
15 #ifdef AFS_FREELANCE_CLIENT
16 #include "cm_freelance.h"
19 extern void afsi_log(char *pattern, ...);
21 int cm_noLocalMountPoints;
23 int cm_fakeDirCallback=0;
24 int cm_fakeGettingCallback=0;
25 cm_localMountPoint_t* cm_localMountPoints;
26 osi_mutex_t cm_Freelance_Lock;
27 int cm_localMountPointChangeFlag = 0;
28 int cm_freelanceEnabled = 1;
29 time_t FakeFreelanceModTime = 0x3b49f6e2;
31 static int freelance_ShutdownFlag = 0;
32 static HANDLE hFreelanceChangeEvent = 0;
33 static HANDLE hFreelanceSymlinkChangeEvent = 0;
35 void cm_InitFakeRootDir();
37 void cm_FreelanceChangeNotifier(void * parmp) {
40 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
41 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance",
44 &hkFreelance) == ERROR_SUCCESS) {
46 hFreelanceChangeEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
47 if (hFreelanceChangeEvent == NULL) {
48 RegCloseKey(hkFreelance);
54 /* check hFreelanceChangeEvent to see if it is set.
55 * if so, call cm_noteLocalMountPointChange()
57 if (RegNotifyChangeKeyValue( hkFreelance, /* hKey */
58 FALSE, /* bWatchSubtree */
59 REG_NOTIFY_CHANGE_LAST_SET, /* dwNotifyFilter */
60 hFreelanceChangeEvent, /* hEvent */
61 TRUE /* fAsynchronous */
63 RegCloseKey(hkFreelance);
64 CloseHandle(hFreelanceChangeEvent);
65 hFreelanceChangeEvent = 0;
69 if (WaitForSingleObject(hFreelanceChangeEvent, INFINITE) == WAIT_OBJECT_0)
71 if (freelance_ShutdownFlag == 1) {
72 RegCloseKey(hkFreelance);
73 CloseHandle(hFreelanceChangeEvent);
74 hFreelanceChangeEvent = 0;
77 cm_noteLocalMountPointChange();
82 void cm_FreelanceSymlinkChangeNotifier(void * parmp) {
85 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
86 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance\\Symlinks",
89 &hkFreelance) == ERROR_SUCCESS) {
91 hFreelanceSymlinkChangeEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
92 if (hFreelanceSymlinkChangeEvent == NULL) {
93 RegCloseKey(hkFreelance);
99 /* check hFreelanceSymlinkChangeEvent to see if it is set.
100 * if so, call cm_noteLocalMountPointSymlinkChange()
102 if (RegNotifyChangeKeyValue( hkFreelance, /* hKey */
103 FALSE, /* bWatchSubtree */
104 REG_NOTIFY_CHANGE_LAST_SET, /* dwNotifyFilter */
105 hFreelanceSymlinkChangeEvent, /* hEvent */
106 TRUE /* fAsynchronous */
107 ) != ERROR_SUCCESS) {
108 RegCloseKey(hkFreelance);
109 CloseHandle(hFreelanceSymlinkChangeEvent);
110 hFreelanceSymlinkChangeEvent = 0;
114 if (WaitForSingleObject(hFreelanceSymlinkChangeEvent, INFINITE) == WAIT_OBJECT_0)
116 if (freelance_ShutdownFlag == 1) {
117 RegCloseKey(hkFreelance);
118 CloseHandle(hFreelanceSymlinkChangeEvent);
119 hFreelanceSymlinkChangeEvent = 0;
122 cm_noteLocalMountPointChange();
128 cm_FreelanceShutdown(void)
130 freelance_ShutdownFlag = 1;
131 if (hFreelanceChangeEvent != 0)
132 thrd_SetEvent(hFreelanceChangeEvent);
133 if (hFreelanceSymlinkChangeEvent != 0)
134 thrd_SetEvent(hFreelanceSymlinkChangeEvent);
137 void cm_InitFreelance() {
141 lock_InitializeMutex(&cm_Freelance_Lock, "Freelance Lock");
143 // make sure we sync the data version to the cached root scache_t
144 if (cm_data.rootSCachep && cm_data.rootSCachep->fid.cell == AFS_FAKE_ROOT_CELL_ID)
145 cm_data.fakeDirVersion = cm_data.rootSCachep->dataVersion;
147 // yj: first we make a call to cm_initLocalMountPoints
148 // to read all the local mount points from the registry
149 cm_InitLocalMountPoints();
151 // then we make a call to InitFakeRootDir to create
152 // a fake root directory based on the local mount points
153 cm_InitFakeRootDir();
154 // --- end of yj code
156 /* Start the registry monitor */
157 phandle = thrd_Create(NULL, 65536, (ThreadFunc) cm_FreelanceChangeNotifier,
158 NULL, 0, &lpid, "cm_FreelanceChangeNotifier");
159 osi_assert(phandle != NULL);
160 thrd_CloseHandle(phandle);
162 phandle = thrd_Create(NULL, 65536, (ThreadFunc) cm_FreelanceSymlinkChangeNotifier,
163 NULL, 0, &lpid, "cm_FreelanceSymlinkChangeNotifier");
164 osi_assert(phandle != NULL);
165 thrd_CloseHandle(phandle);
168 /* yj: Initialization of the fake root directory */
169 /* to be called while holding freelance lock unless during init. */
170 void cm_InitFakeRootDir() {
175 // allocate space for the fake info
176 cm_dirHeader_t fakeDirHeader;
177 cm_dirEntry_t fakeEntry;
178 cm_pageHeader_t fakePageHeader;
180 // i'm going to calculate how much space is needed for
181 // this fake root directory. we have these rules:
182 // 1. there are cm_noLocalMountPoints number of entries
183 // 2. each page is CM_DIR_PAGESIZE in size
184 // 3. the first 13 chunks of the first page are used for
186 // 4. the first chunk of all subsequent pages are used
187 // for page header stuff
188 // 5. a max of CM_DIR_EPP entries are allowed per page
189 // 6. each entry takes 1 or more chunks, depending on
190 // the size of the mount point string, as determined
192 // 7. each chunk is CM_DIR_CHUNKSIZE bytes
194 int CPP = CM_DIR_PAGESIZE / CM_DIR_CHUNKSIZE;
195 int curChunk = 13; // chunks 0 - 12 are used for header stuff
196 // of the first page in the directory
199 int curDirEntryInPage = 0;
203 /* Reserve 2 directory chunks for "." and ".." */
206 while (curDirEntry<cm_noLocalMountPoints) {
207 sizeOfCurEntry = cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0);
208 if ((curChunk + sizeOfCurEntry >= CPP) ||
209 (curDirEntryInPage + 1 >= CM_DIR_EPP)) {
211 curDirEntryInPage = 0;
214 curChunk += sizeOfCurEntry;
219 dirSize = (curPage+1) * CM_DIR_PAGESIZE;
220 cm_FakeRootDir = malloc(dirSize);
221 cm_fakeDirSize = dirSize;
223 // yj: when we get here, we've figured out how much memory we need and
224 // allocated the appropriate space for it. we now prceed to fill
225 // it up with entries.
228 curDirEntryInPage = 0;
231 // fields in the directory entry that are unused.
233 fakeEntry.length = 0;
235 fakeEntry.fid.unique = htonl(1);
237 // the first page is special, it uses fakeDirHeader instead of fakePageHeader
238 // we fill up the page with dirEntries that belong there and we make changes
239 // to the fakeDirHeader.header.freeBitmap along the way. Then when we're done
240 // filling up the dirEntries in this page, we copy the fakeDirHeader into
241 // the top of the page.
243 // init the freeBitmap array
245 fakeDirHeader.header.freeBitmap[i]=0;
247 fakeDirHeader.header.freeBitmap[0] = 0xff;
248 fakeDirHeader.header.freeBitmap[1] = 0x7f;
251 // we start counting at 13 because the 0th to 12th chunks are used for header
254 // stick the first 2 entries "." and ".." in
255 fakeEntry.fid.unique = htonl(1);
256 fakeEntry.fid.vnode = htonl(1);
257 strcpy(fakeEntry.name, ".");
258 currentPos = cm_FakeRootDir + curPage * CM_DIR_PAGESIZE + curChunk * CM_DIR_CHUNKSIZE;
259 memcpy(currentPos, &fakeEntry, CM_DIR_CHUNKSIZE);
260 curChunk++; curDirEntryInPage++;
261 strcpy(fakeEntry.name, "..");
262 currentPos = cm_FakeRootDir + curPage * CM_DIR_PAGESIZE + curChunk * CM_DIR_CHUNKSIZE;
263 memcpy(currentPos, &fakeEntry, CM_DIR_CHUNKSIZE);
264 curChunk++; curDirEntryInPage++;
266 // keep putting stuff into page 0 if
267 // 1. we're not done with all entries
268 // 2. we have less than CM_DIR_EPP entries in page 0
269 // 3. we're not out of chunks in page 0
271 while( (curDirEntry<cm_noLocalMountPoints) &&
272 (curDirEntryInPage < CM_DIR_EPP) &&
273 (curChunk + cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0) <= CPP))
276 noChunks = cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0);
277 fakeEntry.fid.vnode = htonl(curDirEntry + 2);
278 currentPos = cm_FakeRootDir + curPage * CM_DIR_PAGESIZE + curChunk * CM_DIR_CHUNKSIZE;
280 memcpy(currentPos, &fakeEntry, CM_DIR_CHUNKSIZE);
281 strcpy(currentPos + 12, (cm_localMountPoints+curDirEntry)->namep);
284 for (i=0; i<noChunks; i++) {
285 t1 = (curChunk + i) / 8;
286 t2 = curChunk + i - (t1*8);
287 fakeDirHeader.header.freeBitmap[t1] |= (1 << t2);
292 // when we get here, we're done with filling in the entries for page 0
293 // copy in the header info
295 memcpy(cm_FakeRootDir, &fakeDirHeader, 13 * CM_DIR_CHUNKSIZE);
299 // ok, page 0's done. Move on to the next page.
300 while (curDirEntry<cm_noLocalMountPoints) {
302 curChunk = 1; // the zeroth chunk is reserved for page header
303 curDirEntryInPage = 0;
304 for (i=0; i<8; i++) {
305 fakePageHeader.freeBitmap[i]=0;
307 fakePageHeader.freeCount = 0;
308 fakePageHeader.pgcount = 0;
309 fakePageHeader.tag = htons(1234);
311 // while we're on the same page...
312 while ( (curDirEntry<cm_noLocalMountPoints) &&
313 (curDirEntryInPage < CM_DIR_EPP) &&
314 (curChunk + cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0) <= CPP))
316 // add an entry to this page
318 noChunks = cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0);
319 fakeEntry.fid.vnode=htonl(curDirEntry+2);
320 currentPos = cm_FakeRootDir + curPage * CM_DIR_PAGESIZE + curChunk * CM_DIR_CHUNKSIZE;
321 memcpy(currentPos, &fakeEntry, CM_DIR_CHUNKSIZE);
322 strcpy(currentPos + 12, (cm_localMountPoints+curDirEntry)->namep);
325 for (i=0; i<noChunks; i++) {
326 t1 = (curChunk + i) / 8;
327 t2 = curChunk + i - (t1*8);
328 fakePageHeader.freeBitmap[t1] |= (1 << t2);
332 memcpy(cm_FakeRootDir + curPage * CM_DIR_PAGESIZE, &fakePageHeader, sizeof(fakePageHeader));
337 // we know the fakeDir is setup properly, so we claim that we have callback
338 osi_Log0(afsd_logp,"cm_InitFakeRootDir fakeDirCallback=1");
339 cm_fakeDirCallback=1;
341 // when we get here, we've set up everything! done!
344 int cm_FakeRootFid(cm_fid_t *fidp)
346 fidp->cell = AFS_FAKE_ROOT_CELL_ID; /* root cell */
347 fidp->volume = AFS_FAKE_ROOT_VOL_ID; /* root.afs ? */
353 /* called directly from ioctl */
354 /* called while not holding freelance lock */
355 int cm_noteLocalMountPointChange(void) {
356 lock_ObtainMutex(&cm_Freelance_Lock);
357 cm_data.fakeDirVersion++;
358 cm_localMountPointChangeFlag = 1;
359 lock_ReleaseMutex(&cm_Freelance_Lock);
363 int cm_getLocalMountPointChange() {
364 return cm_localMountPointChangeFlag;
367 int cm_clearLocalMountPointChange() {
368 cm_localMountPointChangeFlag = 0;
372 int cm_reInitLocalMountPoints() {
375 cm_scache_t *scp, **lscpp, *tscp;
377 osi_Log0(afsd_logp,"----- freelance reinitialization starts ----- ");
379 // first we invalidate all the SCPs that were created
380 // for the local mount points
382 osi_Log0(afsd_logp,"Invalidating local mount point scp... ");
384 aFid.cell = AFS_FAKE_ROOT_CELL_ID;
385 aFid.volume=AFS_FAKE_ROOT_VOL_ID;
389 lock_ObtainWrite(&cm_scacheLock);
390 lock_ObtainMutex(&cm_Freelance_Lock); /* always scache then freelance lock */
391 for (i=0; i<cm_noLocalMountPoints; i++) {
392 hash = CM_SCACHE_HASH(&aFid);
393 for (scp=cm_data.scacheHashTablep[hash]; scp; scp=scp->nextp) {
394 if (scp->fid.volume == aFid.volume &&
395 scp->fid.vnode == aFid.vnode &&
396 scp->fid.unique == aFid.unique
399 // mark the scp to be reused
400 cm_HoldSCacheNoLock(scp);
401 lock_ReleaseWrite(&cm_scacheLock);
402 lock_ObtainMutex(&scp->mx);
403 cm_DiscardSCache(scp);
404 lock_ReleaseMutex(&scp->mx);
405 cm_CallbackNotifyChange(scp);
406 lock_ObtainWrite(&cm_scacheLock);
407 cm_ReleaseSCacheNoLock(scp);
409 // take the scp out of the hash
410 for (lscpp = &cm_data.scacheHashTablep[hash], tscp = cm_data.scacheHashTablep[hash];
412 lscpp = &tscp->nextp, tscp = tscp->nextp) {
415 lock_ObtainMutex(&scp->mx);
416 scp->flags &= ~CM_SCACHEFLAG_INHASH;
417 lock_ReleaseMutex(&scp->mx);
423 aFid.vnode = aFid.vnode + 1;
425 lock_ReleaseWrite(&cm_scacheLock);
426 osi_Log0(afsd_logp,"\tall old scp cleared!");
428 // we must free the memory that was allocated in the prev
429 // cm_InitLocalMountPoints call
430 osi_Log0(afsd_logp,"Removing old localmountpoints... ");
431 free(cm_localMountPoints);
432 osi_Log0(afsd_logp,"\tall old localmountpoints cleared!");
434 // now re-init the localmountpoints
435 osi_Log0(afsd_logp,"Creating new localmountpoints... ");
436 cm_InitLocalMountPoints();
437 osi_Log0(afsd_logp,"\tcreated new set of localmountpoints!");
439 // now we have to free the memory allocated in cm_initfakerootdir
440 osi_Log0(afsd_logp,"Removing old fakedir... ");
441 free(cm_FakeRootDir);
442 osi_Log0(afsd_logp,"\t\told fakedir removed!");
444 // then we re-create that dir
445 osi_Log0(afsd_logp,"Creating new fakedir... ");
446 cm_InitFakeRootDir();
447 osi_Log0(afsd_logp,"\t\tcreated new fakedir!");
449 lock_ReleaseMutex(&cm_Freelance_Lock);
451 osi_Log0(afsd_logp,"----- freelance reinit complete -----");
456 // yj: open up the registry and read all the local mount
457 // points that are stored there. Part of the initialization
458 // process for the freelance client.
459 /* to be called while holding freelance lock unless during init. */
460 long cm_InitLocalMountPoints() {
465 cm_localMountPoint_t* aLocalMountPoint;
468 char rootCellName[256];
469 HKEY hkFreelance = 0, hkFreelanceSymlinks = 0;
470 DWORD dwType, dwSize;
471 DWORD dwMountPoints = 0;
473 DWORD dwSymlinks = 0;
474 FILETIME ftLastWriteTime;
476 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
477 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance",
479 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
480 &hkFreelance) == ERROR_SUCCESS) {
482 RegQueryInfoKey( hkFreelance,
485 NULL, /* lpReserved */
486 NULL, /* lpcSubKeys */
487 NULL, /* lpcMaxSubKeyLen */
488 NULL, /* lpcMaxClassLen */
489 &dwMountPoints, /* lpcValues */
490 NULL, /* lpcMaxValueNameLen */
491 NULL, /* lpcMaxValueLen */
492 NULL, /* lpcbSecurityDescriptor */
493 &ftLastWriteTime /* lpftLastWriteTime */
496 smb_UnixTimeFromLargeSearchTime(&FakeFreelanceModTime, &ftLastWriteTime);
498 if ( dwMountPoints == 0 ) {
499 rootCellName[0] = '.';
500 code = cm_GetRootCellName(&rootCellName[1]);
502 cm_FreelanceAddMount(&rootCellName[1], &rootCellName[1], "root.cell.", 0, NULL);
503 cm_FreelanceAddMount(rootCellName, &rootCellName[1], "root.cell.", 1, NULL);
504 cm_FreelanceAddMount(".root", &rootCellName[1], "root.afs.", 1, NULL);
509 if (RegCreateKeyEx( HKEY_LOCAL_MACHINE,
510 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance\\Symlinks",
513 REG_OPTION_NON_VOLATILE,
514 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
516 &hkFreelanceSymlinks,
517 NULL) == ERROR_SUCCESS) {
519 RegQueryInfoKey( hkFreelanceSymlinks,
522 NULL, /* lpReserved */
523 NULL, /* lpcSubKeys */
524 NULL, /* lpcMaxSubKeyLen */
525 NULL, /* lpcMaxClassLen */
526 &dwSymlinks, /* lpcValues */
527 NULL, /* lpcMaxValueNameLen */
528 NULL, /* lpcMaxValueLen */
529 NULL, /* lpcbSecurityDescriptor */
530 NULL /* lpftLastWriteTime */
534 // get the number of entries there are from the first line
536 cm_noLocalMountPoints = dwMountPoints + dwSymlinks;
538 // create space to store the local mount points
539 cm_localMountPoints = malloc(sizeof(cm_localMountPoint_t) * cm_noLocalMountPoints);
540 aLocalMountPoint = cm_localMountPoints;
542 // now we read n lines and parse them into local mount points
543 // where n is the number of local mount points there are, as
545 // Each line in the ini file represents 1 local mount point and
546 // is in the format xxx#yyy:zzz, where xxx is the directory
547 // entry name, yyy is the cell name and zzz is the volume name.
548 // #yyy:zzz together make up the mount point.
549 for ( dwIndex = 0 ; dwIndex < dwMountPoints; dwIndex++ ) {
550 TCHAR szValueName[16];
551 DWORD dwValueSize = 16;
552 dwSize = sizeof(line);
553 if (RegEnumValue( hkFreelance, dwIndex, szValueName, &dwValueSize, NULL,
554 &dwType, line, &dwSize))
556 afsi_log("RegEnumValue(hkFreelance) failed");
557 cm_noLocalMountPoints--;
561 afsi_log("Mountpoint[%d] = %s",dwIndex, line);
563 /* find the trailing dot; null terminate after it */
564 t2 = strrchr(line, '.');
568 for ( t=line;*t;t++ ) {
569 if ( !isprint(*t) ) {
570 afsi_log("error occurred while parsing mountpoint entry [%d]: non-printable character", dwIndex);
571 fprintf(stderr, "error occurred while parsing mountpoint entry [%d]: non-printable character", dwIndex);
572 cm_noLocalMountPoints--;
577 // line is not empty, so let's parse it
578 t = strchr(line, '#');
580 t = strchr(line, '%');
581 // make sure that there is a '#' or '%' separator in the line
583 afsi_log("error occurred while parsing mountpoint entry [%d]: no # or %% separator", dwIndex);
584 fprintf(stderr, "error occurred while parsing mountpoint entry [%d]: no # or %% separator", dwIndex);
585 cm_noLocalMountPoints--;
589 aLocalMountPoint->fileType = CM_SCACHETYPE_MOUNTPOINT;
590 aLocalMountPoint->namep=malloc(t-line+1);
591 strncpy(aLocalMountPoint->namep, line, t-line);
592 aLocalMountPoint->namep[t-line] = '\0';
594 /* copy the mount point string */
595 aLocalMountPoint->mountPointStringp=malloc(strlen(t));
596 strncpy(aLocalMountPoint->mountPointStringp, t, strlen(t)-1);
597 aLocalMountPoint->mountPointStringp[strlen(t)-1] = '\0';
599 osi_Log2(afsd_logp,"found mount point: name %s, string %s",
600 osi_LogSaveString(afsd_logp,aLocalMountPoint->namep),
601 osi_LogSaveString(afsd_logp,aLocalMountPoint->mountPointStringp));
606 for ( dwIndex = 0 ; dwIndex < dwSymlinks; dwIndex++ ) {
607 TCHAR szValueName[16];
608 DWORD dwValueSize = 16;
609 dwSize = sizeof(line);
610 if (RegEnumValue( hkFreelanceSymlinks, dwIndex, szValueName, &dwValueSize, NULL,
611 &dwType, line, &dwSize))
613 afsi_log("RegEnumValue(hkFreelanceSymlinks) failed");
614 cm_noLocalMountPoints--;
618 afsi_log("Symlink[%d] = %s",dwIndex, line);
620 /* find the trailing dot; null terminate after it */
621 t2 = strrchr(line, '.');
625 for ( t=line;*t;t++ ) {
626 if ( !isprint(*t) ) {
627 afsi_log("error occurred while parsing symlink entry [%d]: non-printable character", dwIndex);
628 fprintf(stderr, "error occurred while parsing symlink entry [%d]: non-printable character", dwIndex);
629 cm_noLocalMountPoints--;
634 // line is not empty, so let's parse it
635 t = strchr(line, ':');
637 // make sure that there is a ':' separator in the line
639 afsi_log("error occurred while parsing symlink entry [%d]: no ':' separator", dwIndex);
640 fprintf(stderr, "error occurred while parsing symlink entry [%d]: no ':' separator", dwIndex);
641 cm_noLocalMountPoints--;
645 aLocalMountPoint->fileType = CM_SCACHETYPE_SYMLINK;
646 aLocalMountPoint->namep=malloc(t-line+1);
647 strncpy(aLocalMountPoint->namep, line, t-line);
648 aLocalMountPoint->namep[t-line] = '\0';
650 /* copy the symlink string */
651 aLocalMountPoint->mountPointStringp=malloc(strlen(t)-1);
652 strncpy(aLocalMountPoint->mountPointStringp, t+1, strlen(t)-2);
653 aLocalMountPoint->mountPointStringp[strlen(t)-2] = '\0';
655 osi_Log2(afsd_logp,"found symlink: name %s, string %s",
656 osi_LogSaveString(afsd_logp,aLocalMountPoint->namep),
657 osi_LogSaveString(afsd_logp,aLocalMountPoint->mountPointStringp));
662 if ( hkFreelanceSymlinks )
663 RegCloseKey( hkFreelanceSymlinks );
664 RegCloseKey(hkFreelance);
668 /* What follows is the old code to read freelance mount points
669 * out of a text file modified to copy the data into the registry
671 cm_GetConfigDir(hdir);
672 strcat(hdir, AFS_FREELANCE_INI);
673 // open the ini file for reading
674 fp = fopen(hdir, "r");
676 /* look in the Windows directory where we used to store the file */
677 GetWindowsDirectory(hdir, sizeof(hdir));
679 strcat(hdir, AFS_FREELANCE_INI);
680 fp = fopen(hdir, "r");
683 RegCreateKeyEx( HKEY_LOCAL_MACHINE,
684 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance",
687 REG_OPTION_NON_VOLATILE,
695 RegCloseKey(hkFreelance);
696 rootCellName[0] = '.';
697 code = cm_GetRootCellName(&rootCellName[1]);
699 cm_FreelanceAddMount(&rootCellName[1], &rootCellName[1], "root.cell.", 0, NULL);
700 cm_FreelanceAddMount(rootCellName, &rootCellName[1], "root.cell.", 1, NULL);
701 cm_FreelanceAddMount(".root", &rootCellName[1], "root.afs.", 1, NULL);
706 // we successfully opened the file
707 osi_Log0(afsd_logp,"opened afs_freelance.ini");
709 // now we read the first line to see how many entries
711 fgets(line, sizeof(line), fp);
713 // if the line is empty at any point when we're reading
714 // we're screwed. report error and return.
716 afsi_log("error occurred while reading afs_freelance.ini");
717 fprintf(stderr, "error occurred while reading afs_freelance.ini");
721 // get the number of entries there are from the first line
723 cm_noLocalMountPoints = atoi(line);
725 if (cm_noLocalMountPoints > 0) {
726 // create space to store the local mount points
727 cm_localMountPoints = malloc(sizeof(cm_localMountPoint_t) * cm_noLocalMountPoints);
728 aLocalMountPoint = cm_localMountPoints;
731 // now we read n lines and parse them into local mount points
732 // where n is the number of local mount points there are, as
734 // Each line in the ini file represents 1 local mount point and
735 // is in the format xxx#yyy:zzz, where xxx is the directory
736 // entry name, yyy is the cell name and zzz is the volume name.
737 // #yyy:zzz together make up the mount point.
738 for (i=0; i<cm_noLocalMountPoints; i++) {
739 fgets(line, sizeof(line), fp);
740 // check that the line is not empty
742 afsi_log("error occurred while parsing entry in %s: empty line in line %d", AFS_FREELANCE_INI, i);
743 fprintf(stderr, "error occurred while parsing entry in afs_freelance.ini: empty line in line %d", i);
747 /* find the trailing dot; null terminate after it */
748 t2 = strrchr(line, '.');
754 /* we are migrating to the registry */
755 sprintf(szIndex,"%d",dwIndex++);
757 dwSize = (DWORD)strlen(line) + 1;
758 RegSetValueEx( hkFreelance, szIndex, 0, dwType, line, dwSize);
761 // line is not empty, so let's parse it
762 t = strchr(line, '#');
764 t = strchr(line, '%');
765 // make sure that there is a '#' or '%' separator in the line
767 afsi_log("error occurred while parsing entry in %s: no # or %% separator in line %d", AFS_FREELANCE_INI, i);
768 fprintf(stderr, "error occurred while parsing entry in afs_freelance.ini: no # or %% separator in line %d", i);
771 aLocalMountPoint->namep=malloc(t-line+1);
772 memcpy(aLocalMountPoint->namep, line, t-line);
773 *(aLocalMountPoint->namep + (t-line)) = 0;
775 aLocalMountPoint->mountPointStringp=malloc(strlen(line) - (t-line) + 1);
776 memcpy(aLocalMountPoint->mountPointStringp, t, strlen(line)-(t-line)-1);
777 *(aLocalMountPoint->mountPointStringp + (strlen(line)-(t-line)-1)) = 0;
779 osi_Log2(afsd_logp,"found mount point: name %s, string %s",
780 aLocalMountPoint->namep,
781 aLocalMountPoint->mountPointStringp);
787 RegCloseKey(hkFreelance);
793 int cm_getNoLocalMountPoints() {
794 return cm_noLocalMountPoints;
797 long cm_FreelanceMountPointExists(char * filename)
803 HKEY hkFreelance = 0;
804 DWORD dwType, dwSize;
808 lock_ObtainMutex(&cm_Freelance_Lock);
810 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
811 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance",
813 KEY_READ|KEY_QUERY_VALUE,
814 &hkFreelance) == ERROR_SUCCESS)
816 RegQueryInfoKey( hkFreelance,
819 NULL, /* lpReserved */
820 NULL, /* lpcSubKeys */
821 NULL, /* lpcMaxSubKeyLen */
822 NULL, /* lpcMaxClassLen */
823 &dwMountPoints, /* lpcValues */
824 NULL, /* lpcMaxValueNameLen */
825 NULL, /* lpcMaxValueLen */
826 NULL, /* lpcbSecurityDescriptor */
827 NULL /* lpftLastWriteTime */
830 for ( dwIndex = 0; dwIndex < dwMountPoints; dwIndex++ ) {
831 TCHAR szValueName[16];
832 DWORD dwValueSize = 16;
833 dwSize = sizeof(line);
834 RegEnumValue( hkFreelance, dwIndex, szValueName, &dwValueSize, NULL,
835 &dwType, line, &dwSize);
837 cp=strchr(line, '#');
839 cp=strchr(line, '%');
840 memcpy(shortname, line, cp-line);
841 shortname[cp-line]=0;
843 if (!strcmp(shortname, filename)) {
848 for ( dwIndex = 0; dwIndex < dwMountPoints; dwIndex++ ) {
849 TCHAR szValueName[16];
850 DWORD dwValueSize = 16;
851 dwSize = sizeof(line);
852 RegEnumValue( hkFreelance, dwIndex, szValueName, &dwValueSize, NULL,
853 &dwType, line, &dwSize);
855 cp=strchr(line, '#');
857 cp=strchr(line, '%');
858 memcpy(shortname, line, cp-line);
859 shortname[cp-line]=0;
861 if (!stricmp(shortname, filename)) {
866 RegCloseKey(hkFreelance);
869 lock_ReleaseMutex(&cm_Freelance_Lock);
874 long cm_FreelanceSymlinkExists(char * filename)
880 HKEY hkFreelance = 0;
881 DWORD dwType, dwSize;
885 lock_ObtainMutex(&cm_Freelance_Lock);
887 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
888 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance\\Symlinks",
890 KEY_READ|KEY_QUERY_VALUE,
891 &hkFreelance) == ERROR_SUCCESS)
893 RegQueryInfoKey( hkFreelance,
896 NULL, /* lpReserved */
897 NULL, /* lpcSubKeys */
898 NULL, /* lpcMaxSubKeyLen */
899 NULL, /* lpcMaxClassLen */
900 &dwSymlinks, /* lpcValues */
901 NULL, /* lpcMaxValueNameLen */
902 NULL, /* lpcMaxValueLen */
903 NULL, /* lpcbSecurityDescriptor */
904 NULL /* lpftLastWriteTime */
907 for ( dwIndex = 0; dwIndex < dwSymlinks; dwIndex++ ) {
908 TCHAR szValueName[16];
909 DWORD dwValueSize = 16;
910 dwSize = sizeof(line);
911 RegEnumValue( hkFreelance, dwIndex, szValueName, &dwValueSize, NULL,
912 &dwType, line, &dwSize);
914 cp=strchr(line, ':');
915 memcpy(shortname, line, cp-line);
916 shortname[cp-line]=0;
918 if (!strcmp(shortname, filename)) {
923 for ( dwIndex = 0; dwIndex < dwSymlinks; dwIndex++ ) {
924 TCHAR szValueName[16];
925 DWORD dwValueSize = 16;
926 dwSize = sizeof(line);
927 RegEnumValue( hkFreelance, dwIndex, szValueName, &dwValueSize, NULL,
928 &dwType, line, &dwSize);
930 cp=strchr(line, ':');
931 memcpy(shortname, line, cp-line);
932 shortname[cp-line]=0;
934 if (!stricmp(shortname, filename)) {
939 RegCloseKey(hkFreelance);
942 lock_ReleaseMutex(&cm_Freelance_Lock);
947 long cm_FreelanceAddMount(char *filename, char *cellname, char *volume, int rw, cm_fid_t *fidp)
955 HKEY hkFreelance = 0;
956 DWORD dwType, dwSize;
960 /* before adding, verify the cell name; if it is not a valid cell,
961 don't add the mount point.
962 allow partial matches as a means of poor man's alias. */
963 /* major performance issue? */
964 osi_Log4(afsd_logp,"Freelance Add Mount request: filename=%s cellname=%s volume=%s %s",
965 osi_LogSaveString(afsd_logp,filename),
966 osi_LogSaveString(afsd_logp,cellname),
967 osi_LogSaveString(afsd_logp,volume),
970 if ( filename[0] == '\0' || cellname[0] == '\0' || volume[0] == '\0' )
973 if (cellname[0] == '.') {
974 if (!cm_GetCell_Gen(&cellname[1], fullname, CM_FLAG_CREATE))
977 if (!cm_GetCell_Gen(cellname, fullname, CM_FLAG_CREATE))
981 if ( cm_FreelanceMountPointExists(filename) ||
982 cm_FreelanceSymlinkExists(filename) )
985 osi_Log1(afsd_logp,"Freelance Adding Mount for Cell: %s",
986 osi_LogSaveString(afsd_logp,cellname));
988 lock_ObtainMutex(&cm_Freelance_Lock);
990 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
991 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance",
993 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
994 &hkFreelance) == ERROR_SUCCESS) {
996 RegQueryInfoKey( hkFreelance,
999 NULL, /* lpReserved */
1000 NULL, /* lpcSubKeys */
1001 NULL, /* lpcMaxSubKeyLen */
1002 NULL, /* lpcMaxClassLen */
1003 &dwMountPoints, /* lpcValues */
1004 NULL, /* lpcMaxValueNameLen */
1005 NULL, /* lpcMaxValueLen */
1006 NULL, /* lpcbSecurityDescriptor */
1007 NULL /* lpftLastWriteTime */
1011 sprintf(line, "%s%%%s:%s", filename, fullname, volume);
1013 sprintf(line, "%s#%s:%s", filename, fullname, volume);
1015 /* If we are adding a new value, there must be an unused name
1016 * within the range 0 to dwMountPoints
1018 for ( dwIndex = 0; dwIndex <= dwMountPoints; dwIndex++ ) {
1022 dwSize = sizeof(szMount);
1023 sprintf(szIndex, "%d", dwIndex);
1024 if (RegQueryValueEx( hkFreelance, szIndex, 0, &dwType, szMount, &dwSize) != ERROR_SUCCESS) {
1025 /* found an unused value */
1027 dwSize = (DWORD)strlen(line) + 1;
1028 RegSetValueEx( hkFreelance, szIndex, 0, dwType, line, dwSize);
1031 int len = (int)strlen(filename);
1032 if ( dwType == REG_SZ && !strncmp(filename, szMount, len) &&
1033 (szMount[len] == '%' || szMount[len] == '#')) {
1034 /* Replace the existing value */
1036 dwSize = (DWORD)strlen(line) + 1;
1037 RegSetValueEx( hkFreelance, szIndex, 0, dwType, line, dwSize);
1042 RegCloseKey(hkFreelance);
1045 cm_GetConfigDir(hfile);
1046 strcat(hfile, AFS_FREELANCE_INI);
1047 fp = fopen(hfile, "r+");
1049 return CM_ERROR_INVAL;
1050 fgets(line, sizeof(line), fp);
1053 fseek(fp, 0, SEEK_SET);
1054 fprintf(fp, "%d", n);
1055 fseek(fp, 0, SEEK_END);
1057 fprintf(fp, "%s%%%s:%s\n", filename, fullname, volume);
1059 fprintf(fp, "%s#%s:%s\n", filename, fullname, volume);
1062 lock_ReleaseMutex(&cm_Freelance_Lock);
1064 /* cm_reInitLocalMountPoints(); */
1067 fidp->vnode = cm_noLocalMountPoints + 1; /* vnode value of last mt pt */
1069 cm_noteLocalMountPointChange();
1073 long cm_FreelanceRemoveMount(char *toremove)
1078 char shortname[200];
1079 char hfile[120], hfile2[120];
1082 HKEY hkFreelance = 0;
1083 DWORD dwType, dwSize;
1084 DWORD dwMountPoints;
1087 lock_ObtainMutex(&cm_Freelance_Lock);
1089 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
1090 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance",
1092 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
1093 &hkFreelance) == ERROR_SUCCESS) {
1095 RegQueryInfoKey( hkFreelance,
1097 NULL, /* lpcClass */
1098 NULL, /* lpReserved */
1099 NULL, /* lpcSubKeys */
1100 NULL, /* lpcMaxSubKeyLen */
1101 NULL, /* lpcMaxClassLen */
1102 &dwMountPoints, /* lpcValues */
1103 NULL, /* lpcMaxValueNameLen */
1104 NULL, /* lpcMaxValueLen */
1105 NULL, /* lpcbSecurityDescriptor */
1106 NULL /* lpftLastWriteTime */
1109 for ( dwIndex = 0; dwIndex < dwMountPoints; dwIndex++ ) {
1110 TCHAR szValueName[16];
1111 DWORD dwValueSize = 16;
1112 dwSize = sizeof(line);
1113 RegEnumValue( hkFreelance, dwIndex, szValueName, &dwValueSize, NULL,
1114 &dwType, line, &dwSize);
1116 cp=strchr(line, '#');
1118 cp=strchr(line, '%');
1119 memcpy(shortname, line, cp-line);
1120 shortname[cp-line]=0;
1122 if (!strcmp(shortname, toremove)) {
1123 RegDeleteValue( hkFreelance, szValueName );
1127 RegCloseKey(hkFreelance);
1130 cm_GetConfigDir(hfile);
1131 strcat(hfile, AFS_FREELANCE_INI);
1132 strcpy(hfile2, hfile);
1133 strcat(hfile2, "2");
1134 fp1=fopen(hfile, "r+");
1136 return CM_ERROR_INVAL;
1137 fp2=fopen(hfile2, "w+");
1140 return CM_ERROR_INVAL;
1143 fgets(line, sizeof(line), fp1);
1145 fprintf(fp2, "%d\n", n-1);
1147 for (i=0; i<n; i++) {
1148 fgets(line, sizeof(line), fp1);
1149 cp=strchr(line, '#');
1151 cp=strchr(line, '%');
1152 memcpy(shortname, line, cp-line);
1153 shortname[cp-line]=0;
1155 if (strcmp(shortname, toremove)==0) {
1166 return CM_ERROR_NOSUCHFILE;
1169 rename(hfile2, hfile);
1172 lock_ReleaseMutex(&cm_Freelance_Lock);
1173 cm_noteLocalMountPointChange();
1177 long cm_FreelanceAddSymlink(char *filename, char *destination, cm_fid_t *fidp)
1182 HKEY hkFreelanceSymlinks = 0;
1183 DWORD dwType, dwSize;
1187 /* before adding, verify the filename. If it is already in use, either as
1188 * as mount point or a cellname, do not permit the creation of the symlink.
1190 osi_Log2(afsd_logp,"Freelance Add Symlink request: filename=%s destination=%s",
1191 osi_LogSaveString(afsd_logp,filename),
1192 osi_LogSaveString(afsd_logp,destination));
1194 if ( filename[0] == '\0' || destination[0] == '\0' )
1198 if (filename[0] == '.') {
1199 cm_GetCell_Gen(&filename[1], fullname, CM_FLAG_CREATE);
1200 if (stricmp(&filename[1],fullname) == 0)
1203 cm_GetCell_Gen(filename, fullname, CM_FLAG_CREATE);
1204 if (stricmp(filename,fullname) == 0)
1208 if ( cm_FreelanceMountPointExists(filename) ||
1209 cm_FreelanceSymlinkExists(filename) )
1212 lock_ObtainMutex(&cm_Freelance_Lock);
1214 if (RegCreateKeyEx( HKEY_LOCAL_MACHINE,
1215 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance\\Symlinks",
1218 REG_OPTION_NON_VOLATILE,
1219 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
1221 &hkFreelanceSymlinks,
1222 NULL) == ERROR_SUCCESS) {
1224 RegQueryInfoKey( hkFreelanceSymlinks,
1226 NULL, /* lpcClass */
1227 NULL, /* lpReserved */
1228 NULL, /* lpcSubKeys */
1229 NULL, /* lpcMaxSubKeyLen */
1230 NULL, /* lpcMaxClassLen */
1231 &dwSymlinks, /* lpcValues */
1232 NULL, /* lpcMaxValueNameLen */
1233 NULL, /* lpcMaxValueLen */
1234 NULL, /* lpcbSecurityDescriptor */
1235 NULL /* lpftLastWriteTime */
1238 sprintf(line, "%s:%s.", filename, destination);
1240 /* If we are adding a new value, there must be an unused name
1241 * within the range 0 to dwSymlinks
1243 for ( dwIndex = 0; dwIndex <= dwSymlinks; dwIndex++ ) {
1247 dwSize = sizeof(szLink);
1248 sprintf(szIndex, "%d", dwIndex);
1249 if (RegQueryValueEx( hkFreelanceSymlinks, szIndex, 0, &dwType, szLink, &dwSize) != ERROR_SUCCESS) {
1250 /* found an unused value */
1252 dwSize = (DWORD)strlen(line) + 1;
1253 RegSetValueEx( hkFreelanceSymlinks, szIndex, 0, dwType, line, dwSize);
1256 int len = (int)strlen(filename);
1257 if ( dwType == REG_SZ && !strncmp(filename, szLink, len) && szLink[len] == ':') {
1258 /* Replace the existing value */
1260 dwSize = (DWORD)strlen(line) + 1;
1261 RegSetValueEx( hkFreelanceSymlinks, szIndex, 0, dwType, line, dwSize);
1266 RegCloseKey(hkFreelanceSymlinks);
1268 lock_ReleaseMutex(&cm_Freelance_Lock);
1270 /* cm_reInitLocalMountPoints(); */
1273 fidp->vnode = cm_noLocalMountPoints + 1; /* vnode value of last mt pt */
1275 cm_noteLocalMountPointChange();
1279 long cm_FreelanceRemoveSymlink(char *toremove)
1283 char shortname[200];
1285 HKEY hkFreelanceSymlinks = 0;
1286 DWORD dwType, dwSize;
1290 lock_ObtainMutex(&cm_Freelance_Lock);
1292 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
1293 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance\\Symlinks",
1295 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
1296 &hkFreelanceSymlinks) == ERROR_SUCCESS) {
1298 RegQueryInfoKey( hkFreelanceSymlinks,
1300 NULL, /* lpcClass */
1301 NULL, /* lpReserved */
1302 NULL, /* lpcSubKeys */
1303 NULL, /* lpcMaxSubKeyLen */
1304 NULL, /* lpcMaxClassLen */
1305 &dwSymlinks, /* lpcValues */
1306 NULL, /* lpcMaxValueNameLen */
1307 NULL, /* lpcMaxValueLen */
1308 NULL, /* lpcbSecurityDescriptor */
1309 NULL /* lpftLastWriteTime */
1312 for ( dwIndex = 0; dwIndex < dwSymlinks; dwIndex++ ) {
1313 TCHAR szValueName[16];
1314 DWORD dwValueSize = 16;
1315 dwSize = sizeof(line);
1316 RegEnumValue( hkFreelanceSymlinks, dwIndex, szValueName, &dwValueSize, NULL,
1317 &dwType, line, &dwSize);
1319 cp=strchr(line, ':');
1320 memcpy(shortname, line, cp-line);
1321 shortname[cp-line]=0;
1323 if (!strcmp(shortname, toremove)) {
1324 RegDeleteValue( hkFreelanceSymlinks, szValueName );
1328 RegCloseKey(hkFreelanceSymlinks);
1331 lock_ReleaseMutex(&cm_Freelance_Lock);
1332 cm_noteLocalMountPointChange();
1335 #endif /* AFS_FREELANCE_CLIENT */