+sub make_new_tape_label {
+ my $self = shift;
+ my %params = @_;
+
+ my $tl = $self->{'tapelist'};
+ die ("make_new_tape_label: no tapelist") if !$tl;
+ if (!defined $self->{'autolabel'}) {
+ return (undef, "autolabel not set");
+ }
+ if (!defined $self->{'autolabel'}->{'template'}) {
+ return (undef, "template is not set, you must set autolabel");
+ }
+ if (!defined $self->{'labelstr'}) {
+ return (undef, "labelstr not set");
+ }
+ my $template = $self->{'autolabel'}->{'template'};
+ my $labelstr = $self->{'labelstr'};
+ my $slot_digit = 1;
+
+ $template =~ s/\$\$/SUBSTITUTE_DOLLAR/g;
+ $template =~ s/\$b/SUBSTITUTE_BARCODE/g;
+ $template =~ s/\$m/SUBSTITUTE_META/g;
+ $template =~ s/\$o/SUBSTITUTE_ORG/g;
+ $template =~ s/\$c/SUBSTITUTE_CONFIG/g;
+ if ($template =~ /\$([0-9]*)s/) {
+ $slot_digit = $1;
+ $slot_digit = 1 if $slot_digit < 1;
+ $template =~ s/\$[0-9]*s/SUBSTITUTE_SLOT/g;
+ }
+
+ my $org = getconf($CNF_ORG);
+ my $config = Amanda::Config::get_config_name();
+ my $barcode = $params{'barcode'};
+ $barcode = '' if !defined $barcode;
+ my $meta = $params{'meta'};
+ my $slot = $params{'slot'};
+ $slot = '' if !defined $slot;
+ $meta = $self->make_new_meta_label(%params) if !defined $meta;
+ $meta = '' if !defined $meta;
+
+ $template =~ s/SUBSTITUTE_DOLLAR/\$/g;
+ $template =~ s/SUBSTITUTE_ORG/$org/g;
+ $template =~ s/SUBSTITUTE_CONFIG/$config/g;
+ $template =~ s/SUBSTITUTE_META/$meta/g;
+ # Do not susbtitute the barcode and slot now
+
+ (my $npercents =
+ $template) =~ s/[^%]*(%+)[^%]*/length($1)/e;
+ $npercents = 0 if $npercents eq $template;
+
+ my $label;
+ if ($npercents == 0) {
+ $label = $template;
+ $label =~ s/SUBSTITUTE_BARCODE/$barcode/g;
+ if ($template =~ /SUBSTITUTE_SLOT/) {
+ my $slot_label = sprintf("%0*d", $slot_digit, $slot);
+ $label =~ s/SUBSTITUTE_SLOT/$slot_label/g;
+ }
+ if ($template =~ /SUBSTITUTE_BARCODE/ && !defined $barcode) {
+ return (undef, "Can't generate new label because volume has no barcode");
+ } elsif ($template =~ /SUBSTITUTE_SLOT/ && !defined $slot) {
+ return (undef, "Can't generate new label because volume has no slot");
+ } elsif ($label eq $template) {
+ return (undef, "autolabel require at least one '%'");
+ } elsif ($tl->lookup_tapelabel($label)) {
+ return (undef, "Label '$label' already exists");
+ }
+ } else {
+ # make up a sprintf pattern
+ (my $sprintf_pat =
+ $template) =~ s/(%+)/"%0" . length($1) . "d"/e;
+
+ my %existing_labels;
+ for my $tle (@{$tl->{'tles'}}) {
+ if (defined $tle && defined $tle->{'label'}) {
+ my $tle_label = $tle->{'label'};
+ my $tle_barcode = $tle->{'barcode'};
+ if (defined $tle_barcode) {
+ $tle_label =~ s/$tle_barcode/SUBSTITUTE_BARCODE/g;
+ }
+ $existing_labels{$tle_label} = 1 if defined $tle_label;
+ }
+ }
+
+ my $nlabels = 10 ** $npercents;
+ my ($i);
+ for ($i = 1; $i < $nlabels; $i++) {
+ $label = sprintf($sprintf_pat, $i);
+ last unless (exists $existing_labels{$label});
+ }
+
+ # susbtitute the barcode and slot
+ $label =~ s/SUBSTITUTE_BARCODE/$barcode/g;
+ if ($template =~ /SUBSTITUTE_SLOT/) {
+ my $slot_label = sprintf("%0*d", $slot_digit, $slot);
+ $label =~ s/SUBSTITUTE_SLOT/$slot_label/g;
+ }
+
+ # bail out if we didn't find an unused label
+ return (undef, "Can't label unlabeled volume: All label used")
+ if ($i >= $nlabels);
+ }
+
+ # verify $label matches $labelstr
+ if ($label !~ /$labelstr/) {
+ return (undef, "Newly-generated label '$label' does not match labelstr '$labelstr'");
+ }
+
+ if (!$label) {
+ return (undef, "Generated label is empty");
+ }
+
+ return $label;
+}
+
+sub make_new_meta_label {
+ my $self = shift;
+ my %params = @_;
+
+ my $tl = $self->{'tapelist'};
+ die ("make_new_meta_label: no tapelist") if !$tl;
+ return undef if !defined $self->{'meta_autolabel'};
+ my $template = $self->{'meta_autolabel'};
+ return if !defined $template;
+
+ if (!$template) {
+ return (undef, "template is not set, you must set meta-autolabel");
+ }
+ $template =~ s/\$\$/SUBSTITUTE_DOLLAR/g;
+ $template =~ s/\$o/SUBSTITUTE_ORG/g;
+ $template =~ s/\$c/SUBSTITUTE_CONFIG/g;
+
+ my $org = getconf($CNF_ORG);
+ my $config = Amanda::Config::get_config_name();
+
+ $template =~ s/SUBSTITUTE_DOLLAR/\$/g;
+ $template =~ s/SUBSTITUTE_ORG/$org/g;
+ $template =~ s/SUBSTITUTE_CONFIG/$config/g;
+
+ (my $npercents =
+ $template) =~ s/[^%]*(%+)[^%]*/length($1)/e;
+ $npercents = 0 if $npercents eq $template;
+ my $nlabels = 10 ** $npercents;
+
+ # make up a sprintf pattern
+ (my $sprintf_pat = $template) =~ s/(%+)/"%0" . length($1) . "d"/e;
+
+ my %existing_meta_labels =
+ map { $_->{'meta'} => 1 } @{$tl->{'tles'}};
+
+ my ($i, $meta);
+ for ($i = 1; $i < $nlabels; $i++) {
+ $meta = sprintf($sprintf_pat, $i);
+ last unless (exists $existing_meta_labels{$meta});
+ }
+
+ # bail out if we didn't find an unused label
+ return (undef, "Can't label unlabeled meta volume: All meta label used")
+ if ($i >= $nlabels);
+
+ if (!$meta) {
+ return (undef, "Generated meta-label is empty");
+ }
+
+ return $meta;
+}
+
+sub volume_is_labelable {
+ my $self = shift;
+ my $dev_status = shift;
+ my $f_type = shift;
+ my $label = shift;
+ my $autolabel = $self->{'autolabel'};
+
+ if (!defined $dev_status) {
+ return 0;
+ } elsif ($dev_status & $DEVICE_STATUS_VOLUME_UNLABELED and
+ defined $f_type and
+ $f_type == $Amanda::Header::F_EMPTY) {
+ return 0 if (!$autolabel->{'empty'});
+ } elsif ($dev_status & $DEVICE_STATUS_VOLUME_UNLABELED and
+ defined $f_type and
+ $f_type == $Amanda::Header::F_WEIRD) {
+ return 0 if (!$autolabel->{'non_amanda'});
+ } elsif ($dev_status & $DEVICE_STATUS_VOLUME_ERROR) {
+ return 0 if (!$autolabel->{'volume_error'});
+ } elsif ($dev_status != $DEVICE_STATUS_SUCCESS) {
+ return 0;
+ } elsif ($dev_status & $DEVICE_STATUS_SUCCESS and
+ $f_type == $Amanda::Header::F_TAPESTART and
+ $label !~ /$self->{'labelstr'}/) {
+ return 0 if (!$autolabel->{'other_config'});
+ }
+
+ return 1;
+}
+