Craig Miskell <craig@catalyst.net.nz>
Anton Baranov <abaranov@linuxfoundation.org>
Josef Reidinger <jreidinger@suse.cz>
+ James Valleroy <jvalleroy@mailbox.org>
+1.8.0 - 2017-03-20
+ - General changes/additions
+ * augtool: add a 'source' command exposing the aug_source API call
+ * augtool: add a 'context' command to make changing into a node more
+ discoverable
+ * augtool: add an 'info' command to print important information
+ * augtool: dramatically reduce memory consumption when all lenses are
+ loaded by more aggressively releasing temporary data structures. On
+ my machine, maximum memory usage of 'augtool -L' drops from roughly
+ 90MB to about 20MB. This will not change the amount of memory used
+ when only specific lenses are used, only the default behavior of
+ loading all lenses, i.e., when -A is not passed.
+ * make building augtool statically possible (Jörg Krause)
+ * split aug_to_xml into its own source file, so that statically linking
+ against libaugeas.a doesn't require also linking against libXml2 and
+ its dependencies, provided aug_to_xml is not needed.
+ - API changes
+ * add aug_source to find the source file for a particular node
+ * reduce memory consumption when AUG_NO_MODL_AUTOLOAD is _not_ passed;
+ exact same details as described above for augtool
+ - Lens changes/additions
+ * Chrony: allow floating point numbers (Miroslav Lichvar)
+ add new directives from chrony 3.0 and 3.1 (Miroslav Lichvar)
+ * Krb5: support include/includedir directives (Jason Smith) (Issue #430)
+ support realms that start with numbers (Dustin Wheeler) (Issue #437)
+ * Multipath: update to multipath-0.4.9-99.el7 (Xavier Mol)
+ * Php: also look for FPM files in /etc/php/*/fpm/pool.d (Daniel Dico)
+ * Postfix_virtual: allow underscores in e-mail addresses (Jason Lingohr)
+ (Issue #439)
+ * Radicale: new lens for config of http://radicale.org/ (James Valleroy)
+ * Rsyslog: support multiple options in module statements (Craig Miskell)
+ * Ssh: also look for files in in /etc/ssh/ssh_config.d (Ian Mortimer)
+ * Tmpfiles: parse 'q'/'Q' modes, parse two-character arguments,
+ parse three-digit file modes
+ * Xml: support external entity declarations in the doctype (Issue #142)
+ * Yum: also read DNF files from /etc/dnf (Pat Riehecky) (Issue #434)
+
1.7.0 - 2016-11-08
- General changes/additions
* allow multiple transforms handling the same file as long as they
License: LGPLv2+
URL: http://augeas.net/
Source0: http://download.augeas.net/%{name}-%{version}.tar.gz
+
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
BuildRequires: readline-devel libselinux-devel libxml2-devel
Requires: %{name}-libs = %{version}-%{release}
-# Bundling exception for gnulib: https://fedorahosted.org/fpc/ticket/174
-Provides: bundled(gnulib)
%description
A library for programmatically editing configuration files. Augeas parses
public API. Changes made through the API are written back to the initially
read files.
+%package static
+Summary: Static libraries for %{name}
+Group: Development/Libraries
+Requires: %{name}-devel = %{version}-%{release}
+
+%description static
+The %{name}-static package contains static libraries needed to produce
+static builds using %{name}.
+
+
+
%prep
%setup -q
%build
-%configure --disable-static
+%configure \
+%ifarch riscv64
+ --disable-gnulib-tests \
+%endif
+ --enable-static
make %{?_smp_mflags}
%check
%files libs
%defattr(-,root,root,-)
-# %{_datadir}/augeas and %{_datadir}/augeas/lenses are owned
+# _datadir/augeas and _datadir/augeas/lenses are owned
# by filesystem.
%{_datadir}/augeas/lenses/dist
%{_libdir}/*.so.*
%{_libdir}/*.so
%{_libdir}/pkgconfig/augeas.pc
+%files static
+%defattr(-,root,root,-)
+%{_libdir}/libaugeas.a
+%{_libdir}/libfa.a
+
%changelog
-* Tue Oct 15 2013 Dominic Cleal <dcleal@redhat.com> - 1.1.0-2
-- Add %check stage to run make check (rjones@redhat.com)
-- Don't package lenses in tests/ subdirectory (rjones@redhat.com)
-- Fix source URL to download.augeas.net (RHBZ#996033)
+* Fri Mar 17 2017 David Lutterkort <lutter@watzmann.net> - 1.8.0-1
+- add static subpackage
-* Fri Jun 14 2013 David Lutterkort <lutter@watzmann.net> - 1.1.0-1
-- New version
+* Fri Feb 10 2017 Fedora Release Engineering <releng@fedoraproject.org> - 1.7.0-4
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild
-* Fri Dec 21 2012 David Lutterkort <lutter@redhat.com> - 1.0.0-1
-- New version
+* Thu Jan 12 2017 Igor Gnatenko <ignatenko@redhat.com> - 1.7.0-3
+- Rebuild for readline 7.x
+
+* Sat Nov 12 2016 Richard W.M. Jones <rjones@redhat.com> - 1.7.0-2
+- riscv64: Disable gnulib tests on riscv64 architecture.
+
+* Wed Nov 09 2016 Dominic Cleal <dominic@cleal.org> - 1.7.0-1
+- Update to 1.7.0
+
+* Mon Aug 08 2016 Dominic Cleal <dominic@cleal.org> - 1.6.0-1
+- Update to 1.6.0
+
+* Thu May 12 2016 Dominic Cleal <dominic@cleal.org> - 1.5.0-1
+- Update to 1.5.0
+
+* Wed Feb 03 2016 Fedora Release Engineering <releng@fedoraproject.org> - 1.4.0-3
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild
+
+* Wed Jun 17 2015 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.4.0-2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild
+
+* Tue Jun 02 2015 Dominic Cleal <dcleal@redhat.com> - 1.4.0-1
+- Update to 1.4.0
+
+* Sat Nov 08 2014 Dominic Cleal <dcleal@redhat.com> - 1.3.0-1
+- Update to 1.3.0; remove all patches
+
+* Fri Aug 15 2014 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.2.0-4
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_22_Mass_Rebuild
+
+* Sat Jun 07 2014 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.2.0-3
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild
+
+* Mon Mar 31 2014 Dominic Cleal <dcleal@redhat.com> - 1.2.0-2
+- Add patch for Krb5, parse braces in values (RHBZ#1079444)
+
+* Wed Feb 12 2014 Dominic Cleal <dcleal@redhat.com> - 1.2.0-1
+- Update to 1.2.0, add check section
+- Update source URL to download.augeas.net (RHBZ#996032)
+
+* Sat Aug 03 2013 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.1.0-2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_20_Mass_Rebuild
+
+* Wed Jun 19 2013 David Lutterkort <lutter@redhat.com> - 1.1.0-1
+- Update to 1.1.0; remove all patches
+
+* Tue Jun 18 2013 Richard W.M. Jones <rjones@redhat.com> - 1.0.0-4
+- Fix /etc/sysconfig/network (RHBZ#904222).
+
+* Wed Jun 5 2013 Richard W.M. Jones <rjones@redhat.com> - 1.0.0-3
+- Don't package lenses in tests/ subdirectory.
+
+* Wed Feb 13 2013 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.0.0-2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild
+
+* Fri Jan 4 2013 David Lutterkort <lutter@redhat.com> - 1.0.0-1
+- New version; remove all patches
+
+* Wed Jul 18 2012 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 0.10.0-4
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild
+
+* Tue Jan 10 2012 David Lutterkort <lutter@redhat.com> - 0.10.0-3
+- Add patches for bugs 247 and 248 (JSON lens)
+
+* Sat Dec 3 2011 Richard W.M. Jones <rjones@redhat.com> - 0.10.0-2
+- Add patch to resolve missing libxml2 requirement in augeas.pc.
* Fri Dec 2 2011 David Lutterkort <lutter@redhat.com> - 0.10.0-1
- New version
* Mon Jul 25 2011 David Lutterkort <lutter@redhat.com> - 0.9.0-1
-- New version
+- New version; removed patch pathx-whitespace-ea010d8
+
+* Tue May 3 2011 David Lutterkort <lutter@redhat.com> - 0.8.1-2
+- Add patch pathx-whitespace-ea010d8.patch to fix BZ 700608
* Fri Apr 15 2011 David Lutterkort <lutter@redhat.com> - 0.8.1-1
- New version
-* Tue Feb 22 2011 David Lutterkort <lutter@redhat.com> - 0.8.0-1
+* Wed Feb 23 2011 David Lutterkort <lutter@redhat.com> - 0.8.0-1
- New version
-* Fri Nov 19 2010 David Lutterkort <lutter@redhat.com> - 0.7.4-1
-- New version
+* Mon Feb 07 2011 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 0.7.4-2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild
+
+* Mon Nov 22 2010 Matthew Booth <mbooth@redhat.com> - 0.7.4-1
+- Update to version 0.7.4
+
+* Thu Nov 18 2010 Richard W.M. Jones <rjones@redhat.com> - 0.7.3-2
+- Upstream patch proposed to fix GCC optimization bug (RHBZ#651992).
* Fri Aug 6 2010 David Lutterkort <lutter@redhat.com> - 0.7.3-1
-- New version
+- Remove upstream patches
+
+* Tue Jun 29 2010 David Lutterkort <lutter@redhat.com> - 0.7.2-2
+- Patches based on upstream fix for BZ 600141
* Tue Jun 22 2010 David Lutterkort <lutter@redhat.com> - 0.7.2-1
- Fix ownership of /usr/share/augeas. BZ 569393
- New version
* Thu Jan 14 2010 David Lutterkort <lutter@redhat.com> - 0.7.0-1
-- New version
+- Remove patch vim-ftdetect-syntax.patch. It's upstream
+
+* Tue Dec 15 2009 David Lutterkort <lutter@redhat.com> - 0.6.0-2
+- Fix ftdetect file for vim
* Mon Nov 30 2009 David Lutterkort <lutter@redhat.com> - 0.6.0-1
- Install vim syntax files
* Mon Sep 14 2009 David Lutterkort <lutter@redhat.com> - 0.5.3-1
-- New version
+- Remove separate xorg.aug, included in upstream source
+
+* Tue Aug 25 2009 Matthew Booth <mbooth@redhat.com> - 0.5.2-3
+- Include new xorg lens from upstream
+
+* Fri Jul 24 2009 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 0.5.2-2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild
* Mon Jul 13 2009 David Lutterkort <lutter@redhat.com> - 0.5.2-1
- New version
-AC_INIT(augeas, 1.7.0)
+AC_INIT(augeas, 1.8.0)
AC_CONFIG_SRCDIR([src/augeas.c])
AC_CONFIG_AUX_DIR([build/ac-aux])
AM_CONFIG_HEADER([config.h])
fi
dnl Version info in libtool's notation
-AC_SUBST([LIBAUGEAS_VERSION_INFO], [21:1:21])
+AC_SUBST([LIBAUGEAS_VERSION_INFO], [22:0:22])
AC_SUBST([LIBFA_VERSION_INFO], [5:4:4])
AC_GNU_SOURCE
* Group: Create required expressions
************************************************************************)
(* Variable: number *)
- let number = integer | decimal
+ let number = integer | decimal | decimal . /[eE]/ . integer
(* Variable: address_re *)
let address_re = Rx.ip | Rx.hostname
| /(min|max)poll/
| /(min|max)samples/
| "maxsources"
+ | "offset"
| "polltarget"
| "port"
| "presend"
Server/Peer/Pool options without values
*)
let cmd_flags = "auto_offline"|"iburst"|"noselect"|"offline"|"prefer"
- |"require"|"trust"
+ |"require"|"trust"|"xleave"
(* Variable: ntp_source
Server/Peer/Pool key names
*)
let allowdeny_types = "allow"|"deny"|"cmdallow"|"cmddeny"
+ (* Variable: hwtimestamp_options
+ HW timestamping options with values
+ *)
+ let hwtimestamp_options = "minpoll"|"precision"|"rxcomp"|"txcomp"
+
+ (* Variable: hwtimestamp_flags
+ HW timestamping options without values
+ *)
+ let hwtimestamp_flags = "nocrossts"
+
(* Variable: local_options
local options with values
*)
(* Variable: log_flags
log has a specific options list
*)
- let log_flags = /measurements|statistics|tracking|rtc|refclocks|tempcomp/
+ let log_flags = "measurements"|"rawmeasurements"|"refclocks"|"rtc"
+ |"statistics"|"tempcomp"|"tracking"
(* Variable: simple_keys
Options with single values
| "dumpdir" | "hwclockfile" | "include" | "keyfile"
| "leapsecmode" | "leapsectz" | "linux_freq_scale"
| "linux_hz" | "logbanner" | "logchange" | "logdir"
- | "maxdistance" | "maxdrift"
- | "maxclockerror" | "maxsamples" | "maxslewrate"
- | "maxupdateskew" | "minsamples" | "minsources" | "pidfile"
+ | "maxclockerror" | "maxdistance" | "maxdrift"
+ | "maxjitter" | "maxsamples" | "maxslewrate"
+ | "maxupdateskew" | "minsamples" | "minsources"
+ | "ntpsigndsocket" | "pidfile"
| "port" | "reselectdist" | "rtcautotrim" | "rtcdevice"
| "rtcfile" | "sched_priority" | "stratumweight" | "user"
(* View: host_flags *)
let host_flags = [ space . key cmd_flags ]
(* View: host_options *)
- let host_options = [ space . key cmd_options . space . store integer ]
+ let host_options = [ space . key cmd_options . space . store number ]
(* View: log_flag_list *)
let log_flag_list = [ space . key log_flags ]
(* View: store_address *)
- log <options>
- broadcast <interval> <address> <optional port>
- fallbackdrift <min> <max>
+ - hwtimestamp <interface> <options>
- initstepslew <threshold> <addr> <optional extra addrs>
- local <options>
- mailonchange <emailaddress> <threshold>
. space . [ label "max" . store integer ]
. eol ]
+ (* View: hwtimestamp
+ hwtimestamp has specific syntax
+ *)
+ let hwtimestamp = [ Util.indent . key "hwtimestamp"
+ . space . [ label "interface" . store no_space ]
+ . ( space . ( [ key hwtimestamp_flags ]
+ | [ key hwtimestamp_options . space . store number ] )
+ )*
+ . eol ]
(* View: istepslew
initstepslew has specific syntax
*)
*)
let settings = host_list | allowdeny | log_list | bcast | fdrift | istepslew
| local | email | makestep | maxchange | refclock | smoothtime
- | ratelimit | tempcomp | kv | all_flags
+ | hwtimestamp | ratelimit | tempcomp | kv | all_flags
(*
* View: lns
-(* Intefraces module for Augeas
+(* Interfaces module for Augeas
Author: Free Ekanayaka <free@64studio.com>
Reference: man interfaces
let stanza_id (t:string) = key t . sep_spc . sto_to_spc
let stanza_param (l:string) = [ sep_spc . label l . sto_to_spc ]
-(* Define reseverved words and multi-value options*)
+(* Define reserved words and multi-value options *)
let stanza_word =
/(source(-directory)?|iface|auto|allow-[a-z-]+|mapping|bond-slaves|bridge-ports)/
iface and mapping can spand along more lines. Comment nodes are
inserted in the tree as direct children of the root node only when they
come after an auto or hotplug stanza, otherwise they are considered part
- of a iface or mapping block *)
+ of an iface or mapping block *)
let stanza_single = (auto|allow|source|source_directory) . (comment|empty)*
let stanza_multi = iface|mapping
and realms in the [appdefaults] section.
*)
-let realm_re = /[A-Z][.a-zA-Z0-9-]*/
-let realm_anycase_re = /[A-Za-z][.a-zA-Z0-9-]*/
+let realm_re = /[A-Z0-9][.a-zA-Z0-9-]*/
+let realm_anycase_re = /[A-Za-z0-9][.a-zA-Z0-9-]*/
let app_re = /[a-z][a-zA-Z0-9_]*/
let name_re = /[.a-zA-Z0-9_-]+/
let pam =
simple_section "pam" name_re
-let lns = (comment|empty)* .
+let includes = Build.key_value_line /include(dir)?/ Sep.space (store Rx.fspath)
+
+let lns = (comment|empty|includes)* .
(libdefaults|login|appdefaults|realms|domain_realm
|logging|capaths|dbdefaults|dbmodules|instance_mapping|kdc|pam)*
-let xfm = transform lns (incl "/etc/krb5.conf")
+let filter = (incl "/etc/krb5.conf.d/*.conf")
+ . (incl "/etc/krb5.conf")
+
+let xfm = transform lns filter
(* Settings that can be changed in various places *)
let common_setting =
- kv "path_grouping_policy"
- /failover|multibus|group_by_(serial|prio|node_name)/
- |qstr /(getuid|prio)_callout/
- |qstr /path_(selector|checker)|features/
- |kv "failback" (Rx.integer | /immediate|manual/)
- |kv "rr_weight" /priorities|uniform/
- |kv "no_path_retry" (Rx.integer | /fail|queue/)
- |kv /rr_min_io(_rq)?/ Rx.integer
- |kv "flush_on_last_del" /yes|no/
- |kv "reservation_key" Rx.word
- |kv "delay_watch_checks" (Rx.integer|"no")
- |kv "delay_wait_checks" (Rx.integer|"no")
-
-let default_setting =
- kv "polling_interval" Rx.integer
+ qstr "path_selector"
+ |kv "path_grouping_policy" /failover|multibus|group_by_(serial|prio|node_name)/
+ |kv "path_checker" /tur|emc_clariion|hp_sw|rdac|directio|rdb|readsector0/
+ |kv "prio" /const|emc|alua|ontap|rdac|hp_sw|hds|random|weightedpath/
+ |qstr "prio_args"
+ |kv "failback" (Rx.integer | /immediate|manual|followover/)
+ |kv "rr_weight" /priorities|uniform/
+ |kv "flush_on_last_del" /yes|no/
+ |kv "user_friendly_names" /yes|no/
+ |kv "no_path_retry" (Rx.integer | /fail|queue/)
+ |kv /rr_min_io(_q)?/ Rx.integer
+ |qstr "features"
+ |kv "reservation_key" Rx.word
+ |kv "deferred_remove" /yes|no/
+ |kv "delay_watch_checks" (Rx.integer | "no")
+ |kv "delay_wait_checks" (Rx.integer | "no")
+ |kv "skip_kpartx" /yes|no/
+ (* Deprecated settings for backwards compatibility *)
+ |qstr /(getuid|prio)_callout/
+ (* Settings not documented in `man multipath.conf` *)
+ |kv /rr_min_io_rq/ Rx.integer
|kv "udev_dir" Rx.fspath
|qstr "selector"
- |kv "user_friendly_names" /yes|no/
- |kv "dev_loss_tmo" Rx.integer
- |kv "fast_io_fail_tmo" Rx.integer
- |kv "verbosity" /[0-6]/
- |kv "reassign_maps" /yes|no/
- |kv "prio" Rx.word
- |kv "max_fds" Rx.integer
- |kv "find_multipaths" /yes|no/
- |kv "checker_timeout" Rx.integer
- |kv "hwtable_regex_match" /yes|no/
- |kv "reload_readwrite" /yes|no/
- |kv "replace_wwid_whitespace" /yes|no/
- |kv "force_sync" /yes|no/
- |kv "config_dir" Rx.fspath
- (* SUSE extensions *)
|kv "async_timeout" Rx.integer
- |kv "max_polling_interval" Rx.integer
|kv "pg_timeout" Rx.word
- |kv "bindings_file" Rx.fspath
- |kv "multipath_dir" Rx.fspath
- |kv "alias_prefix" Rx.word
- |kv "queue_without_daemon" /yes|no/
|kv "h_on_last_deleassign_maps" /yes|no/
- |qstr "prio_args"
- (* SUSE extensions SP3 *)
|qstr "uid_attribute"
+ |kv "hwtable_regex_match" /yes|no|on|off/
+ |kv "reload_readwrite" /yes|no/
+
+let default_setting =
+ common_setting
+ |kv "polling_interval" Rx.integer
+ |kv "max_polling_interval" Rx.integer
+ |kv "multipath_dir" Rx.fspath
+ |kv "find_multipaths" /yes|no/
+ |kv "verbosity" /[0-6]/
+ |kv "reassign_maps" /yes|no/
+ |kv "uid_attrribute" Rx.word
+ |kv "max_fds" (Rx.integer|"max")
+ |kv "checker_timeout" Rx.integer
+ |kv "fast_io_fail_tmo" (Rx.integer|"off")
+ |kv "dev_loss_tmo" (Rx.integer|"infinity")
+ |kv "queue_without_daemon" /yes|no/
+ |kv "bindings_file" Rx.fspath
|kv "wwids_file" Rx.fspath
- |kv "log_checker_err" Rx.word
+ |kv "log_checker_err" /once|always/
|kv "retain_attached_hw_handler" /yes|no/
|kv "detect_prio" /yes|no/
+ |kv "hw_str_match" /yes|no/
+ |kv "force_sync" /yes|no/
+ |kv "config_dir" Rx.fspath
+ |kv "missing_uev_wait_timeout" Rx.integer
+ |kv "ignore_new_boot_devs" /yes|no/
+ |kv "retrigger_tries" Rx.integer
+ |kv "retrigger_delay" Rx.integer
+ |kv "new_bindings_in_boot" /yes|no/
(* A device subsection *)
let device =
let setting =
- qstr /vendor|product|product_blacklist|hardware_handler/
- |common_setting
+ qstr /vendor|product|product_blacklist|hardware_handler|alias_prefix/
|default_setting in
section "device" setting
(* The defaults section *)
let defaults =
- let setting =
- common_setting
- |default_setting
- in section "defaults" setting
+ section "defaults" default_setting
(* The blacklist and blacklist_exceptions sections *)
let blacklist =
. (incl "/etc/php.d/*.ini")
(* PHPFPM Support *)
. (incl "/etc/php*/fpm/pool.d/*.conf")
+ . (incl "/etc/php/*/fpm/pool.d/*.conf")
(* Zend Community edition *)
. (incl "/usr/local/zend/etc/php.ini")
. (incl "/usr/local/zend/etc/conf.d/*.ini")
del (space_or_eol_re? . sep . space_or_eol_re?) default
(* View: word *)
-let word = store /[A-Za-z0-9@\*.+=-]+/
+let word = store /[A-Za-z0-9@\*.+=_-]+/
(* View: comma *)
let comma = space_or_eol "," ", "
--- /dev/null
+(* Radicale module for Augeas
+ Based on Puppet lens.
+
+ Manage config file for http://radicale.org/
+ /etc/radicale/config is a standard INI File.
+*)
+
+
+module Radicale =
+ autoload xfm
+
+(************************************************************************
+ * INI File settings
+ *
+ * /etc/radicale/config only supports "#" as commentary and "=" as separator
+ *************************************************************************)
+let comment = IniFile.comment "#" "#"
+let sep = IniFile.sep "=" "="
+
+
+(************************************************************************
+ * ENTRY
+ * /etc/radicale/config uses standard INI File entries
+ *************************************************************************)
+let entry = IniFile.indented_entry IniFile.entry_re sep comment
+
+
+(************************************************************************
+ * RECORD
+ * /etc/radicale/config uses standard INI File records
+ *************************************************************************)
+let title = IniFile.indented_title IniFile.record_re
+let record = IniFile.record title entry
+
+
+(************************************************************************
+ * LENS & FILTER
+ * /etc/radicale/config uses standard INI File records
+ *************************************************************************)
+let lns = IniFile.lns record comment
+
+let filter = (incl "/etc/radicale/config")
+
+let xfm = transform lns filter
let macro_rx = /[^,# \n\t][^#\n]*[^,# \n\t]|[^,# \n\t]/
let macro = [ key /$[A-Za-z0-9]+/ . Sep.space . store macro_rx . Util.comment_or_eol ]
-let config_object_param = [ key /[A-Za-z]+/ . Sep.equal . Quote.dquote
- . store /[^"]+/ . Quote.dquote . Sep.opt_space ]
+let config_object_param = [ key /[A-Za-z.]+/ . Sep.equal . Quote.dquote
+ . store /[^"]+/ . Quote.dquote ]
let config_object = [ key /action|global|input|module|parser|timezone/ . Sep.lbracket
- . config_object_param+ . Sep.rbracket . Util.comment_or_eol ]
+ . config_object_param . ( Sep.space . config_object_param )* . Sep.rbracket . Util.comment_or_eol ]
(* View: users
Map :omusrmsg: and a list of users, or a single *
| "require"
| "reverse-lookup"
| "rootDSE"
- | "sasl-host "
+ | "sasl-host"
| "sasl-realm"
| "sasl-secprops"
| "schemadn"
let lns = entry* . host*
let xfm = transform lns (incl "/etc/ssh/ssh_config" .
- incl (Sys.getenv("HOME") . "/.ssh/config"))
+ incl (Sys.getenv("HOME") . "/.ssh/config") .
+ incl "/etc/ssh/ssh_config.d/*.conf")
server ntp3.example.com presend 2
server ntp4.example.com offline polltarget 4
server ntp5.example.com maxdelay 2 offline
-server ntp6.example.com maxdelay 2 iburst presend 2
+server ntp6.example.com maxdelay 2 iburst presend 2 xleave offset 1e-4
server ntp7.example.com iburst presend 2 offline prefer trust require
server ntp8.example.com minsamples 8 maxsamples 16 version 3
peer ntpc1.example.com
noclientlog
logchange 0.5
logdir /var/log/chrony
-log rtc measurements
+log rtc measurements rawmeasurements statistics tracking refclocks tempcomp
leapsectz right/UTC
broadcast 10 192.168.1.255
broadcast 10 192.168.100.255 123
maxchange 1000 1 2
maxdistance 1.0
maxdrift 100
+hwtimestamp eth0 minpoll -2 txcomp 300e-9 rxcomp 645e-9 nocrossts
initstepslew 30 foo.bar.com
initstepslew 30 foo.bar.com baz.quz.com
ratelimit interval 4 burst 16 leak 2
smoothtime 400 0.001 leaponly
tempcomp /sys/class/hwmon/hwmon0/temp2_input 30 26000 0.0 0.000183 0.0
tempcomp /sys/class/hwmon/hwmon0/temp2_input 30 /etc/chrony.tempcomp
+ntpsigndsocket /var/lib/samba/ntp_signd
"
test Chrony.lns get exampleconf =
{ "maxdelay" = "2" }
{ "iburst" }
{ "presend" = "2" }
+ { "xleave" }
+ { "offset" = "1e-4" }
}
{ "server" = "ntp7.example.com"
{ "iburst" }
{ "log"
{ "rtc" }
{ "measurements" }
+ { "rawmeasurements" }
+ { "statistics" }
+ { "tracking" }
+ { "refclocks" }
+ { "tempcomp" }
}
{ "leapsectz" = "right/UTC" }
{ "broadcast"
}
{ "maxdistance" = "1.0" }
{ "maxdrift" = "100" }
+ { "hwtimestamp"
+ { "interface" = "eth0" }
+ { "minpoll" = "-2" }
+ { "txcomp" = "300e-9" }
+ { "rxcomp" = "645e-9" }
+ { "nocrossts" }
+ }
{ "initstepslew"
{ "threshold" = "30" }
{ "address" = "foo.bar.com" }
{ "interval" = "30" }
{ "pointfile" = "/etc/chrony.tempcomp" }
}
+ { "ntpsigndsocket" = "/var/lib/samba/ntp_signd" }
(* Local Variables: *)
}
}
}
+ 1TS.ORG = {
+ kdc = kerberos.1ts.org
+ admin_server = kerberos.1ts.org
+ }
stanford.edu = {
kdc = krb5auth1.stanford.edu
kdc = krb5auth2.stanford.edu
}
}
}
+ { "realm" = "1TS.ORG"
+ { "kdc" = "kerberos.1ts.org" }
+ { "admin_server" = "kerberos.1ts.org" }
+ }
{ "realm" = "stanford.edu"
{ "kdc" = "krb5auth1.stanford.edu" }
{ "kdc" = "krb5auth2.stanford.edu" }
{ "libdefaults"
{ }
{ "default_ccache_name" = "KEYRING:persistent:%{uid}" } }
+
+(* Include(dir) test *)
+let include_test = "include /etc/krb5.other_conf.d/other.conf
+includedir /etc/krb5.conf.d/
+"
+
+test Krb5.lns get include_test =
+ { "include" = "/etc/krb5.other_conf.d/other.conf" }
+ { "includedir" = "/etc/krb5.conf.d/" }
root robert.oot@domain.com
@example.net root,postmaster
postmaster mtaadmin+root=mta1
+some_user localuser
"
(* Test: Postfix_Virtual.lns *)
{ "pattern" = "postmaster"
{ "destination" = "mtaadmin+root=mta1" }
}
+ { "pattern" = "some_user"
+ { "destination" = "localuser" }
+ }
--- /dev/null
+module Test_radicale =
+
+ let conf = "
+[server]
+
+[encoding]
+
+[well-known]
+
+[auth]
+
+[git]
+
+[rights]
+
+[storage]
+
+[logging]
+
+[headers]
+
+"
+
+ test Radicale.lns get conf =
+ {}
+ { "server"
+ {} }
+ { "encoding"
+ {} }
+ { "well-known"
+ {} }
+ { "auth"
+ {} }
+ { "git"
+ {} }
+ { "rights"
+ {} }
+ { "storage"
+ {} }
+ { "logging"
+ {} }
+ { "headers"
+ {} }
+
+ test Radicale.lns put conf after
+ set "server/hosts" "127.0.0.1:5232, [::1]:5232";
+ set "server/base_prefix" "/radicale/";
+ set "well-known/caldav" "/radicale/%(user)s/caldav/";
+ set "well-known/cardav" "/radicale/%(user)s/carddav/";
+ set "auth/type" "remote_user";
+ set "rights/type" "owner_only"
+ = "
+[server]
+
+hosts=127.0.0.1:5232, [::1]:5232
+base_prefix=/radicale/
+[encoding]
+
+[well-known]
+
+caldav=/radicale/%(user)s/caldav/
+cardav=/radicale/%(user)s/carddav/
+[auth]
+
+type=remote_user
+[git]
+
+[rights]
+
+type=owner_only
+[storage]
+
+[logging]
+
+[headers]
+
+"
$ModLoad imuxsock # provides support for local system logging (e.g. via logger command)
$ModLoad imklog # provides kernel logging support (previously done by rklogd)
-module(load=\"immark\") #provides --MARK-- message capability
+module(load=\"immark\" markmessageperiod=\"60\" fakeoption=\"bar\") #provides --MARK-- message capability
timezone(id=\"CET\" offset=\"+01:00\")
}
{ "module"
{ "load" = "immark" }
+ { "markmessageperiod" = "60" }
+ { "fakeoption" = "bar" }
{ "#comment" = "provides --MARK-- message capability" }
}
{ }
{ "value" = "garbage" }
{ "action"
{ "discard" } } }
+
+test Rsyslog.lns put "" after
+ set "/module[1]/load" "imuxsock"
+ = "module(load=\"imuxsock\")\n"
+
+test Rsyslog.lns put "" after
+ set "/module[1]/load" "imuxsock" ;
+ set "/module[1]/SysSock.RateLimit.Interval" "0"
+ = "module(load=\"imuxsock\" SysSock.RateLimit.Interval=\"0\")\n"
+
+test Rsyslog.lns put "" after
+ set "/module[1]/load" "imuxsock" ;
+ set "/module[1]/SysSock.RateLimit.Interval" "0" ;
+ set "/module[1]/SysSock.RateLimit.Burst" "1"
+ = "module(load=\"imuxsock\" SysSock.RateLimit.Interval=\"0\" SysSock.RateLimit.Burst=\"1\")\n"
{ "argument" = "user.name=\"John Smith\" security.SMACK64=screen" }
}
+ (* Variable: valid_short_args
+A short argument value example. *)
+ let valid_short_args = "h /var/log/journal - - - - C\nh /var/log/journal - - - - +C\n"
+
+ (* Variable: valid_short_args_tree
+Tree for <valid_short_args> *)
+ let valid_short_args_tree =
+ {
+ "1"
+ { "type" = "h" }
+ { "path" = "/var/log/journal" }
+ { "mode" = "-" }
+ { "uid" = "-" }
+ { "gid" = "-" }
+ { "age" = "-" }
+ { "argument" = "C" }
+ }
+ {
+ "2"
+ { "type" = "h" }
+ { "path" = "/var/log/journal" }
+ { "mode" = "-" }
+ { "uid" = "-" }
+ { "gid" = "-" }
+ { "age" = "-" }
+ { "argument" = "+C" }
+ }
+
(* Variable: valid_age
Example with a complex age. *)
let valid_age = "v /var/tmp/js 4221 johnsmith - ~10d12h\n"
{ "argument" = "foo" }
}
+ (* Variable: mode3
+Mode field example with only three digits *)
+ let mode3 = "c+! /tmp/foo 755\n"
+
+ (* Variable: mode3_tree
+Tree for <mode3> *)
+ let mode3_tree =
+ {
+ "1"
+ { "type" = "c+!" }
+ { "path" = "/tmp/foo" }
+ { "mode" = "755" }
+ }
+
(************************************************************************
* Group: INVALID EXAMPLES
*************************************************************************)
(* Variable: invalid_type
Invalid example that contain invalid type (bad letter) *)
- let invalid_type = "q /var/tmp/js 0000 jonhsmith 60 1s foo\n"
+ let invalid_type = "e /var/tmp/js 0000 jonhsmith 60 1s foo\n"
(* Variable: invalid_type_num
Invalid example that contain invalid type (numeric) *)
test Tmpfiles.lns get complex_arg = complex_arg_tree
+ test Tmpfiles.lns get valid_short_args = valid_short_args_tree
+
test Tmpfiles.lns get valid_second = valid_second_tree
test Tmpfiles.lns get valid_days = valid_days_tree
test Tmpfiles.lns get valid_base = valid_base_tree
+ test Tmpfiles.lns get mode3 = mode3_tree
+
(* failure cases *)
test Xml.lns put ""
after set "/a" "#empty" = "<a/>\n"
+
+(* Issue #142 *)
+test Xml.entity_def get
+ "<!ENTITY open-hatch SYSTEM \"http://examplecom/OpenHatch.xml\">" =
+ { "!ENTITY" = "open-hatch"
+ { "SYSTEM"
+ { "#systemliteral" = "http://examplecom/OpenHatch.xml" }
+ } }
+
+test Xml.entity_def get
+ "<!ENTITY open-hatch PUBLIC \"-//Textuality//TEXT Standard open-hatch boilerplate//EN\" \"http://www.textuality.com/boilerplate/OpenHatch.xml\">" =
+ { "!ENTITY" = "open-hatch"
+ { "PUBLIC"
+ { "#pubidliteral" =
+ "-//Textuality//TEXT Standard open-hatch boilerplate//EN" }
+ { "#systemliteral" =
+ "http://www.textuality.com/boilerplate/OpenHatch.xml" } } }
+
+let dt_with_entities =
+"<!DOCTYPE server-xml [
+ <!ENTITY sys-ent SYSTEM \"sys-file.xml\">
+ <!ENTITY pub-ent PUBLIC \"-//something public//TEXT\"
+ \"pub-file.xml\">
+ ]>"
+
+test Xml.doctype get dt_with_entities =
+ { "!DOCTYPE" = "server-xml"
+ { "!ENTITY" = "sys-ent"
+ { "SYSTEM"
+ { "#systemliteral" = "sys-file.xml" }
+ }
+ }
+ { "!ENTITY" = "pub-ent"
+ { "PUBLIC"
+ { "#pubidliteral" = "-//something public//TEXT" }
+ { "#systemliteral" = "pub-file.xml" }
+ }
+ }
+ }
+
+test Xml.doctype put dt_with_entities after
+ rm "/\!DOCTYPE/\!ENTITY[2]";
+ set "/\!DOCTYPE/\!ENTITY[. = \"sys-ent\"]/SYSTEM/#systemliteral"
+ "other-file.xml"
+ =
+"<!DOCTYPE server-xml [
+ <!ENTITY sys-ent SYSTEM \"other-file.xml\">
+ ]>"
+
+test Xml.lns get (dt_with_entities . "<body></body>") =
+ { "!DOCTYPE" = "server-xml"
+ { "!ENTITY" = "sys-ent"
+ { "SYSTEM"
+ { "#systemliteral" = "sys-file.xml" }
+ }
+ }
+ { "!ENTITY" = "pub-ent"
+ { "PUBLIC"
+ { "#pubidliteral" = "-//something public//TEXT" }
+ { "#systemliteral" = "pub-file.xml" }
+ }
+ }
+ }
+ { "body" }
+
+test Xml.lns put "<?xml version=\"1.0\"?>
+<body>
+</body>"
+ after
+ insa "!DOCTYPE" "#declaration";
+ set "\\!DOCTYPE" "Server";
+ set "\\!DOCTYPE/\\!ENTITY" "resourcesFile";
+ set "\\!DOCTYPE/\\!ENTITY/SYSTEM/#systemliteral" "data.xml"
+ =
+"<?xml version=\"1.0\"?><!DOCTYPE Server[
+<!ENTITY resourcesFile SYSTEM \"data.xml\">]>
+<body>\n</body>"
Not all letters are valid.
*)
- let type = /([fFwdDvpLcbCxXrRzZtThHaAm]|[AabcLp]\+)!?/
+ let type = /([fFwdDvqQpLcbCxXrRzZtThHaAm]|[AabcLp]\+)!?/
(* View: mode
-"-", or 4 bytes. Optionally starts with a "~". *)
- let mode = /(-|~?[0-7]{4})/
+"-", or 3-4 bytes. Optionally starts with a "~". *)
+ let mode = /(-|~?[0-7]{3,4})/
(* View: age
"-", or one of the formats seen in the manpage: 10d, 5seconds, 1y5days.
(* View: argument
The last field. It can contain spaces. *)
- let argument = /([^# \t\n][^#\n]+)?[^# \t\n]/
+ let argument = /([^# \t\n][^#\n]*[^# \t\n]|[^# \t\n])/
(* View: field
Applies to the other fields: path, gid and uid fields *)
let att_list_def = decl_def /!ATTLIST/ att_def
-let entity_def = decl_def /!ENTITY/ ([sep_spc . label "#decl" . sto_dquote ])
+let entity_def =
+ let literal (lbl:string) = [ sep_spc . label lbl . sto_dquote ] in
+ decl_def /!ENTITY/
+ ( literal "#decl"
+ | [ sep_spc . key /SYSTEM/ . literal "#systemliteral" ]
+ | [ sep_spc . key /PUBLIC/ . literal "#pubidliteral"
+ . literal "#systemliteral" ] )
let decl_def_item = elem_def | entity_def | att_list_def | notation_def
. (incl "/etc/yum/yum-cron*.conf")
. (incl "/etc/yum/pluginconf.d/*")
. (excl "/etc/yum/pluginconf.d/versionlock.list")
+ . (incl "/etc/dnf/dnf.conf")
+ . (incl "/etc/dnf/automatic.conf")
+ . (incl "/etc/dnf/plugins/*.conf")
. Util.stdexcl
let xfm = transform lns filter
memory.h memory.c ref.h ref.c \
syntax.c syntax.h parser.y builtin.c lens.c lens.h regexp.c regexp.h \
transform.h transform.c ast.c get.c put.c list.h \
- info.c info.h errcode.c errcode.h jmt.h jmt.c
+ info.c info.h errcode.c errcode.h jmt.h jmt.c xml.c
if USE_VERSION_SCRIPT
AUGEAS_VERSION_SCRIPT = $(VERSION_SCRIPT_FLAGS)$(srcdir)/augeas_sym.version
/*
* augeas.c: the core data structure for storing key/value pairs
*
- * Copyright (C) 2007-2016 David Lutterkort
+ * Copyright (C) 2007-2017 David Lutterkort
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
#include <string.h>
#include <stdarg.h>
#include <locale.h>
-#include <libxml/tree.h>
/* Some popular labels that we use in /augeas */
static const char *const s_augeas = "augeas";
static const char *const s_excl = "excl";
static const char *const s_incl = "incl";
-#define TREE_HIDDEN(tree) ((tree)->label == NULL)
-
#define AUGEAS_META_PATHX_FUNC AUGEAS_META_TREE "/version/pathx/functions"
static const char *const static_nodes[][2] = {
return result;
}
-static int to_xml_span(xmlNodePtr elem, const char *pfor, int start, int end) {
- int r;
- char *buf;
- xmlAttrPtr prop;
- xmlNodePtr span_elem;
-
- span_elem = xmlNewChild(elem, NULL, BAD_CAST "span", NULL);
- if (span_elem == NULL)
- return -1;
-
- prop = xmlSetProp(span_elem, BAD_CAST "for", BAD_CAST pfor);
- if (prop == NULL)
- return -1;
-
- /* Format and set the start property */
- r = xasprintf(&buf, "%d", start);
- if (r < 0)
- return -1;
-
- prop = xmlSetProp(span_elem, BAD_CAST "start", BAD_CAST buf);
- FREE(buf);
- if (prop == NULL)
- return -1;
-
- /* Format and set the end property */
- r = xasprintf(&buf, "%d", end);
- if (r < 0)
- return -1;
-
- prop = xmlSetProp(span_elem, BAD_CAST "end", BAD_CAST buf);
- FREE(buf);
- if (prop == NULL)
- return -1;
-
- return 0;
-}
-
-static int to_xml_one(xmlNodePtr elem, const struct tree *tree,
- const char *pathin) {
- xmlNodePtr value;
- xmlAttrPtr prop;
- int r;
-
- prop = xmlSetProp(elem, BAD_CAST "label", BAD_CAST tree->label);
- if (prop == NULL)
- goto error;
-
- if (tree->span) {
- struct span *span = tree->span;
-
- prop = xmlSetProp(elem, BAD_CAST "file",
- BAD_CAST span->filename->str);
- if (prop == NULL)
- goto error;
-
- r = to_xml_span(elem, "label", span->label_start, span->label_end);
- if (r < 0)
- goto error;
-
- r = to_xml_span(elem, "value", span->value_start, span->value_end);
- if (r < 0)
- goto error;
-
- r = to_xml_span(elem, "node", span->span_start, span->span_end);
- if (r < 0)
- goto error;
- }
-
- if (pathin != NULL) {
- prop = xmlSetProp(elem, BAD_CAST "path", BAD_CAST pathin);
- if (prop == NULL)
- goto error;
- }
- if (tree->value != NULL) {
- value = xmlNewTextChild(elem, NULL, BAD_CAST "value",
- BAD_CAST tree->value);
- if (value == NULL)
- goto error;
- }
- return 0;
- error:
- return -1;
-}
-
-static int to_xml_rec(xmlNodePtr pnode, struct tree *start,
- const char *pathin) {
- int r;
- xmlNodePtr elem;
-
- elem = xmlNewChild(pnode, NULL, BAD_CAST "node", NULL);
- if (elem == NULL)
- goto error;
- r = to_xml_one(elem, start, pathin);
- if (r < 0)
- goto error;
-
- list_for_each(tree, start->children) {
- if (TREE_HIDDEN(tree))
- continue;
- r = to_xml_rec(elem, tree, NULL);
- if (r < 0)
- goto error;
- }
-
- return 0;
- error:
- return -1;
-}
-
-static int tree_to_xml(struct pathx *p, xmlNode **xml, const char *pathin) {
- char *path = NULL;
- struct tree *tree;
- xmlAttrPtr expr;
- int r;
-
- *xml = xmlNewNode(NULL, BAD_CAST "augeas");
- if (*xml == NULL)
- goto error;
- expr = xmlSetProp(*xml, BAD_CAST "match", BAD_CAST pathin);
- if (expr == NULL)
- goto error;
-
- for (tree = pathx_first(p); tree != NULL; tree = pathx_next(p)) {
- if (TREE_HIDDEN(tree))
- continue;
- path = path_of_tree(tree);
- if (path == NULL)
- goto error;
- r = to_xml_rec(*xml, tree, path);
- if (r < 0)
- goto error;
- FREE(path);
- }
- return 0;
- error:
- free(path);
- xmlFree(*xml);
- *xml = NULL;
- return -1;
-}
-
int aug_text_store(augeas *aug, const char *lens, const char *node,
const char *path) {
return -1;
}
-int aug_to_xml(const struct augeas *aug, const char *pathin,
- xmlNode **xmldoc, unsigned int flags) {
- struct pathx *p = NULL;
- int result = -1;
-
- api_entry(aug);
-
- ARG_CHECK(flags != 0, aug, "aug_to_xml: FLAGS must be 0");
- ARG_CHECK(xmldoc == NULL, aug, "aug_to_xml: XMLDOC must be non-NULL");
-
- *xmldoc = NULL;
-
- if (pathin == NULL || strlen(pathin) == 0 || strcmp(pathin, "/") == 0) {
- pathin = "/*";
- }
-
- p = pathx_aug_parse(aug, aug->origin, tree_root_ctx(aug), pathin, true);
- ERR_BAIL(aug);
- result = tree_to_xml(p, xmldoc, pathin);
- ERR_THROW(result < 0, aug, AUG_ENOMEM, NULL);
-error:
- free_pathx(p);
- api_exit(aug);
-
- return result;
-}
-
int aug_transform(struct augeas *aug, const char *lens,
const char *file, int excl) {
struct tree *meta = tree_child_cr(aug->origin, s_augeas);
return result;
}
+int aug_source(const augeas *aug, const char *path, char **file_path) {
+ int result = -1, r;
+ struct pathx *p = NULL;
+ struct tree *match;
+
+ api_entry(aug);
+
+ ARG_CHECK(file_path == NULL, aug,
+ "aug_source_file: FILE_PATH must not be NULL");
+ *file_path = NULL;
+
+ p = pathx_aug_parse(aug, aug->origin, tree_root_ctx(aug), path, true);
+ ERR_BAIL(aug);
+
+ r = pathx_find_one(p, &match);
+ ERR_BAIL(aug);
+ ERR_THROW(r > 1, aug, AUG_EMMATCH, "There are %d nodes matching %s",
+ r, path);
+ ERR_THROW(r == 0, aug, AUG_ENOMATCH, "There is no node matching %s",
+ path);
+ while (!(ROOT_P(match) || match->file))
+ match = match->parent;
+
+ if (match->file) {
+ *file_path = path_of_tree(match);
+ ERR_NOMEM(file_path == NULL, aug);
+ }
+
+ result = 0;
+ error:
+ free_pathx(p);
+ api_exit(aug);
+ return result;
+}
+
void aug_close(struct augeas *aug) {
if (aug == NULL)
return;
*/
int aug_print(const augeas *aug, FILE *out, const char *path);
+/* Function: aug_source
+ *
+ * For the node matching PATH, return the path to the node representing the
+ * file to which PATH belongs. If PATH belongs to a file, *FILE_PATH will
+ * contain the path to the toplevel node of that file underneath /files. If
+ * it does not, *FILE_PATH will be NULL.
+ *
+ * Returns:
+ * 0 on success, or a negative value on failure. It is an error if PATH
+ * matches more than one node.
+ */
+int aug_source(const augeas *aug, const char *path, char **file_path);
+
/* Function: aug_to_xml
*
* Turn the Augeas tree(s) matching PATH into an XML tree XMLDOC. The
global:
aug_load_file;
} AUGEAS_0.20.0;
+
+AUGEAS_0.22.0 {
+ global:
+ aug_source;
+} AUGEAS_0.21.0;
#include <ctype.h>
#include <libxml/tree.h>
+#include <argz.h>
/*
* Command handling infrastructure
.help = "Print entries in the tree. If PATH is given, printing starts there,\n otherwise the whole tree is printed"
};
+static void cmd_source(struct command *cmd) {
+ const char *path = arg_value(cmd, "path");
+ char *file_path = NULL;
+
+ aug_source(cmd->aug, path, &file_path);
+ ERR_RET(cmd);
+ if (file_path != NULL) {
+ fprintf(cmd->out, "%s\n", file_path);
+ }
+ free(file_path);
+}
+
+static const struct command_opt_def cmd_source_opts[] = {
+ { .type = CMD_PATH, .name = "path", .optional = false,
+ .help = "path to a single node" },
+ CMD_OPT_DEF_LAST
+};
+
+static const struct command_def cmd_source_def = {
+ .name = "source",
+ .opts = cmd_source_opts,
+ .handler = cmd_source,
+ .synopsis = "print the file to which a node belongs",
+ .help = "Print the file to which the node for PATH belongs. PATH must match\n a single node coming from some file. In particular, that means\n it must be underneath /files."
+};
+
+static void cmd_context(struct command *cmd) {
+ const char *path = arg_value(cmd, "path");
+
+ if (path == NULL) {
+ aug_get(cmd->aug, "/augeas/context", &path);
+ ERR_RET(cmd);
+ if (path == NULL) {
+ fprintf(cmd->out, "/\n");
+ } else {
+ fprintf(cmd->out, "%s\n", path);
+ }
+ } else {
+ aug_set(cmd->aug, "/augeas/context", path);
+ ERR_RET(cmd);
+ }
+}
+
+static const struct command_opt_def cmd_context_opts[] = {
+ { .type = CMD_PATH, .name = "path", .optional = true,
+ .help = "new context for relative paths" },
+ CMD_OPT_DEF_LAST
+};
+
+static const struct command_def cmd_context_def = {
+ .name = "context",
+ .opts = cmd_context_opts,
+ .handler = cmd_context,
+ .synopsis = "change how relative paths are interpreted",
+ .help = "Relative paths are interpreted relative to a context path which\n is stored in /augeas/context.\n\n When no PATH is given, this command prints the current context path\n and is equivalent to 'get /augeas/context'\n\n When PATH is given, this command changes that context, and has a\n similar effect to 'cd' in a shell and and is the same as running\n the command 'set /augeas/context PATH'."
+};
+
static void cmd_dump_xml(struct command *cmd) {
const char *path = arg_value(cmd, "path");
xmlNodePtr xmldoc;
"is an error if one file\n can be processed by multiple transforms."
};
+static void cmd_info(struct command *cmd) {
+ const char *v;
+ int n;
+
+ aug_get(cmd->aug, "/augeas/version", &v);
+ ERR_RET(cmd);
+ if (v != NULL) {
+ fprintf(cmd->out, "version = %s\n", v);
+ }
+
+ aug_get(cmd->aug, "/augeas/root", &v);
+ ERR_RET(cmd);
+ if (v != NULL) {
+ fprintf(cmd->out, "root = %s\n", v);
+ }
+
+ fprintf(cmd->out, "loadpath = ");
+ for (char *entry = cmd->aug->modpathz;
+ entry != NULL;
+ entry = argz_next(cmd->aug->modpathz, cmd->aug->nmodpath, entry)) {
+ if (entry != cmd->aug->modpathz) {
+ fprintf(cmd->out, ":");
+ }
+ fprintf(cmd->out, "%s", entry);
+ }
+ fprintf(cmd->out, "\n");
+
+ aug_get(cmd->aug, "/augeas/context", &v);
+ ERR_RET(cmd);
+ if (v == NULL) {
+ v = "/";
+ }
+ fprintf(cmd->out, "context = %s\n", v);
+
+ n = aug_match(cmd->aug, "/augeas/files//path", NULL);
+ fprintf(cmd->out, "num_files = %d\n", n);
+}
+
+static const struct command_opt_def cmd_info_opts[] = {
+ CMD_OPT_DEF_LAST
+};
+
+static const struct command_def cmd_info_def = {
+ .name = "info",
+ .opts = cmd_info_opts,
+ .handler = cmd_info,
+ .synopsis = "print runtime information",
+ .help = "Print information about Augeas. The output contains:\n"
+ " version : the version number from /augeas/version\n"
+ " root : what Augeas considers the filesystem root\n"
+ " from /augeas/root\n"
+ " loadpath : the paths from which Augeas loads modules\n"
+ " context : the context path (see context command)\n"
+ " num_files : the number of files currently loaded (based on\n"
+ " the number of /augeas/files//path nodes)"
+};
+
static void cmd_ins(struct command *cmd) {
const char *label = arg_value(cmd, "label");
const char *where = arg_value(cmd, "where");
static const struct command_grp_def cmd_grp_admin_def = {
.name = "Admin",
.commands = {
- &cmd_help_def,
+ &cmd_context_def,
&cmd_load_def,
- &cmd_quit_def,
- &cmd_retrieve_def,
&cmd_save_def,
- &cmd_store_def,
&cmd_transform_def,
&cmd_load_file_def,
+ &cmd_retrieve_def,
+ &cmd_store_def,
+ &cmd_quit_def,
+ &cmd_def_last
+ }
+};
+
+static const struct command_grp_def cmd_grp_info_def = {
+ .name = "Informational",
+ .commands = {
+ &cmd_errors_def,
+ &cmd_info_def,
+ &cmd_help_def,
+ &cmd_source_def,
&cmd_def_last
}
};
&cmd_ls_def,
&cmd_match_def,
&cmd_print_def,
- &cmd_errors_def,
&cmd_span_def,
&cmd_def_last
}
static const struct command_grp_def const *cmd_groups[] = {
&cmd_grp_admin_def,
+ &cmd_grp_info_def,
&cmd_grp_read_def,
&cmd_grp_write_def,
&cmd_grp_pathx_def,
* General utilities
*/
-/* Not static, since prototype is in internal.h */
-int xasprintf(char **strp, const char *format, ...) {
+/* Private copy of xasprintf from internal to avoid Multiple definition in
+ * static builds.
+ */
+static int _xasprintf(char **strp, const char *format, ...) {
va_list args;
int result;
"get", "label", "ins", "load", "ls", "match",
"mv", "cp", "rename", "print", "dump-xml", "rm", "save", "set", "setm",
"clearm", "span", "store", "retrieve", "transform", "load-file",
- "help", "touch", "insert", "move", "copy", "errors", NULL };
+ "help", "touch", "insert", "move", "copy", "errors", "source", "context",
+ "info",
+ NULL };
static int current = 0;
const char *name;
if (home_dir == NULL)
goto done;
- if (xasprintf(&history_dir, "%s/.augeas", home_dir) < 0)
+ if (_xasprintf(&history_dir, "%s/.augeas", home_dir) < 0)
goto done;
if (mkdir(history_dir, 0755) < 0 && errno != EEXIST)
goto done;
- if (xasprintf(&history_file, "%s/history", history_dir) < 0)
+ if (_xasprintf(&history_file, "%s/history", history_dir) < 0)
goto done;
stifle_history(500);
bool added_transform = false;
while ((t = argz_next(ts, tslen, t))) {
- r = xasprintf(&command, "transform %s", t);
+ r = _xasprintf(&command, "transform %s", t);
if (r < 0)
fprintf(stderr, "error: Failed to add transform %s: could not allocate memory\n", t);
char *t = NULL;
while ((t = argz_next(ts, tslen, t))) {
- r = xasprintf(&command, "load-file %s", t);
+ r = _xasprintf(&command, "load-file %s", t);
if (r < 0)
fprintf(stderr, "error: Failed to load file %s: could not allocate memory\n", t);
/*
* internal.h: Useful definitions
*
- * Copyright (C) 2007-2016 David Lutterkort
+ * Copyright (C) 2007-2017 David Lutterkort
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* file should have a need to mark nodes as dirty)
*
* The FILE flag is set for entries underneath /augeas/files that hold the
- * metadata for a file. It is only set by ADD_FILE_INFO and can not be set
- * by the user.
+ * metadata for a file by ADD_FILE_INFO. The FILE flag is set for entries
+ * underneath /files for the toplevel node corresponding to a file by
+ * TREE_FREPLACE and is used by AUG_SOURCE to find the file to which a node
+ * belongs.
*/
struct tree {
struct tree *next;
#define ROOT_P(t) ((t) != NULL && (t)->parent == (t)->parent->parent)
+#define TREE_HIDDEN(tree) ((tree)->label == NULL)
+
/* Function: make_tree
* Allocate a new tree node with the given LABEL, VALUE, and CHILDREN,
* which are not copied. The new tree is marked as dirty
}
}
+ if (lens->tag == L_REC && !lens->rec_internal) {
+ lens_release(lens->body);
+ }
+
jmt_free(lens->jmt);
lens->jmt = NULL;
}
*/
module = module_create(name);
}
- if (module != NULL)
+ if (module != NULL) {
list_append(aug->modules, module);
-
+ list_for_each(bnd, module->bindings) {
+ if (bnd->value->tag == V_LENS) {
+ lens_release(bnd->value->lens);
+ }
+ }
+ }
ERR_THROW(bad_module, aug, AUG_ESYNTAX, "Failed to load %s", filename);
result = 0;
parent = tree_fpath_cr(aug, fpath);
ERR_RET(aug);
+ parent->file = true;
tree_unlink_children(aug, parent);
list_append(parent->children, sub);
list_for_each(s, sub) {
--- /dev/null
+/*
+ * xml.c: the implementation of aug_to_xml and supporting functions
+ *
+ * Copyright (C) 2017 David Lutterkort
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: David Lutterkort <lutter@watzmann.net>
+ */
+
+#include <config.h>
+#include "augeas.h"
+#include "internal.h"
+#include "memory.h"
+#include "info.h"
+#include "errcode.h"
+
+#include <libxml/tree.h>
+
+static int to_xml_span(xmlNodePtr elem, const char *pfor, int start, int end) {
+ int r;
+ char *buf;
+ xmlAttrPtr prop;
+ xmlNodePtr span_elem;
+
+ span_elem = xmlNewChild(elem, NULL, BAD_CAST "span", NULL);
+ if (span_elem == NULL)
+ return -1;
+
+ prop = xmlSetProp(span_elem, BAD_CAST "for", BAD_CAST pfor);
+ if (prop == NULL)
+ return -1;
+
+ /* Format and set the start property */
+ r = xasprintf(&buf, "%d", start);
+ if (r < 0)
+ return -1;
+
+ prop = xmlSetProp(span_elem, BAD_CAST "start", BAD_CAST buf);
+ FREE(buf);
+ if (prop == NULL)
+ return -1;
+
+ /* Format and set the end property */
+ r = xasprintf(&buf, "%d", end);
+ if (r < 0)
+ return -1;
+
+ prop = xmlSetProp(span_elem, BAD_CAST "end", BAD_CAST buf);
+ FREE(buf);
+ if (prop == NULL)
+ return -1;
+
+ return 0;
+}
+
+static int to_xml_one(xmlNodePtr elem, const struct tree *tree,
+ const char *pathin) {
+ xmlNodePtr value;
+ xmlAttrPtr prop;
+ int r;
+
+ prop = xmlSetProp(elem, BAD_CAST "label", BAD_CAST tree->label);
+ if (prop == NULL)
+ goto error;
+
+ if (tree->span) {
+ struct span *span = tree->span;
+
+ prop = xmlSetProp(elem, BAD_CAST "file",
+ BAD_CAST span->filename->str);
+ if (prop == NULL)
+ goto error;
+
+ r = to_xml_span(elem, "label", span->label_start, span->label_end);
+ if (r < 0)
+ goto error;
+
+ r = to_xml_span(elem, "value", span->value_start, span->value_end);
+ if (r < 0)
+ goto error;
+
+ r = to_xml_span(elem, "node", span->span_start, span->span_end);
+ if (r < 0)
+ goto error;
+ }
+
+ if (pathin != NULL) {
+ prop = xmlSetProp(elem, BAD_CAST "path", BAD_CAST pathin);
+ if (prop == NULL)
+ goto error;
+ }
+ if (tree->value != NULL) {
+ value = xmlNewTextChild(elem, NULL, BAD_CAST "value",
+ BAD_CAST tree->value);
+ if (value == NULL)
+ goto error;
+ }
+ return 0;
+ error:
+ return -1;
+}
+
+static int to_xml_rec(xmlNodePtr pnode, struct tree *start,
+ const char *pathin) {
+ int r;
+ xmlNodePtr elem;
+
+ elem = xmlNewChild(pnode, NULL, BAD_CAST "node", NULL);
+ if (elem == NULL)
+ goto error;
+ r = to_xml_one(elem, start, pathin);
+ if (r < 0)
+ goto error;
+
+ list_for_each(tree, start->children) {
+ if (TREE_HIDDEN(tree))
+ continue;
+ r = to_xml_rec(elem, tree, NULL);
+ if (r < 0)
+ goto error;
+ }
+
+ return 0;
+ error:
+ return -1;
+}
+
+static int tree_to_xml(struct pathx *p, xmlNode **xml, const char *pathin) {
+ char *path = NULL;
+ struct tree *tree;
+ xmlAttrPtr expr;
+ int r;
+
+ *xml = xmlNewNode(NULL, BAD_CAST "augeas");
+ if (*xml == NULL)
+ goto error;
+ expr = xmlSetProp(*xml, BAD_CAST "match", BAD_CAST pathin);
+ if (expr == NULL)
+ goto error;
+
+ for (tree = pathx_first(p); tree != NULL; tree = pathx_next(p)) {
+ if (TREE_HIDDEN(tree))
+ continue;
+ path = path_of_tree(tree);
+ if (path == NULL)
+ goto error;
+ r = to_xml_rec(*xml, tree, path);
+ if (r < 0)
+ goto error;
+ FREE(path);
+ }
+ return 0;
+ error:
+ free(path);
+ xmlFree(*xml);
+ *xml = NULL;
+ return -1;
+}
+
+int aug_to_xml(const struct augeas *aug, const char *pathin,
+ xmlNode **xmldoc, unsigned int flags) {
+ struct pathx *p = NULL;
+ int result = -1;
+
+ api_entry(aug);
+
+ ARG_CHECK(flags != 0, aug, "aug_to_xml: FLAGS must be 0");
+ ARG_CHECK(xmldoc == NULL, aug, "aug_to_xml: XMLDOC must be non-NULL");
+
+ *xmldoc = NULL;
+
+ if (pathin == NULL || strlen(pathin) == 0 || strcmp(pathin, "/") == 0) {
+ pathin = "/*";
+ }
+
+ p = pathx_aug_parse(aug, aug->origin, tree_root_ctx(aug), pathin, true);
+ ERR_BAIL(aug);
+ result = tree_to_xml(p, xmldoc, pathin);
+ ERR_THROW(result < 0, aug, AUG_ENOMEM, NULL);
+error:
+ free_pathx(p);
+ api_exit(aug);
+
+ return result;
+}
lens-qpid.sh \
lens-quote.sh \
lens-rabbitmq.sh \
+ lens-radicale.sh \
lens-redis.sh \
lens-reprepro_uploaders.sh \
lens-resolv.sh \