From: Jelmer Vernooij Date: Thu, 24 Apr 2003 03:46:17 +0000 (+0000) Subject: Patch from Stephan Metzmacher to add default arguments to lp_parm() smb.conf X-Git-Url: http://git.samba.org/?a=commitdiff_plain;h=1f008c1203b082039a9824c186fa2eda730c6f46;p=metze%2Fsamba%2Fwip.git Patch from Stephan Metzmacher to add default arguments to lp_parm() smb.conf parameters. Does not break binary compatibility with older modules. (This used to be commit 147c4d56d873a20a49194c5b036a3694299b1b48) --- diff --git a/source3/include/smb_macros.h b/source3/include/smb_macros.h index 8efb966d0b8e..b39c7a0ebcec 100644 --- a/source3/include/smb_macros.h +++ b/source3/include/smb_macros.h @@ -98,8 +98,11 @@ #define ERROR_WAS_LOCK_DENIED(status) (NT_STATUS_EQUAL((status), NT_STATUS_LOCK_NOT_GRANTED) || \ NT_STATUS_EQUAL((status), NT_STATUS_FILE_LOCK_CONFLICT) ) +/* the service number for the [globals] defaults */ +#define GLOBAL_SECTION_SNUM (-1) /* translates a connection number into a service number */ -#define SNUM(conn) ((conn)?(conn)->service:-1) +#define SNUM(conn) ((conn)?(conn)->service:GLOBAL_SECTION_SNUM) + /* access various service details */ #define SERVICE(snum) (lp_servicename(snum)) diff --git a/source3/modules/vfs_recycle.c b/source3/modules/vfs_recycle.c index 5372a7e64c15..85ce257c0264 100644 --- a/source3/modules/vfs_recycle.c +++ b/source3/modules/vfs_recycle.c @@ -37,7 +37,7 @@ static const char *delimiter = "|"; /* delimiter for options */ typedef struct recycle_bin_struct { - TALLOC_CTX *ctx; + TALLOC_CTX *mem_ctx; char *repository; /* name of the recycle bin directory */ BOOL keep_dir_tree; /* keep directory structure of deleted file in recycle bin */ BOOL versions; /* create versions of deleted files with identical name */ @@ -48,6 +48,19 @@ typedef struct recycle_bin_struct SMB_OFF_T maxsize; /* maximum file size to be saved */ } recycle_bin_struct; +typedef struct recycle_bin_connections { + int conn; + recycle_bin_struct *data; + struct recycle_bin_connections *next; +} recycle_bin_connections; + +typedef struct recycle_bin_private_data { + TALLOC_CTX *mem_ctx; + recycle_bin_connections *conns; +} recycle_bin_private_data; + +struct smb_vfs_handle_struct *recycle_bin_private_handle; + /* VFS operations */ static struct vfs_ops default_vfs_ops; /* For passthrough operation */ @@ -69,16 +82,6 @@ static vfs_op_tuple recycle_ops[] = { {NULL, SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP} }; -static BOOL check_bool_param(const char *value) -{ - if (strwicmp(value, "yes") == 0 || - strwicmp(value, "true") == 0 || - strwicmp(value, "1") == 0) - return True; - - return False; -} - /** * VFS initialisation function. * @@ -87,6 +90,8 @@ static BOOL check_bool_param(const char *value) static vfs_op_tuple *recycle_init(const struct vfs_ops *def_vfs_ops, struct smb_vfs_handle_struct *vfs_handle) { + TALLOC_CTX *mem_ctx = NULL; + DEBUG(10, ("Initializing VFS module recycle\n")); memcpy(&default_vfs_ops, def_vfs_ops, sizeof(struct vfs_ops)); vfs_recycle_debug_level = debug_add_class("vfs_recycle_bin"); @@ -97,6 +102,20 @@ static vfs_op_tuple *recycle_init(const struct vfs_ops *def_vfs_ops, DEBUG(0, ("vfs_recycle: Debug class number of 'vfs_recycle': %d\n", vfs_recycle_debug_level)); } + recycle_bin_private_handle = vfs_handle; + if (!(mem_ctx = talloc_init("recycle bin data"))) { + DEBUG(0, ("Failed to allocate memory in VFS module recycle_bin\n")); + return NULL; + } + + recycle_bin_private_handle->data = talloc(mem_ctx, sizeof(recycle_bin_private_data)); + if (recycle_bin_private_handle->data == NULL) { + DEBUG(0, ("Failed to allocate memory in VFS module recycle_bin\n")); + return NULL; + } + ((recycle_bin_private_data *)(recycle_bin_private_handle->data))->mem_ctx = mem_ctx; + ((recycle_bin_private_data *)(recycle_bin_private_handle->data))->conns = NULL; + return recycle_ops; } @@ -104,84 +123,91 @@ static int recycle_connect(struct connection_struct *conn, const char *service, { TALLOC_CTX *ctx = NULL; recycle_bin_struct *recbin; - char *servicename; - char *tmp_str; + recycle_bin_connections *recconn; + recycle_bin_connections *recconnbase; + recycle_bin_private_data *recdata; + const char *tmp_str; DEBUG(10, ("Called for service %s (%d) as user %s\n", service, SNUM(conn), user)); - if (!(ctx = talloc_init("recycle bin"))) { - DEBUG(0, ("Failed to allocate memory in VFS module recycle_bin\n")); - return 0; + if (recycle_bin_private_handle) + recdata = (recycle_bin_private_data *)(recycle_bin_private_handle->data); + else { + DEBUG(0, ("Recycle bin not initialized!\n")); + return -1; } - recbin = talloc(ctx,sizeof(recycle_bin_struct)); - if ( recbin == NULL) { + if (!(ctx = talloc_init("recycle bin connection"))) { DEBUG(0, ("Failed to allocate memory in VFS module recycle_bin\n")); return -1; } - recbin->ctx = ctx; - /* Set defaults */ - recbin->repository = talloc_strdup(ctx, ".recycle"); - ALLOC_CHECK(recbin->repository, error); - recbin->keep_dir_tree = False; - recbin->versions = False; - recbin->touch = False; - recbin->exclude = ""; - recbin->exclude_dir = ""; - recbin->noversions = ""; - recbin->maxsize = 0; + recbin = talloc_zero(ctx, sizeof(recycle_bin_struct)); + if (recbin == NULL) { + DEBUG(0, ("Failed to allocate memory in VFS module recycle_bin\n")); + return -1; + } + recbin->mem_ctx = ctx; /* parse configuration options */ - servicename = talloc_strdup(recbin->ctx, lp_servicename(SNUM(conn))); - DEBUG(10, ("servicename = %s\n",servicename)); - if ((tmp_str = lp_parm_string(servicename, "vfs_recycle_bin", "repository")) != NULL) { - recbin->repository = talloc_sub_conn(ctx, conn, tmp_str); + if ((tmp_str = lp_parm_const_string(SNUM(conn), "vfs_recycle_bin", "repository", ".recycle")) != NULL) { + recbin->repository = talloc_sub_conn(recbin->mem_ctx, conn, tmp_str); ALLOC_CHECK(recbin->repository, error); trim_string(recbin->repository, "/", "/"); DEBUG(5, ("recycle.bin: repository = %s\n", recbin->repository)); + } else { + DEBUG(0,("recycle.bin: no repository found (fail) !\n")); + goto error; + } + + recbin->keep_dir_tree = lp_parm_bool(SNUM(conn), "vfs_recycle_bin", "keeptree", False); + DEBUG(5, ("recycle.bin: keeptree = %d\n", recbin->keep_dir_tree)); + + recbin->versions = lp_parm_bool(SNUM(conn), "vfs_recycle_bin", "versions", False); + DEBUG(5, ("recycle.bin: versions = %d\n", recbin->versions)); + + recbin->touch = lp_parm_bool(SNUM(conn), "vfs_recycle_bin", "touch", False); + DEBUG(5, ("recycle.bin: touch = %d\n", recbin->touch)); + + recbin->maxsize = lp_parm_ulong(SNUM(conn), "vfs_recycle_bin", "maxsize" , 0); + if (recbin->maxsize == 0) { + recbin->maxsize = -1; + DEBUG(5, ("recycle.bin: maxsize = -infinite-\n")); + } else { + DEBUG(5, ("recycle.bin: maxsize = %ld\n", (long int)recbin->maxsize)); } - if ((tmp_str = lp_parm_string(servicename, "vfs_recycle_bin", "keeptree")) != NULL) { - if (check_bool_param(tmp_str) == True) - recbin->keep_dir_tree = True; - DEBUG(5, ("recycle.bin: keeptree = %s\n", tmp_str)); - } - if ((tmp_str = lp_parm_string(servicename, "vfs_recycle_bin", "versions")) != NULL) { - if (check_bool_param(tmp_str) == True) - recbin->versions = True; - DEBUG(5, ("recycle.bin: versions = %s\n", tmp_str)); - } - if ((tmp_str = lp_parm_string(servicename, "vfs_recycle_bin", "touch")) != NULL) { - if (check_bool_param(tmp_str) == True) - recbin->touch = True; - DEBUG(5, ("recycle.bin: touch = %s\n", tmp_str)); - } - if ((tmp_str = lp_parm_string(servicename, "vfs_recycle_bin", "maxsize")) != NULL) { - recbin->maxsize = strtoul(tmp_str, NULL, 10); - if (recbin->maxsize == 0) { - recbin->maxsize = -1; - DEBUG(5, ("recycle.bin: maxsize = -infinite-\n")); - } else { - DEBUG(5, ("recycle.bin: maxsize = %ld\n", (long int)recbin->maxsize)); - } - } - if ((tmp_str = lp_parm_string(servicename, "vfs_recycle_bin", "exclude")) != NULL) { - recbin->exclude = talloc_strdup(ctx, tmp_str); + + if ((tmp_str = lp_parm_const_string(SNUM(conn), "vfs_recycle_bin", "exclude", "")) != NULL) { + recbin->exclude = talloc_strdup(recbin->mem_ctx, tmp_str); ALLOC_CHECK(recbin->exclude, error); DEBUG(5, ("recycle.bin: exclude = %s\n", recbin->exclude)); } - if ((tmp_str = lp_parm_string(servicename,"vfs_recycle_bin", "exclude_dir")) != NULL) { - recbin->exclude_dir = talloc_strdup(ctx, tmp_str); + if ((tmp_str = lp_parm_const_string(SNUM(conn), "vfs_recycle_bin", "exclude_dir", "")) != NULL) { + recbin->exclude_dir = talloc_strdup(recbin->mem_ctx, tmp_str); ALLOC_CHECK(recbin->exclude_dir, error); DEBUG(5, ("recycle.bin: exclude_dir = %s\n", recbin->exclude_dir)); } - if ((tmp_str = lp_parm_string(servicename,"vfs_recycle_bin", "noversions")) != NULL) { - recbin->noversions = talloc_strdup(ctx, tmp_str); + if ((tmp_str = lp_parm_const_string(SNUM(conn), "vfs_recycle_bin", "noversions", "")) != NULL) { + recbin->noversions = talloc_strdup(recbin->mem_ctx, tmp_str); ALLOC_CHECK(recbin->noversions, error); DEBUG(5, ("recycle.bin: noversions = %s\n", recbin->noversions)); } - conn->vfs_private = (void *)recbin; + recconn = talloc(recdata->mem_ctx, sizeof(recycle_bin_connections)); + if (recconn == NULL) { + DEBUG(0, ("Failed to allocate memory in VFS module recycle_bin\n")); + goto error; + } + recconn->conn = SNUM(conn); + recconn->data = recbin; + recconn->next = NULL; + if (recdata->conns) { + recconnbase = recdata->conns; + while (recconnbase->next != NULL) recconnbase = recconnbase->next; + recconnbase->next = recconn; + } else { + recdata->conns = recconn; + } return default_vfs_ops.connect(conn, service, user); error: @@ -191,10 +217,35 @@ error: static void recycle_disconnect(struct connection_struct *conn) { + recycle_bin_private_data *recdata; + recycle_bin_connections *recconn; + DEBUG(10, ("Disconnecting VFS module recycle bin\n")); - if (conn->vfs_private) { - talloc_destroy(((recycle_bin_struct *)conn->vfs_private)->ctx); - conn->vfs_private = NULL; + + if (recycle_bin_private_handle) + recdata = (recycle_bin_private_data *)(recycle_bin_private_handle->data); + else { + DEBUG(0, ("Recycle bin not initialized!\n")); + return; + } + + if (recdata) { + if (recdata->conns) { + if (recdata->conns->conn == SNUM(conn)) { + talloc_destroy(recdata->conns->data->mem_ctx); + recdata->conns = recdata->conns->next; + } else { + recconn = recdata->conns; + while (recconn->next) { + if (recconn->next->conn == SNUM(conn)) { + talloc_destroy(recconn->next->data->mem_ctx); + recconn->next = recconn->next->next; + break; + } + recconn = recconn->next; + } + } + } } default_vfs_ops.disconnect(conn); } @@ -379,26 +430,35 @@ static void recycle_touch(connection_struct *conn, const char *fname) /** * Check if file should be recycled **/ -static int recycle_unlink(connection_struct *conn, const char *inname) +static int recycle_unlink(connection_struct *conn, const char *file_name) { + recycle_bin_private_data *recdata; + recycle_bin_connections *recconn; recycle_bin_struct *recbin; - char *file_name = NULL; char *path_name = NULL; char *temp_name = NULL; char *final_name = NULL; - char *base; + const char *base; int i; - SMB_BIG_UINT dfree, dsize, bsize; - SMB_OFF_T file_size, space_avail; +/* SMB_BIG_UINT dfree, dsize, bsize; */ + SMB_OFF_T file_size; /* space_avail; */ BOOL exist; int rc = -1; - file_name = strdup(inname); - ALLOC_CHECK(file_name, done); - - if (conn->vfs_private) - recbin = (recycle_bin_struct *)conn->vfs_private; - else { + recbin = NULL; + if (recycle_bin_private_handle) { + recdata = (recycle_bin_private_data *)(recycle_bin_private_handle->data); + if (recdata) { + if (recdata->conns) { + recconn = recdata->conns; + while (recconn && recconn->conn != SNUM(conn)) recconn = recconn->next; + if (recconn != NULL) { + recbin = recconn->data; + } + } + } + } + if (recbin == NULL) { DEBUG(0, ("Recycle bin not initialized!\n")); rc = default_vfs_ops.unlink(conn, file_name); goto done; @@ -504,10 +564,9 @@ static int recycle_unlink(connection_struct *conn, const char *inname) } } - final_name = (char *)malloc(PATH_MAX); + asprintf(&final_name, "%s/%s", temp_name, base); ALLOC_CHECK(final_name, done); - snprintf(final_name, PATH_MAX, "%s/%s", temp_name, base); - DEBUG(10, ("recycle.bin: recycled file name%s\n", temp_name)); /* new filename with path */ + DEBUG(10, ("recycle.bin: recycled file name: %s\n", temp_name)); /* new filename with path */ /* check if we should delete file from recycle bin */ if (recycle_file_exist(conn, final_name)) { @@ -538,7 +597,6 @@ static int recycle_unlink(connection_struct *conn, const char *inname) recycle_touch(conn, final_name); done: - SAFE_FREE(file_name); SAFE_FREE(path_name); SAFE_FREE(temp_name); SAFE_FREE(final_name); @@ -546,6 +604,6 @@ done: } int vfs_recycle_init(void) -{ - return smb_register_vfs("recycle", recycle_init, SMB_VFS_INTERFACE_VERSION); +{ + return smb_register_vfs("recycle", recycle_init, SMB_VFS_INTERFACE_VERSION); } diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index 90cf288430c4..c96e750a542a 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -81,6 +81,14 @@ extern int extra_time_offset; static BOOL defaults_saved = False; +typedef struct _param_opt_struct param_opt_struct; +struct _param_opt_struct { + param_opt_struct *prev, *next; + char *key; + char *value; + char **list; +}; + /* * This structure describes global (ie., server-wide) parameters. */ @@ -278,6 +286,7 @@ typedef struct int restrict_anonymous; int name_cache_timeout; BOOL client_signing; + param_opt_struct *param_opt; } global; @@ -400,6 +409,7 @@ typedef struct BOOL bNTAclSupport; BOOL bUseSendfile; BOOL bProfileAcls; + param_opt_struct *param_opt; char dummy[3]; /* for alignment */ } @@ -520,6 +530,8 @@ static service sDefault = { True, /* bNTAclSupport */ False, /* bUseSendfile */ False, /* bProfileAcls */ + + NULL, /* Parametric options */ "" /* dummy */ }; @@ -1856,49 +1868,6 @@ FN_GLOBAL_BOOL(lp_algorithmic_rid_base, &Globals.bAlgorithmicRidBase) FN_GLOBAL_INTEGER(lp_name_cache_timeout, &Globals.name_cache_timeout) FN_GLOBAL_BOOL(lp_client_signing, &Globals.client_signing) -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(const char *pszParmName); @@ -1912,6 +1881,238 @@ static BOOL do_parameter(const char *pszParmName, const char *pszParmValue); static BOOL do_section(const char *pszSectionName); static void init_copymap(service * pservice); +/* This is a helper function for parametrical options support. */ +/* It returns a pointer to parametrical option value if it exists or NULL otherwise */ +/* Actual parametrical functions are quite simple */ +static param_opt_struct *get_parametrics(int snum, const char *type, const char *option) +{ + BOOL global_section = False; + char* param_key; + param_opt_struct *data; + + if (snum >= iNumServices) return NULL; + + if (snum < 0) { + data = Globals.param_opt; + global_section = True; + } else { + data = ServicePtrs[snum]->param_opt; + } + + asprintf(¶m_key, "%s:%s", type, option); + if (!param_key) { + DEBUG(0,("asprintf failed!\n")); + return NULL; + } + + while (data) { + if (strcmp(data->key, param_key) == 0) { + string_free(¶m_key); + return data; + } + data = data->next; + } + + if (!global_section) { + /* Try to fetch the same option but from globals */ + /* but only if we are not already working with Globals */ + data = Globals.param_opt; + while (data) { + if (strcmp(data->key, param_key) == 0) { + string_free(¶m_key); + return data; + } + data = data->next; + } + } + + string_free(¶m_key); + + return NULL; +} + + +/******************************************************************* +convenience routine to return int parameters. +********************************************************************/ +static int lp_int(const char *s) +{ + + if (!s) { + DEBUG(0,("lp_int(%s): is called with NULL!\n",s)); + return (-1); + } + + return atoi(s); +} + +/******************************************************************* +convenience routine to return unsigned long parameters. +********************************************************************/ +static int lp_ulong(const char *s) +{ + + if (!s) { + DEBUG(0,("lp_int(%s): is called with NULL!\n",s)); + return (-1); + } + + return strtoul(s, NULL, 10); +} + +/******************************************************************* +convenience routine to return boolean parameters. +********************************************************************/ +static BOOL lp_bool(const char *s) +{ + BOOL ret = False; + + if (!s) { + DEBUG(0,("lp_bool(%s): is called with NULL!\n",s)); + return False; + } + + if (!set_boolean(&ret,s)) { + DEBUG(0,("lp_bool(%s): value is not boolean!\n",s)); + return False; + } + + return ret; +} + +/******************************************************************* +convenience routine to return enum parameters. +********************************************************************/ +static int lp_enum(const char *s,const struct enum_list *_enum) +{ + int i; + + if (!s || !_enum) { + DEBUG(0,("lp_enum(%s,enum): is called with NULL!\n",s)); + return (-1); + } + + for (i=0; _enum[i].name; i++) { + if (strcasecmp(_enum[i].name,s)==0) + return _enum[i].value; + } + + DEBUG(0,("lp_enum(%s,enum): value is not in enum_list!\n",s)); + return (-1); +} + + +/* DO NOT USE lp_parm_string ANYMORE!!!! + * use lp_parm_const_string or lp_parm_talloc_string + * + * lp_parm_string is only used to let old modules find this symbol + */ +#undef lp_parm_string + char *lp_parm_string(const char *servicename, const char *type, const char *option) +{ + return lp_parm_talloc_string(lp_servicenumber(servicename), type, option, NULL); +} + +/* Return parametric option from a given service. Type is a part of option before ':' */ +/* Parametric option has following syntax: 'Type: option = value' */ +/* the returned value is talloced in lp_talloc */ +char *lp_parm_talloc_string(int snum, const char *type, const char *option, const char *def) +{ + param_opt_struct *data = get_parametrics(snum, type, option); + + if (data == NULL||data->value==NULL) { + if (def) { + return lp_string(def); + } else { + return NULL; + } + } + + return lp_string(data->value); +} + +/* Return parametric option from a given service. Type is a part of option before ':' */ +/* Parametric option has following syntax: 'Type: option = value' */ +const char *lp_parm_const_string(int snum, const char *type, const char *option, const char *def) +{ + param_opt_struct *data = get_parametrics(snum, type, option); + + if (data == NULL||data->value==NULL) + return def; + + return data->value; +} + +/* Return parametric option from a given service. Type is a part of option before ':' */ +/* Parametric option has following syntax: 'Type: option = value' */ + +const char **lp_parm_string_list(int snum, const char *type, const char *option, const char **def) +{ + param_opt_struct *data = get_parametrics(snum, type, option); + + if (data == NULL||data->value==NULL) + return (const char **)def; + + if (data->list==NULL) { + data->list = str_list_make(data->value, NULL); + } + + return (const char **)data->list; +} + +/* Return parametric option from a given service. Type is a part of option before ':' */ +/* Parametric option has following syntax: 'Type: option = value' */ + +int lp_parm_int(int snum, const char *type, const char *option, int def) +{ + param_opt_struct *data = get_parametrics(snum, type, option); + + if (data && data->value && *data->value) + return lp_int(data->value); + + return def; +} + +/* Return parametric option from a given service. Type is a part of option before ':' */ +/* Parametric option has following syntax: 'Type: option = value' */ + +unsigned long lp_parm_ulong(int snum, const char *type, const char *option, unsigned long def) +{ + param_opt_struct *data = get_parametrics(snum, type, option); + + if (data && data->value && *data->value) + return lp_ulong(data->value); + + return def; +} + +/* Return parametric option from a given service. Type is a part of option before ':' */ +/* Parametric option has following syntax: 'Type: option = value' */ + +BOOL lp_parm_bool(int snum, const char *type, const char *option, BOOL def) +{ + param_opt_struct *data = get_parametrics(snum, type, option); + + if (data && data->value && *data->value) + return lp_bool(data->value); + + return def; +} + +/* Return parametric option from a given service. Type is a part of option before ':' */ +/* Parametric option has following syntax: 'Type: option = value' */ + +int lp_parm_enum(int snum, const char *type, const char *option, + const struct enum_list *_enum, int def) +{ + param_opt_struct *data = get_parametrics(snum, type, option); + + if (data && data->value && *data->value && _enum) + return lp_enum(data->value, _enum); + + return def; +} + /*************************************************************************** Initialise a service to the defaults. @@ -1930,6 +2131,7 @@ static void init_service(service * pservice) static void free_service(service *pservice) { int i; + param_opt_struct *data, *pdata; if (!pservice) return; @@ -1953,7 +2155,19 @@ static void free_service(service *pservice) (((char *)pservice) + PTR_DIFF(parm_table[i].ptr, &sDefault))); } - + + data = pservice->param_opt; + if (data) + DEBUG(5,("Freeing parametrics:\n")); + while (data) { + DEBUG(5,("[%s = %s]\n", data->key, data->value)); + string_free(&data->key); + string_free(&data->value); + str_list_free(&data->list); + pdata = data->next; + SAFE_FREE(data); + data = pdata; + } ZERO_STRUCTP(pservice); } @@ -1968,14 +2182,28 @@ static int add_a_service(const service *pservice, const char *name) int i; service tservice; int num_to_alloc = iNumServices + 1; + param_opt_struct *data, *pdata; tservice = *pservice; /* it might already exist */ if (name) { i = getservicebyname(name, NULL); - if (i >= 0) + if (i >= 0) { + /* Clean all parametric options for service */ + /* They will be added during parsing again */ + data = ServicePtrs[i]->param_opt; + while (data) { + string_free(&data->key); + string_free(&data->value); + str_list_free(&data->list); + pdata = data->next; + SAFE_FREE(data); + data = pdata; + } + ServicePtrs[i]->param_opt = NULL; return (i); + } } /* find an invalid one */ @@ -2035,7 +2263,7 @@ BOOL lp_add_home(const char *pszHomename, int iDefaultService, return (False); if (!(*(ServicePtrs[iDefaultService]->szPath)) - || strequal(ServicePtrs[iDefaultService]->szPath, lp_pathname(-1))) { + || strequal(ServicePtrs[iDefaultService]->szPath, lp_pathname(GLOBAL_SECTION_SNUM))) { pstrcpy(newHomedir, pszHomedir); } else { pstrcpy(newHomedir, lp_pathname(iDefaultService)); @@ -2219,6 +2447,8 @@ static void copy_service(service * pserviceDest, service * pserviceSource, BOOL { int i; BOOL bcopyall = (pcopymapDest == NULL); + param_opt_struct *data, *pdata, *paramo; + BOOL not_added; for (i = 0; parm_table[i].label; i++) if (parm_table[i].ptr && parm_table[i].class == P_LOCAL && @@ -2272,6 +2502,32 @@ static void copy_service(service * pserviceDest, service * pserviceSource, BOOL (void *)pserviceSource->copymap, sizeof(BOOL) * NUMPARAMETERS); } + + data = pserviceSource->param_opt; + while (data) { + not_added = True; + pdata = pserviceDest->param_opt; + /* Traverse destination */ + while (pdata) { + /* If we already have same option, override it */ + if (strcmp(pdata->key, data->key) == 0) { + string_free(&pdata->value); + str_list_free(&data->list); + pdata->value = strdup(data->value); + not_added = False; + break; + } + pdata = pdata->next; + } + if (not_added) { + paramo = smb_xmalloc(sizeof(param_opt_struct)); + paramo->key = strdup(data->key); + paramo->value = strdup(data->value); + paramo->list = NULL; + DLIST_ADD(pserviceDest->param_opt, paramo); + } + data = data->next; + } } /*************************************************************************** @@ -2868,25 +3124,48 @@ BOOL lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue int parmnum, i, slen; void *parm_ptr = NULL; /* where we are going to store the result */ void *def_ptr = NULL; - pstring vfskey; + pstring param_key; char *sep; - param_opt_struct *paramo; + param_opt_struct *paramo, *data; + BOOL not_added; 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); - pstrcat(vfskey, sep+1); - 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 = '\0'; + ZERO_STRUCT(param_key); + pstr_sprintf(param_key, "%s:", pszParmName); + slen = strlen(param_key); + pstrcat(param_key, sep+1); + trim_string(param_key+slen, " ", " "); + not_added = True; + data = (snum < 0) ? Globals.param_opt : + ServicePtrs[snum]->param_opt; + /* Traverse destination */ + while (data) { + /* If we already have same option, override it */ + if (strcmp(data->key, param_key) == 0) { + string_free(&data->value); + str_list_free(&data->list); + data->value = strdup(pszParmValue); + not_added = False; + break; + } + data = data->next; + } + if (not_added) { + paramo = smb_xmalloc(sizeof(param_opt_struct)); + paramo->key = strdup(param_key); + paramo->value = strdup(pszParmValue); + paramo->list = NULL; + if (snum < 0) { + DLIST_ADD(Globals.param_opt, paramo); + } else { + DLIST_ADD(ServicePtrs[snum]->param_opt, paramo); + } + } + *sep = ':'; return (True); } @@ -3236,7 +3515,6 @@ static void dump_globals(FILE *f) { int i; param_opt_struct *data; - char *s; fprintf(f, "# Global parameters\n[global]\n"); @@ -3250,14 +3528,11 @@ 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; + if (Globals.param_opt != NULL) { + data = Globals.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; + fprintf(f, "\t%s = %s\n", data->key, data->value); + data = data->next; } } @@ -3284,8 +3559,6 @@ static void dump_a_service(service * pService, FILE * f) { int i; param_opt_struct *data; - const char *sn; - char *s; if (pService != &sDefault) fprintf(f, "\n[%s]\n", pService->szService); @@ -3314,28 +3587,24 @@ 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; + if (pService->param_opt != NULL) { + data = pService->param_opt; 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; + fprintf(f, "\t%s = %s\n", data->key, data->value); + data = data->next; } } } /*************************************************************************** - Return info about the next service in a service. snum==-1 gives the globals. + Return info about the next service in a service. snum==GLOBAL_SECTION_SNUM gives the globals. Return NULL when out of parameters. ***************************************************************************/ struct parm_struct *lp_next_parameter(int snum, int *i, int allparameters) { - if (snum == -1) { + if (snum < 0) { /* do the globals */ for (; parm_table[*i].label; (*i)++) { if (parm_table[*i].class == P_SEPARATOR) @@ -3657,16 +3926,17 @@ BOOL lp_load(const char *pszFname, BOOL global_only, BOOL save_defaults, lp_save_defaults(); } - if (param_opt != NULL) { - data = param_opt; + if (Globals.param_opt != NULL) { + data = Globals.param_opt; while (data) { - SAFE_FREE(data->key); - SAFE_FREE(data->value); + string_free(&data->key); + string_free(&data->value); + str_list_free(&data->list); pdata = data->next; SAFE_FREE(data); data = pdata; } - param_opt = NULL; + Globals.param_opt = NULL; } /* We get sections first, so have to start 'behind' to make up */ @@ -3696,7 +3966,7 @@ BOOL lp_load(const char *pszFname, BOOL global_only, BOOL save_defaults, /* Now we check bWINSsupport and set szWINSserver to 127.0.0.1 */ /* if bWINSsupport is true and we are in the client */ if (in_client && Globals.bWINSsupport) { - lp_do_parameter(-1, "wins server", "127.0.0.1"); + lp_do_parameter(GLOBAL_SECTION_SNUM, "wins server", "127.0.0.1"); } init_iconv(); @@ -3765,8 +4035,10 @@ int lp_servicenumber(const char *pszServiceName) { int iService; fstring serviceName; - - + + if (!pszServiceName) + return GLOBAL_SECTION_SNUM; + for (iService = iNumServices - 1; iService >= 0; iService--) { if (VALID(iService) && ServicePtrs[iService]->szService) { /* @@ -3780,8 +4052,10 @@ int lp_servicenumber(const char *pszServiceName) } } - if (iService < 0) + if (iService < 0) { DEBUG(7,("lp_servicenumber: couldn't find %s\n", pszServiceName)); + return GLOBAL_SECTION_SNUM; + } return (iService); } diff --git a/source3/passdb/pdb_mysql.c b/source3/passdb/pdb_mysql.c index f3cb998ee156..ec8c6f9ab8a3 100644 --- a/source3/passdb/pdb_mysql.c +++ b/source3/passdb/pdb_mysql.c @@ -25,12 +25,12 @@ #define CONFIG_LOGON_TIME_DEFAULT "logon_time" #define CONFIG_LOGOFF_TIME_DEFAULT "logoff_time" #define CONFIG_KICKOFF_TIME_DEFAULT "kickoff_time" -#define CONFIG_PASS_LAST_SET_TIME_DEFAULT "pass_last_set_time" -#define CONFIG_PASS_CAN_CHANGE_TIME_DEFAULT "pass_can_change_time" -#define CONFIG_PASS_MUST_CHANGE_TIME_DEFAULT "pass_must_change_time" +#define CONFIG_PASS_LAST_SET_TIME_DEFAULT "pass_last_set_time" +#define CONFIG_PASS_CAN_CHANGE_TIME_DEFAULT "pass_can_change_time" +#define CONFIG_PASS_MUST_CHANGE_TIME_DEFAULT "pass_must_change_time" #define CONFIG_USERNAME_DEFAULT "username" #define CONFIG_DOMAIN_DEFAULT "domain" -#define CONFIG_NT_USERNAME_DEFAULT "nt_username" +#define CONFIG_NT_USERNAME_DEFAULT "nt_username" #define CONFIG_FULLNAME_DEFAULT "nt_fullname" #define CONFIG_HOME_DIR_DEFAULT "home_dir" #define CONFIG_DIR_DRIVE_DEFAULT "dir_drive" @@ -40,8 +40,8 @@ #define CONFIG_WORKSTATIONS_DEFAULT "workstations" #define CONFIG_UNKNOWN_STR_DEFAULT "unknown_str" #define CONFIG_MUNGED_DIAL_DEFAULT "munged_dial" -#define CONFIG_UID_DEFAULT "uid" -#define CONFIG_GID_DEFAULT "gid" +#define CONFIG_UID_DEFAULT "uid" +#define CONFIG_GID_DEFAULT "gid" #define CONFIG_USER_SID_DEFAULT "user_sid" #define CONFIG_GROUP_SID_DEFAULT "group_sid" #define CONFIG_LM_PW_DEFAULT "lm_pw" @@ -53,11 +53,11 @@ #define CONFIG_HOURS_LEN_DEFAULT "hours_len" #define CONFIG_UNKNOWN_5_DEFAULT "unknown_5" #define CONFIG_UNKNOWN_6_DEFAULT "unknown_6" -#define CONFIG_HOST_DEFAULT "localhost" -#define CONFIG_USER_DEFAULT "samba" -#define CONFIG_PASS_DEFAULT "" -#define CONFIG_PORT_DEFAULT "3306" -#define CONFIG_DB_DEFAULT "samba" +#define CONFIG_HOST_DEFAULT "localhost" +#define CONFIG_USER_DEFAULT "samba" +#define CONFIG_PASS_DEFAULT "" +#define CONFIG_PORT_DEFAULT "3306" +#define CONFIG_DB_DEFAULT "samba" static int mysqlsam_debug_level = DBGC_ALL; @@ -91,7 +91,7 @@ typedef struct pdb_mysql_query { } static void pdb_mysql_int_field(struct pdb_methods *m, - struct pdb_mysql_query *q, char *name, int value) + struct pdb_mysql_query *q, const char *name, int value) { if (!name || strchr(name, '\'')) return; /* This field shouldn't be set by us */ @@ -110,7 +110,7 @@ static void pdb_mysql_int_field(struct pdb_methods *m, static NTSTATUS pdb_mysql_string_field(struct pdb_methods *methods, struct pdb_mysql_query *q, - char *name, const char *value) + const char *name, const char *value) { char *esc_value; struct pdb_mysql_data *data; @@ -145,20 +145,17 @@ static NTSTATUS pdb_mysql_string_field(struct pdb_methods *methods, return NT_STATUS_OK; } -static char * config_value(pdb_mysql_data * data, char *name, char *default_value) -{ - if (lp_parm_string(NULL, data->location, name)) - return lp_parm_string(NULL, data->location, name); +#define config_value(data,name,default_value) \ + lp_parm_const_string(GLOBAL_SECTION_SNUM, (data)->location, name, default_value) - return default_value; -} +static const char * config_value_write(pdb_mysql_data * data, const char *name, const char *default_value) { + char const *v = NULL; + char const *swrite = NULL; -static char * config_value_write(pdb_mysql_data * data, char *name, char *default_value) { - char *v = config_value(data, name, NULL); - char *swrite; + v = lp_parm_const_string(GLOBAL_SECTION_SNUM, data->location, name, default_value); if (!v) - return default_value; + return NULL; swrite = strchr(v, ':'); @@ -176,13 +173,15 @@ static char * config_value_write(pdb_mysql_data * data, char *name, char *defaul return swrite; } -static const char * config_value_read(pdb_mysql_data * data, char *name, char *default_value) +static const char * config_value_read(pdb_mysql_data * data, const char *name, const char *default_value) { - char *v = config_value(data, name, NULL); + char *v = NULL; char *swrite; + v = lp_parm_talloc_string(GLOBAL_SECTION_SNUM, data->location, name, default_value); + if (!v) - return default_value; + return "NULL"; swrite = strchr(v, ':'); @@ -190,7 +189,7 @@ static const char * config_value_read(pdb_mysql_data * data, char *name, char *d if (!swrite) { if (strlen(v) == 0) return "NULL"; - return v; + return (const char *)v; } /* Otherwise, we have to cut the ':write_part' */ @@ -198,11 +197,11 @@ static const char * config_value_read(pdb_mysql_data * data, char *name, char *d if (strlen(v) == 0) return "NULL"; - return v; + return (const char *)v; } /* Wrapper for atol that returns 0 if 'a' points to NULL */ -static long xatol(char *a) +static long xatol(const char *a) { long ret = 0; @@ -369,7 +368,7 @@ static NTSTATUS mysqlsam_setsampwent(struct pdb_methods *methods, BOOL update) } DEBUG(5, - ("mysqlsam_setsampwent succeeded(%lu results)!\n", + ("mysqlsam_setsampwent succeeded(%llu results)!\n", mysql_num_rows(data->pwent))); return NT_STATUS_OK; @@ -893,59 +892,6 @@ static NTSTATUS mysqlsam_update_sam_account(struct pdb_methods *methods, return mysqlsam_replace_sam_account(methods, newpwd, 1); } -static NTSTATUS mysqlsam_getgrsid(struct pdb_methods *methods, GROUP_MAP *map, - DOM_SID sid, BOOL with_priv) -{ - return get_group_map_from_sid(sid, map, with_priv) ? - NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL; -} - -static NTSTATUS mysqlsam_getgrgid(struct pdb_methods *methods, GROUP_MAP *map, - gid_t gid, BOOL with_priv) -{ - return get_group_map_from_gid(gid, map, with_priv) ? - NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL; -} - -static NTSTATUS mysqlsam_getgrnam(struct pdb_methods *methods, GROUP_MAP *map, - char *name, BOOL with_priv) -{ - return get_group_map_from_ntname(name, map, with_priv) ? - NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL; -} - -static NTSTATUS mysqlsam_add_group_mapping_entry(struct pdb_methods *methods, - GROUP_MAP *map) -{ - return add_mapping_entry(map, TDB_INSERT) ? - NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL; -} - -static NTSTATUS mysqlsam_update_group_mapping_entry(struct pdb_methods *methods, - GROUP_MAP *map) -{ - return add_mapping_entry(map, TDB_REPLACE) ? - NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL; -} - -static NTSTATUS mysqlsam_delete_group_mapping_entry(struct pdb_methods *methods, - DOM_SID sid) -{ - return group_map_remove(sid) ? - NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL; -} - -static NTSTATUS mysqlsam_enum_group_mapping(struct pdb_methods *methods, - enum SID_NAME_USE sid_name_use, - GROUP_MAP **rmap, int *num_entries, - BOOL unix_only, BOOL with_priv) -{ - return enum_group_mapping(sid_name_use, rmap, num_entries, unix_only, - with_priv) ? - NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL; -} - - static NTSTATUS mysqlsam_init(struct pdb_context * pdb_context, struct pdb_methods ** pdb_method, const char *location) { @@ -979,13 +925,6 @@ static NTSTATUS mysqlsam_init(struct pdb_context * pdb_context, struct pdb_metho (*pdb_method)->add_sam_account = mysqlsam_add_sam_account; (*pdb_method)->update_sam_account = mysqlsam_update_sam_account; (*pdb_method)->delete_sam_account = mysqlsam_delete_sam_account; - (*pdb_method)->getgrsid = mysqlsam_getgrsid; - (*pdb_method)->getgrgid = mysqlsam_getgrgid; - (*pdb_method)->getgrnam = mysqlsam_getgrnam; - (*pdb_method)->add_group_mapping_entry = mysqlsam_add_group_mapping_entry; - (*pdb_method)->update_group_mapping_entry = mysqlsam_update_group_mapping_entry; - (*pdb_method)->delete_group_mapping_entry = mysqlsam_delete_group_mapping_entry; - (*pdb_method)->enum_group_mapping = mysqlsam_enum_group_mapping; data = talloc(pdb_context->mem_ctx, sizeof(struct pdb_mysql_data)); (*pdb_method)->private_data = data; @@ -993,7 +932,7 @@ static NTSTATUS mysqlsam_init(struct pdb_context * pdb_context, struct pdb_metho data->pwent = NULL; if (!location) { - DEBUG(0, ("No identifier specified. See README for details\n")); + DEBUG(0, ("No identifier specified. Check the Samba HOWTO Collection for details\n")); return NT_STATUS_INVALID_PARAMETER; } @@ -1032,7 +971,7 @@ static NTSTATUS mysqlsam_init(struct pdb_context * pdb_context, struct pdb_metho return NT_STATUS_OK; } -int pdb_mysql_init() +int pdb_mysql_init(void) { return smb_register_passdb("mysql", mysqlsam_init, PASSDB_INTERFACE_VERSION); } diff --git a/source3/passdb/pdb_xml.c b/source3/passdb/pdb_xml.c index ae3199e3a4d1..26e722dea1ff 100644 --- a/source3/passdb/pdb_xml.c +++ b/source3/passdb/pdb_xml.c @@ -512,7 +512,7 @@ static NTSTATUS xmlsam_add_sam_account(struct pdb_methods *methods, SAM_ACCOUNT return NT_STATUS_OK; } -NTSTATUS xmlsam_init(PDB_CONTEXT * pdb_context, PDB_METHODS ** pdb_method, +static NTSTATUS xmlsam_init(PDB_CONTEXT * pdb_context, PDB_METHODS ** pdb_method, const char *location) { NTSTATUS nt_status; @@ -553,8 +553,7 @@ NTSTATUS xmlsam_init(PDB_CONTEXT * pdb_context, PDB_METHODS ** pdb_method, (*pdb_method)->enum_group_mapping = NULL; data = talloc(pdb_context->mem_ctx, sizeof(pdb_xml)); - data->location = - (location ? talloc_strdup(pdb_context->mem_ctx, location) : "passdb.xml"); + data->location = talloc_strdup(pdb_context->mem_ctx, (location ? location : "passdb.xml")); data->pwent = NULL; data->written = 0; (*pdb_method)->private_data = data; @@ -564,7 +563,7 @@ NTSTATUS xmlsam_init(PDB_CONTEXT * pdb_context, PDB_METHODS ** pdb_method, return NT_STATUS_OK; } -int pdb_xml_init() +int pdb_xml_init(void) { return smb_register_passdb("xml", xmlsam_init, PASSDB_INTERFACE_VERSION); }