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.unique = htonl(1);
261 fakeEntry.fid.vnode = htonl(1);
262 strcpy(fakeEntry.name, ".");
263 currentPos = cm_FakeRootDir + curPage * CM_DIR_PAGESIZE + curChunk * CM_DIR_CHUNKSIZE;
264 memcpy(currentPos, &fakeEntry, CM_DIR_CHUNKSIZE);
265 curChunk++; curDirEntryInPage++;
266 strcpy(fakeEntry.name, "..");
267 currentPos = cm_FakeRootDir + curPage * CM_DIR_PAGESIZE + curChunk * CM_DIR_CHUNKSIZE;
268 memcpy(currentPos, &fakeEntry, CM_DIR_CHUNKSIZE);
269 curChunk++; curDirEntryInPage++;
271 // keep putting stuff into page 0 if
272 // 1. we're not done with all entries
273 // 2. we have less than CM_DIR_EPP entries in page 0
274 // 3. we're not out of chunks in page 0
276 while( (curDirEntry<cm_noLocalMountPoints) &&
277 (curDirEntryInPage < CM_DIR_EPP) &&
278 (curChunk + cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0) <= CPP))
281 noChunks = cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0);
282 fakeEntry.fid.vnode = htonl(curDirEntry + 2);
283 currentPos = cm_FakeRootDir + curPage * CM_DIR_PAGESIZE + curChunk * CM_DIR_CHUNKSIZE;
285 memcpy(currentPos, &fakeEntry, CM_DIR_CHUNKSIZE);
286 strcpy(currentPos + 12, (cm_localMountPoints+curDirEntry)->namep);
289 for (i=0; i<noChunks; i++) {
290 t1 = (curChunk + i) / 8;
291 t2 = curChunk + i - (t1*8);
292 fakeDirHeader.header.freeBitmap[t1] |= (1 << t2);
297 // when we get here, we're done with filling in the entries for page 0
298 // copy in the header info
300 memcpy(cm_FakeRootDir, &fakeDirHeader, 13 * CM_DIR_CHUNKSIZE);
304 // ok, page 0's done. Move on to the next page.
305 while (curDirEntry<cm_noLocalMountPoints) {
307 curChunk = 1; // the zeroth chunk is reserved for page header
308 curDirEntryInPage = 0;
309 for (i=0; i<8; i++) {
310 fakePageHeader.freeBitmap[i]=0;
312 fakePageHeader.freeCount = 0;
313 fakePageHeader.pgcount = 0;
314 fakePageHeader.tag = htons(1234);
316 // while we're on the same page...
317 while ( (curDirEntry<cm_noLocalMountPoints) &&
318 (curDirEntryInPage < CM_DIR_EPP) &&
319 (curChunk + cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0) <= CPP))
321 // add an entry to this page
323 noChunks = cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0);
324 fakeEntry.fid.vnode=htonl(curDirEntry+2);
325 currentPos = cm_FakeRootDir + curPage * CM_DIR_PAGESIZE + curChunk * CM_DIR_CHUNKSIZE;
326 memcpy(currentPos, &fakeEntry, CM_DIR_CHUNKSIZE);
327 strcpy(currentPos + 12, (cm_localMountPoints+curDirEntry)->namep);
330 for (i=0; i<noChunks; i++) {
331 t1 = (curChunk + i) / 8;
332 t2 = curChunk + i - (t1*8);
333 fakePageHeader.freeBitmap[t1] |= (1 << t2);
337 memcpy(cm_FakeRootDir + curPage * CM_DIR_PAGESIZE, &fakePageHeader, sizeof(fakePageHeader));
342 // we know the fakeDir is setup properly, so we claim that we have callback
343 osi_Log0(afsd_logp,"cm_InitFakeRootDir fakeDirCallback=1");
344 cm_fakeDirCallback=1;
346 // when we get here, we've set up everything! done!
349 int cm_FakeRootFid(cm_fid_t *fidp)
352 AFS_FAKE_ROOT_CELL_ID, /* root cell */
353 AFS_FAKE_ROOT_VOL_ID, /* root.afs ? */
358 /* called directly from ioctl */
359 /* called while not holding freelance lock */
360 int cm_noteLocalMountPointChange(void) {
361 lock_ObtainMutex(&cm_Freelance_Lock);
362 cm_data.fakeDirVersion++;
363 cm_localMountPointChangeFlag = 1;
364 lock_ReleaseMutex(&cm_Freelance_Lock);
368 int cm_getLocalMountPointChange() {
369 return cm_localMountPointChangeFlag;
372 int cm_clearLocalMountPointChange() {
373 cm_localMountPointChangeFlag = 0;
377 int cm_reInitLocalMountPoints() {
380 cm_scache_t *scp, **lscpp, *tscp;
382 osi_Log0(afsd_logp,"----- freelance reinitialization starts ----- ");
384 // first we invalidate all the SCPs that were created
385 // for the local mount points
387 osi_Log0(afsd_logp,"Invalidating local mount point scp... ");
389 cm_SetFid(&aFid, AFS_FAKE_ROOT_CELL_ID, AFS_FAKE_ROOT_VOL_ID, 1, 2);
391 lock_ObtainWrite(&cm_scacheLock);
392 lock_ObtainMutex(&cm_Freelance_Lock); /* always scache then freelance lock */
393 for (i=0; i<cm_noLocalMountPoints; i++) {
394 hash = CM_SCACHE_HASH(&aFid);
395 for (scp=cm_data.scacheHashTablep[hash]; scp; scp=scp->nextp) {
396 if (scp->fid.volume == aFid.volume &&
397 scp->fid.vnode == aFid.vnode &&
398 scp->fid.unique == aFid.unique
401 // mark the scp to be reused
402 cm_HoldSCacheNoLock(scp);
403 lock_ReleaseWrite(&cm_scacheLock);
404 lock_ObtainMutex(&scp->mx);
405 cm_DiscardSCache(scp);
406 lock_ReleaseMutex(&scp->mx);
407 cm_CallbackNotifyChange(scp);
408 lock_ObtainWrite(&cm_scacheLock);
409 cm_ReleaseSCacheNoLock(scp);
411 // take the scp out of the hash
412 for (lscpp = &cm_data.scacheHashTablep[hash], tscp = cm_data.scacheHashTablep[hash];
414 lscpp = &tscp->nextp, tscp = tscp->nextp) {
417 lock_ObtainMutex(&scp->mx);
418 scp->flags &= ~CM_SCACHEFLAG_INHASH;
419 lock_ReleaseMutex(&scp->mx);
425 cm_SetFid(&aFid, AFS_FAKE_ROOT_CELL_ID, AFS_FAKE_ROOT_VOL_ID, aFid.vnode + 1, 2);
427 lock_ReleaseWrite(&cm_scacheLock);
428 osi_Log0(afsd_logp,"\tall old scp cleared!");
430 // we must free the memory that was allocated in the prev
431 // cm_InitLocalMountPoints call
432 osi_Log0(afsd_logp,"Removing old localmountpoints... ");
433 free(cm_localMountPoints);
434 osi_Log0(afsd_logp,"\tall old localmountpoints cleared!");
436 // now re-init the localmountpoints
437 osi_Log0(afsd_logp,"Creating new localmountpoints... ");
438 cm_InitLocalMountPoints();
439 osi_Log0(afsd_logp,"\tcreated new set of localmountpoints!");
441 // then we re-create that dir
442 osi_Log0(afsd_logp,"Creating new fakedir... ");
443 cm_InitFakeRootDir();
444 osi_Log0(afsd_logp,"\t\tcreated new fakedir!");
446 lock_ReleaseMutex(&cm_Freelance_Lock);
448 osi_Log0(afsd_logp,"----- freelance reinit complete -----");
453 // yj: open up the registry and read all the local mount
454 // points that are stored there. Part of the initialization
455 // process for the freelance client.
456 /* to be called while holding freelance lock unless during init. */
457 long cm_InitLocalMountPoints() {
462 cm_localMountPoint_t* aLocalMountPoint;
465 char rootCellName[256];
466 HKEY hkFreelance = 0, hkFreelanceSymlinks = 0;
467 DWORD dwType, dwSize;
468 DWORD dwMountPoints = 0;
470 DWORD dwSymlinks = 0;
471 FILETIME ftLastWriteTime;
473 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
474 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance",
476 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
477 &hkFreelance) == ERROR_SUCCESS) {
479 RegQueryInfoKey( hkFreelance,
482 NULL, /* lpReserved */
483 NULL, /* lpcSubKeys */
484 NULL, /* lpcMaxSubKeyLen */
485 NULL, /* lpcMaxClassLen */
486 &dwMountPoints, /* lpcValues */
487 NULL, /* lpcMaxValueNameLen */
488 NULL, /* lpcMaxValueLen */
489 NULL, /* lpcbSecurityDescriptor */
490 &ftLastWriteTime /* lpftLastWriteTime */
493 smb_UnixTimeFromLargeSearchTime(&FakeFreelanceModTime, &ftLastWriteTime);
495 if ( dwMountPoints == 0 ) {
496 rootCellName[0] = '.';
497 code = cm_GetRootCellName(&rootCellName[1]);
499 cm_FreelanceAddMount(&rootCellName[1], &rootCellName[1], "root.cell.", 0, NULL);
500 cm_FreelanceAddMount(rootCellName, &rootCellName[1], "root.cell.", 1, NULL);
501 cm_FreelanceAddMount(".root", &rootCellName[1], "root.afs.", 1, NULL);
506 if (RegCreateKeyEx( HKEY_LOCAL_MACHINE,
507 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance\\Symlinks",
510 REG_OPTION_NON_VOLATILE,
511 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
513 &hkFreelanceSymlinks,
514 NULL) == ERROR_SUCCESS) {
516 RegQueryInfoKey( hkFreelanceSymlinks,
519 NULL, /* lpReserved */
520 NULL, /* lpcSubKeys */
521 NULL, /* lpcMaxSubKeyLen */
522 NULL, /* lpcMaxClassLen */
523 &dwSymlinks, /* lpcValues */
524 NULL, /* lpcMaxValueNameLen */
525 NULL, /* lpcMaxValueLen */
526 NULL, /* lpcbSecurityDescriptor */
527 NULL /* lpftLastWriteTime */
531 // get the number of entries there are from the first line
533 cm_noLocalMountPoints = dwMountPoints + dwSymlinks;
535 // create space to store the local mount points
536 cm_localMountPoints = malloc(sizeof(cm_localMountPoint_t) * cm_noLocalMountPoints);
537 aLocalMountPoint = cm_localMountPoints;
539 // now we read n lines and parse them into local mount points
540 // where n is the number of local mount points there are, as
542 // Each line in the ini file represents 1 local mount point and
543 // is in the format xxx#yyy:zzz, where xxx is the directory
544 // entry name, yyy is the cell name and zzz is the volume name.
545 // #yyy:zzz together make up the mount point.
546 for ( dwIndex = 0 ; dwIndex < dwMountPoints; dwIndex++ ) {
547 TCHAR szValueName[16];
548 DWORD dwValueSize = 16;
549 dwSize = sizeof(line);
550 if (RegEnumValue( hkFreelance, dwIndex, szValueName, &dwValueSize, NULL,
551 &dwType, line, &dwSize))
553 afsi_log("RegEnumValue(hkFreelance) failed");
554 cm_noLocalMountPoints--;
558 afsi_log("Mountpoint[%d] = %s",dwIndex, line);
560 /* find the trailing dot; null terminate after it */
561 t2 = strrchr(line, '.');
565 for ( t=line;*t;t++ ) {
566 if ( !isprint(*t) ) {
567 afsi_log("error occurred while parsing mountpoint entry [%d]: non-printable character", dwIndex);
568 fprintf(stderr, "error occurred while parsing mountpoint entry [%d]: non-printable character", dwIndex);
569 cm_noLocalMountPoints--;
574 // line is not empty, so let's parse it
575 t = strchr(line, '#');
577 t = strchr(line, '%');
578 // make sure that there is a '#' or '%' separator in the line
580 afsi_log("error occurred while parsing mountpoint entry [%d]: no # or %% separator", dwIndex);
581 fprintf(stderr, "error occurred while parsing mountpoint entry [%d]: no # or %% separator", dwIndex);
582 cm_noLocalMountPoints--;
586 aLocalMountPoint->fileType = CM_SCACHETYPE_MOUNTPOINT;
587 aLocalMountPoint->namep=malloc(t-line+1);
588 strncpy(aLocalMountPoint->namep, line, t-line);
589 aLocalMountPoint->namep[t-line] = '\0';
591 /* copy the mount point string */
592 aLocalMountPoint->mountPointStringp=malloc(strlen(t));
593 strncpy(aLocalMountPoint->mountPointStringp, t, strlen(t)-1);
594 aLocalMountPoint->mountPointStringp[strlen(t)-1] = '\0';
596 osi_Log2(afsd_logp,"found mount point: name %s, string %s",
597 osi_LogSaveString(afsd_logp,aLocalMountPoint->namep),
598 osi_LogSaveString(afsd_logp,aLocalMountPoint->mountPointStringp));
603 for ( dwIndex = 0 ; dwIndex < dwSymlinks; dwIndex++ ) {
604 TCHAR szValueName[16];
605 DWORD dwValueSize = 16;
606 dwSize = sizeof(line);
607 if (RegEnumValue( hkFreelanceSymlinks, dwIndex, szValueName, &dwValueSize, NULL,
608 &dwType, line, &dwSize))
610 afsi_log("RegEnumValue(hkFreelanceSymlinks) failed");
611 cm_noLocalMountPoints--;
615 afsi_log("Symlink[%d] = %s",dwIndex, line);
617 /* find the trailing dot; null terminate after it */
618 t2 = strrchr(line, '.');
622 for ( t=line;*t;t++ ) {
623 if ( !isprint(*t) ) {
624 afsi_log("error occurred while parsing symlink entry [%d]: non-printable character", dwIndex);
625 fprintf(stderr, "error occurred while parsing symlink entry [%d]: non-printable character", dwIndex);
626 cm_noLocalMountPoints--;
631 // line is not empty, so let's parse it
632 t = strchr(line, ':');
634 // make sure that there is a ':' separator in the line
636 afsi_log("error occurred while parsing symlink entry [%d]: no ':' separator", dwIndex);
637 fprintf(stderr, "error occurred while parsing symlink entry [%d]: no ':' separator", dwIndex);
638 cm_noLocalMountPoints--;
642 aLocalMountPoint->fileType = CM_SCACHETYPE_SYMLINK;
643 aLocalMountPoint->namep=malloc(t-line+1);
644 strncpy(aLocalMountPoint->namep, line, t-line);
645 aLocalMountPoint->namep[t-line] = '\0';
647 /* copy the symlink string */
648 aLocalMountPoint->mountPointStringp=malloc(strlen(t)-1);
649 strncpy(aLocalMountPoint->mountPointStringp, t+1, strlen(t)-2);
650 aLocalMountPoint->mountPointStringp[strlen(t)-2] = '\0';
652 osi_Log2(afsd_logp,"found symlink: name %s, string %s",
653 osi_LogSaveString(afsd_logp,aLocalMountPoint->namep),
654 osi_LogSaveString(afsd_logp,aLocalMountPoint->mountPointStringp));
659 if ( hkFreelanceSymlinks )
660 RegCloseKey( hkFreelanceSymlinks );
661 RegCloseKey(hkFreelance);
665 /* What follows is the old code to read freelance mount points
666 * out of a text file modified to copy the data into the registry
668 cm_GetConfigDir(hdir, sizeof(hdir));
669 strcat(hdir, AFS_FREELANCE_INI);
670 // open the ini file for reading
671 fp = fopen(hdir, "r");
673 /* look in the Windows directory where we used to store the file */
674 GetWindowsDirectory(hdir, sizeof(hdir));
676 strcat(hdir, AFS_FREELANCE_INI);
677 fp = fopen(hdir, "r");
680 RegCreateKeyEx( HKEY_LOCAL_MACHINE,
681 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance",
684 REG_OPTION_NON_VOLATILE,
692 RegCloseKey(hkFreelance);
693 rootCellName[0] = '.';
694 code = cm_GetRootCellName(&rootCellName[1]);
696 cm_FreelanceAddMount(&rootCellName[1], &rootCellName[1], "root.cell.", 0, NULL);
697 cm_FreelanceAddMount(rootCellName, &rootCellName[1], "root.cell.", 1, NULL);
698 cm_FreelanceAddMount(".root", &rootCellName[1], "root.afs.", 1, NULL);
703 // we successfully opened the file
704 osi_Log0(afsd_logp,"opened afs_freelance.ini");
706 // now we read the first line to see how many entries
708 fgets(line, sizeof(line), fp);
710 // if the line is empty at any point when we're reading
711 // we're screwed. report error and return.
713 afsi_log("error occurred while reading afs_freelance.ini");
714 fprintf(stderr, "error occurred while reading afs_freelance.ini");
718 // get the number of entries there are from the first line
720 cm_noLocalMountPoints = atoi(line);
722 if (cm_noLocalMountPoints > 0) {
723 // create space to store the local mount points
724 cm_localMountPoints = malloc(sizeof(cm_localMountPoint_t) * cm_noLocalMountPoints);
725 aLocalMountPoint = cm_localMountPoints;
728 // now we read n lines and parse them into local mount points
729 // where n is the number of local mount points there are, as
731 // Each line in the ini file represents 1 local mount point and
732 // is in the format xxx#yyy:zzz, where xxx is the directory
733 // entry name, yyy is the cell name and zzz is the volume name.
734 // #yyy:zzz together make up the mount point.
735 for (i=0; i<cm_noLocalMountPoints; i++) {
736 fgets(line, sizeof(line), fp);
737 // check that the line is not empty
739 afsi_log("error occurred while parsing entry in %s: empty line in line %d", AFS_FREELANCE_INI, i);
740 fprintf(stderr, "error occurred while parsing entry in afs_freelance.ini: empty line in line %d", i);
744 /* find the trailing dot; null terminate after it */
745 t2 = strrchr(line, '.');
751 /* we are migrating to the registry */
752 sprintf(szIndex,"%d",dwIndex++);
754 dwSize = (DWORD)strlen(line) + 1;
755 RegSetValueEx( hkFreelance, szIndex, 0, dwType, line, dwSize);
758 // line is not empty, so let's parse it
759 t = strchr(line, '#');
761 t = strchr(line, '%');
762 // make sure that there is a '#' or '%' separator in the line
764 afsi_log("error occurred while parsing entry in %s: no # or %% separator in line %d", AFS_FREELANCE_INI, i);
765 fprintf(stderr, "error occurred while parsing entry in afs_freelance.ini: no # or %% separator in line %d", i);
768 aLocalMountPoint->namep=malloc(t-line+1);
769 memcpy(aLocalMountPoint->namep, line, t-line);
770 *(aLocalMountPoint->namep + (t-line)) = 0;
772 aLocalMountPoint->mountPointStringp=malloc(strlen(line) - (t-line) + 1);
773 memcpy(aLocalMountPoint->mountPointStringp, t, strlen(line)-(t-line)-1);
774 *(aLocalMountPoint->mountPointStringp + (strlen(line)-(t-line)-1)) = 0;
776 osi_Log2(afsd_logp,"found mount point: name %s, string %s",
777 aLocalMountPoint->namep,
778 aLocalMountPoint->mountPointStringp);
784 RegCloseKey(hkFreelance);
790 int cm_getNoLocalMountPoints() {
791 return cm_noLocalMountPoints;
794 long cm_FreelanceMountPointExists(char * filename, int prefix_ok)
800 HKEY hkFreelance = 0;
801 DWORD dwType, dwSize;
805 lock_ObtainMutex(&cm_Freelance_Lock);
807 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
808 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance",
810 KEY_READ|KEY_QUERY_VALUE,
811 &hkFreelance) == ERROR_SUCCESS)
813 RegQueryInfoKey( hkFreelance,
816 NULL, /* lpReserved */
817 NULL, /* lpcSubKeys */
818 NULL, /* lpcMaxSubKeyLen */
819 NULL, /* lpcMaxClassLen */
820 &dwMountPoints, /* lpcValues */
821 NULL, /* lpcMaxValueNameLen */
822 NULL, /* lpcMaxValueLen */
823 NULL, /* lpcbSecurityDescriptor */
824 NULL /* lpftLastWriteTime */
827 for ( dwIndex = 0; dwIndex < dwMountPoints; dwIndex++ ) {
828 TCHAR szValueName[16];
829 DWORD dwValueSize = 16;
830 dwSize = sizeof(line);
831 RegEnumValue( hkFreelance, dwIndex, szValueName, &dwValueSize, NULL,
832 &dwType, line, &dwSize);
834 cp=strchr(line, '#');
836 cp=strchr(line, '%');
837 memcpy(shortname, line, cp-line);
838 shortname[cp-line]=0;
840 if (!strcmp(shortname, filename)) {
845 for ( dwIndex = 0; dwIndex < dwMountPoints; dwIndex++ ) {
846 TCHAR szValueName[16];
847 DWORD dwValueSize = 16;
848 dwSize = sizeof(line);
849 RegEnumValue( hkFreelance, dwIndex, szValueName, &dwValueSize, NULL,
850 &dwType, line, &dwSize);
852 cp=strchr(line, '#');
854 cp=strchr(line, '%');
855 memcpy(shortname, line, cp-line);
856 shortname[cp-line]=0;
858 if (!stricmp(shortname, filename)) {
863 if (prefix_ok && strlen(shortname) - strlen(filename) == 1 && !strncmp(shortname, filename, strlen(filename))) {
868 RegCloseKey(hkFreelance);
871 lock_ReleaseMutex(&cm_Freelance_Lock);
876 long cm_FreelanceSymlinkExists(char * filename, int prefix_ok)
882 HKEY hkFreelance = 0;
883 DWORD dwType, dwSize;
887 lock_ObtainMutex(&cm_Freelance_Lock);
889 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
890 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance\\Symlinks",
892 KEY_READ|KEY_QUERY_VALUE,
893 &hkFreelance) == ERROR_SUCCESS)
895 RegQueryInfoKey( hkFreelance,
898 NULL, /* lpReserved */
899 NULL, /* lpcSubKeys */
900 NULL, /* lpcMaxSubKeyLen */
901 NULL, /* lpcMaxClassLen */
902 &dwSymlinks, /* lpcValues */
903 NULL, /* lpcMaxValueNameLen */
904 NULL, /* lpcMaxValueLen */
905 NULL, /* lpcbSecurityDescriptor */
906 NULL /* lpftLastWriteTime */
909 for ( dwIndex = 0; dwIndex < dwSymlinks; dwIndex++ ) {
910 TCHAR szValueName[16];
911 DWORD dwValueSize = 16;
912 dwSize = sizeof(line);
913 RegEnumValue( hkFreelance, dwIndex, szValueName, &dwValueSize, NULL,
914 &dwType, line, &dwSize);
916 cp=strchr(line, ':');
917 memcpy(shortname, line, cp-line);
918 shortname[cp-line]=0;
920 if (!strcmp(shortname, filename)) {
925 if (prefix_ok && strlen(shortname) - strlen(filename) == 1 && !strncmp(shortname, filename, strlen(filename))) {
930 for ( dwIndex = 0; dwIndex < dwSymlinks; dwIndex++ ) {
931 TCHAR szValueName[16];
932 DWORD dwValueSize = 16;
933 dwSize = sizeof(line);
934 RegEnumValue( hkFreelance, dwIndex, szValueName, &dwValueSize, NULL,
935 &dwType, line, &dwSize);
937 cp=strchr(line, ':');
938 memcpy(shortname, line, cp-line);
939 shortname[cp-line]=0;
941 if (!stricmp(shortname, filename)) {
946 RegCloseKey(hkFreelance);
949 lock_ReleaseMutex(&cm_Freelance_Lock);
954 long cm_FreelanceAddMount(char *filename, char *cellname, char *volume, int rw, cm_fid_t *fidp)
962 HKEY hkFreelance = 0;
963 DWORD dwType, dwSize;
967 /* before adding, verify the cell name; if it is not a valid cell,
968 don't add the mount point.
969 allow partial matches as a means of poor man's alias. */
970 /* major performance issue? */
971 osi_Log4(afsd_logp,"Freelance Add Mount request: filename=%s cellname=%s volume=%s %s",
972 osi_LogSaveString(afsd_logp,filename),
973 osi_LogSaveString(afsd_logp,cellname),
974 osi_LogSaveString(afsd_logp,volume),
977 if ( filename[0] == '\0' || cellname[0] == '\0' || volume[0] == '\0' )
980 if (cellname[0] == '.') {
981 if (!cm_GetCell_Gen(&cellname[1], fullname, CM_FLAG_CREATE))
984 if (!cm_GetCell_Gen(cellname, fullname, CM_FLAG_CREATE))
988 if ( cm_FreelanceMountPointExists(filename, 0) ||
989 cm_FreelanceSymlinkExists(filename, 0) )
992 osi_Log1(afsd_logp,"Freelance Adding Mount for Cell: %s",
993 osi_LogSaveString(afsd_logp,cellname));
995 lock_ObtainMutex(&cm_Freelance_Lock);
997 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
998 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance",
1000 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
1001 &hkFreelance) == ERROR_SUCCESS) {
1003 RegQueryInfoKey( hkFreelance,
1005 NULL, /* lpcClass */
1006 NULL, /* lpReserved */
1007 NULL, /* lpcSubKeys */
1008 NULL, /* lpcMaxSubKeyLen */
1009 NULL, /* lpcMaxClassLen */
1010 &dwMountPoints, /* lpcValues */
1011 NULL, /* lpcMaxValueNameLen */
1012 NULL, /* lpcMaxValueLen */
1013 NULL, /* lpcbSecurityDescriptor */
1014 NULL /* lpftLastWriteTime */
1018 sprintf(line, "%s%%%s:%s", filename, fullname, volume);
1020 sprintf(line, "%s#%s:%s", filename, fullname, volume);
1022 /* If we are adding a new value, there must be an unused name
1023 * within the range 0 to dwMountPoints
1025 for ( dwIndex = 0; dwIndex <= dwMountPoints; dwIndex++ ) {
1029 dwSize = sizeof(szMount);
1030 sprintf(szIndex, "%d", dwIndex);
1031 if (RegQueryValueEx( hkFreelance, szIndex, 0, &dwType, szMount, &dwSize) != ERROR_SUCCESS) {
1032 /* found an unused value */
1034 dwSize = (DWORD)strlen(line) + 1;
1035 RegSetValueEx( hkFreelance, szIndex, 0, dwType, line, dwSize);
1038 int len = (int)strlen(filename);
1039 if ( dwType == REG_SZ && !strncmp(filename, szMount, len) &&
1040 (szMount[len] == '%' || szMount[len] == '#')) {
1041 /* Replace the existing value */
1043 dwSize = (DWORD)strlen(line) + 1;
1044 RegSetValueEx( hkFreelance, szIndex, 0, dwType, line, dwSize);
1049 RegCloseKey(hkFreelance);
1052 cm_GetConfigDir(hfile, sizeof(hfile));
1053 strcat(hfile, AFS_FREELANCE_INI);
1054 fp = fopen(hfile, "r+");
1056 return CM_ERROR_INVAL;
1057 fgets(line, sizeof(line), fp);
1060 fseek(fp, 0, SEEK_SET);
1061 fprintf(fp, "%d", n);
1062 fseek(fp, 0, SEEK_END);
1064 fprintf(fp, "%s%%%s:%s\n", filename, fullname, volume);
1066 fprintf(fp, "%s#%s:%s\n", filename, fullname, volume);
1069 lock_ReleaseMutex(&cm_Freelance_Lock);
1071 /* cm_reInitLocalMountPoints(); */
1073 cm_SetFid(fidp, fidp->cell, fidp->volume, cm_noLocalMountPoints + 1, 1);
1074 cm_noteLocalMountPointChange();
1078 long cm_FreelanceRemoveMount(char *toremove)
1083 char shortname[200];
1084 char hfile[260], hfile2[260];
1087 HKEY hkFreelance = 0;
1088 DWORD dwType, dwSize;
1089 DWORD dwMountPoints;
1092 lock_ObtainMutex(&cm_Freelance_Lock);
1094 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
1095 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance",
1097 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
1098 &hkFreelance) == ERROR_SUCCESS) {
1100 RegQueryInfoKey( hkFreelance,
1102 NULL, /* lpcClass */
1103 NULL, /* lpReserved */
1104 NULL, /* lpcSubKeys */
1105 NULL, /* lpcMaxSubKeyLen */
1106 NULL, /* lpcMaxClassLen */
1107 &dwMountPoints, /* lpcValues */
1108 NULL, /* lpcMaxValueNameLen */
1109 NULL, /* lpcMaxValueLen */
1110 NULL, /* lpcbSecurityDescriptor */
1111 NULL /* lpftLastWriteTime */
1114 for ( dwIndex = 0; dwIndex < dwMountPoints; dwIndex++ ) {
1115 TCHAR szValueName[16];
1116 DWORD dwValueSize = 16;
1117 dwSize = sizeof(line);
1118 RegEnumValue( hkFreelance, dwIndex, szValueName, &dwValueSize, NULL,
1119 &dwType, line, &dwSize);
1121 cp=strchr(line, '#');
1123 cp=strchr(line, '%');
1124 memcpy(shortname, line, cp-line);
1125 shortname[cp-line]=0;
1127 if (!strcmp(shortname, toremove)) {
1128 RegDeleteValue( hkFreelance, szValueName );
1132 RegCloseKey(hkFreelance);
1135 cm_GetConfigDir(hfile, sizeof(hfile));
1136 strcat(hfile, AFS_FREELANCE_INI);
1137 strcpy(hfile2, hfile);
1138 strcat(hfile2, "2");
1139 fp1=fopen(hfile, "r+");
1141 return CM_ERROR_INVAL;
1142 fp2=fopen(hfile2, "w+");
1145 return CM_ERROR_INVAL;
1148 fgets(line, sizeof(line), fp1);
1150 fprintf(fp2, "%d\n", n-1);
1152 for (i=0; i<n; i++) {
1153 fgets(line, sizeof(line), fp1);
1154 cp=strchr(line, '#');
1156 cp=strchr(line, '%');
1157 memcpy(shortname, line, cp-line);
1158 shortname[cp-line]=0;
1160 if (strcmp(shortname, toremove)==0) {
1171 return CM_ERROR_NOSUCHFILE;
1174 rename(hfile2, hfile);
1177 lock_ReleaseMutex(&cm_Freelance_Lock);
1178 cm_noteLocalMountPointChange();
1182 long cm_FreelanceAddSymlink(char *filename, char *destination, cm_fid_t *fidp)
1187 HKEY hkFreelanceSymlinks = 0;
1188 DWORD dwType, dwSize;
1192 /* before adding, verify the filename. If it is already in use, either as
1193 * as mount point or a cellname, do not permit the creation of the symlink.
1195 osi_Log2(afsd_logp,"Freelance Add Symlink request: filename=%s destination=%s",
1196 osi_LogSaveString(afsd_logp,filename),
1197 osi_LogSaveString(afsd_logp,destination));
1199 if ( filename[0] == '\0' || destination[0] == '\0' )
1200 return CM_ERROR_INVAL;
1203 if (filename[0] == '.') {
1204 cm_GetCell_Gen(&filename[1], fullname, CM_FLAG_CREATE);
1205 if (stricmp(&filename[1],fullname) == 0)
1206 return CM_ERROR_EXISTS;
1208 cm_GetCell_Gen(filename, fullname, CM_FLAG_CREATE);
1209 if (stricmp(filename,fullname) == 0)
1210 return CM_ERROR_EXISTS;
1213 if ( cm_FreelanceMountPointExists(filename, 0) ||
1214 cm_FreelanceSymlinkExists(filename, 0) )
1215 return CM_ERROR_EXISTS;
1217 lock_ObtainMutex(&cm_Freelance_Lock);
1219 if (RegCreateKeyEx( HKEY_LOCAL_MACHINE,
1220 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance\\Symlinks",
1223 REG_OPTION_NON_VOLATILE,
1224 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
1226 &hkFreelanceSymlinks,
1227 NULL) == ERROR_SUCCESS) {
1229 RegQueryInfoKey( hkFreelanceSymlinks,
1231 NULL, /* lpcClass */
1232 NULL, /* lpReserved */
1233 NULL, /* lpcSubKeys */
1234 NULL, /* lpcMaxSubKeyLen */
1235 NULL, /* lpcMaxClassLen */
1236 &dwSymlinks, /* lpcValues */
1237 NULL, /* lpcMaxValueNameLen */
1238 NULL, /* lpcMaxValueLen */
1239 NULL, /* lpcbSecurityDescriptor */
1240 NULL /* lpftLastWriteTime */
1243 sprintf(line, "%s:%s.", filename, destination);
1245 /* If we are adding a new value, there must be an unused name
1246 * within the range 0 to dwSymlinks
1248 for ( dwIndex = 0; dwIndex <= dwSymlinks; dwIndex++ ) {
1252 dwSize = sizeof(szLink);
1253 sprintf(szIndex, "%d", dwIndex);
1254 if (RegQueryValueEx( hkFreelanceSymlinks, szIndex, 0, &dwType, szLink, &dwSize) != ERROR_SUCCESS) {
1255 /* found an unused value */
1257 dwSize = (DWORD)strlen(line) + 1;
1258 RegSetValueEx( hkFreelanceSymlinks, szIndex, 0, dwType, line, dwSize);
1261 int len = (int)strlen(filename);
1262 if ( dwType == REG_SZ && !strncmp(filename, szLink, len) && szLink[len] == ':') {
1263 /* Replace the existing value */
1265 dwSize = (DWORD)strlen(line) + 1;
1266 RegSetValueEx( hkFreelanceSymlinks, szIndex, 0, dwType, line, dwSize);
1271 RegCloseKey(hkFreelanceSymlinks);
1273 lock_ReleaseMutex(&cm_Freelance_Lock);
1275 /* cm_reInitLocalMountPoints(); */
1277 cm_SetFid(fidp, fidp->cell, fidp->volume, cm_noLocalMountPoints + 1, 1);
1278 cm_noteLocalMountPointChange();
1282 long cm_FreelanceRemoveSymlink(char *toremove)
1286 char shortname[200];
1288 HKEY hkFreelanceSymlinks = 0;
1289 DWORD dwType, dwSize;
1293 lock_ObtainMutex(&cm_Freelance_Lock);
1295 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
1296 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance\\Symlinks",
1298 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
1299 &hkFreelanceSymlinks) == ERROR_SUCCESS) {
1301 RegQueryInfoKey( hkFreelanceSymlinks,
1303 NULL, /* lpcClass */
1304 NULL, /* lpReserved */
1305 NULL, /* lpcSubKeys */
1306 NULL, /* lpcMaxSubKeyLen */
1307 NULL, /* lpcMaxClassLen */
1308 &dwSymlinks, /* lpcValues */
1309 NULL, /* lpcMaxValueNameLen */
1310 NULL, /* lpcMaxValueLen */
1311 NULL, /* lpcbSecurityDescriptor */
1312 NULL /* lpftLastWriteTime */
1315 for ( dwIndex = 0; dwIndex < dwSymlinks; dwIndex++ ) {
1316 TCHAR szValueName[16];
1317 DWORD dwValueSize = 16;
1318 dwSize = sizeof(line);
1319 RegEnumValue( hkFreelanceSymlinks, dwIndex, szValueName, &dwValueSize, NULL,
1320 &dwType, line, &dwSize);
1322 cp=strchr(line, ':');
1323 memcpy(shortname, line, cp-line);
1324 shortname[cp-line]=0;
1326 if (!strcmp(shortname, toremove)) {
1327 RegDeleteValue( hkFreelanceSymlinks, szValueName );
1331 RegCloseKey(hkFreelanceSymlinks);
1334 lock_ReleaseMutex(&cm_Freelance_Lock);
1335 cm_noteLocalMountPointChange();
1338 #endif /* AFS_FREELANCE_CLIENT */