/* * Free a list of dt_rec_t's */ void free_dtrec_list(dt_rec_list_t *dtlp) { dt_rec_list_t *next; for (; dtlp != NULL; dtlp = next) { free_dtrec(dtlp->dtl_rec); next = dtlp->dtl_next; free(dtlp); } }
/* * Internal version of lookup_dt() used by both lookup_dt() and * update_dt(); same semantics as lookup_dt() except that the `partial' * argument has been generalized into a `flags' field and the handle has * been turned into a FILE pointer. */ static int find_dt(FILE *fp, uint_t flags, uint_t query, int count, const dt_rec_t *targetp, dt_rec_list_t **recordsp, uint_t *nrecordsp) { int retval = DSVC_SUCCESS; char *buf = NULL, *fields[DTF_MAX_FIELDS]; uint_t nrecords; dt_rec_t *recordp; dt_rec_list_t *records, *new_records; unsigned int nfields; off_t recoff; if (fseek(fp, 0, SEEK_SET) == -1) return (DSVC_INTERNAL); records = NULL; for (nrecords = 0; count < 0 || nrecords < count; ) { free(buf); if (flags & FIND_POSITION) recoff = ftello(fp); buf = read_entry(fp); if (buf == NULL) { if (!feof(fp)) retval = DSVC_NO_MEMORY; break; } /* * Skip pure comment lines; for now this just skips the * header information at the top of the container. */ if (buf[0] == DTF_COMMENT_CHAR) continue; /* * Parse out the entry into the dt_rec_t */ nfields = field_split(buf, DTF_MAX_FIELDS, fields, " \t"); if (nfields < DTF_MAX_FIELDS) continue; /* * See if we've got a match. If so, allocate the new * record, fill it in, and continue. */ if (DSVC_QISEQ(query, DT_QTYPE) && targetp->dt_type != fields[DTF_TYPE][0]) continue; else if (DSVC_QISNEQ(query, DT_QTYPE) && targetp->dt_type == fields[DTF_TYPE][0]) continue; if (DSVC_QISEQ(query, DT_QKEY) && strcmp(targetp->dt_key, fields[DTF_KEY]) != 0) continue; else if (DSVC_QISNEQ(query, DT_QKEY) && strcmp(targetp->dt_key, fields[DTF_KEY]) == 0) 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 (dt_recpos_t) record. */ if (flags & FIND_POSITION) recordp = malloc(sizeof (dt_recpos_t)); else recordp = malloc(sizeof (dt_rec_t)); if (recordp == NULL) { if ((flags & FIND_PARTIAL) == 0) retval = DSVC_NO_MEMORY; break; } /* * Fill in record; if FIND_POSITION flag is set, then pass * back additional location information. */ (void) strlcpy(recordp->dt_key, fields[DTF_KEY], sizeof (recordp->dt_key)); recordp->dt_sig = 1; recordp->dt_type = fields[DTF_TYPE][0]; recordp->dt_value = strdup(fields[DTF_VALUE]); if (recordp->dt_value == NULL) { free(recordp); if ((flags & FIND_PARTIAL) == 0) retval = DSVC_NO_MEMORY; break; } if (flags & FIND_POSITION) { ((dt_recpos_t *)recordp)->dtp_off = recoff; ((dt_recpos_t *)recordp)->dtp_size = ftello(fp) - recoff; } /* * Chuck the record on the list; up the counter. */ new_records = add_dtrec_to_list(recordp, records); if (new_records == NULL) { free_dtrec(recordp); if ((flags & FIND_PARTIAL) == 0) retval = DSVC_NO_MEMORY; break; } records = new_records; nrecords++; } free(buf); if (retval == DSVC_SUCCESS) { *nrecordsp = nrecords; if (recordsp != NULL) *recordsp = records; return (DSVC_SUCCESS); } if (records != NULL) free_dtrec_list(records); return (retval); }