2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
11 #include <afsconfig.h>
12 #include <afs/param.h>
24 #include <WINNT\afssw.h>
25 #include <WINNT\afsreg.h>
28 #include <afs/cellconfig.h>
31 #include <afs/afsint.h>
33 static long cm_ParsePair(char *lineBufferp, char *leftp, char *rightp)
42 for(tp = lineBufferp; *tp; tp++) {
51 /* comment or line end */
52 if (tc == '#' || tc == '\r' || tc == '\n')
55 /* square bracket comment -- look for closing delim */
62 if (tc == ' ' || tc == '\t')
70 /* now we have a real character, put it in the appropriate bucket */
79 /* null terminate the strings */
83 return 0; /* and return success */
87 IsWindowsModule(const char * name)
92 /* Do not perform searches for probable Windows modules */
93 for (p = name, i=0; *p; p++) {
97 p = strrchr(name, '.');
99 /* as of 2009-09-04 these are not valid ICANN ccTLDs */
101 (!cm_stricmp_utf8N(p,".dll") ||
102 !cm_stricmp_utf8N(p,".exe") ||
103 !cm_stricmp_utf8N(p,".ini") ||
104 !cm_stricmp_utf8N(p,".db") ||
105 !cm_stricmp_utf8N(p,".drv")))
111 /* search for a cell, and either return an error code if we don't find it,
112 * or return 0 if we do, in which case we also fill in the addresses in
115 * new feature: we can handle abbreviations and are insensitive to case.
116 * If the caller wants the "real" cell name, it puts a non-null pointer in
117 * newCellNamep. Anomaly: if cellNamep is ambiguous, we may modify
118 * newCellNamep but return an error code.
120 * Linked Cells: the CellServDB format permits linked cells
121 * >cell [linked-cell] #Description
123 * newCellNamep and linkedNamep are required to be CELL_MAXNAMELEN in size.
125 long cm_SearchCellFile(char *cellNamep, char *newCellNamep,
126 cm_configProc_t *procp, void *rockp)
128 return cm_SearchCellFileEx(cellNamep, newCellNamep, NULL, procp, rockp);
131 long cm_SearchCellFileEx(char *cellNamep, char *newCellNamep,
133 cm_configProc_t *procp, void *rockp)
135 char wdir[MAX_PATH]="";
136 FILE *tfilep = NULL, *bestp, *tempp;
138 char lineBuffer[257];
141 struct sockaddr_in vlSockAddr;
145 int tracking = 1, partial = 0;
148 if ( IsWindowsModule(cellNamep) )
151 cm_GetCellServDB(wdir, sizeof(wdir));
153 tfilep = fopen(wdir, "r");
158 bestp = fopen(wdir, "r");
160 #ifdef CELLSERV_DEBUG
161 osi_Log2(afsd_logp,"cm_searchfile fopen handle[%p], wdir[%s]", bestp,
162 osi_LogSaveString(afsd_logp,wdir));
164 /* have we seen the cell line for the guy we're looking for? */
167 tp = fgets(lineBuffer, sizeof(lineBuffer), tfilep);
169 (void) fgets(lineBuffer, sizeof(lineBuffer), bestp);
175 * found partial match earlier;
188 return (foundCell? 0 : -3);
193 /* turn trailing cr or lf into null */
194 tp = strrchr(lineBuffer, '\r');
196 tp = strrchr(lineBuffer, '\n');
199 /* skip blank lines */
200 if (lineBuffer[0] == 0) continue;
204 * >[cell] [linked-cell] #[Description]
205 * where linked-cell and Description are optional
207 if (lineBuffer[0] == '>') {
211 return(foundCell ? 0 : -6);
215 * terminate the cellname at the first white space
216 * leaving 'tp' pointing to the next string if any
218 for (tp = &lineBuffer[1]; tp && !isspace(*tp); tp++);
221 for (tp++ ;tp && isspace(*tp); tp++);
224 for (; tp && !isspace(*tp); tp++);
230 /* now see if this is the right cell */
231 if (stricmp(lineBuffer+1, cellNamep) == 0) {
232 /* found the cell we're looking for */
234 if (FAILED(StringCchCopy(newCellNamep, CELL_MAXNAMELEN, lineBuffer+1))) {
239 strlwr(newCellNamep);
242 if (FAILED(StringCchCopy(linkedNamep, CELL_MAXNAMELEN, linkp ? linkp : ""))) {
251 #ifdef CELLSERV_DEBUG
252 osi_Log2(afsd_logp, "cm_searchfile is cell inRightCell[%p], linebuffer[%s]",
253 inRightCell, osi_LogSaveString(afsd_logp,lineBuffer));
256 else if (cm_stricmp_utf8(lineBuffer+1, cellNamep) == 0) {
258 if (partial) { /* ambiguous */
264 if (FAILED(StringCchCopy(newCellNamep, CELL_MAXNAMELEN, lineBuffer+1))) {
269 strlwr(newCellNamep);
272 if (FAILED(StringCchCopy(linkedNamep, CELL_MAXNAMELEN, linkp ? linkp : ""))) {
283 else inRightCell = 0;
286 valuep = strchr(lineBuffer, '#');
287 if (valuep == NULL) {
292 valuep++; /* skip the "#" */
294 valuep += strspn(valuep, " \t"); /* skip SP & TAB */
296 * strip spaces and tabs in the end. They should not be there according to CellServDB format
297 * so do this just in case
299 if(FAILED(StringCchLength(valuep, sizeof(lineBuffer), &len))) {
305 while(isspace(valuep[len]))
306 valuep[len--] = '\0';
307 while(isspace(*valuep))
315 isClone = (lineBuffer[0] == '[');
317 /* copy just the first word and ignore trailing white space */
318 for ( i=0; valuep[i] && !isspace(valuep[i]) && i<sizeof(hostname); i++)
319 hostname[i] = valuep[i];
322 /* add the server to the VLDB list */
324 thp = gethostbyname(hostname);
325 #ifdef CELLSERV_DEBUG
326 osi_Log3(afsd_logp,"cm_searchfile inRightCell thp[%p], valuep[%s], WSAGetLastError[%d]",
327 thp, osi_LogSaveString(afsd_logp,hostname), WSAGetLastError());
331 for (i=0 ; thp->h_addr_list[i]; i++) {
332 if (thp->h_addrtype != AF_INET)
334 memcpy(&vlSockAddr.sin_addr.s_addr, thp->h_addr_list[i],
336 vlSockAddr.sin_port = htons(7003);
337 vlSockAddr.sin_family = AF_INET;
338 /* sin_port supplied by connection code */
340 (*procp)(rockp, &vlSockAddr, hostname, 0);
343 /* if we didn't find a valid address, force the use of the specified one */
349 unsigned int c1, c2, c3, c4;
351 /* Since there is no gethostbyname() data
352 * available we will read the IP address
353 * stored in the CellServDB file
356 code = sscanf(lineBuffer, "[%u.%u.%u.%u]",
359 code = sscanf(lineBuffer, " %u.%u.%u.%u",
361 if (code == 4 && c1<256 && c2<256 && c3<256 && c4<256) {
362 tp = (unsigned char *) &ip_addr;
367 memcpy(&vlSockAddr.sin_addr.s_addr, &ip_addr,
369 vlSockAddr.sin_port = htons(7003);
370 vlSockAddr.sin_family = AF_INET;
371 /* sin_port supplied by connection code */
373 (*procp)(rockp, &vlSockAddr, hostname, 0);
379 } /* while loop processing all lines */
381 /* if for some unknown reason cell is not found, return negative code (-11) ??? */
382 return (foundCell) ? 0 : -11;
386 cm_EnumerateCellFile(afs_uint32 client, cm_enumCellProc_t *procp, void *rockp)
388 char wdir[MAX_PATH]="";
391 char lineBuffer[257];
396 cm_GetCellServDB(wdir, sizeof(wdir));
398 tfilep = fopen(wdir, "r");
403 #ifdef CELLSERV_DEBUG
404 osi_Log2(afsd_logp,"cm_enumfile fopen handle[%p], wdir[%s]", tfilep,
405 osi_LogSaveString(afsd_logp,wdir));
408 tp = fgets(lineBuffer, sizeof(lineBuffer), tfilep);
409 if (tp == NULL && feof(tfilep)) {
415 /* turn trailing cr or lf into null */
416 tp = strrchr(lineBuffer, '\r');
418 tp = strrchr(lineBuffer, '\n');
421 /* skip blank lines */
422 if (lineBuffer[0] == 0)
427 * >[cell] [linked-cell] #[Description]
428 * where linked-cell and Description are optional
429 * but we are only going to use the initial cell name
431 if (lineBuffer[0] == '>') {
433 * terminate the cellname at the first white space
434 * leaving 'tp' pointing to the next string if any
436 for (tp = &lineBuffer[1]; tp && !isspace(*tp); tp++);
440 /* Now process the cell */
441 (*procp)(rockp, &lineBuffer[1]);
443 } /* while loop processing all lines */
449 * The CellServDB registry schema is as follows:
451 * HKLM\SOFTWARE\OpenAFS\Client\CellServDB\[cellname]\
452 * "LinkedCell" REG_SZ "[cellname]"
453 * "Description" REG_SZ "[comment]"
454 * "ForceDNS" DWORD {0,1}
456 * HKLM\SOFTWARE\OpenAFS\Client\CellServDB\[cellname]\[servername]\
457 * "HostName" REG_SZ "[hostname]"
458 * "IPv4Address" REG_SZ "[address]"
459 * "IPv6Address" REG_SZ "[address]" <future>
460 * "Comment" REG_SZ "[comment]"
461 * "Rank" DWORD "0..65535"
462 * "Clone" DWORD "{0,1}"
463 * "vlserver" DWORD "7003" <future>
464 * "ptserver" DWORD "7002" <future>
466 * ForceDNS is implied non-zero if there are no [servername]
467 * keys under the [cellname] key. Otherwise, ForceDNS is zero.
468 * If [servername] keys are specified and none of them evaluate
469 * to a valid server configuration, the return code is success.
470 * This prevents failover to the CellServDB file or DNS.
472 long cm_SearchCellRegistry(afs_uint32 client,
473 char *cellNamep, char *newCellNamep,
475 cm_configProc_t *procp, void *rockp)
477 HKEY hkCellServDB = 0, hkCellName = 0, hkServerName = 0;
478 DWORD dwType, dwSize;
479 DWORD dwCells, dwServers, dwForceDNS;
480 DWORD dwIndex, dwRank, dwPort;
481 unsigned short ipRank;
482 unsigned short vlPort;
484 FILETIME ftLastWriteTime;
485 char szCellName[CELL_MAXNAMELEN];
486 char szServerName[MAXHOSTCHARS];
487 char szHostName[MAXHOSTCHARS];
490 struct sockaddr_in vlSockAddr;
494 if ( IsWindowsModule(cellNamep) )
497 /* No Server CellServDB list (yet) */
499 return CM_ERROR_NOSUCHCELL;
501 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
502 AFSREG_CLT_OPENAFS_SUBKEY "\\CellServDB",
504 KEY_READ|KEY_QUERY_VALUE,
505 &hkCellServDB) != ERROR_SUCCESS)
506 return CM_ERROR_NOSUCHCELL;
508 if (RegOpenKeyEx( hkCellServDB,
511 KEY_READ|KEY_QUERY_VALUE,
512 &hkCellName) != ERROR_SUCCESS) {
515 /* We did not find an exact match. Much search for partial matches. */
517 code = RegQueryInfoKey( hkCellServDB,
520 NULL, /* lpReserved */
521 &dwCells, /* lpcSubKeys */
522 NULL, /* lpcMaxSubKeyLen */
523 NULL, /* lpcMaxClassLen */
524 NULL, /* lpcValues */
525 NULL, /* lpcMaxValueNameLen */
526 NULL, /* lpcMaxValueLen */
527 NULL, /* lpcbSecurityDescriptor */
528 &ftLastWriteTime /* lpftLastWriteTime */
530 if (code != ERROR_SUCCESS)
534 * We search the entire list to ensure that there is only
535 * one prefix match. If there is more than one, we return none.
537 for ( dwIndex = 0; dwIndex < dwCells; dwIndex++ ) {
538 dwSize = CELL_MAXNAMELEN;
539 code = RegEnumKeyEx( hkCellServDB, dwIndex, szCellName, &dwSize, NULL,
540 NULL, NULL, &ftLastWriteTime);
541 if (code != ERROR_SUCCESS)
543 szCellName[CELL_MAXNAMELEN-1] = '\0';
546 /* if not a prefix match, try the next key */
547 if (FAILED(StringCchLength(cellNamep, CELL_MAXNAMELEN, &len)))
550 if (strncmp(cellNamep, szCellName, len))
553 /* If we have a prefix match and we already found another
554 * match, return neither */
557 RegCloseKey( hkCellName);
561 if (RegOpenKeyEx( hkCellServDB,
564 KEY_READ|KEY_QUERY_VALUE,
565 &hkCellName) != ERROR_SUCCESS)
569 if (FAILED(StringCchCopy(newCellNamep, CELL_MAXNAMELEN, cellNamep)))
576 RegCloseKey(hkCellServDB);
577 return CM_ERROR_NOSUCHCELL;
579 } else if (newCellNamep) {
580 strncpy(newCellNamep, cellNamep, CELL_MAXNAMELEN);
581 newCellNamep[CELL_MAXNAMELEN-1] = '\0';
582 strlwr(newCellNamep);
586 dwSize = CELL_MAXNAMELEN;
587 code = RegQueryValueEx(hkCellName, "LinkedCell", NULL, &dwType,
588 (BYTE *) linkedNamep, &dwSize);
589 if (code == ERROR_SUCCESS && dwType == REG_SZ) {
590 linkedNamep[CELL_MAXNAMELEN-1] = '\0';
593 linkedNamep[0] = '\0';
597 /* Check to see if DNS lookups are required */
598 dwSize = sizeof(DWORD);
599 code = RegQueryValueEx(hkCellName, "ForceDNS", NULL, &dwType,
600 (BYTE *) &dwForceDNS, &dwSize);
601 if (code == ERROR_SUCCESS && dwType == REG_DWORD) {
609 * Using the defined server list. Enumerate and populate
610 * the server list for the cell.
612 code = RegQueryInfoKey( hkCellName,
615 NULL, /* lpReserved */
616 &dwServers, /* lpcSubKeys */
617 NULL, /* lpcMaxSubKeyLen */
618 NULL, /* lpcMaxClassLen */
619 NULL, /* lpcValues */
620 NULL, /* lpcMaxValueNameLen */
621 NULL, /* lpcMaxValueLen */
622 NULL, /* lpcbSecurityDescriptor */
623 &ftLastWriteTime /* lpftLastWriteTime */
625 if (code != ERROR_SUCCESS)
628 for ( dwIndex = 0; dwIndex < dwServers; dwIndex++ ) {
629 dwSize = MAXHOSTCHARS;
630 code = RegEnumKeyEx( hkCellName, dwIndex, szServerName, &dwSize, NULL,
631 NULL, NULL, &ftLastWriteTime);
632 if (code != ERROR_SUCCESS)
635 szServerName[MAXHOSTCHARS-1] = '\0';
636 if (RegOpenKeyEx( hkCellName,
639 KEY_READ|KEY_QUERY_VALUE,
640 &hkServerName) != ERROR_SUCCESS)
643 /* We have a handle to a valid server key. Now we need
644 * to add the server to the cell */
646 /* First, see if there is an alternate hostname specified */
647 dwSize = MAXHOSTCHARS;
648 code = RegQueryValueEx(hkServerName, "HostName", NULL, &dwType,
649 (BYTE *) szHostName, &dwSize);
650 if (code == ERROR_SUCCESS && dwType == REG_SZ) {
651 szHostName[MAXHOSTCHARS-1] = '\0';
658 dwSize = sizeof(DWORD);
659 code = RegQueryValueEx(hkServerName, "Rank", NULL, &dwType,
660 (BYTE *) &dwRank, &dwSize);
661 if (code == ERROR_SUCCESS && dwType == REG_DWORD) {
662 ipRank = (unsigned short)(dwRank <= 65535 ? dwRank : 65535);
667 dwSize = sizeof(szAddr);
668 code = RegQueryValueEx(hkServerName, "IPv4Address", NULL, &dwType,
669 (BYTE *) szAddr, &dwSize);
670 if (code == ERROR_SUCCESS && dwType == REG_SZ) {
676 dwSize = sizeof(DWORD);
677 code = RegQueryValueEx(hkServerName, "vlserver", NULL, &dwType,
678 (BYTE *) &dwPort, &dwSize);
679 if (code == ERROR_SUCCESS && dwType == REG_DWORD) {
680 vlPort = htons((unsigned short)dwPort);
682 vlPort = htons(7003);
686 thp = gethostbyname(s);
688 memcpy(&vlSockAddr.sin_addr.s_addr, thp->h_addr, sizeof(long));
689 vlSockAddr.sin_port = htons(7003);
690 vlSockAddr.sin_family = AF_INET;
691 /* sin_port supplied by connection code */
693 (*procp)(rockp, &vlSockAddr, s, ipRank);
694 } else if (szAddr[0]) {
696 unsigned int c1, c2, c3, c4;
698 /* Since there is no gethostbyname() data
699 * available we will read the IP address
700 * stored in the CellServDB file
702 code = sscanf(szAddr, " %u.%u.%u.%u",
704 if (code == 4 && c1<256 && c2<256 && c3<256 && c4<256) {
705 unsigned char * tp = (unsigned char *) &ip_addr;
710 memcpy(&vlSockAddr.sin_addr.s_addr, &ip_addr,
712 vlSockAddr.sin_port = vlPort;
713 vlSockAddr.sin_family = AF_INET;
714 /* sin_port supplied by connection code */
716 (*procp)(rockp, &vlSockAddr, s, ipRank);
720 RegCloseKey( hkServerName);
724 RegCloseKey(hkCellName);
725 RegCloseKey(hkCellServDB);
727 return ((dwForceDNS || dwServers == 0) ? CM_ERROR_FORCE_DNS_LOOKUP : 0);
731 * Following the registry schema listed above, cm_AddCellToRegistry
732 * will either create or update the registry configuration data for
733 * the specified cellname.
735 long cm_AddCellToRegistry( char * cellname,
736 char * linked_cellname,
737 unsigned short vlport,
738 afs_uint32 host_count,
742 HKEY hkCellServDB = 0, hkCellName = 0, hkServerName = 0;
743 DWORD dwPort, dwDisposition;
747 if (RegCreateKeyEx( HKEY_LOCAL_MACHINE,
748 AFSREG_CLT_OPENAFS_SUBKEY "\\CellServDB",
751 REG_OPTION_NON_VOLATILE,
752 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
755 &dwDisposition) != ERROR_SUCCESS) {
756 code = CM_ERROR_NOACCESS;
760 /* Perform a recursive deletion of the cellname key */
761 SHDeleteKey( hkCellServDB, cellname);
763 if (RegCreateKeyEx( hkCellServDB,
767 REG_OPTION_NON_VOLATILE,
768 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
771 &dwDisposition) != ERROR_SUCCESS ||
772 (dwDisposition == REG_OPENED_EXISTING_KEY) ) {
773 code = CM_ERROR_NOACCESS;
777 /* If we get here, hkCellName is a handle to an empty key */
779 if (linked_cellname && linked_cellname[0]) {
780 code = RegSetValueEx( hkCellName, "LinkedCell",
782 (BYTE *) linked_cellname, CELL_MAXNAMELEN);
785 if (flags & CM_CELLFLAG_DNS) {
786 DWORD dwForceDNS = 1;
787 code = RegSetValueEx( hkCellName, "ForceDNS",
789 (BYTE *) &dwForceDNS, sizeof(DWORD));
792 for ( i = 0; i < host_count; i++ ) {
793 if (RegCreateKeyEx( hkCellName,
797 REG_OPTION_NON_VOLATILE,
798 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
801 &dwDisposition) != ERROR_SUCCESS ||
802 (dwDisposition == REG_OPENED_EXISTING_KEY)) {
803 code = CM_ERROR_NOACCESS;
807 /* We have a handle to a valid server key. Now we need
808 * to add the server to the cell */
810 /* First, see if there is an alternate hostname specified */
811 code = RegSetValueEx( hkServerName, "HostName",
813 (BYTE *) hostname[i], (DWORD)strlen(hostname[i]) + 1);
817 code = RegSetValueEx( hkServerName, "vlserver",
819 (BYTE *) &dwPort, (DWORD)sizeof(DWORD));
821 RegCloseKey( hkServerName);
827 RegCloseKey(hkServerName);
829 RegCloseKey(hkCellName);
831 RegCloseKey(hkCellServDB);
836 long cm_EnumerateCellRegistry(afs_uint32 client, cm_enumCellProc_t *procp, void *rockp)
838 HKEY hkCellServDB = 0;
843 FILETIME ftLastWriteTime;
844 char szCellName[CELL_MAXNAMELEN];
846 /* No server CellServDB in the registry. */
847 if (!client || procp == NULL)
850 if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
851 AFSREG_CLT_OPENAFS_SUBKEY "\\CellServDB",
853 KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
854 &hkCellServDB) != ERROR_SUCCESS)
857 code = RegQueryInfoKey( hkCellServDB,
860 NULL, /* lpReserved */
861 &dwCells, /* lpcSubKeys */
862 NULL, /* lpcMaxSubKeyLen */
863 NULL, /* lpcMaxClassLen */
864 NULL, /* lpcValues */
865 NULL, /* lpcMaxValueNameLen */
866 NULL, /* lpcMaxValueLen */
867 NULL, /* lpcbSecurityDescriptor */
868 &ftLastWriteTime /* lpftLastWriteTime */
870 if (code != ERROR_SUCCESS)
874 * Enumerate each Cell and
876 for ( dwIndex = 0; dwIndex < dwCells; dwIndex++ ) {
877 dwSize = CELL_MAXNAMELEN;
878 code = RegEnumKeyEx( hkCellServDB, dwIndex, szCellName, &dwSize, NULL,
879 NULL, NULL, &ftLastWriteTime);
880 if (code != ERROR_SUCCESS)
882 szCellName[CELL_MAXNAMELEN-1] = '\0';
885 (*procp)(rockp, szCellName);
888 RegCloseKey(hkCellServDB);
892 /* newCellNamep is required to be CELL_MAXNAMELEN in size */
893 long cm_SearchCellByDNS(char *cellNamep, char *newCellNamep, int *ttl,
894 cm_configProc_t *procp, void *rockp)
897 int cellHostAddrs[AFSMAXCELLHOSTS];
898 char cellHostNames[AFSMAXCELLHOSTS][MAXHOSTCHARS];
899 unsigned short ipRanks[AFSMAXCELLHOSTS];
900 unsigned short ports[AFSMAXCELLHOSTS]; /* network byte order */
903 struct sockaddr_in vlSockAddr;
905 #ifdef CELLSERV_DEBUG
906 osi_Log1(afsd_logp,"SearchCellDNS-Doing search for [%s]", osi_LogSaveString(afsd_logp,cellNamep));
909 * Do not perform a DNS lookup if the name is
910 * either a well-known Windows DLL or directory,
911 * or if the name does not contain a top-level
912 * domain, or if the file prefix is the afs pioctl
915 if ( IsWindowsModule(cellNamep) ||
916 cm_FsStrChr(cellNamep, '.') == NULL ||
917 strncasecmp(cellNamep, CM_IOCTL_FILENAME_NOSLASH, sizeof(CM_IOCTL_FILENAME_NOSLASH)-1) == 0)
920 rc = getAFSServer("afs3-vlserver", "udp", cellNamep, htons(7003),
921 cellHostAddrs, cellHostNames, ports, ipRanks, &numServers, ttl);
922 if (rc == 0 && numServers > 0) { /* found the cell */
923 for (i = 0; i < numServers; i++) {
924 memcpy(&vlSockAddr.sin_addr.s_addr, &cellHostAddrs[i],
926 vlSockAddr.sin_port = ports[i];
927 vlSockAddr.sin_family = AF_INET;
929 (*procp)(rockp, &vlSockAddr, cellHostNames[i], ipRanks[i]);
932 if(FAILED(StringCchCopy(newCellNamep, CELL_MAXNAMELEN, cellNamep)))
934 strlwr(newCellNamep);
936 return 0; /* found cell */
939 return -1; /* not found */
942 /* use cm_GetConfigDir() plus AFS_CELLSERVDB to
943 * generate the fully qualified name of the CellServDB
946 long cm_GetCellServDB(char *cellNamep, afs_uint32 len)
950 cm_GetConfigDir(cellNamep, len);
952 /* add trailing backslash, if required */
953 if (FAILED(StringCchLength(cellNamep, len, &tlen)))
957 if (cellNamep[tlen-1] != '\\') {
958 if (FAILED(StringCchCat(cellNamep, len, "\\")))
962 if (FAILED(StringCchCat(cellNamep, len, AFS_CELLSERVDB)))
968 /* look up the root cell's name in the Registry
969 * Input buffer must be at least CELL_MAXNAMELEN
970 * in size. (Defined in cm_cell.h)
972 long cm_GetRootCellName(char *cellNamep)
974 DWORD code, dummyLen;
977 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
978 0, KEY_QUERY_VALUE, &parmKey);
979 if (code != ERROR_SUCCESS)
982 dummyLen = CELL_MAXNAMELEN;
983 code = RegQueryValueEx(parmKey, "Cell", NULL, NULL,
984 cellNamep, &dummyLen);
985 RegCloseKey (parmKey);
986 if (code != ERROR_SUCCESS || cellNamep[0] == 0)
992 cm_configFile_t *cm_CommonOpen(char *namep, char *rwp)
994 char wdir[MAX_PATH]="";
997 cm_GetConfigDir(wdir, sizeof(wdir));
999 if (FAILED(StringCchCat(wdir, MAX_PATH, namep)))
1002 tfilep = fopen(wdir, rwp);
1004 return ((cm_configFile_t *) tfilep);
1007 long cm_WriteConfigString(char *labelp, char *valuep)
1009 DWORD code, dummyDisp;
1013 code = RegCreateKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
1014 0, "container", 0, KEY_SET_VALUE, NULL,
1015 &parmKey, &dummyDisp);
1016 if (code != ERROR_SUCCESS)
1019 if (FAILED(StringCchLength(valuep, CM_CONFIGDEFAULT_CELLS, &len)))
1022 code = RegSetValueEx(parmKey, labelp, 0, REG_SZ, valuep, (DWORD)(len + 1));
1023 RegCloseKey (parmKey);
1024 if (code != ERROR_SUCCESS)
1030 long cm_WriteConfigInt(char *labelp, long value)
1032 DWORD code, dummyDisp;
1035 code = RegCreateKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
1036 0, "container", 0, KEY_SET_VALUE, NULL,
1037 &parmKey, &dummyDisp);
1038 if (code != ERROR_SUCCESS)
1041 code = RegSetValueEx(parmKey, labelp, 0, REG_DWORD,
1042 (LPBYTE)&value, sizeof(value));
1043 RegCloseKey (parmKey);
1044 if (code != ERROR_SUCCESS)
1050 cm_configFile_t *cm_OpenCellFile(void)
1052 cm_configFile_t *cfp;
1054 cfp = cm_CommonOpen(AFS_CELLSERVDB ".new", "w");
1058 long cm_AppendPrunedCellList(cm_configFile_t *ofp, char *cellNamep)
1060 cm_configFile_t *tfilep; /* input file */
1062 char lineBuffer[256];
1067 tfilep = cm_CommonOpen(AFS_CELLSERVDB, "r");
1073 /* have we seen the cell line for the guy we're looking for? */
1076 tp = fgets(lineBuffer, sizeof(lineBuffer), (FILE *)tfilep);
1078 if (feof((FILE *)tfilep)) {
1080 fclose((FILE *)tfilep);
1085 /* turn trailing cr or lf into null */
1086 tp = strchr(lineBuffer, '\r');
1088 tp = strchr(lineBuffer, '\n');
1091 /* skip blank lines */
1092 if (lineBuffer[0] == 0) {
1093 fprintf((FILE *)ofp, "%s\n", lineBuffer);
1097 if (lineBuffer[0] == '>') {
1098 /* trim off at white space or '#' chars */
1099 tp = strchr(lineBuffer, ' ');
1101 tp = strchr(lineBuffer, '\t');
1103 tp = strchr(lineBuffer, '#');
1106 /* now see if this is the right cell */
1107 if (strcmp(lineBuffer+1, cellNamep) == 0) {
1108 /* found the cell we're looking for */
1113 fprintf((FILE *)ofp, "%s\n", lineBuffer);
1117 valuep = strchr(lineBuffer, '#');
1118 if (valuep == NULL) return -2;
1119 valuep++; /* skip the "#" */
1121 fprintf((FILE *)ofp, "%s\n", lineBuffer);
1124 } /* while loop processing all lines */
1127 long cm_AppendNewCell(cm_configFile_t *filep, char *cellNamep)
1129 fprintf((FILE *)filep, ">%s\n", cellNamep);
1133 long cm_AppendNewCellLine(cm_configFile_t *filep, char *linep)
1135 fprintf((FILE *)filep, "%s\n", linep);
1139 long cm_CloseCellFile(cm_configFile_t *filep)
1141 char wdir[MAX_PATH];
1142 char sdir[MAX_PATH];
1144 long closeCode = fclose((FILE *)filep);
1146 cm_GetConfigDir(wdir, sizeof(wdir));
1147 if (FAILED(StringCchCopy(sdir, sizeof(sdir), wdir)))
1150 if (closeCode != 0) {
1151 /* something went wrong, preserve original database */
1152 if (FAILED(StringCchCat(wdir, sizeof(wdir), AFS_CELLSERVDB ".new")))
1158 if (FAILED(StringCchCat(wdir, sizeof(wdir), AFS_CELLSERVDB)))
1160 if (FAILED(StringCchCat(sdir, sizeof(sdir), AFS_CELLSERVDB ".new"))) /* new file */
1163 unlink(sdir); /* delete old file */
1165 code = rename(sdir, wdir); /* do the rename */
1173 void cm_GetConfigDir(char *dir, afs_uint32 len)
1177 if (!afssw_GetClientCellServDBDir(&dirp)) {
1178 if (FAILED(StringCchCopy(dir, len, dirp)))