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;
22 char * cm_FakeRootDir = NULL;
23 int cm_fakeDirSize = 0;
24 int cm_fakeDirCallback=0;
25 int cm_fakeGettingCallback=0;
26 cm_localMountPoint_t* cm_localMountPoints;
27 osi_mutex_t cm_Freelance_Lock;
28 int cm_localMountPointChangeFlag = 0;
29 int cm_freelanceEnabled = 1;
30 time_t FakeFreelanceModTime = 0x3b49f6e2;
32 static int freelance_ShutdownFlag = 0;
33 static HANDLE hFreelanceChangeEvent = 0;
34 static HANDLE hFreelanceSymlinkChangeEvent = 0;
36 void cm_InitFakeRootDir();
38 void cm_FreelanceChangeNotifier(void * parmp) {
41 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
42 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance",
45 &hkFreelance) == ERROR_SUCCESS) {
47 hFreelanceChangeEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
48 if (hFreelanceChangeEvent == NULL) {
49 RegCloseKey(hkFreelance);
55 /* check hFreelanceChangeEvent to see if it is set.
56 * if so, call cm_noteLocalMountPointChange()
58 if (RegNotifyChangeKeyValue( hkFreelance, /* hKey */
59 FALSE, /* bWatchSubtree */
60 REG_NOTIFY_CHANGE_LAST_SET, /* dwNotifyFilter */
61 hFreelanceChangeEvent, /* hEvent */
62 TRUE /* fAsynchronous */
64 RegCloseKey(hkFreelance);
65 CloseHandle(hFreelanceChangeEvent);
66 hFreelanceChangeEvent = 0;
70 if (WaitForSingleObject(hFreelanceChangeEvent, INFINITE) == WAIT_OBJECT_0)
72 if (freelance_ShutdownFlag == 1) {
73 RegCloseKey(hkFreelance);
74 CloseHandle(hFreelanceChangeEvent);
75 hFreelanceChangeEvent = 0;
78 cm_noteLocalMountPointChange();
83 void cm_FreelanceSymlinkChangeNotifier(void * parmp) {
86 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
87 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance\\Symlinks",
90 &hkFreelance) == ERROR_SUCCESS) {
92 hFreelanceSymlinkChangeEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
93 if (hFreelanceSymlinkChangeEvent == NULL) {
94 RegCloseKey(hkFreelance);
100 /* check hFreelanceSymlinkChangeEvent to see if it is set.
101 * if so, call cm_noteLocalMountPointSymlinkChange()
103 if (RegNotifyChangeKeyValue( hkFreelance, /* hKey */
104 FALSE, /* bWatchSubtree */
105 REG_NOTIFY_CHANGE_LAST_SET, /* dwNotifyFilter */
106 hFreelanceSymlinkChangeEvent, /* hEvent */
107 TRUE /* fAsynchronous */
108 ) != ERROR_SUCCESS) {
109 RegCloseKey(hkFreelance);
110 CloseHandle(hFreelanceSymlinkChangeEvent);
111 hFreelanceSymlinkChangeEvent = 0;
115 if (WaitForSingleObject(hFreelanceSymlinkChangeEvent, INFINITE) == WAIT_OBJECT_0)
117 if (freelance_ShutdownFlag == 1) {
118 RegCloseKey(hkFreelance);
119 CloseHandle(hFreelanceSymlinkChangeEvent);
120 hFreelanceSymlinkChangeEvent = 0;
123 cm_noteLocalMountPointChange();
129 cm_FreelanceShutdown(void)
131 freelance_ShutdownFlag = 1;
132 if (hFreelanceChangeEvent != 0)
133 thrd_SetEvent(hFreelanceChangeEvent);
134 if (hFreelanceSymlinkChangeEvent != 0)
135 thrd_SetEvent(hFreelanceSymlinkChangeEvent);
138 void cm_InitFreelance() {
142 lock_InitializeMutex(&cm_Freelance_Lock, "Freelance Lock");
144 // make sure we sync the data version to the cached root scache_t
145 if (cm_data.rootSCachep && cm_data.rootSCachep->fid.cell == AFS_FAKE_ROOT_CELL_ID)
146 cm_data.fakeDirVersion = cm_data.rootSCachep->dataVersion;
148 // yj: first we make a call to cm_initLocalMountPoints
149 // to read all the local mount points from the registry
150 cm_InitLocalMountPoints();
152 // then we make a call to InitFakeRootDir to create
153 // a fake root directory based on the local mount points
154 cm_InitFakeRootDir();
155 // --- end of yj code
157 /* Start the registry monitor */
158 phandle = thrd_Create(NULL, 65536, (ThreadFunc) cm_FreelanceChangeNotifier,
159 NULL, 0, &lpid, "cm_FreelanceChangeNotifier");
160 osi_assertx(phandle != NULL, "cm_FreelanceChangeNotifier thread create failure");
161 thrd_CloseHandle(phandle);
163 phandle = thrd_Create(NULL, 65536, (ThreadFunc) cm_FreelanceSymlinkChangeNotifier,
164 NULL, 0, &lpid, "cm_FreelanceSymlinkChangeNotifier");
165 osi_assertx(phandle != NULL, "cm_FreelanceSymlinkChangeNotifier thread create failure");
166 thrd_CloseHandle(phandle);
169 /* yj: Initialization of the fake root directory */
170 /* to be called while holding freelance lock unless during init. */
171 void cm_InitFakeRootDir() {
176 // allocate space for the fake info
177 cm_dirHeader_t fakeDirHeader;
178 cm_dirEntry_t fakeEntry;
179 cm_pageHeader_t fakePageHeader;
181 // i'm going to calculate how much space is needed for
182 // this fake root directory. we have these rules:
183 // 1. there are cm_noLocalMountPoints number of entries
184 // 2. each page is CM_DIR_PAGESIZE in size
185 // 3. the first 13 chunks of the first page are used for
187 // 4. the first chunk of all subsequent pages are used
188 // for page header stuff
189 // 5. a max of CM_DIR_EPP entries are allowed per page
190 // 6. each entry takes 1 or more chunks, depending on
191 // the size of the mount point string, as determined
193 // 7. each chunk is CM_DIR_CHUNKSIZE bytes
195 int CPP = CM_DIR_PAGESIZE / CM_DIR_CHUNKSIZE;
196 int curChunk = 13; // chunks 0 - 12 are used for header stuff
197 // of the first page in the directory
200 int curDirEntryInPage = 0;
204 /* Reserve 2 directory chunks for "." and ".." */
207 while (curDirEntry<cm_noLocalMountPoints) {
208 sizeOfCurEntry = cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0);
209 if ((curChunk + sizeOfCurEntry >= CPP) ||
210 (curDirEntryInPage + 1 >= CM_DIR_EPP)) {
212 curDirEntryInPage = 0;
215 curChunk += sizeOfCurEntry;
220 dirSize = (curPage+1) * CM_DIR_PAGESIZE;
221 if (cm_fakeDirSize != dirSize) {
223 free(cm_FakeRootDir);
224 cm_FakeRootDir = malloc(dirSize);
225 cm_fakeDirSize = dirSize;
228 // yj: when we get here, we've figured out how much memory we need and
229 // allocated the appropriate space for it. we now prceed to fill
230 // it up with entries.
233 curDirEntryInPage = 0;
236 // fields in the directory entry that are unused.
238 fakeEntry.length = 0;
240 fakeEntry.fid.unique = htonl(1);
242 // the first page is special, it uses fakeDirHeader instead of fakePageHeader
243 // we fill up the page with dirEntries that belong there and we make changes
244 // to the fakeDirHeader.header.freeBitmap along the way. Then when we're done
245 // filling up the dirEntries in this page, we copy the fakeDirHeader into
246 // the top of the page.
248 // init the freeBitmap array
250 fakeDirHeader.header.freeBitmap[i]=0;
252 fakeDirHeader.header.freeBitmap[0] = 0xff;
253 fakeDirHeader.header.freeBitmap[1] = 0x7f;
256 // we start counting at 13 because the 0th to 12th chunks are used for header
259 // stick the first 2 entries "." and ".." in
260 fakeEntry.fid.vnode = htonl(1);
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++;
265 strcpy(fakeEntry.name, "..");
266 currentPos = cm_FakeRootDir + curPage * CM_DIR_PAGESIZE + curChunk * CM_DIR_CHUNKSIZE;
267 memcpy(currentPos, &fakeEntry, CM_DIR_CHUNKSIZE);
268 curChunk++; curDirEntryInPage++;
270 // keep putting stuff into page 0 if
271 // 1. we're not done with all entries
272 // 2. we have less than CM_DIR_EPP entries in page 0
273 // 3. we're not out of chunks in page 0
275 while( (curDirEntry<cm_noLocalMountPoints) &&
276 (curDirEntryInPage < CM_DIR_EPP) &&
277 (curChunk + cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0) <= CPP))
280 noChunks = cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0);
281 fakeEntry.fid.vnode = htonl(curDirEntry + 2);
282 currentPos = cm_FakeRootDir + curPage * CM_DIR_PAGESIZE + curChunk * CM_DIR_CHUNKSIZE;
284 memcpy(currentPos, &fakeEntry, CM_DIR_CHUNKSIZE);
285 strcpy(currentPos + 12, (cm_localMountPoints+curDirEntry)->namep);
288 for (i=0; i<noChunks; i++) {
289 t1 = (curChunk + i) / 8;
290 t2 = curChunk + i - (t1*8);
291 fakeDirHeader.header.freeBitmap[t1] |= (1 << t2);
296 // when we get here, we're done with filling in the entries for page 0
297 // copy in the header info
299 memcpy(cm_FakeRootDir, &fakeDirHeader, 13 * CM_DIR_CHUNKSIZE);
303 // ok, page 0's done. Move on to the next page.
304 while (curDirEntry<cm_noLocalMountPoints) {
306 curChunk = 1; // the zeroth chunk is reserved for page header
307 curDirEntryInPage = 0;
308 for (i=0; i<8; i++) {
309 fakePageHeader.freeBitmap[i]=0;
311 fakePageHeader.freeCount = 0;
312 fakePageHeader.pgcount = 0;
313 fakePageHeader.tag = htons(1234);
315 // while we're on the same page...
316 while ( (curDirEntry<cm_noLocalMountPoints) &&
317 (curDirEntryInPage < CM_DIR_EPP) &&
318 (curChunk + cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0) <= CPP))
320 // add an entry to this page
322 noChunks = cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0);
323 fakeEntry.fid.vnode=htonl(curDirEntry+2);
324 currentPos = cm_FakeRootDir + curPage * CM_DIR_PAGESIZE + curChunk * CM_DIR_CHUNKSIZE;
325 memcpy(currentPos, &fakeEntry, CM_DIR_CHUNKSIZE);
326 strcpy(currentPos + 12, (cm_localMountPoints+curDirEntry)->namep);
329 for (i=0; i<noChunks; i++) {
330 t1 = (curChunk + i) / 8;
331 t2 = curChunk + i - (t1*8);
332 fakePageHeader.freeBitmap[t1] |= (1 << t2);
336 memcpy(cm_FakeRootDir + curPage * CM_DIR_PAGESIZE, &fakePageHeader, sizeof(fakePageHeader));
341 // we know the fakeDir is setup properly, so we claim that we have callback
342 osi_Log0(afsd_logp,"cm_InitFakeRootDir fakeDirCallback=1");
343 cm_fakeDirCallback=1;
345 // when we get here, we've set up everything! done!
348 int cm_FakeRootFid(cm_fid_t *fidp)
351 AFS_FAKE_ROOT_CELL_ID, /* root cell */
352 AFS_FAKE_ROOT_VOL_ID, /* root.afs ? */
357 /* called directly from ioctl */
358 /* called while not holding freelance lock */
359 int cm_noteLocalMountPointChange(void) {
360 lock_ObtainMutex(&cm_Freelance_Lock);
361 cm_data.fakeDirVersion++;
362 cm_localMountPointChangeFlag = 1;
363 lock_ReleaseMutex(&cm_Freelance_Lock);
367 int cm_getLocalMountPointChange() {
368 return cm_localMountPointChangeFlag;
371 int cm_clearLocalMountPointChange() {
372 cm_localMountPointChangeFlag = 0;
376 int cm_reInitLocalMountPoints() {
379 cm_scache_t *scp, **lscpp, *tscp;
381 osi_Log0(afsd_logp,"----- freelance reinitialization starts ----- ");
383 // first we invalidate all the SCPs that were created
384 // for the local mount points
386 osi_Log0(afsd_logp,"Invalidating local mount point scp... ");
388 cm_SetFid(&aFid, AFS_FAKE_ROOT_CELL_ID, AFS_FAKE_ROOT_VOL_ID, 1, 1);
390 lock_ObtainWrite(&cm_scacheLock);
391 lock_ObtainMutex(&cm_Freelance_Lock); /* always scache then freelance lock */
392 for (i=0; i<cm_noLocalMountPoints; i++) {
393 hash = CM_SCACHE_HASH(&aFid);
394 for (scp=cm_data.scacheHashTablep[hash]; scp; scp=scp->nextp) {
395 if (cm_FidCmp(&scp->fid, &aFid) == 0) {
396 // mark the scp to be reused
397 cm_HoldSCacheNoLock(scp);
398 lock_ReleaseWrite(&cm_scacheLock);
399 lock_ObtainWrite(&scp->rw);
400 cm_DiscardSCache(scp);
401 lock_ReleaseWrite(&scp->rw);
402 cm_CallbackNotifyChange(scp);
403 lock_ObtainWrite(&cm_scacheLock);
404 cm_ReleaseSCacheNoLock(scp);
406 // take the scp out of the hash
407 for (lscpp = &cm_data.scacheHashTablep[hash], tscp = cm_data.scacheHashTablep[hash];
409 lscpp = &tscp->nextp, tscp = tscp->nextp) {
412 lock_ObtainWrite(&scp->rw);
413 scp->flags &= ~CM_SCACHEFLAG_INHASH;
414 lock_ReleaseWrite(&scp->rw);
420 cm_SetFid(&aFid, AFS_FAKE_ROOT_CELL_ID, AFS_FAKE_ROOT_VOL_ID, aFid.vnode + 1, 1);
422 lock_ReleaseWrite(&cm_scacheLock);
423 osi_Log0(afsd_logp,"\tall old scp cleared!");
425 // we must free the memory that was allocated in the prev
426 // cm_InitLocalMountPoints call
427 osi_Log0(afsd_logp,"Removing old localmountpoints... ");
428 free(cm_localMountPoints);
429 osi_Log0(afsd_logp,"\tall old localmountpoints cleared!");
431 // now re-init the localmountpoints
432 osi_Log0(afsd_logp,"Creating new localmountpoints... ");
433 cm_InitLocalMountPoints();
434 osi_Log0(afsd_logp,"\tcreated new set of localmountpoints!");
436 // then we re-create that dir
437 osi_Log0(afsd_logp,"Creating new fakedir... ");
438 cm_InitFakeRootDir();
439 osi_Log0(afsd_logp,"\t\tcreated new fakedir!");
441 lock_ReleaseMutex(&cm_Freelance_Lock);
443 osi_Log0(afsd_logp,"----- freelance reinit complete -----");
448 // yj: open up the registry and read all the local mount
449 // points that are stored there. Part of the initialization
450 // process for the freelance client.
451 /* to be called while holding freelance lock unless during init. */
452 long cm_InitLocalMountPoints() {
457 cm_localMountPoint_t* aLocalMountPoint;
460 char rootCellName[256];
461 HKEY hkFreelance = 0, hkFreelanceSymlinks = 0;
462 DWORD dwType, dwSize;
463 DWORD dwMountPoints = 0;
465 DWORD dwSymlinks = 0;
466 FILETIME ftLastWriteTime;
468 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
469 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance",
471 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
472 &hkFreelance) == ERROR_SUCCESS) {
474 RegQueryInfoKey( hkFreelance,
477 NULL, /* lpReserved */
478 NULL, /* lpcSubKeys */
479 NULL, /* lpcMaxSubKeyLen */
480 NULL, /* lpcMaxClassLen */
481 &dwMountPoints, /* lpcValues */
482 NULL, /* lpcMaxValueNameLen */
483 NULL, /* lpcMaxValueLen */
484 NULL, /* lpcbSecurityDescriptor */
485 &ftLastWriteTime /* lpftLastWriteTime */
488 smb_UnixTimeFromLargeSearchTime(&FakeFreelanceModTime, &ftLastWriteTime);
490 if ( dwMountPoints == 0 ) {
491 rootCellName[0] = '.';
492 code = cm_GetRootCellName(&rootCellName[1]);
494 cm_FreelanceAddMount(&rootCellName[1], &rootCellName[1], "root.cell.", 0, NULL);
495 cm_FreelanceAddMount(rootCellName, &rootCellName[1], "root.cell.", 1, NULL);
496 cm_FreelanceAddMount(".root", &rootCellName[1], "root.afs.", 1, NULL);
501 if (RegCreateKeyEx( HKEY_LOCAL_MACHINE,
502 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance\\Symlinks",
505 REG_OPTION_NON_VOLATILE,
506 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
508 &hkFreelanceSymlinks,
509 NULL) == ERROR_SUCCESS) {
511 RegQueryInfoKey( hkFreelanceSymlinks,
514 NULL, /* lpReserved */
515 NULL, /* lpcSubKeys */
516 NULL, /* lpcMaxSubKeyLen */
517 NULL, /* lpcMaxClassLen */
518 &dwSymlinks, /* lpcValues */
519 NULL, /* lpcMaxValueNameLen */
520 NULL, /* lpcMaxValueLen */
521 NULL, /* lpcbSecurityDescriptor */
522 NULL /* lpftLastWriteTime */
526 // get the number of entries there are from the first line
528 cm_noLocalMountPoints = dwMountPoints + dwSymlinks;
530 // create space to store the local mount points
531 cm_localMountPoints = malloc(sizeof(cm_localMountPoint_t) * cm_noLocalMountPoints);
532 aLocalMountPoint = cm_localMountPoints;
534 // now we read n lines and parse them into local mount points
535 // where n is the number of local mount points there are, as
537 // Each line in the ini file represents 1 local mount point and
538 // is in the format xxx#yyy:zzz, where xxx is the directory
539 // entry name, yyy is the cell name and zzz is the volume name.
540 // #yyy:zzz together make up the mount point.
541 for ( dwIndex = 0 ; dwIndex < dwMountPoints; dwIndex++ ) {
542 TCHAR szValueName[16];
543 DWORD dwValueSize = 16;
544 dwSize = sizeof(line);
545 if (RegEnumValue( hkFreelance, dwIndex, szValueName, &dwValueSize, NULL,
546 &dwType, line, &dwSize))
548 afsi_log("RegEnumValue(hkFreelance) failed");
549 cm_noLocalMountPoints--;
553 afsi_log("Mountpoint[%d] = %s",dwIndex, line);
555 /* find the trailing dot; null terminate after it */
556 t2 = strrchr(line, '.');
560 for ( t=line;*t;t++ ) {
561 if ( !isprint(*t) ) {
562 afsi_log("error occurred while parsing mountpoint entry [%d]: non-printable character", dwIndex);
563 fprintf(stderr, "error occurred while parsing mountpoint entry [%d]: non-printable character", dwIndex);
564 cm_noLocalMountPoints--;
569 // line is not empty, so let's parse it
570 t = strchr(line, '#');
572 t = strchr(line, '%');
573 // make sure that there is a '#' or '%' separator in the line
575 afsi_log("error occurred while parsing mountpoint entry [%d]: no # or %% separator", dwIndex);
576 fprintf(stderr, "error occurred while parsing mountpoint entry [%d]: no # or %% separator", dwIndex);
577 cm_noLocalMountPoints--;
581 aLocalMountPoint->fileType = CM_SCACHETYPE_MOUNTPOINT;
582 aLocalMountPoint->namep=malloc(t-line+1);
583 strncpy(aLocalMountPoint->namep, line, t-line);
584 aLocalMountPoint->namep[t-line] = '\0';
586 /* copy the mount point string */
587 aLocalMountPoint->mountPointStringp=malloc(strlen(t));
588 strncpy(aLocalMountPoint->mountPointStringp, t, strlen(t)-1);
589 aLocalMountPoint->mountPointStringp[strlen(t)-1] = '\0';
591 osi_Log2(afsd_logp,"found mount point: name %s, string %s",
592 osi_LogSaveString(afsd_logp,aLocalMountPoint->namep),
593 osi_LogSaveString(afsd_logp,aLocalMountPoint->mountPointStringp));
598 for ( dwIndex = 0 ; dwIndex < dwSymlinks; dwIndex++ ) {
599 TCHAR szValueName[16];
600 DWORD dwValueSize = 16;
601 dwSize = sizeof(line);
602 if (RegEnumValue( hkFreelanceSymlinks, dwIndex, szValueName, &dwValueSize, NULL,
603 &dwType, line, &dwSize))
605 afsi_log("RegEnumValue(hkFreelanceSymlinks) failed");
606 cm_noLocalMountPoints--;
610 afsi_log("Symlink[%d] = %s",dwIndex, line);
612 /* find the trailing dot; null terminate after it */
613 t2 = strrchr(line, '.');
617 for ( t=line;*t;t++ ) {
618 if ( !isprint(*t) ) {
619 afsi_log("error occurred while parsing symlink entry [%d]: non-printable character", dwIndex);
620 fprintf(stderr, "error occurred while parsing symlink entry [%d]: non-printable character", dwIndex);
621 cm_noLocalMountPoints--;
626 // line is not empty, so let's parse it
627 t = strchr(line, ':');
629 // make sure that there is a ':' separator in the line
631 afsi_log("error occurred while parsing symlink entry [%d]: no ':' separator", dwIndex);
632 fprintf(stderr, "error occurred while parsing symlink entry [%d]: no ':' separator", dwIndex);
633 cm_noLocalMountPoints--;
637 aLocalMountPoint->fileType = CM_SCACHETYPE_SYMLINK;
638 aLocalMountPoint->namep=malloc(t-line+1);
639 strncpy(aLocalMountPoint->namep, line, t-line);
640 aLocalMountPoint->namep[t-line] = '\0';
642 /* copy the symlink string */
643 aLocalMountPoint->mountPointStringp=malloc(strlen(t)-1);
644 strncpy(aLocalMountPoint->mountPointStringp, t+1, strlen(t)-2);
645 aLocalMountPoint->mountPointStringp[strlen(t)-2] = '\0';
647 osi_Log2(afsd_logp,"found symlink: name %s, string %s",
648 osi_LogSaveString(afsd_logp,aLocalMountPoint->namep),
649 osi_LogSaveString(afsd_logp,aLocalMountPoint->mountPointStringp));
654 if ( hkFreelanceSymlinks )
655 RegCloseKey( hkFreelanceSymlinks );
656 RegCloseKey(hkFreelance);
660 /* What follows is the old code to read freelance mount points
661 * out of a text file modified to copy the data into the registry
663 cm_GetConfigDir(hdir, sizeof(hdir));
664 strcat(hdir, AFS_FREELANCE_INI);
665 // open the ini file for reading
666 fp = fopen(hdir, "r");
668 /* look in the Windows directory where we used to store the file */
669 GetWindowsDirectory(hdir, sizeof(hdir));
671 strcat(hdir, AFS_FREELANCE_INI);
672 fp = fopen(hdir, "r");
675 RegCreateKeyEx( HKEY_LOCAL_MACHINE,
676 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance",
679 REG_OPTION_NON_VOLATILE,
687 RegCloseKey(hkFreelance);
688 rootCellName[0] = '.';
689 code = cm_GetRootCellName(&rootCellName[1]);
691 cm_FreelanceAddMount(&rootCellName[1], &rootCellName[1], "root.cell.", 0, NULL);
692 cm_FreelanceAddMount(rootCellName, &rootCellName[1], "root.cell.", 1, NULL);
693 cm_FreelanceAddMount(".root", &rootCellName[1], "root.afs.", 1, NULL);
698 // we successfully opened the file
699 osi_Log0(afsd_logp,"opened afs_freelance.ini");
701 // now we read the first line to see how many entries
703 fgets(line, sizeof(line), fp);
705 // if the line is empty at any point when we're reading
706 // we're screwed. report error and return.
708 afsi_log("error occurred while reading afs_freelance.ini");
709 fprintf(stderr, "error occurred while reading afs_freelance.ini");
713 // get the number of entries there are from the first line
715 cm_noLocalMountPoints = atoi(line);
717 if (cm_noLocalMountPoints > 0) {
718 // create space to store the local mount points
719 cm_localMountPoints = malloc(sizeof(cm_localMountPoint_t) * cm_noLocalMountPoints);
720 aLocalMountPoint = cm_localMountPoints;
723 // now we read n lines and parse them into local mount points
724 // where n is the number of local mount points there are, as
726 // Each line in the ini file represents 1 local mount point and
727 // is in the format xxx#yyy:zzz, where xxx is the directory
728 // entry name, yyy is the cell name and zzz is the volume name.
729 // #yyy:zzz together make up the mount point.
730 for (i=0; i<cm_noLocalMountPoints; i++) {
731 fgets(line, sizeof(line), fp);
732 // check that the line is not empty
734 afsi_log("error occurred while parsing entry in %s: empty line in line %d", AFS_FREELANCE_INI, i);
735 fprintf(stderr, "error occurred while parsing entry in afs_freelance.ini: empty line in line %d", i);
739 /* find the trailing dot; null terminate after it */
740 t2 = strrchr(line, '.');
746 /* we are migrating to the registry */
747 sprintf(szIndex,"%d",dwIndex++);
749 dwSize = (DWORD)strlen(line) + 1;
750 RegSetValueEx( hkFreelance, szIndex, 0, dwType, line, dwSize);
753 // line is not empty, so let's parse it
754 t = strchr(line, '#');
756 t = strchr(line, '%');
757 // make sure that there is a '#' or '%' separator in the line
759 afsi_log("error occurred while parsing entry in %s: no # or %% separator in line %d", AFS_FREELANCE_INI, i);
760 fprintf(stderr, "error occurred while parsing entry in afs_freelance.ini: no # or %% separator in line %d", i);
763 aLocalMountPoint->namep=malloc(t-line+1);
764 memcpy(aLocalMountPoint->namep, line, t-line);
765 *(aLocalMountPoint->namep + (t-line)) = 0;
767 aLocalMountPoint->mountPointStringp=malloc(strlen(line) - (t-line) + 1);
768 memcpy(aLocalMountPoint->mountPointStringp, t, strlen(line)-(t-line)-1);
769 *(aLocalMountPoint->mountPointStringp + (strlen(line)-(t-line)-1)) = 0;
771 osi_Log2(afsd_logp,"found mount point: name %s, string %s",
772 aLocalMountPoint->namep,
773 aLocalMountPoint->mountPointStringp);
779 RegCloseKey(hkFreelance);
785 int cm_getNoLocalMountPoints() {
786 return cm_noLocalMountPoints;
789 long cm_FreelanceMountPointExists(char * filename, int prefix_ok)
795 HKEY hkFreelance = 0;
796 DWORD dwType, dwSize;
800 lock_ObtainMutex(&cm_Freelance_Lock);
802 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
803 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance",
805 KEY_READ|KEY_QUERY_VALUE,
806 &hkFreelance) == ERROR_SUCCESS)
808 RegQueryInfoKey( hkFreelance,
811 NULL, /* lpReserved */
812 NULL, /* lpcSubKeys */
813 NULL, /* lpcMaxSubKeyLen */
814 NULL, /* lpcMaxClassLen */
815 &dwMountPoints, /* lpcValues */
816 NULL, /* lpcMaxValueNameLen */
817 NULL, /* lpcMaxValueLen */
818 NULL, /* lpcbSecurityDescriptor */
819 NULL /* lpftLastWriteTime */
822 for ( dwIndex = 0; dwIndex < dwMountPoints; dwIndex++ ) {
823 TCHAR szValueName[16];
824 DWORD dwValueSize = 16;
825 dwSize = sizeof(line);
826 RegEnumValue( hkFreelance, dwIndex, szValueName, &dwValueSize, NULL,
827 &dwType, line, &dwSize);
829 cp=strchr(line, '#');
831 cp=strchr(line, '%');
832 memcpy(shortname, line, cp-line);
833 shortname[cp-line]=0;
835 if (!strcmp(shortname, filename)) {
840 for ( dwIndex = 0; dwIndex < dwMountPoints; dwIndex++ ) {
841 TCHAR szValueName[16];
842 DWORD dwValueSize = 16;
843 dwSize = sizeof(line);
844 RegEnumValue( hkFreelance, dwIndex, szValueName, &dwValueSize, NULL,
845 &dwType, line, &dwSize);
847 cp=strchr(line, '#');
849 cp=strchr(line, '%');
850 memcpy(shortname, line, cp-line);
851 shortname[cp-line]=0;
853 if (!stricmp(shortname, filename)) {
858 if (prefix_ok && strlen(shortname) - strlen(filename) == 1 && !strncmp(shortname, filename, strlen(filename))) {
863 RegCloseKey(hkFreelance);
866 lock_ReleaseMutex(&cm_Freelance_Lock);
871 long cm_FreelanceSymlinkExists(char * filename, int prefix_ok)
877 HKEY hkFreelance = 0;
878 DWORD dwType, dwSize;
882 lock_ObtainMutex(&cm_Freelance_Lock);
884 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
885 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance\\Symlinks",
887 KEY_READ|KEY_QUERY_VALUE,
888 &hkFreelance) == ERROR_SUCCESS)
890 RegQueryInfoKey( hkFreelance,
893 NULL, /* lpReserved */
894 NULL, /* lpcSubKeys */
895 NULL, /* lpcMaxSubKeyLen */
896 NULL, /* lpcMaxClassLen */
897 &dwSymlinks, /* lpcValues */
898 NULL, /* lpcMaxValueNameLen */
899 NULL, /* lpcMaxValueLen */
900 NULL, /* lpcbSecurityDescriptor */
901 NULL /* lpftLastWriteTime */
904 for ( dwIndex = 0; dwIndex < dwSymlinks; dwIndex++ ) {
905 TCHAR szValueName[16];
906 DWORD dwValueSize = 16;
907 dwSize = sizeof(line);
908 RegEnumValue( hkFreelance, dwIndex, szValueName, &dwValueSize, NULL,
909 &dwType, line, &dwSize);
911 cp=strchr(line, ':');
912 memcpy(shortname, line, cp-line);
913 shortname[cp-line]=0;
915 if (!strcmp(shortname, filename)) {
920 if (prefix_ok && strlen(shortname) - strlen(filename) == 1 && !strncmp(shortname, filename, strlen(filename))) {
925 for ( dwIndex = 0; dwIndex < dwSymlinks; dwIndex++ ) {
926 TCHAR szValueName[16];
927 DWORD dwValueSize = 16;
928 dwSize = sizeof(line);
929 RegEnumValue( hkFreelance, dwIndex, szValueName, &dwValueSize, NULL,
930 &dwType, line, &dwSize);
932 cp=strchr(line, ':');
933 memcpy(shortname, line, cp-line);
934 shortname[cp-line]=0;
936 if (!stricmp(shortname, filename)) {
941 RegCloseKey(hkFreelance);
944 lock_ReleaseMutex(&cm_Freelance_Lock);
949 long cm_FreelanceAddMount(char *filename, char *cellname, char *volume, int rw, cm_fid_t *fidp)
957 HKEY hkFreelance = 0;
958 DWORD dwType, dwSize;
962 /* before adding, verify the cell name; if it is not a valid cell,
963 don't add the mount point.
964 allow partial matches as a means of poor man's alias. */
965 /* major performance issue? */
966 osi_Log4(afsd_logp,"Freelance Add Mount request: filename=%s cellname=%s volume=%s %s",
967 osi_LogSaveString(afsd_logp,filename),
968 osi_LogSaveString(afsd_logp,cellname),
969 osi_LogSaveString(afsd_logp,volume),
972 if ( filename[0] == '\0' || cellname[0] == '\0' || volume[0] == '\0' )
975 if (cellname[0] == '.') {
976 if (!cm_GetCell_Gen(&cellname[1], fullname, CM_FLAG_CREATE))
979 if (!cm_GetCell_Gen(cellname, fullname, CM_FLAG_CREATE))
983 if ( cm_FreelanceMountPointExists(filename, 0) ||
984 cm_FreelanceSymlinkExists(filename, 0) )
987 osi_Log1(afsd_logp,"Freelance Adding Mount for Cell: %s",
988 osi_LogSaveString(afsd_logp,cellname));
990 lock_ObtainMutex(&cm_Freelance_Lock);
992 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
993 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance",
995 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
996 &hkFreelance) == ERROR_SUCCESS) {
998 RegQueryInfoKey( hkFreelance,
1000 NULL, /* lpcClass */
1001 NULL, /* lpReserved */
1002 NULL, /* lpcSubKeys */
1003 NULL, /* lpcMaxSubKeyLen */
1004 NULL, /* lpcMaxClassLen */
1005 &dwMountPoints, /* lpcValues */
1006 NULL, /* lpcMaxValueNameLen */
1007 NULL, /* lpcMaxValueLen */
1008 NULL, /* lpcbSecurityDescriptor */
1009 NULL /* lpftLastWriteTime */
1013 sprintf(line, "%s%%%s:%s", filename, fullname, volume);
1015 sprintf(line, "%s#%s:%s", filename, fullname, volume);
1017 /* If we are adding a new value, there must be an unused name
1018 * within the range 0 to dwMountPoints
1020 for ( dwIndex = 0; dwIndex <= dwMountPoints; dwIndex++ ) {
1024 dwSize = sizeof(szMount);
1025 sprintf(szIndex, "%d", dwIndex);
1026 if (RegQueryValueEx( hkFreelance, szIndex, 0, &dwType, szMount, &dwSize) != ERROR_SUCCESS) {
1027 /* found an unused value */
1029 dwSize = (DWORD)strlen(line) + 1;
1030 RegSetValueEx( hkFreelance, szIndex, 0, dwType, line, dwSize);
1033 int len = (int)strlen(filename);
1034 if ( dwType == REG_SZ && !strncmp(filename, szMount, len) &&
1035 (szMount[len] == '%' || szMount[len] == '#')) {
1036 /* Replace the existing value */
1038 dwSize = (DWORD)strlen(line) + 1;
1039 RegSetValueEx( hkFreelance, szIndex, 0, dwType, line, dwSize);
1044 RegCloseKey(hkFreelance);
1047 cm_GetConfigDir(hfile, sizeof(hfile));
1048 strcat(hfile, AFS_FREELANCE_INI);
1049 fp = fopen(hfile, "r+");
1051 return CM_ERROR_INVAL;
1052 fgets(line, sizeof(line), fp);
1055 fseek(fp, 0, SEEK_SET);
1056 fprintf(fp, "%d", n);
1057 fseek(fp, 0, SEEK_END);
1059 fprintf(fp, "%s%%%s:%s\n", filename, fullname, volume);
1061 fprintf(fp, "%s#%s:%s\n", filename, fullname, volume);
1064 lock_ReleaseMutex(&cm_Freelance_Lock);
1066 /* cm_reInitLocalMountPoints(); */
1068 cm_SetFid(fidp, fidp->cell, fidp->volume, ++cm_noLocalMountPoints, 1);
1069 cm_noteLocalMountPointChange();
1073 long cm_FreelanceRemoveMount(char *toremove)
1078 char shortname[200];
1079 char hfile[260], hfile2[260];
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 );
1128 RegCloseKey(hkFreelance);
1131 cm_GetConfigDir(hfile, sizeof(hfile));
1132 strcat(hfile, AFS_FREELANCE_INI);
1133 strcpy(hfile2, hfile);
1134 strcat(hfile2, "2");
1135 fp1=fopen(hfile, "r+");
1137 return CM_ERROR_INVAL;
1138 fp2=fopen(hfile2, "w+");
1141 return CM_ERROR_INVAL;
1144 fgets(line, sizeof(line), fp1);
1146 fprintf(fp2, "%d\n", n-1);
1148 for (i=0; i<n; i++) {
1149 fgets(line, sizeof(line), fp1);
1150 cp=strchr(line, '#');
1152 cp=strchr(line, '%');
1153 memcpy(shortname, line, cp-line);
1154 shortname[cp-line]=0;
1156 if (strcmp(shortname, toremove)==0) {
1168 rename(hfile2, hfile);
1172 lock_ReleaseMutex(&cm_Freelance_Lock);
1174 cm_noteLocalMountPointChange();
1177 return CM_ERROR_NOSUCHFILE;
1180 long cm_FreelanceAddSymlink(char *filename, char *destination, cm_fid_t *fidp)
1185 HKEY hkFreelanceSymlinks = 0;
1186 DWORD dwType, dwSize;
1190 /* before adding, verify the filename. If it is already in use, either as
1191 * as mount point or a cellname, do not permit the creation of the symlink.
1193 osi_Log2(afsd_logp,"Freelance Add Symlink request: filename=%s destination=%s",
1194 osi_LogSaveString(afsd_logp,filename),
1195 osi_LogSaveString(afsd_logp,destination));
1197 if ( filename[0] == '\0' || destination[0] == '\0' )
1198 return CM_ERROR_INVAL;
1201 if (filename[0] == '.') {
1202 cm_GetCell_Gen(&filename[1], fullname, CM_FLAG_CREATE);
1203 if (stricmp(&filename[1],fullname) == 0)
1204 return CM_ERROR_EXISTS;
1206 cm_GetCell_Gen(filename, fullname, CM_FLAG_CREATE);
1207 if (stricmp(filename,fullname) == 0)
1208 return CM_ERROR_EXISTS;
1211 if ( cm_FreelanceMountPointExists(filename, 0) ||
1212 cm_FreelanceSymlinkExists(filename, 0) )
1213 return CM_ERROR_EXISTS;
1215 lock_ObtainMutex(&cm_Freelance_Lock);
1217 if (RegCreateKeyEx( HKEY_LOCAL_MACHINE,
1218 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance\\Symlinks",
1221 REG_OPTION_NON_VOLATILE,
1222 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
1224 &hkFreelanceSymlinks,
1225 NULL) == ERROR_SUCCESS) {
1227 RegQueryInfoKey( hkFreelanceSymlinks,
1229 NULL, /* lpcClass */
1230 NULL, /* lpReserved */
1231 NULL, /* lpcSubKeys */
1232 NULL, /* lpcMaxSubKeyLen */
1233 NULL, /* lpcMaxClassLen */
1234 &dwSymlinks, /* lpcValues */
1235 NULL, /* lpcMaxValueNameLen */
1236 NULL, /* lpcMaxValueLen */
1237 NULL, /* lpcbSecurityDescriptor */
1238 NULL /* lpftLastWriteTime */
1241 sprintf(line, "%s:%s.", filename, destination);
1243 /* If we are adding a new value, there must be an unused name
1244 * within the range 0 to dwSymlinks
1246 for ( dwIndex = 0; dwIndex <= dwSymlinks; dwIndex++ ) {
1250 dwSize = sizeof(szLink);
1251 sprintf(szIndex, "%d", dwIndex);
1252 if (RegQueryValueEx( hkFreelanceSymlinks, szIndex, 0, &dwType, szLink, &dwSize) != ERROR_SUCCESS) {
1253 /* found an unused value */
1255 dwSize = (DWORD)strlen(line) + 1;
1256 RegSetValueEx( hkFreelanceSymlinks, szIndex, 0, dwType, line, dwSize);
1259 int len = (int)strlen(filename);
1260 if ( dwType == REG_SZ && !strncmp(filename, szLink, len) && szLink[len] == ':') {
1261 /* Replace the existing value */
1263 dwSize = (DWORD)strlen(line) + 1;
1264 RegSetValueEx( hkFreelanceSymlinks, szIndex, 0, dwType, line, dwSize);
1269 RegCloseKey(hkFreelanceSymlinks);
1271 lock_ReleaseMutex(&cm_Freelance_Lock);
1273 /* cm_reInitLocalMountPoints(); */
1275 cm_SetFid(fidp, fidp->cell, fidp->volume, ++cm_noLocalMountPoints, 1);
1276 cm_noteLocalMountPointChange();
1280 long cm_FreelanceRemoveSymlink(char *toremove)
1284 char shortname[200];
1286 HKEY hkFreelanceSymlinks = 0;
1287 DWORD dwType, dwSize;
1291 lock_ObtainMutex(&cm_Freelance_Lock);
1293 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
1294 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance\\Symlinks",
1296 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
1297 &hkFreelanceSymlinks) == ERROR_SUCCESS) {
1299 RegQueryInfoKey( hkFreelanceSymlinks,
1301 NULL, /* lpcClass */
1302 NULL, /* lpReserved */
1303 NULL, /* lpcSubKeys */
1304 NULL, /* lpcMaxSubKeyLen */
1305 NULL, /* lpcMaxClassLen */
1306 &dwSymlinks, /* lpcValues */
1307 NULL, /* lpcMaxValueNameLen */
1308 NULL, /* lpcMaxValueLen */
1309 NULL, /* lpcbSecurityDescriptor */
1310 NULL /* lpftLastWriteTime */
1313 for ( dwIndex = 0; dwIndex < dwSymlinks; dwIndex++ ) {
1314 TCHAR szValueName[16];
1315 DWORD dwValueSize = 16;
1316 dwSize = sizeof(line);
1317 RegEnumValue( hkFreelanceSymlinks, dwIndex, szValueName, &dwValueSize, NULL,
1318 &dwType, line, &dwSize);
1320 cp=strchr(line, ':');
1321 memcpy(shortname, line, cp-line);
1322 shortname[cp-line]=0;
1324 if (!strcmp(shortname, toremove)) {
1325 RegDeleteValue( hkFreelanceSymlinks, szValueName );
1330 RegCloseKey(hkFreelanceSymlinks);
1333 lock_ReleaseMutex(&cm_Freelance_Lock);
1335 cm_noteLocalMountPointChange();
1338 return CM_ERROR_NOSUCHFILE;
1340 #endif /* AFS_FREELANCE_CLIENT */