/* Prototypes */
static afs_int32 afsconf_FindService(register const char *aname);
-static int TrimLine(char *abuffer);
+static int TrimLine(char *abuffer, int abufsize);
#ifdef AFS_NT40_ENV
static int IsClientConfigDirectory(const char *path);
static int GetCellNT(struct afsconf_dir *adir);
* CellServDB changes.
*/
+#if defined(AFS_SUN5_ENV) && !defined(__sparcv9)
+/* Solaris through 10 in 32 bit mode will return EMFILE if fopen can't
+ get an fd <= 255. We allow the fileserver to claim more fds than that.
+ This has always been a problem since pr_Initialize would have the same
+ issue, but hpr_Initialize makes it more likely that we would see this.
+ Work around it. This is not generic. It's coded with the needs of
+ afsconf_* in mind only.
+
+ http://www.opensolaris.org/os/community/onnv/flag-days/pages/2006042001/
+*/
+
+#define BUFFER 4096
+
+struct afsconf_iobuffer {
+ int _file;
+ char *buffer;
+ char *ptr;
+ char *endptr;
+};
+
+typedef struct afsconf_iobuffer afsconf_FILE;
+
+static afsconf_FILE *
+afsconf_fopen(const char *fname, const char *fmode)
+{
+ int fd;
+ afsconf_FILE *iop;
+
+ if ((fd = open(fname, O_RDONLY)) == -1) {
+ return NULL;
+ }
+
+ iop = malloc(sizeof(struct afsconf_iobuffer));
+ if (iop == NULL) {
+ (void) close(fd);
+ errno = ENOMEM;
+ return NULL;
+ }
+ iop->_file = fd;
+ iop->buffer = malloc(BUFFER);
+ if (iop->buffer == NULL) {
+ (void) close(fd);
+ free((void *) iop);
+ errno = ENOMEM;
+ return NULL;
+ }
+ iop->ptr = iop->buffer;
+ iop->endptr = iop->buffer;
+ return iop;
+}
+
+static int
+afsconf_fclose(afsconf_FILE *iop)
+{
+ if (iop == NULL) {
+ return 0;
+ }
+ close(iop->_file);
+ free((void *)iop->buffer);
+ free((void *)iop);
+ return 0;
+}
+
+static char *
+afsconf_fgets(char *s, int n, afsconf_FILE *iop)
+{
+ char *p;
+
+ p = s;
+ for (;;) {
+ char c;
+
+ if (iop->ptr == iop->endptr) {
+ ssize_t len;
+
+ if ((len = read(iop->_file, (void *)iop->buffer, BUFFER)) == -1) {
+ return NULL;
+ }
+ if (len == 0) {
+ *p = 0;
+ if (s == p) {
+ return NULL;
+ }
+ return s;
+ }
+ iop->ptr = iop->buffer;
+ iop->endptr = iop->buffer + len;
+ }
+ c = *iop->ptr++;
+ *p++ = c;
+ if ((p - s) == (n - 1)) {
+ *p = 0;
+ return s;
+ }
+ if (c == '\n') {
+ *p = 0;
+ return s;
+ }
+ }
+}
+#define fopen afsconf_fopen
+#define fclose afsconf_fclose
+#define fgets afsconf_fgets
+#else
+#define afsconf_FILE FILE
+#endif /* AFS_SUN5_ENV && ! __sparcv9 */
+
/* return port number in network byte order in the low 16 bits of a long; return -1 if not found */
static afs_int32
afsconf_FindService(register const char *aname)
}
static int
-TrimLine(char *abuffer)
+TrimLine(char *abuffer, int abufsize)
{
char tbuffer[256];
register char *tp;
break;
tp++;
}
- strcpy(tbuffer, tp);
- strcpy(abuffer, tbuffer);
+ strlcpy(tbuffer, tp, sizeof tbuffer);
+ strlcpy(abuffer, tbuffer, abufsize);
return 0;
}
} else {
int len;
strncpy(tbuffer, adir->name, sizeof(tbuffer));
- len = strlen(tbuffer);
+ len = (int)strlen(tbuffer);
if (tbuffer[len - 1] != '\\' && tbuffer[len - 1] != '/') {
strncat(tbuffer, "\\", sizeof(tbuffer));
}
AFSDIR_CELLSERVDB_FILE_NTCLIENT, NULL);
free(p);
} else {
- int len = strlen(tbuffer);
+ int len = (int)strlen(tbuffer);
if (tbuffer[len - 1] != '\\' && tbuffer[len - 1] != '/') {
strncat(tbuffer, "\\", sizeof(tbuffer));
}
/* zero structure and fill in name; rest is done by internal routine */
tdir = (struct afsconf_dir *)malloc(sizeof(struct afsconf_dir));
memset(tdir, 0, sizeof(struct afsconf_dir));
- tdir->name = (char *)malloc(strlen(adir) + 1);
- strcpy(tdir->name, adir);
+ tdir->name = strdup(adir);
code = afsconf_OpenInternal(tdir, 0, 0);
if (code) {
if (!(afsconf_path = getenv("AFSCONF"))) {
/* The "AFSCONF" environment (or contents of "/.AFSCONF") will be typically set to something like "/afs/<cell>/common/etc" where, by convention, the default files for "ThisCell" and "CellServDB" will reside; note that a major drawback is that a given afs client on that cell may NOT contain the same contents... */
char *home_dir;
- FILE *fp;
+ afsconf_FILE *fp;
size_t len;
if (!(home_dir = getenv("HOME"))) {
}
afsconf_path = afs_confdir;
}
- tdir->name = (char *)malloc(strlen(afsconf_path) + 1);
- strcpy(tdir->name, afsconf_path);
+ tdir->name = strdup(afsconf_path);
code = afsconf_OpenInternal(tdir, 0, 0);
if (code) {
free(tdir->name);
return tdir;
}
-
static int
GetCellUnix(struct afsconf_dir *adir)
{
- int rc;
+ char *rc;
char tbuffer[256];
- FILE *tf;
-
+ char *start, *p;
+ afsconf_FILE *fp;
+
strcompose(tbuffer, 256, adir->name, "/", AFSDIR_THISCELL_FILE, NULL);
- tf = fopen(tbuffer, "r");
- if (tf) {
- /* FIXME: buffer overflow waiting to happen */
- rc = fscanf(tf, "%s", tbuffer);
- if (rc == 1) {
- adir->cellName = (char *)malloc(strlen(tbuffer) + 1);
- strcpy(adir->cellName, tbuffer);
- }
- fclose(tf);
- } else {
+ fp = fopen(tbuffer, "r");
+ if (fp == 0) {
return -1;
}
+ rc = fgets(tbuffer, 256, fp);
+ fclose(fp);
+ if (rc == NULL)
+ return -1;
+
+ start = tbuffer;
+ while (*start != '\0' && isspace(*start))
+ start++;
+ p = start;
+ while (*p != '\0' && !isspace(*p))
+ p++;
+ *p = '\0';
+ if (*start == '\0')
+ return -1;
+
+ adir->cellName = strdup(start);
return 0;
}
afsconf_OpenInternal(register struct afsconf_dir *adir, char *cell,
char clones[])
{
- FILE *tf;
+ afsconf_FILE *tf;
register char *tp, *bp;
register struct afsconf_entry *curEntry;
struct afsconf_aliasentry *curAlias;
char tbuffer[256], tbuf1[256];
struct stat tstat;
- /* figure out the cell name */
+ /* figure out the local cell name */
#ifdef AFS_NT40_ENV
i = GetCellNT(adir);
#else
} else {
int len;
strncpy(tbuffer, adir->name, sizeof(tbuffer));
- len = strlen(tbuffer);
+ len = (int)strlen(tbuffer);
if (tbuffer[len - 1] != '\\' && tbuffer[len - 1] != '/') {
strncat(tbuffer, "\\", sizeof(tbuffer));
}
adir->timeRead = 0;
}
- strcpy(tbuf1, tbuffer);
+ strlcpy(tbuf1, tbuffer, sizeof tbuf1);
tf = fopen(tbuffer, "r");
if (!tf) {
return -1;
tp = fgets(tbuffer, sizeof(tbuffer), tf);
if (!tp)
break;
- TrimLine(tbuffer); /* remove white space */
+ TrimLine(tbuffer, sizeof tbuffer); /* remove white space */
if (tbuffer[0] == 0 || tbuffer[0] == '\n')
continue; /* empty line */
if (tbuffer[0] == '>') {
free(curEntry);
return -1;
}
- if (linkedcell[0] != '\0') {
- curEntry->cellInfo.linkedCell =
- (char *)malloc(strlen(linkedcell) + 1);
- strcpy(curEntry->cellInfo.linkedCell, linkedcell);
- }
+ if (linkedcell[0] != '\0')
+ curEntry->cellInfo.linkedCell = strdup(linkedcell);
} else {
/* new host in the current cell */
if (!curEntry) {
tp = fgets(tbuffer, sizeof(tbuffer), tf);
if (!tp)
break;
- TrimLine(tbuffer); /* remove white space */
+ TrimLine(tbuffer, sizeof tbuffer); /* remove white space */
if (tbuffer[0] == '\0' || tbuffer[0] == '\n' || tbuffer[0] == '#')
continue; /* empty line */
curAlias = malloc(sizeof(*curAlias));
memset(curAlias, 0, sizeof(*curAlias));
- strcpy(curAlias->aliasInfo.aliasName, aliasPtr);
- strcpy(curAlias->aliasInfo.realName, tbuffer);
+ strlcpy(curAlias->aliasInfo.aliasName, aliasPtr, sizeof curAlias->aliasInfo.aliasName);
+ strlcpy(curAlias->aliasInfo.realName, tbuffer, sizeof curAlias->aliasInfo.realName);
curAlias->next = adir->alias_entries;
adir->alias_entries = curAlias;
struct afsconf_cell *acellInfo)
{
afs_int32 code;
- int tservice, i;
- size_t len;
+ int tservice, i, len;
unsigned char answer[1024];
unsigned char *p;
char *dotcellname;
char host[256];
int server_num = 0;
int minttl = 0;
+ int try_init = 0;
/* The resolver isn't always MT-safe.. Perhaps this ought to be
* replaced with a more fine-grained lock just for the resolver
* operations.
*/
+ retryafsdb:
if ( ! strchr(acellName,'.') ) {
cellnamelength=strlen(acellName);
dotcellname=malloc(cellnamelength+2);
dotcellname[cellnamelength]='.';
dotcellname[cellnamelength+1]=0;
LOCK_GLOBAL_MUTEX;
- len = res_search(dotcellname, C_IN, T_AFSDB, answer, sizeof(answer));
+ len = res_search(dotcellname, C_IN, T_AFSDB, answer, sizeof(answer));
if ( len < 0 ) {
len = res_search(acellName, C_IN, T_AFSDB, answer, sizeof(answer));
}
free(dotcellname);
} else {
LOCK_GLOBAL_MUTEX;
- len = res_search(acellName, C_IN, T_AFSDB, answer, sizeof(answer));
+ len = res_search(acellName, C_IN, T_AFSDB, answer, sizeof(answer));
UNLOCK_GLOBAL_MUTEX;
}
- if (len < 0)
+ if (len < 0) {
+ if (try_init < 1) {
+ try_init++;
+ res_init();
+ goto retryafsdb;
+ }
return AFSCONF_NOTFOUND;
+ }
p = answer + sizeof(HEADER); /* Skip header */
code = dn_expand(answer, answer + len, p, host, sizeof(host));
* right AFSDB type. Write down the true cell name that
* the resolver gave us above.
*/
- strcpy(realCellName, host);
+ strlcpy(realCellName, host, sizeof realCellName);
}
code = dn_expand(answer, answer + len, p + 2, host, sizeof(host));
}
acellInfo->numServers = numServers;
- strcpy(acellInfo->name, acellName);
+ strlcpy(acellInfo->name, acellName, sizeof acellInfo->name);
if (aservice) {
LOCK_GLOBAL_MUTEX;
tservice = afsconf_FindService(aservice);
register afs_int32 i;
int tservice;
char *tcell;
- size_t cnLen;
+ int cnLen;
int ambig;
char tbuffer[64];
afsconf_Check(adir);
if (acellName) {
tcell = acellName;
- cnLen = strlen(tcell) + 1;
+ cnLen = (int)(strlen(tcell) + 1);
lcstring(tcell, tcell, cnLen);
afsconf_SawCell = 1; /* will ignore the AFSCELL switch on future */
/* call to afsconf_GetLocalCell: like klog */
return 0;
}
+ /* convert key structure to host order */
+ tstr->nkeys = ntohl(tstr->nkeys);
+
if (code < sizeof(afs_int32) + (tstr->nkeys*sizeof(struct afsconf_key))) {
tstr->nkeys = 0;
UNLOCK_GLOBAL_MUTEX;
return 0;
}
- /* convert key structure to host order */
- tstr->nkeys = ntohl(tstr->nkeys);
for (fd = 0; fd < tstr->nkeys; fd++)
tstr->key[fd].kvno = ntohl(tstr->key[fd].kvno);