1 /* 2 * Copyright (c) 2018 The Linux Foundation. All rights reserved. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for 5 * any purpose with or without fee is hereby granted, provided that the 6 * above copyright notice and this permission notice appear in all 7 * copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 15 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 16 * PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include "qdf_file.h" 20 #include "qdf_module.h" 21 #include "qdf_parse.h" 22 #include "qdf_status.h" 23 #include "qdf_str.h" 24 #include "qdf_trace.h" 25 #include "qdf_types.h" 26 27 QDF_STATUS qdf_ini_parse(const char *ini_path, void *context, 28 qdf_ini_item_cb item_cb, qdf_ini_section_cb section_cb) 29 { 30 QDF_STATUS status; 31 char *fbuf; 32 char *cursor; 33 34 status = qdf_file_read(ini_path, &fbuf); 35 if (QDF_IS_STATUS_ERROR(status)) { 36 qdf_err("Failed to read *.ini file @ %s", ini_path); 37 return status; 38 } 39 40 /* foreach line */ 41 cursor = fbuf; 42 while (*cursor != '\0') { 43 char *key = cursor; 44 char *value = NULL; 45 bool comment = false; 46 bool eol = false; 47 48 /* 49 * Look for the end of the line, while noting any 50 * value ('=') or comment ('#') indicators 51 */ 52 while (!eol) { 53 switch (*cursor) { 54 case '\r': 55 case '\n': 56 *cursor = '\0'; 57 cursor++; 58 /* fall through */ 59 case '\0': 60 eol = true; 61 break; 62 63 case '=': 64 /* 65 * The first '=' is the value indicator. 66 * Subsequent '=' are valid value characters. 67 */ 68 if (!value && !comment) { 69 value = cursor + 1; 70 *cursor = '\0'; 71 } 72 73 cursor++; 74 break; 75 76 case '#': 77 /* 78 * We don't process comments, so we can null- 79 * terminate unconditionally here (unlike '='). 80 */ 81 comment = true; 82 *cursor = '\0'; 83 /* fall through */ 84 default: 85 cursor++; 86 break; 87 } 88 } 89 90 key = qdf_str_trim(key); 91 92 /* 93 * Ignoring comments, a valid ini line contains one of: 94 * 1) some 'key=value' config item 95 * 2) section header 96 * 3) a line containing whitespace 97 */ 98 if (value) { 99 status = item_cb(context, key, value); 100 if (QDF_IS_STATUS_ERROR(status)) 101 goto free_fbuf; 102 } else if (key[0] == '[') { 103 qdf_size_t len = qdf_str_len(key); 104 105 if (key[len - 1] != ']') { 106 qdf_err("Invalid *.ini syntax '%s'", key); 107 } else { 108 key[len - 1] = '\0'; 109 status = section_cb(context, key + 1); 110 if (QDF_IS_STATUS_ERROR(status)) 111 goto free_fbuf; 112 } 113 } else if (key[0] != '\0') { 114 qdf_err("Invalid *.ini syntax '%s'", key); 115 } 116 117 /* skip remaining EoL characters */ 118 while (*cursor == '\n' || *cursor == '\r') 119 cursor++; 120 } 121 122 status = QDF_STATUS_SUCCESS; 123 124 free_fbuf: 125 qdf_file_buf_free(fbuf); 126 127 return status; 128 } 129 qdf_export_symbol(qdf_ini_parse); 130 131