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 // yj: first we make a call to cm_initLocalMountPoints
145 // to read all the local mount points from the registry
146 cm_InitLocalMountPoints();
148 // then we make a call to InitFakeRootDir to create
149 // a fake root directory based on the local mount points
150 cm_InitFakeRootDir();
151 // --- end of yj code
153 /* Start the registry monitor */
154 phandle = thrd_Create(NULL, 65536, (ThreadFunc) cm_FreelanceChangeNotifier,
155 NULL, 0, &lpid, "cm_FreelanceChangeNotifier");
156 osi_assertx(phandle != NULL, "cm_FreelanceChangeNotifier thread create failure");
157 thrd_CloseHandle(phandle);
159 phandle = thrd_Create(NULL, 65536, (ThreadFunc) cm_FreelanceSymlinkChangeNotifier,
160 NULL, 0, &lpid, "cm_FreelanceSymlinkChangeNotifier");
161 osi_assertx(phandle != NULL, "cm_FreelanceSymlinkChangeNotifier thread create failure");
162 thrd_CloseHandle(phandle);
165 /* yj: Initialization of the fake root directory */
166 /* to be called while holding freelance lock unless during init. */
167 void cm_InitFakeRootDir() {
172 // allocate space for the fake info
173 cm_dirHeader_t fakeDirHeader;
174 cm_dirEntry_t fakeEntry;
175 cm_pageHeader_t fakePageHeader;
177 // i'm going to calculate how much space is needed for
178 // this fake root directory. we have these rules:
179 // 1. there are cm_noLocalMountPoints number of entries
180 // 2. each page is CM_DIR_PAGESIZE in size
181 // 3. the first 13 chunks of the first page are used for
183 // 4. the first chunk of all subsequent pages are used
184 // for page header stuff
185 // 5. a max of CM_DIR_EPP entries are allowed per page
186 // 6. each entry takes 1 or more chunks, depending on
187 // the size of the mount point string, as determined
189 // 7. each chunk is CM_DIR_CHUNKSIZE bytes
191 int CPP = CM_DIR_PAGESIZE / CM_DIR_CHUNKSIZE;
192 int curChunk = 13; // chunks 0 - 12 are used for header stuff
193 // of the first page in the directory
196 int curDirEntryInPage = 0;
200 /* Reserve 2 directory chunks for "." and ".." */
203 while (curDirEntry<cm_noLocalMountPoints) {
204 sizeOfCurEntry = cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0);
205 if ((curChunk + sizeOfCurEntry >= CPP) ||
206 (curDirEntryInPage + 1 >= CM_DIR_EPP)) {
208 curDirEntryInPage = 0;
211 curChunk += sizeOfCurEntry;
216 dirSize = (curPage+1) * CM_DIR_PAGESIZE;
217 if (cm_fakeDirSize != dirSize) {
219 free(cm_FakeRootDir);
220 cm_FakeRootDir = malloc(dirSize);
221 cm_fakeDirSize = dirSize;
224 // yj: when we get here, we've figured out how much memory we need and
225 // allocated the appropriate space for it. we now prceed to fill
226 // it up with entries.
229 curDirEntryInPage = 0;
232 // fields in the directory entry that are unused.
234 fakeEntry.length = 0;
236 fakeEntry.fid.unique = htonl(1);
238 // the first page is special, it uses fakeDirHeader instead of fakePageHeader
239 // we fill up the page with dirEntries that belong there and we make changes
240 // to the fakeDirHeader.header.freeBitmap along the way. Then when we're done
241 // filling up the dirEntries in this page, we copy the fakeDirHeader into
242 // the top of the page.
244 // init the freeBitmap array
246 fakeDirHeader.header.freeBitmap[i]=0;
248 fakeDirHeader.header.freeBitmap[0] = 0xff;
249 fakeDirHeader.header.freeBitmap[1] = 0x7f;
252 // we start counting at 13 because the 0th to 12th chunks are used for header
255 // stick the first 2 entries "." and ".." in
256 fakeEntry.fid.vnode = htonl(1);
257 strcpy(fakeEntry.name, ".");
258 currentPos = cm_FakeRootDir + curPage * CM_DIR_PAGESIZE + curChunk * CM_DIR_CHUNKSIZE;
259 memcpy(currentPos, &fakeEntry, CM_DIR_CHUNKSIZE);
260 curChunk++; curDirEntryInPage++;
261 strcpy(fakeEntry.name, "..");
262 currentPos = cm_FakeRootDir + curPage * CM_DIR_PAGESIZE + curChunk * CM_DIR_CHUNKSIZE;
263 memcpy(currentPos, &fakeEntry, CM_DIR_CHUNKSIZE);
264 curChunk++; curDirEntryInPage++;
266 // keep putting stuff into page 0 if
267 // 1. we're not done with all entries
268 // 2. we have less than CM_DIR_EPP entries in page 0
269 // 3. we're not out of chunks in page 0
271 while( (curDirEntry<cm_noLocalMountPoints) &&
272 (curDirEntryInPage < CM_DIR_EPP) &&
273 (curChunk + cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0) <= CPP))
276 noChunks = cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0);
277 fakeEntry.fid.vnode = htonl(curDirEntry + 2);
278 currentPos = cm_FakeRootDir + curPage * CM_DIR_PAGESIZE + curChunk * CM_DIR_CHUNKSIZE;
280 memcpy(currentPos, &fakeEntry, CM_DIR_CHUNKSIZE);
281 strcpy(currentPos + 12, (cm_localMountPoints+curDirEntry)->namep);
284 for (i=0; i<noChunks; i++) {
285 t1 = (curChunk + i) / 8;
286 t2 = curChunk + i - (t1*8);
287 fakeDirHeader.header.freeBitmap[t1] |= (1 << t2);
292 // when we get here, we're done with filling in the entries for page 0
293 // copy in the header info
295 memcpy(cm_FakeRootDir, &fakeDirHeader, 13 * CM_DIR_CHUNKSIZE);
299 // ok, page 0's done. Move on to the next page.
300 while (curDirEntry<cm_noLocalMountPoints) {
302 curChunk = 1; // the zeroth chunk is reserved for page header
303 curDirEntryInPage = 0;
304 for (i=0; i<8; i++) {
305 fakePageHeader.freeBitmap[i]=0;
307 fakePageHeader.freeCount = 0;
308 fakePageHeader.pgcount = 0;
309 fakePageHeader.tag = htons(1234);
311 // while we're on the same page...
312 while ( (curDirEntry<cm_noLocalMountPoints) &&
313 (curDirEntryInPage < CM_DIR_EPP) &&
314 (curChunk + cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0) <= CPP))
316 // add an entry to this page
318 noChunks = cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0);
319 fakeEntry.fid.vnode=htonl(curDirEntry+2);
320 currentPos = cm_FakeRootDir + curPage * CM_DIR_PAGESIZE + curChunk * CM_DIR_CHUNKSIZE;
321 memcpy(currentPos, &fakeEntry, CM_DIR_CHUNKSIZE);
322 strcpy(currentPos + 12, (cm_localMountPoints+curDirEntry)->namep);
325 for (i=0; i<noChunks; i++) {
326 t1 = (curChunk + i) / 8;
327 t2 = curChunk + i - (t1*8);
328 fakePageHeader.freeBitmap[t1] |= (1 << t2);
332 memcpy(cm_FakeRootDir + curPage * CM_DIR_PAGESIZE, &fakePageHeader, sizeof(fakePageHeader));
337 // we know the fakeDir is setup properly, so we claim that we have callback
338 osi_Log0(afsd_logp,"cm_InitFakeRootDir fakeDirCallback=1");
339 cm_fakeDirCallback=1;
341 // when we get here, we've set up everything! done!
344 int cm_FakeRootFid(cm_fid_t *fidp)
347 AFS_FAKE_ROOT_CELL_ID, /* root cell */
348 AFS_FAKE_ROOT_VOL_ID, /* root.afs ? */
353 /* called directly from ioctl */
354 /* called while not holding freelance lock */
355 int cm_noteLocalMountPointChange(void) {
356 lock_ObtainMutex(&cm_Freelance_Lock);
357 cm_data.fakeDirVersion++;
358 cm_localMountPointChangeFlag = 1;
359 lock_ReleaseMutex(&cm_Freelance_Lock);
363 int cm_getLocalMountPointChange() {
364 return cm_localMountPointChangeFlag;
367 int cm_clearLocalMountPointChange() {
368 cm_localMountPointChangeFlag = 0;
372 int cm_reInitLocalMountPoints() {
375 cm_scache_t *scp, **lscpp, *tscp;
377 osi_Log0(afsd_logp,"----- freelance reinitialization starts ----- ");
379 // first we invalidate all the SCPs that were created
380 // for the local mount points
382 osi_Log0(afsd_logp,"Invalidating local mount point scp... ");
384 cm_SetFid(&aFid, AFS_FAKE_ROOT_CELL_ID, AFS_FAKE_ROOT_VOL_ID, 1, 1);
386 lock_ObtainWrite(&cm_scacheLock);
387 lock_ObtainMutex(&cm_Freelance_Lock); /* always scache then freelance lock */
388 for (i=0; i<cm_noLocalMountPoints; i++) {
389 hash = CM_SCACHE_HASH(&aFid);
390 for (scp=cm_data.scacheHashTablep[hash]; scp; scp=scp->nextp) {
391 if (scp != cm_data.rootSCachep && cm_FidCmp(&scp->fid, &aFid) == 0) {
392 // mark the scp to be reused
393 cm_HoldSCacheNoLock(scp);
394 lock_ReleaseWrite(&cm_scacheLock);
395 lock_ObtainWrite(&scp->rw);
396 cm_DiscardSCache(scp);
397 lock_ReleaseWrite(&scp->rw);
398 cm_CallbackNotifyChange(scp);
399 lock_ObtainWrite(&cm_scacheLock);
400 cm_ReleaseSCacheNoLock(scp);
402 // take the scp out of the hash
403 for (lscpp = &cm_data.scacheHashTablep[hash], tscp = cm_data.scacheHashTablep[hash];
405 lscpp = &tscp->nextp, tscp = tscp->nextp) {
409 lock_ObtainWrite(&scp->rw);
410 scp->flags &= ~CM_SCACHEFLAG_INHASH;
411 lock_ReleaseWrite(&scp->rw);
417 cm_SetFid(&aFid, AFS_FAKE_ROOT_CELL_ID, AFS_FAKE_ROOT_VOL_ID, aFid.vnode + 1, 1);
419 lock_ReleaseWrite(&cm_scacheLock);
420 osi_Log0(afsd_logp,"\tall old scp cleared!");
422 // we must free the memory that was allocated in the prev
423 // cm_InitLocalMountPoints call
424 osi_Log0(afsd_logp,"Removing old localmountpoints... ");
425 free(cm_localMountPoints);
426 osi_Log0(afsd_logp,"\tall old localmountpoints cleared!");
428 // now re-init the localmountpoints
429 osi_Log0(afsd_logp,"Creating new localmountpoints... ");
430 cm_InitLocalMountPoints();
431 osi_Log0(afsd_logp,"\tcreated new set of localmountpoints!");
433 // then we re-create that dir
434 osi_Log0(afsd_logp,"Creating new fakedir... ");
435 cm_InitFakeRootDir();
436 osi_Log0(afsd_logp,"\t\tcreated new fakedir!");
438 lock_ReleaseMutex(&cm_Freelance_Lock);
440 osi_Log0(afsd_logp,"----- freelance reinit complete -----");
445 // yj: open up the registry and read all the local mount
446 // points that are stored there. Part of the initialization
447 // process for the freelance client.
448 /* to be called while holding freelance lock unless during init. */
449 long cm_InitLocalMountPoints() {
454 cm_localMountPoint_t* aLocalMountPoint;
457 char rootCellName[256];
458 HKEY hkFreelance = 0, hkFreelanceSymlinks = 0;
459 DWORD dwType, dwSize;
460 DWORD dwMountPoints = 0;
462 DWORD dwSymlinks = 0;
463 FILETIME ftLastWriteTime;
465 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
466 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance",
468 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
469 &hkFreelance) == ERROR_SUCCESS) {
471 RegQueryInfoKey( hkFreelance,
474 NULL, /* lpReserved */
475 NULL, /* lpcSubKeys */
476 NULL, /* lpcMaxSubKeyLen */
477 NULL, /* lpcMaxClassLen */
478 &dwMountPoints, /* lpcValues */
479 NULL, /* lpcMaxValueNameLen */
480 NULL, /* lpcMaxValueLen */
481 NULL, /* lpcbSecurityDescriptor */
482 &ftLastWriteTime /* lpftLastWriteTime */
485 smb_UnixTimeFromLargeSearchTime(&FakeFreelanceModTime, &ftLastWriteTime);
487 if ( dwMountPoints == 0 ) {
488 rootCellName[0] = '.';
489 code = cm_GetRootCellName(&rootCellName[1]);
491 cm_FreelanceAddMount(&rootCellName[1], &rootCellName[1], "root.cell.", 0, NULL);
492 cm_FreelanceAddMount(rootCellName, &rootCellName[1], "root.cell.", 1, NULL);
493 cm_FreelanceAddMount(".root", &rootCellName[1], "root.afs.", 1, NULL);
498 if (RegCreateKeyEx( HKEY_LOCAL_MACHINE,
499 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance\\Symlinks",
502 REG_OPTION_NON_VOLATILE,
503 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
505 &hkFreelanceSymlinks,
506 NULL) == ERROR_SUCCESS) {
508 RegQueryInfoKey( hkFreelanceSymlinks,
511 NULL, /* lpReserved */
512 NULL, /* lpcSubKeys */
513 NULL, /* lpcMaxSubKeyLen */
514 NULL, /* lpcMaxClassLen */
515 &dwSymlinks, /* lpcValues */
516 NULL, /* lpcMaxValueNameLen */
517 NULL, /* lpcMaxValueLen */
518 NULL, /* lpcbSecurityDescriptor */
519 NULL /* lpftLastWriteTime */
523 // get the number of entries there are from the first line
525 cm_noLocalMountPoints = dwMountPoints + dwSymlinks;
527 // create space to store the local mount points
528 cm_localMountPoints = malloc(sizeof(cm_localMountPoint_t) * cm_noLocalMountPoints);
529 aLocalMountPoint = cm_localMountPoints;
531 // now we read n lines and parse them into local mount points
532 // where n is the number of local mount points there are, as
534 // Each line in the ini file represents 1 local mount point and
535 // is in the format xxx#yyy:zzz, where xxx is the directory
536 // entry name, yyy is the cell name and zzz is the volume name.
537 // #yyy:zzz together make up the mount point.
538 for ( dwIndex = 0 ; dwIndex < dwMountPoints; dwIndex++ ) {
539 TCHAR szValueName[16];
540 DWORD dwValueSize = 16;
541 dwSize = sizeof(line);
542 if (RegEnumValue( hkFreelance, dwIndex, szValueName, &dwValueSize, NULL,
543 &dwType, line, &dwSize))
545 afsi_log("RegEnumValue(hkFreelance) failed");
546 cm_noLocalMountPoints--;
550 afsi_log("Mountpoint[%d] = %s",dwIndex, line);
552 /* find the trailing dot; null terminate after it */
553 t2 = strrchr(line, '.');
557 for ( t=line;*t;t++ ) {
558 if ( !isprint(*t) ) {
559 afsi_log("error occurred while parsing mountpoint entry [%d]: non-printable character", dwIndex);
560 fprintf(stderr, "error occurred while parsing mountpoint entry [%d]: non-printable character", dwIndex);
561 cm_noLocalMountPoints--;
566 // line is not empty, so let's parse it
567 t = strchr(line, '#');
569 t = strchr(line, '%');
570 // make sure that there is a '#' or '%' separator in the line
572 afsi_log("error occurred while parsing mountpoint entry [%d]: no # or %% separator", dwIndex);
573 fprintf(stderr, "error occurred while parsing mountpoint entry [%d]: no # or %% separator", dwIndex);
574 cm_noLocalMountPoints--;
578 aLocalMountPoint->fileType = CM_SCACHETYPE_MOUNTPOINT;
579 aLocalMountPoint->namep=malloc(t-line+1);
580 strncpy(aLocalMountPoint->namep, line, t-line);
581 aLocalMountPoint->namep[t-line] = '\0';
583 /* copy the mount point string */
584 aLocalMountPoint->mountPointStringp=malloc(strlen(t));
585 strncpy(aLocalMountPoint->mountPointStringp, t, strlen(t)-1);
586 aLocalMountPoint->mountPointStringp[strlen(t)-1] = '\0';
588 osi_Log2(afsd_logp,"found mount point: name %s, string %s",
589 osi_LogSaveString(afsd_logp,aLocalMountPoint->namep),
590 osi_LogSaveString(afsd_logp,aLocalMountPoint->mountPointStringp));
595 for ( dwIndex = 0 ; dwIndex < dwSymlinks; dwIndex++ ) {
596 TCHAR szValueName[16];
597 DWORD dwValueSize = 16;
598 dwSize = sizeof(line);
599 if (RegEnumValue( hkFreelanceSymlinks, dwIndex, szValueName, &dwValueSize, NULL,
600 &dwType, line, &dwSize))
602 afsi_log("RegEnumValue(hkFreelanceSymlinks) failed");
603 cm_noLocalMountPoints--;
607 afsi_log("Symlink[%d] = %s",dwIndex, line);
609 /* find the trailing dot; null terminate after it */
610 t2 = strrchr(line, '.');
614 for ( t=line;*t;t++ ) {
615 if ( !isprint(*t) ) {
616 afsi_log("error occurred while parsing symlink entry [%d]: non-printable character", dwIndex);
617 fprintf(stderr, "error occurred while parsing symlink entry [%d]: non-printable character", dwIndex);
618 cm_noLocalMountPoints--;
623 // line is not empty, so let's parse it
624 t = strchr(line, ':');
626 // make sure that there is a ':' separator in the line
628 afsi_log("error occurred while parsing symlink entry [%d]: no ':' separator", dwIndex);
629 fprintf(stderr, "error occurred while parsing symlink entry [%d]: no ':' separator", dwIndex);
630 cm_noLocalMountPoints--;
634 aLocalMountPoint->fileType = CM_SCACHETYPE_SYMLINK;
635 aLocalMountPoint->namep=malloc(t-line+1);
636 strncpy(aLocalMountPoint->namep, line, t-line);
637 aLocalMountPoint->namep[t-line] = '\0';
639 /* copy the symlink string */
640 aLocalMountPoint->mountPointStringp=malloc(strlen(t)-1);
641 strncpy(aLocalMountPoint->mountPointStringp, t+1, strlen(t)-2);
642 aLocalMountPoint->mountPointStringp[strlen(t)-2] = '\0';
644 osi_Log2(afsd_logp,"found symlink: name %s, string %s",
645 osi_LogSaveString(afsd_logp,aLocalMountPoint->namep),
646 osi_LogSaveString(afsd_logp,aLocalMountPoint->mountPointStringp));
651 if ( hkFreelanceSymlinks )
652 RegCloseKey( hkFreelanceSymlinks );
653 RegCloseKey(hkFreelance);
657 /* What follows is the old code to read freelance mount points
658 * out of a text file modified to copy the data into the registry
660 cm_GetConfigDir(hdir, sizeof(hdir));
661 strcat(hdir, AFS_FREELANCE_INI);
662 // open the ini file for reading
663 fp = fopen(hdir, "r");
665 /* look in the Windows directory where we used to store the file */
666 GetWindowsDirectory(hdir, sizeof(hdir));
668 strcat(hdir, AFS_FREELANCE_INI);
669 fp = fopen(hdir, "r");
672 RegCreateKeyEx( HKEY_LOCAL_MACHINE,
673 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance",
676 REG_OPTION_NON_VOLATILE,
684 RegCloseKey(hkFreelance);
685 rootCellName[0] = '.';
686 code = cm_GetRootCellName(&rootCellName[1]);
688 cm_FreelanceAddMount(&rootCellName[1], &rootCellName[1], "root.cell.", 0, NULL);
689 cm_FreelanceAddMount(rootCellName, &rootCellName[1], "root.cell.", 1, NULL);
690 cm_FreelanceAddMount(".root", &rootCellName[1], "root.afs.", 1, NULL);
695 // we successfully opened the file
696 osi_Log0(afsd_logp,"opened afs_freelance.ini");
698 // now we read the first line to see how many entries
700 fgets(line, sizeof(line), fp);
702 // if the line is empty at any point when we're reading
703 // we're screwed. report error and return.
705 afsi_log("error occurred while reading afs_freelance.ini");
706 fprintf(stderr, "error occurred while reading afs_freelance.ini");
710 // get the number of entries there are from the first line
712 cm_noLocalMountPoints = atoi(line);
714 if (cm_noLocalMountPoints > 0) {
715 // create space to store the local mount points
716 cm_localMountPoints = malloc(sizeof(cm_localMountPoint_t) * cm_noLocalMountPoints);
717 aLocalMountPoint = cm_localMountPoints;
720 // now we read n lines and parse them into local mount points
721 // where n is the number of local mount points there are, as
723 // Each line in the ini file represents 1 local mount point and
724 // is in the format xxx#yyy:zzz, where xxx is the directory
725 // entry name, yyy is the cell name and zzz is the volume name.
726 // #yyy:zzz together make up the mount point.
727 for (i=0; i<cm_noLocalMountPoints; i++) {
728 fgets(line, sizeof(line), fp);
729 // check that the line is not empty
731 afsi_log("error occurred while parsing entry in %s: empty line in line %d", AFS_FREELANCE_INI, i);
732 fprintf(stderr, "error occurred while parsing entry in afs_freelance.ini: empty line in line %d", i);
736 /* find the trailing dot; null terminate after it */
737 t2 = strrchr(line, '.');
743 /* we are migrating to the registry */
744 sprintf(szIndex,"%d",dwIndex++);
746 dwSize = (DWORD)strlen(line) + 1;
747 RegSetValueEx( hkFreelance, szIndex, 0, dwType, line, dwSize);
750 // line is not empty, so let's parse it
751 t = strchr(line, '#');
753 t = strchr(line, '%');
754 // make sure that there is a '#' or '%' separator in the line
756 afsi_log("error occurred while parsing entry in %s: no # or %% separator in line %d", AFS_FREELANCE_INI, i);
757 fprintf(stderr, "error occurred while parsing entry in afs_freelance.ini: no # or %% separator in line %d", i);
760 aLocalMountPoint->namep=malloc(t-line+1);
761 memcpy(aLocalMountPoint->namep, line, t-line);
762 *(aLocalMountPoint->namep + (t-line)) = 0;
764 aLocalMountPoint->mountPointStringp=malloc(strlen(line) - (t-line) + 1);
765 memcpy(aLocalMountPoint->mountPointStringp, t, strlen(line)-(t-line)-1);
766 *(aLocalMountPoint->mountPointStringp + (strlen(line)-(t-line)-1)) = 0;
768 osi_Log2(afsd_logp,"found mount point: name %s, string %s",
769 aLocalMountPoint->namep,
770 aLocalMountPoint->mountPointStringp);
776 RegCloseKey(hkFreelance);
782 int cm_getNoLocalMountPoints() {
783 return cm_noLocalMountPoints;
786 long cm_FreelanceMountPointExists(char * filename, int prefix_ok)
792 HKEY hkFreelance = 0;
793 DWORD dwType, dwSize;
797 lock_ObtainMutex(&cm_Freelance_Lock);
799 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
800 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance",
802 KEY_READ|KEY_QUERY_VALUE,
803 &hkFreelance) == ERROR_SUCCESS)
805 RegQueryInfoKey( hkFreelance,
808 NULL, /* lpReserved */
809 NULL, /* lpcSubKeys */
810 NULL, /* lpcMaxSubKeyLen */
811 NULL, /* lpcMaxClassLen */
812 &dwMountPoints, /* lpcValues */
813 NULL, /* lpcMaxValueNameLen */
814 NULL, /* lpcMaxValueLen */
815 NULL, /* lpcbSecurityDescriptor */
816 NULL /* lpftLastWriteTime */
819 for ( dwIndex = 0; dwIndex < dwMountPoints; dwIndex++ ) {
820 TCHAR szValueName[16];
821 DWORD dwValueSize = 16;
822 dwSize = sizeof(line);
823 RegEnumValue( hkFreelance, dwIndex, szValueName, &dwValueSize, NULL,
824 &dwType, line, &dwSize);
826 cp=strchr(line, '#');
828 cp=strchr(line, '%');
829 memcpy(shortname, line, cp-line);
830 shortname[cp-line]=0;
832 if (!strcmp(shortname, filename)) {
837 for ( dwIndex = 0; dwIndex < dwMountPoints; dwIndex++ ) {
838 TCHAR szValueName[16];
839 DWORD dwValueSize = 16;
840 dwSize = sizeof(line);
841 RegEnumValue( hkFreelance, dwIndex, szValueName, &dwValueSize, NULL,
842 &dwType, line, &dwSize);
844 cp=strchr(line, '#');
846 cp=strchr(line, '%');
847 memcpy(shortname, line, cp-line);
848 shortname[cp-line]=0;
850 if (!cm_stricmp_utf8(shortname, filename)) {
855 if (prefix_ok && strlen(shortname) - strlen(filename) == 1 && !strncmp(shortname, filename, strlen(filename))) {
860 RegCloseKey(hkFreelance);
863 lock_ReleaseMutex(&cm_Freelance_Lock);
868 long cm_FreelanceSymlinkExists(char * filename, int prefix_ok)
874 HKEY hkFreelance = 0;
875 DWORD dwType, dwSize;
879 lock_ObtainMutex(&cm_Freelance_Lock);
881 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
882 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance\\Symlinks",
884 KEY_READ|KEY_QUERY_VALUE,
885 &hkFreelance) == ERROR_SUCCESS)
887 RegQueryInfoKey( hkFreelance,
890 NULL, /* lpReserved */
891 NULL, /* lpcSubKeys */
892 NULL, /* lpcMaxSubKeyLen */
893 NULL, /* lpcMaxClassLen */
894 &dwSymlinks, /* lpcValues */
895 NULL, /* lpcMaxValueNameLen */
896 NULL, /* lpcMaxValueLen */
897 NULL, /* lpcbSecurityDescriptor */
898 NULL /* lpftLastWriteTime */
901 for ( dwIndex = 0; dwIndex < dwSymlinks; dwIndex++ ) {
902 TCHAR szValueName[16];
903 DWORD dwValueSize = 16;
904 dwSize = sizeof(line);
905 RegEnumValue( hkFreelance, dwIndex, szValueName, &dwValueSize, NULL,
906 &dwType, line, &dwSize);
908 cp=strchr(line, ':');
909 memcpy(shortname, line, cp-line);
910 shortname[cp-line]=0;
912 if (!strcmp(shortname, filename)) {
917 if (prefix_ok && strlen(shortname) - strlen(filename) == 1 && !strncmp(shortname, filename, strlen(filename))) {
922 for ( dwIndex = 0; dwIndex < dwSymlinks; dwIndex++ ) {
923 TCHAR szValueName[16];
924 DWORD dwValueSize = 16;
925 dwSize = sizeof(line);
926 RegEnumValue( hkFreelance, dwIndex, szValueName, &dwValueSize, NULL,
927 &dwType, line, &dwSize);
929 cp=strchr(line, ':');
930 memcpy(shortname, line, cp-line);
931 shortname[cp-line]=0;
933 if (!cm_stricmp_utf8(shortname, filename)) {
938 RegCloseKey(hkFreelance);
941 lock_ReleaseMutex(&cm_Freelance_Lock);
946 long cm_FreelanceAddMount(char *filename, char *cellname, char *volume, int rw, cm_fid_t *fidp)
951 char fullname[CELL_MAXNAMELEN];
954 HKEY hkFreelance = 0;
955 DWORD dwType, dwSize;
959 /* before adding, verify the cell name; if it is not a valid cell,
960 don't add the mount point.
961 allow partial matches as a means of poor man's alias. */
962 /* major performance issue? */
963 osi_Log4(afsd_logp,"Freelance Add Mount request: filename=%s cellname=%s volume=%s %s",
964 osi_LogSaveString(afsd_logp,filename),
965 osi_LogSaveString(afsd_logp,cellname),
966 osi_LogSaveString(afsd_logp,volume),
969 if ( filename[0] == '\0' || cellname[0] == '\0' || volume[0] == '\0' )
972 if (cellname[0] == '.') {
973 if (!cm_GetCell_Gen(&cellname[1], fullname, CM_FLAG_CREATE))
976 if (!cm_GetCell_Gen(cellname, fullname, CM_FLAG_CREATE))
980 if ( cm_FreelanceMountPointExists(filename, 0) ||
981 cm_FreelanceSymlinkExists(filename, 0) )
984 osi_Log1(afsd_logp,"Freelance Adding Mount for Cell: %s",
985 osi_LogSaveString(afsd_logp,cellname));
987 lock_ObtainMutex(&cm_Freelance_Lock);
989 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
990 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance",
992 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
993 &hkFreelance) == ERROR_SUCCESS) {
995 RegQueryInfoKey( hkFreelance,
998 NULL, /* lpReserved */
999 NULL, /* lpcSubKeys */
1000 NULL, /* lpcMaxSubKeyLen */
1001 NULL, /* lpcMaxClassLen */
1002 &dwMountPoints, /* lpcValues */
1003 NULL, /* lpcMaxValueNameLen */
1004 NULL, /* lpcMaxValueLen */
1005 NULL, /* lpcbSecurityDescriptor */
1006 NULL /* lpftLastWriteTime */
1010 sprintf(line, "%s%%%s:%s", filename, fullname, volume);
1012 sprintf(line, "%s#%s:%s", filename, fullname, volume);
1014 /* If we are adding a new value, there must be an unused name
1015 * within the range 0 to dwMountPoints
1017 for ( dwIndex = 0; dwIndex <= dwMountPoints; dwIndex++ ) {
1021 dwSize = sizeof(szMount);
1022 sprintf(szIndex, "%d", dwIndex);
1023 if (RegQueryValueEx( hkFreelance, szIndex, 0, &dwType, szMount, &dwSize) != ERROR_SUCCESS) {
1024 /* found an unused value */
1026 dwSize = (DWORD)strlen(line) + 1;
1027 RegSetValueEx( hkFreelance, szIndex, 0, dwType, line, dwSize);
1030 int len = (int)strlen(filename);
1031 if ( dwType == REG_SZ && !strncmp(filename, szMount, len) &&
1032 (szMount[len] == '%' || szMount[len] == '#')) {
1033 /* Replace the existing value */
1035 dwSize = (DWORD)strlen(line) + 1;
1036 RegSetValueEx( hkFreelance, szIndex, 0, dwType, line, dwSize);
1041 RegCloseKey(hkFreelance);
1044 cm_GetConfigDir(hfile, sizeof(hfile));
1045 strcat(hfile, AFS_FREELANCE_INI);
1046 fp = fopen(hfile, "r+");
1048 return CM_ERROR_INVAL;
1049 fgets(line, sizeof(line), fp);
1052 fseek(fp, 0, SEEK_SET);
1053 fprintf(fp, "%d", n);
1054 fseek(fp, 0, SEEK_END);
1056 fprintf(fp, "%s%%%s:%s\n", filename, fullname, volume);
1058 fprintf(fp, "%s#%s:%s\n", filename, fullname, volume);
1061 lock_ReleaseMutex(&cm_Freelance_Lock);
1063 /* cm_reInitLocalMountPoints(); */
1065 cm_SetFid(fidp, fidp->cell, fidp->volume, ++cm_noLocalMountPoints, 1);
1066 cm_noteLocalMountPointChange();
1070 long cm_FreelanceRemoveMount(char *toremove)
1075 char shortname[200];
1076 char hfile[260], hfile2[260];
1079 HKEY hkFreelance = 0;
1080 DWORD dwType, dwSize;
1081 DWORD dwMountPoints;
1084 lock_ObtainMutex(&cm_Freelance_Lock);
1086 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
1087 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance",
1089 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
1090 &hkFreelance) == ERROR_SUCCESS) {
1092 RegQueryInfoKey( hkFreelance,
1094 NULL, /* lpcClass */
1095 NULL, /* lpReserved */
1096 NULL, /* lpcSubKeys */
1097 NULL, /* lpcMaxSubKeyLen */
1098 NULL, /* lpcMaxClassLen */
1099 &dwMountPoints, /* lpcValues */
1100 NULL, /* lpcMaxValueNameLen */
1101 NULL, /* lpcMaxValueLen */
1102 NULL, /* lpcbSecurityDescriptor */
1103 NULL /* lpftLastWriteTime */
1106 for ( dwIndex = 0; dwIndex < dwMountPoints; dwIndex++ ) {
1107 TCHAR szValueName[16];
1108 DWORD dwValueSize = 16;
1109 dwSize = sizeof(line);
1110 RegEnumValue( hkFreelance, dwIndex, szValueName, &dwValueSize, NULL,
1111 &dwType, line, &dwSize);
1113 cp=strchr(line, '#');
1115 cp=strchr(line, '%');
1116 memcpy(shortname, line, cp-line);
1117 shortname[cp-line]=0;
1119 if (!strcmp(shortname, toremove)) {
1120 RegDeleteValue( hkFreelance, szValueName );
1125 RegCloseKey(hkFreelance);
1128 cm_GetConfigDir(hfile, sizeof(hfile));
1129 strcat(hfile, AFS_FREELANCE_INI);
1130 strcpy(hfile2, hfile);
1131 strcat(hfile2, "2");
1132 fp1=fopen(hfile, "r+");
1134 return CM_ERROR_INVAL;
1135 fp2=fopen(hfile2, "w+");
1138 return CM_ERROR_INVAL;
1141 fgets(line, sizeof(line), fp1);
1143 fprintf(fp2, "%d\n", n-1);
1145 for (i=0; i<n; i++) {
1146 fgets(line, sizeof(line), fp1);
1147 cp=strchr(line, '#');
1149 cp=strchr(line, '%');
1150 memcpy(shortname, line, cp-line);
1151 shortname[cp-line]=0;
1153 if (strcmp(shortname, toremove)==0) {
1165 rename(hfile2, hfile);
1169 lock_ReleaseMutex(&cm_Freelance_Lock);
1171 cm_noteLocalMountPointChange();
1174 return CM_ERROR_NOSUCHFILE;
1177 long cm_FreelanceAddSymlink(char *filename, char *destination, cm_fid_t *fidp)
1180 char fullname[CELL_MAXNAMELEN];
1182 HKEY hkFreelanceSymlinks = 0;
1183 DWORD dwType, dwSize;
1187 /* before adding, verify the filename. If it is already in use, either as
1188 * as mount point or a cellname, do not permit the creation of the symlink.
1190 osi_Log2(afsd_logp,"Freelance Add Symlink request: filename=%s destination=%s",
1191 osi_LogSaveString(afsd_logp,filename),
1192 osi_LogSaveString(afsd_logp,destination));
1194 if ( filename[0] == '\0' || destination[0] == '\0' )
1195 return CM_ERROR_INVAL;
1198 if (filename[0] == '.') {
1199 cm_GetCell_Gen(&filename[1], fullname, CM_FLAG_CREATE);
1200 if (cm_stricmp_utf8(&filename[1],fullname) == 0)
1201 return CM_ERROR_EXISTS;
1203 cm_GetCell_Gen(filename, fullname, CM_FLAG_CREATE);
1204 if (cm_stricmp_utf8(filename,fullname) == 0)
1205 return CM_ERROR_EXISTS;
1208 if ( cm_FreelanceMountPointExists(filename, 0) ||
1209 cm_FreelanceSymlinkExists(filename, 0) )
1210 return CM_ERROR_EXISTS;
1212 lock_ObtainMutex(&cm_Freelance_Lock);
1214 if (RegCreateKeyEx( HKEY_LOCAL_MACHINE,
1215 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance\\Symlinks",
1218 REG_OPTION_NON_VOLATILE,
1219 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
1221 &hkFreelanceSymlinks,
1222 NULL) == ERROR_SUCCESS) {
1224 RegQueryInfoKey( hkFreelanceSymlinks,
1226 NULL, /* lpcClass */
1227 NULL, /* lpReserved */
1228 NULL, /* lpcSubKeys */
1229 NULL, /* lpcMaxSubKeyLen */
1230 NULL, /* lpcMaxClassLen */
1231 &dwSymlinks, /* lpcValues */
1232 NULL, /* lpcMaxValueNameLen */
1233 NULL, /* lpcMaxValueLen */
1234 NULL, /* lpcbSecurityDescriptor */
1235 NULL /* lpftLastWriteTime */
1238 sprintf(line, "%s:%s.", filename, destination);
1240 /* If we are adding a new value, there must be an unused name
1241 * within the range 0 to dwSymlinks
1243 for ( dwIndex = 0; dwIndex <= dwSymlinks; dwIndex++ ) {
1247 dwSize = sizeof(szLink);
1248 sprintf(szIndex, "%d", dwIndex);
1249 if (RegQueryValueEx( hkFreelanceSymlinks, szIndex, 0, &dwType, szLink, &dwSize) != ERROR_SUCCESS) {
1250 /* found an unused value */
1252 dwSize = (DWORD)strlen(line) + 1;
1253 RegSetValueEx( hkFreelanceSymlinks, szIndex, 0, dwType, line, dwSize);
1256 int len = (int)strlen(filename);
1257 if ( dwType == REG_SZ && !strncmp(filename, szLink, len) && szLink[len] == ':') {
1258 /* Replace the existing value */
1260 dwSize = (DWORD)strlen(line) + 1;
1261 RegSetValueEx( hkFreelanceSymlinks, szIndex, 0, dwType, line, dwSize);
1266 RegCloseKey(hkFreelanceSymlinks);
1268 lock_ReleaseMutex(&cm_Freelance_Lock);
1270 /* cm_reInitLocalMountPoints(); */
1272 cm_SetFid(fidp, fidp->cell, fidp->volume, ++cm_noLocalMountPoints, 1);
1273 cm_noteLocalMountPointChange();
1277 long cm_FreelanceRemoveSymlink(char *toremove)
1281 char shortname[200];
1283 HKEY hkFreelanceSymlinks = 0;
1284 DWORD dwType, dwSize;
1288 lock_ObtainMutex(&cm_Freelance_Lock);
1290 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
1291 AFSREG_CLT_OPENAFS_SUBKEY "\\Freelance\\Symlinks",
1293 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
1294 &hkFreelanceSymlinks) == ERROR_SUCCESS) {
1296 RegQueryInfoKey( hkFreelanceSymlinks,
1298 NULL, /* lpcClass */
1299 NULL, /* lpReserved */
1300 NULL, /* lpcSubKeys */
1301 NULL, /* lpcMaxSubKeyLen */
1302 NULL, /* lpcMaxClassLen */
1303 &dwSymlinks, /* lpcValues */
1304 NULL, /* lpcMaxValueNameLen */
1305 NULL, /* lpcMaxValueLen */
1306 NULL, /* lpcbSecurityDescriptor */
1307 NULL /* lpftLastWriteTime */
1310 for ( dwIndex = 0; dwIndex < dwSymlinks; dwIndex++ ) {
1311 TCHAR szValueName[16];
1312 DWORD dwValueSize = 16;
1313 dwSize = sizeof(line);
1314 RegEnumValue( hkFreelanceSymlinks, dwIndex, szValueName, &dwValueSize, NULL,
1315 &dwType, line, &dwSize);
1317 cp=strchr(line, ':');
1318 memcpy(shortname, line, cp-line);
1319 shortname[cp-line]=0;
1321 if (!strcmp(shortname, toremove)) {
1322 RegDeleteValue( hkFreelanceSymlinks, szValueName );
1327 RegCloseKey(hkFreelanceSymlinks);
1330 lock_ReleaseMutex(&cm_Freelance_Lock);
1332 cm_noteLocalMountPointChange();
1335 return CM_ERROR_NOSUCHFILE;
1337 #endif /* AFS_FREELANCE_CLIENT */