"Fossies" - the Fresh Open Source Software Archive

Member "cfengine-3.15.4/libpromises/mod_files.c" (7 Jun 2021, 30675 Bytes) of package /linux/misc/cfengine-3.15.4.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "mod_files.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 3.15.3_vs_3.15.4.

    1 /*
    2   Copyright 2019 Northern.tech AS
    3 
    4   This file is part of CFEngine 3 - written and maintained by Northern.tech AS.
    5 
    6   This program is free software; you can redistribute it and/or modify it
    7   under the terms of the GNU General Public License as published by the
    8   Free Software Foundation; version 3.
    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, write to the Free Software
   17   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
   18 
   19   To the extent this program is licensed as part of the Enterprise
   20   versions of CFEngine, the applicable Commercial Open Source License
   21   (COSL) may apply to this file if you as a licensee so wish it. See
   22   included file COSL.txt.
   23 */
   24 
   25 #include <mod_files.h>
   26 
   27 #include <policy.h>
   28 #include <syntax.h>
   29 
   30 static const ConstraintSyntax location_constraints[] =
   31 {
   32     CONSTRAINT_SYNTAX_GLOBAL,
   33     ConstraintSyntaxNewOption("before_after", "before,after", "Menu option, point cursor before of after matched line. Default value: after", SYNTAX_STATUS_NORMAL),
   34     ConstraintSyntaxNewOption("first_last", "first,last", "Menu option, choose first or last occurrence of match in file. Default value: last", SYNTAX_STATUS_NORMAL),
   35     ConstraintSyntaxNewString("select_line_matching", CF_ANYSTRING, "Regular expression for matching file line location", SYNTAX_STATUS_NORMAL),
   36     ConstraintSyntaxNewNull()
   37 };
   38 
   39 static const BodySyntax location_body = BodySyntaxNew("location", location_constraints, NULL, SYNTAX_STATUS_NORMAL);
   40 
   41 static const ConstraintSyntax edit_field_constraints[] =
   42 {
   43     CONSTRAINT_SYNTAX_GLOBAL,
   44     ConstraintSyntaxNewBool("allow_blank_fields", "true/false allow blank fields in a line (do not purge). Default value: false", SYNTAX_STATUS_NORMAL),
   45     ConstraintSyntaxNewBool("extend_fields", "true/false add new fields at end of line if necessary to complete edit. Default value: false", SYNTAX_STATUS_NORMAL),
   46     ConstraintSyntaxNewOption("field_operation", "prepend,append,alphanum,delete,set", "Menu option policy for editing subfields. Default value: none", SYNTAX_STATUS_NORMAL),
   47     ConstraintSyntaxNewString("field_separator", CF_ANYSTRING, "The regular expression used to separate fields in a line. Default value: none", SYNTAX_STATUS_NORMAL),
   48     ConstraintSyntaxNewString("field_value", CF_ANYSTRING, "Set field value to a fixed value", SYNTAX_STATUS_NORMAL),
   49     ConstraintSyntaxNewInt("select_field", "0,99999999", "Integer index of the field required 0..n (default starts from 1)", SYNTAX_STATUS_NORMAL),
   50     ConstraintSyntaxNewBool("start_fields_from_zero", "If set, the default field numbering starts from 0", SYNTAX_STATUS_NORMAL),
   51     ConstraintSyntaxNewString("value_separator", CF_CHARRANGE, "Character separator for subfields inside the selected field. Default value: none", SYNTAX_STATUS_NORMAL),
   52     ConstraintSyntaxNewNull()
   53 };
   54 
   55 static const BodySyntax edit_field_body = BodySyntaxNew("edit_field", edit_field_constraints, NULL, SYNTAX_STATUS_NORMAL);
   56 
   57 static const ConstraintSyntax replace_with_constraints[] =
   58 {
   59     CONSTRAINT_SYNTAX_GLOBAL,
   60     ConstraintSyntaxNewOption("occurrences", "all,first", "Menu option to replace all occurrences or just first (NB the latter is non-convergent). Default value: all", SYNTAX_STATUS_NORMAL),
   61     ConstraintSyntaxNewString("replace_value", CF_ANYSTRING, "Value used to replace regular expression matches in search", SYNTAX_STATUS_NORMAL),
   62     ConstraintSyntaxNewNull()
   63 };
   64 
   65 static const BodySyntax replace_with_body = BodySyntaxNew("replace_with", replace_with_constraints, NULL, SYNTAX_STATUS_NORMAL);
   66 
   67 static const ConstraintSyntax select_region_constraints[] =
   68 {
   69     CONSTRAINT_SYNTAX_GLOBAL,
   70     ConstraintSyntaxNewBool("include_start_delimiter", "Whether to include the section delimiter. Default value: false", SYNTAX_STATUS_NORMAL),
   71     ConstraintSyntaxNewBool("include_end_delimiter", "Whether to include the section delimiter. Default value: false", SYNTAX_STATUS_NORMAL),
   72     ConstraintSyntaxNewString("select_start", CF_ANYSTRING, "Regular expression matching start of edit region", SYNTAX_STATUS_NORMAL),
   73     ConstraintSyntaxNewString("select_end", CF_ANYSTRING, "Regular expression matches end of edit region from start", SYNTAX_STATUS_NORMAL),
   74     ConstraintSyntaxNewBool("select_end_match_eof", "Whether to include EOF as end of the region. Default value: false", SYNTAX_STATUS_NORMAL),
   75     ConstraintSyntaxNewNull()
   76 };
   77 
   78 static const BodySyntax select_region_body = BodySyntaxNew("select_region", select_region_constraints, NULL, SYNTAX_STATUS_NORMAL);
   79 
   80 static const ConstraintSyntax delete_select_constraints[] =
   81 {
   82     CONSTRAINT_SYNTAX_GLOBAL,
   83     ConstraintSyntaxNewStringList("delete_if_startwith_from_list", CF_ANYSTRING, "Delete line if it starts with a string in the list", SYNTAX_STATUS_NORMAL),
   84     ConstraintSyntaxNewStringList("delete_if_not_startwith_from_list", CF_ANYSTRING, "Delete line if it DOES NOT start with a string in the list", SYNTAX_STATUS_NORMAL),
   85     ConstraintSyntaxNewStringList("delete_if_match_from_list", CF_ANYSTRING, "Delete line if it fully matches a regex in the list", SYNTAX_STATUS_NORMAL),
   86     ConstraintSyntaxNewStringList("delete_if_not_match_from_list", CF_ANYSTRING,"Delete line if it DOES NOT fully match a regex in the list", SYNTAX_STATUS_NORMAL),
   87     ConstraintSyntaxNewStringList("delete_if_contains_from_list", CF_ANYSTRING, "Delete line if a regex in the list match a line fragment", SYNTAX_STATUS_NORMAL),
   88     ConstraintSyntaxNewStringList("delete_if_not_contains_from_list", CF_ANYSTRING,"Delete line if a regex in the list DOES NOT match a line fragment", SYNTAX_STATUS_NORMAL),
   89     ConstraintSyntaxNewNull()
   90 };
   91 
   92 static const BodySyntax delete_select_body = BodySyntaxNew("delete_select", delete_select_constraints, NULL, SYNTAX_STATUS_NORMAL);
   93 
   94 static const ConstraintSyntax insert_select_constraints[] =
   95 {
   96     CONSTRAINT_SYNTAX_GLOBAL,
   97     ConstraintSyntaxNewStringList("insert_if_startwith_from_list", CF_ANYSTRING, "Insert line if it starts with a string in the list", SYNTAX_STATUS_NORMAL),
   98     ConstraintSyntaxNewStringList("insert_if_not_startwith_from_list", CF_ANYSTRING,"Insert line if it DOES NOT start with a string in the list", SYNTAX_STATUS_NORMAL),
   99     ConstraintSyntaxNewStringList("insert_if_match_from_list", CF_ANYSTRING, "Insert line if it fully matches a regex in the list", SYNTAX_STATUS_NORMAL),
  100     ConstraintSyntaxNewStringList("insert_if_not_match_from_list", CF_ANYSTRING,"Insert line if it DOES NOT fully match a regex in the list", SYNTAX_STATUS_NORMAL),
  101     ConstraintSyntaxNewStringList("insert_if_contains_from_list", CF_ANYSTRING,"Insert line if a regex in the list match a line fragment", SYNTAX_STATUS_NORMAL),
  102     ConstraintSyntaxNewStringList("insert_if_not_contains_from_list", CF_ANYSTRING, "Insert line if a regex in the list DOES NOT match a line fragment", SYNTAX_STATUS_NORMAL),
  103     ConstraintSyntaxNewNull()
  104 };
  105 
  106 static const BodySyntax insert_select_body = BodySyntaxNew("insert_select", insert_select_constraints, NULL, SYNTAX_STATUS_NORMAL);
  107 
  108 static const ConstraintSyntax CF_INSERTLINES_BODIES[] =
  109 {
  110     ConstraintSyntaxNewBool("expand_scalars", "Expand any unexpanded variables. Default value: false", SYNTAX_STATUS_NORMAL),
  111     ConstraintSyntaxNewOption("insert_type", "literal,string,file,file_preserve_block,preserve_block,preserve_all_lines", "Type of object the promiser string refers to. Default value: literal", SYNTAX_STATUS_NORMAL),
  112     ConstraintSyntaxNewBody("insert_select", &insert_select_body, "Insert only if lines pass filter criteria", SYNTAX_STATUS_NORMAL),
  113     ConstraintSyntaxNewBody("location", &location_body, "Specify where in a file an insertion will be made", SYNTAX_STATUS_NORMAL),
  114     ConstraintSyntaxNewOptionList("whitespace_policy", "ignore_leading,ignore_trailing,ignore_embedded,exact_match", "Criteria for matching and recognizing existing lines", SYNTAX_STATUS_NORMAL),
  115     ConstraintSyntaxNewNull()
  116 };
  117 
  118 static const ConstraintSyntax CF_DELETELINES_BODIES[] =
  119 {
  120     ConstraintSyntaxNewBody("delete_select", &delete_select_body, "Delete only if lines pass filter criteria", SYNTAX_STATUS_NORMAL),
  121     ConstraintSyntaxNewBool("not_matching", "true/false negate match criterion. Default value: false", SYNTAX_STATUS_NORMAL),
  122     ConstraintSyntaxNewNull()
  123 };
  124 
  125 static const ConstraintSyntax CF_COLUMN_BODIES[] =
  126 {
  127     ConstraintSyntaxNewBody("edit_field", &edit_field_body, "Edit line-based file as matrix of fields", SYNTAX_STATUS_NORMAL),
  128     ConstraintSyntaxNewNull()
  129 };
  130 
  131 static const ConstraintSyntax CF_REPLACE_BODIES[] =
  132 {
  133     ConstraintSyntaxNewBody("replace_with", &replace_with_body, "Search-replace pattern", SYNTAX_STATUS_NORMAL),
  134     ConstraintSyntaxNewNull()
  135 };
  136 
  137 const ConstraintSyntax CF_COMMON_EDITBODIES[] =
  138 {
  139     ConstraintSyntaxNewBody("select_region", &select_region_body, "Limit edits to a demarked region of the file", SYNTAX_STATUS_NORMAL),
  140     ConstraintSyntaxNewNull()
  141 };
  142 
  143 static bool AclCheck(const Body *body, Seq *errors)
  144 {
  145     bool success = true;
  146 
  147     if (BodyHasConstraint(body, "acl_directory_inherit")
  148         && BodyHasConstraint(body, "acl_default"))
  149     {
  150         SeqAppend(errors, PolicyErrorNew(POLICY_ELEMENT_TYPE_BODY, body, "An acl body cannot have both acl_directory_inherit and acl_default. Please use acl_default only"));
  151         success = false;
  152     }
  153     if (BodyHasConstraint(body, "specify_inherit_aces")
  154         && BodyHasConstraint(body, "specify_default_aces"))
  155     {
  156         SeqAppend(errors, PolicyErrorNew(POLICY_ELEMENT_TYPE_BODY, body, "An acl body cannot have both specify_inherit_aces and specify_default_aces. Please use specify_default_aces only"));
  157         success = false;
  158     }
  159 
  160     return success;
  161 }
  162 
  163 static const ConstraintSyntax acl_constraints[] =
  164 {
  165     CONSTRAINT_SYNTAX_GLOBAL,
  166     ConstraintSyntaxNewStringList("aces", "((user|group):[^:]+:[-=+,rwx()dtTabBpcoD]*(:(allow|deny))?)|((all|mask):[-=+,rwx()]*(:(allow|deny))?)", "Native settings for access control entry", SYNTAX_STATUS_NORMAL),
  167     ConstraintSyntaxNewOption("acl_directory_inherit", "nochange,parent,specify,clear", "Access control list type for the affected file system", SYNTAX_STATUS_DEPRECATED),
  168     ConstraintSyntaxNewOption("acl_default", "nochange,access,specify,clear", "How to apply default (inheritable) access control list", SYNTAX_STATUS_NORMAL),
  169     ConstraintSyntaxNewOption("acl_method", "append,overwrite", "Editing method for access control list", SYNTAX_STATUS_NORMAL),
  170     ConstraintSyntaxNewOption("acl_type", "generic,posix,ntfs", "Access control list type for the affected file system", SYNTAX_STATUS_NORMAL),
  171     ConstraintSyntaxNewStringList("specify_inherit_aces", "((user|group):[^:]+:[-=+,rwx()dtTabBpcoD]*(:(allow|deny))?)|((all|mask):[-=+,rwx()]*(:(allow|deny))?)", "Native settings for access control entry", SYNTAX_STATUS_DEPRECATED),
  172     ConstraintSyntaxNewStringList("specify_default_aces", "((user|group):[^:]+:[-=+,rwx()dtTabBpcoD]*(:(allow|deny))?)|((all|mask):[-=+,rwx()]*(:(allow|deny))?)", "Native settings for access control entry", SYNTAX_STATUS_NORMAL),
  173     ConstraintSyntaxNewOption("acl_inherit", CF_BOOL ",nochange", "Whether the object inherits its ACL from the parent (Windows only)", SYNTAX_STATUS_NORMAL),
  174     ConstraintSyntaxNewNull()
  175 };
  176 
  177 static const BodySyntax acl_body = BodySyntaxNew("acl", acl_constraints, &AclCheck, SYNTAX_STATUS_NORMAL);
  178 
  179 static const ConstraintSyntax changes_constraints[] =
  180 {
  181     CONSTRAINT_SYNTAX_GLOBAL,
  182     ConstraintSyntaxNewOption("hash", "md5,sha1,sha224,sha256,sha384,sha512,best", "Hash files for change detection", SYNTAX_STATUS_NORMAL),
  183     ConstraintSyntaxNewOption("report_changes", "all,stats,content,none", "Specify criteria for change warnings", SYNTAX_STATUS_NORMAL),
  184     ConstraintSyntaxNewBool("update_hashes", "Update hash values immediately after change warning", SYNTAX_STATUS_NORMAL),
  185     ConstraintSyntaxNewBool("report_diffs","Generate reports summarizing the major differences between individual text files", SYNTAX_STATUS_NORMAL),
  186     ConstraintSyntaxNewNull()
  187 };
  188 
  189 static const BodySyntax changes_body = BodySyntaxNew("changes", changes_constraints, NULL, SYNTAX_STATUS_NORMAL);
  190 
  191 static const ConstraintSyntax depth_search_constraints[] =
  192 {
  193     CONSTRAINT_SYNTAX_GLOBAL,
  194     ConstraintSyntaxNewInt("depth", CF_VALRANGE, "Maximum depth level for search", SYNTAX_STATUS_NORMAL),
  195     ConstraintSyntaxNewStringList("exclude_dirs", ".*", "List of regexes of directory names NOT to include in depth search", SYNTAX_STATUS_NORMAL),
  196     ConstraintSyntaxNewBool("include_basedir", "true/false include the start/root dir of the search results", SYNTAX_STATUS_NORMAL),
  197     ConstraintSyntaxNewStringList("include_dirs", ".*", "List of regexes of directory names to include in depth search", SYNTAX_STATUS_NORMAL),
  198     ConstraintSyntaxNewBool("rmdeadlinks", "true/false remove links that point to nowhere. Default value: false", SYNTAX_STATUS_NORMAL),
  199     ConstraintSyntaxNewBool("traverse_links", "true/false traverse symbolic links to directories. Default value: false", SYNTAX_STATUS_NORMAL),
  200     ConstraintSyntaxNewBool("xdev", "When true files and directories on different devices from the promiser will be excluded from depth_search results. Default value: false", SYNTAX_STATUS_NORMAL),
  201     ConstraintSyntaxNewNull()
  202 };
  203 
  204 static const BodySyntax depth_search_body = BodySyntaxNew("depth_search", depth_search_constraints, NULL, SYNTAX_STATUS_NORMAL);
  205 
  206 static const ConstraintSyntax edit_defaults_constraints[] =
  207 {
  208     CONSTRAINT_SYNTAX_GLOBAL,
  209     ConstraintSyntaxNewOption("edit_backup", "true,false,timestamp,rotate", "Menu option for backup policy on edit changes. Default value: true", SYNTAX_STATUS_NORMAL),
  210     ConstraintSyntaxNewBool("empty_file_before_editing", "Baseline memory model of file to zero/empty before commencing promised edits. Default value: false", SYNTAX_STATUS_NORMAL),
  211     ConstraintSyntaxNewBool("inherit", "If true this causes the sub-bundle to inherit the private classes of its parent", SYNTAX_STATUS_NORMAL),
  212     ConstraintSyntaxNewInt("max_file_size", CF_VALRANGE, "Do not edit files bigger than this number of bytes", SYNTAX_STATUS_NORMAL),
  213     ConstraintSyntaxNewBool("recognize_join", "Join together lines that end with a backslash, up to 4kB limit. Default value: false", SYNTAX_STATUS_NORMAL),
  214     ConstraintSyntaxNewInt("rotate", "0,99", "How many backups to store if 'rotate' edit_backup strategy is selected. Default value: 1", SYNTAX_STATUS_NORMAL),
  215     ConstraintSyntaxNewNull()
  216 };
  217 
  218 static const BodySyntax edit_defaults_body = BodySyntaxNew("edit_defaults", edit_defaults_constraints, NULL, SYNTAX_STATUS_NORMAL);
  219 
  220 static const ConstraintSyntax delete_constraints[] =
  221 {
  222     CONSTRAINT_SYNTAX_GLOBAL,
  223     ConstraintSyntaxNewOption("dirlinks", "delete,tidy,keep", "Menu option policy for dealing with symbolic links to directories during deletion", SYNTAX_STATUS_NORMAL),
  224     ConstraintSyntaxNewBool("rmdirs", "true/false whether to delete empty directories during recursive deletion", SYNTAX_STATUS_NORMAL),
  225     ConstraintSyntaxNewNull()
  226 };
  227 
  228 static const BodySyntax delete_body = BodySyntaxNew("delete", delete_constraints, NULL, SYNTAX_STATUS_NORMAL);
  229 
  230 static const ConstraintSyntax rename_constraints[] =
  231 {
  232     CONSTRAINT_SYNTAX_GLOBAL,
  233     ConstraintSyntaxNewBool("disable", "true/false automatically rename and remove permissions. Default value: false", SYNTAX_STATUS_NORMAL),
  234     ConstraintSyntaxNewString("disable_mode", CF_MODERANGE, "The permissions to set when a file is disabled", SYNTAX_STATUS_NORMAL),
  235     ConstraintSyntaxNewString("disable_suffix", "", "The suffix to add to files when disabling (.cfdisabled)", SYNTAX_STATUS_NORMAL),
  236     ConstraintSyntaxNewString("newname", "", "The desired name for the current file", SYNTAX_STATUS_NORMAL),
  237     ConstraintSyntaxNewInt("rotate", "0,99", "Maximum number of file rotations to keep", SYNTAX_STATUS_NORMAL),
  238     ConstraintSyntaxNewNull()
  239 };
  240 
  241 static const BodySyntax rename_body = BodySyntaxNew("rename", rename_constraints, NULL, SYNTAX_STATUS_NORMAL);
  242 
  243 static const ConstraintSyntax perms_constraints[] =
  244 {
  245     CONSTRAINT_SYNTAX_GLOBAL,
  246     ConstraintSyntaxNewStringList("bsdflags", CF_BSDFLAGRANGE, "List of menu options for bsd file system flags to set", SYNTAX_STATUS_NORMAL),
  247     ConstraintSyntaxNewStringList("groups", CF_USERRANGE, "List of acceptable groups of group ids, first is change target", SYNTAX_STATUS_NORMAL),
  248     ConstraintSyntaxNewString("mode", CF_MODERANGE, "File permissions (like posix chmod)", SYNTAX_STATUS_NORMAL),
  249     ConstraintSyntaxNewStringList("owners", CF_USERRANGE, "List of acceptable owners or user ids, first is change target", SYNTAX_STATUS_NORMAL),
  250     ConstraintSyntaxNewBool("rxdirs", "true/false add execute flag for directories if read flag is set", SYNTAX_STATUS_NORMAL),
  251     ConstraintSyntaxNewNull()
  252 };
  253 
  254 static const BodySyntax perms_body = BodySyntaxNew("perms", perms_constraints, NULL, SYNTAX_STATUS_NORMAL);
  255 
  256 static const ConstraintSyntax file_select_constraints[] =
  257 {
  258     CONSTRAINT_SYNTAX_GLOBAL,
  259     ConstraintSyntaxNewStringList("leaf_name", "", "List of regexes that match an acceptable name", SYNTAX_STATUS_NORMAL),
  260     ConstraintSyntaxNewStringList("path_name", CF_ABSPATHRANGE, "List of pathnames to match acceptable target", SYNTAX_STATUS_NORMAL),
  261     ConstraintSyntaxNewStringList("search_mode", CF_MODERANGE, "A list of mode masks for acceptable file permissions", SYNTAX_STATUS_NORMAL),
  262     ConstraintSyntaxNewIntRange("search_size", "0,inf", "Integer range of file sizes", SYNTAX_STATUS_NORMAL),
  263     ConstraintSyntaxNewStringList("search_owners", "", "List of acceptable user names or ids for the file, or regexes to match", SYNTAX_STATUS_NORMAL),
  264     ConstraintSyntaxNewStringList("search_groups", "", "List of acceptable group names or ids for the file, or regexes to match", SYNTAX_STATUS_NORMAL),
  265     ConstraintSyntaxNewStringList("search_bsdflags", CF_BSDFLAGRANGE, "String of flags for bsd file system flags expected set", SYNTAX_STATUS_NORMAL),
  266     ConstraintSyntaxNewIntRange("ctime", CF_TIMERANGE, "Range of change times (ctime) for acceptable files", SYNTAX_STATUS_NORMAL),
  267     ConstraintSyntaxNewIntRange("mtime", CF_TIMERANGE, "Range of modification times (mtime) for acceptable files", SYNTAX_STATUS_NORMAL),
  268     ConstraintSyntaxNewIntRange("atime", CF_TIMERANGE, "Range of access times (atime) for acceptable files", SYNTAX_STATUS_NORMAL),
  269     ConstraintSyntaxNewString("exec_regex", CF_ANYSTRING, "Matches file if this regular expression matches any full line returned by the command", SYNTAX_STATUS_NORMAL),
  270     ConstraintSyntaxNewString("exec_program", CF_ABSPATHRANGE, "Execute this command on each file and match if the exit status is zero", SYNTAX_STATUS_NORMAL),
  271     ConstraintSyntaxNewOptionList("file_types", "plain,reg,symlink,dir,socket,fifo,door,char,block", "List of acceptable file types from menu choices", SYNTAX_STATUS_NORMAL),
  272     ConstraintSyntaxNewStringList("issymlinkto", "", "List of regular expressions to match file objects", SYNTAX_STATUS_NORMAL),
  273     ConstraintSyntaxNewString("file_result", "[!*(leaf_name|path_name|file_types|mode|size|owner|group|atime|ctime|mtime|issymlinkto|exec_regex|exec_program|bsdflags)[|&.]*]*",
  274                         "Logical expression combining classes defined by file search criteria", SYNTAX_STATUS_NORMAL),
  275     ConstraintSyntaxNewNull()
  276 };
  277 
  278 static const BodySyntax file_select_body = BodySyntaxNew("file_select", file_select_constraints, NULL, SYNTAX_STATUS_NORMAL);
  279 
  280 /* Copy and link are really the same body and should have
  281    non-overlapping patterns so that they are XOR but it's
  282    okay that some names overlap (like source) as there is
  283    no ambiguity in XOR */
  284 
  285 static const ConstraintSyntax link_from_constraints[] =
  286 {
  287     CONSTRAINT_SYNTAX_GLOBAL,
  288     ConstraintSyntaxNewStringList("copy_patterns", "", "A set of patterns that should be copied and synchronized instead of linked", SYNTAX_STATUS_NORMAL),
  289     ConstraintSyntaxNewBool("link_children", "true/false whether to link all directory's children to source originals. Default value: false", SYNTAX_STATUS_NORMAL),
  290     ConstraintSyntaxNewOption("link_type", CF_LINKRANGE, "The type of link used to alias the file. Default value: symlink", SYNTAX_STATUS_NORMAL),
  291     ConstraintSyntaxNewString("source", CF_PATHRANGE, "The source file to which the link should point", SYNTAX_STATUS_NORMAL),
  292     ConstraintSyntaxNewOption("when_linking_children", "override_file,if_no_such_file", "Policy for overriding existing files when linking directories of children", SYNTAX_STATUS_NORMAL),
  293     ConstraintSyntaxNewOption("when_no_source", "force,delete,nop", "Behaviour when the source file to link to does not exist. Default value: nop", SYNTAX_STATUS_NORMAL),
  294     ConstraintSyntaxNewNull()
  295 };
  296 
  297 static const BodySyntax link_from_body = BodySyntaxNew("link_from", link_from_constraints, NULL, SYNTAX_STATUS_NORMAL);
  298 
  299 static const ConstraintSyntax copy_from_constraints[] =
  300 {
  301     /* We use CF_PATHRANGE due to collision with LINKTO_BODY and a bug lurking in
  302      * a verification stage -- this attribute gets picked instead of another
  303      * 'source'
  304      */
  305     CONSTRAINT_SYNTAX_GLOBAL,
  306     ConstraintSyntaxNewString("source", CF_PATHRANGE, "Reference source file from which to copy", SYNTAX_STATUS_NORMAL),
  307     ConstraintSyntaxNewStringList("servers", "[A-Za-z0-9_.:\\-\\[\\]]+", "List of servers in order of preference from which to copy", SYNTAX_STATUS_NORMAL),
  308     ConstraintSyntaxNewBool("collapse_destination_dir", "Copy files from subdirectories to the root destination directory. Default: false", SYNTAX_STATUS_NORMAL),
  309     ConstraintSyntaxNewOption("compare", "atime,mtime,ctime,digest,hash,exists,binary", "Menu option policy for comparing source and image file attributes. Default: mtime or ctime differs", SYNTAX_STATUS_NORMAL),
  310     ConstraintSyntaxNewOption("copy_backup", "true,false,timestamp", "Menu option policy for file backup/version control. Default value: true", SYNTAX_STATUS_NORMAL),
  311     ConstraintSyntaxNewBool("encrypt", "true/false use encrypted data stream to connect to remote host. Default value: false", SYNTAX_STATUS_NORMAL),
  312     ConstraintSyntaxNewBool("check_root", "true/false check permissions on the root directory when depth_search", SYNTAX_STATUS_NORMAL),
  313     ConstraintSyntaxNewStringList("copylink_patterns", "", "List of patterns matching files that should be copied instead of linked", SYNTAX_STATUS_NORMAL),
  314     ConstraintSyntaxNewIntRange("copy_size", "0,inf", "Integer range of file sizes that may be copied", SYNTAX_STATUS_NORMAL),
  315     ConstraintSyntaxNewOption("findertype", "MacOSX", "Menu option for default finder type on MacOSX", SYNTAX_STATUS_NORMAL),
  316     ConstraintSyntaxNewStringList("linkcopy_patterns", "", "List of patterns matching files that should be replaced with symbolic links", SYNTAX_STATUS_NORMAL),
  317     ConstraintSyntaxNewOption("link_type", CF_LINKRANGE, "Menu option for type of links to use when copying. Default value: symlink", SYNTAX_STATUS_NORMAL),
  318     ConstraintSyntaxNewBool("force_update", "true/false force copy update always. Default value: false", SYNTAX_STATUS_NORMAL),
  319     ConstraintSyntaxNewBool("force_ipv4", "true/false force use of ipv4 on ipv6 enabled network. Default value: false", SYNTAX_STATUS_NORMAL),
  320     ConstraintSyntaxNewString("portnumber", "", "Port number or service name to connect to on server host", SYNTAX_STATUS_NORMAL),
  321     ConstraintSyntaxNewBool("preserve", "true/false whether to preserve file permissions on copied file. Default value: false", SYNTAX_STATUS_NORMAL),
  322     ConstraintSyntaxNewBool("purge", "true/false purge files on client that do not match files on server when a depth_search is used. Default value: false", SYNTAX_STATUS_NORMAL),
  323     ConstraintSyntaxNewBool("stealth", "true/false whether to preserve time stamps on copied file. Default value: false", SYNTAX_STATUS_NORMAL),
  324     ConstraintSyntaxNewInt("timeout", "1,3600", "Connection timeout, seconds", SYNTAX_STATUS_NORMAL),
  325     ConstraintSyntaxNewBool("trustkey", "true/false trust public keys from remote server if previously unknown. Default value: false", SYNTAX_STATUS_NORMAL),
  326     ConstraintSyntaxNewBool("type_check", "true/false compare file types before copying and require match", SYNTAX_STATUS_NORMAL),
  327     ConstraintSyntaxNewBool("verify", "true/false verify transferred file by hashing after copy (resource penalty). Default value: false", SYNTAX_STATUS_NORMAL),
  328     ConstraintSyntaxNewOption("protocol_version", "0,undefined,1,classic,2,latest", "CFEngine protocol version to use when connecting to the server. Default: undefined", SYNTAX_STATUS_NORMAL),
  329     ConstraintSyntaxNewBool("missing_ok", "true/false Do not treat missing file as an error. Default value: false", SYNTAX_STATUS_NORMAL),
  330     ConstraintSyntaxNewNull()
  331 };
  332 
  333 static const BodySyntax copy_from_body = BodySyntaxNew("copy_from", copy_from_constraints, NULL, SYNTAX_STATUS_NORMAL);
  334 
  335 static const ConstraintSyntax CF_FILES_BODIES[] =
  336 {
  337     ConstraintSyntaxNewBody("acl", &acl_body, "Criteria for access control lists on file", SYNTAX_STATUS_NORMAL),
  338     ConstraintSyntaxNewBody("changes", &changes_body, "Criteria for change management", SYNTAX_STATUS_NORMAL),
  339     ConstraintSyntaxNewBody("copy_from", &copy_from_body, "Criteria for copying file from a source", SYNTAX_STATUS_NORMAL),
  340     ConstraintSyntaxNewBool("create", "true/false whether to create non-existing file. Default value: false", SYNTAX_STATUS_NORMAL),
  341     ConstraintSyntaxNewBody("delete", &delete_body, "Criteria for deleting files", SYNTAX_STATUS_NORMAL),
  342     ConstraintSyntaxNewBody("depth_search", &depth_search_body, "Criteria for file depth searches", SYNTAX_STATUS_NORMAL),
  343     ConstraintSyntaxNewBody("edit_defaults", &edit_defaults_body, "Default promise details for file edits", SYNTAX_STATUS_NORMAL),
  344     ConstraintSyntaxNewBundle("edit_line", "Line editing model for file", SYNTAX_STATUS_NORMAL),
  345     ConstraintSyntaxNewString("edit_template", CF_ABSPATHRANGE, "The name of a special CFEngine template file to expand", SYNTAX_STATUS_NORMAL),
  346     ConstraintSyntaxNewString("edit_template_string", CF_ANYSTRING, "Template string to expand", SYNTAX_STATUS_NORMAL),
  347     ConstraintSyntaxNewBundle("edit_xml", "XML editing model for file", SYNTAX_STATUS_NORMAL),
  348     ConstraintSyntaxNewBody("file_select", &file_select_body, "Choose which files select in a search", SYNTAX_STATUS_NORMAL),
  349     ConstraintSyntaxNewOption("file_type", "regular,fifo", "Type of file to create. Default value: regular", SYNTAX_STATUS_NORMAL),
  350     ConstraintSyntaxNewBody("link_from", &link_from_body, "Criteria for linking file from a source", SYNTAX_STATUS_NORMAL),
  351     ConstraintSyntaxNewBool("move_obstructions", "true/false whether to move obstructions to file-object creation. Default value: false", SYNTAX_STATUS_NORMAL),
  352     ConstraintSyntaxNewOption("pathtype", "literal,regex,guess", "Menu option for interpreting promiser file object", SYNTAX_STATUS_NORMAL),
  353     ConstraintSyntaxNewBody("perms", &perms_body, "Criteria for setting permissions on a file", SYNTAX_STATUS_NORMAL),
  354     ConstraintSyntaxNewBody("rename", &rename_body, "Criteria for renaming files", SYNTAX_STATUS_NORMAL),
  355     ConstraintSyntaxNewString("repository", CF_ABSPATHRANGE, "Name of a repository for versioning", SYNTAX_STATUS_NORMAL),
  356     ConstraintSyntaxNewBool("touch", "true/false whether to touch time stamps on file", SYNTAX_STATUS_NORMAL),
  357     ConstraintSyntaxNewString("transformer", CF_ABSPATHRANGE, "Command (with full path) used to transform current file (no shell wrapper used)", SYNTAX_STATUS_NORMAL),
  358     ConstraintSyntaxNewOption("template_method", "cfengine,inline_mustache,mustache", "", SYNTAX_STATUS_NORMAL),
  359     ConstraintSyntaxNewContainer("template_data", "", SYNTAX_STATUS_NORMAL),
  360 
  361     ConstraintSyntaxNewNull()
  362 };
  363 
  364 // edit_xml body syntax
  365 const ConstraintSyntax CF_COMMON_XMLBODIES[] =
  366 {
  367     ConstraintSyntaxNewString("build_xpath", "", "Build an XPath within the XML file", SYNTAX_STATUS_NORMAL),
  368     ConstraintSyntaxNewString("select_xpath", "", "Select the XPath node in the XML file to edit", SYNTAX_STATUS_NORMAL),
  369     ConstraintSyntaxNewNull()
  370 };
  371 
  372 static const ConstraintSyntax CF_INSERTTAGS_BODIES[] =
  373 {
  374     ConstraintSyntaxNewNull()
  375 };
  376 
  377 static const ConstraintSyntax CF_DELETETAGS_BODIES[] =
  378 {
  379     ConstraintSyntaxNewNull()
  380 };
  381 
  382 static const ConstraintSyntax CF_INSERTATTRIBUTES_BODIES[] =
  383 {
  384     ConstraintSyntaxNewString("attribute_value", "", "Value of the attribute to be inserted into the XPath node of the XML file", SYNTAX_STATUS_NORMAL),
  385     ConstraintSyntaxNewNull()
  386 };
  387 
  388 static const ConstraintSyntax CF_DELETEATTRIBUTES_BODIES[] =
  389 {
  390     ConstraintSyntaxNewNull()
  391 };
  392 
  393 
  394 // Master Syntax for Files
  395 
  396 const PromiseTypeSyntax CF_FILES_PROMISE_TYPES[] =
  397 {
  398     /* Body lists belonging to "files:" type in Agent */
  399 
  400     PromiseTypeSyntaxNew("agent", "files", CF_FILES_BODIES, NULL, SYNTAX_STATUS_NORMAL),
  401 
  402     /* Body lists belonging to th edit_line sub-bundle of files: */
  403 
  404     PromiseTypeSyntaxNew("edit_line", "*", CF_COMMON_EDITBODIES, NULL, SYNTAX_STATUS_NORMAL),
  405     PromiseTypeSyntaxNew("edit_line", "delete_lines", CF_DELETELINES_BODIES, NULL, SYNTAX_STATUS_NORMAL),
  406     PromiseTypeSyntaxNew("edit_line", "insert_lines", CF_INSERTLINES_BODIES, NULL, SYNTAX_STATUS_NORMAL),
  407     PromiseTypeSyntaxNew("edit_line", "field_edits", CF_COLUMN_BODIES, NULL, SYNTAX_STATUS_NORMAL),
  408     PromiseTypeSyntaxNew("edit_line", "replace_patterns", CF_REPLACE_BODIES, NULL, SYNTAX_STATUS_NORMAL),
  409 
  410     PromiseTypeSyntaxNew("edit_xml", "*", CF_COMMON_XMLBODIES, NULL, SYNTAX_STATUS_NORMAL),
  411     PromiseTypeSyntaxNew("edit_xml", "build_xpath", CF_INSERTTAGS_BODIES, NULL, SYNTAX_STATUS_NORMAL),
  412     PromiseTypeSyntaxNew("edit_xml", "delete_tree", CF_DELETETAGS_BODIES, NULL, SYNTAX_STATUS_NORMAL),
  413     PromiseTypeSyntaxNew("edit_xml", "insert_tree", CF_INSERTTAGS_BODIES, NULL, SYNTAX_STATUS_NORMAL),
  414     PromiseTypeSyntaxNew("edit_xml", "delete_attribute", CF_DELETEATTRIBUTES_BODIES, NULL, SYNTAX_STATUS_NORMAL),
  415     PromiseTypeSyntaxNew("edit_xml", "set_attribute", CF_INSERTATTRIBUTES_BODIES, NULL, SYNTAX_STATUS_NORMAL),
  416     PromiseTypeSyntaxNew("edit_xml", "delete_text", CF_DELETETAGS_BODIES, NULL, SYNTAX_STATUS_NORMAL),
  417     PromiseTypeSyntaxNew("edit_xml", "set_text", CF_INSERTTAGS_BODIES, NULL, SYNTAX_STATUS_NORMAL),
  418     PromiseTypeSyntaxNew("edit_xml", "insert_text", CF_INSERTTAGS_BODIES, NULL, SYNTAX_STATUS_NORMAL),
  419 
  420     PromiseTypeSyntaxNewNull()
  421 };