)
%.o: %.c
+ @echo building $@ because of $?
$(CC) $(CFLAGS) -c -o $@ $<
Alternatively it may be obtained from gitweb, go to:
https://git.opensvc.com/?p=multipath-tools/.git;a=tags
-select a release-tag and then click on "snapshot".
+select a release-tag and then click on "snapshot". Or get it with
+wget "https://git.opensvc.com/?p=multipath-tools/.git;a=snapshot;sf=tgz;h=refs/tags/X.Y.Z" -O multipath-tools-X.Y.Z.tar.gz
Source code
/*
* dm_get_first_dep
*
- * Return the device number of the first dependend device
+ * Return the device number of the first dependent device
* for a given target.
*/
dev_t dm_get_first_dep(char *devname)
DIR *dir;
struct dirent *dent;
char dev[64], *found = NULL, *p;
- int fd;
+ int fd, bytes_read;
struct stat statbuf;
struct loop_info loopinfo;
const char VIRT_BLOCK[] = "/sys/devices/virtual/block";
if (fd < 0)
continue;
- if (read(fd, dev, sizeof(dev)) <= 0) {
+ bytes_read = read(fd, dev, sizeof(dev) - 1);
+ if (bytes_read <= 0) {
close(fd);
continue;
}
close(fd);
- dev[sizeof(dev)-1] = '\0';
+ dev[bytes_read] = '\0';
p = strchr(dev, '\n');
if (p != NULL)
*p = '\0';
struct solaris_x86_slice {
unsigned short s_tag; /* ID tag of partition */
- unsigned short s_flag; /* permision flags */
+ unsigned short s_flag; /* permission flags */
long s_start; /* start sector no of partition */
long s_size; /* # of blocks in partition */
};
# stale DM or loop devices may keep lurking around.
# Set WORKDIR in environment to existing dir to for persistence
-# WARNING: exisiting files will be truncated.
+# WARNING: existing files will be truncated.
# If empty, test will be done in temporary dir
: ${WORKDIR:=}
# Set this environment variable to test an alternative kpartx executable
-== Planed features ==
+== Planned features ==
* Expose all properties used by /usr/bin/multipath
== Code style ==
and print formatted documentation to standard output.
The documentation comments are identified by "/**" opening comment mark. See
-Documentation/kernel-doc-nano-HOWTO.txt for the documentation comment syntax.
+Documentation/doc-guide/kernel-doc.rst for the documentation comment syntax.
Output format selection (mutually exclusive):
- -docbook Output DocBook format.
- -html Output HTML format.
- -html5 Output HTML5 format.
- -list Output symbol list format. This is for use by docproc.
-man Output troff manual page format. This is the default.
-rst Output reStructuredText format.
- -text Output plain text format.
+ -none Do not output documentation, only warnings.
Output selection (mutually exclusive):
-export Only output documentation for symbols that have been
my $type_constant = '\b``([^\`]+)``\b';
my $type_constant2 = '\%([-_\w]+)';
my $type_func = '(\w+)\(\)';
-my $type_param = '\@(\w+(\.\.\.)?)';
+my $type_param = '\@(\w*(\.\w+)*(\.\.\.)?)';
my $type_fp_param = '\@(\w+)\(\)'; # Special RST handling for func ptr params
my $type_env = '(\$\w+)';
my $type_enum = '\&(enum\s*([_\w]+))';
my $type_union = '\&(union\s*([_\w]+))';
my $type_member = '\&([_\w]+)(\.|->)([_\w]+)';
my $type_fallback = '\&([_\w]+)';
-my $type_enum_xml = '\&(enum\s*([_\w]+))';
-my $type_struct_xml = '\&(struct\s*([_\w]+))';
-my $type_typedef_xml = '\&(typedef\s*([_\w]+))';
-my $type_union_xml = '\&(union\s*([_\w]+))';
-my $type_member_xml = '\&([_\w]+)(\.|-\>)([_\w]+)';
-my $type_fallback_xml = '\&([_\w]+)';
my $type_member_func = $type_member . '\(\)';
# Output conversion substitutions.
# One for each output format
-# these work fairly well
-my @highlights_html = (
- [$type_constant, "<i>\$1</i>"],
- [$type_constant2, "<i>\$1</i>"],
- [$type_func, "<b>\$1</b>"],
- [$type_enum_xml, "<i>\$1</i>"],
- [$type_struct_xml, "<i>\$1</i>"],
- [$type_typedef_xml, "<i>\$1</i>"],
- [$type_union_xml, "<i>\$1</i>"],
- [$type_env, "<b><i>\$1</i></b>"],
- [$type_param, "<tt><b>\$1</b></tt>"],
- [$type_member_xml, "<tt><i>\$1</i>\$2\$3</tt>"],
- [$type_fallback_xml, "<i>\$1</i>"]
- );
-my $local_lt = "\\\\\\\\lt:";
-my $local_gt = "\\\\\\\\gt:";
-my $blankline_html = $local_lt . "p" . $local_gt; # was "<p>"
-
-# html version 5
-my @highlights_html5 = (
- [$type_constant, "<span class=\"const\">\$1</span>"],
- [$type_constant2, "<span class=\"const\">\$1</span>"],
- [$type_func, "<span class=\"func\">\$1</span>"],
- [$type_enum_xml, "<span class=\"enum\">\$1</span>"],
- [$type_struct_xml, "<span class=\"struct\">\$1</span>"],
- [$type_typedef_xml, "<span class=\"typedef\">\$1</span>"],
- [$type_union_xml, "<span class=\"union\">\$1</span>"],
- [$type_env, "<span class=\"env\">\$1</span>"],
- [$type_param, "<span class=\"param\">\$1</span>]"],
- [$type_member_xml, "<span class=\"literal\"><span class=\"struct\">\$1</span>\$2<span class=\"member\">\$3</span></span>"],
- [$type_fallback_xml, "<span class=\"struct\">\$1</span>"]
- );
-my $blankline_html5 = $local_lt . "br /" . $local_gt;
-
-# XML, docbook format
-my @highlights_xml = (
- ["([^=])\\\"([^\\\"<]+)\\\"", "\$1<quote>\$2</quote>"],
- [$type_constant, "<constant>\$1</constant>"],
- [$type_constant2, "<constant>\$1</constant>"],
- [$type_enum_xml, "<type>\$1</type>"],
- [$type_struct_xml, "<structname>\$1</structname>"],
- [$type_typedef_xml, "<type>\$1</type>"],
- [$type_union_xml, "<structname>\$1</structname>"],
- [$type_param, "<parameter>\$1</parameter>"],
- [$type_func, "<function>\$1</function>"],
- [$type_env, "<envar>\$1</envar>"],
- [$type_member_xml, "<literal><structname>\$1</structname>\$2<structfield>\$3</structfield></literal>"],
- [$type_fallback_xml, "<structname>\$1</structname>"]
- );
-my $blankline_xml = $local_lt . "/para" . $local_gt . $local_lt . "para" . $local_gt . "\n";
-
-# gnome, docbook format
-my @highlights_gnome = (
- [$type_constant, "<replaceable class=\"option\">\$1</replaceable>"],
- [$type_constant2, "<replaceable class=\"option\">\$1</replaceable>"],
- [$type_func, "<function>\$1</function>"],
- [$type_enum, "<type>\$1</type>"],
- [$type_struct, "<structname>\$1</structname>"],
- [$type_typedef, "<type>\$1</type>"],
- [$type_union, "<structname>\$1</structname>"],
- [$type_env, "<envar>\$1</envar>"],
- [$type_param, "<parameter>\$1</parameter>" ],
- [$type_member, "<literal><structname>\$1</structname>\$2<structfield>\$3</structfield></literal>"],
- [$type_fallback, "<structname>\$1</structname>"]
- );
-my $blankline_gnome = "</para><para>\n";
-
# these are pretty rough
my @highlights_man = (
[$type_constant, "\$1"],
);
my $blankline_man = "";
-# text-mode
-my @highlights_text = (
- [$type_constant, "\$1"],
- [$type_constant2, "\$1"],
- [$type_func, "\$1"],
- [$type_enum, "\$1"],
- [$type_struct, "\$1"],
- [$type_typedef, "\$1"],
- [$type_union, "\$1"],
- [$type_param, "\$1"],
- [$type_member, "\$1\$2\$3"],
- [$type_fallback, "\$1"]
- );
-my $blankline_text = "";
-
# rst-mode
my @highlights_rst = (
[$type_constant, "``\$1``"],
);
my $blankline_rst = "\n";
-# list mode
-my @highlights_list = (
- [$type_constant, "\$1"],
- [$type_constant2, "\$1"],
- [$type_func, "\$1"],
- [$type_enum, "\$1"],
- [$type_struct, "\$1"],
- [$type_typedef, "\$1"],
- [$type_union, "\$1"],
- [$type_param, "\$1"],
- [$type_member, "\$1"],
- [$type_fallback, "\$1"]
- );
-my $blankline_list = "";
-
# read arguments
if ($#ARGV == -1) {
usage();
my $dohighlight = "";
my $verbose = 0;
-my $output_mode = "man";
+my $output_mode = "rst";
my $output_preformatted = 0;
my $no_doc_sections = 0;
my $enable_lineno = 0;
-my @highlights = @highlights_man;
-my $blankline = $blankline_man;
+my @highlights = @highlights_rst;
+my $blankline = $blankline_rst;
my $modulename = "Kernel API";
use constant {
reset_state();
-while ($ARGV[0] =~ m/^-(.*)/) {
- my $cmd = shift @ARGV;
- if ($cmd eq "-html") {
- $output_mode = "html";
- @highlights = @highlights_html;
- $blankline = $blankline_html;
- } elsif ($cmd eq "-html5") {
- $output_mode = "html5";
- @highlights = @highlights_html5;
- $blankline = $blankline_html5;
- } elsif ($cmd eq "-man") {
+while ($ARGV[0] =~ m/^--?(.*)/) {
+ my $cmd = $1;
+ shift @ARGV;
+ if ($cmd eq "man") {
$output_mode = "man";
@highlights = @highlights_man;
$blankline = $blankline_man;
- } elsif ($cmd eq "-text") {
- $output_mode = "text";
- @highlights = @highlights_text;
- $blankline = $blankline_text;
- } elsif ($cmd eq "-rst") {
+ } elsif ($cmd eq "rst") {
$output_mode = "rst";
@highlights = @highlights_rst;
$blankline = $blankline_rst;
- } elsif ($cmd eq "-docbook") {
- $output_mode = "xml";
- @highlights = @highlights_xml;
- $blankline = $blankline_xml;
- } elsif ($cmd eq "-list") {
- $output_mode = "list";
- @highlights = @highlights_list;
- $blankline = $blankline_list;
- } elsif ($cmd eq "-gnome") {
- $output_mode = "gnome";
- @highlights = @highlights_gnome;
- $blankline = $blankline_gnome;
- } elsif ($cmd eq "-module") { # not needed for XML, inherits from calling document
+ } elsif ($cmd eq "none") {
+ $output_mode = "none";
+ } elsif ($cmd eq "module") { # not needed for XML, inherits from calling document
$modulename = shift @ARGV;
- } elsif ($cmd eq "-function") { # to only output specific functions
+ } elsif ($cmd eq "function") { # to only output specific functions
$output_selection = OUTPUT_INCLUDE;
$function = shift @ARGV;
$function_table{$function} = 1;
- } elsif ($cmd eq "-nofunction") { # output all except specific functions
+ } elsif ($cmd eq "nofunction") { # output all except specific functions
$output_selection = OUTPUT_EXCLUDE;
$function = shift @ARGV;
$function_table{$function} = 1;
- } elsif ($cmd eq "-export") { # only exported symbols
+ } elsif ($cmd eq "export") { # only exported symbols
$output_selection = OUTPUT_EXPORTED;
%function_table = ();
- } elsif ($cmd eq "-internal") { # only non-exported symbols
+ } elsif ($cmd eq "internal") { # only non-exported symbols
$output_selection = OUTPUT_INTERNAL;
%function_table = ();
- } elsif ($cmd eq "-export-file") {
+ } elsif ($cmd eq "export-file") {
my $file = shift @ARGV;
push(@export_file_list, $file);
- } elsif ($cmd eq "-v") {
+ } elsif ($cmd eq "v") {
$verbose = 1;
- } elsif (($cmd eq "-h") || ($cmd eq "--help")) {
+ } elsif (($cmd eq "h") || ($cmd eq "help")) {
usage();
- } elsif ($cmd eq '-no-doc-sections') {
+ } elsif ($cmd eq 'no-doc-sections') {
$no_doc_sections = 1;
- } elsif ($cmd eq '-enable-lineno') {
+ } elsif ($cmd eq 'enable-lineno') {
$enable_lineno = 1;
- } elsif ($cmd eq '-show-not-found') {
+ } elsif ($cmd eq 'show-not-found') {
$show_not_found = 1;
+ } else {
+ # Unknown argument
+ usage();
}
}
# confess "output_highlight got called with no args?\n";
# }
- if ($output_mode eq "html" || $output_mode eq "html5" ||
- $output_mode eq "xml") {
- $contents = local_unescape($contents);
- # convert data read & converted thru xml_escape() into &xyz; format:
- $contents =~ s/\\\\\\/\&/g;
- }
# print STDERR "contents b4:$contents\n";
eval $dohighlight;
die $@ if $@;
# print STDERR "contents af:$contents\n";
-# strip whitespaces when generating html5
- if ($output_mode eq "html5") {
- $contents =~ s/^\s+//;
- $contents =~ s/\s+$//;
- }
foreach $line (split "\n", $contents) {
if (! $output_preformatted) {
$line =~ s/^\s*//;
}
}
-# output sections in html
-sub output_section_html(%) {
- my %args = %{$_[0]};
- my $section;
-
- foreach $section (@{$args{'sectionlist'}}) {
- print "<h3>$section</h3>\n";
- print "<blockquote>\n";
- output_highlight($args{'sections'}{$section});
- print "</blockquote>\n";
- }
-}
-
-# output enum in html
-sub output_enum_html(%) {
- my %args = %{$_[0]};
- my ($parameter);
- my $count;
- print "<h2>enum " . $args{'enum'} . "</h2>\n";
-
- print "<b>enum " . $args{'enum'} . "</b> {<br>\n";
- $count = 0;
- foreach $parameter (@{$args{'parameterlist'}}) {
- print " <b>" . $parameter . "</b>";
- if ($count != $#{$args{'parameterlist'}}) {
- $count++;
- print ",\n";
- }
- print "<br>";
- }
- print "};<br>\n";
-
- print "<h3>Constants</h3>\n";
- print "<dl>\n";
- foreach $parameter (@{$args{'parameterlist'}}) {
- print "<dt><b>" . $parameter . "</b>\n";
- print "<dd>";
- output_highlight($args{'parameterdescs'}{$parameter});
- }
- print "</dl>\n";
- output_section_html(@_);
- print "<hr>\n";
-}
-
-# output typedef in html
-sub output_typedef_html(%) {
- my %args = %{$_[0]};
- my ($parameter);
- my $count;
- print "<h2>typedef " . $args{'typedef'} . "</h2>\n";
-
- print "<b>typedef " . $args{'typedef'} . "</b>\n";
- output_section_html(@_);
- print "<hr>\n";
-}
-
-# output struct in html
-sub output_struct_html(%) {
- my %args = %{$_[0]};
- my ($parameter);
-
- print "<h2>" . $args{'type'} . " " . $args{'struct'} . " - " . $args{'purpose'} . "</h2>\n";
- print "<b>" . $args{'type'} . " " . $args{'struct'} . "</b> {<br>\n";
- foreach $parameter (@{$args{'parameterlist'}}) {
- if ($parameter =~ /^#/) {
- print "$parameter<br>\n";
- next;
- }
- my $parameter_name = $parameter;
- $parameter_name =~ s/\[.*//;
-
- ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
- $type = $args{'parametertypes'}{$parameter};
- if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
- # pointer-to-function
- print " <i>$1</i><b>$parameter</b>) <i>($2)</i>;<br>\n";
- } elsif ($type =~ m/^(.*?)\s*(:.*)/) {
- # bitfield
- print " <i>$1</i> <b>$parameter</b>$2;<br>\n";
- } else {
- print " <i>$type</i> <b>$parameter</b>;<br>\n";
- }
- }
- print "};<br>\n";
-
- print "<h3>Members</h3>\n";
- print "<dl>\n";
- foreach $parameter (@{$args{'parameterlist'}}) {
- ($parameter =~ /^#/) && next;
-
- my $parameter_name = $parameter;
- $parameter_name =~ s/\[.*//;
-
- ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
- print "<dt><b>" . $parameter . "</b>\n";
- print "<dd>";
- output_highlight($args{'parameterdescs'}{$parameter_name});
- }
- print "</dl>\n";
- output_section_html(@_);
- print "<hr>\n";
-}
-
-# output function in html
-sub output_function_html(%) {
- my %args = %{$_[0]};
- my ($parameter, $section);
- my $count;
-
- print "<h2>" . $args{'function'} . " - " . $args{'purpose'} . "</h2>\n";
- print "<i>" . $args{'functiontype'} . "</i>\n";
- print "<b>" . $args{'function'} . "</b>\n";
- print "(";
- $count = 0;
- foreach $parameter (@{$args{'parameterlist'}}) {
- $type = $args{'parametertypes'}{$parameter};
- if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
- # pointer-to-function
- print "<i>$1</i><b>$parameter</b>) <i>($2)</i>";
- } else {
- print "<i>" . $type . "</i> <b>" . $parameter . "</b>";
- }
- if ($count != $#{$args{'parameterlist'}}) {
- $count++;
- print ",\n";
- }
- }
- print ")\n";
-
- print "<h3>Arguments</h3>\n";
- print "<dl>\n";
- foreach $parameter (@{$args{'parameterlist'}}) {
- my $parameter_name = $parameter;
- $parameter_name =~ s/\[.*//;
-
- ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
- print "<dt><b>" . $parameter . "</b>\n";
- print "<dd>";
- output_highlight($args{'parameterdescs'}{$parameter_name});
- }
- print "</dl>\n";
- output_section_html(@_);
- print "<hr>\n";
-}
-
-# output DOC: block header in html
-sub output_blockhead_html(%) {
- my %args = %{$_[0]};
- my ($parameter, $section);
- my $count;
-
- foreach $section (@{$args{'sectionlist'}}) {
- print "<h3>$section</h3>\n";
- print "<ul>\n";
- output_highlight($args{'sections'}{$section});
- print "</ul>\n";
- }
- print "<hr>\n";
-}
-
-# output sections in html5
-sub output_section_html5(%) {
- my %args = %{$_[0]};
- my $section;
-
- foreach $section (@{$args{'sectionlist'}}) {
- print "<section>\n";
- print "<h1>$section</h1>\n";
- print "<p>\n";
- output_highlight($args{'sections'}{$section});
- print "</p>\n";
- print "</section>\n";
- }
-}
-
-# output enum in html5
-sub output_enum_html5(%) {
- my %args = %{$_[0]};
- my ($parameter);
- my $count;
- my $html5id;
-
- $html5id = $args{'enum'};
- $html5id =~ s/[^a-zA-Z0-9\-]+/_/g;
- print "<article class=\"enum\" id=\"enum:". $html5id . "\">";
- print "<h1>enum " . $args{'enum'} . "</h1>\n";
- print "<ol class=\"code\">\n";
- print "<li>";
- print "<span class=\"keyword\">enum</span> ";
- print "<span class=\"identifier\">" . $args{'enum'} . "</span> {";
- print "</li>\n";
- $count = 0;
- foreach $parameter (@{$args{'parameterlist'}}) {
- print "<li class=\"indent\">";
- print "<span class=\"param\">" . $parameter . "</span>";
- if ($count != $#{$args{'parameterlist'}}) {
- $count++;
- print ",";
- }
- print "</li>\n";
- }
- print "<li>};</li>\n";
- print "</ol>\n";
-
- print "<section>\n";
- print "<h1>Constants</h1>\n";
- print "<dl>\n";
- foreach $parameter (@{$args{'parameterlist'}}) {
- print "<dt>" . $parameter . "</dt>\n";
- print "<dd>";
- output_highlight($args{'parameterdescs'}{$parameter});
- print "</dd>\n";
- }
- print "</dl>\n";
- print "</section>\n";
- output_section_html5(@_);
- print "</article>\n";
-}
-
-# output typedef in html5
-sub output_typedef_html5(%) {
- my %args = %{$_[0]};
- my ($parameter);
- my $count;
- my $html5id;
-
- $html5id = $args{'typedef'};
- $html5id =~ s/[^a-zA-Z0-9\-]+/_/g;
- print "<article class=\"typedef\" id=\"typedef:" . $html5id . "\">\n";
- print "<h1>typedef " . $args{'typedef'} . "</h1>\n";
-
- print "<ol class=\"code\">\n";
- print "<li>";
- print "<span class=\"keyword\">typedef</span> ";
- print "<span class=\"identifier\">" . $args{'typedef'} . "</span>";
- print "</li>\n";
- print "</ol>\n";
- output_section_html5(@_);
- print "</article>\n";
-}
-
-# output struct in html5
-sub output_struct_html5(%) {
- my %args = %{$_[0]};
- my ($parameter);
- my $html5id;
-
- $html5id = $args{'struct'};
- $html5id =~ s/[^a-zA-Z0-9\-]+/_/g;
- print "<article class=\"struct\" id=\"struct:" . $html5id . "\">\n";
- print "<hgroup>\n";
- print "<h1>" . $args{'type'} . " " . $args{'struct'} . "</h1>";
- print "<h2>". $args{'purpose'} . "</h2>\n";
- print "</hgroup>\n";
- print "<ol class=\"code\">\n";
- print "<li>";
- print "<span class=\"type\">" . $args{'type'} . "</span> ";
- print "<span class=\"identifier\">" . $args{'struct'} . "</span> {";
- print "</li>\n";
- foreach $parameter (@{$args{'parameterlist'}}) {
- print "<li class=\"indent\">";
- if ($parameter =~ /^#/) {
- print "<span class=\"param\">" . $parameter ."</span>\n";
- print "</li>\n";
- next;
- }
- my $parameter_name = $parameter;
- $parameter_name =~ s/\[.*//;
-
- ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
- $type = $args{'parametertypes'}{$parameter};
- if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
- # pointer-to-function
- print "<span class=\"type\">$1</span> ";
- print "<span class=\"param\">$parameter</span>";
- print "<span class=\"type\">)</span> ";
- print "(<span class=\"args\">$2</span>);";
- } elsif ($type =~ m/^(.*?)\s*(:.*)/) {
- # bitfield
- print "<span class=\"type\">$1</span> ";
- print "<span class=\"param\">$parameter</span>";
- print "<span class=\"bits\">$2</span>;";
- } else {
- print "<span class=\"type\">$type</span> ";
- print "<span class=\"param\">$parameter</span>;";
- }
- print "</li>\n";
- }
- print "<li>};</li>\n";
- print "</ol>\n";
-
- print "<section>\n";
- print "<h1>Members</h1>\n";
- print "<dl>\n";
- foreach $parameter (@{$args{'parameterlist'}}) {
- ($parameter =~ /^#/) && next;
-
- my $parameter_name = $parameter;
- $parameter_name =~ s/\[.*//;
-
- ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
- print "<dt>" . $parameter . "</dt>\n";
- print "<dd>";
- output_highlight($args{'parameterdescs'}{$parameter_name});
- print "</dd>\n";
- }
- print "</dl>\n";
- print "</section>\n";
- output_section_html5(@_);
- print "</article>\n";
-}
-
-# output function in html5
-sub output_function_html5(%) {
- my %args = %{$_[0]};
- my ($parameter, $section);
- my $count;
- my $html5id;
-
- $html5id = $args{'function'};
- $html5id =~ s/[^a-zA-Z0-9\-]+/_/g;
- print "<article class=\"function\" id=\"func:". $html5id . "\">\n";
- print "<hgroup>\n";
- print "<h1>" . $args{'function'} . "</h1>";
- print "<h2>" . $args{'purpose'} . "</h2>\n";
- print "</hgroup>\n";
- print "<ol class=\"code\">\n";
- print "<li>";
- print "<span class=\"type\">" . $args{'functiontype'} . "</span> ";
- print "<span class=\"identifier\">" . $args{'function'} . "</span> (";
- print "</li>";
- $count = 0;
- foreach $parameter (@{$args{'parameterlist'}}) {
- print "<li class=\"indent\">";
- $type = $args{'parametertypes'}{$parameter};
- if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
- # pointer-to-function
- print "<span class=\"type\">$1</span> ";
- print "<span class=\"param\">$parameter</span>";
- print "<span class=\"type\">)</span> ";
- print "(<span class=\"args\">$2</span>)";
- } else {
- print "<span class=\"type\">$type</span> ";
- print "<span class=\"param\">$parameter</span>";
- }
- if ($count != $#{$args{'parameterlist'}}) {
- $count++;
- print ",";
- }
- print "</li>\n";
- }
- print "<li>)</li>\n";
- print "</ol>\n";
-
- print "<section>\n";
- print "<h1>Arguments</h1>\n";
- print "<p>\n";
- print "<dl>\n";
- foreach $parameter (@{$args{'parameterlist'}}) {
- my $parameter_name = $parameter;
- $parameter_name =~ s/\[.*//;
-
- ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
- print "<dt>" . $parameter . "</dt>\n";
- print "<dd>";
- output_highlight($args{'parameterdescs'}{$parameter_name});
- print "</dd>\n";
- }
- print "</dl>\n";
- print "</section>\n";
- output_section_html5(@_);
- print "</article>\n";
-}
-
-# output DOC: block header in html5
-sub output_blockhead_html5(%) {
- my %args = %{$_[0]};
- my ($parameter, $section);
- my $count;
- my $html5id;
-
- foreach $section (@{$args{'sectionlist'}}) {
- $html5id = $section;
- $html5id =~ s/[^a-zA-Z0-9\-]+/_/g;
- print "<article class=\"doc\" id=\"doc:". $html5id . "\">\n";
- print "<h1>$section</h1>\n";
- print "<p>\n";
- output_highlight($args{'sections'}{$section});
- print "</p>\n";
- }
- print "</article>\n";
-}
-
-sub output_section_xml(%) {
- my %args = %{$_[0]};
- my $section;
- # print out each section
- $lineprefix=" ";
- foreach $section (@{$args{'sectionlist'}}) {
- print "<refsect1>\n";
- print "<title>$section</title>\n";
- if ($section =~ m/EXAMPLE/i) {
- print "<informalexample><programlisting>\n";
- $output_preformatted = 1;
- } else {
- print "<para>\n";
- }
- output_highlight($args{'sections'}{$section});
- $output_preformatted = 0;
- if ($section =~ m/EXAMPLE/i) {
- print "</programlisting></informalexample>\n";
- } else {
- print "</para>\n";
- }
- print "</refsect1>\n";
- }
-}
-
-# output function in XML DocBook
-sub output_function_xml(%) {
- my %args = %{$_[0]};
- my ($parameter, $section);
- my $count;
- my $id;
-
- $id = "API-" . $args{'function'};
- $id =~ s/[^A-Za-z0-9]/-/g;
-
- print "<refentry id=\"$id\">\n";
- print "<refentryinfo>\n";
- print " <title>LINUX</title>\n";
- print " <productname>Kernel Hackers Manual</productname>\n";
- print " <date>$man_date</date>\n";
- print "</refentryinfo>\n";
- print "<refmeta>\n";
- print " <refentrytitle><phrase>" . $args{'function'} . "</phrase></refentrytitle>\n";
- print " <manvolnum>9</manvolnum>\n";
- print " <refmiscinfo class=\"version\">" . $kernelversion . "</refmiscinfo>\n";
- print "</refmeta>\n";
- print "<refnamediv>\n";
- print " <refname>" . $args{'function'} . "</refname>\n";
- print " <refpurpose>\n";
- print " ";
- output_highlight ($args{'purpose'});
- print " </refpurpose>\n";
- print "</refnamediv>\n";
-
- print "<refsynopsisdiv>\n";
- print " <title>Synopsis</title>\n";
- print " <funcsynopsis><funcprototype>\n";
- print " <funcdef>" . $args{'functiontype'} . " ";
- print "<function>" . $args{'function'} . " </function></funcdef>\n";
-
- $count = 0;
- if ($#{$args{'parameterlist'}} >= 0) {
- foreach $parameter (@{$args{'parameterlist'}}) {
- $type = $args{'parametertypes'}{$parameter};
- if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
- # pointer-to-function
- print " <paramdef>$1<parameter>$parameter</parameter>)\n";
- print " <funcparams>$2</funcparams></paramdef>\n";
- } else {
- print " <paramdef>" . $type;
- print " <parameter>$parameter</parameter></paramdef>\n";
- }
- }
- } else {
- print " <void/>\n";
- }
- print " </funcprototype></funcsynopsis>\n";
- print "</refsynopsisdiv>\n";
-
- # print parameters
- print "<refsect1>\n <title>Arguments</title>\n";
- if ($#{$args{'parameterlist'}} >= 0) {
- print " <variablelist>\n";
- foreach $parameter (@{$args{'parameterlist'}}) {
- my $parameter_name = $parameter;
- $parameter_name =~ s/\[.*//;
- $type = $args{'parametertypes'}{$parameter};
-
- print " <varlistentry>\n <term><parameter>$type $parameter</parameter></term>\n";
- print " <listitem>\n <para>\n";
- $lineprefix=" ";
- output_highlight($args{'parameterdescs'}{$parameter_name});
- print " </para>\n </listitem>\n </varlistentry>\n";
- }
- print " </variablelist>\n";
- } else {
- print " <para>\n None\n </para>\n";
- }
- print "</refsect1>\n";
-
- output_section_xml(@_);
- print "</refentry>\n\n";
-}
-
-# output struct in XML DocBook
-sub output_struct_xml(%) {
- my %args = %{$_[0]};
- my ($parameter, $section);
- my $id;
-
- $id = "API-struct-" . $args{'struct'};
- $id =~ s/[^A-Za-z0-9]/-/g;
-
- print "<refentry id=\"$id\">\n";
- print "<refentryinfo>\n";
- print " <title>LINUX</title>\n";
- print " <productname>Kernel Hackers Manual</productname>\n";
- print " <date>$man_date</date>\n";
- print "</refentryinfo>\n";
- print "<refmeta>\n";
- print " <refentrytitle><phrase>" . $args{'type'} . " " . $args{'struct'} . "</phrase></refentrytitle>\n";
- print " <manvolnum>9</manvolnum>\n";
- print " <refmiscinfo class=\"version\">" . $kernelversion . "</refmiscinfo>\n";
- print "</refmeta>\n";
- print "<refnamediv>\n";
- print " <refname>" . $args{'type'} . " " . $args{'struct'} . "</refname>\n";
- print " <refpurpose>\n";
- print " ";
- output_highlight ($args{'purpose'});
- print " </refpurpose>\n";
- print "</refnamediv>\n";
-
- print "<refsynopsisdiv>\n";
- print " <title>Synopsis</title>\n";
- print " <programlisting>\n";
- print $args{'type'} . " " . $args{'struct'} . " {\n";
- foreach $parameter (@{$args{'parameterlist'}}) {
- if ($parameter =~ /^#/) {
- my $prm = $parameter;
- # convert data read & converted thru xml_escape() into &xyz; format:
- # This allows us to have #define macros interspersed in a struct.
- $prm =~ s/\\\\\\/\&/g;
- print "$prm\n";
- next;
- }
-
- my $parameter_name = $parameter;
- $parameter_name =~ s/\[.*//;
-
- defined($args{'parameterdescs'}{$parameter_name}) || next;
- ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
- $type = $args{'parametertypes'}{$parameter};
- if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
- # pointer-to-function
- print " $1 $parameter) ($2);\n";
- } elsif ($type =~ m/^(.*?)\s*(:.*)/) {
- # bitfield
- print " $1 $parameter$2;\n";
- } else {
- print " " . $type . " " . $parameter . ";\n";
- }
- }
- print "};";
- print " </programlisting>\n";
- print "</refsynopsisdiv>\n";
-
- print " <refsect1>\n";
- print " <title>Members</title>\n";
-
- if ($#{$args{'parameterlist'}} >= 0) {
- print " <variablelist>\n";
- foreach $parameter (@{$args{'parameterlist'}}) {
- ($parameter =~ /^#/) && next;
-
- my $parameter_name = $parameter;
- $parameter_name =~ s/\[.*//;
-
- defined($args{'parameterdescs'}{$parameter_name}) || next;
- ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
- $type = $args{'parametertypes'}{$parameter};
- print " <varlistentry>";
- print " <term><literal>$type $parameter</literal></term>\n";
- print " <listitem><para>\n";
- output_highlight($args{'parameterdescs'}{$parameter_name});
- print " </para></listitem>\n";
- print " </varlistentry>\n";
- }
- print " </variablelist>\n";
- } else {
- print " <para>\n None\n </para>\n";
- }
- print " </refsect1>\n";
-
- output_section_xml(@_);
-
- print "</refentry>\n\n";
-}
-
-# output enum in XML DocBook
-sub output_enum_xml(%) {
- my %args = %{$_[0]};
- my ($parameter, $section);
- my $count;
- my $id;
-
- $id = "API-enum-" . $args{'enum'};
- $id =~ s/[^A-Za-z0-9]/-/g;
-
- print "<refentry id=\"$id\">\n";
- print "<refentryinfo>\n";
- print " <title>LINUX</title>\n";
- print " <productname>Kernel Hackers Manual</productname>\n";
- print " <date>$man_date</date>\n";
- print "</refentryinfo>\n";
- print "<refmeta>\n";
- print " <refentrytitle><phrase>enum " . $args{'enum'} . "</phrase></refentrytitle>\n";
- print " <manvolnum>9</manvolnum>\n";
- print " <refmiscinfo class=\"version\">" . $kernelversion . "</refmiscinfo>\n";
- print "</refmeta>\n";
- print "<refnamediv>\n";
- print " <refname>enum " . $args{'enum'} . "</refname>\n";
- print " <refpurpose>\n";
- print " ";
- output_highlight ($args{'purpose'});
- print " </refpurpose>\n";
- print "</refnamediv>\n";
-
- print "<refsynopsisdiv>\n";
- print " <title>Synopsis</title>\n";
- print " <programlisting>\n";
- print "enum " . $args{'enum'} . " {\n";
- $count = 0;
- foreach $parameter (@{$args{'parameterlist'}}) {
- print " $parameter";
- if ($count != $#{$args{'parameterlist'}}) {
- $count++;
- print ",";
- }
- print "\n";
- }
- print "};";
- print " </programlisting>\n";
- print "</refsynopsisdiv>\n";
-
- print "<refsect1>\n";
- print " <title>Constants</title>\n";
- print " <variablelist>\n";
- foreach $parameter (@{$args{'parameterlist'}}) {
- my $parameter_name = $parameter;
- $parameter_name =~ s/\[.*//;
-
- print " <varlistentry>";
- print " <term>$parameter</term>\n";
- print " <listitem><para>\n";
- output_highlight($args{'parameterdescs'}{$parameter_name});
- print " </para></listitem>\n";
- print " </varlistentry>\n";
- }
- print " </variablelist>\n";
- print "</refsect1>\n";
-
- output_section_xml(@_);
-
- print "</refentry>\n\n";
-}
-
-# output typedef in XML DocBook
-sub output_typedef_xml(%) {
- my %args = %{$_[0]};
- my ($parameter, $section);
- my $id;
-
- $id = "API-typedef-" . $args{'typedef'};
- $id =~ s/[^A-Za-z0-9]/-/g;
-
- print "<refentry id=\"$id\">\n";
- print "<refentryinfo>\n";
- print " <title>LINUX</title>\n";
- print " <productname>Kernel Hackers Manual</productname>\n";
- print " <date>$man_date</date>\n";
- print "</refentryinfo>\n";
- print "<refmeta>\n";
- print " <refentrytitle><phrase>typedef " . $args{'typedef'} . "</phrase></refentrytitle>\n";
- print " <manvolnum>9</manvolnum>\n";
- print "</refmeta>\n";
- print "<refnamediv>\n";
- print " <refname>typedef " . $args{'typedef'} . "</refname>\n";
- print " <refpurpose>\n";
- print " ";
- output_highlight ($args{'purpose'});
- print " </refpurpose>\n";
- print "</refnamediv>\n";
-
- print "<refsynopsisdiv>\n";
- print " <title>Synopsis</title>\n";
- print " <synopsis>typedef " . $args{'typedef'} . ";</synopsis>\n";
- print "</refsynopsisdiv>\n";
-
- output_section_xml(@_);
-
- print "</refentry>\n\n";
-}
-
-# output in XML DocBook
-sub output_blockhead_xml(%) {
- my %args = %{$_[0]};
- my ($parameter, $section);
- my $count;
-
- my $id = $args{'module'};
- $id =~ s/[^A-Za-z0-9]/-/g;
-
- # print out each section
- $lineprefix=" ";
- foreach $section (@{$args{'sectionlist'}}) {
- if (!$args{'content-only'}) {
- print "<refsect1>\n <title>$section</title>\n";
- }
- if ($section =~ m/EXAMPLE/i) {
- print "<example><para>\n";
- $output_preformatted = 1;
- } else {
- print "<para>\n";
- }
- output_highlight($args{'sections'}{$section});
- $output_preformatted = 0;
- if ($section =~ m/EXAMPLE/i) {
- print "</para></example>\n";
- } else {
- print "</para>";
- }
- if (!$args{'content-only'}) {
- print "\n</refsect1>\n";
- }
- }
-
- print "\n\n";
-}
-
-# output in XML DocBook
-sub output_function_gnome {
- my %args = %{$_[0]};
- my ($parameter, $section);
- my $count;
- my $id;
-
- $id = $args{'module'} . "-" . $args{'function'};
- $id =~ s/[^A-Za-z0-9]/-/g;
-
- print "<sect2>\n";
- print " <title id=\"$id\">" . $args{'function'} . "</title>\n";
-
- print " <funcsynopsis>\n";
- print " <funcdef>" . $args{'functiontype'} . " ";
- print "<function>" . $args{'function'} . " ";
- print "</function></funcdef>\n";
-
- $count = 0;
- if ($#{$args{'parameterlist'}} >= 0) {
- foreach $parameter (@{$args{'parameterlist'}}) {
- $type = $args{'parametertypes'}{$parameter};
- if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
- # pointer-to-function
- print " <paramdef>$1 <parameter>$parameter</parameter>)\n";
- print " <funcparams>$2</funcparams></paramdef>\n";
- } else {
- print " <paramdef>" . $type;
- print " <parameter>$parameter</parameter></paramdef>\n";
- }
- }
- } else {
- print " <void>\n";
- }
- print " </funcsynopsis>\n";
- if ($#{$args{'parameterlist'}} >= 0) {
- print " <informaltable pgwide=\"1\" frame=\"none\" role=\"params\">\n";
- print "<tgroup cols=\"2\">\n";
- print "<colspec colwidth=\"2*\">\n";
- print "<colspec colwidth=\"8*\">\n";
- print "<tbody>\n";
- foreach $parameter (@{$args{'parameterlist'}}) {
- my $parameter_name = $parameter;
- $parameter_name =~ s/\[.*//;
-
- print " <row><entry align=\"right\"><parameter>$parameter</parameter></entry>\n";
- print " <entry>\n";
- $lineprefix=" ";
- output_highlight($args{'parameterdescs'}{$parameter_name});
- print " </entry></row>\n";
- }
- print " </tbody></tgroup></informaltable>\n";
- } else {
- print " <para>\n None\n </para>\n";
- }
-
- # print out each section
- $lineprefix=" ";
- foreach $section (@{$args{'sectionlist'}}) {
- print "<simplesect>\n <title>$section</title>\n";
- if ($section =~ m/EXAMPLE/i) {
- print "<example><programlisting>\n";
- $output_preformatted = 1;
- } else {
- }
- print "<para>\n";
- output_highlight($args{'sections'}{$section});
- $output_preformatted = 0;
- print "</para>\n";
- if ($section =~ m/EXAMPLE/i) {
- print "</programlisting></example>\n";
- } else {
- }
- print " </simplesect>\n";
- }
-
- print "</sect2>\n\n";
-}
-
##
# output function in man
sub output_function_man(%) {
print ".SH NAME\n";
print $args{'type'} . " " . $args{'struct'} . " \\- " . $args{'purpose'} . "\n";
+ my $declaration = $args{'definition'};
+ $declaration =~ s/\t/ /g;
+ $declaration =~ s/\n/"\n.br\n.BI \"/g;
print ".SH SYNOPSIS\n";
print $args{'type'} . " " . $args{'struct'} . " {\n.br\n";
-
- foreach my $parameter (@{$args{'parameterlist'}}) {
- if ($parameter =~ /^#/) {
- print ".BI \"$parameter\"\n.br\n";
- next;
- }
- my $parameter_name = $parameter;
- $parameter_name =~ s/\[.*//;
-
- ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
- $type = $args{'parametertypes'}{$parameter};
- if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
- # pointer-to-function
- print ".BI \" " . $1 . "\" " . $parameter . " \") (" . $2 . ")" . "\"\n;\n";
- } elsif ($type =~ m/^(.*?)\s*(:.*)/) {
- # bitfield
- print ".BI \" " . $1 . "\ \" " . $parameter . $2 . " \"" . "\"\n;\n";
- } else {
- $type =~ s/([^\*])$/$1 /;
- print ".BI \" " . $type . "\" " . $parameter . " \"" . "\"\n;\n";
- }
- print "\n.br\n";
- }
- print "};\n.br\n";
+ print ".BI \"$declaration\n};\n.br\n\n";
print ".SH Members\n";
foreach $parameter (@{$args{'parameterlist'}}) {
}
##
-# output in text
-sub output_function_text(%) {
- my %args = %{$_[0]};
- my ($parameter, $section);
- my $start;
-
- print "Name:\n\n";
- print $args{'function'} . " - " . $args{'purpose'} . "\n";
-
- print "\nSynopsis:\n\n";
- if ($args{'functiontype'} ne "") {
- $start = $args{'functiontype'} . " " . $args{'function'} . " (";
- } else {
- $start = $args{'function'} . " (";
- }
- print $start;
-
- my $count = 0;
- foreach my $parameter (@{$args{'parameterlist'}}) {
- $type = $args{'parametertypes'}{$parameter};
- if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
- # pointer-to-function
- print $1 . $parameter . ") (" . $2;
- } else {
- print $type . " " . $parameter;
- }
- if ($count != $#{$args{'parameterlist'}}) {
- $count++;
- print ",\n";
- print " " x length($start);
- } else {
- print ");\n\n";
- }
- }
-
- print "Arguments:\n\n";
- foreach $parameter (@{$args{'parameterlist'}}) {
- my $parameter_name = $parameter;
- $parameter_name =~ s/\[.*//;
-
- print $parameter . "\n\t" . $args{'parameterdescs'}{$parameter_name} . "\n";
- }
- output_section_text(@_);
-}
-
-#output sections in text
-sub output_section_text(%) {
- my %args = %{$_[0]};
- my $section;
-
- print "\n";
- foreach $section (@{$args{'sectionlist'}}) {
- print "$section:\n\n";
- output_highlight($args{'sections'}{$section});
- }
- print "\n\n";
-}
-
-# output enum in text
-sub output_enum_text(%) {
- my %args = %{$_[0]};
- my ($parameter);
- my $count;
- print "Enum:\n\n";
-
- print "enum " . $args{'enum'} . " - " . $args{'purpose'} . "\n\n";
- print "enum " . $args{'enum'} . " {\n";
- $count = 0;
- foreach $parameter (@{$args{'parameterlist'}}) {
- print "\t$parameter";
- if ($count != $#{$args{'parameterlist'}}) {
- $count++;
- print ",";
- }
- print "\n";
- }
- print "};\n\n";
-
- print "Constants:\n\n";
- foreach $parameter (@{$args{'parameterlist'}}) {
- print "$parameter\n\t";
- print $args{'parameterdescs'}{$parameter} . "\n";
- }
-
- output_section_text(@_);
-}
-
-# output typedef in text
-sub output_typedef_text(%) {
- my %args = %{$_[0]};
- my ($parameter);
- my $count;
- print "Typedef:\n\n";
-
- print "typedef " . $args{'typedef'} . " - " . $args{'purpose'} . "\n";
- output_section_text(@_);
-}
-
-# output struct as text
-sub output_struct_text(%) {
- my %args = %{$_[0]};
- my ($parameter);
-
- print $args{'type'} . " " . $args{'struct'} . " - " . $args{'purpose'} . "\n\n";
- print $args{'type'} . " " . $args{'struct'} . " {\n";
- foreach $parameter (@{$args{'parameterlist'}}) {
- if ($parameter =~ /^#/) {
- print "$parameter\n";
- next;
- }
-
- my $parameter_name = $parameter;
- $parameter_name =~ s/\[.*//;
-
- ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
- $type = $args{'parametertypes'}{$parameter};
- if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
- # pointer-to-function
- print "\t$1 $parameter) ($2);\n";
- } elsif ($type =~ m/^(.*?)\s*(:.*)/) {
- # bitfield
- print "\t$1 $parameter$2;\n";
- } else {
- print "\t" . $type . " " . $parameter . ";\n";
- }
- }
- print "};\n\n";
-
- print "Members:\n\n";
- foreach $parameter (@{$args{'parameterlist'}}) {
- ($parameter =~ /^#/) && next;
-
- my $parameter_name = $parameter;
- $parameter_name =~ s/\[.*//;
-
- ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
- print "$parameter\n\t";
- print $args{'parameterdescs'}{$parameter_name} . "\n";
- }
- print "\n";
- output_section_text(@_);
-}
-
-sub output_blockhead_text(%) {
- my %args = %{$_[0]};
- my ($parameter, $section);
-
- foreach $section (@{$args{'sectionlist'}}) {
- print " $section:\n";
- print " -> ";
- output_highlight($args{'sections'}{$section});
- }
-}
-
-##
# output in restructured text
#
print "**Definition**\n\n";
print "::\n\n";
- print " " . $args{'type'} . " " . $args{'struct'} . " {\n";
- foreach $parameter (@{$args{'parameterlist'}}) {
- if ($parameter =~ /^#/) {
- print " " . "$parameter\n";
- next;
- }
-
- my $parameter_name = $parameter;
- $parameter_name =~ s/\[.*//;
-
- ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
- $type = $args{'parametertypes'}{$parameter};
- if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
- # pointer-to-function
- print " $1 $parameter) ($2);\n";
- } elsif ($type =~ m/^(.*?)\s*(:.*)/) {
- # bitfield
- print " $1 $parameter$2;\n";
- } else {
- print " " . $type . " " . $parameter . ";\n";
- }
- }
- print " };\n\n";
+ my $declaration = $args{'definition'};
+ $declaration =~ s/\t/ /g;
+ print " " . $args{'type'} . " " . $args{'struct'} . " {\n$declaration };\n\n";
print "**Members**\n\n";
$lineprefix = " ";
output_section_rst(@_);
}
+## none mode output functions
-## list mode output functions
-
-sub output_function_list(%) {
- my %args = %{$_[0]};
-
- print $args{'function'} . "\n";
+sub output_function_none(%) {
}
-# output enum in list
-sub output_enum_list(%) {
- my %args = %{$_[0]};
- print $args{'enum'} . "\n";
+sub output_enum_none(%) {
}
-# output typedef in list
-sub output_typedef_list(%) {
- my %args = %{$_[0]};
- print $args{'typedef'} . "\n";
+sub output_typedef_none(%) {
}
-# output struct as list
-sub output_struct_list(%) {
- my %args = %{$_[0]};
-
- print $args{'struct'} . "\n";
+sub output_struct_none(%) {
}
-sub output_blockhead_list(%) {
- my %args = %{$_[0]};
- my ($parameter, $section);
-
- foreach $section (@{$args{'sectionlist'}}) {
- print "DOC: $section\n";
- }
+sub output_blockhead_none(%) {
}
##
sub dump_struct($$) {
my $x = shift;
my $file = shift;
- my $nested;
if ($x =~ /(struct|union)\s+(\w+)\s*{(.*)}/) {
my $decl_type = $1;
$declaration_name = $2;
my $members = $3;
- # ignore embedded structs or unions
- $members =~ s/({.*})//g;
- $nested = $1;
-
# ignore members marked private:
$members =~ s/\/\*\s*private:.*?\/\*\s*public:.*?\*\///gosi;
$members =~ s/\/\*\s*private:.*//gosi;
# strip comments:
$members =~ s/\/\*.*?\*\///gos;
- $nested =~ s/\/\*.*?\*\///gos;
# strip attributes
$members =~ s/__attribute__\s*\(\([a-z,_\*\s\(\)]*\)\)//i;
$members =~ s/__aligned\s*\([^;]*\)//gos;
$members =~ s/\s*CRYPTO_MINALIGN_ATTR//gos;
# replace DECLARE_BITMAP
- $members =~ s/DECLARE_BITMAP\s*\(([^,)]+), ([^,)]+)\)/unsigned long $1\[BITS_TO_LONGS($2)\]/gos;
+ $members =~ s/DECLARE_BITMAP\s*\(([^,)]+),\s*([^,)]+)\)/unsigned long $1\[BITS_TO_LONGS($2)\]/gos;
# replace DECLARE_HASHTABLE
- $members =~ s/DECLARE_HASHTABLE\s*\(([^,)]+), ([^,)]+)\)/unsigned long $1\[1 << (($2) - 1)\]/gos;
-
- create_parameterlist($members, ';', $file);
- check_sections($file, $declaration_name, $decl_type, $sectcheck, $struct_actual, $nested);
-
+ $members =~ s/DECLARE_HASHTABLE\s*\(([^,)]+),\s*([^,)]+)\)/unsigned long $1\[1 << (($2) - 1)\]/gos;
+ # replace DECLARE_KFIFO
+ $members =~ s/DECLARE_KFIFO\s*\(([^,)]+),\s*([^,)]+),\s*([^,)]+)\)/$2 \*$1/gos;
+ # replace DECLARE_KFIFO_PTR
+ $members =~ s/DECLARE_KFIFO_PTR\s*\(([^,)]+),\s*([^,)]+)\)/$2 \*$1/gos;
+
+ my $declaration = $members;
+
+ # Split nested struct/union elements as newer ones
+ while ($members =~ m/(struct|union)([^\{\};]+)\{([^\{\}]*)\}([^\{\}\;]*)\;/) {
+ my $newmember;
+ my $maintype = $1;
+ my $ids = $4;
+ my $content = $3;
+ foreach my $id(split /,/, $ids) {
+ $newmember .= "$maintype $id; ";
+
+ $id =~ s/[:\[].*//;
+ $id =~ s/^\s*\**(\S+)\s*/$1/;
+ foreach my $arg (split /;/, $content) {
+ next if ($arg =~ m/^\s*$/);
+ if ($arg =~ m/^([^\(]+\(\*?\s*)([\w\.]*)(\s*\).*)/) {
+ # pointer-to-function
+ my $type = $1;
+ my $name = $2;
+ my $extra = $3;
+ next if (!$name);
+ if ($id =~ m/^\s*$/) {
+ # anonymous struct/union
+ $newmember .= "$type$name$extra; ";
+ } else {
+ $newmember .= "$type$id.$name$extra; ";
+ }
+ } else {
+ my $type;
+ my $names;
+ $arg =~ s/^\s+//;
+ $arg =~ s/\s+$//;
+ # Handle bitmaps
+ $arg =~ s/:\s*\d+\s*//g;
+ # Handle arrays
+ $arg =~ s/\[\S+\]//g;
+ # The type may have multiple words,
+ # and multiple IDs can be defined, like:
+ # const struct foo, *bar, foobar
+ # So, we remove spaces when parsing the
+ # names, in order to match just names
+ # and commas for the names
+ $arg =~ s/\s*,\s*/,/g;
+ if ($arg =~ m/(.*)\s+([\S+,]+)/) {
+ $type = $1;
+ $names = $2;
+ } else {
+ $newmember .= "$arg; ";
+ next;
+ }
+ foreach my $name (split /,/, $names) {
+ $name =~ s/^\s*\**(\S+)\s*/$1/;
+ next if (($name =~ m/^\s*$/));
+ if ($id =~ m/^\s*$/) {
+ # anonymous struct/union
+ $newmember .= "$type $name; ";
+ } else {
+ $newmember .= "$type $id.$name; ";
+ }
+ }
+ }
+ }
+ }
+ $members =~ s/(struct|union)([^\{\};]+)\{([^\{\}]*)}([^\{\}\;]*)\;/$newmember/;
+ }
+
+ # Ignore other nested elements, like enums
+ $members =~ s/({[^\{\}]*})//g;
+
+ create_parameterlist($members, ';', $file, $declaration_name);
+ check_sections($file, $declaration_name, $decl_type, $sectcheck, $struct_actual);
+
+ # Adjust declaration for better display
+ $declaration =~ s/([{;])/$1\n/g;
+ $declaration =~ s/}\s+;/};/g;
+ # Better handle inlined enums
+ do {} while ($declaration =~ s/(enum\s+{[^}]+),([^\n])/$1,\n$2/);
+
+ my @def_args = split /\n/, $declaration;
+ my $level = 1;
+ $declaration = "";
+ foreach my $clause (@def_args) {
+ $clause =~ s/^\s+//;
+ $clause =~ s/\s+$//;
+ $clause =~ s/\s+/ /;
+ next if (!$clause);
+ $level-- if ($clause =~ m/(})/ && $level > 1);
+ if (!($clause =~ m/^\s*#/)) {
+ $declaration .= "\t" x $level;
+ }
+ $declaration .= "\t" . $clause . "\n";
+ $level++ if ($clause =~ m/({)/ && !($clause =~m/}/));
+ }
output_declaration($declaration_name,
'struct',
{'struct' => $declaration_name,
'module' => $modulename,
+ 'definition' => $declaration,
'parameterlist' => \@parameterlist,
'parameterdescs' => \%parameterdescs,
'parametertypes' => \%parametertypes,
}
}
+
+sub show_warnings($$) {
+ my $functype = shift;
+ my $name = shift;
+
+ return 1 if ($output_selection == OUTPUT_ALL);
+
+ if ($output_selection == OUTPUT_EXPORTED) {
+ if (defined($function_table{$name})) {
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+ if ($output_selection == OUTPUT_INTERNAL) {
+ if (!($functype eq "function" && defined($function_table{$name}))) {
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+ if ($output_selection == OUTPUT_INCLUDE) {
+ if (defined($function_table{$name})) {
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+ if ($output_selection == OUTPUT_EXCLUDE) {
+ if (!defined($function_table{$name})) {
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+ die("Please add the new output type at show_warnings()");
+}
+
sub dump_enum($$) {
my $x = shift;
my $file = shift;
push @parameterlist, $arg;
if (!$parameterdescs{$arg}) {
$parameterdescs{$arg} = $undescribed;
- print STDERR "${file}:$.: warning: Enum value '$arg' ".
- "not described in enum '$declaration_name'\n";
+ if (show_warnings("enum", $declaration_name)) {
+ print STDERR "${file}:$.: warning: Enum value '$arg' not described in enum '$declaration_name'\n";
+ }
}
$_members{$arg} = 1;
}
while (my ($k, $v) = each %parameterdescs) {
if (!exists($_members{$k})) {
- print STDERR "${file}:$.: warning: Excess enum value " .
- "'$k' description in '$declaration_name'\n";
+ if (show_warnings("enum", $declaration_name)) {
+ print STDERR "${file}:$.: warning: Excess enum value '$k' description in '$declaration_name'\n";
+ }
}
}
$declaration_name = $2;
my $args = $3;
- create_parameterlist($args, ',', $file);
+ create_parameterlist($args, ',', $file, $declaration_name);
output_declaration($declaration_name,
'function',
$struct_actual = $struct_actual . $actual . " ";
}
-sub create_parameterlist($$$) {
+sub create_parameterlist($$$$) {
my $args = shift;
my $splitter = shift;
my $file = shift;
+ my $declaration_name = shift;
my $type;
my $param;
} elsif ($arg =~ m/\(.+\)\s*\(/) {
# pointer-to-function
$arg =~ tr/#/,/;
- $arg =~ m/[^\(]+\(\*?\s*(\w*)\s*\)/;
+ $arg =~ m/[^\(]+\(\*?\s*([\w\.]*)\s*\)/;
$param = $1;
$type = $arg;
$type =~ s/([^\(]+\(\*?)\s*$param/$1/;
save_struct_actual($param);
- push_parameter($param, $type, $file);
+ push_parameter($param, $type, $file, $declaration_name);
} elsif ($arg) {
$arg =~ s/\s*:\s*/:/g;
$arg =~ s/\s*\[/\[/g;
foreach $param (@args) {
if ($param =~ m/^(\*+)\s*(.*)/) {
save_struct_actual($2);
- push_parameter($2, "$type $1", $file);
+ push_parameter($2, "$type $1", $file, $declaration_name);
}
elsif ($param =~ m/(.*?):(\d+)/) {
if ($type ne "") { # skip unnamed bit-fields
save_struct_actual($1);
- push_parameter($1, "$type:$2", $file)
+ push_parameter($1, "$type:$2", $file, $declaration_name)
}
}
else {
save_struct_actual($param);
- push_parameter($param, $type, $file);
+ push_parameter($param, $type, $file, $declaration_name);
}
}
}
}
}
-sub push_parameter($$$) {
+sub push_parameter($$$$) {
my $param = shift;
my $type = shift;
my $file = shift;
+ my $declaration_name = shift;
if (($anon_struct_union == 1) && ($type eq "") &&
($param eq "}")) {
# warn if parameter has no description
# (but ignore ones starting with # as these are not parameters
# but inline preprocessor statements);
- # also ignore unnamed structs/unions;
- if (!$anon_struct_union) {
+ # Note: It will also ignore void params and unnamed structs/unions
if (!defined $parameterdescs{$param} && $param !~ /^#/) {
+ $parameterdescs{$param} = $undescribed;
- $parameterdescs{$param} = $undescribed;
-
- if (($type eq 'function') || ($type eq 'enum')) {
- print STDERR "${file}:$.: warning: Function parameter ".
- "or member '$param' not " .
- "described in '$declaration_name'\n";
- }
- print STDERR "${file}:$.: warning:" .
- " No description found for parameter '$param'\n";
- ++$warnings;
- }
+ if (show_warnings($type, $declaration_name)) {
+ print STDERR
+ "${file}:$.: warning: Function parameter or member '$param' not described in '$declaration_name'\n";
+ ++$warnings;
+ }
}
$param = xml_escape($param);
$parametertypes{$param} = $type;
}
-sub check_sections($$$$$$) {
- my ($file, $decl_name, $decl_type, $sectcheck, $prmscheck, $nested) = @_;
+sub check_sections($$$$$) {
+ my ($file, $decl_name, $decl_type, $sectcheck, $prmscheck) = @_;
my @sects = split ' ', $sectcheck;
my @prms = split ' ', $prmscheck;
my $err;
"'$sects[$sx]' " .
"description in '$decl_name'\n";
++$warnings;
- } else {
- if ($nested !~ m/\Q$sects[$sx]\E/) {
- print STDERR "${file}:$.: warning: " .
- "Excess $decl_type member " .
- "'$sects[$sx]' " .
- "description in '$decl_name'\n";
- ++$warnings;
- }
}
}
}
$declaration_name = $2;
my $args = $3;
- create_parameterlist($args, ',', $file);
+ create_parameterlist($args, ',', $file, $declaration_name);
} else {
print STDERR "${file}:$.: warning: cannot understand function prototype: '$prototype'\n";
return;
}
my $prms = join " ", @parameterlist;
- check_sections($file, $declaration_name, "function", $sectcheck, $prms, "");
+ check_sections($file, $declaration_name, "function", $sectcheck, $prms);
# This check emits a lot of warnings at the moment, because many
# functions don't have a 'Return' doc section. So until the number
sub syscall_munge() {
my $void = 0;
- $prototype =~ s@[\r\n\t]+@ @gos; # strip newlines/CR's/tabs
+ $prototype =~ s@[\r\n]+@ @gos; # strip newlines/CR's
## if ($prototype =~ m/SYSCALL_DEFINE0\s*\(\s*(a-zA-Z0-9_)*\s*\)/) {
if ($prototype =~ m/SYSCALL_DEFINE0/) {
$void = 1;
# just before actual output; (this is done by local_unescape())
sub xml_escape($) {
my $text = shift;
- if (($output_mode eq "text") || ($output_mode eq "man")) {
+ if ($output_mode eq "man") {
return $text;
}
$text =~ s/\&/\\\\\\amp;/g;
# xml_unescape: reverse the effects of xml_escape
sub xml_unescape($) {
my $text = shift;
- if (($output_mode eq "text") || ($output_mode eq "man")) {
+ if ($output_mode eq "man") {
return $text;
}
$text =~ s/\\\\\\amp;/\&/g;
# local escape strings look like: '\\\\menmonic:' (that's 4 backslashes)
sub local_unescape($) {
my $text = shift;
- if (($output_mode eq "text") || ($output_mode eq "man")) {
+ if ($output_mode eq "man") {
return $text;
}
$text =~ s/\\\\\\\\lt:/</g;
while (s/\\\s*$//) {
$_ .= <IN>;
}
+ # Replace tabs by spaces
+ while ($_ =~ s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e) {};
if ($state == STATE_NORMAL) {
if (/$doc_start/o) {
$state = STATE_NAME; # next line is always the function name
$in_purpose = 0;
$contents = $newcontents;
$new_start_line = $.;
- while ((substr($contents, 0, 1) eq " ") ||
- substr($contents, 0, 1) eq "\t") {
+ while (substr($contents, 0, 1) eq " ") {
$contents = substr($contents, 1);
}
if ($contents ne "") {
$contents = $2;
$new_start_line = $.;
if ($contents ne "") {
- while ((substr($contents, 0, 1) eq " ") ||
- substr($contents, 0, 1) eq "\t") {
+ while (substr($contents, 0, 1) eq " ") {
$contents = substr($contents, 1);
}
$contents .= "\n";
}
}
if ($initial_section_counter == $section_counter) {
- print STDERR "${file}:1: warning: no structured comments found\n";
+ if ($output_mode ne "none") {
+ print STDERR "${file}:1: warning: no structured comments found\n";
+ }
if (($output_selection == OUTPUT_INCLUDE) && ($show_not_found == 1)) {
print STDERR " Was looking for '$_'.\n" for keys %function_table;
}
- if ($output_mode eq "xml") {
- # The template wants at least one RefEntry here; make one.
- print "<refentry>\n";
- print " <refnamediv>\n";
- print " <refname>\n";
- print " ${orig_file}\n";
- print " </refname>\n";
- print " <refpurpose>\n";
- print " Document generation inconsistency\n";
- print " </refpurpose>\n";
- print " </refnamediv>\n";
- print " <refsect1>\n";
- print " <title>\n";
- print " Oops\n";
- print " </title>\n";
- print " <warning>\n";
- print " <para>\n";
- print " The template for this document tried to insert\n";
- print " the structured comment from the file\n";
- print " <filename>${orig_file}</filename> at this point,\n";
- print " but none was found.\n";
- print " This dummy section is inserted to allow\n";
- print " generation to continue.\n";
- print " </para>\n";
- print " </warning>\n";
- print " </refsect1>\n";
- print "</refentry>\n";
- }
}
}
print STDERR "$warnings warnings\n";
}
-exit($errors);
+exit($output_mode eq "none" ? 0 : $errors);
ipc_tmo = _DEFAULT_UXSOCK_TIMEOUT;
invoke:
- _debug(ctx, "Invoking IPC command '%s' with IPC tmo %u miliseconds",
+ _debug(ctx, "Invoking IPC command '%s' with IPC tmo %u milliseconds",
cmd, ipc_tmo);
flag_check_tmo = false;
if (mpath_process_cmd(fd, cmd, output, ipc_tmo) != 0) {
thread[i].param.noisy = noisy;
thread[i].param.status = MPATH_PR_SKIP;
- condlog (3, "THRED ID [%d] INFO]", i);
+ condlog (3, "THREAD ID [%d] INFO]", i);
condlog (3, "rq_servact=%d ", thread[i].param.rq_servact);
condlog (3, "rq_scope=%d ", thread[i].param.rq_scope);
condlog (3, "rq_type=%d ", thread[i].param.rq_type);
#include <libudev.h>
#include "mpath_pr_ioctl.h"
#include "mpath_persist.h"
+#include "unaligned.h"
#include "debug.h"
memcpy(&fdesc.key, p, 8 );
fdesc.flag = p[12];
fdesc.scope_type = p[13];
- fdesc.rtpi = ((p[18] << 8) | p[19]);
+ fdesc.rtpi = get_unaligned_be16(&p[18]);
- tid_len_len = ((p[20] << 24) | (p[21] << 16) |
- (p[22] << 8) | p[23]);
+ tid_len_len = get_unaligned_be32(&p[20]);
if (tid_len_len > 0)
decode_transport_id( &fdesc, &p[24], tid_len_len);
jump = 24;
break;
case MPATH_PROTOCOL_ID_ISCSI:
- num = ((p[2] << 8) | p[3]);
+ num = get_unaligned_be16(&p[2]);
memcpy(&fdesc->trnptid.iscsi_name, &p[4], num);
jump = (((num + 4) < 24) ? 24 : num + 4);
break;
$(RM) core *.a *.o *.gz *.so
OBJS := $(LIBS:libcheck%.so=%.o) libsg.o directio.o
+.SECONDARY: $(OBJS)
+
include $(wildcard $(OBJS:.o=.d))
dep_clean:
#include "checkers.h"
#include "../libmultipath/sg_include.h"
+#include "../libmultipath/unaligned.h"
#define TUR_CMD_LEN 6
#define INQUIRY_CMDLEN 6
if (evpd)
inqCmdBlk[1] |= 1;
inqCmdBlk[2] = (unsigned char) pg_op;
- inqCmdBlk[3] = (unsigned char)((mx_resp_len >> 8) & 0xff);
- inqCmdBlk[4] = (unsigned char) (mx_resp_len & 0xff);
+ put_unaligned_be16(mx_resp_len, &inqCmdBlk[3]);
memset(&io_hdr, 0, sizeof (struct sg_io_hdr));
memset(sense_b, 0, SENSE_BUFF_LEN);
io_hdr.interface_id = 'S';
#define DEFAULT_FORCE_SYNC 0
#define DEFAULT_PARTITION_DELIM NULL
#define DEFAULT_SKIP_KPARTX SKIP_KPARTX_OFF
-#define DEFAULT_DISABLE_CHANGED_WWIDS 0
+#define DEFAULT_DISABLE_CHANGED_WWIDS 1
#define DEFAULT_MAX_SECTORS_KB MAX_SECTORS_KB_UNDEF
#define DEFAULT_GHOST_DELAY GHOST_DELAY_OFF
#include <sys/types.h>
#include <time.h>
-#define FREE_CONST(p) do { free((void*)(unsigned long)p); p = NULL; } while(0)
#define MAX_WAIT 5
#define LOOPS_PER_SEC 5
void dm_reassign_deps(char *table, const char *dep, const char *newdep)
{
- char *n;
- const char *p, *newtable;
+ char *n, *newtable;
+ const char *p;
newtable = strdup(table);
if (!newtable)
n += strlen(newdep);
p += strlen(dep);
strcat(n, p);
- FREE_CONST(newtable);
+ FREE(newtable);
}
int dm_reassign_table(const char *name, char *old, char *new)
declare_def_snprint(checker_timeout, print_nonzero)
declare_def_handler(flush_on_last_del, set_yes_no_undef)
-declare_def_snprint_defint(flush_on_last_del, print_yes_no_undef, YNU_NO)
+declare_def_snprint_defint(flush_on_last_del, print_yes_no_undef, DEFAULT_FLUSH)
declare_ovr_handler(flush_on_last_del, set_yes_no_undef)
declare_ovr_snprint(flush_on_last_del, print_yes_no_undef)
declare_hw_handler(flush_on_last_del, set_yes_no_undef)
declare_mp_snprint(flush_on_last_del, print_yes_no_undef)
declare_def_handler(user_friendly_names, set_yes_no_undef)
-declare_def_snprint_defint(user_friendly_names, print_yes_no_undef, YNU_NO)
+declare_def_snprint_defint(user_friendly_names, print_yes_no_undef,
+ DEFAULT_USER_FRIENDLY_NAMES)
declare_ovr_handler(user_friendly_names, set_yes_no_undef)
declare_ovr_snprint(user_friendly_names, print_yes_no_undef)
declare_hw_handler(user_friendly_names, set_yes_no_undef)
declare_def_snprint(prkeys_file, print_str)
declare_def_handler(retain_hwhandler, set_yes_no_undef)
-declare_def_snprint_defint(retain_hwhandler, print_yes_no_undef, YNU_NO)
+declare_def_snprint_defint(retain_hwhandler, print_yes_no_undef,
+ DEFAULT_RETAIN_HWHANDLER)
declare_ovr_handler(retain_hwhandler, set_yes_no_undef)
declare_ovr_snprint(retain_hwhandler, print_yes_no_undef)
declare_hw_handler(retain_hwhandler, set_yes_no_undef)
declare_hw_snprint(retain_hwhandler, print_yes_no_undef)
declare_def_handler(detect_prio, set_yes_no_undef)
-declare_def_snprint_defint(detect_prio, print_yes_no_undef, YNU_NO)
+declare_def_snprint_defint(detect_prio, print_yes_no_undef,
+ DEFAULT_DETECT_PRIO)
declare_ovr_handler(detect_prio, set_yes_no_undef)
declare_ovr_snprint(detect_prio, print_yes_no_undef)
declare_hw_handler(detect_prio, set_yes_no_undef)
declare_hw_snprint(detect_prio, print_yes_no_undef)
declare_def_handler(detect_checker, set_yes_no_undef)
-declare_def_snprint_defint(detect_checker, print_yes_no_undef, YNU_NO)
+declare_def_snprint_defint(detect_checker, print_yes_no_undef,
+ DEFAULT_DETECT_CHECKER)
declare_ovr_handler(detect_checker, set_yes_no_undef)
declare_ovr_snprint(detect_checker, print_yes_no_undef)
declare_hw_handler(detect_checker, set_yes_no_undef)
declare_def_snprint(force_sync, print_yes_no)
declare_def_handler(deferred_remove, set_yes_no_undef)
-declare_def_snprint_defint(deferred_remove, print_yes_no_undef, YNU_NO)
+declare_def_snprint_defint(deferred_remove, print_yes_no_undef,
+ DEFAULT_DEFERRED_REMOVE)
declare_ovr_handler(deferred_remove, set_yes_no_undef)
declare_ovr_snprint(deferred_remove, print_yes_no_undef)
declare_hw_handler(deferred_remove, set_yes_no_undef)
declare_def_snprint(strict_timing, print_yes_no)
declare_def_handler(skip_kpartx, set_yes_no_undef)
-declare_def_snprint_defint(skip_kpartx, print_yes_no_undef, YNU_NO)
+declare_def_snprint_defint(skip_kpartx, print_yes_no_undef,
+ DEFAULT_SKIP_KPARTX)
declare_ovr_handler(skip_kpartx, set_yes_no_undef)
declare_ovr_snprint(skip_kpartx, print_yes_no_undef)
declare_hw_handler(skip_kpartx, set_yes_no_undef)
}
declare_def_handler(fast_io_fail, set_fast_io_fail)
-declare_def_snprint_defint(fast_io_fail, print_fast_io_fail, DEFAULT_FAST_IO_FAIL)
+declare_def_snprint_defint(fast_io_fail, print_fast_io_fail,
+ DEFAULT_FAST_IO_FAIL)
declare_ovr_handler(fast_io_fail, set_fast_io_fail)
declare_ovr_snprint(fast_io_fail, print_fast_io_fail)
declare_hw_handler(fast_io_fail, set_fast_io_fail)
}
declare_def_handler(rr_weight, set_rr_weight)
-declare_def_snprint_defint(rr_weight, print_rr_weight, RR_WEIGHT_NONE)
+declare_def_snprint_defint(rr_weight, print_rr_weight, DEFAULT_RR_WEIGHT)
declare_ovr_handler(rr_weight, set_rr_weight)
declare_ovr_snprint(rr_weight, print_rr_weight)
declare_hw_handler(rr_weight, set_rr_weight)
#include "discovery.h"
#include "prio.h"
#include "defaults.h"
+#include "unaligned.h"
#include "prioritizers/alua_rtpg.h"
#include "foreign.h"
if (!pp)
return PATHINFO_FAILED;
- if(wwid)
- strncpy(pp->wwid, wwid, sizeof(pp->wwid));
+ if (wwid)
+ strlcpy(pp->wwid, wwid, sizeof(pp->wwid));
if (safe_sprintf(pp->dev, "%s", devname)) {
condlog(0, "pp->dev too small");
#define DEFAULT_SGIO_LEN 254
+/* Query VPD page @pg. Returns number of INQUIRY bytes
+ upon success and -1 upon failure. */
static int
sgio_get_vpd (unsigned char * buff, int maxlen, int fd, int pg)
{
}
retry:
if (0 == do_inq(fd, 0, 1, pg, buff, len)) {
- len = buff[3] + (buff[2] << 8);
+ len = get_unaligned_be16(&buff[2]) + 4;
if (len >= maxlen)
return len;
if (len > DEFAULT_SGIO_LEN)
parse_vpd_pg80(const unsigned char *in, char *out, size_t out_len)
{
char *p = NULL;
- int len = in[3] + (in[2] << 8);
+ int len = get_unaligned_be16(&in[2]);
if (len >= out_len) {
condlog(2, "vpd pg80 overflow, %d/%d bytes required",
pg, buff[1]);
return -ENODATA;
}
- buff_len = (buff[2] << 8) + buff[3] + 4;
+ buff_len = get_unaligned_be16(&buff[2]) + 4;
if (buff_len > 4096)
condlog(3, "vpd pg%02x page truncated", pg);
unsigned char buff[4096];
memset(buff, 0x0, 4096);
- if (sgio_get_vpd(buff, 4096, fd, pg) <= 0) {
+ if (sgio_get_vpd(buff, 4096, fd, pg) < 0) {
condlog(3, "failed to issue vpd inquiry for pg%02x",
pg);
return -errno;
pg, buff[1]);
return -ENODATA;
}
- buff_len = (buff[2] << 8) + buff[3] + 4;
+ buff_len = get_unaligned_be16(&buff[2]) + 4;
if (buff_len > 4096)
condlog(3, "vpd pg%02x page truncated", pg);
parent = udev_device_get_parent(parent);
}
+ if (!parent)
+ return -EINVAL;
+
return get_vpd_sysfs(parent, 0x83, pp->wwid, WWID_SIZE);
}
+static ssize_t scsi_uid_fallback(struct path *pp, int path_state,
+ const char **origin)
+{
+ ssize_t len = 0;
+ int retrigger;
+ struct config *conf;
+
+ conf = get_multipath_config();
+ retrigger = conf->retrigger_tries;
+ put_multipath_config(conf);
+ if (pp->retriggers >= retrigger &&
+ !strcmp(pp->uid_attribute, DEFAULT_UID_ATTRIBUTE)) {
+ len = get_vpd_uid(pp);
+ *origin = "sysfs";
+ pp->uid_attribute = NULL;
+ if (len < 0 && path_state == PATH_UP) {
+ condlog(1, "%s: failed to get sysfs uid: %s",
+ pp->dev, strerror(-len));
+ len = get_vpd_sgio(pp->fd, 0x83, pp->wwid,
+ WWID_SIZE);
+ *origin = "sgio";
+ }
+ }
+ return len;
+}
+
int
get_uid (struct path * pp, int path_state, struct udev_device *udev)
{
put_multipath_config(conf);
}
- if (!udev) {
- condlog(1, "%s: no udev information", pp->dev);
- return 1;
- }
-
memset(pp->wwid, 0, WWID_SIZE);
if (pp->getuid) {
char buff[CALLOUT_MAX_SIZE];
len = get_rbd_uid(pp);
origin = "sysfs";
} else {
- int retrigger;
- if (pp->uid_attribute) {
+ if (udev && pp->uid_attribute) {
len = get_udev_uid(pp, pp->uid_attribute, udev);
origin = "udev";
if (len <= 0)
"%s: failed to get udev uid: %s",
pp->dev, strerror(-len));
- } else {
+ } else if (pp->bus == SYSFS_BUS_SCSI) {
len = get_vpd_uid(pp);
origin = "sysfs";
}
- conf = get_multipath_config();
- retrigger = conf->retrigger_tries;
- put_multipath_config(conf);
- if (len <= 0 && pp->retriggers >= retrigger &&
- !strcmp(pp->uid_attribute, DEFAULT_UID_ATTRIBUTE)) {
- len = get_vpd_uid(pp);
- origin = "sysfs";
- pp->uid_attribute = NULL;
- if (len < 0 && path_state == PATH_UP) {
- condlog(1, "%s: failed to get sysfs uid: %s",
- pp->dev, strerror(-len));
- len = get_vpd_sgio(pp->fd, 0x83, pp->wwid,
- WWID_SIZE);
- origin = "sgio";
- }
- }
+ if (len <= 0 && pp->bus == SYSFS_BUS_SCSI)
+ len = scsi_uid_fallback(pp, path_state, &origin);
}
if ( len < 0 ) {
condlog(1, "%s: failed to get %s uid: %s",
pp->dev, origin, strerror(-len));
memset(pp->wwid, 0x0, WWID_SIZE);
+ return 1;
} else {
/* Strip any trailing blanks */
c = strchr(pp->wwid, '\0');
* @retval FOREIGN_CLAIMED: device newly claimed
* @retval FOREIGN_OK: device already registered, no action taken
* @retval FOREIGN_IGNORED: device is ignored, no action taken
- * @retval FOREIGN_ERR: an error occured (e.g. out-of-memory)
+ * @retval FOREIGN_ERR: an error occurred (e.g. out-of-memory)
*/
int (*add)(struct context *, struct udev_device *);
* @returns status code
* @retval FOREIGN_OK: event processed
* @retval FOREIGN_IGNORED: the device is ignored
- * @retval FOREIGN_ERR: an error occured (e.g. out-of-memory)
+ * @retval FOREIGN_ERR: an error occurred (e.g. out-of-memory)
*
* Note: theoretically it can happen that the status of a foreign device
* (claimed vs. not claimed) changes in a change event.
* @returns status code
* @retval FOREIGN_OK: processed correctly (device deleted)
* @retval FOREIGN_IGNORED: device wasn't registered internally
- * @retval FOREIGN_ERR: error occured.
+ * @retval FOREIGN_ERR: error occurred.
*/
int (*delete)(struct context *, struct udev_device *);
* @returns status code
* @retval FOREIGN_OK: processed correctly
* @retval FOREIGN_IGNORED: nothing to delete
- * @retval FOREIGN_ERR: error occured
+ * @retval FOREIGN_ERR: error occurred
*/
int (*delete_all)(struct context*);
void (*check)(struct context *);
/**
- * lock internal data stuctures.
+ * lock internal data structures.
* @param[in] ctx: foreign context
*/
void (*lock)(struct context *ctx);
/**
- * unlock internal data stuctures.
+ * unlock internal data structures.
* @param[in] ctx: foreign context (void* in order to use the function
* as argument to pthread_cleanup_push())
*/
* @retval FOREIGN_CLAIMED: newly claimed by a foreign lib
* @retval FOREIGN_OK: already claimed by a foreign lib
* @retval FOREIGN_IGNORED: ignored by all foreign libs
- * @retval FOREIGN_ERR: an error occured
+ * @retval FOREIGN_ERR: an error occurred
*/
int add_foreign(struct udev_device *);
/**
* is_claimed_by_foreign(ud)
* @param udev: udev device
- * @returns: true iff device is (newly or already) claimed by a foreign lib
+ * @returns: true if device is (newly or already) claimed by a foreign lib
*/
static inline bool
is_claimed_by_foreign(struct udev_device *ud)
$(RM) core *.a *.o *.gz *.so
OBJS := $(LIBS:libforeign-%.so=%.o)
+.SECONDARY: $(OBJS)
+
include $(wildcard $(OBJS:.o=.d))
dep_clean:
.delay_wait_checks = DELAY_CHECKS_OFF,
.skip_kpartx = SKIP_KPARTX_OFF,
.max_sectors_kb = MAX_SECTORS_KB_UNDEF,
- .ghost_delay = GHOST_DELAY_OFF
+ .ghost_delay = GHOST_DELAY_OFF,
},
#endif
static struct hwentry default_hw[] = {
/*
- * Generic NVMe devices
+ * Generic NVMe
*
* Due to the parsing logic in find_hwe(), generic entries
* have to be put on top of this list, and more specific ones
.prio_name = PRIO_ALUA,
},
{
- /* MSA 1040, 2040 and 2050 families */
+ /* MSA 1040, 1050, 2040 and 2050 families */
.vendor = "HP",
.product = "MSA [12]0[45]0 SA[NS]",
.pgpolicy = GROUP_BY_PRIO,
.no_path_retry = 18,
.prio_name = PRIO_ALUA,
},
+ {
+ /* Nimble Storage */
+ .vendor = "Nimble",
+ .product = "Server",
+ .hwhandler = "1 alua",
+ .pgpolicy = GROUP_BY_PRIO,
+ .pgfailback = -FAILBACK_IMMEDIATE,
+ .prio_name = PRIO_ALUA,
+ .no_path_retry = NO_PATH_RETRY_QUEUE,
+ },
+ /* SGI */
+ {
+ .vendor = "SGI",
+ .product = "TP9100",
+ .pgpolicy = MULTIBUS,
+ },
+ {
+ /* Total Performance family */
+ .vendor = "SGI",
+ .product = "TP9[3457]00",
+ .bl_product = "Universal Xport",
+ .pgpolicy = GROUP_BY_PRIO,
+ .checker_name = RDAC,
+ .features = "2 pg_init_retries 50",
+ .hwhandler = "1 rdac",
+ .prio_name = PRIO_RDAC,
+ .pgfailback = -FAILBACK_IMMEDIATE,
+ .no_path_retry = 30,
+ },
+ {
+ /* InfiniteStorage family */
+ .vendor = "SGI",
+ .product = "IS",
+ .bl_product = "Universal Xport",
+ .pgpolicy = GROUP_BY_PRIO,
+ .checker_name = RDAC,
+ .features = "2 pg_init_retries 50",
+ .hwhandler = "1 rdac",
+ .prio_name = PRIO_RDAC,
+ .pgfailback = -FAILBACK_IMMEDIATE,
+ .no_path_retry = 30,
+ },
+ {
+ /* (DDN) */
+ .vendor = "SGI",
+ .product = "^DD[46]A-",
+ .pgpolicy = GROUP_BY_PRIO,
+ .pgfailback = -FAILBACK_IMMEDIATE,
+ .prio_name = PRIO_ALUA,
+ .no_path_retry = 30,
+ },
/*
* DataDirect Networks
*/
* Mail : matthias.rudolph@hds.com
*/
{
- /* USP-V, HUS VM, VSP, VSP G1000 and VSP GX00 families */
+ /* USP-V, HUS VM, VSP, VSP G1X00 and VSP GX00 families */
.vendor = "(HITACHI|HP)",
.product = "^OPEN-",
.pgpolicy = MULTIBUS,
.pgpolicy = MULTIBUS,
},
{
- /* DDN */
+ /* (DDN) DCS9900, SONAS 2851-DR1 */
.vendor = "IBM",
.product = "^(DCS9900|2851)",
.pgpolicy = GROUP_BY_PRIO,
.pgpolicy = MULTIBUS,
.no_path_retry = 24,
},
- /*
- * NetApp NVMe-FC namespace devices: MULTIBUS, queueing preferred
- *
- * The table is searched backwards, so place this after generic NVMe
- */
{
+ /*
+ * NVMe-FC namespace devices: MULTIBUS, queueing preferred
+ *
+ * The hwtable is searched backwards, so place this after "Generic NVMe"
+ */
.vendor = "NVME",
.product = "^NetApp ONTAP Controller",
.uid_attribute = "ID_WWN",
.no_path_retry = 30,
},
/*
- * SGI
- */
- {
- .vendor = "SGI",
- .product = "TP9100",
- .pgpolicy = MULTIBUS,
- },
- {
- /* Total Performance family */
- .vendor = "SGI",
- .product = "TP9[3457]00",
- .bl_product = "Universal Xport",
- .pgpolicy = GROUP_BY_PRIO,
- .checker_name = RDAC,
- .features = "2 pg_init_retries 50",
- .hwhandler = "1 rdac",
- .prio_name = PRIO_RDAC,
- .pgfailback = -FAILBACK_IMMEDIATE,
- .no_path_retry = 30,
- },
- {
- /* InfiniteStorage family */
- .vendor = "SGI",
- .product = "IS",
- .bl_product = "Universal Xport",
- .pgpolicy = GROUP_BY_PRIO,
- .checker_name = RDAC,
- .features = "2 pg_init_retries 50",
- .hwhandler = "1 rdac",
- .prio_name = PRIO_RDAC,
- .pgfailback = -FAILBACK_IMMEDIATE,
- .no_path_retry = 30,
- },
- {
- /* DDN */
- .vendor = "SGI",
- .product = "^DD[46]A-",
- .pgpolicy = GROUP_BY_PRIO,
- .pgfailback = -FAILBACK_IMMEDIATE,
- .prio_name = PRIO_ALUA,
- .no_path_retry = 30,
- },
- /*
* NEC
*/
{
.dev_loss = 15,
},
/*
- * Nimble Storage
- */
- {
- .vendor = "Nimble",
- .product = "Server",
- .hwhandler = "1 alua",
- .pgpolicy = GROUP_BY_PRIO,
- .pgfailback = -FAILBACK_IMMEDIATE,
- .prio_name = PRIO_ALUA,
- .no_path_retry = NO_PATH_RETRY_QUEUE,
- },
- /*
* Kaminario
*/
{
.no_path_retry = 30,
},
/*
- * Dot Hill Systems - Seagate Technology
+ * Seagate Technology (Dot Hill Systems)
*/
{
/* SANnet family */
void stop_io_err_stat_thread(void)
{
+ if (io_err_stat_thr == (pthread_t)0)
+ return;
+
if (uatomic_read(&io_err_thread_running) == 1)
pthread_cancel(io_err_stat_thr);
* ! 9 ! Allocated !
* +----+-----------------------+
*
- * global variabel debug bit 9 ( 512 ) used to
+ * global variable debug bit 9 ( 512 ) used to
* flag some memory error.
*
*/
(__FILE__), (char *)(__FUNCTION__), (__LINE__)) )
#define STRDUP(n) ( dbg_strdup((n), \
(__FILE__), (char *)(__FUNCTION__), (__LINE__)) )
-#define FREE_CONST(p) do { FREE((void*)(unsigned long)p); } while(0)
/* Memory debug prototypes defs */
extern void *dbg_malloc(unsigned long, char *, char *, int);
#define MALLOC(n) (calloc(1,(n)))
#define FREE(p) do { free(p); p = NULL; } while(0)
-/*
- * Double cast to avoid warnings with -Wcast-qual
- * use this for valid free() operations on const pointers
- */
-#define FREE_CONST(p) do { free((void*)(unsigned long)p); p = NULL; } while(0)
#define REALLOC(p,n) (realloc((p),(n)))
#define STRDUP(n) (strdup(n))
return fwd;
}
+static const char quote_marker[] = { '\0', '"', '\0' };
+bool is_quote(const char* token)
+{
+ return !memcmp(token, quote_marker, sizeof(quote_marker));
+}
+
vector
alloc_strvec(char *string)
{
in_string = 0;
while (1) {
+ int two_quotes = 0;
+
if (!vector_alloc_slot(strvec))
goto out;
start = cp;
- if (*cp == '"') {
+ if (*cp == '"' && !(in_string && *(cp + 1) == '"')) {
cp++;
- token = MALLOC(2);
+ token = MALLOC(sizeof(quote_marker));
if (!token)
goto out;
- *(token) = '"';
- *(token + 1) = '\0';
+ memcpy(token, quote_marker, sizeof(quote_marker));
if (in_string)
in_string = 0;
else
*(token + 1) = '\0';
cp++;
} else {
+
+ move_on:
while ((in_string ||
(!isspace((int) *cp) && isascii((int) *cp) &&
*cp != '!' && *cp != '#' && *cp != '{' &&
*cp != '}')) && *cp != '\0' && *cp != '"')
cp++;
+
+ /* Two consecutive double quotes - don't end string */
+ if (in_string && *cp == '"') {
+ if (*(cp + 1) == '"') {
+ two_quotes = 1;
+ cp += 2;
+ goto move_on;
+ }
+ }
+
strlen = cp - start;
token = MALLOC(strlen + 1);
memcpy(token, start, strlen);
*(token + strlen) = '\0';
+
+ /* Replace "" by " */
+ if (two_quotes) {
+ char *qq = strstr(token, "\"\"");
+ while (qq != NULL) {
+ memmove(qq + 1, qq + 2,
+ strlen + 1 - (qq + 2 - token));
+ qq = strstr(qq + 1, "\"\"");
+ }
+ }
}
vector_set_slot(strvec, token);
- while ((isspace((int) *cp) || !isascii((int) *cp))
+ while ((!in_string &&
+ (isspace((int) *cp) || !isascii((int) *cp)))
&& *cp != '\0')
cp++;
if (*cp == '\0' || *cp == '!' || *cp == '#')
(char *)VECTOR_SLOT(strvec, 0));
return NULL;
}
- size = strlen(str);
- if (size == 0) {
- condlog(0, "option '%s' has empty value",
- (char *)VECTOR_SLOT(strvec, 0));
- return NULL;
- }
- if (*str != '"') {
+ if (!is_quote(str)) {
+ size = strlen(str);
+ if (size == 0) {
+ condlog(0, "option '%s' has empty value",
+ (char *)VECTOR_SLOT(strvec, 0));
+ return NULL;
+ }
alloc = MALLOC(sizeof (char) * (size + 1));
if (alloc)
memcpy(alloc, str, size);
(char *)VECTOR_SLOT(strvec, 0));
return NULL;
}
- if (*str == '"')
+ if (is_quote(str))
break;
tmp = alloc;
/* The first +1 is for the NULL byte. The rest are for the
(char *)VECTOR_SLOT(strvec, 0), line_nr, file);
return -1;
}
- if (*str != '"') {
+ if (!is_quote(str)) {
if (VECTOR_SIZE(strvec) > 2)
condlog(0, "ignoring extra data starting with '%s' on line %d of %s", (char *)VECTOR_SLOT(strvec, 2), line_nr, file);
return 0;
line_nr, file);
return -1;
}
- if (*str == '"') {
+ if (is_quote(str)) {
if (VECTOR_SIZE(strvec) > i + 1)
condlog(0, "ignoring extra data starting with '%s' on line %d of %s", (char *)VECTOR_SLOT(strvec, (i + 1)), line_nr, file);
return 0;
FILE *stream;
if (!conf->keywords) {
- condlog(0, "No keywords alocated");
+ condlog(0, "No keywords allocated");
return 1;
}
stream = fopen(file, "r");
extern struct keyword * find_keyword(vector keywords, vector v, char * name);
int snprint_keyword(char *buff, int len, char *fmt, struct keyword *kw,
const void *data);
+bool is_quote(const char* token);
#endif
$(RM) core *.a *.o *.gz *.so
OBJS = $(LIBS:libprio%.so=%.o) alua_rtpg.o
+.SECONDARY: $(OBJS)
+
include $(wildcard $(OBJS:.o=.d))
dep_clean:
#include "../structs.h"
#include "../prio.h"
#include "../discovery.h"
+#include "../unaligned.h"
#include "alua_rtpg.h"
#define SENSE_BUFF_LEN 32
inquiry_command_set_evpd(&cmd);
cmd.page = codepage;
}
- set_uint16(cmd.length, resplen);
+ put_unaligned_be16(resplen, cmd.length);
PRINT_HEX((unsigned char *) &cmd, sizeof(cmd));
memset(&hdr, 0, sizeof(hdr));
if (rc < 0)
goto out;
- scsi_buflen = (buf[2] << 8 | buf[3]) + 4;
+ scsi_buflen = get_unaligned_be16(&buf[2]) + 4;
/* Paranoia */
if (scsi_buflen >= USHRT_MAX)
scsi_buflen = USHRT_MAX;
continue;
}
p = (struct vpd83_tpg_dscr *)dscr->data;
- rc = get_uint16(p->tpg);
+ rc = get_unaligned_be16(p->tpg);
}
}
memset(&cmd, 0, sizeof(cmd));
cmd.op = OPERATION_CODE_RTPG;
rtpg_command_set_service_action(&cmd);
- set_uint32(cmd.length, resplen);
+ put_unaligned_be32(resplen, cmd.length);
PRINT_HEX((unsigned char *) &cmd, sizeof(cmd));
memset(&hdr, 0, sizeof(hdr));
rc = do_rtpg(fd, buf, buflen, timeout);
if (rc < 0)
goto out;
- scsi_buflen = (buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3]) + 4;
+ scsi_buflen = get_unaligned_be32(&buf[0]) + 4;
if (scsi_buflen > UINT_MAX)
scsi_buflen = UINT_MAX;
if (buflen < scsi_buflen) {
tpgd = (struct rtpg_data *) buf;
rc = -RTPG_TPG_NOT_FOUND;
RTPG_FOR_EACH_PORT_GROUP(tpgd, dscr) {
- if (get_uint16(dscr->tpg) == tpg) {
+ if (get_unaligned_be16(dscr->tpg) == tpg) {
if (rc != -RTPG_TPG_NOT_FOUND) {
PRINT_DEBUG("get_asymmetric_access_state: "
"more than one entry with same port "
*/
#ifndef __SPC3_H__
#define __SPC3_H__
-/*=============================================================================
- * Some helper functions for getting and setting 16 and 32 bit values.
- *=============================================================================
- */
-static inline unsigned short
-get_uint16(unsigned char *p)
-{
- return (p[0] << 8) + p[1];
-}
-
-static inline void
-set_uint16(unsigned char *p, unsigned short v)
-{
- p[0] = (v >> 8) & 0xff;
- p[1] = v & 0xff;
-}
-
-static inline unsigned int
-get_uint32(unsigned char *p)
-{
- return (p[0] << 24) + (p[1] << 16) + (p[2] << 8) + p[3];
-}
-
-static inline void
-set_uint32(unsigned char *p, unsigned int v)
-{
- p[0] = (v >> 24) & 0xff;
- p[1] = (v >> 16) & 0xff;
- p[2] = (v >> 8) & 0xff;
- p[3] = v & 0xff;
-}
/*=============================================================================
* Definitions to support the standard inquiry command as defined in SPC-3.
unsigned char b0; /* xxx..... = peripheral_qualifier */
/* ...xxxxx = peripheral_device_type */
unsigned char b1; /* x....... = removable medium */
- /* .xxxxxxx = reserverd */
+ /* .xxxxxxx = reserved */
unsigned char version;
unsigned char b3; /* xx...... = obsolete */
/* ..x..... = normal aca supported */
for( \
d = p->data; \
(((char *) d) - ((char *) p)) < \
- get_uint16(p->length); \
+ get_unaligned_be16(p->length); \
d = (struct vpd83_dscr *) \
((char *) d + d->length + 4) \
)
/*=============================================================================
- * The following stuctures and macros are used to call the report target port
+ * The following structures and macros are used to call the report target port
* groups command defined in SPC-3.
* This command is used to get information about the target port groups (which
* states are supported, which ports belong to this group, and so on) and the
#define RTPG_FOR_EACH_PORT_GROUP(p, g) \
for( \
g = &(p->data[0]); \
- (((char *) g) - ((char *) p)) < get_uint32(p->length); \
+ (((char *) g) - ((char *) p)) < get_unaligned_be32(p->length); \
g = (struct rtpg_tpg_dscr *) ( \
((char *) g) + \
sizeof(struct rtpg_tpg_dscr) + \
#include "debug.h"
#include "prio.h"
#include "structs.h"
+#include "unaligned.h"
#define INQUIRY_CMD 0x12
#define INQUIRY_CMDLEN 6
memset(&results, 0, sizeof (results));
rc = send_gva(dev, fd, 0x41, results, &results_size, timeout);
if (rc >= 0) {
- tot_len = results[0] << 24 | results[1] << 16 |
- results[2] << 8 | results[3];
+ tot_len = get_unaligned_be32(&results[0]);
if (tot_len <= 8) {
goto try_fcp_proxy;
}
void
uevent_get_wwid(struct uevent *uev)
{
- const char *uid_attribute;
+ char *uid_attribute;
const char *val;
struct config * conf;
val = uevent_get_env_var(uev, uid_attribute);
if (val)
uev->wwid = val;
- FREE_CONST(uid_attribute);
+ FREE(uid_attribute);
}
bool
if (!earlier->wwid || !later->wwid)
return true;
/*
- * uevents merging stoped
+ * uevents merging stopped
* when we meet an opposite action uevent from the same LUN to AVOID
* "add path1 |remove path1 |add path2 |remove path2 |add path3"
* to merge as "remove path1, path2" and "add path1, path2, path3"
return uevent_get_env_positive_int(uev, "DISK_RO");
}
-static const char *uevent_get_dm_str(const struct uevent *uev, char *attr)
+static char *uevent_get_dm_str(const struct uevent *uev, char *attr)
{
const char *tmp = uevent_get_env_var(uev, attr);
return strdup(tmp);
}
-const char *uevent_get_dm_name(const struct uevent *uev)
+char *uevent_get_dm_name(const struct uevent *uev)
{
return uevent_get_dm_str(uev, "DM_NAME");
}
-const char *uevent_get_dm_path(const struct uevent *uev)
+char *uevent_get_dm_path(const struct uevent *uev)
{
return uevent_get_dm_str(uev, "DM_PATH");
}
-const char *uevent_get_dm_action(const struct uevent *uev)
+char *uevent_get_dm_action(const struct uevent *uev)
{
return uevent_get_dm_str(uev, "DM_ACTION");
}
int uevent_get_major(const struct uevent *uev);
int uevent_get_minor(const struct uevent *uev);
int uevent_get_disk_ro(const struct uevent *uev);
-const char *uevent_get_dm_name(const struct uevent *uev);
-const char *uevent_get_dm_path(const struct uevent *uev);
-const char *uevent_get_dm_action(const struct uevent *uev);
+char *uevent_get_dm_name(const struct uevent *uev);
+char *uevent_get_dm_path(const struct uevent *uev);
+char *uevent_get_dm_action(const struct uevent *uev);
bool uevent_is_mpath(const struct uevent *uev);
#endif /* _UEVENT_H */
--- /dev/null
+#ifndef _UNALIGNED_H_
+#define _UNALIGNED_H_
+
+#include <stdint.h>
+
+static inline uint16_t get_unaligned_be16(const void *ptr)
+{
+ const uint8_t *p = ptr;
+
+ return p[0] << 8 | p[1];
+}
+
+static inline uint32_t get_unaligned_be32(void *ptr)
+{
+ const uint8_t *p = ptr;
+
+ return p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3];
+}
+
+static inline void put_unaligned_be16(uint16_t val, void *ptr)
+{
+ uint8_t *p = ptr;
+
+ p[0] = val >> 8;
+ p[1] = val;
+}
+
+static inline void put_unaligned_be32(uint32_t val, void *ptr)
+{
+ uint8_t *p = ptr;
+
+ p[0] = val >> 24;
+ p[1] = val >> 16;
+ p[2] = val >> 8;
+ p[3] = val;
+}
+
+#endif /* _UNALIGNED_H_ */
#ifndef _VERSION_H
#define _VERSION_H
-#define VERSION_CODE 0x000705
-#define DATE_CODE 0x030712
+#define VERSION_CODE 0x000706
+#define DATE_CODE 0x030a12
#define PROG "multipath-tools"
enum devtypes dev_type, const struct config *conf)
{
int fd;
- char command[1024], *p, *reply;
+ char command[1024], *p, *reply = NULL;
int n, r = 0;
fd = mpath_connect();
section in which they occur.
.LP
.
+\fB<attribute>\fR and \fB<value>\fR must be on a single line.
+\fB<attribute>\fR is one of the keywords listed in this man page.
+\fB<value>\fR is either a simple word (containing no whitespace and none of the
+characters '\(dq', '#', and '!') or \fIone\fR string enclosed in double
+quotes ("..."). Outside a quoted string, text starting with '#', and '!' is
+regarded as a comment and ignored until the end of the line. Inside a quoted
+string, '#' and '!' are normal characters, and whitespace is preserved.
+To represent a double quote character inside a double quoted string, use two
+consecutive double quotes ('""'). Thus '2.5\(dq SSD' can be written as "2.5"" SSD".
+.LP
+.
+Opening braces ('{') must follow the (sub)section name on the same line. Closing
+braces ('}') that mark the end of a (sub)section must be the only non-whitespace
+character on the line. Whitespace is ignored except inside double quotes, thus
+the indentation shown in the above example is helpful for human readers but
+not mandatory.
+.LP
.
The following \fIsection\fP keywords are recognized:
.TP 17
}
vector_foreach_slot(strvec, buff, i) {
- if (*buff == '"')
+ if (is_quote(buff))
continue;
if (get_param) {
get_param = 0;
len = strlen(str);
int r = get_cmdvec(rl_line_buffer, &v);
/*
- * If a word completion is in progess, we don't want
+ * If a word completion is in progress, we don't want
* to take an exact keyword match in the fingerprint.
* For ex "show map[tab]" would validate "map" and discard
* "maps" as a valid candidate.
static int
uev_add_map (struct uevent * uev, struct vectors * vecs)
{
- const char *alias;
+ char *alias;
int major = -1, minor = -1, rc;
condlog(3, "%s: add map (uevent)", uev->kernel);
pthread_testcancel();
rc = ev_add_map(uev->kernel, alias, vecs);
lock_cleanup_pop(vecs->lock);
- FREE_CONST(alias);
+ FREE(alias);
return rc;
}
static int
uev_remove_map (struct uevent * uev, struct vectors * vecs)
{
- const char *alias;
+ char *alias;
int minor;
struct multipath *mpp;
remove_map_and_stop_waiter(mpp, vecs, 1);
out:
lock_cleanup_pop(vecs->lock);
- FREE_CONST(alias);
+ FREE(alias);
return 0;
}
vector_del_slot(mpp->paths, i);
/*
- * remove the map IFF removing the last path
+ * remove the map IF removing the last path
*/
if (VECTOR_SIZE(mpp->paths) == 0) {
char alias[WWID_SIZE];
pp = find_path_by_dev(vecs->pathvec, uev->kernel);
if (pp) {
struct multipath *mpp = pp->mpp;
-
- if (disable_changed_wwids &&
- (strlen(pp->wwid) || pp->wwid_changed)) {
- char wwid[WWID_SIZE];
-
- strcpy(wwid, pp->wwid);
- get_uid(pp, pp->state, uev->udev);
- if (strcmp(wwid, pp->wwid) != 0) {
- condlog(0, "%s: path wwid changed from '%s' to '%s'. disallowing", uev->kernel, wwid, pp->wwid);
+ char wwid[WWID_SIZE];
+
+ strcpy(wwid, pp->wwid);
+ get_uid(pp, pp->state, uev->udev);
+
+ if (strncmp(wwid, pp->wwid, WWID_SIZE) != 0) {
+ condlog(0, "%s: path wwid changed from '%s' to '%s'. %s",
+ uev->kernel, wwid, pp->wwid,
+ (disable_changed_wwids ? "disallowing" :
+ "continuing"));
+ if (disable_changed_wwids &&
+ (strlen(wwid) || pp->wwid_changed)) {
strcpy(pp->wwid, wwid);
if (!pp->wwid_changed) {
pp->wwid_changed = 1;
dm_fail_path(pp->mpp->alias, pp->dev_t);
}
goto out;
- } else
+ } else if (!disable_changed_wwids)
+ strcpy(pp->wwid, wwid);
+ else
pp->wwid_changed = 0;
+ } else {
+ udev_device_unref(pp->udev);
+ pp->udev = udev_device_ref(uev->udev);
+ conf = get_multipath_config();
+ if (pathinfo(pp, conf, DI_SYSFS|DI_NOIO) != PATHINFO_OK)
+ condlog(1, "%s: pathinfo failed after change uevent",
+ uev->kernel);
+ put_multipath_config(conf);
}
if (pp->initialized == INIT_REQUESTED_UDEV)
static int
uev_pathfail_check(struct uevent *uev, struct vectors *vecs)
{
- const char *action = NULL, *devt = NULL;
+ char *action = NULL, *devt = NULL;
struct path *pp;
int r = 1;
pp->dev);
out_lock:
lock_cleanup_pop(vecs->lock);
- FREE_CONST(devt);
- FREE_CONST(action);
+ FREE(devt);
+ FREE(action);
return r;
out:
- FREE_CONST(action);
+ FREE(action);
return 1;
}
set_handler_callback(LIST+PATHS+RAW+FMT, cli_list_paths_raw);
set_handler_callback(LIST+PATH, cli_list_path);
set_handler_callback(LIST+MAPS, cli_list_maps);
- set_unlocked_handler_callback(LIST+STATUS, cli_list_status);
+ set_handler_callback(LIST+STATUS, cli_list_status);
set_unlocked_handler_callback(LIST+DAEMON, cli_list_daemon);
set_handler_callback(LIST+MAPS+STATUS, cli_list_maps_status);
set_handler_callback(LIST+MAPS+STATS, cli_list_maps_stats);
vector_foreach_slot (mpvec, mpp, i) {
/*
- * defered failback getting sooner
+ * deferred failback getting sooner
*/
if (mpp->pgfailback > 0 && mpp->failback_tick > 0) {
mpp->failback_tick--;
{
struct client *client_loop;
struct client *client_tmp;
- int ux_sock = (int)arg;
+ long ux_sock = (long)arg;
close(ux_sock);
*/
void * uxsock_listen(uxsock_trigger_fn uxsock_trigger, void * trigger_data)
{
- int ux_sock;
+ long ux_sock;
int rlen;
char *inbuf;
char *reply;
CFLAGS += $(BIN_CFLAGS) -I$(multipathdir) -I$(mpathcmddir)
LIBDEPS += -L$(multipathdir) -lmultipath -lcmocka
-TESTS := uevent
+TESTS := uevent parser
.SILENT: $(TESTS:%=%.o)
.PRECIOUS: $(TESTS:%=%-test)
rm -f $(TESTS:%=%-test) $(TESTS:%=%.out) $(TESTS:%=%.o)
OBJS = $(TESTS:%=%.o)
-include $(wildcard $(OBJS:.o=.d))
-
-
+.SECONDARY: $(OBJS)
+include $(wildcard $(OBJS:.o=.d))
dep_clean:
$(RM) $(OBJS:.o=.d)
int logsink = 0;
struct config conf = {
.uid_attrs = "sd:ID_BOGUS",
+ .verbosity = 4,
};
struct config *get_multipath_config(void)
--- /dev/null
+/*
+ * Copyright (c) 2018 SUSE Linux GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ *
+ */
+
+#include <stdbool.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <stdlib.h>
+#include <cmocka.h>
+// #include "list.h"
+#include "parser.h"
+#include "vector.h"
+
+#include "globals.c"
+
+/* Set these to 1 to get success for current broken behavior */
+/* Strip leading whitespace between quotes */
+#define LSTRIP_QUOTED_WSP 0
+/* Stop parsing at 2nd quote */
+#define TWO_QUOTES_ONLY 0
+
+static char *test_file = "test.conf";
+
+/* Missing declaration */
+int validate_config_strvec(vector strvec, char *file);
+
+/* Stringify helpers */
+#define _str_(x) #x
+#define str(x) _str_(x)
+
+static int setup(void **state)
+{
+ return 0;
+}
+
+static int teardown(void **state)
+{
+ return 0;
+}
+
+static void test01(void **state)
+{
+ vector v = alloc_strvec("keyword value");
+ char *val;
+
+ assert_int_equal(validate_config_strvec(v, test_file), 0);
+ assert_int_equal(VECTOR_SIZE(v), 2);
+ assert_string_equal(VECTOR_SLOT(v, 0), "keyword");
+ assert_string_equal(VECTOR_SLOT(v, 1), "value");
+
+ val = set_value(v);
+ assert_string_equal(val, "value");
+
+ free(val);
+ free_strvec(v);
+}
+
+static void test02(void **state)
+{
+ vector v = alloc_strvec("keyword \"value\"");
+ char *val;
+
+ assert_int_equal(validate_config_strvec(v, test_file), 0);
+ assert_int_equal(VECTOR_SIZE(v), 4);
+ assert_string_equal(VECTOR_SLOT(v, 0), "keyword");
+ assert_true(is_quote(VECTOR_SLOT(v, 1)));;
+ assert_string_equal(VECTOR_SLOT(v, 2), "value");
+ assert_true(is_quote(VECTOR_SLOT(v, 3)));;
+
+ val = set_value(v);
+ assert_string_equal(val, "value");
+
+ free(val);
+ free_strvec(v);
+}
+
+static void test03(void **state)
+{
+ vector v = alloc_strvec("keyword value\n");
+ char *val;
+
+ assert_int_equal(validate_config_strvec(v, test_file), 0);
+ assert_int_equal(VECTOR_SIZE(v), 2);
+ assert_string_equal(VECTOR_SLOT(v, 0), "keyword");
+ assert_string_equal(VECTOR_SLOT(v, 1), "value");
+
+ val = set_value(v);
+ assert_string_equal(val, "value");
+
+ free(val);
+ free_strvec(v);
+}
+
+static void test04(void **state)
+{
+ vector v = alloc_strvec("keyword \t value \t \n ");
+ char *val;
+
+ assert_int_equal(validate_config_strvec(v, test_file), 0);
+ assert_int_equal(VECTOR_SIZE(v), 2);
+ assert_string_equal(VECTOR_SLOT(v, 0), "keyword");
+ assert_string_equal(VECTOR_SLOT(v, 1), "value");
+
+ val = set_value(v);
+ assert_string_equal(val, "value");
+
+ free(val);
+ free_strvec(v);
+}
+
+static void test05(void **state)
+{
+ vector v = alloc_strvec("keyword \t value \t ! comment ");
+ char *val;
+
+ assert_int_equal(validate_config_strvec(v, test_file), 0);
+ assert_int_equal(VECTOR_SIZE(v), 2);
+ assert_string_equal(VECTOR_SLOT(v, 0), "keyword");
+ assert_string_equal(VECTOR_SLOT(v, 1), "value");
+
+ val = set_value(v);
+ assert_string_equal(val, "value");
+
+ free(val);
+ free_strvec(v);
+}
+
+static void test06(void **state)
+{
+ vector v = alloc_strvec("keyword \t value # \n comment ");
+ char *val;
+
+ assert_int_equal(validate_config_strvec(v, test_file), 0);
+ assert_int_equal(VECTOR_SIZE(v), 2);
+ assert_string_equal(VECTOR_SLOT(v, 0), "keyword");
+ assert_string_equal(VECTOR_SLOT(v, 1), "value");
+
+ val = set_value(v);
+ assert_string_equal(val, "value");
+
+ free(val);
+ free_strvec(v);
+}
+
+static void test07(void **state)
+{
+ vector v = alloc_strvec("keyword \t value more ");
+ char *val;
+
+ assert_int_equal(validate_config_strvec(v, test_file), 0);
+ assert_int_equal(VECTOR_SIZE(v), 3);
+ assert_string_equal(VECTOR_SLOT(v, 0), "keyword");
+ assert_string_equal(VECTOR_SLOT(v, 1), "value");
+ assert_string_equal(VECTOR_SLOT(v, 2), "more");
+
+ val = set_value(v);
+ assert_string_equal(val, "value");
+
+ free(val);
+ free_strvec(v);
+}
+
+static void test08(void **state)
+{
+#define QUOTED08 " value more "
+#define QUOTED08B "value more "
+ vector v = alloc_strvec("keyword \t \"" QUOTED08 "\"");
+ char *val;
+
+ assert_int_equal(validate_config_strvec(v, test_file), 0);
+ assert_int_equal(VECTOR_SIZE(v), 4);
+ assert_string_equal(VECTOR_SLOT(v, 0), "keyword");
+ assert_true(is_quote(VECTOR_SLOT(v, 1)));;
+#if LSTRIP_QUOTED_WSP
+ assert_string_equal(VECTOR_SLOT(v, 2), QUOTED08B);
+#else
+ assert_string_equal(VECTOR_SLOT(v, 2), QUOTED08);
+#endif
+ assert_true(is_quote(VECTOR_SLOT(v, 3)));;
+
+ val = set_value(v);
+#if LSTRIP_QUOTED_WSP
+ assert_string_equal(val, QUOTED08B);
+#else
+ assert_string_equal(val, QUOTED08);
+#endif
+ free(val);
+ free_strvec(v);
+}
+
+static void test09(void **state)
+{
+#define QUOTED09 "value # more"
+ vector v = alloc_strvec("keyword \"" QUOTED09 "\"");
+ char *val;
+
+ assert_int_equal(validate_config_strvec(v, test_file), 0);
+ assert_int_equal(VECTOR_SIZE(v), 4);
+ assert_string_equal(VECTOR_SLOT(v, 0), "keyword");
+ assert_true(is_quote(VECTOR_SLOT(v, 1)));;
+ assert_string_equal(VECTOR_SLOT(v, 2), QUOTED09);
+ assert_true(is_quote(VECTOR_SLOT(v, 3)));;
+
+ val = set_value(v);
+ assert_string_equal(val, QUOTED09);
+
+ free(val);
+ free_strvec(v);
+}
+
+static void test10(void **state)
+{
+#define QUOTED10 "value ! more"
+ vector v = alloc_strvec("keyword \"" QUOTED10 "\"");
+ char *val;
+
+ assert_int_equal(validate_config_strvec(v, test_file), 0);
+ assert_int_equal(VECTOR_SIZE(v), 4);
+ assert_string_equal(VECTOR_SLOT(v, 0), "keyword");
+ assert_true(is_quote(VECTOR_SLOT(v, 1)));;
+ assert_string_equal(VECTOR_SLOT(v, 2), QUOTED10);
+ assert_true(is_quote(VECTOR_SLOT(v, 3)));;
+
+ val = set_value(v);
+ assert_string_equal(val, QUOTED10);
+
+ free(val);
+ free_strvec(v);
+}
+
+static void test11(void **state)
+{
+#define QUOTED11 "value comment"
+ vector v = alloc_strvec("keyword\"" QUOTED11 "\"");
+ char *val;
+
+ assert_int_equal(validate_config_strvec(v, test_file), 0);
+ assert_int_equal(VECTOR_SIZE(v), 4);
+ assert_string_equal(VECTOR_SLOT(v, 0), "keyword");
+ assert_true(is_quote(VECTOR_SLOT(v, 1)));;
+ assert_string_equal(VECTOR_SLOT(v, 2), QUOTED11);
+ assert_true(is_quote(VECTOR_SLOT(v, 3)));;
+
+ val = set_value(v);
+ assert_string_equal(val, QUOTED11);
+
+ free(val);
+ free_strvec(v);
+}
+
+static void test12(void **state)
+{
+ vector v = alloc_strvec("key\"word\"");
+ char *val;
+
+ assert_int_equal(validate_config_strvec(v, test_file), 0);
+ assert_int_equal(VECTOR_SIZE(v), 4);
+ assert_string_equal(VECTOR_SLOT(v, 0), "key");
+ assert_true(is_quote(VECTOR_SLOT(v, 1)));;
+ assert_string_equal(VECTOR_SLOT(v, 2), "word");
+ assert_true(is_quote(VECTOR_SLOT(v, 3)));;
+
+ val = set_value(v);
+ assert_string_equal(val, "word");
+
+ free(val);
+ free_strvec(v);
+}
+
+static void test13(void **state)
+{
+ vector v = alloc_strvec("keyword value \"quoted\"");
+ char *val;
+
+ assert_int_equal(validate_config_strvec(v, test_file), 0);
+ assert_int_equal(VECTOR_SIZE(v), 5);
+ assert_string_equal(VECTOR_SLOT(v, 0), "keyword");
+ assert_string_equal(VECTOR_SLOT(v, 1), "value");
+ assert_true(is_quote(VECTOR_SLOT(v, 2)));;
+ assert_string_equal(VECTOR_SLOT(v, 3), "quoted");
+ assert_true(is_quote(VECTOR_SLOT(v, 4)));;
+
+ val = set_value(v);
+ assert_string_equal(val, "value");
+
+ free(val);
+ free_strvec(v);
+}
+
+static void test14(void **state)
+{
+ vector v = alloc_strvec("keyword \"value \" comment\"\"");
+ char *val;
+
+ assert_int_equal(validate_config_strvec(v, test_file), 0);
+ assert_int_equal(VECTOR_SIZE(v), 7);
+ assert_string_equal(VECTOR_SLOT(v, 0), "keyword");
+ assert_true(is_quote(VECTOR_SLOT(v, 1)));;
+ assert_string_equal(VECTOR_SLOT(v, 2), "value ");
+ assert_true(is_quote(VECTOR_SLOT(v, 3)));;
+ assert_string_equal(VECTOR_SLOT(v, 4), "comment");
+ assert_true(is_quote(VECTOR_SLOT(v, 5)));;
+ assert_true(is_quote(VECTOR_SLOT(v, 6)));;
+
+ val = set_value(v);
+ assert_string_equal(val, "value ");
+
+ free(val);
+ free_strvec(v);
+}
+
+static void test15(void **state)
+{
+#define QUOTED15 "word value\n comment"
+ vector v = alloc_strvec("key\"" QUOTED15 "\"");
+ char *val;
+
+ assert_int_equal(VECTOR_SIZE(v), 4);
+ assert_string_equal(VECTOR_SLOT(v, 0), "key");
+ assert_true(is_quote(VECTOR_SLOT(v, 1)));;
+ assert_string_equal(VECTOR_SLOT(v, 2), QUOTED15);
+ assert_true(is_quote(VECTOR_SLOT(v, 3)));;
+ assert_int_equal(validate_config_strvec(v, test_file), 0);
+
+ val = set_value(v);
+ assert_string_equal(val, QUOTED15);
+
+ free(val);
+ free_strvec(v);
+}
+
+static void test16(void **state)
+{
+ vector v = alloc_strvec("keyword \"2.5\"\" SSD\"");
+ char *val;
+
+#if TWO_QUOTES_ONLY
+ assert_int_equal(validate_config_strvec(v, test_file), 0);
+ assert_int_equal(VECTOR_SIZE(v), 6);
+ assert_string_equal(VECTOR_SLOT(v, 0), "keyword");
+ assert_true(is_quote(VECTOR_SLOT(v, 1)));;
+ assert_string_equal(VECTOR_SLOT(v, 2), "2.5");
+ assert_true(is_quote(VECTOR_SLOT(v, 3)));;
+ assert_string_equal(VECTOR_SLOT(v, 4), "SSD");
+ assert_true(is_quote(VECTOR_SLOT(v, 5)));;
+
+ val = set_value(v);
+ assert_string_equal(val, "2.5");
+#else
+ assert_int_equal(VECTOR_SIZE(v), 4);
+ assert_string_equal(VECTOR_SLOT(v, 0), "keyword");
+ assert_true(is_quote(VECTOR_SLOT(v, 1)));;
+ assert_string_equal(VECTOR_SLOT(v, 2), "2.5\" SSD");
+ assert_true(is_quote(VECTOR_SLOT(v, 3)));;
+
+ val = set_value(v);
+ assert_string_equal(val, "2.5\" SSD");
+#endif
+ free(val);
+ free_strvec(v);
+}
+
+static void test17(void **state)
+{
+ vector v = alloc_strvec("keyword \"\"\"\"\" is empty\"");
+ char *val;
+#if TWO_QUOTES_ONLY
+ assert_int_equal(validate_config_strvec(v, test_file), 0);
+ assert_int_equal(VECTOR_SIZE(v), 6);
+ assert_string_equal(VECTOR_SLOT(v, 0), "keyword");
+ assert_true(is_quote(VECTOR_SLOT(v, 1)));;
+ assert_true(is_quote(VECTOR_SLOT(v, 2)));;
+ assert_true(is_quote(VECTOR_SLOT(v, 3)));;
+#if LSTRIP_QUOTED_WSP
+ assert_string_equal(VECTOR_SLOT(v, 4), "is empty");
+#else
+ assert_string_equal(VECTOR_SLOT(v, 4), " is empty");
+#endif
+ assert_true(is_quote(VECTOR_SLOT(v, 5)));;
+
+ val = set_value(v);
+ assert_string_equal(val, "");
+#else
+ assert_int_equal(validate_config_strvec(v, test_file), 0);
+ assert_int_equal(VECTOR_SIZE(v), 4);
+ assert_string_equal(VECTOR_SLOT(v, 0), "keyword");
+ assert_true(is_quote(VECTOR_SLOT(v, 1)));;
+ assert_string_equal(VECTOR_SLOT(v, 2), "\"\" is empty");
+ assert_true(is_quote(VECTOR_SLOT(v, 3)));;
+
+ val = set_value(v);
+ assert_string_equal(val, "\"\" is empty");
+#endif
+ free(val);
+ free_strvec(v);
+}
+
+static void test18(void **state)
+{
+ vector v = alloc_strvec("keyword \"\"\"\"");
+ char *val;
+#if TWO_QUOTES_ONLY
+ assert_int_equal(validate_config_strvec(v, test_file), 0);
+ assert_int_equal(VECTOR_SIZE(v), 5);
+ assert_string_equal(VECTOR_SLOT(v, 0), "keyword");
+ assert_true(is_quote(VECTOR_SLOT(v, 1)));;
+ assert_true(is_quote(VECTOR_SLOT(v, 2)));;
+ assert_true(is_quote(VECTOR_SLOT(v, 3)));;
+ assert_true(is_quote(VECTOR_SLOT(v, 4)));;
+
+ val = set_value(v);
+ assert_string_equal(val, "");
+#else
+ assert_int_equal(validate_config_strvec(v, test_file), 0);
+ assert_int_equal(VECTOR_SIZE(v), 4);
+ assert_string_equal(VECTOR_SLOT(v, 0), "keyword");
+ assert_true(is_quote(VECTOR_SLOT(v, 1)));;
+ assert_string_equal(VECTOR_SLOT(v, 2), "\"");
+ assert_true(is_quote(VECTOR_SLOT(v, 3)));;
+
+ val = set_value(v);
+ assert_string_equal(val, "\"");
+#endif
+ free(val);
+ free_strvec(v);
+}
+
+int test_config_parser(void)
+{
+ const struct CMUnitTest tests[] = {
+ cmocka_unit_test(test01),
+ cmocka_unit_test(test02),
+ cmocka_unit_test(test03),
+ cmocka_unit_test(test04),
+ cmocka_unit_test(test05),
+ cmocka_unit_test(test06),
+ cmocka_unit_test(test07),
+ cmocka_unit_test(test08),
+ cmocka_unit_test(test09),
+ cmocka_unit_test(test10),
+ cmocka_unit_test(test11),
+ cmocka_unit_test(test12),
+ cmocka_unit_test(test13),
+ cmocka_unit_test(test14),
+ cmocka_unit_test(test15),
+ cmocka_unit_test(test16),
+ cmocka_unit_test(test17),
+ cmocka_unit_test(test18),
+ };
+ return cmocka_run_group_tests(tests, setup, teardown);
+}
+
+int main(void)
+{
+ int ret = 0;
+
+ ret += test_config_parser();
+ return ret;
+}
static void test_dm_name_good(void **state)
{
struct uevent *uev = *state;
- const char *name = uevent_get_dm_name(uev);
+ char *name = uevent_get_dm_name(uev);
assert_string_equal(name, DM_NAME);
- free((void*)name);
+ FREE(name);
}
static void test_dm_name_bad_0(void **state)
{
struct uevent *uev = *state;
- const char *name;
+ char *name;
uev->envp[3] = "DM_NAME" DM_NAME;
name = uevent_get_dm_name(uev);
assert_ptr_equal(name, NULL);
- free((void*)name);
+ FREE(name);
}
static void test_dm_name_bad_1(void **state)
{
struct uevent *uev = *state;
- const char *name;
+ char *name;
uev->envp[3] = "DM_NAMES=" DM_NAME;
name = uevent_get_dm_name(uev);
assert_ptr_equal(name, NULL);
- free((void*)name);
+ FREE(name);
}
static void test_dm_name_good_1(void **state)
{
struct uevent *uev = *state;
- const char *name;
+ char *name;
/* Note we change index 2 here */
uev->envp[2] = "DM_NAME=" DM_NAME;
name = uevent_get_dm_name(uev);
assert_string_equal(name, DM_NAME);
- free((void*)name);
+ FREE(name);
}
static void test_dm_uuid_false_0(void **state)