1/* 2 * Unix SMB/CIFS implementation. 3 * Copyright (C) Jelmer Vernooij 2005 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 3 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, see <http://www.gnu.org/licenses/>. 17 */ 18 19#include "includes.h" 20#include "../lib/util/dlinklist.h" 21#include "param/param.h" 22#include "param/loadparm.h" 23#include "system/filesys.h" 24 25struct param_section *param_get_section(struct param_context *ctx, const char *name) 26{ 27 struct param_section *sect; 28 29 if (name == NULL) 30 name = GLOBAL_NAME; 31 32 for (sect = ctx->sections; sect; sect = sect->next) { 33 if (!strcasecmp_m(sect->name, name)) 34 return sect; 35 } 36 37 return NULL; 38} 39 40struct parmlist_entry *param_section_get(struct param_section *section, const char *name) 41{ 42 return parmlist_get(section->parameters, name); 43} 44 45struct param_section *param_add_section(struct param_context *ctx, const char *section_name) 46{ 47 struct param_section *section; 48 section = talloc_zero(ctx, struct param_section); 49 if (section == NULL) 50 return NULL; 51 52 section->name = talloc_strdup(section, section_name); 53 DLIST_ADD_END(ctx->sections, section, struct param_section *); 54 return section; 55} 56 57/* Look up parameter. If it is not found, add it */ 58struct parmlist_entry *param_get_add(struct param_context *ctx, const char *name, const char *section_name) 59{ 60 struct param_section *section; 61 struct parmlist_entry *p; 62 63 SMB_ASSERT(section_name != NULL); 64 SMB_ASSERT(name != NULL); 65 66 section = param_get_section(ctx, section_name); 67 68 if (section == NULL) { 69 section = param_add_section(ctx, section_name); 70 } 71 72 p = param_section_get(section, name); 73 if (p == NULL) { 74 p = talloc_zero(section, struct parmlist_entry); 75 if (p == NULL) 76 return NULL; 77 78 p->key = talloc_strdup(p, name); 79 DLIST_ADD_END(section->parameters->entries, p, struct parmlist_entry *); 80 } 81 82 return p; 83} 84 85const char *param_get_string(struct param_context *ctx, const char *param, const char *section_name) 86{ 87 struct param_section *section = param_get_section(ctx, section_name); 88 89 if (section == NULL) 90 return NULL; 91 92 return parmlist_get_string(section->parameters, param, NULL); 93} 94 95int param_set_string(struct param_context *ctx, const char *param, const char *value, const char *section_name) 96{ 97 struct param_section *section = param_get_section(ctx, section_name); 98 99 if (section == NULL) 100 return -1; 101 102 return parmlist_set_string(section->parameters, param, value); 103} 104 105const char **param_get_string_list(struct param_context *ctx, const char *param, const char *separator, const char *section_name) 106{ 107 struct param_section *section = param_get_section(ctx, section_name); 108 109 if (section == NULL) 110 return NULL; 111 112 return parmlist_get_string_list(section->parameters, param, separator); 113} 114 115int param_set_string_list(struct param_context *ctx, const char *param, const char **list, const char *section) 116{ 117 struct parmlist_entry *p = param_get_add(ctx, param, section); 118 119 p->value = str_list_join(p, list, ' '); 120 121 return 0; 122} 123 124int param_get_int(struct param_context *ctx, const char *param, int default_v, const char *section_name) 125{ 126 struct param_section *section = param_get_section(ctx, section_name); 127 128 if (section == NULL) 129 return default_v; 130 131 return parmlist_get_int(section->parameters, param, default_v); 132} 133 134void param_set_int(struct param_context *ctx, const char *param, int value, const char *section) 135{ 136 struct parmlist_entry *p = param_get_add(ctx, section, param); 137 138 if (!p) 139 return; 140 141 p->value = talloc_asprintf(p, "%d", value); 142} 143 144unsigned long param_get_ulong(struct param_context *ctx, const char *param, unsigned long default_v, const char *section) 145{ 146 const char *value = param_get_string(ctx, param, section); 147 148 if (value) 149 return strtoul(value, NULL, 0); 150 151 return default_v; 152} 153 154void param_set_ulong(struct param_context *ctx, const char *name, unsigned long value, const char *section) 155{ 156 struct parmlist_entry *p = param_get_add(ctx, name, section); 157 158 if (!p) 159 return; 160 161 p->value = talloc_asprintf(p, "%lu", value); 162} 163 164static bool param_sfunc (const char *name, void *_ctx) 165{ 166 struct param_context *ctx = (struct param_context *)_ctx; 167 struct param_section *section = param_get_section(ctx, name); 168 169 if (section == NULL) { 170 section = talloc_zero(ctx, struct param_section); 171 if (section == NULL) 172 return false; 173 174 section->name = talloc_strdup(section, name); 175 176 DLIST_ADD_END(ctx->sections, section, struct param_section *); 177 } 178 179 /* Make sure this section is on top of the list for param_pfunc */ 180 DLIST_PROMOTE(ctx->sections, section); 181 182 return true; 183} 184 185static bool param_pfunc (const char *name, const char *value, void *_ctx) 186{ 187 struct param_context *ctx = (struct param_context *)_ctx; 188 struct parmlist_entry *p = param_section_get(ctx->sections, name); 189 190 if (!p) { 191 p = talloc_zero(ctx->sections, struct parmlist_entry); 192 if (p == NULL) 193 return false; 194 195 p->key = talloc_strdup(p, name); 196 p->value = talloc_strdup(p, value); 197 DLIST_ADD(ctx->sections->parameters->entries, p); 198 } else { /* Replace current value */ 199 talloc_free(p->value); 200 p->value = talloc_strdup(p, value); 201 } 202 203 return true; 204} 205 206struct param_context *param_init(TALLOC_CTX *mem_ctx) 207{ 208 return talloc_zero(mem_ctx, struct param_context); 209} 210 211 212int param_read(struct param_context *ctx, const char *fn) 213{ 214 ctx->sections = talloc_zero(ctx, struct param_section); 215 if (ctx->sections == NULL) 216 return -1; 217 218 ctx->sections->name = talloc_strdup(ctx->sections, "global"); 219 if (!pm_process( fn, param_sfunc, param_pfunc, ctx)) { 220 return -1; 221 } 222 223 return 0; 224} 225 226int param_use(struct loadparm_context *lp_ctx, struct param_context *ctx) 227{ 228 struct param_section *section; 229 230 for (section = ctx->sections; section; section = section->next) { 231 struct parmlist_entry *param; 232 bool isglobal = strcmp(section->name, "global") == 0; 233 for (param = section->parameters->entries; param; param = param->next) { 234 if (isglobal) 235 lp_do_global_parameter(lp_ctx, param->key, 236 param->value); 237 else { 238 struct loadparm_service *service = 239 lp_service(lp_ctx, section->name); 240 if (service == NULL) 241 service = lp_add_service(lp_ctx, lp_default_service(lp_ctx), section->name); 242 lp_do_service_parameter(lp_ctx, service, param->key, param->value); 243 } 244 } 245 } 246 return 0; 247} 248 249int param_write(struct param_context *ctx, const char *fn) 250{ 251 int file; 252 struct param_section *section; 253 254 if (fn == NULL || ctx == NULL) 255 return -1; 256 257 file = open(fn, O_WRONLY|O_CREAT, 0755); 258 259 if (file == -1) 260 return -1; 261 262 for (section = ctx->sections; section; section = section->next) { 263 struct parmlist_entry *param; 264 265 fdprintf(file, "[%s]\n", section->name); 266 for (param = section->parameters->entries; param; param = param->next) { 267 fdprintf(file, "\t%s = %s\n", param->key, param->value); 268 } 269 fdprintf(file, "\n"); 270 } 271 272 close(file); 273 274 return 0; 275} 276