Attached are patches for various bugs and new features to cfengine. All patches are against cfengine 3.0.2.
[FIX] patch-bsd-df space returned from statfs() is in number of blocks, which is not necessarily 1024 bytes. [FEATURE] patch-collapse-level Extend collapse_destination_dir constraint to allow collapsing of up to an arbitrary number of directory levels. This is useful if you have organized files into sets by putting them into different source directories, such as in the example below: body copy_from copy_c1($srcdir) { source => "$(srcdir"); collapse_destination_dir => 1; } bundle agent docopy($src, $dst) { vars: "dirs" slist => { "$(src)/$(sys.os)", "$(src)/$(sys.os)-$(sys.arch)", "$(src)/$(sys.os)-$(sys.release)", "$(src)/$(sys.os)-$(sys.release)-$(sys.arch)", "$(src)/.*/.*" }; files: "$dst" copy_from => copy_c1("$(src)"), depth_search => recurse_pkg_includedirs("inf", "@(dirs)"); } [FEATURE] patch-diskfree adds diskfree(dir) function to return space available at any location. [FEATURE] patch-dz-arithmetic adds simple arithmetic functions [FIX] patch-exclude-first Fixes the bug where only include_dirs is considered when both include_dirs and exclude_dirs are specified in a search, by evaluating the exclusion list first. [FIX] patch-linkstatus Fixes the problem where various link promises are always counted as repaired. [FIX] patch-method-nochg Fixes the problem where usemethod invocations are counted as extra repaired promises. [FIX] patch-moveobstructions-whennofile Whether or not a directory is moved aside in file operations should not depend on the when_no_source attribute. [FEATURE/FIX] patch-netgroup Allow various server controls to match based on netgroup in addition to IP or hostname. Specify "@netgroup-name" in place of hostnames to do netgroup matching. This patch also fixes the lack of hostname based matching on the trustkeysfrom and dynamicaddresses promises. [FIX] patch-nodeleteslash When verifying soft links, do not attempt to delete the trailing slash from the current on-disk state if the expected link destination also has a trailing slash. [FIX] patch-nodupclass Avoid adding duplicate result classes to the global class list. This prevents /var/cfengine/state/allclasses.txt from exploding in size when you have lots of result classes. [FIX] patch-regex-detect Improve regex detection in IsRegex() to decrease the chance of false positives. [FIX] patch-single-copy The files_single_copy list was only being matched quazi-literally, where the file name was actually being used as a regex and the single copy list was being matched against that.
--- src/storage_tools.c~ 2009-08-24 21:37:25.000000000 -0400 +++ src/storage_tools.c 2009-08-24 21:38:53.000000000 -0400 @@ -100,9 +100,9 @@ #endif #if defined NETBSD || defined FREEBSD || defined OPENBSD || defined SUNOS || defined HPuUX || defined DARWIN - total = buf.f_blocks; - used = buf.f_blocks - buf.f_bfree; - avail = buf.f_bavail; + total = buf.f_blocks * buf.f_bsize / blocksize; + used = (buf.f_blocks - buf.f_bfree) * buf.f_bsize / blocksize; + avail = buf.f_bavail * buf.f_bsize / blocksize; #endif #if defined OSF
diff -u src~/attributes.c src/attributes.c --- src~/attributes.c 2009-08-25 20:40:55.000000000 -0400 +++ src/attributes.c 2009-08-25 21:14:00.000000000 -0400 @@ -733,7 +733,13 @@ } f.stealth = GetBooleanConstraint("stealth",pp->conlist); -f.collapse = GetBooleanConstraint("collapse_destination_dir",pp->conlist); + +value = (char *)GetConstraint("collapse_destination_dir",pp->conlist,CF_SCALAR); +if (value == NULL) + f.collapse = 0; +else + f.collapse = String2CollapseLevel(value); + f.preserve = GetBooleanConstraint("preserve",pp->conlist); f.type_check = GetBooleanConstraint("type_check",pp->conlist); f.force_update = GetBooleanConstraint("force_update",pp->conlist); diff -u src~/conversion.c src/conversion.c --- src~/conversion.c 2009-08-25 20:40:55.000000000 -0400 +++ src/conversion.c 2009-08-25 21:20:42.000000000 -0400 @@ -237,6 +237,29 @@ /****************************************************************************/ +int String2CollapseLevel(char *s) + +{ int i; + static char *infs[] = {"true", "yes", "on", "inf", NULL}; + static char *zeros[] = {"false", "no", "off", NULL}; + +if (!s) return 0; +for (i = 0; infs[i] != NULL; i++) + { + if (strcmp(s,infs[i]) == 0) + return CF_INFINITY; + } +for (i = 0; zeros[i] != NULL; i++) + { + if (strcmp(s,zeros[i]) == 0) + return 0; + } + +return (int)Str2Int(s); +} + +/****************************************************************************/ + enum cfcomparison String2Comparison(char *s) { int i; diff -u src~/files_copy.c src/files_copy.c --- src~/files_copy.c 2009-08-25 20:40:55.000000000 -0400 +++ src/files_copy.c 2009-08-25 20:59:45.000000000 -0400 @@ -80,7 +80,7 @@ CfOut(cf_verbose,""," ->> Entering %s\n",source); SetSearchDevice(&ssb,pp); - SourceSearchAndCopy(source,destination,attr.recursion.depth,attr,pp); + SourceSearchAndCopy(source,destination,attr.recursion.depth,0,attr,pp); if (stat(destination,&dsb) != -1) { diff -u src~/files_interfaces.c src/files_interfaces.c --- src~/files_interfaces.c 2009-08-25 20:40:55.000000000 -0400 +++ src/files_interfaces.c 2009-08-25 21:07:30.000000000 -0400 @@ -36,7 +36,7 @@ /* File copying is a special case, particularly complex - cannot be integrated */ -void SourceSearchAndCopy(char *from,char *to,int maxrecurse,struct Attributes attr,struct Promise *pp) +void SourceSearchAndCopy(char *from,char *to,int maxrecurse,int level,struct Attributes attr,struct Promise *pp) { struct stat sb, dsb; char newfrom[CF_BUFSIZE]; @@ -124,7 +124,7 @@ /* If we are tracking subdirs in copy, then join else don't add*/ - if (attr.copy.collapse) + if (level < attr.copy.collapse) { if (!S_ISDIR(sb.st_mode) && !JoinPath(newto,dirp->d_name)) { @@ -164,7 +164,7 @@ /* Only copy dirs if we are tracking subdirs */ - if (!attr.copy.collapse && (stat(newto,&dsb) == -1)) + if (!(level < attr.copy.collapse) && (stat(newto,&dsb) == -1)) { if (mkdir(newto,0700) == -1) { @@ -181,12 +181,12 @@ CfOut(cf_verbose,""," ->> Entering %s\n",newto); - if (!attr.copy.collapse) + if (!(level < attr.copy.collapse)) { VerifyCopiedFileAttributes(newto,&dsb,&sb,attr,pp); } - SourceSearchAndCopy(newfrom,newto,maxrecurse-1,attr,pp); + SourceSearchAndCopy(newfrom,newto,maxrecurse-1,level+1,attr,pp); } else { diff -u src~/mod_files.c src/mod_files.c --- src~/mod_files.c 2009-08-25 20:40:55.000000000 -0400 +++ src/mod_files.c 2009-08-25 21:11:16.000000000 -0400 @@ -303,7 +303,7 @@ { {"source",cf_str,CF_PATHRANGE,"Reference source file from which to copy"}, {"servers",cf_slist,"[A-Za-z0-9_.:-]+","List of servers in order of preference from which to copy"}, - {"collapse_destination_dir",cf_opts,CF_BOOL,"true/false Place files in subdirectories into the root destination directory during copy"}, + {"collapse_destination_dir",cf_str,"0|true|false|yes|no|on|off|[0-9][0-9]*|inf","Place files in subdirectories into the root destination directory during copy, up to the specified number of levels"}, {"compare",cf_opts,"atime,mtime,ctime,digest,hash","Menu option policy for comparing source and image file attributes"}, {"copy_backup",cf_opts,"true,false,timestamp","Menu option policy for file backup/version control"}, {"encrypt",cf_opts,CF_BOOL,"true/false use encrypted data stream to connect to remote host"}, diff -u src~/prototypes3.h src/prototypes3.h --- src~/prototypes3.h 2009-08-25 20:40:55.000000000 -0400 +++ src/prototypes3.h 2009-08-25 21:20:55.000000000 -0400 @@ -231,6 +231,7 @@ int Signal2Int(char *s); enum cfreport String2ReportLevel(char *typestr); enum cfhashes String2HashType(char *typestr); +int String2CollapseLevel(char *s); enum cfcomparison String2Comparison(char *s); enum cflinktype String2LinkType(char *s); enum cfdatatype Typename2Datatype(char *name); @@ -550,7 +551,7 @@ /* files_interfaces.c */ -void SourceSearchAndCopy(char *from,char *to,int maxrecurse,struct Attributes attr,struct Promise *pp); +void SourceSearchAndCopy(char *from,char *to,int maxrecurse,int level,struct Attributes attr,struct Promise *pp); void VerifyCopy(char *source,char *destination,struct Attributes attr,struct Promise *pp); void PurgeLocalFiles(struct Item *filelist,char *directory,struct Attributes attr,struct Promise *pp); void CopyFile(char *sourcefile,char *destfile,struct stat sourcestatbuf,struct Attributes attr, struct Promise *pp);
Only in src~: .mod_common.c.swp diff -u src~/cf3.defs.h src/cf3.defs.h --- src~/cf3.defs.h 2009-08-24 21:12:52.000000000 -0400 +++ src/cf3.defs.h 2009-08-24 21:13:55.000000000 -0400 @@ -488,6 +488,7 @@ cfn_changedbefore, cfn_classify, cfn_classmatch, + cfn_diskfree, cfn_execresult, cfn_fileexists, cfn_filesexist, diff -u src~/evalfunction.c src/evalfunction.c --- src~/evalfunction.c 2009-08-24 21:12:52.000000000 -0400 +++ src/evalfunction.c 2009-08-24 21:42:52.000000000 -0400 @@ -3898,6 +3898,45 @@ return rval; } +/*********************************************************************/ + +struct Rval FnCallDiskFree(struct FnCall *fp,struct Rlist *finalargs) + +{ static char *argtemplate[] = + { + CF_ANYSTRING, + NULL + }; + static enum cfdatatype argtypes[] = + { + cf_str, + cf_notype + }; + + struct Rlist *rp; + struct Rval rval; + char buffer[CF_BUFSIZE]; + u_long df; + +buffer[0] = '\0'; +ArgTemplate(fp,argtemplate,argtypes,finalargs); /* Arg validation */ + +df = GetDiskUsage((char *)finalargs->item, cfabs); +if (df == CF_INFINITY) df = 0; +snprintf(buffer,CF_BUFSIZE-1,"%d", df); + +if ((rval.item = strdup(buffer)) == NULL) + { + FatalError("Memory allocation in FnCallGetGid"); + } + +/* end fn specific content */ + +rval.rtype = CF_SCALAR; +return rval; +} + + /*********************************************************************/ /* Level */ diff -u src~/fncall.c src/fncall.c --- src~/fncall.c 2009-08-24 21:12:52.000000000 -0400 +++ src/fncall.c 2009-08-24 21:16:16.000000000 -0400 @@ -444,6 +444,9 @@ case cfn_selectservers: rval = FnCallSelectServers(fp,expargs); break; + case cfn_diskfree: + rval = FnCallDiskFree(fp,expargs); + break; case cfn_unknown: CfOut(cf_error,"","Un-registered function call"); diff -u src~/mod_common.c src/mod_common.c --- src~/mod_common.c 2009-08-24 21:12:52.000000000 -0400 +++ src/mod_common.c 2009-08-24 21:13:47.000000000 -0400 @@ -52,6 +52,7 @@ {"changedbefore",cf_class,2,"True if arg1 was changed before arg2 (ctime)"}, {"classify",cf_class,1,"True if the canonicalization of the argument is a currently defined class"}, {"classmatch",cf_class,1,"True if the regular expression matches any currently defined class"}, + {"diskfree",cf_int,1,"Return the free space (in KB) available for a directory (0 if not found)"}, {"execresult",cf_str,2,"Execute named command and assign output to variable"}, {"fileexists",cf_class,1,"True if the named file can be accessed"}, {"filesexist",cf_class,1,"True if the named list of files can ALL be accessed"}, diff -u src~/prototypes3.h src/prototypes3.h --- src~/prototypes3.h 2009-08-24 21:12:52.000000000 -0400 +++ src/prototypes3.h 2009-08-24 21:16:06.000000000 -0400 @@ -437,6 +437,7 @@ struct Rval FnCallRegistryValue(struct FnCall *fp,struct Rlist *finalargs); struct Rval FnCallLastNode(struct FnCall *fp,struct Rlist *finalargs); struct Rval FnCallFileSexist(struct FnCall *fp,struct Rlist *finalargs); +struct Rval FnCallDiskFree(struct FnCall *fp,struct Rlist *finalargs); void *CfReadFile(char *filename,int maxsize); char *StripPatterns(char *file_buffer,char *pattern);
diff -ur src~/cf3.defs.h src/cf3.defs.h --- src~/cf3.defs.h 2009-08-24 22:04:43.000000000 -0400 +++ src/cf3.defs.h 2009-08-24 22:06:51.000000000 -0400 @@ -483,12 +483,14 @@ { cfn_accessedbefore, cfn_accum, + cfn_add, cfn_ago, cfn_canonify, cfn_changedbefore, cfn_classify, cfn_classmatch, cfn_diskfree, + cfn_divide, cfn_execresult, cfn_fileexists, cfn_filesexist, @@ -513,6 +515,7 @@ cfn_ldaparray, cfn_ldaplist, cfn_ldapvalue, + cfn_multiply, cfn_now, cfn_date, cfn_peers, @@ -540,6 +543,7 @@ cfn_splayclass, cfn_splitstring, cfn_strcmp, + cfn_subtract, cfn_usemodule, cfn_userexists, cfn_unknown, diff -ur src~/fncall.c src/fncall.c --- src~/fncall.c 2009-08-24 22:04:43.000000000 -0400 +++ src/fncall.c 2009-08-24 22:15:14.000000000 -0400 @@ -447,6 +447,18 @@ case cfn_diskfree: rval = FnCallDiskFree(fp,expargs); break; + case cfn_add: + rval = FnCallArithmetic(fp,expargs,'+'); + break; + case cfn_subtract: + rval = FnCallArithmetic(fp,expargs,'-'); + break; + case cfn_multiply: + rval = FnCallArithmetic(fp,expargs,'*'); + break; + case cfn_divide: + rval = FnCallArithmetic(fp,expargs,'/'); + break; case cfn_unknown: CfOut(cf_error,"","Un-registered function call"); diff -ur src~/mod_common.c src/mod_common.c --- src~/mod_common.c 2009-08-24 22:04:43.000000000 -0400 +++ src/mod_common.c 2009-08-24 22:17:25.000000000 -0400 @@ -47,12 +47,14 @@ { {"accessedbefore",cf_class,2,"True if arg1 was accessed before arg2 (atime)"}, {"accumulated",cf_int,6,"Convert an accumulated amount of time into a system representation"}, + {"add",cf_int,2,"Add two integers"}, {"ago",cf_int,6,"Convert a time relative to now to an integer system representation"}, {"canonify",cf_str,1,"Convert an abitrary string into a legal class name"}, {"changedbefore",cf_class,2,"True if arg1 was changed before arg2 (ctime)"}, {"classify",cf_class,1,"True if the canonicalization of the argument is a currently defined class"}, {"classmatch",cf_class,1,"True if the regular expression matches any currently defined class"}, {"diskfree",cf_int,1,"Return the free space (in KB) available for a directory (0 if not found)"}, + {"divide",cf_int,2,"Divide two integers"}, {"execresult",cf_str,2,"Execute named command and assign output to variable"}, {"fileexists",cf_class,1,"True if the named file can be accessed"}, {"filesexist",cf_class,1,"True if the named list of files can ALL be accessed"}, @@ -77,6 +79,7 @@ {"ldaparray",cf_class,6,"Extract all values from an ldap record"}, {"ldaplist",cf_slist,6,"Extract all named values from multiple ldap records"}, {"ldapvalue",cf_str,6,"Extract the first matching named value from ldap"}, + {"multiply",cf_int,2,"Multiply two integers"}, {"now",cf_int,0,"Convert the current time into system representation"}, {"on",cf_int,6,"Convert an exact date/time to an integer system representation"}, {"peers",cf_slist,3,"Get a list of peers (not including ourself) from the partition to which we belong"}, @@ -104,6 +107,7 @@ {"splayclass",cf_class,2,"True if the first argument's time-slot has arrived, according to a policy in arg2"}, {"splitstring",cf_slist,3,"Convert a string in arg1 into a list of max arg3 strings by splitting on a regular expression in arg2"}, {"strcmp",cf_class,2,"True if the two strings match exactly"}, + {"subtract",cf_int,2,"Subtract two integers"}, {"usemodule",cf_class,2,"Execute cfengine module script and set class if successful"}, {"userexists",cf_class,1,"True if user name or numerical id exists on this host"}, {NULL,cf_notype,0,NULL} --- src/prototypes3.h~ 2009-08-24 22:22:00.000000000 -0400 +++ src/prototypes3.h 2009-08-24 22:22:16.000000000 -0400 @@ -438,6 +438,7 @@ struct Rval FnCallLastNode(struct FnCall *fp,struct Rlist *finalargs); struct Rval FnCallFileSexist(struct FnCall *fp,struct Rlist *finalargs); struct Rval FnCallDiskFree(struct FnCall *fp,struct Rlist *finalargs); +struct Rval FnCallArithmetic(struct FnCall *fp,struct Rlist *finalargs,char ch); void *CfReadFile(char *filename,int maxsize); char *StripPatterns(char *file_buffer,char *pattern); --- src/evalfunction.c~ 2009-08-24 22:25:31.000000000 -0400 +++ src/evalfunction.c 2009-08-24 22:25:55.000000000 -0400 @@ -3937,6 +3937,63 @@ return rval; } +/*********************************************************************/ + +struct Rval FnCallArithmetic(struct FnCall *fp,struct Rlist *finalargs, char ch) + +{ static char *argtemplate[] = + { + CF_ANYSTRING, + CF_ANYSTRING, + NULL + }; + static enum cfdatatype argtypes[] = + { + cf_str, + cf_str, + cf_notype + }; + + struct Rlist *rp; + struct Rval rval; + char buffer[CF_BUFSIZE]; + int a, b; + +buffer[0] = '\0'; + +ArgTemplate(fp,argtemplate,argtypes,finalargs); /* Arg validation */ + +a = Str2Int(finalargs->item); +b = Str2Int(finalargs->next->item); + +switch (ch) + { + case '+': + a += b; + break; + case '-': + a -= b; + break; + case '*': + a *= b; + break; + case '/': + if (b==0) a = 0; else a /= b; + break; + } + +snprintf(buffer,CF_BUFSIZE-1,"%d", a); + +if ((rval.item = strdup(buffer)) == NULL) + { + FatalError("Memory allocation in FnCallGetGid"); + } + +/* end fn specific content */ + +rval.rtype = CF_SCALAR; +return rval; +} /*********************************************************************/
diff -ur src~/recursion.c src/recursion.c --- src~/recursion.c 2009-08-26 00:06:42.000000000 -0400 +++ src/recursion.c 2009-08-26 00:07:38.000000000 -0400 @@ -217,18 +217,18 @@ { Debug("SkipDirLinks(%s,%s)\n",path,lastnode); -if ((r.include_dirs != NULL) && !(MatchRlistItem(r.include_dirs,path) || MatchRlistItem(r.include_dirs,lastnode))) - { - CfOut(cf_verbose,"","Skipping matched non-included directory %s\n",path); - return true; - } - if (MatchRlistItem(r.exclude_dirs,path) || MatchRlistItem(r.exclude_dirs,lastnode)) { CfOut(cf_verbose,"","Skipping matched excluded directory %s\n",path); return true; } +if ((r.include_dirs != NULL) && !(MatchRlistItem(r.include_dirs,path) || MatchRlistItem(r.include_dirs,lastnode))) + { + CfOut(cf_verbose,"","Skipping matched non-included directory %s\n",path); + return true; + } + return false; }
diff -ur src~/files_interfaces.c src/files_interfaces.c --- src~/files_interfaces.c 2009-08-22 08:05:02.000000000 -0400 +++ src/files_interfaces.c 2009-08-24 20:05:20.000000000 -0400 @@ -1322,7 +1322,7 @@ void LinkCopy(char *sourcefile,char *destfile,struct stat *sb,struct Attributes attr, struct Promise *pp) { char linkbuf[CF_BUFSIZE],*lastnode; - int succeed = false; + int status = CF_UNKNOWN; struct stat dsb; /* Link the file to the source, instead of copying */ @@ -1370,20 +1370,20 @@ if (*linkbuf == '.') { - succeed = VerifyRelativeLink(destfile,linkbuf,attr,pp); + status = VerifyRelativeLink(destfile,linkbuf,attr,pp); } else { - succeed = VerifyLink(destfile,linkbuf,attr,pp); + status = VerifyLink(destfile,linkbuf,attr,pp); } break; case cfa_relative: - succeed = VerifyRelativeLink(destfile,linkbuf,attr,pp); + status = VerifyRelativeLink(destfile,linkbuf,attr,pp); break; case cfa_absolute: - succeed = VerifyAbsoluteLink(destfile,linkbuf,attr,pp); + status = VerifyAbsoluteLink(destfile,linkbuf,attr,pp); break; default: @@ -1391,7 +1391,7 @@ return; } -if (succeed) +if (status == CF_CHG || status == CF_NOP) { if (lstat(destfile,&dsb) == -1) { @@ -1402,7 +1402,12 @@ VerifyCopiedFileAttributes(destfile,&dsb,sb,attr,pp); } - cfPS(cf_inform,CF_CHG,"",pp,attr," -> Created link %s", destfile); + if (status == CF_CHG) + cfPS(cf_inform,status,"",pp,attr," -> Created link %s", destfile); + else if (status == CF_NOP) + ; /*cfPS(cf_inform,status,"",pp,attr," -> Link %s as promised", destfile);*/ + else + cfPS(cf_inform,status,"",pp,attr," -> Unable to create link %s", destfile); } } diff -ur src~/files_links.c src/files_links.c --- src~/files_links.c 2009-08-22 08:08:32.000000000 -0400 +++ src/files_links.c 2009-08-24 20:00:50.000000000 -0400 @@ -34,7 +34,7 @@ /*****************************************************************************/ -int VerifyLink(char *destination,char *source,struct Attributes attr,struct Promise *pp) +char VerifyLink(char *destination,char *source,struct Attributes attr,struct Promise *pp) { char to[CF_BUFSIZE],linkbuf[CF_BUFSIZE],saved[CF_BUFSIZE],absto[CF_BUFSIZE]; int nofile = false; @@ -84,13 +84,13 @@ if (nofile && (attr.link.when_no_file != cfa_force) && (attr.link.when_no_file != cfa_delete)) { CfOut(cf_inform,"","Source %s for linking is absent",absto); - return false; + return CF_WARN; } if (nofile && attr.link.when_no_file == cfa_delete) { KillGhostLink(destination,attr,pp); - return true; + return CF_CHG; } memset(linkbuf,0,CF_BUFSIZE); @@ -99,16 +99,16 @@ { if (!MakeParentDirectory(destination,attr.move_obstructions)) /* link doesn't exist */ { - return true; + return CF_FAIL; } else { if (!MoveObstruction(destination,attr,pp)) { - return false; + return CF_FAIL; } - return MakeLink(destination,to,attr,pp); + return MakeLink(destination,to,attr,pp)?CF_CHG:CF_FAIL; } } else @@ -137,34 +137,34 @@ if (unlink(destination) == -1) { perror("unlink"); - return true; + return CF_FAIL; } - return MakeLink(destination,to,attr,pp); + return MakeLink(destination,to,attr,pp)?CF_CHG:CF_FAIL; } else { CfOut(cf_error,""," !! Must remove incorrect link %s\n",destination); - return false; + return CF_FAIL; } } else { cfPS(cf_inform,CF_FAIL,"",pp,attr," !! Link %s points to %s not %s - not authorized to override",destination,linkbuf,to); - return true; + return CF_FAIL; } } else { cfPS(cf_inform,CF_NOP,"",pp,attr," -> Link %s points to %s - promise kept",destination,to); - return true; + return CF_NOP; } } } /*****************************************************************************/ -int VerifyAbsoluteLink(char *destination,char *source,struct Attributes attr,struct Promise *pp) +char VerifyAbsoluteLink(char *destination,char *source,struct Attributes attr,struct Promise *pp) { char absto[CF_BUFSIZE]; char expand[CF_BUFSIZE]; @@ -194,7 +194,7 @@ { CfOut(cf_error,""," !! Failed to make absolute link in\n"); PromiseRef(cf_error,pp); - return false; + return CF_FAIL; } else { @@ -213,7 +213,7 @@ /*****************************************************************************/ -int VerifyRelativeLink(char *destination,char *source,struct Attributes attr,struct Promise *pp) +char VerifyRelativeLink(char *destination,char *source,struct Attributes attr,struct Promise *pp) { char *sp, *commonto, *commonfrom; char buff[CF_BUFSIZE],linkto[CF_BUFSIZE],add[CF_BUFSIZE]; @@ -229,7 +229,7 @@ if (!CompressPath(linkto,source)) { cfPS(cf_error,CF_INTERPT,"",pp,attr," !! Failed to link %s to %s\n",destination,source); - return false; + return CF_FAIL; } commonto = linkto; @@ -239,7 +239,7 @@ { CfOut(cf_error,""," !! Can't link file %s to itself!\n",commonto); PromiseRef(cf_error,pp); - return false; + return CF_FAIL; } while (*commonto == *commonfrom) @@ -275,13 +275,13 @@ if (!JoinPath(buff,add)) { - return false; + return CF_FAIL; } } if (!JoinPath(buff,commonto)) { - return false; + return CF_FAIL; } return VerifyLink(destination,buff,attr,pp); @@ -289,7 +289,7 @@ /*****************************************************************************/ -int VerifyHardLink(char *destination,char *source,struct Attributes attr,struct Promise *pp) +char VerifyHardLink(char *destination,char *source,struct Attributes attr,struct Promise *pp) { char to[CF_BUFSIZE],linkbuf[CF_BUFSIZE],saved[CF_BUFSIZE],absto[CF_BUFSIZE]; struct stat ssb,dsb; @@ -319,21 +319,20 @@ if (stat(absto,&ssb) == -1) { cfPS(cf_inform,CF_INTERPT,"",pp,attr," !! Source file %s doesn't exist\n",source); - return false; + return CF_WARN; } if (!S_ISREG(ssb.st_mode)) { cfPS(cf_inform,CF_FAIL,"",pp,attr," !! Source file %s is not a regular file, not appropriate to hard-link\n",to); - return false; + return CF_WARN; } Debug2("Trying to (hard) link %s -> %s\n",destination,to); if (stat(destination,&dsb) == -1) { - MakeHardLink(destination,to,attr,pp); - return true; + return MakeHardLink(destination,to,attr,pp)?CF_CHG:CF_FAIL; } /* both files exist, but are they the same file? POSIX says */ @@ -348,25 +347,24 @@ if (dsb.st_mode == ssb.st_mode && dsb.st_size == ssb.st_size) { cfPS(cf_verbose,CF_NOP,"",pp,attr,"Hard link (%s->%s) on different device APPEARS okay\n",destination,to); - return true; + return CF_NOP; } } if (dsb.st_ino == ssb.st_ino && dsb.st_dev == ssb.st_dev) { cfPS(cf_verbose,CF_NOP,"",pp,attr," -> Hard link (%s->%s) exists and is okay\n",destination,to); - return true; + return CF_NOP; } CfOut(cf_inform,""," !! %s does not appear to be a hard link to %s\n",destination,to); if (!MoveObstruction(destination,attr,pp)) { - return false; + return CF_FAIL; } -MakeHardLink(destination,to,attr,pp); -return true; +return MakeHardLink(destination,to,attr,pp)?CF_CHG:CF_FAIL; } /*****************************************************************************/ diff -ur src~/prototypes3.h src/prototypes3.h --- src~/prototypes3.h 2009-08-18 07:51:50.000000000 -0400 +++ src/prototypes3.h 2009-08-24 20:01:10.000000000 -0400 @@ -511,10 +511,10 @@ /* files_links.c */ -int VerifyLink(char *destination,char *source,struct Attributes attr,struct Promise *pp); -int VerifyAbsoluteLink(char *destination,char *source,struct Attributes attr,struct Promise *pp); -int VerifyRelativeLink(char *destination,char *source,struct Attributes attr,struct Promise *pp); -int VerifyHardLink(char *destination,char *source,struct Attributes attr,struct Promise *pp); +char VerifyLink(char *destination,char *source,struct Attributes attr,struct Promise *pp); +char VerifyAbsoluteLink(char *destination,char *source,struct Attributes attr,struct Promise *pp); +char VerifyRelativeLink(char *destination,char *source,struct Attributes attr,struct Promise *pp); +char VerifyHardLink(char *destination,char *source,struct Attributes attr,struct Promise *pp); int KillGhostLink(char *name,struct Attributes attr,struct Promise *pp); int MakeLink (char *from,char *to,struct Attributes attr,struct Promise *pp); int MakeHardLink (char *from,char *to,struct Attributes attr,struct Promise *pp);
--- src/verify_methods.c~ 2009-08-24 23:30:38.000000000 -0400 +++ src/verify_methods.c 2009-08-24 23:30:50.000000000 -0400 @@ -105,7 +105,7 @@ if (retval) { - cfPS(cf_verbose,CF_CHG,"",pp,a,"Method invoked successfully\n"); + cfPS(cf_verbose,CF_REGULAR,"",pp,a,"Method invoked successfully\n"); } else { --- src/logging.c~ 2009-08-24 23:34:09.000000000 -0400 +++ src/logging.c 2009-08-24 23:34:56.000000000 -0400 @@ -173,7 +173,6 @@ case CF_REGULAR: AddAllClasses(attr.classes.change,attr.classes.persist,attr.classes.timer); NotePromiseCompliance(pp,0.5); - PR_REPAIRED++; break; case CF_UNKNOWN:
--- src/files_operators.c~ 2009-08-26 13:34:17.000000000 -0400 +++ src/files_operators.c 2009-08-26 13:34:29.000000000 -0400 @@ -739,7 +739,7 @@ return true; } - if (S_ISDIR(sb.st_mode) && attr.link.when_no_file == cfa_force) + if (S_ISDIR(sb.st_mode)) { cfPS(cf_verbose,CF_CHG,"",pp,attr," -> Moving directory %s to %s%s\n",from,from,CF_SAVED);
diff -ur src.orig/item-lib.c src/item-lib.c --- src.orig/item-lib.c 2009-08-31 16:44:08.000000000 +0000 +++ src/item-lib.c 2009-08-31 17:01:53.000000000 +0000 @@ -910,6 +910,47 @@ return(false); } +int IsHostIn(struct Item *list,char *ip,char*username,char*hostname) + +/* Solve for possible regex/fuzzy models unified */ + +{ struct Item *ptr; + +if ((ip == NULL) || (strlen(ip) == 0)) + { + return true; + } + +for (ptr = list; ptr != NULL; ptr=ptr->next) + { + if (ptr->name[0] == '@' && hostname) + { + if (innetgr(ptr->name+1, hostname, username?username:"", NULL)) + return(true); + } + + if (FuzzySetMatch(ptr->name,ip) == 0) + { + return(true); + } + + if (IsRegex(ptr->name)) + { + if (FullTextMatch(ptr->name,ip)) + { + return(true); + } + + if (hostname && FullTextMatch(ptr->name,hostname)) + { + return(true); + } + } + } + +return(false); +} + /*********************************************************************/ int IsFuzzyItemIn(struct Item *list,char *item) Only in src: item-lib.c~ diff -ur src.orig/prototypes3.h src/prototypes3.h --- src.orig/prototypes3.h 2009-08-31 16:44:08.000000000 +0000 +++ src/prototypes3.h 2009-08-31 16:58:45.000000000 +0000 @@ -774,6 +774,7 @@ int IsItemIn (struct Item *list, char *item); int IsFuzzyItemIn (struct Item *list, char *item); int IsMatchItemIn(struct Item *list,char *item); +int IsHostIn(struct Item *list,char *ip,char *username,char *hostname); int GetItemListCounter (struct Item *list, char *item); struct Item *ConcatLists (struct Item *list1, struct Item *list2); void CopyList (struct Item **dest,struct Item *source); Only in src: prototypes3.h~ diff -ur src.orig/server.c src/server.c --- src.orig/server.c 2009-08-31 16:44:08.000000000 +0000 +++ src/server.c 2009-08-31 17:08:29.000000000 +0000 @@ -1950,7 +1950,7 @@ { Debug("Checking whether to map root privileges..\n"); - if (IsMatchItemIn(ap->maproot,MapAddress(conn->ipaddr)) || IsRegexItemIn(ap->maproot,conn->hostname)) + if (IsHostIn(ap->maproot,MapAddress(conn->ipaddr),conn->username,conn->hostname)) { conn->maproot = true; CfOut(cf_verbose,"","Mapping root privileges\n"); @@ -1960,7 +1960,7 @@ CfOut(cf_verbose,"","No root privileges granted\n"); } - if (IsMatchItemIn(ap->accesslist,MapAddress(conn->ipaddr)) || IsRegexItemIn(ap->accesslist,conn->hostname)) + if (IsHostIn(ap->accesslist,MapAddress(conn->ipaddr),conn->username,conn->hostname)) { access = true; Debug("Access privileges - match found\n"); @@ -1974,8 +1974,7 @@ { if (strncmp(transpath,transrequest,strlen(transpath)) == 0) { - if (IsMatchItemIn(ap->accesslist,MapAddress(conn->ipaddr)) || - IsRegexItemIn(ap->accesslist,conn->hostname)) + if (IsHostIn(ap->accesslist,MapAddress(conn->ipaddr),conn->username,conn->hostname)) { access = false; CfOut(cf_verbose,"","Host %s explicitly denied access to %s\n",conn->hostname,transrequest); @@ -2048,7 +2047,7 @@ { Debug("Checking whether to map root privileges..\n"); - if (IsMatchItemIn(ap->maproot,MapAddress(conn->ipaddr)) || IsRegexItemIn(ap->maproot,conn->hostname)) + if (IsHostIn(ap->maproot,MapAddress(conn->ipaddr),conn->username,conn->hostname)) { conn->maproot = true; CfOut(cf_verbose,"","Mapping root privileges\n"); @@ -2058,7 +2057,7 @@ CfOut(cf_verbose,"","No root privileges granted\n"); } - if (IsMatchItemIn(ap->accesslist,MapAddress(conn->ipaddr)) || IsRegexItemIn(ap->accesslist,conn->hostname)) + if (IsHostIn(ap->accesslist,MapAddress(conn->ipaddr),conn->username,conn->hostname)) { access = true; Debug("Access privileges - match found\n"); @@ -2072,7 +2071,7 @@ { if (strcmp(ap->path,name) == 0) { - if (IsMatchItemIn(ap->accesslist,MapAddress(conn->ipaddr)) || IsRegexItemIn(ap->accesslist,conn->hostname)) + if (IsHostIn(ap->accesslist,MapAddress(conn->ipaddr),conn->username,conn->hostname)) { access = false; CfOut(cf_verbose,"","Host %s explicitly denied access to %s\n",conn->hostname,name); @@ -2148,8 +2147,7 @@ if (FullTextMatch(ap->path,rp->item)) { /* We have a pattern covering this class - so are we allowed to activate it? */ - if (IsMatchItemIn(ap->accesslist,MapAddress(conn->ipaddr)) || - IsRegexItemIn(ap->accesslist,conn->hostname) || + if (IsHostIn(ap->accesslist,MapAddress(conn->ipaddr),conn->username,conn->hostname) || IsRegexItemIn(ap->accesslist,userid1) || IsRegexItemIn(ap->accesslist,userid2) || IsRegexItemIn(ap->accesslist,conn->username) @@ -3279,7 +3277,7 @@ { /* If we find a key, but it doesn't match, see if we permit dynamical IP addressing */ - if ((DHCPLIST != NULL) && IsMatchItemIn(DHCPLIST,MapAddress(conn->ipaddr))) + if ((DHCPLIST != NULL) && IsHostIn(DHCPLIST,MapAddress(conn->ipaddr),conn->username,conn->hostname)) { int result; result = IsKnownHost(savedkey,key,MapAddress(conn->ipaddr),conn->username); @@ -3305,11 +3303,11 @@ return true; } -else if ((DHCPLIST != NULL) && IsMatchItemIn(DHCPLIST,MapAddress(conn->ipaddr))) +else if ((DHCPLIST != NULL) && IsHostIn(DHCPLIST,MapAddress(conn->ipaddr),conn->username,conn->hostname)) { /* If the host is expected to have a dynamic address, check for the key */ - if ((DHCPLIST != NULL) && IsMatchItemIn(DHCPLIST,MapAddress(conn->ipaddr))) + if ((DHCPLIST != NULL) && IsHostIn(DHCPLIST,MapAddress(conn->ipaddr),conn->username,conn->hostname)) { int result; result = IsKnownHost(savedkey,key,MapAddress(conn->ipaddr),conn->username); @@ -3328,7 +3326,7 @@ /* Finally, if we're still here, we should consider trusting a new key ... */ -if ((TRUSTKEYLIST != NULL) && IsMatchItemIn(TRUSTKEYLIST,MapAddress(conn->ipaddr))) +if ((TRUSTKEYLIST != NULL) && IsHostIn(TRUSTKEYLIST,MapAddress(conn->ipaddr),conn->username,conn->hostname)) { CfOut(cf_verbose,"","Host %s/%s was found in the list of hosts to trust\n",conn->hostname,conn->ipaddr); conn->trust = true;
--- src/files_links.c~ 2009-09-02 21:19:52.000000000 -0400 +++ src/files_links.c 2009-09-02 21:21:13.000000000 -0400 @@ -114,7 +114,8 @@ else { int off1 = 0, off2 = 0; /* Link exists */ - DeleteSlash(linkbuf); + if (*to && !IsFileSep(to[strlen(to)-1])) + DeleteSlash(linkbuf); if (strncmp(linkbuf,"./",2) == 0) /* Ignore ./ at beginning */ {
--- src/logging.c~ 2009-08-27 20:48:10.000000000 -0400 +++ src/logging.c 2009-08-27 20:48:16.000000000 -0400 @@ -274,12 +274,14 @@ { CfOut(cf_verbose,""," ?> defining persistent promise result class %s\n",(char *)rp->item); NewPersistentContext(rp->item,persist,policy); - PrependItem(&VHEAP,CanonifyName((char *)rp->item),NULL); + if (!IsItemIn(VHEAP, CanonifyName((char *)rp->item))) + PrependItem(&VHEAP,CanonifyName((char *)rp->item),NULL); } else { CfOut(cf_verbose,""," ?> defining promise result class %s\n",(char *)rp->item); - PrependItem(&VHEAP,CanonifyName((char *)rp->item),NULL); + if (!IsItemIn(VHEAP, CanonifyName((char *)rp->item))) + PrependItem(&VHEAP,CanonifyName((char *)rp->item),NULL); } } }
--- src/matching.c~ 2009-08-27 12:45:55.000000000 -0400 +++ src/matching.c 2009-08-27 13:23:59.000000000 -0400 @@ -158,16 +158,71 @@ int IsRegex(char *str) { char *sp; + int ret = false; + enum { r_norm, r_norepeat, r_literal } special = r_norepeat; + int bracket = 0; + int paren = 0; for (sp = str; *sp != '\0'; sp++) { - if (strchr("^*+\[]()$",*sp)) + if (special == r_literal) { - return true; /* Maybe */ + special = r_norm; + continue; + } + else if (*sp == '\\') + { + special = r_literal; + continue; + } + else if (bracket && *sp != ']') + { + if (*sp == '[') return false; + continue; + } + + switch (*sp) + { + case '^': + special = (sp == str)?r_norepeat:r_norm; + break; + case '*': + case '+': + if (special == r_norepeat) return false; + special = r_norepeat; + ret = true; + break; + case '[': + special = r_norm; + bracket++; + ret = true; + break; + case ']': + if (bracket == 0) return false; + bracket = 0; + special = r_norm; + break; + case '(': + special = r_norepeat; + paren++; + break; + case ')': + special = r_norm; + paren--; + if (paren < 0) return false; + break; + case '|': + special = r_norepeat; + if (paren > 0) ret = true; + break; + default: + special = r_norm; } + } -return false; +if (bracket != 0 || paren != 0 || special == r_literal) return false; +return ret; } /*********************************************************************/
--- src/files_interfaces.c~ 2009-09-02 17:24:07.000000000 -0400 +++ src/files_interfaces.c 2009-09-02 17:25:06.000000000 -0400 @@ -647,7 +647,7 @@ return; } -if (IsStringIn(SINGLE_COPY_CACHE,destfile)) +if (IsInListOfRegex(SINGLE_COPY_CACHE,destfile)) { CfOut(cf_inform,""," -> Skipping single-copied file %s\n",destfile); return; @@ -898,7 +898,7 @@ VerifyCopiedFileAttributes(destfile,&dsb,&ssb,attr,pp); } - if (IsRegexIn(SINGLE_COPY_LIST,destfile)) + if (IsInListOfRegex(SINGLE_COPY_LIST,destfile)) { IdempPrependRScalar(&SINGLE_COPY_CACHE,destfile,CF_SCALAR); } @@ -924,7 +924,7 @@ otherwise we can get oscillations between multipe versions if type is based on a checksum */ - if (IsRegexIn(SINGLE_COPY_LIST,destfile)) + if (IsInListOfRegex(SINGLE_COPY_LIST,destfile)) { IdempPrependRScalar(&SINGLE_COPY_CACHE,destfile,CF_SCALAR); }
_______________________________________________ Bug-cfengine mailing list Bug-cfengine@cfengine.org https://cfengine.org/mailman/listinfo/bug-cfengine