test: Support more options

Adds -g, -G, -k, -O and -u options.
This commit is contained in:
implicitfield 2022-09-30 21:11:49 +03:00 committed by Andreas Kling
parent caab6ac968
commit 6c86b40724
Notes: sideshowbarker 2024-07-17 06:25:32 +09:00
2 changed files with 97 additions and 3 deletions

View File

@ -71,6 +71,11 @@ The expression can take any of the following forms:
* `-w <file>` whether the current user has write access to the file
* `-x <file>` whether the current user has execute access to the file
* `-e <file>` whether the file exists
* `-g <file>` whether the file exists and has the set-group-ID bit set
* `-G <file>` whether the file exists and is owned by the effective group ID
* `-k <file>` whether the file exists and has the sticky bit set
* `-O <file>` whether the file exists and is owned by the effective user ID
* `-u <file>` whether the file exists and has the set-user-ID bit set
Except for `-h/-L`, all file checks dereference symbolic links.

View File

@ -182,6 +182,89 @@ private:
Permission m_kind { Read };
};
class FileHasFlag : public Condition {
public:
enum Flag {
SGID,
SUID,
SVTX,
};
FileHasFlag(StringView path, Flag kind)
: m_path(path)
, m_kind(kind)
{
}
private:
virtual bool check() const override
{
struct stat statbuf;
int rc = stat(m_path.characters(), &statbuf);
if (rc < 0) {
if (errno != ENOENT) {
perror(m_path.characters());
g_there_was_an_error = true;
}
return false;
}
switch (m_kind) {
case SGID:
return statbuf.st_mode & S_ISGID;
case SUID:
return statbuf.st_mode & S_ISUID;
case SVTX:
return statbuf.st_mode & S_ISVTX;
default:
VERIFY_NOT_REACHED();
}
}
String m_path;
Flag m_kind { SGID };
};
class FileIsOwnedBy : public Condition {
public:
enum Owner {
EffectiveGID,
EffectiveUID,
};
FileIsOwnedBy(StringView path, Owner kind)
: m_path(path)
, m_kind(kind)
{
}
private:
virtual bool check() const override
{
struct stat statbuf;
int rc = stat(m_path.characters(), &statbuf);
if (rc < 0) {
if (errno != ENOENT) {
perror(m_path.characters());
g_there_was_an_error = true;
}
return false;
}
switch (m_kind) {
case EffectiveGID:
return statbuf.st_gid == getgid();
case EffectiveUID:
return statbuf.st_uid == getuid();
default:
VERIFY_NOT_REACHED();
}
}
String m_path;
Owner m_kind { EffectiveGID };
};
class StringCompare : public Condition {
public:
enum Mode {
@ -374,6 +457,12 @@ static OwnPtr<Condition> parse_simple_expression(char* argv[])
return make<UserHasPermission>(value, UserHasPermission::Execute);
case 'e':
return make<UserHasPermission>(value, UserHasPermission::Any);
case 'g':
return make<FileHasFlag>(value, FileHasFlag::SGID);
case 'k':
return make<FileHasFlag>(value, FileHasFlag::SVTX);
case 'u':
return make<FileHasFlag>(value, FileHasFlag::SUID);
case 'o':
case 'a':
// '-a' and '-o' are boolean ops, which are part of a complex expression
@ -384,11 +473,11 @@ static OwnPtr<Condition> parse_simple_expression(char* argv[])
return make<StringCompare>(""sv, value, StringCompare::NotEqual);
case 'z':
return make<StringCompare>(""sv, value, StringCompare::Equal);
case 'g':
case 'G':
case 'k':
case 'N':
return make<FileIsOwnedBy>(value, FileIsOwnedBy::EffectiveGID);
case 'O':
return make<FileIsOwnedBy>(value, FileIsOwnedBy::EffectiveUID);
case 'N':
case 's':
// 'optind' has been incremented to refer to the argument after the
// operator, while we want to print the operator itself.