cifs: Label SMB2 statuses with errors
Label the SMB2 status entries with error codes as a prelude to
autogenerating the mapping table. This was done with the following script:
#!/usr/bin/perl -w
use strict;
my @error_mapping_table = ();
my %statuses = ();
#
# Read the status list
#
my $f = "fs/smb/common/smb2status.h";
open FILE, "<$f" || die $f;
my @contents = <FILE>;
close FILE || die;
my $l = 0;
foreach (@contents) {
$l++;
if (m!^#define\s*([A-Za-z0-9_]+)\s+cpu_to_le32[(]([0-9a-fA-Fx]+)[)]!) {
my $status = $1;
my $code = $2;
my $s;
next if ($status =~ /^STATUS_SEVERITY/);
if (exists($statuses{$status})) {
print("$f:$l: Duplicate declaration of ", $s->{status}, "\n");
} else {
my %_s = (
status => $status,
code => hex($code)
);
$statuses{$status} = \%_s;
}
}
}
#
# Read the SMB2 status => error mapping table
#
$f = "fs/smb/client/smb2maperror.c";
open(MFILE, "<$f") || die $f;
my @maperror = <MFILE>;
close MFILE || die;
my $parse = 0;
my $acc = "";
$l = 0;
foreach my $line (@maperror) {
chomp $line;
$l++;
if ($parse == 0 &&
$line =~ /^static const struct status_to_posix_error smb2_error_map_table/) {
$parse = 1;
next;
}
last if ($parse >= 1 && $line =~ /^[}];/);
if ($parse == 1) {
if ($line =~ /[\t][{].*[}],/) {
$acc = $line;
$parse = 3;
} elsif ($line =~ /[\t][{].*/) {
$acc = $line;
$parse = 2;
next;
} elsif ($line =~ m!^\s*/[*].*[*]/!) {
next;
} else {
die "smb2maperror.c:$l: unparseable mapping element\n";
}
}
if ($parse == 2) {
if ($line =~ /.*[}],/) {
$acc .= $line;
$parse = 3;
} else {
$acc .= $line;
}
}
if ($parse == 3) {
$acc =~ s/\s+//g;
if ($acc =~ m/[{](.*)[}]/) {
$acc = $1;
} else {
die "'$acc'";
}
my ($status, $error, $string) = split(/,/, $acc);
if (exists($statuses{$status})) {
my $s = $statuses{$status};
if (exists($s->{error})) {
print("$f:$l: Dup mapping entry $status\n");
}
$s->{error} = $error;
#print $s->{code}, " => ", $error, "\n";
} else {
print STDERR "$f:$l: Unknown status $status\n";
}
$acc = "";
$parse = 1;
}
}
#
# Sort the error table by STATUS_* value
#
my @order = ();
foreach my $status (keys(%statuses)) {
my $s = $statuses{$status};
push @order, $s;
unless (exists($s->{code})) {
print("Unknown code for ", $s->{status}, "\n")
} else {
#print("Code for ", $s->{status}, " is ", $s->{code}, "\n");
}
}
@order = sort( { $a->{code} <=> $b->{code} } @order);
foreach my $s (@order) {
my $status = $s->{status};
my $error = $s->{error};
my $code = $s->{code};
my $pad = " ";
if (length($status) < 32) {
my $n = 32 - length($status);
$pad = "\t" x ((($n-1) / 8) + 1);
}
#printf("#define %s%scpu_to_le32(0x%08x) // -%s\n", $status, $pad, $code, $error);
#printf("\t%s%s= 0x%08x, // -%s\n", $status, $pad, $code, $error);
}
#
# Decorate the definitions
#
my @output = ();
for (my $i = 0; $i <= $#contents; $i++) {
my $line = $contents[$i];
if ($line =~ m!^#define\s*([A-Za-z0-9_]+)\s+cpu_to_le32[(]([0-9a-fA-Fx]+)[)]!) {
my $status = $1;
my $code = $2;
if ($status =~ /^STATUS_SEVERITY/) {
push @output, $line;
next;
}
my $pad = " ";
if (length($status) < 40) {
my $n = 40 - length($status);
$pad = "\t" x ((($n-1) / 8) + 1);
}
my $s = $statuses{$1};
my $error = "EIO";
if (exists($s->{error})) {
$error = $s->{error};
} else {
if (!$s->{code}) {
print "ZERO ", $status, "\n";
$error = "0";
} else {
$error = "-EIO";
}
}
#my $rev = "#define " . $status . $pad . "_S(" . $2 . ", " . $error . ")\n";
my $rev = "#define " . $status . $pad . "cpu_to_le32(" . $2 . ") // " . $error . "\n";
push @output, $rev;
} else {
push @output, $line;
}
}
open FILE, ">fs/smb/common/smb2status.h" || die;
print FILE @output;
close FILE || die;
Signed-off-by: David Howells <dhowells@redhat.com>
cc: Steve French <stfrench@microsoft.com>
cc: ChenXiaoSong <chenxiaosong@kylinos.cn>
cc: linux-cifs@vger.kernel.org
Signed-off-by: ChenXiaoSong <chenxiaosong@kylinos.cn>
Reviewed-by: David Howells <dhowells@redhat.com>
Link: https://lore.kernel.org/linux-cifs/20260106071507.1420900-2-chenxiaosong.chenxiaosong@linux.dev/
Signed-off-by: Steve French <stfrench@microsoft.com>