File Coverage

blib/lib/Config/Model/Backend/Fstab.pm
Criterion Covered Total %
statement 64 64 100.0
branch 18 20 90.0
condition 3 5 60.0
subroutine 8 8 100.0
pod 3 4 75.0
total 96 101 95.0


line stmt bran cond sub pod time code
1             #
2             # This file is part of Config-Model
3             #
4             # This software is Copyright (c) 2005-2022 by Dominique Dumont.
5             #
6             # This is free software, licensed under:
7             #
8             # The GNU Lesser General Public License, Version 2.1, February 1999
9             #
10             package Config::Model::Backend::Fstab 2.153; # TRIAL
11              
12 1     1   8 use Mouse;
  1         3  
  1         8  
13 1     1   644 use Carp;
  1         2  
  1         91  
14 1     1   7 use Log::Log4perl qw(get_logger :levels);
  1         1  
  1         13  
15              
16             extends 'Config::Model::Backend::Any';
17              
18             my $logger = get_logger("Backend::Fstab");
19              
20 4     4 1 18 sub annotation { return 1; }
21              
22             my %opt_r_translate = (
23             ro => 'rw=0',
24             rw => 'rw=1',
25             bsddf => 'statfs_behavior=bsddf',
26             minixdf => 'statfs_behavior=minixdf',
27             );
28              
29             sub read {
30 4     4 1 14 my $self = shift;
31 4         64 my %args = @_;
32              
33             # args are:
34             # root => './my_test', # fake root directory, userd for tests
35             # config_dir => /etc/foo', # absolute path
36             # file => 'foo.conf', # file name
37             # file_path => './my_test/etc/foo/foo.conf'
38             # check => yes|no|skip
39              
40 4 50       22 return 0 unless $args{file_path}->exists; # no file to read
41 4   50     103 my $check = $args{check} || 'yes';
42              
43 4         17 my @lines = $args{file_path}->lines_utf8;
44              
45             # try to get global comments (comments before a blank line)
46 4         1110 $self->read_global_comments( \@lines, '#' );
47              
48 4         26 my @assoc = $self->associates_comments_with_data( \@lines, '#' );
49 4         23 foreach my $item (@assoc) {
50 58         261 my ( $data, $comment ) = @$item;
51 58         358 $logger->trace("fstab read data '$data' comment '$comment'");
52              
53 58         999 my ( $device, $mount_point, $type, $options, $dump, $pass ) =
54             split /\s+/, $data;
55              
56 58         155 my $swap_idx = 0;
57 58 100       449 my $label =
    100          
58             $device =~ /LABEL=(\w+)$/ ? $1
59             : $type eq 'swap' ? "swap-" . $swap_idx++
60             : $mount_point;
61              
62 58         417 my $fs_obj = $self->node->fetch_element('fs')->fetch_with_id($label);
63              
64 58 100       185 if ($comment) {
65 22         151 $logger->trace("Annotation: $comment\n");
66 22         306 $fs_obj->annotation($comment);
67             }
68              
69 58         331 my $load_line = "fs_vfstype=$type fs_spec=$device fs_file=$mount_point "
70             . "fs_freq=$dump fs_passno=$pass";
71 58         291 $logger->debug("Loading:$load_line\n");
72 58         595 $fs_obj->load( step => $load_line, check => $check );
73              
74             # now load fs options
75 58         336 $logger->trace("fs_type $type options is $options");
76 58         486 my @options;
77 58         354 foreach ( split /,/, $options ) {
78 118   66     491 my $o = $opt_r_translate{$_} // $_;
79 118         416 $o =~ s/no(.*)/$1=0/;
80 118 100       377 $o .= '=1' unless $o =~ /=/;
81 118         287 push @options, $o;
82             }
83              
84 58         298 $logger->debug("Loading:@options");
85 58         533 $fs_obj->fetch_element('fs_mntopts')->load( step => "@options", check => $check );
86             }
87 4         117 return 1;
88             }
89              
90             sub write {
91 2     2 1 8 my $self = shift;
92 2         12 my %args = @_;
93              
94             # args are:
95             # object => $obj, # Config::Model::Node object
96             # root => './my_test', # fake root directory, userd for tests
97             # config_dir => /etc/foo', # absolute path
98             # file => 'foo.conf', # file name
99             # file_path => './my_test/etc/foo/foo.conf'
100             # check => yes|no|skip
101              
102 2         13 my $node = $args{object};
103              
104 2 50       15 croak "Undefined file handle to write" unless defined $args{file_path};
105              
106 2         33 my $res = $self->write_global_comment( '#' );
107              
108             # Using Config::Model::ObjTreeScanner would be overkill
109 2         11 foreach my $line_obj ( $node->fetch_element('fs')->fetch_all ) {
110             my $d = sprintf(
111             "%-30s %-25s %-6s %-10s %d %d\n",
112 87         349 (map { $line_obj->fetch_element_value($_); } qw/fs_spec fs_file fs_vfstype/),
113             $self->option_string( $line_obj->fetch_element('fs_mntopts') ),
114 29         80 (map { $line_obj->fetch_element_value($_); } qw/fs_freq fs_passno/),
  58         224  
115             );
116 29         158 $res .= $self->write_data_and_comments( '#', $d, $line_obj->annotation );
117              
118             }
119              
120 2         36 $args{file_path}->spew_utf8($res);
121 2         1933 return 1;
122             }
123              
124             my %rev_opt_r_translate = reverse %opt_r_translate;
125              
126             sub option_string {
127 29     29 0 60 my ( $self, $obj ) = @_;
128              
129 29         48 my @options;
130 29         95 foreach my $opt ( $obj->get_element_name ) {
131 312         915 my $v = $obj->fetch_element_value($opt);
132 312 100       878 next unless defined $v;
133 59         162 my $key = "$opt=$v";
134             my $str =
135 59 100       276 defined $rev_opt_r_translate{$key} ? $rev_opt_r_translate{$key}
    100          
    100          
136             : "$v" eq '0' ? 'no' . $opt
137             : "$v" eq '1' ? $opt
138             : $key;
139 59         149 push @options, $str;
140             }
141              
142 29         153 return join ',', @options;
143             }
144              
145 1     1   1189 no Mouse;
  1         3  
  1         8  
146             __PACKAGE__->meta->make_immutable;
147              
148             1;
149              
150             # ABSTRACT: Read and write config from fstab file
151              
152             __END__
153              
154             =pod
155              
156             =encoding UTF-8
157              
158             =head1 NAME
159              
160             Config::Model::Backend::Fstab - Read and write config from fstab file
161              
162             =head1 VERSION
163              
164             version 2.153
165              
166             =head1 SYNOPSIS
167              
168             No synopsis. This class is dedicated to configuration class C<Fstab>
169              
170             =head1 DESCRIPTION
171              
172             This module is used directly by L<Config::Model> to read or write the
173             content of a configuration tree written with C<fstab> syntax in
174             C<Config::Model> configuration tree. Typically this backend is
175             used to read and write C</etc/fstab>.
176              
177             =head1 Comments in file_path
178              
179             This backend is able to read and write comments in the C</etc/fstab> file.
180              
181             =head1 STOP
182              
183             The documentation below describes methods that are currently used only by
184             L<Config::Model>. You don't need to read it to write a model.
185              
186             =head1 CONSTRUCTOR
187              
188             =head2 new
189              
190             Parameters: C<< ( node => $node_obj, name => 'fstab' ) >>
191              
192             Inherited from L<Config::Model::Backend::Any>. The constructor is
193             called by L<Config::Model::BackendMgr>.
194              
195             =head2 read
196              
197             Of all parameters passed to this read call-back, only C<file_path> is
198             used. This parameter must be a L<Path::Tiny> object.
199              
200             When a file is read, C<read> returns 1.
201              
202             =head2 write
203              
204             Of all parameters passed to this write call-back, only C<file_path> is
205             used.
206              
207             C<write> returns 1.
208              
209             =head1 AUTHOR
210              
211             Dominique Dumont, (ddumont at cpan dot org)
212              
213             =head1 SEE ALSO
214              
215             L<Config::Model>,
216             L<Config::Model::BackendMgr>,
217             L<Config::Model::Backend::Any>,
218              
219             =head1 AUTHOR
220              
221             Dominique Dumont
222              
223             =head1 COPYRIGHT AND LICENSE
224              
225             This software is Copyright (c) 2005-2022 by Dominique Dumont.
226              
227             This is free software, licensed under:
228              
229             The GNU Lesser General Public License, Version 2.1, February 1999
230              
231             =cut