From d0821f99a693cf9aef8c50d2639c5ca772becae1 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 13 Apr 2002 10:52:31 +0000 Subject: Patch for arbitary smb.conf paramaters (to make the life of plugin maintainers sane) from ab. Attached is his e-mail to the samba-technical list, as it describes it rather well: Andrew Bartlett Subject: [PATCH] Parametrical options support for Samba 3.0 Date: Fri, 12 Apr 2002 19:13:13 +0300 From: Alexander Bokovoy To: samba-technical@samba.org CC: tridge@samba.org Greetings! Attached patch makes possible arbitrary options to be specified in smb.conf and later queried from VFS modules (and other places) without problems. Below such options are called 'parametrical options'. Patch introduces new notation to smb.conf option's language, as discussed today with Tridgell on @samba-technical: TYPE: OPTION = VALUE Colon sign is important here, it is what distinguishes parametrical options from ones hardcoded in param/loadparm.c. TYPE is 'option domain', OPTION is option name itself. In order to access values of parametrical options, lp_parm_string() function was implemented: char *lp_parm_string(const char *servicename, const char *type, const char *option); This function accepts service name, type and option name, and returns value of option or NULL if this option is underfined. Service name can be NULL, resulting in search in 'global' section only. If option does not exist in specified service, 'global' section is scanned. This allows propagation of globally specified options to all services and later overloading of the option in some services. Caution: 'TYPE: OPTION' combination is case sensitive. So far, testparm is able to handle parametrical options, while SWAT can't. Thus, everyone familiar with SWAT internals is welcomed to add parametrical options support. (This used to be commit bfd7cd43556bed3131d0d18869abfd1cbc30bcd0) --- source3/param/loadparm.c | 116 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 112 insertions(+), 4 deletions(-) diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index 39e7ce6e4f..17b9f022f0 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -6,6 +6,7 @@ Largely re-written by Andrew Tridgell, September 1994 Copyright (C) Simo Sorce 2001 + Copyright (C) Alexander Bokovoy 2002 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -1802,6 +1803,48 @@ FN_GLOBAL_INTEGER(lp_winbind_cache_time, &Globals.winbind_cache_time) FN_GLOBAL_BOOL(lp_hide_local_users, &Globals.bHideLocalUsers) FN_GLOBAL_BOOL(lp_algorithmic_rid_base, &Globals.bAlgorithmicRidBase) +typedef struct _param_opt_struct param_opt_struct; +struct _param_opt_struct { + char *key; + char *value; + param_opt_struct *prev, *next; +}; + +static param_opt_struct *param_opt = NULL; + +/* Return parametric option from given service. Type is a part of option before ':' */ +/* Parametric option has following syntax: 'Type: option = value' */ +/* Returned value is allocated in 'lp_talloc' context */ +char *lp_parm_string(const char *servicename, const char *type, const char *option) +{ + param_opt_struct *data; + pstring vfskey; + + if (param_opt != NULL) { + ZERO_STRUCT(vfskey); + pstr_sprintf(vfskey, "%s:%s:%s", (servicename==NULL) ? "global" : servicename, + type, option); + data = param_opt; + while (data) { + if (strcmp(data->key, vfskey) == 0) { + return lp_string(data->value); + } + data = data->next; + } + /* Try to fetch the same option but from globals */ + pstr_sprintf(vfskey, "global:%s:%s", type, option); + data = param_opt; + while (data) { + if (strcmp(data->key, vfskey) == 0) { + return lp_string(data->value); + } + data = data->next; + } + + } + return NULL; +} + /* local prototypes */ static int map_parameter(char *pszParmName); @@ -2054,7 +2097,12 @@ static int map_parameter(char *pszParmName) if (strwicmp(parm_table[iIndex].label, pszParmName) == 0) return (iIndex); - DEBUG(0, ("Unknown parameter encountered: \"%s\"\n", pszParmName)); + /* Warn only if it isn't parametric option */ + if (strchr(pszParmName, ':') == NULL) + DEBUG(0, ("Unknown parameter encountered: \"%s\"\n", pszParmName)); + /* We do return 'fail' for parametric options as well because they are + stored in different storage + */ return (-1); } @@ -2780,14 +2828,32 @@ then assume we are in the globals ***************************************************************************/ BOOL lp_do_parameter(int snum, char *pszParmName, char *pszParmValue) { - int parmnum, i; + int parmnum, i, slen; void *parm_ptr = NULL; /* where we are going to store the result */ void *def_ptr = NULL; + pstring vfskey; + char *sep; + param_opt_struct *paramo; parmnum = map_parameter(pszParmName); if (parmnum < 0) { + if ((sep=strchr(pszParmName, ':')) != NULL) { + *sep = 0; + ZERO_STRUCT(vfskey); + pstr_sprintf(vfskey, "%s:%s:", + (snum >= 0) ? lp_servicename(snum) : "global", pszParmName); + slen = strlen(vfskey); + safe_strcat(vfskey, sep+1, sizeof(pstring)); + trim_string(vfskey+slen, " ", " "); + paramo = smb_xmalloc(sizeof(param_opt_struct)); + paramo->key = strdup(vfskey); + paramo->value = strdup(pszParmValue); + DLIST_ADD(param_opt, paramo); + *sep = ':'; + return (True); + } DEBUG(0, ("Ignoring unknown parameter \"%s\"\n", pszParmName)); return (True); @@ -3147,6 +3213,9 @@ Display the contents of the global structure. static void dump_globals(FILE *f) { int i; + param_opt_struct *data; + char *s; + fprintf(f, "# Global parameters\n[global]\n"); for (i = 0; parm_table[i].label; i++) @@ -3160,6 +3229,17 @@ static void dump_globals(FILE *f) print_parameter(&parm_table[i], parm_table[i].ptr, f); fprintf(f, "\n"); } + if (param_opt != NULL) { + data = param_opt; + while(data) { + if (((s=strstr(data->key, "global")) == data->key) && + (*(s+strlen("global")) == ':')) { + fprintf(f, "\t%s = %s\n", s+strlen("global")+1, data->value); + } + data = data->next; + } + } + } /*************************************************************************** @@ -3174,13 +3254,15 @@ BOOL lp_is_default(int snum, struct parm_struct *parm) ((char *)&sDefault) + pdiff); } - /*************************************************************************** Display the contents of a single services record. ***************************************************************************/ static void dump_a_service(service * pService, FILE * f) { int i; + param_opt_struct *data; + char *s, *sn; + if (pService != &sDefault) fprintf(f, "\n[%s]\n", pService->szService); @@ -3212,6 +3294,17 @@ static void dump_a_service(service * pService, FILE * f) ((char *)pService) + pdiff, f); fprintf(f, "\n"); } + if (param_opt != NULL) { + data = param_opt; + sn = (pService == &sDefault) ? "global" : pService->szService; + while(data) { + if (((s=strstr(data->key, sn)) == data->key) && + (*(s+strlen(sn)) == ':')) { + fprintf(f, "\t%s = %s\n", s+strlen(sn)+1, data->value); + } + data = data->next; + } + } } @@ -3492,6 +3585,7 @@ static void set_server_role(void) } + /*************************************************************************** Load the services array from the services file. Return True on success, False on failure. @@ -3501,6 +3595,7 @@ BOOL lp_load(const char *pszFname, BOOL global_only, BOOL save_defaults, { pstring n2; BOOL bRetval; + param_opt_struct *data, *pdata; pstrcpy(n2, pszFname); standard_sub_basic(current_user_info.smb_name, n2); @@ -3509,6 +3604,8 @@ BOOL lp_load(const char *pszFname, BOOL global_only, BOOL save_defaults, bRetval = False; + DEBUG(3, ("lp_load: refreshing parmaters\n")); + bInGlobalSection = True; bGlobalOnly = global_only; @@ -3520,6 +3617,18 @@ BOOL lp_load(const char *pszFname, BOOL global_only, BOOL save_defaults, lp_save_defaults(); } + if (param_opt != NULL) { + data = param_opt; + while (data) { + SAFE_FREE(data->key); + SAFE_FREE(data->value); + pdata = data->next; + SAFE_FREE(data); + data = pdata; + } + param_opt = NULL; + } + /* We get sections first, so have to start 'behind' to make up */ iServiceIndex = -1; bRetval = pm_process(n2, do_section, do_parameter); @@ -3553,7 +3662,6 @@ BOOL lp_load(const char *pszFname, BOOL global_only, BOOL save_defaults, return (bRetval); } - /*************************************************************************** reset the max number of services ***************************************************************************/ -- cgit