static bool record_match_all(struct record *re, char **matches) { while (*matches != NULL) { if (!record_match(re, *matches)) return false; matches++; } return true; }
int index_match(struct index *src, struct index *dest, const struct match *match) { int n; struct record *re; index_blank(dest); for (n = 0; n < src->entries; n++) { re = src->record[n]; if (record_match(re, match)) { if (index_reserve(dest, 1) == -1) return -1; index_add(dest, re); } } return 0; }
/* * Internal version lookup routine used by both lookup_dn() and * update_dn(); same semantics as lookup_dn() except that the `partial' * argument has been generalized into a `flags' field. */ static int find_dn(int fd, uint_t flags, uint_t query, int count, const dn_rec_t *targetp, dn_rec_list_t **recordsp, uint_t *nrecordsp) { int retval = DSVC_SUCCESS; char *fields[DNF_FIELDS]; uint_t nrecords; dn_rec_t dn, *recordp; dn_rec_list_t *records, *new_records; unsigned int nfields; struct stat st; struct in_addr cip_nbo; char *ent0, *ent, *entend; char cip[INET_ADDRSTRLEN + 2]; /* * Page the whole container into memory via mmap() so we can scan it * quickly; map it MAP_PRIVATE so that we can change newlines to * NULs without changing the actual container itself. */ if (fstat(fd, &st) == -1 || st.st_size < 1) return (DSVC_INTERNAL); ent0 = mmap(0, st.st_size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0); if (ent0 == MAP_FAILED) return (DSVC_INTERNAL); /* * NUL-terminate the last byte (which should be a newline) so that * we can safely use string functions on the mapped container. */ ent0[st.st_size - 1] = '\0'; /* * If we're searching by client IP address, then build a target * string we can use to find it quickly. */ if (DSVC_QISEQ(query, DN_QCIP)) { cip[0] = '\n'; cip_nbo.s_addr = htonl(targetp->dn_cip.s_addr); (void) inet_ntop(AF_INET, &cip_nbo, cip + 1, INET_ADDRSTRLEN); (void) strlcat(cip, "|", sizeof (cip)); } records = NULL; ent = ent0; for (nrecords = 0; count < 0 || nrecords < count; ent = entend + 1) { /* * Bail if we've reached the end of the container. */ if (ent - ent0 >= st.st_size) break; /* * If we're searching by client IP address, locate it * quickly using strstr(3C); if we can't find it by this * technique then it's not in the container. */ if (DSVC_QISEQ(query, DN_QCIP)) { /* * If we've already found the DN_QCIP record, bail. */ if (nrecords > 0) break; ent = strstr(ent, cip); if (ent == NULL) break; ent++; } /* * Find the end of the record and change it a NUL byte so * that it is interpreted correctly with field_split() and * record_match() below. If we can't find a trailing * newline, then it must be the last record (whose newline * we already changed to a NUL above). */ entend = strchr(ent, '\n'); if (entend != NULL) *entend = '\0'; else entend = &ent0[st.st_size - 1]; /* * Skip pure comment lines; for now this just skips the * header information at the top of the container. */ if (ent[0] == DNF_COMMENT_CHAR) continue; /* * Split the buffer up into DNF_FIELDS fields. */ nfields = field_split(ent, DNF_FIELDS, fields, "|"); if (nfields < DNF_FIELDS) continue; /* * See if we've got a match, filling in dnf.dnf_rec as * we go. If record_match() succeeds, dnf.dnf_rec will * be completely filled in. */ if (!record_match(fields, &dn, targetp, query)) continue; /* * Caller just wants a count of the number of matching * records, not the records themselves; continue. */ if (recordsp == NULL) { nrecords++; continue; } /* * Allocate record; if FIND_POSITION flag is set, then * we need to allocate an extended (dn_recpos_t) record. */ if (flags & FIND_POSITION) recordp = malloc(sizeof (dn_recpos_t)); else recordp = malloc(sizeof (dn_rec_t)); if (recordp == NULL) { if ((flags & FIND_PARTIAL) == 0) retval = DSVC_NO_MEMORY; break; } /* * Fill in record; do a structure copy from our automatic * dn. If FIND_POSITION flag is on, pass back additional * position information. */ *recordp = dn; if (flags & FIND_POSITION) { ((dn_recpos_t *)recordp)->dnp_off = ent - ent0; ((dn_recpos_t *)recordp)->dnp_size = entend - ent + 1; } /* * Chuck the record on the list; up the counter. */ new_records = add_dnrec_to_list(recordp, records); if (new_records == NULL) { free(recordp); if ((flags & FIND_PARTIAL) == 0) retval = DSVC_NO_MEMORY; break; } records = new_records; nrecords++; } (void) munmap(ent0, st.st_size); if (retval == DSVC_SUCCESS) { *nrecordsp = nrecords; if (recordsp != NULL) *recordsp = records; return (DSVC_SUCCESS); } if (records != NULL) free_dnrec_list(records); return (retval); }