augeas 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/COPYING +510 -0
- data/NEWS +41 -0
- data/README.rdoc +86 -0
- data/Rakefile +96 -0
- data/ext/augeas/_augeas.c +646 -0
- data/ext/augeas/_augeas.h +48 -0
- data/ext/augeas/extconf.rb +46 -0
- data/lib/augeas.rb +383 -0
- data/tests/root/etc/group +26 -0
- data/tests/root/etc/hosts +6 -0
- data/tests/root/etc/inittab +53 -0
- data/tests/root/etc/ssh/sshd_config +2 -0
- data/tests/tc_augeas.rb +666 -0
- metadata +88 -0
data/NEWS
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
0.6.0 - 2014-01-19
|
|
2
|
+
- merge pull request by mapleoin (https://github.com/mapleoin):
|
|
3
|
+
raise exceptions instead of returning error codes
|
|
4
|
+
|
|
5
|
+
0.5.0 - 2013-03-12
|
|
6
|
+
- add libxml2 headers and library to Makefile
|
|
7
|
+
- add libxml2-devel build req to rpm spec
|
|
8
|
+
- split out header, add memstream utils from Augeas
|
|
9
|
+
- integrate with Travis CI
|
|
10
|
+
- Takefile: add gem authors metadata
|
|
11
|
+
- Augeas::transform: add .lns suffix if a module name is passed
|
|
12
|
+
to match aug_transform behaviour
|
|
13
|
+
- add Augeas::clearm
|
|
14
|
+
- add Augeas::context and Augeas::context=
|
|
15
|
+
- add Augeas::label
|
|
16
|
+
- add Augeas::rename
|
|
17
|
+
- add Augeas::srun
|
|
18
|
+
- add Augeas::text_retrieve
|
|
19
|
+
- add Augeas::text_store
|
|
20
|
+
|
|
21
|
+
0.4.1 - 2011-03-29
|
|
22
|
+
- remove object files from release tarball
|
|
23
|
+
|
|
24
|
+
0.4.0 - 2011-03-25
|
|
25
|
+
- set can now set multiple elements at once
|
|
26
|
+
- expose aug_setm as Augeas#setm
|
|
27
|
+
- expose error functions through Augeas#error
|
|
28
|
+
- expose aug_span as Augeas#span
|
|
29
|
+
|
|
30
|
+
0.3.0 - 2009-08-12
|
|
31
|
+
- Require augeas >= 0.5.1
|
|
32
|
+
- Bindings for aug_load, aug_defvar, and aug_defnode
|
|
33
|
+
- Map flags AUG_NO_STDINC, AUG_NO_LOAD, AUG_NO_MODL_AUTOLOAD
|
|
34
|
+
- Augeas::transform: convenience method for setting up transforms
|
|
35
|
+
- Augeas::set: allow passing in nil as the value
|
|
36
|
+
- Augeas::open: make args optional, accept block
|
|
37
|
+
- Exception raising versions of set, load, and save
|
|
38
|
+
|
|
39
|
+
0.2.0 - 2008-08-26
|
|
40
|
+
Details for this and earlier releases need to be extracted from the
|
|
41
|
+
history of the git repo
|
data/README.rdoc
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
= Ruby bindings for augeas
|
|
2
|
+
|
|
3
|
+
The class Augeas provides bindings to augeas [http://augeas.net] library.
|
|
4
|
+
|
|
5
|
+
== Usage: Setting Data
|
|
6
|
+
Augeas::create do |aug|
|
|
7
|
+
aug.set("/files/etc/sysconfig/firstboot/RUN_FIRSTBOOT", "YES")
|
|
8
|
+
unless aug.save
|
|
9
|
+
raise IOError, "Failed to save changes"
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
== Usage: Accessing Data
|
|
14
|
+
firstboot = Augeas::create {
|
|
15
|
+
|aug| aug.get("/files/etc/sysconfig/firstboot/RUN_FIRSTBOOT") }
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
== Usage: Removing Data
|
|
19
|
+
Augeas::create do |aug|
|
|
20
|
+
aug.rm("/files/etc/sysconfig/firstboot/RUN_FIRSTBOOT")
|
|
21
|
+
unless aug.save
|
|
22
|
+
raise IOError, "Failed to save changes"
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
== Usage: Minimal Setup with a Custom Root
|
|
27
|
+
|
|
28
|
+
By passing using the +:no_modl_autoload+ flag, no files are read on
|
|
29
|
+
startup; that allows setting up a custom transform.
|
|
30
|
+
|
|
31
|
+
Augeas::create(:root => "/var/tmp/augeas-root",
|
|
32
|
+
:loadpath => "/usr/local/share/mylenses",
|
|
33
|
+
:no_modl_autoload => true) do |aug|
|
|
34
|
+
aug.transform(:lens => "Aliases.lns", :incl => "/etc/aliases")
|
|
35
|
+
aug.load
|
|
36
|
+
aug.get("/files/etc/aliases/*[name = 'postmaster']/value")
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
== Deprecation Warning
|
|
41
|
+
|
|
42
|
+
The Augeas API has been heavily rewritten in order to better support
|
|
43
|
+
errors.
|
|
44
|
+
|
|
45
|
+
To use the new API, just use <tt>Augeas::create</tt> instead of
|
|
46
|
+
<tt>Augeas::open</tt>. This is the documentation for the
|
|
47
|
+
<tt>Augeas::create</tt> method.
|
|
48
|
+
|
|
49
|
+
Create a new Augeas instance and return it.
|
|
50
|
+
|
|
51
|
+
Use <tt>:root</tt> as the filesystem root. If <tt>:root</tt> is
|
|
52
|
+
<tt>nil</tt>, use the value of the environment variable
|
|
53
|
+
<tt>AUGEAS_ROOT</tt>. If that doesn't exist either, use "/".
|
|
54
|
+
|
|
55
|
+
<tt>:loadpath</tt> is a colon-spearated list of directories that modules
|
|
56
|
+
should be searched in. This is in addition to the standard load path and
|
|
57
|
+
the directories in <tt>AUGEAS_LENS_LIB</tt>.
|
|
58
|
+
|
|
59
|
+
The following flags can be specified in a hash. They all default to
|
|
60
|
+
false and can be enabled by setting them to true
|
|
61
|
+
|
|
62
|
+
<tt>:type_check</tt> - typecheck lenses (since it can be very expensive
|
|
63
|
+
it is not done by default)
|
|
64
|
+
|
|
65
|
+
<tt>:no_stdinc</tt> - do not use the builtin load path for modules
|
|
66
|
+
|
|
67
|
+
<tt>:no_load</tt> - do not load the tree during the initialization phase
|
|
68
|
+
|
|
69
|
+
<tt>:no_modl_autoload</tt> - do not load the tree during the
|
|
70
|
+
initialization phase
|
|
71
|
+
|
|
72
|
+
<tt>:enable_span</tt> - track the span in the input nodes
|
|
73
|
+
|
|
74
|
+
<tt>:save_mode</tt> can be one of <tt>:backup</tt>, <tt>:newfile</tt>,
|
|
75
|
+
<tt>:noop</tt> as explained below.
|
|
76
|
+
|
|
77
|
+
:noop - make save a no-op process, just record what would have changed
|
|
78
|
+
|
|
79
|
+
:backup - keep the original file with an .augsave extension
|
|
80
|
+
|
|
81
|
+
:newfile - save changes into a file with an .augnew extension and do
|
|
82
|
+
not overwrite the original file.
|
|
83
|
+
|
|
84
|
+
When a block is given, the Augeas instance is passed as the only
|
|
85
|
+
argument into the block and closed when the block exits. With no block,
|
|
86
|
+
the Augeas instance is returned.
|
data/Rakefile
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# -*- ruby -*-
|
|
2
|
+
|
|
3
|
+
require 'rake/clean'
|
|
4
|
+
require 'rdoc/task'
|
|
5
|
+
require 'rake/testtask'
|
|
6
|
+
require 'rubygems/package_task'
|
|
7
|
+
|
|
8
|
+
GEM_NAME='augeas'
|
|
9
|
+
GEM_VERSION='0.6.0'
|
|
10
|
+
EXT_CONF='ext/augeas/extconf.rb'
|
|
11
|
+
MAKEFILE="ext/augeas/Makefile"
|
|
12
|
+
AUGEAS_MODULE="ext/augeas/_augeas.so"
|
|
13
|
+
SPEC_FILE="augeas.spec"
|
|
14
|
+
AUGEAS_SRC=AUGEAS_MODULE.gsub(/.so$/, ".c")
|
|
15
|
+
|
|
16
|
+
#
|
|
17
|
+
# Building the actual bits
|
|
18
|
+
#
|
|
19
|
+
CLEAN.include [ "**/*~",
|
|
20
|
+
"ext/**/*.o", AUGEAS_MODULE,
|
|
21
|
+
"ext/**/depend" ]
|
|
22
|
+
|
|
23
|
+
CLOBBER.include [ "config.save",
|
|
24
|
+
"ext/**/mkmf.log",
|
|
25
|
+
MAKEFILE ]
|
|
26
|
+
|
|
27
|
+
file MAKEFILE => EXT_CONF do |t|
|
|
28
|
+
Dir::chdir(File::dirname(EXT_CONF)) do
|
|
29
|
+
unless sh "ruby #{File::basename(EXT_CONF)}"
|
|
30
|
+
$stderr.puts "Failed to run extconf"
|
|
31
|
+
break
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
file AUGEAS_MODULE => [ MAKEFILE, AUGEAS_SRC ] do |t|
|
|
36
|
+
Dir::chdir(File::dirname(EXT_CONF)) do
|
|
37
|
+
unless sh "make"
|
|
38
|
+
$stderr.puts "make failed"
|
|
39
|
+
break
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
desc "Build the native library"
|
|
44
|
+
task :build => AUGEAS_MODULE
|
|
45
|
+
|
|
46
|
+
#
|
|
47
|
+
# Testing
|
|
48
|
+
#
|
|
49
|
+
Rake::TestTask.new(:test) do |t|
|
|
50
|
+
t.test_files = FileList['tests/tc_*.rb']
|
|
51
|
+
t.libs = [ 'lib', 'ext/augeas' ]
|
|
52
|
+
end
|
|
53
|
+
task :test => :build
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
#
|
|
57
|
+
# Generate the documentation
|
|
58
|
+
#
|
|
59
|
+
RDoc::Task.new do |rd|
|
|
60
|
+
rd.main = "README.rdoc"
|
|
61
|
+
rd.rdoc_dir = "doc/site/api"
|
|
62
|
+
rd.rdoc_files.include("README.rdoc", "ext/**/*.[ch]","lib/**/*.rb")
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
#
|
|
66
|
+
# Packaging
|
|
67
|
+
#
|
|
68
|
+
PKG_FILES = FileList[
|
|
69
|
+
"Rakefile", "COPYING","README.rdoc", "NEWS",
|
|
70
|
+
"ext/**/*.[ch]", "lib/**/*.rb", "ext/**/MANIFEST", "ext/**/extconf.rb",
|
|
71
|
+
"tests/**/*",
|
|
72
|
+
"spec/**/*"
|
|
73
|
+
]
|
|
74
|
+
|
|
75
|
+
SPEC = Gem::Specification.new do |s|
|
|
76
|
+
s.name = GEM_NAME
|
|
77
|
+
s.version = GEM_VERSION
|
|
78
|
+
s.email = "dot.doom@gmail.com"
|
|
79
|
+
s.homepage = "http://augeas.net/"
|
|
80
|
+
s.summary = "Ruby bindings for augeas"
|
|
81
|
+
s.authors = [ "Bryan Kearney", "David Lutterkort", "Ionut Artarisi", "Artem Sheremet" ]
|
|
82
|
+
s.files = PKG_FILES
|
|
83
|
+
s.licenses = ['LGPLv2']
|
|
84
|
+
s.required_ruby_version = '>= 1.8.7'
|
|
85
|
+
s.extensions = "ext/augeas/extconf.rb"
|
|
86
|
+
s.description = "Provides bindings for augeas."
|
|
87
|
+
s.add_development_dependency "rake"
|
|
88
|
+
s.add_development_dependency "rdoc"
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
Gem::PackageTask.new(SPEC) do |pkg|
|
|
92
|
+
pkg.need_tar = true
|
|
93
|
+
pkg.need_zip = true
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
task :default => [:build, :test]
|
|
@@ -0,0 +1,646 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* augeas.c: Ruby bindings for augeas
|
|
3
|
+
*
|
|
4
|
+
* Copyright (C) 2008-2011 Red Hat Inc.
|
|
5
|
+
* Copyright (C) 2011 SUSE LINUX Products GmbH, Nuernberg, Germany.
|
|
6
|
+
*
|
|
7
|
+
* This library is free software; you can redistribute it and/or
|
|
8
|
+
* modify it under the terms of the GNU Lesser General Public
|
|
9
|
+
* License as published by the Free Software Foundation; either
|
|
10
|
+
* version 2.1 of the License, or (at your option) any later version.
|
|
11
|
+
*
|
|
12
|
+
* This library is distributed in the hope that it will be useful,
|
|
13
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
15
|
+
* Lesser General Public License for more details.
|
|
16
|
+
*
|
|
17
|
+
* You should have received a copy of the GNU Lesser General Public
|
|
18
|
+
* License along with this library; if not, write to the Free Software
|
|
19
|
+
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
20
|
+
*
|
|
21
|
+
* Authors: Bryan Kearney <bkearney@redhat.com>
|
|
22
|
+
* Ionuț Arțăriși <iartarisi@suse.cz>
|
|
23
|
+
*/
|
|
24
|
+
#include "_augeas.h"
|
|
25
|
+
|
|
26
|
+
#include <ruby.h>
|
|
27
|
+
#include <augeas.h>
|
|
28
|
+
|
|
29
|
+
static VALUE c_augeas;
|
|
30
|
+
|
|
31
|
+
static augeas *aug_handle(VALUE s) {
|
|
32
|
+
augeas *aug;
|
|
33
|
+
|
|
34
|
+
Data_Get_Struct(s, struct augeas, aug);
|
|
35
|
+
if (aug == NULL) {
|
|
36
|
+
rb_raise(rb_eSystemCallError, "Failed to retrieve connection");
|
|
37
|
+
}
|
|
38
|
+
return aug;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
static void augeas_free(augeas *aug) {
|
|
42
|
+
if (aug != NULL)
|
|
43
|
+
aug_close(aug);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/*
|
|
47
|
+
* call-seq:
|
|
48
|
+
* get(PATH) -> String
|
|
49
|
+
*
|
|
50
|
+
* Lookup the value associated with PATH
|
|
51
|
+
*/
|
|
52
|
+
VALUE augeas_get(VALUE s, VALUE path) {
|
|
53
|
+
augeas *aug = aug_handle(s);
|
|
54
|
+
const char *cpath = StringValueCStr(path);
|
|
55
|
+
const char *value = NULL;
|
|
56
|
+
|
|
57
|
+
int retval = aug_get(aug, cpath, &value);
|
|
58
|
+
|
|
59
|
+
if (retval == 1 && value != NULL) {
|
|
60
|
+
return rb_str_new(value, strlen(value));
|
|
61
|
+
} else {
|
|
62
|
+
return Qnil;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/*
|
|
67
|
+
* call-seq:
|
|
68
|
+
* exists(PATH) -> boolean
|
|
69
|
+
*
|
|
70
|
+
* Return true if there is an entry for this path, false otherwise
|
|
71
|
+
*/
|
|
72
|
+
VALUE augeas_exists(VALUE s, VALUE path) {
|
|
73
|
+
augeas *aug = aug_handle(s);
|
|
74
|
+
const char *cpath = StringValueCStr(path);
|
|
75
|
+
int ret = aug_get(aug, cpath, NULL);
|
|
76
|
+
|
|
77
|
+
return (ret == 1) ? Qtrue : Qfalse;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/*
|
|
81
|
+
* call-seq:
|
|
82
|
+
* set(PATH, VALUE) -> int
|
|
83
|
+
*
|
|
84
|
+
* Set the value associated with PATH to VALUE. VALUE is copied into the
|
|
85
|
+
* internal data structure. Intermediate entries are created if they don't
|
|
86
|
+
* exist.
|
|
87
|
+
*/
|
|
88
|
+
VALUE augeas_set(VALUE s, VALUE path, VALUE value) {
|
|
89
|
+
augeas *aug = aug_handle(s);
|
|
90
|
+
const char *cpath = StringValueCStr(path) ;
|
|
91
|
+
const char *cvalue = StringValueCStrOrNull(value) ;
|
|
92
|
+
|
|
93
|
+
int callValue = aug_set(aug, cpath, cvalue) ;
|
|
94
|
+
return INT2FIX(callValue);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/*
|
|
98
|
+
* call-seq:
|
|
99
|
+
* set(PATH, VALUE) -> boolean
|
|
100
|
+
*
|
|
101
|
+
* Set the value associated with PATH to VALUE. VALUE is copied into the
|
|
102
|
+
* internal data structure. Intermediate entries are created if they don't
|
|
103
|
+
* exist.
|
|
104
|
+
*/
|
|
105
|
+
VALUE augeas_set_old(VALUE s, VALUE path, VALUE value) {
|
|
106
|
+
augeas *aug = aug_handle(s);
|
|
107
|
+
const char *cpath = StringValueCStr(path) ;
|
|
108
|
+
const char *cvalue = StringValueCStrOrNull(value) ;
|
|
109
|
+
|
|
110
|
+
int callValue = aug_set(aug, cpath, cvalue) ;
|
|
111
|
+
VALUE returnValue ;
|
|
112
|
+
|
|
113
|
+
if (callValue == 0)
|
|
114
|
+
returnValue = Qtrue ;
|
|
115
|
+
else
|
|
116
|
+
returnValue = Qfalse ;
|
|
117
|
+
|
|
118
|
+
return returnValue ;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/*
|
|
122
|
+
* call-seq:
|
|
123
|
+
* setm(BASE, SUB, VALUE) -> boolean
|
|
124
|
+
*
|
|
125
|
+
* Set multiple nodes in one operation. Find or create a node matching
|
|
126
|
+
* SUB by interpreting SUB as a path expression relative to each node
|
|
127
|
+
* matching BASE. SUB may be NULL, in which case all the nodes matching
|
|
128
|
+
* BASE will be modified.
|
|
129
|
+
*/
|
|
130
|
+
VALUE augeas_setm(VALUE s, VALUE base, VALUE sub, VALUE value) {
|
|
131
|
+
augeas *aug = aug_handle(s);
|
|
132
|
+
const char *cbase = StringValueCStr(base) ;
|
|
133
|
+
const char *csub = StringValueCStrOrNull(sub) ;
|
|
134
|
+
const char *cvalue = StringValueCStrOrNull(value) ;
|
|
135
|
+
|
|
136
|
+
int callValue = aug_setm(aug, cbase, csub, cvalue) ;
|
|
137
|
+
return INT2FIX(callValue);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/*
|
|
141
|
+
* call-seq:
|
|
142
|
+
* insert(PATH, LABEL, BEFORE) -> int
|
|
143
|
+
*
|
|
144
|
+
* Make LABEL a sibling of PATH by inserting it directly before or after PATH.
|
|
145
|
+
* The boolean BEFORE determines if LABEL is inserted before or after PATH.
|
|
146
|
+
*/
|
|
147
|
+
VALUE augeas_insert(VALUE s, VALUE path, VALUE label, VALUE before) {
|
|
148
|
+
augeas *aug = aug_handle(s);
|
|
149
|
+
const char *cpath = StringValueCStr(path) ;
|
|
150
|
+
const char *clabel = StringValueCStr(label) ;
|
|
151
|
+
|
|
152
|
+
int callValue = aug_insert(aug, cpath, clabel, RTEST(before));
|
|
153
|
+
return INT2FIX(callValue) ;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/*
|
|
157
|
+
* call-seq:
|
|
158
|
+
* mv(SRC, DST) -> int
|
|
159
|
+
*
|
|
160
|
+
* Move the node SRC to DST. SRC must match exactly one node in the
|
|
161
|
+
* tree. DST must either match exactly one node in the tree, or may not
|
|
162
|
+
* exist yet. If DST exists already, it and all its descendants are
|
|
163
|
+
* deleted. If DST does not exist yet, it and all its missing ancestors are
|
|
164
|
+
* created.
|
|
165
|
+
*/
|
|
166
|
+
VALUE augeas_mv(VALUE s, VALUE src, VALUE dst) {
|
|
167
|
+
augeas *aug = aug_handle(s);
|
|
168
|
+
const char *csrc = StringValueCStr(src);
|
|
169
|
+
const char *cdst = StringValueCStr(dst);
|
|
170
|
+
int r = aug_mv(aug, csrc, cdst);
|
|
171
|
+
|
|
172
|
+
return INT2FIX(r);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/*
|
|
176
|
+
* call-seq:
|
|
177
|
+
* rm(PATH) -> int
|
|
178
|
+
*
|
|
179
|
+
* Remove path and all its children. Returns the number of entries removed
|
|
180
|
+
*/
|
|
181
|
+
VALUE augeas_rm(VALUE s, VALUE path, VALUE sibling) {
|
|
182
|
+
augeas *aug = aug_handle(s);
|
|
183
|
+
const char *cpath = StringValueCStr(path) ;
|
|
184
|
+
|
|
185
|
+
int callValue = aug_rm(aug, cpath) ;
|
|
186
|
+
return INT2FIX(callValue) ;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/*
|
|
190
|
+
* call-seq:
|
|
191
|
+
* match(PATH) -> an_array
|
|
192
|
+
*
|
|
193
|
+
* Return all the paths that match the path expression PATH as an aray of
|
|
194
|
+
* strings.
|
|
195
|
+
* Returns an empty array if no paths were found.
|
|
196
|
+
*/
|
|
197
|
+
VALUE augeas_match(VALUE s, VALUE p) {
|
|
198
|
+
augeas *aug = aug_handle(s);
|
|
199
|
+
const char *path = StringValueCStr(p);
|
|
200
|
+
char **matches = NULL;
|
|
201
|
+
int cnt, i;
|
|
202
|
+
|
|
203
|
+
cnt = aug_match(aug, path, &matches) ;
|
|
204
|
+
if (cnt < 0)
|
|
205
|
+
return -1;
|
|
206
|
+
|
|
207
|
+
VALUE result = rb_ary_new();
|
|
208
|
+
for (i = 0; i < cnt; i++) {
|
|
209
|
+
rb_ary_push(result, rb_str_new(matches[i], strlen(matches[i])));
|
|
210
|
+
free(matches[i]) ;
|
|
211
|
+
}
|
|
212
|
+
free (matches) ;
|
|
213
|
+
|
|
214
|
+
return result ;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/*
|
|
218
|
+
* call-seq:
|
|
219
|
+
* match(PATH) -> an_array
|
|
220
|
+
*
|
|
221
|
+
* Return all the paths that match the path expression PATH as an aray of
|
|
222
|
+
* strings.
|
|
223
|
+
* Raises an error if no paths were found.
|
|
224
|
+
*/
|
|
225
|
+
VALUE augeas_match_old(VALUE s, VALUE p) {
|
|
226
|
+
augeas *aug = aug_handle(s);
|
|
227
|
+
const char *path = StringValueCStr(p);
|
|
228
|
+
char **matches = NULL;
|
|
229
|
+
int cnt, i;
|
|
230
|
+
|
|
231
|
+
cnt = aug_match(aug, path, &matches) ;
|
|
232
|
+
if (cnt < 0)
|
|
233
|
+
rb_raise(rb_eSystemCallError, "Matching path expression '%s' failed",
|
|
234
|
+
path);
|
|
235
|
+
|
|
236
|
+
VALUE result = rb_ary_new();
|
|
237
|
+
for (i = 0; i < cnt; i++) {
|
|
238
|
+
rb_ary_push(result, rb_str_new(matches[i], strlen(matches[i])));
|
|
239
|
+
free(matches[i]) ;
|
|
240
|
+
}
|
|
241
|
+
free (matches) ;
|
|
242
|
+
|
|
243
|
+
return result ;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/*
|
|
247
|
+
* call-seq:
|
|
248
|
+
* save() -> int
|
|
249
|
+
*
|
|
250
|
+
* Write all pending changes to disk
|
|
251
|
+
*/
|
|
252
|
+
VALUE augeas_save(VALUE s) {
|
|
253
|
+
augeas *aug = aug_handle(s);
|
|
254
|
+
int callValue = aug_save(aug);
|
|
255
|
+
return INT2FIX(callValue);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/*
|
|
259
|
+
* call-seq:
|
|
260
|
+
* save() -> boolean
|
|
261
|
+
*
|
|
262
|
+
* Write all pending changes to disk
|
|
263
|
+
*/
|
|
264
|
+
VALUE augeas_save_old(VALUE s) {
|
|
265
|
+
augeas *aug = aug_handle(s);
|
|
266
|
+
int callValue = aug_save(aug) ;
|
|
267
|
+
VALUE returnValue ;
|
|
268
|
+
|
|
269
|
+
if (callValue == 0)
|
|
270
|
+
returnValue = Qtrue ;
|
|
271
|
+
else
|
|
272
|
+
returnValue = Qfalse ;
|
|
273
|
+
|
|
274
|
+
return returnValue ;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/*
|
|
278
|
+
* call-seq:
|
|
279
|
+
* load() -> int
|
|
280
|
+
*
|
|
281
|
+
* Load files from disk according to the transforms under +/augeas/load+
|
|
282
|
+
*/
|
|
283
|
+
VALUE augeas_load(VALUE s) {
|
|
284
|
+
augeas *aug = aug_handle(s);
|
|
285
|
+
int callValue = aug_load(aug);
|
|
286
|
+
return INT2FIX(callValue);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/*
|
|
290
|
+
* call-seq:
|
|
291
|
+
* load() -> boolean
|
|
292
|
+
*
|
|
293
|
+
* Load files from disk according to the transforms under +/augeas/load+
|
|
294
|
+
*/
|
|
295
|
+
VALUE augeas_load_old(VALUE s) {
|
|
296
|
+
augeas *aug = aug_handle(s);
|
|
297
|
+
int callValue = aug_load(aug);
|
|
298
|
+
VALUE returnValue ;
|
|
299
|
+
|
|
300
|
+
if (callValue == 0)
|
|
301
|
+
returnValue = Qtrue ;
|
|
302
|
+
else
|
|
303
|
+
returnValue = Qfalse ;
|
|
304
|
+
|
|
305
|
+
return returnValue ;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/*
|
|
309
|
+
* call-seq:
|
|
310
|
+
* defvar(NAME, EXPR) -> boolean
|
|
311
|
+
*
|
|
312
|
+
* Define a variable NAME whose value is the result of evaluating EXPR. If
|
|
313
|
+
* a variable NAME already exists, its name will be replaced with the
|
|
314
|
+
* result of evaluating EXPR.
|
|
315
|
+
*
|
|
316
|
+
* If EXPR is NULL, the variable NAME will be removed if it is defined.
|
|
317
|
+
*
|
|
318
|
+
*/
|
|
319
|
+
VALUE augeas_defvar(VALUE s, VALUE name, VALUE expr) {
|
|
320
|
+
augeas *aug = aug_handle(s);
|
|
321
|
+
const char *cname = StringValueCStr(name);
|
|
322
|
+
const char *cexpr = StringValueCStrOrNull(expr);
|
|
323
|
+
|
|
324
|
+
int r = aug_defvar(aug, cname, cexpr);
|
|
325
|
+
|
|
326
|
+
return (r < 0) ? Qfalse : Qtrue;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/*
|
|
330
|
+
* call-seq:
|
|
331
|
+
* defnode(NAME, EXPR, VALUE) -> boolean
|
|
332
|
+
*
|
|
333
|
+
* Define a variable NAME whose value is the result of evaluating EXPR,
|
|
334
|
+
* which must be non-NULL and evaluate to a nodeset. If a variable NAME
|
|
335
|
+
* already exists, its name will be replaced with the result of evaluating
|
|
336
|
+
* EXPR.
|
|
337
|
+
*
|
|
338
|
+
* If EXPR evaluates to an empty nodeset, a node is created, equivalent to
|
|
339
|
+
* calling AUG_SET(AUG, EXPR, VALUE) and NAME will be the nodeset containing
|
|
340
|
+
* that single node.
|
|
341
|
+
*
|
|
342
|
+
* Returns +false+ if +aug_defnode+ fails, and the number of nodes in the
|
|
343
|
+
* nodeset on success.
|
|
344
|
+
*/
|
|
345
|
+
VALUE augeas_defnode(VALUE s, VALUE name, VALUE expr, VALUE value) {
|
|
346
|
+
augeas *aug = aug_handle(s);
|
|
347
|
+
const char *cname = StringValueCStr(name);
|
|
348
|
+
const char *cexpr = StringValueCStrOrNull(expr);
|
|
349
|
+
const char *cvalue = StringValueCStrOrNull(value);
|
|
350
|
+
|
|
351
|
+
/* FIXME: Figure out a way to return created, maybe accept a block
|
|
352
|
+
that gets run when created == 1 ? */
|
|
353
|
+
int r = aug_defnode(aug, cname, cexpr, cvalue, NULL);
|
|
354
|
+
|
|
355
|
+
return (r < 0) ? Qfalse : INT2NUM(r);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
/* This function returns different names for different augeas API */
|
|
359
|
+
/* version specified in the +version+ argument. See augeas_init_old and */
|
|
360
|
+
/* augeas_init. */
|
|
361
|
+
VALUE augeas_init_split(VALUE m, VALUE r, VALUE l, VALUE f, char version) {
|
|
362
|
+
unsigned int flags = NUM2UINT(f);
|
|
363
|
+
const char *root = StringValueCStrOrNull(r);
|
|
364
|
+
const char *loadpath = StringValueCStrOrNull(l);
|
|
365
|
+
augeas *aug = NULL;
|
|
366
|
+
|
|
367
|
+
aug = aug_init(root, loadpath, flags);
|
|
368
|
+
if (aug == NULL) {
|
|
369
|
+
rb_raise(rb_eSystemCallError, "Failed to initialize Augeas");
|
|
370
|
+
}
|
|
371
|
+
return Data_Wrap_Struct(c_augeas, NULL, augeas_free, aug);
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
VALUE augeas_init_old(VALUE m, VALUE r, VALUE l, VALUE f) {
|
|
375
|
+
return augeas_init_split(m, r, l, f, 0);
|
|
376
|
+
}
|
|
377
|
+
VALUE augeas_init(VALUE m, VALUE r, VALUE l, VALUE f) {
|
|
378
|
+
return augeas_init_split(m, r, l, f, 1);
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
|
|
382
|
+
VALUE augeas_close (VALUE s) {
|
|
383
|
+
augeas *aug = aug_handle(s);
|
|
384
|
+
|
|
385
|
+
aug_close(aug);
|
|
386
|
+
DATA_PTR(s) = NULL;
|
|
387
|
+
|
|
388
|
+
return Qnil;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
static void hash_set(VALUE hash, const char *sym, VALUE v) {
|
|
392
|
+
rb_hash_aset(hash, ID2SYM(rb_intern(sym)), v);
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
/*
|
|
396
|
+
* call-seq:
|
|
397
|
+
* error -> HASH
|
|
398
|
+
*
|
|
399
|
+
* Retrieve details about the last error encountered and return those
|
|
400
|
+
* details in a HASH with the following entries:
|
|
401
|
+
* - :code error code from +aug_error+
|
|
402
|
+
* - :message error message from +aug_error_message+
|
|
403
|
+
* - :minor minor error message from +aug_minor_error_message+
|
|
404
|
+
* - :details error details from +aug_error_details+
|
|
405
|
+
*/
|
|
406
|
+
VALUE augeas_error(VALUE s) {
|
|
407
|
+
augeas *aug = aug_handle(s);
|
|
408
|
+
int code;
|
|
409
|
+
const char *msg = NULL;
|
|
410
|
+
VALUE result;
|
|
411
|
+
|
|
412
|
+
result = rb_hash_new();
|
|
413
|
+
|
|
414
|
+
code = aug_error(aug);
|
|
415
|
+
hash_set(result, "code", INT2NUM(code));
|
|
416
|
+
|
|
417
|
+
msg = aug_error_message(aug);
|
|
418
|
+
if (msg != NULL)
|
|
419
|
+
hash_set(result, "message", rb_str_new2(msg));
|
|
420
|
+
|
|
421
|
+
msg = aug_error_minor_message(aug);
|
|
422
|
+
if (msg != NULL)
|
|
423
|
+
hash_set(result, "minor", rb_str_new2(msg));
|
|
424
|
+
|
|
425
|
+
msg = aug_error_details(aug);
|
|
426
|
+
if (msg != NULL)
|
|
427
|
+
hash_set(result, "details", rb_str_new2(msg));
|
|
428
|
+
|
|
429
|
+
return result;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
static void hash_set_range(VALUE hash, const char *sym,
|
|
433
|
+
unsigned int start, unsigned int end) {
|
|
434
|
+
VALUE r;
|
|
435
|
+
|
|
436
|
+
r = rb_range_new(INT2NUM(start), INT2NUM(end), 0);
|
|
437
|
+
hash_set(hash, sym, r);
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
VALUE augeas_span(VALUE s, VALUE path) {
|
|
441
|
+
augeas *aug = aug_handle(s);
|
|
442
|
+
char *cpath = StringValueCStr(path);
|
|
443
|
+
char *filename = NULL;
|
|
444
|
+
unsigned int label_start, label_end, value_start, value_end,
|
|
445
|
+
span_start, span_end;
|
|
446
|
+
int r;
|
|
447
|
+
VALUE result;
|
|
448
|
+
|
|
449
|
+
r = aug_span(aug, cpath,
|
|
450
|
+
&filename,
|
|
451
|
+
&label_start, &label_end,
|
|
452
|
+
&value_start, &value_end,
|
|
453
|
+
&span_start, &span_end);
|
|
454
|
+
|
|
455
|
+
result = rb_hash_new();
|
|
456
|
+
|
|
457
|
+
if (r == 0) {
|
|
458
|
+
hash_set(result, "filename", rb_str_new2(filename));
|
|
459
|
+
hash_set_range(result, "label", label_start, label_end);
|
|
460
|
+
hash_set_range(result, "value", value_start, value_end);
|
|
461
|
+
hash_set_range(result, "span", span_start, span_end);
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
free(filename);
|
|
465
|
+
|
|
466
|
+
return result;
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
/*
|
|
470
|
+
* call-seq:
|
|
471
|
+
* srun(COMMANDS) -> [int, String]
|
|
472
|
+
*
|
|
473
|
+
* Run one or more newline-separated commands, returning their output.
|
|
474
|
+
*
|
|
475
|
+
* Returns:
|
|
476
|
+
* an array where the first element is the number of executed commands on
|
|
477
|
+
* success, -1 on failure, and -2 if a 'quit' command was encountered.
|
|
478
|
+
* The second element is a string of the output from all commands.
|
|
479
|
+
*/
|
|
480
|
+
VALUE augeas_srun(VALUE s, VALUE text) {
|
|
481
|
+
augeas *aug = aug_handle(s);
|
|
482
|
+
const char *ctext = StringValueCStr(text);
|
|
483
|
+
|
|
484
|
+
struct memstream ms;
|
|
485
|
+
__aug_init_memstream(&ms);
|
|
486
|
+
|
|
487
|
+
int r = aug_srun(aug, ms.stream, ctext);
|
|
488
|
+
__aug_close_memstream(&ms);
|
|
489
|
+
|
|
490
|
+
VALUE result = rb_ary_new();
|
|
491
|
+
rb_ary_push(result, INT2NUM(r));
|
|
492
|
+
rb_ary_push(result, rb_str_new2(ms.buf));
|
|
493
|
+
|
|
494
|
+
free(ms.buf);
|
|
495
|
+
return result;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
/*
|
|
499
|
+
* call-seq:
|
|
500
|
+
* label(PATH) -> String
|
|
501
|
+
*
|
|
502
|
+
* Lookup the label associated with PATH
|
|
503
|
+
*/
|
|
504
|
+
VALUE augeas_label(VALUE s, VALUE path) {
|
|
505
|
+
augeas *aug = aug_handle(s);
|
|
506
|
+
const char *cpath = StringValueCStr(path);
|
|
507
|
+
const char *label = NULL;
|
|
508
|
+
|
|
509
|
+
aug_label(aug, cpath, &label);
|
|
510
|
+
if (label != NULL) {
|
|
511
|
+
return rb_str_new(label, strlen(label)) ;
|
|
512
|
+
} else {
|
|
513
|
+
return Qnil;
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
/*
|
|
518
|
+
* call-seq:
|
|
519
|
+
* rename(SRC, LABEL) -> int
|
|
520
|
+
*
|
|
521
|
+
* Rename the label of all nodes matching SRC to LABEL.
|
|
522
|
+
*
|
|
523
|
+
* Returns +false+ if +aug_rename+ fails, and the number of nodes renamed
|
|
524
|
+
* on success.
|
|
525
|
+
*/
|
|
526
|
+
VALUE augeas_rename(VALUE s, VALUE src, VALUE label) {
|
|
527
|
+
augeas *aug = aug_handle(s);
|
|
528
|
+
const char *csrc = StringValueCStr(src);
|
|
529
|
+
const char *clabel = StringValueCStr(label);
|
|
530
|
+
int r = aug_rename(aug, csrc, clabel);
|
|
531
|
+
|
|
532
|
+
return (r < 0) ? Qfalse : INT2NUM(r);
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
/*
|
|
536
|
+
* call-seq:
|
|
537
|
+
* text_store(LENS, NODE, PATH) -> boolean
|
|
538
|
+
*
|
|
539
|
+
* Use the value of node NODE as a string and transform it into a tree
|
|
540
|
+
* using the lens LENS and store it in the tree at PATH, which will be
|
|
541
|
+
* overwritten. PATH and NODE are path expressions.
|
|
542
|
+
*/
|
|
543
|
+
VALUE augeas_text_store(VALUE s, VALUE lens, VALUE node, VALUE path) {
|
|
544
|
+
augeas *aug = aug_handle(s);
|
|
545
|
+
const char *clens = StringValueCStr(lens);
|
|
546
|
+
const char *cnode = StringValueCStr(node);
|
|
547
|
+
const char *cpath = StringValueCStr(path);
|
|
548
|
+
int r = aug_text_store(aug, clens, cnode, cpath);
|
|
549
|
+
|
|
550
|
+
return (r < 0) ? Qfalse : Qtrue;
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
/*
|
|
554
|
+
* call-seq:
|
|
555
|
+
* text_retrieve(LENS, NODE_IN, PATH, NODE_OUT) -> boolean
|
|
556
|
+
*
|
|
557
|
+
* Transform the tree at PATH into a string using lens LENS and store it in
|
|
558
|
+
* the node NODE_OUT, assuming the tree was initially generated using the
|
|
559
|
+
* value of node NODE_IN. PATH, NODE_IN, and NODE_OUT are path expressions.
|
|
560
|
+
*/
|
|
561
|
+
VALUE augeas_text_retrieve(VALUE s, VALUE lens, VALUE node_in, VALUE path, VALUE node_out) {
|
|
562
|
+
augeas *aug = aug_handle(s);
|
|
563
|
+
const char *clens = StringValueCStr(lens);
|
|
564
|
+
const char *cnode_in = StringValueCStr(node_in);
|
|
565
|
+
const char *cpath = StringValueCStr(path);
|
|
566
|
+
const char *cnode_out = StringValueCStr(node_out);
|
|
567
|
+
int r = aug_text_retrieve(aug, clens, cnode_in, cpath, cnode_out);
|
|
568
|
+
|
|
569
|
+
return (r < 0) ? Qfalse : Qtrue;
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
void Init__augeas() {
|
|
573
|
+
/* Define the NEW ruby class
|
|
574
|
+
*
|
|
575
|
+
* This class is basically the same as the old one, but uses a
|
|
576
|
+
* different naming scheme for methods (prefixing everything with
|
|
577
|
+
* "augeas_"). Also some methods point to different C functions.
|
|
578
|
+
*/
|
|
579
|
+
c_augeas = rb_define_class("Augeas", rb_cObject) ;
|
|
580
|
+
|
|
581
|
+
/* Constants for enum aug_flags */
|
|
582
|
+
#define DEF_AUG_FLAG(name) \
|
|
583
|
+
rb_define_const(c_augeas, #name, INT2NUM(AUG_##name))
|
|
584
|
+
DEF_AUG_FLAG(NONE);
|
|
585
|
+
DEF_AUG_FLAG(SAVE_BACKUP);
|
|
586
|
+
DEF_AUG_FLAG(SAVE_NEWFILE);
|
|
587
|
+
DEF_AUG_FLAG(TYPE_CHECK);
|
|
588
|
+
DEF_AUG_FLAG(NO_STDINC);
|
|
589
|
+
DEF_AUG_FLAG(SAVE_NOOP);
|
|
590
|
+
DEF_AUG_FLAG(NO_LOAD);
|
|
591
|
+
DEF_AUG_FLAG(NO_MODL_AUTOLOAD);
|
|
592
|
+
DEF_AUG_FLAG(ENABLE_SPAN);
|
|
593
|
+
#undef DEF_AUG_FLAG
|
|
594
|
+
|
|
595
|
+
/* Constants for enum aug_errcode_t */
|
|
596
|
+
#define DEF_AUG_ERR(name) \
|
|
597
|
+
rb_define_const(c_augeas, #name, INT2NUM(AUG_##name))
|
|
598
|
+
DEF_AUG_ERR(NOERROR);
|
|
599
|
+
DEF_AUG_ERR(ENOMEM);
|
|
600
|
+
DEF_AUG_ERR(EINTERNAL);
|
|
601
|
+
DEF_AUG_ERR(EPATHX);
|
|
602
|
+
DEF_AUG_ERR(ENOMATCH);
|
|
603
|
+
DEF_AUG_ERR(EMMATCH);
|
|
604
|
+
DEF_AUG_ERR(ESYNTAX);
|
|
605
|
+
DEF_AUG_ERR(ENOLENS);
|
|
606
|
+
DEF_AUG_ERR(EMXFM);
|
|
607
|
+
DEF_AUG_ERR(ENOSPAN);
|
|
608
|
+
DEF_AUG_ERR(EMVDESC);
|
|
609
|
+
DEF_AUG_ERR(ECMDRUN);
|
|
610
|
+
DEF_AUG_ERR(EBADARG);
|
|
611
|
+
DEF_AUG_ERR(ELABEL);
|
|
612
|
+
#undef DEF_AUG_ERR
|
|
613
|
+
|
|
614
|
+
/* Define the methods */
|
|
615
|
+
rb_define_singleton_method(c_augeas, "open3", augeas_init, 3);
|
|
616
|
+
rb_define_method(c_augeas, "augeas_defvar", augeas_defvar, 2);
|
|
617
|
+
rb_define_method(c_augeas, "augeas_defnode", augeas_defnode, 3);
|
|
618
|
+
rb_define_method(c_augeas, "augeas_get", augeas_get, 1);
|
|
619
|
+
rb_define_method(c_augeas, "augeas_exists", augeas_exists, 1);
|
|
620
|
+
rb_define_method(c_augeas, "augeas_insert", augeas_insert, 3);
|
|
621
|
+
rb_define_method(c_augeas, "augeas_mv", augeas_mv, 2);
|
|
622
|
+
rb_define_method(c_augeas, "augeas_rm", augeas_rm, 1);
|
|
623
|
+
rb_define_method(c_augeas, "augeas_match", augeas_match, 1);
|
|
624
|
+
rb_define_method(c_augeas, "augeas_save", augeas_save, 0);
|
|
625
|
+
rb_define_method(c_augeas, "augeas_load", augeas_load, 0);
|
|
626
|
+
rb_define_method(c_augeas, "augeas_set", augeas_set, 2);
|
|
627
|
+
rb_define_method(c_augeas, "augeas_setm", augeas_setm, 3);
|
|
628
|
+
/* The `close` and `error` methods as used unchanged in the ruby bindings */
|
|
629
|
+
rb_define_method(c_augeas, "close", augeas_close, 0);
|
|
630
|
+
rb_define_method(c_augeas, "error", augeas_error, 0);
|
|
631
|
+
rb_define_method(c_augeas, "augeas_span", augeas_span, 1);
|
|
632
|
+
rb_define_method(c_augeas, "augeas_srun", augeas_srun, 1);
|
|
633
|
+
rb_define_method(c_augeas, "augeas_label", augeas_label, 1);
|
|
634
|
+
rb_define_method(c_augeas, "augeas_rename", augeas_rename, 2);
|
|
635
|
+
rb_define_method(c_augeas, "augeas_text_store", augeas_text_store, 3);
|
|
636
|
+
rb_define_method(c_augeas, "augeas_text_retrieve", augeas_text_retrieve, 4);
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
/*
|
|
640
|
+
* Local variables:
|
|
641
|
+
* indent-tabs-mode: nil
|
|
642
|
+
* c-indent-level: 4
|
|
643
|
+
* c-basic-offset: 4
|
|
644
|
+
* tab-width: 4
|
|
645
|
+
* End:
|
|
646
|
+
*/
|