12fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o/* 22fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * profile.c -- A simple configuration file parsing "library in a file" 3efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o * 42fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * The profile library was originally written by Theodore Ts'o in 1995 52fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * for use in the MIT Kerberos v5 library. It has been 62fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * modified/enhanced/bug-fixed over time by other members of the MIT 72fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * Kerberos team. This version was originally taken from the Kerberos 82fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * v5 distribution, version 1.4.2, and radically simplified for use in 92fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * e2fsprogs. (Support for locking for multi-threaded operations, 102fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * being able to modify and update the configuration file 112fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * programmatically, and Mac/Windows portability have been removed. 122fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * It has been folded into a single C source file to make it easier to 132fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * fold into an application program.) 142fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * 15d45544ca5419e218537f8b9689bbb028abbf8f28Theodore Ts'o * Copyright (C) 2005, 2006 by Theodore Ts'o. 162fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * 172fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * %Begin-Header% 182fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * This file may be redistributed under the terms of the GNU Public 192fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * License. 202fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * %End-Header% 21efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o * 222fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * Copyright (C) 1985-2005 by the Massachusetts Institute of Technology. 23efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o * 242fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * All rights reserved. 25efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o * 262fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * Export of this software from the United States of America may require 272fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * a specific license from the United States Government. It is the 282fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * responsibility of any person or organization contemplating export to 292fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * obtain such a license before exporting. 30efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o * 312fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 322fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * distribute this software and its documentation for any purpose and 332fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * without fee is hereby granted, provided that the above copyright 342fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * notice appear in all copies and that both that copyright notice and 352fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * this permission notice appear in supporting documentation, and that 362fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * the name of M.I.T. not be used in advertising or publicity pertaining 372fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * to distribution of the software without specific, written prior 382fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * permission. Furthermore if you modify this software you must label 392fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * your software as modified software and not distribute it in such a 402fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * fashion that it might be confused with the original MIT software. 412fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * M.I.T. makes no representations about the suitability of this software 422fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * for any purpose. It is provided "as is" without express or implied 432fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * warranty. 44efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o * 452fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 462fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 472fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 48efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o * 492fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o */ 502fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 51d1154eb460efe588eaed3d439c1caaca149fa362Theodore Ts'o#include "config.h" 522fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o#ifdef HAVE_UNISTD_H 532fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o#include <unistd.h> 542fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o#endif 552fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o#include <stdio.h> 562fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o#ifdef HAVE_STDLIB_H 572fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o#include <stdlib.h> 582fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o#endif 592fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o#include <time.h> 602fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o#include <string.h> 610fad49b50d97cd2f56775f76f9649b26212ee435Theodore Ts'o#include <strings.h> 622fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o#include <errno.h> 632fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o#include <ctype.h> 642fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o#include <limits.h> 652fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o#include <stddef.h> 662fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o#include <sys/types.h> 672fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o#include <sys/stat.h> 687d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o#include <dirent.h> 692fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o#ifdef HAVE_PWD_H 702fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o#include <pwd.h> 712fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o#endif 722fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 73cec7103d922f89156acf25055a249fad82ed0e7aTheodore Ts'o#include <et/com_err.h> 742fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o#include "profile.h" 75fd7ac1fc9889075885cd698ddd3287af6457c7beTheodore Ts'o#include "prof_err.h" 76fd7ac1fc9889075885cd698ddd3287af6457c7beTheodore Ts'o 775582275fe06d6f4d0679d0a1a28d069769da8b41Theodore Ts'o#undef STAT_ONCE_PER_SECOND 785582275fe06d6f4d0679d0a1a28d069769da8b41Theodore Ts'o#undef HAVE_STAT 792fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 802fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o/* 812fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * prof_int.h 822fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o */ 832fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 842fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'otypedef long prf_magic_t; 852fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 862fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o/* 872fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * This is the structure which stores the profile information for a 882fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * particular configuration file. 892fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o */ 90d45544ca5419e218537f8b9689bbb028abbf8f28Theodore Ts'ostruct _prf_file_t { 912fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o prf_magic_t magic; 92d45544ca5419e218537f8b9689bbb028abbf8f28Theodore Ts'o char *filespec; 932fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o#ifdef STAT_ONCE_PER_SECOND 942fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o time_t last_stat; 952fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o#endif 962fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o time_t timestamp; /* time tree was last updated from file */ 972fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o int flags; /* r/w, dirty */ 982fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o int upd_serial; /* incremented when data changes */ 99d45544ca5419e218537f8b9689bbb028abbf8f28Theodore Ts'o struct profile_node *root; 1002fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o struct _prf_file_t *next; 1012fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o}; 1022fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 1032fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'otypedef struct _prf_file_t *prf_file_t; 1042fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 1052fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o/* 1062fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * The profile flags 1072fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o */ 1082fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o#define PROFILE_FILE_RW 0x0001 1092fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o#define PROFILE_FILE_DIRTY 0x0002 1106bde5c28ba25600f02f6d8cd2e8de39017bc421dTheodore Ts'o#define PROFILE_FILE_NO_RELOAD 0x0004 1112fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 1122fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o/* 1132fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * This structure defines the high-level, user visible profile_t 1142fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * object, which is used as a handle by users who need to query some 1152fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * configuration file(s) 1162fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o */ 1172fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'ostruct _profile_t { 1182fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o prf_magic_t magic; 1192fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o prf_file_t first_file; 1202fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o}; 1212fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 1222fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o/* 1232fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * Used by the profile iterator in prof_get.c 1242fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o */ 1252fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o#define PROFILE_ITER_LIST_SECTION 0x0001 1262fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o#define PROFILE_ITER_SECTIONS_ONLY 0x0002 1272fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o#define PROFILE_ITER_RELATIONS_ONLY 0x0004 1282fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 1292fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o#define PROFILE_ITER_FINAL_SEEN 0x0100 1302fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 1312fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o/* 1322fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * Check if a filespec is last in a list (NULL on UNIX, invalid FSSpec on MacOS 1332fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o */ 1342fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 1352fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o#define PROFILE_LAST_FILESPEC(x) (((x) == NULL) || ((x)[0] == '\0')) 1362fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 1379a4c209cd26a7eae3d1de427d9b028f69e1c2554Theodore Ts'ostruct profile_node { 1389a4c209cd26a7eae3d1de427d9b028f69e1c2554Theodore Ts'o errcode_t magic; 1399a4c209cd26a7eae3d1de427d9b028f69e1c2554Theodore Ts'o char *name; 1409a4c209cd26a7eae3d1de427d9b028f69e1c2554Theodore Ts'o char *value; 1419a4c209cd26a7eae3d1de427d9b028f69e1c2554Theodore Ts'o int group_level; 142642935c082ca22e1186fc9926fe06e4207d5ab56Theodore Ts'o unsigned int final:1; /* Indicate don't search next file */ 143642935c082ca22e1186fc9926fe06e4207d5ab56Theodore Ts'o unsigned int deleted:1; 1449a4c209cd26a7eae3d1de427d9b028f69e1c2554Theodore Ts'o struct profile_node *first_child; 1459a4c209cd26a7eae3d1de427d9b028f69e1c2554Theodore Ts'o struct profile_node *parent; 1469a4c209cd26a7eae3d1de427d9b028f69e1c2554Theodore Ts'o struct profile_node *next, *prev; 1479a4c209cd26a7eae3d1de427d9b028f69e1c2554Theodore Ts'o}; 1489a4c209cd26a7eae3d1de427d9b028f69e1c2554Theodore Ts'o 1499a4c209cd26a7eae3d1de427d9b028f69e1c2554Theodore Ts'o#define CHECK_MAGIC(node) \ 1509a4c209cd26a7eae3d1de427d9b028f69e1c2554Theodore Ts'o if ((node)->magic != PROF_MAGIC_NODE) \ 1519a4c209cd26a7eae3d1de427d9b028f69e1c2554Theodore Ts'o return PROF_MAGIC_NODE; 1529a4c209cd26a7eae3d1de427d9b028f69e1c2554Theodore Ts'o 153204ae371ad2e038b41c03aba13d3a57e4e6921ecTheodore Ts'o/* profile parser declarations */ 154204ae371ad2e038b41c03aba13d3a57e4e6921ecTheodore Ts'ostruct parse_state { 155204ae371ad2e038b41c03aba13d3a57e4e6921ecTheodore Ts'o int state; 156204ae371ad2e038b41c03aba13d3a57e4e6921ecTheodore Ts'o int group_level; 157204ae371ad2e038b41c03aba13d3a57e4e6921ecTheodore Ts'o int line_num; 158204ae371ad2e038b41c03aba13d3a57e4e6921ecTheodore Ts'o struct profile_node *root_section; 159204ae371ad2e038b41c03aba13d3a57e4e6921ecTheodore Ts'o struct profile_node *current_section; 160204ae371ad2e038b41c03aba13d3a57e4e6921ecTheodore Ts'o}; 161204ae371ad2e038b41c03aba13d3a57e4e6921ecTheodore Ts'o 1626f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'ostatic const char *default_filename = "<default>"; 1636f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o 164204ae371ad2e038b41c03aba13d3a57e4e6921ecTheodore Ts'ostatic profile_syntax_err_cb_t syntax_err_cb; 165204ae371ad2e038b41c03aba13d3a57e4e6921ecTheodore Ts'o 166204ae371ad2e038b41c03aba13d3a57e4e6921ecTheodore Ts'ostatic errcode_t parse_line(char *line, struct parse_state *state); 1672fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 1682fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o#ifdef DEBUG_PROGRAM 1692fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'ostatic errcode_t profile_write_tree_file 1702fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o (struct profile_node *root, FILE *dstfile); 1712fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 1722fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'ostatic errcode_t profile_write_tree_to_buffer 1732fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o (struct profile_node *root, char **buf); 1742fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o#endif 1752fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 1762fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 1772fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'ostatic void profile_free_node 1782fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o (struct profile_node *relation); 1792fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 1802fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'ostatic errcode_t profile_create_node 1812fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o (const char *name, const char *value, 1822fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o struct profile_node **ret_node); 1832fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 1842fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o#ifdef DEBUG_PROGRAM 1852fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'ostatic errcode_t profile_verify_node 1862fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o (struct profile_node *node); 1872fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o#endif 1882fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 1892fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'ostatic errcode_t profile_add_node 1902fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o (struct profile_node *section, 1912fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o const char *name, const char *value, 1922fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o struct profile_node **ret_node); 1932fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 1942fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'ostatic errcode_t profile_find_node 1952fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o (struct profile_node *section, 1962fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o const char *name, const char *value, 1972fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o int section_flag, void **state, 1982fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o struct profile_node **node); 1992fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 2002fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'ostatic errcode_t profile_node_iterator 2012fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o (void **iter_p, struct profile_node **ret_node, 2022fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o char **ret_name, char **ret_value); 2032fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 2042fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'ostatic errcode_t profile_open_file 2052fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o (const char * file, prf_file_t *ret_prof); 2062fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 207d45544ca5419e218537f8b9689bbb028abbf8f28Theodore Ts'ostatic errcode_t profile_update_file 208d45544ca5419e218537f8b9689bbb028abbf8f28Theodore Ts'o (prf_file_t prf); 2092fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 2102fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'ostatic void profile_free_file 2112fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o (prf_file_t profile); 2122fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 2139a4c209cd26a7eae3d1de427d9b028f69e1c2554Theodore Ts'ostatic errcode_t profile_get_value(profile_t profile, const char *name, 2149a4c209cd26a7eae3d1de427d9b028f69e1c2554Theodore Ts'o const char *subname, const char *subsubname, 2159a4c209cd26a7eae3d1de427d9b028f69e1c2554Theodore Ts'o const char **ret_value); 2169a4c209cd26a7eae3d1de427d9b028f69e1c2554Theodore Ts'o 2172fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 2182fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o/* 2192fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * prof_init.c --- routines that manipulate the user-visible profile_t 2202fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * object. 2212fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o */ 2222fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 223efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'ostatic int compstr(const void *m1, const void *m2) 2247d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o{ 225642935c082ca22e1186fc9926fe06e4207d5ab56Theodore Ts'o const char *s1 = *((const char * const *) m1); 226642935c082ca22e1186fc9926fe06e4207d5ab56Theodore Ts'o const char *s2 = *((const char * const *) m2); 2277d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o 228efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o return strcmp(s1, s2); 2297d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o} 2307d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o 2317d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'ostatic void free_list(char **list) 2327d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o{ 2337d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o char **cp; 2347d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o 2357d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o if (list == 0) 2367d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o return; 237efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 2387d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o for (cp = list; *cp; cp++) 2397d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o free(*cp); 2407d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o free(list); 2417d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o} 2427d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o 2437d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'ostatic errcode_t get_dirlist(const char *dirname, char***ret_array) 2447d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o{ 2457d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o DIR *dir; 2467d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o struct dirent *de; 2477d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o struct stat st; 2487d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o errcode_t retval; 2497d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o char *fn, *cp; 2507d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o char **array = 0, **new_array; 2517d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o int max = 0, num = 0; 2527d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o 2537d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o dir = opendir(dirname); 2547d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o if (!dir) 2557d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o return errno; 2567d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o 2577d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o while ((de = readdir(dir)) != NULL) { 2587d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o for (cp = de->d_name; *cp; cp++) { 2597d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o if (!isalnum(*cp) && 2607d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o (*cp != '-') && 2617d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o (*cp != '_')) 2627d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o break; 2637d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o } 2647d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o if (*cp) 2657d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o continue; 2667d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o fn = malloc(strlen(dirname) + strlen(de->d_name) + 2); 2677d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o if (!fn) { 2687d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o retval = ENOMEM; 2697d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o goto errout; 2707d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o } 2717d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o sprintf(fn, "%s/%s", dirname, de->d_name); 2727d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o if ((stat(fn, &st) < 0) || !S_ISREG(st.st_mode)) { 2737d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o free(fn); 2747d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o continue; 2757d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o } 2767d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o if (num >= max) { 2777d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o max += 10; 2787d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o new_array = realloc(array, sizeof(char *) * (max+1)); 2797d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o if (!new_array) { 2807d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o retval = ENOMEM; 2816d4ced2192766f09f021ed801797961ad2f8e258Eric Sandeen free(fn); 2827d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o goto errout; 2837d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o } 2847d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o array = new_array; 2857d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o } 2867d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o array[num++] = fn; 2877d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o } 28812f91959993f0d2882592427c94f35f32436e03aBrian Behlendorf if (array) { 28912f91959993f0d2882592427c94f35f32436e03aBrian Behlendorf qsort(array, num, sizeof(char *), compstr); 29012f91959993f0d2882592427c94f35f32436e03aBrian Behlendorf array[num++] = 0; 29112f91959993f0d2882592427c94f35f32436e03aBrian Behlendorf } 2927d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o *ret_array = array; 2937d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o closedir(dir); 2947d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o return 0; 2957d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'oerrout: 2966d4ced2192766f09f021ed801797961ad2f8e258Eric Sandeen if (array) 2976d4ced2192766f09f021ed801797961ad2f8e258Eric Sandeen array[num] = 0; 2987d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o closedir(dir); 2997d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o free_list(array); 3007d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o return retval; 3017d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o} 3027d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o 303efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'oerrcode_t 304a701823a31505c5765d327d02bb14aa43fc34ae5Theodore Ts'oprofile_init(const char * const *files, profile_t *ret_profile) 3052fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o{ 306a701823a31505c5765d327d02bb14aa43fc34ae5Theodore Ts'o const char * const *fs; 3072fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o profile_t profile; 3087d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o prf_file_t new_file, *last; 3092fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o errcode_t retval = 0; 3107d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o char **cpp, *cp, **array = 0; 3112fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 3122fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o profile = malloc(sizeof(struct _profile_t)); 3132fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (!profile) 3142fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return ENOMEM; 3152fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o memset(profile, 0, sizeof(struct _profile_t)); 3162fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o profile->magic = PROF_MAGIC_PROFILE; 3177d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o last = &profile->first_file; 3182fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 3192fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o /* if the filenames list is not specified return an empty profile */ 3202fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if ( files ) { 3212fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o for (fs = files; !PROFILE_LAST_FILESPEC(*fs); fs++) { 322f0131bdc6ff2b349e84e4767d9fe8b078a0ee521Darrick J. Wong if (array) 323f0131bdc6ff2b349e84e4767d9fe8b078a0ee521Darrick J. Wong free_list(array); 324603fc2cb4b0f04f7c4e9c75bfea1b91fe000e47aTheodore Ts'o array = NULL; 3257d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o retval = get_dirlist(*fs, &array); 3267d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o if (retval == 0) { 32712f91959993f0d2882592427c94f35f32436e03aBrian Behlendorf if (!array) 32812f91959993f0d2882592427c94f35f32436e03aBrian Behlendorf continue; 3297d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o for (cpp = array; (cp = *cpp); cpp++) { 3307d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o retval = profile_open_file(cp, &new_file); 3317d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o if (retval == EACCES) 3327d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o continue; 3337d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o if (retval) 3347d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o goto errout; 3357d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o *last = new_file; 3367d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o last = &new_file->next; 3377d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o } 338efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o } else if ((retval != ENOTDIR) && 3396f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o strcmp(*fs, default_filename)) 3407d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o goto errout; 3417d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o 3422fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o retval = profile_open_file(*fs, &new_file); 3432fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o /* if this file is missing, skip to the next */ 3442fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (retval == ENOENT || retval == EACCES) { 3452fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o continue; 3462fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } 3477d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o if (retval) 3487d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o goto errout; 3497d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o *last = new_file; 3507d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o last = &new_file->next; 3512fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } 3522fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o /* 3537d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o * If all the files were not found, return the appropriate error. 3542fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o */ 3557d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o if (!profile->first_file) { 3566d4ced2192766f09f021ed801797961ad2f8e258Eric Sandeen retval = ENOENT; 3576d4ced2192766f09f021ed801797961ad2f8e258Eric Sandeen goto errout; 3582fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } 3592fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } 3602fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 3617d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o free_list(array); 3622fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o *ret_profile = profile; 3632fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return 0; 3647d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'oerrout: 3657d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o free_list(array); 3667d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o profile_release(profile); 3677d922f8bcba93f7d830825cb2e07b3eaee99b994Theodore Ts'o return retval; 3682fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o} 3692fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 370efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'ovoid 3712fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'oprofile_release(profile_t profile) 3722fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o{ 3732fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o prf_file_t p, next; 3742fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 3752fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (!profile || profile->magic != PROF_MAGIC_PROFILE) 3762fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return; 3772fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 3782fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o for (p = profile->first_file; p; p = next) { 3792fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o next = p->next; 3802fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o profile_free_file(p); 3812fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } 3822fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o profile->magic = 0; 3832fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o free(profile); 3842fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o} 3852fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 3866f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o/* 3876f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o * This function sets the value of the pseudo file "<default>". If 3886f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o * the file "<default>" had previously been passed to profile_init(), 3896f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o * then def_string parameter will be parsed and used as the profile 3906f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o * information for the "<default>" file. 3916f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o */ 3926f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'oerrcode_t profile_set_default(profile_t profile, const char *def_string) 3936f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o{ 3946f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o struct parse_state state; 3956f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o prf_file_t prf; 3966f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o errcode_t retval; 3976f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o const char *in; 3986f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o char *line, *p, *end; 3996f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o int line_size, len; 4006f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o 4016f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o if (!def_string || !profile || profile->magic != PROF_MAGIC_PROFILE) 4026f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o return PROF_MAGIC_PROFILE; 4036f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o 4046f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o for (prf = profile->first_file; prf; prf = prf->next) { 4056f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o if (strcmp(prf->filespec, default_filename) == 0) 4066f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o break; 4076f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o } 4086f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o if (!prf) 4096f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o return 0; 4106f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o 4116f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o if (prf->root) { 4126f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o profile_free_node(prf->root); 4136f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o prf->root = 0; 4146f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o } 4156f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o 4166f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o memset(&state, 0, sizeof(struct parse_state)); 4176f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o retval = profile_create_node("(root)", 0, &state.root_section); 4186f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o if (retval) 4196f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o return retval; 4206f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o 4216f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o line = 0; 4226f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o line_size = 0; 4236f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o in = def_string; 4246f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o while (*in) { 4256f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o end = strchr(in, '\n'); 4266f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o len = end ? (end - in) : (int) strlen(in); 4276f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o if (len >= line_size) { 4286f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o line_size = len+1; 4296f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o p = realloc(line, line_size); 4306f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o if (!p) { 4316f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o retval = ENOMEM; 4326f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o goto errout; 4336f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o } 4346f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o line = p; 4356f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o } 4366f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o memcpy(line, in, len); 4376f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o line[len] = 0; 4386f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o retval = parse_line(line, &state); 4396f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o if (retval) { 4406f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o errout: 4416f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o if (syntax_err_cb) 442efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o (syntax_err_cb)(prf->filespec, retval, 4436f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o state.line_num); 4446f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o free(line); 4456f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o if (prf->root) 4466f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o profile_free_node(prf->root); 4476f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o return retval; 4486f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o } 4496f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o if (!end) 4506f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o break; 4516f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o in = end+1; 4526f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o } 4536f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o prf->root = state.root_section; 4546f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o free(line); 4556f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o 4566f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o return 0; 4576f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o} 4582fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 4592fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o/* 4602fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * prof_file.c ---- routines that manipulate an individual profile file. 4612fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o */ 4622fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 4632fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'oerrcode_t profile_open_file(const char * filespec, 4642fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o prf_file_t *ret_prof) 4652fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o{ 4662fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o prf_file_t prf; 4672fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o errcode_t retval; 4682fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o char *home_env = 0; 4692fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o unsigned int len; 4702fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o char *expanded_filename; 4712fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 4722fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o prf = malloc(sizeof(struct _prf_file_t)); 4732fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (!prf) 4742fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return ENOMEM; 4752fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o memset(prf, 0, sizeof(struct _prf_file_t)); 4762fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o prf->magic = PROF_MAGIC_FILE; 4772fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 4782fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o len = strlen(filespec)+1; 4792fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (filespec[0] == '~' && filespec[1] == '/') { 4802fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o home_env = getenv("HOME"); 4812fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o#ifdef HAVE_PWD_H 4822fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (home_env == NULL) { 48395a8d1de512f7ae55b78d99db21bb0d5973d115eTheodore Ts'o#ifdef HAVE_GETWUID_R 4842fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o struct passwd *pw, pwx; 48595a8d1de512f7ae55b78d99db21bb0d5973d115eTheodore Ts'o uid_t uid; 4862fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o char pwbuf[BUFSIZ]; 4872fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 4882fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o uid = getuid(); 48995a8d1de512f7ae55b78d99db21bb0d5973d115eTheodore Ts'o if (!getpwuid_r(uid, &pwx, pwbuf, sizeof(pwbuf), &pw) 4902fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o && pw != NULL && pw->pw_dir[0] != 0) 4912fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o home_env = pw->pw_dir; 49295a8d1de512f7ae55b78d99db21bb0d5973d115eTheodore Ts'o#else 49395a8d1de512f7ae55b78d99db21bb0d5973d115eTheodore Ts'o struct passwd *pw; 49495a8d1de512f7ae55b78d99db21bb0d5973d115eTheodore Ts'o 49595a8d1de512f7ae55b78d99db21bb0d5973d115eTheodore Ts'o pw = getpwuid(getuid()); 49695a8d1de512f7ae55b78d99db21bb0d5973d115eTheodore Ts'o home_env = pw->pw_dir; 49795a8d1de512f7ae55b78d99db21bb0d5973d115eTheodore Ts'o#endif 4982fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } 4992fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o#endif 5002fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (home_env) 5012fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o len += strlen(home_env); 5022fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } 5032fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o expanded_filename = malloc(len); 50493503267c9765f80f8bbbdbb132d495a859361e1Brian Behlendorf if (expanded_filename == 0) { 505efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o profile_free_file(prf); 5062fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return errno; 50793503267c9765f80f8bbbdbb132d495a859361e1Brian Behlendorf } 5082fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (home_env) { 5092fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o strcpy(expanded_filename, home_env); 5102fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o strcat(expanded_filename, filespec+1); 5112fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } else 5122fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o memcpy(expanded_filename, filespec, len); 5132fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 514d45544ca5419e218537f8b9689bbb028abbf8f28Theodore Ts'o prf->filespec = expanded_filename; 5152fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 5166f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o if (strcmp(prf->filespec, default_filename) != 0) { 5176f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o retval = profile_update_file(prf); 5186f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o if (retval) { 5196f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o profile_free_file(prf); 5206f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o return retval; 5216f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o } 5222fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } 5232fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 5242fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o *ret_prof = prf; 5252fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return 0; 5262fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o} 5272fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 528d45544ca5419e218537f8b9689bbb028abbf8f28Theodore Ts'oerrcode_t profile_update_file(prf_file_t prf) 5292fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o{ 5302fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o errcode_t retval; 5312fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o#ifdef HAVE_STAT 5322fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o struct stat st; 5332fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o#ifdef STAT_ONCE_PER_SECOND 5342fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o time_t now; 5352fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o#endif 5362fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o#endif 5372fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o FILE *f; 538204ae371ad2e038b41c03aba13d3a57e4e6921ecTheodore Ts'o char buf[2048]; 539204ae371ad2e038b41c03aba13d3a57e4e6921ecTheodore Ts'o struct parse_state state; 5402fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 5416bde5c28ba25600f02f6d8cd2e8de39017bc421dTheodore Ts'o if (prf->flags & PROFILE_FILE_NO_RELOAD) 5426bde5c28ba25600f02f6d8cd2e8de39017bc421dTheodore Ts'o return 0; 5436bde5c28ba25600f02f6d8cd2e8de39017bc421dTheodore Ts'o 5442fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o#ifdef HAVE_STAT 5452fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o#ifdef STAT_ONCE_PER_SECOND 5462fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o now = time(0); 547d45544ca5419e218537f8b9689bbb028abbf8f28Theodore Ts'o if (now == prf->last_stat && prf->root != NULL) { 5482fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return 0; 5492fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } 5502fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o#endif 551d45544ca5419e218537f8b9689bbb028abbf8f28Theodore Ts'o if (stat(prf->filespec, &st)) { 5522fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o retval = errno; 5532fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return retval; 5542fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } 5552fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o#ifdef STAT_ONCE_PER_SECOND 556d45544ca5419e218537f8b9689bbb028abbf8f28Theodore Ts'o prf->last_stat = now; 5572fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o#endif 558d45544ca5419e218537f8b9689bbb028abbf8f28Theodore Ts'o if (st.st_mtime == prf->timestamp && prf->root != NULL) { 5592fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return 0; 5602fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } 561d45544ca5419e218537f8b9689bbb028abbf8f28Theodore Ts'o if (prf->root) { 562d45544ca5419e218537f8b9689bbb028abbf8f28Theodore Ts'o profile_free_node(prf->root); 563d45544ca5419e218537f8b9689bbb028abbf8f28Theodore Ts'o prf->root = 0; 5642fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } 5652fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o#else 5662fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o /* 5672fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * If we don't have the stat() call, assume that our in-core 5682fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * memory image is correct. That is, we won't reread the 5692fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * profile file if it changes. 5702fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o */ 571d45544ca5419e218537f8b9689bbb028abbf8f28Theodore Ts'o if (prf->root) { 5722fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return 0; 5732fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } 5742fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o#endif 575204ae371ad2e038b41c03aba13d3a57e4e6921ecTheodore Ts'o memset(&state, 0, sizeof(struct parse_state)); 576204ae371ad2e038b41c03aba13d3a57e4e6921ecTheodore Ts'o retval = profile_create_node("(root)", 0, &state.root_section); 577204ae371ad2e038b41c03aba13d3a57e4e6921ecTheodore Ts'o if (retval) 578204ae371ad2e038b41c03aba13d3a57e4e6921ecTheodore Ts'o return retval; 5792fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o errno = 0; 580d45544ca5419e218537f8b9689bbb028abbf8f28Theodore Ts'o f = fopen(prf->filespec, "r"); 5812fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (f == NULL) { 5822fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o retval = errno; 5832fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (retval == 0) 5842fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o retval = ENOENT; 5852fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return retval; 5862fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } 587d45544ca5419e218537f8b9689bbb028abbf8f28Theodore Ts'o prf->upd_serial++; 588204ae371ad2e038b41c03aba13d3a57e4e6921ecTheodore Ts'o while (!feof(f)) { 589204ae371ad2e038b41c03aba13d3a57e4e6921ecTheodore Ts'o if (fgets(buf, sizeof(buf), f) == NULL) 590204ae371ad2e038b41c03aba13d3a57e4e6921ecTheodore Ts'o break; 591204ae371ad2e038b41c03aba13d3a57e4e6921ecTheodore Ts'o retval = parse_line(buf, &state); 592204ae371ad2e038b41c03aba13d3a57e4e6921ecTheodore Ts'o if (retval) { 593204ae371ad2e038b41c03aba13d3a57e4e6921ecTheodore Ts'o if (syntax_err_cb) 594efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o (syntax_err_cb)(prf->filespec, retval, 595204ae371ad2e038b41c03aba13d3a57e4e6921ecTheodore Ts'o state.line_num); 596204ae371ad2e038b41c03aba13d3a57e4e6921ecTheodore Ts'o fclose(f); 597204ae371ad2e038b41c03aba13d3a57e4e6921ecTheodore Ts'o return retval; 598204ae371ad2e038b41c03aba13d3a57e4e6921ecTheodore Ts'o } 5992fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } 600204ae371ad2e038b41c03aba13d3a57e4e6921ecTheodore Ts'o prf->root = state.root_section; 601204ae371ad2e038b41c03aba13d3a57e4e6921ecTheodore Ts'o 602204ae371ad2e038b41c03aba13d3a57e4e6921ecTheodore Ts'o fclose(f); 603204ae371ad2e038b41c03aba13d3a57e4e6921ecTheodore Ts'o 6042fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o#ifdef HAVE_STAT 605d45544ca5419e218537f8b9689bbb028abbf8f28Theodore Ts'o prf->timestamp = st.st_mtime; 6062fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o#endif 6072fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return 0; 6082fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o} 6092fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 6102fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'ovoid profile_free_file(prf_file_t prf) 6112fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o{ 612d45544ca5419e218537f8b9689bbb028abbf8f28Theodore Ts'o if (prf->root) 613d45544ca5419e218537f8b9689bbb028abbf8f28Theodore Ts'o profile_free_node(prf->root); 61445e338f5332a54295893dba2e32cc093d1316f60Jim Meyering free(prf->filespec); 6152fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o free(prf); 6162fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o} 6172fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 618d45544ca5419e218537f8b9689bbb028abbf8f28Theodore Ts'o/* Begin the profile parser */ 6192fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 620f5f14fcfe9eba0282a3dfe5600364bbf797dcfc3Theodore Ts'oprofile_syntax_err_cb_t profile_set_syntax_err_cb(profile_syntax_err_cb_t hook) 621f5f14fcfe9eba0282a3dfe5600364bbf797dcfc3Theodore Ts'o{ 622f5f14fcfe9eba0282a3dfe5600364bbf797dcfc3Theodore Ts'o profile_syntax_err_cb_t old; 623f5f14fcfe9eba0282a3dfe5600364bbf797dcfc3Theodore Ts'o 624f5f14fcfe9eba0282a3dfe5600364bbf797dcfc3Theodore Ts'o old = syntax_err_cb; 625f5f14fcfe9eba0282a3dfe5600364bbf797dcfc3Theodore Ts'o syntax_err_cb = hook; 626f5f14fcfe9eba0282a3dfe5600364bbf797dcfc3Theodore Ts'o return(old); 627f5f14fcfe9eba0282a3dfe5600364bbf797dcfc3Theodore Ts'o} 628f5f14fcfe9eba0282a3dfe5600364bbf797dcfc3Theodore Ts'o 629f5f14fcfe9eba0282a3dfe5600364bbf797dcfc3Theodore Ts'o#define STATE_INIT_COMMENT 0 630f5f14fcfe9eba0282a3dfe5600364bbf797dcfc3Theodore Ts'o#define STATE_STD_LINE 1 631f5f14fcfe9eba0282a3dfe5600364bbf797dcfc3Theodore Ts'o#define STATE_GET_OBRACE 2 6322fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 6332fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'ostatic char *skip_over_blanks(char *cp) 6342fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o{ 6352fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o while (*cp && isspace((int) (*cp))) 6362fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o cp++; 6372fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return cp; 6382fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o} 6392fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 64095a8d1de512f7ae55b78d99db21bb0d5973d115eTheodore Ts'ostatic int end_or_comment(char ch) 64195a8d1de512f7ae55b78d99db21bb0d5973d115eTheodore Ts'o{ 64295a8d1de512f7ae55b78d99db21bb0d5973d115eTheodore Ts'o return (ch == 0 || ch == '#' || ch == ';'); 64395a8d1de512f7ae55b78d99db21bb0d5973d115eTheodore Ts'o} 64495a8d1de512f7ae55b78d99db21bb0d5973d115eTheodore Ts'o 64595a8d1de512f7ae55b78d99db21bb0d5973d115eTheodore Ts'ostatic char *skip_over_nonblanks(char *cp) 64695a8d1de512f7ae55b78d99db21bb0d5973d115eTheodore Ts'o{ 64795a8d1de512f7ae55b78d99db21bb0d5973d115eTheodore Ts'o while (!end_or_comment(*cp) && !isspace(*cp)) 64895a8d1de512f7ae55b78d99db21bb0d5973d115eTheodore Ts'o cp++; 64995a8d1de512f7ae55b78d99db21bb0d5973d115eTheodore Ts'o return cp; 65095a8d1de512f7ae55b78d99db21bb0d5973d115eTheodore Ts'o} 65195a8d1de512f7ae55b78d99db21bb0d5973d115eTheodore Ts'o 6522fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'ostatic void strip_line(char *line) 6532fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o{ 6542fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o char *p = line + strlen(line); 6552fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o while (p > line && (p[-1] == '\n' || p[-1] == '\r')) 6562fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o *p-- = 0; 6572fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o} 6582fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 6592fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'ostatic void parse_quoted_string(char *str) 6602fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o{ 6612fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o char *to, *from; 6622fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 6632fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o to = from = str; 6642fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 6652fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o for (to = from = str; *from && *from != '"'; to++, from++) { 6662fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (*from == '\\') { 6672fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o from++; 6682fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o switch (*from) { 6692fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o case 'n': 6702fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o *to = '\n'; 6712fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o break; 6722fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o case 't': 6732fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o *to = '\t'; 6742fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o break; 6752fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o case 'b': 6762fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o *to = '\b'; 6772fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o break; 6782fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o default: 6792fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o *to = *from; 6802fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } 6812fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o continue; 6822fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } 6832fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o *to = *from; 6842fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } 6852fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o *to = '\0'; 6862fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o} 6872fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 688204ae371ad2e038b41c03aba13d3a57e4e6921ecTheodore Ts'ostatic errcode_t parse_line(char *line, struct parse_state *state) 6892fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o{ 6902fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o char *cp, ch, *tag, *value; 6912fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o char *p; 6922fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o errcode_t retval; 6932fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o struct profile_node *node; 6942fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o int do_subsection = 0; 6952fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o void *iter = 0; 696efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 697204ae371ad2e038b41c03aba13d3a57e4e6921ecTheodore Ts'o state->line_num++; 698204ae371ad2e038b41c03aba13d3a57e4e6921ecTheodore Ts'o if (state->state == STATE_GET_OBRACE) { 699204ae371ad2e038b41c03aba13d3a57e4e6921ecTheodore Ts'o cp = skip_over_blanks(line); 700204ae371ad2e038b41c03aba13d3a57e4e6921ecTheodore Ts'o if (*cp != '{') 701204ae371ad2e038b41c03aba13d3a57e4e6921ecTheodore Ts'o return PROF_MISSING_OBRACE; 702204ae371ad2e038b41c03aba13d3a57e4e6921ecTheodore Ts'o state->state = STATE_STD_LINE; 703204ae371ad2e038b41c03aba13d3a57e4e6921ecTheodore Ts'o return 0; 704204ae371ad2e038b41c03aba13d3a57e4e6921ecTheodore Ts'o } 705204ae371ad2e038b41c03aba13d3a57e4e6921ecTheodore Ts'o if (state->state == STATE_INIT_COMMENT) { 706204ae371ad2e038b41c03aba13d3a57e4e6921ecTheodore Ts'o if (line[0] != '[') 707204ae371ad2e038b41c03aba13d3a57e4e6921ecTheodore Ts'o return 0; 708204ae371ad2e038b41c03aba13d3a57e4e6921ecTheodore Ts'o state->state = STATE_STD_LINE; 709204ae371ad2e038b41c03aba13d3a57e4e6921ecTheodore Ts'o } 710204ae371ad2e038b41c03aba13d3a57e4e6921ecTheodore Ts'o 7112fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (*line == 0) 7122fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return 0; 7132fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o strip_line(line); 7142fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o cp = skip_over_blanks(line); 7152fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o ch = *cp; 71695a8d1de512f7ae55b78d99db21bb0d5973d115eTheodore Ts'o if (end_or_comment(ch)) 7172fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return 0; 7182fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (ch == '[') { 7192fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (state->group_level > 0) 7202fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return PROF_SECTION_NOTOP; 7212fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o cp++; 72222fe674da4bdec2ff1c1abb7ad074df3a641377bTheodore Ts'o cp = skip_over_blanks(cp); 7232fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o p = strchr(cp, ']'); 7242fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (p == NULL) 7252fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return PROF_SECTION_SYNTAX; 72622fe674da4bdec2ff1c1abb7ad074df3a641377bTheodore Ts'o if (*cp == '"') { 72722fe674da4bdec2ff1c1abb7ad074df3a641377bTheodore Ts'o cp++; 72822fe674da4bdec2ff1c1abb7ad074df3a641377bTheodore Ts'o parse_quoted_string(cp); 72922fe674da4bdec2ff1c1abb7ad074df3a641377bTheodore Ts'o } else { 73022fe674da4bdec2ff1c1abb7ad074df3a641377bTheodore Ts'o *p-- = '\0'; 73122fe674da4bdec2ff1c1abb7ad074df3a641377bTheodore Ts'o while (isspace(*p) && (p > cp)) 73222fe674da4bdec2ff1c1abb7ad074df3a641377bTheodore Ts'o *p-- = '\0'; 73322fe674da4bdec2ff1c1abb7ad074df3a641377bTheodore Ts'o if (*cp == 0) 73422fe674da4bdec2ff1c1abb7ad074df3a641377bTheodore Ts'o return PROF_SECTION_SYNTAX; 73522fe674da4bdec2ff1c1abb7ad074df3a641377bTheodore Ts'o } 736efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o retval = profile_find_node(state->root_section, cp, 0, 1, 7379a4c209cd26a7eae3d1de427d9b028f69e1c2554Theodore Ts'o &iter, &state->current_section); 7382fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (retval == PROF_NO_SECTION) { 7392fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o retval = profile_add_node(state->root_section, 7402fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o cp, 0, 7412fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o &state->current_section); 7422fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (retval) 7432fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return retval; 7442fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } else if (retval) 7452fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return retval; 7462fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 7472fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o /* 7482fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * Finish off the rest of the line. 7492fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o */ 7502fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o cp = p+1; 7512fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (*cp == '*') { 7529a4c209cd26a7eae3d1de427d9b028f69e1c2554Theodore Ts'o state->current_section->final = 1; 7532fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o cp++; 7542fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } 7552fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o /* 756efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o * Spaces or comments after ']' should not be fatal 7572fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o */ 7582fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o cp = skip_over_blanks(cp); 75995a8d1de512f7ae55b78d99db21bb0d5973d115eTheodore Ts'o if (!end_or_comment(*cp)) 7602fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return PROF_SECTION_SYNTAX; 7612fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return 0; 7622fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } 7632fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (ch == '}') { 7642fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (state->group_level == 0) 7652fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return PROF_EXTRA_CBRACE; 7662fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (*(cp+1) == '*') 7679a4c209cd26a7eae3d1de427d9b028f69e1c2554Theodore Ts'o state->current_section->final = 1; 7689a4c209cd26a7eae3d1de427d9b028f69e1c2554Theodore Ts'o state->current_section = state->current_section->parent; 7692fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o state->group_level--; 7702fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return 0; 7712fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } 7722fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o /* 7732fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * Parse the relations 7742fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o */ 7752fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o tag = cp; 7762fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o cp = strchr(cp, '='); 7772fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (!cp) 7782fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return PROF_RELATION_SYNTAX; 7792fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (cp == tag) 7802fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return PROF_RELATION_SYNTAX; 7812fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o *cp = '\0'; 78222fe674da4bdec2ff1c1abb7ad074df3a641377bTheodore Ts'o if (*tag == '"') { 78322fe674da4bdec2ff1c1abb7ad074df3a641377bTheodore Ts'o tag++; 78422fe674da4bdec2ff1c1abb7ad074df3a641377bTheodore Ts'o parse_quoted_string(tag); 78522fe674da4bdec2ff1c1abb7ad074df3a641377bTheodore Ts'o } else { 78622fe674da4bdec2ff1c1abb7ad074df3a641377bTheodore Ts'o /* Look for whitespace on left-hand side. */ 78722fe674da4bdec2ff1c1abb7ad074df3a641377bTheodore Ts'o p = skip_over_nonblanks(tag); 78822fe674da4bdec2ff1c1abb7ad074df3a641377bTheodore Ts'o if (*p) 78922fe674da4bdec2ff1c1abb7ad074df3a641377bTheodore Ts'o *p++ = 0; 79022fe674da4bdec2ff1c1abb7ad074df3a641377bTheodore Ts'o p = skip_over_blanks(p); 79122fe674da4bdec2ff1c1abb7ad074df3a641377bTheodore Ts'o /* If we have more non-whitespace, it's an error. */ 79222fe674da4bdec2ff1c1abb7ad074df3a641377bTheodore Ts'o if (*p) 79322fe674da4bdec2ff1c1abb7ad074df3a641377bTheodore Ts'o return PROF_RELATION_SYNTAX; 79422fe674da4bdec2ff1c1abb7ad074df3a641377bTheodore Ts'o } 79595a8d1de512f7ae55b78d99db21bb0d5973d115eTheodore Ts'o 7962fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o cp = skip_over_blanks(cp+1); 7972fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o value = cp; 79895a8d1de512f7ae55b78d99db21bb0d5973d115eTheodore Ts'o ch = value[0]; 79995a8d1de512f7ae55b78d99db21bb0d5973d115eTheodore Ts'o if (ch == '"') { 8002fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o value++; 8012fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o parse_quoted_string(value); 80295a8d1de512f7ae55b78d99db21bb0d5973d115eTheodore Ts'o } else if (end_or_comment(ch)) { 8032fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o do_subsection++; 8042fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o state->state = STATE_GET_OBRACE; 80595a8d1de512f7ae55b78d99db21bb0d5973d115eTheodore Ts'o } else if (value[0] == '{') { 80695a8d1de512f7ae55b78d99db21bb0d5973d115eTheodore Ts'o cp = skip_over_blanks(value+1); 80795a8d1de512f7ae55b78d99db21bb0d5973d115eTheodore Ts'o ch = *cp; 80895a8d1de512f7ae55b78d99db21bb0d5973d115eTheodore Ts'o if (end_or_comment(ch)) 80995a8d1de512f7ae55b78d99db21bb0d5973d115eTheodore Ts'o do_subsection++; 81095a8d1de512f7ae55b78d99db21bb0d5973d115eTheodore Ts'o else 81195a8d1de512f7ae55b78d99db21bb0d5973d115eTheodore Ts'o return PROF_RELATION_SYNTAX; 81295a8d1de512f7ae55b78d99db21bb0d5973d115eTheodore Ts'o } else { 81395a8d1de512f7ae55b78d99db21bb0d5973d115eTheodore Ts'o cp = skip_over_nonblanks(value); 81495a8d1de512f7ae55b78d99db21bb0d5973d115eTheodore Ts'o p = skip_over_blanks(cp); 81595a8d1de512f7ae55b78d99db21bb0d5973d115eTheodore Ts'o ch = *p; 81695a8d1de512f7ae55b78d99db21bb0d5973d115eTheodore Ts'o *cp = 0; 81795a8d1de512f7ae55b78d99db21bb0d5973d115eTheodore Ts'o if (!end_or_comment(ch)) 81895a8d1de512f7ae55b78d99db21bb0d5973d115eTheodore Ts'o return PROF_RELATION_SYNTAX; 8192fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } 8202fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (do_subsection) { 8212fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o p = strchr(tag, '*'); 8222fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (p) 8232fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o *p = '\0'; 8242fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o retval = profile_add_node(state->current_section, 8252fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o tag, 0, &state->current_section); 8262fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (retval) 8272fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return retval; 8282fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (p) 8299a4c209cd26a7eae3d1de427d9b028f69e1c2554Theodore Ts'o state->current_section->final = 1; 8302fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o state->group_level++; 8312fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return 0; 8322fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } 8332fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o p = strchr(tag, '*'); 8342fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (p) 8352fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o *p = '\0'; 8362fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o profile_add_node(state->current_section, tag, value, &node); 8372fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (p) 8389a4c209cd26a7eae3d1de427d9b028f69e1c2554Theodore Ts'o node->final = 1; 8392fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return 0; 8402fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o} 8412fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 84244dc5f8804b2480764f792315d84977ec9569163Theodore Ts'o#ifdef DEBUG_PROGRAM 8432fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o/* 8442fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * Return TRUE if the string begins or ends with whitespace 8452fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o */ 8462fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'ostatic int need_double_quotes(char *str) 8472fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o{ 8482fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (!str || !*str) 8492fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return 0; 8502fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (isspace((int) (*str)) ||isspace((int) (*(str + strlen(str) - 1)))) 8512fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return 1; 85295a8d1de512f7ae55b78d99db21bb0d5973d115eTheodore Ts'o if (strchr(str, '\n') || strchr(str, '\t') || strchr(str, '\b') || 85395a8d1de512f7ae55b78d99db21bb0d5973d115eTheodore Ts'o strchr(str, ' ') || strchr(str, '#') || strchr(str, ';')) 8542fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return 1; 8552fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return 0; 8562fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o} 8572fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 8582fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o/* 8592fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * Output a string with double quotes, doing appropriate backquoting 8602fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * of characters as necessary. 8612fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o */ 8622fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'ostatic void output_quoted_string(char *str, void (*cb)(const char *,void *), 8632fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o void *data) 8642fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o{ 8652fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o char ch; 8662fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o char buf[2]; 8672fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 8682fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o cb("\"", data); 8692fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (!str) { 8702fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o cb("\"", data); 8712fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return; 8722fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } 8732fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o buf[1] = 0; 8742fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o while ((ch = *str++)) { 8752fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o switch (ch) { 8762fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o case '\\': 8772fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o cb("\\\\", data); 8782fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o break; 8792fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o case '\n': 8802fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o cb("\\n", data); 8812fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o break; 8822fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o case '\t': 8832fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o cb("\\t", data); 8842fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o break; 8852fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o case '\b': 8862fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o cb("\\b", data); 8872fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o break; 8882fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o default: 8892fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o /* This would be a lot faster if we scanned 8902fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o forward for the next "interesting" 8912fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o character. */ 8922fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o buf[0] = ch; 8932fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o cb(buf, data); 8942fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o break; 8952fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } 8962fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } 8972fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o cb("\"", data); 8982fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o} 8992fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 9002fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o#ifndef EOL 9012fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o#define EOL "\n" 9022fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o#endif 9032fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 9042fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o/* Errors should be returned, not ignored! */ 9052fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'ostatic void dump_profile(struct profile_node *root, int level, 9062fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o void (*cb)(const char *, void *), void *data) 9072fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o{ 9082fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o int i; 9092fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o struct profile_node *p; 9102fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o void *iter; 9112fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o long retval; 912efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 9132fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o iter = 0; 9142fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o do { 9159a4c209cd26a7eae3d1de427d9b028f69e1c2554Theodore Ts'o retval = profile_find_node(root, 0, 0, 0, &iter, &p); 9162fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (retval) 9172fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o break; 9182fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o for (i=0; i < level; i++) 9192fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o cb("\t", data); 92022fe674da4bdec2ff1c1abb7ad074df3a641377bTheodore Ts'o if (need_double_quotes(p->name)) 92122fe674da4bdec2ff1c1abb7ad074df3a641377bTheodore Ts'o output_quoted_string(p->name, cb, data); 92222fe674da4bdec2ff1c1abb7ad074df3a641377bTheodore Ts'o else 9239a4c209cd26a7eae3d1de427d9b028f69e1c2554Theodore Ts'o cb(p->name, data); 92422fe674da4bdec2ff1c1abb7ad074df3a641377bTheodore Ts'o cb(" = ", data); 92522fe674da4bdec2ff1c1abb7ad074df3a641377bTheodore Ts'o if (need_double_quotes(p->value)) 9269a4c209cd26a7eae3d1de427d9b028f69e1c2554Theodore Ts'o output_quoted_string(p->value, cb, data); 92722fe674da4bdec2ff1c1abb7ad074df3a641377bTheodore Ts'o else 9289a4c209cd26a7eae3d1de427d9b028f69e1c2554Theodore Ts'o cb(p->value, data); 92922fe674da4bdec2ff1c1abb7ad074df3a641377bTheodore Ts'o cb(EOL, data); 9302fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } while (iter != 0); 9312fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 9322fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o iter = 0; 9332fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o do { 9349a4c209cd26a7eae3d1de427d9b028f69e1c2554Theodore Ts'o retval = profile_find_node(root, 0, 0, 1, &iter, &p); 9352fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (retval) 9362fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o break; 9372fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (level == 0) { /* [xxx] */ 9382fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o cb("[", data); 93922fe674da4bdec2ff1c1abb7ad074df3a641377bTheodore Ts'o if (need_double_quotes(p->name)) 94022fe674da4bdec2ff1c1abb7ad074df3a641377bTheodore Ts'o output_quoted_string(p->name, cb, data); 94122fe674da4bdec2ff1c1abb7ad074df3a641377bTheodore Ts'o else 94222fe674da4bdec2ff1c1abb7ad074df3a641377bTheodore Ts'o cb(p->name, data); 9432fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o cb("]", data); 9449a4c209cd26a7eae3d1de427d9b028f69e1c2554Theodore Ts'o cb(p->final ? "*" : "", data); 9452fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o cb(EOL, data); 9462fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o dump_profile(p, level+1, cb, data); 9472fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o cb(EOL, data); 9482fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } else { /* xxx = { ... } */ 9492fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o for (i=0; i < level; i++) 9502fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o cb("\t", data); 95122fe674da4bdec2ff1c1abb7ad074df3a641377bTheodore Ts'o if (need_double_quotes(p->name)) 95222fe674da4bdec2ff1c1abb7ad074df3a641377bTheodore Ts'o output_quoted_string(p->name, cb, data); 95322fe674da4bdec2ff1c1abb7ad074df3a641377bTheodore Ts'o else 95422fe674da4bdec2ff1c1abb7ad074df3a641377bTheodore Ts'o cb(p->name, data); 9552fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o cb(" = {", data); 9562fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o cb(EOL, data); 9572fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o dump_profile(p, level+1, cb, data); 9582fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o for (i=0; i < level; i++) 9592fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o cb("\t", data); 9602fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o cb("}", data); 9619a4c209cd26a7eae3d1de427d9b028f69e1c2554Theodore Ts'o cb(p->final ? "*" : "", data); 9622fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o cb(EOL, data); 9632fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } 9642fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } while (iter != 0); 9652fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o} 9662fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 9672fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'ostatic void dump_profile_to_file_cb(const char *str, void *data) 9682fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o{ 9692fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o fputs(str, data); 9702fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o} 9712fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 9722fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'oerrcode_t profile_write_tree_file(struct profile_node *root, FILE *dstfile) 9732fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o{ 9742fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o dump_profile(root, 0, dump_profile_to_file_cb, dstfile); 9752fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return 0; 9762fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o} 9772fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 9782fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'ostruct prof_buf { 9792fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o char *base; 9802fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o size_t cur, max; 9812fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o int err; 9822fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o}; 9832fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 9842fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'ostatic void add_data_to_buffer(struct prof_buf *b, const void *d, size_t len) 9852fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o{ 9862fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (b->err) 9872fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return; 9882fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (b->max - b->cur < len) { 9892fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o size_t newsize; 9902fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o char *newptr; 9912fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 9922fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o newsize = b->max + (b->max >> 1) + len + 1024; 9932fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o newptr = realloc(b->base, newsize); 9942fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (newptr == NULL) { 9952fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o b->err = 1; 9962fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return; 9972fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } 9982fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o b->base = newptr; 9992fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o b->max = newsize; 10002fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } 10012fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o memcpy(b->base + b->cur, d, len); 10022fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o b->cur += len; /* ignore overflow */ 10032fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o} 10042fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 10052fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'ostatic void dump_profile_to_buffer_cb(const char *str, void *data) 10062fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o{ 10072fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o add_data_to_buffer((struct prof_buf *)data, str, strlen(str)); 10082fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o} 10092fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 10102fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'oerrcode_t profile_write_tree_to_buffer(struct profile_node *root, 10112fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o char **buf) 10122fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o{ 10132fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o struct prof_buf prof_buf = { 0, 0, 0, 0 }; 10142fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 10152fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o dump_profile(root, 0, dump_profile_to_buffer_cb, &prof_buf); 10162fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (prof_buf.err) { 10172fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o *buf = NULL; 10182fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return ENOMEM; 10192fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } 10202fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o add_data_to_buffer(&prof_buf, "", 1); /* append nul */ 10212fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (prof_buf.max - prof_buf.cur > (prof_buf.max >> 3)) { 10222fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o char *newptr = realloc(prof_buf.base, prof_buf.cur); 10232fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (newptr) 10242fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o prof_buf.base = newptr; 10252fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } 10262fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o *buf = prof_buf.base; 10272fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return 0; 10282fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o} 10292fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o#endif 10302fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 10312fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o/* 10322fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * prof_tree.c --- these routines maintain the parse tree of the 10332fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * config file. 1034efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o * 10352fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * All of the details of how the tree is stored is abstracted away in 10362fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * this file; all of the other profile routines build, access, and 10372fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * modify the tree via the accessor functions found in this file. 10382fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * 10392fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * Each node may represent either a relation or a section header. 1040efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o * 10412fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * A section header must have its value field set to 0, and may a one 10422fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * or more child nodes, pointed to by first_child. 1043efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o * 10442fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * A relation has as its value a pointer to allocated memory 10452fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * containing a string. Its first_child pointer must be null. 10462fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * 10472fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o */ 10482fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 10492fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o/* 10502fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * Free a node, and any children 10512fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o */ 10522fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'ovoid profile_free_node(struct profile_node *node) 10532fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o{ 10542fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o struct profile_node *child, *next; 10552fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 10562fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (node->magic != PROF_MAGIC_NODE) 10572fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return; 1058efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 105945e338f5332a54295893dba2e32cc093d1316f60Jim Meyering free(node->name); 106045e338f5332a54295893dba2e32cc093d1316f60Jim Meyering free(node->value); 10612fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 10622fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o for (child=node->first_child; child; child = next) { 10632fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o next = child->next; 10642fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o profile_free_node(child); 10652fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } 10662fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o node->magic = 0; 1067efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 10682fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o free(node); 10692fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o} 10702fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 10712fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o#ifndef HAVE_STRDUP 10722fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o#undef strdup 10732fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o#define strdup MYstrdup 10742fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'ostatic char *MYstrdup (const char *s) 10752fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o{ 10762fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o size_t sz = strlen(s) + 1; 10772fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o char *p = malloc(sz); 10782fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (p != 0) 10792fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o memcpy(p, s, sz); 10802fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return p; 10812fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o} 10822fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o#endif 10832fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 10842fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o/* 10852fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * Create a node 10862fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o */ 10872fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'oerrcode_t profile_create_node(const char *name, const char *value, 10882fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o struct profile_node **ret_node) 10892fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o{ 10902fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o struct profile_node *new; 10912fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 10922fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o new = malloc(sizeof(struct profile_node)); 10932fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (!new) 10942fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return ENOMEM; 10952fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o memset(new, 0, sizeof(struct profile_node)); 10962fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o new->name = strdup(name); 10972fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (new->name == 0) { 10982fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o profile_free_node(new); 10992fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return ENOMEM; 11002fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } 11012fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (value) { 11022fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o new->value = strdup(value); 11032fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (new->value == 0) { 11042fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o profile_free_node(new); 11052fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return ENOMEM; 11062fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } 11072fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } 11082fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o new->magic = PROF_MAGIC_NODE; 11092fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 11102fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o *ret_node = new; 11112fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return 0; 11122fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o} 11132fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 11142fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o/* 11152fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * This function verifies that all of the representation invarients of 11162fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * the profile are true. If not, we have a programming bug somewhere, 11172fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * probably in this file. 11182fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o */ 11192fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o#ifdef DEBUG_PROGRAM 11202fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'oerrcode_t profile_verify_node(struct profile_node *node) 11212fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o{ 11222fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o struct profile_node *p, *last; 11232fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o errcode_t retval; 11242fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 11252fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o CHECK_MAGIC(node); 11262fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 11272fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (node->value && node->first_child) 11282fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return PROF_SECTION_WITH_VALUE; 11292fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 11302fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o last = 0; 11312fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o for (p = node->first_child; p; last = p, p = p->next) { 11322fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (p->prev != last) 11332fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return PROF_BAD_LINK_LIST; 11342fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (last && (last->next != p)) 11352fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return PROF_BAD_LINK_LIST; 11362fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (node->group_level+1 != p->group_level) 11372fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return PROF_BAD_GROUP_LVL; 11382fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (p->parent != node) 11392fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return PROF_BAD_PARENT_PTR; 11402fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o retval = profile_verify_node(p); 11412fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (retval) 11422fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return retval; 11432fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } 11442fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return 0; 11452fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o} 11462fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o#endif 11472fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 11482fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o/* 11492fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * Add a node to a particular section 11502fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o */ 11512fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'oerrcode_t profile_add_node(struct profile_node *section, const char *name, 11522fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o const char *value, struct profile_node **ret_node) 11532fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o{ 11542fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o errcode_t retval; 11552fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o struct profile_node *p, *last, *new; 11562fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 11572fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o CHECK_MAGIC(section); 11582fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 11592fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (section->value) 11602fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return PROF_ADD_NOT_SECTION; 11612fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 11622fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o /* 11632fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * Find the place to insert the new node. We look for the 1164efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o * place *after* the last match of the node name, since 11652fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * order matters. 11662fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o */ 11672fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o for (p=section->first_child, last = 0; p; last = p, p = p->next) { 11682fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o int cmp; 11692fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o cmp = strcmp(p->name, name); 11702fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (cmp > 0) 11712fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o break; 11722fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } 11732fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o retval = profile_create_node(name, value, &new); 11742fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (retval) 11752fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return retval; 11762fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o new->group_level = section->group_level+1; 11772fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o new->deleted = 0; 11782fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o new->parent = section; 11792fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o new->prev = last; 11802fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o new->next = p; 11812fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (p) 11822fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o p->prev = new; 11832fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (last) 11842fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o last->next = new; 11852fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o else 11862fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o section->first_child = new; 11872fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (ret_node) 11882fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o *ret_node = new; 11892fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return 0; 11902fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o} 11912fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 11922fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o/* 11932fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * Iterate through the section, returning the nodes which match 11942fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * the given name. If name is NULL, then interate through all the 11952fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * nodes in the section. If section_flag is non-zero, only return the 11962fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * section which matches the name; don't return relations. If value 11972fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * is non-NULL, then only return relations which match the requested 11982fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * value. (The value argument is ignored if section_flag is non-zero.) 1199efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o * 12002fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * The first time this routine is called, the state pointer must be 12012fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * null. When this profile_find_node_relation() returns, if the state 12022fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * pointer is non-NULL, then this routine should be called again. 12032fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * (This won't happen if section_flag is non-zero, obviously.) 12042fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * 12052fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o */ 12062fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'oerrcode_t profile_find_node(struct profile_node *section, const char *name, 12072fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o const char *value, int section_flag, void **state, 12082fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o struct profile_node **node) 12092fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o{ 12102fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o struct profile_node *p; 12112fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 12122fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o CHECK_MAGIC(section); 12132fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o p = *state; 12142fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (p) { 12152fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o CHECK_MAGIC(p); 12162fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } else 12172fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o p = section->first_child; 1218efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 12192fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o for (; p; p = p->next) { 12202fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (name && (strcmp(p->name, name))) 12212fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o continue; 12222fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (section_flag) { 12232fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (p->value) 12242fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o continue; 12252fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } else { 12262fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (!p->value) 12272fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o continue; 12282fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (value && (strcmp(p->value, value))) 12292fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o continue; 12302fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } 12312fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (p->deleted) 12322fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o continue; 12332fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o /* A match! */ 12342fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (node) 12352fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o *node = p; 12362fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o break; 12372fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } 12382fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (p == 0) { 12392fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o *state = 0; 12402fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return section_flag ? PROF_NO_SECTION : PROF_NO_RELATION; 12412fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } 12422fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o /* 12432fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * OK, we've found one match; now let's try to find another 12442fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * one. This way, if we return a non-zero state pointer, 12452fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * there's guaranteed to be another match that's returned. 12462fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o */ 12472fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o for (p = p->next; p; p = p->next) { 12482fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (name && (strcmp(p->name, name))) 12492fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o continue; 12502fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (section_flag) { 12512fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (p->value) 12522fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o continue; 12532fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } else { 12542fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (!p->value) 12552fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o continue; 12562fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (value && (strcmp(p->value, value))) 12572fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o continue; 12582fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } 12592fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o /* A match! */ 12602fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o break; 12612fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } 12622fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o *state = p; 12632fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return 0; 12642fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o} 12652fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 12662fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o/* 12672fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * This is a general-purpose iterator for returning all nodes that 1268efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o * match the specified name array. 12692fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o */ 12702fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'ostruct profile_iterator { 12712fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o prf_magic_t magic; 12722fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o profile_t profile; 12732fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o int flags; 12742fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o const char *const *names; 12752fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o const char *name; 12762fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o prf_file_t file; 12772fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o int file_serial; 12782fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o int done_idx; 12792fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o struct profile_node *node; 12802fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o int num; 12812fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o}; 12822fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 1283efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'oerrcode_t 12849a4c209cd26a7eae3d1de427d9b028f69e1c2554Theodore Ts'oprofile_iterator_create(profile_t profile, const char *const *names, int flags, 12859a4c209cd26a7eae3d1de427d9b028f69e1c2554Theodore Ts'o void **ret_iter) 12862fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o{ 12872fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o struct profile_iterator *iter; 12882fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o int done_idx = 0; 12892fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 12902fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (profile == 0) 12912fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return PROF_NO_PROFILE; 12922fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (profile->magic != PROF_MAGIC_PROFILE) 12932fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return PROF_MAGIC_PROFILE; 12942fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (!names) 12952fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return PROF_BAD_NAMESET; 12962fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (!(flags & PROFILE_ITER_LIST_SECTION)) { 12972fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (!names[0]) 12982fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return PROF_BAD_NAMESET; 12992fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o done_idx = 1; 13002fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } 13012fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 13022fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if ((iter = malloc(sizeof(struct profile_iterator))) == NULL) 13032fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return ENOMEM; 13042fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 13052fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o iter->magic = PROF_MAGIC_ITERATOR; 13062fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o iter->profile = profile; 13072fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o iter->names = names; 13082fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o iter->flags = flags; 13092fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o iter->file = profile->first_file; 13102fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o iter->done_idx = done_idx; 13112fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o iter->node = 0; 13122fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o iter->num = 0; 13132fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o *ret_iter = iter; 13142fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return 0; 13152fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o} 13162fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 13179a4c209cd26a7eae3d1de427d9b028f69e1c2554Theodore Ts'ovoid profile_iterator_free(void **iter_p) 13182fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o{ 13192fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o struct profile_iterator *iter; 13202fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 13212fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (!iter_p) 13222fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return; 13232fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o iter = *iter_p; 13242fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (!iter || iter->magic != PROF_MAGIC_ITERATOR) 13252fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return; 13262fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o free(iter); 13272fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o *iter_p = 0; 13282fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o} 13292fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 13302fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o/* 13312fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * Note: the returned character strings in ret_name and ret_value 13322fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * points to the stored character string in the parse string. Before 13332fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * this string value is returned to a calling application 13342fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * (profile_node_iterator is not an exported interface), it should be 13352fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * strdup()'ed. 13362fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o */ 13372fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'oerrcode_t profile_node_iterator(void **iter_p, struct profile_node **ret_node, 13382fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o char **ret_name, char **ret_value) 13392fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o{ 13402fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o struct profile_iterator *iter = *iter_p; 13412fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o struct profile_node *section, *p; 13422fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o const char *const *cpp; 13432fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o errcode_t retval; 13442fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o int skip_num = 0; 13452fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 13462fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (!iter || iter->magic != PROF_MAGIC_ITERATOR) 13472fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return PROF_MAGIC_ITERATOR; 13482fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (iter->file && iter->file->magic != PROF_MAGIC_FILE) 13492fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return PROF_MAGIC_FILE; 13502fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o /* 13512fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * If the file has changed, then the node pointer is invalid, 13522fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * so we'll have search the file again looking for it. 13532fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o */ 1354efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o if (iter->node && (iter->file && 13558f234d9650eb6f6a897148d5136cb27f373de4a7Brian Behlendorf iter->file->upd_serial != iter->file_serial)) { 13562fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o iter->flags &= ~PROFILE_ITER_FINAL_SEEN; 13572fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o skip_num = iter->num; 13582fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o iter->node = 0; 13592fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } 13602fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (iter->node && iter->node->magic != PROF_MAGIC_NODE) { 13612fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return PROF_MAGIC_NODE; 13622fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } 13632fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'oget_new_file: 13642fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (iter->node == 0) { 13652fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (iter->file == 0 || 13662fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o (iter->flags & PROFILE_ITER_FINAL_SEEN)) { 13679a4c209cd26a7eae3d1de427d9b028f69e1c2554Theodore Ts'o profile_iterator_free(iter_p); 13682fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (ret_node) 13692fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o *ret_node = 0; 13702fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (ret_name) 13712fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o *ret_name = 0; 13722fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (ret_value) 13732fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o *ret_value =0; 13742fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return 0; 13752fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } 13762fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if ((retval = profile_update_file(iter->file))) { 13772fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (retval == ENOENT || retval == EACCES) { 13782fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o /* XXX memory leak? */ 13792fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o iter->file = iter->file->next; 13802fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o skip_num = 0; 13812fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o retval = 0; 13822fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o goto get_new_file; 13832fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } else { 13849a4c209cd26a7eae3d1de427d9b028f69e1c2554Theodore Ts'o profile_iterator_free(iter_p); 13852fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return retval; 13862fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } 13872fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } 1388d45544ca5419e218537f8b9689bbb028abbf8f28Theodore Ts'o iter->file_serial = iter->file->upd_serial; 13892fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o /* 13902fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * Find the section to list if we are a LIST_SECTION, 13912fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * or find the containing section if not. 13922fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o */ 1393d45544ca5419e218537f8b9689bbb028abbf8f28Theodore Ts'o section = iter->file->root; 13942fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o for (cpp = iter->names; cpp[iter->done_idx]; cpp++) { 13952fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o for (p=section->first_child; p; p = p->next) { 13962fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (!strcmp(p->name, *cpp) && !p->value) 13972fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o break; 13982fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } 13992fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (!p) { 14002fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o section = 0; 14012fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o break; 14022fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } 14032fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o section = p; 14042fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (p->final) 14052fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o iter->flags |= PROFILE_ITER_FINAL_SEEN; 14062fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } 14072fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (!section) { 14082fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o iter->file = iter->file->next; 14092fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o skip_num = 0; 14102fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o goto get_new_file; 14112fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } 14122fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o iter->name = *cpp; 14132fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o iter->node = section->first_child; 14142fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } 14152fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o /* 14162fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * OK, now we know iter->node is set up correctly. Let's do 14172fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * the search. 14182fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o */ 14192fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o for (p = iter->node; p; p = p->next) { 14202fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (iter->name && strcmp(p->name, iter->name)) 14212fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o continue; 14222fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if ((iter->flags & PROFILE_ITER_SECTIONS_ONLY) && 14232fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o p->value) 14242fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o continue; 14252fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if ((iter->flags & PROFILE_ITER_RELATIONS_ONLY) && 14262fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o !p->value) 14272fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o continue; 14282fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (skip_num > 0) { 14292fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o skip_num--; 14302fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o continue; 14312fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } 14322fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (p->deleted) 14332fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o continue; 14342fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o break; 14352fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } 14362fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o iter->num++; 14372fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (!p) { 14382fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o iter->file = iter->file->next; 14392fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o iter->node = 0; 14402fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o skip_num = 0; 14412fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o goto get_new_file; 14422fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } 14432fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if ((iter->node = p->next) == NULL) 14442fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o iter->file = iter->file->next; 14452fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (ret_node) 14462fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o *ret_node = p; 14472fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (ret_name) 14482fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o *ret_name = p->name; 14492fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (ret_value) 14502fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o *ret_value = p->value; 14512fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return 0; 14522fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o} 14532fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 14542fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 14552fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o/* 14562fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * prof_get.c --- routines that expose the public interfaces for 14572fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * querying items from the profile. 14582fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * 14592fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o */ 14602fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 14612fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o/* 14622fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * This function only gets the first value from the file; it is a 14632fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * helper function for profile_get_string, profile_get_integer, etc. 14642fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o */ 14659a4c209cd26a7eae3d1de427d9b028f69e1c2554Theodore Ts'oerrcode_t profile_get_value(profile_t profile, const char *name, 14669a4c209cd26a7eae3d1de427d9b028f69e1c2554Theodore Ts'o const char *subname, const char *subsubname, 14672fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o const char **ret_value) 14682fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o{ 14692fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o errcode_t retval; 14702fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o void *state; 14712fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o char *value; 14729a4c209cd26a7eae3d1de427d9b028f69e1c2554Theodore Ts'o const char *names[4]; 14732fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 14749a4c209cd26a7eae3d1de427d9b028f69e1c2554Theodore Ts'o names[0] = name; 14759a4c209cd26a7eae3d1de427d9b028f69e1c2554Theodore Ts'o names[1] = subname; 14769a4c209cd26a7eae3d1de427d9b028f69e1c2554Theodore Ts'o names[2] = subsubname; 14779a4c209cd26a7eae3d1de427d9b028f69e1c2554Theodore Ts'o names[3] = 0; 14789a4c209cd26a7eae3d1de427d9b028f69e1c2554Theodore Ts'o 14799a4c209cd26a7eae3d1de427d9b028f69e1c2554Theodore Ts'o if ((retval = profile_iterator_create(profile, names, 14809a4c209cd26a7eae3d1de427d9b028f69e1c2554Theodore Ts'o PROFILE_ITER_RELATIONS_ONLY, 14819a4c209cd26a7eae3d1de427d9b028f69e1c2554Theodore Ts'o &state))) 14822fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return retval; 14832fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 14842fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if ((retval = profile_node_iterator(&state, 0, 0, &value))) 14852fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o goto cleanup; 14862fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 14872fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (value) 14882fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o *ret_value = value; 14892fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o else 14902fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o retval = PROF_NO_RELATION; 1491efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 14922fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'ocleanup: 14939a4c209cd26a7eae3d1de427d9b028f69e1c2554Theodore Ts'o profile_iterator_free(&state); 14942fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return retval; 14952fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o} 14962fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 1497efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'oerrcode_t 14982fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'oprofile_get_string(profile_t profile, const char *name, const char *subname, 14992fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o const char *subsubname, const char *def_val, 15002fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o char **ret_string) 15012fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o{ 15022fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o const char *value; 15032fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o errcode_t retval; 15042fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 15052fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (profile) { 1506efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o retval = profile_get_value(profile, name, subname, 15079a4c209cd26a7eae3d1de427d9b028f69e1c2554Theodore Ts'o subsubname, &value); 15082fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (retval == PROF_NO_SECTION || retval == PROF_NO_RELATION) 15092fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o value = def_val; 15102fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o else if (retval) 15112fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return retval; 15122fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } else 15132fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o value = def_val; 1514efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 15152fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (value) { 15162fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o *ret_string = malloc(strlen(value)+1); 15172fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (*ret_string == 0) 15182fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return ENOMEM; 15192fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o strcpy(*ret_string, value); 15202fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } else 15212fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o *ret_string = 0; 15222fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return 0; 15232fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o} 15242fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 1525efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'oerrcode_t 15262fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'oprofile_get_integer(profile_t profile, const char *name, const char *subname, 15272fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o const char *subsubname, int def_val, int *ret_int) 15282fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o{ 15292fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o const char *value; 15302fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o errcode_t retval; 15312fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o char *end_value; 15322fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o long ret_long; 15332fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 15342fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o *ret_int = def_val; 15352fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (profile == 0) 15362fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return 0; 15372fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 15389a4c209cd26a7eae3d1de427d9b028f69e1c2554Theodore Ts'o retval = profile_get_value(profile, name, subname, subsubname, &value); 15392fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (retval == PROF_NO_SECTION || retval == PROF_NO_RELATION) { 15402fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o *ret_int = def_val; 15412fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return 0; 15422fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } else if (retval) 15432fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return retval; 15442fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 15452fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (value[0] == 0) 15462fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o /* Empty string is no good. */ 15472fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return PROF_BAD_INTEGER; 15482fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o errno = 0; 1549a9d7fc69b6b0ef5ce02af387c8886fd9e56b463eTheodore Ts'o ret_long = strtol(value, &end_value, 0); 15502fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 15512fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o /* Overflow or underflow. */ 15522fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if ((ret_long == LONG_MIN || ret_long == LONG_MAX) && errno != 0) 15532fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return PROF_BAD_INTEGER; 15542fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o /* Value outside "int" range. */ 15552fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if ((long) (int) ret_long != ret_long) 15562fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return PROF_BAD_INTEGER; 15572fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o /* Garbage in string. */ 15582fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (end_value != value + strlen (value)) 15592fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return PROF_BAD_INTEGER; 1560efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 1561efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 15622fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o *ret_int = ret_long; 15632fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return 0; 15642fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o} 15652fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 1566efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'oerrcode_t 156732460c1e4c7259b532bdd1e74583c80f573b467aTheodore Ts'oprofile_get_uint(profile_t profile, const char *name, const char *subname, 1568efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o const char *subsubname, unsigned int def_val, 156932460c1e4c7259b532bdd1e74583c80f573b467aTheodore Ts'o unsigned int *ret_int) 157032460c1e4c7259b532bdd1e74583c80f573b467aTheodore Ts'o{ 157132460c1e4c7259b532bdd1e74583c80f573b467aTheodore Ts'o const char *value; 157232460c1e4c7259b532bdd1e74583c80f573b467aTheodore Ts'o errcode_t retval; 157332460c1e4c7259b532bdd1e74583c80f573b467aTheodore Ts'o char *end_value; 157432460c1e4c7259b532bdd1e74583c80f573b467aTheodore Ts'o unsigned long ret_long; 157532460c1e4c7259b532bdd1e74583c80f573b467aTheodore Ts'o 157632460c1e4c7259b532bdd1e74583c80f573b467aTheodore Ts'o *ret_int = def_val; 157732460c1e4c7259b532bdd1e74583c80f573b467aTheodore Ts'o if (profile == 0) 157832460c1e4c7259b532bdd1e74583c80f573b467aTheodore Ts'o return 0; 157932460c1e4c7259b532bdd1e74583c80f573b467aTheodore Ts'o 158032460c1e4c7259b532bdd1e74583c80f573b467aTheodore Ts'o retval = profile_get_value(profile, name, subname, subsubname, &value); 158132460c1e4c7259b532bdd1e74583c80f573b467aTheodore Ts'o if (retval == PROF_NO_SECTION || retval == PROF_NO_RELATION) { 158232460c1e4c7259b532bdd1e74583c80f573b467aTheodore Ts'o *ret_int = def_val; 158332460c1e4c7259b532bdd1e74583c80f573b467aTheodore Ts'o return 0; 158432460c1e4c7259b532bdd1e74583c80f573b467aTheodore Ts'o } else if (retval) 158532460c1e4c7259b532bdd1e74583c80f573b467aTheodore Ts'o return retval; 158632460c1e4c7259b532bdd1e74583c80f573b467aTheodore Ts'o 158732460c1e4c7259b532bdd1e74583c80f573b467aTheodore Ts'o if (value[0] == 0) 158832460c1e4c7259b532bdd1e74583c80f573b467aTheodore Ts'o /* Empty string is no good. */ 158932460c1e4c7259b532bdd1e74583c80f573b467aTheodore Ts'o return PROF_BAD_INTEGER; 159032460c1e4c7259b532bdd1e74583c80f573b467aTheodore Ts'o errno = 0; 1591a9d7fc69b6b0ef5ce02af387c8886fd9e56b463eTheodore Ts'o ret_long = strtoul(value, &end_value, 0); 159232460c1e4c7259b532bdd1e74583c80f573b467aTheodore Ts'o 159332460c1e4c7259b532bdd1e74583c80f573b467aTheodore Ts'o /* Overflow or underflow. */ 159432460c1e4c7259b532bdd1e74583c80f573b467aTheodore Ts'o if ((ret_long == ULONG_MAX) && errno != 0) 159532460c1e4c7259b532bdd1e74583c80f573b467aTheodore Ts'o return PROF_BAD_INTEGER; 159632460c1e4c7259b532bdd1e74583c80f573b467aTheodore Ts'o /* Value outside "int" range. */ 159732460c1e4c7259b532bdd1e74583c80f573b467aTheodore Ts'o if ((unsigned long) (unsigned int) ret_long != ret_long) 159832460c1e4c7259b532bdd1e74583c80f573b467aTheodore Ts'o return PROF_BAD_INTEGER; 159932460c1e4c7259b532bdd1e74583c80f573b467aTheodore Ts'o /* Garbage in string. */ 160032460c1e4c7259b532bdd1e74583c80f573b467aTheodore Ts'o if (end_value != value + strlen (value)) 160132460c1e4c7259b532bdd1e74583c80f573b467aTheodore Ts'o return PROF_BAD_INTEGER; 1602efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 160332460c1e4c7259b532bdd1e74583c80f573b467aTheodore Ts'o *ret_int = ret_long; 160432460c1e4c7259b532bdd1e74583c80f573b467aTheodore Ts'o return 0; 160532460c1e4c7259b532bdd1e74583c80f573b467aTheodore Ts'o} 160632460c1e4c7259b532bdd1e74583c80f573b467aTheodore Ts'o 1607d3859af33f5bbbc432dedb20e85a5ae62e0fff03Aditya Kalierrcode_t 1608d3859af33f5bbbc432dedb20e85a5ae62e0fff03Aditya Kaliprofile_get_double(profile_t profile, const char *name, const char *subname, 1609d3859af33f5bbbc432dedb20e85a5ae62e0fff03Aditya Kali const char *subsubname, double def_val, double *ret_double) 1610d3859af33f5bbbc432dedb20e85a5ae62e0fff03Aditya Kali{ 1611d3859af33f5bbbc432dedb20e85a5ae62e0fff03Aditya Kali const char *value; 1612d3859af33f5bbbc432dedb20e85a5ae62e0fff03Aditya Kali errcode_t retval; 1613d3859af33f5bbbc432dedb20e85a5ae62e0fff03Aditya Kali char *end_value; 1614d3859af33f5bbbc432dedb20e85a5ae62e0fff03Aditya Kali double double_val; 1615d3859af33f5bbbc432dedb20e85a5ae62e0fff03Aditya Kali 1616d3859af33f5bbbc432dedb20e85a5ae62e0fff03Aditya Kali *ret_double = def_val; 1617d3859af33f5bbbc432dedb20e85a5ae62e0fff03Aditya Kali if (profile == 0) 1618d3859af33f5bbbc432dedb20e85a5ae62e0fff03Aditya Kali return 0; 1619d3859af33f5bbbc432dedb20e85a5ae62e0fff03Aditya Kali 1620d3859af33f5bbbc432dedb20e85a5ae62e0fff03Aditya Kali retval = profile_get_value(profile, name, subname, subsubname, &value); 1621d3859af33f5bbbc432dedb20e85a5ae62e0fff03Aditya Kali if (retval == PROF_NO_SECTION || retval == PROF_NO_RELATION) { 1622d3859af33f5bbbc432dedb20e85a5ae62e0fff03Aditya Kali *ret_double = def_val; 1623d3859af33f5bbbc432dedb20e85a5ae62e0fff03Aditya Kali return 0; 1624d3859af33f5bbbc432dedb20e85a5ae62e0fff03Aditya Kali } else if (retval) 1625d3859af33f5bbbc432dedb20e85a5ae62e0fff03Aditya Kali return retval; 1626d3859af33f5bbbc432dedb20e85a5ae62e0fff03Aditya Kali 1627d3859af33f5bbbc432dedb20e85a5ae62e0fff03Aditya Kali if (value[0] == 0) 1628d3859af33f5bbbc432dedb20e85a5ae62e0fff03Aditya Kali /* Empty string is no good. */ 1629d3859af33f5bbbc432dedb20e85a5ae62e0fff03Aditya Kali return PROF_BAD_INTEGER; 1630d3859af33f5bbbc432dedb20e85a5ae62e0fff03Aditya Kali errno = 0; 1631d3859af33f5bbbc432dedb20e85a5ae62e0fff03Aditya Kali double_val = strtod(value, &end_value); 1632d3859af33f5bbbc432dedb20e85a5ae62e0fff03Aditya Kali 1633d3859af33f5bbbc432dedb20e85a5ae62e0fff03Aditya Kali /* Overflow or underflow. */ 1634d3859af33f5bbbc432dedb20e85a5ae62e0fff03Aditya Kali if (errno != 0) 1635d3859af33f5bbbc432dedb20e85a5ae62e0fff03Aditya Kali return PROF_BAD_INTEGER; 1636d3859af33f5bbbc432dedb20e85a5ae62e0fff03Aditya Kali /* Garbage in string. */ 1637d3859af33f5bbbc432dedb20e85a5ae62e0fff03Aditya Kali if (end_value != value + strlen(value)) 1638d3859af33f5bbbc432dedb20e85a5ae62e0fff03Aditya Kali return PROF_BAD_INTEGER; 1639d3859af33f5bbbc432dedb20e85a5ae62e0fff03Aditya Kali 1640d3859af33f5bbbc432dedb20e85a5ae62e0fff03Aditya Kali *ret_double = double_val; 1641d3859af33f5bbbc432dedb20e85a5ae62e0fff03Aditya Kali return 0; 1642d3859af33f5bbbc432dedb20e85a5ae62e0fff03Aditya Kali} 1643d3859af33f5bbbc432dedb20e85a5ae62e0fff03Aditya Kali 16442fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'ostatic const char *const conf_yes[] = { 16452fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o "y", "yes", "true", "t", "1", "on", 16462fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 0, 16472fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o}; 16482fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 16492fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'ostatic const char *const conf_no[] = { 16502fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o "n", "no", "false", "nil", "0", "off", 16512fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 0, 16522fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o}; 16532fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 16542fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'ostatic errcode_t 16552fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'oprofile_parse_boolean(const char *s, int *ret_boolean) 16562fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o{ 16572fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o const char *const *p; 1658efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 16592fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (ret_boolean == NULL) 16602fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return PROF_EINVAL; 16612fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 16622fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o for(p=conf_yes; *p; p++) { 16632fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (!strcasecmp(*p,s)) { 16642fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o *ret_boolean = 1; 16652fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return 0; 16662fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } 16672fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } 16682fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 16692fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o for(p=conf_no; *p; p++) { 16702fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (!strcasecmp(*p,s)) { 16712fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o *ret_boolean = 0; 16722fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return 0; 16732fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } 16742fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } 1675efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 16762fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return PROF_BAD_BOOLEAN; 16772fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o} 16782fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 1679efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'oerrcode_t 16802fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'oprofile_get_boolean(profile_t profile, const char *name, const char *subname, 16812fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o const char *subsubname, int def_val, int *ret_boolean) 16822fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o{ 16832fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o const char *value; 16842fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o errcode_t retval; 16852fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 16862fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (profile == 0) { 16872fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o *ret_boolean = def_val; 16882fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return 0; 16892fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } 16902fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 16919a4c209cd26a7eae3d1de427d9b028f69e1c2554Theodore Ts'o retval = profile_get_value(profile, name, subname, subsubname, &value); 16922fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (retval == PROF_NO_SECTION || retval == PROF_NO_RELATION) { 16932fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o *ret_boolean = def_val; 16942fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return 0; 16952fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } else if (retval) 16962fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return retval; 1697efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 16982fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return profile_parse_boolean (value, ret_boolean); 16992fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o} 17002fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 1701efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'oerrcode_t 17022fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'oprofile_iterator(void **iter_p, char **ret_name, char **ret_value) 17032fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o{ 17042fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o char *name, *value; 17052fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o errcode_t retval; 1706efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 17072fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o retval = profile_node_iterator(iter_p, 0, &name, &value); 17082fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (retval) 17092fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return retval; 17102fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 17112fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (ret_name) { 17122fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (name) { 17132fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o *ret_name = malloc(strlen(name)+1); 17142fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (!*ret_name) 17152fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return ENOMEM; 17162fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o strcpy(*ret_name, name); 17172fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } else 17182fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o *ret_name = 0; 17192fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } 17202fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (ret_value) { 17212fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (value) { 17222fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o *ret_value = malloc(strlen(value)+1); 17232fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (!*ret_value) { 17242fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (ret_name) { 17252fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o free(*ret_name); 17262fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o *ret_name = 0; 17272fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } 17282fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return ENOMEM; 17292fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } 17302fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o strcpy(*ret_value, value); 17312fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } else 17322fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o *ret_value = 0; 17332fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } 17342fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return 0; 17352fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o} 17362fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 17372fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o#ifdef DEBUG_PROGRAM 17382fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 17392fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o/* 17402fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o * test_profile.c --- testing program for the profile routine 17412fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o */ 17422fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 17432fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o#include "argv_parse.h" 17449a4c209cd26a7eae3d1de427d9b028f69e1c2554Theodore Ts'o#include "profile_helpers.h" 17452fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 17462fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'oconst char *program_name = "test_profile"; 17472fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 17482fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o#define PRINT_VALUE 1 17492fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o#define PRINT_VALUES 2 17502fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 175144dc5f8804b2480764f792315d84977ec9569163Theodore Ts'ostatic void do_cmd(profile_t profile, char **argv) 17522fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o{ 17532fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o errcode_t retval; 17542fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o const char **names, *value; 175544dc5f8804b2480764f792315d84977ec9569163Theodore Ts'o char **values, **cpp; 175644dc5f8804b2480764f792315d84977ec9569163Theodore Ts'o char *cmd; 17572fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o int print_status; 17582fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 175944dc5f8804b2480764f792315d84977ec9569163Theodore Ts'o cmd = *(argv); 176044dc5f8804b2480764f792315d84977ec9569163Theodore Ts'o names = (const char **) argv + 1; 176144dc5f8804b2480764f792315d84977ec9569163Theodore Ts'o print_status = 0; 176244dc5f8804b2480764f792315d84977ec9569163Theodore Ts'o retval = 0; 176344dc5f8804b2480764f792315d84977ec9569163Theodore Ts'o if (cmd == 0) 176444dc5f8804b2480764f792315d84977ec9569163Theodore Ts'o return; 176544dc5f8804b2480764f792315d84977ec9569163Theodore Ts'o if (!strcmp(cmd, "query")) { 176644dc5f8804b2480764f792315d84977ec9569163Theodore Ts'o retval = profile_get_values(profile, names, &values); 176744dc5f8804b2480764f792315d84977ec9569163Theodore Ts'o print_status = PRINT_VALUES; 176844dc5f8804b2480764f792315d84977ec9569163Theodore Ts'o } else if (!strcmp(cmd, "query1")) { 17699a4c209cd26a7eae3d1de427d9b028f69e1c2554Theodore Ts'o const char *name = 0; 17709a4c209cd26a7eae3d1de427d9b028f69e1c2554Theodore Ts'o const char *subname = 0; 17719a4c209cd26a7eae3d1de427d9b028f69e1c2554Theodore Ts'o const char *subsubname = 0; 17729a4c209cd26a7eae3d1de427d9b028f69e1c2554Theodore Ts'o 17739a4c209cd26a7eae3d1de427d9b028f69e1c2554Theodore Ts'o name = names[0]; 17749a4c209cd26a7eae3d1de427d9b028f69e1c2554Theodore Ts'o if (name) 17759a4c209cd26a7eae3d1de427d9b028f69e1c2554Theodore Ts'o subname = names[1]; 17769a4c209cd26a7eae3d1de427d9b028f69e1c2554Theodore Ts'o if (subname) 17779a4c209cd26a7eae3d1de427d9b028f69e1c2554Theodore Ts'o subsubname = names[2]; 17789a4c209cd26a7eae3d1de427d9b028f69e1c2554Theodore Ts'o if (subsubname && names[3]) { 1779efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o fprintf(stderr, 17809a4c209cd26a7eae3d1de427d9b028f69e1c2554Theodore Ts'o "Only 3 levels are allowed with query1\n"); 17819a4c209cd26a7eae3d1de427d9b028f69e1c2554Theodore Ts'o retval = EINVAL; 17829a4c209cd26a7eae3d1de427d9b028f69e1c2554Theodore Ts'o } else 1783efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o retval = profile_get_value(profile, name, subname, 17849a4c209cd26a7eae3d1de427d9b028f69e1c2554Theodore Ts'o subsubname, &value); 178544dc5f8804b2480764f792315d84977ec9569163Theodore Ts'o print_status = PRINT_VALUE; 178644dc5f8804b2480764f792315d84977ec9569163Theodore Ts'o } else if (!strcmp(cmd, "list_sections")) { 1787efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o retval = profile_get_subsection_names(profile, names, 178844dc5f8804b2480764f792315d84977ec9569163Theodore Ts'o &values); 178944dc5f8804b2480764f792315d84977ec9569163Theodore Ts'o print_status = PRINT_VALUES; 179044dc5f8804b2480764f792315d84977ec9569163Theodore Ts'o } else if (!strcmp(cmd, "list_relations")) { 1791efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o retval = profile_get_relation_names(profile, names, 179244dc5f8804b2480764f792315d84977ec9569163Theodore Ts'o &values); 179344dc5f8804b2480764f792315d84977ec9569163Theodore Ts'o print_status = PRINT_VALUES; 179444dc5f8804b2480764f792315d84977ec9569163Theodore Ts'o } else if (!strcmp(cmd, "dump")) { 179544dc5f8804b2480764f792315d84977ec9569163Theodore Ts'o retval = profile_write_tree_file 1796d45544ca5419e218537f8b9689bbb028abbf8f28Theodore Ts'o (profile->first_file->root, stdout); 179744dc5f8804b2480764f792315d84977ec9569163Theodore Ts'o#if 0 179844dc5f8804b2480764f792315d84977ec9569163Theodore Ts'o } else if (!strcmp(cmd, "clear")) { 179944dc5f8804b2480764f792315d84977ec9569163Theodore Ts'o retval = profile_clear_relation(profile, names); 180044dc5f8804b2480764f792315d84977ec9569163Theodore Ts'o } else if (!strcmp(cmd, "update")) { 180144dc5f8804b2480764f792315d84977ec9569163Theodore Ts'o retval = profile_update_relation(profile, names+2, 180244dc5f8804b2480764f792315d84977ec9569163Theodore Ts'o *names, *(names+1)); 180344dc5f8804b2480764f792315d84977ec9569163Theodore Ts'o#endif 180444dc5f8804b2480764f792315d84977ec9569163Theodore Ts'o } else if (!strcmp(cmd, "verify")) { 180544dc5f8804b2480764f792315d84977ec9569163Theodore Ts'o retval = profile_verify_node 1806d45544ca5419e218537f8b9689bbb028abbf8f28Theodore Ts'o (profile->first_file->root); 180744dc5f8804b2480764f792315d84977ec9569163Theodore Ts'o#if 0 180844dc5f8804b2480764f792315d84977ec9569163Theodore Ts'o } else if (!strcmp(cmd, "rename_section")) { 180944dc5f8804b2480764f792315d84977ec9569163Theodore Ts'o retval = profile_rename_section(profile, names+1, *names); 181044dc5f8804b2480764f792315d84977ec9569163Theodore Ts'o } else if (!strcmp(cmd, "add")) { 181144dc5f8804b2480764f792315d84977ec9569163Theodore Ts'o value = *names; 181244dc5f8804b2480764f792315d84977ec9569163Theodore Ts'o if (strcmp(value, "NULL") == 0) 181344dc5f8804b2480764f792315d84977ec9569163Theodore Ts'o value = NULL; 181444dc5f8804b2480764f792315d84977ec9569163Theodore Ts'o retval = profile_add_relation(profile, names+1, value); 181544dc5f8804b2480764f792315d84977ec9569163Theodore Ts'o } else if (!strcmp(cmd, "flush")) { 181644dc5f8804b2480764f792315d84977ec9569163Theodore Ts'o retval = profile_flush(profile); 181744dc5f8804b2480764f792315d84977ec9569163Theodore Ts'o#endif 181844dc5f8804b2480764f792315d84977ec9569163Theodore Ts'o } else { 181944dc5f8804b2480764f792315d84977ec9569163Theodore Ts'o printf("Invalid command.\n"); 182044dc5f8804b2480764f792315d84977ec9569163Theodore Ts'o } 182144dc5f8804b2480764f792315d84977ec9569163Theodore Ts'o if (retval) { 182244dc5f8804b2480764f792315d84977ec9569163Theodore Ts'o com_err(cmd, retval, ""); 182344dc5f8804b2480764f792315d84977ec9569163Theodore Ts'o print_status = 0; 182444dc5f8804b2480764f792315d84977ec9569163Theodore Ts'o } 182544dc5f8804b2480764f792315d84977ec9569163Theodore Ts'o switch (print_status) { 182644dc5f8804b2480764f792315d84977ec9569163Theodore Ts'o case PRINT_VALUE: 182744dc5f8804b2480764f792315d84977ec9569163Theodore Ts'o printf("%s\n", value); 182844dc5f8804b2480764f792315d84977ec9569163Theodore Ts'o break; 182944dc5f8804b2480764f792315d84977ec9569163Theodore Ts'o case PRINT_VALUES: 183044dc5f8804b2480764f792315d84977ec9569163Theodore Ts'o for (cpp = values; *cpp; cpp++) 183144dc5f8804b2480764f792315d84977ec9569163Theodore Ts'o printf("%s\n", *cpp); 183244dc5f8804b2480764f792315d84977ec9569163Theodore Ts'o profile_free_list(values); 183344dc5f8804b2480764f792315d84977ec9569163Theodore Ts'o break; 183444dc5f8804b2480764f792315d84977ec9569163Theodore Ts'o } 183544dc5f8804b2480764f792315d84977ec9569163Theodore Ts'o} 183644dc5f8804b2480764f792315d84977ec9569163Theodore Ts'o 183744dc5f8804b2480764f792315d84977ec9569163Theodore Ts'ostatic void do_batchmode(profile_t profile) 183844dc5f8804b2480764f792315d84977ec9569163Theodore Ts'o{ 183944dc5f8804b2480764f792315d84977ec9569163Theodore Ts'o int argc, ret; 184044dc5f8804b2480764f792315d84977ec9569163Theodore Ts'o char **argv; 184144dc5f8804b2480764f792315d84977ec9569163Theodore Ts'o char buf[256]; 184244dc5f8804b2480764f792315d84977ec9569163Theodore Ts'o 18432fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o while (!feof(stdin)) { 18442fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (fgets(buf, sizeof(buf), stdin) == NULL) 18452fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o break; 18462fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o printf(">%s", buf); 18472fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o ret = argv_parse(buf, &argc, &argv); 18482fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (ret != 0) { 18492fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o printf("Argv_parse returned %d!\n", ret); 18502fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o continue; 18512fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } 185244dc5f8804b2480764f792315d84977ec9569163Theodore Ts'o do_cmd(profile, argv); 18532fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o printf("\n"); 18542fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o argv_free(argv); 18552fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } 18562fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o profile_release(profile); 18572fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o exit(0); 1858efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 18592fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o} 18602fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 1861f5f14fcfe9eba0282a3dfe5600364bbf797dcfc3Theodore Ts'ovoid syntax_err_report(const char *filename, long err, int line_num) 1862f5f14fcfe9eba0282a3dfe5600364bbf797dcfc3Theodore Ts'o{ 1863f5f14fcfe9eba0282a3dfe5600364bbf797dcfc3Theodore Ts'o fprintf(stderr, "Syntax error in %s, line number %d: %s\n", 1864f5f14fcfe9eba0282a3dfe5600364bbf797dcfc3Theodore Ts'o filename, line_num, error_message(err)); 1865f5f14fcfe9eba0282a3dfe5600364bbf797dcfc3Theodore Ts'o exit(1); 1866f5f14fcfe9eba0282a3dfe5600364bbf797dcfc3Theodore Ts'o} 18672fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 18686f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'oconst char *default_str = "[foo]\n\tbar=quux\n\tsub = {\n\t\twin = true\n}\n"; 18696f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o 187044dc5f8804b2480764f792315d84977ec9569163Theodore Ts'oint main(int argc, char **argv) 18712fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o{ 18722fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o profile_t profile; 18732fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o long retval; 18742fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o char *cmd; 1875efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 18762fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (argc < 2) { 18772fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o fprintf(stderr, "Usage: %s filename [cmd argset]\n", program_name); 18782fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o exit(1); 18792fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } 18802fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 18812fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o initialize_prof_error_table(); 1882f5f14fcfe9eba0282a3dfe5600364bbf797dcfc3Theodore Ts'o 1883f5f14fcfe9eba0282a3dfe5600364bbf797dcfc3Theodore Ts'o profile_set_syntax_err_cb(syntax_err_report); 1884efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 18852fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o retval = profile_init_path(argv[1], &profile); 18862fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (retval) { 18872fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o com_err(program_name, retval, "while initializing profile"); 18882fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o exit(1); 18892fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o } 18906f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o retval = profile_set_default(profile, default_str); 18916f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o if (retval) { 18926f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o com_err(program_name, retval, "while setting default"); 18936f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o exit(1); 18946f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o } 18956f890e516d1eddb52a566d1f77888c9edf5772f2Theodore Ts'o 18962fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o cmd = *(argv+2); 18972fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o if (!cmd || !strcmp(cmd, "batch")) 18982fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o do_batchmode(profile); 189944dc5f8804b2480764f792315d84977ec9569163Theodore Ts'o else 190044dc5f8804b2480764f792315d84977ec9569163Theodore Ts'o do_cmd(profile, argv+2); 19012fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o profile_release(profile); 19022fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 19032fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o return 0; 19042fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o} 19052fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o 19062fa9ba98337b07d6acfac52b5ee5dc8116dda866Theodore Ts'o#endif 1907