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();
78 void cm_InitFreelance() {
84 lock_InitializeMutex(&cm_Freelance_Lock, "Freelance Lock");
86 // yj: first we make a call to cm_initLocalMountPoints
87 // to read all the local mount points from an ini file
88 cm_InitLocalMountPoints();
90 // then we make a call to InitFakeRootDir to create
91 // a fake root directory based on the local mount points
96 /* Start the registry monitor */
97 phandle = thrd_Create(NULL, 65536, (ThreadFunc) cm_FreelanceChangeNotifier,
98 NULL, 0, &lpid, "cm_FreelanceChangeNotifier");
99 osi_assert(phandle != NULL);
100 thrd_CloseHandle(phandle);
104 /* yj: Initialization of the fake root directory */
105 /* to be called while holding freelance lock unless during init. */
106 void cm_InitFakeRootDir() {
112 // allocate space for the fake info
113 cm_dirHeader_t fakeDirHeader;
114 cm_dirEntry_t fakeEntry;
115 cm_pageHeader_t fakePageHeader;
117 // i'm going to calculate how much space is needed for
118 // this fake root directory. we have these rules:
119 // 1. there are cm_noLocalMountPoints number of entries
120 // 2. each page is CM_DIR_PAGESIZE in size
121 // 3. the first 13 chunks of the first page are used for
123 // 4. the first chunk of all subsequent pages are used
124 // for page header stuff
125 // 5. a max of CM_DIR_EPP entries are allowed per page
126 // 6. each entry takes 1 or more chunks, depending on
127 // the size of the mount point string, as determined
129 // 7. each chunk is CM_DIR_CHUNKSIZE bytes
131 int CPP = CM_DIR_PAGESIZE / CM_DIR_CHUNKSIZE;
132 int curChunk = 13; // chunks 0 - 12 are used for header stuff
133 // of the first page in the directory
136 int curDirEntryInPage = 0;
140 /* Reserve 2 directory chunks for "." and ".." */
143 while (curDirEntry!=cm_noLocalMountPoints) {
144 sizeOfCurEntry = cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0);
145 if ((curChunk + sizeOfCurEntry >= CPP) ||
146 (curDirEntryInPage + 1 >= CM_DIR_EPP)) {
148 curDirEntryInPage = 0;
151 curChunk += sizeOfCurEntry;
156 dirSize = (curPage+1) * CM_DIR_PAGESIZE;
157 cm_FakeRootDir = malloc(dirSize);
158 cm_fakeDirSize = dirSize;
160 // yj: when we get here, we've figured out how much memory we need and
161 // allocated the appropriate space for it. we now prceed to fill
162 // it up with entries.
165 curDirEntryInPage = 0;
168 // fields in the directory entry that are unused.
170 fakeEntry.length = 0;
172 fakeEntry.fid.unique = htonl(1);
174 // the first page is special, it uses fakeDirHeader instead of fakePageHeader
175 // we fill up the page with dirEntries that belong there and we make changes
176 // to the fakeDirHeader.header.freeBitmap along the way. Then when we're done
177 // filling up the dirEntries in this page, we copy the fakeDirHeader into
178 // the top of the page.
180 // init the freeBitmap array
182 fakeDirHeader.header.freeBitmap[i]=0;
184 fakeDirHeader.header.freeBitmap[0] = 0xff;
185 fakeDirHeader.header.freeBitmap[1] = 0x7f;
188 // we start counting at 13 because the 0th to 12th chunks are used for header
191 // stick the first 2 entries "." and ".." in
192 fakeEntry.fid.unique = htonl(1);
193 fakeEntry.fid.vnode = htonl(1);
194 strcpy(fakeEntry.name, ".");
195 currentPos = cm_FakeRootDir + curPage * CM_DIR_PAGESIZE + curChunk * CM_DIR_CHUNKSIZE;
196 memcpy(currentPos, &fakeEntry, CM_DIR_CHUNKSIZE);
197 curChunk++; curDirEntryInPage++;
198 strcpy(fakeEntry.name, "..");
199 currentPos = cm_FakeRootDir + curPage * CM_DIR_PAGESIZE + curChunk * CM_DIR_CHUNKSIZE;
200 memcpy(currentPos, &fakeEntry, CM_DIR_CHUNKSIZE);
201 curChunk++; curDirEntryInPage++;
203 // keep putting stuff into page 0 if
204 // 1. we're not done with all entries
205 // 2. we have less than CM_DIR_EPP entries in page 0
206 // 3. we're not out of chunks in page 0
208 while( (curDirEntry!=cm_noLocalMountPoints) &&
209 (curDirEntryInPage < CM_DIR_EPP) &&
210 (curChunk + cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0) <= CPP))
213 noChunks = cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0);
214 fakeEntry.fid.vnode = htonl(curDirEntry + 2);
215 currentPos = cm_FakeRootDir + curPage * CM_DIR_PAGESIZE + curChunk * CM_DIR_CHUNKSIZE;
217 memcpy(currentPos, &fakeEntry, CM_DIR_CHUNKSIZE);
218 strcpy(currentPos + 12, (cm_localMountPoints+curDirEntry)->namep);
221 for (i=0; i<noChunks; i++) {
222 t1 = (curChunk + i) / 8;
223 t2 = curChunk + i - (t1*8);
224 fakeDirHeader.header.freeBitmap[t1] |= (1 << t2);
229 // when we get here, we're done with filling in the entries for page 0
230 // copy in the header info
232 memcpy(cm_FakeRootDir, &fakeDirHeader, 13 * CM_DIR_CHUNKSIZE);
236 // ok, page 0's done. Move on to the next page.
237 while (curDirEntry!=cm_noLocalMountPoints) {
239 curChunk = 1; // the zeroth chunk is reserved for page header
240 curDirEntryInPage = 0;
241 for (i=0; i<8; i++) {
242 fakePageHeader.freeBitmap[i]=0;
244 fakePageHeader.freeCount = 0;
245 fakePageHeader.pgcount = 0;
246 fakePageHeader.tag = htons(1234);
248 // while we're on the same page...
249 while ( (curDirEntry!=cm_noLocalMountPoints) &&
250 (curDirEntryInPage < CM_DIR_EPP) &&
251 (curChunk + cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0) <= CPP))
253 // add an entry to this page
255 noChunks = cm_NameEntries((cm_localMountPoints+curDirEntry)->namep, 0);
256 fakeEntry.fid.vnode=htonl(curDirEntry+2);
257 currentPos = cm_FakeRootDir + curPage * CM_DIR_PAGESIZE + curChunk * CM_DIR_CHUNKSIZE;
258 memcpy(currentPos, &fakeEntry, CM_DIR_CHUNKSIZE);
259 strcpy(currentPos + 12, (cm_localMountPoints+curDirEntry)->namep);
262 for (i=0; i<noChunks; i++) {
263 t1 = (curChunk + i) / 8;
264 t2 = curChunk + i - (t1*8);
265 fakePageHeader.freeBitmap[t1] |= (1 << t2);
269 memcpy(cm_FakeRootDir + curPage * CM_DIR_PAGESIZE, &fakePageHeader, sizeof(fakePageHeader));
274 // we know the fakeDir is setup properly, so we claim that we have callback
275 osi_Log0(afsd_logp,"cm_InitFakeRootDir fakeDirCallback=1");
276 cm_fakeDirCallback=1;
278 // when we get here, we've set up everything! done!
281 int cm_FakeRootFid(cm_fid_t *fidp)
283 fidp->cell = AFS_FAKE_ROOT_CELL_ID; /* root cell */
284 fidp->volume = AFS_FAKE_ROOT_VOL_ID; /* root.afs ? */
290 /* called directly from ioctl */
291 /* called while not holding freelance lock */
292 int cm_noteLocalMountPointChange() {
293 lock_ObtainMutex(&cm_Freelance_Lock);
295 cm_localMountPointChangeFlag = 1;
296 lock_ReleaseMutex(&cm_Freelance_Lock);
300 int cm_getLocalMountPointChange() {
301 return cm_localMountPointChangeFlag;
304 int cm_clearLocalMountPointChange() {
305 cm_localMountPointChangeFlag = 0;
309 int cm_reInitLocalMountPoints() {
312 cm_scache_t *scp, **lscpp, *tscp;
314 osi_Log0(afsd_logp,"----- freelance reinitialization starts ----- ");
316 // first we invalidate all the SCPs that were created
317 // for the local mount points
319 osi_Log0(afsd_logp,"Invalidating local mount point scp... ");
321 aFid.cell = AFS_FAKE_ROOT_CELL_ID;
322 aFid.volume=AFS_FAKE_ROOT_VOL_ID;
326 lock_ObtainWrite(&cm_scacheLock);
327 lock_ObtainMutex(&cm_Freelance_Lock); /* always scache then freelance lock */
328 for (i=0; i<cm_noLocalMountPoints; i++) {
329 hash = CM_SCACHE_HASH(&aFid);
330 for (scp=cm_hashTablep[hash]; scp; scp=scp->nextp) {
331 if (scp->fid.volume == aFid.volume &&
332 scp->fid.vnode == aFid.vnode &&
333 scp->fid.unique == aFid.unique
336 // mark the scp to be reused
337 lock_ReleaseWrite(&cm_scacheLock);
338 lock_ObtainMutex(&scp->mx);
339 cm_DiscardSCache(scp);
340 lock_ReleaseMutex(&scp->mx);
341 cm_CallbackNotifyChange(scp);
342 lock_ObtainWrite(&cm_scacheLock);
345 // take the scp out of the hash
346 lscpp = &cm_hashTablep[hash];
347 for (tscp=*lscpp; tscp; lscpp = &tscp->nextp, tscp = *lscpp) {
348 if (tscp == scp) break;
351 scp->flags &= ~CM_SCACHEFLAG_INHASH;
354 aFid.vnode = aFid.vnode + 1;
356 lock_ReleaseWrite(&cm_scacheLock);
357 osi_Log0(afsd_logp,"\tall old scp cleared!");
359 // we must free the memory that was allocated in the prev
360 // cm_InitLocalMountPoints call
361 osi_Log0(afsd_logp,"Removing old localmountpoints... ");
362 free(cm_localMountPoints);
363 osi_Log0(afsd_logp,"\tall old localmountpoints cleared!");
365 // now re-init the localmountpoints
366 osi_Log0(afsd_logp,"Creating new localmountpoints... ");
367 cm_InitLocalMountPoints();
368 osi_Log0(afsd_logp,"\tcreated new set of localmountpoints!");
370 // now we have to free the memory allocated in cm_initfakerootdir
371 osi_Log0(afsd_logp,"Removing old fakedir... ");
372 free(cm_FakeRootDir);
373 osi_Log0(afsd_logp,"\t\told fakedir removed!");
375 // then we re-create that dir
376 osi_Log0(afsd_logp,"Creating new fakedir... ");
377 cm_InitFakeRootDir();
378 osi_Log0(afsd_logp,"\t\tcreated new fakedir!");
380 lock_ReleaseMutex(&cm_Freelance_Lock);
382 osi_Log0(afsd_logp,"----- freelance reinit complete -----");
387 // yj: open up the ini file and read all the local mount
388 // points that are stored there. Part of the initialization
389 // process for the freelance client.
390 /* to be called while holding freelance lock unless during init. */
391 long cm_InitLocalMountPoints() {
396 cm_localMountPoint_t* aLocalMountPoint;
399 char rootCellName[256];
401 HKEY hkFreelance = 0;
402 DWORD dwType, dwSize;
405 FILETIME ftLastWriteTime;
410 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
411 "SOFTWARE\\OpenAFS\\Client\\Freelance",
413 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
414 &hkFreelance) == ERROR_SUCCESS) {
416 RegQueryInfoKey( hkFreelance,
419 NULL, /* lpReserved */
420 NULL, /* lpcSubKeys */
421 NULL, /* lpcMaxSubKeyLen */
422 NULL, /* lpcMaxClassLen */
423 &dwMountPoints, /* lpcValues */
424 NULL, /* lpcMaxValueNameLen */
425 NULL, /* lpcMaxValueLen */
426 NULL, /* lpcbSecurityDescriptor */
427 &ftLastWriteTime /* lpftLastWriteTime */
430 smb_UnixTimeFromLargeSearchTime(&FakeFreelanceModTime, &ftLastWriteTime);
432 if ( dwMountPoints == 0 ) {
433 sprintf(line,"%s#%s:root.cell.\n",rootCellName,rootCellName);
435 dwSize = strlen(line) + 1;
436 RegSetValueEx( hkFreelance, "0", 0, dwType, line, dwSize);
437 sprintf(line,".%s%%%s:root.cell.\n",rootCellName,rootCellName);
438 dwSize = strlen(line) + 1;
439 RegSetValueEx( hkFreelance, "1", 0, dwType, line, dwSize);
443 // get the number of entries there are from the first line
445 cm_noLocalMountPoints = dwMountPoints;
447 // create space to store the local mount points
448 cm_localMountPoints = malloc(sizeof(cm_localMountPoint_t) * cm_noLocalMountPoints);
449 aLocalMountPoint = cm_localMountPoints;
451 // now we read n lines and parse them into local mount points
452 // where n is the number of local mount points there are, as
454 // Each line in the ini file represents 1 local mount point and
455 // is in the format xxx#yyy:zzz, where xxx is the directory
456 // entry name, yyy is the cell name and zzz is the volume name.
457 // #yyy:zzz together make up the mount point.
458 for ( dwIndex = 0 ; dwIndex < dwMountPoints; dwIndex++ ) {
459 TCHAR szValueName[16];
460 DWORD dwValueSize = 16;
461 dwSize = sizeof(line);
462 RegEnumValue( hkFreelance, dwIndex, szValueName, &dwValueSize, NULL,
463 &dwType, line, &dwSize);
465 /* find the trailing dot; null terminate after it */
466 t2 = strrchr(line, '.');
470 // line is not empty, so let's parse it
471 t = strchr(line, '#');
473 t = strchr(line, '%');
474 // make sure that there is a '#' or '%' separator in the line
476 afsi_log("error occurred while parsing entry in %s: no # or %% separator in line %d", AFS_FREELANCE_INI, dwIndex);
477 fprintf(stderr, "error occurred while parsing entry in afs_freelance.ini: no # or %% separator in line %d", dwIndex);
478 cm_noLocalMountPoints--;
481 aLocalMountPoint->namep=malloc(t-line+1);
482 strncpy(aLocalMountPoint->namep, line, t-line);
483 aLocalMountPoint->namep[t-line] = '\0';
485 /* copy the mount point string without the trailing dot */
486 aLocalMountPoint->mountPointStringp=malloc(strlen(t));
487 strncpy(aLocalMountPoint->mountPointStringp, t, strlen(t)-1);
488 aLocalMountPoint->mountPointStringp[strlen(t)-1] = '\0';
490 osi_Log2(afsd_logp,"found mount point: name %s, string %s",
491 osi_LogSaveString(afsd_logp,aLocalMountPoint->namep),
492 osi_LogSaveString(afsd_logp,aLocalMountPoint->mountPointStringp));
497 RegCloseKey(hkFreelance);
502 /* What follows is the old code to read freelance mount points
503 * out of a text file modified to copy the data into the registry
505 cm_GetConfigDir(hdir);
506 strcat(hdir, AFS_FREELANCE_INI);
507 // open the ini file for reading
508 fp = fopen(hdir, "r");
510 // if we fail to open the file, create an empty one
512 fp = fopen(hdir, "w");
513 code = cm_GetRootCellName(rootCellName);
516 fprintf(fp,"%s#%s:root.cell.\n",rootCellName,rootCellName);
517 fprintf(fp,".%s%%%s:root.cell.\n",rootCellName,rootCellName);
519 fp = fopen(hdir, "r");
523 return 0; /* success */
527 // we successfully opened the file
528 osi_Log0(afsd_logp,"opened afs_freelance.ini");
531 RegCreateKeyEx( HKEY_LOCAL_MACHINE,
532 "SOFTWARE\\OpenAFS\\Client\\Freelance",
535 REG_OPTION_NON_VOLATILE,
543 // now we read the first line to see how many entries
545 fgets(line, sizeof(line), fp);
547 // if the line is empty at any point when we're reading
548 // we're screwed. report error and return.
550 afsi_log("error occurred while reading afs_freelance.ini");
551 fprintf(stderr, "error occurred while reading afs_freelance.ini");
555 // get the number of entries there are from the first line
557 cm_noLocalMountPoints = atoi(line);
559 // create space to store the local mount points
560 cm_localMountPoints = malloc(sizeof(cm_localMountPoint_t) * cm_noLocalMountPoints);
561 aLocalMountPoint = cm_localMountPoints;
563 // now we read n lines and parse them into local mount points
564 // where n is the number of local mount points there are, as
566 // Each line in the ini file represents 1 local mount point and
567 // is in the format xxx#yyy:zzz, where xxx is the directory
568 // entry name, yyy is the cell name and zzz is the volume name.
569 // #yyy:zzz together make up the mount point.
570 for (i=0; i<cm_noLocalMountPoints; i++) {
571 fgets(line, sizeof(line), fp);
572 // check that the line is not empty
574 afsi_log("error occurred while parsing entry in %s: empty line in line %d", AFS_FREELANCE_INI, i);
575 fprintf(stderr, "error occurred while parsing entry in afs_freelance.ini: empty line in line %d", i);
582 /* we are migrating to the registry */
583 sprintf(szIndex,"%d",dwIndex++);
585 dwSize = strlen(line) + 1;
586 RegSetValueEx( hkFreelance, szIndex, 0, dwType, line, dwSize);
590 // line is not empty, so let's parse it
591 t = strchr(line, '#');
593 t = strchr(line, '%');
594 // make sure that there is a '#' or '%' separator in the line
596 afsi_log("error occurred while parsing entry in %s: no # or %% separator in line %d", AFS_FREELANCE_INI, i);
597 fprintf(stderr, "error occurred while parsing entry in afs_freelance.ini: no # or %% separator in line %d", i);
600 aLocalMountPoint->namep=malloc(t-line+1);
601 memcpy(aLocalMountPoint->namep, line, t-line);
602 *(aLocalMountPoint->namep + (t-line)) = 0;
604 aLocalMountPoint->mountPointStringp=malloc(strlen(line) - (t-line) + 1);
605 memcpy(aLocalMountPoint->mountPointStringp, t, strlen(line)-(t-line)-2);
606 *(aLocalMountPoint->mountPointStringp + (strlen(line)-(t-line)-2)) = 0;
608 osi_Log2(afsd_logp,"found mount point: name %s, string %s",
609 aLocalMountPoint->namep,
610 aLocalMountPoint->mountPointStringp);
617 RegCloseKey(hkFreelance);
624 int cm_getNoLocalMountPoints() {
625 return cm_noLocalMountPoints;
628 cm_localMountPoint_t* cm_getLocalMountPoint(int vnode) {
632 long cm_FreelanceAddMount(char *filename, char *cellname, char *volume, int rw, cm_fid_t *fidp)
641 HKEY hkFreelance = 0;
642 DWORD dwType, dwSize;
647 /* before adding, verify the cell name; if it is not a valid cell,
648 don't add the mount point.
649 allow partial matches as a means of poor man's alias. */
650 /* major performance issue? */
651 osi_Log4(afsd_logp,"Freelance Add Mount request: filename=%s cellname=%s volume=%s %s",
652 osi_LogSaveString(afsd_logp,filename),
653 osi_LogSaveString(afsd_logp,cellname),
654 osi_LogSaveString(afsd_logp,volume),
656 if (cellname[0] == '.') {
657 if (!cm_GetCell_Gen(&cellname[1], fullname, CM_FLAG_CREATE))
660 if (!cm_GetCell_Gen(cellname, fullname, CM_FLAG_CREATE))
664 osi_Log1(afsd_logp,"Freelance Adding Mount for Cell: %s",
665 osi_LogSaveString(afsd_logp,cellname));
667 lock_ObtainMutex(&cm_Freelance_Lock);
670 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
671 "SOFTWARE\\OpenAFS\\Client\\Freelance",
673 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
674 &hkFreelance) == ERROR_SUCCESS) {
676 RegQueryInfoKey( hkFreelance,
679 NULL, /* lpReserved */
680 NULL, /* lpcSubKeys */
681 NULL, /* lpcMaxSubKeyLen */
682 NULL, /* lpcMaxClassLen */
683 &dwMountPoints, /* lpcValues */
684 NULL, /* lpcMaxValueNameLen */
685 NULL, /* lpcMaxValueLen */
686 NULL, /* lpcbSecurityDescriptor */
687 NULL /* lpftLastWriteTime */
691 sprintf(line, "%s%%%s:%s\n", filename, fullname, volume);
693 sprintf(line, "%s#%s:%s\n", filename, fullname, volume);
695 /* If we are adding a new value, there must be an unused name
696 * within the range 0 to dwMountPoints
698 for ( dwIndex = 0; dwIndex <= dwMountPoints; dwIndex++ ) {
700 sprintf(szIndex, "%d", dwIndex);
701 if (RegQueryValueEx( hkFreelance, szIndex, 0, &dwType, NULL, &dwSize) != ERROR_SUCCESS) {
702 /* found an unused value */
704 dwSize = strlen(line) + 1;
705 RegSetValueEx( hkFreelance, szIndex, 0, dwType, line, dwSize);
709 RegCloseKey(hkFreelance);
713 cm_GetConfigDir(hfile);
714 strcat(hfile, AFS_FREELANCE_INI);
715 fp = fopen(hfile, "r+");
717 return CM_ERROR_INVAL;
718 fgets(line, sizeof(line), fp);
721 fseek(fp, 0, SEEK_SET);
722 fprintf(fp, "%d", n);
723 fseek(fp, 0, SEEK_END);
725 fprintf(fp, "%s%%%s:%s\n", filename, fullname, volume);
727 fprintf(fp, "%s#%s:%s\n", filename, fullname, volume);
730 lock_ReleaseMutex(&cm_Freelance_Lock);
732 /* cm_reInitLocalMountPoints(); */
735 fidp->vnode = cm_noLocalMountPoints + 1; /* vnode value of last mt pt */
737 cm_noteLocalMountPointChange();
741 long cm_FreelanceRemoveMount(char *toremove)
747 char hfile[120], hfile2[120];
751 HKEY hkFreelance = 0;
752 DWORD dwType, dwSize;
757 lock_ObtainMutex(&cm_Freelance_Lock);
761 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
762 "SOFTWARE\\OpenAFS\\Client\\Freelance",
764 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
765 &hkFreelance) == ERROR_SUCCESS) {
767 RegQueryInfoKey( hkFreelance,
770 NULL, /* lpReserved */
771 NULL, /* lpcSubKeys */
772 NULL, /* lpcMaxSubKeyLen */
773 NULL, /* lpcMaxClassLen */
774 &dwMountPoints, /* lpcValues */
775 NULL, /* lpcMaxValueNameLen */
776 NULL, /* lpcMaxValueLen */
777 NULL, /* lpcbSecurityDescriptor */
778 NULL /* lpftLastWriteTime */
781 for ( dwIndex = 0; dwIndex < dwMountPoints; dwIndex++ ) {
782 TCHAR szValueName[16];
783 DWORD dwValueSize = 16;
784 dwSize = sizeof(line);
785 RegEnumValue( hkFreelance, dwIndex, szValueName, &dwValueSize, NULL,
786 &dwType, line, &dwSize);
788 cp=strchr(line, '#');
790 cp=strchr(line, '%');
791 memcpy(shortname, line, cp-line);
792 shortname[cp-line]=0;
794 if (!strcmp(shortname, toremove)) {
795 RegDeleteValue( hkFreelance, szValueName );
799 RegCloseKey(hkFreelance);
803 cm_GetConfigDir(hfile);
804 strcat(hfile, AFS_FREELANCE_INI);
805 strcpy(hfile2, hfile);
807 fp1=fopen(hfile, "r+");
809 return CM_ERROR_INVAL;
810 fp2=fopen(hfile2, "w+");
813 return CM_ERROR_INVAL;
816 fgets(line, sizeof(line), fp1);
818 fprintf(fp2, "%d\n", n-1);
820 for (i=0; i<n; i++) {
821 fgets(line, sizeof(line), fp1);
822 cp=strchr(line, '#');
824 cp=strchr(line, '%');
825 memcpy(shortname, line, cp-line);
826 shortname[cp-line]=0;
828 if (strcmp(shortname, toremove)==0) {
839 return CM_ERROR_NOSUCHFILE;
842 rename(hfile2, hfile);
845 lock_ReleaseMutex(&cm_Freelance_Lock);
846 cm_noteLocalMountPointChange();
850 #endif /* AFS_FREELANCE_CLIENT */