6 # The contents of this file are subject to the terms of the
7 # Common Development and Distribution License (the "License").
8 # You may not use this file except in compliance with the License.
10 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
11 # or http://www.opensolaris.org/os/licensing.
12 # See the License for the specific language governing permissions
13 # and limitations under the License.
15 # When distributing Covered Code, include this CDDL HEADER in each
16 # file and include the License file at usr/src/OPENSOLARIS.LICENSE.
17 # If applicable, add the following below this CDDL HEADER, with the
18 # fields enclosed by brackets "[]" replaced with your own identifying
19 # information: Portions Copyright [yyyy] [name of copyright owner]
25 # Copyright 2008 Sun Microsystems, Inc. All rights reserved.
26 # Use is subject to license terms.
49 $self->{FILE
} = undef;
50 $self->{MAJOR
} = undef;
51 $self->{MINOR
} = undef;
52 $self->{NODE_SEC_SZ
} = undef;
53 $self->{NAME_SEC_SZ
} = undef;
54 $self->{DATA_SEC_SZ
} = undef;
55 $self->{NODES
} = undef;
56 $self->{NAMES
} = undef;
57 $self->{DATA
} = undef;
67 $self->{NAME
} = shift;
69 $self->{NAME
} = '/dev/mdesc';
71 return unless open(MD
, "$self->{NAME}");
73 # Read and parse MD header
74 unless (read(MD
, $mdhdr, 16) == 16) {
79 ($self->{MAJOR
}, $self->{MINOR
},
82 $self->{DATA_SEC_SZ
}) = unpack("nnNNN", $mdhdr);
84 $size = read(MD
, $self->{NODES
}, $self->{NODE_SEC_SZ
});
85 $size = read(MD
, $self->{NAMES
}, $self->{NAME_SEC_SZ
});
86 $size = read(MD
, $self->{DATA
}, $self->{DATA_SEC_SZ
});
92 # return hash of given node's information
95 my ($self, $nodeid) = @_;
96 my ($tag, $name, $namelen, $nameoff, $datalen, $dataoff, %node);
98 ($tag, $namelen, $nameoff, $datalen, $dataoff) =
99 unpack("CCx2NNN", substr($self->{NODES
}, $nodeid * 16, 16));
100 $name = substr($self->{NAMES
}, $nameoff, $namelen);
101 %node = (tag
=> $tag, name
=> $name, nameid
=> $nameoff);
103 if ($tag == MDSTR
|| $tag == MDDATA
) {
104 $node{'datalen'} = $datalen;
105 $node{'dataoff'} = $dataoff;
106 } elsif ($tag == MDVAL
) {
107 $node{'val'} = ($datalen << 32) | $dataoff;
108 } elsif ($tag == MDARC
|| $tag == MDNODE
) {
109 $node{'idx'} = ($datalen << 32) | $dataoff;
117 # return hash of given property's information
120 my ($self, $propid) = @_;
121 my (%node, $tag, %prop);
123 %node = $self->getnode($propid);
125 %prop = (name
=> $node{'name'}, tag
=> $tag);
129 substr($self->{DATA
}, $node{'dataoff'}, $node{'datalen'} - 1);
130 } elsif ($tag == MDARC
) {
131 $prop{'arc'} = $node{'idx'};
132 } elsif ($tag == MDVAL
) {
133 $prop{'val'} = $node{'val'};
134 } elsif ($tag == MDDATA
) {
135 $prop{'length'} = $node{'datalen'};
136 $prop{'offset'} = $node{'dataoff'};
146 # find name table index of given name
149 my ($self, $name) = @_;
150 my ($idx, $next, $p);
152 for ($idx = 0; $idx < $self->{NAME_SEC_SZ
}; $idx = $next + 1) {
153 $next = index($self->{NAMES
}, "\0", $idx);
154 $p = substr($self->{NAMES
}, $idx, $next - $idx);
155 return $idx if ($p eq $name);
163 # find given property in node
166 my ($self, $nodeid, $propname, $type) = @_;
169 %node = $self->getnode($nodeid);
170 return -1 if ($node{'tag'} != MDNODE
);
172 $nameid = $self->findname($propname);
173 return -1 if ($nameid == -1);
177 %node = $self->getnode($nodeid);
178 if ($node{'tag'} == $type && $node{'nameid'} == $nameid) {
181 } while ($node{'tag'} != MDEND
);
188 # lookup property in node and return its hash
191 my ($self, $nodeid, $propname, $type) = @_;
194 $propid = $self->findprop($nodeid, $propname, $type);
195 return undef if ($propid == -1);
197 return $self->getprop($propid);
202 my ($self, $nodeid, $nameid, $arcid, $ret, $seen) = @_;
205 return if ($seen->[$nodeid] == 1);
206 $seen->[$nodeid] = 1;
208 %node = $self->getnode($nodeid);
209 return if ($node{'tag'} != MDNODE
);
210 push(@
$ret, $nodeid) if ($node{'nameid'} == $nameid);
214 %node = $self->getnode($nodeid);
215 if ($node{'tag'} == MDARC
&& $node{'nameid'} == $arcid) {
216 $self->scan_node($node{'idx'}, $nameid, $arcid, $ret, $seen);
218 } while ($node{'tag'} != MDEND
);
223 # scan dag from 'start' via 'arcname'
224 # return list of nodes named 'nodename'
227 my ($self, $start, $nodename, $arcname) = @_;
228 my ($nameid, $arcid, @ret, @seen);
230 $nameid = $self->findname($nodename);
231 $arcid = $self->findname($arcname);
232 $self->scan_node($start, $nameid, $arcid, \
@ret, \
@seen);
242 # 'find' needs to use globals anyway,
243 # so we might as well use the same ones
255 my ($oldpat, $newpat);
258 $oldpat = '"' . $old . '/';
259 $newpat = '"' . $new . '/';
261 $in = "etc/path_to_inst";
262 $out = "/tmp/path$$";
264 open(IN
, "<", $in) or die "can't open $in\n";
265 open(OUT
, ">", $out) or die "can't open $out\n";
270 # see if there are any old paths that need to be re-written
274 ($path, undef, undef) = split;
275 if ($path =~ /^$oldpat/) {
280 # return if no old paths found
288 print "replacing $old with $new in /etc/path_to_inst\n";
291 # substitute new for old
295 ($path, undef, undef) = split;
296 if ($path =~ /^$oldpat/) {
305 print "path_to_inst changes:\n";
306 system("/usr/bin/diff", $in, $out);
310 move
$out, $in or die "can't modify $in\n";
323 if ($targ =~ /$oldpat/) {
324 $targ =~ s/$old/$new/;
327 print "symlink $_ changed to $targ\n" if ($opts{v
});
336 $oldpat = "/devices" . $old;
338 print "updating /dev symlinks\n";
339 find \
&wanted
, "dev";
344 # fixup path_to_inst and /dev symlinks
350 # if fixinst finds no matches, no need to run fixdev
351 return if (fixinst
== 0);
353 print "\n" if ($opts{v
});
360 unlink "etc/devices/devid_cache";
361 unlink "etc/devices/devname_cache";
362 unlink <etc
/devices/mdi_
*_cache
>;
363 unlink "etc/devices/retire_store";
364 unlink "etc/devices/snapshot_cache";
365 unlink "dev/.devlink_db";
369 # $< == 0 or die "$0: must be run as root\n";
371 getopts
("vR:", \
%opts);
374 chdir $opts{R
} or die "can't chdir to $opts{R}\n";
376 cwd
() ne "/" or die "can't run on root directory\n";
380 # manual run (no MD needed)
388 my ($md, @nodes, $nodeid, @aliases, $alias);
389 my (%newpath, %roots);
392 # scan MD for ioaliases
397 @nodes = $md->scan(0, "ioaliases", "fwd");
398 $#nodes == 0 or die "missing ioaliases node\n";
401 # foreach ioalias node, replace any 'alias' paths
402 # with the 'current' one
404 # complicating this is that the alias paths can be
405 # substrings of each other, which can cause false
406 # hits in /etc/path_to_inst, so first gather all
407 # aliases with the same root into a list, then sort
408 # it by length so we always fix the longer alias
409 # paths before the shorter ones
411 @nodes = $md->scan(@nodes[0], "ioalias", "fwd");
412 foreach $nodeid (@nodes) {
413 my (%prop, $current);
415 %prop = $md->lookup($nodeid, "aliases", $md->MDSTR);
416 @aliases = split(/ /, $prop{'string'});
418 %prop = $md->lookup($nodeid, "current", $md->MDSTR);
419 $current = $prop{'string'};
421 foreach $alias (@aliases) {
422 next if ($alias eq $current);
425 $newpath{$alias} = $current;
426 $slash = index($alias, '/', 1);
430 $root = substr($alias, 0, $slash);
432 push(@
{ $roots{$root} }, $alias);
437 foreach $aref (values %roots) {
438 @aliases = sort { length($b) <=> length($a) } @
$aref;
439 foreach $alias (@aliases) {
440 fixup
$alias, $newpath{$alias};