/* Call with mutex locked! */ static void profile_free_file_data(prf_data_t data) { scan_shared_trees_locked(); if (data->flags & PROFILE_FILE_SHARED) { /* Remove from linked list. */ if (g_shared_trees == data) g_shared_trees = data->next; else { prf_data_t prev, next; prev = g_shared_trees; next = prev->next; while (next) { if (next == data) { prev->next = next->next; break; } prev = next; next = next->next; } } } if (data->root) profile_free_node(data->root); if (data->comment) free(data->comment); data->magic = 0; k5_mutex_destroy(&data->lock); free(data); scan_shared_trees_locked(); }
void profile_free_file(prf_file_t prf) { if (prf->root) profile_free_node(prf->root); free(prf->filespec); free(prf); }
errcode_t profile_process_directory(const char *dirname, struct profile_node **root) { errcode_t retval; struct profile_node *node; *root = NULL; retval = profile_create_node("(root)", 0, &node); if (retval) return retval; retval = parse_include_dir(dirname, node); if (retval) { profile_free_node(node); return retval; } *root = node; return 0; }
errcode_t profile_parse_file(FILE *f, struct profile_node **root, char **ret_modspec) { struct parse_state state; errcode_t retval; *root = NULL; /* Initialize parsing state with a new root node. */ state.state = STATE_INIT_COMMENT; state.group_level = 0; state.current_section = NULL; retval = profile_create_node("(root)", 0, &state.root_section); if (retval) return retval; retval = parse_file(f, &state, ret_modspec); if (retval) { profile_free_node(state.root_section); return retval; } *root = state.root_section; return 0; }
errcode_t profile_update_file_data(prf_data_t data) { errcode_t retval; #ifdef HAVE_STAT struct stat st; unsigned long frac; time_t now; #endif FILE *f; retval = k5_mutex_lock(&data->lock); if (retval) return retval; #ifdef HAVE_STAT now = time(0); if (now == data->last_stat && data->root != NULL) { k5_mutex_unlock(&data->lock); return 0; } if (stat(data->filespec, &st)) { retval = errno; k5_mutex_unlock(&data->lock); return retval; } data->last_stat = now; #if defined HAVE_STRUCT_STAT_ST_MTIMENSEC frac = st.st_mtimensec; #elif defined HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC frac = st.st_mtimespec.tv_nsec; #elif defined HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC frac = st.st_mtim.tv_nsec; #else frac = 0; #endif if (st.st_mtime == data->timestamp && frac == data->frac_ts && data->root != NULL) { k5_mutex_unlock(&data->lock); return 0; } if (data->root) { profile_free_node(data->root); data->root = 0; } if (data->comment) { free(data->comment); data->comment = 0; } #else /* * If we don't have the stat() call, assume that our in-core * memory image is correct. That is, we won't reread the * profile file if it changes. */ if (data->root) { k5_mutex_unlock(&data->lock); return 0; } #endif errno = 0; f = fopen(data->filespec, "r"); if (f == NULL) { retval = errno; k5_mutex_unlock(&data->lock); if (retval == 0) retval = ENOENT; return retval; } set_cloexec_file(f); data->upd_serial++; data->flags &= PROFILE_FILE_SHARED; /* FIXME same as '=' operator */ retval = profile_parse_file(f, &data->root); fclose(f); if (retval) { k5_mutex_unlock(&data->lock); return retval; } assert(data->root != NULL); #ifdef HAVE_STAT data->timestamp = st.st_mtime; data->frac_ts = frac; #endif k5_mutex_unlock(&data->lock); return 0; }
errcode_t profile_parse_file(FILE *f, struct profile_node **root) { #define BUF_SIZE 2048 char *bptr; errcode_t retval; struct parse_state state; bptr = malloc (BUF_SIZE); if (!bptr) return ENOMEM; retval = parse_init_state(&state); if (retval) { free (bptr); return retval; } while (!feof(f)) { if (fgets(bptr, BUF_SIZE, f) == NULL) break; #ifndef PROFILE_SUPPORTS_FOREIGN_NEWLINES retval = parse_line(bptr, &state); if (retval) { profile_free_node(state.root_section); free (bptr); return retval; } #else { char *p, *end; if (strlen(bptr) >= BUF_SIZE - 1) { /* The string may have foreign newlines and gotten chopped off on a non-newline boundary. Seek backwards to the last known newline. */ long offset; char *c = bptr + strlen (bptr); for (offset = 0; offset > -BUF_SIZE; offset--) { if (*c == '\r' || *c == '\n') { *c = '\0'; fseek (f, offset, SEEK_CUR); break; } c--; } } /* First change all newlines to \n */ for (p = bptr; *p != '\0'; p++) { if (*p == '\r') *p = '\n'; } /* Then parse all lines */ p = bptr; end = bptr + strlen (bptr); while (p < end) { char* newline; char* newp; newline = strchr (p, '\n'); if (newline != NULL) *newline = '\0'; /* parse_line modifies contents of p */ newp = p + strlen (p) + 1; retval = parse_line (p, &state); if (retval) { profile_free_node(state.root_section); free (bptr); return retval; } p = newp; } } #endif } *root = state.root_section; free (bptr); return 0; }
/* * This function sets the value of the pseudo file "<default>". If * the file "<default>" had previously been passed to profile_init(), * then def_string parameter will be parsed and used as the profile * information for the "<default>" file. */ long profile_set_default(profile_t profile, const char *def_string) { struct parse_state state; prf_file_t prf; long retval; const char *in; char *line, *p, *end; int line_size, len; if (!def_string || !profile || profile->magic != PROF_MAGIC_PROFILE) return PROF_MAGIC_PROFILE; for (prf = profile->first_file; prf; prf = prf->next) { if (strcmp(prf->filespec, default_filename) == 0) break; } if (!prf) return 0; if (prf->root) { profile_free_node(prf->root); prf->root = 0; } memset(&state, 0, sizeof(struct parse_state)); retval = profile_create_node("(root)", 0, &state.root_section); if (retval) return retval; line = 0; line_size = 0; in = def_string; while (*in) { end = strchr(in, '\n'); len = end ? (end - in) : (int) strlen(in); if (len >= line_size) { line_size = len+1; p = realloc(line, line_size); if (!p) { retval = ENOMEM; goto errout; } line = p; } memcpy(line, in, len); line[len] = 0; retval = parse_line(line, &state); if (retval) { errout: if (syntax_err_cb) (syntax_err_cb)(prf->filespec, retval, state.line_num); free(line); if (prf->root) profile_free_node(prf->root); return retval; } if (!end) break; in = end+1; } prf->root = state.root_section; free(line); return 0; }