… | |
… | |
24 | our $VERSION = '1.3'; |
24 | our $VERSION = '1.3'; |
25 | our $JSON_VERSION = 3; # the version of the json objects generated by this program |
25 | our $JSON_VERSION = 3; # the version of the json objects generated by this program |
26 | |
26 | |
27 | our $CHANGELOG = <<EOF; |
27 | our $CHANGELOG = <<EOF; |
28 | |
28 | |
|
|
29 | 1.4 Thu Aug 22 10:48:22 CEST 2019 |
|
|
30 | - new "create" subcommand. |
|
|
31 | - "create" and "edit" try to save and restore ownership/permissions |
|
|
32 | of bcd hives when writing the new file. |
29 | - editorial fixes to the documentation. |
33 | - editorial fixes to the documentation. |
30 | |
34 | |
31 | 1.3 Sat Aug 17 07:04:15 CEST 2019 |
35 | 1.3 Sat Aug 17 07:04:15 CEST 2019 |
32 | - output of pbcdedit elements --json has changed, as it didn't |
36 | - output of pbcdedit elements --json has changed, as it didn't |
33 | take the reorganisation by classes fully into account. |
37 | take the reorganisation by classes fully into account. |
… | |
… | |
154 | |
158 | |
155 | =item C<parse> F<path> I<instructions...> |
159 | =item C<parse> F<path> I<instructions...> |
156 | |
160 | |
157 | Same as C<edit>, above, except it doesn't save the data store again. Can |
161 | Same as C<edit>, above, except it doesn't save the data store again. Can |
158 | be useful to extract some data from it. |
162 | be useful to extract some data from it. |
|
|
163 | |
|
|
164 | =item C<create> F<path> I<instructions...> |
|
|
165 | |
|
|
166 | Same as C<edit>, above, except it creates a new data store from scratch if |
|
|
167 | needed. An existing store will be emptied completely. |
159 | |
168 | |
160 | =item C<lsblk> [C<--json>] |
169 | =item C<lsblk> [C<--json>] |
161 | |
170 | |
162 | On a GNU/Linux system, you can get a list of partition device descriptors |
171 | On a GNU/Linux system, you can get a list of partition device descriptors |
163 | using this command - the external C<lsblk> command is required, as well as |
172 | using this command - the external C<lsblk> command is required, as well as |
… | |
… | |
907 | sub xxd($$) { |
916 | sub xxd($$) { |
908 | open my $xxd, "| xxd | sed -e 's/^/\Q$_[0]\E: /'"; |
917 | open my $xxd, "| xxd | sed -e 's/^/\Q$_[0]\E: /'"; |
909 | syswrite $xxd, $_[1]; |
918 | syswrite $xxd, $_[1]; |
910 | } |
919 | } |
911 | |
920 | |
|
|
921 | # get some meta info on a file (uid, gid, perms) |
|
|
922 | sub stat_get($) { |
|
|
923 | [(stat shift)[4, 5, 2]] |
|
|
924 | } |
|
|
925 | |
|
|
926 | # set stat info on a file |
|
|
927 | sub stat_set($$) { |
|
|
928 | my ($fh_or_path, $stat) = @_; |
|
|
929 | |
|
|
930 | return unless $stat; |
|
|
931 | chown $stat->[0], $stat->[1], $fh_or_path; |
|
|
932 | chmod +($stat->[2] & 07777), $fh_or_path; |
|
|
933 | } |
|
|
934 | |
912 | sub file_load($) { |
935 | sub file_load($) { |
913 | my ($path) = @_; |
936 | my ($path) = @_; |
914 | |
937 | |
915 | open my $fh, "<:raw", $path |
938 | open my $fh, "<:raw", $path |
916 | or die "$path: $!\n"; |
939 | or die "$path: $!\n"; |
917 | my $size = -s $fh; |
940 | my $size = -s $fh; |
918 | $size = read $fh, my $buf, $size |
941 | $size = read $fh, my $buf, $size |
919 | or die "$path: short read\n"; |
942 | or die "$path: short read\n"; |
920 | |
943 | |
921 | $buf |
944 | $buf |
|
|
945 | } |
|
|
946 | |
|
|
947 | sub file_save($$;$) { |
|
|
948 | my ($path, $data, $stat) = @_; |
|
|
949 | |
|
|
950 | open my $fh, ">:raw", "$path~" |
|
|
951 | or die "$path~: $!\n"; |
|
|
952 | print $fh $data |
|
|
953 | or die "$path~: short write\n"; |
|
|
954 | stat_set $fh, $stat; |
|
|
955 | $fh->sync; |
|
|
956 | close $fh; |
|
|
957 | |
|
|
958 | rename "$path~", $path; |
922 | } |
959 | } |
923 | |
960 | |
924 | # sources and resources used for writing pbcdedit |
961 | # sources and resources used for writing pbcdedit |
925 | # |
962 | # |
926 | # registry: |
963 | # registry: |
… | |
… | |
1283 | |
1320 | |
1284 | regf_decode file_load $path |
1321 | regf_decode file_load $path |
1285 | } |
1322 | } |
1286 | |
1323 | |
1287 | # encode and save registry to file |
1324 | # encode and save registry to file |
1288 | sub regf_save { |
1325 | sub regf_save($$;$) { |
1289 | my ($path, $hive) = @_; |
1326 | my ($path, $hive, $stat) = @_; |
1290 | |
1327 | |
1291 | $hive = regf_encode $hive; |
1328 | $hive = regf_encode $hive; |
1292 | |
1329 | |
1293 | open my $regf, ">:raw", "$path~" |
1330 | file_save $path, $hive, $stat; |
1294 | or die "$path~: $!\n"; |
|
|
1295 | print $regf $hive |
|
|
1296 | or die "$path~: short write\n"; |
|
|
1297 | $regf->sync; |
|
|
1298 | close $regf; |
|
|
1299 | |
|
|
1300 | rename "$path~", $path; |
|
|
1301 | } |
1331 | } |
1302 | |
1332 | |
1303 | ############################################################################# |
1333 | ############################################################################# |
1304 | # bcd stuff |
1334 | # bcd stuff |
1305 | |
1335 | |
… | |
… | |
2240 | or die "$_: malformed or missing vmbus interface instance guid\n"; |
2270 | or die "$_: malformed or missing vmbus interface instance guid\n"; |
2241 | my $instance = enc_guid $1; |
2271 | my $instance = enc_guid $1; |
2242 | |
2272 | |
2243 | $payload = pack "a16a16x24", $type, $instance; |
2273 | $payload = pack "a16a16x24", $type, $instance; |
2244 | |
2274 | |
|
|
2275 | # } elsif ($type eq "udp") { |
|
|
2276 | # $payload = pack "Va16", 1, "12345678"; |
|
|
2277 | |
2245 | } else { |
2278 | } else { |
2246 | die "$type: not a supported device type (binary, null, boot, legacypartition, partition, block, locate)\n"; |
2279 | die "$type: not a supported device type (binary, null, boot, legacypartition, partition, block, locate)\n"; |
2247 | } |
2280 | } |
2248 | |
2281 | |
2249 | return ( |
2282 | return ( |
… | |
… | |
2591 | |
2624 | |
2592 | import => sub { |
2625 | import => sub { |
2593 | regf_save shift, bcd_encode rdjson; |
2626 | regf_save shift, bcd_encode rdjson; |
2594 | }, |
2627 | }, |
2595 | |
2628 | |
|
|
2629 | create => sub { |
|
|
2630 | my $path = shift; |
|
|
2631 | my $stat = stat_get $path; # should actually be done at file load time |
|
|
2632 | my $bcd = { }; |
|
|
2633 | bcd_edit $path, $bcd, @_; |
|
|
2634 | regf_save $path, bcd_encode $bcd; |
|
|
2635 | stat_set $path, $stat; |
|
|
2636 | }, |
|
|
2637 | |
2596 | edit => sub { |
2638 | edit => sub { |
2597 | my $path = shift; |
2639 | my $path = shift; |
|
|
2640 | my $stat = stat_get $path; # should actually be done at file load time |
2598 | my $bcd = bcd_decode regf_load $path; |
2641 | my $bcd = bcd_decode regf_load $path; |
2599 | bcd_edit $path, $bcd, @_; |
2642 | bcd_edit $path, $bcd, @_; |
2600 | regf_save $path, bcd_encode $bcd; |
2643 | regf_save $path, bcd_encode $bcd; |
|
|
2644 | stat_set $path, $stat; |
2601 | }, |
2645 | }, |
2602 | |
2646 | |
2603 | parse => sub { |
2647 | parse => sub { |
2604 | my $path = shift; |
2648 | my $path = shift; |
2605 | my $bcd = bcd_decode regf_load $path; |
2649 | my $bcd = bcd_decode regf_load $path; |