Project

General

Profile

« Previous | Next » 

Revision 20563d41

Added by Nicolas CHARLES over 6 years ago

Refs #6564: Creation of copyGitFile version 2.2 from 2.1

View differences:

maintained-techniques
fileDistribution/checkGenericFileContent/7.0
fileDistribution/copyGitFile/2.0
fileDistribution/copyGitFile/2.1
fileDistribution/copyGitFile/2.2
fileDistribution/downloadFile/3.0
fileDistribution/fileTemplate/1.0
fileDistribution/manageKeyValueFile/1.0
techniques/fileDistribution/copyGitFile/2.1/metadata.xml
-->
<TECHNIQUE name="File download (Rudder server)">
<DEPRECATED>This technique version has been superseded by a new version. It will no longer be available in the next stable version of Rudder. Please upgrade to the latest version.</DEPRECATED>
<DESCRIPTION>This technique ensure that some files are the copy of files on the shared folder of the Rudder Root Server, and let you optionally execute a command if the content of the file was modified</DESCRIPTION>
<MULTIINSTANCE>true</MULTIINSTANCE>
techniques/fileDistribution/copyGitFile/2.2/changelog
-- BenoƮt Peccatte <benoit.peccatte@normation.com> Fri Oct 17 14:10:43 CEST 2014
* Version 2.0
** Use rudder_common_report instead of reports:
** Add an option to purge local directory
-- Nicolas Charles <nicolas.charles@normation.com> Fri Nov 13 18:20:30 CEST 2014
* Version 2.1
** Add option to set sticky bit on whole folder
-- Nicolas Charles <nicolas.charles@normation.com> Wed Dec 13 15:41:33 2017
* Version 2.2
** Report on desrination rather than on source
techniques/fileDistribution/copyGitFile/2.2/copyFileFromSharedFolder.st
#####################################################################################
# Copyright 2011 Normation SAS
#####################################################################################
#
# 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, Version 3.
#
# 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/>.
#
#####################################################################################
bundle agent download_from_shared_folder
{
vars:
&COPYFILE_NAME:{name |"copyfile[&i&][name]" string => "&name&";
}&
&COPYFILE_EXCLUDE_INCLUDE:{exclude_include |"copyfile[&i&][exclude_include]" string => "&exclude_include&";
}&
&COPYFILE_EXCLUDE_INCLUDE_OPTION:{exclude_include_option |"copyfile[&i&][exclude_include_option]" string => "&exclude_include_option&";
}&
&COPYFILE_RECURSION:{rec |"copyfile[&i&][recursion]" string => "&rec&";
}&
&COPYFILE_OWNER:{owner |"copyfile[&i&][owner]" string => "&owner&";
}&
&COPYFILE_GROUP:{group |"copyfile[&i&][group]" string => "&group&";
}&
&COPYFILE_PURGE:{purge |"copyfile[&i&][purge]" string => "&purge&";
}&
&COPYFILE_COMPARE_METHOD:{compare_method |"copyfile[&i&][compare_method]" string => "&compare_method&";
}&
&COPYFILE_PERM:{perms |"copyfile[&i&][perm]" string => "&perms&";
}&
&COPYFILE_DESTINATION:{destination |"copyfile[&i&][destination]" string => "&destination&";
}&
&COPYFILE_POST_HOOK_COMMAND:{command |"copyfile[&i&][posthook]" string => "&command&";
}&
&TRACKINGKEY:{piuuid |"copyfile[&i&][uuid]" string => "&piuuid&";
}&
"shared_folder" string => "&SHARED_FILES_FOLDER&";
"canon_dirname_${index}" string => canonify(dirname("${copyfile[${index}][destination]}"));
"index" slist => getindices("copyfile");
iteration_1::
"extended_modes_${index}"
string => "4",
ifvarclass => "(enable_suid_${index}.!enable_sgid_${index}).(authorize_sticky_on_folder_${index}|is_file_${index})";
"extended_modes_${index}"
string => "2",
ifvarclass => "(!enable_suid_${index}.enable_sgid_${index}).(authorize_sticky_on_folder_${index}|is_file_${index})";
"extended_modes_${index}"
string => "6",
ifvarclass => "(enable_suid_${index}.enable_sgid_${index}).(authorize_sticky_on_folder_${index}|is_file_${index})";
"extended_modes_${index}"
string => "0",
ifvarclass => "(!enable_suid_${index}.!enable_sgid_${index})|!(authorize_sticky_on_folder_${index}|is_file_${index})";
defaults:
# Add a trailing slash to force considering destination as a directory and avoid replacing it with a file
"copyfile[${index}][destination]" string => "${copyfile[${index}][destination]}/", if_match_regex => ".*[^\/]",
ifvarclass => "pass1.!is_file_${index}";
classes:
"is_valid" not => strcmp("&SHARED_FILES_FOLDER&", "");
"exist_${index}" expression => fileexists("${copyfile[${index}][destination]}");
"is_file_${index}" not => isdir("${copyfile[${index}][destination]}");
"copy_file_${index}_dest_notdir" not => isdir(dirname("${copyfile[${index}][destination]}"));
"copy_file_${index}_user_absent" not => userexists("${copyfile[${index}][owner]}");
"copy_file_${index}_group_absent" not => groupexists("${copyfile[${index}][group]}");
"need_exclusion_${index}" and => { isvariable("copyfile[${index}][exclude_include]"), strcmp("${copyfile[${index}][exclude_include_option]}", "exclude") };
"need_inclusion_${index}" and => { isvariable("copyfile[${index}][exclude_include]"), strcmp("${copyfile[${index}][exclude_include_option]}", "include") };
"apply_regex_${index}" or => { "need_exclusion_${index}", "need_inclusion_${index}"};
&COPYFILE_SUID:{suid |"enable_suid_&i&" expression => strcmp("&suid&", "true");
}&
&COPYFILE_SGID:{sgid |"enable_sgid_&i&" expression => strcmp("&sgid&", "true");
}&
# We authorize sticky only we recursion is level 1
&COPYFILE_STICKY_FOLDER:{sticky_folder |"enable_sticky_bit_folder_&i&" expression => strcmp("&sticky_folder&", "true");
}&
"recursion_only_on_folder_${index}" expression => strcmp("1", "${copyfile[${index}][recursion]}");
"authorize_sticky_on_folder_${index}" and => {
"recursion_only_on_folder_${index}",
"enable_sticky_bit_folder_${index}"
};
# Set a class to define when we need to run the post-modification hook
&COPYFILE_POST_HOOK_RUN:{run |"execute_command_&i&" expression => strcmp("&run&", "true");
}&
"iteration_2" expression => "iteration_1";
"iteration_1" expression => "any";
any::
"pass3" expression => "pass2";
"pass2" expression => "pass1";
"pass1" expression => "any";
files:
is_valid.iteration_2::
# Suid and sgid may be setted only if the option to set it recursively, and recursion level is 1, or we are managing a file
# If it's a directory, without exclusion
"${copyfile[${index}][destination]}"
copy_from => rudder_copy_from("&SHARED_FILES_FOLDER&/${copyfile[${index}][name]}", "${server_info.cfserved}", "${copyfile[${index}][compare_method]}", "false", "false", "${copyfile[${index}][purge]}"),
depth_search => recurse("${copyfile[${index}][recursion]}"),
perms => mog(
"${extended_modes_${index}}${copyfile[${index}][perm]}",
"${copyfile[${index}][owner]}",
"${copyfile[${index}][group]}"
),
comment => "Enforce content of ${copyfile[${index}][destination]} based on the content on the Rudder server with ${copyfile[${index}][compare_method]} method",
classes => rudder_common_classes("copy_file_${index}"),
ifvarclass => "(!exist_${index}|!is_file_${index}).!apply_regex_${index}";
# If it's a directory, with exclusion
"${copyfile[${index}][destination]}"
copy_from => rudder_copy_from("&SHARED_FILES_FOLDER&/${copyfile[${index}][name]}", "${server_info.cfserved}", "${copyfile[${index}][compare_method]}", "false", "false", "${copyfile[${index}][purge]}"),
depth_search => recurse("${copyfile[${index}][recursion]}"),
file_select => exclude("${copyfile[${index}][exclude_include]}"),
perms => mog(
"${extended_modes_${index}}${copyfile[${index}][perm]}",
"${copyfile[${index}][owner]}",
"${copyfile[${index}][group]}"
),
comment => "Enforce content of ${copyfile[${index}][destination]} based on the content on the Rudder server with ${copyfile[${index}][compare_method]} method",
classes => rudder_common_classes("copy_file_${index}"),
ifvarclass => "(!exist_${index}|!is_file_${index}).need_exclusion_${index}";
# If it's a directory, with inclusion
"${copyfile[${index}][destination]}"
copy_from => rudder_copy_from("&SHARED_FILES_FOLDER&/${copyfile[${index}][name]}", "${server_info.cfserved}", "${copyfile[${index}][compare_method]}", "false", "false", "${copyfile[${index}][purge]}"),
depth_search => recurse("${copyfile[${index}][recursion]}"),
file_select => by_name("${copyfile[${index}][exclude_include]}"),
perms => mog(
"${extended_modes_${index}}${copyfile[${index}][perm]}",
"${copyfile[${index}][owner]}",
"${copyfile[${index}][group]}"
),
comment => "Enforce content of ${copyfile[${index}][destination]} based on the content on the Rudder server with ${copyfile[${index}][compare_method]} method with inclusion of '${copyfile[${index}][exclude_include]}'",
classes => rudder_common_classes("copy_file_${index}"),
ifvarclass => "(!exist_${index}|!is_file_${index}).need_inclusion_${index}";
# If it s a file, the depth_search prevents from enforcing the file content
# Besides it is possible to specify suid or sgid only for a file since this
# is too dangerous to apply suid or sgid recursively and only copy an empty
# directory does not make sense.
# Don't take purge in account as well.
"${copyfile[${index}][destination]}"
copy_from => rudder_copy_from("&SHARED_FILES_FOLDER&/${copyfile[${index}][name]}", "${server_info.cfserved}", "${copyfile[${index}][compare_method]}", "false", "false", "false"),
perms => mog(
"${extended_modes_${index}}${copyfile[${index}][perm]}",
"${copyfile[${index}][owner]}",
"${copyfile[${index}][group]}"
),
comment => "Enforce content of file ${copyfile[${index}][destination]} based on the content on the Rudder server with ${copyfile[${index}][compare_method]} method with exclusion of '${copyfile[${index}][exclude_include]}'",
classes => rudder_common_classes("copy_file_${index}"),
ifvarclass => "exist_${index}.is_file_${index}";
methods:
"any" usebundle => file_check_symlink(dirname("${copyfile[${index}][destination]}"));
pass3.(!is_valid)::
"any" usebundle => rudder_common_report("copyFile", "result_error", "${copyfile[${index}][uuid]}", "Copy file", "${copyfile[${index}][name]}", "There is no shared folder on the Rudder Server, so it's not possible to copy a file from it");
pass3.is_valid::
"any" usebundle => rudder_common_report("copyFile", "result_success", "${copyfile[${index}][uuid]}", "Copy file", "${copyfile[${index}][name]}", "The content of the file(s) is valid"),
ifvarclass => "copy_file_${index}_kept.!copy_file_${index}_repaired.!copy_file_${index}_error";
"any" usebundle => rudder_common_report("copyFile", "result_repaired", "${copyfile[${index}][uuid]}", "Copy file", "${copyfile[${index}][name]}", "The content or permissions of the file(s) has been repaired"),
ifvarclass => "copy_file_${index}_repaired.!copy_file_${index}_error";
# Error conditons
## The destination is not an existing directory or symbolic link
"any" usebundle => rudder_common_report("copyFile", "result_error", "${copyfile[${index}][uuid]}", "Copy file", "${copyfile[${index}][name]}", "The copy of the file failed: the destination (${copyfile[${index}][destination]}) is not stored in a valid directory"),
ifvarclass => "copy_file_${index}_dest_notdir.file_check_symlink_${canon_dirname_${index}}_failed";
## File access denied
"any" usebundle => rudder_common_report("copyFile", "result_error", "${copyfile[${index}][uuid]}", "Copy file", "${copyfile[${index}][name]}", "The copy of the file failed: access to ${copyfile[${index}][name]} denied by the server"),
ifvarclass => "copy_file_${index}_denied";
## User does not exist
"any" usebundle => rudder_common_report("copyFile", "result_error", "${copyfile[${index}][uuid]}", "Copy file", "${copyfile[${index}][name]}", "The permissions could not be applied on the file: user \"${copyfile[${index}][owner]}\" not found"),
ifvarclass => "copy_file_${index}_user_absent";
## Group does not exist
"any" usebundle => rudder_common_report("copyFile", "result_error", "${copyfile[${index}][uuid]}", "Copy file", "${copyfile[${index}][name]}", "The permissions could not be applied on the file: group \"${copyfile[${index}][group]}\" not found"),
ifvarclass => "copy_file_${index}_group_absent";
## Generic failure
"any" usebundle => rudder_common_report("copyFile", "result_error", "${copyfile[${index}][uuid]}", "Copy file", "${copyfile[${index}][name]}", "The content or permissions of the file(s) could not have been repaired (file not found?)"),
ifvarclass => "copy_file_${index}_error.!copy_file_${index}_dest_notdir.!copy_file_${index}_denied.!copy_file_${index}_user_absent.!copy_file_${index}_group_absent";
#posthook reports
"any" usebundle => rudder_common_report("copyFile", "result_success", "${copyfile[${index}][uuid]}", "Post-modification hook", "${copyfile[${index}][name]}", "No post-hook command for ${copyfile[${index}][destination]} was defined, not executing"),
ifvarclass => "!execute_command_${index}";
"any" usebundle => rudder_common_report("copyFile", "result_success", "${copyfile[${index}][uuid]}", "Post-modification hook", "${copyfile[${index}][name]}", "${copyfile[${index}][destination]} was already in the desired state, so no command was executed"),
ifvarclass => "execute_command_${index}.!copy_file_${index}_failed.!copy_file_${index}_repaired.copy_file_${index}_kept";
"any" usebundle => rudder_common_report("copyFile", "result_success", "${copyfile[${index}][uuid]}", "Post-modification hook", "${copyfile[${index}][name]}", "The post-hook command for ${copyfile[${index}][destination]} was correctly executed"),
ifvarclass => "execute_command_${index}.copyfile_posthook_${index}_command_run_ok";
"any" usebundle => rudder_common_report("copyFile", "result_error", "${copyfile[${index}][uuid]}", "Post-modification hook", "${copyfile[${index}][name]}", "The post-hook command for ${copyfile[${index}][destination]} couldn't be executed"),
ifvarclass => "execute_command_${index}.copyfile_posthook_${index}_command_run_failed";
# A copy_from + perms could result in any combinaision of success/repaired/failed, so we have to cover the failed.modified which results in no copy
"any" usebundle => rudder_common_report("copyFile", "result_error", "${copyfile[${index}][uuid]}", "Post-modification hook", "${copyfile[${index}][name]}", "${copyfile[${index}][destination]} couldn't be copied, so the post-hook command is not executed"),
ifvarclass => "execute_command_${index}.copy_file_${index}_error";
commands:
"${copyfile[${index}][posthook]}"
contain => in_shell,
classes => if_else("copyfile_posthook_${index}_command_run_ok", "copyfile_posthook_${index}_command_run_failed"),
ifvarclass => "execute_command_${index}.copy_file_${index}_repaired.!copy_file_${index}_error",
comment => "Execute the posthook command if a file was changed";
}
techniques/fileDistribution/copyGitFile/2.2/metadata.xml
<!--
Copyright 2011 Normation SAS
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, Version 3.
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/>.
-->
<TECHNIQUE name="File download (Rudder server)">
<DESCRIPTION>This technique ensure that some files are the copy of files on the shared folder of the Rudder Root Server, and let you optionally execute a command if the content of the file was modified</DESCRIPTION>
<MULTIINSTANCE>true</MULTIINSTANCE>
<COMPATIBLE>
<OS version=">= 4 (Etch)">Debian</OS>
<OS version=">= 4 (Nahant)">RHEL / CentOS</OS>
<OS version=">= 10 SP1 (Agama Lizard)">SuSE LES / DES / OpenSuSE</OS>
<AGENT version=">= 3.2.0">cfengine-community</AGENT>
</COMPATIBLE>
<BUNDLES>
<NAME>download_from_shared_folder</NAME>
</BUNDLES>
<TMLS>
<TML name="copyFileFromSharedFolder"/>
</TMLS>
<TRACKINGVARIABLE>
<SAMESIZEAS>COPYFILE_NAME</SAMESIZEAS>
</TRACKINGVARIABLE>
<SYSTEMVARS>
<NAME>SHARED_FILES_FOLDER</NAME>
</SYSTEMVARS>
<SECTIONS>
<SECTION name="Copy file and PostHook" multivalued="true">
<SECTION name="Copy file" multivalued="false" component="true" componentKey="COPYFILE_NAME">
<INPUT>
<NAME>COPYFILE_NAME</NAME>
<DESCRIPTION>Path of the file to be copied</DESCRIPTION>
<LONGDESCRIPTION>This is the relative path of the file/folder to be copied, on the Rudder policy server</LONGDESCRIPTION>
<CONSTRAINT>
<TYPE>sharedfile</TYPE>
</CONSTRAINT>
</INPUT>
<SECTION name="Exclusion/Inclusion" multivalued="false" component="false" displayPriority="low">
<SELECT1>
<NAME>COPYFILE_EXCLUDE_INCLUDE_OPTION</NAME>
<DESCRIPTION>Exclude or include files from the copy</DESCRIPTION>
<LONGDESCRIPTION>Limit list of files to copy (include) or don't copy some files matching a pattern (exclude). Only applies if the path to copy from is a directory.</LONGDESCRIPTION>
<ITEM>
<VALUE>none</VALUE>
<LABEL>No include/exclude rules</LABEL>
</ITEM>
<ITEM>
<VALUE>exclude</VALUE>
<LABEL>Exclude file(s) matching</LABEL>
</ITEM>
<ITEM>
<VALUE>include</VALUE>
<LABEL>Include file(s) matching</LABEL>
</ITEM>
<CONSTRAINT>
<DEFAULT>none</DEFAULT>
</CONSTRAINT>
</SELECT1>
<INPUT>
<NAME>COPYFILE_EXCLUDE_INCLUDE</NAME>
<DESCRIPTION>File name patterns to exclude or include</DESCRIPTION>
<LONGDESCRIPTION>If one or several files should be excluded or included in this copy, please insert their name or a regular expression matching the appropriate file name(s))</LONGDESCRIPTION>
<CONSTRAINT>
<MAYBEEMPTY>true</MAYBEEMPTY>
</CONSTRAINT>
</INPUT>
</SECTION>
<INPUT>
<NAME>COPYFILE_DESTINATION</NAME>
<DESCRIPTION>Full path of destination file or directory (on which permissions defined below will be applied)</DESCRIPTION>
<LONGDESCRIPTION>This is the absolute path of the file/folder on the managed node. If you are copying a file, the destination
path needs to contain the destination filename. The permissions defined below will be applied on the whole content of the destination, including files that were not copied.</LONGDESCRIPTION>
</INPUT>
<SELECT1>
<NAME>COPYFILE_RECURSION</NAME>
<DESCRIPTION>What should be the recursion level of the copy</DESCRIPTION>
<ITEM>
<VALUE>0</VALUE>
<LABEL>Only this file</LABEL>
</ITEM>
<ITEM>
<VALUE>1</VALUE>
<LABEL>The whole content of the folder</LABEL>
</ITEM>
<ITEM>
<VALUE>inf</VALUE>
<LABEL>The folder, its content, and all the subfolders</LABEL>
</ITEM>
<CONSTRAINT>
<DEFAULT>0</DEFAULT>
</CONSTRAINT>
</SELECT1>
<SELECT1>
<NAME>COPYFILE_PURGE</NAME>
<DESCRIPTION>Purge the destination directory</DESCRIPTION>
<LONGDESCRIPTION>If this is enabled, all other content than the source in the destination directory will be purged.</LONGDESCRIPTION>
<ITEM>
<VALUE>false</VALUE>
<LABEL>False</LABEL>
</ITEM>
<ITEM>
<VALUE>true</VALUE>
<LABEL>True</LABEL>
</ITEM>
<CONSTRAINT>
<DEFAULT>false</DEFAULT>
</CONSTRAINT>
</SELECT1>
<SELECT1>
<NAME>COPYFILE_COMPARE_METHOD</NAME>
<DESCRIPTION>File comparison method</DESCRIPTION>
<LONGDESCRIPTION>This is the method to use for comparison between source and destination files.
- "mtime" copies the file if the modification time of the source file is more recent than that of the promised file.
- "ctime" copies the file if the creation time of the source file is more recent than that of the promised file.
- "atime" copies the file if the modification time or creation time of the source file is more recent than that of the promised file. If the times are equal, a byte-for-byte comparison is done on the files to determine if it needs to be copied.
- "exists" copies the file if the promised file does not already exist.
- "binary" copies the file if they are both plain files and a byte-for-byte comparison determines that they are different. If both are not plain files, the agent reverts to comparing the mtime and ctime of the files. If the source file is on a different machine (i.e., network copy), then hash is used instead to reduce network bandwidth.
- "digest" copies the file if they are both plain files and a MD5 message digest comparison indicates that the files are different.
The "digest" option is set by default but may offer poor performance on large numbers (over 100) of file copies - in that case use "mtime" instead.</LONGDESCRIPTION>
<ITEM>
<VALUE>mtime</VALUE>
<LABEL>mtime</LABEL>
</ITEM>
<ITEM>
<VALUE>atime</VALUE>
<LABEL>atime</LABEL>
</ITEM>
<ITEM>
<VALUE>ctime</VALUE>
<LABEL>ctime</LABEL>
</ITEM>
<ITEM>
<VALUE>digest</VALUE>
<LABEL>digest</LABEL>
</ITEM>
<ITEM>
<VALUE>binary</VALUE>
<LABEL>binary</LABEL>
</ITEM>
<ITEM>
<VALUE>exists</VALUE>
<LABEL>exists</LABEL>
</ITEM>
<CONSTRAINT>
<DEFAULT>digest</DEFAULT>
</CONSTRAINT>
</SELECT1>
<INPUT>
<NAME>COPYFILE_OWNER</NAME>
<DESCRIPTION>Owner of the destination file or whole directory content</DESCRIPTION>
<LONGDESCRIPTION>If the destination is a directory, this will apply to the whole content, including files that were not copied.</LONGDESCRIPTION>
<CONSTRAINT>
<DEFAULT>root</DEFAULT>
</CONSTRAINT>
</INPUT>
<INPUT>
<NAME>COPYFILE_GROUP</NAME>
<DESCRIPTION>Group of the destination file or whole directory content</DESCRIPTION>
<LONGDESCRIPTION>If the destination is a directory, this will apply to the whole content, including files that were not copied.</LONGDESCRIPTION>
<CONSTRAINT>
<DEFAULT>root</DEFAULT>
</CONSTRAINT>
</INPUT>
<INPUT>
<NAME>COPYFILE_PERM</NAME>
<DESCRIPTION>Permissions to apply on the file or whole directory content</DESCRIPTION>
<LONGDESCRIPTION>If the destination is a directory, this will apply to the whole content, including files that were not copied.</LONGDESCRIPTION>
<CONSTRAINT>
<TYPE>perm</TYPE>
<DEFAULT>644</DEFAULT>
</CONSTRAINT>
</INPUT>
<INPUT>
<NAME>COPYFILE_SUID</NAME>
<DESCRIPTION>Set SetUID bit?</DESCRIPTION>
<LONGDESCRIPTION>Note: The SetUID and SetGID bits will not be applied recursively, for obvious security reasons.</LONGDESCRIPTION>
<CONSTRAINT>
<TYPE>boolean</TYPE>
<DEFAULT>false</DEFAULT>
</CONSTRAINT>
</INPUT>
<INPUT>
<NAME>COPYFILE_SGID</NAME>
<DESCRIPTION>Set SetGID bit?</DESCRIPTION>
<LONGDESCRIPTION>Note: The SetUID and SetGID bits will not be applied recursively, for obvious security reasons.</LONGDESCRIPTION>
<CONSTRAINT>
<TYPE>boolean</TYPE>
<DEFAULT>false</DEFAULT>
</CONSTRAINT>
</INPUT>
<INPUT>
<NAME>COPYFILE_STICKY_FOLDER</NAME>
<DESCRIPTION>Apply the sticky bit to the whole folder? (caution, use with care)</DESCRIPTION>
<LONGDESCRIPTION>If set, and the path is a folder, and recursion is set to "The whole content of the folder", apply on the whole folder (won't apply to subfolders, for obvious security reasons).</LONGDESCRIPTION>
<CONSTRAINT>
<TYPE>boolean</TYPE>
<DEFAULT>false</DEFAULT>
</CONSTRAINT>
</INPUT>
</SECTION>
<SECTION name="Post-modification hook" component="true" multivalued="false" componentKey="COPYFILE_NAME" displayPriority="low">
<INPUT>
<NAME>COPYFILE_POST_HOOK_RUN</NAME>
<DESCRIPTION>Should the command(s) below be run if any modifications (permission or overwriting) are made on the files above?</DESCRIPTION>
<CONSTRAINT>
<TYPE>boolean</TYPE>
<DEFAULT>false</DEFAULT>
</CONSTRAINT>
</INPUT>
<INPUT>
<NAME>COPYFILE_POST_HOOK_COMMAND</NAME>
<DESCRIPTION>Command to run after any modifications</DESCRIPTION>
<CONSTRAINT>
<TYPE>textarea</TYPE>
<MAYBEEMPTY>true</MAYBEEMPTY>
</CONSTRAINT>
</INPUT>
</SECTION>
</SECTION>
</SECTIONS>
</TECHNIQUE>

Also available in: Unified diff