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