mksquashfs: fix cmdline arg free if >1 source dir and one of them is excluded

If you specify multiple sources (directories and/or files) on the command
line, Mksquashfs will merge those sources into a root directory
containing all of them.  This is different to the behaviour when
a single directory is specified, in which case Mksquashfs creates
a filesystem with the root containing the contents of the source
directory.

The difference manifests itself in the way the pathname of each
of the directory entries is stored/obtained.  Normally to reduce
runtime overhead when the directory entries have all come from the
same parent directory, the source pathname is not stored in each
directory entry, but is computed from the source pathname of the
parent directory.  But in the case of the "dummy" root created
to merge multiple sources specified on the command line, each
directory entry does not share the same parent pathname, and so
the source pathname of each directory entry is stored in the
nonstandard_pathname field.  This nonstandard_pathname was originally
filled in using a pointer to the source pathname on the command line.

Now, if you later exclude one of these source directories, Mksquashfs
will free the storage, and it will try and free the nonstandard_pathname
field, which leads to a crash as you cannot free a command line argument.

The fix to this is to strdup the command line source and store the
copy in the directory entry.

This is not considered a serious bug, it has not been reported, and
the scenario was discovered by chance whilst looking at the code.
Additionally the trigger scenario is highly artificial and there
is no use-case where this bug will be triggered.  To trigger it you
need to specifiy multiple source command arguments, and then you
need to exclude one of them.  But, if you explicitly specified it
on the command line why would you later exclude it, and if
you did want to exclude it the obvious way would be to remove it
from the command line.

Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>
action: split the execute mode code out of mode_action()

Allowing it to be used by the (to be added later) perm test function.

Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>
actions: update test function parser to handle variable amount of arguments

Update the test function parser to handle variable amount of arguments,
as that's now needed for the perm() test function.  Up till now, though
updating the test parser has been a TODO, it been a low priority because
it's done what's needed.

Updating the parser to speculatively read the number of arguments
present (and hence handle variable number of arguments) has been a
TODO even without the need to handle a variable number of arguments
because experience gained updating the action parser to do this showed
it generates better syntax error messages.

Previously the parser just parsed the number of arguments expected, and
then quit.  The parser now parses all the arguments present, and then
compares it against what was expected.

No big deal?  Well guess what gives the better syntax error if you
enter too many arguments.  Reading just the number of arguments
expected, and then quitting, means the extra arguments cause to
paraphrase a "I expected a ) here, and I got a comma or string".
Now, you get an error message like "I got 5 arguments, but only
expected 2".  Which IMHO is a better syntax error message.

Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>
action: fix move argument parsing

At one point in time it was anticipated that the move action
might take multiple arguments.  So it used the multi argument
setting of "-2"...

But the current implementation expects one argument only.  But
the -2 setting allows zero arguments which isn't expected.  So
enforce 1 argument.

Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>
actions: implement perm() test function

Implement perm() test function, this is modelled directly on
find -perm and implements its behaviour.

Following find, three types of match are supported:

perm(mode) - exact match
perm(-mode) - all of the permission bits are set for the file
perm(/mode) - any of the permission bits are set for the file

With perm(/mode) if no permission bits are set in mode match
on any file, this is to be consistent with find, which
does this to be consistent with the behaviour of
-perm -000

Note, only symbolic modes are currently implemented.  Octal modes
will be implemented next.

Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>