The branch, master has been updated via 11a3a8d9b9c WHATSNEW: document new preopen:* options via 83563b37213 vfs_preopen: add useful debug messages which can be configured on adjustable log levels via ade3b16490e vfs_preopen: introduce support for "preopen:posix-basic-regex = yes" via 67159410175 docs-xml:vfs_preopen.8: improve the documentation of the current detection algorithm via 430cbfc7918 vfs_preopen: make use of any hints from samba_path_matching_check_last_component() via e51a2e6e4ee vfs_preopen: cap the queue length to the maximum number that fits into the digits space via 1197c87c916 vfs_preopen: introduce helper variables in preopen_parse_fname() via 0900ab40d6d vfs_preopen: completely reset the queue if the name structure changes via d34c291d98e vfs_preopen: only reset the queue state if preopen_parse_fname() found matching digits via 68832c91bd7 vfs_preopen: make use of new samba_path_matching_* infrastructure via a843e74b85f vfs_preopen: only try to preopen if we can construct an absolute path via c6aaa36497f vfs_preopen: introduce "preopen" debug class via ebe5203c576 docs-xml: document dynamic debug classes from modules via e2e3b032cd9 lib/util: improve debug message about unknown classes via bc39450d80b s3:lib: add samba_path_matching_regex_sub1_create() via 845a59919e5 s3:lib: add a new samba_path_matching* infrastructure via 0a459c6b2df s3:torture: add STR-MATCH-MSWILD test for is_in_path() from accaa2f1f67 vfs_default: use copy_file_range()
https://git.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit 11a3a8d9b9c6d008a06a39f4669bb3b50cbe2464 Author: Stefan Metzmacher <me...@samba.org> Date: Thu Jul 1 14:07:34 2021 +0200 WHATSNEW: document new preopen:* options Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Ralph Boehme <s...@samba.org> Autobuild-User(master): Stefan Metzmacher <me...@samba.org> Autobuild-Date(master): Thu Jul 1 13:48:32 UTC 2021 on sn-devel-184 commit 83563b37213cdb58776e034c0bbd22ba55d51022 Author: Stefan Metzmacher <me...@samba.org> Date: Fri Jun 18 14:00:25 2021 +0000 vfs_preopen: add useful debug messages which can be configured on adjustable log levels The following are the default values: preopen:nomatch_log_level = 5 preopen:match_log_level = 5 preopen:nodigits_log_level = 1 preopen:founddigits_log_level = 3 preopen:reset_log_level = 5 preopen:push_log_level = 3 preopen:queue_log_level = 10 This gives admins a way to debug/audit the preopen usage. Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Ralph Boehme <s...@samba.org> commit ade3b16490e9afdf909a761828a38d80d6596fd1 Author: Stefan Metzmacher <me...@samba.org> Date: Fri Jun 11 19:07:03 2021 +0000 vfs_preopen: introduce support for "preopen:posix-basic-regex = yes" This will allow the usage of patterns as 'POSIX Basic Regular Expression' vfs objects = preopen preopen:posix-basic-regex = yes preopen:names = /Re7599Ex\([0-9]\).*\.txt/test\([0-9]*\)\.dat/ The key is that exactly one 'subexpression' starting with '\(' and ending with '\)' is specified in order to select the position where the digits are searched. E.g. given a file name 'Re7599Ex01234.txt' will actually preopen: Re7599Ex01234.txt Re7599Ex11234.txt Re7599Ex21234.txt Re7599Ex31234.txt Re7599Ex41234.txt As '\([0-9]\)' will only match the first digit after 'Re7599Ex'. It also means it's now possible to have digits in the fixed part of the filename, which was the actual motivation for this patchset. Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Ralph Boehme <s...@samba.org> commit 67159410175a9ceccc7beda01601b9dc6656be04 Author: Stefan Metzmacher <me...@samba.org> Date: Mon Jun 28 11:54:29 2021 +0200 docs-xml:vfs_preopen.8: improve the documentation of the current detection algorithm We should be more verbose that the first digits in a name are taken by default, if at least 3 digits were found. There might be cases were the last group of digits describe the increasing frame number, while the fixed name already contains 3 digits. This is currently not supported. It's also possible to provide more than one pattern. Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Ralph Boehme <s...@samba.org> commit 430cbfc7918939fde22d8da2327451b6801173bd Author: Stefan Metzmacher <me...@samba.org> Date: Fri Jun 11 21:08:19 2021 +0000 vfs_preopen: make use of any hints from samba_path_matching_check_last_component() samba_path_matching_check_last_component() may return the start and end offset of a submatch (for us the bytes where the digits are expected). We use that in order to allow preopen_parse_fname() to just look at these bytes and ignore any trailing digits after the submatch. For the current use of samba_path_matching_mswild_create(), there's no difference as we'll always get replace_start=-1 and replace_end=-1. But the next commit will make optional use of samba_path_matching_regex_sub1_create(), which will change the situation and allow to return hints we got from regexec(). Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Ralph Boehme <s...@samba.org> commit e51a2e6e4ee5409a61b2adb069561fcf40da3818 Author: Stefan Metzmacher <me...@samba.org> Date: Fri Jun 18 18:29:31 2021 +0000 vfs_preopen: cap the queue length to the maximum number that fits into the digits space If we have a single digit we only replace up to '9', which also fits into a single digit. We operate on numbers from 0 to 9999999999999999999 independent of the architecture. Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Ralph Boehme <s...@samba.org> commit 1197c87c916bc947d8143a57e59e9b36aaba309c Author: Stefan Metzmacher <me...@samba.org> Date: Fri Jun 11 21:08:19 2021 +0000 vfs_preopen: introduce helper variables in preopen_parse_fname() Calculating the start_idx and num_digits at the first possible place will make the following commits much easier. At the end we just want to assign the return values without any logic. Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Ralph Boehme <s...@samba.org> commit 0900ab40d6de6b6d878b6a48cb3df464d536d91b Author: Stefan Metzmacher <me...@samba.org> Date: Fri Jun 18 13:31:58 2021 +0000 vfs_preopen: completely reset the queue if the name structure changes There's no point in trying to check if the current number is part of the existing queue. This makes the logic at least more unstandable to me. Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Ralph Boehme <s...@samba.org> commit d34c291d98e6b0e061406e4d0760ce7db8e69a3f Author: Stefan Metzmacher <me...@samba.org> Date: Fri Jun 11 20:03:49 2021 +0000 vfs_preopen: only reset the queue state if preopen_parse_fname() found matching digits Otherwise there's no point in stopping the existing queue to continue via pending preopen_helper_readable() invocations. Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Ralph Boehme <s...@samba.org> commit 68832c91bd718b577c3a25139ab8bee883c36767 Author: Stefan Metzmacher <me...@samba.org> Date: Wed Jun 9 15:08:38 2021 +0200 vfs_preopen: make use of new samba_path_matching_* infrastructure There should not be any logic change in this commit, for now we'll keep the same ms wildcard matching we had before. Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Ralph Boehme <s...@samba.org> commit a843e74b85f50ca6285b7670f7bafb3199bb6008 Author: Stefan Metzmacher <me...@samba.org> Date: Fri Jun 11 20:05:14 2021 +0000 vfs_preopen: only try to preopen if we can construct an absolute path So we make sure the dirfsp contains an absolute path to begin with and smb_fname is a relative name within the directory. Note: dirfsp->fsp_name->base_name[0] is only '/' because currently all callers pass conn->cwd_fsp as dirfsp ... though there's already one caller that calls fd_openat() with a real dirfsp, that is in vfs_fruit though on the resource fork stream so doesn't really effect us currently. If more callers are changed in future the situation may change, but I guess then this is not the only place with potential problems. We most likely need a generic helper function that returns the absolute path of a dirfsp and use it here. Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Ralph Boehme <s...@samba.org> commit c6aaa36497f6dc6d4a8488d6ff8f43a6591eda59 Author: Stefan Metzmacher <me...@samba.org> Date: Tue Jun 8 10:56:22 2021 +0200 vfs_preopen: introduce "preopen" debug class It might be useful to change the level/location of debug messages specific to this module. Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Ralph Boehme <s...@samba.org> commit ebe5203c576576f96e7deffde34364e68d6c4805 Author: Stefan Metzmacher <me...@samba.org> Date: Mon Jun 28 11:44:27 2021 +0200 docs-xml: document dynamic debug classes from modules Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Ralph Boehme <s...@samba.org> commit e2e3b032cd94500dd409a44c01abd2357da31c29 Author: Stefan Metzmacher <me...@samba.org> Date: Fri Jun 18 12:18:00 2021 +0000 lib/util: improve debug message about unknown classes debug classes registered by vfs modules are not available immediately. Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Ralph Boehme <s...@samba.org> commit bc39450d80b2f319501747d8b285d0d70ca6505b Author: Stefan Metzmacher <me...@samba.org> Date: Fri Jun 11 19:03:42 2021 +0000 s3:lib: add samba_path_matching_regex_sub1_create() This will allow the usage 'POSIX Basic Regular Expression' instead of 'ms wildcard' strings. We allow exactly one 'subexpression' starting with '\(' and ending with '\)' in order to find a replacement (byte) region in the matching string. This will be used in the vfs_preopen module in the following commits. Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Ralph Boehme <s...@samba.org> commit 845a59919e528d083b1ab025844c41155ac93e43 Author: Stefan Metzmacher <me...@samba.org> Date: Wed Jun 9 14:44:39 2021 +0200 s3:lib: add a new samba_path_matching* infrastructure This aims to replace the current is_in_path() code in the long run. For now it implements samba_path_matching_mswild_create() in order to replace is_in_path() in the long run. But there will be other "backends" using regexec() too. Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Ralph Boehme <s...@samba.org> commit 0a459c6b2df45895c7a89a65ce736a1402a88dcc Author: Stefan Metzmacher <me...@samba.org> Date: Fri Jun 18 21:54:27 2021 +0000 s3:torture: add STR-MATCH-MSWILD test for is_in_path() I want to assert at least some of the behavior as the next commits will add a new abstraction that should at least partly behave the same. Note: case_[in]sensitive_idx is the index to the patterns in the namelist, set to -1 on non-match, otherwise to a value >= 0. Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Ralph Boehme <s...@samba.org> ----------------------------------------------------------------------- Summary of changes: WHATSNEW.txt | 20 +- docs-xml/manpages/vfs_preopen.8.xml | 166 ++++++++- docs-xml/smbdotconf/logging/loglevel.xml | 17 + lib/util/debug.c | 3 +- source3/lib/util_matching.c | 391 +++++++++++++++++++++ .../secace.h => source3/lib/util_matching.h | 31 +- source3/modules/vfs_preopen.c | 351 ++++++++++++++++-- source3/selftest/tests.py | 2 + source3/torture/proto.h | 2 + source3/torture/test_matching.c | 276 +++++++++++++++ source3/torture/torture.c | 8 + source3/wscript_build | 2 + 12 files changed, 1215 insertions(+), 54 deletions(-) create mode 100644 source3/lib/util_matching.c copy libcli/security/secace.h => source3/lib/util_matching.h (50%) create mode 100644 source3/torture/test_matching.c Changeset truncated at 500 lines: diff --git a/WHATSNEW.txt b/WHATSNEW.txt index d8effc5ce09..82bd5eaefc6 100644 --- a/WHATSNEW.txt +++ b/WHATSNEW.txt @@ -135,12 +135,20 @@ which have been out of support since 2018. smb.conf changes ================ - Parameter Name Description Default - -------------- ----------- ------- - client use kerberos New desired - client protection New default - winbind use krb5 enterprise principals Changed Yes - winbind scan trusted domains Changed No + Parameter Name Description Default + -------------- ----------- ------- + client use kerberos New desired + client protection New default + preopen:posix-basic-regex New No + preopen:nomatch_log_level New 5 + preopen:match_log_level New 5 + preopen:nodigits_log_level New 1 + preopen:founddigits_log_level New 3 + preopen:reset_log_level New 5 + preopen:push_log_level New 3 + preopen:queue_log_level New 10 + winbind use krb5 enterprise principals Changed Yes + winbind scan trusted domains Changed No KNOWN ISSUES diff --git a/docs-xml/manpages/vfs_preopen.8.xml b/docs-xml/manpages/vfs_preopen.8.xml index f9f3d60a02a..e826d72ffef 100644 --- a/docs-xml/manpages/vfs_preopen.8.xml +++ b/docs-xml/manpages/vfs_preopen.8.xml @@ -49,15 +49,42 @@ <variablelist> <varlistentry> - <term>preopen:names = /pattern/</term> + <term>preopen:posix-basic-regex = BOOL (default: no)</term> <listitem> <para> - preopen:names specifies the file name pattern which should + <command>preopen:posix-basic-regex = yes</command> changes + the meaning of the <command>preopen:names</command> option. + Further details are described there. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>preopen:names = /pattern1/pattern2/</term> + <listitem> + <para> + preopen:names specifies the file name pattern(s) which should trigger the preopen helpers to do their work. We assume that the files are numbered incrementally. So if your file names are numbered FRAME00000.frm FRAME00001.frm and so on you would - list them as <command>preopen:names=/FRAME*.frm/</command> + list them as <command>preopen:names=/FRAME*.frm/</command>. + The default algorithm uses the first (at least 3) digits it finds + in order to calculate the name of the next frames. </para> + + <para><command>preopen:posix-basic-regex = yes</command> changes + the meaning of the <command>preopen:names</command> option. + It means 'POSIX Basic Regular Expression' strings are used + as patterns. The key is each pattern requires exactly one + 'subexpression' starting with '\(' and ending with '\)' in + order to specify the position of the digits representing + the incrementing frame numbers. Given a file names like + Movie7599Frame0v1234.txt, Movie7599Frame1v1234.txt, Movie7599Frame2v1234.txt + up to Movie7599Frame9v1234.txt you can use <command>preopen:names = /.*Frame\([0-9]\).*\.txt/</command> + in order to match just a single digits, this might not be a real world example, + but it shows the flexiblity that is possible here. + </para> + </listitem> </varlistentry> @@ -90,6 +117,139 @@ </listitem> </varlistentry> + <varlistentry> + <term>preopen:nomatch_log_level = LOGLEVEL</term> + <listitem> + <para> + In order to debug or audit the usage of the preopen logic + you can use this option to specify at what log level details + about filenames not matching any pattern from '<command>preopen:names</command>' + are logged. + </para> + <para> + Defaults to the log level 5. + See also <citerefentry><refentrytitle>smb.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry> + in the '<smbconfoption name="log level"/>' section + for special handling of the 'preopen' debug class. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>preopen:match_log_level = LOGLEVEL</term> + <listitem> + <para> + In order to debug or audit the usage of the preopen logic + you can use this option to specify at what log level details + about filenames actually matching a pattern from '<command>preopen:names</command>' + are logged. + </para> + <para> + See also '<command>preopen:founddigits_log_level</command>' and '<command>preopen:push_log_level</command>'. + </para> + <para> + Defaults to the log level 5. + See also <citerefentry><refentrytitle>smb.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry> + in the '<smbconfoption name="log level"/>' section + for special handling of the 'preopen' debug class. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>preopen:nodigits_log_level = LOGLEVEL</term> + <listitem> + <para> + In order to debug or audit problems with the preopen configuration + you can use this option to specify at what log level details + about filenames actually matching a pattern from '<command>preopen:names</command>', + but at the same time don't contain the expected digits, are logged. + This is typically something the administrator wants to notice and + adjust the configuration in order to define more precisely where to + find the digits in the filename. + </para> + <para> + Defaults to the log level 1. + See also <citerefentry><refentrytitle>smb.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry> + in the '<smbconfoption name="log level"/>' section + for special handling of the 'preopen' debug class. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>preopen:founddigits_log_level = LOGLEVEL</term> + <listitem> + <para> + In order to debug or audit the usage of the preopen logic + you can use this option to specify at what log level details + about filenames actually matching a pattern from '<command>preopen:names</command>', + and at the same time having valid expected digits, are logged. This means enough information is available + in order to queue preopens. + </para> + <para> + Defaults to the log level 3. + See also <citerefentry><refentrytitle>smb.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry> + in the '<smbconfoption name="log level"/>' section + for special handling of the 'preopen' debug class. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>preopen:reset_log_level = LOGLEVEL</term> + <listitem> + <para> + If a matching filename belongs to a different pattern from '<command>preopen:names</command>', + a different parent directory or differs in a significant way from the last filename + that was found before, the module needs to reset it's internal queue state. + This means that no more preopens will be pushed to helper processes belonging to the + former queue state. In order to debug or audit such queue resets you can use this option to specify at what + log level details are logged. + </para> + <para> + Defaults to the log level 5. + See also <citerefentry><refentrytitle>smb.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry> + in the '<smbconfoption name="log level"/>' section + for special handling of the 'preopen' debug class. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>preopen:push_log_level = LOGLEVEL</term> + <listitem> + <para> + In order to debug or audit the usage of the preopen logic + you can use this option to specify at what log level details + about filenames actually pushed to preopen helper processes are logged. + This means they will actually be preopened soon. + </para> + <para> + Defaults to the log level 3. + See also <citerefentry><refentrytitle>smb.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry> + in the '<smbconfoption name="log level"/>' section + for special handling of the 'preopen' debug class. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term>preopen:queue_log_level = LOGLEVEL</term> + <listitem> + <para> + In order to debug details about internal queue processing + you can use this option to specify at what log level the details are logged. + </para> + <para> + Defaults to the log level 10. + See also <citerefentry><refentrytitle>smb.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry> + in the '<smbconfoption name="log level"/>' section + for special handling of the 'preopen' debug class. + </para> + </listitem> + </varlistentry> + </variablelist> </refsect1> diff --git a/docs-xml/smbdotconf/logging/loglevel.xml b/docs-xml/smbdotconf/logging/loglevel.xml index 4c6bb5e7e73..434c5d06832 100644 --- a/docs-xml/smbdotconf/logging/loglevel.xml +++ b/docs-xml/smbdotconf/logging/loglevel.xml @@ -59,6 +59,23 @@ <listitem><para><parameter moreinfo="none">dsdb_group_json_audit</parameter></para></listitem> </itemizedlist> + <para>Various modules register dynamic debug classes at first usage:</para> + <itemizedlist> + <listitem><para><parameter moreinfo="none">catia</parameter></para></listitem> + <listitem><para><parameter moreinfo="none">dfs_samba4</parameter></para></listitem> + <listitem><para><parameter moreinfo="none">extd_audit</parameter></para></listitem> + <listitem><para><parameter moreinfo="none">fileid</parameter></para></listitem> + <listitem><para><parameter moreinfo="none">fruit</parameter></para></listitem> + <listitem><para><parameter moreinfo="none">full_audit</parameter></para></listitem> + <listitem><para><parameter moreinfo="none">media_harmony</parameter></para></listitem> + <listitem><para><parameter moreinfo="none">preopen</parameter></para></listitem> + <listitem><para><parameter moreinfo="none">recycle</parameter></para></listitem> + <listitem><para><parameter moreinfo="none">shadow_copy</parameter></para></listitem> + <listitem><para><parameter moreinfo="none">shadow_copy</parameter></para></listitem> + <listitem><para><parameter moreinfo="none">unityed_media</parameter></para></listitem> + <listitem><para><parameter moreinfo="none">virusfilter</parameter></para></listitem> + </itemizedlist> + <para>To configure the logging for specific classes to go into a different file then <smbconfoption name="log file"/>, you can append <emphasis>@PATH</emphasis> to the class, eg <parameter>log level = 1 diff --git a/lib/util/debug.c b/lib/util/debug.c index 05a76efc5a4..cd52fe4be77 100644 --- a/lib/util/debug.c +++ b/lib/util/debug.c @@ -795,8 +795,7 @@ static int debug_lookup_classname(const char *classname) if (ndx != -1) return ndx; - DEBUG(0, ("debug_lookup_classname(%s): Unknown class\n", - classname)); + DBG_WARNING("Unknown classname[%s] -> adding it...\n", classname); return debug_add_class(classname); } diff --git a/source3/lib/util_matching.c b/source3/lib/util_matching.c new file mode 100644 index 00000000000..4a321f2ca44 --- /dev/null +++ b/source3/lib/util_matching.c @@ -0,0 +1,391 @@ +/* + Unix SMB/CIFS implementation. + Samba utility functions + Copyright (C) Stefan Metzmacher 2021 + + 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 + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "includes.h" +#include "lib/util_matching.h" +#include "lib/util/string_wrappers.h" + +struct samba_path_matching_entry { + const char *name; + bool is_wild; + regex_t re; +}; + +struct samba_path_matching_result { + ssize_t replace_start; + ssize_t replace_end; + bool match; +}; + +struct samba_path_matching { + bool case_sensitive; + NTSTATUS (*matching_fn)(const struct samba_path_matching *pm, + const struct samba_path_matching_entry *e, + const char *namecomponent, + struct samba_path_matching_result *result); + size_t num_entries; + struct samba_path_matching_entry *entries; +}; + +static NTSTATUS samba_path_matching_split(TALLOC_CTX *mem_ctx, + const char *namelist_in, + struct samba_path_matching **ppm) +{ + TALLOC_CTX *frame = talloc_stackframe(); + char *name_end = NULL; + char *namelist = NULL; + char *namelist_end = NULL; + char *nameptr = NULL; + struct samba_path_matching *pm = NULL; + size_t num_entries = 0; + struct samba_path_matching_entry *entries = NULL; + + *ppm = NULL; + + pm = talloc_zero(mem_ctx, struct samba_path_matching); + if (pm == NULL) { + TALLOC_FREE(frame); + return NT_STATUS_NO_MEMORY; + } + talloc_reparent(mem_ctx, frame, pm); + + namelist = talloc_strdup(frame, namelist_in); + if (namelist == NULL) { + TALLOC_FREE(frame); + return NT_STATUS_NO_MEMORY; + } + nameptr = namelist; + + namelist_end = &namelist[strlen(namelist)]; + + /* + * We need to make two passes over the string. The + * first to count the number of elements, the second + * to split it. + * + * The 1st time entries is NULL. + * the 2nd time entries is allocated. + */ +again: + while (nameptr <= namelist_end) { + /* anything left? */ + if (*nameptr == '\0') { + break; + } + + if (*nameptr == '/') { + /* cope with multiple (useless) /s) */ + nameptr++; + continue; + } + + /* find the next '/' or consume remaining */ + name_end = strchr_m(nameptr, '/'); + if (entries != NULL) { + if (name_end != NULL) { + *name_end = '\0'; + } + entries[num_entries].name = talloc_strdup(entries, + nameptr); + if (entries[num_entries].name == NULL) { + TALLOC_FREE(frame); + return NT_STATUS_NO_MEMORY; + } + } + num_entries++; + if (name_end != NULL) { + /* next segment please */ + nameptr = name_end + 1; + continue; + } + + /* no entries remaining */ + break; + } + + if (num_entries == 0) { + /* + * No entries in the first round => we're done + */ + goto done; + } + + if (entries != NULL) { + /* + * We finished the 2nd round => we're done + */ + goto done; + } + + /* + * Now allocate the array and loop again + * in order to split the names. + */ + entries = talloc_zero_array(pm, + struct samba_path_matching_entry, + num_entries); + if (entries == NULL) { + TALLOC_FREE(frame); + return NT_STATUS_NO_MEMORY; + } + num_entries = 0; + nameptr = namelist; + goto again; + +done: + pm->num_entries = num_entries; + pm->entries = entries; + *ppm = talloc_move(mem_ctx, &pm); + TALLOC_FREE(frame); + return NT_STATUS_OK; +}; + +static NTSTATUS samba_path_create_mswild_fn(const struct samba_path_matching *pm, + const struct samba_path_matching_entry *e, + const char *namecomponent, + struct samba_path_matching_result *result) +{ + bool match = false; + + if (e->is_wild) { + match = mask_match(namecomponent, e->name, pm->case_sensitive); + } else if (pm->case_sensitive) { + match = (strcmp(namecomponent, e->name) == 0); + } else { + match = (strcasecmp_m(namecomponent, e->name) == 0); + } + + *result = (struct samba_path_matching_result) { + .match = match, + .replace_start = -1, + .replace_end = -1, + }; + + return NT_STATUS_OK; +} + +NTSTATUS samba_path_matching_mswild_create(TALLOC_CTX *mem_ctx, + bool case_sensitive, + const char *namelist_in, + struct samba_path_matching **ppm) +{ + NTSTATUS status; + TALLOC_CTX *frame = talloc_stackframe(); + struct samba_path_matching *pm = NULL; + size_t i; + + *ppm = NULL; + + status = samba_path_matching_split(mem_ctx, namelist_in, &pm); + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(frame); + return status; + } + talloc_reparent(mem_ctx, frame, pm); + + for (i = 0; i < pm->num_entries; i++) { + struct samba_path_matching_entry *e = &pm->entries[i]; + + e->is_wild = ms_has_wild(e->name); + } + + pm->case_sensitive = case_sensitive; + pm->matching_fn = samba_path_create_mswild_fn; + *ppm = talloc_move(mem_ctx, &pm); + TALLOC_FREE(frame); + return NT_STATUS_OK; +}; + +static int samba_path_matching_regex_sub1_destructor(struct samba_path_matching *pm) +{ + ssize_t i; + + for (i = 0; i < pm->num_entries; i++) { + struct samba_path_matching_entry *e = &pm->entries[i]; + + regfree(&e->re); + } + + pm->num_entries = 0; + + return 0; +} + +static NTSTATUS samba_path_create_regex_sub1_fn(const struct samba_path_matching *pm, + const struct samba_path_matching_entry *e, -- Samba Shared Repository