better usage of system tar, to be cleaned up
[deployable.git] / deployable
blob2a787c0b1d67f2837bd4820762628ba8367a41bc
1 #!/usr/bin/env perl
2 use strict;
3 use warnings;
4 use Carp;
5 use version; our $VERSION = qv('0.1.1');
6 use Fatal qw( close );
7 use Pod::Usage qw( pod2usage );
8 use Getopt::Long qw( :config gnu_getopt );
9 use English qw( -no_match_vars );
10 use File::Basename qw( basename dirname );
11 use File::Spec::Functions qw( file_name_is_absolute catfile );
12 use File::Temp qw( tempfile );
13 use POSIX qw( strftime );
14 use Cwd qw( cwd realpath );
15 use Archive::Tar;
16 use File::Find::Rule;
17 use Data::Dumper;
18 use Encode;
20 my %config = (
21 output => '-',
22 remote => catfile(dirname(realpath(__FILE__)), 'remote'),
23 tarfile => [],
24 heredir => [],
25 rootdir => [],
26 root => [],
27 deploy => [],
29 GetOptions(
30 \%config,
31 qw(
32 usage! help! man! version!
34 bundle|all-exec|X!
35 cleanup|c!
36 deploy|exec|d=s@
37 heredir|H=s@
38 include-archive-tar|T!
39 no-tar!
40 output|o=s
41 root|r=s@
42 rootdir|R=s@
43 tar|t=s
44 workdir|work-directory|deploy-directory|w=s
47 pod2usage(message => "$0 $VERSION", -verbose => 99, -sections => '')
48 if $config{version};
49 pod2usage(-verbose => 99, -sections => 'USAGE') if $config{usage};
50 pod2usage(-verbose => 99, -sections => 'USAGE|EXAMPLES|OPTIONS')
51 if $config{help};
52 pod2usage(-verbose => 2) if $config{man};
54 pod2usage(
55 message => 'working directory must be an absolute path',
56 -verbose => 99,
57 -sections => ''
58 ) if exists $config{workdir} && !file_name_is_absolute($config{workdir});
60 if ($config{'include-archive-tar'}) {
61 $config{remote} = catfile(dirname(realpath(__FILE__)), 'remote-at');
62 if (!-e $config{remote}) { # "make" it
63 print {*STDERR} "### Making remote-at...\n";
64 my $startdir = cwd();
65 chdir dirname realpath __FILE__;
66 system {'make'} qw( make remote-at );
67 chdir $startdir;
68 } ## end if (!-e $config{remote...
69 } ## end if ($config{'include-archive-tar'...
71 # Establish output channel
72 my $out_fh = \*STDOUT;
73 if ($config{output} ne '-') {
74 open my $fh, '>', $config{output} ## no critic
75 or croak "open('$config{output}'): $OS_ERROR";
76 $out_fh = $fh;
78 binmode $out_fh;
80 # Emit script code to be executed remotely. It is guaranteed to end
81 # with __END__, so that all what comes next is data
82 print {$out_fh} get_remote_script();
84 # If a tarfile was given, simply put it and exit
85 if (@{$config{tarfile}}) {
86 croak "UNSUPPORTED";
87 open my $fh, '<', $config{tarfile}
88 or croak "open('$config{tarfile}'): $OS_ERROR";
89 print {$out_fh} <$fh>;
90 close $fh;
91 close $out_fh;
92 exit 0;
93 } ## end if (@{$config{tarfile}...
95 # Where all the data will be kept
96 print_configuration($out_fh, \%config);
98 print_here_stuff($out_fh, \%config, @ARGV);
99 print_root_stuff($out_fh, \%config);
101 close $out_fh;
103 # Set as executable
104 if ($config{output} ne '-') {
105 chmod oct(755), $config{output}
106 or carp "chmod(0755, '$config{output}'): $OS_ERROR";
109 sub header {
110 my %params = @_;
111 my $namesize = length $params{name};
112 return "$namesize $params{size}\n$params{name}";
115 sub print_configuration { # FIXME
116 my ($fh, $config) = @_;
117 my %general_configuration;
118 for my $name (qw( workdir cleanup bundle deploy )) {
119 $general_configuration{$name} = $config->{$name}
120 if exists $config->{$name};
122 my $configuration = Dumper \%general_configuration;
123 print {$fh} header(name => 'config.pl', size => length($configuration)),
124 "\n", $configuration, "\n\n";
125 } ## end sub freeze_configuration
127 # Process files and directories. All these will be reported in the
128 # extraction directory, i.e. basename() will be applied to them. For
129 # directories, they will be re-created
130 sub print_here_stuff {
131 my $fh = shift;
132 my $config = shift;
133 my @ARGV = @_;
135 my $ai = Deployable::Tar->new($config);
136 $ai->add(
137 '.' => \@ARGV,
138 map { $_ => [ '.' ] } @{$config->{heredir}}
141 print {$fh} header(name => 'here.tar', size => $ai->size()), "\n";
142 $ai->copy_to($fh);
143 print {$fh} "\n\n";
145 return;
146 } ## end sub get_here_tar
148 sub print_root_stuff {
149 my ($fh, $config) = @_;
151 my $ai = Deployable::Tar->new($config);
152 $ai->add(
153 '.' => $config->{rootdir},
154 map { $_ => [ '.' ] } @{$config->{root}}
157 print {$fh} header(name => 'root.tar', size => $ai->size()), "\n";
158 $ai->copy_to($fh);
159 print {$fh} "\n\n";
161 return;
162 } ## end sub get_root_tar
164 sub get_remote_script {
165 open my $fh, '<', $config{remote}
166 or croak "open('$config{remote}'): $OS_ERROR";
167 my @lines;
168 while (<$fh>) {
169 last if /\A __END__ \s*\z/mxs;
170 push @lines, $_;
172 close $fh;
173 return join '', @lines, "__END__\n";
174 } ## end sub get_remote_script
176 package Deployable::Tar;
178 sub new {
179 my $package = shift;
180 my $self = { ref $_[0] ? %{$_[0]} : @_ };
181 $package = 'Deployable::Tar::Internal';
182 if (! $self->{'no-tar'}) {
183 if ((exists $self->{tar}) || (open my $fh, '-|', 'tar', '--help')) {
184 $package = 'Deployable::Tar::External';
185 $self->{tar} ||= 'tar';
188 bless $self, $package;
189 $self->initialise();
190 return $self;
194 package Deployable::Tar::External;
195 use File::Temp qw( :seekable );
196 use English qw( -no_match_vars );
197 use Cwd ();
198 use Carp;
199 our @ISA = qw( Deployable::Tar );
201 sub initialise {
202 my $self = shift;
203 $self->{_temp} = File::Temp->new();
204 $self->{_filename} = Cwd::abs_path($self->{_temp}->filename());
205 return $self;
208 sub add {
209 my $self = shift;
210 my $tar = $self->{tar};
211 while (@_) {
212 my ($directory, $stuff) = splice @_, 0, 2;
213 my @stuff = @$stuff;
214 while (@stuff) {
215 my @chunk = splice @stuff, 0, 50;
216 system {$tar} $tar, 'rvf', $self->{_filename},
217 '-C', $directory, '--', @chunk;
220 return $self;
223 sub size {
224 my ($self) = @_;
225 return (stat $self->{_temp})[7];
228 sub copy_to {
229 my ($self, $out_fh) = @_;
230 my $in_fh = $self->{_temp};
231 $in_fh->sysseek(0, SEEK_SET);
232 while ('true') {
233 my $nread = $in_fh->sysread(my $buffer, 4096);
234 croak "sysread(): $OS_ERROR" unless defined $nread;
235 last unless $nread;
236 print {$out_fh} $buffer;
238 return $self;
243 package Deployable::Tar::Internal;
244 use Archive::Tar ();
245 use Cwd ();
246 use File::Find::Rule ();
247 our @ISA = qw( Deployable::Tar );
249 sub initialise {
250 my $self = shift;
251 $self->{_tar} = Archive::Tar->new();
252 return $self;
255 sub add {
256 my $self = shift;
257 delete $self->{_string};
258 my $tar = $self->{_tar};
259 my $cwd = Cwd::getcwd();
260 while (@_) {
261 my ($directory, $stuff) = splice @_, 0, 2;
262 chdir $directory;
263 for my $item (@$stuff) {
264 $tar->add_files($_) for File::Find::Rule->in($item);
266 chdir $cwd;
268 return $self;
271 sub size {
272 my ($self) = @_;
273 $self->{_string} = $self->{_tar}->write() unless exists $self->{_string};
274 return length $self->{_string};
277 sub copy_to {
278 my ($self, $out_fh) = @_;
279 $self->{_string} = $self->{_tar}->write() unless exists $self->{_string};
280 print {$out_fh} $self->{_string};
283 __END__
285 =head1 NAME
287 deployable - create a deploy script for some files/scripts
289 =head1 VERSION
291 See version at beginning of script, variable $VERSION, or call
293 shell$ deployable --version
295 =head1 USAGE
297 deployable [--usage] [--help] [--man] [--version]
299 deployable [--bundle|--all-exec|-X] [--cleanup|-c]
300 [--deploy|--exec|d <program>] [--heredir|-H <dirname>]
301 [--include-archive-tar|-T] [--output|-o <filename>]
302 [--root|-r <dirname>] [--rootdir|-R <dirname>]
303 [--tarfile|--tar|-t <filename>]
304 [--workdir|-w <path>] [ files or directories... ]
306 =head1 EXAMPLES
308 # pack some files and a deploy script together.
309 shell$ deployable script.sh file.txt some/directory -d script.sh
311 # Use a directory's contents as elements for the target root
312 shell$ ls -1 /path/to/target/root
317 # The above will be deployed as /etc, /opt, /usr and /var
318 shell$ deployable -o dep.pl --root /path/to/target/root
320 # Include directory /path/to/etc for inclusion and extraction
321 # directly as /etc
322 shell$ deployable -o dep.pl --rootdir /path/to/etc
324 =head1 DESCRIPTION
326 This is a meta-script to create deploy scripts. The latter ones are
327 suitable to be distributed in order to deploy something.
329 You basically have to provide two things: files to install and programs
330 to be executed. Files can be put directly into the deployed script, or
331 can be included in gzipped tar archives.
333 When called, this script creates a deploy script for you. This script
334 includes all the specified files, and when executed it will extract
335 those files and execute the given programs. In this way, you can ship
336 both files and logic needed to correctly install those files, but this
337 is of course of of scope.
339 All files and archives will be extracted under a configured path
340 (see L<--workdir> below), which we'll call I<workdir> from now on. Under
341 the I<workdir> a temporary directory will be created, and the files
342 will be put in the temporary directory. You can specify if you want to
343 clean up this temporary directory or keep it, at your choice. (You're able
344 to both set a default for this cleanup when invoking deployable, or when
345 invoking the deploy script itself). The temporary directory will be
346 called I<tmpdir> in the following.
348 There are several ways to embed files to be shipped:
350 =over
352 =item *
354 pass the name of an already-prepared tar file via L</--tarfile>. This is
355 by far the most flexible of the options, but it requires more work on
356 your side. If you pass this option, all other input files/directories will
357 be ignored;
359 =item *
361 specify the file name directly on the command line. A file given in this
362 way will always be extracted into the I<tmpdir>, whatever its initial path
363 was;
365 =item *
367 specify the name of a directory on the command line. In this case,
368 C<tar> will be used to archive the directory, with the usual option to
369 turn absolute paths into relative ones; this means that directories will
370 be re-created under I<tmpdir> when extraction is performed;
372 =item *
374 give the name of a directory to be used as a "here directory", using
375 the C<--heredir|-H> option. This is much the same as giving the directory
376 name (see above), but in this case C<tar> will be told to change into the
377 directory first, and archive '.'. This means that the contents of the
378 "here-directory" will be extracted directly into I<tmpdir>.
380 =back
382 =head2 Extended Example
384 Suppose you have a few server which have the same configuration, apart
385 from some specific stuff (e.g. the hostname, the IP addresses, etc.).
386 You'd like to perform changes to all with the minimum work possible...
387 so you know you should script something.
389 For example, suppose you want to update a few files in /etc, setting these
390 files equal for all hosts. You would typically do the following:
392 # In your computer
393 shell$ mkdir -p /tmp/newfiles/etc
394 shell$ cd /tmp/newfiles/etc
395 # Craft the new files
396 shell$ cd ..
397 shell$ tar cvzf newetc.tar.gz etc
399 # Now, for each server:
400 shell$ scp newetc.tar.gz $server:/tmp
401 shell$ ssh $server tar xvzf /tmp/newetc.tar.gz -C /
404 So far, so good. But what if you need to kick in a little more logic?
405 For example, if you update some configuration files, you'll most likey
406 want to restart some services. So you could do the following:
408 shell$ mkdir -p /tmp/newfiles/tmp
409 shell$ cd /tmp/newfiles/tmp
410 # craft a shell script to be executed remotely and set the exec bit
411 # Suppose it's called deploy.sh
412 shell$ cd ..
413 shell$ tar cvzf newetc.tar.gz etc tmp
415 # Now, for each server:
416 shell$ scp newetc.tar.gz $server:/tmp
417 shell$ ssh $server tar xvzf /tmp/newetc.tar.gz -C /
418 shell$ ssh $server /tmp/deploy.sh
420 And what if you want to install files depending on the particular machine?
421 Or you have a bundle of stuff to deploy and a bunch of scripts to execute?
422 You can use deployable. In this case, you can do the following:
424 shell$ mkdir -p /tmp/newfiles/etc
425 shell$ cd /tmp/newfiles/etc
426 # Craft the new files
427 shell$ cd ..
428 # craft a shell script to be executed remotely and set the exec bit
429 # Suppose it's called deploy.sh
430 shell$ deployable -o deploy.pl etc deploy.sh --exec deploy.sh
432 # Now, for each server
433 shell$ scp deploy.pl $server:/tmp
434 shell$ ssh $server /tmp/deploy.pl
436 And you're done. This can be particularly useful if you have another
437 layer of deployment, e.g. if you have to run a script to decide which
438 of a group of archives should be deployed. For example, you could craft
439 a different new "etc" for each server (which is particularly true if
440 network configurations are in the package), and produce a simple script
441 to choose which file to use based on the MAC address of the machine. In
442 this case you could have:
444 =over
446 =item newetc.*.tar.gz
448 a bunch of tar files with the configurations for each different server
450 =item newetc.list
452 a list file with the association between the MAC addresses and the
453 real tar file to deploy from the bunch in the previous bullet
455 =item deploy-the-right-stuff.sh
457 a script to get the real MAC address of the machine, select the right
458 tar file and do the deployment.
460 =back
462 So, you can do the following:
464 shell$ deployable -o deploy.pl newetc.*.tar.gz newetc.list \
465 deploy-the-right-stuff.sh --exec deploy-the-right-stuff.sh
467 # Now, for each server:
468 shell$ scp deploy.pl $server:/tmp
469 shell$ ssh $server /tmp/deploy.pl
471 So, once you have the deploy script on the target machine all you need
472 to do is to execute it. This can come handy when you cannot access the
473 machines from the network, but you have to go there physically: you
474 can prepare all in advance, and just call the deploy script.
477 =head1 OPTIONS
479 Meta-options:
481 =over
483 =item B<--help>
485 print a somewhat more verbose help, showing usage, this description of
486 the options and some examples from the synopsis.
488 =item B<--man>
490 print out the full documentation for the script.
492 =item B<--usage>
494 print a concise usage line and exit.
496 =item B<--version>
498 print the version of the script.
500 =back
502 Real-world options:
504 =over
506 =item B<< --bundle | --all-exec | -X >>
508 Set bundle flag in the produced script. If the bundle flag is set, the
509 I<deploy script> will treat all executables in the main deployment
510 directory as scripts to be executed.
512 By default the flag is not set.
514 =item B<< --cleanup | -c >>
516 Set cleanup flag in the produced script. If the cleanup flag is set, the
517 I<deploy script> will clean up after having performed all operations.
519 You can set this flag to C<0> by using C<--no-cleanup>.
521 =item B<< --deploy | --exec | -d <filename> >>
523 Set the name of a program to execute after extraction. You can provide
524 multiple program names, they will be executed in the same order.
526 =item B<< --heredir | -H <path> >>
528 Set the name of a "here directory" (see L<DESCRIPTION>). You can use this
529 option multiple times to provide multiple directories.
531 =item B<< --include-archive-tar | -T >>
533 Embed L<Archive::Tar> (with its dependencies L<Archive::Tar::Constant> and
534 L<Archive::Tar::File>) inside the final script. Use this when you know (or
535 aren't sure) that L<Archive::Tar> will not be available in the target
536 machine.
538 =item B<< --no-tar >>
540 Don't use system C<tar>.
542 =item B<< --output | -o <filename> >>
544 Set the output file name. By default the I<deploy script> will be given
545 out on the standard output; if you provide a filename (different from
546 C<->, of course!) the script will be saved there and the permissions will
547 be set to 0755.
549 =item B<< --root | -r <dirname> >>
551 Include C<dirname> contents for deployment under root directory. The
552 actual production procedure is: hop into C<dirname> and grab a tarball
553 of C<.>. During deployment, hop into C</> and extract the tarball.
555 This is useful if you're already building up the absolute deployment
556 layout under a given directory: just treat that directory as if it were
557 the root of the target system.
559 =item B<< --rootdir | -R <dirname >>
561 Include C<dirname> as a directory that will be extracted under root
562 directory. The actual production procedure is: grab a tarball of
563 C<dirname>. During deployment, hop into C</> and extract the tarball.
565 This is useful if you have a directory (or a group of directories) that
566 you want to deploy directly under the root.
568 =item B<< --tar | -t <program-path> >>
570 Set the system C<tar> program to use.
572 =item B<< --workdir | --deploy-directory | -w <path> >>
574 Set the working directory for the deploy.
576 =back
578 =head1 THE DEPLOY SCRIPT
580 The net result of calling this script is to produce another script,
581 that we call the I<deploy script>. This script is made of two parts: the
582 code, which is fixed, and the configurations/files, which is what is
583 actually produced. The latter part is put after the C<__END__> marker,
584 as usual.
586 Stuff in the configuration part is always hexified in order to prevent
587 strange tricks or errors. Comments will help you devise what's inside the
588 configurations themselves.
590 The I<deploy script> has options itself, even if they are quite minimal.
591 In particular, it supports the same options C<--workdir|-w> and
592 C<--cleanup> described above, allowing the final user to override the
593 configured values. By default, the I<workdir> is set to C</tmp/our-deploy>
594 and the script will clean up after itself.
596 The following options are supported in the I<deploy script>:
598 =over
600 =item B<--usage | --man | --help>
602 print a minimal help and exit
604 =item B<--version>
606 print script version and exit
608 =item B<--bundle | --all-exec | -X>
610 treat all executables in the main deployment directory as scripts
611 to be executed
613 =item B<--cleanup | --no-cleanup>
615 perform / don't perform temporary directory cleanup after work done
617 =item B<< --deploy | --no-deploy >>
619 deploy scripts are executed by default (same as specifying '--deploy')
620 but you can prevent it.
622 =item B<--dryrun | --dry-run>
624 print final options and exit
626 =item B<< --filelist | --list | -l >>
628 print a list of files that are shipped in the deploy script
630 =item B<< --heretar | --here-tar | -H >>
632 print out the tar file that contains all the files that would be
633 extracted in the temporary directory, useful to redirect to file or
634 pipe to the tar program
636 =item B<< --inspect <dirname> >>
638 just extract all the stuff into <dirname> for inspection. Implies
639 C<--no-deploy>, C<--no-tempdir>, ignores C<--bundle> (as a consequence of
640 C<--no-deploy>), disables C<--cleanup> and sets the working directory
641 to C<dirname>
643 =item B<< --no-tar >>
645 don't use system C<tar>
647 =item B<< --rootar | --root-tar | -R >>
649 print out the tar file that contains all the files that would be
650 extracted in the root directory, useful to redirect to file or
651 pipe to the tar program
653 =item B<--show | --show-options | -s>
655 print configured options and exit
657 =item B<< --tar | -t <program-path> >>
659 set the system C<tar> program to use.
661 =item B<< --tempdir | --no-tempdir >>
663 by default a temporary directory is created (same as specifying
664 C<--tempdir>), but you can execute directly in the workdir (see below)
665 without creating it.
667 =item B<--workdir | --work-directory | --deploy-directory | -w>
669 working base directory (a temporary subdirectory will be created
670 there anyway)
672 =back
674 Note the difference between C<--show> and C<--dryrun>: the former will
675 give you the options that are "embedded" in the I<deploy script> without
676 taking into account other options given on the command line, while the
677 latter will give you the final options that would be used if the script
678 were called without C<--dryrun>.
680 =head2 Deploy Script Example Usage
682 In the following, we'll assume that the I<deploy script> is called
683 C<deploy.pl>.
685 To execute the script with the already configured options, you just have
686 to call it:
688 shell$ ./deploy.pl
690 If you just want to see which configurations are in the I<deploy script>:
692 shell$ ./deploy.pl --show
694 To see which files are included, you have two options. One is asking the
695 script:
697 shell$ ./deploy.pl --filelist
699 the other is piping to tar:
701 shell$ ./deploy.pl --tar | tar tvf -
703 Extract contents of the script in a temp directory and simply inspect
704 what's inside:
706 # extract stuff into subdirectory 'inspect' for... inspection
707 shell$ ./deploy.pl --no-tempdir --no-deploy --workdir inspect
709 =head2 Deploy Script Requirements
711 You'll need a working Perl with version at least 5.6.2.
713 If you specify L</--include-archive-tar>, the module L<Archive::Tar> will
714 be included as well. This should ease your life and avoid you to have
715 B<tar> on the target machine. On the other hand, if you already know
716 that B<tar> will be available, you can avoid including C<Archive::Tar>
717 and have the generated script use it (it could be rather slower anyway).
719 =head1 DIAGNOSTICS
721 Each error message should be enough explicit to be understood without the
722 need for furter explainations. Which is another way to say that I'm way
723 too lazy to list all possible ways that this script has to fail.
726 =head1 CONFIGURATION AND ENVIRONMENT
728 deployable requires no configuration files or environment variables.
730 Please note that deployable B<needs> to find its master B<remote> file
731 to produce the final script. This must be put in the same directory where
732 deployable is put. You should be able to B<symlink> deployable where you
733 think it's better, anyway - it will go search for the original file
734 and look for B<remote> inside the same directory. This does not apply to
735 hard links, of course.
738 =head1 DEPENDENCIES
740 All core modules, apart the following:
742 =over
744 =item B<< Archive::Tar >>
746 =item B<< File::Find::Rule >>
748 =back
750 =head1 BUGS AND LIMITATIONS
752 No bugs have been reported.
754 Please report any bugs or feature requests to the AUTHOR below.
756 Be sure to read L<CONFIGURATION AND ENVIRONMENT> for a slight limitation
757 about the availability of the B<remote> script.
759 =head1 AUTHOR
761 Flavio Poletti C<flavio [AT] polettix.it>
764 =head1 LICENSE AND COPYRIGHT
766 Copyright (c) 2008, Flavio Poletti C<flavio [AT] polettix.it>. All rights reserved.
768 This script is free software; you can redistribute it and/or
769 modify it under the same terms as Perl itself. See L<perlartistic>
770 and L<perlgpl>.
772 Questo script è software libero: potete ridistribuirlo e/o
773 modificarlo negli stessi termini di Perl stesso. Vedete anche
774 L<perlartistic> e L<perlgpl>.
777 =head1 DISCLAIMER OF WARRANTY
779 BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
780 FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
781 OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
782 PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
783 EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
784 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
785 ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH
786 YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
787 NECESSARY SERVICING, REPAIR, OR CORRECTION.
789 IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
790 WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
791 REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE
792 LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL,
793 OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE
794 THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
795 RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
796 FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
797 SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
798 SUCH DAMAGES.
800 =head1 NEGAZIONE DELLA GARANZIA
802 Poiché questo software viene dato con una licenza gratuita, non
803 c'è alcuna garanzia associata ad esso, ai fini e per quanto permesso
804 dalle leggi applicabili. A meno di quanto possa essere specificato
805 altrove, il proprietario e detentore del copyright fornisce questo
806 software "così com'è" senza garanzia di alcun tipo, sia essa espressa
807 o implicita, includendo fra l'altro (senza però limitarsi a questo)
808 eventuali garanzie implicite di commerciabilità e adeguatezza per
809 uno scopo particolare. L'intero rischio riguardo alla qualità ed
810 alle prestazioni di questo software rimane a voi. Se il software
811 dovesse dimostrarsi difettoso, vi assumete tutte le responsabilità
812 ed i costi per tutti i necessari servizi, riparazioni o correzioni.
814 In nessun caso, a meno che ciò non sia richiesto dalle leggi vigenti
815 o sia regolato da un accordo scritto, alcuno dei detentori del diritto
816 di copyright, o qualunque altra parte che possa modificare, o redistribuire
817 questo software così come consentito dalla licenza di cui sopra, potrà
818 essere considerato responsabile nei vostri confronti per danni, ivi
819 inclusi danni generali, speciali, incidentali o conseguenziali, derivanti
820 dall'utilizzo o dall'incapacità di utilizzo di questo software. Ciò
821 include, a puro titolo di esempio e senza limitarsi ad essi, la perdita
822 di dati, l'alterazione involontaria o indesiderata di dati, le perdite
823 sostenute da voi o da terze parti o un fallimento del software ad
824 operare con un qualsivoglia altro software. Tale negazione di garanzia
825 rimane in essere anche se i dententori del copyright, o qualsiasi altra
826 parte, è stata avvisata della possibilità di tali danneggiamenti.
828 Se decidete di utilizzare questo software, lo fate a vostro rischio
829 e pericolo. Se pensate che i termini di questa negazione di garanzia
830 non si confacciano alle vostre esigenze, o al vostro modo di
831 considerare un software, o ancora al modo in cui avete sempre trattato
832 software di terze parti, non usatelo. Se lo usate, accettate espressamente
833 questa negazione di garanzia e la piena responsabilità per qualsiasi
834 tipo di danno, di qualsiasi natura, possa derivarne.
836 =cut