Merge branch 'misc' of git://github.com/kerolasa/lelux-utiliteetit

* 'misc' of git://github.com/kerolasa/lelux-utiliteetit:
  textual: share crypt() error message in sulogin and newgrp
  newgrp: avoid use of obsolete getpass() function
  newgrp: use libc function to read gshadow if it is available
  setarch: use personality() system call when it is available
  setarch: reindent code
  hwclock: remove referal to deprecated keyboard interface
  eject: make open_device() and select_speed() to use struct eject_control
  eject: add struct eject_control to remove global variables
  mountpoint: simplify if statement
  mkfs.minix: fix couple compiler warnings
  mountpoint: add struct mountpoint_control
  last: improve code readability by renaming variable names
  last: make is_phantom() when kernel config does not include audit support
  lib: remove xgetpass()
  include: simplify fputc_careful() in carefulputc.h
  libuuid: add extern qualifiers to uuid/uuid.h system header
This commit is contained in:
Karel Zak 2014-09-22 14:55:37 +02:00
commit 286f1e229b
17 changed files with 627 additions and 813 deletions

View File

@ -310,6 +310,7 @@ AC_CHECK_FUNCS([ \
getexecname \
getmntinfo \
getrlimit \
getsgnam \
inotify_init \
inotify_init1 \
jrand48 \

View File

@ -362,9 +362,11 @@ static void make_bad_inode_v2_v3 (void)
static void make_bad_inode(void)
{
if (fs_version < 2)
return make_bad_inode_v1();
return make_bad_inode_v2_v3();
if (fs_version < 2) {
make_bad_inode_v1();
return;
}
make_bad_inode_v2_v3();
}
static void make_root_inode_v1(void) {
@ -412,9 +414,11 @@ static void make_root_inode_v2_v3 (void) {
static void make_root_inode(void)
{
if (fs_version < 2)
return make_root_inode_v1();
return make_root_inode_v2_v3();
if (fs_version < 2) {
make_root_inode_v1();
return;
}
make_root_inode_v2_v3();
}
static void super_set_nzones(void)

View File

@ -49,7 +49,6 @@ dist_noinst_HEADERS += \
include/ttyutils.h \
include/widechar.h \
include/xalloc.h \
include/xgetpass.h \
include/pt-sgi.h \
include/pt-bsd.h \
include/pt-mbr.h \

View File

@ -10,26 +10,22 @@
#include <string.h>
#include <ctype.h>
#define iso8859x_iscntrl(c) \
(((c) & 0x7f) < 0x20 || (c) == 0x7f)
static inline int fputc_careful(int c, FILE *fp, const char fail) {
static inline int fputc_careful(int c, FILE *fp, const char fail)
{
int ret;
if (c == '\007' || c == '\t' || c == '\r' || c == '\n' ||
(!iso8859x_iscntrl(c) && (isprint(c) || isspace(c))))
if (isprint(c) || c == '\a' || c == '\t' || c == '\r' || c == '\n')
ret = putc(c, fp);
else if ((c & 0x80) || !isprint(c^0x40))
ret = fprintf(fp, "\\%3o", (unsigned char) c);
else if (!isascii(c))
ret = fprintf(fp, "\\%3o", (unsigned char)c);
else {
ret = putc(fail, fp);
if (ret != EOF)
ret = putc(c^0x40, fp);
ret = putc(c ^ 0x40, fp);
}
return (ret < 0) ? EOF : 0;
}
static inline void fputs_quoted(const char *data, FILE *out)
{
const char *p;

View File

@ -1,6 +0,0 @@
#ifndef UTIL_LINUX_XGETPASS_H
#define UTIL_LINUX_XGETPASS_H
extern char *xgetpass(int pfd, const char *prompt);
#endif /* UTIL_LINUX_XGETPASS_H */

View File

@ -24,7 +24,6 @@ libcommon_la_SOURCES = \
lib/sysfs.c \
lib/timeutils.c \
lib/ttyutils.c \
lib/xgetpass.c \
lib/exec_shell.c \
lib/readutmp.c

View File

@ -1,46 +0,0 @@
/*
* A function to read the passphrase either from the terminal or from
* an open file descriptor.
*
* Public domain.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include "c.h"
#include "xgetpass.h"
char *xgetpass(int pfd, const char *prompt)
{
char *pass = NULL;
int len = 0, i;
if (pfd < 0) /* terminal */
return getpass(prompt);
for (i=0; ; i++) {
if (i >= len-1) {
char *tmppass = pass;
len += 128;
pass = realloc(tmppass, len);
if (!pass) {
pass = tmppass; /* the old buffer hasn't changed */
break;
}
}
if (pass && (read(pfd, pass + i, 1) != 1 ||
pass[i] == '\n' || pass[i] == 0))
break;
}
if (pass)
pass[i] = '\0';
return pass;
}

View File

@ -67,35 +67,35 @@ extern "C" {
#endif
/* clear.c */
void uuid_clear(uuid_t uu);
extern void uuid_clear(uuid_t uu);
/* compare.c */
int uuid_compare(const uuid_t uu1, const uuid_t uu2);
extern int uuid_compare(const uuid_t uu1, const uuid_t uu2);
/* copy.c */
void uuid_copy(uuid_t dst, const uuid_t src);
extern void uuid_copy(uuid_t dst, const uuid_t src);
/* gen_uuid.c */
void uuid_generate(uuid_t out);
void uuid_generate_random(uuid_t out);
void uuid_generate_time(uuid_t out);
int uuid_generate_time_safe(uuid_t out);
extern void uuid_generate(uuid_t out);
extern void uuid_generate_random(uuid_t out);
extern void uuid_generate_time(uuid_t out);
extern int uuid_generate_time_safe(uuid_t out);
/* isnull.c */
int uuid_is_null(const uuid_t uu);
extern int uuid_is_null(const uuid_t uu);
/* parse.c */
int uuid_parse(const char *in, uuid_t uu);
extern int uuid_parse(const char *in, uuid_t uu);
/* unparse.c */
void uuid_unparse(const uuid_t uu, char *out);
void uuid_unparse_lower(const uuid_t uu, char *out);
void uuid_unparse_upper(const uuid_t uu, char *out);
extern void uuid_unparse(const uuid_t uu, char *out);
extern void uuid_unparse_lower(const uuid_t uu, char *out);
extern void uuid_unparse_upper(const uuid_t uu, char *out);
/* uuid_time.c */
time_t uuid_time(const uuid_t uu, struct timeval *ret_tv);
int uuid_type(const uuid_t uu);
int uuid_variant(const uuid_t uu);
extern time_t uuid_time(const uuid_t uu, struct timeval *ret_tv);
extern int uuid_type(const uuid_t uu);
extern int uuid_variant(const uuid_t uu);
#ifdef __cplusplus
}

View File

@ -376,9 +376,9 @@ static void trim_trailing_spaces(char *s)
/*
* Show one line of information on screen
*/
static int list(const struct last_control *ctl, struct utmp *p, time_t t, int what)
static int list(const struct last_control *ctl, struct utmp *p, time_t logout_time, int what)
{
time_t secs, tmp, epoch;
time_t secs, utmp_time, now;
char logintime[LAST_TIMESTAMP_LEN];
char logouttime[LAST_TIMESTAMP_LEN];
char length[LAST_TIMESTAMP_LEN];
@ -417,22 +417,25 @@ static int list(const struct last_control *ctl, struct utmp *p, time_t t, int wh
/*
* Calculate times
*/
tmp = p->UL_UT_TIME;
utmp_time = p->UL_UT_TIME;
if (ctl->present && (ctl->present < tmp || (0 < t && t < ctl->present)))
return 0;
if (time_formatter(ctl, &logintime[0], sizeof(logintime), &tmp, 0) < 0 ||
time_formatter(ctl, &logouttime[0], sizeof(logouttime), &t, 1) < 0)
if (ctl->present) {
if (ctl->present < utmp_time)
return 0;
if (0 < logout_time && logout_time < ctl->present)
return 0;
}
if (time_formatter(ctl, &logintime[0], sizeof(logintime), &utmp_time, 0) < 0 ||
time_formatter(ctl, &logouttime[0], sizeof(logouttime), &logout_time, 1) < 0)
errx(EXIT_FAILURE, _("preallocation size exceeded"));
secs = t - p->UL_UT_TIME;
secs = logout_time - utmp_time;
mins = (secs / 60) % 60;
hours = (secs / 3600) % 24;
days = secs / 86400;
epoch = time(NULL);
if (t == epoch) {
now = time(NULL);
if (logout_time == now) {
if (ctl->time_fmt > LAST_TIMEFTM_SHORT_CTIME) {
sprintf(logouttime, " still running");
length[0] = 0;
@ -582,8 +585,6 @@ static int is_phantom(const struct last_control *ctl, struct utmp *ut)
{
struct passwd *pw;
char path[32];
FILE *f = NULL;
unsigned int loginuid;
int ret = 0;
if (ut->UL_UT_TIME < ctl->boot_time.tv_sec)
@ -592,14 +593,26 @@ static int is_phantom(const struct last_control *ctl, struct utmp *ut)
if (!pw)
return 1;
sprintf(path, "/proc/%u/loginuid", ut->ut_pid);
if (access(path, R_OK) != 0 || !(f = fopen(path, "r")))
return 1;
if (access(path, R_OK) == 0) {
unsigned int loginuid;
FILE *f = NULL;
if (fscanf(f, "%u", &loginuid) != 1)
ret = 1;
fclose(f);
if (!ret && pw->pw_uid != loginuid)
return 1;
if (!(f = fopen(path, "r")))
return 1;
if (fscanf(f, "%u", &loginuid) != 1)
ret = 1;
fclose(f);
if (!ret && pw->pw_uid != loginuid)
return 1;
} else {
struct stat st;
sprintf(path, "/dev/%s", ut->ut_line);
if (stat(path, &st))
return 1;
if (pw->pw_uid != st.st_uid)
return 1;
}
return ret;
}

View File

@ -22,21 +22,75 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
#ifdef HAVE_CRYPT_H
# include <crypt.h>
#endif
#ifdef HAVE_GETSGNAM
# include <gshadow.h>
#endif
#include "c.h"
#include "closestream.h"
#include "nls.h"
#include "pathnames.h"
#include "xalloc.h"
static char *xgetpass(FILE *input, const char *prompt)
{
char *pass = NULL;
struct termios saved, no_echo;
const int fd = fileno(input);
size_t dummy = 0;
ssize_t len;
fputs(prompt, stdout);
if (isatty(fd)) {
/* disable echo */
tcgetattr(fd, &saved);
no_echo = saved;
no_echo.c_lflag &= ~ECHO;
no_echo.c_lflag |= ECHONL;
if (tcsetattr(fd, TCSANOW, &no_echo))
err(EXIT_FAILURE, _("could not set terminal attributes"));
}
len = getline(&pass, &dummy, input);
if (isatty(fd))
/* restore terminal */
if (tcsetattr(fd, TCSANOW, &saved))
err(EXIT_FAILURE, _("could not set terminal attributes"));
if (len < 0)
err(EXIT_FAILURE, _("could not getline"));
if (0 < len && *(pass + len - 1) == '\n')
*(pass + len - 1) = '\0';
return pass;
}
/* Ensure memory is set to value c without compiler optimization getting
* into way that could happen with memset(3). */
static int memset_s(void *v, size_t sz, const int c)
{
volatile unsigned char *p = v;
if (v == NULL)
return EINVAL;
while (sz--)
*p++ = c;
return 0;
}
/* try to read password from gshadow */
static char *get_gshadow_pwd(char *groupname)
{
#ifdef HAVE_GETSGNAM
struct sgrp *sgrp;
sgrp = getsgnam(groupname);
return sgrp ? xstrdup(sgrp->sg_passwd) : NULL;
#else
char buf[BUFSIZ];
char *pwd = NULL;
FILE *f;
@ -69,6 +123,7 @@ static char *get_gshadow_pwd(char *groupname)
}
fclose(f);
return pwd ? xstrdup(pwd) : NULL;
#endif /* HAVE_GETSGNAM */
}
static int allow_setgid(struct passwd *pe, struct group *ge)
@ -99,11 +154,13 @@ static int allow_setgid(struct passwd *pe, struct group *ge)
if (!(pwd = get_gshadow_pwd(ge->gr_name)))
pwd = ge->gr_passwd;
if (pwd && *pwd && (xpwd = getpass(_("Password: ")))) {
if (pwd && *pwd && (xpwd = xgetpass(stdin, _("Password: ")))) {
char *cbuf = crypt(xpwd, pwd);
memset_s(xpwd, strlen(xpwd), 0);
free(xpwd);
if (!cbuf)
warn(_("crypt() failed"));
warn(_("crypt failed"));
else if (strcmp(pwd, cbuf) == 0)
return TRUE;
}

View File

@ -359,8 +359,7 @@ PATHFILES += sys-utils/hwclock.8
hwclock_SOURCES = \
sys-utils/hwclock.c \
sys-utils/hwclock.h \
sys-utils/hwclock-cmos.c \
sys-utils/hwclock-kd.c
sys-utils/hwclock-cmos.c
if LINUX
hwclock_SOURCES += sys-utils/hwclock-rtc.c
endif

View File

@ -81,31 +81,34 @@ static const char * const hotplug_subsystems[] = {
"ccw"
};
/* Global Variables */
static int a_option; /* command flags and arguments */
static int c_option;
static int d_option;
static int f_option;
static int F_option;
static int n_option;
static int q_option;
static int r_option;
static int s_option;
static int t_option;
static int T_option;
static int X_option;
static int v_option;
static int x_option;
static int p_option;
static int m_option;
static int M_option;
static int i_option;
static int a_arg;
static int i_arg;
static long int c_arg;
static long int x_arg;
struct libmnt_table *mtab;
struct eject_control {
struct libmnt_table *mtab;
char *device; /* device or mount point to be ejected */
int fd; /* file descriptor for device */
unsigned int /* command flags and arguments */
a_option:1,
c_option:1,
d_option:1,
F_option:1,
f_option:1,
i_option:1,
M_option:1,
m_option:1,
n_option:1,
p_option:1,
q_option:1,
r_option:1,
s_option:1,
T_option:1,
t_option:1,
v_option:1,
X_option:1,
x_option:1,
a_arg:1,
i_arg:1;
long int c_arg; /* changer slot number */
long int x_arg; /* cd speed */
};
static void vinfo(const char *fmt, va_list va)
{
@ -114,11 +117,11 @@ static void vinfo(const char *fmt, va_list va)
fputc('\n', stdout);
}
static inline void verbose(const char *fmt, ...)
static inline void verbose(const struct eject_control *ctl, const char *fmt, ...)
{
va_list va;
if (!v_option)
if (!ctl->v_option)
return;
va_start(va, fmt);
@ -174,7 +177,7 @@ static void __attribute__ ((__noreturn__)) usage(FILE * out)
/* Handle command line options. */
static void parse_args(int argc, char **argv, char **device)
static void parse_args(struct eject_control *ctl, int argc, char **argv)
{
static const struct option long_opts[] =
{
@ -206,75 +209,75 @@ static void parse_args(int argc, char **argv, char **device)
"a:c:i:x:dfFhnqrstTXvVpmM", long_opts, NULL)) != -1) {
switch (c) {
case 'a':
a_option = 1;
ctl->a_option = 1;
if (!strcmp(optarg, "0") || !strcmp(optarg, "off"))
a_arg = 0;
ctl->a_arg = 0;
else if (!strcmp(optarg, "1") || !strcmp(optarg, "on"))
a_arg = 1;
ctl->a_arg = 1;
else
errx(EXIT_FAILURE, _("invalid argument to --auto/-a option"));
break;
case 'c':
c_option = 1;
c_arg = strtoul_or_err(optarg, _("invalid argument to --changerslot/-c option"));
ctl->c_option = 1;
ctl->c_arg = strtoul_or_err(optarg, _("invalid argument to --changerslot/-c option"));
break;
case 'x':
x_option = 1;
x_arg = strtoul_or_err(optarg, _("invalid argument to --cdspeed/-x option"));
ctl->x_option = 1;
ctl->x_arg = strtoul_or_err(optarg, _("invalid argument to --cdspeed/-x option"));
break;
case 'd':
d_option = 1;
ctl->d_option = 1;
break;
case 'f':
f_option = 1;
ctl->f_option = 1;
break;
case 'F':
F_option = 1;
ctl->F_option = 1;
break;
case 'h':
usage(stdout);
break;
case 'i':
i_option = 1;
ctl->i_option = 1;
if (!strcmp(optarg, "0") || !strcmp(optarg, "off"))
i_arg = 0;
ctl->i_arg = 0;
else if (!strcmp(optarg, "1") || !strcmp(optarg, "on"))
i_arg = 1;
ctl->i_arg = 1;
else
errx(EXIT_FAILURE, _("invalid argument to --manualeject/-i option"));
break;
case 'm':
m_option = 1;
ctl->m_option = 1;
break;
case 'M':
M_option = 1;
ctl->M_option = 1;
break;
case 'n':
n_option = 1;
ctl->n_option = 1;
break;
case 'p':
p_option = 1;
ctl->p_option = 1;
break;
case 'q':
q_option = 1;
ctl->q_option = 1;
break;
case 'r':
r_option = 1;
ctl->r_option = 1;
break;
case 's':
s_option = 1;
ctl->s_option = 1;
break;
case 't':
t_option = 1;
ctl->t_option = 1;
break;
case 'T':
T_option = 1;
ctl->T_option = 1;
break;
case 'X':
X_option = 1;
ctl->X_option = 1;
break;
case 'v':
v_option = 1;
ctl->v_option = 1;
break;
case 'V':
printf(UTIL_LINUX_VERSION);
@ -292,7 +295,7 @@ static void parse_args(int argc, char **argv, char **device)
errx(EXIT_FAILURE, _("too many arguments"));
if ((argc - optind) == 1)
*device = xstrdup(argv[optind]);
ctl->device = xstrdup(argv[optind]);
}
/*
@ -323,15 +326,15 @@ static char *find_device(const char *name)
}
/* Set or clear auto-eject mode. */
static void auto_eject(int fd, int on)
static void auto_eject(const struct eject_control *ctl)
{
int status = -1;
#if defined(CDROM_SET_OPTIONS) && defined(CDROM_CLEAR_OPTIONS)
if (on)
status = ioctl(fd, CDROM_SET_OPTIONS, CDO_AUTO_EJECT);
if (ctl->a_arg)
status = ioctl(ctl->fd, CDROM_SET_OPTIONS, CDO_AUTO_EJECT);
else
status = ioctl(fd, CDROM_CLEAR_OPTIONS, CDO_AUTO_EJECT);
status = ioctl(ctl->fd, CDROM_CLEAR_OPTIONS, CDO_AUTO_EJECT);
#else
errno = ENOSYS;
#endif
@ -350,12 +353,12 @@ static void auto_eject(int fd, int on)
* EBUSY Attempt to unlock when multiple users
* have the drive open and not CAP_SYS_ADMIN
*/
static void manual_eject(int fd, int on)
static void manual_eject(const struct eject_control *ctl)
{
if (ioctl(fd, CDROM_LOCKDOOR, on) < 0)
if (ioctl(ctl->fd, CDROM_LOCKDOOR, ctl->i_arg) < 0)
err(EXIT_FAILURE, _("CD-ROM lock door command failed"));
if (on)
if (ctl->i_arg)
info(_("CD-Drive may NOT be ejected with device button"));
else
info(_("CD-Drive may be ejected with device button"));
@ -365,14 +368,14 @@ static void manual_eject(int fd, int on)
* Changer select. CDROM_SELECT_DISC is preferred, older kernels used
* CDROMLOADFROMSLOT.
*/
static void changer_select(int fd, int slot)
static void changer_select(const struct eject_control *ctl)
{
#ifdef CDROM_SELECT_DISC
if (ioctl(fd, CDROM_SELECT_DISC, slot) < 0)
if (ioctl(ctl->fd, CDROM_SELECT_DISC, ctl->c_arg) < 0)
err(EXIT_FAILURE, _("CD-ROM select disc command failed"));
#elif defined CDROMLOADFROMSLOT
if (ioctl(fd, CDROMLOADFROMSLOT, slot) != 0)
if (ioctl(ctl->fd, CDROMLOADFROMSLOT, ctl->c_arg) != 0)
err(EXIT_FAILURE, _("CD-ROM load from slot command failed"));
#else
warnx(_("IDE/ATAPI CD-ROM changer not supported by this kernel\n") );
@ -485,10 +488,10 @@ static void toggle_tray(int fd)
* Thanks to Roland Krivanek (krivanek@fmph.uniba.sk)
* http://dmpc.dbp.fmph.uniba.sk/~krivanek/cdrom_speed/
*/
static void select_speed(int fd, int speed)
static void select_speed(const struct eject_control *ctl)
{
#ifdef CDROM_SELECT_SPEED
if (ioctl(fd, CDROM_SELECT_SPEED, speed) != 0)
if (ioctl(ctl->fd, CDROM_SELECT_SPEED, ctl->x_arg) != 0)
err(EXIT_FAILURE, _("CD-ROM select speed command failed"));
#else
warnx(_("CD-ROM select speed command not supported by this kernel"));
@ -557,22 +560,22 @@ static int read_speed(const char *devname)
/*
* List Speed of CD-ROM drive.
*/
static void list_speeds(const char *name, int fd)
static void list_speeds(struct eject_control *ctl)
{
#ifdef CDROM_SELECT_SPEED
int max_speed, curr_speed = 0, prev_speed;
int max_speed, curr_speed = 0;
select_speed(fd, 0);
max_speed = read_speed(name);
select_speed(ctl);
max_speed = read_speed(ctl->device);
while (curr_speed < max_speed) {
prev_speed = curr_speed;
select_speed(fd, prev_speed + 1);
curr_speed = read_speed(name);
if (curr_speed > prev_speed)
ctl->x_arg = curr_speed + 1;
select_speed(ctl);
curr_speed = read_speed(ctl->device);
if (ctl->x_arg < curr_speed)
printf("%d ", curr_speed);
else
curr_speed = prev_speed + 1;
curr_speed = ctl->x_arg + 1;
}
printf("\n");
@ -584,7 +587,7 @@ static void list_speeds(const char *name, int fd)
/*
* Eject using SCSI SG_IO commands. Return 1 if successful, 0 otherwise.
*/
static int eject_scsi(int fd)
static int eject_scsi(const struct eject_control *ctl)
{
int status, k;
sg_io_hdr_t io_hdr;
@ -594,8 +597,8 @@ static int eject_scsi(int fd)
unsigned char inqBuff[2];
unsigned char sense_buffer[32];
if ((ioctl(fd, SG_GET_VERSION_NUM, &k) < 0) || (k < 30000)) {
verbose(_("not an sg device, or old sg driver"));
if ((ioctl(ctl->fd, SG_GET_VERSION_NUM, &k) < 0) || (k < 30000)) {
verbose(ctl, _("not an sg device, or old sg driver"));
return 0;
}
@ -610,12 +613,12 @@ static int eject_scsi(int fd)
io_hdr.timeout = 10000;
io_hdr.cmdp = allowRmBlk;
status = ioctl(fd, SG_IO, (void *)&io_hdr);
status = ioctl(ctl->fd, SG_IO, (void *)&io_hdr);
if (status < 0 || io_hdr.host_status || io_hdr.driver_status)
return 0;
io_hdr.cmdp = startStop1Blk;
status = ioctl(fd, SG_IO, (void *)&io_hdr);
status = ioctl(ctl->fd, SG_IO, (void *)&io_hdr);
if (status < 0 || io_hdr.host_status)
return 0;
@ -630,12 +633,12 @@ static int eject_scsi(int fd)
return 0;
io_hdr.cmdp = startStop2Blk;
status = ioctl(fd, SG_IO, (void *)&io_hdr);
status = ioctl(ctl->fd, SG_IO, (void *)&io_hdr);
if (status < 0 || io_hdr.host_status || io_hdr.driver_status)
return 0;
/* force kernel to reread partition table when new disc inserted */
ioctl(fd, BLKRRPART);
ioctl(ctl->fd, BLKRRPART);
return 1;
}
@ -660,14 +663,14 @@ static int eject_tape(int fd)
/* umount a device. */
static void umount_one(const char *name)
static void umount_one(const struct eject_control *ctl, const char *name)
{
int status;
if (!name)
return;
verbose(_("%s: unmounting"), name);
verbose(ctl, _("%s: unmounting"), name);
switch (fork()) {
case 0: /* child */
@ -677,7 +680,7 @@ static void umount_one(const char *name)
if (setuid(getuid()) < 0)
err(EXIT_FAILURE, _("cannot set user id"));
if (p_option)
if (ctl->p_option)
execl("/bin/umount", "/bin/umount", name, "-n", NULL);
else
execl("/bin/umount", "/bin/umount", name, NULL);
@ -701,51 +704,49 @@ static void umount_one(const char *name)
}
/* Open a device file. */
static int open_device(const char *name)
static void open_device(struct eject_control *ctl)
{
int fd = open(name, O_RDWR|O_NONBLOCK);
if (fd < 0)
fd = open(name, O_RDONLY|O_NONBLOCK);
if (fd == -1)
err(EXIT_FAILURE, _("cannot open %s"), name);
return fd;
ctl->fd = open(ctl->device, O_RDWR | O_NONBLOCK);
if (ctl->fd < 0)
ctl->fd = open(ctl->device, O_RDONLY | O_NONBLOCK);
if (ctl->fd == -1)
err(EXIT_FAILURE, _("cannot open %s"), ctl->device);
}
/*
* See if device has been mounted by looking in mount table. If so, set
* device name and mount point name, and return 1, otherwise return 0.
*/
static int device_get_mountpoint(char **devname, char **mnt)
static int device_get_mountpoint(struct eject_control *ctl, char **devname, char **mnt)
{
struct libmnt_fs *fs;
int rc;
*mnt = NULL;
if (!mtab) {
if (!ctl->mtab) {
struct libmnt_cache *cache;
mtab = mnt_new_table();
if (!mtab)
ctl->mtab = mnt_new_table();
if (!ctl->mtab)
err(EXIT_FAILURE, _("failed to initialize libmount table"));
cache = mnt_new_cache();
mnt_table_set_cache(mtab, cache);
mnt_table_set_cache(ctl->mtab, cache);
mnt_unref_cache(cache);
if (p_option)
rc = mnt_table_parse_file(mtab, _PATH_PROC_MOUNTINFO);
if (ctl->p_option)
rc = mnt_table_parse_file(ctl->mtab, _PATH_PROC_MOUNTINFO);
else
rc = mnt_table_parse_mtab(mtab, NULL);
rc = mnt_table_parse_mtab(ctl->mtab, NULL);
if (rc)
err(EXIT_FAILURE, _("failed to parse mount table"));
}
fs = mnt_table_find_source(mtab, *devname, MNT_ITER_BACKWARD);
fs = mnt_table_find_source(ctl->mtab, *devname, MNT_ITER_BACKWARD);
if (!fs) {
/* maybe 'devname' is mountpoint rather than a real device */
fs = mnt_table_find_target(mtab, *devname, MNT_ITER_BACKWARD);
fs = mnt_table_find_target(ctl->mtab, *devname, MNT_ITER_BACKWARD);
if (fs) {
free(*devname);
*devname = xstrdup(mnt_fs_get_source(fs));
@ -774,7 +775,7 @@ static char *get_disk_devname(const char *device)
return st.st_rdev == diskno ? NULL : find_device(diskname);
}
static int umount_partitions(const char *disk, int checkonly)
static int umount_partitions(struct eject_control *ctl)
{
struct sysfs_cxt cxt = UL_SYSFSCXT_EMPTY;
dev_t devno;
@ -782,7 +783,7 @@ static int umount_partitions(const char *disk, int checkonly)
struct dirent *d;
int count = 0;
devno = sysfs_devname_to_devno(disk, NULL);
devno = sysfs_devname_to_devno(ctl->device, NULL);
if (sysfs_init(&cxt, devno, NULL) != 0)
return 0;
@ -795,14 +796,14 @@ static int umount_partitions(const char *disk, int checkonly)
if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
continue;
if (sysfs_is_partition_dirent(dir, d, disk)) {
if (sysfs_is_partition_dirent(dir, d, ctl->device)) {
char *mnt = NULL;
char *dev = find_device(d->d_name);
if (dev && device_get_mountpoint(&dev, &mnt) == 0) {
verbose(_("%s: mounted on %s"), dev, mnt);
if (!checkonly)
umount_one(mnt);
if (dev && device_get_mountpoint(ctl, &dev, &mnt) == 0) {
verbose(ctl, _("%s: mounted on %s"), dev, mnt);
if (!ctl->M_option)
umount_one(ctl, mnt);
count++;
}
free(dev);
@ -881,7 +882,7 @@ static char *get_subsystem(char *chain, char *buf, size_t bufsz)
return NULL;
}
static int is_hotpluggable(const char* device)
static int is_hotpluggable(const struct eject_control *ctl)
{
struct sysfs_cxt cxt = UL_SYSFSCXT_EMPTY;
char devchain[PATH_MAX];
@ -891,13 +892,13 @@ static int is_hotpluggable(const char* device)
ssize_t sz;
char *sub;
devno = sysfs_devname_to_devno(device, NULL);
devno = sysfs_devname_to_devno(ctl->device, NULL);
if (sysfs_init(&cxt, devno, NULL) != 0)
return 0;
/* check /sys/dev/block/<maj>:<min>/removable attribute */
if (sysfs_read_int(&cxt, "removable", &rc) == 0 && rc == 1) {
verbose(_("%s: is removable device"), device);
verbose(ctl, _("%s: is removable device"), ctl->device);
goto done;
}
@ -916,8 +917,8 @@ static int is_hotpluggable(const char* device)
while ((sub = get_subsystem(devchain, subbuf, sizeof(subbuf)))) {
rc = is_hotpluggable_subsystem(sub);
if (rc) {
verbose(_("%s: connected by hotplug subsystem: %s"),
device, sub);
verbose(ctl, _("%s: connected by hotplug subsystem: %s"),
ctl->device, sub);
break;
}
}
@ -929,20 +930,18 @@ done:
/* handle -x option */
static void set_device_speed(char *name)
static void set_device_speed(struct eject_control *ctl)
{
int fd;
if (!x_option)
if (!ctl->x_option)
return;
if (x_arg == 0)
verbose(_("setting CD-ROM speed to auto"));
if (ctl->x_arg == 0)
verbose(ctl, _("setting CD-ROM speed to auto"));
else
verbose(_("setting CD-ROM speed to %ldX"), x_arg);
verbose(ctl, _("setting CD-ROM speed to %ldX"), ctl->x_arg);
fd = open_device(name);
select_speed(fd, x_arg);
open_device(ctl);
select_speed(ctl);
exit(EXIT_SUCCESS);
}
@ -950,11 +949,10 @@ static void set_device_speed(char *name)
/* main program */
int main(int argc, char **argv)
{
char *device = NULL;
char *disk = NULL;
char *mountpoint = NULL;
int worked = 0; /* set to 1 when successfully ejected */
int fd; /* file descriptor for device */
struct eject_control ctl = { 0 };
setlocale(LC_ALL,"");
bindtextdomain(PACKAGE, LOCALEDIR);
@ -962,118 +960,118 @@ int main(int argc, char **argv)
atexit(close_stdout);
/* parse the command line arguments */
parse_args(argc, argv, &device);
parse_args(&ctl, argc, argv);
/* handle -d option */
if (d_option) {
if (ctl.d_option) {
info(_("default device: `%s'"), EJECT_DEFAULT_DEVICE);
return EXIT_SUCCESS;
}
if (!device) {
device = mnt_resolve_path(EJECT_DEFAULT_DEVICE, NULL);
verbose(_("using default device `%s'"), device);
if (!ctl.device) {
ctl.device = mnt_resolve_path(EJECT_DEFAULT_DEVICE, NULL);
verbose(&ctl, _("using default device `%s'"), ctl.device);
} else {
char *p;
if (device[strlen(device)-1] == '/')
device[strlen(device)-1] = '\0';
if (ctl.device[strlen(ctl.device) - 1] == '/')
ctl.device[strlen(ctl.device) - 1] = '\0';
/* figure out full device or mount point name */
p = find_device(device);
p = find_device(ctl.device);
if (p)
free(device);
free(ctl.device);
else
p = device;
p = ctl.device;
device = mnt_resolve_spec(p, NULL);
ctl.device = mnt_resolve_spec(p, NULL);
free(p);
}
if (!device)
errx(EXIT_FAILURE, _("%s: unable to find device"), device);
if (!ctl.device)
errx(EXIT_FAILURE, _("%s: unable to find device"), ctl.device);
verbose(_("device name is `%s'"), device);
verbose(&ctl, _("device name is `%s'"), ctl.device);
device_get_mountpoint(&device, &mountpoint);
device_get_mountpoint(&ctl, &ctl.device, &mountpoint);
if (mountpoint)
verbose(_("%s: mounted on %s"), device, mountpoint);
verbose(&ctl, _("%s: mounted on %s"), ctl.device, mountpoint);
else
verbose(_("%s: not mounted"), device);
verbose(&ctl, _("%s: not mounted"), ctl.device);
disk = get_disk_devname(device);
disk = get_disk_devname(ctl.device);
if (disk) {
verbose(_("%s: disc device: %s (disk device will be used for eject)"), device, disk);
free(device);
device = disk;
verbose(&ctl, _("%s: disc device: %s (disk device will be used for eject)"), ctl.device, disk);
free(ctl.device);
ctl.device = disk;
disk = NULL;
} else {
struct stat st;
if (stat(device, &st) != 0 || !S_ISBLK(st.st_mode))
if (stat(ctl.device, &st) != 0 || !S_ISBLK(st.st_mode))
errx(EXIT_FAILURE, _("%s: not found mountpoint or device "
"with the given name"), device);
"with the given name"), ctl.device);
verbose(_("%s: is whole-disk device"), device);
verbose(&ctl, _("%s: is whole-disk device"), ctl.device);
}
if (F_option == 0 && is_hotpluggable(device) == 0)
errx(EXIT_FAILURE, _("%s: is not hot-pluggable device"), device);
if (ctl.F_option == 0 && is_hotpluggable(&ctl) == 0)
errx(EXIT_FAILURE, _("%s: is not hot-pluggable device"), ctl.device);
/* handle -n option */
if (n_option) {
info(_("device is `%s'"), device);
verbose(_("exiting due to -n/--noop option"));
if (ctl.n_option) {
info(_("device is `%s'"), ctl.device);
verbose(&ctl, _("exiting due to -n/--noop option"));
return EXIT_SUCCESS;
}
/* handle -i option */
if (i_option) {
fd = open_device(device);
manual_eject(fd, i_arg);
if (ctl.i_option) {
open_device(&ctl);
manual_eject(&ctl);
return EXIT_SUCCESS;
}
/* handle -a option */
if (a_option) {
if (a_arg)
verbose(_("%s: enabling auto-eject mode"), device);
if (ctl.a_option) {
if (ctl.a_arg)
verbose(&ctl, _("%s: enabling auto-eject mode"), ctl.device);
else
verbose(_("%s: disabling auto-eject mode"), device);
fd = open_device(device);
auto_eject(fd, a_arg);
verbose(&ctl, _("%s: disabling auto-eject mode"), ctl.device);
open_device(&ctl);
auto_eject(&ctl);
return EXIT_SUCCESS;
}
/* handle -t option */
if (t_option) {
verbose(_("%s: closing tray"), device);
fd = open_device(device);
close_tray(fd);
set_device_speed(device);
if (ctl.t_option) {
verbose(&ctl, _("%s: closing tray"), ctl.device);
open_device(&ctl);
close_tray(ctl.fd);
set_device_speed(&ctl);
return EXIT_SUCCESS;
}
/* handle -T option */
if (T_option) {
verbose(_("%s: toggling tray"), device);
fd = open_device(device);
toggle_tray(fd);
set_device_speed(device);
if (ctl.T_option) {
verbose(&ctl, _("%s: toggling tray"), ctl.device);
open_device(&ctl);
toggle_tray(ctl.fd);
set_device_speed(&ctl);
return EXIT_SUCCESS;
}
/* handle -X option */
if (X_option) {
verbose(_("%s: listing CD-ROM speed"), device);
fd = open_device(device);
list_speeds(device, fd);
if (ctl.X_option) {
verbose(&ctl, _("%s: listing CD-ROM speed"), ctl.device);
open_device(&ctl);
list_speeds(&ctl);
return EXIT_SUCCESS;
}
/* handle -x option only */
if (!c_option)
set_device_speed(device);
if (!ctl.c_option)
set_device_speed(&ctl);
/*
@ -1081,62 +1079,62 @@ int main(int argc, char **argv)
* mountpoint if -M is specified, otherwise print error of another
* partition is mounted.
*/
if (!m_option) {
int ct = umount_partitions(device, M_option);
if (!ctl.m_option) {
int ct = umount_partitions(&ctl);
if (ct == 0 && mountpoint)
umount_one(mountpoint); /* probably whole-device */
umount_one(&ctl, mountpoint); /* probably whole-device */
if (M_option) {
if (ctl.M_option) {
if (ct == 1 && mountpoint)
umount_one(mountpoint);
umount_one(&ctl, mountpoint);
else if (ct)
errx(EXIT_FAILURE, _("error: %s: device in use"), device);
errx(EXIT_FAILURE, _("error: %s: device in use"), ctl.device);
}
}
/* handle -c option */
if (c_option) {
verbose(_("%s: selecting CD-ROM disc #%ld"), device, c_arg);
fd = open_device(device);
changer_select(fd, c_arg);
set_device_speed(device);
if (ctl.c_option) {
verbose(&ctl, _("%s: selecting CD-ROM disc #%ld"), ctl.device, ctl.c_arg);
open_device(&ctl);
changer_select(&ctl);
set_device_speed(&ctl);
return EXIT_SUCCESS;
}
/* if user did not specify type of eject, try all four methods */
if (r_option + s_option + f_option + q_option == 0)
r_option = s_option = f_option = q_option = 1;
if (ctl.r_option + ctl.s_option + ctl.f_option + ctl.q_option == 0)
ctl.r_option = ctl.s_option = ctl.f_option = ctl.q_option = 1;
/* open device */
fd = open_device(device);
open_device(&ctl);
/* try various methods of ejecting until it works */
if (r_option) {
verbose(_("%s: trying to eject using CD-ROM eject command"), device);
worked = eject_cdrom(fd);
verbose(worked ? _("CD-ROM eject command succeeded") :
if (ctl.r_option) {
verbose(&ctl, _("%s: trying to eject using CD-ROM eject command"), ctl.device);
worked = eject_cdrom(ctl.fd);
verbose(&ctl, worked ? _("CD-ROM eject command succeeded") :
_("CD-ROM eject command failed"));
}
if (s_option && !worked) {
verbose(_("%s: trying to eject using SCSI commands"), device);
worked = eject_scsi(fd);
verbose(worked ? _("SCSI eject succeeded") :
if (ctl.s_option && !worked) {
verbose(&ctl, _("%s: trying to eject using SCSI commands"), ctl.device);
worked = eject_scsi(&ctl);
verbose(&ctl, worked ? _("SCSI eject succeeded") :
_("SCSI eject failed"));
}
if (f_option && !worked) {
verbose(_("%s: trying to eject using floppy eject command"), device);
worked = eject_floppy(fd);
verbose(worked ? _("floppy eject command succeeded") :
if (ctl.f_option && !worked) {
verbose(&ctl, _("%s: trying to eject using floppy eject command"), ctl.device);
worked = eject_floppy(ctl.fd);
verbose(&ctl, worked ? _("floppy eject command succeeded") :
_("floppy eject command failed"));
}
if (q_option && !worked) {
verbose(_("%s: trying to eject using tape offline command"), device);
worked = eject_tape(fd);
verbose(worked ? _("tape offline command succeeded") :
if (ctl.q_option && !worked) {
verbose(&ctl, _("%s: trying to eject using tape offline command"), ctl.device);
worked = eject_tape(ctl.fd);
verbose(&ctl, worked ? _("tape offline command succeeded") :
_("tape offline command failed"));
}
@ -1144,11 +1142,11 @@ int main(int argc, char **argv)
errx(EXIT_FAILURE, _("unable to eject"));
/* cleanup */
close(fd);
free(device);
close(ctl.fd);
free(ctl.device);
free(mountpoint);
mnt_unref_table(mtab);
mnt_unref_table(ctl.mtab);
return EXIT_SUCCESS;
}

View File

@ -1,180 +0,0 @@
/*
* kd.c - KDGHWCLK stuff, possibly m68k only, likely to be deprecated
*/
#include "hwclock.h"
#ifdef __m68k__
# include <fcntl.h>
# include <sysexits.h>
# include <sys/ioctl.h>
# include <unistd.h>
# include "nls.h"
/* Get defines for KDGHWCLK and KDSHWCLK (m68k) */
# include <linux/kd.h>
/* Even on m68k, if KDGHWCLK (antique) is not defined, don't build this */
#endif
#if !defined(__m68k__) || !defined(KDGHWCLK)
#include <stddef.h>
struct clock_ops *probe_for_kd_clock(void)
{
return NULL;
}
#else /* __m68k__ && KDGHWCLK */
/* Opened by probe_for_kd_clock(), and never closed. */
static int con_fd = -1;
static char *con_fd_filename; /* usually "/dev/tty1" */
/*
* Wait for the top of a clock tick by calling KDGHWCLK in a busy loop until
* we see it.
*/
static int synchronize_to_clock_tick_kd(void)
{
/* The time when we were called (and started waiting) */
struct hwclk_time start_time, nowtime;
struct timeval begin, now;
if (debug)
printf(_("Waiting in loop for time from KDGHWCLK to change\n"));
if (ioctl(con_fd, KDGHWCLK, &start_time) == -1) {
warn(_("KDGHWCLK ioctl to read time failed"));
return 3;
}
/*
* Wait for change. Should be within a second, but in case something
* weird happens, we have a time limit (1.5s) on this loop to reduce
* the impact of this failure.
*/
gettimeofday(&begin, NULL);
do {
/*
* Added by Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
*
* "The culprit is the fast loop with KDGHWCLK ioctls. It
* seems the kernel gets confused by those on Amigas with
* A2000 RTCs and simply hangs after some time. Inserting a
* sleep helps."
*/
xusleep(1);
if (ioctl(con_fd, KDGHWCLK, &nowtime) == -1) {
warn(_("KDGHWCLK ioctl to read time failed in loop"));
return 3;
}
if (start_time.tm_sec != nowtime.tm_sec)
break;
gettimeofday(&now, NULL);
if (time_diff(now, begin) > 1.5) {
warnx(_("Timed out waiting for time change."));
return 2;
}
} while (1);
return 0;
}
/*
* Read the hardware clock and return the current time via <tm> argument.
* Use ioctls to /dev/tty1 on what we assume is an m68k machine.
*
* Note that we don't use /dev/console here. That might be a serial console.
*/
static int read_hardware_clock_kd(struct tm *tm)
{
struct hwclk_time t;
if (ioctl(con_fd, KDGHWCLK, &t) == -1) {
warn(_("ioctl() failed to read time from %s"),
con_fd_filename);
hwclock_exit(EX_IOERR);
}
tm->tm_sec = t.sec;
tm->tm_min = t.min;
tm->tm_hour = t.hour;
tm->tm_mday = t.day;
tm->tm_mon = t.mon;
tm->tm_year = t.year;
tm->tm_wday = t.wday;
tm->tm_isdst = -1; /* Don't know if it's Daylight Savings Time */
return 0;
}
/*
* Set the Hardware Clock to the time <new_broken_time>. Use ioctls to
* /dev/tty1 on what we assume is an m68k machine.
*
* Note that we don't use /dev/console here. That might be a serial console.
*/
static int set_hardware_clock_kd(const struct tm *new_broken_time)
{
struct hwclk_time t;
t.sec = new_broken_time->tm_sec;
t.min = new_broken_time->tm_min;
t.hour = new_broken_time->tm_hour;
t.day = new_broken_time->tm_mday;
t.mon = new_broken_time->tm_mon;
t.year = new_broken_time->tm_year;
t.wday = new_broken_time->tm_wday;
if (ioctl(con_fd, KDSHWCLK, &t) == -1) {
warn(_("ioctl KDSHWCLK failed"));
hwclock_exit(EX_IOERR);
}
return 0;
}
static int get_permissions_kd(void)
{
return 0;
}
static struct clock_ops kd = {
N_("Using the KDGHWCLK interface to m68k clock."),
get_permissions_kd,
read_hardware_clock_kd,
set_hardware_clock_kd,
synchronize_to_clock_tick_kd,
};
/* return &kd if KDGHWCLK works, NULL otherwise */
struct clock_ops *probe_for_kd_clock()
{
struct clock_ops *ret = NULL;
struct hwclk_time t;
if (con_fd < 0) { /* first time here */
con_fd_filename = "/dev/tty1";
con_fd = open(con_fd_filename, O_RDONLY);
}
if (con_fd < 0) {
/* perhaps they are using devfs? */
con_fd_filename = "/dev/vc/1";
con_fd = open(con_fd_filename, O_RDONLY);
}
if (con_fd < 0) {
/* probably KDGHWCLK exists on m68k only */
warn(_("Can't open /dev/tty1 or /dev/vc/1"));
} else {
if (ioctl(con_fd, KDGHWCLK, &t) == -1) {
if (errno != EINVAL)
warn(_("KDGHWCLK ioctl failed"));
} else
ret = &kd;
}
return ret;
}
#endif /* __m68k__ && KDGHWCLK */

View File

@ -1256,9 +1256,6 @@ static void determine_clock_access_method(const bool user_requests_ISA)
ur = probe_for_rtc_clock();
#endif
if (!ur)
ur = probe_for_kd_clock();
if (!ur && !user_requests_ISA)
ur = probe_for_cmos_clock();

View File

@ -19,7 +19,6 @@ struct clock_ops {
extern struct clock_ops *probe_for_cmos_clock(void);
extern struct clock_ops *probe_for_rtc_clock(void);
extern struct clock_ops *probe_for_kd_clock(void);
typedef int bool;

View File

@ -40,9 +40,17 @@
#include "closestream.h"
#include "pathnames.h"
static int quiet;
struct mountpoint_control {
char *path;
dev_t dev;
struct stat st;
unsigned int
dev_devno:1,
fs_devno:1,
quiet:1;
};
static int dir_to_device(const char *spec, dev_t *dev)
static int dir_to_device(struct mountpoint_control *ctl)
{
struct libmnt_table *tb = mnt_new_table_from_file(_PATH_PROC_MOUNTINFO);
struct libmnt_fs *fs;
@ -54,16 +62,13 @@ static int dir_to_device(const char *spec, dev_t *dev)
* Fallback. Traditional way to detect mountpoints. This way
* is independent on /proc, but not able to detect bind mounts.
*/
struct stat pst, st;
struct stat pst;
char buf[PATH_MAX], *cn;
int len;
if (stat(spec, &st) != 0)
return -1;
cn = mnt_resolve_path(ctl->path, NULL); /* canonicalize */
cn = mnt_resolve_path(spec, NULL); /* canonicalize */
len = snprintf(buf, sizeof(buf), "%s/..", cn ? cn : spec);
len = snprintf(buf, sizeof(buf), "%s/..", cn ? cn : ctl->path);
free(cn);
if (len < 0 || (size_t) len + 1 > sizeof(buf))
@ -71,9 +76,9 @@ static int dir_to_device(const char *spec, dev_t *dev)
if (stat(buf, &pst) !=0)
return -1;
if ((st.st_dev != pst.st_dev) ||
(st.st_dev == pst.st_dev && st.st_ino == pst.st_ino)) {
*dev = st.st_dev;
if ((ctl->st.st_dev != pst.st_dev) ||
(ctl->st.st_dev == pst.st_dev && ctl->st.st_ino == pst.st_ino)) {
ctl->dev = ctl->st.st_dev;
return 0;
}
@ -85,9 +90,9 @@ static int dir_to_device(const char *spec, dev_t *dev)
mnt_table_set_cache(tb, cache);
mnt_unref_cache(cache);
fs = mnt_table_find_target(tb, spec, MNT_ITER_BACKWARD);
fs = mnt_table_find_target(tb, ctl->path, MNT_ITER_BACKWARD);
if (fs && mnt_fs_get_target(fs)) {
*dev = mnt_fs_get_devno(fs);
ctl->dev = mnt_fs_get_devno(fs);
rc = 0;
}
@ -95,20 +100,14 @@ static int dir_to_device(const char *spec, dev_t *dev)
return rc;
}
static int print_devno(const char *devname, struct stat *st)
static int print_devno(const struct mountpoint_control *ctl)
{
struct stat stbuf;
if (!st && stat(devname, &stbuf) == 0)
st = &stbuf;
if (!st)
return -1;
if (!S_ISBLK(st->st_mode)) {
if (!quiet)
warnx(_("%s: not a block device"), devname);
if (!S_ISBLK(ctl->st.st_mode)) {
if (!ctl->quiet)
warnx(_("%s: not a block device"), ctl->path);
return -1;
}
printf("%u:%u\n", major(st->st_rdev), minor(st->st_rdev));
printf("%u:%u\n", major(ctl->st.st_rdev), minor(ctl->st.st_rdev));
return 0;
}
@ -133,9 +132,8 @@ static void __attribute__((__noreturn__)) usage(FILE *out)
int main(int argc, char **argv)
{
int c, fs_devno = 0, dev_devno = 0, rc = 0;
char *spec;
struct stat st;
int c;
struct mountpoint_control ctl = { 0 };
static const struct option longopts[] = {
{ "quiet", 0, 0, 'q' },
@ -157,13 +155,13 @@ int main(int argc, char **argv)
switch(c) {
case 'q':
quiet = 1;
ctl.quiet = 1;
break;
case 'd':
fs_devno = 1;
ctl.fs_devno = 1;
break;
case 'x':
dev_devno = 1;
ctl.dev_devno = 1;
break;
case 'h':
usage(stdout);
@ -180,28 +178,23 @@ int main(int argc, char **argv)
if (optind + 1 != argc)
usage(stderr);
spec = argv[optind++];
ctl.path = argv[optind];
if (stat(spec, &st)) {
if (!quiet)
err(EXIT_FAILURE, "%s", spec);
if (stat(ctl.path, &ctl.st)) {
if (!ctl.quiet)
err(EXIT_FAILURE, "%s", ctl.path);
return EXIT_FAILURE;
}
if (dev_devno)
rc = print_devno(spec, &st);
else {
dev_t src;
if ( dir_to_device(spec, &src)) {
if (!quiet)
printf(_("%s is not a mountpoint\n"), spec);
return EXIT_FAILURE;
}
if (fs_devno)
printf("%u:%u\n", major(src), minor(src));
else if (!quiet)
printf(_("%s is a mountpoint\n"), spec);
if (ctl.dev_devno)
return print_devno(&ctl) ? EXIT_FAILURE : EXIT_SUCCESS;
if (dir_to_device(&ctl)) {
if (!ctl.quiet)
printf(_("%s is not a mountpoint\n"), ctl.path);
return EXIT_FAILURE;
}
return rc ? EXIT_FAILURE : EXIT_SUCCESS;
if (ctl.fs_devno)
printf("%u:%u\n", major(ctl.dev), minor(ctl.dev));
else if (!ctl.quiet)
printf(_("%s is a mountpoint\n"), ctl.path);
return EXIT_SUCCESS;
}

View File

@ -24,8 +24,7 @@
* sparc32 util by Jakub Jelinek (1998, 1999)
*/
#include <syscall.h>
#include <linux/personality.h>
#include <sys/personality.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
@ -37,11 +36,14 @@
#include "c.h"
#include "closestream.h"
#define set_pers(pers) ((long)syscall(SYS_personality, pers))
#ifndef HAVE_PERSONALITY
# include <syscall.h>
# define personality(pers) ((long)syscall(SYS_personality, pers))
#endif
/* Options without equivalent short options */
enum {
OPT_4GB = CHAR_MAX + 1,
OPT_4GB = CHAR_MAX + 1,
OPT_UNAME26
};
@ -52,7 +54,6 @@ enum {
printf(_("Switching on %s.\n"), #_flag); \
} while(0)
#ifndef UNAME26
# define UNAME26 0x0020000
#endif
@ -87,301 +88,291 @@ enum {
# define ADDR_LIMIT_3GB 0x8000000
#endif
static void __attribute__((__noreturn__))
show_help(void)
static void __attribute__((__noreturn__)) show_help(void)
{
fputs(USAGE_HEADER, stdout);
printf(_(" %s%s [options] [program [program arguments]]\n"),
program_invocation_short_name,
!strcmp(program_invocation_short_name, "setarch") ? " <arch>" : "");
fputs(USAGE_HEADER, stdout);
printf(_(" %s%s [options] [program [program arguments]]\n"),
program_invocation_short_name,
!strcmp(program_invocation_short_name, "setarch") ? " <arch>" : "");
fputs(USAGE_OPTIONS, stdout);
fputs(_(" -v, --verbose says what options are being switched on\n"), stdout);
fputs(_(" -R, --addr-no-randomize disables randomization of the virtual address space\n"), stdout);
fputs(_(" -F, --fdpic-funcptrs makes function pointers point to descriptors\n"), stdout);
fputs(_(" -Z, --mmap-page-zero turns on MMAP_PAGE_ZERO\n"), stdout);
fputs(_(" -L, --addr-compat-layout changes the way virtual memory is allocated\n"), stdout);
fputs(_(" -X, --read-implies-exec turns on READ_IMPLIES_EXEC\n"), stdout);
fputs(_(" -B, --32bit turns on ADDR_LIMIT_32BIT\n"), stdout);
fputs(_(" -I, --short-inode turns on SHORT_INODE\n"), stdout);
fputs(_(" -S, --whole-seconds turns on WHOLE_SECONDS\n"), stdout);
fputs(_(" -T, --sticky-timeouts turns on STICKY_TIMEOUTS\n"), stdout);
fputs(_(" -3, --3gb limits the used address space to a maximum of 3 GB\n"), stdout);
fputs(_(" --4gb ignored (for backward compatibility only)\n"), stdout);
fputs(_(" --uname-2.6 turns on UNAME26\n"), stdout);
fputs(_(" --list list settable architectures, and exit\n"), stdout);
fputs(USAGE_SEPARATOR, stdout);
fputs(USAGE_HELP, stdout);
fputs(USAGE_VERSION, stdout);
printf(USAGE_MAN_TAIL("setarch(8)"));
exit(EXIT_SUCCESS);
}
fputs(USAGE_OPTIONS, stdout);
fputs(_(" -v, --verbose says what options are being switched on\n"), stdout);
fputs(_(" -R, --addr-no-randomize disables randomization of the virtual address space\n"), stdout);
fputs(_(" -F, --fdpic-funcptrs makes function pointers point to descriptors\n"), stdout);
fputs(_(" -Z, --mmap-page-zero turns on MMAP_PAGE_ZERO\n"), stdout);
fputs(_(" -L, --addr-compat-layout changes the way virtual memory is allocated\n"), stdout);
fputs(_(" -X, --read-implies-exec turns on READ_IMPLIES_EXEC\n"), stdout);
fputs(_(" -B, --32bit turns on ADDR_LIMIT_32BIT\n"), stdout);
fputs(_(" -I, --short-inode turns on SHORT_INODE\n"), stdout);
fputs(_(" -S, --whole-seconds turns on WHOLE_SECONDS\n"), stdout);
fputs(_(" -T, --sticky-timeouts turns on STICKY_TIMEOUTS\n"), stdout);
fputs(_(" -3, --3gb limits the used address space to a maximum of 3 GB\n"), stdout);
fputs(_(" --4gb ignored (for backward compatibility only)\n"), stdout);
fputs(_(" --uname-2.6 turns on UNAME26\n"), stdout);
fputs(_(" --list list settable architectures, and exit\n"), stdout);
fputs(USAGE_SEPARATOR, stdout);
fputs(USAGE_HELP, stdout);
fputs(USAGE_VERSION, stdout);
printf(USAGE_MAN_TAIL("setarch(8)"));
exit(EXIT_SUCCESS);
static void __attribute__((__noreturn__)) show_usage(const char *s)
{
if (s)
errx(EXIT_FAILURE,
_("%s\nTry `%s --help' for more information."), s,
program_invocation_short_name);
else
errx(EXIT_FAILURE, _("Try `%s --help' for more information."),
program_invocation_short_name);
}
static void __attribute__((__noreturn__))
show_usage(const char *s)
show_version(void)
{
if (s)
errx(EXIT_FAILURE, _("%s\nTry `%s --help' for more information."), s, program_invocation_short_name);
else
errx(EXIT_FAILURE, _("Try `%s --help' for more information."), program_invocation_short_name);
printf(UTIL_LINUX_VERSION);
exit(EXIT_SUCCESS);
}
static void __attribute__((__noreturn__))
show_version(void)
static int set_arch(const char *pers, unsigned long options, int list)
{
printf(UTIL_LINUX_VERSION);
exit(EXIT_SUCCESS);
}
struct utsname un;
int i;
unsigned long pers_value;
static int
set_arch(const char *pers, unsigned long options, int list)
{
struct utsname un;
int i;
unsigned long pers_value;
struct {
int perval;
const char *target_arch, *result_arch;
} transitions[] = {
{UNAME26, "uname26", NULL},
{PER_LINUX32, "linux32", NULL},
{PER_LINUX, "linux64", NULL},
struct {
int perval;
const char *target_arch, *result_arch;
} transitions[] = {
{UNAME26, "uname26", NULL},
{PER_LINUX32, "linux32", NULL},
{PER_LINUX, "linux64", NULL},
#if defined(__powerpc__) || defined(__powerpc64__)
#ifdef __BIG_ENDIAN__
{PER_LINUX32, "ppc32", "ppc"},
{PER_LINUX32, "ppc", "ppc"},
{PER_LINUX, "ppc64", "ppc64"},
{PER_LINUX, "ppc64pseries", "ppc64"},
{PER_LINUX, "ppc64iseries", "ppc64"},
#else
{PER_LINUX32, "ppc32le", "ppcle"},
{PER_LINUX32, "ppcle", "ppcle"},
{PER_LINUX, "ppc64le", "ppc64le"},
#endif
# ifdef __BIG_ENDIAN__
{PER_LINUX32, "ppc32", "ppc"},
{PER_LINUX32, "ppc", "ppc"},
{PER_LINUX, "ppc64", "ppc64"},
{PER_LINUX, "ppc64pseries", "ppc64"},
{PER_LINUX, "ppc64iseries", "ppc64"},
# else
PER_LINUX32, "ppc32le", "ppcle"},
PER_LINUX32, "ppcle", "ppcle"},
PER_LINUX, "ppc64le", "ppc64le"},
# endif
#endif
#if defined(__x86_64__) || defined(__i386__) || defined(__ia64__)
{PER_LINUX32, "i386", "i386"},
{PER_LINUX32, "i486", "i386"},
{PER_LINUX32, "i586", "i386"},
{PER_LINUX32, "i686", "i386"},
{PER_LINUX32, "athlon", "i386"},
{PER_LINUX32, "i386", "i386"},
{PER_LINUX32, "i486", "i386"},
{PER_LINUX32, "i586", "i386"},
{PER_LINUX32, "i686", "i386"},
{PER_LINUX32, "athlon", "i386"},
#endif
#if defined(__x86_64__) || defined(__i386__)
{PER_LINUX, "x86_64", "x86_64"},
{PER_LINUX, "x86_64", "x86_64"},
#endif
#if defined(__ia64__) || defined(__i386__)
{PER_LINUX, "ia64", "ia64"},
{PER_LINUX, "ia64", "ia64"},
#endif
#if defined(__hppa__)
{PER_LINUX32, "parisc32", "parisc"},
{PER_LINUX32, "parisc", "parisc"},
{PER_LINUX, "parisc64", "parisc64"},
{PER_LINUX32, "parisc32", "parisc"},
{PER_LINUX32, "parisc", "parisc"},
{PER_LINUX, "parisc64", "parisc64"},
#endif
#if defined(__s390x__) || defined(__s390__)
{PER_LINUX32, "s390", "s390"},
{PER_LINUX, "s390x", "s390x"},
{PER_LINUX32, "s390", "s390"},
{PER_LINUX, "s390x", "s390x"},
#endif
#if defined(__sparc64__) || defined(__sparc__)
{PER_LINUX32, "sparc", "sparc"},
{PER_LINUX32, "sparc32bash", "sparc"},
{PER_LINUX32, "sparc32", "sparc"},
{PER_LINUX, "sparc64", "sparc64"},
{PER_LINUX32, "sparc", "sparc"},
{PER_LINUX32, "sparc32bash", "sparc"},
{PER_LINUX32, "sparc32", "sparc"},
{PER_LINUX, "sparc64", "sparc64"},
#endif
#if defined(__mips64__) || defined(__mips__)
{PER_LINUX32, "mips32", "mips"},
{PER_LINUX32, "mips", "mips"},
{PER_LINUX, "mips64", "mips64"},
{PER_LINUX32, "mips32", "mips"},
{PER_LINUX32, "mips", "mips"},
{PER_LINUX, "mips64", "mips64"},
#endif
#if defined(__alpha__)
{PER_LINUX, "alpha", "alpha"},
{PER_LINUX, "alphaev5", "alpha"},
{PER_LINUX, "alphaev56", "alpha"},
{PER_LINUX, "alphaev6", "alpha"},
{PER_LINUX, "alphaev67", "alpha"},
{PER_LINUX, "alpha", "alpha"},
{PER_LINUX, "alphaev5", "alpha"},
{PER_LINUX, "alphaev56", "alpha"},
{PER_LINUX, "alphaev6", "alpha"},
{PER_LINUX, "alphaev67", "alpha"},
#endif
{-1, NULL, NULL}, /* place holder, eventually filled up at runtime */
{-1, NULL, NULL}
};
/* place holder, will be filled up at runtime */
{-1, NULL, NULL},
{-1, NULL, NULL}
};
/* Add the trivial transition {PER_LINUX, machine, machine} if no such
target_arch is hardcoded yet. */
uname(&un);
for (i = 0; transitions[i].perval >= 0; i++)
if(!strcmp(un.machine, transitions[i].target_arch))
break;
if (transitions[i].perval < 0) {
unsigned long wrdsz = CHAR_BIT * sizeof(void*);
if (wrdsz == 32 || wrdsz == 64) {
transitions[i].perval = wrdsz == 32 ? PER_LINUX32 : PER_LINUX;
transitions[i].target_arch = un.machine;
transitions[i].result_arch = un.machine;
/* Add the trivial transition {PER_LINUX, machine, machine} if no
* such target_arch is hardcoded yet. */
uname(&un);
for (i = 0; transitions[i].perval >= 0; i++)
if (!strcmp(un.machine, transitions[i].target_arch))
break;
if (transitions[i].perval < 0) {
unsigned long wrdsz = CHAR_BIT * sizeof(void *);
if (wrdsz == 32 || wrdsz == 64) {
/* fill up the place holder */
transitions[i].perval = wrdsz == 32 ? PER_LINUX32 : PER_LINUX;
transitions[i].target_arch = un.machine;
transitions[i].result_arch = un.machine;
}
}
}
if (list) {
for(i = 0; transitions[i].target_arch != NULL; i++)
printf("%s\n", transitions[i].target_arch);
return 0;
}
for(i = 0; transitions[i].perval >= 0; i++)
if(!strcmp(pers, transitions[i].target_arch))
break;
if(transitions[i].perval < 0)
errx(EXIT_FAILURE, _("%s: Unrecognized architecture"), pers);
pers_value = transitions[i].perval | options;
if (set_pers(pers_value) == -EINVAL)
return 1;
uname(&un);
if(transitions[i].result_arch &&
strcmp(un.machine, transitions[i].result_arch))
{
if(strcmp(transitions[i].result_arch, "i386")
|| (strcmp(un.machine, "i486")
&& strcmp(un.machine, "i586")
&& strcmp(un.machine, "i686")
&& strcmp(un.machine, "athlon")))
errx(EXIT_FAILURE, _("%s: Unrecognized architecture"), pers);
}
return 0;
if (list) {
for (i = 0; transitions[i].target_arch != NULL; i++)
printf("%s\n", transitions[i].target_arch);
return 0;
}
for (i = 0; transitions[i].perval >= 0; i++)
if (!strcmp(pers, transitions[i].target_arch))
break;
if (transitions[i].perval < 0)
errx(EXIT_FAILURE, _("%s: Unrecognized architecture"), pers);
pers_value = transitions[i].perval | options;
if (personality(pers_value) == -EINVAL)
return 1;
uname(&un);
if (transitions[i].result_arch && strcmp(un.machine, transitions[i].result_arch)) {
if (strcmp(transitions[i].result_arch, "i386")
|| (strcmp(un.machine, "i486")
&& strcmp(un.machine, "i586")
&& strcmp(un.machine, "i686")
&& strcmp(un.machine, "athlon")))
errx(EXIT_FAILURE, _("%s: Unrecognized architecture"), pers);
}
return 0;
}
int main(int argc, char *argv[])
{
const char *p;
unsigned long options = 0;
int verbose = 0;
int c;
const char *p;
unsigned long options = 0;
int verbose = 0;
int c;
/* Options --3gb and --4gb are for compatibitity with an old Debian setarch
implementation. */
static const struct option longopts[] =
{
{ "help", 0, 0, 'h' },
{ "version", 0, 0, 'V' },
{ "verbose", 0, 0, 'v' },
{ "addr-no-randomize", 0, 0, 'R' },
{ "fdpic-funcptrs", 0, 0, 'F' },
{ "mmap-page-zero", 0, 0, 'Z' },
{ "addr-compat-layout", 0, 0, 'L' },
{ "read-implies-exec", 0, 0, 'X' },
{ "32bit", 0, 0, 'B' },
{ "short-inode", 0, 0, 'I' },
{ "whole-seconds", 0, 0, 'S' },
{ "sticky-timeouts", 0, 0, 'T' },
{ "3gb", 0, 0, '3' },
{ "4gb", 0, 0, OPT_4GB },
{ "uname-2.6", 0, 0, OPT_UNAME26 },
{ NULL, 0, 0, 0 }
};
/* Options --3gb and --4gb are for compatibitity with an old
* Debian setarch implementation. */
static const struct option longopts[] = {
{"help", no_argument, NULL, 'h'},
{"version", no_argument, NULL, 'V'},
{"verbose", no_argument, NULL, 'v'},
{"addr-no-randomize", no_argument, NULL, 'R'},
{"fdpic-funcptrs", no_argument, NULL, 'F'},
{"mmap-page-zero", no_argument, NULL, 'Z'},
{"addr-compat-layout", no_argument, NULL, 'L'},
{"read-implies-exec", no_argument, NULL, 'X'},
{"32bit", no_argument, NULL, 'B'},
{"short-inode", no_argument, NULL, 'I'},
{"whole-seconds", no_argument, NULL, 'S'},
{"sticky-timeouts", no_argument, NULL, 'T'},
{"3gb", no_argument, NULL, '3'},
{"4gb", no_argument, NULL, OPT_4GB},
{"uname-2.6", no_argument, NULL, OPT_UNAME26},
{NULL, 0, NULL, 0}
};
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
atexit(close_stdout);
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
atexit(close_stdout);
if (argc < 1)
show_usage(_("Not enough arguments"));
if (argc < 1)
show_usage(_("Not enough arguments"));
p = program_invocation_short_name;
if (!strcmp(p, "setarch")) {
argc--;
if (argc < 1)
show_usage(_("Not enough arguments"));
p = argv[1];
argv[1] = argv[0]; /* for getopt_long() to get the program name */
argv++;
if (!strcmp(p, "-h") || !strcmp(p, "--help"))
show_help();
else if (!strcmp(p, "-V") || !strcmp(p, "--version"))
show_version();
else if (!strcmp(p, "--list")) {
set_arch(argv[0], 0L, 1);
return EXIT_SUCCESS;
}
}
#if defined(__sparc64__) || defined(__sparc__)
if (!strcmp(p, "sparc32bash")) {
if (set_arch(p, 0L, 0))
err(EXIT_FAILURE, _("Failed to set personality to %s"), p);
execl("/bin/bash", NULL);
err(EXIT_FAILURE, _("failed to execute %s"), "/bin/bash");
}
#endif
p = program_invocation_short_name;
if (!strcmp(p, "setarch")) {
argc--;
if (argc < 1)
show_usage(_("Not enough arguments"));
p = argv[1];
argv[1] = argv[0]; /* for getopt_long() to get the program name */
argv++;
if (!strcmp(p, "-h") || !strcmp(p, "--help"))
show_help();
else if (!strcmp(p, "-V") || !strcmp(p, "--version"))
show_version();
else if (!strcmp(p, "--list")) {
set_arch(argv[0], 0L, 1);
return EXIT_SUCCESS;
}
}
#if defined(__sparc64__) || defined(__sparc__)
if (!strcmp(p, "sparc32bash")) {
if (set_arch(p, 0L, 0))
err(EXIT_FAILURE, _("Failed to set personality to %s"), p);
execl("/bin/bash", NULL);
err(EXIT_FAILURE, _("failed to execute %s"), "/bin/bash");
}
#endif
while ((c = getopt_long(argc, argv, "+hVv3BFILRSTXZ", longopts, NULL)) != -1) {
switch (c) {
case 'h':
show_help();
break;
case 'V':
show_version();
break;
case 'v':
verbose = 1;
break;
case 'R':
turn_on(ADDR_NO_RANDOMIZE, options);
break;
case 'F':
turn_on(FDPIC_FUNCPTRS, options);
break;
case 'Z':
turn_on(MMAP_PAGE_ZERO, options);
break;
case 'L':
turn_on(ADDR_COMPAT_LAYOUT, options);
break;
case 'X':
turn_on(READ_IMPLIES_EXEC, options);
break;
case 'B':
turn_on(ADDR_LIMIT_32BIT, options);
break;
case 'I':
turn_on(SHORT_INODE, options);
break;
case 'S':
turn_on(WHOLE_SECONDS, options);
break;
case 'T':
turn_on(STICKY_TIMEOUTS, options);
break;
case '3':
turn_on(ADDR_LIMIT_3GB, options);
break;
case OPT_4GB: /* just ignore this one */
break;
case OPT_UNAME26:
turn_on(UNAME26, options);
break;
default:
show_usage(NULL);
}
}
while ((c = getopt_long(argc, argv, "+hVv3BFILRSTXZ", longopts, NULL)) != -1) {
switch (c) {
case 'h':
show_help();
break;
case 'V':
show_version();
break;
case 'v':
verbose = 1;
break;
case 'R':
turn_on(ADDR_NO_RANDOMIZE, options);
break;
case 'F':
turn_on(FDPIC_FUNCPTRS, options);
break;
case 'Z':
turn_on(MMAP_PAGE_ZERO, options);
break;
case 'L':
turn_on(ADDR_COMPAT_LAYOUT, options);
break;
case 'X':
turn_on(READ_IMPLIES_EXEC, options);
break;
case 'B':
turn_on(ADDR_LIMIT_32BIT, options);
break;
case 'I':
turn_on(SHORT_INODE, options);
break;
case 'S':
turn_on(WHOLE_SECONDS, options);
break;
case 'T':
turn_on(STICKY_TIMEOUTS, options);
break;
case '3':
turn_on(ADDR_LIMIT_3GB, options);
break;
case OPT_4GB: /* just ignore this one */
break;
case OPT_UNAME26:
turn_on(UNAME26, options);
break;
default:
show_usage(NULL);
}
}
argc -= optind;
argv += optind;
argc -= optind;
argv += optind;
if (set_arch(p, options, 0))
err(EXIT_FAILURE, _("Failed to set personality to %s"), p);
if (set_arch(p, options, 0))
err(EXIT_FAILURE, _("Failed to set personality to %s"), p);
/* flush all output streams before exec */
fflush(NULL);
/* flush all output streams before exec */
fflush(NULL);
if (!argc) {
execl("/bin/sh", "-sh", NULL);
err(EXIT_FAILURE, _("failed to execute %s"), "/bin/sh");
}
if (!argc) {
execl("/bin/sh", "-sh", NULL);
err(EXIT_FAILURE, _("failed to execute %s"), "/bin/sh");
}
execvp(argv[0], argv);
err(EXIT_FAILURE, "%s", argv[0]);
return EXIT_FAILURE;
execvp(argv[0], argv);
err(EXIT_FAILURE, "%s", argv[0]);
return EXIT_FAILURE;
}