18 #ifdef AFS_FREELANCE_CLIENT
19 #include "cm_freelance.h"
22 extern void afsi_log(char *pattern, ...);
24 int cm_noLocalMountPoints;
26 int cm_fakeDirCallback=0;
27 int cm_fakeGettingCallback=0;
28 int cm_fakeDirVersion = 0x8;
29 cm_localMountPoint_t* cm_localMountPoints;
30 osi_mutex_t cm_Freelance_Lock;
31 int cm_localMountPointChangeFlag = 0;
32 int cm_freelanceEnabled = 0;
33 time_t FakeFreelanceModTime = 0x3b49f6e2;
35 void cm_InitFakeRootDir();
38 void cm_FreelanceChangeNotifier(void * parmp) {
39 HANDLE hFreelanceChangeEvent = 0;
42 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
43 "SOFTWARE\\OpenAFS\\Client\\Freelance",
46 &hkFreelance) == ERROR_SUCCESS) {
48 hFreelanceChangeEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
49 if (hFreelanceChangeEvent == NULL) {
50 RegCloseKey(hkFreelance);
56 /* check hFreelanceChangeEvent to see if it is set.
57 * if so, call cm_noteLocalMountPointChange()
59 if (RegNotifyChangeKeyValue( hkFreelance, /* hKey */
60 FALSE, /* bWatchSubtree */
61 REG_NOTIFY_CHANGE_LAST_SET, /* dwNotifyFilter */
62 hFreelanceChangeEvent, /* hEvent */
63 TRUE /* fAsynchronous */
65 RegCloseKey(hkFreelance);
66 CloseHandle(hFreelanceChangeEvent);
70 if (WaitForSingleObject(hFreelanceChangeEvent, INFINITE) == WAIT_OBJECT_0)
72 cm_noteLocalMountPointChange();
77 void cm_FreelanceSymlinkChangeNotifier(void * parmp) {
78 HANDLE hFreelanceSymlinkChangeEvent = 0;
81 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
82 "SOFTWARE\\OpenAFS\\Client\\Freelance\\Symlinks",
85 &hkFreelance) == ERROR_SUCCESS) {
87 hFreelanceSymlinkChangeEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
88 if (hFreelanceSymlinkChangeEvent == NULL) {
89 RegCloseKey(hkFreelance);
95 /* check hFreelanceSymlinkChangeEvent to see if it is set.
96 * if so, call cm_noteLocalMountPointSymlinkChange()
98 if (RegNotifyChangeKeyValue( hkFreelance, /* hKey */
99 FALSE, /* bWatchSubtree */
100 REG_NOTIFY_CHANGE_LAST_SET, /* dwNotifyFilter */
101 hFreelanceSymlinkChangeEvent, /* hEvent */
102 TRUE /* fAsynchronous */
103 ) != ERROR_SUCCESS) {
104 RegCloseKey(hkFreelance);
105 CloseHandle(hFreelanceSymlinkChangeEvent);
109 if (WaitForSingleObject(hFreelanceSymlinkChangeEvent, INFINITE) == WAIT_OBJECT_0)
111 cm_noteLocalMountPointChange();
117 void cm_InitFreelance() {
123 lock_InitializeMutex(&cm_Freelance_Lock, "Freelance Lock");
125 // yj: first we make a call to cm_initLocalMountPoints
126 // to read all the local mount points from an ini file
127 cm_InitLocalMountPoints();
129 // then we make a call to InitFakeRootDir to create
130 // a fake root directory based on the local mount points
131 cm_InitFakeRootDir();
132 // --- end of yj code
135 /* Start the registry monitor */
136 phandle = thrd_Create(NULL, 65536, (ThreadFunc) cm_FreelanceChangeNotifier,
137 NULL, 0, &lpid, "cm_FreelanceChangeNotifier");
138 osi_assert(phandle != NULL);
139 thrd_CloseHandle(phandle);
141 phandle = thrd_Create(NULL, 65536, (ThreadFunc) cm_FreelanceSymlinkChangeNotifier,
142 NULL, 0, &lpid, "cm_FreelanceSymlinkChangeNotifier");
143 osi_assert(phandle != NULL);
144 thrd_CloseHandle(phandle);
148 /* yj: Initialization of the fake root directory */
149 /* to be called while holding freelance lock unless during init. */
150 void cm_InitFakeRootDir() {
155 // allocate space for the fake info
156 cm_dirHeader_t fakeDirHeader;
157 cm_dirEntry_t fakeEntry;
158 cm_pageHeader_t fakePageHeader;
160 // i'm going to calculate how much space is needed for
161 // this fake root directory. we have these rules:
162 // 1. there are cm_noLocalMountPoints number of entries
163 // 2. each page is CM_DIR_PAGESIZE in size
164 // 3. the first 13 chunks of the first page are used for
166 // 4. the first chunk of all subsequent pages are used
167 // for page header stuff
168 // 5. a max of CM_DIR_EPP entries are allowed per page
169 // 6. each entry takes 1 or more chunks, depending on
170 // the size of the mount point string, as determined
172 // 7. each chunk is CM_DIR_CHUNKSIZE bytes
174 int CPP = CM_DIR_PAGESIZE / CM_DIR_CHUNKSIZE;
175 int curChunk = 13; // chunks 0 - 12 are used for header stuff
176 // of the first page in the directory
179 int curDirEntryInPage = 0;
183 /* Reserve 2 directory chunks for "." and ".." */
186 while (curDirEntry!=cm_noLocalMountPoints) {
187 sizeOfCurEntry = cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0);
188 if ((curChunk + sizeOfCurEntry >= CPP) ||
189 (curDirEntryInPage + 1 >= CM_DIR_EPP)) {
191 curDirEntryInPage = 0;
194 curChunk += sizeOfCurEntry;
199 dirSize = (curPage+1) * CM_DIR_PAGESIZE;
200 cm_FakeRootDir = malloc(dirSize);
201 cm_fakeDirSize = dirSize;
203 // yj: when we get here, we've figured out how much memory we need and
204 // allocated the appropriate space for it. we now prceed to fill
205 // it up with entries.
208 curDirEntryInPage = 0;
211 // fields in the directory entry that are unused.
213 fakeEntry.length = 0;
215 fakeEntry.fid.unique = htonl(1);
217 // the first page is special, it uses fakeDirHeader instead of fakePageHeader
218 // we fill up the page with dirEntries that belong there and we make changes
219 // to the fakeDirHeader.header.freeBitmap along the way. Then when we're done
220 // filling up the dirEntries in this page, we copy the fakeDirHeader into
221 // the top of the page.
223 // init the freeBitmap array
225 fakeDirHeader.header.freeBitmap[i]=0;
227 fakeDirHeader.header.freeBitmap[0] = 0xff;
228 fakeDirHeader.header.freeBitmap[1] = 0x7f;
231 // we start counting at 13 because the 0th to 12th chunks are used for header
234 // stick the first 2 entries "." and ".." in
235 fakeEntry.fid.unique = htonl(1);
236 fakeEntry.fid.vnode = htonl(1);
237 strcpy(fakeEntry.name, ".");
238 currentPos = cm_FakeRootDir + curPage * CM_DIR_PAGESIZE + curChunk * CM_DIR_CHUNKSIZE;
239 memcpy(currentPos, &fakeEntry, CM_DIR_CHUNKSIZE);
240 curChunk++; curDirEntryInPage++;
241 strcpy(fakeEntry.name, "..");
242 currentPos = cm_FakeRootDir + curPage * CM_DIR_PAGESIZE + curChunk * CM_DIR_CHUNKSIZE;
243 memcpy(currentPos, &fakeEntry, CM_DIR_CHUNKSIZE);
244 curChunk++; curDirEntryInPage++;
246 // keep putting stuff into page 0 if
247 // 1. we're not done with all entries
248 // 2. we have less than CM_DIR_EPP entries in page 0
249 // 3. we're not out of chunks in page 0
251 while( (curDirEntry!=cm_noLocalMountPoints) &&
252 (curDirEntryInPage < CM_DIR_EPP) &&
253 (curChunk + cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0) <= CPP))
256 noChunks = cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0);
257 fakeEntry.fid.vnode = htonl(curDirEntry + 2);
258 currentPos = cm_FakeRootDir + curPage * CM_DIR_PAGESIZE + curChunk * CM_DIR_CHUNKSIZE;
260 memcpy(currentPos, &fakeEntry, CM_DIR_CHUNKSIZE);
261 strcpy(currentPos + 12, (cm_localMountPoints+curDirEntry)->namep);
264 for (i=0; i<noChunks; i++) {
265 t1 = (curChunk + i) / 8;
266 t2 = curChunk + i - (t1*8);
267 fakeDirHeader.header.freeBitmap[t1] |= (1 << t2);
272 // when we get here, we're done with filling in the entries for page 0
273 // copy in the header info
275 memcpy(cm_FakeRootDir, &fakeDirHeader, 13 * CM_DIR_CHUNKSIZE);
279 // ok, page 0's done. Move on to the next page.
280 while (curDirEntry!=cm_noLocalMountPoints) {
282 curChunk = 1; // the zeroth chunk is reserved for page header
283 curDirEntryInPage = 0;
284 for (i=0; i<8; i++) {
285 fakePageHeader.freeBitmap[i]=0;
287 fakePageHeader.freeCount = 0;
288 fakePageHeader.pgcount = 0;
289 fakePageHeader.tag = htons(1234);
291 // while we're on the same page...
292 while ( (curDirEntry!=cm_noLocalMountPoints) &&
293 (curDirEntryInPage < CM_DIR_EPP) &&
294 (curChunk + cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0) <= CPP))
296 // add an entry to this page
298 noChunks = cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0);
299 fakeEntry.fid.vnode=htonl(curDirEntry+2);
300 currentPos = cm_FakeRootDir + curPage * CM_DIR_PAGESIZE + curChunk * CM_DIR_CHUNKSIZE;
301 memcpy(currentPos, &fakeEntry, CM_DIR_CHUNKSIZE);
302 strcpy(currentPos + 12, (cm_localMountPoints+curDirEntry)->namep);
305 for (i=0; i<noChunks; i++) {
306 t1 = (curChunk + i) / 8;
307 t2 = curChunk + i - (t1*8);
308 fakePageHeader.freeBitmap[t1] |= (1 << t2);
312 memcpy(cm_FakeRootDir + curPage * CM_DIR_PAGESIZE, &fakePageHeader, sizeof(fakePageHeader));
317 // we know the fakeDir is setup properly, so we claim that we have callback
318 osi_Log0(afsd_logp,"cm_InitFakeRootDir fakeDirCallback=1");
319 cm_fakeDirCallback=1;
321 // when we get here, we've set up everything! done!
324 int cm_FakeRootFid(cm_fid_t *fidp)
326 fidp->cell = AFS_FAKE_ROOT_CELL_ID; /* root cell */
327 fidp->volume = AFS_FAKE_ROOT_VOL_ID; /* root.afs ? */
333 /* called directly from ioctl */
334 /* called while not holding freelance lock */
335 int cm_noteLocalMountPointChange(void) {
336 lock_ObtainMutex(&cm_Freelance_Lock);
338 cm_localMountPointChangeFlag = 1;
339 lock_ReleaseMutex(&cm_Freelance_Lock);
343 int cm_getLocalMountPointChange() {
344 return cm_localMountPointChangeFlag;
347 int cm_clearLocalMountPointChange() {
348 cm_localMountPointChangeFlag = 0;
352 int cm_reInitLocalMountPoints() {
355 cm_scache_t *scp, **lscpp, *tscp;
357 osi_Log0(afsd_logp,"----- freelance reinitialization starts ----- ");
359 // first we invalidate all the SCPs that were created
360 // for the local mount points
362 osi_Log0(afsd_logp,"Invalidating local mount point scp... ");
364 aFid.cell = AFS_FAKE_ROOT_CELL_ID;
365 aFid.volume=AFS_FAKE_ROOT_VOL_ID;
369 lock_ObtainWrite(&cm_scacheLock);
370 lock_ObtainMutex(&cm_Freelance_Lock); /* always scache then freelance lock */
371 for (i=0; i<cm_noLocalMountPoints; i++) {
372 hash = CM_SCACHE_HASH(&aFid);
373 for (scp=cm_hashTablep[hash]; scp; scp=scp->nextp) {
374 if (scp->fid.volume == aFid.volume &&
375 scp->fid.vnode == aFid.vnode &&
376 scp->fid.unique == aFid.unique
379 // mark the scp to be reused
380 cm_HoldSCacheNoLock(scp);
381 lock_ReleaseWrite(&cm_scacheLock);
382 lock_ObtainMutex(&scp->mx);
383 cm_DiscardSCache(scp);
384 lock_ReleaseMutex(&scp->mx);
385 cm_CallbackNotifyChange(scp);
386 lock_ObtainWrite(&cm_scacheLock);
387 cm_ReleaseSCacheNoLock(scp);
389 // take the scp out of the hash
390 lscpp = &cm_hashTablep[hash];
391 for (tscp=*lscpp; tscp; lscpp = &tscp->nextp, tscp = *lscpp) {
392 if (tscp == scp) break;
395 scp->flags &= ~CM_SCACHEFLAG_INHASH;
398 aFid.vnode = aFid.vnode + 1;
400 lock_ReleaseWrite(&cm_scacheLock);
401 osi_Log0(afsd_logp,"\tall old scp cleared!");
403 // we must free the memory that was allocated in the prev
404 // cm_InitLocalMountPoints call
405 osi_Log0(afsd_logp,"Removing old localmountpoints... ");
406 free(cm_localMountPoints);
407 osi_Log0(afsd_logp,"\tall old localmountpoints cleared!");
409 // now re-init the localmountpoints
410 osi_Log0(afsd_logp,"Creating new localmountpoints... ");
411 cm_InitLocalMountPoints();
412 osi_Log0(afsd_logp,"\tcreated new set of localmountpoints!");
414 // now we have to free the memory allocated in cm_initfakerootdir
415 osi_Log0(afsd_logp,"Removing old fakedir... ");
416 free(cm_FakeRootDir);
417 osi_Log0(afsd_logp,"\t\told fakedir removed!");
419 // then we re-create that dir
420 osi_Log0(afsd_logp,"Creating new fakedir... ");
421 cm_InitFakeRootDir();
422 osi_Log0(afsd_logp,"\t\tcreated new fakedir!");
424 lock_ReleaseMutex(&cm_Freelance_Lock);
426 osi_Log0(afsd_logp,"----- freelance reinit complete -----");
431 // yj: open up the ini file and read all the local mount
432 // points that are stored there. Part of the initialization
433 // process for the freelance client.
434 /* to be called while holding freelance lock unless during init. */
435 long cm_InitLocalMountPoints() {
440 cm_localMountPoint_t* aLocalMountPoint;
443 char rootCellName[256];
445 HKEY hkFreelance = 0, hkFreelanceSymlinks = 0;
446 DWORD dwType, dwSize;
447 DWORD dwMountPoints = 0;
449 DWORD dwSymlinks = 0;
450 FILETIME ftLastWriteTime;
454 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
455 "SOFTWARE\\OpenAFS\\Client\\Freelance",
457 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
458 &hkFreelance) == ERROR_SUCCESS) {
460 RegQueryInfoKey( hkFreelance,
463 NULL, /* lpReserved */
464 NULL, /* lpcSubKeys */
465 NULL, /* lpcMaxSubKeyLen */
466 NULL, /* lpcMaxClassLen */
467 &dwMountPoints, /* lpcValues */
468 NULL, /* lpcMaxValueNameLen */
469 NULL, /* lpcMaxValueLen */
470 NULL, /* lpcbSecurityDescriptor */
471 &ftLastWriteTime /* lpftLastWriteTime */
474 smb_UnixTimeFromLargeSearchTime(&FakeFreelanceModTime, &ftLastWriteTime);
476 if ( dwMountPoints == 0 ) {
477 rootCellName[0] = '.';
478 code = cm_GetRootCellName(&rootCellName[1]);
480 cm_FreelanceAddMount(&rootCellName[1], &rootCellName[1], "root.cell", 0, NULL);
481 cm_FreelanceAddMount(rootCellName, &rootCellName[1], "root.cell", 1, NULL);
486 if (RegCreateKeyEx( HKEY_LOCAL_MACHINE,
487 "SOFTWARE\\OpenAFS\\Client\\Freelance\\Symlinks",
490 REG_OPTION_NON_VOLATILE,
491 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
493 &hkFreelanceSymlinks,
494 NULL) == ERROR_SUCCESS) {
496 RegQueryInfoKey( hkFreelanceSymlinks,
499 NULL, /* lpReserved */
500 NULL, /* lpcSubKeys */
501 NULL, /* lpcMaxSubKeyLen */
502 NULL, /* lpcMaxClassLen */
503 &dwSymlinks, /* lpcValues */
504 NULL, /* lpcMaxValueNameLen */
505 NULL, /* lpcMaxValueLen */
506 NULL, /* lpcbSecurityDescriptor */
507 NULL /* lpftLastWriteTime */
511 // get the number of entries there are from the first line
513 cm_noLocalMountPoints = dwMountPoints + dwSymlinks;
515 // create space to store the local mount points
516 cm_localMountPoints = malloc(sizeof(cm_localMountPoint_t) * cm_noLocalMountPoints);
517 aLocalMountPoint = cm_localMountPoints;
519 // now we read n lines and parse them into local mount points
520 // where n is the number of local mount points there are, as
522 // Each line in the ini file represents 1 local mount point and
523 // is in the format xxx#yyy:zzz, where xxx is the directory
524 // entry name, yyy is the cell name and zzz is the volume name.
525 // #yyy:zzz together make up the mount point.
526 for ( dwIndex = 0 ; dwIndex < dwMountPoints; dwIndex++ ) {
527 TCHAR szValueName[16];
528 DWORD dwValueSize = 16;
529 dwSize = sizeof(line);
530 if (RegEnumValue( hkFreelance, dwIndex, szValueName, &dwValueSize, NULL,
531 &dwType, line, &dwSize))
533 afsi_log("RegEnumValue(hkFreelance) failed");
534 cm_noLocalMountPoints--;
538 afsi_log("Mountpoint[%d] = %s",dwIndex, line);
540 /* find the trailing dot; null terminate after it */
541 t2 = strrchr(line, '.');
545 // line is not empty, so let's parse it
546 t = strchr(line, '#');
548 t = strchr(line, '%');
549 // make sure that there is a '#' or '%' separator in the line
551 afsi_log("error occurred while parsing entry in %s: no # or %% separator in line %d", AFS_FREELANCE_INI, dwIndex);
552 fprintf(stderr, "error occurred while parsing entry in afs_freelance.ini: no # or %% separator in line %d", dwIndex);
553 cm_noLocalMountPoints--;
557 aLocalMountPoint->fileType = CM_SCACHETYPE_MOUNTPOINT;
558 aLocalMountPoint->namep=malloc(t-line+1);
559 strncpy(aLocalMountPoint->namep, line, t-line);
560 aLocalMountPoint->namep[t-line] = '\0';
562 /* copy the mount point string */
563 aLocalMountPoint->mountPointStringp=malloc(strlen(t));
564 strncpy(aLocalMountPoint->mountPointStringp, t, strlen(t)-1);
565 aLocalMountPoint->mountPointStringp[strlen(t)-1] = '\0';
567 osi_Log2(afsd_logp,"found mount point: name %s, string %s",
568 osi_LogSaveString(afsd_logp,aLocalMountPoint->namep),
569 osi_LogSaveString(afsd_logp,aLocalMountPoint->mountPointStringp));
574 for ( dwIndex = 0 ; dwIndex < dwSymlinks; dwIndex++ ) {
575 TCHAR szValueName[16];
576 DWORD dwValueSize = 16;
577 dwSize = sizeof(line);
578 if (RegEnumValue( hkFreelanceSymlinks, dwIndex, szValueName, &dwValueSize, NULL,
579 &dwType, line, &dwSize))
581 afsi_log("RegEnumValue(hkFreelanceSymlinks) failed");
582 cm_noLocalMountPoints--;
586 afsi_log("Symlink[%d] = %s",dwIndex, line);
588 /* find the trailing dot; null terminate after it */
589 t2 = strrchr(line, '.');
593 // line is not empty, so let's parse it
594 t = strchr(line, ':');
596 // make sure that there is a ':' separator in the line
598 afsi_log("error occurred while parsing symlink entry: no ':' separator in line %d", dwIndex);
599 fprintf(stderr, "error occurred while parsing symlink entry: no ':' separator in line %d", dwIndex);
600 cm_noLocalMountPoints--;
604 aLocalMountPoint->fileType = CM_SCACHETYPE_SYMLINK;
605 aLocalMountPoint->namep=malloc(t-line+1);
606 strncpy(aLocalMountPoint->namep, line, t-line);
607 aLocalMountPoint->namep[t-line] = '\0';
609 /* copy the symlink string */
610 aLocalMountPoint->mountPointStringp=malloc(strlen(t)-1);
611 strncpy(aLocalMountPoint->mountPointStringp, t+1, strlen(t)-2);
612 aLocalMountPoint->mountPointStringp[strlen(t)-2] = '\0';
614 osi_Log2(afsd_logp,"found symlink: name %s, string %s",
615 osi_LogSaveString(afsd_logp,aLocalMountPoint->namep),
616 osi_LogSaveString(afsd_logp,aLocalMountPoint->mountPointStringp));
621 if ( hkFreelanceSymlinks )
622 RegCloseKey( hkFreelanceSymlinks );
623 RegCloseKey(hkFreelance);
628 /* What follows is the old code to read freelance mount points
629 * out of a text file modified to copy the data into the registry
631 cm_GetConfigDir(hdir);
632 strcat(hdir, AFS_FREELANCE_INI);
633 // open the ini file for reading
634 fp = fopen(hdir, "r");
636 /* look in the Windows directory where we used to store the file */
637 GetWindowsDirectory(hdir, sizeof(hdir));
639 strcat(hdir, AFS_FREELANCE_INI);
640 fp = fopen(hdir, "r");
644 RegCreateKeyEx( HKEY_LOCAL_MACHINE,
645 "SOFTWARE\\OpenAFS\\Client\\Freelance",
648 REG_OPTION_NON_VOLATILE,
658 RegCloseKey(hkFreelance);
660 rootCellName[0] = '.';
661 code = cm_GetRootCellName(&rootCellName[1]);
663 cm_FreelanceAddMount(&rootCellName[1], &rootCellName[1], "root.cell", 0, NULL);
664 cm_FreelanceAddMount(rootCellName, &rootCellName[1], "root.cell", 1, NULL);
669 // we successfully opened the file
670 osi_Log0(afsd_logp,"opened afs_freelance.ini");
672 // now we read the first line to see how many entries
674 fgets(line, sizeof(line), fp);
676 // if the line is empty at any point when we're reading
677 // we're screwed. report error and return.
679 afsi_log("error occurred while reading afs_freelance.ini");
680 fprintf(stderr, "error occurred while reading afs_freelance.ini");
684 // get the number of entries there are from the first line
686 cm_noLocalMountPoints = atoi(line);
688 if (cm_noLocalMountPoints > 0) {
689 // create space to store the local mount points
690 cm_localMountPoints = malloc(sizeof(cm_localMountPoint_t) * cm_noLocalMountPoints);
691 aLocalMountPoint = cm_localMountPoints;
694 // now we read n lines and parse them into local mount points
695 // where n is the number of local mount points there are, as
697 // Each line in the ini file represents 1 local mount point and
698 // is in the format xxx#yyy:zzz, where xxx is the directory
699 // entry name, yyy is the cell name and zzz is the volume name.
700 // #yyy:zzz together make up the mount point.
701 for (i=0; i<cm_noLocalMountPoints; i++) {
702 fgets(line, sizeof(line), fp);
703 // check that the line is not empty
705 afsi_log("error occurred while parsing entry in %s: empty line in line %d", AFS_FREELANCE_INI, i);
706 fprintf(stderr, "error occurred while parsing entry in afs_freelance.ini: empty line in line %d", i);
710 /* find the trailing dot; null terminate after it */
711 t2 = strrchr(line, '.');
718 /* we are migrating to the registry */
719 sprintf(szIndex,"%d",dwIndex++);
721 dwSize = strlen(line) + 1;
722 RegSetValueEx( hkFreelance, szIndex, 0, dwType, line, dwSize);
726 // line is not empty, so let's parse it
727 t = strchr(line, '#');
729 t = strchr(line, '%');
730 // make sure that there is a '#' or '%' separator in the line
732 afsi_log("error occurred while parsing entry in %s: no # or %% separator in line %d", AFS_FREELANCE_INI, i);
733 fprintf(stderr, "error occurred while parsing entry in afs_freelance.ini: no # or %% separator in line %d", i);
736 aLocalMountPoint->namep=malloc(t-line+1);
737 memcpy(aLocalMountPoint->namep, line, t-line);
738 *(aLocalMountPoint->namep + (t-line)) = 0;
740 aLocalMountPoint->mountPointStringp=malloc(strlen(line) - (t-line) + 1);
741 memcpy(aLocalMountPoint->mountPointStringp, t, strlen(line)-(t-line)-1);
742 *(aLocalMountPoint->mountPointStringp + (strlen(line)-(t-line)-1)) = 0;
744 osi_Log2(afsd_logp,"found mount point: name %s, string %s",
745 aLocalMountPoint->namep,
746 aLocalMountPoint->mountPointStringp);
753 RegCloseKey(hkFreelance);
760 int cm_getNoLocalMountPoints() {
761 return cm_noLocalMountPoints;
765 long cm_FreelanceMountPointExists(char * filename)
771 HKEY hkFreelance = 0;
772 DWORD dwType, dwSize;
776 lock_ObtainMutex(&cm_Freelance_Lock);
778 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
779 "SOFTWARE\\OpenAFS\\Client\\Freelance",
781 KEY_READ|KEY_QUERY_VALUE,
782 &hkFreelance) == ERROR_SUCCESS)
784 RegQueryInfoKey( hkFreelance,
787 NULL, /* lpReserved */
788 NULL, /* lpcSubKeys */
789 NULL, /* lpcMaxSubKeyLen */
790 NULL, /* lpcMaxClassLen */
791 &dwMountPoints, /* lpcValues */
792 NULL, /* lpcMaxValueNameLen */
793 NULL, /* lpcMaxValueLen */
794 NULL, /* lpcbSecurityDescriptor */
795 NULL /* lpftLastWriteTime */
798 for ( dwIndex = 0; dwIndex < dwMountPoints; dwIndex++ ) {
799 TCHAR szValueName[16];
800 DWORD dwValueSize = 16;
801 dwSize = sizeof(line);
802 RegEnumValue( hkFreelance, dwIndex, szValueName, &dwValueSize, NULL,
803 &dwType, line, &dwSize);
805 cp=strchr(line, '#');
807 cp=strchr(line, '%');
808 memcpy(shortname, line, cp-line);
809 shortname[cp-line]=0;
811 if (!strcmp(shortname, filename)) {
816 for ( dwIndex = 0; dwIndex < dwMountPoints; dwIndex++ ) {
817 TCHAR szValueName[16];
818 DWORD dwValueSize = 16;
819 dwSize = sizeof(line);
820 RegEnumValue( hkFreelance, dwIndex, szValueName, &dwValueSize, NULL,
821 &dwType, line, &dwSize);
823 cp=strchr(line, '#');
825 cp=strchr(line, '%');
826 memcpy(shortname, line, cp-line);
827 shortname[cp-line]=0;
829 if (!stricmp(shortname, filename)) {
834 RegCloseKey(hkFreelance);
837 lock_ReleaseMutex(&cm_Freelance_Lock);
842 long cm_FreelanceSymlinkExists(char * filename)
848 HKEY hkFreelance = 0;
849 DWORD dwType, dwSize;
853 lock_ObtainMutex(&cm_Freelance_Lock);
855 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
856 "SOFTWARE\\OpenAFS\\Client\\Freelance\\Symlinks",
858 KEY_READ|KEY_QUERY_VALUE,
859 &hkFreelance) == ERROR_SUCCESS)
861 RegQueryInfoKey( hkFreelance,
864 NULL, /* lpReserved */
865 NULL, /* lpcSubKeys */
866 NULL, /* lpcMaxSubKeyLen */
867 NULL, /* lpcMaxClassLen */
868 &dwSymlinks, /* lpcValues */
869 NULL, /* lpcMaxValueNameLen */
870 NULL, /* lpcMaxValueLen */
871 NULL, /* lpcbSecurityDescriptor */
872 NULL /* lpftLastWriteTime */
875 for ( dwIndex = 0; dwIndex < dwSymlinks; 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, ':');
883 memcpy(shortname, line, cp-line);
884 shortname[cp-line]=0;
886 if (!strcmp(shortname, filename)) {
891 for ( dwIndex = 0; dwIndex < dwSymlinks; dwIndex++ ) {
892 TCHAR szValueName[16];
893 DWORD dwValueSize = 16;
894 dwSize = sizeof(line);
895 RegEnumValue( hkFreelance, dwIndex, szValueName, &dwValueSize, NULL,
896 &dwType, line, &dwSize);
898 cp=strchr(line, ':');
899 memcpy(shortname, line, cp-line);
900 shortname[cp-line]=0;
902 if (!stricmp(shortname, filename)) {
907 RegCloseKey(hkFreelance);
910 lock_ReleaseMutex(&cm_Freelance_Lock);
916 long cm_FreelanceAddMount(char *filename, char *cellname, char *volume, int rw, cm_fid_t *fidp)
925 HKEY hkFreelance = 0;
926 DWORD dwType, dwSize;
931 /* before adding, verify the cell name; if it is not a valid cell,
932 don't add the mount point.
933 allow partial matches as a means of poor man's alias. */
934 /* major performance issue? */
935 osi_Log4(afsd_logp,"Freelance Add Mount request: filename=%s cellname=%s volume=%s %s",
936 osi_LogSaveString(afsd_logp,filename),
937 osi_LogSaveString(afsd_logp,cellname),
938 osi_LogSaveString(afsd_logp,volume),
941 if ( filename[0] == '\0' || cellname[0] == '\0' || volume[0] == '\0' )
944 if (cellname[0] == '.') {
945 if (!cm_GetCell_Gen(&cellname[1], fullname, CM_FLAG_CREATE))
948 if (!cm_GetCell_Gen(cellname, fullname, CM_FLAG_CREATE))
953 if ( cm_FreelanceMountPointExists(filename) ||
954 cm_FreelanceSymlinkExists(filename) )
958 osi_Log1(afsd_logp,"Freelance Adding Mount for Cell: %s",
959 osi_LogSaveString(afsd_logp,cellname));
961 lock_ObtainMutex(&cm_Freelance_Lock);
964 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
965 "SOFTWARE\\OpenAFS\\Client\\Freelance",
967 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
968 &hkFreelance) == ERROR_SUCCESS) {
970 RegQueryInfoKey( hkFreelance,
973 NULL, /* lpReserved */
974 NULL, /* lpcSubKeys */
975 NULL, /* lpcMaxSubKeyLen */
976 NULL, /* lpcMaxClassLen */
977 &dwMountPoints, /* lpcValues */
978 NULL, /* lpcMaxValueNameLen */
979 NULL, /* lpcMaxValueLen */
980 NULL, /* lpcbSecurityDescriptor */
981 NULL /* lpftLastWriteTime */
985 sprintf(line, "%s%%%s:%s", filename, fullname, volume);
987 sprintf(line, "%s#%s:%s", filename, fullname, volume);
989 /* If we are adding a new value, there must be an unused name
990 * within the range 0 to dwMountPoints
992 for ( dwIndex = 0; dwIndex <= dwMountPoints; dwIndex++ ) {
996 dwSize = sizeof(szMount);
997 sprintf(szIndex, "%d", dwIndex);
998 if (RegQueryValueEx( hkFreelance, szIndex, 0, &dwType, szMount, &dwSize) != ERROR_SUCCESS) {
999 /* found an unused value */
1001 dwSize = strlen(line) + 1;
1002 RegSetValueEx( hkFreelance, szIndex, 0, dwType, line, dwSize);
1005 int len = strlen(filename);
1006 if ( dwType == REG_SZ && !strncmp(filename, szMount, len) &&
1007 (szMount[len] == '%' || szMount[len] == '#')) {
1008 /* Replace the existing value */
1010 dwSize = strlen(line) + 1;
1011 RegSetValueEx( hkFreelance, szIndex, 0, dwType, line, dwSize);
1016 RegCloseKey(hkFreelance);
1020 cm_GetConfigDir(hfile);
1021 strcat(hfile, AFS_FREELANCE_INI);
1022 fp = fopen(hfile, "r+");
1024 return CM_ERROR_INVAL;
1025 fgets(line, sizeof(line), fp);
1028 fseek(fp, 0, SEEK_SET);
1029 fprintf(fp, "%d", n);
1030 fseek(fp, 0, SEEK_END);
1032 fprintf(fp, "%s%%%s:%s\n", filename, fullname, volume);
1034 fprintf(fp, "%s#%s:%s\n", filename, fullname, volume);
1037 lock_ReleaseMutex(&cm_Freelance_Lock);
1039 /* cm_reInitLocalMountPoints(); */
1042 fidp->vnode = cm_noLocalMountPoints + 1; /* vnode value of last mt pt */
1044 cm_noteLocalMountPointChange();
1048 long cm_FreelanceRemoveMount(char *toremove)
1053 char shortname[200];
1054 char hfile[120], hfile2[120];
1058 HKEY hkFreelance = 0;
1059 DWORD dwType, dwSize;
1060 DWORD dwMountPoints;
1064 lock_ObtainMutex(&cm_Freelance_Lock);
1067 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
1068 "SOFTWARE\\OpenAFS\\Client\\Freelance",
1070 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
1071 &hkFreelance) == ERROR_SUCCESS) {
1073 RegQueryInfoKey( hkFreelance,
1075 NULL, /* lpcClass */
1076 NULL, /* lpReserved */
1077 NULL, /* lpcSubKeys */
1078 NULL, /* lpcMaxSubKeyLen */
1079 NULL, /* lpcMaxClassLen */
1080 &dwMountPoints, /* lpcValues */
1081 NULL, /* lpcMaxValueNameLen */
1082 NULL, /* lpcMaxValueLen */
1083 NULL, /* lpcbSecurityDescriptor */
1084 NULL /* lpftLastWriteTime */
1087 for ( dwIndex = 0; dwIndex < dwMountPoints; dwIndex++ ) {
1088 TCHAR szValueName[16];
1089 DWORD dwValueSize = 16;
1090 dwSize = sizeof(line);
1091 RegEnumValue( hkFreelance, dwIndex, szValueName, &dwValueSize, NULL,
1092 &dwType, line, &dwSize);
1094 cp=strchr(line, '#');
1096 cp=strchr(line, '%');
1097 memcpy(shortname, line, cp-line);
1098 shortname[cp-line]=0;
1100 if (!strcmp(shortname, toremove)) {
1101 RegDeleteValue( hkFreelance, szValueName );
1105 RegCloseKey(hkFreelance);
1109 cm_GetConfigDir(hfile);
1110 strcat(hfile, AFS_FREELANCE_INI);
1111 strcpy(hfile2, hfile);
1112 strcat(hfile2, "2");
1113 fp1=fopen(hfile, "r+");
1115 return CM_ERROR_INVAL;
1116 fp2=fopen(hfile2, "w+");
1119 return CM_ERROR_INVAL;
1122 fgets(line, sizeof(line), fp1);
1124 fprintf(fp2, "%d\n", n-1);
1126 for (i=0; i<n; i++) {
1127 fgets(line, sizeof(line), fp1);
1128 cp=strchr(line, '#');
1130 cp=strchr(line, '%');
1131 memcpy(shortname, line, cp-line);
1132 shortname[cp-line]=0;
1134 if (strcmp(shortname, toremove)==0) {
1145 return CM_ERROR_NOSUCHFILE;
1148 rename(hfile2, hfile);
1151 lock_ReleaseMutex(&cm_Freelance_Lock);
1152 cm_noteLocalMountPointChange();
1156 long cm_FreelanceAddSymlink(char *filename, char *destination, cm_fid_t *fidp)
1162 HKEY hkFreelanceSymlinks = 0;
1163 DWORD dwType, dwSize;
1168 /* before adding, verify the filename. If it is already in use, either as
1169 * as mount point or a cellname, do not permit the creation of the symlink.
1171 osi_Log2(afsd_logp,"Freelance Add Symlink request: filename=%s destination=%s",
1172 osi_LogSaveString(afsd_logp,filename),
1173 osi_LogSaveString(afsd_logp,destination));
1175 if ( filename[0] == '\0' || destination[0] == '\0' )
1179 if (filename[0] == '.') {
1180 cm_GetCell_Gen(&filename[1], fullname, CM_FLAG_CREATE);
1181 if (stricmp(&filename[1],fullname) == 0)
1184 cm_GetCell_Gen(filename, fullname, CM_FLAG_CREATE);
1185 if (stricmp(filename,fullname) == 0)
1190 if ( cm_FreelanceMountPointExists(filename) ||
1191 cm_FreelanceSymlinkExists(filename) )
1195 lock_ObtainMutex(&cm_Freelance_Lock);
1198 if (RegCreateKeyEx( HKEY_LOCAL_MACHINE,
1199 "SOFTWARE\\OpenAFS\\Client\\Freelance\\Symlinks",
1202 REG_OPTION_NON_VOLATILE,
1203 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
1205 &hkFreelanceSymlinks,
1206 NULL) == ERROR_SUCCESS) {
1208 RegQueryInfoKey( hkFreelanceSymlinks,
1210 NULL, /* lpcClass */
1211 NULL, /* lpReserved */
1212 NULL, /* lpcSubKeys */
1213 NULL, /* lpcMaxSubKeyLen */
1214 NULL, /* lpcMaxClassLen */
1215 &dwSymlinks, /* lpcValues */
1216 NULL, /* lpcMaxValueNameLen */
1217 NULL, /* lpcMaxValueLen */
1218 NULL, /* lpcbSecurityDescriptor */
1219 NULL /* lpftLastWriteTime */
1222 sprintf(line, "%s:%s.", filename, destination);
1224 /* If we are adding a new value, there must be an unused name
1225 * within the range 0 to dwSymlinks
1227 for ( dwIndex = 0; dwIndex <= dwSymlinks; dwIndex++ ) {
1231 dwSize = sizeof(szLink);
1232 sprintf(szIndex, "%d", dwIndex);
1233 if (RegQueryValueEx( hkFreelanceSymlinks, szIndex, 0, &dwType, szLink, &dwSize) != ERROR_SUCCESS) {
1234 /* found an unused value */
1236 dwSize = strlen(line) + 1;
1237 RegSetValueEx( hkFreelanceSymlinks, szIndex, 0, dwType, line, dwSize);
1240 int len = strlen(filename);
1241 if ( dwType == REG_SZ && !strncmp(filename, szLink, len) && szLink[len] == ':') {
1242 /* Replace the existing value */
1244 dwSize = strlen(line) + 1;
1245 RegSetValueEx( hkFreelanceSymlinks, szIndex, 0, dwType, line, dwSize);
1250 RegCloseKey(hkFreelanceSymlinks);
1253 lock_ReleaseMutex(&cm_Freelance_Lock);
1255 /* cm_reInitLocalMountPoints(); */
1258 fidp->vnode = cm_noLocalMountPoints + 1; /* vnode value of last mt pt */
1260 cm_noteLocalMountPointChange();
1264 long cm_FreelanceRemoveSymlink(char *toremove)
1268 char shortname[200];
1271 HKEY hkFreelanceSymlinks = 0;
1272 DWORD dwType, dwSize;
1277 lock_ObtainMutex(&cm_Freelance_Lock);
1280 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
1281 "SOFTWARE\\OpenAFS\\Client\\Freelance\\Symlinks",
1283 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
1284 &hkFreelanceSymlinks) == ERROR_SUCCESS) {
1286 RegQueryInfoKey( hkFreelanceSymlinks,
1288 NULL, /* lpcClass */
1289 NULL, /* lpReserved */
1290 NULL, /* lpcSubKeys */
1291 NULL, /* lpcMaxSubKeyLen */
1292 NULL, /* lpcMaxClassLen */
1293 &dwSymlinks, /* lpcValues */
1294 NULL, /* lpcMaxValueNameLen */
1295 NULL, /* lpcMaxValueLen */
1296 NULL, /* lpcbSecurityDescriptor */
1297 NULL /* lpftLastWriteTime */
1300 for ( dwIndex = 0; dwIndex < dwSymlinks; dwIndex++ ) {
1301 TCHAR szValueName[16];
1302 DWORD dwValueSize = 16;
1303 dwSize = sizeof(line);
1304 RegEnumValue( hkFreelanceSymlinks, dwIndex, szValueName, &dwValueSize, NULL,
1305 &dwType, line, &dwSize);
1307 cp=strchr(line, ':');
1308 memcpy(shortname, line, cp-line);
1309 shortname[cp-line]=0;
1311 if (!strcmp(shortname, toremove)) {
1312 RegDeleteValue( hkFreelanceSymlinks, szValueName );
1316 RegCloseKey(hkFreelanceSymlinks);
1320 lock_ReleaseMutex(&cm_Freelance_Lock);
1321 cm_noteLocalMountPointChange();
1324 #endif /* AFS_FREELANCE_CLIENT */