2 use Cwd
qw(abs_path getcwd);
3 use Getopt
::Long
qw(:config bundling);
7 use File
::Spec
::Functions
qw(tmpdir);
8 use File
::Temp
qw(tempfile tempdir);
9 use Fatal
qw(:void copy rename move chdir mkdir unlink rmtree);
16 use Verbose
qw(:2 copy rename move utime chdir mkdir mkpath unlink rmtree tempfile tempdir);
18 our @ISA = qw(Exporter);
20 Verbose GetOptions pod2usage shellwords
21 $datadir $libexecdir @common_options $help
22 child_error runval runval_raw runstr runstr_err runval_in runval_infile unpack_update
23 get_stage set_stage set_debug_level get_abort_cause get_patch update_loaded
24 get_debug_output get_conflicts
25 abs_path getcwd basename dirname tmpdir
26 copy rename move utime chdir mkdir mkpath unlink rmtree tempfile tempdir
29 our ($datadir, $libexecdir) = qw(KSPLICE_DATA_DIR KSPLICE_LIBEXEC_DIR);
32 our @common_options = (
34 "version" => sub { print "Ksplice version PACKAGE_VERSION\n"; exit(0); },
35 "verbose|v:+" => \
$Verbose::level
,
36 "quiet|q:+" => sub { $Verbose::level
-= $_[1]; },
41 print STDERR
"Failed to exec child\n";
42 } elsif(($?
& 127) != 0) {
43 print STDERR
"Child exited with signal ", ($?
& 127), ($?
& 128) ?
" (core dumped)\n" : "\n";
44 } elsif($?
>> 8 != 0) {
45 print STDERR
"Child exited with status ", $?
>> 8, "\n";
54 if(runval_raw
(@cmd) != 0) {
56 die "Failed during: @cmd\n";
63 print "+ @cmd\n" if($Verbose::level
>= 1);
69 print "+ @cmd\n" if($Verbose::level
>= 1);
71 open PIPE
, '-|', @cmd or die "Can't run @cmd: $!";
73 close PIPE
or $! == 0 or die "Can't run @cmd: $!";
79 print "+ @cmd\n" if($Verbose::level
>= 1);
81 my $pid = open3
(fileno STDIN
, '>&STDOUT', \
*ERROR
, @cmd);
91 print "+ @cmd <<'EOF'\n${in}EOF\n" if($Verbose::level >= 1);
93 open(WRITE, '|-', @cmd) or die "Can
't run @cmd: $!";
95 close(WRITE) or $! == 0 or die "Can't run
@cmd: $!";
97 die "Failed during
: @cmd";
102 my ($infile, @cmd) = @_;
103 print "+ @cmd < $infile\n" if($Verbose::level >= 1);
105 open(INFILE, '<', $infile) or die "Can
't open $infile: $!";
106 my $pid = open2('>&STDOUT
', '<&INFILE
', @cmd) or die "Can't run
@cmd: $!";
109 die "Failed during
: @cmd";
115 runval("tar
", "zxf
", $file);
116 my ($ksplice) = glob('*/');
117 chop($ksplice); # remove the trailing slash
123 if(! -d "/sys/module
") {
124 die "/sys
not mounted?
\n";
126 my $update = "ksplice_
$kid";
127 if (-d "/sys/kernel
/ksplice/$kid") {
128 return "/sys/kernel
/ksplice/$kid";
130 if (-d "/sys/module
/$update/ksplice
") {
131 return "/sys/module
/$update/ksplice
";
138 return defined(get_sysfs($kid));
144 open(INPUT, "<", $file) or die $!;
149 my ($file, $string) = @_;
151 open(INPUT, ">", $file) or die $!;
156 my ($kid, $attr) = @_;
157 my $sysfs = get_sysfs($kid);
158 return undef if (!defined($sysfs));
159 return read_file("$sysfs/$attr");
163 my ($kid, $attr, $string) = @_;
164 my $sysfs = get_sysfs($kid);
165 return undef if (!defined($sysfs));
166 write_file("$sysfs/$attr", $string);
169 sub get_debug_output {
171 my $update = "ksplice_
$kid";
172 my (undef, $debugfs_out) = tempfile('ksplice-debug-XXXXXX', DIR => tmpdir());
173 my $debugfsdir = tempdir('ksplice-debugfs-XXXXXX',
174 TMPDIR => 1, CLEANUP => 1);
175 if (runval_raw("grep", "-qFx
", "nodev
\tdebugfs
", "/proc/filesystems
") == 0) {
176 runval(qw(mount -t debugfs debugfs), $debugfsdir);
177 copy
("$debugfsdir/$update", "$debugfs_out");
178 my $debug = read_file
("$debugfsdir/$update");
179 runval
(qw(umount), $debugfsdir);
180 return ($debugfs_out, $debug);
181 } elsif ($?
>> 8 == 1) {
191 chomp(my $result = read_sysfs
($kid, "stage"));
195 sub get_abort_cause
{
197 chomp(my $result = read_sysfs
($kid, "abort_cause"));
203 chomp(my $conflicts = read_sysfs
($kid, "conflicts"));
204 my @conflicts = split('\n', $conflicts);
206 foreach my $conflict (@conflicts) {
207 my ($name, $pid, @symbols) = split(' ', $conflict);
209 $out .= "Process $name(pid $pid) is using the following symbols changed by update $kid:\n";
210 foreach my $symbol (@symbols) {
211 $out .= " $symbol\n";
219 my $result = read_file
("/var/run/ksplice/updates/$kid/patch");
224 my ($kid, $string) = @_;
225 write_sysfs
($kid, "stage", "$string\n");
228 sub set_debug_level
{
229 my ($kid, $string) = @_;
230 write_sysfs
($kid, "debug", "$string\n");