blob: d6cc79e5a38ba12181072d9f1263e408fd280afc [file] [log] [blame]
/*
* Copyright (c) International Business Machines Corp., 2001
* 03/2001 Written by Wayne Boyer
* 11/2016 Modified by Guangwen Feng <fenggw-fnst@cn.fujitsu.com>
*
* 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, see <http://www.gnu.org/licenses/>.
*/
/*
* Verify that setpriority(2) succeeds set the scheduling priority of
* the current process, process group or user.
*/
#define _GNU_SOURCE
#include <errno.h>
#include <pwd.h>
#include <stdlib.h>
#include <sys/resource.h>
#include "tst_test.h"
static const char *username = "ltp_setpriority01";
static int pid, uid, user_added;
static struct tcase {
int which;
int *who;
} tcases[] = {
{PRIO_PROCESS, &pid},
{PRIO_PGRP, &pid},
{PRIO_USER, &uid}
};
static const char *str_which(int which)
{
switch (which) {
case PRIO_PROCESS:
return "PRIO_PROCESS";
case PRIO_PGRP:
return "PRIO_PGRP";
case PRIO_USER:
return "PRIO_USER";
default:
return "???";
}
}
static void setpriority_test(struct tcase *tc)
{
int new_prio, cur_prio;
int failflag = 0;
for (new_prio = -20; new_prio < 20; new_prio++) {
TEST(setpriority(tc->which, *tc->who, new_prio));
if (TEST_RETURN != 0) {
tst_res(TFAIL | TTERRNO,
"setpriority(%d, %d, %d) failed",
tc->which, *tc->who, new_prio);
failflag = 1;
continue;
}
cur_prio = SAFE_GETPRIORITY(tc->which, *tc->who);
if (cur_prio != new_prio) {
tst_res(TFAIL, "current priority(%d) and "
"new priority(%d) do not match",
cur_prio, new_prio);
failflag = 1;
}
}
if (!failflag) {
tst_res(TPASS, "setpriority(%s(%d), %d, -20..19) succeeded",
str_which(tc->which), tc->which, *tc->who);
}
}
static void verify_setpriority(unsigned int n)
{
struct tcase *tc = &tcases[n];
pid = SAFE_FORK();
if (pid == 0) {
SAFE_SETUID(uid);
SAFE_SETPGID(0, 0);
TST_CHECKPOINT_WAKE_AND_WAIT(0);
exit(0);
}
TST_CHECKPOINT_WAIT(0);
setpriority_test(tc);
TST_CHECKPOINT_WAKE(0);
tst_reap_children();
}
static void setup(void)
{
const char *const cmd_useradd[] = {"useradd", username, NULL};
struct passwd *ltpuser;
if (eaccess("/etc/passwd", W_OK))
tst_brk(TCONF, "/etc/passwd is not accessible");
tst_run_cmd(cmd_useradd, NULL, NULL, 0);
user_added = 1;
ltpuser = SAFE_GETPWNAM(username);
uid = ltpuser->pw_uid;
}
static void cleanup(void)
{
if (!user_added)
return;
const char *const cmd_userdel[] = {"userdel", "-r", username, NULL};
if (tst_run_cmd(cmd_userdel, NULL, NULL, 1))
tst_res(TWARN | TERRNO, "'userdel -r %s' failed", username);
}
static struct tst_test test = {
.tcnt = ARRAY_SIZE(tcases),
.needs_root = 1,
.forks_child = 1,
.needs_checkpoints = 1,
.setup = setup,
.cleanup = cleanup,
.test = verify_setpriority,
};