Using stdio in getent() results in a minor wallclock speedup but halves the system time on my test machine. As a bonus we can reuse pfp in tcgetnext().
- todd Index: lib/libc/gen/getcap.c =================================================================== RCS file: /cvs/src/lib/libc/gen/getcap.c,v retrieving revision 1.28 diff -u -r1.28 getcap.c --- lib/libc/gen/getcap.c 6 Jul 2011 18:51:09 -0000 1.28 +++ lib/libc/gen/getcap.c 6 Jul 2011 21:28:46 -0000 @@ -58,7 +58,7 @@ static int gottoprec; /* Flag indicating retrieval of toprecord */ static int cdbget(DB *, char **, const char *); -static int getent(char **, u_int *, char **, int, const char *, int, char *); +static int getent(char **, u_int *, char **, FILE *, const char *, int, char *); static int nfcmp(const char *, char *); static int usedb = 1; @@ -168,12 +168,12 @@ { u_int dummy; - return (getent(buf, &dummy, db_array, -1, name, 0, NULL)); + return (getent(buf, &dummy, db_array, NULL, name, 0, NULL)); } /* - * Getent implements the functions of cgetent. If fd is non-negative, - * *db_array has already been opened and fd is the open file descriptor. We + * Getent implements the functions of cgetent. If fp is non-NULL, + * *db_array has already been opened and fp is the open file descriptor. We * do this to save time and avoid using up file descriptors for tc= * recursions. * @@ -190,7 +190,7 @@ * MAX_RECURSION. */ static int -getent(char **cap, u_int *len, char **db_array, int fd, +getent(char **cap, u_int *len, char **db_array, FILE *fp, const char *name, int depth, char *nfield) { DB *capdbp; @@ -240,8 +240,8 @@ /* * Open database if not already open. */ - if (fd >= 0) { - (void)lseek(fd, (off_t)0, SEEK_SET); + if (fp != NULL) { + (void)fseek(fp, 0L, SEEK_SET); myfd = 0; opened++; } else { @@ -272,8 +272,8 @@ *cap = cbuf; return (retval); } else { - fd = open(*db_p, O_RDONLY, 0); - if (fd < 0) { + fp = fopen(*db_p, "r"); + if (fp == NULL) { /* No error on unfound file. */ continue; } @@ -308,20 +308,19 @@ rp = record; for (;;) { if (bp >= b_end) { - int n; + size_t n; - n = read(fd, buf, sizeof(buf)); - if (n <= 0) { + n = fread(buf, 1, sizeof(buf), fp); + if (n == 0) { + eof = feof(fp); if (myfd) - (void)close(fd); - if (n < 0) { - free(record); - return (-2); - } else { - fd = -1; - eof = 1; + (void)fclose(fp); + if (eof) { + fp = NULL; break; } + free(record); + return (-2); } b_end = buf+n; bp = buf; @@ -343,7 +342,7 @@ * some more. */ if (rp >= r_end) { - u_int pos; + size_t pos; size_t newsize; char *nrecord; @@ -354,7 +353,7 @@ if (record) free(record); if (myfd) - (void)close(fd); + (void)fclose(fp); errno = ENOMEM; return (-2); } @@ -440,13 +439,13 @@ tclen = s - tcstart; tcend = s; - iret = getent(&icap, &ilen, db_p, fd, tc, depth+1, + iret = getent(&icap, &ilen, db_p, fp, tc, depth+1, NULL); if (iret != 0) { /* an error */ if (iret < -1) { if (myfd) - (void)close(fd); + (void)fclose(fp); free(record); return (iret); } @@ -498,7 +497,7 @@ if (record) free(record); if (myfd) - (void)close(fd); + (void)fclose(fp); free(ibuf); errno = ENOMEM; return (-2); @@ -532,7 +531,7 @@ * return capability, length and success. */ if (myfd) - (void)close(fd); + (void)fclose(fp); *len = rp - record - 1; /* don't count NUL */ if (r_end > rp) { char *nrecord; @@ -660,13 +659,12 @@ cgetnext(char **cap, char **db_array) { size_t len; - int serrno, status = -1; - char nbuf[BSIZE]; - char *record = NULL, *r_end, *rp; - char buf[BUFSIZ]; - char *b_end, *bp; - int c; + int c, serrno, status = -1; + char buf[BUFSIZ], nbuf[BSIZE]; + char *b_end, *bp, *r_end, *rp; + char *record = NULL; u_int dummy; + off_t pos; if (dbp == NULL) dbp = db_array; @@ -747,17 +745,17 @@ * some more. */ if (rp >= r_end) { - size_t newsize, pos; + size_t newsize, off; char *nrecord; - pos = rp - record; + off = rp - record; newsize = r_end - record + BFRAG; nrecord = realloc(record, newsize); if (nrecord == NULL) goto done; record = nrecord; r_end = record + newsize; - rp = record + pos; + rp = record + off; } } /* loop invariant lets us do this */ @@ -783,7 +781,10 @@ nbuf[len] = '\0'; /* return value of getent() is one less than cgetnext() */ - status = getent(cap, &dummy, db_array, -1, nbuf, 0, NULL) + 1; + pos = ftello(pfp); + status = getent(cap, &dummy, db_array, pfp, nbuf, 0, NULL) + 1; + if (status > 0) + fseeko(pfp, pos, SEEK_SET); done: serrno = errno; free(record);