augeas 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
*/
|