From 6717ab94e8f5aab7056c0d10483e715c7a92ca3e Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Nov 11 2014 02:57:08 +0000 Subject: import util-linux-2.23.2-18.el7 --- diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f8a9b2b --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +SOURCES/util-linux-2.23.2.tar.xz diff --git a/.util-linux.metadata b/.util-linux.metadata new file mode 100644 index 0000000..0cacf1c --- /dev/null +++ b/.util-linux.metadata @@ -0,0 +1 @@ +1c3023304dd66663fd314bee424d7cc829fff538 SOURCES/util-linux-2.23.2.tar.xz diff --git a/README.md b/README.md deleted file mode 100644 index 0e7897f..0000000 --- a/README.md +++ /dev/null @@ -1,5 +0,0 @@ -The master branch has no content - -Look at the c7 branch if you are working with CentOS-7, or the c4/c5/c6 branch for CentOS-4, 5 or 6 - -If you find this file in a distro specific branch, it means that no content has been checked in yet diff --git a/SOURCES/2.17-kill-strtol.patch b/SOURCES/2.17-kill-strtol.patch new file mode 100644 index 0000000..bedd0ab --- /dev/null +++ b/SOURCES/2.17-kill-strtol.patch @@ -0,0 +1,22 @@ +diff -up util-linux-2.23.2/misc-utils/kill.c.kzak util-linux-2.23.2/misc-utils/kill.c +--- util-linux-2.23.2/misc-utils/kill.c.kzak 2013-06-13 09:46:10.448650861 +0200 ++++ util-linux-2.23.2/misc-utils/kill.c 2014-09-25 10:08:27.879359310 +0200 +@@ -48,6 +48,7 @@ + #include /* for isdigit() */ + #include + #include ++#include + + #include "c.h" + #include "nls.h" +@@ -279,8 +280,9 @@ int main (int argc, char *argv[]) + the rest of the arguments should be process ids and names. + kill them. */ + for (errors = 0; (arg = *argv) != NULL; argv++) { ++ errno = 0; + pid = strtol (arg, &ep, 10); +- if (! *ep) ++ if (errno == 0 && ep && *ep == '\0' && arg < ep) + errors += kill_verbose (arg, pid, numsig); + else { + struct proc_processes *ps = proc_open_processes(); diff --git a/SOURCES/2.23-login-lastlog-create.patch b/SOURCES/2.23-login-lastlog-create.patch new file mode 100644 index 0000000..839193a --- /dev/null +++ b/SOURCES/2.23-login-lastlog-create.patch @@ -0,0 +1,12 @@ +diff -up util-linux-2.23.2/login-utils/login.c.kzak util-linux-2.23.2/login-utils/login.c +--- util-linux-2.23.2/login-utils/login.c.kzak 2013-07-30 10:39:26.222738397 +0200 ++++ util-linux-2.23.2/login-utils/login.c 2013-09-09 09:01:39.923225757 +0200 +@@ -502,7 +502,7 @@ static void log_lastlog(struct login_con + if (!cxt->pwd) + return; + +- fd = open(_PATH_LASTLOG, O_RDWR, 0); ++ fd = open(_PATH_LASTLOG, O_RDWR | O_CREAT, 0); + if (fd < 0) + return; + diff --git a/SOURCES/2.24-agetty-clocal.patch b/SOURCES/2.24-agetty-clocal.patch new file mode 100644 index 0000000..22fe361 --- /dev/null +++ b/SOURCES/2.24-agetty-clocal.patch @@ -0,0 +1,149 @@ +diff -up util-linux-2.23.2/term-utils/agetty.c.kzak util-linux-2.23.2/term-utils/agetty.c +--- util-linux-2.23.2/term-utils/agetty.c.kzak 2013-07-30 11:14:18.124912322 +0200 ++++ util-linux-2.23.2/term-utils/agetty.c 2013-09-09 09:07:46.406689270 +0200 +@@ -132,13 +132,20 @@ struct options { + int delay; /* Sleep seconds before prompt */ + int nice; /* Run login with this priority */ + int numspeed; /* number of baud rates to try */ ++ int clocal; /* CLOCAL_MODE_* */ + speed_t speeds[MAX_SPEED]; /* baud rates to be tried */ + }; + ++enum { ++ CLOCAL_MODE_AUTO = 0, ++ CLOCAL_MODE_ALWAYS, ++ CLOCAL_MODE_NEVER ++}; ++ + #define F_PARSE (1<<0) /* process modem status messages */ + #define F_ISSUE (1<<1) /* display /etc/issue */ + #define F_RTSCTS (1<<2) /* enable RTS/CTS flow control */ +-#define F_LOCAL (1<<3) /* force local */ ++ + #define F_INITSTRING (1<<4) /* initstring is set */ + #define F_WAITCRLF (1<<5) /* wait for CR or LF */ + #define F_CUSTISSUE (1<<6) /* give alternative issue file */ +@@ -235,10 +242,13 @@ static void login_options_to_argv(char * + static char *fakehost; + + #ifdef DEBUGGING +-#define debug(s) do { fprintf(dbf,s); fflush(dbf); } while (0) ++# ifndef DEBUG_OUTPUT ++# define DEBUG_OUTPUT "/dev/ttyp0" ++# endif ++# define debug(s) do { fprintf(dbf,s); fflush(dbf); } while (0) + FILE *dbf; + #else +-#define debug(s) do { ; } while (0) ++# define debug(s) do { ; } while (0) + #endif + + int main(int argc, char **argv) +@@ -270,7 +280,7 @@ int main(int argc, char **argv) + sigaction(SIGINT, &sa, &sa_int); + + #ifdef DEBUGGING +- dbf = fopen("/dev/ttyp0", "w"); ++ dbf = fopen(DEBUG_OUTPUT, "w"); + for (int i = 1; i < argc; i++) + debug(argv[i]); + #endif /* DEBUGGING */ +@@ -311,8 +321,10 @@ int main(int argc, char **argv) + strlen(options.initstring)); + } + +- if (!serial_tty_option(&options, F_LOCAL)) +- /* Go to blocking write mode unless -L is specified. */ ++ if (options.flags & F_VCONSOLE || options.clocal != CLOCAL_MODE_ALWAYS) ++ /* Go to blocking mode unless -L is specified, this change ++ * affects stdout, stdin and stderr as all the file descriptors ++ * are created by dup(). */ + fcntl(STDOUT_FILENO, F_SETFL, + fcntl(STDOUT_FILENO, F_GETFL, 0) & ~O_NONBLOCK); + +@@ -420,6 +432,12 @@ int main(int argc, char **argv) + options.tty); + } + ++#ifdef DEBUGGING ++ fprintf(dbf, "read %c\n", ch); ++ if (close_stream(dbf) != 0) ++ log_err("write failed: %s", DEBUG_OUTPUT); ++#endif ++ + /* Let the login program take care of password validation. */ + execv(options.login, login_argv); + log_err(_("%s: can't exec %s: %m"), options.tty, login_argv[0]); +@@ -534,7 +552,7 @@ static void parse_args(int argc, char ** + { "init-string", required_argument, 0, 'I' }, + { "noclear", no_argument, 0, 'J' }, + { "login-program", required_argument, 0, 'l' }, +- { "local-line", no_argument, 0, 'L' }, ++ { "local-line", optional_argument, 0, 'L' }, + { "extract-baud", no_argument, 0, 'm' }, + { "skip-login", no_argument, 0, 'n' }, + { "nonewline", no_argument, 0, 'N' }, +@@ -603,7 +621,18 @@ static void parse_args(int argc, char ** + op->login = optarg; + break; + case 'L': +- op->flags |= F_LOCAL; ++ /* -L and -L=always have the same meaning */ ++ op->clocal = CLOCAL_MODE_ALWAYS; ++ if (optarg) { ++ if (strcmp(optarg, "=always") == 0) ++ op->clocal = CLOCAL_MODE_ALWAYS; ++ else if (strcmp(optarg, "=never") == 0) ++ op->clocal = CLOCAL_MODE_NEVER; ++ else if (strcmp(optarg, "=auto") == 0) ++ op->clocal = CLOCAL_MODE_AUTO; ++ else ++ log_err(_("unssuported --local-line mode argument")); ++ } + break; + case 'm': + op->flags |= F_PARSE; +@@ -1090,8 +1119,19 @@ static void termio_init(struct options * + cfsetispeed(tp, ispeed); + cfsetospeed(tp, ospeed); + +- if (op->flags & F_LOCAL) +- tp->c_cflag |= CLOCAL; ++ /* The default is to follow setting from kernel, but it's possible ++ * to explicitly remove/add CLOCAL flag by -L[=]*/ ++ switch (op->clocal) { ++ case CLOCAL_MODE_ALWAYS: ++ tp->c_cflag |= CLOCAL; /* -L or -L=always */ ++ break; ++ case CLOCAL_MODE_NEVER: ++ tp->c_cflag &= ~CLOCAL; /* -L=never */ ++ break; ++ case CLOCAL_MODE_AUTO: /* -L=auto */ ++ break; ++ } ++ + #ifdef HAVE_STRUCT_TERMIOS_C_LINE + tp->c_line = 0; + #endif +@@ -1412,9 +1452,10 @@ static char *get_logname(struct options + + if (read(STDIN_FILENO, &c, 1) < 1) { + +- /* Do not report trivial like EINTR/EIO errors. */ ++ /* The terminal could be open with O_NONBLOCK when ++ * -L (force CLOCAL) is specified... */ + if (errno == EINTR || errno == EAGAIN) { +- usleep(1000); ++ usleep(250000); + continue; + } + switch (errno) { +@@ -1648,7 +1689,7 @@ static void __attribute__ ((__noreturn__ + fputs(_(" -i, --noissue do not display issue file\n"), out); + fputs(_(" -I, --init-string set init string\n"), out); + fputs(_(" -l, --login-program specify login program\n"), out); +- fputs(_(" -L, --local-line force local line\n"), out); ++ fputs(_(" -L, --local-line[=] cotrol local line flag\n"), out); + fputs(_(" -m, --extract-baud extract baud rate during connect\n"), out); + fputs(_(" -n, --skip-login do not prompt for login\n"), out); + fputs(_(" -o, --login-options options that are passed to login\n"), out); diff --git a/SOURCES/2.24-agetty-etc-os-release.patch b/SOURCES/2.24-agetty-etc-os-release.patch new file mode 100644 index 0000000..43b901a --- /dev/null +++ b/SOURCES/2.24-agetty-etc-os-release.patch @@ -0,0 +1,176 @@ +diff -up util-linux-2.23.2/include/pathnames.h.kzak util-linux-2.23.2/include/pathnames.h +--- util-linux-2.23.2/include/pathnames.h.kzak 2013-07-30 10:39:26.201738190 +0200 ++++ util-linux-2.23.2/include/pathnames.h 2013-09-12 13:05:35.928359383 +0200 +@@ -63,6 +63,7 @@ + + /* used in term-utils/agetty.c */ + #define _PATH_ISSUE "/etc/issue" ++#define _PATH_OS_RELEASE "/etc/os-release" + #define _PATH_NUMLOCK_ON _PATH_LOCALSTATEDIR "/numlock-on" + + #define _PATH_LOGINDEFS "/etc/login.defs" +diff -up util-linux-2.23.2/term-utils/agetty.8.kzak util-linux-2.23.2/term-utils/agetty.8 +--- util-linux-2.23.2/term-utils/agetty.8.kzak 2013-07-30 10:58:20.889261333 +0200 ++++ util-linux-2.23.2/term-utils/agetty.8 2013-09-12 13:05:35.928359383 +0200 +@@ -310,6 +310,14 @@ Insert the current date. + .TP + s + Insert the system name, the name of the operating system. Same as `uname \-s'. ++See also \\S escape code. ++.TP ++S or S{VARIABLE} ++Insert the VARIABLE data from \fI/etc/os-release\fP. If the VARIABLE argument ++is not specified then use PRETTY_NAME from the file or the system name (see \\s). ++This escape code allows to keep \fI/etc/issue\fP distribution and release ++independent. Note that \\S{ANSI_COLOR} is converted to the real terminal ++escape sequence. + .TP + l + Insert the name of the current tty line. +@@ -368,11 +376,14 @@ the system status file. + .B /etc/issue + printed before the login prompt. + .TP ++.B /etc/os-release ++operating system identification data. ++.TP + .B /dev/console + problem reports (if syslog(3) is not used). + .TP + .B /etc/inittab +-\fIinit\fP(8) configuration file. ++\fIinit\fP(8) configuration file for SysV-style init daemon. + .SH BUGS + .ad + .fi +diff -up util-linux-2.23.2/term-utils/agetty.c.kzak util-linux-2.23.2/term-utils/agetty.c +--- util-linux-2.23.2/term-utils/agetty.c.kzak 2013-09-12 13:05:35.927359379 +0200 ++++ util-linux-2.23.2/term-utils/agetty.c 2013-09-12 13:05:35.929359388 +0200 +@@ -129,6 +129,7 @@ struct options { + char *issue; /* alternative issue file */ + char *erasechars; /* string with erase chars */ + char *killchars; /* string with kill chars */ ++ char *osrelease; /* /etc/os-release data */ + int delay; /* Sleep seconds before prompt */ + int nice; /* Run login with this priority */ + int numspeed; /* number of baud rates to try */ +@@ -431,7 +432,8 @@ int main(int argc, char **argv) + log_warn(_("%s: can't change process priority: %m"), + options.tty); + } +- ++ if (options.osrelease) ++ free(options.osrelease); + #ifdef DEBUGGING + fprintf(dbf, "read %c\n", ch); + if (close_stream(dbf) != 0) +@@ -1279,6 +1281,84 @@ static char *xgetdomainname(void) + return NULL; + } + ++static char *read_os_release(struct options *op, const char *varname) ++{ ++ int fd = -1; ++ struct stat st; ++ size_t varsz = strlen(varname); ++ char *p, *buf = NULL, *ret = NULL; ++ ++ /* read the file only once */ ++ if (!op->osrelease) { ++ fd = open(_PATH_OS_RELEASE, O_RDONLY); ++ if (fd == -1) { ++ log_warn(_("cannot open: %s: %m"), _PATH_OS_RELEASE); ++ return NULL; ++ } ++ ++ if (fstat(fd, &st) < 0 || st.st_size > 4 * 1024 * 1024) ++ goto done; ++ ++ op->osrelease = malloc(st.st_size + 1); ++ if (!op->osrelease) ++ log_err(_("failed to allocate memory: %m")); ++ if (read_all(fd, op->osrelease, st.st_size) != (ssize_t) st.st_size) { ++ free(op->osrelease); ++ op->osrelease = NULL; ++ goto done; ++ } ++ op->osrelease[st.st_size] = 0; ++ } ++ buf = strdup(op->osrelease); ++ if (!buf) ++ log_err(_("failed to allocate memory: %m")); ++ p = buf; ++ ++ for (;;) { ++ char *eol, *eon; ++ ++ p += strspn(p, "\n\r"); ++ p += strspn(p, " \t\n\r"); ++ if (!*p) ++ break; ++ if (strspn(p, "#;\n") != 0) { ++ p += strcspn(p, "\n\r"); ++ continue; ++ } ++ if (strncmp(p, varname, varsz) != 0) { ++ p += strcspn(p, "\n\r"); ++ continue; ++ } ++ p += varsz; ++ p += strspn(p, " \t\n\r=\""); ++ eol = p + strcspn(p, "\n\r"); ++ *eol = '\0'; ++ eon = eol-1; ++ while (eon > p) { ++ if (*eon == '\t' || *eon == ' ') { ++ eon--; ++ continue; ++ } ++ if (*eon == '"') { ++ *eon = '\0'; ++ break; ++ } ++ break; ++ } ++ if (ret) ++ free(ret); ++ ret = strdup(p); ++ if (!ret) ++ log_err(_("failed to allocate memory: %m")); ++ p = eol + 1; ++ } ++done: ++ free(buf); ++ if (fd >= 0) ++ close(fd); ++ return ret; ++} ++ + /* Show login prompt, optionally preceded by /etc/issue contents. */ + static void do_prompt(struct options *op, struct termios *tp) + { +@@ -1968,6 +2048,24 @@ static void output_special_char(unsigned + } + break; + } ++ case 'S': ++ { ++ char *var = NULL, varname[64]; ++ ++ if (get_escape_argument(fp, varname, sizeof(varname))) ++ var = read_os_release(op, varname); ++ else if (!(var = read_os_release(op, "PRETTY_NAME"))) ++ var = uts.sysname; ++ if (var) { ++ if (strcmp(varname, "ANSI_COLOR") == 0) ++ printf("\033[%sm", var); ++ else ++ printf("%s", var); ++ if (var != uts.sysname) ++ free(var); ++ } ++ break; ++ } + case 'u': + case 'U': + { diff --git a/SOURCES/2.24-blockdev-setbsz-hint.patch b/SOURCES/2.24-blockdev-setbsz-hint.patch new file mode 100644 index 0000000..6bb5957 --- /dev/null +++ b/SOURCES/2.24-blockdev-setbsz-hint.patch @@ -0,0 +1,42 @@ +From 7ab32ae64d05f018c171ba1525bc337805d84391 Mon Sep 17 00:00:00 2001 +From: Karel Zak +Date: Fri, 11 Oct 2013 11:16:23 +0200 +Subject: [PATCH] blockdev: add note about --setbsz usability + +Signed-off-by: Karel Zak +--- + disk-utils/blockdev.8 | 4 +++- + disk-utils/blockdev.c | 2 +- + 2 files changed, 4 insertions(+), 2 deletions(-) + +diff --git a/disk-utils/blockdev.8 b/disk-utils/blockdev.8 +index 2b3d64c..f4282da 100644 +--- a/disk-utils/blockdev.8 ++++ b/disk-utils/blockdev.8 +@@ -68,7 +68,9 @@ Get size in 512-byte sectors. + .IP "\fB\-\-rereadpt\fP" + Reread partition table + .IP "\fB\-\-setbsz\fP \fIbytes\fP" +-Set blocksize. ++Set blocksize. Note that the block size is specific to the current file ++descriptor opening the block device, so the change of block size only persists ++for as long as blockdev has the device open, and is lost once blockdev exits. + .IP "\fB\-\-setfra\fP \fIsectors\fP" + Set filesystem readahead (same like --setra on 2.6 kernels). + .IP "\fB\-\-setra\fP \fIsectors\fP" +diff --git a/disk-utils/blockdev.c b/disk-utils/blockdev.c +index 4543818..d030217 100644 +--- a/disk-utils/blockdev.c ++++ b/disk-utils/blockdev.c +@@ -127,7 +127,7 @@ static const struct bdc bdcms[] = + .argname = "", + .argtype = ARG_INT, + .flags = FL_NORESULT, +- .help = N_("set blocksize") ++ .help = N_("set blocksize on file descriptor opening the block device") + },{ + IOCTL_ENTRY(BLKGETSIZE), + .name = "--getsize", +-- +1.8.3.1 + diff --git a/SOURCES/2.24-fsck-fstab.patch b/SOURCES/2.24-fsck-fstab.patch new file mode 100644 index 0000000..113c52b --- /dev/null +++ b/SOURCES/2.24-fsck-fstab.patch @@ -0,0 +1,22 @@ +diff -up util-linux-2.23.2/disk-utils/fsck.c.kzak util-linux-2.23.2/disk-utils/fsck.c +--- util-linux-2.23.2/disk-utils/fsck.c.kzak 2013-06-13 09:46:10.377650254 +0200 ++++ util-linux-2.23.2/disk-utils/fsck.c 2014-03-25 12:46:59.525939425 +0100 +@@ -437,10 +437,14 @@ static void load_fs_info(void) + if (mnt_table_parse_fstab(fstab, path)) { + if (!path) + path = mnt_get_fstab_path(); +- if (errno) +- warn(_("%s: failed to parse fstab"), path); +- else +- warnx(_("%s: failed to parse fstab"), path); ++ ++ /* don't print error when there is no fstab at all */ ++ if (access(path, F_OK) == 0) { ++ if (errno) ++ warn(_("%s: failed to parse fstab"), path); ++ else ++ warnx(_("%s: failed to parse fstab"), path); ++ } + } + } + diff --git a/SOURCES/2.24-libfdisk-fix-SIGFPE.patch b/SOURCES/2.24-libfdisk-fix-SIGFPE.patch new file mode 100644 index 0000000..bb8e872 --- /dev/null +++ b/SOURCES/2.24-libfdisk-fix-SIGFPE.patch @@ -0,0 +1,40 @@ +From 44baaedaffee029dca76796b933412d97a19dff6 Mon Sep 17 00:00:00 2001 +From: Karel Zak +Date: Mon, 9 Sep 2013 10:57:50 +0200 +Subject: [PATCH] libfdisk: fix SIGFPE + + #0 recount_geometry at libfdisk/src/alignment.c:143 + #1 fdisk_discover_geometry at libfdisk/src/alignment.c:205 + #2 fdisk_context_assign_device at libfdisk/src/context.c:173 + #3 print_partition_table_from_option at fdisks/fdisk.c:924 + +References: https://bugzilla.redhat.com/show_bug.cgi?id=1005566 +Signed-off-by: Karel Zak +--- + libfdisk/src/alignment.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +diff --git a/libfdisk/src/alignment.c b/libfdisk/src/alignment.c +index ac44e73..4d4ab48 100644 +--- a/libfdisk/src/alignment.c ++++ b/libfdisk/src/alignment.c +@@ -193,11 +193,12 @@ int fdisk_discover_geometry(struct fdisk_context *cxt) + + /* what the kernel/bios thinks the geometry is */ + blkdev_get_geometry(cxt->dev_fd, &h, &s); +- if (!h && !s) { +- /* unable to discover geometry, use default values */ +- s = 63; ++ ++ /* defaults */ ++ if (!h) + h = 255; +- } ++ if (!s) ++ s = 63; + + /* obtained heads and sectors */ + cxt->geom.heads = h; +-- +1.8.1.4 + diff --git a/SOURCES/2.24-libmount-3.14.patch b/SOURCES/2.24-libmount-3.14.patch new file mode 100644 index 0000000..64de1a9 --- /dev/null +++ b/SOURCES/2.24-libmount-3.14.patch @@ -0,0 +1,80 @@ +diff -up util-linux-2.23.2/libmount/src/tab.c.kzak util-linux-2.23.2/libmount/src/tab.c +--- util-linux-2.23.2/libmount/src/tab.c.kzak 2013-07-30 10:39:26.218738358 +0200 ++++ util-linux-2.23.2/libmount/src/tab.c 2014-09-25 10:53:43.525269554 +0200 +@@ -47,6 +47,8 @@ + #include "strutils.h" + #include "loopdev.h" + ++static int is_mountinfo(struct libmnt_table *tb); ++ + /** + * mnt_new_table: + * +@@ -233,7 +235,7 @@ int mnt_table_get_root_fs(struct libmnt_ + assert(tb); + assert(root); + +- if (!tb || !root) ++ if (!tb || !root || !is_mountinfo(tb)) + return -EINVAL; + + DBG(TAB, mnt_debug_h(tb, "lookup root fs")); +@@ -241,8 +243,6 @@ int mnt_table_get_root_fs(struct libmnt_ + mnt_reset_iter(&itr, MNT_ITER_FORWARD); + while(mnt_table_next_fs(tb, &itr, &fs) == 0) { + int id = mnt_fs_get_parent_id(fs); +- if (!id) +- break; /* @tab is not mountinfo file? */ + + if (!*root || id < root_id) { + *root = fs; +@@ -250,7 +250,7 @@ int mnt_table_get_root_fs(struct libmnt_ + } + } + +- return root_id ? 0 : -EINVAL; ++ return *root ? 0 : -EINVAL; + } + + /** +@@ -271,15 +271,13 @@ int mnt_table_next_child_fs(struct libmn + struct libmnt_fs *fs; + int parent_id, lastchld_id = 0, chld_id = 0; + +- if (!tb || !itr || !parent) ++ if (!tb || !itr || !parent || !is_mountinfo(tb)) + return -EINVAL; + + DBG(TAB, mnt_debug_h(tb, "lookup next child of '%s'", + mnt_fs_get_target(parent))); + + parent_id = mnt_fs_get_id(parent); +- if (!parent_id) +- return -EINVAL; + + /* get ID of the previously returned child */ + if (itr->head && itr->p != itr->head) { +@@ -310,7 +308,7 @@ int mnt_table_next_child_fs(struct libmn + } + } + +- if (!chld_id) ++ if (!*chld) + return 1; /* end of iterator */ + + /* set the iterator to the @chld for the next call */ +diff -up util-linux-2.23.2/misc-utils/findmnt.c.kzak util-linux-2.23.2/misc-utils/findmnt.c +--- util-linux-2.23.2/misc-utils/findmnt.c.kzak 2013-07-30 11:07:35.138395654 +0200 ++++ util-linux-2.23.2/misc-utils/findmnt.c 2014-09-25 10:49:50.953050560 +0200 +@@ -826,8 +826,9 @@ static int tab_is_tree(struct libmnt_tab + if (!itr) + return 0; + +- if (mnt_table_next_fs(tb, itr, &fs) == 0) +- rc = mnt_fs_get_id(fs) > 0 && mnt_fs_get_parent_id(fs) > 0; ++ rc = (mnt_table_next_fs(tb, itr, &fs) == 0 && ++ mnt_fs_is_kernel(fs) && ++ mnt_fs_get_root(fs)); + + mnt_free_iter(itr); + return rc; diff --git a/SOURCES/2.24-libmount-canonicalize-for-conversion-from-loopdev.patch b/SOURCES/2.24-libmount-canonicalize-for-conversion-from-loopdev.patch new file mode 100644 index 0000000..d1e2341 --- /dev/null +++ b/SOURCES/2.24-libmount-canonicalize-for-conversion-from-loopdev.patch @@ -0,0 +1,40 @@ +From 3f420a49dd4d0c413b635dd621aa34eebce2d3d2 Mon Sep 17 00:00:00 2001 +From: Karel Zak +Date: Mon, 5 Aug 2013 13:58:01 +0200 +Subject: [PATCH] libmount: canonicalize for conversion from loopdev backing + file + + # mount foo.img /mnt + # umount foo.img + umount: foo.img: not mounted + +The loopdev code (and sysfs backing_file) uses absolute paths, but +libmount does not canonicalize the path before lookup for the backing file. + +References: https://bugzilla.redhat.com/show_bug.cgi?id=950497 +Signed-off-by: Karel Zak +--- + libmount/src/context_umount.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/libmount/src/context_umount.c b/libmount/src/context_umount.c +index 2b791c4..b02902c 100644 +--- a/libmount/src/context_umount.c ++++ b/libmount/src/context_umount.c +@@ -161,7 +161,12 @@ try_loopdev: + struct stat st; + + if (stat(tgt, &st) == 0 && S_ISREG(st.st_mode)) { +- int count = loopdev_count_by_backing_file(tgt, &loopdev); ++ int count; ++ ++ cn_tgt = mnt_resolve_path(tgt, cache); ++ count = loopdev_count_by_backing_file(cn_tgt, &loopdev); ++ if (!cache) ++ free(cn_tgt); + if (count == 1) { + DBG(CXT, mnt_debug_h(cxt, + "umount: %s --> %s (retry)", tgt, loopdev)); +-- +1.8.1.4 + diff --git a/SOURCES/2.24-libmount-mem.patch b/SOURCES/2.24-libmount-mem.patch new file mode 100644 index 0000000..64926a0 --- /dev/null +++ b/SOURCES/2.24-libmount-mem.patch @@ -0,0 +1,24 @@ +diff -up util-linux-2.23.2/libmount/src/context_umount.c.kzak util-linux-2.23.2/libmount/src/context_umount.c +--- util-linux-2.23.2/libmount/src/context_umount.c.kzak 2013-10-07 11:43:10.990598629 +0200 ++++ util-linux-2.23.2/libmount/src/context_umount.c 2013-10-07 11:46:01.051031431 +0200 +@@ -423,6 +423,8 @@ static int evaluate_permissions(struct l + if (optstr && !mnt_optstr_get_option(optstr, + "user", &mtab_user, &sz) && sz) + ok = !strncmp(curr_user, mtab_user, sz); ++ ++ free(curr_user); + } + + if (ok) { +diff -up util-linux-2.23.2/libmount/src/utils.c.kzak util-linux-2.23.2/libmount/src/utils.c +--- util-linux-2.23.2/libmount/src/utils.c.kzak 2013-07-30 11:15:27.391515623 +0200 ++++ util-linux-2.23.2/libmount/src/utils.c 2013-10-07 11:43:27.209924834 +0200 +@@ -159,7 +159,7 @@ int mnt_chdir_to_parent(const char *targ + if (!last || !*last) + memcpy(*filename, ".", 2); + else +- memcpy(*filename, last, strlen(last) + 1); ++ memmove(*filename, last, strlen(last) + 1); + } else + free(buf); + return 0; diff --git a/SOURCES/2.24-losetup-add-device.patch b/SOURCES/2.24-losetup-add-device.patch new file mode 100644 index 0000000..680d616 --- /dev/null +++ b/SOURCES/2.24-losetup-add-device.patch @@ -0,0 +1,63 @@ +diff -up util-linux-2.23.2/include/loopdev.h.kzak util-linux-2.23.2/include/loopdev.h +--- util-linux-2.23.2/include/loopdev.h.kzak 2013-06-13 09:46:10.397650425 +0200 ++++ util-linux-2.23.2/include/loopdev.h 2014-01-14 11:11:48.427643690 +0100 +@@ -149,6 +149,7 @@ extern void loopcxt_enable_debug(struct + extern int loopcxt_set_device(struct loopdev_cxt *lc, const char *device) + __attribute__ ((warn_unused_result)); + extern int loopcxt_has_device(struct loopdev_cxt *lc); ++extern int loopcxt_add_device(struct loopdev_cxt *lc); + extern char *loopcxt_strdup_device(struct loopdev_cxt *lc); + extern const char *loopcxt_get_device(struct loopdev_cxt *lc); + extern struct sysfs_cxt *loopcxt_get_sysfs(struct loopdev_cxt *lc); +diff -up util-linux-2.23.2/lib/loopdev.c.kzak util-linux-2.23.2/lib/loopdev.c +--- util-linux-2.23.2/lib/loopdev.c.kzak 2013-07-30 11:19:20.143600300 +0200 ++++ util-linux-2.23.2/lib/loopdev.c 2014-01-14 11:11:48.428643700 +0100 +@@ -1298,6 +1298,36 @@ int loopcxt_delete_device(struct loopdev + return 0; + } + ++int loopcxt_add_device(struct loopdev_cxt *lc) ++{ ++ int rc = -EINVAL; ++ int ctl, nr = -1; ++ const char *p, *dev = loopcxt_get_device(lc); ++ ++ if (!dev) ++ goto done; ++ ++ if (!(lc->flags & LOOPDEV_FL_CONTROL)) { ++ rc = -ENOSYS; ++ goto done; ++ } ++ ++ p = strrchr(dev, '/'); ++ if (!p || (sscanf(p, "/loop%d", &nr) != 1 && sscanf(p, "/%d", &nr) != 1) ++ || nr < 0) ++ goto done; ++ ++ ctl = open(_PATH_DEV_LOOPCTL, O_RDWR|O_CLOEXEC); ++ if (ctl >= 0) { ++ DBG(lc, loopdev_debug("add_device %d", nr)); ++ rc = ioctl(ctl, LOOP_CTL_ADD, nr); ++ close(ctl); ++ } ++done: ++ DBG(lc, loopdev_debug("add_device done [rc=%d]", rc)); ++ return rc; ++} ++ + /* + * Note that LOOP_CTL_GET_FREE ioctl is supported since kernel 3.1. In older + * kernels we have to check all loop devices to found unused one. +diff -up util-linux-2.23.2/sys-utils/losetup.c.kzak util-linux-2.23.2/sys-utils/losetup.c +--- util-linux-2.23.2/sys-utils/losetup.c.kzak 2013-07-30 11:20:16.987117853 +0200 ++++ util-linux-2.23.2/sys-utils/losetup.c 2014-01-14 11:11:48.428643700 +0100 +@@ -600,6 +600,8 @@ int main(int argc, char **argv) + { + int hasdev = loopcxt_has_device(&lc); + ++ if (hasdev && !is_loopdev(loopcxt_get_device(&lc))) ++ loopcxt_add_device(&lc); + do { + const char *errpre; + diff --git a/SOURCES/2.24-losetup-offset.patch b/SOURCES/2.24-losetup-offset.patch new file mode 100644 index 0000000..a93cc55 --- /dev/null +++ b/SOURCES/2.24-losetup-offset.patch @@ -0,0 +1,32 @@ +diff -up util-linux-2.23.2/lib/loopdev.c.kzak util-linux-2.23.2/lib/loopdev.c +--- util-linux-2.23.2/lib/loopdev.c.kzak 2014-09-25 10:16:23.521897462 +0200 ++++ util-linux-2.23.2/lib/loopdev.c 2014-09-25 10:23:38.852050990 +0200 +@@ -1129,6 +1129,12 @@ static int loopcxt_check_size(struct loo + return -errno; + } + ++ /* It's block device, so, align to 512-byte sectors */ ++ if (expected_size % 512) { ++ DBG(lc, loopdev_debug("expected size misaligned to 512-byte sectors")); ++ expected_size = (expected_size >> 9) << 9; ++ } ++ + if (expected_size != size) { + DBG(lc, loopdev_debug("warning: loopdev and expected " + "size dismatch (%ju/%ju)", +diff -up util-linux-2.23.2/sys-utils/losetup.c.kzak util-linux-2.23.2/sys-utils/losetup.c +--- util-linux-2.23.2/sys-utils/losetup.c.kzak 2014-09-25 10:16:23.521897462 +0200 ++++ util-linux-2.23.2/sys-utils/losetup.c 2014-09-25 10:23:38.852050990 +0200 +@@ -632,11 +632,7 @@ int main(int argc, char **argv) + /* errors */ + errpre = hasdev && loopcxt_get_fd(&lc) < 0 ? + loopcxt_get_device(&lc) : file; +- if (errno == ERANGE && offset && offset % 512) +- warnx(_("%s: failed to set up loop device, " +- "offset is not 512-byte aligned."), errpre); +- else +- warn(_("%s: failed to set up loop device"), errpre); ++ warn(_("%s: failed to set up loop device"), errpre); + break; + } while (hasdev == 0); + diff --git a/SOURCES/2.24-partx-update.patch b/SOURCES/2.24-partx-update.patch new file mode 100644 index 0000000..f1dc8e7 --- /dev/null +++ b/SOURCES/2.24-partx-update.patch @@ -0,0 +1,131 @@ +From 5cc378e4cdeb957b405e0264a09295eda7d75ff7 Mon Sep 17 00:00:00 2001 +From: Scott Moser +Date: Mon, 13 Jan 2014 15:32:49 -0500 +Subject: [PATCH] partx: fix --update ranges and out of order tables + +partx --update DEVICE NUMBER +was broken in 2 cases: + * if NUMBER != 1 + * if the partition table was "out of order". + Ie, where sda2 came after sda3. + +References: https://bugs.launchpad.net/ubuntu/+source/cloud-utils/+bug/1244662 +Signed-off-by: Scott Moser +Signed-off-by: Karel Zak +--- + disk-utils/partx.c | 75 ++++++++++++++++++++++++++++++++++++------------------ + 1 file changed, 50 insertions(+), 25 deletions(-) + +diff --git a/disk-utils/partx.c b/disk-utils/partx.c +index 880d779..df03e59 100644 +--- a/disk-utils/partx.c ++++ b/disk-utils/partx.c +@@ -412,10 +412,41 @@ static void upd_parts_warnx(const char *device, int first, int last) + device, first, last); + } + ++/** ++ * get_partition_by_partno: ++ * @ls: partitions list ++ * @n: the partition number (e.g. 'N' from sda'N') ++ * ++ * This does not assume any order of the input blkid_partlist. ++ * And correctly handles "out of order" partition tables. ++ * partition N is located after partition N+1 on the disk. ++ * ++ * Returns: partition object or NULL in case or error. ++ */ ++blkid_partition get_partition_by_partno(blkid_partlist ls, int n) ++{ ++ int i, nparts; ++ blkid_partition par; ++ if (!ls) ++ return NULL; ++ ++ nparts = blkid_partlist_numof_partitions(ls); ++ if (nparts < 0) ++ return NULL; ++ ++ for (i = 0; i < nparts; i++) { ++ par = blkid_partlist_get_partition(ls, i); ++ if (n == blkid_partition_get_partno(par)) { ++ return par; ++ } ++ } ++ return NULL; ++} ++ + static int upd_parts(int fd, const char *device, dev_t devno, + blkid_partlist ls, int lower, int upper) + { +- int i, n, an, nparts, rc = 0, errfirst = 0, errlast = 0, err; ++ int n, nparts, rc = 0, errfirst = 0, errlast = 0, err; + blkid_partition par; + uintmax_t start, size; + +@@ -441,18 +472,16 @@ static int upd_parts(int fd, const char *device, dev_t devno, + return -1; + } + +- for (i = 0, n = lower; n <= upper; n++) { +- par = blkid_partlist_get_partition(ls, i); +- an = blkid_partition_get_partno(par); +- +- if (lower && n < lower) +- continue; +- if (upper && n > upper) ++ for (n = lower; n <= upper; n++) { ++ par = get_partition_by_partno(ls, n); ++ if (!par) { ++ if (verbose) ++ warn(_("%s: no partition #%d"), device, n); + continue; ++ } + + start = blkid_partition_get_start(par); + size = blkid_partition_get_size(par); +- + if (blkid_partition_is_extended(par)) + /* + * Let's follow the Linux kernel and reduce +@@ -463,25 +492,21 @@ static int upd_parts(int fd, const char *device, dev_t devno, + err = partx_del_partition(fd, n); + if (err == -1 && errno == ENXIO) + err = 0; /* good, it already doesn't exist */ +- if (an == n) ++ if (err == -1 && errno == EBUSY) + { +- if (i < nparts) +- i++; +- if (err == -1 && errno == EBUSY) +- { +- /* try to resize */ +- err = partx_resize_partition(fd, n, start, size); +- if (verbose) +- printf(_("%s: partition #%d resized\n"), device, n); +- if (err == 0) +- continue; +- } +- if (err == 0 && partx_add_partition(fd, n, start, size) == 0) { +- if (verbose) +- printf(_("%s: partition #%d added\n"), device, n); ++ /* try to resize */ ++ err = partx_resize_partition(fd, n, start, size); ++ if (verbose) ++ printf(_("%s: partition #%d resized\n"), device, n); ++ if (err == 0) + continue; +- } + } ++ if (err == 0 && partx_add_partition(fd, n, start, size) == 0) { ++ if (verbose) ++ printf(_("%s: partition #%d added\n"), device, n); ++ continue; ++ } ++ + if (err == 0) + continue; + rc = -1; +-- +1.9.3 + diff --git a/SOURCES/2.24-sfdisk-y-n-miscmatch.patch b/SOURCES/2.24-sfdisk-y-n-miscmatch.patch new file mode 100644 index 0000000..68ef91b --- /dev/null +++ b/SOURCES/2.24-sfdisk-y-n-miscmatch.patch @@ -0,0 +1,15 @@ +diff -up util-linux-2.23.2/fdisks/sfdisk.c.kzak util-linux-2.23.2/fdisks/sfdisk.c +--- util-linux-2.23.2/fdisks/sfdisk.c.kzak 2013-07-30 10:39:26.200738180 +0200 ++++ util-linux-2.23.2/fdisks/sfdisk.c 2013-10-07 11:52:10.701445115 +0200 +@@ -3201,9 +3201,9 @@ do_fdisk(char *dev) { + ignore_result( fgets(answer, sizeof(answer), stdin) ); + if (answer[0] == 'q' || answer[0] == 'Q') { + errx(EXIT_FAILURE, _("Quitting - nothing changed")); +- } else if (rpmatch(answer) == 1) { +- continue; + } else if (rpmatch(answer) == 0) { ++ continue; ++ } else if (rpmatch(answer) == 1) { + break; + } else { + printf(_("Please answer one of y,n,q\n")); diff --git a/SOURCES/2.24-su-fix-lastlog-and-btmp-logging.patch b/SOURCES/2.24-su-fix-lastlog-and-btmp-logging.patch new file mode 100644 index 0000000..40c6081 --- /dev/null +++ b/SOURCES/2.24-su-fix-lastlog-and-btmp-logging.patch @@ -0,0 +1,48 @@ +From 9b5dc4cb8d5d82c31c0cda898832998c21afc303 Mon Sep 17 00:00:00 2001 +From: Karel Zak +Date: Mon, 9 Sep 2013 12:24:01 +0200 +Subject: [PATCH] su: fix lastlog and btmp logging + +The su(1) logging code mix ups "old" and "new" passwd structs. The +result is things like + + Sep 9 11:50:45 x2 su: (to kzak) kzak on none + +in /var/log/messages. The right log entry is + + Sep 9 11:50:45 x2 su: (to root) kzak on pts/3 + +The bug has been introduced by commit c74a7af17c7a176c358dfaa8e1814786c89ebc14. + +References: https://bugzilla.redhat.com/show_bug.cgi?id=1005194 +Signed-off-by: Karel Zak +--- + login-utils/su-common.c | 5 +---- + 1 file changed, 1 insertion(+), 4 deletions(-) + +diff --git a/login-utils/su-common.c b/login-utils/su-common.c +index ade5c92..858af01 100644 +--- a/login-utils/su-common.c ++++ b/login-utils/su-common.c +@@ -161,7 +161,7 @@ log_syslog(struct passwd const *pw, bool successful) + old_user = pwd ? pwd->pw_name : ""; + } + +- if (get_terminal_name(STDERR_FILENO, NULL, &tty, NULL) == 0 && tty) ++ if (get_terminal_name(STDERR_FILENO, NULL, &tty, NULL) != 0 || !tty) + tty = "none"; + + openlog (program_invocation_short_name, 0 , LOG_AUTH); +@@ -483,9 +483,6 @@ authenticate (const struct passwd *pw) + + done: + +- if (lpw && lpw->pw_name) +- pw = lpw; +- + log_syslog(pw, !is_pam_failure(retval)); + + if (is_pam_failure(retval)) +-- +1.8.1.4 + diff --git a/SOURCES/2.24-su-suppress-PAM-info-messages.patch b/SOURCES/2.24-su-suppress-PAM-info-messages.patch new file mode 100644 index 0000000..3b54521 --- /dev/null +++ b/SOURCES/2.24-su-suppress-PAM-info-messages.patch @@ -0,0 +1,48 @@ +diff -up util-linux-2.23.2/login-utils/su-common.c.kzak util-linux-2.23.2/login-utils/su-common.c +--- util-linux-2.23.2/login-utils/su-common.c.kzak 2013-07-30 10:39:26.223738407 +0200 ++++ util-linux-2.23.2/login-utils/su-common.c 2013-09-09 09:32:05.497238691 +0200 +@@ -111,6 +111,9 @@ static int same_session = 0; + /* SU_MODE_{RUNUSER,SU} */ + static int su_mode; + ++/* Don't print PAM info messages (Last login, etc.). */ ++static int suppress_pam_info; ++ + static bool _pam_session_opened; + static bool _pam_cred_established; + static sig_atomic_t volatile caught_signal = false; +@@ -208,10 +211,23 @@ static void log_btmp(struct passwd const + updwtmp(_PATH_BTMP, &ut); + } + ++ ++static int su_pam_conv(int num_msg, const struct pam_message **msg, ++ struct pam_response **resp, void *appdata_ptr) ++{ ++ if (suppress_pam_info ++ && num_msg == 1 ++ && msg ++ && msg[0]->msg_style == PAM_TEXT_INFO) ++ return PAM_SUCCESS; ++ ++ return misc_conv(num_msg, msg, resp, appdata_ptr); ++} ++ + static struct pam_conv conv = + { +- misc_conv, +- NULL ++ su_pam_conv, ++ NULL + }; + + static void +@@ -902,6 +918,9 @@ su_main (int argc, char **argv, int mode + + init_groups (pw, groups, num_supp_groups); + ++ if (!simulate_login || command) ++ suppress_pam_info = 1; /* don't print PAM info messages */ ++ + create_watching_parent (); + /* Now we're in the child. */ diff --git a/SOURCES/2.24-tests-portability.patch b/SOURCES/2.24-tests-portability.patch new file mode 100644 index 0000000..be6f0b1 --- /dev/null +++ b/SOURCES/2.24-tests-portability.patch @@ -0,0 +1,37 @@ +diff -up util-linux-2.23.2/tests/functions.sh.kzak util-linux-2.23.2/tests/functions.sh +--- util-linux-2.23.2/tests/functions.sh.kzak 2013-06-13 09:46:10.554651768 +0200 ++++ util-linux-2.23.2/tests/functions.sh 2013-09-09 10:01:23.355469268 +0200 +@@ -483,7 +483,7 @@ function ts_scsi_debug_init { + modprobe scsi_debug $* + [ "$?" == 0 ] || ts_die "Cannot init device" + +- DEVNAME=$(grep scsi_debug /sys/block/*/device/model | awk -F '/' '{print $4}') ++ DEVNAME=$(grep --with-filename scsi_debug /sys/block/*/device/model | awk -F '/' '{print $4}') + [ "x${DEVNAME}" == "x" ] && ts_die "Cannot find device" + + DEVICE="/dev/${DEVNAME}" +diff -up util-linux-2.23.2/tests/ts/cramfs/mkfs.kzak util-linux-2.23.2/tests/ts/cramfs/mkfs +--- util-linux-2.23.2/tests/ts/cramfs/mkfs.kzak 2013-06-13 09:46:10.557651793 +0200 ++++ util-linux-2.23.2/tests/ts/cramfs/mkfs 2013-09-09 10:01:23.355469268 +0200 +@@ -80,7 +80,7 @@ cd $TS_MOUNTPOINT + + ts_log "list the image" + export TZ='GMT-1' +-ls -laR --time-style=long-iso . >> $TS_OUTPUT ++ls -laR --time-style=long-iso . | sed 's:\. : :g' >> $TS_OUTPUT + echo >> $TS_OUTPUT + + ts_log "list checksums from new data" +diff -up util-linux-2.23.2/tests/ts/libmount/context-utab.kzak util-linux-2.23.2/tests/ts/libmount/context-utab +--- util-linux-2.23.2/tests/ts/libmount/context-utab.kzak 2013-06-13 09:46:10.561651827 +0200 ++++ util-linux-2.23.2/tests/ts/libmount/context-utab 2013-09-09 10:01:23.355469268 +0200 +@@ -85,7 +85,9 @@ grep -q $DEVICE $LIBMOUNT_UTAB && \ + echo "umount (mountpoint) failed: found $DEVICE in $LIBMOUNT_UTAB" >> $TS_OUTPUT 2>&1 + ts_finalize_subtest + ++ + if [ -x "/sbin/mkfs.btrfs" ]; then ++ $TS_CMD_WIPEFS -a $DEVICE &> /dev/null + ts_log "Create filesystem [btrfs]" + /sbin/mkfs.btrfs -L "$LABEL" $DEVICE &> /dev/null + udevadm settle diff --git a/SOURCES/2.24-unshare-mount-fork.patch b/SOURCES/2.24-unshare-mount-fork.patch new file mode 100644 index 0000000..1f2d816 --- /dev/null +++ b/SOURCES/2.24-unshare-mount-fork.patch @@ -0,0 +1,248 @@ +diff -up util-linux-2.23.2/sys-utils/Makemodule.am.kzak util-linux-2.23.2/sys-utils/Makemodule.am +--- util-linux-2.23.2/sys-utils/Makemodule.am.kzak 2014-09-25 14:16:33.526384729 +0200 ++++ util-linux-2.23.2/sys-utils/Makemodule.am 2014-09-25 14:15:34.861825005 +0200 +@@ -290,6 +290,7 @@ usrbin_exec_PROGRAMS += unshare + dist_man_MANS += sys-utils/unshare.1 + unshare_SOURCES = sys-utils/unshare.c + unshare_LDADD = $(LDADD) libcommon.la ++unshare_CFLAGS = $(AM_CFLAGS) -I$(ul_libmount_incdir) + endif + + if BUILD_NSENTER +diff -up util-linux-2.23.2/sys-utils/unshare.1.kzak util-linux-2.23.2/sys-utils/unshare.1 +--- util-linux-2.23.2/sys-utils/unshare.1.kzak 2014-09-25 14:14:30.194208005 +0200 ++++ util-linux-2.23.2/sys-utils/unshare.1 2014-09-25 14:15:17.617660476 +0200 +@@ -1,63 +1,82 @@ + .\" Process this file with + .\" groff -man -Tascii lscpu.1 + .\" +-.TH UNSHARE 1 "January 2013" "util-linux" "User Commands" ++.TH UNSHARE 1 "July 2013" "util-linux" "User Commands" + .SH NAME + unshare \- run program with some namespaces unshared from parent + .SH SYNOPSIS + .B unshare + .RI [ options ] +-program ++.I program + .RI [ arguments ] + .SH DESCRIPTION +-Unshares specified namespaces from parent process and then executes specified +-program. Unshareable namespaces are: ++Unshares the indicated namespaces from the parent process and then executes ++the specified program. The namespaces to be unshared are indicated via ++options. Unshareable namespaces are: + .TP + .BR "mount namespace" +-mounting and unmounting filesystems will not affect rest of the system ++Mounting and unmounting filesystems will not affect the rest of the system + (\fBCLONE_NEWNS\fP flag), except for filesystems which are explicitly marked as +-shared (by mount --make-shared). See /proc/self/mountinfo for the shared flags. ++shared (with \fBmount --make-shared\fP; see \fI/proc/self/mountinfo\fP for the ++\fBshared\fP flags). ++ ++It's recommended to use \fBmount --make-rprivate\fP or \fBmount --make-rslave\fP ++after \fBunshare --mount\fP to make sure that mountpoints in the new namespace ++are really unshared from parental namespace. + .TP + .BR "UTS namespace" +-setting hostname, domainname will not affect rest of the system +-(\fBCLONE_NEWUTS\fP flag). ++Setting hostname or domainname will not affect the rest of the system. ++(\fBCLONE_NEWUTS\fP flag) + .TP + .BR "IPC namespace" +-process will have independent namespace for System V message queues, semaphore +-sets and shared memory segments (\fBCLONE_NEWIPC\fP flag). ++The process will have an independent namespace for System V message queues, ++semaphore sets and shared memory segments. (\fBCLONE_NEWIPC\fP flag) + .TP + .BR "network namespace" +-process will have independent IPv4 and IPv6 stacks, IP routing tables, firewall +-rules, the \fI/proc/net\fP and \fI/sys/class/net\fP directory trees, sockets +-etc. (\fBCLONE_NEWNET\fP flag). ++The process will have independent IPv4 and IPv6 stacks, IP routing tables, ++firewall rules, the \fI/proc/net\fP and \fI/sys/class/net\fP directory trees, ++sockets, etc. (\fBCLONE_NEWNET\fP flag) + .TP + .BR "pid namespace" +-children will have a distinct set of pid to process mappings than their parent. +-(\fBCLONE_NEWPID\fP flag). ++Children will have a distinct set of PID to process mappings from their parent. ++(\fBCLONE_NEWPID\fP flag) + .PP +-See the \fBclone\fR(2) for exact semantics of the flags. ++See \fBclone\fR(2) for the exact semantics of the flags. + .SH OPTIONS + .TP + .BR \-h , " \-\-help" +-Print a help message, +-.TP +-.BR \-m , " \-\-mount" +-Unshare the mount namespace, +-.TP +-.BR \-u , " \-\-uts" +-Unshare the UTS namespace, ++Display help text and exit. + .TP + .BR \-i , " \-\-ipc" +-Unshare the IPC namespace, ++Unshare the IPC namespace. ++.TP ++.BR \-m , " \-\-mount" ++Unshare the mount namespace. + .TP + .BR \-n , " \-\-net" + Unshare the network namespace. + .TP + .BR \-p , " \-\-pid" + Unshare the pid namespace. ++See also the \fB--fork\fP and \fB--mount-proc\fP options. ++.TP ++.BR \-u , " \-\-uts" ++Unshare the UTS namespace. ++.TP ++.BR \-f , " \-\-fork" ++Fork the specified \fIprogram\fR as a child process of \fBunshare\fR rather than ++running it directly. This is useful when creating a new pid namespace. ++.TP ++.BR \-\-mount-proc "[=\fImountpoint\fP]" ++Just before running the program, mount the proc filesystem at the \fImountpoint\fP ++(default is /proc). This is useful when creating a new pid namespace. It also ++implies creating a new mount namespace since the /proc mount would otherwise ++mess up existing programs on the system. The new proc filesystem is explicitly ++mounted as private (by MS_PRIVATE|MS_REC). + .SH SEE ALSO + .BR unshare (2), +-.BR clone (2) ++.BR clone (2), ++.BR mount (8) + .SH BUGS + None known so far. + .SH AUTHOR +diff -up util-linux-2.23.2/sys-utils/unshare.c.kzak util-linux-2.23.2/sys-utils/unshare.c +--- util-linux-2.23.2/sys-utils/unshare.c.kzak 2014-09-25 14:14:30.194208005 +0200 ++++ util-linux-2.23.2/sys-utils/unshare.c 2014-09-25 14:15:34.861825005 +0200 +@@ -24,12 +24,19 @@ + #include + #include + #include ++#include ++#include ++ ++/* we only need some defines missing in sys/mount.h, no libmount linkage */ ++#include + + #include "nls.h" + #include "c.h" +-#include "closestream.h" + #include "namespace.h" + #include "exec_shell.h" ++#include "xalloc.h" ++#include "pathnames.h" ++ + + static void usage(int status) + { +@@ -40,11 +47,13 @@ static void usage(int status) + _(" %s [options] [args...]\n"), program_invocation_short_name); + + fputs(USAGE_OPTIONS, out); +- fputs(_(" -m, --mount unshare mounts namespace\n"), out); +- fputs(_(" -u, --uts unshare UTS namespace (hostname etc)\n"), out); +- fputs(_(" -i, --ipc unshare System V IPC namespace\n"), out); +- fputs(_(" -n, --net unshare network namespace\n"), out); +- fputs(_(" -p, --pid unshare pid namespace\n"), out); ++ fputs(_(" -m, --mount unshare mounts namespace\n"), out); ++ fputs(_(" -u, --uts unshare UTS namespace (hostname etc)\n"), out); ++ fputs(_(" -i, --ipc unshare System V IPC namespace\n"), out); ++ fputs(_(" -n, --net unshare network namespace\n"), out); ++ fputs(_(" -p, --pid unshare pid namespace\n"), out); ++ fputs(_(" -f, --fork fork before launching \n"), out); ++ fputs(_(" --mount-proc[=] mount proc filesystem first (implies --mount)\n"), out); + + fputs(USAGE_SEPARATOR, out); + fputs(USAGE_HELP, out); +@@ -56,6 +65,9 @@ static void usage(int status) + + int main(int argc, char *argv[]) + { ++ enum { ++ OPT_MOUNTPROC = CHAR_MAX + 1 ++ }; + static const struct option longopts[] = { + { "help", no_argument, 0, 'h' }, + { "version", no_argument, 0, 'V'}, +@@ -64,20 +76,24 @@ int main(int argc, char *argv[]) + { "ipc", no_argument, 0, 'i' }, + { "net", no_argument, 0, 'n' }, + { "pid", no_argument, 0, 'p' }, ++ { "fork", no_argument, 0, 'f' }, ++ { "mount-proc", optional_argument, 0, OPT_MOUNTPROC }, + { NULL, 0, 0, 0 } + }; + + int unshare_flags = 0; ++ int c, forkit = 0; ++ const char *procmnt = NULL; + +- int c; +- +- setlocale(LC_MESSAGES, ""); ++ setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); +- atexit(close_stdout); + +- while ((c = getopt_long(argc, argv, "hVmuinp", longopts, NULL)) != -1) { ++ while ((c = getopt_long(argc, argv, "+fhVmuinp", longopts, NULL)) != -1) { + switch (c) { ++ case 'f': ++ forkit = 1; ++ break; + case 'h': + usage(EXIT_SUCCESS); + case 'V': +@@ -98,6 +114,10 @@ int main(int argc, char *argv[]) + case 'p': + unshare_flags |= CLONE_NEWPID; + break; ++ case OPT_MOUNTPROC: ++ unshare_flags |= CLONE_NEWNS; ++ procmnt = optarg ? optarg : "/proc"; ++ break; + default: + usage(EXIT_FAILURE); + } +@@ -106,6 +126,31 @@ int main(int argc, char *argv[]) + if (-1 == unshare(unshare_flags)) + err(EXIT_FAILURE, _("unshare failed")); + ++ if (forkit) { ++ int status; ++ pid_t pid = fork(); ++ ++ switch(pid) { ++ case -1: ++ err(EXIT_FAILURE, _("fork failed")); ++ case 0: /* child */ ++ break; ++ default: /* parent */ ++ if (waitpid(pid, &status, 0) == -1) ++ err(EXIT_FAILURE, _("waitpid failed")); ++ if (WIFEXITED(status)) ++ return WEXITSTATUS(status); ++ else if (WIFSIGNALED(status)) ++ kill(getpid(), WTERMSIG(status)); ++ err(EXIT_FAILURE, _("child exit failed")); ++ } ++ } ++ ++ if (procmnt && ++ (mount("none", procmnt, NULL, MS_PRIVATE|MS_REC, NULL) != 0 || ++ mount("proc", procmnt, "proc", MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL) != 0)) ++ err(EXIT_FAILURE, _("mount %s failed"), procmnt); ++ + if (optind < argc) { + execvp(argv[optind], argv + optind); + err(EXIT_FAILURE, _("failed to execute %s"), argv[optind]); diff --git a/SOURCES/2.24-utmpdump-ipv6.patch b/SOURCES/2.24-utmpdump-ipv6.patch new file mode 100644 index 0000000..562892a --- /dev/null +++ b/SOURCES/2.24-utmpdump-ipv6.patch @@ -0,0 +1,56 @@ +diff -up util-linux-2.23.2/login-utils/utmpdump.c.kzak util-linux-2.23.2/login-utils/utmpdump.c +--- util-linux-2.23.2/login-utils/utmpdump.c.kzak 2013-10-07 11:56:02.030191040 +0200 ++++ util-linux-2.23.2/login-utils/utmpdump.c 2013-10-07 12:05:08.671171091 +0200 +@@ -85,11 +85,14 @@ static void xcleanse(char *s, int len) + + static void print_utline(struct utmp ut) + { +- char *addr_string, *time_string; +- struct in_addr in; ++ const char *addr_string, *time_string; ++ char buffer[INET6_ADDRSTRLEN]; ++ ++ if (ut.ut_addr_v6[1] || ut.ut_addr_v6[2] || ut.ut_addr_v6[3]) ++ addr_string = inet_ntop(AF_INET6, &(ut.ut_addr_v6), buffer, sizeof(buffer)); ++ else ++ addr_string = inet_ntop(AF_INET, &(ut.ut_addr_v6), buffer, sizeof(buffer)); + +- in.s_addr = ut.ut_addr; +- addr_string = inet_ntoa(in); + time_string = timetostr(ut.ut_time); + cleanse(ut.ut_id); + cleanse(ut.ut_user); +@@ -97,7 +100,7 @@ static void print_utline(struct utmp ut) + cleanse(ut.ut_host); + + /* pid id user line host addr time */ +- printf("[%d] [%05d] [%-4.4s] [%-*.*s] [%-*.*s] [%-*.*s] [%-15.15s] [%-28.28s]\n", ++ printf("[%d] [%05d] [%-4.4s] [%-*.*s] [%-*.*s] [%-*.*s] [%-15s] [%-28.28s]\n", + ut.ut_type, ut.ut_pid, ut.ut_id, 8, UT_NAMESIZE, ut.ut_user, + 12, UT_LINESIZE, ut.ut_line, 20, UT_HOSTSIZE, ut.ut_host, + addr_string, time_string); +@@ -248,11 +251,10 @@ static int gettok(char *line, char *dest + static void undump(FILE *fp) + { + struct utmp ut; +- char s_addr[16], s_time[29], *linestart, *line; ++ char s_addr[INET6_ADDRSTRLEN + 1], s_time[29], *linestart, *line; + int count = 0; + + line = linestart = xmalloc(1024 * sizeof(*linestart)); +- s_addr[15] = 0; + s_time[28] = 0; + + while (fgets(linestart, 1023, fp)) { +@@ -267,7 +269,10 @@ static void undump(FILE *fp) + line += gettok(line, s_addr, sizeof(s_addr) - 1, 1); + line += gettok(line, s_time, sizeof(s_time) - 1, 0); + +- ut.ut_addr = inet_addr(s_addr); ++ if (strchr(s_addr, '.')) ++ inet_pton(AF_INET, s_addr, &(ut.ut_addr_v6)); ++ else ++ inet_pton(AF_INET6, s_addr, &(ut.ut_addr_v6)); + ut.ut_time = strtotime(s_time); + + ignore_result( fwrite(&ut, sizeof(ut), 1, stdout) ); diff --git a/SOURCES/2.25-dmesg-w.patch b/SOURCES/2.25-dmesg-w.patch new file mode 100644 index 0000000..c01449c --- /dev/null +++ b/SOURCES/2.25-dmesg-w.patch @@ -0,0 +1,12 @@ +diff -up util-linux-2.23.2/sys-utils/dmesg.c.kzak util-linux-2.23.2/sys-utils/dmesg.c +--- util-linux-2.23.2/sys-utils/dmesg.c.kzak 2013-07-30 11:22:47.213494455 +0200 ++++ util-linux-2.23.2/sys-utils/dmesg.c 2014-09-24 10:24:49.179371108 +0200 +@@ -991,6 +991,8 @@ static int init_kmsg(struct dmesg_contro + + if (!ctl->follow) + mode |= O_NONBLOCK; ++ else ++ setlinebuf(stdout); + + ctl->kmsg = open("/dev/kmsg", mode); + if (ctl->kmsg < 0) diff --git a/SOURCES/2.25-flock-nfs4.patch b/SOURCES/2.25-flock-nfs4.patch new file mode 100644 index 0000000..7a01332 --- /dev/null +++ b/SOURCES/2.25-flock-nfs4.patch @@ -0,0 +1,11 @@ +diff -up util-linux-2.23.2/sys-utils/flock.c.kzak util-linux-2.23.2/sys-utils/flock.c +--- util-linux-2.23.2/sys-utils/flock.c.kzak 2014-03-25 12:00:53.735361387 +0100 ++++ util-linux-2.23.2/sys-utils/flock.c 2014-03-25 12:01:44.534886083 +0100 +@@ -250,6 +250,7 @@ int main(int argc, char *argv[]) + /* otherwise try again */ + continue; + case EIO: ++ case EBADF: /* since Linux 3.4 (commit 55725513) */ + /* Probably NFSv4 where flock() is emulated by fcntl(). + * Let's try to reopen in read-write mode. + */ diff --git a/SOURCES/2.25-fsck-nohelper.patch b/SOURCES/2.25-fsck-nohelper.patch new file mode 100644 index 0000000..b8dc8fa --- /dev/null +++ b/SOURCES/2.25-fsck-nohelper.patch @@ -0,0 +1,173 @@ +diff -up util-linux-2.23.2/disk-utils/fsck.c.kzak util-linux-2.23.2/disk-utils/fsck.c +--- util-linux-2.23.2/disk-utils/fsck.c.kzak 2014-03-25 12:52:33.429389852 +0100 ++++ util-linux-2.23.2/disk-utils/fsck.c 2014-03-25 12:56:27.126804792 +0100 +@@ -79,9 +79,7 @@ static const char *really_wanted[] = { + "ext4dev", + "jfs", + "reiserfs", +- "xiafs", +- "xfs", +- NULL ++ "xiafs" + }; + + /* +@@ -167,6 +165,19 @@ static int string_to_int(const char *s) + return (int) l; + } + ++/* Do we really really want to check this fs? */ ++static int fs_check_required(const char *type) ++{ ++ size_t i; ++ ++ for(i = 0; i < ARRAY_SIZE(really_wanted); i++) { ++ if (strcmp(type, really_wanted[i]) == 0) ++ return 1; ++ } ++ ++ return 0; ++} ++ + static int is_mounted(struct libmnt_fs *fs) + { + int rc; +@@ -546,17 +557,17 @@ static void print_stats(struct fsck_inst + * Execute a particular fsck program, and link it into the list of + * child processes we are waiting for. + */ +-static int execute(const char *type, struct libmnt_fs *fs, int interactive) ++static int execute(const char *progname, const char *progpath, ++ const char *type, struct libmnt_fs *fs, int interactive) + { +- char *s, *argv[80], prog[80]; ++ char *argv[80]; + int argc, i; + struct fsck_instance *inst, *p; + pid_t pid; + + inst = xcalloc(1, sizeof(*inst)); + +- sprintf(prog, "fsck.%s", type); +- argv[0] = xstrdup(prog); ++ argv[0] = xstrdup(progname); + argc = 1; + + for (i=0; i pid = pid; +- inst->prog = xstrdup(prog); ++ inst->prog = xstrdup(progname); + inst->type = xstrdup(type); + gettimeofday(&inst->start_time, NULL); + inst->next = NULL; +@@ -822,6 +826,7 @@ static int wait_many(int flags) + */ + static int fsck_device(struct libmnt_fs *fs, int interactive) + { ++ char progname[80], *progpath; + const char *type; + int retval; + +@@ -838,15 +843,27 @@ static int fsck_device(struct libmnt_fs + else + type = DEFAULT_FSTYPE; + ++ sprintf(progname, "fsck.%s", type); ++ progpath = find_fsck(progname); ++ if (progpath == NULL) { ++ if (fs_check_required(type)) { ++ retval = ENOENT; ++ goto err; ++ } ++ return 0; ++ } ++ + num_running++; +- retval = execute(type, fs, interactive); ++ retval = execute(progname, progpath, type, fs, interactive); + if (retval) { +- warnx(_("error %d while executing fsck.%s for %s"), +- retval, type, fs_get_device(fs)); + num_running--; +- return FSCK_EX_ERROR; ++ goto err; + } + return 0; ++err: ++ warnx(_("error %d (%m) while executing fsck.%s for %s"), ++ retval, type, fs_get_device(fs)); ++ return FSCK_EX_ERROR; + } + + +@@ -1014,8 +1031,7 @@ static int fs_ignored_type(struct libmnt + /* Check if we should ignore this filesystem. */ + static int ignore(struct libmnt_fs *fs) + { +- const char **ip, *type; +- int wanted = 0; ++ const char *type; + + /* + * If the pass number is 0, ignore it. +@@ -1070,16 +1086,11 @@ static int ignore(struct libmnt_fs *fs) + if (fs_ignored_type(fs)) + return 1; + +- /* Do we really really want to check this fs? */ +- for(ip = really_wanted; *ip; ip++) +- if (strcmp(type, *ip) == 0) { +- wanted = 1; +- break; +- } ++ + + /* See if the program is available. */ + if (find_fsck(type) == NULL) { +- if (wanted) ++ if (fs_check_required(type)) + warnx(_("cannot check %s: fsck.%s not found"), + fs_get_device(fs), type); + return 1; +@@ -1557,7 +1568,6 @@ int main(int argc, char *argv[]) + fs = add_dummy_fs(devices[i]); + else if (fs_ignored_type(fs)) + continue; +- + if (ignore_mounted && is_mounted(fs)) + continue; + status |= fsck_device(fs, interactive); diff --git a/SOURCES/2.25-hwclock-hang.patch b/SOURCES/2.25-hwclock-hang.patch new file mode 100644 index 0000000..de7df17 --- /dev/null +++ b/SOURCES/2.25-hwclock-hang.patch @@ -0,0 +1,255 @@ +From 4a44a54b3caf77923f0e3f1d5bdf5eda6ef07f62 Mon Sep 17 00:00:00 2001 +From: Chris MacGregor +Date: Thu, 27 Feb 2014 10:40:59 -0800 +Subject: [PATCH] hwclock: fix possible hang and other + set_hardware_clock_exact() issues + +In sys-utils/hwclock.c, set_hardware_clock_exact() has some problems when the +process gets pre-empted (for more than 100ms) before reaching the time for +which it waits: + +1. The "continue" statement causes execution to skip the final tdiff +assignment at the end of the do...while loop, leading to the while condition +using the wrong value of tdiff, and thus always exiting the loop once +newhwtime != sethwtime (e.g., after 1 second). This masks bug # 2, below. + +2. The previously-existing bug is that because it starts over waiting for the +desired time whenever two successive calls to gettimeofday() return values > +100ms apart, the loop will never terminate unless the process holds the CPU +(without losing it for more than 100ms) for at least 500ms. This can happen +on a heavily loaded machine or on a virtual machine (or on a heavily loaded +virtual machine). This has been observed to occur, preventing a machine from +completing the shutdown or reboot process due to a "hwclock --systohc" call in +a shutdown script. + +The new implementation presented in this patch takes a somewhat different +approach, intended to accomplish the same goals: + +It computes the desired target system time (at which the requested hardware +clock time will be applied to the hardware clock), and waits for that time to +arrive. If it misses the time (such as due to being pre-empted for too long), +it recalculates the target time, and increases the tolerance (how late it can +be relative to the target time, and still be "close enough". Thus, if all is +well, the time will be set *very* precisely. On a machine where the hwclock +process is repeatedly pre-empted, it will set the time as precisely as is +possible under the conditions present on that particular machine. In any +case, it will always terminate eventually (and pretty quickly); it will never +hang forever. + +[kzak@redhat.com: - tiny coding style changes] + +Signed-off-by: Chris MacGregor +Signed-off-by: Karel Zak +--- + sys-utils/hwclock.c | 170 ++++++++++++++++++++++++++++++++++++++++------------ + 1 file changed, 131 insertions(+), 39 deletions(-) + +diff --git a/sys-utils/hwclock.c b/sys-utils/hwclock.c +index 30660d4..395b5c3 100644 +--- a/sys-utils/hwclock.c ++++ b/sys-utils/hwclock.c +@@ -125,7 +125,7 @@ struct adjtime { + * We are running in debug mode, wherein we put a lot of information about + * what we're doing to standard output. + */ +-bool debug; ++int debug; + + /* Workaround for Award 4.50g BIOS bug: keep the year in a file. */ + bool badyear; +@@ -526,43 +526,141 @@ set_hardware_clock_exact(const time_t sethwtime, + const struct timeval refsystime, + const bool universal, const bool testing) + { +- time_t newhwtime = sethwtime; +- struct timeval beginsystime, nowsystime; +- double tdiff; +- int time_resync = 1; +- + /* +- * Now delay some more until Hardware Clock time newhwtime arrives. +- * The 0.5 s is because the Hardware Clock always sets to your set +- * time plus 500 ms (because it is designed to update to the next +- * second precisely 500 ms after you finish the setting). ++ * The Hardware Clock can only be set to any integer time plus one ++ * half second. The integer time is required because there is no ++ * interface to set or get a fractional second. The additional half ++ * second is because the Hardware Clock updates to the following ++ * second precisely 500 ms (not 1 second!) after you release the ++ * divider reset (after setting the new time) - see description of ++ * DV2, DV1, DV0 in Register A in the MC146818A data sheet (and note ++ * that although that document doesn't say so, real-world code seems ++ * to expect that the SET bit in Register B functions the same way). ++ * That means that, e.g., when you set the clock to 1:02:03, it ++ * effectively really sets it to 1:02:03.5, because it will update to ++ * 1:02:04 only half a second later. Our caller passes the desired ++ * integer Hardware Clock time in sethwtime, and the corresponding ++ * system time (which may have a fractional part, and which may or may ++ * not be the same!) in refsystime. In an ideal situation, we would ++ * then apply sethwtime to the Hardware Clock at refsystime+500ms, so ++ * that when the Hardware Clock ticks forward to sethwtime+1s half a ++ * second later at refsystime+1000ms, everything is in sync. So we ++ * spin, waiting for gettimeofday() to return a time at or after that ++ * time (refsystime+500ms) up to a tolerance value, initially 1ms. If ++ * we miss that time due to being preempted for some other process, ++ * then we increase the margin a little bit (initially 1ms, doubling ++ * each time), add 1 second (or more, if needed to get a time that is ++ * in the future) to both the time for which we are waiting and the ++ * time that we will apply to the Hardware Clock, and start waiting ++ * again. ++ * ++ * For example, the caller requests that we set the Hardware Clock to ++ * 1:02:03, with reference time (current system time) = 6:07:08.250. ++ * We want the Hardware Clock to update to 1:02:04 at 6:07:09.250 on ++ * the system clock, and the first such update will occur 0.500 ++ * seconds after we write to the Hardware Clock, so we spin until the ++ * system clock reads 6:07:08.750. If we get there, great, but let's ++ * imagine the system is so heavily loaded that our process is ++ * preempted and by the time we get to run again, the system clock ++ * reads 6:07:11.990. We now want to wait until the next xx:xx:xx.750 ++ * time, which is 6:07:12.750 (4.5 seconds after the reference time), ++ * at which point we will set the Hardware Clock to 1:02:07 (4 seconds ++ * after the originally requested time). If we do that successfully, ++ * then at 6:07:13.250 (5 seconds after the reference time), the ++ * Hardware Clock will update to 1:02:08 (5 seconds after the ++ * originally requested time), and all is well thereafter. + */ +- do { +- if (time_resync) { +- gettimeofday(&beginsystime, NULL); +- tdiff = time_diff(beginsystime, refsystime); +- newhwtime = sethwtime + (int)(tdiff + 0.5); +- if (debug) +- printf(_ +- ("Time elapsed since reference time has been %.6f seconds.\n" +- "Delaying further to reach the new time.\n"), +- tdiff); +- time_resync = 0; ++ ++ time_t newhwtime = sethwtime; ++ double target_time_tolerance_secs = 0.001; /* initial value */ ++ double tolerance_incr_secs = 0.001; /* initial value */ ++ const double RTC_SET_DELAY_SECS = 0.5; /* 500 ms */ ++ const struct timeval RTC_SET_DELAY_TV = { 0, RTC_SET_DELAY_SECS * 1E6 }; ++ ++ struct timeval targetsystime; ++ struct timeval nowsystime; ++ struct timeval prevsystime = refsystime; ++ double deltavstarget; ++ ++ timeradd(&refsystime, &RTC_SET_DELAY_TV, &targetsystime); ++ ++ while (1) { ++ double ticksize; ++ ++ /* FOR TESTING ONLY: inject random delays of up to 1000ms */ ++ if (debug >= 10) { ++ int usec = random() % 1000000; ++ printf(_("sleeping ~%d usec\n"), usec); ++ usleep(usec); + } + + gettimeofday(&nowsystime, NULL); +- tdiff = time_diff(nowsystime, beginsystime); +- if (tdiff < 0) { +- time_resync = 1; /* probably backward time reset */ +- continue; +- } +- if (tdiff > 0.1) { +- time_resync = 1; /* probably forward time reset */ +- continue; ++ deltavstarget = time_diff(nowsystime, targetsystime); ++ ticksize = time_diff(nowsystime, prevsystime); ++ prevsystime = nowsystime; ++ ++ if (ticksize < 0) { ++ if (debug) ++ printf(_("time jumped backward %.6f seconds " ++ "to %ld.%06d - retargeting\n"), ++ ticksize, (long)nowsystime.tv_sec, ++ (int)nowsystime.tv_usec); ++ /* The retarget is handled at the end of the loop. */ ++ } else if (deltavstarget < 0) { ++ /* deltavstarget < 0 if current time < target time */ ++ if (debug >= 2) ++ printf(_("%ld.%06d < %ld.%06d (%.6f)\n"), ++ (long)nowsystime.tv_sec, ++ (int)nowsystime.tv_usec, ++ (long)targetsystime.tv_sec, ++ (int)targetsystime.tv_usec, ++ deltavstarget); ++ continue; /* not there yet - keep spinning */ ++ } else if (deltavstarget <= target_time_tolerance_secs) { ++ /* Close enough to the target time; done waiting. */ ++ break; ++ } else /* (deltavstarget > target_time_tolerance_secs) */ { ++ /* ++ * We missed our window. Increase the tolerance and ++ * aim for the next opportunity. ++ */ ++ if (debug) ++ printf(_("missed it - %ld.%06d is too far " ++ "past %ld.%06d (%.6f > %.6f)\n"), ++ (long)nowsystime.tv_sec, ++ (int)nowsystime.tv_usec, ++ (long)targetsystime.tv_sec, ++ (int)targetsystime.tv_usec, ++ deltavstarget, ++ target_time_tolerance_secs); ++ target_time_tolerance_secs += tolerance_incr_secs; ++ tolerance_incr_secs *= 2; + } +- beginsystime = nowsystime; +- tdiff = time_diff(nowsystime, refsystime); +- } while (newhwtime == sethwtime + (int)(tdiff + 0.5)); ++ ++ /* ++ * Aim for the same offset (tv_usec) within the second in ++ * either the current second (if that offset hasn't arrived ++ * yet), or the next second. ++ */ ++ if (nowsystime.tv_usec < targetsystime.tv_usec) ++ targetsystime.tv_sec = nowsystime.tv_sec; ++ else ++ targetsystime.tv_sec = nowsystime.tv_sec + 1; ++ } ++ ++ newhwtime = sethwtime ++ + (int)(time_diff(nowsystime, refsystime) ++ - RTC_SET_DELAY_SECS /* don't count this */ ++ + 0.5 /* for rounding */); ++ if (debug) ++ printf(_("%ld.%06d is close enough to %ld.%06d (%.6f < %.6f)\n" ++ "Set RTC to %ld (%ld + %d; refsystime = %ld.%06d)\n"), ++ (long)nowsystime.tv_sec, (int)nowsystime.tv_usec, ++ (long)targetsystime.tv_sec, (int)targetsystime.tv_usec, ++ deltavstarget, target_time_tolerance_secs, ++ (long)newhwtime, (long)sethwtime, ++ (int)(newhwtime - sethwtime), ++ (long)refsystime.tv_sec, (int)refsystime.tv_usec); + + set_hardware_clock(newhwtime, universal, testing); + } +@@ -1636,7 +1734,7 @@ int main(int argc, char **argv) + + switch (c) { + case 'D': +- debug = TRUE; ++ ++debug; + break; + case 'a': + adjust = TRUE; +@@ -1953,10 +2051,4 @@ void __attribute__((__noreturn__)) hwaudit_exit(int status) + * + * hwclock uses this method, and considers the Hardware Clock to have + * infinite precision. +- * +- * TODO: Enhancements needed: +- * +- * - When waiting for whole second boundary in set_hardware_clock_exact, +- * fail if we miss the goal by more than .1 second, as could happen if we +- * get pre-empted (by the kernel dispatcher). + */ +-- +1.9.3 + diff --git a/SOURCES/2.25-lib-add-path_strdup.patch b/SOURCES/2.25-lib-add-path_strdup.patch new file mode 100644 index 0000000..e3a9cc3 --- /dev/null +++ b/SOURCES/2.25-lib-add-path_strdup.patch @@ -0,0 +1,51 @@ +From dd3bc51a539ffdd5c6c6b7d0b20acd1f61bdd337 Mon Sep 17 00:00:00 2001 +From: Karel Zak +Date: Mon, 6 Jan 2014 16:48:13 +0100 +Subject: [PATCH] lib/path: add path_strdup() + +Signed-off-by: Karel Zak +--- + include/path.h | 2 ++ + lib/path.c | 13 +++++++++++++ + 2 files changed, 15 insertions(+) + +diff --git a/include/path.h b/include/path.h +index 615d284..45da692 100644 +--- a/include/path.h ++++ b/include/path.h +@@ -4,6 +4,8 @@ + #include + #include + ++extern char *path_strdup(const char *path, ...) ++ __attribute__ ((__format__ (__printf__, 1, 2))); + extern FILE *path_fopen(const char *mode, int exit_on_err, const char *path, ...) + __attribute__ ((__format__ (__printf__, 3, 4))); + extern void path_read_str(char *result, size_t len, const char *path, ...) +diff --git a/lib/path.c b/lib/path.c +index 1f7e258..42d321c 100644 +--- a/lib/path.c ++++ b/lib/path.c +@@ -49,6 +49,19 @@ path_vcreate(const char *path, va_list ap) + return pathbuf; + } + ++char * ++path_strdup(const char *path, ...) ++{ ++ const char *p; ++ va_list ap; ++ ++ va_start(ap, path); ++ p = path_vcreate(path, ap); ++ va_end(ap); ++ ++ return p ? strdup(p) : NULL; ++} ++ + static FILE * + path_vfopen(const char *mode, int exit_on_error, const char *path, va_list ap) + { +-- +1.8.4.2 + diff --git a/SOURCES/2.25-libblkid-Identify-extN-file-system-properly.patch b/SOURCES/2.25-libblkid-Identify-extN-file-system-properly.patch new file mode 100644 index 0000000..da4bcb3 --- /dev/null +++ b/SOURCES/2.25-libblkid-Identify-extN-file-system-properly.patch @@ -0,0 +1,240 @@ +diff -up util-linux-2.23.2/libblkid/src/superblocks/ext.c.kzak util-linux-2.23.2/libblkid/src/superblocks/ext.c +--- util-linux-2.23.2/libblkid/src/superblocks/ext.c.kzak 2013-06-13 09:46:10.422650639 +0200 ++++ util-linux-2.23.2/libblkid/src/superblocks/ext.c 2014-01-23 10:28:51.175358545 +0100 +@@ -18,7 +18,6 @@ + #endif + #include + +-#include "linux_version.h" + #include "superblocks.h" + + struct ext2_super_block { +@@ -132,140 +131,11 @@ struct ext2_super_block { + #define EXT3_FEATURE_RO_COMPAT_UNSUPPORTED ~EXT3_FEATURE_RO_COMPAT_SUPP + + /* +- * Check to see if a filesystem is in /proc/filesystems. +- * Returns 1 if found, 0 if not +- */ +-static int fs_proc_check(const char *fs_name) +-{ +- FILE *f; +- char buf[80], *cp, *t; +- +- f = fopen("/proc/filesystems", "r" UL_CLOEXECSTR); +- if (!f) +- return 0; +- while (!feof(f)) { +- if (!fgets(buf, sizeof(buf), f)) +- break; +- cp = buf; +- if (!isspace(*cp)) { +- while (*cp && !isspace(*cp)) +- cp++; +- } +- while (*cp && isspace(*cp)) +- cp++; +- if ((t = strchr(cp, '\n')) != NULL) +- *t = 0; +- if ((t = strchr(cp, '\t')) != NULL) +- *t = 0; +- if ((t = strchr(cp, ' ')) != NULL) +- *t = 0; +- if (!strcmp(fs_name, cp)) { +- fclose(f); +- return 1; +- } +- } +- fclose(f); +- return (0); +-} +- +-/* +- * Check to see if a filesystem is available as a module +- * Returns 1 if found, 0 if not +- */ +-static int check_for_modules(const char *fs_name) +-{ +-#ifdef __linux__ +- struct utsname uts; +- FILE *f; +- char buf[1024], *cp; +- int namesz; +- +- if (uname(&uts)) +- return 0; +- snprintf(buf, sizeof(buf), "/lib/modules/%s/modules.dep", uts.release); +- +- f = fopen(buf, "r" UL_CLOEXECSTR); +- if (!f) +- return 0; +- +- namesz = strlen(fs_name); +- +- while (!feof(f)) { +- if (!fgets(buf, sizeof(buf), f)) +- break; +- if ((cp = strchr(buf, ':')) != NULL) +- *cp = 0; +- else +- continue; +- if ((cp = strrchr(buf, '/')) == NULL) +- continue; +- cp++; +- +- if (!strncmp(cp, fs_name, namesz) && +- (!strcmp(cp + namesz, ".ko") || +- !strcmp(cp + namesz, ".ko.gz"))) { +- fclose(f); +- return 1; +- } +- } +- fclose(f); +-#endif /* __linux__ */ +- return 0; +-} +- +-/* + * Starting in 2.6.29, ext4 can be used to support filesystems + * without a journal. + */ + #define EXT4_SUPPORTS_EXT2 KERNEL_VERSION(2, 6, 29) + +-static int system_supports_ext2(void) +-{ +- static time_t last_check = 0; +- static int ret = -1; +- time_t now = time(0); +- +- if (ret != -1 || (now - last_check) < 5) +- return ret; +- last_check = now; +- ret = (fs_proc_check("ext2") || check_for_modules("ext2")); +- return ret; +-} +- +-static int system_supports_ext4(void) +-{ +- static time_t last_check = 0; +- static int ret = -1; +- time_t now = time(0); +- +- if (ret != -1 || (now - last_check) < 5) +- return ret; +- last_check = now; +- ret = (fs_proc_check("ext4") || check_for_modules("ext4")); +- return ret; +-} +- +-static int system_supports_ext4dev(void) +-{ +- static time_t last_check = 0; +- static int ret = -1; +- time_t now = time(0); +- +- if (ret != -1 || (now - last_check) < 5) +- return ret; +- last_check = now; +- ret = (fs_proc_check("ext4dev") || check_for_modules("ext4dev")); +- return ret; +-} +- +-static int system_supports_ext4_ext2(void) +-{ +-#ifdef __linux__ +- return get_linux_version() >= EXT4_SUPPORTS_EXT2; +-#else +- return 0; +-#endif +-} + /* + * reads superblock and returns: + * fc = feature_compat +@@ -355,15 +225,6 @@ static int probe_ext2(blkid_probe pr, + (fi & EXT2_FEATURE_INCOMPAT_UNSUPPORTED)) + return -BLKID_ERR_PARAM; + +- /* +- * If ext2 is not present, but ext4 or ext4dev are, then +- * disclaim we are ext2 +- */ +- if (!system_supports_ext2() && +- (system_supports_ext4() || system_supports_ext4dev()) && +- system_supports_ext4_ext2()) +- return -BLKID_ERR_PARAM; +- + ext_get_info(pr, 2, es); + return 0; + } +@@ -406,34 +267,9 @@ static int probe_ext4dev(blkid_probe pr, + if (fi & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) + return -BLKID_ERR_PARAM; + +- /* +- * If the filesystem does not have a journal and ext2 and ext4 +- * is not present, then force this to be detected as an +- * ext4dev filesystem. +- */ +- if (!(fc & EXT3_FEATURE_COMPAT_HAS_JOURNAL) && +- !system_supports_ext2() && !system_supports_ext4() && +- system_supports_ext4dev() && +- system_supports_ext4_ext2()) +- goto force_ext4dev; +- +- /* +- * If the filesystem is marked as OK for use by in-development +- * filesystem code, but ext4dev is not supported, and ext4 is, +- * then don't call ourselves ext4dev, since we should be +- * detected as ext4 in that case. +- * +- * If the filesystem is marked as in use by production +- * filesystem, then it can only be used by ext4 and NOT by +- * ext4dev, so always disclaim we are ext4dev in that case. +- */ +- if (le32_to_cpu(es->s_flags) & EXT2_FLAGS_TEST_FILESYS) { +- if (!system_supports_ext4dev() && system_supports_ext4()) +- return -BLKID_ERR_PARAM; +- } else ++ if (!(le32_to_cpu(es->s_flags) & EXT2_FLAGS_TEST_FILESYS)) + return -BLKID_ERR_PARAM; + +-force_ext4dev: + ext_get_info(pr, 4, es); + return 0; + } +@@ -452,22 +288,11 @@ static int probe_ext4(blkid_probe pr, + if (fi & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) + return -BLKID_ERR_PARAM; + +- /* +- * If the filesystem does not have a journal and ext2 is not +- * present, then force this to be detected as an ext2 +- * filesystem. +- */ +- if (!(fc & EXT3_FEATURE_COMPAT_HAS_JOURNAL) && +- !system_supports_ext2() && system_supports_ext4() && +- system_supports_ext4_ext2()) +- goto force_ext4; +- + /* Ext4 has at least one feature which ext3 doesn't understand */ + if (!(frc & EXT3_FEATURE_RO_COMPAT_UNSUPPORTED) && + !(fi & EXT3_FEATURE_INCOMPAT_UNSUPPORTED)) + return -BLKID_ERR_PARAM; + +-force_ext4: + /* + * If the filesystem is a OK for use by in-development + * filesystem code, and ext4dev is supported or ext4 is not +@@ -478,10 +303,8 @@ force_ext4: + * filesystem, then it can only be used by ext4 and NOT by + * ext4dev. + */ +- if (le32_to_cpu(es->s_flags) & EXT2_FLAGS_TEST_FILESYS) { +- if (system_supports_ext4dev() || !system_supports_ext4()) +- return -BLKID_ERR_PARAM; +- } ++ if (le32_to_cpu(es->s_flags) & EXT2_FLAGS_TEST_FILESYS) ++ return -BLKID_ERR_PARAM; + + ext_get_info(pr, 4, es); + return 0; diff --git a/SOURCES/2.25-libblkid-detect-alone-PMBR.patch b/SOURCES/2.25-libblkid-detect-alone-PMBR.patch new file mode 100644 index 0000000..fe06167 --- /dev/null +++ b/SOURCES/2.25-libblkid-detect-alone-PMBR.patch @@ -0,0 +1,100 @@ +diff -up util-linux-2.23.2/libblkid/src/partitions/gpt.c.kzak util-linux-2.23.2/libblkid/src/partitions/gpt.c +--- util-linux-2.23.2/libblkid/src/partitions/gpt.c.kzak 2013-07-30 10:39:26.206738239 +0200 ++++ util-linux-2.23.2/libblkid/src/partitions/gpt.c 2014-01-23 11:06:17.364011293 +0100 +@@ -156,13 +156,15 @@ static int last_lba(blkid_probe pr, uint + * Note that the PMBR detection is optional (enabled by default) and could be + * disabled by BLKID_PARTS_FOPCE_GPT flag (see also blkid_paertitions_set_flags()). + */ +-static int is_pmbr_valid(blkid_probe pr) ++static int is_pmbr_valid(blkid_probe pr, int *has) + { + int flags = blkid_partitions_get_flags(pr); + unsigned char *data; + struct dos_partition *p; + int i; + ++ if (has) ++ *has = 0; + if (flags & BLKID_PARTS_FORCE_GPT) + goto ok; /* skip PMBR check */ + +@@ -182,6 +184,8 @@ static int is_pmbr_valid(blkid_probe pr) + failed: + return 0; + ok: ++ if (has) ++ *has = 1; + return 1; + } + +@@ -305,7 +309,7 @@ static int probe_gpt_pt(blkid_probe pr, + if (last_lba(pr, &lastlba)) + goto nothing; + +- if (!is_pmbr_valid(pr)) ++ if (!is_pmbr_valid(pr, NULL)) + goto nothing; + + h = get_gpt_header(pr, &hdr, &e, (lba = GPT_PRIMARY_LBA), lastlba); +@@ -410,3 +414,39 @@ const struct blkid_idinfo gpt_pt_idinfo + .magics = BLKID_NONE_MAGIC + }; + ++ ++ ++/* probe for *alone* protective MBR */ ++static int probe_pmbr_pt(blkid_probe pr, ++ const struct blkid_idmag *mag __attribute__((__unused__))) ++{ ++ int has = 0; ++ struct gpt_entry *e; ++ uint64_t lastlba = 0; ++ struct gpt_header hdr; ++ ++ if (last_lba(pr, &lastlba)) ++ goto nothing; ++ ++ is_pmbr_valid(pr, &has); ++ if (!has) ++ goto nothing; ++ ++ if (!get_gpt_header(pr, &hdr, &e, GPT_PRIMARY_LBA, lastlba) && ++ !get_gpt_header(pr, &hdr, &e, lastlba, lastlba)) ++ return 0; ++nothing: ++ return 1; ++} ++ ++const struct blkid_idinfo pmbr_pt_idinfo = ++{ ++ .name = "PMBR", ++ .probefunc = probe_pmbr_pt, ++ .magics = ++ { ++ { .magic = "\x55\xAA", .len = 2, .sboff = 510 }, ++ { NULL } ++ } ++}; ++ +diff -up util-linux-2.23.2/libblkid/src/partitions/partitions.c.kzak util-linux-2.23.2/libblkid/src/partitions/partitions.c +--- util-linux-2.23.2/libblkid/src/partitions/partitions.c.kzak 2013-07-30 10:39:26.207738249 +0200 ++++ util-linux-2.23.2/libblkid/src/partitions/partitions.c 2014-01-23 11:06:17.364011293 +0100 +@@ -125,6 +125,7 @@ static const struct blkid_idinfo *idinfo + &sun_pt_idinfo, + &dos_pt_idinfo, + &gpt_pt_idinfo, ++ &pmbr_pt_idinfo, /* always after GPT */ + &mac_pt_idinfo, + &ultrix_pt_idinfo, + &bsd_pt_idinfo, +diff -up util-linux-2.23.2/libblkid/src/partitions/partitions.h.kzak util-linux-2.23.2/libblkid/src/partitions/partitions.h +--- util-linux-2.23.2/libblkid/src/partitions/partitions.h.kzak 2013-07-30 10:39:26.208738259 +0200 ++++ util-linux-2.23.2/libblkid/src/partitions/partitions.h 2014-01-23 11:06:17.364011293 +0100 +@@ -59,6 +59,7 @@ extern const struct blkid_idinfo mac_pt_ + extern const struct blkid_idinfo dos_pt_idinfo; + extern const struct blkid_idinfo minix_pt_idinfo; + extern const struct blkid_idinfo gpt_pt_idinfo; ++extern const struct blkid_idinfo pmbr_pt_idinfo; + extern const struct blkid_idinfo ultrix_pt_idinfo; + + #endif /* BLKID_PARTITIONS_H */ diff --git a/SOURCES/2.25-libblkid-gpt-512.patch b/SOURCES/2.25-libblkid-gpt-512.patch new file mode 100644 index 0000000..3e711ce --- /dev/null +++ b/SOURCES/2.25-libblkid-gpt-512.patch @@ -0,0 +1,22 @@ +diff -up util-linux-2.23.2/libblkid/src/partitions/gpt.c.kzak util-linux-2.23.2/libblkid/src/partitions/gpt.c +--- util-linux-2.23.2/libblkid/src/partitions/gpt.c.kzak 2014-09-25 10:36:26.761377688 +0200 ++++ util-linux-2.23.2/libblkid/src/partitions/gpt.c 2014-09-25 10:36:56.912665364 +0200 +@@ -332,7 +332,7 @@ static int probe_gpt_pt(blkid_probe pr, + + blkid_probe_use_wiper(pr, lba * blkid_probe_get_size(pr), 8); + +- if (blkid_probe_set_magic(pr, lba << 9, ++ if (blkid_probe_set_magic(pr, blkid_probe_get_sectorsize(pr) * lba, + sizeof(GPT_HEADER_SIGNATURE_STR) - 1, + (unsigned char *) GPT_HEADER_SIGNATURE_STR)) + goto err; +@@ -345,7 +345,8 @@ static int probe_gpt_pt(blkid_probe pr, + if (!ls) + goto err; + +- tab = blkid_partlist_new_parttable(ls, "gpt", lba << 9); ++ tab = blkid_partlist_new_parttable(ls, "gpt", ++ blkid_probe_get_sectorsize(pr) * lba); + if (!tab) + goto err; + diff --git a/SOURCES/2.25-libblkid-io-errors.patch b/SOURCES/2.25-libblkid-io-errors.patch new file mode 100644 index 0000000..4392cf5 --- /dev/null +++ b/SOURCES/2.25-libblkid-io-errors.patch @@ -0,0 +1,2590 @@ +diff -up util-linux-2.23.2/libblkid/src/blkidP.h.kzak util-linux-2.23.2/libblkid/src/blkidP.h +--- util-linux-2.23.2/libblkid/src/blkidP.h.kzak 2014-03-28 15:11:18.334283704 +0100 ++++ util-linux-2.23.2/libblkid/src/blkidP.h 2014-03-28 15:11:44.676551975 +0100 +@@ -297,6 +297,9 @@ struct blkid_struct_cache + /* old systems */ + #define BLKID_CACHE_FILE_OLD "/etc/blkid.tab" + ++#define BLKID_PROBE_OK 0 ++#define BLKID_PROBE_NONE 1 ++ + #define BLKID_ERR_IO 5 + #define BLKID_ERR_PROC 9 + #define BLKID_ERR_MEM 12 +diff -up util-linux-2.23.2/libblkid/src/partitions/aix.c.kzak util-linux-2.23.2/libblkid/src/partitions/aix.c +--- util-linux-2.23.2/libblkid/src/partitions/aix.c.kzak 2013-05-30 15:21:43.120591308 +0200 ++++ util-linux-2.23.2/libblkid/src/partitions/aix.c 2014-03-28 15:11:44.676551975 +0100 +@@ -22,19 +22,17 @@ static int probe_aix_pt(blkid_probe pr, + + if (blkid_partitions_need_typeonly(pr)) + /* caller does not ask for details about partitions */ +- return 0; ++ return BLKID_PROBE_OK; + + ls = blkid_probe_get_partlist(pr); + if (!ls) +- goto err; ++ return BLKID_PROBE_NONE; + + tab = blkid_partlist_new_parttable(ls, "aix", 0); + if (!tab) +- goto err; ++ return -ENOMEM; + +- return 0; +-err: +- return -1; ++ return BLKID_PROBE_OK; + } + + /* +diff -up util-linux-2.23.2/libblkid/src/partitions/bsd.c.kzak util-linux-2.23.2/libblkid/src/partitions/bsd.c +--- util-linux-2.23.2/libblkid/src/partitions/bsd.c.kzak 2013-07-15 10:25:46.283049056 +0200 ++++ util-linux-2.23.2/libblkid/src/partitions/bsd.c 2014-03-28 15:11:44.677551986 +0100 +@@ -113,20 +113,24 @@ static int probe_bsd_pt(blkid_probe pr, + blkid_partlist ls; + int i, nparts = BSD_MAXPARTITIONS; + unsigned char *data; ++ int rc = BLKID_PROBE_NONE; + + if (blkid_partitions_need_typeonly(pr)) + /* caller does not ask for details about partitions */ +- return 0; ++ return rc; + + data = blkid_probe_get_sector(pr, BLKID_MAG_SECTOR(mag)); +- if (!data) ++ if (!data) { ++ if (errno) ++ rc = -errno; + goto nothing; ++ } + + l = (struct bsd_disklabel *) data + BLKID_MAG_LASTOFFSET(mag); + + ls = blkid_probe_get_partlist(pr); + if (!ls) +- goto err; ++ goto nothing; + + /* try to determine the real type of BSD system according to + * (parental) primary partition */ +@@ -152,8 +156,10 @@ static int probe_bsd_pt(blkid_probe pr, + } + + tab = blkid_partlist_new_parttable(ls, name, BLKID_MAG_OFFSET(mag)); +- if (!tab) +- goto err; ++ if (!tab) { ++ rc = -ENOMEM; ++ goto nothing; ++ } + + if (le16_to_cpu(l->d_npartitions) < BSD_MAXPARTITIONS) + nparts = le16_to_cpu(l->d_npartitions); +@@ -189,18 +195,18 @@ static int probe_bsd_pt(blkid_probe pr, + } + + par = blkid_partlist_add_partition(ls, tab, start, size); +- if (!par) +- goto err; ++ if (!par) { ++ rc = -ENOMEM; ++ goto nothing; ++ } + + blkid_partition_set_type(par, p->p_fstype); + } + +- return 0; ++ return BLKID_PROBE_OK; + + nothing: +- return 1; +-err: +- return -1; ++ return rc; + } + + +diff -up util-linux-2.23.2/libblkid/src/partitions/dos.c.kzak util-linux-2.23.2/libblkid/src/partitions/dos.c +--- util-linux-2.23.2/libblkid/src/partitions/dos.c.kzak 2013-07-30 10:39:26.205738229 +0200 ++++ util-linux-2.23.2/libblkid/src/partitions/dos.c 2014-03-28 15:13:23.220555797 +0100 +@@ -53,10 +53,13 @@ static int parse_dos_extended(blkid_prob + uint32_t start, size; + + if (++ct_nodata > 100) +- return 0; ++ return BLKID_PROBE_OK; + data = blkid_probe_get_sector(pr, cur_start); +- if (!data) ++ if (!data) { ++ if (errno) ++ return -errno; + goto leave; /* malformed partition? */ ++ } + + if (!is_valid_mbr_signature(data)) + goto leave; +@@ -99,7 +102,7 @@ static int parse_dos_extended(blkid_prob + + par = blkid_partlist_add_partition(ls, tab, abs_start, size); + if (!par) +- goto err; ++ return -ENOMEM; + + blkid_partition_set_type(par, p->sys_type); + blkid_partition_set_flags(par, p->boot_ind); +@@ -123,9 +126,7 @@ static int parse_dos_extended(blkid_prob + cur_size = size; + } + leave: +- return 0; +-err: +- return -1; ++ return BLKID_PROBE_OK; + } + + static int probe_dos_pt(blkid_probe pr, +@@ -140,8 +141,11 @@ static int probe_dos_pt(blkid_probe pr, + uint32_t start, size, id; + + data = blkid_probe_get_sector(pr, 0); +- if (!data) ++ if (!data) { ++ if (errno) ++ return -errno; + goto nothing; ++ } + + /* ignore disks with AIX magic number -- for more details see aix.c */ + if (memcmp(data, BLKID_AIX_MAGIC_STRING, BLKID_AIX_MAGIC_STRLEN) == 0) +@@ -152,7 +156,7 @@ static int probe_dos_pt(blkid_probe pr, + * either the boot sector of a FAT filesystem or a DOS-type + * partition table. + */ +- if (blkid_probe_is_vfat(pr)) { ++ if (blkid_probe_is_vfat(pr) == 1) { + DBG(LOWPROBE, blkid_debug("probably FAT -- ignore")); + goto nothing; + } +@@ -189,6 +193,8 @@ static int probe_dos_pt(blkid_probe pr, + return 0; + + ls = blkid_probe_get_partlist(pr); ++ if (!ls) ++ goto nothing; + + /* sector size factor (the start and size are in the real sectors, but + * we need to convert all sizes to 512 logical sectors +@@ -198,7 +204,7 @@ static int probe_dos_pt(blkid_probe pr, + /* allocate a new partition table */ + tab = blkid_partlist_new_parttable(ls, "dos", BLKID_MSDOS_PT_OFFSET); + if (!tab) +- goto err; ++ return -ENOMEM; + + id = dos_parttable_id(data); + if (id) { +@@ -224,7 +230,7 @@ static int probe_dos_pt(blkid_probe pr, + } + par = blkid_partlist_add_partition(ls, tab, start, size); + if (!par) +- goto err; ++ return -ENOMEM; + + blkid_partition_set_type(par, p->sys_type); + blkid_partition_set_flags(par, p->boot_ind); +@@ -244,13 +250,14 @@ static int probe_dos_pt(blkid_probe pr, + continue; + if (is_extended(p) && + parse_dos_extended(pr, tab, start, size, ssf) == -1) +- goto err; ++ goto nothing; + } + + /* Parse subtypes (nested partitions) on large disks */ + if (!blkid_probe_is_tiny(pr)) { + for (p = p0, i = 0; i < 4; i++, p++) { + size_t n; ++ int rc; + + if (!dos_partition_size(p) || is_extended(p)) + continue; +@@ -259,20 +266,19 @@ static int probe_dos_pt(blkid_probe pr, + if (dos_nested[n].type != p->sys_type) + continue; + +- if (blkid_partitions_do_subprobe(pr, ++ rc = blkid_partitions_do_subprobe(pr, + blkid_partlist_get_partition(ls, i), +- dos_nested[n].id) == -1) +- goto err; ++ dos_nested[n].id); ++ if (rc < 0) ++ return rc; + break; + } + } + } +- return 0; ++ return BLKID_PROBE_OK; + + nothing: +- return 1; +-err: +- return -1; ++ return BLKID_PROBE_NONE; + } + + +diff -up util-linux-2.23.2/libblkid/src/partitions/gpt.c.kzak util-linux-2.23.2/libblkid/src/partitions/gpt.c +--- util-linux-2.23.2/libblkid/src/partitions/gpt.c.kzak 2014-03-28 15:11:18.336283724 +0100 ++++ util-linux-2.23.2/libblkid/src/partitions/gpt.c 2014-03-28 15:11:44.677551986 +0100 +@@ -169,8 +169,11 @@ static int is_pmbr_valid(blkid_probe pr, + goto ok; /* skip PMBR check */ + + data = blkid_probe_get_sector(pr, 0); +- if (!data) ++ if (!data) { ++ if (errno) ++ return -errno; + goto failed; ++ } + + if (!is_valid_mbr_signature(data)) + goto failed; +@@ -305,19 +308,27 @@ static int probe_gpt_pt(blkid_probe pr, + uint64_t fu, lu; + uint32_t ssf, i; + efi_guid_t guid; ++ int ret; + + if (last_lba(pr, &lastlba)) + goto nothing; + +- if (!is_pmbr_valid(pr, NULL)) ++ ret = is_pmbr_valid(pr, NULL); ++ if (ret < 0) ++ return ret; ++ else if (ret == 0) + goto nothing; + ++ errno = 0; + h = get_gpt_header(pr, &hdr, &e, (lba = GPT_PRIMARY_LBA), lastlba); +- if (!h) ++ if (!h && !errno) + h = get_gpt_header(pr, &hdr, &e, (lba = lastlba), lastlba); + +- if (!h) ++ if (!h) { ++ if (errno) ++ return -errno; + goto nothing; ++ } + + blkid_probe_use_wiper(pr, lba * blkid_probe_get_size(pr), 8); + +@@ -388,12 +399,13 @@ static int probe_gpt_pt(blkid_probe pr, + blkid_partition_set_flags(par, e->attributes); + } + +- return 0; ++ return BLKID_PROBE_OK; + + nothing: +- return 1; ++ return BLKID_PROBE_NONE; ++ + err: +- return -1; ++ return -ENOMEM; + } + + +diff -up util-linux-2.23.2/libblkid/src/partitions/mac.c.kzak util-linux-2.23.2/libblkid/src/partitions/mac.c +--- util-linux-2.23.2/libblkid/src/partitions/mac.c.kzak 2013-06-13 09:46:10.418650605 +0200 ++++ util-linux-2.23.2/libblkid/src/partitions/mac.c 2014-03-28 15:11:44.677551986 +0100 +@@ -87,8 +87,11 @@ static int probe_mac_pt(blkid_probe pr, + * the first block on the disk. + */ + md = (struct mac_driver_desc *) blkid_probe_get_sector(pr, 0); +- if (!md) ++ if (!md) { ++ if (errno) ++ return -errno; + goto nothing; ++ } + + block_size = be16_to_cpu(md->block_size); + +@@ -96,8 +99,11 @@ static int probe_mac_pt(blkid_probe pr, + * the second block on the disk. + */ + p = (struct mac_partition *) get_mac_block(pr, block_size, 1); +- if (!p) ++ if (!p) { ++ if (errno) ++ return -errno; + goto nothing; ++ } + + /* check the first partition signature */ + if (!has_part_signature(p)) +@@ -109,7 +115,7 @@ static int probe_mac_pt(blkid_probe pr, + + ls = blkid_probe_get_partlist(pr); + if (!ls) +- goto err; ++ goto nothing; + + tab = blkid_partlist_new_parttable(ls, "mac", 0); + if (!tab) +@@ -124,15 +130,18 @@ static int probe_mac_pt(blkid_probe pr, + uint32_t size; + + p = (struct mac_partition *) get_mac_block(pr, block_size, i); +- if (!p) ++ if (!p) { ++ if (errno) ++ return -errno; + goto nothing; ++ } + if (!has_part_signature(p)) + goto nothing; + + if (be32_to_cpu(p->map_count) != nblks) { + DBG(LOWPROBE, blkid_debug( + "mac: inconsisten map_count in partition map, " +- "entry[0]: %d, entry[%d]: %d", ++ "entry[0]: %d, entry[%d]: %d", + nblks, i - 1, + be32_to_cpu(p->map_count))); + } +@@ -157,12 +166,12 @@ static int probe_mac_pt(blkid_probe pr, + sizeof(p->type)); + } + +- return 0; ++ return BLKID_PROBE_OK; + + nothing: +- return 1; ++ return BLKID_PROBE_NONE; + err: +- return -1; ++ return -ENOMEM; + } + + /* +diff -up util-linux-2.23.2/libblkid/src/partitions/minix.c.kzak util-linux-2.23.2/libblkid/src/partitions/minix.c +--- util-linux-2.23.2/libblkid/src/partitions/minix.c.kzak 2013-07-15 10:25:46.284049064 +0200 ++++ util-linux-2.23.2/libblkid/src/partitions/minix.c 2014-03-28 15:36:23.866715100 +0100 +@@ -26,12 +26,15 @@ static int probe_minix_pt(blkid_probe pr + int i; + + data = blkid_probe_get_sector(pr, 0); +- if (!data) ++ if (!data) { ++ if (errno) ++ return -errno; + goto nothing; ++ } + + ls = blkid_probe_get_partlist(pr); + if (!ls) +- goto err; ++ goto nothing; + + /* Parent is required, because Minix uses the same PT as DOS and + * difference is only in primary partition (parent) type. +@@ -78,12 +81,12 @@ static int probe_minix_pt(blkid_probe pr + blkid_partition_set_flags(par, p->boot_ind); + } + +- return 0; ++ return BLKID_PROBE_OK; + + nothing: +- return 1; ++ return BLKID_PROBE_NONE; + err: +- return -1; ++ return -ENOMEM; + } + + /* same as DOS */ +diff -up util-linux-2.23.2/libblkid/src/partitions/partitions.c.kzak util-linux-2.23.2/libblkid/src/partitions/partitions.c +--- util-linux-2.23.2/libblkid/src/partitions/partitions.c.kzak 2014-03-28 15:11:18.336283724 +0100 ++++ util-linux-2.23.2/libblkid/src/partitions/partitions.c 2014-03-28 15:12:28.036993622 +0100 +@@ -533,12 +533,13 @@ static int idinfo_probe(blkid_probe pr, + { + const struct blkid_idmag *mag = NULL; + blkid_loff_t off; +- int rc = 1; /* = nothing detected */ ++ int rc = BLKID_PROBE_NONE; /* = nothing detected */ + + if (pr->size <= 0 || (id->minsz && id->minsz > pr->size)) + goto nothing; /* the device is too small */ + +- if (blkid_probe_get_idmag(pr, id, &off, &mag)) ++ rc = blkid_probe_get_idmag(pr, id, &off, &mag); ++ if (rc != BLKID_PROBE_OK) + goto nothing; + + /* final check by probing function */ +@@ -546,14 +547,15 @@ static int idinfo_probe(blkid_probe pr, + DBG(LOWPROBE, blkid_debug( + "%s: ---> call probefunc()", id->name)); + rc = id->probefunc(pr, mag); +- if (rc == -1) { ++ if (rc < 0) { + /* reset after error */ + reset_partlist(blkid_probe_get_partlist(pr)); + if (chn && !chn->binary) + blkid_probe_chain_reset_vals(pr, chn); +- DBG(LOWPROBE, blkid_debug("%s probefunc failed", id->name)); ++ DBG(LOWPROBE, blkid_debug("%s probefunc failed, rc %d", ++ id->name, rc)); + } +- if (rc == 0 && mag && chn && !chn->binary) ++ if (rc == BLKID_PROBE_OK && mag && chn && !chn->binary) + rc = blkid_probe_set_magic(pr, off, mag->len, + (unsigned char *) mag->magic); + +@@ -569,11 +571,11 @@ nothing: + */ + static int partitions_probe(blkid_probe pr, struct blkid_chain *chn) + { +- int rc = 1; ++ int rc = BLKID_PROBE_NONE; + size_t i; + + if (!pr || chn->idx < -1) +- return -1; ++ return -EINVAL; + blkid_probe_chain_reset_vals(pr, chn); + + if (chn->binary) +@@ -597,7 +599,10 @@ static int partitions_probe(blkid_probe + continue; + + /* apply checks from idinfo */ +- if (idinfo_probe(pr, idinfos[i], chn) != 0) ++ rc = idinfo_probe(pr, idinfos[i], chn); ++ if (rc < 0) ++ break; ++ if (rc != BLKID_PROBE_OK) + continue; + + name = idinfos[i]->name; +@@ -613,20 +618,21 @@ static int partitions_probe(blkid_probe + break; + } + +- if (rc == 1) { +- DBG(LOWPROBE, blkid_debug("<-- leaving probing loop (failed) [PARTS idx=%d]", +- chn->idx)); ++ if (rc != BLKID_PROBE_OK) { ++ DBG(LOWPROBE, blkid_debug("<-- leaving probing loop (failed=%d) [PARTS idx=%d]", ++ rc, chn->idx)); + } + + details_only: + /* + * Gather PART_ENTRY_* values if the current device is a partition. + */ +- if (!chn->binary && ++ if ((rc == BLKID_PROBE_OK || rc == BLKID_PROBE_NONE) && !chn->binary && + (blkid_partitions_get_flags(pr) & BLKID_PARTS_ENTRY_DETAILS)) { + +- if (!blkid_partitions_probe_partition(pr)) +- rc = 0; ++ int xrc = blkid_partitions_probe_partition(pr); ++ if (xrc < 0) ++ rc = xrc; /* optional, care about errors only */ + } + + return rc; +@@ -637,7 +643,7 @@ int blkid_partitions_do_subprobe(blkid_p + const struct blkid_idinfo *id) + { + blkid_probe prc; +- int rc = 1; ++ int rc; + blkid_partlist ls; + blkid_loff_t sz, off; + +@@ -646,7 +652,7 @@ int blkid_partitions_do_subprobe(blkid_p + id->name, parent)); + + if (!pr || !parent || !parent->size) +- return -1; ++ return -EINVAL; + + /* range defined by parent */ + sz = ((blkid_loff_t) parent->size) << 9; +@@ -656,13 +662,13 @@ int blkid_partitions_do_subprobe(blkid_p + DBG(LOWPROBE, blkid_debug( + "ERROR: parts: <---- '%s' subprobe: overflow detected.", + id->name)); +- return -1; ++ return -ENOSPC; + } + + /* create private prober */ + prc = blkid_clone_probe(pr); + if (!prc) +- return -1; ++ return -ENOMEM; + + blkid_probe_set_dimension(prc, off, sz); + +@@ -695,7 +701,7 @@ int blkid_partitions_do_subprobe(blkid_p + + static int blkid_partitions_probe_partition(blkid_probe pr) + { +- int rc = 1; ++ int rc = BLKID_PROBE_NONE; + blkid_probe disk_pr = NULL; + blkid_partlist ls; + blkid_partition par; +@@ -761,7 +767,7 @@ static int blkid_partitions_probe_partit + blkid_probe_sprintf_value(pr, "PART_ENTRY_DISK", "%u:%u", + major(disk), minor(disk)); + } +- rc = 0; ++ rc = BLKID_PROBE_OK; + nothing: + return rc; + } +diff -up util-linux-2.23.2/libblkid/src/partitions/sgi.c.kzak util-linux-2.23.2/libblkid/src/partitions/sgi.c +--- util-linux-2.23.2/libblkid/src/partitions/sgi.c.kzak 2013-07-15 10:25:46.285049072 +0200 ++++ util-linux-2.23.2/libblkid/src/partitions/sgi.c 2014-03-28 15:11:44.677551986 +0100 +@@ -99,8 +99,11 @@ static int probe_sgi_pt(blkid_probe pr, + int i; + + l = (struct sgi_disklabel *) blkid_probe_get_sector(pr, 0); +- if (!l) ++ if (!l) { ++ if (errno) ++ return -errno; + goto nothing; ++ } + + if (count_checksum(l)) { + DBG(LOWPROBE, blkid_debug( +@@ -110,11 +113,11 @@ static int probe_sgi_pt(blkid_probe pr, + + if (blkid_partitions_need_typeonly(pr)) + /* caller does not ask for details about partitions */ +- return 0; ++ return BLKID_PROBE_OK; + + ls = blkid_probe_get_partlist(pr); + if (!ls) +- goto err; ++ goto nothing; + + tab = blkid_partlist_new_parttable(ls, "sgi", 0); + if (!tab) +@@ -138,12 +141,12 @@ static int probe_sgi_pt(blkid_probe pr, + blkid_partition_set_type(par, type); + } + +- return 0; ++ return BLKID_PROBE_OK; + + nothing: +- return 1; ++ return BLKID_PROBE_NONE; + err: +- return -1; ++ return -ENOMEM; + } + + const struct blkid_idinfo sgi_pt_idinfo = +diff -up util-linux-2.23.2/libblkid/src/partitions/solaris_x86.c.kzak util-linux-2.23.2/libblkid/src/partitions/solaris_x86.c +--- util-linux-2.23.2/libblkid/src/partitions/solaris_x86.c.kzak 2013-06-13 09:46:10.418650605 +0200 ++++ util-linux-2.23.2/libblkid/src/partitions/solaris_x86.c 2014-03-28 15:11:44.677551986 +0100 +@@ -69,8 +69,11 @@ static int probe_solaris_pt(blkid_probe + uint16_t nparts; + + l = (struct solaris_vtoc *) blkid_probe_get_sector(pr, SOLARIS_SECTOR); +- if (!l) ++ if (!l) { ++ if (errno) ++ return -errno; + goto nothing; ++ } + + if (le32_to_cpu(l->v_version) != 1) { + DBG(LOWPROBE, blkid_debug( +@@ -81,11 +84,11 @@ static int probe_solaris_pt(blkid_probe + + if (blkid_partitions_need_typeonly(pr)) + /* caller does not ask for details about partitions */ +- return 0; ++ return BLKID_PROBE_OK; + + ls = blkid_probe_get_partlist(pr); + if (!ls) +- goto err; ++ goto nothing; + + parent = blkid_partlist_get_parent(ls); + +@@ -126,12 +129,12 @@ static int probe_solaris_pt(blkid_probe + blkid_partition_set_flags(par, le16_to_cpu(p->s_flag)); + } + +- return 0; ++ return BLKID_PROBE_OK; + + nothing: +- return 1; ++ return BLKID_PROBE_NONE; + err: +- return -1; ++ return -ENOMEM; + } + + const struct blkid_idinfo solaris_x86_pt_idinfo = +diff -up util-linux-2.23.2/libblkid/src/partitions/sun.c.kzak util-linux-2.23.2/libblkid/src/partitions/sun.c +--- util-linux-2.23.2/libblkid/src/partitions/sun.c.kzak 2013-06-13 09:46:10.419650613 +0200 ++++ util-linux-2.23.2/libblkid/src/partitions/sun.c 2014-03-28 15:11:44.678551996 +0100 +@@ -27,8 +27,11 @@ static int probe_sun_pt(blkid_probe pr, + int i, use_vtoc; + + l = (struct sun_disklabel *) blkid_probe_get_sector(pr, 0); +- if (!l) ++ if (!l) { ++ if (errno) ++ return -errno; + goto nothing; ++ } + + if (sun_pt_checksum(l)) { + DBG(LOWPROBE, blkid_debug( +@@ -38,11 +41,11 @@ static int probe_sun_pt(blkid_probe pr, + + if (blkid_partitions_need_typeonly(pr)) + /* caller does not ask for details about partitions */ +- return 0; ++ return BLKID_PROBE_OK; + + ls = blkid_probe_get_partlist(pr); + if (!ls) +- goto err; ++ goto nothing; + + tab = blkid_partlist_new_parttable(ls, "sun", 0); + if (!tab) +@@ -76,7 +79,7 @@ static int probe_sun_pt(blkid_probe pr, + uint16_t type = 0, flags = 0; + blkid_partition par; + +- start = be32_to_cpu(p->start_cylinder) * spc; ++ start = be32_to_cpu(p->start_cylinder) * spc; + size = be32_to_cpu(p->num_sectors); + if (use_vtoc) { + type = be16_to_cpu(l->vtoc.infos[i].id); +@@ -96,12 +99,12 @@ static int probe_sun_pt(blkid_probe pr, + if (flags) + blkid_partition_set_flags(par, flags); + } +- return 0; ++ return BLKID_PROBE_OK; + + nothing: +- return 1; ++ return BLKID_PROBE_NONE; + err: +- return -1; ++ return -ENOMEM; + } + + +diff -up util-linux-2.23.2/libblkid/src/partitions/ultrix.c.kzak util-linux-2.23.2/libblkid/src/partitions/ultrix.c +--- util-linux-2.23.2/libblkid/src/partitions/ultrix.c.kzak 2013-05-30 15:21:43.127591380 +0200 ++++ util-linux-2.23.2/libblkid/src/partitions/ultrix.c 2014-03-28 15:11:44.678551996 +0100 +@@ -44,8 +44,11 @@ static int probe_ultrix_pt(blkid_probe p + int i; + + data = blkid_probe_get_sector(pr, ULTRIX_SECTOR); +- if (!data) ++ if (!data) { ++ if (errno) ++ return -errno; + goto nothing; ++ } + + l = (struct ultrix_disklabel *) (data + ULTRIX_OFFSET); + +@@ -59,11 +62,11 @@ static int probe_ultrix_pt(blkid_probe p + + if (blkid_partitions_need_typeonly(pr)) + /* caller does not ask for details about partitions */ +- return 0; ++ return BLKID_PROBE_OK; + + ls = blkid_probe_get_partlist(pr); + if (!ls) +- goto err; ++ goto nothing; + + tab = blkid_partlist_new_parttable(ls, "ultrix", 0); + if (!tab) +@@ -80,11 +83,11 @@ static int probe_ultrix_pt(blkid_probe p + } + } + +- return 0; ++ return BLKID_PROBE_OK; + nothing: +- return 1; ++ return BLKID_PROBE_NONE; + err: +- return -1; ++ return -ENOMEM; + } + + const struct blkid_idinfo ultrix_pt_idinfo = +diff -up util-linux-2.23.2/libblkid/src/partitions/unixware.c.kzak util-linux-2.23.2/libblkid/src/partitions/unixware.c +--- util-linux-2.23.2/libblkid/src/partitions/unixware.c.kzak 2013-06-13 09:46:10.419650613 +0200 ++++ util-linux-2.23.2/libblkid/src/partitions/unixware.c 2014-03-28 15:11:44.678551996 +0100 +@@ -106,19 +106,22 @@ static int probe_unixware_pt(blkid_probe + + l = (struct unixware_disklabel *) + blkid_probe_get_sector(pr, UNIXWARE_SECTOR); +- if (!l) ++ if (!l) { ++ if (errno) ++ return -errno; + goto nothing; ++ } + + if (le32_to_cpu(l->vtoc.v_magic) != UNIXWARE_VTOCMAGIC) + goto nothing; + + if (blkid_partitions_need_typeonly(pr)) + /* caller does not ask for details about partitions */ +- return 0; ++ return BLKID_PROBE_OK; + + ls = blkid_probe_get_partlist(pr); + if (!ls) +- goto err; ++ goto nothing; + + parent = blkid_partlist_get_parent(ls); + +@@ -161,12 +164,12 @@ static int probe_unixware_pt(blkid_probe + blkid_partition_set_flags(par, flg); + } + +- return 0; ++ return BLKID_PROBE_OK; + + nothing: +- return 1; ++ return BLKID_PROBE_NONE; + err: +- return -1; ++ return -ENOMEM; + } + + +diff -up util-linux-2.23.2/libblkid/src/probe.c.kzak util-linux-2.23.2/libblkid/src/probe.c +--- util-linux-2.23.2/libblkid/src/probe.c.kzak 2014-03-28 15:11:18.334283704 +0100 ++++ util-linux-2.23.2/libblkid/src/probe.c 2014-03-28 15:11:44.678551996 +0100 +@@ -559,13 +559,17 @@ unsigned char *blkid_probe_get_buffer(bl + if (!bf) { + ssize_t ret; + +- if (blkid_llseek(pr->fd, pr->off + off, SEEK_SET) < 0) ++ if (blkid_llseek(pr->fd, pr->off + off, SEEK_SET) < 0) { ++ errno = 0; + return NULL; ++ } + + /* allocate info and space for data by why call */ + bf = calloc(1, sizeof(struct blkid_bufinfo) + len); +- if (!bf) ++ if (!bf) { ++ errno = ENOMEM; + return NULL; ++ } + + bf->data = ((unsigned char *) bf) + sizeof(struct blkid_bufinfo); + bf->len = len; +@@ -577,7 +581,10 @@ unsigned char *blkid_probe_get_buffer(bl + + ret = read(pr->fd, bf->data, len); + if (ret != (ssize_t) len) { ++ DBG(LOWPROBE, blkid_debug("\tbuffer read: return %zd error %m", ret)); + free(bf); ++ if (ret >= 0) ++ errno = 0; + return NULL; + } + list_add_tail(&bf->bufs, &pr->buffers); +@@ -766,6 +773,17 @@ int blkid_probe_set_dimension(blkid_prob + return 0; + } + ++/** ++ * blkid_probe_get_idmag: ++ * @pr: probe ++ * @id: id information ++ * @offset: begin of probing area ++ * @res: found id information ++ * ++ * Check for matching magic value. ++ * Returns BLKID_PROBE_OK if found, BLKID_PROBE_NONE if not found ++ * or no magic present, or negative value on error. ++ */ + int blkid_probe_get_idmag(blkid_probe pr, const struct blkid_idinfo *id, + blkid_loff_t *offset, const struct blkid_idmag **res) + { +@@ -784,6 +802,8 @@ int blkid_probe_get_idmag(blkid_probe pr + off = (mag->kboff + (mag->sboff >> 10)) << 10; + buf = blkid_probe_get_buffer(pr, off, 1024); + ++ if (!buf && errno) ++ return -errno; + if (buf && !memcmp(mag->magic, + buf + (mag->sboff & 0x3ff), mag->len)) { + DBG(LOWPROBE, blkid_debug("\tmagic sboff=%u, kboff=%ld", +@@ -792,16 +812,16 @@ int blkid_probe_get_idmag(blkid_probe pr + *offset = off + (mag->sboff & 0x3ff); + if (res) + *res = mag; +- return 0; ++ return BLKID_PROBE_OK; + } + mag++; + } + + if (id && id->magics[0].magic) + /* magic string(s) defined, but not found */ +- return 1; ++ return BLKID_PROBE_NONE; + +- return 0; ++ return BLKID_PROBE_OK; + } + + static inline void blkid_probe_start(blkid_probe pr) +diff -up util-linux-2.23.2/libblkid/src/superblocks/adaptec_raid.c.kzak util-linux-2.23.2/libblkid/src/superblocks/adaptec_raid.c +--- util-linux-2.23.2/libblkid/src/superblocks/adaptec_raid.c.kzak 2013-04-08 17:55:40.232855970 +0200 ++++ util-linux-2.23.2/libblkid/src/superblocks/adaptec_raid.c 2014-03-28 15:11:44.678551996 +0100 +@@ -80,10 +80,10 @@ static int probe_adraid(blkid_probe pr, + struct adaptec_metadata *ad; + + if (pr->size < 0x10000) +- return -1; ++ return BLKID_PROBE_NONE; + + if (!S_ISREG(pr->mode) && !blkid_probe_is_wholedisk(pr)) +- return -1; ++ return BLKID_PROBE_NONE; + + off = ((pr->size / 0x200)-1) * 0x200; + ad = (struct adaptec_metadata *) +@@ -91,17 +91,19 @@ static int probe_adraid(blkid_probe pr, + off, + sizeof(struct adaptec_metadata)); + if (!ad) +- return -1; ++ return errno ? -errno : BLKID_PROBE_NONE;; ++ + if (ad->smagic != be32_to_cpu(AD_SIGNATURE)) +- return -1; ++ return BLKID_PROBE_NONE; + if (ad->b0idcode != be32_to_cpu(AD_MAGIC)) +- return -1; ++ return BLKID_PROBE_NONE; + if (blkid_probe_sprintf_version(pr, "%u", ad->resver) != 0) +- return -1; ++ return BLKID_PROBE_NONE; + if (blkid_probe_set_magic(pr, off, sizeof(ad->b0idcode), + (unsigned char *) &ad->b0idcode)) +- return -1; +- return 0; ++ return BLKID_PROBE_NONE; ++ ++ return BLKID_PROBE_OK; + } + + const struct blkid_idinfo adraid_idinfo = { +diff -up util-linux-2.23.2/libblkid/src/superblocks/befs.c.kzak util-linux-2.23.2/libblkid/src/superblocks/befs.c +--- util-linux-2.23.2/libblkid/src/superblocks/befs.c.kzak 2013-04-08 17:55:40.237856017 +0200 ++++ util-linux-2.23.2/libblkid/src/superblocks/befs.c 2014-03-28 15:11:44.679552006 +0100 +@@ -261,21 +261,23 @@ static int64_t get_key_value(blkid_probe + int64_t node_pointer; + int32_t first, last, mid, cmp; + ++ errno = 0; + bh = (struct bplustree_header *) get_tree_node(pr, bs, &bi->data, 0, + sizeof(struct bplustree_header), fs_le); + if (!bh) +- return -1; ++ return errno ? -errno : -ENOENT; + + if ((int32_t) FS32_TO_CPU(bh->magic, fs_le) != BPLUSTREE_MAGIC) +- return -1; ++ return -ENOENT; + + node_pointer = FS64_TO_CPU(bh->root_node_pointer, fs_le); + + do { ++ errno = 0; + bn = (struct bplustree_node *) get_tree_node(pr, bs, &bi->data, + node_pointer, FS32_TO_CPU(bh->node_size, fs_le), fs_le); + if (!bn) +- return -1; ++ return errno ? -errno : -ENOENT; + + keylengths = (uint16_t *) ((uint8_t *) bn + + ((sizeof(struct bplustree_node) +@@ -336,10 +338,10 @@ static int get_uuid(blkid_probe pr, cons + + bi = (struct befs_inode *) get_block_run(pr, bs, &bs->root_dir, fs_le); + if (!bi) +- return -1; ++ return errno ? -errno : BLKID_PROBE_NONE; + + if (FS32_TO_CPU(bi->magic1, fs_le) != INODE_MAGIC1) +- return -1; ++ return BLKID_PROBE_NONE; + + sd = (struct small_data *) bi->small_data; + +@@ -376,24 +378,24 @@ static int get_uuid(blkid_probe pr, cons + bi = (struct befs_inode *) get_block_run(pr, bs, + &bi->attributes, fs_le); + if (!bi) +- return -1; ++ return errno ? -errno : BLKID_PROBE_NONE; + + if (FS32_TO_CPU(bi->magic1, fs_le) != INODE_MAGIC1) +- return -1; ++ return BLKID_PROBE_NONE; + + value = get_key_value(pr, bs, bi, KEY_NAME, fs_le); +- + if (value < 0) +- return value; ++ return value == -ENOENT ? BLKID_PROBE_NONE : value; ++ + else if (value > 0) { + bi = (struct befs_inode *) blkid_probe_get_buffer(pr, + value << FS32_TO_CPU(bs->block_shift, fs_le), + FS32_TO_CPU(bs->block_size, fs_le)); + if (!bi) +- return -1; ++ return errno ? -errno : BLKID_PROBE_NONE; + + if (FS32_TO_CPU(bi->magic1, fs_le) != INODE_MAGIC1) +- return -1; ++ return 1; + + if (FS32_TO_CPU(bi->type, fs_le) == B_UINT64_TYPE + && FS64_TO_CPU(bi->data.size, fs_le) == KEY_SIZE +@@ -404,7 +406,7 @@ static int get_uuid(blkid_probe pr, cons + attr_data = (uint64_t *) get_block_run(pr, bs, + &bi->data.direct[0], fs_le); + if (!attr_data) +- return -1; ++ return errno ? -errno : BLKID_PROBE_NONE; + + *uuid = *attr_data; + } +@@ -424,7 +426,7 @@ static int probe_befs(blkid_probe pr, co + mag->sboff - B_OS_NAME_LENGTH, + sizeof(struct befs_super_block)); + if (!bs) +- return -1; ++ return errno ? -errno : BLKID_PROBE_NONE; + + if (le32_to_cpu(bs->magic1) == SUPER_BLOCK_MAGIC1 + && le32_to_cpu(bs->magic2) == SUPER_BLOCK_MAGIC2 +@@ -439,11 +441,11 @@ static int probe_befs(blkid_probe pr, co + fs_le = 0; + version = "big-endian"; + } else +- return -1; ++ return BLKID_PROBE_NONE; + + ret = get_uuid(pr, bs, &volume_id, fs_le); + +- if (ret < 0) ++ if (ret != 0) + return ret; + + /* +@@ -459,7 +461,7 @@ static int probe_befs(blkid_probe pr, co + blkid_probe_sprintf_uuid(pr, (unsigned char *) &volume_id, + sizeof(volume_id), "%016" PRIx64, + FS64_TO_CPU(volume_id, fs_le)); +- return 0; ++ return BLKID_PROBE_OK; + } + + const struct blkid_idinfo befs_idinfo = +diff -up util-linux-2.23.2/libblkid/src/superblocks/btrfs.c.kzak util-linux-2.23.2/libblkid/src/superblocks/btrfs.c +--- util-linux-2.23.2/libblkid/src/superblocks/btrfs.c.kzak 2014-03-28 15:11:18.335283714 +0100 ++++ util-linux-2.23.2/libblkid/src/superblocks/btrfs.c 2014-03-28 15:11:44.679552006 +0100 +@@ -65,7 +65,7 @@ static int probe_btrfs(blkid_probe pr, c + + bfs = blkid_probe_get_sb(pr, mag, struct btrfs_super_block); + if (!bfs) +- return -1; ++ return errno ? -errno : 1; + + if (*bfs->label) + blkid_probe_set_label(pr, +diff -up util-linux-2.23.2/libblkid/src/superblocks/cramfs.c.kzak util-linux-2.23.2/libblkid/src/superblocks/cramfs.c +--- util-linux-2.23.2/libblkid/src/superblocks/cramfs.c.kzak 2013-04-08 17:55:40.240856046 +0200 ++++ util-linux-2.23.2/libblkid/src/superblocks/cramfs.c 2014-03-28 15:11:44.679552006 +0100 +@@ -40,7 +40,7 @@ static int probe_cramfs(blkid_probe pr, + + cs = blkid_probe_get_sb(pr, mag, struct cramfs_super); + if (!cs) +- return -1; ++ return errno ? -errno : 1; + + blkid_probe_set_label(pr, cs->name, sizeof(cs->name)); + return 0; +diff -up util-linux-2.23.2/libblkid/src/superblocks/ddf_raid.c.kzak util-linux-2.23.2/libblkid/src/superblocks/ddf_raid.c +--- util-linux-2.23.2/libblkid/src/superblocks/ddf_raid.c.kzak 2013-04-08 17:55:40.241856056 +0200 ++++ util-linux-2.23.2/libblkid/src/superblocks/ddf_raid.c 2014-03-28 15:11:44.679552006 +0100 +@@ -81,7 +81,7 @@ static int probe_ddf(blkid_probe pr, + uint64_t off, lba; + + if (pr->size < 0x30000) +- return -1; ++ return 1; + + for (i = 0; i < ARRAY_SIZE(hdrs); i++) { + off = ((pr->size / 0x200) - hdrs[i]) * 0x200; +@@ -90,8 +90,7 @@ static int probe_ddf(blkid_probe pr, + off, + sizeof(struct ddf_header)); + if (!ddf) +- return -1; +- ++ return errno ? -errno : 1; + if (ddf->signature == cpu_to_be32(DDF_MAGIC) || + ddf->signature == cpu_to_le32(DDF_MAGIC)) + break; +@@ -99,7 +98,7 @@ static int probe_ddf(blkid_probe pr, + } + + if (!ddf) +- return -1; ++ return 1; + + lba = ddf->signature == cpu_to_be32(DDF_MAGIC) ? + be64_to_cpu(ddf->primary_lba) : +@@ -111,8 +110,12 @@ static int probe_ddf(blkid_probe pr, + + buf = blkid_probe_get_buffer(pr, + lba << 9, sizeof(ddf->signature)); +- if (!buf || memcmp(buf, &ddf->signature, 4)) +- return -1; ++ if (!buf) { ++ if (errno) ++ return -errno; ++ if (memcmp(buf, &ddf->signature, 4)) ++ return 1; ++ } + } + + blkid_probe_strncpy_uuid(pr, ddf->guid, sizeof(ddf->guid)); +@@ -121,11 +124,11 @@ static int probe_ddf(blkid_probe pr, + *(version + sizeof(ddf->ddf_rev)) = '\0'; + + if (blkid_probe_set_version(pr, version) != 0) +- return -1; ++ return 1; + if (blkid_probe_set_magic(pr, off, + sizeof(ddf->signature), + (unsigned char *) &ddf->signature)) +- return -1; ++ return 1; + return 0; + } + +diff -up util-linux-2.23.2/libblkid/src/superblocks/drbd.c.kzak util-linux-2.23.2/libblkid/src/superblocks/drbd.c +--- util-linux-2.23.2/libblkid/src/superblocks/drbd.c.kzak 2013-04-08 17:55:40.243856074 +0200 ++++ util-linux-2.23.2/libblkid/src/superblocks/drbd.c 2014-03-28 15:11:44.679552006 +0100 +@@ -75,18 +75,18 @@ static int probe_drbd(blkid_probe pr, + + /* Small devices cannot be drbd (?) */ + if (pr->size < 0x10000) +- return -1; ++ return 1; + + md = (struct md_on_disk_08 *) + blkid_probe_get_buffer(pr, + off, + sizeof(struct md_on_disk_08)); + if (!md) +- return -1; ++ return errno ? -errno : 1; + + if (be32_to_cpu(md->magic) != DRBD_MD_MAGIC_08 && + be32_to_cpu(md->magic) != DRBD_MD_MAGIC_84_UNCLEAN) +- return -1; ++ return 1; + + /* + * DRBD does not have "real" uuids; the following resembles DRBD's +@@ -102,7 +102,7 @@ static int probe_drbd(blkid_probe pr, + off + offsetof(struct md_on_disk_08, magic), + sizeof(md->magic), + (unsigned char *) &md->magic)) +- return -1; ++ return 1; + + return 0; + } +diff -up util-linux-2.23.2/libblkid/src/superblocks/drbdproxy_datalog.c.kzak util-linux-2.23.2/libblkid/src/superblocks/drbdproxy_datalog.c +--- util-linux-2.23.2/libblkid/src/superblocks/drbdproxy_datalog.c.kzak 2013-04-08 17:55:40.244856084 +0200 ++++ util-linux-2.23.2/libblkid/src/superblocks/drbdproxy_datalog.c 2014-03-28 15:11:44.679552006 +0100 +@@ -33,7 +33,7 @@ static int probe_drbdproxy_datalog(blkid + + lh = (struct log_header_t *) blkid_probe_get_buffer(pr, 0, sizeof(*lh)); + if (!lh) +- return -1; ++ return errno ? -errno : 1; + + blkid_probe_set_uuid(pr, lh->uuid); + blkid_probe_sprintf_version(pr, "v%jd", le64_to_cpu(lh->version)); +diff -up util-linux-2.23.2/libblkid/src/superblocks/exfat.c.kzak util-linux-2.23.2/libblkid/src/superblocks/exfat.c +--- util-linux-2.23.2/libblkid/src/superblocks/exfat.c.kzak 2013-04-08 17:55:40.245856093 +0200 ++++ util-linux-2.23.2/libblkid/src/superblocks/exfat.c 2014-03-28 15:11:44.680552016 +0100 +@@ -115,12 +115,14 @@ static int probe_exfat(blkid_probe pr, c + + sb = blkid_probe_get_sb(pr, mag, struct exfat_super_block); + if (!sb) +- return -1; ++ return errno ? -errno : BLKID_PROBE_NONE; + + label = find_label(pr, sb); + if (label) + blkid_probe_set_utf8label(pr, label->name, + min(label->length * 2, 30), BLKID_ENC_UTF16LE); ++ else if (errno) ++ return -errno; + + blkid_probe_sprintf_uuid(pr, sb->volume_serial, 4, + "%02hhX%02hhX-%02hhX%02hhX", +@@ -130,7 +132,7 @@ static int probe_exfat(blkid_probe pr, c + blkid_probe_sprintf_version(pr, "%u.%u", + sb->version.major, sb->version.minor); + +- return 0; ++ return BLKID_PROBE_OK; + } + + const struct blkid_idinfo exfat_idinfo = +diff -up util-linux-2.23.2/libblkid/src/superblocks/ext.c.kzak util-linux-2.23.2/libblkid/src/superblocks/ext.c +--- util-linux-2.23.2/libblkid/src/superblocks/ext.c.kzak 2014-03-28 15:11:18.333283694 +0100 ++++ util-linux-2.23.2/libblkid/src/superblocks/ext.c 2014-03-28 15:11:44.680552016 +0100 +@@ -198,9 +198,9 @@ static int probe_jbd(blkid_probe pr, + + es = ext_get_super(pr, NULL, &fi, NULL); + if (!es) +- return -BLKID_ERR_PARAM; ++ return errno ? -errno : 1; + if (!(fi & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) +- return -BLKID_ERR_PARAM; ++ return 1; + + ext_get_info(pr, 2, es); + return 0; +@@ -214,16 +214,16 @@ static int probe_ext2(blkid_probe pr, + + es = ext_get_super(pr, &fc, &fi, &frc); + if (!es) +- return -BLKID_ERR_PARAM; ++ return errno ? -errno : 1; + + /* Distinguish between ext3 and ext2 */ + if (fc & EXT3_FEATURE_COMPAT_HAS_JOURNAL) +- return -BLKID_ERR_PARAM; ++ return 1; + + /* Any features which ext2 doesn't understand */ + if ((frc & EXT2_FEATURE_RO_COMPAT_UNSUPPORTED) || + (fi & EXT2_FEATURE_INCOMPAT_UNSUPPORTED)) +- return -BLKID_ERR_PARAM; ++ return 1; + + ext_get_info(pr, 2, es); + return 0; +@@ -237,16 +237,16 @@ static int probe_ext3(blkid_probe pr, + + es = ext_get_super(pr, &fc, &fi, &frc); + if (!es) +- return -BLKID_ERR_PARAM; ++ return errno ? -errno : 1; + + /* ext3 requires journal */ + if (!(fc & EXT3_FEATURE_COMPAT_HAS_JOURNAL)) +- return -BLKID_ERR_PARAM; ++ return 1; + + /* Any features which ext3 doesn't understand */ + if ((frc & EXT3_FEATURE_RO_COMPAT_UNSUPPORTED) || + (fi & EXT3_FEATURE_INCOMPAT_UNSUPPORTED)) +- return -BLKID_ERR_PARAM; ++ return 1; + + ext_get_info(pr, 3, es); + return 0; +@@ -261,14 +261,14 @@ static int probe_ext4dev(blkid_probe pr, + + es = ext_get_super(pr, &fc, &fi, &frc); + if (!es) +- return -BLKID_ERR_PARAM; ++ return errno ? -errno : 1; + + /* Distinguish from jbd */ + if (fi & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) +- return -BLKID_ERR_PARAM; ++ return 1; + + if (!(le32_to_cpu(es->s_flags) & EXT2_FLAGS_TEST_FILESYS)) +- return -BLKID_ERR_PARAM; ++ return 1; + + ext_get_info(pr, 4, es); + return 0; +@@ -282,16 +282,16 @@ static int probe_ext4(blkid_probe pr, + + es = ext_get_super(pr, &fc, &fi, &frc); + if (!es) +- return -1; ++ return errno ? -errno : 1; + + /* Distinguish from jbd */ + if (fi & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) +- return -BLKID_ERR_PARAM; ++ return 1; + + /* Ext4 has at least one feature which ext3 doesn't understand */ + if (!(frc & EXT3_FEATURE_RO_COMPAT_UNSUPPORTED) && + !(fi & EXT3_FEATURE_INCOMPAT_UNSUPPORTED)) +- return -BLKID_ERR_PARAM; ++ return 1; + + /* + * If the filesystem is a OK for use by in-development +@@ -304,7 +304,7 @@ static int probe_ext4(blkid_probe pr, + * ext4dev. + */ + if (le32_to_cpu(es->s_flags) & EXT2_FLAGS_TEST_FILESYS) +- return -BLKID_ERR_PARAM; ++ return 1; + + ext_get_info(pr, 4, es); + return 0; +diff -up util-linux-2.23.2/libblkid/src/superblocks/f2fs.c.kzak util-linux-2.23.2/libblkid/src/superblocks/f2fs.c +--- util-linux-2.23.2/libblkid/src/superblocks/f2fs.c.kzak 2013-06-13 09:46:10.422650639 +0200 ++++ util-linux-2.23.2/libblkid/src/superblocks/f2fs.c 2014-03-28 15:11:44.680552016 +0100 +@@ -62,7 +62,7 @@ static int probe_f2fs(blkid_probe pr, co + + sb = blkid_probe_get_sb(pr, mag, struct f2fs_super_block); + if (!sb) +- return -1; ++ return errno ? -errno : 1; + + major = le16_to_cpu(sb->major_ver); + minor = le16_to_cpu(sb->minor_ver); +diff -up util-linux-2.23.2/libblkid/src/superblocks/gfs.c.kzak util-linux-2.23.2/libblkid/src/superblocks/gfs.c +--- util-linux-2.23.2/libblkid/src/superblocks/gfs.c.kzak 2013-04-08 17:55:40.250856141 +0200 ++++ util-linux-2.23.2/libblkid/src/superblocks/gfs.c 2014-03-28 15:11:44.680552016 +0100 +@@ -64,7 +64,7 @@ static int probe_gfs(blkid_probe pr, con + + sbd = blkid_probe_get_sb(pr, mag, struct gfs2_sb); + if (!sbd) +- return -1; ++ return errno ? -errno : 1; + + if (be32_to_cpu(sbd->sb_fs_format) == GFS_FORMAT_FS && + be32_to_cpu(sbd->sb_multihost_format) == GFS_FORMAT_MULTI) +@@ -78,7 +78,7 @@ static int probe_gfs(blkid_probe pr, con + return 0; + } + +- return -1; ++ return 1; + } + + static int probe_gfs2(blkid_probe pr, const struct blkid_idmag *mag) +@@ -87,7 +87,7 @@ static int probe_gfs2(blkid_probe pr, co + + sbd = blkid_probe_get_sb(pr, mag, struct gfs2_sb); + if (!sbd) +- return -1; ++ return errno ? -errno : 1; + + if (be32_to_cpu(sbd->sb_fs_format) == GFS2_FORMAT_FS && + be32_to_cpu(sbd->sb_multihost_format) == GFS2_FORMAT_MULTI) +@@ -100,7 +100,7 @@ static int probe_gfs2(blkid_probe pr, co + blkid_probe_set_version(pr, "1"); + return 0; + } +- return -1; ++ return 1; + } + + const struct blkid_idinfo gfs_idinfo = +diff -up util-linux-2.23.2/libblkid/src/superblocks/hfs.c.kzak util-linux-2.23.2/libblkid/src/superblocks/hfs.c +--- util-linux-2.23.2/libblkid/src/superblocks/hfs.c.kzak 2013-04-08 17:55:40.251856150 +0200 ++++ util-linux-2.23.2/libblkid/src/superblocks/hfs.c 2014-03-28 15:11:44.680552016 +0100 +@@ -154,7 +154,7 @@ static int probe_hfs(blkid_probe pr, con + + hfs = blkid_probe_get_sb(pr, mag, struct hfs_mdb); + if (!hfs) +- return -1; ++ return errno ? -errno : 1; + + if ((memcmp(hfs->embed_sig, "H+", 2) == 0) || + (memcmp(hfs->embed_sig, "HX", 2) == 0)) +@@ -193,7 +193,7 @@ static int probe_hfsplus(blkid_probe pr, + + sbd = blkid_probe_get_sb(pr, mag, struct hfs_mdb); + if (!sbd) +- return -1; ++ return errno ? -errno : 1; + + /* Check for a HFS+ volume embedded in a HFS volume */ + if (memcmp(sbd->signature, "BD", 2) == 0) { +@@ -218,7 +218,7 @@ static int probe_hfsplus(blkid_probe pr, + struct hfsplus_vol_header); + + if (!hfsplus) +- return -1; ++ return errno ? -errno : 1; + + if ((memcmp(hfsplus->signature, "H+", 2) != 0) && + (memcmp(hfsplus->signature, "HX", 2) != 0)) +@@ -228,7 +228,7 @@ static int probe_hfsplus(blkid_probe pr, + + blocksize = be32_to_cpu(hfsplus->blocksize); + if (blocksize < HFSPLUS_SECTOR_SIZE) +- return -1; ++ return 1; + + memcpy(extents, hfsplus->cat_file.extents, sizeof(extents)); + cat_block = be32_to_cpu(extents[0].start_block); +@@ -236,7 +236,7 @@ static int probe_hfsplus(blkid_probe pr, + buf = blkid_probe_get_buffer(pr, + off + ((blkid_loff_t) cat_block * blocksize), 0x2000); + if (!buf) +- return 0; ++ return errno ? -errno : 0; + + bnode = (struct hfsplus_bheader_record *) + &buf[sizeof(struct hfsplus_bnode_descriptor)]; +@@ -271,7 +271,7 @@ static int probe_hfsplus(blkid_probe pr, + (blkid_loff_t) off + leaf_off, + leaf_node_size); + if (!buf) +- return 0; ++ return errno ? -errno : 0; + + descr = (struct hfsplus_bnode_descriptor *) buf; + record_count = be16_to_cpu(descr->num_recs); +diff -up util-linux-2.23.2/libblkid/src/superblocks/highpoint_raid.c.kzak util-linux-2.23.2/libblkid/src/superblocks/highpoint_raid.c +--- util-linux-2.23.2/libblkid/src/superblocks/highpoint_raid.c.kzak 2013-04-08 17:55:40.251856150 +0200 ++++ util-linux-2.23.2/libblkid/src/superblocks/highpoint_raid.c 2014-03-28 15:11:44.680552016 +0100 +@@ -30,9 +30,9 @@ static int probe_highpoint45x(blkid_prob + uint32_t magic; + + if (pr->size < 0x10000) +- return -1; ++ return 1; + if (!S_ISREG(pr->mode) && !blkid_probe_is_wholedisk(pr)) +- return -1; ++ return 1; + + off = ((pr->size / 0x200) - 11) * 0x200; + hpt = (struct hpt45x_metadata *) +@@ -40,13 +40,13 @@ static int probe_highpoint45x(blkid_prob + off, + sizeof(struct hpt45x_metadata)); + if (!hpt) +- return -1; ++ return errno ? -errno : 1; + magic = le32_to_cpu(hpt->magic); + if (magic != HPT45X_MAGIC_OK && magic != HPT45X_MAGIC_BAD) +- return -1; ++ return 1; + if (blkid_probe_set_magic(pr, off, sizeof(hpt->magic), + (unsigned char *) &hpt->magic)) +- return -1; ++ return 1; + return 0; + } + +@@ -54,7 +54,7 @@ static int probe_highpoint37x(blkid_prob + const struct blkid_idmag *mag __attribute__((__unused__))) + { + if (!S_ISREG(pr->mode) && !blkid_probe_is_wholedisk(pr)) +- return -1; ++ return 1; + return 0; + } + +diff -up util-linux-2.23.2/libblkid/src/superblocks/hpfs.c.kzak util-linux-2.23.2/libblkid/src/superblocks/hpfs.c +--- util-linux-2.23.2/libblkid/src/superblocks/hpfs.c.kzak 2013-04-08 17:55:40.252856159 +0200 ++++ util-linux-2.23.2/libblkid/src/superblocks/hpfs.c 2014-03-28 15:11:44.680552016 +0100 +@@ -68,7 +68,7 @@ static int probe_hpfs(blkid_probe pr, co + /* super block */ + hs = blkid_probe_get_sb(pr, mag, struct hpfs_super_block); + if (!hs) +- return -1; ++ return errno ? -errno : 1; + version = hs->version; + + /* spare super block */ +@@ -77,9 +77,9 @@ static int probe_hpfs(blkid_probe pr, co + HPFS_SBSPARE_OFFSET, + sizeof(struct hpfs_spare_super)); + if (!hss) +- return -1; ++ return errno ? -errno : 1; + if (memcmp(hss->magic, "\x49\x18\x91\xf9", 4) != 0) +- return -1; ++ return 1; + + /* boot block (with UUID and LABEL) */ + hbb = (struct hpfs_boot_block *) +@@ -87,7 +87,7 @@ static int probe_hpfs(blkid_probe pr, co + 0, + sizeof(struct hpfs_boot_block)); + if (!hbb) +- return -1; ++ return errno ? -errno : 1; + if (memcmp(hbb->magic, "\x55\xaa", 2) == 0 && + memcmp(hbb->sig_hpfs, "HPFS", 4) == 0 && + hbb->sig_28h == 0x28) { +diff -up util-linux-2.23.2/libblkid/src/superblocks/iso9660.c.kzak util-linux-2.23.2/libblkid/src/superblocks/iso9660.c +--- util-linux-2.23.2/libblkid/src/superblocks/iso9660.c.kzak 2013-06-13 09:46:10.422650639 +0200 ++++ util-linux-2.23.2/libblkid/src/superblocks/iso9660.c 2014-03-28 15:11:44.680552016 +0100 +@@ -100,7 +100,7 @@ static int probe_iso9660_hsfs(blkid_prob + + iso = blkid_probe_get_sb(pr, mag, struct high_sierra_volume_descriptor); + if (!iso) +- return -1; ++ return errno ? -errno : 1; + + blkid_probe_set_version(pr, "High Sierra"); + blkid_probe_set_label(pr, iso->volume_id, sizeof(iso->volume_id)); +@@ -178,7 +178,7 @@ int probe_iso9660(blkid_probe pr, const + + iso = blkid_probe_get_sb(pr, mag, struct iso_volume_descriptor); + if (!iso) +- return -1; ++ return errno ? -errno : 1; + + memcpy(label, iso->volume_id, sizeof(label)); + +diff -up util-linux-2.23.2/libblkid/src/superblocks/isw_raid.c.kzak util-linux-2.23.2/libblkid/src/superblocks/isw_raid.c +--- util-linux-2.23.2/libblkid/src/superblocks/isw_raid.c.kzak 2013-04-08 17:55:40.252856159 +0200 ++++ util-linux-2.23.2/libblkid/src/superblocks/isw_raid.c 2014-03-28 15:11:44.680552016 +0100 +@@ -33,9 +33,9 @@ static int probe_iswraid(blkid_probe pr, + struct isw_metadata *isw; + + if (pr->size < 0x10000) +- return -1; ++ return 1; + if (!S_ISREG(pr->mode) && !blkid_probe_is_wholedisk(pr)) +- return -1; ++ return 1; + + off = ((pr->size / 0x200) - 2) * 0x200; + isw = (struct isw_metadata *) +@@ -43,15 +43,16 @@ static int probe_iswraid(blkid_probe pr, + off, + sizeof(struct isw_metadata)); + if (!isw) +- return -1; ++ return errno ? -errno : 1; ++ + if (memcmp(isw->sig, ISW_SIGNATURE, sizeof(ISW_SIGNATURE)-1) != 0) +- return -1; ++ return 1; + if (blkid_probe_sprintf_version(pr, "%6s", + &isw->sig[sizeof(ISW_SIGNATURE)-1]) != 0) +- return -1; ++ return 1; + if (blkid_probe_set_magic(pr, off, sizeof(isw->sig), + (unsigned char *) isw->sig)) +- return -1; ++ return 1; + return 0; + } + +diff -up util-linux-2.23.2/libblkid/src/superblocks/jfs.c.kzak util-linux-2.23.2/libblkid/src/superblocks/jfs.c +--- util-linux-2.23.2/libblkid/src/superblocks/jfs.c.kzak 2013-04-08 17:55:40.253856169 +0200 ++++ util-linux-2.23.2/libblkid/src/superblocks/jfs.c 2014-03-28 15:11:44.681552026 +0100 +@@ -40,7 +40,7 @@ static int probe_jfs(blkid_probe pr, con + + js = blkid_probe_get_sb(pr, mag, struct jfs_super_block); + if (!js) +- return -1; ++ return errno ? -errno : 1; + if (le32_to_cpu(js->js_bsize) != (1U << le16_to_cpu(js->js_l2bsize))) + return 1; + if (le32_to_cpu(js->js_pbsize) != (1U << le16_to_cpu(js->js_l2pbsize))) +diff -up util-linux-2.23.2/libblkid/src/superblocks/jmicron_raid.c.kzak util-linux-2.23.2/libblkid/src/superblocks/jmicron_raid.c +--- util-linux-2.23.2/libblkid/src/superblocks/jmicron_raid.c.kzak 2013-04-08 17:55:40.253856169 +0200 ++++ util-linux-2.23.2/libblkid/src/superblocks/jmicron_raid.c 2014-03-28 15:11:44.681552026 +0100 +@@ -32,9 +32,9 @@ static int probe_jmraid(blkid_probe pr, + struct jm_metadata *jm; + + if (pr->size < 0x10000) +- return -1; ++ return 1; + if (!S_ISREG(pr->mode) && !blkid_probe_is_wholedisk(pr)) +- return -1; ++ return 1; + + off = ((pr->size / 0x200) - 1) * 0x200; + jm = (struct jm_metadata *) +@@ -42,15 +42,16 @@ static int probe_jmraid(blkid_probe pr, + off, + sizeof(struct jm_metadata)); + if (!jm) +- return -1; ++ return errno ? -errno : 1; ++ + if (memcmp(jm->signature, JM_SIGNATURE, sizeof(JM_SIGNATURE) - 1) != 0) +- return -1; ++ return 1; + if (blkid_probe_sprintf_version(pr, "%u.%u", + jm->major_version, jm->minor_version) != 0) +- return -1; ++ return 1; + if (blkid_probe_set_magic(pr, off, sizeof(jm->signature), + (unsigned char *) jm->signature)) +- return -1; ++ return 1; + return 0; + } + +diff -up util-linux-2.23.2/libblkid/src/superblocks/linux_raid.c.kzak util-linux-2.23.2/libblkid/src/superblocks/linux_raid.c +--- util-linux-2.23.2/libblkid/src/superblocks/linux_raid.c.kzak 2013-04-08 17:55:40.253856169 +0200 ++++ util-linux-2.23.2/libblkid/src/superblocks/linux_raid.c 2014-03-28 15:11:44.681552026 +0100 +@@ -110,13 +110,13 @@ static int probe_raid0(blkid_probe pr, b + uint64_t size; + + if (pr->size < MD_RESERVED_BYTES) +- return -1; ++ return 1; + mdp0 = (struct mdp0_super_block *) + blkid_probe_get_buffer(pr, + off, + sizeof(struct mdp0_super_block)); + if (!mdp0) +- return -1; ++ return errno ? -errno : 1; + + memset(uuid.ints, 0, sizeof(uuid.ints)); + +@@ -173,12 +173,12 @@ static int probe_raid0(blkid_probe pr, b + } + + if (blkid_probe_sprintf_version(pr, "%u.%u.%u", ma, mi, pa) != 0) +- return -1; ++ return 1; + if (blkid_probe_set_uuid(pr, (unsigned char *) uuid.bytes) != 0) +- return -1; ++ return 1; + if (blkid_probe_set_magic(pr, off, sizeof(mdp0->md_magic), + (unsigned char *) &mdp0->md_magic)) +- return -1; ++ return 1; + return 0; + } + +@@ -191,24 +191,24 @@ static int probe_raid1(blkid_probe pr, o + off, + sizeof(struct mdp1_super_block)); + if (!mdp1) +- return -1; ++ return errno ? -errno : 1; + if (le32_to_cpu(mdp1->magic) != MD_SB_MAGIC) +- return -1; ++ return 1; + if (le32_to_cpu(mdp1->major_version) != 1U) +- return -1; ++ return 1; + if (le64_to_cpu(mdp1->super_offset) != (uint64_t) off >> 9) +- return -1; ++ return 1; + if (blkid_probe_set_uuid(pr, (unsigned char *) mdp1->set_uuid) != 0) +- return -1; ++ return 1; + if (blkid_probe_set_uuid_as(pr, + (unsigned char *) mdp1->device_uuid, "UUID_SUB") != 0) +- return -1; ++ return 1; + if (blkid_probe_set_label(pr, mdp1->set_name, + sizeof(mdp1->set_name)) != 0) +- return -1; ++ return 1; + if (blkid_probe_set_magic(pr, off, sizeof(mdp1->magic), + (unsigned char *) &mdp1->magic)) +- return -1; ++ return 1; + return 0; + } + +@@ -216,35 +216,44 @@ int probe_raid(blkid_probe pr, + const struct blkid_idmag *mag __attribute__((__unused__))) + { + const char *ver = NULL; ++ int ret = BLKID_PROBE_NONE; + + if (pr->size > MD_RESERVED_BYTES) { + /* version 0 at the end of the device */ + uint64_t sboff = (pr->size & ~(MD_RESERVED_BYTES - 1)) +- - MD_RESERVED_BYTES; +- if (probe_raid0(pr, sboff) == 0) +- return 0; ++ - MD_RESERVED_BYTES; ++ ret = probe_raid0(pr, sboff); ++ if (ret < 1) ++ return ret; /* error */ + + /* version 1.0 at the end of the device */ + sboff = (pr->size & ~(0x1000 - 1)) - 0x2000; +- if (probe_raid1(pr, sboff) == 0) ++ ret = probe_raid1(pr, sboff); ++ if (ret < 0) ++ return ret; /* error */ ++ if (ret == 0) + ver = "1.0"; + } + + if (!ver) { + /* version 1.1 at the start of the device */ +- if (probe_raid1(pr, 0) == 0) ++ ret = probe_raid1(pr, 0); ++ if (ret == 0) + ver = "1.1"; + + /* version 1.2 at 4k offset from the start */ +- else if (probe_raid1(pr, 0x1000) == 0) +- ver = "1.2"; ++ else if (ret == BLKID_PROBE_NONE) { ++ ret = probe_raid1(pr, 0x1000); ++ if (ret == 0) ++ ver = "1.2"; ++ } + } + + if (ver) { + blkid_probe_set_version(pr, ver); +- return 0; ++ return BLKID_PROBE_OK; + } +- return -1; ++ return ret; + } + + +diff -up util-linux-2.23.2/libblkid/src/superblocks/lsi_raid.c.kzak util-linux-2.23.2/libblkid/src/superblocks/lsi_raid.c +--- util-linux-2.23.2/libblkid/src/superblocks/lsi_raid.c.kzak 2013-04-08 17:55:40.254856179 +0200 ++++ util-linux-2.23.2/libblkid/src/superblocks/lsi_raid.c 2014-03-28 15:11:44.681552026 +0100 +@@ -30,9 +30,9 @@ static int probe_lsiraid(blkid_probe pr, + struct lsi_metadata *lsi; + + if (pr->size < 0x10000) +- return -1; ++ return 1; + if (!S_ISREG(pr->mode) && !blkid_probe_is_wholedisk(pr)) +- return -1; ++ return 1; + + off = ((pr->size / 0x200) - 1) * 0x200; + lsi = (struct lsi_metadata *) +@@ -40,13 +40,13 @@ static int probe_lsiraid(blkid_probe pr, + off, + sizeof(struct lsi_metadata)); + if (!lsi) +- return -1; ++ return errno ? -errno : 1; + + if (memcmp(lsi->sig, LSI_SIGNATURE, sizeof(LSI_SIGNATURE)-1) != 0) +- return -1; ++ return 1; + if (blkid_probe_set_magic(pr, off, sizeof(lsi->sig), + (unsigned char *) lsi->sig)) +- return -1; ++ return 1; + return 0; + } + +diff -up util-linux-2.23.2/libblkid/src/superblocks/luks.c.kzak util-linux-2.23.2/libblkid/src/superblocks/luks.c +--- util-linux-2.23.2/libblkid/src/superblocks/luks.c.kzak 2013-04-08 17:55:40.254856179 +0200 ++++ util-linux-2.23.2/libblkid/src/superblocks/luks.c 2014-03-28 15:11:44.681552026 +0100 +@@ -45,7 +45,7 @@ static int probe_luks(blkid_probe pr, co + + header = blkid_probe_get_sb(pr, mag, struct luks_phdr); + if (header == NULL) +- return -1; ++ return errno ? -errno : 1; + + blkid_probe_strncpy_uuid(pr, (unsigned char *) header->uuid, + sizeof(header->uuid)); +diff -up util-linux-2.23.2/libblkid/src/superblocks/lvm.c.kzak util-linux-2.23.2/libblkid/src/superblocks/lvm.c +--- util-linux-2.23.2/libblkid/src/superblocks/lvm.c.kzak 2013-06-13 09:46:10.422650639 +0200 ++++ util-linux-2.23.2/libblkid/src/superblocks/lvm.c 2014-03-28 15:11:44.681552026 +0100 +@@ -82,7 +82,7 @@ static int probe_lvm2(blkid_probe pr, co + mag->kboff << 10, + 512 + sizeof(struct lvm2_pv_label_header)); + if (!buf) +- return -1; ++ return errno ? -errno : 1; + + /* buf is at 0k or 1k offset; find label inside */ + if (memcmp(buf, "LABELONE", 8) == 0) { +@@ -129,7 +129,7 @@ static int probe_lvm1(blkid_probe pr, co + + label = blkid_probe_get_sb(pr, mag, struct lvm1_pv_label_header); + if (!label) +- return -1; ++ return errno ? -errno : 1; + + version = le16_to_cpu(label->version); + if (version != 1 && version != 2) +@@ -164,7 +164,7 @@ static int probe_verity(blkid_probe pr, + + sb = blkid_probe_get_sb(pr, mag, struct verity_sb); + if (sb == NULL) +- return -1; ++ return errno ? -errno : 1; + + version = le32_to_cpu(sb->version); + if (version != 1) +diff -up util-linux-2.23.2/libblkid/src/superblocks/minix.c.kzak util-linux-2.23.2/libblkid/src/superblocks/minix.c +--- util-linux-2.23.2/libblkid/src/superblocks/minix.c.kzak 2013-06-13 09:46:10.423650647 +0200 ++++ util-linux-2.23.2/libblkid/src/superblocks/minix.c 2014-03-28 15:11:44.681552026 +0100 +@@ -80,17 +80,17 @@ static int probe_minix(blkid_probe pr, c + max(sizeof(struct minix_super_block), + sizeof(struct minix3_super_block))); + if (!data) +- return -1; ++ return errno ? -errno : 1; + version = get_minix_version(data, &swabme); + if (version < 1) +- return -1; ++ return 1; + + if (version <= 2) { + struct minix_super_block *sb = (struct minix_super_block *) data; + int zones, ninodes, imaps, zmaps, firstz; + + if (sb->s_imap_blocks == 0 || sb->s_zmap_blocks == 0) +- return -1; ++ return 1; + + zones = version == 2 ? minix_swab32(swabme, sb->s_zones) : + minix_swab16(swabme, sb->s_nzones); +@@ -101,15 +101,15 @@ static int probe_minix(blkid_probe pr, c + + /* sanity checks to be sure that the FS is really minix */ + if (imaps * MINIX_BLOCK_SIZE * 8 < ninodes + 1) +- return -1; ++ return 1; + if (zmaps * MINIX_BLOCK_SIZE * 8 < zones - firstz + 1) +- return -1; ++ return 1; + + } else if (version == 3) { + struct minix3_super_block *sb = (struct minix3_super_block *) data; + + if (sb->s_imap_blocks == 0 || sb->s_zmap_blocks == 0) +- return -1; ++ return 1; + } + + /* unfortunately, some parts of ext3 is sometimes possible to +@@ -117,8 +117,10 @@ static int probe_minix(blkid_probe pr, c + * string. (For extN magic string and offsets see ext.c.) + */ + ext = blkid_probe_get_buffer(pr, 0x400 + 0x38, 2); +- if (ext && memcmp(ext, "\123\357", 2) == 0) +- return -1; ++ if (!ext) ++ return errno ? -errno : 1; ++ else if (memcmp(ext, "\123\357", 2) == 0) ++ return 1; + + blkid_probe_sprintf_version(pr, "%d", version); + return 0; +diff -up util-linux-2.23.2/libblkid/src/superblocks/netware.c.kzak util-linux-2.23.2/libblkid/src/superblocks/netware.c +--- util-linux-2.23.2/libblkid/src/superblocks/netware.c.kzak 2013-04-08 17:55:40.255856188 +0200 ++++ util-linux-2.23.2/libblkid/src/superblocks/netware.c 2014-03-28 15:11:44.681552026 +0100 +@@ -71,7 +71,7 @@ static int probe_netware(blkid_probe pr, + + nw = blkid_probe_get_sb(pr, mag, struct netware_super_block); + if (!nw) +- return -1; ++ return errno ? -errno : 1; + + blkid_probe_set_uuid(pr, nw->SBH_PoolID); + +diff -up util-linux-2.23.2/libblkid/src/superblocks/nilfs.c.kzak util-linux-2.23.2/libblkid/src/superblocks/nilfs.c +--- util-linux-2.23.2/libblkid/src/superblocks/nilfs.c.kzak 2013-04-08 17:55:40.256856198 +0200 ++++ util-linux-2.23.2/libblkid/src/superblocks/nilfs.c 2014-03-28 15:11:44.681552026 +0100 +@@ -82,7 +82,7 @@ static int probe_nilfs2(blkid_probe pr, + + sb = blkid_probe_get_sb(pr, mag, struct nilfs_super_block); + if (!sb) +- return -1; ++ return errno ? -errno : 1; + + bytes = le16_to_cpu(sb->s_bytes); + crc = crc32(le32_to_cpu(sb->s_crc_seed), (unsigned char *)sb, sumoff); +@@ -90,7 +90,7 @@ static int probe_nilfs2(blkid_probe pr, + crc = crc32(crc, (unsigned char *)sb + sumoff + 4, bytes - sumoff - 4); + + if (crc != le32_to_cpu(sb->s_sum)) +- return -1; ++ return 1; + + if (strlen(sb->s_volume_name)) + blkid_probe_set_label(pr, (unsigned char *) sb->s_volume_name, +diff -up util-linux-2.23.2/libblkid/src/superblocks/ntfs.c.kzak util-linux-2.23.2/libblkid/src/superblocks/ntfs.c +--- util-linux-2.23.2/libblkid/src/superblocks/ntfs.c.kzak 2013-06-13 09:46:10.423650647 +0200 ++++ util-linux-2.23.2/libblkid/src/superblocks/ntfs.c 2014-03-28 15:11:44.681552026 +0100 +@@ -91,7 +91,7 @@ static int probe_ntfs(blkid_probe pr, co + + ns = blkid_probe_get_sb(pr, mag, struct ntfs_super_block); + if (!ns) +- return -1; ++ return errno ? -errno : 1; + + /* + * Check bios parameters block +@@ -158,7 +158,7 @@ static int probe_ntfs(blkid_probe pr, co + + buf_mft = blkid_probe_get_buffer(pr, off, mft_record_size); + if (!buf_mft) +- return 1; ++ return errno ? -errno : 1; + + if (memcmp(buf_mft, "FILE", 4)) + return 1; +@@ -167,7 +167,7 @@ static int probe_ntfs(blkid_probe pr, co + + buf_mft = blkid_probe_get_buffer(pr, off, mft_record_size); + if (!buf_mft) +- return 1; ++ return errno ? -errno : 1; + + if (memcmp(buf_mft, "FILE", 4)) + return 1; +diff -up util-linux-2.23.2/libblkid/src/superblocks/nvidia_raid.c.kzak util-linux-2.23.2/libblkid/src/superblocks/nvidia_raid.c +--- util-linux-2.23.2/libblkid/src/superblocks/nvidia_raid.c.kzak 2013-04-08 17:55:40.257856207 +0200 ++++ util-linux-2.23.2/libblkid/src/superblocks/nvidia_raid.c 2014-03-28 15:11:44.682552036 +0100 +@@ -32,9 +32,9 @@ static int probe_nvraid(blkid_probe pr, + struct nv_metadata *nv; + + if (pr->size < 0x10000) +- return -1; ++ return 1; + if (!S_ISREG(pr->mode) && !blkid_probe_is_wholedisk(pr)) +- return -1; ++ return 1; + + off = ((pr->size / 0x200) - 2) * 0x200; + nv = (struct nv_metadata *) +@@ -42,15 +42,15 @@ static int probe_nvraid(blkid_probe pr, + off, + sizeof(struct nv_metadata)); + if (!nv) +- return -1; ++ return errno ? -errno : 1; + + if (memcmp(nv->vendor, NVIDIA_SIGNATURE, sizeof(NVIDIA_SIGNATURE)-1) != 0) +- return -1; ++ return 1; + if (blkid_probe_sprintf_version(pr, "%u", le16_to_cpu(nv->version)) != 0) +- return -1; ++ return 1; + if (blkid_probe_set_magic(pr, off, sizeof(nv->vendor), + (unsigned char *) nv->vendor)) +- return -1; ++ return 1; + return 0; + } + +diff -up util-linux-2.23.2/libblkid/src/superblocks/ocfs.c.kzak util-linux-2.23.2/libblkid/src/superblocks/ocfs.c +--- util-linux-2.23.2/libblkid/src/superblocks/ocfs.c.kzak 2013-04-08 17:55:40.257856207 +0200 ++++ util-linux-2.23.2/libblkid/src/superblocks/ocfs.c 2014-03-28 15:11:44.682552036 +0100 +@@ -109,14 +109,14 @@ static int probe_ocfs(blkid_probe pr, co + buf = blkid_probe_get_buffer(pr, mag->kboff << 10, + sizeof(struct ocfs_volume_header)); + if (!buf) +- return -1; ++ return errno ? -errno : 1; + memcpy(&ovh, buf, sizeof(ovh)); + + /* label */ + buf = blkid_probe_get_buffer(pr, (mag->kboff << 10) + 512, + sizeof(struct ocfs_volume_label)); + if (!buf) +- return -1; ++ return errno ? -errno : 1; + memcpy(&ovl, buf, sizeof(ovl)); + + maj = ocfsmajor(ovh); +@@ -144,7 +144,7 @@ static int probe_ocfs2(blkid_probe pr, c + + osb = blkid_probe_get_sb(pr, mag, struct ocfs2_super_block); + if (!osb) +- return -1; ++ return errno ? -errno : 1; + + blkid_probe_set_label(pr, (unsigned char *) osb->s_label, sizeof(osb->s_label)); + blkid_probe_set_uuid(pr, osb->s_uuid); +@@ -162,7 +162,7 @@ static int probe_oracleasm(blkid_probe p + + dl = blkid_probe_get_sb(pr, mag, struct oracle_asm_disk_label); + if (!dl) +- return -1; ++ return errno ? -errno : 1; + + blkid_probe_set_label(pr, (unsigned char *) dl->dl_id, sizeof(dl->dl_id)); + return 0; +diff -up util-linux-2.23.2/libblkid/src/superblocks/promise_raid.c.kzak util-linux-2.23.2/libblkid/src/superblocks/promise_raid.c +--- util-linux-2.23.2/libblkid/src/superblocks/promise_raid.c.kzak 2013-06-13 09:46:10.423650647 +0200 ++++ util-linux-2.23.2/libblkid/src/superblocks/promise_raid.c 2014-03-28 15:11:44.682552036 +0100 +@@ -33,9 +33,9 @@ static int probe_pdcraid(blkid_probe pr, + }; + + if (pr->size < 0x40000) +- return -1; ++ return 1; + if (!S_ISREG(pr->mode) && !blkid_probe_is_wholedisk(pr)) +- return -1; ++ return 1; + + for (i = 0; sectors[i] != 0; i++) { + uint64_t off; +@@ -47,18 +47,18 @@ static int probe_pdcraid(blkid_probe pr, + off, + sizeof(struct promise_metadata)); + if (!pdc) +- return -1; ++ return errno ? -errno : 1; + + if (memcmp(pdc->sig, PDC_SIGNATURE, + sizeof(PDC_SIGNATURE) - 1) == 0) { + + if (blkid_probe_set_magic(pr, off, sizeof(pdc->sig), + (unsigned char *) pdc->sig)) +- return -1; ++ return 1; + return 0; + } + } +- return -1; ++ return 1; + } + + const struct blkid_idinfo pdcraid_idinfo = { +diff -up util-linux-2.23.2/libblkid/src/superblocks/reiserfs.c.kzak util-linux-2.23.2/libblkid/src/superblocks/reiserfs.c +--- util-linux-2.23.2/libblkid/src/superblocks/reiserfs.c.kzak 2013-04-08 17:55:40.258856216 +0200 ++++ util-linux-2.23.2/libblkid/src/superblocks/reiserfs.c 2014-03-28 15:11:44.682552036 +0100 +@@ -45,17 +45,17 @@ static int probe_reiser(blkid_probe pr, + + rs = blkid_probe_get_sb(pr, mag, struct reiserfs_super_block); + if (!rs) +- return -1; ++ return errno ? -errno : 1; + + blocksize = le16_to_cpu(rs->rs_blocksize); + + /* The blocksize must be at least 512B */ + if ((blocksize >> 9) == 0) +- return -BLKID_ERR_PARAM; ++ return 1; + + /* If the superblock is inside the journal, we have the wrong one */ + if (mag->kboff / (blocksize >> 9) > le32_to_cpu(rs->rs_journal_block) / 2) +- return -BLKID_ERR_BIG; ++ return 1; + + /* LABEL/UUID are only valid for later versions of Reiserfs v3.6. */ + if (mag->magic[6] == '2' || mag->magic[6] == '3') { +@@ -82,7 +82,7 @@ static int probe_reiser4(blkid_probe pr, + + rs4 = blkid_probe_get_sb(pr, mag, struct reiser4_super_block); + if (!rs4) +- return -1; ++ return errno ? -errno : 1; + + if (*rs4->rs4_label) + blkid_probe_set_label(pr, rs4->rs4_label, sizeof(rs4->rs4_label)); +diff -up util-linux-2.23.2/libblkid/src/superblocks/romfs.c.kzak util-linux-2.23.2/libblkid/src/superblocks/romfs.c +--- util-linux-2.23.2/libblkid/src/superblocks/romfs.c.kzak 2013-04-08 17:55:40.258856216 +0200 ++++ util-linux-2.23.2/libblkid/src/superblocks/romfs.c 2014-03-28 15:11:44.682552036 +0100 +@@ -29,7 +29,7 @@ static int probe_romfs(blkid_probe pr, c + + ros = blkid_probe_get_sb(pr, mag, struct romfs_super_block); + if (!ros) +- return -1; ++ return errno ? -errno : 1; + + if (strlen((char *) ros->ros_volume)) + blkid_probe_set_label(pr, ros->ros_volume, +diff -up util-linux-2.23.2/libblkid/src/superblocks/silicon_raid.c.kzak util-linux-2.23.2/libblkid/src/superblocks/silicon_raid.c +--- util-linux-2.23.2/libblkid/src/superblocks/silicon_raid.c.kzak 2013-06-13 09:46:10.424650656 +0200 ++++ util-linux-2.23.2/libblkid/src/superblocks/silicon_raid.c 2014-03-28 15:11:44.682552036 +0100 +@@ -88,9 +88,9 @@ static int probe_silraid(blkid_probe pr, + struct silicon_metadata *sil; + + if (pr->size < 0x10000) +- return -1; ++ return 1; + if (!S_ISREG(pr->mode) && !blkid_probe_is_wholedisk(pr)) +- return -1; ++ return 1; + + off = ((pr->size / 0x200) - 1) * 0x200; + +@@ -98,27 +98,27 @@ static int probe_silraid(blkid_probe pr, + blkid_probe_get_buffer(pr, off, + sizeof(struct silicon_metadata)); + if (!sil) +- return -1; ++ return errno ? -errno : 1; + + if (le32_to_cpu(sil->magic) != SILICON_MAGIC) +- return -1; ++ return 1; + if (sil->disk_number >= 8) +- return -1; ++ return 1; + if (!checksum(sil)) { + DBG(LOWPROBE, blkid_debug("silicon raid: incorrect checksum")); +- return -1; ++ return 1; + } + + if (blkid_probe_sprintf_version(pr, "%u.%u", + le16_to_cpu(sil->major_ver), + le16_to_cpu(sil->minor_ver)) != 0) +- return -1; ++ return 1; + + if (blkid_probe_set_magic(pr, + off + offsetof(struct silicon_metadata, magic), + sizeof(sil->magic), + (unsigned char *) &sil->magic)) +- return -1; ++ return 1; + return 0; + } + +diff -up util-linux-2.23.2/libblkid/src/superblocks/squashfs.c.kzak util-linux-2.23.2/libblkid/src/superblocks/squashfs.c +--- util-linux-2.23.2/libblkid/src/superblocks/squashfs.c.kzak 2013-04-08 17:55:40.258856216 +0200 ++++ util-linux-2.23.2/libblkid/src/superblocks/squashfs.c 2014-03-28 15:11:44.682552036 +0100 +@@ -34,7 +34,7 @@ static int probe_squashfs(blkid_probe pr + + sq = blkid_probe_get_sb(pr, mag, struct sqsh_super_block); + if (!sq) +- return -1; ++ return errno ? -errno : 1; + + if (strcmp(mag->magic, "sqsh") == 0 || + strcmp(mag->magic, "qshs") == 0) +diff -up util-linux-2.23.2/libblkid/src/superblocks/superblocks.c.kzak util-linux-2.23.2/libblkid/src/superblocks/superblocks.c +--- util-linux-2.23.2/libblkid/src/superblocks/superblocks.c.kzak 2013-07-30 10:39:26.209738269 +0200 ++++ util-linux-2.23.2/libblkid/src/superblocks/superblocks.c 2014-03-28 15:11:44.682552036 +0100 +@@ -331,9 +331,10 @@ int blkid_superblocks_get_name(size_t id + static int superblocks_probe(blkid_probe pr, struct blkid_chain *chn) + { + size_t i; ++ int rc = BLKID_PROBE_NONE; + + if (!pr || chn->idx < -1) +- return -1; ++ return -EINVAL; + blkid_probe_chain_reset_vals(pr, chn); + + DBG(LOWPROBE, blkid_debug("--> starting probing loop [SUBLKS idx=%d]", +@@ -351,38 +352,50 @@ static int superblocks_probe(blkid_probe + const struct blkid_idinfo *id; + const struct blkid_idmag *mag = NULL; + blkid_loff_t off = 0; +- int rc = 0; + + chn->idx = i; + id = idinfos[i]; + + if (chn->fltr && blkid_bmp_get_item(chn->fltr, i)) { + DBG(LOWPROBE, blkid_debug("filter out: %s", id->name)); ++ rc = BLKID_PROBE_NONE; + continue; + } + +- if (id->minsz && id->minsz > pr->size) ++ if (id->minsz && id->minsz > pr->size) { ++ rc = BLKID_PROBE_NONE; + continue; /* the device is too small */ ++ } + + /* don't probe for RAIDs, swap or journal on CD/DVDs */ + if ((id->usage & (BLKID_USAGE_RAID | BLKID_USAGE_OTHER)) && +- blkid_probe_is_cdrom(pr)) ++ blkid_probe_is_cdrom(pr)) { ++ rc = BLKID_PROBE_NONE; + continue; ++ } + + /* don't probe for RAIDs on floppies */ +- if ((id->usage & BLKID_USAGE_RAID) && blkid_probe_is_tiny(pr)) ++ if ((id->usage & BLKID_USAGE_RAID) && blkid_probe_is_tiny(pr)) { ++ rc = BLKID_PROBE_NONE; + continue; ++ } + + DBG(LOWPROBE, blkid_debug("[%zd] %s:", i, id->name)); + +- if (blkid_probe_get_idmag(pr, id, &off, &mag)) ++ rc = blkid_probe_get_idmag(pr, id, &off, &mag); ++ if (rc < 0) ++ break; ++ if (rc != BLKID_PROBE_OK) + continue; + + /* final check by probing function */ + if (id->probefunc) { + DBG(LOWPROBE, blkid_debug("\tcall probefunc()")); +- if (id->probefunc(pr, mag) != 0) { ++ rc = id->probefunc(pr, mag); ++ if (rc != BLKID_PROBE_OK) { + blkid_probe_chain_reset_vals(pr, chn); ++ if (rc < 0) ++ break; + continue; + } + } +@@ -407,13 +420,13 @@ static int superblocks_probe(blkid_probe + + DBG(LOWPROBE, blkid_debug("<-- leaving probing loop (type=%s) [SUBLKS idx=%d]", + id->name, chn->idx)); +- return 0; ++ return BLKID_PROBE_OK; + } + + nothing: +- DBG(LOWPROBE, blkid_debug("<-- leaving probing loop (failed) [SUBLKS idx=%d]", +- chn->idx)); +- return 1; ++ DBG(LOWPROBE, blkid_debug("<-- leaving probing loop (failed=%d) [SUBLKS idx=%d]", ++ rc, chn->idx)); ++ return rc; + } + + /* +diff -up util-linux-2.23.2/libblkid/src/superblocks/swap.c.kzak util-linux-2.23.2/libblkid/src/superblocks/swap.c +--- util-linux-2.23.2/libblkid/src/superblocks/swap.c.kzak 2013-06-13 09:46:10.425650665 +0200 ++++ util-linux-2.23.2/libblkid/src/superblocks/swap.c 2014-03-28 15:11:44.682552036 +0100 +@@ -44,17 +44,17 @@ static int swap_set_info(blkid_probe pr, + hdr = (struct swap_header_v1_2 *) blkid_probe_get_buffer(pr, 1024, + sizeof(struct swap_header_v1_2)); + if (!hdr) +- return -1; ++ return errno ? -errno : 1; + + /* SWAPSPACE2 - check for wrong version or zeroed pagecount */ + if (strcmp(version, "2") == 0) { + if (hdr->version != 1 && swab32(hdr->version) != 1) { + DBG(LOWPROBE, blkid_debug("incorrect swap version")); +- return -1; ++ return 1; + } + if (hdr->lastpage == 0) { + DBG(LOWPROBE, blkid_debug("not set last swap page")); +- return -1; ++ return 1; + } + } + +@@ -62,9 +62,9 @@ static int swap_set_info(blkid_probe pr, + if (hdr->padding[32] == 0 && hdr->padding[33] == 0) { + if (hdr->volume[0] && blkid_probe_set_label(pr, hdr->volume, + sizeof(hdr->volume)) < 0) +- return -1; ++ return 1; + if (blkid_probe_set_uuid(pr, hdr->uuid) < 0) +- return -1; ++ return 1; + } + + blkid_probe_set_version(pr, version); +@@ -76,12 +76,12 @@ static int probe_swap(blkid_probe pr, co + unsigned char *buf; + + if (!mag) +- return -1; ++ return 1; + + /* TuxOnIce keeps valid swap header at the end of the 1st page */ + buf = blkid_probe_get_buffer(pr, 0, TOI_MAGIC_STRLEN); + if (!buf) +- return -1; ++ return errno ? -errno : 1; + + if (memcmp(buf, TOI_MAGIC_STRING, TOI_MAGIC_STRLEN) == 0) + return 1; /* Ignore swap signature, it's TuxOnIce */ +@@ -94,13 +94,13 @@ static int probe_swap(blkid_probe pr, co + } else if (!memcmp(mag->magic, "SWAPSPACE2", mag->len)) + return swap_set_info(pr, "2"); + +- return -1; ++ return 1; + } + + static int probe_swsuspend(blkid_probe pr, const struct blkid_idmag *mag) + { + if (!mag) +- return -1; ++ return 1; + if (!memcmp(mag->magic, "S1SUSPEND", mag->len)) + return swap_set_info(pr, "s1suspend"); + if (!memcmp(mag->magic, "S2SUSPEND", mag->len)) +@@ -112,7 +112,7 @@ static int probe_swsuspend(blkid_probe p + if (!memcmp(mag->magic, "LINHIB0001", mag->len)) + return swap_set_info(pr, "linhib0001"); + +- return -1; /* no signature detected */ ++ return 1; /* no signature detected */ + } + + const struct blkid_idinfo swap_idinfo = +diff -up util-linux-2.23.2/libblkid/src/superblocks/sysv.c.kzak util-linux-2.23.2/libblkid/src/superblocks/sysv.c +--- util-linux-2.23.2/libblkid/src/superblocks/sysv.c.kzak 2013-04-08 17:55:40.261856245 +0200 ++++ util-linux-2.23.2/libblkid/src/superblocks/sysv.c 2014-03-28 15:11:44.683552047 +0100 +@@ -80,7 +80,7 @@ static int probe_xenix(blkid_probe pr, c + + sb = blkid_probe_get_sb(pr, mag, struct xenix_super_block); + if (!sb) +- return -1; ++ return errno ? -errno : 1; + blkid_probe_set_label(pr, sb->s_fname, sizeof(sb->s_fname)); + return 0; + } +@@ -105,21 +105,21 @@ static int probe_sysv(blkid_probe pr, + off, + sizeof(struct sysv_super_block)); + if (!sb) +- return -1; ++ return errno ? -errno : 1; + + if (sb->s_magic == cpu_to_le32(0xfd187e20) || + sb->s_magic == cpu_to_be32(0xfd187e20)) { + + if (blkid_probe_set_label(pr, sb->s_fname, + sizeof(sb->s_fname))) +- return -1; ++ return 1; + + if (blkid_probe_set_magic(pr, + off + offsetof(struct sysv_super_block, + s_magic), + sizeof(sb->s_magic), + (unsigned char *) &sb->s_magic)) +- return -1; ++ return 1; + + return 0; + } +diff -up util-linux-2.23.2/libblkid/src/superblocks/ubifs.c.kzak util-linux-2.23.2/libblkid/src/superblocks/ubifs.c +--- util-linux-2.23.2/libblkid/src/superblocks/ubifs.c.kzak 2013-06-13 09:46:10.426650673 +0200 ++++ util-linux-2.23.2/libblkid/src/superblocks/ubifs.c 2014-03-28 15:11:44.683552047 +0100 +@@ -99,7 +99,7 @@ static int probe_ubifs(blkid_probe pr, c + + sb = blkid_probe_get_sb(pr, mag, struct ubifs_sb_node); + if (!sb) +- return -1; ++ return errno ? -errno : 1; + + blkid_probe_set_uuid(pr, sb->uuid); + blkid_probe_sprintf_version(pr, "w%dr%d", +diff -up util-linux-2.23.2/libblkid/src/superblocks/udf.c.kzak util-linux-2.23.2/libblkid/src/superblocks/udf.c +--- util-linux-2.23.2/libblkid/src/superblocks/udf.c.kzak 2013-06-13 09:46:10.426650673 +0200 ++++ util-linux-2.23.2/libblkid/src/superblocks/udf.c 2014-03-28 15:11:44.683552047 +0100 +@@ -85,11 +85,11 @@ static int probe_udf(blkid_probe pr, + UDF_VSD_OFFSET + b, + sizeof(*vsd)); + if (!vsd) +- return 1; ++ return errno ? -errno : 1; + if (vsd->id[0] != '\0') + goto nsr; + } +- return -1; ++ return 1; + + nsr: + /* search the list of VSDs for a NSR descriptor */ +@@ -99,15 +99,15 @@ nsr: + UDF_VSD_OFFSET + ((blkid_loff_t) b * 0x800), + sizeof(*vsd)); + if (!vsd) +- return -1; ++ return errno ? -errno : 1; + if (vsd->id[0] == '\0') +- return -1; ++ return 1; + if (memcmp(vsd->id, "NSR02", 5) == 0) + goto anchor; + if (memcmp(vsd->id, "NSR03", 5) == 0) + goto anchor; + } +- return -1; ++ return 1; + + anchor: + /* read Anchor Volume Descriptor (AVDP), checking block size */ +@@ -115,7 +115,7 @@ anchor: + vd = (struct volume_descriptor *) + blkid_probe_get_buffer(pr, 256 * pbs[i], sizeof(*vd)); + if (!vd) +- return -1; ++ return errno ? -errno : 1; + + type = le16_to_cpu(vd->tag.id); + if (type == 2) /* TAG_ID_AVDP */ +@@ -138,7 +138,7 @@ real_blksz: + (blkid_loff_t) (loc + b) * bs, + sizeof(*vd)); + if (!vd) +- return -1; ++ return errno ? -errno : 1; + } + + /* Try extract all possible ISO9660 information -- if there is +@@ -155,7 +155,7 @@ real_blksz: + (blkid_loff_t) (loc + b) * bs, + sizeof(*vd)); + if (!vd) +- return -1; ++ return errno ? -errno : 1; + type = le16_to_cpu(vd->tag.id); + if (type == 0) + break; +diff -up util-linux-2.23.2/libblkid/src/superblocks/ufs.c.kzak util-linux-2.23.2/libblkid/src/superblocks/ufs.c +--- util-linux-2.23.2/libblkid/src/superblocks/ufs.c.kzak 2013-04-08 17:55:40.263856264 +0200 ++++ util-linux-2.23.2/libblkid/src/superblocks/ufs.c 2014-03-28 15:11:44.683552047 +0100 +@@ -185,7 +185,7 @@ static int probe_ufs(blkid_probe pr, + offsets[i] * 1024, + sizeof(struct ufs_super_block)); + if (!ufs) +- return -1; ++ return errno ? -errno : 1; + + magBE = be32_to_cpu(ufs->fs_magic); + magLE = le32_to_cpu(ufs->fs_magic); +@@ -231,7 +231,7 @@ found: + offsetof(struct ufs_super_block, fs_magic), + sizeof(ufs->fs_magic), + (unsigned char *) &ufs->fs_magic)) +- return -1; ++ return 1; + + return 0; + } +diff -up util-linux-2.23.2/libblkid/src/superblocks/vfat.c.kzak util-linux-2.23.2/libblkid/src/superblocks/vfat.c +--- util-linux-2.23.2/libblkid/src/superblocks/vfat.c.kzak 2013-06-13 09:46:10.426650673 +0200 ++++ util-linux-2.23.2/libblkid/src/superblocks/vfat.c 2014-03-28 15:12:28.036993622 +0100 +@@ -255,16 +255,20 @@ int blkid_probe_is_vfat(blkid_probe pr) + struct vfat_super_block *vs; + struct msdos_super_block *ms; + const struct blkid_idmag *mag = NULL; ++ int rc; + +- if (blkid_probe_get_idmag(pr, &vfat_idinfo, NULL, &mag) || !mag) ++ rc = blkid_probe_get_idmag(pr, &vfat_idinfo, NULL, &mag); ++ if (rc < 0) ++ return rc; /* error */ ++ if (rc != BLKID_PROBE_OK || !mag) + return 0; + + ms = blkid_probe_get_sb(pr, mag, struct msdos_super_block); + if (!ms) +- return 0; ++ return errno ? -errno : 0; + vs = blkid_probe_get_sb(pr, mag, struct vfat_super_block); + if (!vs) +- return 0; ++ return errno ? -errno : 0; + + return fat_valid_superblock(mag, ms, vs, NULL, NULL); + } +@@ -283,10 +287,12 @@ static int probe_vfat(blkid_probe pr, co + + ms = blkid_probe_get_sb(pr, mag, struct msdos_super_block); + if (!ms) +- return 0; ++ return errno ? -errno : 1; ++ + vs = blkid_probe_get_sb(pr, mag, struct vfat_super_block); + if (!vs) +- return 0; ++ return errno ? -errno : 1; ++ + if (!fat_valid_superblock(mag, ms, vs, &cluster_count, &fat_size)) + return 1; + +@@ -376,16 +382,16 @@ static int probe_vfat(blkid_probe pr, co + (blkid_loff_t) fsinfo_sect * sector_size, + sizeof(struct fat32_fsinfo)); + if (buf == NULL) +- return -1; ++ return errno ? -errno : 1; + + fsinfo = (struct fat32_fsinfo *) buf; + if (memcmp(fsinfo->signature1, "\x52\x52\x61\x41", 4) != 0 && + memcmp(fsinfo->signature1, "\x52\x52\x64\x41", 4) != 0 && + memcmp(fsinfo->signature1, "\x00\x00\x00\x00", 4) != 0) +- return -1; ++ return 1; + if (memcmp(fsinfo->signature2, "\x72\x72\x41\x61", 4) != 0 && + memcmp(fsinfo->signature2, "\x00\x00\x00\x00", 4) != 0) +- return -1; ++ return 1; + } + } + +diff -up util-linux-2.23.2/libblkid/src/superblocks/via_raid.c.kzak util-linux-2.23.2/libblkid/src/superblocks/via_raid.c +--- util-linux-2.23.2/libblkid/src/superblocks/via_raid.c.kzak 2013-04-08 17:55:40.264856273 +0200 ++++ util-linux-2.23.2/libblkid/src/superblocks/via_raid.c 2014-03-28 15:11:44.683552047 +0100 +@@ -52,9 +52,9 @@ static int probe_viaraid(blkid_probe pr, + struct via_metadata *v; + + if (pr->size < 0x10000) +- return -1; ++ return 1; + if (!S_ISREG(pr->mode) && !blkid_probe_is_wholedisk(pr)) +- return -1; ++ return 1; + + off = ((pr->size / 0x200)-1) * 0x200; + +@@ -63,19 +63,19 @@ static int probe_viaraid(blkid_probe pr, + off, + sizeof(struct via_metadata)); + if (!v) +- return -1; ++ return errno ? -errno : 1; + if (le16_to_cpu(v->signature) != VIA_SIGNATURE) +- return -1; ++ return 1; + if (v->version_number > 2) +- return -1; ++ return 1; + if (!via_checksum(v)) +- return -1; ++ return 1; + if (blkid_probe_sprintf_version(pr, "%u", v->version_number) != 0) +- return -1; ++ return 1; + if (blkid_probe_set_magic(pr, off, + sizeof(v->signature), + (unsigned char *) &v->signature)) +- return -1; ++ return 1; + return 0; + } + +diff -up util-linux-2.23.2/libblkid/src/superblocks/vmfs.c.kzak util-linux-2.23.2/libblkid/src/superblocks/vmfs.c +--- util-linux-2.23.2/libblkid/src/superblocks/vmfs.c.kzak 2013-04-08 17:55:40.264856273 +0200 ++++ util-linux-2.23.2/libblkid/src/superblocks/vmfs.c 2014-03-28 15:11:44.683552047 +0100 +@@ -28,7 +28,7 @@ static int probe_vmfs_fs(blkid_probe pr, + + header = blkid_probe_get_sb(pr, mag, struct vmfs_fs_info); + if (header == NULL) +- return -1; ++ return errno ? -errno : 1; + + blkid_probe_sprintf_uuid(pr, (unsigned char *) header->uuid, 16, + "%02x%02x%02x%02x-%02x%02x%02x%02x-" +@@ -53,7 +53,7 @@ static int probe_vmfs_volume(blkid_probe + + header = blkid_probe_get_sb(pr, mag, struct vmfs_volume_info); + if (header == NULL) +- return -1; ++ return errno ? -errno : 1; + + blkid_probe_sprintf_value(pr, "UUID_SUB", + "%02x%02x%02x%02x-%02x%02x%02x%02x-" +diff -up util-linux-2.23.2/libblkid/src/superblocks/vxfs.c.kzak util-linux-2.23.2/libblkid/src/superblocks/vxfs.c +--- util-linux-2.23.2/libblkid/src/superblocks/vxfs.c.kzak 2013-04-08 17:55:40.264856273 +0200 ++++ util-linux-2.23.2/libblkid/src/superblocks/vxfs.c 2014-03-28 15:11:44.683552047 +0100 +@@ -20,7 +20,7 @@ static int probe_vxfs(blkid_probe pr, co + + vxs = blkid_probe_get_sb(pr, mag, struct vxfs_super_block); + if (!vxs) +- return -1; ++ return errno ? -errno : 1; + + blkid_probe_sprintf_version(pr, "%u", (unsigned int) vxs->vs_version); + return 0; +diff -up util-linux-2.23.2/libblkid/src/superblocks/xfs.c.kzak util-linux-2.23.2/libblkid/src/superblocks/xfs.c +--- util-linux-2.23.2/libblkid/src/superblocks/xfs.c.kzak 2013-04-08 17:55:40.265856283 +0200 ++++ util-linux-2.23.2/libblkid/src/superblocks/xfs.c 2014-03-28 15:11:44.683552047 +0100 +@@ -40,7 +40,7 @@ static int probe_xfs(blkid_probe pr, con + + xs = blkid_probe_get_sb(pr, mag, struct xfs_super_block); + if (!xs) +- return -1; ++ return errno ? -errno : 1; + + if (strlen(xs->xs_fname)) + blkid_probe_set_label(pr, (unsigned char *) xs->xs_fname, +diff -up util-linux-2.23.2/libblkid/src/superblocks/zfs.c.kzak util-linux-2.23.2/libblkid/src/superblocks/zfs.c +--- util-linux-2.23.2/libblkid/src/superblocks/zfs.c.kzak 2013-06-13 09:46:10.427650682 +0200 ++++ util-linux-2.23.2/libblkid/src/superblocks/zfs.c 2014-03-28 15:11:44.683552047 +0100 +@@ -185,7 +185,7 @@ static int probe_zfs(blkid_probe pr, + blkid_probe_get_buffer(pr, offset, + sizeof(struct zfs_uberblock)); + if (ub == NULL) +- return -1; ++ return errno ? -errno : 1; + + if (ub->ub_magic == UBERBLOCK_MAGIC) { + ub_offset = offset; +@@ -202,7 +202,7 @@ static int probe_zfs(blkid_probe pr, + } + + if (found < 4) +- return -1; ++ return 1; + + /* If we found the 4th uberblock, then we will have exited from the + * scanning loop immediately, and ub will be a valid uberblock. */ +@@ -214,7 +214,7 @@ static int probe_zfs(blkid_probe pr, + if (blkid_probe_set_magic(pr, ub_offset, + sizeof(ub->ub_magic), + (unsigned char *) &ub->ub_magic)) +- return -1; ++ return 1; + + return 0; + } diff --git a/SOURCES/2.25-libblkid-no-more-probe-for-btrfs-backup-superblock.patch b/SOURCES/2.25-libblkid-no-more-probe-for-btrfs-backup-superblock.patch new file mode 100644 index 0000000..5083b38 --- /dev/null +++ b/SOURCES/2.25-libblkid-no-more-probe-for-btrfs-backup-superblock.patch @@ -0,0 +1,68 @@ +diff -up util-linux-2.23.2/libblkid/src/blkidP.h.kzak util-linux-2.23.2/libblkid/src/blkidP.h +--- util-linux-2.23.2/libblkid/src/blkidP.h.kzak 2013-07-30 10:39:26.205738229 +0200 ++++ util-linux-2.23.2/libblkid/src/blkidP.h 2014-01-23 10:51:10.109593273 +0100 +@@ -224,9 +224,6 @@ struct blkid_struct_probe + + /* private per-probing flags */ + #define BLKID_PROBE_FL_IGNORE_PT (1 << 1) /* ignore partition table */ +-#define BLKID_PROBE_FL_IGNORE_BACKUP (1 << 2) /* ignore backup superblocks or PT */ +- +-extern int blkid_probe_ignore_backup(blkid_probe pr); + + extern blkid_probe blkid_clone_probe(blkid_probe parent); + extern blkid_probe blkid_probe_get_wholedisk_probe(blkid_probe pr); +diff -up util-linux-2.23.2/libblkid/src/probe.c.kzak util-linux-2.23.2/libblkid/src/probe.c +--- util-linux-2.23.2/libblkid/src/probe.c.kzak 2013-07-30 10:39:26.208738259 +0200 ++++ util-linux-2.23.2/libblkid/src/probe.c 2014-01-23 10:51:10.109593273 +0100 +@@ -924,7 +924,8 @@ int blkid_do_probe(blkid_probe pr) + * + * This function erases the current signature detected by @pr. The @pr has to + * be open in O_RDWR mode, BLKID_SUBLKS_MAGIC or/and BLKID_PARTS_MAGIC flags +- * has to be enabled. ++ * has to be enabled (if you want to errase also superblock with broken check ++ * sums then use BLKID_SUBLKS_BADCSUM too). + * + * After successful signature removing the @pr prober will be moved one step + * back and the next blkid_do_probe() call will again call previously called +@@ -1125,8 +1126,6 @@ int blkid_do_safeprobe(blkid_probe pr) + + blkid_probe_start(pr); + +- pr->prob_flags |= BLKID_PROBE_FL_IGNORE_BACKUP; +- + for (i = 0; i < BLKID_NCHAINS; i++) { + struct blkid_chain *chn; + +@@ -1764,8 +1763,3 @@ void blkid_probe_use_wiper(blkid_probe p + blkid_probe_chain_reset_vals(pr, chn); + } + } +- +-int blkid_probe_ignore_backup(blkid_probe pr) +-{ +- return pr && (pr->prob_flags & BLKID_PROBE_FL_IGNORE_BACKUP); +-} +diff -up util-linux-2.23.2/libblkid/src/superblocks/btrfs.c.kzak util-linux-2.23.2/libblkid/src/superblocks/btrfs.c +--- util-linux-2.23.2/libblkid/src/superblocks/btrfs.c.kzak 2013-06-13 09:46:10.421650630 +0200 ++++ util-linux-2.23.2/libblkid/src/superblocks/btrfs.c 2014-01-23 10:51:10.109593273 +0100 +@@ -63,11 +63,6 @@ static int probe_btrfs(blkid_probe pr, c + { + struct btrfs_super_block *bfs; + +- if (mag->kboff > 64 && blkid_probe_ignore_backup(pr)) { +- DBG(LOWPROBE, blkid_debug("btrfs: found backup superblock, ignore")); +- return 1; +- } +- + bfs = blkid_probe_get_sb(pr, mag, struct btrfs_super_block); + if (!bfs) + return -1; +@@ -92,8 +87,6 @@ const struct blkid_idinfo btrfs_idinfo = + .magics = + { + { .magic = "_BHRfS_M", .len = 8, .sboff = 0x40, .kboff = 64 }, +- { .magic = "_BHRfS_M", .len = 8, .sboff = 0x40, .kboff = 64 * 1024 }, +- { .magic = "_BHRfS_M", .len = 8, .sboff = 0x40, .kboff = 256 * 1024 * 1024 }, + { NULL } + } + }; diff --git a/SOURCES/2.25-libblkid-xfs.patch b/SOURCES/2.25-libblkid-xfs.patch new file mode 100644 index 0000000..adc717b --- /dev/null +++ b/SOURCES/2.25-libblkid-xfs.patch @@ -0,0 +1,177 @@ +diff -up util-linux-2.23.2/libblkid/src/superblocks/xfs.c.kzak util-linux-2.23.2/libblkid/src/superblocks/xfs.c +--- util-linux-2.23.2/libblkid/src/superblocks/xfs.c.kzak 2014-09-24 10:59:39.548315524 +0200 ++++ util-linux-2.23.2/libblkid/src/superblocks/xfs.c 2014-09-24 11:02:55.595186026 +0200 +@@ -20,20 +20,143 @@ + #include "superblocks.h" + + struct xfs_super_block { +- unsigned char xs_magic[4]; +- uint32_t xs_blocksize; +- uint64_t xs_dblocks; +- uint64_t xs_rblocks; +- uint32_t xs_dummy1[2]; +- unsigned char xs_uuid[16]; +- uint32_t xs_dummy2[15]; +- char xs_fname[12]; +- uint32_t xs_dummy3[2]; +- uint64_t xs_icount; +- uint64_t xs_ifree; +- uint64_t xs_fdblocks; ++ uint32_t sb_magicnum; /* magic number == XFS_SB_MAGIC */ ++ uint32_t sb_blocksize; /* logical block size, bytes */ ++ uint64_t sb_dblocks; /* number of data blocks */ ++ uint64_t sb_rblocks; /* number of realtime blocks */ ++ uint64_t sb_rextents; /* number of realtime extents */ ++ unsigned char sb_uuid[16]; /* file system unique id */ ++ uint64_t sb_logstart; /* starting block of log if internal */ ++ uint64_t sb_rootino; /* root inode number */ ++ uint64_t sb_rbmino; /* bitmap inode for realtime extents */ ++ uint64_t sb_rsumino; /* summary inode for rt bitmap */ ++ uint32_t sb_rextsize; /* realtime extent size, blocks */ ++ uint32_t sb_agblocks; /* size of an allocation group */ ++ uint32_t sb_agcount; /* number of allocation groups */ ++ uint32_t sb_rbmblocks; /* number of rt bitmap blocks */ ++ uint32_t sb_logblocks; /* number of log blocks */ ++ ++ uint16_t sb_versionnum; /* header version == XFS_SB_VERSION */ ++ uint16_t sb_sectsize; /* volume sector size, bytes */ ++ uint16_t sb_inodesize; /* inode size, bytes */ ++ uint16_t sb_inopblock; /* inodes per block */ ++ char sb_fname[12]; /* file system name */ ++ uint8_t sb_blocklog; /* log2 of sb_blocksize */ ++ uint8_t sb_sectlog; /* log2 of sb_sectsize */ ++ uint8_t sb_inodelog; /* log2 of sb_inodesize */ ++ uint8_t sb_inopblog; /* log2 of sb_inopblock */ ++ uint8_t sb_agblklog; /* log2 of sb_agblocks (rounded up) */ ++ uint8_t sb_rextslog; /* log2 of sb_rextents */ ++ uint8_t sb_inprogress; /* mkfs is in progress, don't mount */ ++ uint8_t sb_imax_pct; /* max % of fs for inode space */ ++ /* statistics */ ++ uint64_t sb_icount; /* allocated inodes */ ++ uint64_t sb_ifree; /* free inodes */ ++ uint64_t sb_fdblocks; /* free data blocks */ ++ uint64_t sb_frextents; /* free realtime extents */ ++ ++ /* this is not all... but enough for libblkid */ ++ + } __attribute__((packed)); + ++#define XFS_MIN_BLOCKSIZE_LOG 9 /* i.e. 512 bytes */ ++#define XFS_MAX_BLOCKSIZE_LOG 16 /* i.e. 65536 bytes */ ++#define XFS_MIN_BLOCKSIZE (1 << XFS_MIN_BLOCKSIZE_LOG) ++#define XFS_MAX_BLOCKSIZE (1 << XFS_MAX_BLOCKSIZE_LOG) ++#define XFS_MIN_SECTORSIZE_LOG 9 /* i.e. 512 bytes */ ++#define XFS_MAX_SECTORSIZE_LOG 15 /* i.e. 32768 bytes */ ++#define XFS_MIN_SECTORSIZE (1 << XFS_MIN_SECTORSIZE_LOG) ++#define XFS_MAX_SECTORSIZE (1 << XFS_MAX_SECTORSIZE_LOG) ++ ++#define XFS_DINODE_MIN_LOG 8 ++#define XFS_DINODE_MAX_LOG 11 ++#define XFS_DINODE_MIN_SIZE (1 << XFS_DINODE_MIN_LOG) ++#define XFS_DINODE_MAX_SIZE (1 << XFS_DINODE_MAX_LOG) ++ ++#define XFS_MAX_RTEXTSIZE (1024 * 1024 * 1024) /* 1GB */ ++#define XFS_DFL_RTEXTSIZE (64 * 1024) /* 64kB */ ++#define XFS_MIN_RTEXTSIZE (4 * 1024) /* 4kB */ ++ ++#define XFS_MIN_AG_BLOCKS 64 ++#define XFS_MAX_DBLOCKS(s) ((uint64_t)(s)->sb_agcount * (s)->sb_agblocks) ++#define XFS_MIN_DBLOCKS(s) ((uint64_t)((s)->sb_agcount - 1) * \ ++ (s)->sb_agblocks + XFS_MIN_AG_BLOCKS) ++ ++ ++static void sb_from_disk(struct xfs_super_block *from, ++ struct xfs_super_block *to) ++{ ++ ++ to->sb_magicnum = be32_to_cpu(from->sb_magicnum); ++ to->sb_blocksize = be32_to_cpu(from->sb_blocksize); ++ to->sb_dblocks = be64_to_cpu(from->sb_dblocks); ++ to->sb_rblocks = be64_to_cpu(from->sb_rblocks); ++ to->sb_rextents = be64_to_cpu(from->sb_rextents); ++ to->sb_logstart = be64_to_cpu(from->sb_logstart); ++ to->sb_rootino = be64_to_cpu(from->sb_rootino); ++ to->sb_rbmino = be64_to_cpu(from->sb_rbmino); ++ to->sb_rsumino = be64_to_cpu(from->sb_rsumino); ++ to->sb_rextsize = be32_to_cpu(from->sb_rextsize); ++ to->sb_agblocks = be32_to_cpu(from->sb_agblocks); ++ to->sb_agcount = be32_to_cpu(from->sb_agcount); ++ to->sb_rbmblocks = be32_to_cpu(from->sb_rbmblocks); ++ to->sb_logblocks = be32_to_cpu(from->sb_logblocks); ++ to->sb_versionnum = be16_to_cpu(from->sb_versionnum); ++ to->sb_sectsize = be16_to_cpu(from->sb_sectsize); ++ to->sb_inodesize = be16_to_cpu(from->sb_inodesize); ++ to->sb_inopblock = be16_to_cpu(from->sb_inopblock); ++ to->sb_blocklog = from->sb_blocklog; ++ to->sb_sectlog = from->sb_sectlog; ++ to->sb_inodelog = from->sb_inodelog; ++ to->sb_inopblog = from->sb_inopblog; ++ to->sb_agblklog = from->sb_agblklog; ++ to->sb_rextslog = from->sb_rextslog; ++ to->sb_inprogress = from->sb_inprogress; ++ to->sb_imax_pct = from->sb_imax_pct; ++ to->sb_icount = be64_to_cpu(from->sb_icount); ++ to->sb_ifree = be64_to_cpu(from->sb_ifree); ++ to->sb_fdblocks = be64_to_cpu(from->sb_fdblocks); ++ to->sb_frextents = be64_to_cpu(from->sb_frextents); ++} ++ ++static int xfs_verify_sb(struct xfs_super_block *ondisk) ++{ ++ struct xfs_super_block sb, *sbp = &sb; ++ ++ /* beXX_to_cpu(), but don't convert UUID and fsname! */ ++ sb_from_disk(ondisk, sbp); ++ ++ /* sanity checks, we don't want to rely on magic string only */ ++ if (sbp->sb_agcount <= 0 || ++ sbp->sb_sectsize < XFS_MIN_SECTORSIZE || ++ sbp->sb_sectsize > XFS_MAX_SECTORSIZE || ++ sbp->sb_sectlog < XFS_MIN_SECTORSIZE_LOG || ++ sbp->sb_sectlog > XFS_MAX_SECTORSIZE_LOG || ++ sbp->sb_sectsize != (1 << sbp->sb_sectlog) || ++ sbp->sb_blocksize < XFS_MIN_BLOCKSIZE || ++ sbp->sb_blocksize > XFS_MAX_BLOCKSIZE || ++ sbp->sb_blocklog < XFS_MIN_BLOCKSIZE_LOG || ++ sbp->sb_blocklog > XFS_MAX_BLOCKSIZE_LOG || ++ sbp->sb_blocksize != (1 << sbp->sb_blocklog) || ++ sbp->sb_inodesize < XFS_DINODE_MIN_SIZE || ++ sbp->sb_inodesize > XFS_DINODE_MAX_SIZE || ++ sbp->sb_inodelog < XFS_DINODE_MIN_LOG || ++ sbp->sb_inodelog > XFS_DINODE_MAX_LOG || ++ sbp->sb_inodesize != (1 << sbp->sb_inodelog) || ++ (sbp->sb_blocklog - sbp->sb_inodelog != sbp->sb_inopblog) || ++ (sbp->sb_rextsize * sbp->sb_blocksize > XFS_MAX_RTEXTSIZE) || ++ (sbp->sb_rextsize * sbp->sb_blocksize < XFS_MIN_RTEXTSIZE) || ++ (sbp->sb_imax_pct > 100 /* zero sb_imax_pct is valid */) || ++ sbp->sb_dblocks == 0 || ++ sbp->sb_dblocks > XFS_MAX_DBLOCKS(sbp) || ++ sbp->sb_dblocks < XFS_MIN_DBLOCKS(sbp)) ++ return 0; ++ ++ /* TODO: version 5 has also checksum CRC32, maybe we can check it too */ ++ ++ return 1; ++} ++ + static int probe_xfs(blkid_probe pr, const struct blkid_idmag *mag) + { + struct xfs_super_block *xs; +@@ -42,10 +165,13 @@ static int probe_xfs(blkid_probe pr, con + if (!xs) + return errno ? -errno : 1; + +- if (strlen(xs->xs_fname)) +- blkid_probe_set_label(pr, (unsigned char *) xs->xs_fname, +- sizeof(xs->xs_fname)); +- blkid_probe_set_uuid(pr, xs->xs_uuid); ++ if (!xfs_verify_sb(xs)) ++ return 1; ++ ++ if (strlen(xs->sb_fname)) ++ blkid_probe_set_label(pr, (unsigned char *) xs->sb_fname, ++ sizeof(xs->sb_fname)); ++ blkid_probe_set_uuid(pr, xs->sb_uuid); + return 0; + } + diff --git a/SOURCES/2.25-lscpu-d_type.patch b/SOURCES/2.25-lscpu-d_type.patch new file mode 100644 index 0000000..b6055af --- /dev/null +++ b/SOURCES/2.25-lscpu-d_type.patch @@ -0,0 +1,12 @@ +diff -up util-linux-2.23.2/sys-utils/lscpu.c.kzak util-linux-2.23.2/sys-utils/lscpu.c +--- util-linux-2.23.2/sys-utils/lscpu.c.kzak 2014-09-24 10:27:29.410899893 +0200 ++++ util-linux-2.23.2/sys-utils/lscpu.c 2014-09-24 10:33:20.960254060 +0200 +@@ -809,7 +809,7 @@ static inline int is_node_dirent(struct + return + d && + #ifdef _DIRENT_HAVE_D_TYPE +- d->d_type == DT_DIR && ++ (d->d_type == DT_DIR || d->d_type == DT_UNKNOWN) && + #endif + strncmp(d->d_name, "node", 4) == 0 && + isdigit_string(d->d_name + 4); diff --git a/SOURCES/2.25-lscpu-discontinuous-NUMA-nodes.patch b/SOURCES/2.25-lscpu-discontinuous-NUMA-nodes.patch new file mode 100644 index 0000000..6428857 --- /dev/null +++ b/SOURCES/2.25-lscpu-discontinuous-NUMA-nodes.patch @@ -0,0 +1,102 @@ +diff -up util-linux-2.23.2/sys-utils/lscpu.c.kzak util-linux-2.23.2/sys-utils/lscpu.c +--- util-linux-2.23.2/sys-utils/lscpu.c.kzak 2013-07-30 10:39:26.342739583 +0200 ++++ util-linux-2.23.2/sys-utils/lscpu.c 2014-01-14 11:21:51.837599200 +0100 +@@ -49,6 +49,7 @@ + /* /sys paths */ + #define _PATH_SYS_SYSTEM "/sys/devices/system" + #define _PATH_SYS_CPU _PATH_SYS_SYSTEM "/cpu" ++#define _PATH_SYS_NODE _PATH_SYS_SYSTEM "/node" + #define _PATH_PROC_XEN "/proc/xen" + #define _PATH_PROC_XENCAP _PATH_PROC_XEN "/capabilities" + #define _PATH_PROC_CPUINFO "/proc/cpuinfo" +@@ -157,6 +158,7 @@ struct lscpu_desc { + cpu_set_t *online; /* mask with online CPUs */ + + int nnodes; /* number of NUMA modes */ ++ int *idx2nodenum; /* Support for discontinuous nodes */ + cpu_set_t **nodemaps; /* array with NUMA nodes */ + + /* books -- based on book_siblings (internal kernel map of cpuX's +@@ -802,25 +804,59 @@ read_cache(struct lscpu_desc *desc, int + } + } + ++static inline int is_node_dirent(struct dirent *d) ++{ ++ return ++ d && ++#ifdef _DIRENT_HAVE_D_TYPE ++ d->d_type == DT_DIR && ++#endif ++ strncmp(d->d_name, "node", 4) == 0 && ++ isdigit_string(d->d_name + 4); ++} ++ + static void + read_nodes(struct lscpu_desc *desc) + { +- int i; ++ int i = 0; ++ DIR *dir; ++ struct dirent *d; ++ char *path; + + /* number of NUMA node */ +- while (path_exist(_PATH_SYS_SYSTEM "/node/node%d", desc->nnodes)) +- desc->nnodes++; ++ path = path_strdup(_PATH_SYS_NODE); ++ dir = opendir(path); ++ free(path); ++ ++ while (dir && (d = readdir(dir))) { ++ if (is_node_dirent(d)) ++ desc->nnodes++; ++ } + +- if (!desc->nnodes) ++ if (!desc->nnodes) { ++ if (dir) ++ closedir(dir); + return; ++ } + + desc->nodemaps = xcalloc(desc->nnodes, sizeof(cpu_set_t *)); ++ desc->idx2nodenum = xmalloc(desc->nnodes * sizeof(int)); ++ ++ if (dir) { ++ rewinddir(dir); ++ while ((d = readdir(dir)) && i < desc->nnodes) { ++ if (is_node_dirent(d)) ++ desc->idx2nodenum[i++] = strtol_or_err(((d->d_name) + 4), ++ _("Failed to extract the node number")); ++ } ++ closedir(dir); ++ } + + /* information about how nodes share different CPUs */ + for (i = 0; i < desc->nnodes; i++) + desc->nodemaps[i] = path_read_cpuset(maxcpus, + _PATH_SYS_SYSTEM "/node/node%d/cpumap", +- i); ++ desc->idx2nodenum[i]); + } + + static char * +@@ -850,7 +886,7 @@ get_cell_data(struct lscpu_desc *desc, i + case COL_NODE: + if (cpuset_ary_isset(cpu, desc->nodemaps, + desc->nnodes, setsize, &idx) == 0) +- snprintf(buf, bufsz, "%zd", idx); ++ snprintf(buf, bufsz, "%d", desc->idx2nodenum[idx]); + break; + case COL_BOOK: + if (cpuset_ary_isset(cpu, desc->bookmaps, +@@ -1250,7 +1286,7 @@ print_summary(struct lscpu_desc *desc, s + } + + for (i = 0; i < desc->nnodes; i++) { +- snprintf(buf, sizeof(buf), _("NUMA node%d CPU(s):"), i); ++ snprintf(buf, sizeof(buf), _("NUMA node%d CPU(s):"), desc->idx2nodenum[i]); + print_cpuset(buf, desc->nodemaps[i], mod->hex); + } + } diff --git a/SOURCES/2.25-lscpu-sort-NUMA.patch b/SOURCES/2.25-lscpu-sort-NUMA.patch new file mode 100644 index 0000000..2055d2d --- /dev/null +++ b/SOURCES/2.25-lscpu-sort-NUMA.patch @@ -0,0 +1,144 @@ +diff -up util-linux-2.23.2/sys-utils/lscpu.c.kzak util-linux-2.23.2/sys-utils/lscpu.c +--- util-linux-2.23.2/sys-utils/lscpu.c.kzak 2014-01-14 14:02:52.228996385 +0100 ++++ util-linux-2.23.2/sys-utils/lscpu.c 2014-01-14 14:04:08.109795733 +0100 +@@ -815,6 +815,13 @@ static inline int is_node_dirent(struct + isdigit_string(d->d_name + 4); + } + ++static int ++nodecmp(const void *ap, const void *bp) ++{ ++ int *a = (int *) ap, *b = (int *) bp; ++ return *a - *b; ++} ++ + static void + read_nodes(struct lscpu_desc *desc) + { +@@ -850,6 +857,7 @@ read_nodes(struct lscpu_desc *desc) + _("Failed to extract the node number")); + } + closedir(dir); ++ qsort(desc->idx2nodenum, desc->nnodes, sizeof(int), nodecmp); + } + + /* information about how nodes share different CPUs */ +diff -up util-linux-2.23.2/tests/expected/lscpu/lscpu-x86_64-64cpu.kzak util-linux-2.23.2/tests/expected/lscpu/lscpu-x86_64-64cpu +--- util-linux-2.23.2/tests/expected/lscpu/lscpu-x86_64-64cpu.kzak 2013-06-13 09:46:10.551651742 +0200 ++++ util-linux-2.23.2/tests/expected/lscpu/lscpu-x86_64-64cpu 2014-01-14 14:04:29.662022613 +0100 +@@ -4,7 +4,7 @@ On-line CPU(s) list: 0-63 + Thread(s) per core: 2 + Core(s) per socket: 8 + Socket(s): 4 +-NUMA node(s): 1 ++NUMA node(s): 3 + Vendor ID: GenuineIntel + CPU family: 6 + Model: 46 +@@ -18,72 +18,74 @@ L1i cache: 32K + L2 cache: 256K + L3 cache: 18432K + NUMA node0 CPU(s): 0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52,54,56,58,60,62 ++NUMA node2 CPU(s): 1,5,9,13,17,21,25,29,33,37,41,45,49,53,57,61 ++NUMA node3 CPU(s): 3,7,11,15,19,23,27,31,35,39,43,47,51,55,59,63 + + # The following is the parsable format, which can be fed to other + # programs. Each different item in every column has an unique ID + # starting from zero. + # CPU,Core,Socket,Node,,L1d,L1i,L2,L3 + 0,0,0,0,,0,0,0,0 +-1,1,1,,,1,1,1,1 ++1,1,1,2,,1,1,1,1 + 2,2,2,0,,2,2,2,2 +-3,3,3,,,3,3,3,3 ++3,3,3,3,,3,3,3,3 + 4,4,0,0,,4,4,4,0 +-5,5,1,,,5,5,5,1 ++5,5,1,2,,5,5,5,1 + 6,6,2,0,,6,6,6,2 +-7,7,3,,,7,7,7,3 ++7,7,3,3,,7,7,7,3 + 8,8,0,0,,8,8,8,0 +-9,9,1,,,9,9,9,1 ++9,9,1,2,,9,9,9,1 + 10,10,2,0,,10,10,10,2 +-11,11,3,,,11,11,11,3 ++11,11,3,3,,11,11,11,3 + 12,12,0,0,,12,12,12,0 +-13,13,1,,,13,13,13,1 ++13,13,1,2,,13,13,13,1 + 14,14,2,0,,14,14,14,2 +-15,15,3,,,15,15,15,3 ++15,15,3,3,,15,15,15,3 + 16,16,0,0,,16,16,16,0 +-17,17,1,,,17,17,17,1 ++17,17,1,2,,17,17,17,1 + 18,18,2,0,,18,18,18,2 +-19,19,3,,,19,19,19,3 ++19,19,3,3,,19,19,19,3 + 20,20,0,0,,20,20,20,0 +-21,21,1,,,21,21,21,1 ++21,21,1,2,,21,21,21,1 + 22,22,2,0,,22,22,22,2 +-23,23,3,,,23,23,23,3 ++23,23,3,3,,23,23,23,3 + 24,24,0,0,,24,24,24,0 +-25,25,1,,,25,25,25,1 ++25,25,1,2,,25,25,25,1 + 26,26,2,0,,26,26,26,2 +-27,27,3,,,27,27,27,3 ++27,27,3,3,,27,27,27,3 + 28,28,0,0,,28,28,28,0 +-29,29,1,,,29,29,29,1 ++29,29,1,2,,29,29,29,1 + 30,30,2,0,,30,30,30,2 +-31,31,3,,,31,31,31,3 ++31,31,3,3,,31,31,31,3 + 32,0,0,0,,0,0,0,0 +-33,1,1,,,1,1,1,1 ++33,1,1,2,,1,1,1,1 + 34,2,2,0,,2,2,2,2 +-35,3,3,,,3,3,3,3 ++35,3,3,3,,3,3,3,3 + 36,4,0,0,,4,4,4,0 +-37,5,1,,,5,5,5,1 ++37,5,1,2,,5,5,5,1 + 38,6,2,0,,6,6,6,2 +-39,7,3,,,7,7,7,3 ++39,7,3,3,,7,7,7,3 + 40,8,0,0,,8,8,8,0 +-41,9,1,,,9,9,9,1 ++41,9,1,2,,9,9,9,1 + 42,10,2,0,,10,10,10,2 +-43,11,3,,,11,11,11,3 ++43,11,3,3,,11,11,11,3 + 44,12,0,0,,12,12,12,0 +-45,13,1,,,13,13,13,1 ++45,13,1,2,,13,13,13,1 + 46,14,2,0,,14,14,14,2 +-47,15,3,,,15,15,15,3 ++47,15,3,3,,15,15,15,3 + 48,16,0,0,,16,16,16,0 +-49,17,1,,,17,17,17,1 ++49,17,1,2,,17,17,17,1 + 50,18,2,0,,18,18,18,2 +-51,19,3,,,19,19,19,3 ++51,19,3,3,,19,19,19,3 + 52,20,0,0,,20,20,20,0 +-53,21,1,,,21,21,21,1 ++53,21,1,2,,21,21,21,1 + 54,22,2,0,,22,22,22,2 +-55,23,3,,,23,23,23,3 ++55,23,3,3,,23,23,23,3 + 56,24,0,0,,24,24,24,0 +-57,25,1,,,25,25,25,1 ++57,25,1,2,,25,25,25,1 + 58,26,2,0,,26,26,26,2 +-59,27,3,,,27,27,27,3 ++59,27,3,3,,27,27,27,3 + 60,28,0,0,,28,28,28,0 +-61,29,1,,,29,29,29,1 ++61,29,1,2,,29,29,29,1 + 62,30,2,0,,30,30,30,2 +-63,31,3,,,31,31,31,3 ++63,31,3,3,,31,31,31,3 diff --git a/SOURCES/2.25-mount-man-xfs.patch b/SOURCES/2.25-mount-man-xfs.patch new file mode 100644 index 0000000..b8973cd --- /dev/null +++ b/SOURCES/2.25-mount-man-xfs.patch @@ -0,0 +1,16 @@ +diff -up util-linux-2.23.2/sys-utils/mount.8.kzak util-linux-2.23.2/sys-utils/mount.8 +--- util-linux-2.23.2/sys-utils/mount.8.kzak 2014-03-12 12:35:46.532369960 +0100 ++++ util-linux-2.23.2/sys-utils/mount.8 2014-03-12 12:35:23.041126143 +0100 +@@ -2598,9 +2598,9 @@ None. + .TP + .BR allocsize=size + Sets the buffered I/O end-of-file preallocation size when +-doing delayed allocation writeout (default size is 64KiB). +-Valid values for this option are page size (typically 4KiB) +-through to 1GiB, inclusive, in power-of-2 increments. ++doing delayed allocation writeout. Valid values for this ++option are page size (typically 4KiB) through to 1GiB, ++inclusive, in power-of-2 increments. + .sp + The default behaviour is for dynamic end-of-file + preallocation size, which uses a set of heuristics to diff --git a/SOURCES/2.25-swapon-discard.patch b/SOURCES/2.25-swapon-discard.patch new file mode 100644 index 0000000..15277ff --- /dev/null +++ b/SOURCES/2.25-swapon-discard.patch @@ -0,0 +1,200 @@ +diff -up util-linux-2.23.2/sys-utils/swapon.8.kzak util-linux-2.23.2/sys-utils/swapon.8 +--- util-linux-2.23.2/sys-utils/swapon.8.kzak 2013-06-13 09:46:10.544651682 +0200 ++++ util-linux-2.23.2/sys-utils/swapon.8 2014-09-24 10:57:45.855230767 +0200 +@@ -112,15 +112,25 @@ All devices marked as ``swap'' in + are made available, except for those with the ``noauto'' option. + Devices that are already being used as swap are silently skipped. + .TP +-.B "\-d, \-\-discard" +-Discard freed swap pages before they are reused, if the swap +-device supports the discard or trim operation. This may improve +-performance on some Solid State Devices, but often it does not. ++.B "\-d, \-\-discard\fR [=\fIpolicy\fR]" ++Enable swap discards, if the swap backing device supports the discard or ++trim operation. This may improve performance on some Solid State Devices, ++but often it does not. The option allows one to select between two ++available swap discard policies: ++.BI \-\-discard=once ++to perform a single-time discard operation for the whole swap area at swapon; ++or ++.BI \-\-discard=pages ++to discard freed swap pages before they are reused, while swapping. ++If no policy is selected, the default behavior is to enable both discard types. + The + .I /etc/fstab +-mount option +-.BI discard +-may be also used to enable discard flag. ++mount options ++.BI discard, ++.BI discard=once, ++or ++.BI discard=pages ++may be also used to enable discard flags. + .TP + .B "\-e, \-\-ifexists" + Silently skip devices that do not exist. +diff -up util-linux-2.23.2/sys-utils/swapon.c.kzak util-linux-2.23.2/sys-utils/swapon.c +--- util-linux-2.23.2/sys-utils/swapon.c.kzak 2013-07-30 10:39:26.348739643 +0200 ++++ util-linux-2.23.2/sys-utils/swapon.c 2014-09-24 10:57:45.855230767 +0200 +@@ -34,9 +34,20 @@ + #endif + + #ifndef SWAP_FLAG_DISCARD +-# define SWAP_FLAG_DISCARD 0x10000 /* discard swap cluster after use */ ++# define SWAP_FLAG_DISCARD 0x10000 /* enable discard for swap */ + #endif + ++#ifndef SWAP_FLAG_DISCARD_ONCE ++# define SWAP_FLAG_DISCARD_ONCE 0x20000 /* discard swap area at swapon-time */ ++#endif ++ ++#ifndef SWAP_FLAG_DISCARD_PAGES ++# define SWAP_FLAG_DISCARD_PAGES 0x40000 /* discard page-clusters after use */ ++#endif ++ ++#define SWAP_FLAGS_DISCARD_VALID (SWAP_FLAG_DISCARD | SWAP_FLAG_DISCARD_ONCE | \ ++ SWAP_FLAG_DISCARD_PAGES) ++ + #ifndef SWAP_FLAG_PREFER + # define SWAP_FLAG_PREFER 0x8000 /* set if swap priority specified */ + #endif +@@ -70,7 +81,7 @@ enum { + + static int all; + static int priority = -1; /* non-prioritized swap by default */ +-static int discard; ++static int discard; /* don't send swap discards by default */ + + /* If true, don't complain if the device/file doesn't exist */ + static int ifexists; +@@ -567,8 +578,22 @@ static int do_swapon(const char *orig_sp + << SWAP_FLAG_PRIO_SHIFT); + } + #endif +- if (fl_discard) +- flags |= SWAP_FLAG_DISCARD; ++ /* ++ * Validate the discard flags passed and set them ++ * accordingly before calling sys_swapon. ++ */ ++ if (fl_discard && !(fl_discard & ~SWAP_FLAGS_DISCARD_VALID)) { ++ /* ++ * If we get here with both discard policy flags set, ++ * we just need to tell the kernel to enable discards ++ * and it will do correctly, just as we expect. ++ */ ++ if ((fl_discard & SWAP_FLAG_DISCARD_ONCE) && ++ (fl_discard & SWAP_FLAG_DISCARD_PAGES)) ++ flags |= SWAP_FLAG_DISCARD; ++ else ++ flags |= fl_discard; ++ } + + status = swapon(special, flags); + if (status < 0) +@@ -608,12 +633,22 @@ static int swapon_all(void) + while (mnt_table_find_next_fs(tb, itr, match_swap, NULL, &fs) == 0) { + /* defaults */ + int pri = priority, dsc = discard, nofail = ifexists; +- char *p, *src; ++ char *p, *src, *dscarg; + + if (mnt_fs_get_option(fs, "noauto", NULL, NULL) == 0) + continue; +- if (mnt_fs_get_option(fs, "discard", NULL, NULL) == 0) +- dsc = 1; ++ if (mnt_fs_get_option(fs, "discard", &dscarg, NULL) == 0) { ++ dsc |= SWAP_FLAG_DISCARD; ++ if (dscarg) { ++ /* only single-time discards are wanted */ ++ if (strcmp(dscarg, "once") == 0) ++ dsc |= SWAP_FLAG_DISCARD_ONCE; ++ ++ /* do discard for every released swap page */ ++ if (strcmp(dscarg, "pages") == 0) ++ dsc |= SWAP_FLAG_DISCARD_PAGES; ++ } ++ } + if (mnt_fs_get_option(fs, "nofail", NULL, NULL) == 0) + nofail = 1; + if (mnt_fs_get_option(fs, "pri", &p, NULL) == 0 && p) +@@ -643,17 +678,17 @@ static void __attribute__ ((__noreturn__ + fprintf(out, _(" %s [options] []\n"), program_invocation_short_name); + + fputs(USAGE_OPTIONS, out); +- fputs(_(" -a, --all enable all swaps from /etc/fstab\n" +- " -d, --discard discard freed pages before they are reused\n" +- " -e, --ifexists silently skip devices that do not exist\n" +- " -f, --fixpgsz reinitialize the swap space if necessary\n" +- " -p, --priority specify the priority of the swap device\n" +- " -s, --summary display summary about used swap devices\n" +- " --show[=] display summary in definable table\n" +- " --noheadings don't print headings, use with --show\n" +- " --raw use the raw output format, use with --show\n" +- " --bytes display swap size in bytes in --show output\n" +- " -v, --verbose verbose mode\n"), out); ++ fputs(_(" -a, --all enable all swaps from /etc/fstab\n" ++ " -d, --discard[=] enable swap discards, if supported by device\n" ++ " -e, --ifexists silently skip devices that do not exist\n" ++ " -f, --fixpgsz reinitialize the swap space if necessary\n" ++ " -p, --priority specify the priority of the swap device\n" ++ " -s, --summary display summary about used swap devices\n" ++ " --show[=] display summary in definable table\n" ++ " --noheadings don't print headings, use with --show\n" ++ " --raw use the raw output format, use with --show\n" ++ " --bytes display swap size in bytes in --show output\n" ++ " -v, --verbose verbose mode\n"), out); + + fputs(USAGE_SEPARATOR, out); + fputs(USAGE_HELP, out); +@@ -669,6 +704,11 @@ static void __attribute__ ((__noreturn__ + " name of device to be used\n" + " name of file to be used\n"), out); + ++ fputs(_("\nAvailable discard policy types (for --discard):\n" ++ " once : only single-time area discards are issued. (swapon)\n" ++ " pages : discard freed pages before they are reused.\n" ++ " * if no policy is selected both discard types are enabled. (default)\n"), out); ++ + fputs(_("\nAvailable columns (for --show):\n"), out); + for (i = 0; i < NCOLS; i++) + fprintf(out, " %4s %s\n", infos[i].name, _(infos[i].help)); +@@ -693,7 +733,7 @@ int main(int argc, char *argv[]) + + static const struct option long_opts[] = { + { "priority", 1, 0, 'p' }, +- { "discard", 0, 0, 'd' }, ++ { "discard", 2, 0, 'd' }, + { "ifexists", 0, 0, 'e' }, + { "summary", 0, 0, 's' }, + { "fixpgsz", 0, 0, 'f' }, +@@ -716,7 +756,7 @@ int main(int argc, char *argv[]) + mnt_init_debug(0); + mntcache = mnt_new_cache(); + +- while ((c = getopt_long(argc, argv, "ahdefp:svVL:U:", ++ while ((c = getopt_long(argc, argv, "ahd::efp:svVL:U:", + long_opts, NULL)) != -1) { + switch (c) { + case 'a': /* all */ +@@ -736,7 +776,18 @@ int main(int argc, char *argv[]) + add_uuid(optarg); + break; + case 'd': +- discard = 1; ++ discard |= SWAP_FLAG_DISCARD; ++ if (optarg) { ++ if (*optarg == '=') ++ optarg++; ++ ++ if (strcmp(optarg, "once") == 0) ++ discard |= SWAP_FLAG_DISCARD_ONCE; ++ else if (strcmp(optarg, "pages") == 0) ++ discard |= SWAP_FLAG_DISCARD_PAGES; ++ else ++ errx(EXIT_FAILURE, _("unsupported discard policy: %s"), optarg); ++ } + break; + case 'e': /* ifexists */ + ifexists = 1; diff --git a/SOURCES/2.25-taskset-man-fix-permissions.patch b/SOURCES/2.25-taskset-man-fix-permissions.patch new file mode 100644 index 0000000..ef97f50 --- /dev/null +++ b/SOURCES/2.25-taskset-man-fix-permissions.patch @@ -0,0 +1,36 @@ +From ab0e0fa7a45bccf8304edcb2a904f30a4f3a48b1 Mon Sep 17 00:00:00 2001 +From: Rik van Riel +Date: Fri, 6 Dec 2013 16:07:54 -0500 +Subject: [PATCH] taskset: fix PERMISSIONS section of taskset man page + +A user is always allowed to change the CPU affinity of his or her +own processes. CAP_SYS_NICE is only required to change the affinity +of another user's process. + +Signed-off-by: Rik van Riel +Reported-by: Joe Mario +--- + schedutils/taskset.1 | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/schedutils/taskset.1 b/schedutils/taskset.1 +index ade202b..fb5738c 100644 +--- a/schedutils/taskset.1 ++++ b/schedutils/taskset.1 +@@ -102,10 +102,11 @@ Or set it: + .B taskset \-p + .I mask pid + .SH PERMISSIONS ++A user can change the CPU affinity of a process belonging to the same user. + A user must possess + .B CAP_SYS_NICE +-to change the CPU affinity of a process. Any user can retrieve the affinity +-mask. ++to change the CPU affinity of a process belonging to another user. ++A user can retrieve the affinity mask of any process. + .SH AUTHOR + Written by Robert M. Love. + .SH COPYRIGHT +-- +1.8.4.2 + diff --git a/SOURCES/2.25-wipefs-call-BLKRRPART-when-erase-partition-table.patch b/SOURCES/2.25-wipefs-call-BLKRRPART-when-erase-partition-table.patch new file mode 100644 index 0000000..260b1ad --- /dev/null +++ b/SOURCES/2.25-wipefs-call-BLKRRPART-when-erase-partition-table.patch @@ -0,0 +1,140 @@ +diff -up util-linux-2.23.2/misc-utils/wipefs.8.kzak util-linux-2.23.2/misc-utils/wipefs.8 +--- util-linux-2.23.2/misc-utils/wipefs.8.kzak 2013-07-30 10:39:26.232738496 +0200 ++++ util-linux-2.23.2/misc-utils/wipefs.8 2014-01-23 11:07:54.390022299 +0100 +@@ -23,6 +23,9 @@ does not erase the filesystem itself nor + When used without options \fB-a\fR or \fB-o\fR, it lists all visible filesystems + and the offsets of their basic signatures. + ++.B wipefs ++calls BLKRRPART ioctl when erase partition table to inform kernel about the change. ++ + Note that some filesystems or some partition tables store more magic strings on + the devices. The + .B wipefs +diff -up util-linux-2.23.2/misc-utils/wipefs.c.kzak util-linux-2.23.2/misc-utils/wipefs.c +--- util-linux-2.23.2/misc-utils/wipefs.c.kzak 2013-07-30 10:39:26.232738496 +0200 ++++ util-linux-2.23.2/misc-utils/wipefs.c 2014-01-23 11:12:26.786860550 +0100 +@@ -40,21 +40,24 @@ + #include "c.h" + #include "closestream.h" + #include "optutils.h" ++#include "blkdev.h" + + struct wipe_desc { + loff_t offset; /* magic string offset */ + size_t len; /* length of magic string */ + unsigned char *magic; /* magic string */ + +- int zap; /* zap this offset? */ + char *usage; /* raid, filesystem, ... */ + char *type; /* FS type */ + char *label; /* FS label */ + char *uuid; /* FS uuid */ + +- int on_disk; +- + struct wipe_desc *next; ++ ++ unsigned int zap : 1, ++ on_disk : 1, ++ is_parttable : 1; ++ + }; + + enum { +@@ -72,7 +75,7 @@ print_pretty(struct wipe_desc *wp, int l + printf("----------------------------------------------------------------\n"); + } + +- printf("0x%-17jx %s [%s]", wp->offset, wp->type, wp->usage); ++ printf("0x%-17jx %s [%s]", wp->offset, wp->type, _(wp->usage)); + + if (wp->label && *wp->label) + printf("\n%27s %s", "LABEL:", wp->label); +@@ -141,7 +144,7 @@ add_offset(struct wipe_desc *wp0, loff_t + wp = xcalloc(1, sizeof(struct wipe_desc)); + wp->offset = offset; + wp->next = wp0; +- wp->zap = zap; ++ wp->zap = zap ? 1 : 0; + return wp; + } + +@@ -164,7 +167,7 @@ get_desc_for_probe(struct wipe_desc *wp, + const char *off, *type, *mag, *p, *usage = NULL; + size_t len; + loff_t offset; +- int rc; ++ int rc, ispt = 0; + + /* superblocks */ + if (blkid_probe_lookup_value(pr, "TYPE", &type, NULL) == 0) { +@@ -181,7 +184,8 @@ get_desc_for_probe(struct wipe_desc *wp, + rc = blkid_probe_lookup_value(pr, "PTMAGIC", &mag, &len); + if (rc) + return wp; +- usage = "partition table"; ++ usage = N_("partition table"); ++ ispt = 1; + } else + return wp; + +@@ -199,6 +203,7 @@ get_desc_for_probe(struct wipe_desc *wp, + + wp->type = xstrdup(type); + wp->on_disk = 1; ++ wp->is_parttable = ispt ? 1 : 0; + + wp->magic = xmalloc(len); + memcpy(wp->magic, mag, len); +@@ -309,10 +314,25 @@ static void do_wipe_real(blkid_probe pr, + putchar('\n'); + } + ++ ++static void rereadpt(int fd, const char *devname) ++{ ++#ifdef BLKRRPART ++ struct stat st; ++ ++ if (fstat(fd, &st) || !S_ISBLK(st.st_mode)) ++ return; ++ ++ errno = 0; ++ ioctl(fd, BLKRRPART); ++ printf(_("%s: calling ioclt to re-read partition table: %m\n"), devname); ++#endif ++} ++ + static struct wipe_desc * + do_wipe(struct wipe_desc *wp, const char *devname, int noact, int all, int quiet, int force) + { +- int flags; ++ int flags, reread = 0; + blkid_probe pr; + struct wipe_desc *w, *wp0; + int zap = all ? 1 : wp->zap; +@@ -345,8 +365,11 @@ do_wipe(struct wipe_desc *wp, const char + if (!wp->on_disk) + continue; + +- if (zap) ++ if (zap) { + do_wipe_real(pr, devname, wp, noact, quiet); ++ if (wp->is_parttable) ++ reread = 1; ++ } + } + + for (w = wp0; w != NULL; w = w->next) { +@@ -355,6 +378,10 @@ do_wipe(struct wipe_desc *wp, const char + } + + fsync(blkid_probe_get_fd(pr)); ++ ++ if (reread) ++ rereadpt(blkid_probe_get_fd(pr), devname); ++ + close(blkid_probe_get_fd(pr)); + blkid_free_probe(pr); + free_wipe(wp0); diff --git a/SOURCES/2.25-wipefs-nested-pt.patch b/SOURCES/2.25-wipefs-nested-pt.patch new file mode 100644 index 0000000..a9b97dd --- /dev/null +++ b/SOURCES/2.25-wipefs-nested-pt.patch @@ -0,0 +1,53 @@ +diff -up util-linux-2.23.2/misc-utils/wipefs.8.kzak util-linux-2.23.2/misc-utils/wipefs.8 +--- util-linux-2.23.2/misc-utils/wipefs.8.kzak 2014-09-24 10:41:31.061930168 +0200 ++++ util-linux-2.23.2/misc-utils/wipefs.8 2014-09-24 10:46:30.142783728 +0200 +@@ -37,6 +37,11 @@ table will still be visible by another m + When used with option \fB-a\fR, all magic strings that are visible for libblkid are + erased. + ++Note that by default ++.B wipefs ++does not erase nested partition tables on non-whole disk devices. The option ++\-\-force is required. ++ + .SH OPTIONS + .TP + .BR \-a , " \-\-all" +diff -up util-linux-2.23.2/misc-utils/wipefs.c.kzak util-linux-2.23.2/misc-utils/wipefs.c +--- util-linux-2.23.2/misc-utils/wipefs.c.kzak 2014-09-24 10:41:31.061930168 +0200 ++++ util-linux-2.23.2/misc-utils/wipefs.c 2014-09-24 10:50:07.728859738 +0200 +@@ -332,7 +332,7 @@ static void rereadpt(int fd, const char + static struct wipe_desc * + do_wipe(struct wipe_desc *wp, const char *devname, int noact, int all, int quiet, int force) + { +- int flags, reread = 0; ++ int flags, reread = 0, need_force = 0; + blkid_probe pr; + struct wipe_desc *w, *wp0; + int zap = all ? 1 : wp->zap; +@@ -365,6 +365,15 @@ do_wipe(struct wipe_desc *wp, const char + if (!wp->on_disk) + continue; + ++ if (!force ++ && wp->is_parttable ++ && !blkid_probe_is_wholedisk(pr)) { ++ warnx(_("%s: ignore nested \"%s\" partition " ++ "table on non-whole disk device."), devname, wp->type); ++ need_force = 1; ++ continue; ++ } ++ + if (zap) { + do_wipe_real(pr, devname, wp, noact, quiet); + if (wp->is_parttable) +@@ -377,6 +386,9 @@ do_wipe(struct wipe_desc *wp, const char + warnx(_("%s: offset 0x%jx not found"), devname, w->offset); + } + ++ if (need_force) ++ warnx(_("Use the --force option to force erase.")); ++ + fsync(blkid_probe_get_fd(pr)); + + if (reread) diff --git a/SOURCES/2.26-libsmartcols.patch b/SOURCES/2.26-libsmartcols.patch new file mode 100644 index 0000000..edad5fb --- /dev/null +++ b/SOURCES/2.26-libsmartcols.patch @@ -0,0 +1,5242 @@ +diff -up util-linux-2.23.2/configure.ac.kzak util-linux-2.23.2/configure.ac +--- util-linux-2.23.2/configure.ac.kzak 2013-07-30 10:39:26.188738061 +0200 ++++ util-linux-2.23.2/configure.ac 2014-09-25 14:41:48.980843829 +0200 +@@ -46,6 +46,13 @@ LIBMOUNT_LT_MINOR=1 + LIBMOUNT_LT_MICRO=0 + LIBMOUNT_VERSION_INFO=`expr $LIBMOUNT_LT_MAJOR + $LIBMOUNT_LT_MINOR`:$LIBMOUNT_LT_MICRO:$LIBMOUNT_LT_MINOR + ++dnl libsmartcols version ++LIBSMARTCOLS_VERSION="$PACKAGE_VERSION_MAJOR.$PACKAGE_VERSION_MINOR.$PACKAGE_VERSION_RELEASE" ++LIBSMARTCOLS_LT_MAJOR=1 ++LIBSMARTCOLS_LT_MINOR=1 ++LIBSMARTCOLS_LT_MICRO=0 ++LIBSMARTCOLS_VERSION_INFO=`expr $LIBSMARTCOLS_LT_MAJOR + $LIBSMARTCOLS_LT_MINOR`:$LIBSMARTCOLS_LT_MICRO:$LIBSMARTCOLS_LT_MINOR ++ + # Check whether exec_prefix=/usr: + case $exec_prefix:$prefix in + NONE:NONE | NONE:/usr | /usr:*) +@@ -765,6 +772,18 @@ AC_DEFINE_UNQUOTED(LIBMOUNT_VERSION, "$L + + + dnl ++dnl libsmartcols ++dnl ++UL_BUILD_INIT([libsmartcols], [yes]) ++AM_CONDITIONAL([BUILD_LIBSMARTCOLS], [test "x$build_libsmartcols" = xyes]) ++AM_CONDITIONAL([BUILD_LIBSMARTCOLS_TESTS], [test "x$build_libsmartcols" = xyes -a "x$enable_static" = xyes]) ++ ++AC_SUBST([LIBSMARTCOLS_VERSION]) ++AC_SUBST([LIBSMARTCOLS_VERSION_INFO]) ++AC_DEFINE_UNQUOTED([LIBSMARTCOLS_VERSION], ["$LIBSMARTCOLS_VERSION"], [libsmartcols version string]) ++ ++ ++dnl + dnl libfdisk is enabled all time if possible + dnl + UL_BUILD_INIT([libfdisk], [check]) +@@ -1500,6 +1519,9 @@ libblkid/src/blkid.h + libmount/docs/Makefile + libmount/docs/version.xml + libmount/src/libmount.h ++libsmartcols/docs/Makefile ++libsmartcols/docs/version.xml ++libsmartcols/src/libsmartcols.h + po/Makefile.in + ]) + +diff -up util-linux-2.23.2/include/carefulputc.h.kzak util-linux-2.23.2/include/carefulputc.h +--- util-linux-2.23.2/include/carefulputc.h.kzak 2012-11-29 16:18:33.956147961 +0100 ++++ util-linux-2.23.2/include/carefulputc.h 2014-09-25 14:41:48.980843829 +0200 +@@ -26,4 +26,39 @@ static inline int carefulputc(int c, FIL + return (ret < 0) ? EOF : 0; + } + ++static inline void fputs_quoted(const char *data, FILE *out) ++{ ++ const char *p; ++ ++ fputc('"', out); ++ for (p = data; p && *p; p++) { ++ if ((unsigned char) *p == 0x22 || /* " */ ++ (unsigned char) *p == 0x5c || /* \ */ ++ !isprint((unsigned char) *p) || ++ iscntrl((unsigned char) *p)) { ++ ++ fprintf(out, "\\x%02x", (unsigned char) *p); ++ } else ++ fputc(*p, out); ++ } ++ fputc('"', out); ++} ++ ++static inline void fputs_nonblank(const char *data, FILE *out) ++{ ++ const char *p; ++ ++ for (p = data; p && *p; p++) { ++ if (isblank((unsigned char) *p) || ++ (unsigned char) *p == 0x5c || /* \ */ ++ !isprint((unsigned char) *p) || ++ iscntrl((unsigned char) *p)) { ++ ++ fprintf(out, "\\x%02x", (unsigned char) *p); ++ ++ } else ++ fputc(*p, out); ++ } ++} ++ + #endif /* _CAREFUULPUTC_H */ +diff -up util-linux-2.23.2/include/debug.h.kzak util-linux-2.23.2/include/debug.h +--- util-linux-2.23.2/include/debug.h.kzak 2014-09-25 14:41:48.981843839 +0200 ++++ util-linux-2.23.2/include/debug.h 2014-09-25 14:41:48.981843839 +0200 +@@ -0,0 +1,126 @@ ++/* ++ * Copyright (C) 2014 Ondrej Oprala ++ * ++ * This file may be distributed under the terms of the ++ * GNU Lesser General Public License. ++ */ ++#ifndef UTIL_LINUX_DEBUG_H ++#define UTIL_LINUX_DEBUG_H ++ ++#include ++#include ++ ++struct dbg_mask { char *mname; int val; }; ++#define UL_DEBUG_EMPTY_MASKNAMES {{ NULL, 0 }} ++ ++#define UL_DEBUG_DEFINE_MASK(m) int m ## _debug_mask ++#define UL_DEBUG_DECLARE_MASK(m) extern UL_DEBUG_DEFINE_MASK(m) ++#define UL_DEBUG_DEFINE_MASKANEMS(m) static const struct dbg_mask m ## _masknames[] ++ ++/* p - flag prefix, m - flag postfix */ ++#define UL_DEBUG_DEFINE_FLAG(p, m) p ## m ++ ++/* l - library name, p - flag prefix, m - flag postfix, x - function */ ++#define __UL_DBG(l, p, m, x) \ ++ do { \ ++ if ((p ## m) & l ## _debug_mask) { \ ++ fprintf(stderr, "%d: %s: %8s: ", getpid(), # l, # m); \ ++ x; \ ++ } \ ++ } while (0) ++ ++#define __UL_DBG_CALL(l, p, m, x) \ ++ do { \ ++ if ((p ## m) & l ## _debug_mask) { \ ++ x; \ ++ } \ ++ } while (0) ++ ++#define __UL_DBG_FLUSH(l, p) \ ++ do { \ ++ if (l ## _debug_mask && \ ++ l ## _debug_mask != p ## INIT) { \ ++ fflush(stderr); \ ++ } \ ++ } while (0) ++ ++ ++#define __UL_INIT_DEBUG(lib, pref, mask, env) \ ++ do { \ ++ if (lib ## _debug_mask & pref ## INIT) \ ++ ; \ ++ else if (!mask) { \ ++ char *str = getenv(# env); \ ++ if (str) \ ++ lib ## _debug_mask = parse_envmask(lib ## _masknames, str); \ ++ } else \ ++ lib ## _debug_mask = mask; \ ++ lib ## _debug_mask |= pref ## INIT; \ ++ if (lib ## _debug_mask != pref ## INIT) { \ ++ __UL_DBG(lib, pref, INIT, ul_debug("library debug mask: 0x%04x", \ ++ lib ## _debug_mask)); \ ++ } \ ++ } while (0) ++ ++ ++static inline void __attribute__ ((__format__ (__printf__, 1, 2))) ++ul_debug(const char *mesg, ...) ++{ ++ va_list ap; ++ va_start(ap, mesg); ++ vfprintf(stderr, mesg, ap); ++ va_end(ap); ++ fputc('\n', stderr); ++} ++ ++static inline void __attribute__ ((__format__ (__printf__, 2, 3))) ++ul_debugobj(void *handler, const char *mesg, ...) ++{ ++ va_list ap; ++ ++ if (handler) ++ fprintf(stderr, "[%p]: ", handler); ++ va_start(ap, mesg); ++ vfprintf(stderr, mesg, ap); ++ va_end(ap); ++ fputc('\n', stderr); ++} ++ ++static inline int parse_envmask(const struct dbg_mask const flagnames[], ++ const char *mask) ++{ ++ int res; ++ char *ptr; ++ ++ /* let's check for a numeric mask first */ ++ res = strtoul(mask, &ptr, 0); ++ ++ /* perhaps it's a comma-separated string? */ ++ if (*ptr != '\0' && flagnames) { ++ char *msbuf, *ms, *name; ++ res = 0; ++ ++ ms = msbuf = strdup(mask); ++ if (!ms) ++ return res; ++ ++ while ((name = strtok_r(ms, ",", &ptr))) { ++ size_t i = 0; ++ ms = ptr; ++ ++ while (flagnames[i].mname) { ++ if (!strcmp(name, flagnames[i].mname)) { ++ res |= flagnames[i].val; ++ break; ++ } ++ ++i; ++ } ++ /* nothing else we can do by OR-ing the mask */ ++ if (res == 0xffff) ++ break; ++ } ++ free(msbuf); ++ } ++ return res; ++} ++#endif /* UTIL_LINUX_DEBUG_H */ +diff -up util-linux-2.23.2/include/list.h.kzak util-linux-2.23.2/include/list.h +--- util-linux-2.23.2/include/list.h.kzak 2013-06-13 09:46:10.396650417 +0200 ++++ util-linux-2.23.2/include/list.h 2014-09-25 14:41:48.981843839 +0200 +@@ -212,14 +212,16 @@ _INLINE_ void list_splice(struct list_he + * sentinel head node, "prev" links not maintained. + */ + _INLINE_ struct list_head *merge(int (*cmp)(struct list_head *a, +- struct list_head *b), ++ struct list_head *b, ++ void *data), ++ void *data, + struct list_head *a, struct list_head *b) + { + struct list_head head, *tail = &head; + + while (a && b) { + /* if equal, take 'a' -- important for sort stability */ +- if ((*cmp)(a, b) <= 0) { ++ if ((*cmp)(a, b, data) <= 0) { + tail->next = a; + a = a->next; + } else { +@@ -240,7 +242,9 @@ _INLINE_ struct list_head *merge(int (*c + * throughout. + */ + _INLINE_ void merge_and_restore_back_links(int (*cmp)(struct list_head *a, +- struct list_head *b), ++ struct list_head *b, ++ void *data), ++ void *data, + struct list_head *head, + struct list_head *a, struct list_head *b) + { +@@ -248,7 +252,7 @@ _INLINE_ void merge_and_restore_back_lin + + while (a && b) { + /* if equal, take 'a' -- important for sort stability */ +- if ((*cmp)(a, b) <= 0) { ++ if ((*cmp)(a, b, data) <= 0) { + tail->next = a; + a->prev = tail; + a = a->next; +@@ -268,7 +272,7 @@ _INLINE_ void merge_and_restore_back_lin + * element comparison is needed, so the client's cmp() + * routine can invoke cond_resched() periodically. + */ +- (*cmp)(tail->next, tail->next); ++ (*cmp)(tail->next, tail->next, data); + + tail->next->prev = tail; + tail = tail->next; +@@ -294,7 +298,9 @@ _INLINE_ void merge_and_restore_back_lin + */ + _INLINE_ void list_sort(struct list_head *head, + int (*cmp)(struct list_head *a, +- struct list_head *b)) ++ struct list_head *b, ++ void *data), ++ void *data) + { + struct list_head *part[MAX_LIST_LENGTH_BITS+1]; /* sorted partial lists + -- last slot is a sentinel */ +@@ -316,7 +322,7 @@ _INLINE_ void list_sort(struct list_head + cur->next = NULL; + + for (lev = 0; part[lev]; lev++) { +- cur = merge(cmp, part[lev], cur); ++ cur = merge(cmp, data, part[lev], cur); + part[lev] = NULL; + } + if (lev > max_lev) { +@@ -330,11 +336,12 @@ _INLINE_ void list_sort(struct list_head + + for (lev = 0; lev < max_lev; lev++) + if (part[lev]) +- list = merge(cmp, part[lev], list); ++ list = merge(cmp, data, part[lev], list); + +- merge_and_restore_back_links(cmp, head, part[max_lev], list); ++ merge_and_restore_back_links(cmp, data, head, part[max_lev], list); + } + ++ + #undef _INLINE_ + + #endif /* UTIL_LINUX_LIST_H */ +diff -up util-linux-2.23.2/include/mbsalign.h.kzak util-linux-2.23.2/include/mbsalign.h +--- util-linux-2.23.2/include/mbsalign.h.kzak 2013-06-13 09:46:10.397650425 +0200 ++++ util-linux-2.23.2/include/mbsalign.h 2014-09-25 14:41:48.981843839 +0200 +@@ -1,5 +1,6 @@ + /* Align/Truncate a string in a given screen width + Copyright (C) 2009-2010 Free Software Foundation, Inc. ++ Copyright (C) 2010-2013 Karel Zak + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by +@@ -13,8 +14,9 @@ + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ +- +-#include ++#ifndef UTIL_LINUX_MBSALIGN_H ++# define UTIL_LINUX_MBSALIGN_H ++# include + + typedef enum { MBS_ALIGN_LEFT, MBS_ALIGN_RIGHT, MBS_ALIGN_CENTER } mbs_align_t; + +@@ -43,3 +45,12 @@ extern size_t mbs_truncate(char *str, si + extern size_t mbsalign (const char *src, char *dest, + size_t dest_size, size_t *width, + mbs_align_t align, int flags); ++ ++extern size_t mbs_safe_nwidth(const char *buf, size_t bufsz, size_t *sz); ++extern size_t mbs_safe_width(const char *s); ++ ++extern char *mbs_safe_encode(const char *s, size_t *width); ++extern char *mbs_safe_encode_to_buffer(const char *s, size_t *width, char *buf); ++extern size_t mbs_safe_encode_size(size_t bytes); ++ ++#endif /* UTIL_LINUX_MBSALIGN_H */ +diff -up util-linux-2.23.2/lib/mbsalign.c.kzak util-linux-2.23.2/lib/mbsalign.c +--- util-linux-2.23.2/lib/mbsalign.c.kzak 2013-07-30 10:39:26.203738210 +0200 ++++ util-linux-2.23.2/lib/mbsalign.c 2014-09-25 14:41:48.982843848 +0200 +@@ -23,17 +23,193 @@ + #include + #include + #include ++#include + + #include "c.h" + #include "mbsalign.h" + #include "widechar.h" + +- + #ifdef HAVE_WIDECHAR + /* Replace non printable chars. + Note \t and \n etc. are non printable. + Return 1 if replacement made, 0 otherwise. */ + ++/* ++ * Counts number of cells in multibyte string. For all control and ++ * non-printable chars is the result width enlarged to store \x?? hex ++ * sequence. See mbs_safe_encode(). ++ * ++ * Returns: number of cells, @sz returns number of bytes. ++ */ ++size_t mbs_safe_nwidth(const char *buf, size_t bufsz, size_t *sz) ++{ ++ mbstate_t st; ++ const char *p = buf, *last = buf; ++ size_t width = 0, bytes = 0; ++ ++ memset(&st, 0, sizeof(st)); ++ ++ if (p && *p && bufsz) ++ last = p + (bufsz - 1); ++ ++ while (p && *p && p <= last) { ++ if (iscntrl((unsigned char) *p)) { ++ width += 4, bytes += 4; /* *p encoded to \x?? */ ++ p++; ++ } ++#ifdef HAVE_WIDECHAR ++ else { ++ wchar_t wc; ++ size_t len = mbrtowc(&wc, p, MB_CUR_MAX, &st); ++ ++ if (len == 0) ++ break; ++ ++ if (len == (size_t) -1 || len == (size_t) -2) { ++ len = 1; ++ if (isprint((unsigned char) *p)) ++ width += 1, bytes += 1; ++ else ++ width += 4, bytes += 4; ++ ++ } else if (!iswprint(wc)) { ++ width += len * 4; /* hex encode whole sequence */ ++ bytes += len * 4; ++ } else { ++ width += wcwidth(wc); /* number of cells */ ++ bytes += len; /* number of bytes */ ++ } ++ p += len; ++ } ++#else ++ else if (!isprint((unsigned char) *p)) { ++ width += 4, bytes += 4; /* *p encoded to \x?? */ ++ p++; ++ } else { ++ width++, bytes++; ++ p++; ++ } ++#endif ++ } ++ ++ if (sz) ++ *sz = bytes; ++ return width; ++} ++ ++size_t mbs_safe_width(const char *s) ++{ ++ if (!s || !*s) ++ return 0; ++ return mbs_safe_nwidth(s, strlen(s), NULL); ++} ++ ++/* ++ * Copy @s to @buf and replace control and non-printable chars with ++ * \x?? hex sequence. The @width returns number of cells. ++ * ++ * The @buf has to be big enough to store mbs_safe_encode_size(strlen(s))) ++ * bytes. ++ */ ++char *mbs_safe_encode_to_buffer(const char *s, size_t *width, char *buf) ++{ ++ mbstate_t st; ++ const char *p = s; ++ char *r; ++ size_t sz = s ? strlen(s) : 0; ++ ++ if (!sz || !buf) ++ return NULL; ++ ++ memset(&st, 0, sizeof(st)); ++ ++ r = buf; ++ *width = 0; ++ ++ while (p && *p) { ++ if (iscntrl((unsigned char) *p)) { ++ sprintf(r, "\\x%02x", (unsigned char) *p); ++ r += 4; ++ *width += 4; ++ p++; ++ } ++#ifdef HAVE_WIDECHAR ++ else { ++ wchar_t wc; ++ size_t len = mbrtowc(&wc, p, MB_CUR_MAX, &st); ++ ++ if (len == 0) ++ break; /* end of string */ ++ ++ if (len == (size_t) -1 || len == (size_t) -2) { ++ len = 1; ++ /* ++ * Not valid multibyte sequence -- maybe it's ++ * printable char according to the current locales. ++ */ ++ if (!isprint((unsigned char) *p)) { ++ sprintf(r, "\\x%02x", (unsigned char) *p); ++ r += 4; ++ *width += 4; ++ } else { ++ width++; ++ *r++ = *p; ++ } ++ } else if (!iswprint(wc)) { ++ size_t i; ++ for (i = 0; i < len; i++) { ++ sprintf(r, "\\x%02x", (unsigned char) *p); ++ r += 4; ++ *width += 4; ++ } ++ } else { ++ memcpy(r, p, len); ++ r += len; ++ *width += wcwidth(wc); ++ } ++ p += len; ++ } ++#else ++ else if (!isprint((unsigned char) *p)) { ++ sprintf(r, "\\x%02x", (unsigned char) *p); ++ p++; ++ r += 4; ++ *width += 4; ++ } else { ++ *r++ = *p++; ++ *width++; ++ } ++#endif ++ } ++ ++ *r = '\0'; ++ ++ return buf; ++} ++ ++size_t mbs_safe_encode_size(size_t bytes) ++{ ++ return (bytes * 4) + 1; ++} ++ ++/* ++ * Returns allocated string where all control and non-printable chars are ++ * replaced with \x?? hex sequence. ++ */ ++char *mbs_safe_encode(const char *s, size_t *width) ++{ ++ size_t sz = s ? strlen(s) : 0; ++ char *buf; ++ ++ if (!sz) ++ return NULL; ++ buf = malloc(mbs_safe_encode_size(sz)); ++ if (!buf) ++ return NULL; ++ ++ return mbs_safe_encode_to_buffer(s, width, buf); ++} ++ + static bool + wc_ensure_printable (wchar_t *wchars) + { +@@ -254,8 +430,8 @@ mbsalign_unibyte: + if (dest_size != 0) + { + char *dest_end = dest + dest_size - 1; +- size_t start_spaces = n_spaces / 2 + n_spaces % 2; +- size_t end_spaces = n_spaces / 2; ++ size_t start_spaces; ++ size_t end_spaces; + + switch (align) + { +diff -up util-linux-2.23.2/libsmartcols/COPYING.kzak util-linux-2.23.2/libsmartcols/COPYING +--- util-linux-2.23.2/libsmartcols/COPYING.kzak 2014-09-25 14:41:48.983843858 +0200 ++++ util-linux-2.23.2/libsmartcols/COPYING 2014-09-25 14:41:48.983843858 +0200 +@@ -0,0 +1,8 @@ ++This library is free software; you can redistribute it and/or ++modify it under the terms of the GNU Lesser General Public ++License as published by the Free Software Foundation; either ++version 2.1 of the License, or (at your option) any later ++version. ++ ++The complete text of the license is available in the ++../Documentation/licenses/COPYING.LGPLv2.1 file. +diff -up util-linux-2.23.2/libsmartcols/docs/.gitignore.kzak util-linux-2.23.2/libsmartcols/docs/.gitignore +--- util-linux-2.23.2/libsmartcols/docs/.gitignore.kzak 2014-09-25 14:41:48.983843858 +0200 ++++ util-linux-2.23.2/libsmartcols/docs/.gitignore 2014-09-25 14:41:48.983843858 +0200 +@@ -0,0 +1,18 @@ ++*-decl-list.txt ++*-decl.txt ++*-overrides.txt ++*-undeclared.txt ++*-undocumented.txt ++*-unused.txt ++*.args ++*.bak ++*.hierarchy ++*.interfaces ++*.prerequisites ++*.signals ++*.stamp ++*.types ++html/* ++tmpl/* ++version.xml ++xml/* +diff -up util-linux-2.23.2/libsmartcols/docs/libsmartcols-docs.xml.kzak util-linux-2.23.2/libsmartcols/docs/libsmartcols-docs.xml +--- util-linux-2.23.2/libsmartcols/docs/libsmartcols-docs.xml.kzak 2014-09-25 14:41:48.984843867 +0200 ++++ util-linux-2.23.2/libsmartcols/docs/libsmartcols-docs.xml 2014-09-25 14:41:48.984843867 +0200 +@@ -0,0 +1,52 @@ ++ ++ ++]> ++ ++ ++ libsmartcols Reference Manual ++ for libsmartcols version &version; ++ ++ 2014 ++ Karel Zak <kzak@redhat.com> ++ ++ ++ ++ ++ libsmartcols Overview ++ ++ ++The libsmartcols library is used for smart adaptive formatting of tabular data. ++ ++ ++The library is part of the util-linux package since version 2.25 and is ++available from ftp://ftp.kernel.org/pub/linux/utils/util-linux/. ++ ++ ++ ++ ++ ++ Data manipulation ++ ++ ++ ++ ++ ++ ++ ++ Printing ++ ++ ++ ++ Misc ++ ++ ++ ++ ++ ++ API Index ++ ++ ++ +diff -up util-linux-2.23.2/libsmartcols/docs/libsmartcols-sections.txt.kzak util-linux-2.23.2/libsmartcols/docs/libsmartcols-sections.txt +--- util-linux-2.23.2/libsmartcols/docs/libsmartcols-sections.txt.kzak 2014-09-25 14:41:48.984843867 +0200 ++++ util-linux-2.23.2/libsmartcols/docs/libsmartcols-sections.txt 2014-09-25 14:41:48.984843867 +0200 +@@ -0,0 +1,146 @@ ++
++cell ++libscols_cell ++scols_cell_copy_content ++scols_cell_get_color ++scols_cell_get_data ++scols_cell_get_userdata ++scols_cell_refer_data ++scols_cell_set_color ++scols_cell_set_data ++scols_cell_set_userdata ++scols_cmpstr_cells ++scols_reset_cell ++
++ ++
++column ++libscols_column ++scols_column_get_color ++scols_column_get_flags ++scols_column_get_header ++scols_column_get_whint ++scols_column_is_noextremes ++scols_column_is_right ++scols_column_is_strict_width ++scols_column_is_tree ++scols_column_is_trunc ++scols_column_set_cmpfunc ++scols_column_set_color ++scols_column_set_flags ++scols_column_set_whint ++scols_copy_column ++scols_new_column ++scols_ref_column ++scols_unref_column ++
++ ++
++iter ++libscols_iter ++scols_free_iter ++scols_iter_get_direction ++scols_new_iter ++scols_reset_iter ++
++ ++
++line ++libscols_line ++scols_copy_line ++scols_line_add_child ++scols_line_alloc_cells ++scols_line_free_cells ++scols_line_get_cell ++scols_line_get_color ++scols_line_get_column_cell ++scols_line_get_ncells ++scols_line_get_parent ++scols_line_get_userdata ++scols_line_has_children ++scols_line_next_child ++scols_line_refer_data ++scols_line_remove_child ++scols_line_set_color ++scols_line_set_data ++scols_line_set_userdata ++scols_new_line ++scols_ref_line ++scols_unref_line ++
++ ++
++symbols ++libscols_symbols ++scols_copy_symbols ++scols_new_symbols ++scols_ref_symbols ++scols_symbols_set_branch ++scols_symbols_set_right ++scols_symbols_set_vertical ++scols_unref_symbols ++
++ ++
++table ++libscols_table ++scols_copy_table ++scols_new_table ++scols_ref_table ++scols_table_add_column ++scols_table_add_line ++scols_table_colors_wanted ++scols_table_enable_ascii ++scols_table_enable_colors ++scols_table_enable_export ++scols_table_enable_maxout ++scols_table_enable_noheadings ++scols_table_enable_raw ++scols_table_get_column ++scols_table_get_column_separator ++scols_table_get_line ++scols_table_get_line_separator ++scols_table_get_ncols ++scols_table_get_nlines ++scols_table_get_stream ++scols_table_is_ascii ++scols_table_is_empty ++scols_table_is_export ++scols_table_is_maxout ++scols_table_is_noheadings ++scols_table_is_raw ++scols_table_is_tree ++scols_table_new_column ++scols_table_new_line ++scols_table_next_column ++scols_table_next_line ++scols_table_reduce_termwidth ++scols_table_remove_column ++scols_table_remove_columns ++scols_table_remove_line ++scols_table_remove_lines ++scols_table_set_column_separator ++scols_table_set_line_separator ++scols_table_set_stream ++scols_table_set_symbols ++scols_sort_table ++scols_unref_table ++
++ ++
++table_print ++scols_print_table ++scols_print_table_to_string ++
++ ++
++version-utils ++scols_get_library_version ++scols_parse_version_string ++LIBSMARTCOLS_VERSION ++
++ ++
++init ++scols_init_debug ++
+diff -up util-linux-2.23.2/libsmartcols/docs/Makefile.am.kzak util-linux-2.23.2/libsmartcols/docs/Makefile.am +--- util-linux-2.23.2/libsmartcols/docs/Makefile.am.kzak 2014-09-25 14:41:48.984843867 +0200 ++++ util-linux-2.23.2/libsmartcols/docs/Makefile.am 2014-09-25 14:41:48.984843867 +0200 +@@ -0,0 +1,93 @@ ++## Process this file with automake to produce Makefile.in ++ ++# We require automake 1.10 at least. ++AUTOMAKE_OPTIONS = 1.10 ++ ++# This is a blank Makefile.am for using gtk-doc. ++# Copy this to your project's API docs directory and modify the variables to ++# suit your project. See the GTK+ Makefiles in gtk+/docs/reference for examples ++# of using the various options. ++ ++# The name of the module, e.g. 'glib'. ++DOC_MODULE=libsmartcols ++ ++# Uncomment for versioned docs and specify the version of the module, e.g. '2'. ++#DOC_MODULE_VERSION=2 ++ ++# The top-level SGML file. You can change this if you want to. ++DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.xml ++ ++# The directory containing the source code. Relative to $(srcdir). ++# gtk-doc will search all .c & .h files beneath here for inline comments ++# documenting the functions and macros. ++# e.g. DOC_SOURCE_DIR=../../../gtk ++DOC_SOURCE_DIR=../src ++ ++# Extra options to pass to gtkdoc-scangobj. Not normally needed. ++SCANGOBJ_OPTIONS= ++ ++# Extra options to supply to gtkdoc-scan. ++# e.g. SCAN_OPTIONS=--deprecated-guards="GTK_DISABLE_DEPRECATED" ++SCAN_OPTIONS= ++ ++# Extra options to supply to gtkdoc-mkdb. ++# e.g. MKDB_OPTIONS=--sgml-mode --output-format=xml ++MKDB_OPTIONS=--sgml-mode --output-format=xml --name-space mnt ++ ++# Extra options to supply to gtkdoc-mktmpl ++# e.g. MKTMPL_OPTIONS=--only-section-tmpl ++MKTMPL_OPTIONS= ++ ++# Extra options to supply to gtkdoc-mkhtml ++MKHTML_OPTIONS= ++ ++# Extra options to supply to gtkdoc-fixref. Not normally needed. ++# e.g. FIXXREF_OPTIONS=--extra-dir=../gdk-pixbuf/html --extra-dir=../gdk/html ++FIXXREF_OPTIONS= ++ ++# Used for dependencies. The docs will be rebuilt if any of these change. ++# e.g. HFILE_GLOB=$(top_srcdir)/gtk/*.h ++# e.g. CFILE_GLOB=$(top_srcdir)/gtk/*.c ++HFILE_GLOB=$(top_builddir)/libsmartcols/src/libsmartcols.h ++CFILE_GLOB=$(top_srcdir)/libsmartcols/src/*.c ++ ++# Extra header to include when scanning, which are not under DOC_SOURCE_DIR ++# e.g. EXTRA_HFILES=$(top_srcdir}/contrib/extra.h ++EXTRA_HFILES= ++ ++# Header files to ignore when scanning. Use base file name, no paths ++# e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h ++IGNORE_HFILES=smartcolsP.h ++ ++# Images to copy into HTML directory. ++# e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png ++HTML_IMAGES= ++ ++# Extra SGML files that are included by $(DOC_MAIN_SGML_FILE). ++# e.g. content_files=running.sgml building.sgml changes-2.0.sgml ++content_files = $(builddir)/version.xml ++ ++# SGML files where gtk-doc abbrevations (#GtkWidget) are expanded ++# These files must be listed here *and* in content_files ++# e.g. expand_content_files=running.sgml ++expand_content_files= ++ ++# CFLAGS and LDFLAGS for compiling gtkdoc-scangobj with your library. ++# Only needed if you are using gtkdoc-scangobj to dynamically query widget ++# signals and properties. ++# e.g. GTKDOC_CFLAGS=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS) ++# e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib) ++GTKDOC_CFLAGS= ++GTKDOC_LIBS= ++ ++# This includes the standard gtk-doc make rules, copied by gtkdocize. ++include $(top_srcdir)/config/gtk-doc.make ++ ++# Other files to distribute ++# e.g. EXTRA_DIST += version.xml.in ++EXTRA_DIST += version.xml.in ++ ++# Files not to distribute ++# for --rebuild-types in $(SCAN_OPTIONS), e.g. $(DOC_MODULE).types ++# for --rebuild-sections in $(SCAN_OPTIONS) e.g. $(DOC_MODULE)-sections.txt ++DISTCLEANFILES += version.xml +diff -up util-linux-2.23.2/libsmartcols/docs/version.xml.in.kzak util-linux-2.23.2/libsmartcols/docs/version.xml.in +--- util-linux-2.23.2/libsmartcols/docs/version.xml.in.kzak 2014-09-25 14:41:48.985843877 +0200 ++++ util-linux-2.23.2/libsmartcols/docs/version.xml.in 2014-09-25 14:41:48.984843867 +0200 +@@ -0,0 +1 @@ ++@VERSION@ +diff -up util-linux-2.23.2/libsmartcols/Makemodule.am.kzak util-linux-2.23.2/libsmartcols/Makemodule.am +--- util-linux-2.23.2/libsmartcols/Makemodule.am.kzak 2014-09-25 14:41:48.983843858 +0200 ++++ util-linux-2.23.2/libsmartcols/Makemodule.am 2014-09-25 14:41:48.983843858 +0200 +@@ -0,0 +1,14 @@ ++if BUILD_LIBSMARTCOLS ++ ++include libsmartcols/src/Makemodule.am ++ ++if ENABLE_GTK_DOC ++# Docs uses separate Makefiles ++SUBDIRS += libsmartcols/docs ++endif ++ ++# noinst for RHEL7: pkgconfig_DATA += libsmartcols/smartcols.pc ++PATHFILES += libsmartcols/smartcols.pc ++EXTRA_DIST += libsmartcols/COPYING ++ ++endif # BUILD_LIBSMARTCOLS +diff -up util-linux-2.23.2/libsmartcols/smartcols.pc.in.kzak util-linux-2.23.2/libsmartcols/smartcols.pc.in +--- util-linux-2.23.2/libsmartcols/smartcols.pc.in.kzak 2014-09-25 14:41:48.985843877 +0200 ++++ util-linux-2.23.2/libsmartcols/smartcols.pc.in 2014-09-25 14:41:48.985843877 +0200 +@@ -0,0 +1,10 @@ ++prefix=@prefix@ ++exec_prefix=@exec_prefix@ ++libdir=@usrlib_execdir@ ++includedir=@includedir@ ++ ++Name: smartcols ++Description: table or tree library ++Version: @LIBSMARTCOLS_VERSION@ ++Cflags: -I${includedir}/libsmartcols ++Libs: -L${libdir} -lsmartcols +diff -up util-linux-2.23.2/libsmartcols/src/cell.c.kzak util-linux-2.23.2/libsmartcols/src/cell.c +--- util-linux-2.23.2/libsmartcols/src/cell.c.kzak 2014-09-25 14:41:48.986843886 +0200 ++++ util-linux-2.23.2/libsmartcols/src/cell.c 2014-09-25 14:41:48.986843886 +0200 +@@ -0,0 +1,242 @@ ++/* ++ * cell.c - functions for table handling at the cell level ++ * ++ * Copyright (C) 2014 Ondrej Oprala ++ * Copyright (C) 2014 Karel Zak ++ * ++ * This file may be redistributed under the terms of the ++ * GNU Lesser General Public License. ++ */ ++ ++/** ++ * SECTION: cell ++ * @title: Cell ++ * @short_description: cell API ++ * ++ * An API to access and modify per-cell data and information. Note that cell is ++ * always part of the line. If you destroy (un-reference) a line than it ++ * destroys all line cells too. ++ */ ++ ++ ++#include ++#include ++#include ++#include ++ ++#include "smartcolsP.h" ++ ++/* ++ * The cell has no ref-counting, free() and new() functions. All is ++ * handled by libscols_line. ++ */ ++ ++/** ++ * scols_reset_cell: ++ * @ce: pointer to a struct libscols_cell instance ++ * ++ * Frees the cell's internal data and resets its status. ++ * ++ * Returns: 0, a negative value in case of an error. ++ */ ++int scols_reset_cell(struct libscols_cell *ce) ++{ ++ assert(ce); ++ ++ if (!ce) ++ return -EINVAL; ++ ++ /*DBG(CELL, ul_debugobj(ce, "reset"));*/ ++ free(ce->data); ++ free(ce->color); ++ memset(ce, 0, sizeof(*ce)); ++ return 0; ++} ++ ++/** ++ * scols_cell_set_data: ++ * @ce: a pointer to a struct libscols_cell instance ++ * @str: data (used for scols_printtable()) ++ * ++ * Stores a copy of the @str in @ce. ++ * ++ * Returns: 0, a negative value in case of an error. ++ */ ++int scols_cell_set_data(struct libscols_cell *ce, const char *str) ++{ ++ char *p = NULL; ++ ++ assert(ce); ++ ++ if (!ce) ++ return -EINVAL; ++ if (str) { ++ p = strdup(str); ++ if (!p) ++ return -ENOMEM; ++ } ++ free(ce->data); ++ ce->data = p; ++ return 0; ++} ++ ++/** ++ * scols_cell_refer_data: ++ * @ce: a pointer to a struct libscols_cell instance ++ * @str: data (used for scols_printtable()) ++ * ++ * Adds a reference to @str to @ce. The pointer is deallocated by ++ * scols_reset_cell() or scols_unref_line(). This function is mostly designed ++ * for situations when the data for the cell are already composed in allocated ++ * memory (e.g. asprintf()) to avoid extra unnecessary strdup(). ++ * ++ * Returns: 0, a negative value in case of an error. ++ */ ++int scols_cell_refer_data(struct libscols_cell *ce, char *str) ++{ ++ assert(ce); ++ ++ if (!ce) ++ return -EINVAL; ++ free(ce->data); ++ ce->data = str; ++ return 0; ++} ++ ++/** ++ * scols_cell_get_data: ++ * @ce: a pointer to a struct libscols_cell instance ++ * ++ * Returns: data in @ce or NULL. ++ */ ++const char *scols_cell_get_data(const struct libscols_cell *ce) ++{ ++ assert(ce); ++ return ce ? ce->data : NULL; ++} ++ ++/** ++ * scols_cell_set_userdata: ++ * @ce: a pointer to a struct libscols_cell instance ++ * @data: private user data ++ * ++ * Returns: 0, a negative value in case of an error. ++ */ ++int scols_cell_set_userdata(struct libscols_cell *ce, void *data) ++{ ++ assert(ce); ++ ++ if (!ce) ++ return -EINVAL; ++ ce->userdata = data; ++ return 0; ++} ++ ++/** ++ * scols_cell_get_userdata ++ * @ce: a pointer to a struct libscols_cell instance ++ * ++ * Returns: user data ++ */ ++void *scols_cell_get_userdata(struct libscols_cell *ce) ++{ ++ return ce ? ce->userdata : NULL; ++} ++ ++/** ++ * scols_cmpstr_cells: ++ * @a: pointer to cell ++ * @b: pointer to cell ++ * @data: unused pointer to private data (defined by API) ++ * ++ * Compares cells data by strcmp(). The function is designed for ++ * scols_column_set_cmpfunc() and scols_sort_table(). ++ * ++ * Returns: follows strcmp() return values. ++ */ ++int scols_cmpstr_cells(struct libscols_cell *a, ++ struct libscols_cell *b, ++ __attribute__((__unused__)) void *data) ++{ ++ const char *adata, *bdata; ++ ++ if (a == b) ++ return 0; ++ ++ adata = scols_cell_get_data(a); ++ bdata = scols_cell_get_data(b); ++ ++ if (adata == NULL && bdata == NULL) ++ return 0; ++ if (adata == NULL) ++ return -1; ++ if (bdata == NULL) ++ return 1; ++ return strcmp(adata, bdata); ++} ++ ++/** ++ * scols_cell_set_color: ++ * @ce: a pointer to a struct libscols_cell instance ++ * @color: ESC sequence ++ * ++ * Set the color of @ce to @color. ++ * ++ * Returns: 0, a negative value in case of an error. ++ */ ++int scols_cell_set_color(struct libscols_cell *ce, const char *color) ++{ ++ char *p = NULL; ++ ++ assert(ce); ++ ++ if (!ce) ++ return -EINVAL; ++ if (color) { ++ p = strdup(color); ++ if (!p) ++ return -ENOMEM; ++ } ++ free(ce->color); ++ ce->color = p; ++ return 0; ++} ++ ++/** ++ * scols_cell_get_color: ++ * @ce: a pointer to a struct libscols_cell instance ++ * ++ * Returns: the current color of @ce. ++ */ ++const char *scols_cell_get_color(const struct libscols_cell *ce) ++{ ++ assert(ce); ++ return ce ? ce->color : NULL; ++} ++ ++/** ++ * scols_cell_copy_content: ++ * @dest: a pointer to a struct libscols_cell instance ++ * @src: a pointer to an immutable struct libscols_cell instance ++ * ++ * Copy the contents of @src into @dest. ++ * ++ * Returns: 0, a negative value in case of an error. ++ */ ++int scols_cell_copy_content(struct libscols_cell *dest, ++ const struct libscols_cell *src) ++{ ++ int rc; ++ ++ assert(dest); ++ assert(src); ++ ++ rc = scols_cell_set_data(dest, scols_cell_get_data(src)); ++ if (!rc) ++ rc = scols_cell_set_color(dest, scols_cell_get_color(src)); ++ if (!rc) ++ dest->userdata = src->userdata; ++ ++ DBG(CELL, ul_debugobj((void *) src, "copy into %p", dest)); ++ return rc; ++} +diff -up util-linux-2.23.2/libsmartcols/src/column.c.kzak util-linux-2.23.2/libsmartcols/src/column.c +--- util-linux-2.23.2/libsmartcols/src/column.c.kzak 2014-09-25 14:41:48.986843886 +0200 ++++ util-linux-2.23.2/libsmartcols/src/column.c 2014-09-25 14:41:48.986843886 +0200 +@@ -0,0 +1,337 @@ ++/* ++ * column.c - functions for table handling at the column level ++ * ++ * Copyright (C) 2014 Ondrej Oprala ++ * Copyright (C) 2014 Karel Zak ++ * ++ * This file may be redistributed under the terms of the ++ * GNU Lesser General Public License. ++ */ ++ ++/** ++ * SECTION: column ++ * @title: Column ++ * @short_description: column API ++ * ++ * An API to access and modify per-column data and information. ++ */ ++ ++ ++#include ++#include ++#include ++#include ++ ++#include "smartcolsP.h" ++ ++/** ++ * scols_new_column: ++ * ++ * Allocates space for a new column. ++ * ++ * Returns: a pointer to a new struct libscols_cell instance, NULL in case of an ENOMEM error. ++ */ ++struct libscols_column *scols_new_column(void) ++{ ++ struct libscols_column *cl; ++ ++ cl = calloc(1, sizeof(*cl)); ++ if (!cl) ++ return NULL; ++ DBG(COL, ul_debugobj(cl, "alloc")); ++ cl->refcount = 1; ++ INIT_LIST_HEAD(&cl->cl_columns); ++ return cl; ++} ++ ++/** ++ * scols_ref_column: ++ * @cl: a pointer to a struct libscols_column instance ++ * ++ * Increases the refcount of @cl. ++ */ ++void scols_ref_column(struct libscols_column *cl) ++{ ++ if (cl) ++ cl->refcount++; ++} ++ ++/** ++ * scols_unref_column: ++ * @cl: a pointer to a struct libscols_column instance ++ * ++ * Decreases the refcount of @cl. When the count falls to zero, the instance ++ * is automatically deallocated. ++ */ ++void scols_unref_column(struct libscols_column *cl) ++{ ++ if (cl && --cl->refcount <= 0) { ++ DBG(COL, ul_debugobj(cl, "dealloc")); ++ list_del(&cl->cl_columns); ++ scols_reset_cell(&cl->header); ++ free(cl->color); ++ free(cl); ++ } ++} ++ ++/** ++ * scols_copy_column: ++ * @cl: a pointer to a struct libscols_column instance ++ * ++ * Creates a new column and copies @cl's data over to it. ++ * ++ * Returns: a pointer to a new struct libscols_column instance. ++ */ ++struct libscols_column *scols_copy_column(const struct libscols_column *cl) ++{ ++ struct libscols_column *ret; ++ ++ assert (cl); ++ if (!cl) ++ return NULL; ++ ret = scols_new_column(); ++ if (!ret) ++ return NULL; ++ ++ DBG(COL, ul_debugobj((void *) cl, "copy to %p", ret)); ++ ++ if (scols_column_set_color(ret, cl->color)) ++ goto err; ++ if (scols_cell_copy_content(&ret->header, &cl->header)) ++ goto err; ++ ++ ret->width = cl->width; ++ ret->width_min = cl->width_min; ++ ret->width_max = cl->width_max; ++ ret->width_avg = cl->width_avg; ++ ret->width_hint = cl->width_hint; ++ ret->flags = cl->flags; ++ ret->is_extreme = cl->is_extreme; ++ ++ return ret; ++err: ++ scols_unref_column(ret); ++ return NULL; ++} ++ ++/** ++ * scols_column_set_whint: ++ * @cl: a pointer to a struct libscols_column instance ++ * @whint: a width hint ++ * ++ * Sets the width hint of column @cl to @whint. ++ * ++ * Returns: 0, a negative value in case of an error. ++ */ ++int scols_column_set_whint(struct libscols_column *cl, double whint) ++{ ++ assert(cl); ++ ++ if (!cl) ++ return -EINVAL; ++ ++ cl->width_hint = whint; ++ return 0; ++} ++ ++/** ++ * scols_column_get_whint: ++ * @cl: a pointer to a struct libscols_column instance ++ * ++ * Returns: The width hint of column @cl, a negative value in case of an error. ++ */ ++double scols_column_get_whint(struct libscols_column *cl) ++{ ++ assert(cl); ++ return cl ? cl->width_hint : -EINVAL; ++} ++ ++/** ++ * scols_column_set_flags: ++ * @cl: a pointer to a struct libscols_column instance ++ * @flags: a flag mask ++ * ++ * Sets the flags of @cl to @flags. ++ * ++ * Returns: 0, a negative value in case of an error. ++ */ ++int scols_column_set_flags(struct libscols_column *cl, int flags) ++{ ++ assert(cl); ++ ++ if (!cl) ++ return -EINVAL; ++ ++ cl->flags = flags; ++ return 0; ++} ++ ++/** ++ * scols_column_get_flags: ++ * @cl: a pointer to a struct libscols_column instance ++ * ++ * Returns: The flag mask of @cl, a negative value in case of an error. ++ */ ++int scols_column_get_flags(struct libscols_column *cl) ++{ ++ assert(cl); ++ return cl ? cl->flags : -EINVAL; ++} ++ ++/** ++ * scols_column_get_header: ++ * @cl: a pointer to a struct libscols_column instance ++ * ++ * Returns: A pointer to a struct libscols_cell instance, representing the ++ * header info of column @cl or NULL in case of an error. ++ */ ++struct libscols_cell *scols_column_get_header(struct libscols_column *cl) ++{ ++ assert(cl); ++ return cl ? &cl->header : NULL; ++} ++ ++/** ++ * scols_column_set_color: ++ * @cl: a pointer to a struct libscols_column instance ++ * @color: ESC sequence ++ * ++ * The default color for data cells and column header. ++ * ++ * If you want to set header specific color then use scols_column_get_header() ++ * and scols_cell_set_color(). ++ * ++ * If you want to set data cell specific color the use scols_line_get_cell() + ++ * scols_cell_set_color(). ++ * ++ * Returns: 0, a negative value in case of an error. ++ */ ++int scols_column_set_color(struct libscols_column *cl, const char *color) ++{ ++ char *p = NULL; ++ ++ assert(cl); ++ if (!cl) ++ return -EINVAL; ++ if (color) { ++ p = strdup(color); ++ if (!p) ++ return -ENOMEM; ++ } ++ ++ free(cl->color); ++ cl->color = p; ++ return 0; ++} ++ ++/** ++ * scols_column_get_color: ++ * @cl: a pointer to a struct libscols_column instance ++ * ++ * Returns: The current color setting of the column @cl. ++ */ ++const char *scols_column_get_color(struct libscols_column *cl) ++{ ++ assert(cl); ++ return cl ? cl->color : NULL; ++} ++ ++ ++/** ++ * scols_column_set_cmpfunc: ++ * @cl: column ++ * @cmp: pointer to compare function ++ * @data: private data for cmp function ++ * ++ * Returns: 0, a negative value in case of an error. ++ */ ++int scols_column_set_cmpfunc(struct libscols_column *cl, ++ int (*cmp)(struct libscols_cell *, ++ struct libscols_cell *, ++ void *), ++ void *data) ++{ ++ assert(cl); ++ if (!cl) ++ return -EINVAL; ++ ++ cl->cmpfunc = cmp; ++ cl->cmpfunc_data = data; ++ return 0; ++} ++ ++/** ++ * scols_column_is_trunc: ++ * @cl: a pointer to a struct libscols_column instance ++ * ++ * Gets the value of @cl's flag trunc. ++ * ++ * Returns: trunc flag value, negative value in case of an error. ++ */ ++int scols_column_is_trunc(struct libscols_column *cl) ++{ ++ assert(cl); ++ if (!cl) ++ return -EINVAL; ++ return cl->flags & SCOLS_FL_TRUNC; ++} ++/** ++ * scols_column_is_tree: ++ * @cl: a pointer to a struct libscols_column instance ++ * ++ * Gets the value of @cl's flag tree. ++ * ++ * Returns: tree flag value, negative value in case of an error. ++ */ ++int scols_column_is_tree(struct libscols_column *cl) ++{ ++ assert(cl); ++ if (!cl) ++ return -EINVAL; ++ return cl->flags & SCOLS_FL_TREE; ++} ++/** ++ * scols_column_is_right: ++ * @cl: a pointer to a struct libscols_column instance ++ * ++ * Gets the value of @cl's flag right. ++ * ++ * Returns: right flag value, negative value in case of an error. ++ */ ++int scols_column_is_right(struct libscols_column *cl) ++{ ++ assert(cl); ++ if (!cl) ++ return -EINVAL; ++ return cl->flags & SCOLS_FL_RIGHT; ++} ++/** ++ * scols_column_is_strict_width: ++ * @cl: a pointer to a struct libscols_column instance ++ * ++ * Gets the value of @cl's flag strict_width. ++ * ++ * Returns: strict_width flag value, negative value in case of an error. ++ */ ++int scols_column_is_strict_width(struct libscols_column *cl) ++{ ++ assert(cl); ++ if (!cl) ++ return -EINVAL; ++ return cl->flags & SCOLS_FL_STRICTWIDTH; ++} ++/** ++ * scols_column_is_noextremes: ++ * @cl: a pointer to a struct libscols_column instance ++ * ++ * Gets the value of @cl's flag no_extremes. ++ * ++ * Returns: no_extremes flag value, negative value in case of an error. ++ */ ++int scols_column_is_noextremes(struct libscols_column *cl) ++{ ++ assert(cl); ++ if (!cl) ++ return -EINVAL; ++ return cl->flags & SCOLS_FL_NOEXTREMES; ++} +diff -up util-linux-2.23.2/libsmartcols/src/.gitignore.kzak util-linux-2.23.2/libsmartcols/src/.gitignore +--- util-linux-2.23.2/libsmartcols/src/.gitignore.kzak 2014-09-25 14:41:48.985843877 +0200 ++++ util-linux-2.23.2/libsmartcols/src/.gitignore 2014-09-25 14:41:48.985843877 +0200 +@@ -0,0 +1 @@ ++libsmartcols.h +diff -up util-linux-2.23.2/libsmartcols/src/init.c.kzak util-linux-2.23.2/libsmartcols/src/init.c +--- util-linux-2.23.2/libsmartcols/src/init.c.kzak 2014-09-25 14:41:48.987843896 +0200 ++++ util-linux-2.23.2/libsmartcols/src/init.c 2014-09-25 14:41:48.987843896 +0200 +@@ -0,0 +1,52 @@ ++/* ++ * Copyright (C) 2014 Karel Zak ++ * ++ * This file may be redistributed under the terms of the ++ * GNU Lesser General Public License. ++ */ ++ ++/** ++ * SECTION: init ++ * @title: Library initialization ++ * @short_description: initialize debugging ++ * ++ * The library debug stuff. ++ */ ++ ++#include ++ ++#include "smartcolsP.h" ++ ++UL_DEBUG_DEFINE_MASK(libsmartcols); ++ ++static const struct dbg_mask libsmartcols_masknames [] = { ++ { "all", SCOLS_DEBUG_ALL }, ++ { "cell", SCOLS_DEBUG_CELL }, ++ { "line", SCOLS_DEBUG_LINE }, ++ { "tab", SCOLS_DEBUG_TAB }, ++ { "col", SCOLS_DEBUG_COL }, ++ { "buff", SCOLS_DEBUG_BUFF }, ++ { NULL, 0 } ++}; ++/** ++ * scols_init_debug: ++ * @mask: debug mask (0xffff to enable full debugging) ++ * ++ * If the @mask is not specified, then this function reads ++ * the LIBSMARTCOLS_DEBUG environment variable to get the mask. ++ * ++ * Already initialized debugging stuff cannot be changed. Calling ++ * this function twice has no effect. ++ */ ++void scols_init_debug(int mask) ++{ ++ __UL_INIT_DEBUG(libsmartcols, SCOLS_DEBUG_, mask, LIBSMARTCOLS_DEBUG); ++ ++ if (libsmartcols_debug_mask != SCOLS_DEBUG_INIT) { ++ const char *ver = NULL; ++ ++ scols_get_library_version(&ver); ++ ++ DBG(INIT, ul_debug("library version: %s", ver)); ++ } ++} +diff -up util-linux-2.23.2/libsmartcols/src/iter.c.kzak util-linux-2.23.2/libsmartcols/src/iter.c +--- util-linux-2.23.2/libsmartcols/src/iter.c.kzak 2014-09-25 14:41:48.987843896 +0200 ++++ util-linux-2.23.2/libsmartcols/src/iter.c 2014-09-25 14:41:48.987843896 +0200 +@@ -0,0 +1,74 @@ ++/* ++ * Copyright (C) 2009-2014 Karel Zak ++ * Copyright (C) 2014 Ondrej Oprala ++ * ++ * This file may be redistributed under the terms of the ++ * GNU Lesser General Public License. ++ */ ++ ++/** ++ * SECTION: iter ++ * @title: Iterator ++ * @short_description: unified iterator ++ * ++ * The iterator keeps the direction and the last position ++ * for access to the internal library tables/lists. ++ */ ++ ++#include ++#include ++ ++#include "smartcolsP.h" ++ ++/** ++ * scols_new_iter: ++ * @direction: SCOLS_INTER_{FOR,BACK}WARD direction ++ * ++ * Returns: newly allocated generic libmount iterator. ++ */ ++struct libscols_iter *scols_new_iter(int direction) ++{ ++ struct libscols_iter *itr = calloc(1, sizeof(*itr)); ++ if (!itr) ++ return NULL; ++ itr->direction = direction; ++ return itr; ++} ++ ++/** ++ * scols_free_iter: ++ * @itr: iterator pointer ++ * ++ * Deallocates the iterator. ++ */ ++void scols_free_iter(struct libscols_iter *itr) ++{ ++ free(itr); ++} ++ ++/** ++ * scols_reset_iter: ++ * @itr: iterator pointer ++ * @direction: SCOLS_INTER_{FOR,BACK}WARD or -1 to keep the direction unchanged ++ * ++ * Resets the iterator. ++ */ ++void scols_reset_iter(struct libscols_iter *itr, int direction) ++{ ++ if (direction == -1) ++ direction = itr->direction; ++ ++ memset(itr, 0, sizeof(*itr)); ++ itr->direction = direction; ++} ++ ++/** ++ * scols_iter_get_direction: ++ * @itr: iterator pointer ++ * ++ * Returns: SCOLS_INTER_{FOR,BACK}WARD ++ */ ++int scols_iter_get_direction(struct libscols_iter *itr) ++{ ++ return itr->direction; ++} +diff -up util-linux-2.23.2/libsmartcols/src/libsmartcols.h.in.kzak util-linux-2.23.2/libsmartcols/src/libsmartcols.h.in +--- util-linux-2.23.2/libsmartcols/src/libsmartcols.h.in.kzak 2014-09-25 14:41:48.988843905 +0200 ++++ util-linux-2.23.2/libsmartcols/src/libsmartcols.h.in 2014-09-25 14:41:48.988843905 +0200 +@@ -0,0 +1,229 @@ ++/* ++ * Prints table or tree. ++ * ++ * Copyright (C) 2014 Ondrej Oprala ++ * Copyright (C) 2014 Karel Zak ++ * ++ * This file may be redistributed under the terms of the ++ * GNU Lesser General Public License. ++ */ ++#ifndef _LIBSMARTCOLS_H ++#define _LIBSMARTCOLS_H ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#include ++#include ++#include ++ ++/** ++ * LIBSMARTCOLS_VERSION: ++ * ++ * Library version string ++ */ ++#define LIBSMARTCOLS_VERSION "@LIBSMARTCOLS_VERSION@" ++ ++/** ++ * libscols_iter: ++ * ++ * Generic iterator ++ */ ++struct libscols_iter; ++ ++/** ++ * libscols_symbols: ++ * ++ * Symbol groups for printing tree hierarchies ++ */ ++struct libscols_symbols; ++ ++/** ++ * libscols_cell: ++ * ++ * A cell - the smallest library object ++ */ ++struct libscols_cell; ++ ++/** ++ * libscols_line: ++ * ++ * A line - an array of cells ++ */ ++struct libscols_line; ++ ++/** ++ * libscols_table: ++ * ++ * A table - The most abstract object, encapsulating lines, columns, symbols and cells ++ */ ++struct libscols_table; ++ ++/** ++ * libscols_column: ++ * ++ * A column - defines the number of columns and column names ++ */ ++struct libscols_column; ++ ++/* iter.c */ ++enum { ++ ++ SCOLS_ITER_FORWARD = 0, ++ SCOLS_ITER_BACKWARD ++}; ++ ++/* ++ * Column flags ++ */ ++enum { ++ SCOLS_FL_TRUNC = (1 << 0), /* truncate fields data if necessary */ ++ SCOLS_FL_TREE = (1 << 1), /* use tree "ascii art" */ ++ SCOLS_FL_RIGHT = (1 << 2), /* align to the right */ ++ SCOLS_FL_STRICTWIDTH = (1 << 3), /* don't reduce width if column is empty */ ++ SCOLS_FL_NOEXTREMES = (1 << 4), /* ignore extreme fields when count column width*/ ++}; ++ ++extern struct libscols_iter *scols_new_iter(int direction); ++extern void scols_free_iter(struct libscols_iter *itr); ++extern void scols_reset_iter(struct libscols_iter *itr, int direction); ++extern int scols_iter_get_direction(struct libscols_iter *itr); ++ ++/* init.c */ ++extern void scols_init_debug(int mask); ++ ++/* version.c */ ++extern int scols_parse_version_string(const char *ver_string); ++extern int scols_get_library_version(const char **ver_string); ++ ++/* symbols.c */ ++extern struct libscols_symbols *scols_new_symbols(void); ++extern void scols_ref_symbols(struct libscols_symbols *sy); ++extern void scols_unref_symbols(struct libscols_symbols *sy); ++extern struct libscols_symbols *scols_copy_symbols(const struct libscols_symbols *sb); ++extern int scols_symbols_set_branch(struct libscols_symbols *sb, const char *str); ++extern int scols_symbols_set_vertical(struct libscols_symbols *sb, const char *str); ++extern int scols_symbols_set_right(struct libscols_symbols *sb, const char *str); ++ ++/* cell.c */ ++extern int scols_reset_cell(struct libscols_cell *ce); ++extern int scols_cell_copy_content(struct libscols_cell *dest, ++ const struct libscols_cell *src); ++extern int scols_cell_set_data(struct libscols_cell *ce, const char *str); ++extern int scols_cell_refer_data(struct libscols_cell *ce, char *str); ++extern const char *scols_cell_get_data(const struct libscols_cell *ce); ++extern int scols_cell_set_color(struct libscols_cell *ce, const char *color); ++extern const char *scols_cell_get_color(const struct libscols_cell *ce); ++ ++extern void *scols_cell_get_userdata(struct libscols_cell *ce); ++extern int scols_cell_set_userdata(struct libscols_cell *ce, void *data); ++ ++extern int scols_cmpstr_cells(struct libscols_cell *a, ++ struct libscols_cell *b, void *data); ++/* column.c */ ++extern int scols_column_is_tree(struct libscols_column *cl); ++extern int scols_column_is_trunc(struct libscols_column *cl); ++extern int scols_column_is_right(struct libscols_column *cl); ++extern int scols_column_is_strict_width(struct libscols_column *cl); ++extern int scols_column_is_noextremes(struct libscols_column *cl); ++ ++extern int scols_column_set_flags(struct libscols_column *cl, int flags); ++extern int scols_column_get_flags(struct libscols_column *cl); ++extern struct libscols_column *scols_new_column(void); ++extern void scols_ref_column(struct libscols_column *cl); ++extern void scols_unref_column(struct libscols_column *cl); ++extern struct libscols_column *scols_copy_column(const struct libscols_column *cl); ++extern int scols_column_set_whint(struct libscols_column *cl, double whint); ++extern double scols_column_get_whint(struct libscols_column *cl); ++extern struct libscols_cell *scols_column_get_header(struct libscols_column *cl); ++extern int scols_column_set_color(struct libscols_column *cl, const char *color); ++extern const char *scols_column_get_color(struct libscols_column *cl); ++ ++extern int scols_column_set_cmpfunc(struct libscols_column *cl, ++ int (*cmp)(struct libscols_cell *a, ++ struct libscols_cell *b, void *), ++ void *data); ++ ++/* line.c */ ++extern struct libscols_line *scols_new_line(void); ++extern void scols_ref_line(struct libscols_line *ln); ++extern void scols_unref_line(struct libscols_line *ln); ++extern int scols_line_alloc_cells(struct libscols_line *ln, size_t n); ++extern void scols_line_free_cells(struct libscols_line *ln); ++extern int scols_line_set_userdata(struct libscols_line *ln, void *data); ++extern void *scols_line_get_userdata(struct libscols_line *ln); ++extern int scols_line_remove_child(struct libscols_line *ln, struct libscols_line *child); ++extern int scols_line_add_child(struct libscols_line *ln, struct libscols_line *child); ++extern int scols_line_has_children(struct libscols_line *ln); ++extern int scols_line_next_child(struct libscols_line *ln, ++ struct libscols_iter *itr, struct libscols_line **chld); ++extern struct libscols_line *scols_line_get_parent(struct libscols_line *ln); ++extern int scols_line_set_color(struct libscols_line *ln, const char *color); ++extern const char *scols_line_get_color(struct libscols_line *ln); ++extern size_t scols_line_get_ncells(struct libscols_line *ln); ++extern struct libscols_cell *scols_line_get_cell(struct libscols_line *ln, size_t n); ++extern struct libscols_cell *scols_line_get_column_cell( ++ struct libscols_line *ln, ++ struct libscols_column *cl); ++extern int scols_line_set_data(struct libscols_line *ln, size_t n, const char *data); ++extern int scols_line_refer_data(struct libscols_line *ln, size_t n, char *data); ++extern struct libscols_line *scols_copy_line(struct libscols_line *ln); ++ ++/* table */ ++extern int scols_table_colors_wanted(struct libscols_table *tb); ++extern int scols_table_is_raw(struct libscols_table *tb); ++extern int scols_table_is_ascii(struct libscols_table *tb); ++extern int scols_table_is_noheadings(struct libscols_table *tb); ++extern int scols_table_is_empty(struct libscols_table *tb); ++extern int scols_table_is_export(struct libscols_table *tb); ++extern int scols_table_is_maxout(struct libscols_table *tb); ++extern int scols_table_is_tree(struct libscols_table *tb); ++ ++extern int scols_table_enable_colors(struct libscols_table *tb, int enable); ++extern int scols_table_enable_raw(struct libscols_table *tb, int enable); ++extern int scols_table_enable_ascii(struct libscols_table *tb, int enable); ++extern int scols_table_enable_noheadings(struct libscols_table *tb, int enable); ++extern int scols_table_enable_export(struct libscols_table *tb, int enable); ++extern int scols_table_enable_maxout(struct libscols_table *tb, int enable); ++ ++extern int scols_table_set_column_separator(struct libscols_table *tb, const char *sep); ++extern int scols_table_set_line_separator(struct libscols_table *tb, const char *sep); ++ ++extern struct libscols_table *scols_new_table(void); ++extern void scols_ref_table(struct libscols_table *tb); ++extern void scols_unref_table(struct libscols_table *tb); ++extern int scols_table_add_column(struct libscols_table *tb, struct libscols_column *cl); ++extern int scols_table_remove_column(struct libscols_table *tb, struct libscols_column *cl); ++extern int scols_table_remove_columns(struct libscols_table *tb); ++extern struct libscols_column *scols_table_new_column(struct libscols_table *tb, const char *name, double whint, int flags); ++extern int scols_table_next_column(struct libscols_table *tb, struct libscols_iter *itr, struct libscols_column **cl); ++extern char *scols_table_get_column_separator(struct libscols_table *tb); ++extern char *scols_table_get_line_separator(struct libscols_table *tb); ++extern int scols_table_get_ncols(struct libscols_table *tb); ++extern int scols_table_get_nlines(struct libscols_table *tb); ++extern struct libscols_column *scols_table_get_column(struct libscols_table *tb, size_t n); ++extern int scols_table_add_line(struct libscols_table *tb, struct libscols_line *ln); ++extern int scols_table_remove_line(struct libscols_table *tb, struct libscols_line *ln); ++extern void scols_table_remove_lines(struct libscols_table *tb); ++extern int scols_table_next_line(struct libscols_table *tb, struct libscols_iter *itr, struct libscols_line **ln); ++extern struct libscols_line *scols_table_new_line(struct libscols_table *tb, struct libscols_line *parent); ++extern struct libscols_line *scols_table_get_line(struct libscols_table *tb, size_t n); ++extern struct libscols_table *scols_copy_table(struct libscols_table *tb); ++extern int scols_table_set_symbols(struct libscols_table *tb, struct libscols_symbols *sy); ++ ++extern int scols_table_set_stream(struct libscols_table *tb, FILE *stream); ++extern FILE *scols_table_get_stream(struct libscols_table *tb); ++extern int scols_table_reduce_termwidth(struct libscols_table *tb, size_t reduce); ++ ++extern int scols_sort_table(struct libscols_table *tb, struct libscols_column *cl); ++ ++/* table_print.c */ ++extern int scols_print_table(struct libscols_table *tb); ++extern int scols_print_table_to_string(struct libscols_table *tb, char **data); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif /* _LIBSMARTCOLS_H */ +diff -up util-linux-2.23.2/libsmartcols/src/libsmartcols.sym.kzak util-linux-2.23.2/libsmartcols/src/libsmartcols.sym +--- util-linux-2.23.2/libsmartcols/src/libsmartcols.sym.kzak 2014-09-25 14:41:48.988843905 +0200 ++++ util-linux-2.23.2/libsmartcols/src/libsmartcols.sym 2014-09-25 14:41:48.988843905 +0200 +@@ -0,0 +1,112 @@ ++/* ++ * symbols since util-linux 2.25 ++ */ ++SMARTCOLS_2.25 { ++global: ++ scols_cell_copy_content; ++ scols_cell_get_color; ++ scols_cell_get_data; ++ scols_cell_get_userdata; ++ scols_cell_refer_data; ++ scols_cell_set_color; ++ scols_cell_set_data; ++ scols_cell_set_userdata; ++ scols_cmpstr_cells; ++ scols_column_get_color; ++ scols_column_get_flags; ++ scols_column_get_header; ++ scols_column_get_whint; ++ scols_column_is_noextremes; ++ scols_column_is_right; ++ scols_column_is_strict_width; ++ scols_column_is_tree; ++ scols_column_is_trunc; ++ scols_column_set_cmpfunc; ++ scols_column_set_color; ++ scols_column_set_flags; ++ scols_column_set_whint; ++ scols_copy_column; ++ scols_copy_line; ++ scols_copy_symbols; ++ scols_copy_table; ++ scols_free_iter; ++ scols_get_library_version; ++ scols_init_debug; ++ scols_iter_get_direction; ++ scols_line_add_child; ++ scols_line_alloc_cells; ++ scols_line_free_cells; ++ scols_line_get_cell; ++ scols_line_get_color; ++ scols_line_get_column_cell; ++ scols_line_get_ncells; ++ scols_line_get_parent; ++ scols_line_get_userdata; ++ scols_line_has_children; ++ scols_line_next_child; ++ scols_line_refer_data; ++ scols_line_remove_child; ++ scols_line_set_color; ++ scols_line_set_data; ++ scols_line_set_userdata; ++ scols_new_column; ++ scols_new_iter; ++ scols_new_line; ++ scols_new_symbols; ++ scols_new_table; ++ scols_parse_version_string; ++ scols_print_table; ++ scols_print_table_to_string; ++ scols_ref_column; ++ scols_ref_line; ++ scols_ref_symbols; ++ scols_ref_table; ++ scols_reset_cell; ++ scols_reset_iter; ++ scols_sort_table; ++ scols_symbols_set_branch; ++ scols_symbols_set_right; ++ scols_symbols_set_vertical; ++ scols_table_add_column; ++ scols_table_add_line; ++ scols_table_colors_wanted; ++ scols_table_enable_ascii; ++ scols_table_enable_colors; ++ scols_table_enable_export; ++ scols_table_enable_maxout; ++ scols_table_enable_noheadings; ++ scols_table_enable_raw; ++ scols_table_get_column; ++ scols_table_get_column_separator; ++ scols_table_get_line; ++ scols_table_get_line_separator; ++ scols_table_get_ncols; ++ scols_table_get_nlines; ++ scols_table_get_stream; ++ scols_table_is_ascii; ++ scols_table_is_empty; ++ scols_table_is_export; ++ scols_table_is_maxout; ++ scols_table_is_noheadings; ++ scols_table_is_raw; ++ scols_table_is_tree; ++ scols_table_new_column; ++ scols_table_new_line; ++ scols_table_next_column; ++ scols_table_next_line; ++ scols_table_reduce_termwidth; ++ scols_table_remove_column; ++ scols_table_remove_columns; ++ scols_table_remove_line; ++ scols_table_remove_lines; ++ scols_table_set_column_separator; ++ scols_table_set_line_separator; ++ scols_table_set_stream; ++ scols_table_set_symbols; ++ scols_unref_column; ++ scols_unref_line; ++ scols_unref_symbols; ++ scols_unref_table; ++local: ++ *; ++}; +diff -up util-linux-2.23.2/libsmartcols/src/line.c.kzak util-linux-2.23.2/libsmartcols/src/line.c +--- util-linux-2.23.2/libsmartcols/src/line.c.kzak 2014-09-25 14:41:48.989843915 +0200 ++++ util-linux-2.23.2/libsmartcols/src/line.c 2014-09-25 14:41:48.989843915 +0200 +@@ -0,0 +1,456 @@ ++/* ++ * line.c - functions for table handling at the line level ++ * ++ * Copyright (C) 2014 Karel Zak ++ * Copyright (C) 2014 Ondrej Oprala ++ * ++ * This file may be redistributed under the terms of the ++ * GNU Lesser General Public License. ++ */ ++ ++/** ++ * SECTION: line ++ * @title: Line ++ * @short_description: line API ++ * ++ * An API to access and modify per-line data and information. ++ */ ++ ++ ++#include ++#include ++#include ++#include ++ ++#include "smartcolsP.h" ++ ++/** ++ * scols_new_line: ++ * ++ * Note that the line is allocated without cells, the cells will be allocated ++ * later when you add the line to the table. If you want to use the line ++ * without table then you have to explicitly allocate the cells by ++ * scols_line_alloc_cells(). ++ * ++ * Returns: a pointer to a new struct libscols_line instance. ++ */ ++struct libscols_line *scols_new_line(void) ++{ ++ struct libscols_line *ln; ++ ++ ln = calloc(1, sizeof(*ln)); ++ if (!ln) ++ return NULL; ++ ++ DBG(LINE, ul_debugobj(ln, "alloc")); ++ ln->refcount = 1; ++ INIT_LIST_HEAD(&ln->ln_lines); ++ INIT_LIST_HEAD(&ln->ln_children); ++ INIT_LIST_HEAD(&ln->ln_branch); ++ return ln; ++} ++ ++/** ++ * scols_ref_line: ++ * @ln: a pointer to a struct libscols_line instance ++ * ++ * Increases the refcount of @ln. ++ */ ++void scols_ref_line(struct libscols_line *ln) ++{ ++ if (ln) ++ ln->refcount++; ++} ++ ++/** ++ * scols_unref_line: ++ * @ln: a pointer to a struct libscols_line instance ++ * ++ * Decreases the refcount of @ln. When the count falls to zero, the instance ++ * is automatically deallocated. ++ */ ++void scols_unref_line(struct libscols_line *ln) ++{ ++ ++ if (ln && --ln->refcount <= 0) { ++ DBG(CELL, ul_debugobj(ln, "dealloc")); ++ list_del(&ln->ln_lines); ++ list_del(&ln->ln_children); ++ scols_line_free_cells(ln); ++ free(ln->color); ++ free(ln); ++ return; ++ } ++} ++ ++/** ++ * scols_line_free_cells: ++ * @ln: a pointer to a struct libscols_line instance ++ * ++ * Frees the allocated cells referenced to by @ln. ++ */ ++void scols_line_free_cells(struct libscols_line *ln) ++{ ++ size_t i; ++ ++ if (!ln || !ln->cells) ++ return; ++ ++ DBG(LINE, ul_debugobj(ln, "free cells")); ++ ++ for (i = 0; i < ln->ncells; i++) ++ scols_reset_cell(&ln->cells[i]); ++ ++ free(ln->cells); ++ ln->ncells = 0; ++ ln->cells = NULL; ++} ++ ++/** ++ * scols_line_alloc_cells: ++ * @ln: a pointer to a struct libscols_line instance ++ * @n: the number of elements ++ * ++ * Allocates space for @n cells. This function is optional, ++ * and libsmartcols automatically allocates necessary cells ++ * according to number of columns in the table when you add ++ * the line to the table. See scols_table_add_line(). ++ * ++ * Returns: 0, a negative value in case of an error. ++ */ ++int scols_line_alloc_cells(struct libscols_line *ln, size_t n) ++{ ++ struct libscols_cell *ce; ++ ++ assert(ln); ++ ++ if (!ln) ++ return -EINVAL; ++ if (ln->ncells == n) ++ return 0; ++ ++ if (!n) { ++ scols_line_free_cells(ln); ++ return 0; ++ } ++ ++ DBG(LINE, ul_debugobj(ln, "alloc %zu cells", n)); ++ ++ ce = realloc(ln->cells, n * sizeof(struct libscols_cell)); ++ if (!ce) ++ return -errno; ++ ++ if (n > ln->ncells) ++ memset(ce + ln->ncells, 0, ++ (n - ln->ncells) * sizeof(struct libscols_cell)); ++ ++ ln->cells = ce; ++ ln->ncells = n; ++ return 0; ++} ++ ++/** ++ * scols_line_set_userdata: ++ * @ln: a pointer to a struct libscols_line instance ++ * @data: user data ++ * ++ * Binds @data to @ln. ++ * ++ * Returns: 0, a negative value in case of an error. ++ */ ++int scols_line_set_userdata(struct libscols_line *ln, void *data) ++{ ++ assert(ln); ++ if (!ln) ++ return -EINVAL; ++ ln->userdata = data; ++ return 0; ++} ++ ++/** ++ * scols_line_get_userdata: ++ * @ln: a pointer to a struct libscols_line instance ++ * ++ * Returns: 0, a negative value in case of an error. ++ */ ++void *scols_line_get_userdata(struct libscols_line *ln) ++{ ++ assert(ln); ++ return ln ? ln->userdata : NULL; ++} ++ ++/** ++ * scols_line_remove_child: ++ * @ln: a pointer to a struct libscols_line instance ++ * @child: a pointer to a struct libscols_line instance ++ * ++ * Removes @child as a child of @ln. ++ * ++ * Returns: 0, a negative value in case of an error. ++ */ ++int scols_line_remove_child(struct libscols_line *ln, struct libscols_line *child) ++{ ++ assert(ln); ++ assert(child); ++ ++ if (!ln || !child) ++ return -EINVAL; ++ ++ DBG(LINE, ul_debugobj(ln, "remove child %p", child)); ++ ++ list_del_init(&child->ln_children); ++ child->parent = NULL; ++ scols_unref_line(child); ++ ++ scols_unref_line(ln); ++ return 0; ++} ++ ++/** ++ * scols_line_add_child: ++ * @ln: a pointer to a struct libscols_line instance ++ * @child: a pointer to a struct libscols_line instance ++ * ++ * Sets @child as a child of @ln. ++ * ++ * Returns: 0, a negative value in case of an error. ++ */ ++int scols_line_add_child(struct libscols_line *ln, struct libscols_line *child) ++{ ++ assert(ln); ++ assert(child); ++ ++ if (!ln || !child) ++ return -EINVAL; ++ ++ /* unref old<->parent */ ++ if (child->parent) ++ scols_line_remove_child(child->parent, child); ++ ++ DBG(LINE, ul_debugobj(ln, "add child %p", child)); ++ ++ /* new reference from parent to child */ ++ list_add_tail(&child->ln_children, &ln->ln_branch); ++ scols_ref_line(child); ++ ++ /* new reference from child to parent */ ++ child->parent = ln; ++ scols_ref_line(ln); ++ ++ return 0; ++} ++ ++/** ++ * scols_line_get_parent: ++ * @ln: a pointer to a struct libscols_line instance ++ * ++ * Returns: a pointer to @ln's parent, NULL in case it has no parent or if there was an error. ++ */ ++struct libscols_line *scols_line_get_parent(struct libscols_line *ln) ++{ ++ assert(ln); ++ return ln ? ln->parent : NULL; ++} ++ ++/** ++ * scols_line_has_children: ++ * @ln: a pointer to a struct libscols_line instance ++ * ++ * Returns: 1 if @ln has any children, otherwise 0. ++ */ ++int scols_line_has_children(struct libscols_line *ln) ++{ ++ assert(ln); ++ return ln ? !list_empty(&ln->ln_branch) : 0; ++} ++ ++/** ++ * scols_line_next_child: ++ * @ln: a pointer to a struct libscols_line instance ++ * @itr: a pointer to a struct libscols_iter instance ++ * @chld: a pointer to a pointer to a struct libscols_line instance ++ * ++ * Finds the next child and returns a pointer to it via @chld. ++ * ++ * Returns: 0, a negative value in case of an error. ++ */ ++int scols_line_next_child(struct libscols_line *ln, ++ struct libscols_iter *itr, ++ struct libscols_line **chld) ++{ ++ int rc = 1; ++ ++ if (!ln || !itr || !chld) ++ return -EINVAL; ++ *chld = NULL; ++ ++ if (!itr->head) ++ SCOLS_ITER_INIT(itr, &ln->ln_branch); ++ if (itr->p != itr->head) { ++ SCOLS_ITER_ITERATE(itr, *chld, struct libscols_line, ln_children); ++ rc = 0; ++ } ++ ++ return rc; ++} ++ ++/** ++ * scols_line_set_color: ++ * @ln: a pointer to a struct libscols_line instance ++ * @color: ESC sequence ++ * ++ * Returns: 0, a negative value in case of an error. ++ */ ++int scols_line_set_color(struct libscols_line *ln, const char *color) ++{ ++ char *p = NULL; ++ ++ assert(ln); ++ if (!ln) ++ return -EINVAL; ++ if (color) { ++ p = strdup(color); ++ if (!p) ++ return -ENOMEM; ++ } ++ ++ free(ln->color); ++ ln->color = p; ++ return 0; ++} ++ ++/** ++ * scols_line_get_color: ++ * @ln: a pointer to a struct libscols_line instance ++ * ++ * Returns: @ln's color string, NULL in case of an error. ++ */ ++const char *scols_line_get_color(struct libscols_line *ln) ++{ ++ assert(ln); ++ return ln ? ln->color : NULL; ++} ++ ++/** ++ * scols_line_get_ncells: ++ * @ln: a pointer to a struct libscols_line instance ++ * ++ * Returns: @ln's number of cells ++ */ ++size_t scols_line_get_ncells(struct libscols_line *ln) ++{ ++ assert(ln); ++ return ln ? ln->ncells : 0; ++} ++ ++/** ++ * scols_line_get_cell: ++ * @ln: a pointer to a struct libscols_line instance ++ * @n: cell number to retrieve ++ * ++ * Returns: the @n-th cell in @ln, NULL in case of an error. ++ */ ++struct libscols_cell *scols_line_get_cell(struct libscols_line *ln, ++ size_t n) ++{ ++ assert(ln); ++ ++ if (!ln || n >= ln->ncells) ++ return NULL; ++ return &ln->cells[n]; ++} ++ ++/** ++ * scols_line_get_column_cell: ++ * @ln: a pointer to a struct libscols_line instance ++ * @cl: pointer to cell ++ * ++ * Like scols_line_get_cell() by cell is referenced by column. ++ * ++ * Returns: the @n-th cell in @ln, NULL in case of an error. ++ */ ++struct libscols_cell *scols_line_get_column_cell( ++ struct libscols_line *ln, ++ struct libscols_column *cl) ++{ ++ assert(ln); ++ assert(cl); ++ ++ return scols_line_get_cell(ln, cl->seqnum); ++} ++ ++/** ++ * scols_line_set_data: ++ * @ln: a pointer to a struct libscols_cell instance ++ * @n: number of the cell, whose data is to be set ++ * @data: actual data to set ++ * ++ * Returns: 0, a negative value in case of an error. ++ */ ++int scols_line_set_data(struct libscols_line *ln, size_t n, const char *data) ++{ ++ struct libscols_cell *ce = scols_line_get_cell(ln, n); ++ ++ if (!ce) ++ return -EINVAL; ++ return scols_cell_set_data(ce, data); ++} ++ ++/** ++ * scols_line_refer_data: ++ * @ln: a pointer to a struct libscols_cell instance ++ * @n: number of the cell which will refer to @data ++ * @data: actual data to refer to ++ * ++ * Returns: 0, a negative value in case of an error. ++ */ ++int scols_line_refer_data(struct libscols_line *ln, size_t n, char *data) ++{ ++ struct libscols_cell *ce = scols_line_get_cell(ln, n); ++ ++ if (!ce) ++ return -EINVAL; ++ return scols_cell_refer_data(ce, data); ++} ++ ++/** ++ * scols_copy_line: ++ * @ln: a pointer to a struct libscols_cell instance ++ * ++ * Returns: A newly allocated copy of @ln, NULL in case of an error. ++ */ ++struct libscols_line *scols_copy_line(struct libscols_line *ln) ++{ ++ struct libscols_line *ret; ++ size_t i; ++ ++ assert (ln); ++ if (!ln) ++ return NULL; ++ ++ ret = scols_new_line(); ++ if (!ret) ++ return NULL; ++ if (scols_line_set_color(ret, ln->color)) ++ goto err; ++ if (scols_line_alloc_cells(ret, ln->ncells)) ++ goto err; ++ ++ ret->userdata = ln->userdata; ++ ret->ncells = ln->ncells; ++ ret->seqnum = ln->seqnum; ++ ++ DBG(LINE, ul_debugobj(ln, "copy to %p", ret)); ++ ++ for (i = 0; i < ret->ncells; ++i) { ++ if (scols_cell_copy_content(&ret->cells[i], &ln->cells[i])) ++ goto err; ++ } ++ ++ return ret; ++err: ++ scols_unref_line(ret); ++ return NULL; ++} ++ ++ +diff -up util-linux-2.23.2/libsmartcols/src/Makemodule.am.kzak util-linux-2.23.2/libsmartcols/src/Makemodule.am +--- util-linux-2.23.2/libsmartcols/src/Makemodule.am.kzak 2014-09-25 14:41:48.985843877 +0200 ++++ util-linux-2.23.2/libsmartcols/src/Makemodule.am 2014-09-25 14:42:10.471048869 +0200 +@@ -0,0 +1,75 @@ ++ ++ ++## smartcols.h is generated, so it's stored in builddir! (no distribute in RHEL7) ++#smartcolsincdir = $(includedir)/libsmartcols ++#nodist_smartcolsinc_HEADERS = $(top_builddir)/libsmartcols/src/libsmartcols.h ++ ++noinst_LTLIBRARIES += libsmartcols.la ++libsmartcols_la_SOURCES= \ ++ include/list.h \ ++ \ ++ libsmartcols/src/smartcolsP.h \ ++ libsmartcols/src/iter.c \ ++ libsmartcols/src/symbols.c \ ++ libsmartcols/src/cell.c \ ++ libsmartcols/src/column.c \ ++ libsmartcols/src/line.c \ ++ libsmartcols/src/table.c \ ++ libsmartcols/src/table_print.c \ ++ libsmartcols/src/version.c \ ++ libsmartcols/src/init.c \ ++ $(nodist_smartcolsinc_HEADERS) ++ ++nodist_libsmartcols_la_SOURCES = libsmartcols/src/smartcolsP.h ++ ++libsmartcols_la_LIBADD = libcommon.la ++ ++libsmartcols_la_CFLAGS = \ ++ $(SOLIB_CFLAGS) \ ++ -I$(ul_libsmartcols_incdir) \ ++ -I$(top_srcdir)/libsmartcols/src ++ ++libsmartcols_la_DEPENDENCIES = \ ++ libcommon.la \ ++ libsmartcols/src/libsmartcols.sym \ ++ libsmartcols/src/libsmartcols.h.in ++ ++libsmartcols_la_LDFLAGS = \ ++ $(SOLIB_LDFLAGS) \ ++ -Wl,--version-script=$(top_srcdir)/libsmartcols/src/libsmartcols.sym \ ++ -version-info $(LIBSMARTCOLS_VERSION_INFO) ++ ++EXTRA_DIST += \ ++ libsmartcols/src/libsmartcols.sym \ ++ libsmartcols/src/libsmartcols.h.in ++ ++ ++if BUILD_LIBSMARTCOLS_TESTS ++check_PROGRAMS += test_smartcols ++ ++libsmartcols_tests_cflags = $(libsmartcols_la_CFLAGS) ++libsmartcols_tests_ldadd = libsmartcols.la libcommon.la ++ ++test_smartcols_SOURCES = libsmartcols/src/test.c ++test_smartcols_CFLAGS = $(libsmartcols_tests_cflags) ++test_smartcols_LDADD = $(libsmartcols_tests_ldadd) ++endif # BUILD_LIBSMARTCOLS_TESTS ++ ++ ++# move lib from $(usrlib_execdir) to $(libdir) if needed ++install-exec-hook-libsmartcols: ++ if test "$(usrlib_execdir)" != "$(libdir)" -a -f "$(DESTDIR)$(usrlib_execdir)/libsmartcols.so"; then \ ++ mkdir -p $(DESTDIR)$(libdir); \ ++ mv $(DESTDIR)$(usrlib_execdir)/libsmartcols.so.* $(DESTDIR)$(libdir); \ ++ so_img_name=$$(readlink $(DESTDIR)$(usrlib_execdir)/libsmartcols.so); \ ++ so_img_rel_target=$$(echo $(usrlib_execdir) | sed 's,\(^/\|\)[^/][^/]*,..,g'); \ ++ (cd $(DESTDIR)$(usrlib_execdir) && \ ++ rm -f libsmartcols.so && \ ++ $(LN_S) $$so_img_rel_target$(libdir)/$$so_img_name libsmartcols.so); \ ++ fi ++ ++uninstall-hook-libsmartcols: ++ rm -f $(DESTDIR)$(libdir)/libsmartcols.so* ++ ++INSTALL_EXEC_HOOKS += install-exec-hook-libsmartcols ++UNINSTALL_HOOKS += uninstall-hook-libsmartcols +diff -up util-linux-2.23.2/libsmartcols/src/smartcolsP.h.kzak util-linux-2.23.2/libsmartcols/src/smartcolsP.h +--- util-linux-2.23.2/libsmartcols/src/smartcolsP.h.kzak 2014-09-25 14:41:48.989843915 +0200 ++++ util-linux-2.23.2/libsmartcols/src/smartcolsP.h 2014-09-25 14:41:48.989843915 +0200 +@@ -0,0 +1,173 @@ ++/* ++ * smartcolsP.h - private library header file ++ * ++ * Copyright (C) 2014 Ondrej Oprala ++ * Copyright (C) 2014 Karel Zak ++ * ++ * This file may be redistributed under the terms of the ++ * GNU Lesser General Public License. ++ */ ++ ++#ifndef _LIBSMARTCOLS_PRIVATE_H ++#define _LIBSMARTCOLS_PRIVATE_H ++ ++#include "c.h" ++#include "list.h" ++#include "colors.h" ++#include "debug.h" ++ ++#include "libsmartcols.h" ++ ++/* features */ ++#define CONFIG_LIBSMARTCOLS_ASSERT ++ ++#ifdef CONFIG_LIBSMARTCOLS_ASSERT ++# include ++#else ++# define assert(x) ++#endif ++ ++/* ++ * Debug ++ */ ++#define SCOLS_DEBUG_INIT (1 << 1) ++#define SCOLS_DEBUG_CELL (1 << 2) ++#define SCOLS_DEBUG_LINE (1 << 3) ++#define SCOLS_DEBUG_TAB (1 << 4) ++#define SCOLS_DEBUG_COL (1 << 5) ++#define SCOLS_DEBUG_BUFF (1 << 6) ++#define SCOLS_DEBUG_ALL 0xFFFF ++ ++UL_DEBUG_DECLARE_MASK(libsmartcols); ++#define DBG(m, x) __UL_DBG(libsmartcols, SCOLS_DEBUG_, m, x) ++#define ON_DBG(m, x) __UL_DBG_CALL(libsmartcols, SCOLS_DEBUG_, m, x) ++#define DBG_FLUSH __UL_DBG_FLUSH(libsmartcols, SCOLS_DEBUG_) ++ ++/* ++ * Generic iterator ++ */ ++struct libscols_iter { ++ struct list_head *p; /* current position */ ++ struct list_head *head; /* start position */ ++ int direction; /* SCOLS_ITER_{FOR,BACK}WARD */ ++}; ++ ++/* ++ * Tree symbols ++ */ ++struct libscols_symbols { ++ int refcount; ++ char *branch; ++ char *vert; ++ char *right; ++}; ++ ++/* ++ * Table cells ++ */ ++struct libscols_cell { ++ char *data; ++ char *color; ++ void *userdata; ++}; ++ ++ ++/* ++ * Table column ++ */ ++struct libscols_column { ++ int refcount; /* reference counter */ ++ size_t seqnum; /* column index */ ++ ++ size_t width; /* real column width */ ++ size_t width_min; /* minimal width (usually header width) */ ++ size_t width_max; /* maximal width */ ++ size_t width_avg; /* average width, used to detect extreme fields */ ++ double width_hint; /* hint (N < 1 is in percent of termwidth) */ ++ ++ int flags; ++ int is_extreme; ++ char *color; /* default column color */ ++ ++ int (*cmpfunc)(struct libscols_cell *, ++ struct libscols_cell *, ++ void *); /* cells comparison function */ ++ void *cmpfunc_data; ++ ++ struct libscols_cell header; ++ struct list_head cl_columns; ++}; ++ ++/* ++ * Table line ++ */ ++struct libscols_line { ++ int refcount; ++ size_t seqnum; ++ ++ void *userdata; ++ char *color; /* default line color */ ++ ++ struct libscols_cell *cells; /* array with data */ ++ size_t ncells; /* number of cells */ ++ ++ struct list_head ln_lines; /* table lines */ ++ struct list_head ln_branch; /* begin of branch (head of ln_children) */ ++ struct list_head ln_children; ++ ++ struct libscols_line *parent; ++}; ++ ++enum { ++ SCOLS_FMT_HUMAN = 0, /* default, human readable */ ++ SCOLS_FMT_RAW, /* space separated */ ++ SCOLS_FMT_EXPORT /* COLNAME="data" ... */ ++}; ++ ++/* ++ * The table ++ */ ++struct libscols_table { ++ int refcount; ++ size_t ncols; /* number of columns */ ++ size_t ntreecols; /* number of columns with SCOLS_FL_TREE */ ++ size_t nlines; /* number of lines */ ++ size_t termwidth; /* terminal width */ ++ size_t termreduce; /* extra blank space */ ++ FILE *out; /* output stream */ ++ ++ char *colsep; /* column separator */ ++ char *linesep; /* line separator */ ++ ++ struct list_head tb_columns; ++ struct list_head tb_lines; ++ struct libscols_symbols *symbols; ++ ++ int format; /* SCOLS_FMT_* */ ++ ++ /* flags */ ++ unsigned int ascii :1, /* don't use unicode */ ++ colors_wanted :1, /* enable colors */ ++ is_term :1, /* isatty() */ ++ maxout :1, /* maximalize output */ ++ no_headings :1; /* don't print header */ ++}; ++ ++#define IS_ITER_FORWARD(_i) ((_i)->direction == SCOLS_ITER_FORWARD) ++#define IS_ITER_BACKWARD(_i) ((_i)->direction == SCOLS_ITER_BACKWARD) ++ ++#define SCOLS_ITER_INIT(itr, list) \ ++ do { \ ++ (itr)->p = IS_ITER_FORWARD(itr) ? \ ++ (list)->next : (list)->prev; \ ++ (itr)->head = (list); \ ++ } while(0) ++ ++#define SCOLS_ITER_ITERATE(itr, res, restype, member) \ ++ do { \ ++ res = list_entry((itr)->p, restype, member); \ ++ (itr)->p = IS_ITER_FORWARD(itr) ? \ ++ (itr)->p->next : (itr)->p->prev; \ ++ } while(0) ++ ++#endif /* _LIBSMARTCOLS_PRIVATE_H */ +diff -up util-linux-2.23.2/libsmartcols/src/symbols.c.kzak util-linux-2.23.2/libsmartcols/src/symbols.c +--- util-linux-2.23.2/libsmartcols/src/symbols.c.kzak 2014-09-25 14:41:48.989843915 +0200 ++++ util-linux-2.23.2/libsmartcols/src/symbols.c 2014-09-25 14:41:48.989843915 +0200 +@@ -0,0 +1,175 @@ ++/* ++ * symbols.c - routines for symbol handling ++ * ++ * Copyright (C) 2014 Ondrej Oprala ++ * ++ * This file may be redistributed under the terms of the ++ * GNU Lesser General Public License. ++ */ ++ ++/** ++ * SECTION: symbols ++ * @title: Symbols ++ * @short_description: symbols API ++ * ++ * An API to access and modify data and information per symbol/symbol group. ++ */ ++ ++ ++#include ++#include ++#include ++ ++#include "smartcolsP.h" ++ ++/** ++ * scols_new_symbols: ++ * ++ * Returns: a pointer to a newly allocated struct libscols_symbols instance. ++ */ ++struct libscols_symbols *scols_new_symbols(void) ++{ ++ struct libscols_symbols *sy = calloc(1, sizeof(struct libscols_symbols)); ++ ++ if (!sy) ++ return NULL; ++ sy->refcount = 1; ++ return sy; ++} ++ ++/** ++ * scols_ref_symbols: ++ * @sy: a pointer to a struct libscols_symbols instance ++ * ++ * Increases the refcount of @sy. ++ */ ++void scols_ref_symbols(struct libscols_symbols *sy) ++{ ++ if (sy) ++ sy->refcount++; ++} ++ ++/** ++ * scols_unref_symbols: ++ * @sy: a pointer to a struct libscols_symbols instance ++ * ++ * Decreases the refcount of @sy. ++ */ ++void scols_unref_symbols(struct libscols_symbols *sy) ++{ ++ if (sy && --sy->refcount <= 0) { ++ free(sy->branch); ++ free(sy->vert); ++ free(sy->right); ++ free(sy); ++ } ++} ++ ++/** ++ * scols_symbols_set_branch: ++ * @sb: a pointer to a struct libscols_symbols instance ++ * @str: a string which will represent the branch part of a tree output ++ * ++ * Returns: 0, a negative value in case of an error. ++ */ ++int scols_symbols_set_branch(struct libscols_symbols *sb, const char *str) ++{ ++ char *p = NULL; ++ ++ assert(sb); ++ ++ if (!sb) ++ return -EINVAL; ++ if (str) { ++ p = strdup(str); ++ if (!p) ++ return -ENOMEM; ++ } ++ free(sb->branch); ++ sb->branch = p; ++ return 0; ++} ++ ++/** ++ * scols_symbols_set_vertical: ++ * @sb: a pointer to a struct libscols_symbols instance ++ * @str: a string which will represent the vertical part of a tree output ++ * ++ * Returns: 0, a negative value in case of an error. ++ */ ++int scols_symbols_set_vertical(struct libscols_symbols *sb, const char *str) ++{ ++ char *p = NULL; ++ ++ assert(sb); ++ ++ if (!sb) ++ return -EINVAL; ++ if (str) { ++ p = strdup(str); ++ if (!p) ++ return -ENOMEM; ++ } ++ free(sb->vert); ++ sb->vert = p; ++ return 0; ++} ++ ++/** ++ * scols_symbols_set_right: ++ * @sb: a pointer to a struct libscols_symbols instance ++ * @str: a string which will represent the right part of a tree output ++ * ++ * Returns: 0, a negative value in case of an error. ++ */ ++int scols_symbols_set_right(struct libscols_symbols *sb, const char *str) ++{ ++ char *p = NULL; ++ ++ assert(sb); ++ ++ if (!sb) ++ return -EINVAL; ++ if (str) { ++ p = strdup(str); ++ if (!p) ++ return -ENOMEM; ++ } ++ free(sb->right); ++ sb->right = p; ++ return 0; ++} ++ ++/** ++ * scols_copy_symbols: ++ * @sb: a pointer to a struct libscols_symbols instance ++ * ++ * Returns: a newly allocated copy of the @sb symbol group or NULL in caes of an error. ++ */ ++struct libscols_symbols *scols_copy_symbols(const struct libscols_symbols *sb) ++{ ++ struct libscols_symbols *ret; ++ int rc; ++ ++ assert(sb); ++ if (!sb) ++ return NULL; ++ ++ ret = scols_new_symbols(); ++ if (!ret) ++ return NULL; ++ ++ rc = scols_symbols_set_branch(ret, sb->branch); ++ if (!rc) ++ rc = scols_symbols_set_vertical(ret, sb->vert); ++ if (!rc) ++ rc = scols_symbols_set_right(ret, sb->right); ++ if (!rc) ++ return ret; ++ ++ scols_unref_symbols(ret); ++ return NULL; ++ ++} ++ ++ +diff -up util-linux-2.23.2/libsmartcols/src/table.c.kzak util-linux-2.23.2/libsmartcols/src/table.c +--- util-linux-2.23.2/libsmartcols/src/table.c.kzak 2014-09-25 14:41:48.991843934 +0200 ++++ util-linux-2.23.2/libsmartcols/src/table.c 2014-09-25 14:41:48.991843934 +0200 +@@ -0,0 +1,1049 @@ ++/* ++ * table.c - functions handling the data at the table level ++ * ++ * Copyright (C) 2010-2014 Karel Zak ++ * Copyright (C) 2014 Ondrej Oprala ++ * ++ * This file may be redistributed under the terms of the ++ * GNU Lesser General Public License. ++ */ ++ ++/** ++ * SECTION: table ++ * @title: Table ++ * @short_description: table data API ++ * ++ * Table data manipulation API. ++ */ ++ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "nls.h" ++#include "widechar.h" ++#include "smartcolsP.h" ++ ++#ifdef HAVE_WIDECHAR ++#define UTF_V "\342\224\202" /* U+2502, Vertical line drawing char */ ++#define UTF_VR "\342\224\234" /* U+251C, Vertical and right */ ++#define UTF_H "\342\224\200" /* U+2500, Horizontal */ ++#define UTF_UR "\342\224\224" /* U+2514, Up and right */ ++#endif /* !HAVE_WIDECHAR */ ++ ++#define is_last_column(_tb, _cl) \ ++ list_entry_is_last(&(_cl)->cl_columns, &(_tb)->tb_columns) ++ ++ ++/** ++ * scols_new_table: ++ * ++ * Returns: A newly allocated table. ++ */ ++struct libscols_table *scols_new_table(void) ++{ ++ struct libscols_table *tb; ++ ++ tb = calloc(1, sizeof(struct libscols_table)); ++ if (!tb) ++ return NULL; ++ ++ tb->refcount = 1; ++ tb->out = stdout; ++ ++ INIT_LIST_HEAD(&tb->tb_lines); ++ INIT_LIST_HEAD(&tb->tb_columns); ++ ++ DBG(TAB, ul_debugobj(tb, "alloc")); ++ return tb; ++} ++ ++/** ++ * scols_ref_table: ++ * @tb: a pointer to a struct libscols_table instance ++ * ++ * Increases the refcount of @tb. ++ */ ++void scols_ref_table(struct libscols_table *tb) ++{ ++ if (tb) ++ tb->refcount++; ++} ++ ++/** ++ * scols_unref_table: ++ * @tb: a pointer to a struct libscols_table instance ++ * ++ * Decreases the refcount of @tb. When the count falls to zero, the instance ++ * is automatically deallocated. ++ */ ++void scols_unref_table(struct libscols_table *tb) ++{ ++ if (tb && (--tb->refcount <= 0)) { ++ DBG(TAB, ul_debugobj(tb, "dealloc")); ++ scols_table_remove_lines(tb); ++ scols_table_remove_columns(tb); ++ scols_unref_symbols(tb->symbols); ++ free(tb->linesep); ++ free(tb->colsep); ++ free(tb); ++ } ++} ++ ++/** ++ * scols_table_add_column: ++ * @tb: a pointer to a struct libscols_table instance ++ * @cl: a pointer to a struct libscols_column instance ++ * ++ * Adds @cl to @tb's column list. ++ * ++ * Returns: 0, a negative number in case of an error. ++ */ ++int scols_table_add_column(struct libscols_table *tb, struct libscols_column *cl) ++{ ++ assert(tb); ++ assert(cl); ++ ++ if (!tb || !cl || !list_empty(&tb->tb_lines)) ++ return -EINVAL; ++ ++ if (cl->flags & SCOLS_FL_TREE) ++ tb->ntreecols++; ++ ++ DBG(TAB, ul_debugobj(tb, "add column %p", cl)); ++ list_add_tail(&cl->cl_columns, &tb->tb_columns); ++ cl->seqnum = tb->ncols++; ++ scols_ref_column(cl); ++ ++ /* TODO: ++ * ++ * Currently it's possible to add/remove columns only if the table is ++ * empty (see list_empty(tb->tb_lines) above). It would be nice to ++ * enlarge/reduce lines cells[] always when we add/remove a new column. ++ */ ++ return 0; ++} ++ ++/** ++ * scols_table_remove_column: ++ * @tb: a pointer to a struct libscols_table instance ++ * @cl: a pointer to a struct libscols_column instance ++ * ++ * Removes @cl from @tb. ++ * ++ * Returns: 0, a negative number in case of an error. ++ */ ++int scols_table_remove_column(struct libscols_table *tb, ++ struct libscols_column *cl) ++{ ++ assert(tb); ++ assert(cl); ++ ++ if (!tb || !cl || !list_empty(&tb->tb_lines)) ++ return -EINVAL; ++ ++ if (cl->flags & SCOLS_FL_TREE) ++ tb->ntreecols--; ++ ++ DBG(TAB, ul_debugobj(tb, "remove column %p", cl)); ++ list_del_init(&cl->cl_columns); ++ tb->ncols--; ++ scols_unref_column(cl); ++ return 0; ++} ++ ++/** ++ * scols_table_remove_columns: ++ * @tb: a pointer to a struct libscols_table instance ++ * ++ * Removes all of @tb's columns. ++ * ++ * Returns: 0, a negative number in case of an error. ++ */ ++int scols_table_remove_columns(struct libscols_table *tb) ++{ ++ assert(tb); ++ ++ if (!tb || !list_empty(&tb->tb_lines)) ++ return -EINVAL; ++ ++ DBG(TAB, ul_debugobj(tb, "remove all columns")); ++ while (!list_empty(&tb->tb_columns)) { ++ struct libscols_column *cl = list_entry(tb->tb_columns.next, ++ struct libscols_column, cl_columns); ++ scols_table_remove_column(tb, cl); ++ } ++ return 0; ++} ++ ++ ++/** ++ * scols_table_new_column: ++ * @tb: table ++ * @name: column header ++ * @whint: column width hint (absolute width: N > 1; relative width: N < 1) ++ * @flags: flags integer ++ * ++ * This is shortcut for ++ * ++ * cl = scols_new_column(); ++ * scols_column_set_....(cl, ...); ++ * scols_table_add_column(tb, cl); ++ * ++ * The column width is possible to define by three ways: ++ * ++ * @whint = 0..1 : relative width, percent of terminal width ++ * ++ * @whint = 1..N : absolute width, empty colum will be truncated to ++ * the column header width ++ * ++ * @whint = 1..N ++ * ++ * The column is necessary to address by ++ * sequential number. The first defined column has the colnum = 0. For example: ++ * ++ * scols_table_new_column(tab, "FOO", 0.5, 0); // colnum = 0 ++ * scols_table_new_column(tab, "BAR", 0.5, 0); // colnum = 1 ++ * . ++ * . ++ * scols_line_get_cell(line, 0); // FOO column ++ * scols_line_get_cell(line, 1); // BAR column ++ * ++ * Returns: newly allocated column ++ */ ++struct libscols_column *scols_table_new_column(struct libscols_table *tb, ++ const char *name, ++ double whint, ++ int flags) ++{ ++ struct libscols_column *cl; ++ struct libscols_cell *hr; ++ ++ assert (tb); ++ if (!tb) ++ return NULL; ++ ++ DBG(TAB, ul_debugobj(tb, "new column name=%s, whint=%g, flags=%d", ++ name, whint, flags)); ++ cl = scols_new_column(); ++ if (!cl) ++ return NULL; ++ ++ /* set column name */ ++ hr = scols_column_get_header(cl); ++ if (!hr) ++ goto err; ++ if (scols_cell_set_data(hr, name)) ++ goto err; ++ ++ scols_column_set_whint(cl, whint); ++ scols_column_set_flags(cl, flags); ++ ++ if (scols_table_add_column(tb, cl)) /* this increments column ref-counter */ ++ goto err; ++ ++ scols_unref_column(cl); ++ return cl; ++err: ++ scols_unref_column(cl); ++ return NULL; ++} ++ ++/** ++ * scols_table_next_column: ++ * @tb: a pointer to a struct libscols_table instance ++ * @itr: a pointer to a struct libscols_iter instance ++ * @cl: a pointer to a pointer to a struct libscols_column instance ++ * ++ * Returns the next column of @tb via @cl. ++ * ++ * Returns: 0, a negative value in case of an error. ++ */ ++int scols_table_next_column(struct libscols_table *tb, ++ struct libscols_iter *itr, ++ struct libscols_column **cl) ++{ ++ int rc = 1; ++ ++ if (!tb || !itr || !cl) ++ return -EINVAL; ++ *cl = NULL; ++ ++ if (!itr->head) ++ SCOLS_ITER_INIT(itr, &tb->tb_columns); ++ if (itr->p != itr->head) { ++ SCOLS_ITER_ITERATE(itr, *cl, struct libscols_column, cl_columns); ++ rc = 0; ++ } ++ ++ return rc; ++} ++ ++ ++/** ++ * scols_table_get_ncols: ++ * @tb: table ++ * ++ * Returns: the ncols table member, a negative number in case of an error. ++ */ ++int scols_table_get_ncols(struct libscols_table *tb) ++{ ++ assert(tb); ++ return tb ? tb->ncols : -EINVAL; ++} ++ ++/** ++ * scols_table_get_nlines: ++ * @tb: table ++ * ++ * Returns: the nlines table member, a negative number in case of an error. ++ */ ++int scols_table_get_nlines(struct libscols_table *tb) ++{ ++ assert(tb); ++ return tb ? tb->nlines : -EINVAL; ++} ++ ++/** ++ * scols_table_set_stream: ++ * @tb: table ++ * @stream: output stream ++ * ++ * Sets the output stream for table @tb. ++ * ++ * Returns: 0, a negative number in case of an error. ++ */ ++int scols_table_set_stream(struct libscols_table *tb, FILE *stream) ++{ ++ assert(tb); ++ if (!tb) ++ return -EINVAL; ++ ++ DBG(TAB, ul_debugobj(tb, "setting alternative stream")); ++ tb->out = stream; ++ return 0; ++} ++ ++/** ++ * scols_table_get_stream: ++ * @tb: table ++ * ++ * Gets the output stream for table @tb. ++ * ++ * Returns: stream pointer, NULL in case of an error or an unset stream. ++ */ ++FILE *scols_table_get_stream(struct libscols_table *tb) ++{ ++ assert(tb); ++ return tb ? tb->out: NULL; ++} ++ ++/** ++ * scols_table_reduce_termwidth: ++ * @tb: table ++ * @reduce: width ++ * ++ * Reduce the output width to @reduce. ++ * ++ * Returns: 0, a negative value in case of an error. ++ */ ++int scols_table_reduce_termwidth(struct libscols_table *tb, size_t reduce) ++{ ++ assert(tb); ++ if (!tb) ++ return -EINVAL; ++ ++ DBG(TAB, ul_debugobj(tb, "reduce terminal width: %zu", reduce)); ++ tb->termreduce = reduce; ++ return 0; ++} ++ ++/** ++ * scols_table_get_column: ++ * @tb: table ++ * @n: number of column (0..N) ++ * ++ * Returns: pointer to column or NULL ++ */ ++struct libscols_column *scols_table_get_column(struct libscols_table *tb, ++ size_t n) ++{ ++ struct libscols_iter itr; ++ struct libscols_column *cl; ++ ++ assert(tb); ++ if (!tb) ++ return NULL; ++ if (n >= tb->ncols) ++ return NULL; ++ ++ scols_reset_iter(&itr, SCOLS_ITER_FORWARD); ++ while (scols_table_next_column(tb, &itr, &cl) == 0) { ++ if (cl->seqnum == n) ++ return cl; ++ } ++ return NULL; ++} ++ ++/** ++ * scols_table_add_line: ++ * @tb: table ++ * @ln: line ++ * ++ * Note that this function calls scols_line_alloc_cells() if number ++ * of the cells in the line is too small for @tb. ++ * ++ * Returns: 0, a negative value in case of an error. ++ */ ++int scols_table_add_line(struct libscols_table *tb, struct libscols_line *ln) ++{ ++ ++ assert(tb); ++ assert(ln); ++ ++ if (!tb || !ln) ++ return -EINVAL; ++ ++ if (tb->ncols > ln->ncells) { ++ int rc = scols_line_alloc_cells(ln, tb->ncols); ++ if (rc) ++ return rc; ++ } ++ ++ DBG(TAB, ul_debugobj(tb, "add line %p", ln)); ++ list_add_tail(&ln->ln_lines, &tb->tb_lines); ++ ln->seqnum = tb->nlines++; ++ scols_ref_line(ln); ++ return 0; ++} ++ ++/** ++ * scols_table_remove_line: ++ * @tb: table ++ * @ln: line ++ * ++ * Note that this function does not destroy the parent<->child relationship between lines. ++ * You have to call scols_line_remove_child() ++ * ++ * Returns: 0, a negative value in case of an error. ++ */ ++int scols_table_remove_line(struct libscols_table *tb, ++ struct libscols_line *ln) ++{ ++ assert(tb); ++ assert(ln); ++ ++ if (!tb || !ln) ++ return -EINVAL; ++ ++ DBG(TAB, ul_debugobj(tb, "remove line %p", ln)); ++ list_del_init(&ln->ln_lines); ++ tb->nlines--; ++ scols_unref_line(ln); ++ return 0; ++} ++ ++/** ++ * scols_table_remove_lines: ++ * @tb: table ++ * ++ * This empties the table and also destroys all the parent<->child relationships. ++ */ ++void scols_table_remove_lines(struct libscols_table *tb) ++{ ++ assert(tb); ++ if (!tb) ++ return; ++ ++ DBG(TAB, ul_debugobj(tb, "remove all lines")); ++ while (!list_empty(&tb->tb_lines)) { ++ struct libscols_line *ln = list_entry(tb->tb_lines.next, ++ struct libscols_line, ln_lines); ++ if (ln->parent) ++ scols_line_remove_child(ln->parent, ln); ++ scols_table_remove_line(tb, ln); ++ } ++} ++ ++/** ++ * scols_table_next_line: ++ * @tb: a pointer to a struct libscols_table instance ++ * @itr: a pointer to a struct libscols_iter instance ++ * @ln: a pointer to a pointer to a struct libscols_line instance ++ * ++ * Finds the next line and returns a pointer to it via @ln. ++ * ++ * Returns: 0, a negative value in case of an error. ++ */ ++int scols_table_next_line(struct libscols_table *tb, ++ struct libscols_iter *itr, ++ struct libscols_line **ln) ++{ ++ int rc = 1; ++ ++ if (!tb || !itr || !ln) ++ return -EINVAL; ++ *ln = NULL; ++ ++ if (!itr->head) ++ SCOLS_ITER_INIT(itr, &tb->tb_lines); ++ if (itr->p != itr->head) { ++ SCOLS_ITER_ITERATE(itr, *ln, struct libscols_line, ln_lines); ++ rc = 0; ++ } ++ ++ return rc; ++} ++ ++/** ++ * scols_table_new_line: ++ * @tb: table ++ * @parent: parental line or NULL ++ * ++ * This is shortcut for ++ * ++ * ln = scols_new_line(); ++ * scols_table_add_line(tb, ln); ++ * scols_line_add_child(parent, ln); ++ * ++ * ++ * Returns: newly allocate line ++ */ ++struct libscols_line *scols_table_new_line(struct libscols_table *tb, ++ struct libscols_line *parent) ++{ ++ struct libscols_line *ln; ++ ++ assert(tb); ++ assert(tb->ncols); ++ ++ if (!tb || !tb->ncols) ++ return NULL; ++ ++ ln = scols_new_line(); ++ if (!ln) ++ return NULL; ++ ++ if (scols_table_add_line(tb, ln)) ++ goto err; ++ if (parent) ++ scols_line_add_child(parent, ln); ++ ++ scols_unref_line(ln); /* ref-counter incremented by scols_table_add_line() */ ++ return ln; ++err: ++ scols_unref_line(ln); ++ return NULL; ++} ++ ++/** ++ * scols_table_get_line: ++ * @tb: table ++ * @n: column number (0..N) ++ * ++ * This is a shortcut for ++ * ++ * ln = scols_new_line(); ++ * scols_line_set_....(cl, ...); ++ * scols_table_add_line(tb, ln); ++ * ++ * Returns: a newly allocate line ++ */ ++struct libscols_line *scols_table_get_line(struct libscols_table *tb, ++ size_t n) ++{ ++ struct libscols_iter itr; ++ struct libscols_line *ln; ++ ++ assert(tb); ++ if (!tb) ++ return NULL; ++ if (n >= tb->nlines) ++ return NULL; ++ ++ scols_reset_iter(&itr, SCOLS_ITER_FORWARD); ++ while (scols_table_next_line(tb, &itr, &ln) == 0) { ++ if (ln->seqnum == n) ++ return ln; ++ } ++ return NULL; ++} ++ ++/** ++ * scols_copy_table: ++ * @tb: table ++ * ++ * Creates a new independent table copy, except struct libscols_symbols that ++ * are shared between the tables. ++ * ++ * Returns: a newly allocated copy of @tb ++ */ ++struct libscols_table *scols_copy_table(struct libscols_table *tb) ++{ ++ struct libscols_table *ret; ++ struct libscols_line *ln; ++ struct libscols_column *cl; ++ struct libscols_iter itr; ++ ++ assert(tb); ++ if (!tb) ++ return NULL; ++ ret = scols_new_table(); ++ if (!ret) ++ return NULL; ++ ++ DBG(TAB, ul_debugobj(tb, "copy into %p", ret)); ++ ++ if (tb->symbols) ++ scols_table_set_symbols(ret, tb->symbols); ++ ++ /* columns */ ++ scols_reset_iter(&itr, SCOLS_ITER_FORWARD); ++ while (scols_table_next_column(tb, &itr, &cl) == 0) { ++ cl = scols_copy_column(cl); ++ if (!cl) ++ goto err; ++ if (scols_table_add_column(ret, cl)) ++ goto err; ++ scols_unref_column(cl); ++ } ++ ++ /* lines */ ++ scols_reset_iter(&itr, SCOLS_ITER_FORWARD); ++ while (scols_table_next_line(tb, &itr, &ln) == 0) { ++ struct libscols_line *newln = scols_copy_line(ln); ++ if (!newln) ++ goto err; ++ if (scols_table_add_line(ret, newln)) ++ goto err; ++ if (ln->parent) { ++ struct libscols_line *p = ++ scols_table_get_line(ret, ln->parent->seqnum); ++ if (p) ++ scols_line_add_child(p, newln); ++ } ++ scols_unref_line(newln); ++ } ++ ++ /* separators */ ++ if (scols_table_set_column_separator(ret, tb->colsep) || ++ scols_table_set_line_separator(ret, tb->linesep)) ++ goto err; ++ ++ return ret; ++err: ++ scols_unref_table(ret); ++ return NULL; ++} ++ ++/** ++ * scols_table_set_symbols: ++ * @tb: table ++ * @sy: symbols or NULL ++ * ++ * Add a reference to @sy from the table. The symbols are used by library to ++ * draw tree output. If no symbols are specified then library checks the ++ * current environment to select ASCII or UTF8 symbols. This default behavior ++ * could be controlled by scols_table_enable_ascii(). ++ * ++ * Returns: 0, a negative value in case of an error. ++ */ ++int scols_table_set_symbols(struct libscols_table *tb, ++ struct libscols_symbols *sy) ++{ ++ assert(tb); ++ ++ if (!tb) ++ return -EINVAL; ++ ++ DBG(TAB, ul_debugobj(tb, "setting alternative symbols %p", sy)); ++ ++ if (tb->symbols) /* unref old */ ++ scols_unref_symbols(tb->symbols); ++ if (sy) { /* ref user defined */ ++ tb->symbols = sy; ++ scols_ref_symbols(sy); ++ } else { /* default symbols */ ++ tb->symbols = scols_new_symbols(); ++ if (!tb->symbols) ++ return -ENOMEM; ++#if defined(HAVE_WIDECHAR) ++ if (!scols_table_is_ascii(tb) && ++ !strcmp(nl_langinfo(CODESET), "UTF-8")) { ++ scols_symbols_set_branch(tb->symbols, UTF_VR UTF_H); ++ scols_symbols_set_vertical(tb->symbols, UTF_V " "); ++ scols_symbols_set_right(tb->symbols, UTF_UR UTF_H); ++ } else ++#endif ++ { ++ scols_symbols_set_branch(tb->symbols, "|-"); ++ scols_symbols_set_vertical(tb->symbols, "| "); ++ scols_symbols_set_right(tb->symbols, "`-"); ++ } ++ } ++ ++ return 0; ++} ++/** ++ * scols_table_enable_colors: ++ * @tb: table ++ * @enable: 1 or 0 ++ * ++ * Enable/disable colors. ++ * ++ * Returns: 0 on success, negative number in case of an error. ++ */ ++int scols_table_enable_colors(struct libscols_table *tb, int enable) ++{ ++ assert(tb); ++ if (!tb) ++ return -EINVAL; ++ ++ DBG(TAB, ul_debugobj(tb, "colors: %s", enable ? "ENABLE" : "DISABLE")); ++ tb->colors_wanted = enable; ++ return 0; ++} ++/** ++ * scols_table_enable_raw: ++ * @tb: table ++ * @enable: 1 or 0 ++ * ++ * Enable/disable raw output format. The parsable output formats ++ * (export and raw) are mutually exclusive. ++ * ++ * Returns: 0 on success, negative number in case of an error. ++ */ ++int scols_table_enable_raw(struct libscols_table *tb, int enable) ++{ ++ assert(tb); ++ if (!tb) ++ return -EINVAL; ++ ++ DBG(TAB, ul_debugobj(tb, "raw: %s", enable ? "ENABLE" : "DISABLE")); ++ if (enable) ++ tb->format = SCOLS_FMT_RAW; ++ else if (tb->format == SCOLS_FMT_RAW) ++ tb->format = 0; ++ return 0; ++} ++ ++/** ++ * scols_table_enable_export: ++ * @tb: table ++ * @enable: 1 or 0 ++ * ++ * Enable/disable export output format (COLUMNAME="value" ...). ++ * The parsable output formats (export and raw) are mutually exclusive. ++ * ++ * Returns: 0 on success, negative number in case of an error. ++ */ ++int scols_table_enable_export(struct libscols_table *tb, int enable) ++{ ++ assert(tb); ++ if (!tb) ++ return -EINVAL; ++ ++ DBG(TAB, ul_debugobj(tb, "export: %s", enable ? "ENABLE" : "DISABLE")); ++ if (enable) ++ tb->format = SCOLS_FMT_EXPORT; ++ else if (tb->format == SCOLS_FMT_EXPORT) ++ tb->format = 0; ++ return 0; ++} ++ ++/** ++ * scols_table_enable_ascii: ++ * @tb: table ++ * @enable: 1 or 0 ++ * ++ * The ASCII-only output is relevant for tree-like outputs. The library ++ * checks if the current environment is UTF8 compatible by default. This ++ * function overrides this check and force the library to use ASCII chars ++ * for the tree. ++ * ++ * If a custom libcols_symbols are specified (see scols_table_set_symbols() ++ * then ASCII flag setting is ignored. ++ * ++ * Returns: 0 on success, negative number in case of an error. ++ */ ++int scols_table_enable_ascii(struct libscols_table *tb, int enable) ++{ ++ assert(tb); ++ if (!tb) ++ return -EINVAL; ++ ++ DBG(TAB, ul_debugobj(tb, "ascii: %s", enable ? "ENABLE" : "DISABLE")); ++ tb->ascii = enable ? 1 : 0; ++ return 0; ++} ++ ++/** ++ * scols_table_enable_noheadings: ++ * @tb: table ++ * @enable: 1 or 0 ++ * ++ * Enable/disable header line. ++ * ++ * Returns: 0 on success, negative number in case of an error. ++ */ ++int scols_table_enable_noheadings(struct libscols_table *tb, int enable) ++{ ++ assert(tb); ++ if (!tb) ++ return -EINVAL; ++ DBG(TAB, ul_debugobj(tb, "noheading: %s", enable ? "ENABLE" : "DISABLE")); ++ tb->no_headings = enable ? 1 : 0; ++ return 0; ++} ++ ++/** ++ * scols_table_enable_maxout: ++ * @tb: table ++ * @enable: 1 or 0 ++ * ++ * The extra space after last column is ignored by default. The output ++ * maximization use the extra space for all columns. ++ * ++ * Returns: 0 on success, negative number in case of an error. ++ */ ++int scols_table_enable_maxout(struct libscols_table *tb, int enable) ++{ ++ assert(tb); ++ if (!tb) ++ return -EINVAL; ++ DBG(TAB, ul_debugobj(tb, "maxout: %s", enable ? "ENABLE" : "DISABLE")); ++ tb->maxout = enable ? 1 : 0; ++ return 0; ++} ++ ++/** ++ * scols_table_colors_wanted: ++ * @tb: table ++ * ++ * Returns: 1 if colors are enabled. ++ */ ++int scols_table_colors_wanted(struct libscols_table *tb) ++{ ++ assert(tb); ++ return tb && tb->colors_wanted; ++} ++ ++/** ++ * scols_table_is_empty: ++ * @tb: table ++ * ++ * Returns: 1 if the table is empty. ++ */ ++int scols_table_is_empty(struct libscols_table *tb) ++{ ++ assert(tb); ++ return !tb || !tb->nlines; ++} ++ ++/** ++ * scols_table_is_ascii: ++ * @tb: table ++ * ++ * Returns: 1 if ASCII tree is enabled. ++ */ ++int scols_table_is_ascii(struct libscols_table *tb) ++{ ++ assert(tb); ++ return tb && tb->ascii; ++} ++ ++/** ++ * scols_table_is_noheadings: ++ * @tb: table ++ * ++ * Returns: 1 if header output is disabled. ++ */ ++int scols_table_is_noheadings(struct libscols_table *tb) ++{ ++ assert(tb); ++ return tb && tb->no_headings; ++} ++ ++/** ++ * scols_table_is_export: ++ * @tb: table ++ * ++ * Returns: 1 if export output format is enabled. ++ */ ++int scols_table_is_export(struct libscols_table *tb) ++{ ++ assert(tb); ++ return tb && tb->format == SCOLS_FMT_EXPORT; ++} ++ ++/** ++ * scols_table_is_raw: ++ * @tb: table ++ * ++ * Returns: 1 if raw output format is enabled. ++ */ ++int scols_table_is_raw(struct libscols_table *tb) ++{ ++ assert(tb); ++ return tb && tb->format == SCOLS_FMT_RAW; ++} ++ ++ ++/** ++ * scols_table_is_maxout ++ * @tb: table ++ * ++ * Returns: 1 if output maximization is enabled, negative value in case of an error. ++ */ ++int scols_table_is_maxout(struct libscols_table *tb) ++{ ++ assert(tb); ++ return tb && tb->maxout; ++} ++ ++/** ++ * scols_table_is_tree: ++ * @tb: table ++ * ++ * Returns: returns 1 tree-like output is expected. ++ */ ++int scols_table_is_tree(struct libscols_table *tb) ++{ ++ assert(tb); ++ return tb && tb->ntreecols > 0; ++} ++ ++/** ++ * scols_table_set_column_separator: ++ * @tb: table ++ * @sep: separator ++ * ++ * Sets the column separator of @tb to @sep. ++ * Please note that @sep should always take up a single cell in the output. ++ * ++ * Returns: 0, a negative value in case of an error. ++ */ ++int scols_table_set_column_separator(struct libscols_table *tb, const char *sep) ++{ ++ char *p = NULL; ++ ++ assert (tb); ++ ++ if (!tb) ++ return -EINVAL; ++ ++ if (sep) { ++ p = strdup(sep); ++ if (!p) ++ return -ENOMEM; ++ } ++ ++ DBG(TAB, ul_debugobj(tb, "new columns separator: %s", sep)); ++ free(tb->colsep); ++ tb->colsep = p; ++ return 0; ++} ++ ++/** ++ * scols_table_set_line_separator: ++ * @tb: table ++ * @sep: separator ++ * ++ * Sets the line separator of @tb to @sep. ++ * ++ * Returns: 0, a negative value in case of an error. ++ */ ++int scols_table_set_line_separator(struct libscols_table *tb, const char *sep) ++{ ++ char *p = NULL; ++ ++ assert (tb); ++ ++ if (!tb) ++ return -EINVAL; ++ ++ if (sep) { ++ p = strdup(sep); ++ if (!p) ++ return -ENOMEM; ++ } ++ ++ DBG(TAB, ul_debugobj(tb, "new lines separator: %s", sep)); ++ free(tb->linesep); ++ tb->linesep = p; ++ return 0; ++} ++ ++/** ++ * scols_table_get_column_separator: ++ * @tb: table ++ * ++ * Returns: @tb column separator, NULL in case of an error ++ */ ++char *scols_table_get_column_separator(struct libscols_table *tb) ++{ ++ assert (tb); ++ ++ if (!tb) ++ return NULL; ++ return tb->colsep; ++} ++ ++/** ++ * scols_table_get_line_separator: ++ * @tb: table ++ * ++ * Returns: @tb line separator, NULL in case of an error ++ */ ++char *scols_table_get_line_separator(struct libscols_table *tb) ++{ ++ assert (tb); ++ ++ if (!tb) ++ return NULL; ++ return tb->linesep; ++ ++} ++ ++static int cells_cmp_wrapper(struct list_head *a, struct list_head *b, void *data) ++{ ++ struct libscols_column *cl = (struct libscols_column *) data; ++ struct libscols_line *ra, *rb; ++ struct libscols_cell *ca, *cb; ++ ++ assert(a); ++ assert(b); ++ assert(cl); ++ ++ ra = list_entry(a, struct libscols_line, ln_lines); ++ rb = list_entry(b, struct libscols_line, ln_lines); ++ ca = scols_line_get_cell(ra, cl->seqnum); ++ cb = scols_line_get_cell(rb, cl->seqnum); ++ ++ return cl->cmpfunc(ca, cb, cl->cmpfunc_data); ++} ++ ++/** ++ * scols_sort_table: ++ * @tb: table ++ * @cl: order by this column ++ * ++ * Orders the table by the column. See also scols_column_set_cmpfunc(). ++ * ++ * Returns: 0, a negative value in case of an error. ++ */ ++int scols_sort_table(struct libscols_table *tb, struct libscols_column *cl) ++{ ++ assert(tb); ++ assert(cl); ++ ++ if (!tb || !cl) ++ return -EINVAL; ++ ++ DBG(TAB, ul_debugobj(tb, "sorting table")); ++ list_sort(&tb->tb_lines, cells_cmp_wrapper, cl); ++ return 0; ++} +diff -up util-linux-2.23.2/libsmartcols/src/table_print.c.kzak util-linux-2.23.2/libsmartcols/src/table_print.c +--- util-linux-2.23.2/libsmartcols/src/table_print.c.kzak 2014-09-25 14:41:48.992843944 +0200 ++++ util-linux-2.23.2/libsmartcols/src/table_print.c 2014-09-25 14:41:48.992843944 +0200 +@@ -0,0 +1,841 @@ ++/* ++ * table.c - functions handling the data at the table level ++ * ++ * Copyright (C) 2010-2014 Karel Zak ++ * ++ * This file may be redistributed under the terms of the ++ * GNU Lesser General Public License. ++ */ ++ ++/** ++ * SECTION: table_print ++ * @title: Table print ++ * @short_description: table print API ++ * ++ * Table output API. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "nls.h" ++#include "mbsalign.h" ++#include "widechar.h" ++#include "ttyutils.h" ++#include "carefulputc.h" ++#include "smartcolsP.h" ++ ++/* This is private struct to work with output data */ ++struct libscols_buffer { ++ char *begin; /* begin of the buffer */ ++ char *cur; /* current end of the buffer */ ++ char *encdata; /* encoded buffer mbs_safe_encode() */ ++ ++ size_t bufsz; /* size of the buffer */ ++ size_t art_idx; /* begin of the tree ascii art or zero */ ++}; ++ ++static struct libscols_buffer *new_buffer(size_t sz) ++{ ++ struct libscols_buffer *buf = malloc(sz + sizeof(struct libscols_buffer)); ++ ++ if (!buf) ++ return NULL; ++ ++ buf->cur = buf->begin = ((char *) buf) + sizeof(struct libscols_buffer); ++ buf->encdata = NULL; ++ buf->bufsz = sz; ++ ++ DBG(BUFF, ul_debugobj(buf, "alloc (size=%zu)", sz)); ++ return buf; ++} ++ ++static void free_buffer(struct libscols_buffer *buf) ++{ ++ if (!buf) ++ return; ++ DBG(BUFF, ul_debugobj(buf, "dealloc")); ++ free(buf->encdata); ++ free(buf); ++} ++ ++static int buffer_reset_data(struct libscols_buffer *buf) ++{ ++ if (!buf) ++ return -EINVAL; ++ ++ /*DBG(BUFF, ul_debugobj(buf, "reset data"));*/ ++ buf->begin[0] = '\0'; ++ buf->cur = buf->begin; ++ buf->art_idx = 0; ++ return 0; ++} ++ ++static int buffer_append_data(struct libscols_buffer *buf, const char *str) ++{ ++ size_t maxsz, sz; ++ ++ if (!buf) ++ return -EINVAL; ++ if (!str || !*str) ++ return 0; ++ ++ sz = strlen(str); ++ maxsz = buf->bufsz - (buf->cur - buf->begin); ++ ++ if (maxsz <= sz) ++ return -EINVAL; ++ ++ memcpy(buf->cur, str, sz + 1); ++ buf->cur += sz; ++ return 0; ++} ++ ++static int buffer_set_data(struct libscols_buffer *buf, const char *str) ++{ ++ int rc = buffer_reset_data(buf); ++ return rc ? rc : buffer_append_data(buf, str); ++} ++ ++/* save the current buffer possition to art_idx */ ++static void buffer_set_art_index(struct libscols_buffer *buf) ++{ ++ if (buf) { ++ buf->art_idx = buf->cur - buf->begin; ++ /*DBG(BUFF, ul_debugobj(buf, "art index: %zu", buf->art_idx));*/ ++ } ++} ++ ++static char *buffer_get_data(struct libscols_buffer *buf) ++{ ++ return buf ? buf->begin : NULL; ++} ++ ++/* encode data by mbs_safe_encode() to avoid control and non-printable chars */ ++static char *buffer_get_safe_data(struct libscols_buffer *buf, size_t *cells) ++{ ++ char *data = buffer_get_data(buf); ++ char *res = NULL; ++ ++ if (!data) ++ goto nothing; ++ ++ if (!buf->encdata) { ++ buf->encdata = malloc(mbs_safe_encode_size(buf->bufsz) + 1); ++ if (!buf->encdata) ++ goto nothing; ++ } ++ ++ res = mbs_safe_encode_to_buffer(data, cells, buf->encdata); ++ if (!res || !*cells || *cells == (size_t) -1) ++ goto nothing; ++ return res; ++nothing: ++ *cells = 0; ++ return NULL; ++} ++ ++/* returns size in bytes of the ascii art (according to art_idx) in safe encoding */ ++static size_t buffer_get_safe_art_size(struct libscols_buffer *buf) ++{ ++ char *data = buffer_get_data(buf); ++ size_t bytes = 0; ++ ++ if (!data || !buf->art_idx) ++ return 0; ++ ++ mbs_safe_nwidth(data, buf->art_idx, &bytes); ++ return bytes; ++} ++ ++#define is_last_column(_tb, _cl) \ ++ list_entry_is_last(&(_cl)->cl_columns, &(_tb)->tb_columns) ++ ++#define colsep(tb) ((tb)->colsep ? (tb)->colsep : " ") ++#define linesep(tb) ((tb)->linesep ? (tb)->linesep : "\n") ++ ++static int print_data(struct libscols_table *tb, ++ struct libscols_column *cl, ++ struct libscols_line *ln, /* optional */ ++ struct libscols_cell *ce, /* optional */ ++ struct libscols_buffer *buf) ++{ ++ size_t len = 0, i, width, bytes; ++ const char *color = NULL; ++ char *data; ++ ++ assert(tb); ++ assert(cl); ++ ++ DBG(TAB, ul_debugobj(tb, ++ " -> data, column=%p, line=%p, cell=%p, buff=%p", ++ cl, ln, ce, buf)); ++ ++ data = buffer_get_data(buf); ++ if (!data) ++ data = ""; ++ ++ /* raw mode */ ++ if (scols_table_is_raw(tb)) { ++ fputs_nonblank(data, tb->out); ++ if (!is_last_column(tb, cl)) ++ fputs(colsep(tb), tb->out); ++ return 0; ++ } ++ ++ /* NAME=value mode */ ++ if (scols_table_is_export(tb)) { ++ fprintf(tb->out, "%s=", scols_cell_get_data(&cl->header)); ++ fputs_quoted(data, tb->out); ++ if (!is_last_column(tb, cl)) ++ fputs(colsep(tb), tb->out); ++ return 0; ++ } ++ ++ if (tb->colors_wanted) { ++ if (ce && !color) ++ color = ce->color; ++ if (ln && !color) ++ color = ln->color; ++ if (!color) ++ color = cl->color; ++ } ++ ++ /* encode, note that 'len' and 'width' are number of cells, not bytes */ ++ data = buffer_get_safe_data(buf, &len); ++ if (!data) ++ data = ""; ++ width = cl->width; ++ bytes = strlen(data); ++ ++ if (is_last_column(tb, cl) && len < width && !scols_table_is_maxout(tb)) ++ width = len; ++ ++ /* truncate data */ ++ if (len > width && scols_column_is_trunc(cl)) { ++ len = width; ++ bytes = mbs_truncate(data, &len); /* updates 'len' */ ++ ++ if (!data || bytes == (size_t) -1) { ++ bytes = len = 0; ++ data = NULL; ++ } ++ } ++ ++ if (data) { ++ if (scols_column_is_right(cl)) { ++ size_t xw = cl->width; ++ if (color) ++ fputs(color, tb->out); ++ fprintf(tb->out, "%*s", (int) xw, data); ++ if (color) ++ fputs(UL_COLOR_RESET, tb->out); ++ if (len < xw) ++ len = xw; ++ } else if (color) { ++ char *p = data; ++ size_t art = buffer_get_safe_art_size(buf); ++ ++ /* we don't want to colorize tree ascii art */ ++ if (scols_column_is_tree(cl) && art && art < bytes) { ++ fwrite(p, 1, art, tb->out); ++ p += art; ++ } ++ ++ fputs(color, tb->out); ++ fputs(p, tb->out); ++ fputs(UL_COLOR_RESET, tb->out); ++ } else ++ fputs(data, tb->out); ++ } ++ for (i = len; i < width; i++) ++ fputs(" ", tb->out); /* padding */ ++ ++ if (!is_last_column(tb, cl)) { ++ if (len > width && !scols_column_is_trunc(cl)) { ++ fputs(linesep(tb), tb->out); ++ for (i = 0; i <= (size_t) cl->seqnum; i++) { ++ struct libscols_column *x = scols_table_get_column(tb, i); ++ fprintf(tb->out, "%*s ", -((int)x->width), " "); ++ } ++ } else ++ fputs(colsep(tb), tb->out); /* columns separator */ ++ } ++ ++ return 0; ++} ++ ++/* returns pointer to the end of used data */ ++static int line_ascii_art_to_buffer(struct libscols_table *tb, ++ struct libscols_line *ln, ++ struct libscols_buffer *buf) ++{ ++ const char *art; ++ int rc; ++ ++ assert(ln); ++ assert(buf); ++ ++ if (!ln->parent) ++ return 0; ++ ++ rc = line_ascii_art_to_buffer(tb, ln->parent, buf); ++ if (rc) ++ return rc; ++ ++ if (list_entry_is_last(&ln->ln_children, &ln->parent->ln_branch)) ++ art = " "; ++ else ++ art = tb->symbols->vert; ++ ++ return buffer_append_data(buf, art); ++} ++ ++static int cell_to_buffer(struct libscols_table *tb, ++ struct libscols_line *ln, ++ struct libscols_column *cl, ++ struct libscols_buffer *buf) ++{ ++ const char *data; ++ struct libscols_cell *ce; ++ int rc = 0; ++ ++ assert(tb); ++ assert(ln); ++ assert(cl); ++ assert(buf); ++ assert(cl->seqnum <= tb->ncols); ++ ++ buffer_reset_data(buf); ++ ++ ce = scols_line_get_cell(ln, cl->seqnum); ++ data = ce ? scols_cell_get_data(ce) : NULL; ++ if (!data) ++ return 0; ++ ++ if (!scols_column_is_tree(cl)) ++ return buffer_set_data(buf, data); ++ ++ /* ++ * Tree stuff ++ */ ++ if (ln->parent) { ++ rc = line_ascii_art_to_buffer(tb, ln->parent, buf); ++ ++ if (!rc && list_entry_is_last(&ln->ln_children, &ln->parent->ln_branch)) ++ rc = buffer_append_data(buf, tb->symbols->right); ++ else if (!rc) ++ rc = buffer_append_data(buf, tb->symbols->branch); ++ if (!rc) ++ buffer_set_art_index(buf); ++ } ++ ++ if (!rc) ++ rc = buffer_append_data(buf, data); ++ return rc; ++} ++ ++/* ++ * Prints data, data maybe be printed in more formats (raw, NAME=xxx pairs) and ++ * control and non-printable chars maybe encoded in \x?? hex encoding. ++ */ ++static int print_line(struct libscols_table *tb, ++ struct libscols_line *ln, ++ struct libscols_buffer *buf) ++{ ++ int rc = 0; ++ struct libscols_column *cl; ++ struct libscols_iter itr; ++ ++ assert(ln); ++ ++ DBG(TAB, ul_debugobj(tb, "printing line, line=%p, buff=%p", ln, buf)); ++ ++ scols_reset_iter(&itr, SCOLS_ITER_FORWARD); ++ while (rc == 0 && scols_table_next_column(tb, &itr, &cl) == 0) { ++ rc = cell_to_buffer(tb, ln, cl, buf); ++ if (!rc) ++ rc = print_data(tb, cl, ln, ++ scols_line_get_cell(ln, cl->seqnum), ++ buf); ++ } ++ ++ if (rc == 0) ++ fputs(linesep(tb), tb->out); ++ return 0; ++} ++ ++static int print_header(struct libscols_table *tb, struct libscols_buffer *buf) ++{ ++ int rc = 0; ++ struct libscols_column *cl; ++ struct libscols_iter itr; ++ ++ assert(tb); ++ ++ if (scols_table_is_noheadings(tb) || ++ scols_table_is_export(tb) || ++ list_empty(&tb->tb_lines)) ++ return 0; ++ ++ DBG(TAB, ul_debugobj(tb, "printing header")); ++ ++ /* set width according to the size of data ++ */ ++ scols_reset_iter(&itr, SCOLS_ITER_FORWARD); ++ while (rc == 0 && scols_table_next_column(tb, &itr, &cl) == 0) { ++ rc = buffer_set_data(buf, scols_cell_get_data(&cl->header)); ++ if (!rc) ++ rc = print_data(tb, cl, NULL, &cl->header, buf); ++ } ++ ++ if (rc == 0) ++ fputs(linesep(tb), tb->out); ++ return rc; ++} ++ ++static int print_table(struct libscols_table *tb, struct libscols_buffer *buf) ++{ ++ int rc; ++ struct libscols_line *ln; ++ struct libscols_iter itr; ++ ++ assert(tb); ++ ++ rc = print_header(tb, buf); ++ ++ scols_reset_iter(&itr, SCOLS_ITER_FORWARD); ++ while (rc == 0 && scols_table_next_line(tb, &itr, &ln) == 0) ++ rc = print_line(tb, ln, buf); ++ ++ return rc; ++} ++ ++static int print_tree_line(struct libscols_table *tb, ++ struct libscols_line *ln, ++ struct libscols_buffer *buf) ++{ ++ int rc; ++ struct list_head *p; ++ ++ rc = print_line(tb, ln, buf); ++ if (rc) ++ return rc; ++ if (list_empty(&ln->ln_branch)) ++ return 0; ++ ++ /* print all children */ ++ list_for_each(p, &ln->ln_branch) { ++ struct libscols_line *chld = ++ list_entry(p, struct libscols_line, ln_children); ++ rc = print_tree_line(tb, chld, buf); ++ if (rc) ++ break; ++ } ++ ++ return rc; ++} ++ ++static int print_tree(struct libscols_table *tb, struct libscols_buffer *buf) ++{ ++ int rc; ++ struct libscols_line *ln; ++ struct libscols_iter itr; ++ ++ assert(tb); ++ ++ DBG(TAB, ul_debugobj(tb, "printing tree")); ++ ++ rc = print_header(tb, buf); ++ ++ scols_reset_iter(&itr, SCOLS_ITER_FORWARD); ++ while (rc == 0 && scols_table_next_line(tb, &itr, &ln) == 0) { ++ if (ln->parent) ++ continue; ++ rc = print_tree_line(tb, ln, buf); ++ } ++ ++ return rc; ++} ++ ++static void dbg_column(struct libscols_table *tb, struct libscols_column *cl) ++{ ++ DBG(COL, ul_debugobj(cl, "%15s seq=%zu, width=%zd, " ++ "hint=%d, avg=%zu, max=%zu, min=%zu, " ++ "extreme=%s", ++ ++ cl->header.data, cl->seqnum, cl->width, ++ cl->width_hint > 1 ? (int) cl->width_hint : ++ (int) (cl->width_hint * tb->termwidth), ++ cl->width_avg, ++ cl->width_max, ++ cl->width_min, ++ cl->is_extreme ? "yes" : "not")); ++} ++ ++static void dbg_columns(struct libscols_table *tb) ++{ ++ struct libscols_iter itr; ++ struct libscols_column *cl; ++ ++ scols_reset_iter(&itr, SCOLS_ITER_FORWARD); ++ while (scols_table_next_column(tb, &itr, &cl) == 0) ++ dbg_column(tb, cl); ++} ++ ++/* ++ * This function counts column width. ++ * ++ * For the SCOLS_FL_NOEXTREMES columns is possible to call this function two ++ * times. The first pass counts width and average width. If the column ++ * contains too large fields (width greater than 2 * average) then the column ++ * is marked as "extreme". In the second pass all extreme fields are ignored ++ * and column width is counted from non-extreme fields only. ++ */ ++static int count_column_width(struct libscols_table *tb, ++ struct libscols_column *cl, ++ struct libscols_buffer *buf) ++{ ++ struct libscols_line *ln; ++ struct libscols_iter itr; ++ int count = 0, rc = 0; ++ size_t sum = 0; ++ ++ assert(tb); ++ assert(cl); ++ ++ cl->width = 0; ++ ++ scols_reset_iter(&itr, SCOLS_ITER_FORWARD); ++ while (scols_table_next_line(tb, &itr, &ln) == 0) { ++ size_t len; ++ char *data; ++ ++ rc = cell_to_buffer(tb, ln, cl, buf); ++ if (rc) ++ return rc; ++ ++ data = buffer_get_data(buf); ++ len = data ? mbs_safe_width(data) : 0; ++ ++ if (len == (size_t) -1) /* ignore broken multibyte strings */ ++ len = 0; ++ if (len > cl->width_max) ++ cl->width_max = len; ++ ++ if (cl->is_extreme && len > cl->width_avg * 2) ++ continue; ++ else if (scols_column_is_noextremes(cl)) { ++ sum += len; ++ count++; ++ } ++ if (len > cl->width) ++ cl->width = len; ++ } ++ ++ if (count && cl->width_avg == 0) { ++ cl->width_avg = sum / count; ++ ++ if (cl->width_max > cl->width_avg * 2) ++ cl->is_extreme = 1; ++ } ++ ++ /* check and set minimal column width */ ++ if (scols_cell_get_data(&cl->header)) ++ cl->width_min = mbs_safe_width(scols_cell_get_data(&cl->header)); ++ ++ /* enlarge to minimal width */ ++ if (cl->width < cl->width_min && !scols_column_is_strict_width(cl)) ++ cl->width = cl->width_min; ++ ++ /* use relative size for large columns */ ++ else if (cl->width_hint >= 1 && cl->width < (size_t) cl->width_hint ++ && cl->width_min < (size_t) cl->width_hint) ++ ++ cl->width = (size_t) cl->width_hint; ++ ++ ON_DBG(COL, dbg_column(tb, cl)); ++ return rc; ++} ++ ++ ++/* ++ * This is core of the scols_* voodo... ++ */ ++static int recount_widths(struct libscols_table *tb, struct libscols_buffer *buf) ++{ ++ struct libscols_column *cl; ++ struct libscols_iter itr; ++ size_t width = 0; /* output width */ ++ int trunc_only, rc = 0; ++ int extremes = 0; ++ ++ ++ DBG(TAB, ul_debugobj(tb, "recounting widths (termwidth=%zu)", tb->termwidth)); ++ ++ /* set basic columns width ++ */ ++ scols_reset_iter(&itr, SCOLS_ITER_FORWARD); ++ while (scols_table_next_column(tb, &itr, &cl) == 0) { ++ rc = count_column_width(tb, cl, buf); ++ if (rc) ++ return rc; ++ ++ width += cl->width + (is_last_column(tb, cl) ? 0 : 1); ++ extremes += cl->is_extreme; ++ } ++ ++ if (!tb->is_term) ++ return 0; ++ ++ /* reduce columns with extreme fields ++ */ ++ if (width > tb->termwidth && extremes) { ++ DBG(TAB, ul_debugobj(tb, " reduce width (extreme columns)")); ++ ++ scols_reset_iter(&itr, SCOLS_ITER_FORWARD); ++ while (scols_table_next_column(tb, &itr, &cl) == 0) { ++ size_t org_width; ++ ++ if (!cl->is_extreme) ++ continue; ++ ++ org_width = cl->width; ++ rc = count_column_width(tb, cl, buf); ++ if (rc) ++ return rc; ++ ++ if (org_width > cl->width) ++ width -= org_width - cl->width; ++ else ++ extremes--; /* hmm... nothing reduced */ ++ } ++ } ++ ++ if (width < tb->termwidth) { ++ if (extremes) { ++ DBG(TAB, ul_debugobj(tb, " enlarge width (extreme columns)")); ++ ++ /* enlarge the first extreme column */ ++ scols_reset_iter(&itr, SCOLS_ITER_FORWARD); ++ while (scols_table_next_column(tb, &itr, &cl) == 0) { ++ size_t add; ++ ++ if (!cl->is_extreme) ++ continue; ++ ++ /* this column is tooo large, ignore? ++ if (cl->width_max - cl->width > ++ (tb->termwidth - width)) ++ continue; ++ */ ++ ++ add = tb->termwidth - width; ++ if (add && cl->width + add > cl->width_max) ++ add = cl->width_max - cl->width; ++ ++ cl->width += add; ++ width += add; ++ ++ if (width == tb->termwidth) ++ break; ++ } ++ } ++ ++ if (width < tb->termwidth && scols_table_is_maxout(tb)) { ++ DBG(TAB, ul_debugobj(tb, " enlarge width (max-out)")); ++ ++ /* try enlarge all columns */ ++ while (width < tb->termwidth) { ++ scols_reset_iter(&itr, SCOLS_ITER_FORWARD); ++ while (scols_table_next_column(tb, &itr, &cl) == 0) { ++ cl->width++; ++ width++; ++ if (width == tb->termwidth) ++ break; ++ } ++ } ++ } else if (width < tb->termwidth) { ++ /* enlarge the last column */ ++ struct libscols_column *cl = list_entry( ++ tb->tb_columns.prev, struct libscols_column, cl_columns); ++ ++ DBG(TAB, ul_debugobj(tb, " enlarge width (last column)")); ++ ++ if (!scols_column_is_right(cl) && tb->termwidth - width > 0) { ++ cl->width += tb->termwidth - width; ++ width = tb->termwidth; ++ } ++ } ++ } ++ ++ /* bad, we have to reduce output width, this is done in two steps: ++ * 1/ reduce columns with a relative width and with truncate flag ++ * 2) reduce columns with a relative width without truncate flag ++ */ ++ trunc_only = 1; ++ while (width > tb->termwidth) { ++ size_t org = width; ++ ++ DBG(TAB, ul_debugobj(tb, " reduce width (current=%zu, " ++ "wanted=%zu, mode=%s)", ++ width, tb->termwidth, ++ trunc_only ? "trunc-only" : "all-relative")); ++ ++ scols_reset_iter(&itr, SCOLS_ITER_FORWARD); ++ while (scols_table_next_column(tb, &itr, &cl) == 0) { ++ if (width <= tb->termwidth) ++ break; ++ if (cl->width_hint > 1 && !scols_column_is_trunc(cl)) ++ continue; /* never truncate columns with absolute sizes */ ++ if (scols_column_is_tree(cl)) ++ continue; /* never truncate the tree */ ++ if (trunc_only && !scols_column_is_trunc(cl)) ++ continue; ++ if (cl->width == cl->width_min) ++ continue; ++ ++ /* truncate column with relative sizes */ ++ if (cl->width_hint < 1 && cl->width > 0 && width > 0 && ++ cl->width > cl->width_hint * tb->termwidth) { ++ cl->width--; ++ width--; ++ } ++ /* truncate column with absolute size */ ++ if (cl->width_hint > 1 && cl->width > 0 && width > 0 && ++ !trunc_only) { ++ cl->width--; ++ width--; ++ } ++ ++ } ++ if (org == width) { ++ if (trunc_only) ++ trunc_only = 0; ++ else ++ break; ++ } ++ } ++ ++ DBG(TAB, ul_debugobj(tb, " result: %zu", width)); ++ ON_DBG(TAB, dbg_columns(tb)); ++ ++ return rc; ++} ++ ++static size_t strlen_line(struct libscols_line *ln) ++{ ++ size_t i, sz = 0; ++ ++ assert(ln); ++ ++ for (i = 0; i < ln->ncells; i++) { ++ struct libscols_cell *ce = scols_line_get_cell(ln, i); ++ const char *data = ce ? scols_cell_get_data(ce) : NULL; ++ ++ sz += data ? strlen(data) : 0; ++ } ++ ++ return sz; ++} ++ ++ ++ ++/** ++ * scols_print_table: ++ * @tb: table ++ * ++ * Prints the table to the output stream. ++ * ++ * Returns: 0, a negative value in case of an error. ++ */ ++int scols_print_table(struct libscols_table *tb) ++{ ++ int rc = 0; ++ size_t bufsz; ++ struct libscols_line *ln; ++ struct libscols_iter itr; ++ struct libscols_buffer *buf; ++ ++ assert(tb); ++ if (!tb) ++ return -1; ++ ++ DBG(TAB, ul_debugobj(tb, "printing")); ++ if (!tb->symbols) ++ scols_table_set_symbols(tb, NULL); /* use default */ ++ ++ tb->is_term = isatty(STDOUT_FILENO) ? 1 : 0; ++ tb->termwidth = tb->is_term ? get_terminal_width() : 0; ++ if (tb->termwidth <= 0) ++ tb->termwidth = 80; ++ tb->termwidth -= tb->termreduce; ++ ++ bufsz = tb->termwidth; ++ ++ scols_reset_iter(&itr, SCOLS_ITER_FORWARD); ++ while (scols_table_next_line(tb, &itr, &ln) == 0) { ++ size_t sz = strlen_line(ln); ++ if (sz > bufsz) ++ bufsz = sz; ++ } ++ ++ buf = new_buffer(bufsz + 1); /* data + space for \0 */ ++ if (!buf) ++ return -ENOMEM; ++ ++ if (!(scols_table_is_raw(tb) || scols_table_is_export(tb))) { ++ rc = recount_widths(tb, buf); ++ if (rc != 0) ++ goto done; ++ } ++ ++ if (scols_table_is_tree(tb)) ++ rc = print_tree(tb, buf); ++ else ++ rc = print_table(tb, buf); ++ ++done: ++ free_buffer(buf); ++ return rc; ++} ++ ++/** ++ * scols_print_table_to_string: ++ * @tb: table ++ * @data: pointer to the beginning of a memory area to print to ++ * ++ * Prints the table to @data. ++ * ++ * Returns: 0, a negative value in case of an error. ++ */ ++int scols_print_table_to_string(struct libscols_table *tb, char **data) ++{ ++#ifdef HAVE_OPEN_MEMSTREAM ++ FILE *stream; ++ size_t sz; ++ int rc; ++ ++ if (!tb) ++ return -EINVAL; ++ ++ DBG(TAB, ul_debugobj(tb, "printing to string")); ++ ++ /* create a stream for output */ ++ stream = open_memstream(data, &sz); ++ if (!stream) ++ return -ENOMEM; ++ ++ scols_table_set_stream(tb, stream); ++ rc = scols_print_table(tb); ++ fclose(stream); ++ ++ return rc; ++#else ++ return -ENOSYS; ++#endif ++} ++ +diff -up util-linux-2.23.2/libsmartcols/src/test.c.kzak util-linux-2.23.2/libsmartcols/src/test.c +--- util-linux-2.23.2/libsmartcols/src/test.c.kzak 2014-09-25 14:41:48.993843953 +0200 ++++ util-linux-2.23.2/libsmartcols/src/test.c 2014-09-25 14:41:48.993843953 +0200 +@@ -0,0 +1,218 @@ ++/* ++ * Copyright (C) 2010-2014 Karel Zak ++ * ++ * This file may be redistributed under the terms of the ++ * GNU Lesser General Public License. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "c.h" ++#include "nls.h" ++#include "strutils.h" ++ ++#include "libsmartcols.h" ++ ++static int add_children(struct libscols_table *tb, ++ struct libscols_line *ln, int fd); ++ ++ ++enum { COL_MODE, COL_SIZE, COL_NAME }; ++ ++/* add columns to the @tb */ ++static void setup_columns(struct libscols_table *tb, int notree) ++{ ++ if (!scols_table_new_column(tb, "MODE", 0.3, 0)) ++ goto fail; ++ if (!scols_table_new_column(tb, "SIZE", 5, SCOLS_FL_RIGHT)) ++ goto fail; ++ if (!scols_table_new_column(tb, "NAME", 0.5, ++ (notree ? 0 : SCOLS_FL_TREE) | SCOLS_FL_NOEXTREMES)) ++ goto fail; ++ ++ return; ++fail: ++ scols_unref_table(tb); ++ err(EXIT_FAILURE, "faild to create output columns"); ++} ++ ++/* add a new line to @tb, the content is based on @st */ ++static int add_line_from_stat(struct libscols_table *tb, ++ struct libscols_line *parent, ++ int parent_fd, ++ struct stat *st, ++ const char *name) ++{ ++ struct libscols_line *ln; ++ char modbuf[11], *p; ++ mode_t mode = st->st_mode; ++ int rc = 0; ++ ++ ln = scols_table_new_line(tb, parent); ++ if (!ln) ++ err(EXIT_FAILURE, "failed to create output line"); ++ ++ /* MODE; local buffer, use scols_line_set_data() that calls strdup() */ ++ strmode(mode, modbuf); ++ if (scols_line_set_data(ln, COL_MODE, modbuf)) ++ goto fail; ++ ++ /* SIZE; already allocated string, use scols_line_refer_data() */ ++ p = size_to_human_string(0, st->st_size); ++ if (!p || scols_line_refer_data(ln, COL_SIZE, p)) ++ goto fail; ++ ++ /* NAME */ ++ if (scols_line_set_data(ln, COL_NAME, name)) ++ goto fail; ++ ++ /* colors */ ++ if (scols_table_colors_wanted(tb)) { ++ struct libscols_cell *ce = scols_line_get_cell(ln, COL_NAME); ++ ++ if (S_ISDIR(mode)) ++ scols_cell_set_color(ce, "blue"); ++ else if (S_ISLNK(mode)) ++ scols_cell_set_color(ce, "cyan"); ++ else if (S_ISBLK(mode)) ++ scols_cell_set_color(ce, "magenta"); ++ else if ((mode & S_IXOTH) || (mode & S_IXGRP) || (mode & S_IXUSR)) ++ scols_cell_set_color(ce, "green"); ++ } ++ ++ if (S_ISDIR(st->st_mode)) { ++ int fd; ++ ++ if (parent_fd >= 0) ++ fd = openat(parent_fd, name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC); ++ else ++ fd = open(name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC); ++ if (fd >= 0) { ++ rc = add_children(tb, ln, fd); ++ close(fd); ++ } ++ } ++ return rc; ++fail: ++ err(EXIT_FAILURE, "failed to create cell data"); ++ return -1; ++} ++ ++/* read all entrines from directory addressed by @fd */ ++static int add_children(struct libscols_table *tb, ++ struct libscols_line *ln, ++ int fd) ++{ ++ DIR *dir; ++ struct dirent *d; ++ ++ dir = fdopendir(fd); ++ if (!dir) ++ return -errno; ++ ++ while ((d = readdir(dir))) { ++ struct stat st; ++ ++ if (strcmp(d->d_name, ".") == 0 || strcmp(d->d_name, "..") == 0) ++ continue; ++ if (fstatat(fd, d->d_name, &st, AT_SYMLINK_NOFOLLOW) != 0) ++ continue; ++ add_line_from_stat(tb, ln, fd, &st, d->d_name); ++ } ++ closedir(dir); ++ return 0; ++} ++ ++static void add_lines(struct libscols_table *tb, const char *dirname) ++{ ++ struct stat st; ++ ++ if (lstat(dirname, &st)) ++ err(EXIT_FAILURE, "%s", dirname); ++ ++ add_line_from_stat(tb, NULL, -1, &st, dirname); ++} ++ ++static void __attribute__((__noreturn__)) usage(FILE *out) ++{ ++ fprintf(out, " %s [options] [ ...]\n\n", program_invocation_short_name); ++ fputs(" -c, --csv display a csv-like output\n", out); ++ fputs(" -i, --ascii use ascii characters only\n", out); ++ fputs(" -l, --list use list format output\n", out); ++ fputs(" -n, --noheadings don't print headings\n", out); ++ fputs(" -p, --pairs use key=\"value\" output format\n", out); ++ fputs(" -r, --raw use raw output format\n", out); ++ ++ exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS); ++} ++ ++int main(int argc, char *argv[]) ++{ ++ struct libscols_table *tb; ++ int c, notree = 0; ++ ++ static const struct option longopts[] = { ++ { "ascii", 0, 0, 'i' }, ++ { "csv", 0, 0, 'c' }, ++ { "list", 0, 0, 'l' }, ++ { "noheadings", 0, 0, 'n' }, ++ { "pairs", 0, 0, 'p' }, ++ { "raw", 0, 0, 'r' }, ++ ++ { NULL, 0, 0, 0 }, ++ }; ++ ++ setlocale(LC_ALL, ""); /* just to have enable UTF8 chars */ ++ ++ scols_init_debug(0); ++ ++ tb = scols_new_table(); ++ if (!tb) ++ err(EXIT_FAILURE, "faild to create output table"); ++ ++ while((c = getopt_long(argc, argv, "cilnpr", longopts, NULL)) != -1) { ++ switch(c) { ++ case 'c': ++ scols_table_set_column_separator(tb, ","); ++ scols_table_enable_raw(tb, 1); ++ notree = 1; ++ break; ++ case 'i': ++ scols_table_enable_ascii(tb, 1); ++ break; ++ case 'l': ++ notree = 1; ++ break; ++ case 'n': ++ scols_table_enable_noheadings(tb, 1); ++ break; ++ case 'p': ++ scols_table_enable_export(tb, 1); ++ notree = 1; ++ break; ++ case 'r': ++ scols_table_enable_raw(tb, 1); ++ notree = 1; ++ break; ++ default: ++ usage(stderr); ++ } ++ } ++ ++ scols_table_enable_colors(tb, 1); ++ setup_columns(tb, notree); ++ ++ while (optind < argc) ++ add_lines(tb, argv[optind++]); ++ ++ scols_print_table(tb); ++ scols_unref_table(tb); ++ ++ return EXIT_SUCCESS; ++} +diff -up util-linux-2.23.2/libsmartcols/src/version.c.kzak util-linux-2.23.2/libsmartcols/src/version.c +--- util-linux-2.23.2/libsmartcols/src/version.c.kzak 2014-09-25 14:41:48.993843953 +0200 ++++ util-linux-2.23.2/libsmartcols/src/version.c 2014-09-25 14:41:48.993843953 +0200 +@@ -0,0 +1,62 @@ ++/* ++ * version.c - Return the version of the library ++ * ++ * Copyright (C) 2014 Karel Zak ++ * ++ * See COPYING.libmount for the License of this software. ++ */ ++ ++/** ++ * SECTION: version-utils ++ * @title: Version functions ++ * @short_description: functions to get the library version. ++ * ++ * Note that library version is not the same thing as SONAME version. The ++ * libsmarcols uses symbols versioning and SONAME is not modified for releases. ++ * ++ * The library version and symbols version follow util-linux package versioning. ++ */ ++ ++#include ++ ++#include "smartcolsP.h" ++ ++static const char *lib_version = LIBSMARTCOLS_VERSION; ++ ++/** ++ * scols_parse_version_string: ++ * @ver_string: version string (e.g "2.18.0") ++ * ++ * Returns: release version code. ++ */ ++int scols_parse_version_string(const char *ver_string) ++{ ++ const char *cp; ++ int version = 0; ++ ++ assert(ver_string); ++ ++ for (cp = ver_string; *cp; cp++) { ++ if (*cp == '.') ++ continue; ++ if (!isdigit(*cp)) ++ break; ++ version = (version * 10) + (*cp - '0'); ++ } ++ return version; ++} ++ ++/** ++ * scols_get_library_version: ++ * @ver_string: return pointer to the static library version string if not NULL ++ * ++ * Returns: release version number. ++ */ ++int scols_get_library_version(const char **ver_string) ++{ ++ if (ver_string) ++ *ver_string = lib_version; ++ ++ return scols_parse_version_string(lib_version); ++} ++ +diff -up util-linux-2.23.2/lib/tt.c.kzak util-linux-2.23.2/lib/tt.c +--- util-linux-2.23.2/lib/tt.c.kzak 2013-07-15 10:25:46.280049032 +0200 ++++ util-linux-2.23.2/lib/tt.c 2014-09-25 14:41:48.982843848 +0200 +@@ -52,140 +52,6 @@ static const struct tt_symbols utf8_tt_s + #define is_last_column(_tb, _cl) \ + list_entry_is_last(&(_cl)->cl_columns, &(_tb)->tb_columns) + +-/* +- * Counts number of cells in multibyte string. For all control and +- * non-printable chars is the result width enlarged to store \x?? hex +- * sequence. See mbs_safe_encode(). +- */ +-static size_t mbs_safe_width(const char *s) +-{ +- mbstate_t st; +- const char *p = s; +- size_t width = 0; +- +- memset(&st, 0, sizeof(st)); +- +- while (p && *p) { +- if (iscntrl((unsigned char) *p)) { +- width += 4; /* *p encoded to \x?? */ +- p++; +- } +-#ifdef HAVE_WIDECHAR +- else { +- wchar_t wc; +- size_t len = mbrtowc(&wc, p, MB_CUR_MAX, &st); +- +- if (len == 0) +- break; +- +- if (len == (size_t) -1 || len == (size_t) -2) { +- len = 1; +- width += (isprint((unsigned char) *p) ? 1 : 4); +- +- } if (!iswprint(wc)) +- width += len * 4; /* hex encode whole sequence */ +- else +- width += wcwidth(wc); /* number of cells */ +- p += len; +- } +-#else +- else if (!isprint((unsigned char) *p)) { +- width += 4; /* *p encoded to \x?? */ +- p++; +- } else { +- width++; +- p++; +- } +-#endif +- } +- +- return width; +-} +- +-/* +- * Returns allocated string where all control and non-printable chars are +- * replaced with \x?? hex sequence. +- */ +-static char *mbs_safe_encode(const char *s, size_t *width) +-{ +- mbstate_t st; +- const char *p = s; +- char *res, *r; +- size_t sz = s ? strlen(s) : 0; +- +- +- if (!sz) +- return NULL; +- +- memset(&st, 0, sizeof(st)); +- +- res = malloc((sz * 4) + 1); +- if (!res) +- return NULL; +- +- r = res; +- *width = 0; +- +- while (p && *p) { +- if (iscntrl((unsigned char) *p)) { +- sprintf(r, "\\x%02x", (unsigned char) *p); +- r += 4; +- *width += 4; +- p++; +- } +-#ifdef HAVE_WIDECHAR +- else { +- wchar_t wc; +- size_t len = mbrtowc(&wc, p, MB_CUR_MAX, &st); +- +- if (len == 0) +- break; /* end of string */ +- +- if (len == (size_t) -1 || len == (size_t) -2) { +- len = 1; +- /* +- * Not valid multibyte sequence -- maybe it's +- * printable char according to the current locales. +- */ +- if (!isprint((unsigned char) *p)) { +- sprintf(r, "\\x%02x", (unsigned char) *p); +- r += 4; +- *width += 4; +- } else { +- width++; +- *r++ = *p; +- } +- } else if (!iswprint(wc)) { +- size_t i; +- for (i = 0; i < len; i++) { +- sprintf(r, "\\x%02x", (unsigned char) *p); +- r += 4; +- *width += 4; +- } +- } else { +- memcpy(r, p, len); +- r += len; +- *width += wcwidth(wc); +- } +- p += len; +- } +-#else +- else if (!isprint((unsigned char) *p)) { +- sprintf(r, "\\x%02x", (unsigned char) *p); +- p++; +- r += 4; +- *width += 4; +- } else { +- *r++ = *p++; +- *width++; +- } +-#endif +- } +- +- *r = '\0'; +- +- return res; +-} + + /* + * @flags: TT_FL_* flags (usually TT_FL_{ASCII,RAW}) +diff -up util-linux-2.23.2/Makefile.am.kzak util-linux-2.23.2/Makefile.am +--- util-linux-2.23.2/Makefile.am.kzak 2013-06-13 09:46:10.334649886 +0200 ++++ util-linux-2.23.2/Makefile.am 2014-09-25 14:41:48.979843819 +0200 +@@ -22,6 +22,7 @@ dist_noinst_DATA = $(dist_man_MANS) + # + ul_libblkid_incdir = $(top_builddir)/libblkid/src + ul_libmount_incdir = $(top_builddir)/libmount/src ++ul_libsmartcols_incdir = $(top_builddir)/libsmartcols/src + ul_libuuid_incdir = $(top_srcdir)/libuuid/src + ul_libfdisk_incdir = $(top_srcdir)/libfdisk/src + +@@ -77,6 +78,7 @@ include lib/Makemodule.am + include libuuid/Makemodule.am + include libblkid/Makemodule.am + include libmount/Makemodule.am ++include libsmartcols/Makemodule.am + include libfdisk/Makemodule.am + + include schedutils/Makemodule.am diff --git a/SOURCES/2.26-lslogins.patch b/SOURCES/2.26-lslogins.patch new file mode 100644 index 0000000..f2063ce --- /dev/null +++ b/SOURCES/2.26-lslogins.patch @@ -0,0 +1,2121 @@ +diff -up util-linux-2.23.2/configure.ac.kzak util-linux-2.23.2/configure.ac +--- util-linux-2.23.2/configure.ac.kzak 2014-09-25 14:47:46.944259193 +0200 ++++ util-linux-2.23.2/configure.ac 2014-09-25 14:48:20.087575417 +0200 +@@ -1027,6 +1027,11 @@ UL_REQUIRES_HAVE([lscpu], [cpu_set_t], [ + AM_CONDITIONAL(BUILD_LSCPU, test "x$build_lscpu" = xyes) + + ++UL_BUILD_INIT([lslogins], [check]) ++UL_REQUIRES_BUILD([lslogins], [libsmartcols]) ++AM_CONDITIONAL([BUILD_LSLOGINS], [test "x$build_lslogins" = xyes]) ++ ++ + UL_BUILD_INIT([chcpu], [check]) + UL_REQUIRES_LINUX([chcpu]) + UL_REQUIRES_HAVE([chcpu], [cpu_set_t], [cpu_set_t type]) +@@ -1404,6 +1409,37 @@ fi + AM_CONDITIONAL(HAVE_SYSTEMD, [test -n "$with_systemdsystemunitdir" -a "x$with_systemdsystemunitdir" != "xno" ]) + + ++# ++# Backport from upstrem to RHEL7.1 ++# ++AC_ARG_WITH([systemd], ++ AS_HELP_STRING([--with-systemd], [build with support for systemd]), ++ [], [with_systemd=check] ++) ++ ++have_systemd=no ++AS_IF([test "x$with_systemd" != xno], [ ++ # new version -- all libsystemd-* libs merged into libsystemd ++ PKG_CHECK_MODULES([SYSTEMD], [libsystemd], [have_systemd=yes], [have_systemd=no]) ++ # old versions ++ AS_IF([test "x$have_systemd" != "xyes"], [ ++ PKG_CHECK_MODULES([SYSTEMD_DAEMON], [libsystemd-daemon], ++ [have_systemd_daemon=yes], [have_systemd_daemon=no]) ++ PKG_CHECK_MODULES([SYSTEMD_JOURNAL], [libsystemd-journal], ++ [have_systemd_journal=yes], [have_systemd_journal=no]) ++ AS_IF([test "x$have_systemd_daemon" = "xyes" -a "x$have_systemd_journal" = "xyes" ],[ ++ have_systemd=yes]) ++ ]) ++ AS_CASE([$with_systemd:$have_systemd], ++ [yes:no], ++ [AC_MSG_ERROR([systemd expected but libsystemd not found])], ++ [*:yes], ++ AC_DEFINE([HAVE_LIBSYSTEMD], [1], [Define if libsystemd is available]) ++ ) ++]) ++ ++ ++ + AC_ARG_WITH([bashcompletiondir], + AS_HELP_STRING([--with-bashcompletiondir=DIR], [Bash completions directory]), + [], +diff -up util-linux-2.23.2/include/Makemodule.am.kzak util-linux-2.23.2/include/Makemodule.am +--- util-linux-2.23.2/include/Makemodule.am.kzak 2013-07-15 10:25:46.277049008 +0200 ++++ util-linux-2.23.2/include/Makemodule.am 2014-09-25 14:48:20.087575417 +0200 +@@ -35,6 +35,7 @@ dist_noinst_HEADERS += \ + include/procutils.h \ + include/randutils.h \ + include/rpmatch.h \ ++ include/readutmp.h \ + include/setproctitle.h \ + include/strutils.h \ + include/swapheader.h \ +diff -up util-linux-2.23.2/include/readutmp.h.kzak util-linux-2.23.2/include/readutmp.h +--- util-linux-2.23.2/include/readutmp.h.kzak 2014-09-25 14:48:20.088575426 +0200 ++++ util-linux-2.23.2/include/readutmp.h 2014-09-25 14:48:20.087575417 +0200 +@@ -0,0 +1,28 @@ ++/* Declarations for GNU's read utmp module. ++ ++ Copyright (C) 1992-2007, 2009-2014 Free Software Foundation, Inc. ++ ++ 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 3 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 . */ ++ ++/* Written by jla; revised by djm */ ++ ++#ifndef READUTMP_H ++#define READUTMP_H ++ ++#include ++#include ++ ++int read_utmp (char const *file, size_t *n_entries, struct utmp **utmp_buf); ++ ++#endif /* READUTMP_H */ +diff -up util-linux-2.23.2/lib/Makemodule.am.kzak util-linux-2.23.2/lib/Makemodule.am +--- util-linux-2.23.2/lib/Makemodule.am.kzak 2013-07-30 10:39:26.202738200 +0200 ++++ util-linux-2.23.2/lib/Makemodule.am 2014-09-25 14:48:20.088575426 +0200 +@@ -25,7 +25,8 @@ libcommon_la_SOURCES = \ + lib/wholedisk.c \ + lib/ttyutils.c \ + lib/xgetpass.c \ +- lib/exec_shell.c ++ lib/exec_shell.c \ ++ lib/readutmp.c + + if LINUX + libcommon_la_SOURCES += \ +diff -up util-linux-2.23.2/lib/readutmp.c.kzak util-linux-2.23.2/lib/readutmp.c +--- util-linux-2.23.2/lib/readutmp.c.kzak 2014-09-25 14:48:20.088575426 +0200 ++++ util-linux-2.23.2/lib/readutmp.c 2014-09-25 14:48:20.088575426 +0200 +@@ -0,0 +1,76 @@ ++/* GNU's read utmp module. ++ ++ Copyright (C) 1992-2001, 2003-2006, 2009-2014 Free Software Foundation, Inc. ++ ++ 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 3 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 . */ ++ ++/* Written by jla; revised by djm */ ++/* extracted for util-linux by ooprala */ ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "xalloc.h" ++#include "readutmp.h" ++ ++/* Read the utmp entries corresponding to file FILE into freshly- ++ malloc'd storage, set *UTMP_BUF to that pointer, set *N_ENTRIES to ++ the number of entries, and return zero. If there is any error, ++ return -1, setting errno, and don't modify the parameters. ++ If OPTIONS & READ_UTMP_CHECK_PIDS is nonzero, omit entries whose ++ process-IDs do not currently exist. */ ++int ++read_utmp (char const *file, size_t *n_entries, struct utmp **utmp_buf) ++{ ++ size_t n_read = 0; ++ size_t n_alloc = 0; ++ struct utmp *utmp = NULL; ++ struct utmp *u; ++ ++ /* Ignore the return value for now. ++ Solaris' utmpname returns 1 upon success -- which is contrary ++ to what the GNU libc version does. In addition, older GNU libc ++ versions are actually void. */ ++ utmpname(file); ++ ++ setutent(); ++ ++ errno = 0; ++ while ((u = getutent()) != NULL) { ++ if (n_read == n_alloc) { ++ n_alloc += 32; ++ utmp = xrealloc(utmp, n_alloc * sizeof (struct utmp)); ++ if (!utmp) ++ return -1; ++ } ++ utmp[n_read++] = *u; ++ } ++ if (!u && errno) ++ return -1; ++ ++ endutent(); ++ ++ *n_entries = n_read; ++ *utmp_buf = utmp; ++ ++ return 0; ++} +diff -up util-linux-2.23.2/login-utils/login.c.kzak util-linux-2.23.2/login-utils/login.c +--- util-linux-2.23.2/login-utils/login.c.kzak 2014-09-25 14:47:46.870258487 +0200 ++++ util-linux-2.23.2/login-utils/login.c 2014-09-25 14:48:50.503865622 +0200 +@@ -923,124 +923,6 @@ static void loginpam_session(struct logi + } + + /* +- * We need to check effective UID/GID. For example $HOME could be on root +- * squashed NFS or on NFS with UID mapping and access(2) uses real UID/GID. +- * The open(2) seems as the surest solution. +- * -- kzak@redhat.com (10-Apr-2009) +- */ +-static int effective_access(const char *path, int mode) +-{ +- int fd = open(path, mode); +- if (fd != -1) +- close(fd); +- return fd == -1 ? -1 : 0; +-} +- +-/* +- * Check per accout or global hush-login setting. +- * +- * Hushed mode is enabled: +- * +- * a) if global (e.g. /etc/hushlogins) hush file exists: +- * 1) for ALL ACCOUNTS if the file is empty +- * 2) for the current user if the username or shell are found in the file +- * +- * b) if ~/.hushlogin file exists +- * +- * The ~/.hushlogin is ignored if the global hush file exists. +- * +- * The HUSHLOGIN_FILE login.def variable overwrites the default hush filename. +- * +- * Note that shadow-utils login(1) does not support "a1)". The "a1)" is +- * necessary if you want to use PAM for "Last login" message. +- * +- * -- Karel Zak (26-Aug-2011) +- * +- * +- * Per-account check requires some explanation: As root we may not be able to +- * read the directory of the user if it is on an NFS mounted filesystem. We +- * temporarily set our effective uid to the user-uid making sure that we keep +- * root privs. in the real uid. +- * +- * A portable solution would require a fork(), but we rely on Linux having the +- * BSD setreuid() +- */ +-static int get_hushlogin_status(struct passwd *pwd) +-{ +- const char *files[] = { _PATH_HUSHLOGINS, _PATH_HUSHLOGIN, NULL }; +- const char *file; +- char buf[BUFSIZ]; +- int i; +- +- file = getlogindefs_str("HUSHLOGIN_FILE", NULL); +- if (file) { +- if (!*file) +- return 0; /* empty HUSHLOGIN_FILE defined */ +- +- files[0] = file; +- files[1] = NULL; +- } +- +- for (i = 0; files[i]; i++) { +- int ok = 0; +- +- file = files[i]; +- +- /* Global hush-file*/ +- if (*file == '/') { +- struct stat st; +- FILE *f; +- +- if (stat(file, &st) != 0) +- continue; /* file does not exist */ +- +- if (st.st_size == 0) +- return 1; /* for all accounts */ +- +- f = fopen(file, "r"); +- if (!f) +- continue; /* ignore errors... */ +- +- while (ok == 0 && fgets(buf, sizeof(buf), f)) { +- buf[strlen(buf) - 1] = '\0'; +- ok = !strcmp(buf, *buf == '/' ? pwd->pw_shell : +- pwd->pw_name); +- } +- fclose(f); +- if (ok) +- return 1; /* found username/shell */ +- +- return 0; /* ignore per-account files */ +- } +- +- /* Per-account setting */ +- if (strlen(pwd->pw_dir) + sizeof(file) + 2 > sizeof(buf)) +- continue; +- else { +- uid_t ruid = getuid(); +- gid_t egid = getegid(); +- +- sprintf(buf, "%s/%s", pwd->pw_dir, file); +- +- if (setregid(-1, pwd->pw_gid) == 0 && +- setreuid(0, pwd->pw_uid) == 0) +- ok = effective_access(buf, O_RDONLY) == 0; +- +- if (setuid(0) != 0 || +- setreuid(ruid, 0) != 0 || +- setregid(-1, egid) != 0) { +- syslog(LOG_ALERT, _("hush login status: restore original IDs failed")); +- exit(EXIT_FAILURE); +- } +- if (ok) +- return 1; /* enabled by user */ +- } +- } +- +- return 0; +-} +- +-/* + * Detach the controlling terminal, fork, restore syslog stuff and create a new + * session. + */ +@@ -1372,7 +1254,7 @@ int main(int argc, char **argv) + + endpwent(); + +- cxt.quiet = get_hushlogin_status(pwd); ++ cxt.quiet = get_hushlogin_status(pwd, 1); + + log_utmp(&cxt); + log_audit(&cxt, 1); +diff -up util-linux-2.23.2/login-utils/logindefs.c.kzak util-linux-2.23.2/login-utils/logindefs.c +--- util-linux-2.23.2/login-utils/logindefs.c.kzak 2013-06-13 09:46:10.442650810 +0200 ++++ util-linux-2.23.2/login-utils/logindefs.c 2014-09-25 14:48:20.088575426 +0200 +@@ -27,6 +27,9 @@ + #include + #include + #include ++#include ++#include ++#include + + #include "c.h" + #include "closestream.h" +@@ -259,6 +262,135 @@ int logindefs_setenv(const char *name, c + return val ? setenv(name, val, 1) : -1; + } + ++/* ++ * We need to check the effective UID/GID. For example, $HOME could be on a ++ * root-squashed NFS or on an NFS with UID mapping, and access(2) uses the ++ * real UID/GID. Then open(2) seems as the surest solution. ++ * -- kzak@redhat.com (10-Apr-2009) ++ */ ++int effective_access(const char *path, int mode) ++{ ++ int fd = open(path, mode); ++ if (fd != -1) ++ close(fd); ++ return fd == -1 ? -1 : 0; ++} ++ ++ ++/* ++ * Check the per-account or the global hush-login setting. ++ * ++ * Hushed mode is enabled: ++ * ++ * a) if a global (e.g. /etc/hushlogins) hush file exists: ++ * 1) for ALL ACCOUNTS if the file is empty ++ * 2) for the current user if the username or shell is found in the file ++ * ++ * b) if a ~/.hushlogin file exists ++ * ++ * The ~/.hushlogin file is ignored if the global hush file exists. ++ * ++ * The HUSHLOGIN_FILE login.def variable overrides the default hush filename. ++ * ++ * Note that shadow-utils login(1) does not support "a1)". The "a1)" is ++ * necessary if you want to use PAM for "Last login" message. ++ * ++ * -- Karel Zak (26-Aug-2011) ++ * ++ * ++ * The per-account check requires some explanation: As root we may not be able ++ * to read the directory of the user if it is on an NFS-mounted filesystem. We ++ * temporarily set our effective uid to the user-uid, making sure that we keep ++ * root privileges in the real uid. ++ * ++ * A portable solution would require a fork(), but we rely on Linux having the ++ * BSD setreuid(). ++ */ ++ ++int get_hushlogin_status(struct passwd *pwd, int force_check) ++{ ++ const char *files[] = { _PATH_HUSHLOGINS, _PATH_HUSHLOGIN, NULL }; ++ const char *file; ++ char buf[BUFSIZ]; ++ int i; ++ ++ file = getlogindefs_str("HUSHLOGIN_FILE", NULL); ++ if (file) { ++ if (!*file) ++ return 0; /* empty HUSHLOGIN_FILE defined */ ++ ++ files[0] = file; ++ files[1] = NULL; ++ } ++ ++ for (i = 0; files[i]; i++) { ++ int ok = 0; ++ ++ file = files[i]; ++ ++ /* global hush-file */ ++ if (*file == '/') { ++ struct stat st; ++ FILE *f; ++ ++ if (stat(file, &st) != 0) ++ continue; /* file does not exist */ ++ ++ if (st.st_size == 0) ++ return 1; /* for all accounts */ ++ ++ f = fopen(file, "r"); ++ if (!f) ++ continue; /* ignore errors... */ ++ ++ while (ok == 0 && fgets(buf, sizeof(buf), f)) { ++ buf[strlen(buf) - 1] = '\0'; ++ ok = !strcmp(buf, *buf == '/' ? pwd->pw_shell : ++ pwd->pw_name); ++ } ++ fclose(f); ++ if (ok) ++ return 1; /* found username/shell */ ++ ++ return 0; /* ignore per-account files */ ++ } ++ ++ /* per-account setting */ ++ if (strlen(pwd->pw_dir) + sizeof(file) + 2 > sizeof(buf)) ++ continue; ++ ++ sprintf(buf, "%s/%s", pwd->pw_dir, file); ++ ++ if (force_check) { ++ uid_t ruid = getuid(); ++ gid_t egid = getegid(); ++ ++ if (setregid(-1, pwd->pw_gid) == 0 && ++ setreuid(0, pwd->pw_uid) == 0) ++ ok = effective_access(buf, O_RDONLY) == 0; ++ ++ if (setuid(0) != 0 || ++ setreuid(ruid, 0) != 0 || ++ setregid(-1, egid) != 0) { ++ syslog(LOG_ALERT, _("hush login status: restore original IDs failed")); ++ exit(EXIT_FAILURE); ++ } ++ if (ok) ++ return 1; /* enabled by user */ ++ } ++ else { ++ int rc; ++ rc = effective_access(buf, O_RDONLY); ++ if (rc == 0) ++ return 1; ++ else if (rc == -1 && errno == EACCES) ++ return -1; ++ } ++ ++ } ++ ++ return 0; ++} + #ifdef TEST_PROGRAM + int main(int argc, char *argv[]) + { +diff -up util-linux-2.23.2/login-utils/logindefs.h.kzak util-linux-2.23.2/login-utils/logindefs.h +--- util-linux-2.23.2/login-utils/logindefs.h.kzak 2013-02-27 17:46:29.887020770 +0100 ++++ util-linux-2.23.2/login-utils/logindefs.h 2014-09-25 14:48:20.088575426 +0200 +@@ -8,5 +8,7 @@ extern unsigned long getlogindefs_num(co + extern const char *getlogindefs_str(const char *name, const char *dflt); + extern void free_getlogindefs_data(void); + extern int logindefs_setenv(const char *name, const char *conf, const char *dflt); ++extern int effective_access(const char *path, int mode); ++extern int get_hushlogin_status(struct passwd *pwd, int force_check); + + #endif /* UTIL_LINUX_LOGINDEFS_H */ +diff -up util-linux-2.23.2/login-utils/lslogins.1.kzak util-linux-2.23.2/login-utils/lslogins.1 +--- util-linux-2.23.2/login-utils/lslogins.1.kzak 2014-09-25 14:48:20.088575426 +0200 ++++ util-linux-2.23.2/login-utils/lslogins.1 2014-09-25 14:48:20.088575426 +0200 +@@ -0,0 +1,132 @@ ++.\" Copyright 2014 Ondrej Oprala (ondrej.oprala@gmail.com) ++.\" May be distributed under the GNU General Public License ++.TH LSLOGINS "1" "April 2014" "util-linux" "User Commands" ++.SH NAME ++lslogins \- display information about known users in the system ++.SH SYNOPSIS ++.B lslogins ++[\fIoptions\fR] [\fB-s\fR|\fB-u\fR[=\fIUID\fR]] [\fB-g \fIgroups\fR] [\fB-l \fIlogins\fR] ++.SH DESCRIPTION ++.PP ++Examine the wtmp and btmp logs, /etc/shadow (if necessary) and /etc/passwd ++and output the desired data. ++.PP ++The default action is to list info about all the users in the system. ++.SH OPTIONS ++Mandatory arguments to long options are mandatory for short options too. ++.TP ++\fB\-a\fR, \fB\-\-acc\-expiration\fR ++Display data about the date of last password change and the account expiration ++date (see \fBshadow\fR(5) for more info). (Requires root priviliges.) ++.TP ++\fB\-\-btmp\-file \fIpath\fP ++Alternate path for btmp. ++.TP ++\fB\-c\fR, \fB\-\-colon\-separate\fR ++Separate info about each user with a colon instead of a newline. ++.TP ++\fB\-e\fR, \fB\-\-export\fR ++Output data in the format of NAME=VALUE. ++.TP ++\fB\-f\fR, \fB\-\-failed\fR ++Display data about the users' last failed login attempts. ++.TP ++\fB\-G\fR, \fB\-\-groups\-info\fR ++Show information about groups. ++.TP ++\fB\-g\fR, \fB\-\-groups\fR=\fIgroups\fR ++Only show data of users belonging to \fIgroups\fR. More than one group ++may be specified; the list has to be comma-separated. ++.TP ++\fB\-h\fR, \fB\-\-help\fR ++Display help information and exit. ++.TP ++\fB\-L\fR, \fB\-\-last\fR ++Display data containing information about the users' last login sessions. ++.TP ++\fB\-l\fR, \fB\-\-logins\fR=\fIlogins\fR ++Only show data of users with a login specified in \fIlogins\fR (user names or user ++IDS). More than one login may be specified; the list has to be comma-separated. ++.TP ++\fB\-m\fR, \fB\-\-supp\-groups\fR ++Show supplementary groups. ++.TP ++\fB\-n\fR, \fB\-\-newline\fR ++Display each piece of information on a separate line. ++.TP ++\fB\-\-noheadings\fR ++Do not print a header line. ++.TP ++\fB\-\-notruncate\fR ++Don't truncate output. ++.TP ++\fB\-o\fR, \fB\-\-output \fIlist\fP ++Specify which output columns to print. Use ++.B \-\-help ++to get a list of all supported columns. ++.TP ++\fB\-p\fR, \fB\-\-pwd\fR ++Display information related to login by password (see also \fB\-afL). ++.TP ++\fB\-r\fR, \fB\-\-raw\fR ++Raw output (no columnation). ++.TP ++\fB\-s\fR, \fB\-\-system\-accs\fR[=\fIthreshold\fR] ++Show system accounts. These are by default all accounts with a UID below 1000 ++(non-inclusive), with the exception of either nobody or nfsnobody (UID 65534). The UID ++threshold can also be specified explicitly (necessary for some distributions that ++allocate UIDs starting from 100, 500 - or an entirely different value - rather than 1000). ++.TP ++\fB\-\-time-format\fR \fItype\fP ++Display dates in short, full or iso format. The default is short, this time ++format is designed to be space efficient and human readable. ++.TP ++\fB\-u\fR, \fB\-\-user\-accs\fR[=\fIthreshold\fR] ++Show user accounts. These are by default all accounts with UID above 1000 ++(inclusive), with the exception of either nobody or nfsnobody (UID 65534). The UID ++threshold can also be specified explicitly (necessary for some distributions that ++allocate UIDs starting from 100, 500 - or an entirely different value - rather than 1000). ++.TP ++\fB\-V\fR, \fB\-\-version\fR ++Display version information and exit. ++.TP ++\fB\-\-wtmp\-file \fIpath\fP ++Alternate path for wtmp. ++.TP ++\fB\-Z\fR, \fB\-\-context\fR ++Display the users' security context. ++.TP ++\fB\-z\fR, \fB\-\-print0\fR ++Delimit user entries with a nul character, instead of a newline. ++ ++.SH NOTES ++The default UID thresholds are read from /etc/login.defs. ++ ++.SH EXIT STATUS ++.TP ++0 ++if OK, ++.TP ++1 ++if incorrect arguments specified, ++.TP ++2 ++if a serious error occurs (e.g. a corrupt log). ++.SH SEE ALSO ++\fBgroup\fP(5), \fBpasswd\fP(5), \fBshadow\fP(5), \fButmp\fP(5) ++.SH HISTORY ++The \fBlslogins\fP utility is inspired by the \fBlogins\fP utility, which first appeared in FreeBSD 4.10. ++.SH AUTHORS ++.MT ooprala@redhat.com ++Ondrej Oprala ++.ME ++.br ++.MT kzak@redhat.com ++Karel Zak ++.ME ++ ++.SH AVAILABILITY ++The lslogins command is part of the util-linux package and is available from ++.UR ftp://\:ftp.kernel.org\:/pub\:/linux\:/utils\:/util-linux/ ++Linux Kernel Archive ++.UE . +diff -up util-linux-2.23.2/login-utils/lslogins.c.kzak util-linux-2.23.2/login-utils/lslogins.c +--- util-linux-2.23.2/login-utils/lslogins.c.kzak 2014-09-25 14:48:20.089575436 +0200 ++++ util-linux-2.23.2/login-utils/lslogins.c 2014-09-25 14:48:20.089575436 +0200 +@@ -0,0 +1,1466 @@ ++/* ++ * lslogins - List information about users on the system ++ * ++ * Copyright (C) 2014 Ondrej Oprala ++ * Copyright (C) 2014 Karel Zak ++ * ++ * 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 would 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 Foundation, Inc., ++ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include ++#ifdef HAVE_LIBSELINUX ++# include ++#endif ++ ++#ifdef HAVE_LIBSYSTEMD ++# include ++#endif ++ ++#include "c.h" ++#include "nls.h" ++#include "closestream.h" ++#include "xalloc.h" ++#include "list.h" ++#include "strutils.h" ++#include "optutils.h" ++#include "pathnames.h" ++#include "logindefs.h" ++#include "readutmp.h" ++#include "procutils.h" ++ ++/* ++ * column description ++ */ ++struct lslogins_coldesc { ++ const char *name; ++ const char *help; ++ const char *pretty_name; ++ ++ double whint; /* width hint */ ++ long flag; ++}; ++ ++static int lslogins_flag; ++ ++#define UL_UID_MIN 1000 ++#define UL_UID_MAX 60000 ++#define UL_SYS_UID_MIN 201 ++#define UL_SYS_UID_MAX 999 ++ ++/* we use the value of outmode to determine ++ * appropriate flags for the libsmartcols table ++ * (e.g., a value of out_newline would imply a raw ++ * table with the column separator set to '\n'). ++ */ ++static int outmode; ++/* ++ * output modes ++ */ ++enum { ++ OUT_COLON = 1, ++ OUT_EXPORT, ++ OUT_NEWLINE, ++ OUT_RAW, ++ OUT_NUL, ++ OUT_PRETTY ++}; ++ ++struct lslogins_user { ++ char *login; ++ uid_t uid; ++ char *group; ++ gid_t gid; ++ char *gecos; ++ ++ int pwd_empty; ++ int nologin; ++ int pwd_lock; ++ int pwd_deny; ++ ++ gid_t *sgroups; ++ size_t nsgroups; ++ ++ char *pwd_ctime; ++ char *pwd_warn; ++ char *pwd_expire; ++ char *pwd_ctime_min; ++ char *pwd_ctime_max; ++ ++ char *last_login; ++ char *last_tty; ++ char *last_hostname; ++ ++ char *failed_login; ++ char *failed_tty; ++ ++#ifdef HAVE_LIBSELINUX ++ security_context_t context; ++#endif ++ char *homedir; ++ char *shell; ++ char *pwd_status; ++ int hushed; ++ char *nprocs; ++ ++}; ++ ++/* ++ * time modes ++ * */ ++enum { ++ TIME_INVALID = 0, ++ TIME_SHORT, ++ TIME_FULL, ++ TIME_ISO, ++}; ++ ++/* ++ * flags ++ */ ++enum { ++ F_SYSAC = (1 << 3), ++ F_USRAC = (1 << 4), ++}; ++ ++/* ++ * IDs ++ */ ++enum { ++ COL_USER = 0, ++ COL_UID, ++ COL_GECOS, ++ COL_HOME, ++ COL_SHELL, ++ COL_NOLOGIN, ++ COL_PWDLOCK, ++ COL_PWDEMPTY, ++ COL_PWDDENY, ++ COL_GROUP, ++ COL_GID, ++ COL_SGROUPS, ++ COL_SGIDS, ++ COL_LAST_LOGIN, ++ COL_LAST_TTY, ++ COL_LAST_HOSTNAME, ++ COL_FAILED_LOGIN, ++ COL_FAILED_TTY, ++ COL_HUSH_STATUS, ++ COL_PWD_WARN, ++ COL_PWD_CTIME, ++ COL_PWD_CTIME_MIN, ++ COL_PWD_CTIME_MAX, ++ COL_PWD_EXPIR, ++ COL_SELINUX, ++ COL_NPROCS, ++}; ++ ++#define is_wtmp_col(x) ((x) == COL_LAST_LOGIN || \ ++ (x) == COL_LAST_TTY || \ ++ (x) == COL_LAST_HOSTNAME) ++ ++#define is_btmp_col(x) ((x) == COL_FAILED_LOGIN || \ ++ (x) == COL_FAILED_TTY) ++ ++enum { ++ STATUS_FALSE = 0, ++ STATUS_TRUE, ++ STATUS_UNKNOWN ++}; ++ ++static const char *const status[] = { ++ [STATUS_FALSE] = "0", ++ [STATUS_TRUE] = "1", ++ [STATUS_UNKNOWN]= NULL ++}; ++ ++static const char *const pretty_status[] = { ++ [STATUS_FALSE] = N_("no"), ++ [STATUS_TRUE] = N_("yes"), ++ [STATUS_UNKNOWN]= NULL ++}; ++ ++#define get_status(x) (outmode == OUT_PRETTY ? pretty_status[(x)] : status[(x)]) ++ ++static const struct lslogins_coldesc coldescs[] = ++{ ++ [COL_USER] = { "USER", N_("user name"), N_("Username"), 0.1, SCOLS_FL_NOEXTREMES }, ++ [COL_UID] = { "UID", N_("user ID"), "UID", 1, SCOLS_FL_RIGHT}, ++ [COL_PWDEMPTY] = { "PWD-EMPTY", N_("password not required"), N_("Password not required"), 1, SCOLS_FL_RIGHT }, ++ [COL_PWDDENY] = { "PWD-DENY", N_("login by password disabled"), N_("Login by password disabled"), 1, SCOLS_FL_RIGHT }, ++ [COL_PWDLOCK] = { "PWD-LOCK", N_("password defined, but locked"), N_("Password is locked"), 1, SCOLS_FL_RIGHT }, ++ [COL_NOLOGIN] = { "NOLOGIN", N_("log in disabled by nologin(8) or pam_nologin(8)"), N_("No login"), 1, SCOLS_FL_RIGHT }, ++ [COL_GROUP] = { "GROUP", N_("primary group name"), N_("Primary group"), 0.1 }, ++ [COL_GID] = { "GID", N_("primary group ID"), "GID", 1, SCOLS_FL_RIGHT }, ++ [COL_SGROUPS] = { "SUPP-GROUPS", N_("supplementary group names"), N_("Supplementary groups"), 0.1 }, ++ [COL_SGIDS] = { "SUPP-GIDS", N_("supplementary group IDs"), N_("Supplementary group IDs"), 0.1 }, ++ [COL_HOME] = { "HOMEDIR", N_("home directory"), N_("Home directory"), 0.1 }, ++ [COL_SHELL] = { "SHELL", N_("login shell"), N_("Shell"), 0.1 }, ++ [COL_GECOS] = { "GECOS", N_("full user name"), N_("Gecos field"), 0.1, SCOLS_FL_TRUNC }, ++ [COL_LAST_LOGIN] = { "LAST-LOGIN", N_("date of last login"), N_("Last login"), 0.1, SCOLS_FL_RIGHT }, ++ [COL_LAST_TTY] = { "LAST-TTY", N_("last tty used"), N_("Last terminal"), 0.05 }, ++ [COL_LAST_HOSTNAME] = { "LAST-HOSTNAME",N_("hostname during the last session"), N_("Last hostname"), 0.1}, ++ [COL_FAILED_LOGIN] = { "FAILED-LOGIN", N_("date of last failed login"), N_("Failed login"), 0.1 }, ++ [COL_FAILED_TTY] = { "FAILED-TTY", N_("where did the login fail?"), N_("Failed login terminal"), 0.05 }, ++ [COL_HUSH_STATUS] = { "HUSHED", N_("user's hush settings"), N_("Hushed"), 1, SCOLS_FL_RIGHT }, ++ [COL_PWD_WARN] = { "PWD-WARN", N_("days user is warned of password expiration"), N_("Password expiration warn interval"), 0.1, SCOLS_FL_RIGHT }, ++ [COL_PWD_EXPIR] = { "PWD-EXPIR", N_("password expiration date"), N_("Password expiration"), 0.1, SCOLS_FL_RIGHT }, ++ [COL_PWD_CTIME] = { "PWD-CHANGE", N_("date of last password change"), N_("Password changed"), 0.1, SCOLS_FL_RIGHT}, ++ [COL_PWD_CTIME_MIN] = { "PWD-MIN", N_("number of days required between changes"), N_("Minimum change time"), 0.1, SCOLS_FL_RIGHT }, ++ [COL_PWD_CTIME_MAX] = { "PWD-MAX", N_("max number of days a password may remain unchanged"), N_("Maximum change time"), 0.1, SCOLS_FL_RIGHT }, ++ [COL_SELINUX] = { "CONTEXT", N_("the user's security context"), N_("Selinux context"), 0.1 }, ++ [COL_NPROCS] = { "PROC", N_("number of processes run by the user"), N_("Running processes"), 1, SCOLS_FL_RIGHT }, ++}; ++ ++struct lslogins_control { ++ struct utmp *wtmp; ++ size_t wtmp_size; ++ ++ struct utmp *btmp; ++ size_t btmp_size; ++ ++ void *usertree; ++ ++ uid_t uid; ++ uid_t UID_MIN; ++ uid_t UID_MAX; ++ ++ uid_t SYS_UID_MIN; ++ uid_t SYS_UID_MAX; ++ ++ char **ulist; ++ size_t ulsiz; ++ ++ unsigned int time_mode; ++ ++ const char *journal_path; ++ ++ unsigned int selinux_enabled : 1, ++ noheadings : 1, ++ notrunc : 1; ++}; ++ ++/* these have to remain global since there's no other reasonable way to pass ++ * them for each call of fill_table() via twalk() */ ++static struct libscols_table *tb; ++ ++/* columns[] array specifies all currently wanted output column. The columns ++ * are defined by coldescs[] array and you can specify (on command line) each ++ * column twice. That's enough, dynamically allocated array of the columns is ++ * unnecessary overkill and over-engineering in this case */ ++static int columns[ARRAY_SIZE(coldescs) * 2]; ++static int ncolumns; ++ ++static inline size_t err_columns_index(size_t arysz, size_t idx) ++{ ++ if (idx >= arysz) ++ errx(EXIT_FAILURE, _("too many columns specified, " ++ "the limit is %zu columns"), ++ arysz - 1); ++ return idx; ++} ++ ++#define add_column(ary, n, id) \ ++ ((ary)[ err_columns_index(ARRAY_SIZE(ary), (n)) ] = (id)) ++ ++static struct timeval now; ++ ++static int date_is_today(time_t t) ++{ ++ if (now.tv_sec == 0) ++ gettimeofday(&now, NULL); ++ return t / (3600 * 24) == now.tv_sec / (3600 * 24); ++} ++ ++static int date_is_thisyear(time_t t) ++{ ++ if (now.tv_sec == 0) ++ gettimeofday(&now, NULL); ++ return t / (3600 * 24 * 365) == now.tv_sec / (3600 * 24 * 365); ++} ++ ++static int column_name_to_id(const char *name, size_t namesz) ++{ ++ size_t i; ++ ++ for (i = 0; i < ARRAY_SIZE(coldescs); i++) { ++ const char *cn = coldescs[i].name; ++ ++ if (!strncasecmp(name, cn, namesz) && !*(cn + namesz)) ++ return i; ++ } ++ warnx(_("unknown column: %s"), name); ++ return -1; ++} ++ ++static char *make_time(int mode, time_t time) ++{ ++ char *s; ++ struct tm tm; ++ char buf[64] = {0}; ++ ++ localtime_r(&time, &tm); ++ ++ switch(mode) { ++ case TIME_FULL: ++ asctime_r(&tm, buf); ++ if (*(s = buf + strlen(buf) - 1) == '\n') ++ *s = '\0'; ++ break; ++ case TIME_SHORT: ++ if (date_is_today(time)) ++ strftime(buf, sizeof(buf), "%H:%M:%S", &tm); ++ else if (date_is_thisyear(time)) ++ strftime(buf, sizeof(buf), "%b%d/%H:%M", &tm); ++ else ++ strftime(buf, sizeof(buf), "%Y-%b%d", &tm); ++ break; ++ case TIME_ISO: ++ strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%S%z", &tm); ++ break; ++ default: ++ errx(EXIT_FAILURE, _("unsupported time type")); ++ } ++ return xstrdup(buf); ++} ++ ++ ++static char *uidtostr(uid_t uid) ++{ ++ char *str_uid = NULL; ++ xasprintf(&str_uid, "%u", uid); ++ return str_uid; ++} ++ ++static char *gidtostr(gid_t gid) ++{ ++ char *str_gid = NULL; ++ xasprintf(&str_gid, "%u", gid); ++ return str_gid; ++} ++ ++static char *build_sgroups_string(gid_t *sgroups, size_t nsgroups, int want_names) ++{ ++ size_t n = 0, maxlen, len; ++ char *res, *p; ++ ++ if (!nsgroups) ++ return NULL; ++ ++ len = maxlen = nsgroups * 10; ++ res = p = xmalloc(maxlen); ++ ++ while (n < nsgroups) { ++ int x; ++again: ++ if (!want_names) ++ x = snprintf(p, len, "%u,", sgroups[n]); ++ else { ++ struct group *grp = getgrgid(sgroups[n]); ++ if (!grp) { ++ free(res); ++ return NULL; ++ } ++ x = snprintf(p, len, "%s,", grp->gr_name); ++ } ++ ++ if (x < 0 || (size_t) x + 1 > len) { ++ size_t cur = p - res; ++ ++ maxlen *= 2; ++ res = xrealloc(res, maxlen); ++ p = res + cur; ++ len = maxlen - cur; ++ goto again; ++ } ++ ++ len -= x; ++ p += x; ++ ++n; ++ } ++ ++ if (p > res) ++ *(p - 1) = '\0'; ++ ++ return res; ++} ++ ++static struct utmp *get_last_wtmp(struct lslogins_control *ctl, const char *username) ++{ ++ size_t n = 0; ++ size_t len; ++ ++ if (!username) ++ return NULL; ++ ++ len = strlen(username); ++ n = ctl->wtmp_size - 1; ++ do { ++ if (!strncmp(username, ctl->wtmp[n].ut_user, ++ len < UT_NAMESIZE ? len : UT_NAMESIZE)) ++ return ctl->wtmp + n; ++ } while (n--); ++ return NULL; ++ ++} ++ ++static int require_wtmp(void) ++{ ++ size_t i; ++ for (i = 0; i < (size_t) ncolumns; i++) ++ if (is_wtmp_col(columns[i])) ++ return 1; ++ return 0; ++} ++ ++static int require_btmp(void) ++{ ++ size_t i; ++ for (i = 0; i < (size_t) ncolumns; i++) ++ if (is_btmp_col(columns[i])) ++ return 1; ++ return 0; ++} ++ ++static struct utmp *get_last_btmp(struct lslogins_control *ctl, const char *username) ++{ ++ size_t n = 0; ++ size_t len; ++ ++ if (!username) ++ return NULL; ++ ++ len = strlen(username); ++ n = ctl->btmp_size - 1; ++ do { ++ if (!strncmp(username, ctl->btmp[n].ut_user, ++ len < UT_NAMESIZE ? len : UT_NAMESIZE)) ++ return ctl->btmp + n; ++ }while (n--); ++ return NULL; ++ ++} ++ ++static int parse_wtmp(struct lslogins_control *ctl, char *path) ++{ ++ int rc = 0; ++ ++ rc = read_utmp(path, &ctl->wtmp_size, &ctl->wtmp); ++ if (rc < 0 && errno != EACCES) ++ err(EXIT_FAILURE, "%s", path); ++ return rc; ++} ++ ++static int parse_btmp(struct lslogins_control *ctl, char *path) ++{ ++ int rc = 0; ++ ++ rc = read_utmp(path, &ctl->btmp_size, &ctl->btmp); ++ if (rc < 0 && errno != EACCES) ++ err(EXIT_FAILURE, "%s", path); ++ return rc; ++} ++ ++static int get_sgroups(gid_t **list, size_t *len, struct passwd *pwd) ++{ ++ size_t n = 0; ++ ++ *len = 0; ++ *list = NULL; ++ ++ /* first let's get a supp. group count */ ++ getgrouplist(pwd->pw_name, pwd->pw_gid, *list, (int *) len); ++ if (!*len) ++ return -1; ++ ++ *list = xcalloc(1, *len * sizeof(gid_t)); ++ ++ /* now for the actual list of GIDs */ ++ if (-1 == getgrouplist(pwd->pw_name, pwd->pw_gid, *list, (int *) len)) ++ return -1; ++ ++ /* getgroups also returns the user's primary GID - dispose of it */ ++ while (n < *len) { ++ if ((*list)[n] == pwd->pw_gid) ++ break; ++ ++n; ++ } ++ ++ if (*len) ++ (*list)[n] = (*list)[--(*len)]; ++ return 0; ++} ++ ++static int get_nprocs(const uid_t uid) ++{ ++ int nprocs = 0; ++ pid_t pid; ++ struct proc_processes *proc = proc_open_processes(); ++ ++ proc_processes_filter_by_uid(proc, uid); ++ ++ while (!proc_next_pid(proc, &pid)) ++ ++nprocs; ++ ++ proc_close_processes(proc); ++ return nprocs; ++} ++ ++static int valid_pwd(const char *str) ++{ ++ const char *p; ++ ++ for (p = str; p && *p; p++) ++ if (!isalnum((unsigned int) *p)) ++ return 0; ++ return p > str ? 1 : 0; ++} ++ ++static struct lslogins_user *get_user_info(struct lslogins_control *ctl, const char *username) ++{ ++ struct lslogins_user *user; ++ struct passwd *pwd; ++ struct group *grp; ++ struct spwd *shadow; ++ struct utmp *user_wtmp = NULL, *user_btmp = NULL; ++ int n = 0; ++ time_t time; ++ uid_t uid; ++ errno = 0; ++ ++ pwd = username ? getpwnam(username) : getpwent(); ++ if (!pwd) ++ return NULL; ++ ++ ctl->uid = uid = pwd->pw_uid; ++ ++ /* nfsnobody is an exception to the UID_MAX limit. This is "nobody" on ++ * some systems; the decisive point is the UID - 65534 */ ++ if ((lslogins_flag & F_USRAC) && ++ strcmp("nfsnobody", pwd->pw_name) != 0 && ++ uid != 0) { ++ if (uid < ctl->UID_MIN || uid > ctl->UID_MAX) { ++ errno = EAGAIN; ++ return NULL; ++ } ++ ++ } else if ((lslogins_flag & F_SYSAC) && ++ (uid < ctl->SYS_UID_MIN || uid > ctl->SYS_UID_MAX)) { ++ errno = EAGAIN; ++ return NULL; ++ } ++ ++ user = xcalloc(1, sizeof(struct lslogins_user)); ++ ++ grp = getgrgid(pwd->pw_gid); ++ if (!grp) ++ return NULL; ++ ++ if (ctl->wtmp) ++ user_wtmp = get_last_wtmp(ctl, pwd->pw_name); ++ if (ctl->btmp) ++ user_btmp = get_last_btmp(ctl, pwd->pw_name); ++ ++ lckpwdf(); ++ shadow = getspnam(pwd->pw_name); ++ ulckpwdf(); ++ ++ /* required by tseach() stuff */ ++ user->uid = pwd->pw_uid; ++ ++ while (n < ncolumns) { ++ switch (columns[n++]) { ++ case COL_USER: ++ user->login = xstrdup(pwd->pw_name); ++ break; ++ case COL_UID: ++ user->uid = pwd->pw_uid; ++ break; ++ case COL_GROUP: ++ user->group = xstrdup(grp->gr_name); ++ break; ++ case COL_GID: ++ user->gid = pwd->pw_gid; ++ break; ++ case COL_SGROUPS: ++ case COL_SGIDS: ++ if (get_sgroups(&user->sgroups, &user->nsgroups, pwd)) ++ err(EXIT_FAILURE, _("failed to get supplementary groups")); ++ break; ++ case COL_HOME: ++ user->homedir = xstrdup(pwd->pw_dir); ++ break; ++ case COL_SHELL: ++ user->shell = xstrdup(pwd->pw_shell); ++ break; ++ case COL_GECOS: ++ user->gecos = xstrdup(pwd->pw_gecos); ++ break; ++ case COL_LAST_LOGIN: ++ if (user_wtmp) { ++ time = user_wtmp->ut_tv.tv_sec; ++ user->last_login = make_time(ctl->time_mode, time); ++ } ++ break; ++ case COL_LAST_TTY: ++ if (user_wtmp) ++ user->last_tty = xstrdup(user_wtmp->ut_line); ++ break; ++ case COL_LAST_HOSTNAME: ++ if (user_wtmp) ++ user->last_hostname = xstrdup(user_wtmp->ut_host); ++ break; ++ case COL_FAILED_LOGIN: ++ if (user_btmp) { ++ time = user_btmp->ut_tv.tv_sec; ++ user->failed_login = make_time(ctl->time_mode, time); ++ } ++ break; ++ case COL_FAILED_TTY: ++ if (user_btmp) ++ user->failed_tty = xstrdup(user_btmp->ut_line); ++ break; ++ case COL_HUSH_STATUS: ++ user->hushed = get_hushlogin_status(pwd, 0); ++ if (user->hushed == -1) ++ user->hushed = STATUS_UNKNOWN; ++ break; ++ case COL_PWDEMPTY: ++ if (shadow) { ++ if (!*shadow->sp_pwdp) /* '\0' */ ++ user->pwd_empty = STATUS_TRUE; ++ } else ++ user->pwd_empty = STATUS_UNKNOWN; ++ break; ++ case COL_PWDDENY: ++ if (shadow) { ++ if ((*shadow->sp_pwdp == '!' || ++ *shadow->sp_pwdp == '*') && ++ !valid_pwd(shadow->sp_pwdp + 1)) ++ user->pwd_deny = STATUS_TRUE; ++ } else ++ user->pwd_deny = STATUS_UNKNOWN; ++ break; ++ ++ case COL_PWDLOCK: ++ if (shadow) { ++ if (*shadow->sp_pwdp == '!' && valid_pwd(shadow->sp_pwdp + 1)) ++ user->pwd_lock = STATUS_TRUE; ++ } else ++ user->pwd_lock = STATUS_UNKNOWN; ++ break; ++ case COL_NOLOGIN: ++ if (strstr(pwd->pw_shell, "nologin")) ++ user->nologin = 1; ++ else if (pwd->pw_uid) ++ user->nologin = access("/etc/nologin", F_OK) == 0 || ++ access("/var/run/nologin", F_OK) == 0; ++ break; ++ case COL_PWD_WARN: ++ if (shadow && shadow->sp_warn >= 0) ++ xasprintf(&user->pwd_warn, "%ld", shadow->sp_warn); ++ break; ++ case COL_PWD_EXPIR: ++ if (shadow && shadow->sp_expire >= 0) ++ user->pwd_expire = make_time(TIME_SHORT, ++ shadow->sp_expire * 86400); ++ break; ++ case COL_PWD_CTIME: ++ /* sp_lstchg is specified in days, showing hours ++ * (especially in non-GMT timezones) would only serve ++ * to confuse */ ++ if (shadow) ++ user->pwd_ctime = make_time(TIME_SHORT, ++ shadow->sp_lstchg * 86400); ++ break; ++ case COL_PWD_CTIME_MIN: ++ if (shadow && shadow->sp_min > 0) ++ xasprintf(&user->pwd_ctime_min, "%ld", shadow->sp_min); ++ break; ++ case COL_PWD_CTIME_MAX: ++ if (shadow && shadow->sp_max > 0) ++ xasprintf(&user->pwd_ctime_max, "%ld", shadow->sp_max); ++ break; ++ case COL_SELINUX: ++#ifdef HAVE_LIBSELINUX ++ if (ctl->selinux_enabled) { ++ /* typedefs and pointers are pure evil */ ++ security_context_t con = NULL; ++ if (getcon(&con) == 0) ++ user->context = con; ++ } ++#endif ++ break; ++ case COL_NPROCS: ++ xasprintf(&user->nprocs, "%d", get_nprocs(pwd->pw_uid)); ++ break; ++ default: ++ /* something went very wrong here */ ++ err(EXIT_FAILURE, "fatal: unknown error"); ++ break; ++ } ++ } ++ ++ return user; ++} ++ ++/* some UNIX implementations set errno iff a passwd/grp/... ++ * entry was not found. The original UNIX logins(1) utility always ++ * ignores invalid login/group names, so we're going to as well.*/ ++#define IS_REAL_ERRNO(e) !((e) == ENOENT || (e) == ESRCH || \ ++ (e) == EBADF || (e) == EPERM || (e) == EAGAIN) ++ ++/* get a definitive list of users we want info about... */ ++ ++static int str_to_uint(char *s, unsigned int *ul) ++{ ++ char *end; ++ if (!s || !*s) ++ return -1; ++ *ul = strtoul(s, &end, 0); ++ if (!*end) ++ return 0; ++ return 1; ++} ++ ++static int get_ulist(struct lslogins_control *ctl, char *logins, char *groups) ++{ ++ char *u, *g; ++ size_t i = 0, n = 0, *arsiz; ++ struct group *grp; ++ struct passwd *pwd; ++ char ***ar; ++ uid_t uid; ++ gid_t gid; ++ ++ ar = &ctl->ulist; ++ arsiz = &ctl->ulsiz; ++ ++ /* an arbitrary starting value */ ++ *arsiz = 32; ++ *ar = xcalloc(1, sizeof(char *) * (*arsiz)); ++ ++ while ((u = strtok(logins, ","))) { ++ logins = NULL; ++ ++ /* user specified by UID? */ ++ if (!str_to_uint(u, &uid)) { ++ pwd = getpwuid(uid); ++ if (!pwd) ++ continue; ++ u = pwd->pw_name; ++ } ++ (*ar)[i++] = xstrdup(u); ++ ++ if (i == *arsiz) ++ *ar = xrealloc(*ar, sizeof(char *) * (*arsiz += 32)); ++ } ++ /* FIXME: this might lead to duplicit entries, although not visible ++ * in output, crunching a user's info multiple times is very redundant */ ++ while ((g = strtok(groups, ","))) { ++ groups = NULL; ++ ++ /* user specified by GID? */ ++ if (!str_to_uint(g, &gid)) ++ grp = getgrgid(gid); ++ else ++ grp = getgrnam(g); ++ ++ if (!grp) ++ continue; ++ ++ while ((u = grp->gr_mem[n++])) { ++ (*ar)[i++] = xstrdup(u); ++ ++ if (i == *arsiz) ++ *ar = xrealloc(*ar, sizeof(char *) * (*arsiz += 32)); ++ } ++ } ++ *arsiz = i; ++ return 0; ++} ++ ++static void free_ctl(struct lslogins_control *ctl) ++{ ++ size_t n = 0; ++ ++ free(ctl->wtmp); ++ free(ctl->btmp); ++ ++ while (n < ctl->ulsiz) ++ free(ctl->ulist[n++]); ++ ++ free(ctl->ulist); ++ free(ctl); ++} ++ ++static struct lslogins_user *get_next_user(struct lslogins_control *ctl) ++{ ++ struct lslogins_user *u; ++ errno = 0; ++ while (!(u = get_user_info(ctl, NULL))) { ++ /* no "false" errno-s here, iff we're unable to ++ * get a valid user entry for any reason, quit */ ++ if (errno == EAGAIN) ++ continue; ++ return NULL; ++ } ++ return u; ++} ++ ++static int get_user(struct lslogins_control *ctl, struct lslogins_user **user, ++ const char *username) ++{ ++ *user = get_user_info(ctl, username); ++ if (!*user && errno) ++ if (IS_REAL_ERRNO(errno)) ++ return -1; ++ return 0; ++} ++ ++static int cmp_uid(const void *a, const void *b) ++{ ++ uid_t x = ((struct lslogins_user *)a)->uid; ++ uid_t z = ((struct lslogins_user *)b)->uid; ++ return x > z ? 1 : (x < z ? -1 : 0); ++} ++ ++static int create_usertree(struct lslogins_control *ctl) ++{ ++ struct lslogins_user *user = NULL; ++ size_t n = 0; ++ ++ if (*ctl->ulist) { ++ while (n < ctl->ulsiz) { ++ if (get_user(ctl, &user, ctl->ulist[n])) ++ return -1; ++ if (user) /* otherwise an invalid user name has probably been given */ ++ tsearch(user, &ctl->usertree, cmp_uid); ++ ++n; ++ } ++ } else { ++ while ((user = get_next_user(ctl))) ++ tsearch(user, &ctl->usertree, cmp_uid); ++ } ++ return 0; ++} ++ ++static struct libscols_table *setup_table(struct lslogins_control *ctl) ++{ ++ struct libscols_table *tb = scols_new_table(); ++ int n = 0; ++ ++ if (!tb) ++ errx(EXIT_FAILURE, _("failed to initialize output table")); ++ if (ctl->noheadings) ++ scols_table_enable_noheadings(tb, 1); ++ ++ switch(outmode) { ++ case OUT_COLON: ++ scols_table_enable_raw(tb, 1); ++ scols_table_set_column_separator(tb, ":"); ++ break; ++ case OUT_NEWLINE: ++ scols_table_set_column_separator(tb, "\n"); ++ /* fallthrough */ ++ case OUT_EXPORT: ++ scols_table_enable_export(tb, 1); ++ break; ++ case OUT_NUL: ++ scols_table_set_line_separator(tb, "\0"); ++ /* fallthrough */ ++ case OUT_RAW: ++ scols_table_enable_raw(tb, 1); ++ break; ++ case OUT_PRETTY: ++ scols_table_enable_noheadings(tb, 1); ++ default: ++ break; ++ } ++ ++ while (n < ncolumns) { ++ int flags = coldescs[columns[n]].flag; ++ ++ if (ctl->notrunc) ++ flags &= ~SCOLS_FL_TRUNC; ++ ++ if (!scols_table_new_column(tb, ++ coldescs[columns[n]].name, ++ coldescs[columns[n]].whint, ++ flags)) ++ goto fail; ++ ++n; ++ } ++ ++ return tb; ++fail: ++ scols_unref_table(tb); ++ return NULL; ++} ++ ++static void fill_table(const void *u, const VISIT which, const int depth __attribute__((unused))) ++{ ++ struct libscols_line *ln; ++ struct lslogins_user *user = *(struct lslogins_user **)u; ++ int n = 0; ++ ++ if (which == preorder || which == endorder) ++ return; ++ ++ ln = scols_table_new_line(tb, NULL); ++ while (n < ncolumns) { ++ int rc = 0; ++ ++ switch (columns[n]) { ++ case COL_USER: ++ rc = scols_line_set_data(ln, n, user->login); ++ break; ++ case COL_UID: ++ rc = scols_line_refer_data(ln, n, uidtostr(user->uid)); ++ break; ++ case COL_PWDEMPTY: ++ rc = scols_line_set_data(ln, n, get_status(user->pwd_empty)); ++ break; ++ case COL_NOLOGIN: ++ rc = scols_line_set_data(ln, n, get_status(user->nologin)); ++ break; ++ case COL_PWDLOCK: ++ rc = scols_line_set_data(ln, n, get_status(user->pwd_lock)); ++ break; ++ case COL_PWDDENY: ++ rc = scols_line_set_data(ln, n, get_status(user->pwd_deny)); ++ break; ++ case COL_GROUP: ++ rc = scols_line_set_data(ln, n, user->group); ++ break; ++ case COL_GID: ++ rc = scols_line_refer_data(ln, n, gidtostr(user->gid)); ++ break; ++ case COL_SGROUPS: ++ rc = scols_line_refer_data(ln, n, ++ build_sgroups_string(user->sgroups, ++ user->nsgroups, ++ TRUE)); ++ break; ++ case COL_SGIDS: ++ rc = scols_line_refer_data(ln, n, ++ build_sgroups_string(user->sgroups, ++ user->nsgroups, ++ FALSE)); ++ break; ++ case COL_HOME: ++ rc = scols_line_set_data(ln, n, user->homedir); ++ break; ++ case COL_SHELL: ++ rc = scols_line_set_data(ln, n, user->shell); ++ break; ++ case COL_GECOS: ++ rc = scols_line_set_data(ln, n, user->gecos); ++ break; ++ case COL_LAST_LOGIN: ++ rc = scols_line_set_data(ln, n, user->last_login); ++ break; ++ case COL_LAST_TTY: ++ rc = scols_line_set_data(ln, n, user->last_tty); ++ break; ++ case COL_LAST_HOSTNAME: ++ rc = scols_line_set_data(ln, n, user->last_hostname); ++ break; ++ case COL_FAILED_LOGIN: ++ rc = scols_line_set_data(ln, n, user->failed_login); ++ break; ++ case COL_FAILED_TTY: ++ rc = scols_line_set_data(ln, n, user->failed_tty); ++ break; ++ case COL_HUSH_STATUS: ++ rc = scols_line_set_data(ln, n, get_status(user->hushed)); ++ break; ++ case COL_PWD_WARN: ++ rc = scols_line_set_data(ln, n, user->pwd_warn); ++ break; ++ case COL_PWD_EXPIR: ++ rc = scols_line_set_data(ln, n, user->pwd_expire); ++ break; ++ case COL_PWD_CTIME: ++ rc = scols_line_set_data(ln, n, user->pwd_ctime); ++ break; ++ case COL_PWD_CTIME_MIN: ++ rc = scols_line_set_data(ln, n, user->pwd_ctime_min); ++ break; ++ case COL_PWD_CTIME_MAX: ++ rc = scols_line_set_data(ln, n, user->pwd_ctime_max); ++ break; ++ case COL_SELINUX: ++#ifdef HAVE_LIBSELINUX ++ rc = scols_line_set_data(ln, n, user->context); ++#endif ++ break; ++ case COL_NPROCS: ++ rc = scols_line_set_data(ln, n, user->nprocs); ++ break; ++ default: ++ /* something went very wrong here */ ++ err(EXIT_FAILURE, _("internal error: unknown column")); ++ } ++ ++ if (rc != 0) ++ err(EXIT_FAILURE, _("failed to set data")); ++ ++n; ++ } ++ return; ++} ++#ifdef HAVE_LIBSYSTEMD ++static void print_journal_tail(const char *journal_path, uid_t uid, size_t len) ++{ ++ sd_journal *j; ++ char *match, *buf; ++ uint64_t x; ++ time_t t; ++ const char *identifier, *pid, *message; ++ size_t identifier_len, pid_len, message_len; ++ ++ if (journal_path) ++ sd_journal_open_directory(&j, journal_path, 0); ++ else ++ sd_journal_open(&j, SD_JOURNAL_LOCAL_ONLY); ++ ++ buf = xmalloc(sizeof(char) * 16); ++ xasprintf(&match, "_UID=%d", uid); ++ ++ sd_journal_add_match(j, match, 0); ++ sd_journal_seek_tail(j); ++ sd_journal_previous_skip(j, len); ++ ++ do { ++ if (0 > sd_journal_get_data(j, "SYSLOG_IDENTIFIER", ++ (const void **) &identifier, &identifier_len)) ++ return; ++ if (0 > sd_journal_get_data(j, "_PID", ++ (const void **) &pid, &pid_len)) ++ return; ++ if (0 > sd_journal_get_data(j, "MESSAGE", ++ (const void **) &message, &message_len)) ++ return; ++ ++ sd_journal_get_realtime_usec(j, &x); ++ t = x / 1000000; ++ strftime(buf, 16, "%b %d %H:%M:%S", localtime(&t)); ++ ++ fprintf(stdout, "%s", buf); ++ ++ identifier = strchr(identifier, '=') + 1; ++ pid = strchr(pid, '=') + 1 ; ++ message = strchr(message, '=') + 1; ++ ++ fprintf(stdout, " %s", identifier); ++ fprintf(stdout, "[%s]:", pid); ++ fprintf(stdout, "%s\n", message); ++ } while (sd_journal_next(j)); ++ ++ free(buf); ++ free(match); ++ sd_journal_flush_matches(j); ++ sd_journal_close(j); ++} ++#endif ++ ++static int print_pretty(struct libscols_table *tb) ++{ ++ struct libscols_iter *itr = scols_new_iter(SCOLS_ITER_FORWARD); ++ struct libscols_column *col; ++ struct libscols_cell *data; ++ struct libscols_line *ln; ++ const char *hstr, *dstr; ++ int n = 0; ++ ++ ln = scols_table_get_line(tb, 0); ++ while (!scols_table_next_column(tb, itr, &col)) { ++ ++ data = scols_line_get_cell(ln, n); ++ ++ hstr = _(coldescs[columns[n]].pretty_name); ++ dstr = scols_cell_get_data(data); ++ ++ if (dstr) ++ printf("%s:%*c%-36s\n", hstr, 35 - (int)strlen(hstr), ' ', dstr); ++ ++n; ++ } ++ ++ scols_free_iter(itr); ++ return 0; ++ ++} ++ ++static int print_user_table(struct lslogins_control *ctl) ++{ ++ tb = setup_table(ctl); ++ if (!tb) ++ return -1; ++ ++ twalk(ctl->usertree, fill_table); ++ if (outmode == OUT_PRETTY) { ++ print_pretty(tb); ++#ifdef HAVE_LIBSYSTEMD ++ fprintf(stdout, _("\nLast logs:\n")); ++ print_journal_tail(ctl->journal_path, ctl->uid, 3); ++ fputc('\n', stdout); ++#endif ++ } else ++ scols_print_table(tb); ++ return 0; ++} ++ ++static void free_user(void *f) ++{ ++ struct lslogins_user *u = f; ++ free(u->login); ++ free(u->group); ++ free(u->gecos); ++ free(u->sgroups); ++ free(u->pwd_ctime); ++ free(u->pwd_warn); ++ free(u->pwd_ctime_min); ++ free(u->pwd_ctime_max); ++ free(u->last_login); ++ free(u->last_tty); ++ free(u->last_hostname); ++ free(u->failed_login); ++ free(u->failed_tty); ++ free(u->homedir); ++ free(u->shell); ++ free(u->pwd_status); ++#ifdef HAVE_LIBSELINUX ++ freecon(u->context); ++#endif ++ free(u); ++} ++ ++struct lslogins_timefmt { ++ const char *name; ++ int val; ++}; ++ ++static struct lslogins_timefmt timefmts[] = { ++ { "short", TIME_SHORT }, ++ { "full", TIME_FULL }, ++ { "iso", TIME_ISO }, ++}; ++ ++static void __attribute__((__noreturn__)) usage(FILE *out) ++{ ++ size_t i; ++ ++ fputs(USAGE_HEADER, out); ++ fprintf(out, _(" %s [options]\n"), program_invocation_short_name); ++ ++ fputs(USAGE_OPTIONS, out); ++ fputs(_(" -a, --acc-expiration display info about passwords expiration\n"), out); ++ fputs(_(" -c, --colon-separate display data in a format similar to /etc/passwd\n"), out); ++ fputs(_(" -e, --export display in an export-able output format\n"), out); ++ fputs(_(" -f, --failed display data about the users' last failed logins\n"), out); ++ fputs(_(" -G, --groups-info display information about groups\n"), out); ++ fputs(_(" -g, --groups= display users belonging to a group in \n"), out); ++ fputs(_(" -L, --last show info about the users' last login sessions\n"), out); ++ fputs(_(" -l, --logins= display only users from \n"), out); ++ fputs(_(" -m, --supp-groups display supplementary groups as well\n"), out); ++ fputs(_(" -n, --newline display each piece of information on a new line\n"), out); ++ fputs(_(" --noheadings don't print headings\n"), out); ++ fputs(_(" --notruncate don't truncate output\n"), out); ++ fputs(_(" -o, --output[=] define the columns to output\n"), out); ++ fputs(_(" -p, --pwd display information related to login by password.\n"), out); ++ fputs(_(" -r, --raw display in raw mode\n"), out); ++ fputs(_(" -s, --system-accs display system accounts\n"), out); ++ fputs(_(" --time-format= display dates in short, full or iso format\n"), out); ++ fputs(_(" -u, --user-accs display user accounts\n"), out); ++ fputs(_(" -Z, --context display SELinux contexts\n"), out); ++ fputs(_(" -z, --print0 delimit user entries with a nul character\n"), out); ++ fputs(_(" --wtmp-file set an alternate path for wtmp\n"), out); ++ fputs(_(" --btmp-file set an alternate path for btmp\n"), out); ++ fputs(USAGE_SEPARATOR, out); ++ fputs(USAGE_HELP, out); ++ fputs(USAGE_VERSION, out); ++ ++ fprintf(out, _("\nAvailable columns:\n")); ++ ++ for (i = 0; i < ARRAY_SIZE(coldescs); i++) ++ fprintf(out, " %14s %s\n", coldescs[i].name, ++ _(coldescs[i].help)); ++ ++ fprintf(out, _("\nFor more details see lslogins(1).\n")); ++ ++ exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS); ++} ++ ++int main(int argc, char *argv[]) ++{ ++ int c, opt_o = 0; ++ char *logins = NULL, *groups = NULL; ++ char *path_wtmp = _PATH_WTMP, *path_btmp = _PATH_BTMP; ++ struct lslogins_control *ctl = xcalloc(1, sizeof(struct lslogins_control)); ++ size_t i; ++ ++ /* long only options. */ ++ enum { ++ OPT_VER = CHAR_MAX + 1, ++ OPT_WTMP, ++ OPT_BTMP, ++ OPT_NOTRUNC, ++ OPT_NOHEAD, ++ OPT_TIME_FMT, ++ }; ++ ++ static const struct option longopts[] = { ++ { "acc-expiration", no_argument, 0, 'a' }, ++ { "colon-separate", no_argument, 0, 'c' }, ++ { "export", no_argument, 0, 'e' }, ++ { "failed", no_argument, 0, 'f' }, ++ { "groups", required_argument, 0, 'g' }, ++ { "help", no_argument, 0, 'h' }, ++ { "logins", required_argument, 0, 'l' }, ++ { "supp-groups", no_argument, 0, 'G' }, ++ { "newline", no_argument, 0, 'n' }, ++ { "notruncate", no_argument, 0, OPT_NOTRUNC }, ++ { "noheadings", no_argument, 0, OPT_NOHEAD }, ++ { "output", required_argument, 0, 'o' }, ++ { "last", no_argument, 0, 'L', }, ++ { "raw", no_argument, 0, 'r' }, ++ { "system-accs", no_argument, 0, 's' }, ++ { "time-format", required_argument, 0, OPT_TIME_FMT }, ++ { "user-accs", no_argument, 0, 'u' }, ++ { "version", no_argument, 0, 'V' }, ++ { "pwd", no_argument, 0, 'p' }, ++ { "print0", no_argument, 0, 'z' }, ++ { "wtmp-file", required_argument, 0, OPT_WTMP }, ++ { "btmp-file", required_argument, 0, OPT_BTMP }, ++#ifdef HAVE_LIBSELINUX ++ { "context", no_argument, 0, 'Z' }, ++#endif ++ { NULL, 0, 0, 0 } ++ }; ++ ++ static const ul_excl_t excl[] = { /* rows and cols in ASCII order */ ++ { 'G', 'o' }, ++ { 'L', 'o' }, ++ { 'Z', 'o' }, ++ { 'a', 'o' }, ++ { 'c','n','r','z' }, ++ { 'o', 'p' }, ++ { 0 } ++ }; ++ int excl_st[ARRAY_SIZE(excl)] = UL_EXCL_STATUS_INIT; ++ ++ setlocale(LC_ALL, ""); ++ bindtextdomain(PACKAGE, LOCALEDIR); ++ textdomain(PACKAGE); ++ atexit(close_stdout); ++ ++ ctl->time_mode = TIME_SHORT; ++ ++ /* very basic default */ ++ add_column(columns, ncolumns++, COL_UID); ++ add_column(columns, ncolumns++, COL_USER); ++ ++ while ((c = getopt_long(argc, argv, "acfGg:hLl:no:prsuVxzZ", ++ longopts, NULL)) != -1) { ++ ++ err_exclusive_options(c, longopts, excl, excl_st); ++ ++ switch (c) { ++ case 'a': ++ add_column(columns, ncolumns++, COL_PWD_WARN); ++ add_column(columns, ncolumns++, COL_PWD_CTIME_MIN); ++ add_column(columns, ncolumns++, COL_PWD_CTIME_MAX); ++ add_column(columns, ncolumns++, COL_PWD_CTIME); ++ add_column(columns, ncolumns++, COL_PWD_EXPIR); ++ break; ++ case 'c': ++ outmode = OUT_COLON; ++ break; ++ case 'e': ++ outmode = OUT_EXPORT; ++ break; ++ case 'f': ++ add_column(columns, ncolumns++, COL_FAILED_LOGIN); ++ add_column(columns, ncolumns++, COL_FAILED_TTY); ++ break; ++ case 'G': ++ add_column(columns, ncolumns++, COL_GID); ++ add_column(columns, ncolumns++, COL_GROUP); ++ add_column(columns, ncolumns++, COL_SGIDS); ++ add_column(columns, ncolumns++, COL_SGROUPS); ++ break; ++ case 'g': ++ groups = optarg; ++ break; ++ case 'h': ++ usage(stdout); ++ break; ++ case 'L': ++ add_column(columns, ncolumns++, COL_LAST_TTY); ++ add_column(columns, ncolumns++, COL_LAST_HOSTNAME); ++ add_column(columns, ncolumns++, COL_LAST_LOGIN); ++ break; ++ case 'l': ++ logins = optarg; ++ break; ++ case 'n': ++ outmode = OUT_NEWLINE; ++ break; ++ case 'o': ++ if (optarg) { ++ if (*optarg == '=') ++ optarg++; ++ ncolumns = string_to_idarray(optarg, ++ columns, ARRAY_SIZE(columns), ++ column_name_to_id); ++ if (ncolumns < 0) ++ return EXIT_FAILURE; ++ } ++ opt_o = 1; ++ break; ++ case 'r': ++ outmode = OUT_RAW; ++ break; ++ case 's': ++ ctl->SYS_UID_MIN = getlogindefs_num("SYS_UID_MIN", UL_SYS_UID_MIN); ++ ctl->SYS_UID_MAX = getlogindefs_num("SYS_UID_MAX", UL_SYS_UID_MAX); ++ lslogins_flag |= F_SYSAC; ++ break; ++ case 'u': ++ ctl->UID_MIN = getlogindefs_num("UID_MIN", UL_UID_MIN); ++ ctl->UID_MAX = getlogindefs_num("UID_MAX", UL_UID_MAX); ++ lslogins_flag |= F_USRAC; ++ break; ++ case 'p': ++ add_column(columns, ncolumns++, COL_PWDEMPTY); ++ add_column(columns, ncolumns++, COL_PWDLOCK); ++ add_column(columns, ncolumns++, COL_PWDDENY); ++ add_column(columns, ncolumns++, COL_NOLOGIN); ++ add_column(columns, ncolumns++, COL_HUSH_STATUS); ++ break; ++ case 'z': ++ outmode = OUT_NUL; ++ break; ++ case OPT_WTMP: ++ path_wtmp = optarg; ++ break; ++ case OPT_BTMP: ++ path_btmp = optarg; ++ break; ++ case OPT_NOTRUNC: ++ ctl->notrunc = 1; ++ break; ++ case OPT_NOHEAD: ++ ctl->noheadings = 1; ++ break; ++ case OPT_TIME_FMT: ++ { ++ size_t i; ++ ++ for (i = 0; i < ARRAY_SIZE(timefmts); i++) { ++ if (strcmp(timefmts[i].name, optarg) == 0) { ++ ctl->time_mode = timefmts[i].val; ++ break; ++ } ++ } ++ if (ctl->time_mode == TIME_INVALID) ++ usage(stderr); ++ } ++ break; ++ case 'V': ++ printf(UTIL_LINUX_VERSION); ++ return EXIT_SUCCESS; ++ case 'Z': ++ { ++#ifdef HAVE_LIBSELINUX ++ int sl = is_selinux_enabled(); ++ if (sl < 0) ++ warn(_("failed to request selinux state")); ++ else ++ ctl->selinux_enabled = sl == 1; ++#endif ++ add_column(columns, ncolumns++, COL_SELINUX); ++ break; ++ } ++ default: ++ usage(stderr); ++ } ++ } ++ ++ if (argc - optind == 1) { ++ if (strchr(argv[optind], ',')) ++ errx(EXIT_FAILURE, _("Only one user may be specified. Use -l for multiple users.")); ++ logins = argv[optind]; ++ outmode = OUT_PRETTY; ++ } else if (argc != optind) ++ usage(stderr); ++ ++ scols_init_debug(0); ++ ++ /* lslogins -u -s == lslogins */ ++ if (lslogins_flag & F_USRAC && lslogins_flag & F_SYSAC) ++ lslogins_flag &= ~(F_USRAC | F_SYSAC); ++ ++ if (outmode == OUT_PRETTY && !opt_o) { ++ /* all columns for lslogins */ ++ for (ncolumns = 0, i = 0; i < ARRAY_SIZE(coldescs); i++) ++ columns[ncolumns++] = i; ++ ++ } else if (ncolumns == 2 && !opt_o) { ++ /* default colummns */ ++ add_column(columns, ncolumns++, COL_NPROCS); ++ add_column(columns, ncolumns++, COL_PWDLOCK); ++ add_column(columns, ncolumns++, COL_PWDDENY); ++ add_column(columns, ncolumns++, COL_LAST_LOGIN); ++ add_column(columns, ncolumns++, COL_GECOS); ++ } ++ ++ if (require_wtmp()) ++ parse_wtmp(ctl, path_wtmp); ++ if (require_btmp()) ++ parse_btmp(ctl, path_btmp); ++ ++ get_ulist(ctl, logins, groups); ++ ++ if (create_usertree(ctl)) ++ return EXIT_FAILURE; ++ ++ print_user_table(ctl); ++ ++ scols_unref_table(tb); ++ tdestroy(ctl->usertree, free_user); ++ free_ctl(ctl); ++ ++ return EXIT_SUCCESS; ++} +diff -up util-linux-2.23.2/login-utils/Makemodule.am.kzak util-linux-2.23.2/login-utils/Makemodule.am +--- util-linux-2.23.2/login-utils/Makemodule.am.kzak 2013-06-13 09:46:10.441650801 +0200 ++++ util-linux-2.23.2/login-utils/Makemodule.am 2014-09-25 14:48:20.088575426 +0200 +@@ -145,6 +145,25 @@ endif + endif # BUILD_NEWGRP + + ++if BUILD_LSLOGINS ++usrbin_exec_PROGRAMS += lslogins ++dist_man_MANS += login-utils/lslogins.1 ++lslogins_SOURCES = \ ++ login-utils/lslogins.c \ ++ login-utils/logindefs.c \ ++ login-utils/logindefs.h ++lslogins_LDADD = $(LDADD) libcommon.la libsmartcols.la ++lslogins_CFLAGS = $(AM_CFLAGS) -I$(ul_libsmartcols_incdir) ++if HAVE_SELINUX ++lslogins_LDADD += -lselinux ++endif ++if HAVE_SYSTEMD ++lslogins_LDADD += $(SYSTEMD_LIBS) $(SYSTEMD_JOURNAL_LIBS) ++lslogins_CFLAGS += $(SYSTEMD_CFLAGS) $(SYSTEMD_JOURNAL_CFLAGS) ++endif ++endif # BUILD_LSLOGINS ++ ++ + if BUILD_VIPW + usrsbin_exec_PROGRAMS += vipw + dist_man_MANS += \ diff --git a/SOURCES/2.26-mount-man-move.patch b/SOURCES/2.26-mount-man-move.patch new file mode 100644 index 0000000..1a290a4 --- /dev/null +++ b/SOURCES/2.26-mount-man-move.patch @@ -0,0 +1,12 @@ +diff -up util-linux-2.23.2/sys-utils/mount.8.kzak util-linux-2.23.2/sys-utils/mount.8 +--- util-linux-2.23.2/sys-utils/mount.8.kzak 2014-09-25 11:03:25.492822164 +0200 ++++ util-linux-2.23.2/sys-utils/mount.8 2014-09-25 11:04:00.102152375 +0200 +@@ -451,7 +451,7 @@ has to be a mountpoint. + + Note that moving a mount residing under a shared mount is invalid and + unsupported. Use +-.B findmnt -o TARGET,PROPAGATION /dir ++.B findmnt -o TARGET,PROPAGATION + to see the current propagation flags. + .RE + diff --git a/SOURCES/nologin.8 b/SOURCES/nologin.8 new file mode 100644 index 0000000..5cb1601 --- /dev/null +++ b/SOURCES/nologin.8 @@ -0,0 +1,63 @@ +.\" $OpenBSD: nologin.8,v 1.8 1999/06/04 02:45:19 aaron Exp $ +.\" $NetBSD: nologin.8,v 1.3 1995/03/18 14:59:09 cgd Exp $ +.\" +.\" Copyright (c) 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)nologin.8 8.1 (Berkeley) 6/19/93 +.\" +.Dd February 15, 1997 +.Dt NOLOGIN 8 +.Os +.Sh NAME +.Nm nologin +.Nd politely refuse a login +.Sh SYNOPSIS +.Nm nologin +.Sh DESCRIPTION +.Nm +displays a message that an account is not available and +exits non-zero. +It is intended as a replacement shell field for accounts that +have been disabled. +.Pp +If the file +.Pa /etc/nologin.txt +exists, +.Nm +displays its contents to the user instead of the default message. +.Sh SEE ALSO +.Xr login 1 +.Sh HISTORY +The +.Nm +command appeared in +.Bx 4.4 . diff --git a/SOURCES/nologin.c b/SOURCES/nologin.c new file mode 100644 index 0000000..8a51ba9 --- /dev/null +++ b/SOURCES/nologin.c @@ -0,0 +1,58 @@ +/* $OpenBSD: nologin.c,v 1.2 1997/04/04 16:51:37 millert Exp $ */ + +/* + * Copyright (c) 1997, Jason Downs. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include + +/* Distinctly different from _PATH_NOLOGIN. */ +#define _PATH_NOLOGIN_TXT "/etc/nologin.txt" + +#define DEFAULT_MESG "This account is currently not available.\n" + +/*ARGSUSED*/ +int main(argc, argv) + int argc; + char *argv[]; +{ + int nfd, nrd; + char nbuf[128]; + + nfd = open(_PATH_NOLOGIN_TXT, O_RDONLY); + if (nfd < 0) { + write(STDOUT_FILENO, DEFAULT_MESG, strlen(DEFAULT_MESG)); + exit (1); + } + + while ((nrd = read(nfd, nbuf, sizeof(nbuf))) > 0) + write(STDOUT_FILENO, nbuf, nrd); + close (nfd); + + exit (1); +} diff --git a/SOURCES/rhel7.0-unshare-user.patch b/SOURCES/rhel7.0-unshare-user.patch new file mode 100644 index 0000000..56ec755 --- /dev/null +++ b/SOURCES/rhel7.0-unshare-user.patch @@ -0,0 +1,154 @@ +diff -up util-linux-2.23.2/sys-utils/nsenter.1.kzak util-linux-2.23.2/sys-utils/nsenter.1 +--- util-linux-2.23.2/sys-utils/nsenter.1.kzak 2014-03-12 12:39:19.283577293 +0100 ++++ util-linux-2.23.2/sys-utils/nsenter.1 2014-03-12 12:42:08.930336415 +0100 +@@ -47,12 +47,7 @@ flag). + will fork by default if changing the PID namespace, so that the new program + and its children share the same PID namespace and are visible to each other. + If \-\-no\-fork is used, the new program will be exec'ed without forking. +-.TP +-.B user namespace +-process will have distinct set of UIDs, GIDs and capabilities +-.RB ( CLONE_\:NEWUSER +-flag). +-.TP ++.PP + See the + .BR clone (2) + for exact semantics of the flags. +@@ -88,9 +83,6 @@ the network namespace + /proc/\fIpid\fR/ns/pid + the PID namespace + .TP +-/proc/\fIpid\fR/ns/user +-the user namespace +-.TP + /proc/\fIpid\fR/root + the root directory + .TP +@@ -124,11 +116,6 @@ Enter the PID namespace. If no file is + the target process. If file is specified enter the PID namespace specified by + file. + .TP +-\fB\-U\fR, \fB\-\-user\fR [\fIfile\fR] +-Enter the user namespace. If no file is specified enter the user namespace of +-the target process. If file is specified enter the user namespace specified by +-file. +-.TP + \fB\-r\fR, \fB\-\-root\fR [\fIdirectory\fR] + Set the root directory. If no directory is specified set the root directory to + the root directory of the target process. If directory is specified set the +diff -up util-linux-2.23.2/sys-utils/nsenter.c.kzak util-linux-2.23.2/sys-utils/nsenter.c +--- util-linux-2.23.2/sys-utils/nsenter.c.kzak 2014-03-12 12:39:10.402485179 +0100 ++++ util-linux-2.23.2/sys-utils/nsenter.c 2014-03-12 12:44:07.986570461 +0100 +@@ -42,12 +42,7 @@ static struct namespace_file { + int fd; + } namespace_files[] = { + /* Careful the order is significant in this array. +- * +- * The user namespace comes first, so that it is entered +- * first. This gives an unprivileged user the potential to +- * enter the other namespaces. + */ +- { .nstype = CLONE_NEWUSER, .name = "ns/user", .fd = -1 }, + { .nstype = CLONE_NEWIPC, .name = "ns/ipc", .fd = -1 }, + { .nstype = CLONE_NEWUTS, .name = "ns/uts", .fd = -1 }, + { .nstype = CLONE_NEWNET, .name = "ns/net", .fd = -1 }, +@@ -71,7 +66,6 @@ static void usage(int status) + fputs(_(" -i, --ipc [=] enter System V IPC namespace\n"), out); + fputs(_(" -n, --net [=] enter network namespace\n"), out); + fputs(_(" -p, --pid [=] enter pid namespace\n"), out); +- fputs(_(" -U, --user [=] enter user namespace\n"), out); + fputs(_(" -r, --root [=] set the root directory\n"), out); + fputs(_(" -w, --wd [=] set the working directory\n"), out); + fputs(_(" -F, --no-fork do not fork before exec'ing \n"), out); +@@ -168,7 +162,6 @@ int main(int argc, char *argv[]) + { "ipc", optional_argument, NULL, 'i' }, + { "net", optional_argument, NULL, 'n' }, + { "pid", optional_argument, NULL, 'p' }, +- { "user", optional_argument, NULL, 'U' }, + { "root", optional_argument, NULL, 'r' }, + { "wd", optional_argument, NULL, 'w' }, + { "no-fork", no_argument, NULL, 'F' }, +@@ -186,7 +179,7 @@ int main(int argc, char *argv[]) + atexit(close_stdout); + + while ((c = +- getopt_long(argc, argv, "hVt:m::u::i::n::p::U::r::w::F", ++ getopt_long(argc, argv, "hVt:m::u::i::n::p::r::w::F", + longopts, NULL)) != -1) { + switch (c) { + case 'h': +@@ -228,12 +221,6 @@ int main(int argc, char *argv[]) + else + namespaces |= CLONE_NEWPID; + break; +- case 'U': +- if (optarg) +- open_namespace_fd(CLONE_NEWUSER, optarg); +- else +- namespaces |= CLONE_NEWUSER; +- break; + case 'F': + do_fork = 0; + break; +diff -up util-linux-2.23.2/sys-utils/unshare.1.kzak util-linux-2.23.2/sys-utils/unshare.1 +--- util-linux-2.23.2/sys-utils/unshare.1.kzak 2014-03-12 12:39:41.367806340 +0100 ++++ util-linux-2.23.2/sys-utils/unshare.1 2014-03-12 12:40:25.186260760 +0100 +@@ -34,9 +34,6 @@ etc. (\fBCLONE_NEWNET\fP flag). + .BR "pid namespace" + children will have a distinct set of pid to process mappings than their parent. + (\fBCLONE_NEWPID\fP flag). +-.TP +-.BR "user namespace" +-process will have distinct set of uids, gids and capabilities. (\fBCLONE_NEWUSER\fP flag). + .PP + See the \fBclone\fR(2) for exact semantics of the flags. + .SH OPTIONS +@@ -58,9 +55,6 @@ Unshare the network namespace. + .TP + .BR \-p , " \-\-pid" + Unshare the pid namespace. +-.TP +-.BR \-U , " \-\-user" +-Unshare the user namespace. + .SH SEE ALSO + .BR unshare (2), + .BR clone (2) +diff -up util-linux-2.23.2/sys-utils/unshare.c.kzak util-linux-2.23.2/sys-utils/unshare.c +--- util-linux-2.23.2/sys-utils/unshare.c.kzak 2014-03-12 12:39:46.385858383 +0100 ++++ util-linux-2.23.2/sys-utils/unshare.c 2014-03-12 12:44:49.955005384 +0100 +@@ -45,7 +45,6 @@ static void usage(int status) + fputs(_(" -i, --ipc unshare System V IPC namespace\n"), out); + fputs(_(" -n, --net unshare network namespace\n"), out); + fputs(_(" -p, --pid unshare pid namespace\n"), out); +- fputs(_(" -U, --user unshare user namespace\n"), out); + + fputs(USAGE_SEPARATOR, out); + fputs(USAGE_HELP, out); +@@ -65,7 +64,6 @@ int main(int argc, char *argv[]) + { "ipc", no_argument, 0, 'i' }, + { "net", no_argument, 0, 'n' }, + { "pid", no_argument, 0, 'p' }, +- { "user", no_argument, 0, 'U' }, + { NULL, 0, 0, 0 } + }; + +@@ -78,7 +76,7 @@ int main(int argc, char *argv[]) + textdomain(PACKAGE); + atexit(close_stdout); + +- while ((c = getopt_long(argc, argv, "hVmuinpU", longopts, NULL)) != -1) { ++ while ((c = getopt_long(argc, argv, "hVmuinp", longopts, NULL)) != -1) { + switch (c) { + case 'h': + usage(EXIT_SUCCESS); +@@ -100,9 +98,6 @@ int main(int argc, char *argv[]) + case 'p': + unshare_flags |= CLONE_NEWPID; + break; +- case 'U': +- unshare_flags |= CLONE_NEWUSER; +- break; + default: + usage(EXIT_FAILURE); + } diff --git a/SOURCES/util-linux-60-raw.rules b/SOURCES/util-linux-60-raw.rules new file mode 100644 index 0000000..abbf79d --- /dev/null +++ b/SOURCES/util-linux-60-raw.rules @@ -0,0 +1,8 @@ +# +# Enter raw device bindings here. +# +# An example would be: +# ACTION=="add", KERNEL=="sda", RUN+="/usr/bin/raw /dev/raw/raw1 %N" +# to bind /dev/raw/raw1 to /dev/sda, or +# ACTION=="add", ENV{MAJOR}=="8", ENV{MINOR}=="1", RUN+="/usr/bin/raw /dev/raw/raw2 %M %m" +# to bind /dev/raw/raw2 to the device with major 8, minor 1. diff --git a/SOURCES/util-linux-chsh-chfn.pamd b/SOURCES/util-linux-chsh-chfn.pamd new file mode 100644 index 0000000..2dbc0aa --- /dev/null +++ b/SOURCES/util-linux-chsh-chfn.pamd @@ -0,0 +1,6 @@ +#%PAM-1.0 +auth sufficient pam_rootok.so +auth include system-auth +account include system-auth +password include system-auth +session include system-auth diff --git a/SOURCES/util-linux-login.pamd b/SOURCES/util-linux-login.pamd new file mode 100644 index 0000000..3c03927 --- /dev/null +++ b/SOURCES/util-linux-login.pamd @@ -0,0 +1,18 @@ +#%PAM-1.0 +auth [user_unknown=ignore success=ok ignore=ignore default=bad] pam_securetty.so +auth substack system-auth +auth include postlogin +account required pam_nologin.so +account include system-auth +password include system-auth +# pam_selinux.so close should be the first session rule +session required pam_selinux.so close +session required pam_loginuid.so +session optional pam_console.so +# pam_selinux.so open should only be followed by sessions to be executed in the user context +session required pam_selinux.so open +session required pam_namespace.so +session optional pam_keyinit.so force revoke +session include system-auth +session include postlogin +-session optional pam_ck_connector.so diff --git a/SOURCES/util-linux-remote.pamd b/SOURCES/util-linux-remote.pamd new file mode 100644 index 0000000..2f22cc2 --- /dev/null +++ b/SOURCES/util-linux-remote.pamd @@ -0,0 +1,16 @@ +#%PAM-1.0 +auth required pam_securetty.so +auth substack password-auth +auth include postlogin +account required pam_nologin.so +account include password-auth +password include password-auth +# pam_selinux.so close should be the first session rule +session required pam_selinux.so close +session required pam_loginuid.so +# pam_selinux.so open should only be followed by sessions to be executed in the user context +session required pam_selinux.so open +session required pam_namespace.so +session optional pam_keyinit.so force revoke +session include password-auth +session include postlogin diff --git a/SOURCES/util-linux-runuser-l.pamd b/SOURCES/util-linux-runuser-l.pamd new file mode 100644 index 0000000..7a9a48c --- /dev/null +++ b/SOURCES/util-linux-runuser-l.pamd @@ -0,0 +1,5 @@ +#%PAM-1.0 +auth include runuser +session optional pam_keyinit.so force revoke +-session optional pam_systemd.so +session include runuser diff --git a/SOURCES/util-linux-runuser.pamd b/SOURCES/util-linux-runuser.pamd new file mode 100644 index 0000000..37f0e84 --- /dev/null +++ b/SOURCES/util-linux-runuser.pamd @@ -0,0 +1,5 @@ +#%PAM-1.0 +auth sufficient pam_rootok.so +session optional pam_keyinit.so revoke +session required pam_limits.so +session required pam_unix.so diff --git a/SOURCES/util-linux-su-l.pamd b/SOURCES/util-linux-su-l.pamd new file mode 100644 index 0000000..656a139 --- /dev/null +++ b/SOURCES/util-linux-su-l.pamd @@ -0,0 +1,6 @@ +#%PAM-1.0 +auth include su +account include su +password include su +session optional pam_keyinit.so force revoke +session include su diff --git a/SOURCES/util-linux-su.pamd b/SOURCES/util-linux-su.pamd new file mode 100644 index 0000000..030657f --- /dev/null +++ b/SOURCES/util-linux-su.pamd @@ -0,0 +1,14 @@ +#%PAM-1.0 +auth sufficient pam_rootok.so +# Uncomment the following line to implicitly trust users in the "wheel" group. +#auth sufficient pam_wheel.so trust use_uid +# Uncomment the following line to require a user to be in the "wheel" group. +#auth required pam_wheel.so use_uid +auth substack system-auth +auth include postlogin +account sufficient pam_succeed_if.so uid = 0 use_uid quiet +account include system-auth +password include system-auth +session include system-auth +session include postlogin +session optional pam_xauth.so diff --git a/SPECS/util-linux.spec b/SPECS/util-linux.spec new file mode 100644 index 0000000..6b37d70 --- /dev/null +++ b/SPECS/util-linux.spec @@ -0,0 +1,2699 @@ +### Header +Summary: A collection of basic system utilities +Name: util-linux +Version: 2.23.2 +Release: 18%{?dist} +License: GPLv2 and GPLv2+ and LGPLv2+ and BSD with advertising and Public Domain +Group: System Environment/Base +URL: http://en.wikipedia.org/wiki/Util-linux + +%define upstream_version %{version} + +### Macros +%define cytune_archs %{ix86} alpha %{arm} +%define compldir %{_datadir}/bash-completion/completions/ + +### Dependencies +BuildRequires: audit-libs-devel >= 1.0.6 +BuildRequires: gettext-devel +BuildRequires: libselinux-devel +BuildRequires: ncurses-devel +BuildRequires: pam-devel +BuildRequires: zlib-devel +BuildRequires: popt-devel +BuildRequires: libutempter-devel +Buildrequires: systemd-devel +Buildrequires: libuser-devel +BuildRequires: libcap-ng-devel +BuildRequires: autoconf +BuildRequires: automake +BuildRequires: libtool + +### Sources +Source0: ftp://ftp.kernel.org/pub/linux/utils/util-linux/v2.23/util-linux-%{upstream_version}.tar.xz +Source1: util-linux-login.pamd +Source2: util-linux-remote.pamd +Source3: util-linux-chsh-chfn.pamd +Source4: util-linux-60-raw.rules +Source8: nologin.c +Source9: nologin.8 +Source12: util-linux-su.pamd +Source13: util-linux-su-l.pamd +Source14: util-linux-runuser.pamd +Source15: util-linux-runuser-l.pamd + +### Obsoletes & Conflicts & Provides +Conflicts: bash-completion < 1:2.1-1 +# su(1) and runuser(1) merged into util-linux v2.22 +Conflicts: coreutils < 8.20 +# eject has been merged into util-linux v2.22 +Obsoletes: eject <= 2.1.5 +Provides: eject = 2.1.6 +# sulogin, utmpdump merged into util-linux v2.22 +Conflicts: sysvinit-tools < 2.88-8 +# old versions of e2fsprogs contain fsck, uuidgen +Conflicts: e2fsprogs < 1.41.8-5 +# rename from util-linux-ng back to util-linux +Obsoletes: util-linux-ng < 2.19 +Provides: util-linux-ng = %{version}-%{release} +Conflicts: filesystem < 3 +Provides: /bin/dmesg +Provides: /bin/kill +Provides: /bin/more +Provides: /bin/mount +Provides: /bin/umount +Provides: /sbin/blkid +Provides: /sbin/blockdev +Provides: /sbin/findfs +Provides: /sbin/fsck +Provides: /sbin/nologin + +Requires(post): coreutils +Requires: pam >= 1.1.3-7, /etc/pam.d/system-auth +Requires: audit-libs >= 1.0.6 +Requires: libuuid = %{version}-%{release} +Requires: libblkid = %{version}-%{release} +Requires: libmount = %{version}-%{release} + +### Ready for upstream? +### +# 151635 - makeing /var/log/lastlog +Patch0: 2.23-login-lastlog-create.patch + +# v2.24 backport: #972457 +Patch1: 2.24-agetty-clocal.patch +# v2.24 backport: #987787 - Remove lastlogin from su +Patch2: 2.24-su-suppress-PAM-info-messages.patch +# v2.24 backport: #950497 - problem umounting loop device +Patch3: 2.24-libmount-canonicalize-for-conversion-from-loopdev.patch +# v2.24 backport: #921498 - multiple internal testsuite failures +Patch4: 2.24-tests-portability.patch +# v2.24 backport: #1005566 - recount_geometry: Process /usr/sbin/fdisk was killed by signal 8 (SIGFPE) +Patch5: 2.24-libfdisk-fix-SIGFPE.patch +# v2.24 backport: #1005194 - su generates incorrect log entries +Patch6: 2.24-su-fix-lastlog-and-btmp-logging.patch +# v2.24 backport: #1006462 - RFE: allow \S escape that defaults to PRETTY_NAME in /etc/issue handling +Patch7: 2.24-agetty-etc-os-release.patch +# v2.24 backport: #1010193 - libmount umount issues +Patch8: 2.24-libmount-mem.patch +# v2.24 backport: #1009349 - Joking sfdisk rewriting PT after "n" +Patch9: 2.24-sfdisk-y-n-miscmatch.patch +# v2.24 backport: #1007885 - utmpdump is not IPv6 ready +Patch10: 2.24-utmpdump-ipv6.patch +# v2.24 backport: #1024366 - losetup does not use loop-control to add device +Patch11: 2.24-losetup-add-device.patch +# v2.24 backport: 1016471 - Document that blockdev --setbsz call has never worked +Patch12: 2.24-blockdev-setbsz-hint.patch +# v2.25 backport: #1039189 - taskset man page PERMISSIONS section is incorrect +Patch13: 2.25-taskset-man-fix-permissions.patch +# v2.25 backport: #1050852 - lscpu: support discontinuous NUMA nodes +Patch14: 2.25-lib-add-path_strdup.patch +Patch15: 2.25-lscpu-discontinuous-NUMA-nodes.patch +Patch16: 2.25-lscpu-sort-NUMA.patch +# v2.25 backport: #1046849 - filesystem type is not correctly displayed by df command +Patch17: 2.25-libblkid-Identify-extN-file-system-properly.patch +# v2.25 backport: #1055490 - libblkid: Do not problem for backup btrfs superblock +Patch18: 2.25-libblkid-no-more-probe-for-btrfs-backup-superblock.patch +# v2.25 backport: #1054186 - wipefs does not clean gpt header fully, PMBR remains +Patch19: 2.25-libblkid-detect-alone-PMBR.patch +Patch20: 2.25-wipefs-call-BLKRRPART-when-erase-partition-table.patch +# v2.25 backport: #977162 - fix the description of XFS "allocsize=" +Patch21: 2.25-mount-man-xfs.patch +# rhel7.0: #1073851 - disable user namespaces +Patch22: rhel7.0-unshare-user.patch +# v2.25 backpoprt: #1078618 - flock nfs file fails on nfsv4 +Patch23: 2.25-flock-nfs4.patch +# v2.25 backport: #1047376 - blkid hangs while reading from /dev/fd0 +Patch24: 2.25-libblkid-io-errors.patch +#v2.24 and v2.25 backport: #1079931 - fsck: warning on kdump boot +Patch25: 2.24-fsck-fstab.patch +Patch26: 2.25-fsck-nohelper.patch + +# +# RHEL 7.1 +# +# 1067354 - dmesg -w output not line-buffered +Patch27: 2.25-dmesg-w.patch +# 1072298 - util-linux/lscpu: '--sysroot' broken on XFS +Patch28: 2.25-lscpu-d_type.patch +# 1072930 - hwclock --systohc can hang on busy or virtual machine +Patch29: 2.25-hwclock-hang.patch +# 1077310 - wipefs problem with some live .isos +Patch30: 2.25-wipefs-nested-pt.patch +# 1077864 - Backport swapon: allow a more flexible swap discard policy +Patch31: 2.25-swapon-discard.patch +# 1080407 - libblkid XFS detection is too fragile +Patch32: 2.25-libblkid-xfs.patch +# RHEL6.6 port #1115442 - kill(1) doesn't check errno after calling strtol() +Patch33: 2.17-kill-strtol.patch +# 1127823 - losetup does not accept offset +Patch34: 2.24-losetup-offset.patch +# 1127891 - wipefs 4k disks and gpt partitions +Patch35: 2.25-libblkid-gpt-512.patch +# 1136111 - "findmnt" returns incomplete output on kernel-3.14 +Patch36: 2.24-libmount-3.14.patch +# backport from upstream: #1140591 - improve mount --move documentation +Patch37: 2.26-mount-man-move.patch +# RHEL6.6 port: #1131522 - backport --fork and --mount-proc to unshare(1) +Patch38: 2.24-unshare-mount-fork.patch +# Backport from upstream (v2.25-214-g8a4c64e): #1113043 - backport lslogins(1) +Patch39: 2.26-libsmartcols.patch +Patch40: 2.26-lslogins.patch +# 1149278 - partx fails to update a specific partition other than the first +Patch41: 2.24-partx-update.patch + +%description +The util-linux package contains a large variety of low-level system +utilities that are necessary for a Linux system to function. Among +others, Util-linux contains the fdisk configuration tool and the login +program. + +%package -n libmount +Summary: Device mounting library +Group: Development/Libraries +License: LGPLv2+ +Requires: libblkid = %{version}-%{release} +Requires: libuuid = %{version}-%{release} +Conflicts: filesystem < 3 + +%description -n libmount +This is the device mounting library, part of util-linux. + + +%package -n libmount-devel +Summary: Device mounting library +Group: Development/Libraries +License: LGPLv2+ +Requires: libmount = %{version}-%{release} +Requires: pkgconfig + +%description -n libmount-devel +This is the device mounting development library and headers, +part of util-linux. + + +%package -n libblkid +Summary: Block device ID library +Group: Development/Libraries +License: LGPLv2+ +Requires: libuuid = %{version}-%{release} +Conflicts: filesystem < 3 +Requires(post): coreutils + +%description -n libblkid +This is block device identification library, part of util-linux. + + +%package -n libblkid-devel +Summary: Block device ID library +Group: Development/Libraries +License: LGPLv2+ +Requires: libblkid = %{version}-%{release} +Requires: pkgconfig + +%description -n libblkid-devel +This is the block device identification development library and headers, +part of util-linux. + + +%package -n libuuid +Summary: Universally unique ID library +Group: Development/Libraries +License: BSD +Conflicts: filesystem < 3 + +%description -n libuuid +This is the universally unique ID library, part of util-linux. + +The libuuid library generates and parses 128-bit universally unique +id's (UUID's). A UUID is an identifier that is unique across both +space and time, with respect to the space of all UUIDs. A UUID can +be used for multiple purposes, from tagging objects with an extremely +short lifetime, to reliably identifying very persistent objects +across a network. + +See also the "uuid" package, which is a separate implementation. + +%package -n libuuid-devel +Summary: Universally unique ID library +Group: Development/Libraries +License: BSD +Requires: libuuid = %{version}-%{release} +Requires: pkgconfig + +%description -n libuuid-devel +This is the universally unique ID development library and headers, +part of util-linux. + +The libuuid library generates and parses 128-bit universally unique +id's (UUID's). A UUID is an identifier that is unique across both +space and time, with respect to the space of all UUIDs. A UUID can +be used for multiple purposes, from tagging objects with an extremely +short lifetime, to reliably identifying very persistent objects +across a network. + +See also the "uuid-devel" package, which is a separate implementation. + + +%package -n uuidd +Summary: Helper daemon to guarantee uniqueness of time-based UUIDs +Group: System Environment/Daemons +Requires: libuuid = %{version}-%{release} +License: GPLv2 +Requires: systemd +Requires(pre): shadow-utils +Requires(post): systemd-units +Requires(preun): systemd-units + +%description -n uuidd +The uuidd package contains a userspace daemon (uuidd) which guarantees +uniqueness of time-based UUID generation even at very high rates on +SMP systems. + + +%prep +%autosetup -p1 -n %{name}-%{upstream_version} + +cp %{SOURCE8} %{SOURCE9} . + +%build +unset LINGUAS || : + +# unfortunately, we did changes to build-system +./autogen.sh + +export CFLAGS="-D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 $RPM_OPT_FLAGS" +export SUID_CFLAGS="-fpie" +export SUID_LDFLAGS="-pie -Wl,-z,relro -Wl,-z,now" +%configure \ + --with-systemdsystemunitdir=%{_unitdir} \ + --disable-silent-rules \ + --disable-wall \ + --disable-bfs \ + --disable-pg \ + --enable-socket-activation \ + --enable-chfn-chsh \ + --enable-write \ + --enable-raw \ + --with-udev \ + --with-selinux \ + --with-audit \ + --with-utempter \ + --disable-makeinstall-chown \ +%ifnarch %cytune_archs + --disable-cytune \ +%endif +%ifarch s390 s390x + --disable-hwclock \ + --disable-fdformat +%endif + +# build util-linux +make %{?_smp_mflags} + +# build nologin +gcc $CFLAGS -o nologin nologin.c + + +%check +#to run tests use "--with check" +%if %{?_with_check:1}%{!?_with_check:0} +make check +%endif + + +%install +rm -rf ${RPM_BUILD_ROOT} +mkdir -p ${RPM_BUILD_ROOT}%{_bindir} +mkdir -p ${RPM_BUILD_ROOT}%{_mandir}/man{1,6,8,5} +mkdir -p ${RPM_BUILD_ROOT}%{_sbindir} +mkdir -p ${RPM_BUILD_ROOT}%{_sysconfdir}/{pam.d,security/console.apps} +mkdir -p ${RPM_BUILD_ROOT}/var/log +touch ${RPM_BUILD_ROOT}/var/log/lastlog +chmod 0644 ${RPM_BUILD_ROOT}/var/log/lastlog + +# install util-linux +make install DESTDIR=${RPM_BUILD_ROOT} + +# install nologin +install -m 755 nologin ${RPM_BUILD_ROOT}%{_sbindir} +install -m 644 nologin.8 ${RPM_BUILD_ROOT}%{_mandir}/man8 + +# raw +echo '.so man8/raw.8' > $RPM_BUILD_ROOT%{_mandir}/man8/rawdevices.8 +{ + # see RH bugzilla #216664 + mkdir -p ${RPM_BUILD_ROOT}%{_prefix}/lib/udev/rules.d + pushd ${RPM_BUILD_ROOT}%{_prefix}/lib/udev/rules.d + install -m 644 %{SOURCE4} ./60-raw.rules + popd +} + +# sbin -> bin +mv ${RPM_BUILD_ROOT}%{_sbindir}/raw ${RPM_BUILD_ROOT}%{_bindir}/raw + +# And a dirs uuidd needs that the makefiles don't create +install -d ${RPM_BUILD_ROOT}/run/uuidd +install -d ${RPM_BUILD_ROOT}/var/lib/libuuid + +# libtool junk +rm -rf ${RPM_BUILD_ROOT}%{_libdir}/*.la + +%ifarch %{sparc} +rm -rf ${RPM_BUILD_ROOT}%{_bindir}/sunhostid +cat << E-O-F > ${RPM_BUILD_ROOT}%{_bindir}/sunhostid +#!/bin/sh +# this should be _bindir/sunhostid or somesuch. +# Copyright 1999 Peter Jones, . +# GPL and all that good stuff apply. +( +idprom=\`cat /proc/openprom/idprom\` +echo \$idprom|dd bs=1 skip=2 count=2 +echo \$idprom|dd bs=1 skip=27 count=6 +echo +) 2>/dev/null +E-O-F +chmod 755 ${RPM_BUILD_ROOT}%{_bindir}/sunhostid +%endif + +# PAM settings +{ + pushd ${RPM_BUILD_ROOT}%{_sysconfdir}/pam.d + install -m 644 %{SOURCE1} ./login + install -m 644 %{SOURCE2} ./remote + install -m 644 %{SOURCE3} ./chsh + install -m 644 %{SOURCE3} ./chfn + install -m 644 %{SOURCE12} ./su + install -m 644 %{SOURCE13} ./su-l + install -m 644 %{SOURCE14} ./runuser + install -m 644 %{SOURCE15} ./runuser-l + popd +} + +%ifnarch s390 s390x +ln -sf hwclock ${RPM_BUILD_ROOT}%{_sbindir}/clock +echo ".so man8/hwclock.8" > ${RPM_BUILD_ROOT}%{_mandir}/man8/clock.8 +%endif + +# unsupported on SPARCs +%ifarch %{sparc} +for I in /sbin/sfdisk \ + %{_mandir}/man8/sfdisk.8* \ + %doc Documentation/sfdisk.txt \ + /sbin/cfdisk \ + %{_mandir}/man8/cfdisk.8*; do + + rm -f $RPM_BUILD_ROOT$I +done +%endif + +# we install getopt-*.{bash,tcsh} as doc files +chmod 644 misc-utils/getopt-*.{bash,tcsh} +rm -f ${RPM_BUILD_ROOT}%{_datadir}/getopt/* +rmdir ${RPM_BUILD_ROOT}%{_datadir}/getopt + +ln -sf /proc/mounts %{buildroot}/etc/mtab + + +# remove static libs +rm -f $RPM_BUILD_ROOT%{_libdir}/lib{uuid,blkid,mount}.a + +# find MO files +%find_lang %name + +# the files section supports only one -f option... +mv %{name}.lang %{name}.files + +# create list of setarch(8) symlinks +find $RPM_BUILD_ROOT%{_bindir}/ -regextype posix-egrep -type l \ + -regex ".*(linux32|linux64|s390|s390x|i386|ppc|ppc64|ppc32|sparc|sparc64|sparc32|sparc32bash|mips|mips64|mips32|ia64|x86_64)$" \ + -printf "%{_bindir}/%f\n" >> %{name}.files + +find $RPM_BUILD_ROOT%{_mandir}/man8 -regextype posix-egrep \ + -regex ".*(linux32|linux64|s390|s390x|i386|ppc|ppc64|ppc32|sparc|sparc64|sparc32|sparc32bash|mips|mips64|mips32|ia64|x86_64)\.8.*" \ + -printf "%{_mandir}/man8/%f*\n" >> %{name}.files + +%post +# only for minimal buildroots without /var/log +[ -d /var/log ] || mkdir -p /var/log +touch /var/log/lastlog +chown root:root /var/log/lastlog +chmod 0644 /var/log/lastlog +# Fix the file context, do not use restorecon +if [ -x /usr/sbin/selinuxenabled ] && /usr/sbin/selinuxenabled; then + SECXT=$( /usr/sbin/matchpathcon -n /var/log/lastlog 2> /dev/null ) + if [ -n "$SECXT" ]; then + # Selinux enabled, but without policy? It's true for buildroots + # without selinux stuff on host machine with enabled selinux. + # We don't want to use any RPM dependence on selinux policy for + # matchpathcon(2). SELinux policy should be optional. + /usr/bin/chcon "$SECXT" /var/log/lastlog >/dev/null 2>&1 || : + fi +fi +if [ ! -L /etc/mtab ]; then + ln -fs /proc/mounts /etc/mtab +fi + +%post -n libblkid +/sbin/ldconfig + +### Move blkid cache to /run +[ -d /run/blkid ] || mkdir -p /run/blkid +for I in /etc/blkid.tab /etc/blkid.tab.old \ + /etc/blkid/blkid.tab /etc/blkid/blkid.tab.old; do + + if [ -f "$I" ]; then + mv "$I" /run/blkid/ || : + fi +done + +%postun -n libblkid -p /sbin/ldconfig + +%post -n libuuid -p /sbin/ldconfig +%postun -n libuuid -p /sbin/ldconfig + +%post -n libmount -p /sbin/ldconfig +%postun -n libmount -p /sbin/ldconfig + +%pre -n uuidd +getent group uuidd >/dev/null || groupadd -r uuidd +getent passwd uuidd >/dev/null || \ +useradd -r -g uuidd -d /var/lib/libuuid -s /sbin/nologin \ + -c "UUID generator helper daemon" uuidd +exit 0 + +%post -n uuidd +if [ $1 -eq 1 ]; then + # Package install, + /bin/systemctl enable uuidd.service >/dev/null 2>&1 || : + /bin/systemctl start uuidd.service > /dev/null 2>&1 || : +else + # Package upgrade + if /bin/systemctl --quiet is-enabled uuidd.service ; then + /bin/systemctl reenable uuidd.service >/dev/null 2>&1 || : + fi +fi + +%preun -n uuidd +if [ "$1" = 0 ]; then + /bin/systemctl stop uuidd.service > /dev/null 2>&1 || : + /bin/systemctl disable uuidd.service > /dev/null 2>&1 || : +fi + + +%files -f %{name}.files +%defattr(-,root,root) +%doc README NEWS AUTHORS +%doc Documentation/deprecated.txt Documentation/licenses/* +%doc misc-utils/getopt-*.{bash,tcsh} + +%config(noreplace) %{_sysconfdir}/pam.d/chfn +%config(noreplace) %{_sysconfdir}/pam.d/chsh +%config(noreplace) %{_sysconfdir}/pam.d/login +%config(noreplace) %{_sysconfdir}/pam.d/remote +%config(noreplace) %{_sysconfdir}/pam.d/su +%config(noreplace) %{_sysconfdir}/pam.d/su-l +%config(noreplace) %{_sysconfdir}/pam.d/runuser +%config(noreplace) %{_sysconfdir}/pam.d/runuser-l +%config(noreplace) %{_prefix}/lib/udev/rules.d/60-raw.rules + +%attr(4755,root,root) %{_bindir}/mount +%attr(4755,root,root) %{_bindir}/umount +%attr(4755,root,root) %{_bindir}/su +%attr(755,root,root) %{_bindir}/login +%attr(4711,root,root) %{_bindir}/chfn +%attr(4711,root,root) %{_bindir}/chsh +%attr(2755,root,tty) %{_bindir}/write + +%ghost %attr(0644,root,root) %verify(not md5 size mtime) /var/log/lastlog +%ghost %verify(not md5 size mtime) %config(noreplace,missingok) /etc/mtab + +%{_bindir}/cal +%{_bindir}/chrt +%{_bindir}/col +%{_bindir}/colcrt +%{_bindir}/colrm +%{_bindir}/column +%{_bindir}/dmesg +%{_bindir}/eject +%{_bindir}/fallocate +%{_bindir}/findmnt +%{_bindir}/flock +%{_bindir}/getopt +%{_bindir}/hexdump +%{_bindir}/ionice +%{_bindir}/ipcmk +%{_bindir}/ipcrm +%{_bindir}/ipcs +%{_bindir}/isosize +%{_bindir}/kill +%{_bindir}/logger +%{_bindir}/look +%{_bindir}/lsblk +%{_bindir}/lscpu +%{_bindir}/lslocks +%{_bindir}/lslogins +%{_bindir}/mcookie +%{_bindir}/more +%{_bindir}/mountpoint +%{_bindir}/namei +%{_bindir}/nsenter +%{_bindir}/prlimit +%{_bindir}/raw +%{_bindir}/rename +%{_bindir}/renice +%{_bindir}/rev +%{_bindir}/script +%{_bindir}/scriptreplay +%{_bindir}/setarch +%{_bindir}/setpriv +%{_bindir}/setsid +%{_bindir}/setterm +%{_bindir}/tailf +%{_bindir}/taskset +%{_bindir}/ul +%{_bindir}/unshare +%{_bindir}/utmpdump +%{_bindir}/uuidgen +%{_bindir}/wdctl +%{_bindir}/whereis +%{_mandir}/man1/cal.1* +%{_mandir}/man1/chfn.1* +%{_mandir}/man1/chrt.1* +%{_mandir}/man1/chsh.1* +%{_mandir}/man1/col.1* +%{_mandir}/man1/colcrt.1* +%{_mandir}/man1/colrm.1* +%{_mandir}/man1/column.1* +%{_mandir}/man1/dmesg.1* +%{_mandir}/man1/eject.1* +%{_mandir}/man1/fallocate.1* +%{_mandir}/man1/flock.1* +%{_mandir}/man1/getopt.1* +%{_mandir}/man1/hexdump.1* +%{_mandir}/man1/ionice.1* +%{_mandir}/man1/ipcmk.1* +%{_mandir}/man1/ipcrm.1* +%{_mandir}/man1/ipcs.1* +%{_mandir}/man1/kill.1* +%{_mandir}/man1/logger.1* +%{_mandir}/man1/login.1* +%{_mandir}/man1/look.1* +%{_mandir}/man1/lscpu.1* +%{_mandir}/man1/lslogins.1* +%{_mandir}/man1/mcookie.1* +%{_mandir}/man1/more.1* +%{_mandir}/man1/mountpoint.1* +%{_mandir}/man1/namei.1* +%{_mandir}/man1/nsenter.1* +%{_mandir}/man1/prlimit.1* +%{_mandir}/man1/rename.1* +%{_mandir}/man1/renice.1* +%{_mandir}/man1/rev.1* +%{_mandir}/man1/runuser.1* +%{_mandir}/man1/script.1* +%{_mandir}/man1/scriptreplay.1* +%{_mandir}/man1/setpriv.1* +%{_mandir}/man1/setsid.1* +%{_mandir}/man1/setterm.1* +%{_mandir}/man1/su.1* +%{_mandir}/man1/tailf.1* +%{_mandir}/man1/taskset.1* +%{_mandir}/man1/ul.1* +%{_mandir}/man1/unshare.1* +%{_mandir}/man1/utmpdump.1.gz +%{_mandir}/man1/uuidgen.1* +%{_mandir}/man1/whereis.1* +%{_mandir}/man1/write.1* +%{_mandir}/man5/fstab.5* +%{_mandir}/man8/addpart.8* +%{_mandir}/man8/agetty.8* +%{_mandir}/man8/blkdiscard.8* +%{_mandir}/man8/blkid.8* +%{_mandir}/man8/blockdev.8* +%{_mandir}/man8/chcpu.8* +%{_mandir}/man8/ctrlaltdel.8* +%{_mandir}/man8/delpart.8* +%{_mandir}/man8/fdisk.8* +%{_mandir}/man8/findfs.8* +%{_mandir}/man8/findmnt.8* +%{_mandir}/man8/fsck.8* +%{_mandir}/man8/fsck.cramfs.8* +%{_mandir}/man8/fsck.minix.8* +%{_mandir}/man8/fsfreeze.8* +%{_mandir}/man8/fstrim.8* +%{_mandir}/man8/isosize.8* +%{_mandir}/man8/ldattach.8* +%{_mandir}/man8/losetup.8* +%{_mandir}/man8/lsblk.8* +%{_mandir}/man8/lslocks.8.gz +%{_mandir}/man8/mkfs.8* +%{_mandir}/man8/mkfs.cramfs.8* +%{_mandir}/man8/mkfs.minix.8* +%{_mandir}/man8/mkswap.8* +%{_mandir}/man8/mount.8* +%{_mandir}/man8/nologin.8* +%{_mandir}/man8/partx.8* +%{_mandir}/man8/pivot_root.8* +%{_mandir}/man8/raw.8* +%{_mandir}/man8/rawdevices.8* +%{_mandir}/man8/readprofile.8* +%{_mandir}/man8/resizepart.8* +%{_mandir}/man8/rtcwake.8* +%{_mandir}/man8/setarch.8* +%{_mandir}/man8/sulogin.8.gz +%{_mandir}/man8/swaplabel.8* +%{_mandir}/man8/swapoff.8* +%{_mandir}/man8/swapon.8* +%{_mandir}/man8/switch_root.8* +%{_mandir}/man8/umount.8* +%{_mandir}/man8/wdctl.8.gz +%{_mandir}/man8/wipefs.8* +%{_sbindir}/addpart +%{_sbindir}/agetty +%{_sbindir}/blkdiscard +%{_sbindir}/blkid +%{_sbindir}/blockdev +%{_sbindir}/chcpu +%{_sbindir}/ctrlaltdel +%{_sbindir}/delpart +%{_sbindir}/fdisk +%{_sbindir}/findfs +%{_sbindir}/fsck +%{_sbindir}/fsck.cramfs +%{_sbindir}/fsck.minix +%{_sbindir}/fsfreeze +%{_sbindir}/fstrim +%{_sbindir}/ldattach +%{_sbindir}/losetup +%{_sbindir}/mkfs +%{_sbindir}/mkfs.cramfs +%{_sbindir}/mkfs.minix +%{_sbindir}/mkswap +%{_sbindir}/nologin +%{_sbindir}/partx +%{_sbindir}/pivot_root +%{_sbindir}/readprofile +%{_sbindir}/resizepart +%{_sbindir}/rtcwake +%{_sbindir}/runuser +%{_sbindir}/sulogin +%{_sbindir}/swaplabel +%{_sbindir}/swapoff +%{_sbindir}/swapon +%{_sbindir}/switch_root +%{_sbindir}/wipefs + +%{compldir}/addpart +%{compldir}/blkdiscard +%{compldir}/blkid +%{compldir}/blockdev +%{compldir}/cal +%{compldir}/chcpu +%{compldir}/chfn +%{compldir}/chrt +%{compldir}/chsh +%{compldir}/col +%{compldir}/colcrt +%{compldir}/colrm +%{compldir}/column +%{compldir}/ctrlaltdel +%{compldir}/delpart +%{compldir}/dmesg +%{compldir}/eject +%{compldir}/fallocate +%{compldir}/fdisk +%{compldir}/findmnt +%{compldir}/flock +%{compldir}/fsck +%{compldir}/fsck.cramfs +%{compldir}/fsck.minix +%{compldir}/fsfreeze +%{compldir}/fstrim +%{compldir}/getopt +%{compldir}/hexdump +%{compldir}/ionice +%{compldir}/ipcrm +%{compldir}/ipcs +%{compldir}/isosize +%{compldir}/ldattach +%{compldir}/logger +%{compldir}/look +%{compldir}/losetup +%{compldir}/lsblk +%{compldir}/lscpu +%{compldir}/lslocks +%{compldir}/mcookie +%{compldir}/mkfs +%{compldir}/mkfs.cramfs +%{compldir}/mkfs.minix +%{compldir}/mkswap +%{compldir}/more +%{compldir}/mountpoint +%{compldir}/namei +%{compldir}/nsenter +%{compldir}/partx +%{compldir}/pivot_root +%{compldir}/prlimit +%{compldir}/raw +%{compldir}/readprofile +%{compldir}/rename +%{compldir}/renice +%{compldir}/resizepart +%{compldir}/rev +%{compldir}/rtcwake +%{compldir}/runuser +%{compldir}/script +%{compldir}/scriptreplay +%{compldir}/setarch +%{compldir}/setpriv +%{compldir}/setsid +%{compldir}/setterm +%{compldir}/su +%{compldir}/swaplabel +%{compldir}/swapon +%{compldir}/tailf +%{compldir}/taskset +%{compldir}/ul +%{compldir}/unshare +%{compldir}/utmpdump +%{compldir}/uuidgen +%{compldir}/wdctl +%{compldir}/whereis +%{compldir}/wipefs +%{compldir}/write + +%ifnarch s390 s390x +%{_sbindir}/clock +%{_sbindir}/fdformat +%{_sbindir}/hwclock +%{_mandir}/man8/fdformat.8* +%{_mandir}/man8/hwclock.8* +%{_mandir}/man8/clock.8* +%{compldir}/fdformat +%{compldir}/hwclock +%endif + +%ifnarch %{sparc} +%doc Documentation/sfdisk.txt +%{_sbindir}/cfdisk +%{_sbindir}/sfdisk +%{_mandir}/man8/cfdisk.8* +%{_mandir}/man8/sfdisk.8* +%{compldir}/cfdisk +%{compldir}/sfdisk +%endif + +%ifarch %{sparc} +%{_bindir}/sunhostid +%endif + +%ifarch %cytune_archs +%{_bindir}/cytune +%{_mandir}/man8/cytune.8* +%{compldir}/cytune +%endif + + +%files -n uuidd +%defattr(-,root,root) +%doc Documentation/licenses/COPYING.GPLv2 +%{_mandir}/man8/uuidd.8* +%{_sbindir}/uuidd +%{_unitdir}/* +%dir %attr(2775, uuidd, uuidd) /var/lib/libuuid +%dir %attr(2775, uuidd, uuidd) /run/uuidd +%{compldir}/uuidd + + +%files -n libmount +%defattr(-,root,root) +%doc libmount/COPYING +%{_libdir}/libmount.so.* + +%files -n libmount-devel +%defattr(-,root,root) +%doc libmount/COPYING +%{_libdir}/libmount.so +%{_includedir}/libmount +%{_libdir}/pkgconfig/mount.pc + + +%files -n libblkid +%defattr(-,root,root) +%doc libblkid/COPYING +%{_libdir}/libblkid.so.* + +%files -n libblkid-devel +%defattr(-,root,root) +%doc libblkid/COPYING +%{_libdir}/libblkid.so +%{_includedir}/blkid +%{_mandir}/man3/libblkid.3* +%{_libdir}/pkgconfig/blkid.pc + + +%files -n libuuid +%defattr(-,root,root) +%doc libuuid/COPYING +%{_libdir}/libuuid.so.* + +%files -n libuuid-devel +%defattr(-,root,root) +%doc libuuid/COPYING +%{_libdir}/libuuid.so +%{_includedir}/uuid +%{_mandir}/man3/uuid.3* +%{_mandir}/man3/uuid_clear.3* +%{_mandir}/man3/uuid_compare.3* +%{_mandir}/man3/uuid_copy.3* +%{_mandir}/man3/uuid_generate.3* +%{_mandir}/man3/uuid_generate_random.3* +%{_mandir}/man3/uuid_generate_time.3* +%{_mandir}/man3/uuid_generate_time_safe.3* +%{_mandir}/man3/uuid_is_null.3* +%{_mandir}/man3/uuid_parse.3* +%{_mandir}/man3/uuid_time.3* +%{_mandir}/man3/uuid_unparse.3* +%{_libdir}/pkgconfig/uuid.pc + +%changelog +* Fri Oct 10 2014 Karel Zak 2.23.2-18 +- fix #1149278 - partx fails to update a specific partition other than the first + +* Thu Sep 25 2014 Karel Zak 2.23.2-17 +- fix #1067354 - dmesg -w output not line-buffered +- fix #1072298 - util-linux/lscpu: '--sysroot' broken on XFS +- fix #1072930 - hwclock --systohc can hang on busy or virtual machine +- fix #1077310 - wipefs problem with some live .isos +- fix #1077864 - swapon: allow a more flexible swap discard policy +- fix #1080407 - libblkid XFS detection is too fragile +- fix #1115442 - kill(1) doesn't check errno after calling strtol() +- fix #1127823 - losetup does not accept offset +- fix #1127891 - wipefs 4k disks and gpt partitions +- fix #1136111 - "findmnt" returns incomplete output on kernel-3.14 +- fix #1140591 - improve mount --move documentation +- fix #1131522 - backport --fork and --mount-proc to unshare(1) +- fix #1113043 - backport lslogins(1) + +* Fri Mar 28 2014 Karel Zak 2.23.2-16 +- fix bugs in patch for #1047376 + +* Tue Mar 25 2014 Karel Zak 2.23.2-15 +- fix #1078618 - flock nfs file fails on nfsv4 +- fix #1047376 - blkid hangs while reading from /dev/fd0 +- fix #1079931 - fsck: warning on kdump boot + +* Wed Mar 12 2014 Karel Zak 2.23.2-14 +- fix #1073851 - disable user namespaces at all + +* Thu Feb 20 2014 Karel Zak 2.23.2-13 +- fix #1061751 - nsenter set uid for user namespaces + +* Fri Jan 24 2014 Daniel Mach - 2.23.2-12 +- Mass rebuild 2014-01-24 + +* Thu Jan 23 2014 Karel Zak 2.23.2-11 +- fix #1046849 - filesystem type is not correctly displayed by df command +- fix #1055490 - libblkid: Do not problem for backup btrfs superblock +- fix #1054186 - wipefs does not clean gpt header fully, PMBR remains + +* Tue Jan 14 2014 Karel Zak 2.23.2-10 +- sort NOMA nodes in lscpu(1) output to improve fix for #1050852 + +* Tue Jan 14 2014 Karel Zak 2.23.2-9 +- fix #1039189 - taskset man page PERMISSIONS section is incorrect +- fix #1050852 - lscpu: support discontinuous NUMA nodes + +* Fri Dec 27 2013 Daniel Mach - 2.23.2-8 +- Mass rebuild 2013-12-27 + +* Fri Nov 15 2013 Karel Zak 2.23.2-7 +- fix #1024366 - losetup does not use loop-control to add device +- fix #1016471 - document that blockdev --setbsz call has never worked + +* Mon Oct 7 2013 Karel Zak 2.23.2-6 +- fix #1010193 - libmount umount issues +- fix #1009349 - Joking sfdisk rewriting PT after "n" +- fix #1007885 - utmpdump is not IPv6 ready + +* Thu Sep 12 2013 Karel Zak 2.23.2-5 +- fix #1006462 - RFE: allow \S escape that defaults to PRETTY_NAME in /etc/issue handling + +* Mon Sep 9 2013 Karel Zak 2.23.2-4 +- fix #1005566 - recount_geometry: Process /usr/sbin/fdisk was killed by signal 8 (SIGFPE) +- fix #1005194 - su generates incorrect log entries + +* Mon Sep 9 2013 Karel Zak 2.23.2-3 +- refresh and rename patches +- fix #987787 - Remove lastlogin from su +- fix #950497 - problem umounting loop device +- fix #921498 - multiple internal testsuite failures + +* Thu Aug 1 2013 Karel Zak 2.23.2-2 +- fix 990083 - su doesn't work with pam_ecryptfs + +* Wed Jul 31 2013 Karel Zak 2.23.2-1 +- upgrade to stable release 2.23.2 + ftp://ftp.kernel.org/pub/linux/utils/util-linux/v2.23/v2.23.2-ReleaseNotes + +* Thu Jun 13 2013 Karel Zak 2.23.1-3 +- fix #972457 - agetty idle I/O polling causes elevated CPU usage + +* Wed Jun 5 2013 Karel Zak 2.23.1-2 +- fix #962145 - in.telnetd immediately closes connection + +* Tue May 28 2013 Karel Zak 2.23.1-1 +- upgrade to 2.23.1 +- backport agetty --local-line path + +* Thu Apr 25 2013 Karel Zak 2.23-1 +- upgrade to 2.23 +- add --with check to call make check + +* Mon Apr 15 2013 Karel Zak 2.23-0.7 +- remove unused patches + +* Mon Apr 15 2013 Karel Zak 2.23-0.6 +- remove floppy from util-linux + +* Fri Apr 12 2013 Karel Zak 2.23-0.5 +- fix #948274 - interruption code 0x4003B in libmount.so.1.1.0 + +* Wed Apr 10 2013 Karel Zak 2.23-0.4 +- upgrade to the release 2.23-rc2 + +* Wed Mar 27 2013 Karel Zak 2.23-0.3 +- libblkid ntfs bugfix for build on s390 + +* Wed Mar 27 2013 Karel Zak 2.23-0.2 +- add upstream patches for to fix umount and mount. + +* Fri Mar 22 2013 Karel Zak 2.23-0.1 +- upgrade to the release 2.23-rc1 + ftp://ftp.kernel.org/pub/linux/utils/util-linux/v2.23/v2.23-ReleaseNotes +- add nsenter and blkdiscard +- remove tunelp + +* Wed Feb 20 2013 Karel Zak 2.22.2-6 +- fix #912778 - "runuser -l" doesn't register session to systemd + +* Tue Feb 19 2013 Karel Zak 2.22.2-5 +- fix #902512 - Dependency failed for /home (and blkid fails to tell UUID) +- refresh old patches + +* Wed Feb 6 2013 Karel Zak 2.22.2-4 +- improve convertion to mtab symlink in post script +- spec file cleanup (based on #894199) + +* Sun Feb 3 2013 Karel Zak 2.22.2-3 +- fix #882305 - agetty: unstable /dev/tty* permissions +- fix #885314 - hexdump segfault +- fix #896447 - No newlines in piped "cal" command +- fix libblkid cache usage (upstream patch) +- fix #905008 - uuidd: /usr/sbin/uuidd has incorrect file permissions + +* Tue Jan 15 2013 Karel Zak 2.22.2-2 +- fix #889888 - wipefs does not completely wipe btrfs volume + +* Thu Dec 13 2012 Karel Zak 2.22.2-1 +- upgrade to upstream maintenance release 2.22.2 + +* Mon Nov 19 2012 Karel Zak 2.22.1-5 +- sources cleanup + +* Fri Nov 16 2012 Karel Zak 2.22.1-4 +- fix #872787 - su: COMMAND not specified + +* Thu Nov 1 2012 Karel Zak 2.22.1-3 +- backport upstream runuser(1) +- enable su(1) + +* Thu Nov 1 2012 Karel Zak 2.22.1-2 +- apply pathes from upstream stable/v2.22 branch +- fix #865961 - wipefs -a should use O_EXCL + +* Thu Oct 10 2012 Karel Zak 2.22.1-1 +- upgrade to the release 2.22.1 + +* Wed Oct 3 2012 Karel Zak 2.22-2 +- remove obsolete references to e2fsprogs + +* Thu Sep 6 2012 Karel Zak 2.22-1 +- upgrade to the release 2.22 +- enable eject(1) from util-linux, obsolete original eject package +- fix #853164 - setuid program should have full RELRO +- fix #851230 - probe_ntfs: /usr/sbin/blkid was killed by SIGSEGV + +* Thu Aug 16 2012 Karel Zak 2.22-0.1 +- upgrade to the release 2.22-rc2 + ftp://ftp.kernel.org/pub/linux/utils/util-linux/v2.22/v2.22-ReleaseNotes +- add sulogin, utmpdump, lslocks, wdctl + +* Fri Jul 27 2012 Fedora Release Engineering - 2.21.2-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild + +* Wed Jun 13 2012 Karel Zak 2.21.2-2 +- replace udev dependenceis with systemd + +* Fri May 25 2012 Karel Zak 2.21.2-1 +- upgrade to bugfix release 2.21.2 +- fix #814699 - namei(1) incorrectly resolves relative symlinks +- fix #820707 - Impossible to unmount nfsv4/krb5 mounts after network disconnect +- fix #816877 - libmount does not close device fd before mount(2) +- fix #822705 - unable to login after installing + +* Fri Mar 30 2012 Karel Zak 2.21.1-1 +- upgrade to bugfix release 2.21.1 + +* Fri Feb 24 2012 Karel Zak 2.21-1 +- upgrade to release 2.21 + +* Thu Feb 09 2012 Karel Zak 2.21-0.2 +- fix #788703 - /run/blkid does not exist + +* Thu Feb 07 2012 Karel Zak 2.21-0.1 +- upgrade to the release 2.21-rc2 + ftp://ftp.kernel.org/pub/linux/utils/util-linux/v2.21/v2.21-ReleaseNotes +- add {fsck,mkfs}.minix +- add new command chcpu(8) +- add new command prlimit(1) +- enable raw(8) command +- move 60-raw.rules from /etc from /usr/lib/udev/rules.d +- move blkid cache from etc to /run/blkid + +* Wed Jan 25 2012 Harald Hoyer 2.20.1-5 +- install everything in /usr + https://fedoraproject.org/wiki/Features/UsrMove + +* Sat Jan 14 2012 Fedora Release Engineering - 2.20.1-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild + +* Tue Nov 22 2011 Karel Zak 2.20.1-3 +- fix #748216 - util-linux requires pam >= 1.1.3-7 +- remove ddate(1) + +* Wed Oct 26 2011 Fedora Release Engineering - 2.20.1-2 +- Rebuilt for glibc bug#747377 + +* Thu Oct 20 2011 Karel Zak 2.20.1-1 +- upgrade to the release 2.20.1 + ftp://ftp.infradead.org/pub/util-linux/v2.20/v2.20.1-ReleaseNotes + +* Mon Aug 29 2011 Karel Zak 2.20-1 +- upgrade to the release 2.20 + +* Wed Aug 17 2011 Karel Zak 2.20-0.2 +- upgrade to the release 2.20-rc2 + ftp://ftp.kernel.org/pub/linux/utils/util-linux/v2.20/v2.20-rc2-ChangeLog + +* Fri Aug 2 2011 Karel Zak 2.20-0.1 +- upgrade to the release 2.20-rc1 + ftp://ftp.kernel.org/pub/linux/utils/util-linux/v2.20/v2.20-ReleaseNotes + +* Mon Jul 4 2011 Karel Zak 2.19.1-2 +- fix #716483 - /var/tmp --(BIND-mounted)--> /tmp disrupts/hangs bootup +- fix #709681 - failure to mount if a mount point ends with a slash in /etc/fstab +- fix #709319 - 'mount -a' mounts already mounted directories +- fix kernel version parsing + +* Fri May 6 2011 Karel Zak 2.19.1-1 +- upgrade to the release 2.19.1 + ftp://ftp.kernel.org/pub/linux/utils/util-linux/v2.19/v2.19.1-ReleaseNotes + +* Wed Apr 20 2011 Karel Zak 2.19.1-0.1 +- upgrade to the release 2.19.1-rc1 + ftp://ftp.kernel.org/pub/linux/utils/util-linux/v2.19/v2.19.1-rc1-ChangeLog + +* Mon Mar 7 2011 Karel Zak 2.19-2 +- fix #682502 - Broken source URL to floppy tarball, new version available +- upgrade to floppy-0.18 + +* Thu Feb 10 2011 Karel Zak 2.19-1 +- upgrade to the release 2.19 + ftp://ftp.kernel.org/pub/linux/utils/util-linux/v2.19/v2.19-ReleaseNotes +- remove /sbin/mount.tmpfs -- integrated to mount(8) + +* Tue Feb 8 2011 Karel Zak 2.19-0.6 +- fix #665062 - add support for the postlogin PAM stack to util-linux-ng + +* Mon Feb 07 2011 Fedora Release Engineering - 2.19-0.5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild + +* Tue Jan 25 2011 Karel Zak 2.19-0.4 +- upgrade to the release 2.19-rc3 + ftp://ftp.kernel.org/pub/linux/utils/util-linux/v2.19/v2.19-rc3-ChangeLog + +* Tue Jan 25 2011 Karel Zak 2.19-0.3 +- upgrade to the release 2.19-rc2 + ftp://ftp.kernel.org/pub/linux/utils/util-linux/v2.19/v2.19-rc2-ChangeLog +- fix #671893 - SELinux is preventing /bin/chown from 'setattr' accesses + on the file mounts. + +* Wed Jan 19 2011 Karel Zak 2.19-0.2 +- clean up specfile (review #667416) + +* Wed Jan 5 2011 Karel Zak 2.19-0.1 +- upgrade to the release 2.19-rc1 + ftp://ftp.kernel.org/pub/linux/utils/util-linux/v2.19/v2.19-ReleaseNotes + +* Tue Oct 26 2010 Karel Zak 2.18-5 +- fix #645640 - new "-s" parameter parsing in agetty does not work +- add -l (lock) support to fsck + +* Wed Aug 18 2010 Karel Zak 2.18-4 +- fix #623685 - please extend agetty to not require a baud rate to be specified + +* Thu Aug 5 2010 Karel Zak 2.18-3 +- fix #620924 - /sbin/mount.tmpfs uses not available /usr/bin/id + +* Mon Aug 2 2010 Karel Zak 2.18-2 +- fix #615719 - tmpfs mount fails with 'user' option. +- fix #598631 - shutdown, reboot, halt and C-A-D don't work +- fix #618957 - ISO images listed in fstab are mounted twice at boot + +* Wed Jun 30 2010 Karel Zak 2.18-1 +- upgrade to the final 2.18 + ftp://ftp.kernel.org/pub/linux/utils/util-linux-ng/v2.18/v2.18-ReleaseNotes + +* Fri Jun 18 2010 Karel Zak 2.18-0.2 +- upgrade to 2.18-rc2 + ftp://ftp.kernel.org/pub/linux/utils/util-linux-ng/v2.18/v2.18-rc2-ChangeLog + +* Tue Jun 8 2010 Karel Zak 2.18-0.1 +- upgrade to the release 2.18-rc1 + ftp://ftp.kernel.org/pub/linux/utils/util-linux-ng/v2.18/v2.18-ReleaseNotes + ftp://ftp.kernel.org/pub/linux/utils/util-linux-ng/v2.18/v2.18-rc1-ChangeLog + +* Mon Apr 12 2010 Karel Zak 2.17.2-1 +- fix #581252 - remounting tmpfs fails because of hidden rootcontext= +- fix #580296 - "rtcwake" does miss the "off" option +- fix #575734 - use microsecond resolution for blkid cache entries +- upgrade to the bugfix release 2.17.2 + ftp://ftp.kernel.org/pub/linux/utils/util-linux-ng/v2.17/v2.17.2-ReleaseNotes + ftp://ftp.kernel.org/pub/linux/utils/util-linux-ng/v2.17/v2.17.2-ChangeLog +- minor fixed in spec file + +* Thu Mar 11 2010 Karel Zak 2.17.1-2 +- fix #533874 - libblkid should allow scanning of slow devices (eg. cdroms) + +* Mon Feb 22 2010 Karel Zak 2.17.1-1 +- upgrade to the final 2.17.1 + ftp://ftp.kernel.org/pub/linux/utils/util-linux-ng/v2.17/v2.17.1-ReleaseNotes + ftp://ftp.kernel.org/pub/linux/utils/util-linux-ng/v2.17/v2.17.1-ChangeLog + +* Tue Feb 16 2010 Karel Zak 2.17.1-0.1 +- upgrade to 2.17.1-rc1 + +* Tue Feb 16 2010 Karel Zak 2.17-4 +- fix uuidd init script + +* Fri Feb 12 2010 Karel Zak 2.17-3 +- fix #541402 - uuidd initscript lsb compliance + +* Fri Jan 8 2010 Karel Zak 2.17-2 +- remove Provides: lib{uuid,blkid}-static (thanks to Michael Schwendt) +- remove useless URL to sf.net + +* Thu Jan 8 2010 Karel Zak 2.17-1 +- upgrade to the final 2.17 + ftp://ftp.kernel.org/pub/linux/utils/util-linux-ng/v2.17/v2.17-ReleaseNotes + ftp://ftp.kernel.org/pub/linux/utils/util-linux-ng/v2.17/v2.17-ChangeLog +- fix #545147 - util-linux-ng : Violation of the Packaging Guidelines + (remove uuid and blkid static libs) + +* Mon Dec 14 2009 Karel Zak 2.17-0.6 +- minor fixes in spec file (fix URL, add Requires, add LGPLv2+) + +* Wed Dec 9 2009 Karel Zak 2.17-0.5 +- upgrade to 2.17-rc2 + ftp://ftp.kernel.org/pub/linux/utils/util-linux-ng/v2.17/v2.17-rc2-ChangeLog + +* Mon Dec 7 2009 Karel Zak 2.17-0.4 +- add clock.8 man page (manlink to hwclock) +- add --help to mount.tmpfs + +* Mon Nov 23 2009 Karel Zak 2.17-0.3 +- upgrade to 2.17-rc1 + ftp://ftp.kernel.org/pub/linux/utils/util-linux-ng/v2.17/v2.17-rc1-ChangeLog + +* Tue Nov 10 2009 Karel Zak 2.17-0.2.git10dfc39 +- upgrade to pre-release snapshot (official changelog not available yet, see + http://git.kernel.org/?p=utils/util-linux-ng/util-linux-ng.git for now) + +* Mon Oct 19 2009 Karel Zak 2.17-0.1.git5e51568 +- upgrade to pre-release snapshot (official changelog not available yet, see + http://git.kernel.org/?p=utils/util-linux-ng/util-linux-ng.git for now) +- new commands: fallocate, unshare, wipefs +- libblkid supports topology and partitions probing +- remove support for --rmpart[s] from blockdev(8) (util-linux-ng-2.14-blockdev-rmpart.patch) +- merged upstream: + util-linux-ng-2.14-sfdisk-dump.patch + util-linux-ng-2.16-blkid-swsuspend.patch + util-linux-ng-2.16-libblkid-compression.patch + util-linux-ng-2.16-libblkid-ext2.patch + util-linux-ng-2.16-switchroot-tty.patch + +* Mon Oct 5 2009 Karel Zak 2.16-13 +- fix spec file + +* Fri Oct 2 2009 Karel Zak 2.16-12 +- release++ + +* Thu Oct 1 2009 Karel Zak 2.16-11 +- fix #519237 - bash: cannot set terminal process group (-1): Inappropriate ioctl for device + +* Wed Sep 16 2009 Tomas Mraz - 2.16-10 +- use password-auth common PAM configuration instead of system-auth and + drop pam_console.so call from the remote PAM config file + +* Mon Sep 14 2009 Karel Zak 2.16-9 +- fix #522718 - sfdisk -d /dev/xxx | sfdisk --force /dev/yyy fails when LANG is set +- fix typo in swsuspend detection + +* Wed Aug 26 2009 Tomas Mraz - 2.16-8 +- rebuilt with new audit + +* Sun Aug 23 2009 Karel Zak 2.16-7 +- fix #518572 - blkid requires ext2.ko to be decompressed on installation media + +* Thu Aug 13 2009 Karel Zak 2.16-5 +- fix #513104 - blkid returns no fstype for ext2 device when ext2 module not loaded + +* Wed Aug 5 2009 Stepan Kasal 2.16-4 +- set conflict with versions of e2fsprogs containing fsck + +* Thu Jul 30 2009 Karel Zak 2.16-3 +- remove the mount.conf support (see #214891) + +* Mon Jul 27 2009 Karel Zak 2.16-2 +- fix #214891 - add mount.conf and MTAB_LOCK_DIR= option + +* Sat Jul 25 2009 Karel Zak 2.16-1 +- upgrade to 2.16 + ftp://ftp.kernel.org/pub/linux/utils/util-linux-ng/v2.16/v2.16-ReleaseNotes +- enable built-in libuuid (replacement for the old uuid stuff from e2fsprogs) +- new commands switch_root, uuidgen and uuidd (subpackage) + +* Wed Jun 10 2009 Karel Zak 2.15.1-1 +- upgrade to 2.15.1 + +* Mon Jun 8 2009 Karel Zak 2.15.1-0.2 +- set BuildRequires: e2fsprogs-devel +- add Requires: e2fsprogs-devel to libblkid-devel + +* Thu Jun 4 2009 Karel Zak 2.15.1-0.1 +- upgrade to 2.15.1-rc1 + ftp://ftp.kernel.org/pub/linux/utils/util-linux-ng/v2.15/v2.15-ReleaseNotes + ftp://ftp.kernel.org/pub/linux/utils/util-linux-ng/v2.15/v2.15.1-rc1-ChangeLog +- merged patches: + util-linux-ng-2.14-login-remote.patch + util-linux-ng-2.14-fdisk-4k-I.patch + util-linux-ng-2.14-fdisk-4k-II.patch + util-linux-ng-2.14-fdisk-4k-III.patch + util-linux-ng-2.14-dmesg-r.patch + util-linux-ng-2.14-flock-segfaults.patch + util-linux-ng-2.14-renice-n.patch +- new commands: lscpu, ipcmk +- remove support for "managed" and "kudzu" mount options +- cleanup spec file +- enable built-in libblkid (replacement for the old blkid from e2fsprogs) + +* Thu Apr 2 2009 Karel Zak 2.14.2-8 +- fix #490769 - post scriptlet failed (thanks to Dan Horak) + +* Fri Mar 20 2009 Karel Zak 2.14.2-7 +- fix some nits in mount.tmpfs + +* Fri Mar 20 2009 Karel Zak 2.14.2-6 +- fix #491175 - mount of tmpfs FSs fail at boot + +* Thu Mar 19 2009 Karel Zak 2.14.2-5 +- fix #489672 - flock segfaults when file name is not given (upstream) +- fix #476964 - Mount /var/tmp with tmpfs creates denials +- fix #487227 - fdisk 4KiB hw sectors support (upstream) +- fix #477303 - renice doesn't support -n option (upstream) + +* Wed Feb 25 2009 Fedora Release Engineering - 2.14.2-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_11_Mass_Rebuild + +* Fri Feb 20 2009 Karel Zak 2.14.2-3 +- add -r option to dmesg(1) + +* Mon Feb 9 2009 Karel Zak 2.14.2-2 +- fix typo in spec file + +* Mon Feb 9 2009 Karel Zak 2.14.2-1 +- upgrade to stable 2.14.2 + ftp://ftp.kernel.org/pub/linux/utils/util-linux-ng/v2.14/v2.14.2-ReleaseNotes + +* Thu Jan 22 2009 Karel Zak 2.14.2-0.2 +- fix #480413 - util-linux-ng doesn't include scriptreplay +- fix #479002 - remove dependency on ConsoleKit-libs +- upgrade to 2.14.2-rc2 + +* Mon Dec 22 2008 Karel Zak 2.14.2-0.1 +- upgrade to 2.14.2-rc1 +- refresh old patches + +* Fri Nov 21 2008 Karel Zak 2.14.1-5 +- fix #472502 - problem with fdisk and use +sectors for the end of partition + +* Mon Oct 6 2008 Karel Zak 2.14.1-3 +- fix #465761 - mount manpage is missing uid/gid mount options for tmpfs +- refresh util-linux-ng-2.14-mount-file_t.patch (fuzz=0) + +* Wed Sep 10 2008 Karel Zak 2.14.1-2 +- remove obsolete pam-console support + +* Wed Sep 10 2008 Karel Zak 2.14.1-1 +- upgrade to stable 2.14.1 + +* Thu Aug 14 2008 Karel Zak 2.14.1-0.1 +- upgrade to 2.14.1-rc1 +- refresh old patches + +* Thu Jul 24 2008 Karel Zak 2.14-3 +- update util-linux-ng-2.14-mount-file_t.patch to make + the SELinux warning optional (verbose mode is required) + +* Tue Jul 1 2008 Karel Zak 2.14-2 +- fix #390691 - mount should check selinux context on mount, and warn on file_t + +* Mon Jun 9 2008 Karel Zak 2.14-1 +- upgrade to stable util-linux-ng release + +* Mon May 19 2008 Karel Zak 2.14-0.1 +- upgrade to 2.14-rc3 +- remove arch(8) (deprecated in favor of uname(1) or arch(1) from coreutils) +- add a new command ldattach(8) +- cfdisk(8) linked with libncursesw + +* Tue Apr 22 2008 Karel Zak 2.13.1-9 +- fix audit log injection attack via login + +* Thu Apr 17 2008 Karel Zak 2.13.1-8 +- fix location of the command raw(8) + +* Tue Apr 15 2008 Karel Zak 2.13.1-7 +- fix 244383 - libblkid uses TYPE="swsuspend" for S1SUSPEND/S2SUSPEND + +* Wed Apr 2 2008 Karel Zak 2.13.1-6 +- fix 439984 - backport mkswap -U + +* Wed Mar 26 2008 Tom "spot" Callaway - 2.13.1-5 +- clean up sparc conditionals + +* Tue Feb 19 2008 Fedora Release Engineering - 2.13.1-4 +- Autorebuild for GCC 4.3 + +* Mon Jan 28 2008 Karel Zak 2.13.1-3 +- upgrade to new upstream release +- fix #427874 - util-linux-ng gets "excess command line argument" on update + +* Wed Jan 2 2008 Karel Zak 2.13.1-2 +- update to upstream 2.13.1-rc2 + +* Wed Dec 12 2007 Dan Walsh 2.13.1-1 +- Fix pam files so that pam_keyinit happens after pam_selinux.so + +* Wed Dec 12 2007 Karel Zak 2.13.1-0.2 +- remove viwp and vigr (in favour of shadow-utils) + +* Sun Dec 9 2007 Karel Zak 2.13.1-0.1 +- update to the latest upstream stable branch + (commit: fda9d11739ee88c3b2f22a73f12ec019bd3b8335) + +* Wed Oct 31 2007 Karel Zak 2.13-4 +- fix #354791 - blockdev command calls the blkpg ioctl with a wrong data structure + +* Tue Oct 16 2007 Karel Zak 2.13-3 +- fix mount -L | -U segfault +- fix script die on SIGWINCH + +* Thu Oct 4 2007 Karel Zak 2.13-2 +- update to the latest upstream stable branch + +* Tue Aug 28 2007 Karel Zak 2.13-1 +- upgrade to stable util-linux-ng release + +* Fri Aug 24 2007 Karel Zak 2.13-0.59 +- add release number to util-linux Provides and increment setarch Obsoletes +- fix #254114 - spec typo +- upgrade to floppy-0.16 +- add BuildRequires: popt-devel + +* Wed Aug 22 2007 Jesse Keating 2.13-0.58 +- Obsolete a sufficiently high enough version of setarch + +* Mon Aug 20 2007 Karel Zak 2.13-0.57 +- fix #253664 - util-linux-ng fails to build on sparc (patch by Dennis Gilmore) +- rebase to new GIT snapshot + +* Mon Aug 20 2007 Karel Zak 2.13-0.56 +- fix obsoletes field + +* Mon Aug 20 2007 Karel Zak 2.13-0.55 +- util-linux-ng includes setarch(1), define relevat Obsoletes+Provides + +* Mon Aug 20 2007 Karel Zak 2.13-0.54 +- port "blockdev --rmpart" patch from util-linux +- use same Provides/Obsoletes setting like in util-linux + +* Wed Aug 15 2007 Karel Zak 2.13-0.53 +- fix #252046 - review Request: util-linux-ng (util-linux replacement) + +* Mon Aug 13 2007 Karel Zak 2.13-0.52 +- rebase to util-linux-ng (new util-linux upstream fork, + based on util-linux 2.13-pre7) +- more than 70 Fedora/RHEL patches have been merged to upstream code + +* Fri Apr 6 2007 Karel Zak 2.13-0.51 +- fix #150493 - hwclock --systohc sets clock 0.5 seconds slow +- fix #220873 - starting RPC idmapd: Error: RPC MTAB does not exist. + (added rpc_pipefs to util-linux-2.13-umount-sysfs.patch) +- fix #227903 - mount -f does not work with NFS-mounted + +* Sat Mar 3 2007 David Zeuthen 2.13-0.50 +- include ConsoleKit session module by default (#229172) + +* Thu Jan 11 2007 Karel Zak 2.13-0.49 +- fix #222293 - undocumented partx,addpart, delpart + +* Sun Dec 17 2006 Karel Zak 2.13-0.48 +- fix paths in po/Makefile.in.in + +* Fri Dec 15 2006 Karel Zak 2.13-0.47 +- fix #217240 - namei ignores non-directory components instead of saying "Not a directory" +- fix #217241 - namei enforces symlink limits inconsistently + +* Wed Dec 14 2006 Karel Zak 2.13-0.46 +- fix leaking file descriptor in the more command (patch by Steve Grubb) + +* Wed Dec 13 2006 Karel Zak 2.13-0.45 +- use ncurses only +- fix #218915 - fdisk -b 4K +- upgrade to -pre7 release +- fix building problem with raw0 patch +- fix #217186 - /bin/sh: @MKINSTALLDIRS@: No such file or directory + (port po/Makefile.in.in from gettext-0.16) +- sync with FC6 and RHEL5: +- fix #216489 - SCHED_BATCH option missing in chrt +- fix #216712 - issues with raw device support ("raw0" is wrong device name) +- fix #216760 - mount with context or fscontext option fails + (temporarily disabled the support for additional contexts -- not supported by kernel yet) +- fix #211827 - Can't mount with additional contexts +- fix #213127 - mount --make-unbindable does not work +- fix #211749 - add -r option to losetup to create a read-only loop + +* Thu Oct 12 2006 Karel Zak 2.13-0.44 +- fix #209911 - losetup.8 updated (use dm-crypt rather than deprecated cryptoloop) +- fix #210338 - spurious error from '/bin/login -h $PHONENUMBER' (bug in IPv6 patch) +- fix #208634 - mkswap "works" without warning on a mounted device + +* Sun Oct 01 2006 Jesse Keating - 2.13-0.43 +- rebuilt for unwind info generation, broken in gcc-4.1.1-21 + +* Wed Sep 20 2006 Karel Zak 2.13-0.42 +- remove obsolete NFS code and patches (we use /sbin/mount.nfs + and /sbin/umount.nfs from nfs-utils now) +- move nfs.5 to nfs-utils + +* Fri Sep 15 2006 Karel Zak 2.13-0.41 +- fix #205038 - mount not allowing sloppy option (exports "-s" + to external /sbin/mount.nfs(4) calls) +- fix minor bug in util-linux-2.13-mount-twiceloop.patch +- fix #188193- util-linux should provide plugin infrastructure for HAL + +* Mon Aug 21 2006 Karel Zak 2.13-0.40 +- fix Makefile.am in util-linux-2.13-mount-context.patch +- fix #201343 - pam_securetty requires known user to work + (split PAM login configuration to two files) +- fix #203358 - change location of taskset binary to allow for early affinity work + +* Fri Aug 11 2006 Karel Zak 2.13-0.39 +- fix #199745 - non-existant simpleinit(8) mentioned in ctrlaltdel(8) + +* Thu Aug 10 2006 Dan Walsh 2.13-0.38 +- Change keycreate line to happen after pam_selinux open call so it gets correct context + +* Thu Aug 10 2006 Karel Zak 2.13-0.37 +- fix #176494 - last -i returns strange IP addresses (patch by Bill Nottingham) + +* Thu Jul 27 2006 Karel Zak 2.13-0.36 +- fix #198300, #199557 - util-linux "post" scriptlet failure + +* Thu Jul 27 2006 Steve Dickson 2.13-0.35 +- Added the -o fsc flag to nfsmount. + +* Wed Jul 26 2006 Karel Zak 2.13-0.34 +- rebuild + +* Tue Jul 18 2006 Karel Zak 2.13-0.33 +- add Requires(post): libselinux + +* Mon Jul 17 2006 Karel Zak 2.13-0.32 +- add IPv6 support to the login command (patch by Milan Zazrivec) +- fix #198626 - add keyinit instructions to the login PAM script + (patch by David Howells) + +* Wed Jul 12 2006 Jesse Keating - 2.13-0.31.1 +- rebuild + +* Tue Jul 11 2006 Karel Zak 2.13-0.31 +- cleanup dependences for post and preun scriptlets + +* Mon Jul 10 2006 Karsten Hopp 2.13-0.30 +- silence install in minimal buildroot without /var/log + +* Fri Jul 7 2006 Karel Zak 2.13-0.29 +- include the raw command for RHELs + +* Mon Jun 26 2006 Florian La Roche 2.13-0.28 +- move install-info parts from postun to preun + +* Wed Jun 21 2006 Dan Walsh 2.13-0.27 +- Only execute chcon on machines with selinux enabled + +* Wed Jun 14 2006 Steve Dickson 2.13-0.26 +- Remove unneeded header files from nfsmount.c + +* Mon Jun 12 2006 Karel Zak 2.13-0.25 +- fix #187014 - umount segfaults for normal user +- fix #183446 - cal not UTF-8-aware +- fix #186915 - mount does not translate SELIinux context options though libselinux +- fix #185500 - Need man page entry for -o context= mount option +- fix #152579 - missing info about /etc/mtab and /proc/mounts mismatch +- fix #183890 - missing info about possible ioctl() and fcntl() problems on NFS filesystem +- fix #191230 - using mount --move results in wrong data in /etc/mtab +- added mount subtrees support +- fdisk: wrong number of sectors for large disks (suse#160822) +- merge fdisk-xvd (#182553) with new fdisk-isfull (#188981) patch +- fix #181549 - raw(8) manpage has old information about dd +- remove asm/page.h usage + +* Wed May 24 2006 Dan Walsh 2.13-0.24 +- Remove requirement on restorecon, since we can do the same thing +- with chcon/matchpathcon, and not add requirement on policycoreutils + +* Wed May 24 2006 Steve Dickson 2.13-0.23 +- Fixed bug in patch for bz183713 which cause nfs4 mounts to fail. + +* Tue May 2 2006 Steve Dickson 2.13-0.22 +- Added syslog logging to background mounts as suggested + by a customer. + +* Mon May 1 2006 Steve Dickson 2.13-0.21 +- fix #183713 - foreground mounts are not retrying as advertised +- fix #151549 - Added 'noacl' mount flag +- fix #169042 - Changed nfsmount to try udp before using tcp when rpc-ing + the remote rpc.mountd (iff -o tcp is not specified). + This drastically increases the total number of tcp mounts + that can happen at once (ala autofs). + +* Wed Mar 9 2006 Jesse Keating 2.13-0.20 +- Better calling of restorecon as suggested by Bill Nottingham +- prereq restorecon to avoid ordering issues + +* Wed Mar 9 2006 Jesse Keating 2.13-0.19 +- restorecon /var/log/lastlog + +* Wed Mar 8 2006 Karel Zak 2.13-0.17 +- fix #181782 - mkswap selinux relabeling (fix util-linux-2.13-mkswap-selinux.patch) + +* Wed Feb 22 2006 Karel Zak 2.13-0.16 +- fix #181782 - mkswap should automatically add selinux label to swapfile +- fix #180730 - col is exiting with 1 (fix util-linux-2.12p-col-EILSEQ.patch) +- fix #181896 - broken example in schedutils man pages +- fix #177331 - login omits pam_acct_mgmt & pam_chauthtok when authentication is skipped. +- fix #177523 - umount -a should not unmount sysfs +- fix #182553 - fdisk -l inside xen guest shows no disks + +* Fri Feb 10 2006 Jesse Keating - 2.13-0.15.1 +- bump again for double-long bug on ppc(64) + +* Wed Feb 8 2006 Peter Jones 2.13-0.15 +- add "blockdev --rmpart N " and "blockdev --rmparts " + +* Tue Feb 07 2006 Jesse Keating - 2.13-0.14.1 +- rebuilt for new gcc4.1 snapshot and glibc changes + +* Thu Jan 19 2006 Steve Dickson 2.13-0.14 +- Updated the gssd_check() and idmapd_check(), used with + nfsv4 mounts, to looked for the correct file in /var/lock/subsys + which stops bogus warnings. + +* Tue Jan 3 2006 Karel Zak 2.13-0.13 +- fix #174676 - hwclock audit return code mismatch +- fix #176441: col truncates data +- fix #174111 - mount allows loopback devices to be mounted more than once to the same mount point +- better wide chars usage in the cal command (based on the old 'moremisc' patch) + +* Mon Dec 12 2005 Karel Zak 2.13-0.12 +- rebuilt + +* Fri Dec 09 2005 Jesse Keating +- rebuilt + +* Fri Nov 25 2005 Karel Zak 2.13-0.11.pre6 +- update to upstream version 2.13-pre6 +- fix #172203 - mount man page in RHEL4 lacks any info on cifs mount options + +* Mon Nov 7 2005 Karel Zak 2.13-0.10.pre5 +- fix #171337 - mkfs.cramfs doesn't work correctly with empty files + +* Fri Oct 28 2005 Karel Zak 2.13-0.9.pre5 +- rebuild + +* Wed Oct 26 2005 Karel Zak 2.13-0.8.pre5 +- updated version of the patch for hwclock audit + +* Thu Oct 20 2005 Karel Zak 2.13-0.7.pre5 +- fix #171337 - mkfs.cramfs dies creating installer image + +* Thu Oct 20 2005 Karel Zak 2.13-0.6.pre5 +- update to upstream 2.13pre5 +- remove separated cramfs1.1 (already in upstream package) +- remove odd symlink /usr/bin/mkcramfs -> ../../sbin/mkfs.cramfs +- fix #170171 - ipcs -lm always report "max total shared memory (kbytes) = 0" + +* Mon Oct 17 2005 Karel Zak 2.13-0.5.pre4 +* fix #170564 - add audit message to login + +* Fri Oct 7 2005 Karel Zak 2.13-0.4.pre4 +- fix #169628 - /usr/bin/floppy doesn't work with /dev/fd0 +- fix #168436 - login will attempt to run if it has no read/write access to its terminal +- fix #168434 - login's timeout can fail - needs to call siginterrupt(SIGALRM,1) +- fix #165253 - losetup missing option -a [new feature] +- update PAM files (replace pam_stack with new "include" PAM directive) +- remove kbdrate from src.rpm +- update to 2.13pre4 + +* Fri Oct 7 2005 Steve Dickson 2.13-0.3.pre3 +- fix #170110 - Documentation for 'rsize' and 'wsize' NFS mount options + is misleading + +* Fri Sep 2 2005 Karel Zak 2.13-0.3.pre2 +- fix #166923 - hwclock will not run on a non audit-enabled kernel +- fix #159410 - mkswap(8) claims max swap area size is 2 GB +- fix #165863 - swsusp swaps should be reinitialized +- change /var/log/lastlog perms to 0644 + +* Tue Aug 16 2005 Karel Zak 2.13-0.2.pre2 +- /usr/share/misc/getopt/* -move-> /usr/share/doc/util-linux-2.13/getopt-* +- the arch command marked as deprecated +- removed: elvtune, rescuept and setfdprm +- removed: man8/sln.8 (moved to man-pages, see #10601) +- removed REDAME.pg and README.reset +- .spec file cleanup +- added schedutils (commands: chrt, ionice and taskset) + +* Tue Jul 12 2005 Karel Zak 2.12p-9.7 +- fix #159339 - util-linux updates for new audit system +- fix #158737 - sfdisk warning for large partitions, gpt +- fix #150912 - Add ocfs2 support +- NULL is better than zero at end of execl() + +* Thu Jun 16 2005 Karel Zak 2.12p-9.5 +- fix #157656 - CRM 546998: Possible bug in vipw, changes permissions of /etc/shadow and /etc/gshadow +- fix #159339 - util-linux updates for new audit system (pam_loginuid.so added to util-linux-selinux.pamd) +- fix #159418 - sfdisk unusable - crashes immediately on invocation +- fix #157674 - sync option on VFAT mount destroys flash drives +- fix .spec file /usr/sbin/{hwclock,clock} symlinks + +* Wed May 4 2005 Jeremy Katz - 2.12p-9.3 +- rebuild against new libe2fsprogs (and libblkid) to fix cramfs auto-detection + +* Mon May 2 2005 Karel Zak 2.12p-9.2 +- rebuild + +* Mon May 2 2005 Karel Zak 2.12p-9 +- fix #156597 - look - doesn't work with separators + +* Mon Apr 25 2005 Karel Zak 2.12p-8 +- fix #154498 - util-linux login & pam session +- fix #155293 - man 5 nfs should include vers as a mount option +- fix #76467 - At boot time, fsck chokes on LVs listed by label in fstab +- new Source URL +- added note about ATAPI IDE floppy to fdformat.8 +- fix #145355 - Man pages for fstab and fstab-sync in conflict + +* Tue Apr 5 2005 Karel Zak 2.12p-7 +- enable build with libblkid from e2fsprogs-devel +- remove workaround for duplicated labels + +* Thu Mar 31 2005 Steve Dickson 2.12p-5 +- Fixed nfs mount to rollback correctly. + +* Fri Mar 25 2005 Karel Zak 2.12p-4 +- added /var/log/lastlog to util-linux (#151635) +- disabled 'newgrp' in util-linux (enabled in shadow-utils) (#149997, #151613) +- improved mtab lock (#143118) +- fixed ipcs typo (#151156) +- implemented mount workaround for duplicated labels (#116300) + +* Wed Mar 16 2005 Elliot Lee 2.12p-3 +- rebuilt + +* Fri Feb 25 2005 Steve Dickson 2.12p-2 +- Changed nfsmount to only use reserve ports when necessary + (bz# 141773) + +* Thu Dec 23 2004 Elliot Lee 2.12p-1 +- Update to util-linux-2.12p. This changes swap header format + from - you may need to rerun mkswap if you did a clean install of + FC3. + +* Fri Dec 10 2004 Elliot Lee 2.12j-1 +- Update to util-linux-2.12j + +* Tue Dec 7 2004 Steve Dickson 2.12a-20 +- Corrected a buffer overflow problem with nfs mounts. + (bz# 141733) + +* Wed Dec 01 2004 Elliot Lee 2.12a-19 +- Patches for various bugs. + +* Mon Nov 29 2004 Steve Dickson 2.12a-18 +- Made NFS mounts adhere to the IP protocol if specified on + command line as well as made NFS umounts adhere to the + current IP protocol. Fix #140016 + +* Thu Oct 14 2004 Elliot Lee 2.12a-16 +- Add include_raw macro, build with it off for Fedora + +* Wed Oct 13 2004 Stephen C. Tweedie - 2.12a-15 +- Add raw patch to allow binding of devices not yet in /dev + +* Wed Oct 13 2004 John (J5) Palmieri 2.12a-14 +- Add David Zeuthen's patch to enable the pamconsole flag #133941 + +* Wed Oct 13 2004 Stephen C. Tweedie 2.12a-13 +- Restore raw utils (bugzilla #130016) + +* Mon Oct 11 2004 Phil Knirsch 2.12a-12 +- Add the missing remote entry in pam.d + +* Wed Oct 6 2004 Steve Dickson +- Rechecked in some missing NFS mounting code. + +* Wed Sep 29 2004 Elliot Lee 2.12a-10 +- Make swaplabel support work with swapon -a -e + +* Tue Sep 28 2004 Steve Dickson +- Updated the NFS and NFS4 code to the latest CITI patch set + (in which they incorporate a number of our local patches). + +* Wed Sep 15 2004 Nalin Dahybhai 2.12a-8 +- Fix #132196 - turn on SELinux support at build-time. + +* Wed Sep 15 2004 Phil Knirsch 2.12a-7 +- Fix #91174 with pamstart.patch + +* Tue Aug 31 2004 Elliot Lee 2.12a-6 +- Fix #16415, #70616 with rdevman.patch +- Fix #102566 with loginman.patch +- Fix #104321 with rescuept.patch (just use plain lseek - we're in _FILE_OFFSET_BITS=64 land now) +- Fix #130016 - remove raw. +- Re-add agetty (replacing it with mgetty is too much pain, and mgetty is much larger) + +* Thu Aug 26 2004 Steve Dickson +- Made the NFS security checks more explicit to avoid confusion + (an upstream fix) +- Also removed a compilation warning + +* Wed Aug 11 2004 Alasdair Kergon +- Remove unused mount libdevmapper inclusion. + +* Wed Aug 11 2004 Alasdair Kergon +- Add device-mapper mount-by-label support +- Fix segfault in mount-by-label when a device without a label is present. + +* Wed Aug 11 2004 Steve Dickson +- Updated nfs man page to show that intr are on by + default for nfs4 + +* Thu Aug 05 2004 Jindrich Novy +- modified warning causing heart attack for >16 partitions, #107824 + +* Fri Jul 09 2004 Elliot Lee 2.12a-3 +- Fix #126623, #126572 +- Patch cleanup +- Remove agetty (use mgetty, agetty is broken) + +* Tue Jun 15 2004 Elliot Lee +- rebuilt + +* Thu Jun 03 2004 Elliot Lee 2.12a-1 +- Update to 2.12a +- Fix #122448 + +* Thu May 13 2004 Dan Walsh 2.12-19 +- Change pam_selinux to run last + +* Tue May 04 2004 Elliot Lee 2.12-18 +- Fix #122448 (autofs issues) + +* Fri Apr 23 2004 Elliot Lee 2.12-17 +- Fix #119157 by editing the patch +- Add patch145 to fix #119986 + +* Fri Apr 16 2004 Elliot Lee 2.12-16 +- Fix #118803 + +* Tue Mar 23 2004 Jeremy Katz 2.12-15 +- mkcramfs: use PAGE_SIZE for default blocksize (#118681) + +* Sat Mar 20 2004 +- Updated the nfs-mount.patch to correctly + handle the mounthost option and to ignore + servers that do not set auth flavors + +* Tue Mar 16 2004 Dan Walsh 2.12-13 +- Fix selinux ordering or pam for login + +* Tue Mar 16 2004 +- Make RPC error messages displayed with -v argument +- Added two checks to the nfs4 path what will print warnings + when rpc.idmapd and rpc.gssd are not running +- Ping NFS v4 servers before diving into kernel +- Make v4 mount interruptible which also make the intr option on by default + +* Sun Mar 13 2004 +- Reworked how the rpc.idmapd and rpc.gssd checks were + done due to review comments from upstream. +- Added rpc_strerror() so the '-v' flag will show RPC errors. + +* Sat Mar 13 2004 +- Added two checks to the nfs4 path what will print warnings + when rpc.idmapd and rpc.gssd are not running. + +* Thu Mar 11 2004 +- Reworked and updated the nfsv4 patches. + +* Wed Mar 10 2004 Dan Walsh +- Bump version + +* Wed Mar 10 2004 Steve Dickson +- Tried to make nfs error message a bit more meaninful +- Cleaned up some warnings + +* Sun Mar 7 2004 Steve Dickson +- Added pesudo flavors for nfsv4 mounts. +- Added BuildRequires: libselinux-devel and Requires: libselinux + when WITH_SELINUX is set. + +* Fri Feb 27 2004 Dan Walsh 2.12-5 +- check for 2.6.3 kernel in mount options + +* Mon Feb 23 2004 Elliot Lee 2.12-4 +- Remove /bin/kill for #116100 + +* Fri Feb 20 2004 Dan Walsh 2.12-3 +- rebuilt + +* Fri Feb 13 2004 Elliot Lee +- rebuilt + +* Thu Feb 12 2004 Elliot Lee 2.12-1 +- Final 2.12 has been out for ages - might as well use it. + +* Wed Jan 28 2004 Steve Dickson 2.12pre-4 +- Added mount patches that have NFS version 4 support + +* Mon Jan 26 2004 Elliot Lee 2.12pre-3 +- Provides: mount losetup + +* Mon Jan 26 2004 Dan Walsh 2.12pre-2 +- Add multiple to /etc/pam.d/login for SELinux + +* Thu Jan 15 2004 Elliot Lee 2.12pre-1 +- 2.12pre-1 +- Merge mount/losetup packages into the main package (#112324) +- Lose separate + +* Mon Nov 3 2003 Dan Walsh 2.11y-35.sel +- remove selinux code from login and use pam_selinux + +* Thu Oct 30 2003 Dan Walsh 2.11y-34.sel +- turn on selinux + +* Fri Oct 24 2003 Elliot Lee 2.11y-34 +- Add BuildRequires: texinfo (from a bug# I don't remember) +- Fix #90588 with mountman patch142. + +* Mon Oct 6 2003 Dan Walsh 2.11y-33 +- turn off selinux + +* Thu Sep 25 2003 Dan Walsh 2.11y-32.sel +- turn on selinux +- remove context selection + +* Fri Sep 19 2003 Elliot Lee 2.11y-31 +- Add patch140 (alldevs) to fix #101772. Printing the total size of + all devices was deemed a lower priority than having all devices + (e.g. /dev/ida/c0d9) displayed. + +* Fri Sep 12 2003 Dan Walsh 2.11y-31 +- turn off selinux + +* Fri Sep 12 2003 Dan Walsh 2.11y-30.sel +- turn on selinux + +* Fri Sep 5 2003 Elliot Lee 2.11y-28 +- Fix #103004, #103954 + +* Fri Sep 5 2003 Dan Walsh 2.11y-27 +- turn off selinux + +* Thu Sep 4 2003 Dan Walsh 2.11y-26.sel +- build with selinux + +* Mon Aug 11 2003 Elliot Lee 2.11y-25 +- Use urandom instead for mkcramfs + +* Tue Jul 29 2003 Dan Walsh 2.11y-24 +- add SELINUX 2.5 support + +* Wed Jul 23 2003 Elliot Lee 2.11y-22 +- #100433 patch + +* Mon Jun 14 2003 Elliot Lee 2.11y-20 +- #97381 patch + +* Wed Jun 04 2003 Elliot Lee +- rebuilt + +* Mon Apr 21 2003 Elliot Lee 2.11y-17 +- Change patch128 to improve ipcs -l + +* Fri Apr 11 2003 Elliot Lee 2.11y-16 +- Fix #85407 + +* Fri Apr 11 2003 Elliot Lee 2.11y-15 +- Change patch128 to util-linux-2.11f-ipcs-84243-86285.patch to get all +ipcs fixes + +* Thu Apr 10 2003 Matt Wilson 2.11y-14 +- fix last login date display on AMD64 (#88574) + +* Mon Apr 7 2003 Jeremy Katz 2.11y-13 +- include sfdisk on ppc + +* Fri Mar 28 2003 Jeremy Katz 2.11y-12 +- add patch from msw to change mkcramfs blocksize with a command line option + +* Tue Mar 25 2003 Phil Knirsch 2.11y-11 +- Fix segfault on s390x due to wrong usage of BLKGETSIZE. + +* Thu Mar 13 2003 Elliot Lee 2.11y-10 +- Really apply the ipcs patch. Doh. + +* Mon Feb 24 2003 Elliot Lee +- rebuilt + +* Wed Feb 19 2003 Elliot Lee 2.11y-8 +- ipcs-84243.patch to fix #84243 + +* Thu Feb 13 2003 Yukihiro Nakai 2.11y-7 +- Update moremisc patch to fix swprintf()'s minimum field (bug #83361). + +* Mon Feb 03 2003 Elliot Lee 2.11y-6 +- Fix mcookie segfault on many 64-bit architectures (bug #83345). + +* Mon Feb 03 2003 Tim Waugh 2.11y-5 +- Fix underlined multibyte characters (bug #83376). + +* Sun Feb 02 2003 Florian La Roche +- rebuild to have again a s390 rpm +- disable some more apps for mainframe + +* Wed Jan 29 2003 Elliot Lee 2.11y-4 +- util-linux-2.11y-umask-82552.patch + +* Wed Jan 22 2003 Tim Powers +- rebuilt + +* Mon Jan 13 2003 Elliot Lee 2.11y-2 +- Fix #81069, #75421 + +* Mon Jan 13 2003 Elliot Lee 2.11y-1 +- Update to 2.11y +- Fix #80953 +- Update patch0, patch107, patch117, patch120 for 2.11y +- Remove patch60, patch61, patch207, patch211, patch212, patch119, patch121 +- Remove patch122, patch200 + +* Wed Oct 30 2002 Elliot Lee 2.11w-2 +- Remove some crack/unnecessary patches while submitting stuff upstream. +- Build with -D_FILE_OFFSET_BITS=64 + +* Tue Oct 29 2002 Elliot Lee 2.11w-1 +- Update to 2.11w, resolve patch conflicts + +* Tue Oct 08 2002 Phil Knirsch 2.11r-10hammer.3 +- Extended util-linux-2.11b-s390x patch to work again. + +* Thu Oct 03 2002 Elliot Lee 2.11r-10hammer.2 +- Add patch122 for hwclock on x86_64 + +* Thu Sep 12 2002 Than Ngo 2.11r-10hammer.1 +- Fixed pam config files + +* Wed Sep 11 2002 Bernhard Rosenkraenzer 2.11r-10hammer +- Port to hammer + +* Fri Aug 30 2002 Elliot Lee 2.11r-10 +- Patch120 (hwclock) to fix #72140 +- Include isosize util + +* Wed Aug 7 2002 Elliot Lee 2.11r-9 +- Patch120 (skipraid2) to fix #70353, because the original patch was +totally useless. + +* Fri Aug 2 2002 Elliot Lee 2.11r-8 +- Patch119 (fdisk-add-primary) from #67898 + +* Wed Jul 24 2002 Elliot Lee 2.11r-7 +- Really add the gptsize patch, instead of what I think the patch says. +(+1) + +* Tue Jul 23 2002 Elliot Lee 2.11r-6 +- Add the sp[n].size part of the patch from #69603 + +* Mon Jul 22 2002 Florian La Roche +- adjust mainframe patches + +* Tue Jul 2 2002 Bill Nottingham 2.11r-4 +- only require usermode if we're shipping kbdrate here + +* Fri Jun 28 2002 Trond Eivind Glomsrod 2.11r-3 +- Port the large swap patch to new util-linux... the off_t changes + now in main aren't sufficient + +* Thu Jun 27 2002 Elliot Lee 2.11r-2 +- Remove swapondetect (patch301) until it avoids possible false positives. + +* Thu Jun 27 2002 Elliot Lee 2.11r-1 +- Update to 2.11r, wheeee +- Remove unused patches + +* Thu Jun 27 2002 Elliot Lee 2.11n-19 +- Make a note here that this package was the source of the single change +contained in util-linux-2.11f-18 (in 7.2/Alpha), and also contains the +rawman patch from util-linux-2.11f-17.1 (in 2.1AS). +- Package has no runtime deps on slang, so remove the BuildRequires: +slang-devel. + +* Fri Jun 21 2002 Tim Powers +- automated rebuild + +* Thu Jun 20 2002 Elliot Lee 2.11n-17 +- Fix teg's swapondetect patch to not print out the usage message when +'swapon -a -e' is run. (#66690) (edit existing patch) +- Apply hjl's utmp handling patch (#66950) (patch116) +- Fix fdisk man page notes on IDE disk partition limit (#64013) (patch117) +- Fix mount.8 man page notes on vfat shortname option (#65628) (patch117) +- Fix possible cal overflow with widechars (#67090) (patch117) + +* Tue Jun 11 2002 Trond Eivind Glomsrod 2.11n-16 +- support large swap partitions +- add '-d' option to autodetect available swap partitions + +* Thu May 23 2002 Tim Powers +- automated rebuild + +* Wed May 15 2002 Elliot Lee 2.11n-14 +- Remove kbdrate (again). + +* Mon Apr 29 2002 Florian La Roche +- adjust mainframe patches to apply to current rpm +- do not include fdisk until it is fixed to work on mainframe + +* Mon Apr 01 2002 Elliot Lee 2.11n-12 +- Don't strip binaries - rpm does it for us. + +* Sun Mar 31 2002 Elliot Lee 2.11n-11 +- Apply patch115 from ejb@ql.org for bug #61868 + +* Wed Mar 27 2002 Elliot Lee 2.11n-10 +- Finish fixing #60675 (ipcrm man page), updated the patch. +- Fix #61203 (patch114 - dumboctal.patch). + +* Tue Mar 12 2002 Elliot Lee 2.11n-9 +- Update ctty3 patch to ignore SIGHUP while dropping controlling terminal + +* Fri Mar 08 2002 Elliot Lee 2.11n-8 +- Update ctty3 patch to drop controlling terminal before forking. + +* Fri Mar 08 2002 Elliot Lee 2.11n-7 + Fix various bugs: +- Add patch110 (skipraid) to properly skip devices that are part of a RAID array. +- Add patch111 (mkfsman) to update the mkfs man page's "SEE ALSO" section. +- remove README.cfdisk +- Include partx +- Fix 54741 and related bugs for good(hah!) with patch113 (ctty3) + +* Wed Mar 06 2002 Elliot Lee 2.11n-6 +- Put kbdrate in, add usermode dep. + +* Tue Feb 26 2002 Elliot Lee 2.11n-5 +- Fix #60363 (tweak raw.8 man page, make rawdevices.8 symlink). + +* Tue Jan 28 2002 Bill Nottingham 2.11n-4 +- remove kbdrate (fixes kbd conflict) + +* Fri Dec 28 2001 Elliot Lee 2.11n-3 +- Add util-linux-2.11n-ownerumount.patch (#56593) +- Add patch102 (util-linux-2.11n-colrm.patch) to fix #51887 +- Fix #53452 nits. +- Fix #56953 (remove tunelp on s390) +- Fix #56459, and in addition switch to using sed instead of perl. +- Fix #58471 +- Fix #57300 +- Fix #37436 +- Fix #32132 + +* Wed Dec 26 2001 Elliot Lee 2.11n-1 +- Update to 2.11n +- Merge mount/losetup back in. + +* Tue Dec 04 2001 Elliot Lee 2.11f-17 +- Add patch38 (util-linux-2.11f-ctty2.patch) to ignore SIGINT/SIGTERM/SIGQUIT in the parent, so that ^\ won't break things. + +* Fri Nov 09 2001 Elliot Lee 2.11f-16 +- Merge patches 36, 75, 76, and 77 into patch #37, to attempt resolve all the remaining issues with #54741. + +* Wed Oct 24 2001 Florian La Roche +- add nologin man-page for s390/s390x + +* Wed Oct 24 2001 Bernhard Rosenkraenzer 2.11f-14 +- Don't build kbdrate on s390/s390x +- Don't make the pivot_root.8 man page executable(!) + +* Tue Oct 23 2001 Elliot Lee 2.11f-13 +- Patch/idea #76 from HJL, fixes bug #54741 (race condition in login +acquisition of controlling terminal). + +* Thu Oct 11 2001 Bill Nottingham +- fix permissions problem with vipw & shadow files, again (doh!) + +* Tue Oct 09 2001 Erik Troan +- added patch from Olaf Kirch to fix possible pwent structure overwriting + +* Fri Sep 28 2001 Elliot Lee 2.11f-10 +- fdisk patch from arjan + +* Sun Aug 26 2001 Elliot Lee 2.11f-9 +- Don't include cfdisk, since it appears to be an even bigger pile of junk than fdisk? :) + +* Wed Aug 1 2001 Tim Powers +- don't require usermode + +* Mon Jul 30 2001 Elliot Lee 2.11f-7 +- Incorporate kbdrate back in. + +* Mon Jul 30 2001 Bill Nottingham +- revert the patch that calls setsid() in login that we had reverted + locally but got integrated upstream (#46223) + +* Tue Jul 24 2001 Florian La Roche +- correct s390x patch + +* Mon Jul 23 2001 Elliot Lee +- Add my megapatch (various bugs) +- Include pivot_root (#44828) + +* Thu Jul 12 2001 Bill Nottingham +- make shadow files 0400, not 0600 + +* Wed Jul 11 2001 Bill Nottingham +- fix permissions problem with vipw & shadow files + +* Mon Jun 18 2001 Florian La Roche +- update to 2.11f, remove any merged patches +- add s390x patches for somewhat larger swap + +* Thu Jun 14 2001 Erik Troan +- added --verbose patch to mkcramfs; it's much quieter by default now + +* Tue May 22 2001 Erik Troan +- removed warning about starting partitions on cylinder 0 -- swap version2 + makes it unnecessary + +* Wed May 9 2001 Bernhard Rosenkraenzer 2.11b-2 +- Fix up s390x support + +* Mon May 7 2001 Bernhard Rosenkraenzer 2.11b-1 +- Fix up login for real (a console session should be the controlling tty) + by reverting to 2.10s code (#36839, #36840, #39237) +- Add man page for agetty (#39287) +- 2.11b, while at it + +* Fri Apr 27 2001 Preston Brown 2.11a-4 +- /sbin/nologin from OpenBSD added. + +* Fri Apr 20 2001 Bernhard Rosenkraenzer 2.11a-3 +- Fix up login - exiting immediately even if the password is correct + is not exactly a nice feature. +- Make definite plans to kill people who update login without checking + if the new version works ;) + +* Tue Apr 17 2001 Erik Troan +- upgraded to 2.11a (kbdrate moved to kbd, among other things) +- turned off ALLOW_VCS_USE +- modified mkcramfs to not use a large number of file descriptors +- include mkfs.bfs + +* Sun Apr 8 2001 Matt Wilson +- changed Requires: kernel >= 2.2.12-7 to Conflicts: kernel < 2.2.12-7 + (fixes a initscripts -> util-linux -> kernel -> initscripts prereq loop) + +* Tue Mar 20 2001 Matt Wilson +- patched mkcramfs to use the PAGE_SIZE from asm/page.h instead of hard + coding 4096 (fixes mkcramfs on alpha...) + +* Mon Mar 19 2001 Matt Wilson +- added mkcramfs (from linux/scripts/mkcramfs) + +* Mon Feb 26 2001 Tim Powers +- fixed bug #29131, where ipc.info didn't have an info dir entry, + added the dir entry to ipc.texi (Patch58) + +* Fri Feb 23 2001 Preston Brown +- use lang finder script +- install info files + +* Thu Feb 08 2001 Erik Troan +- reverted login patch; seems to cause problems +- added agetty + +* Wed Feb 07 2001 Erik Troan +- updated kill man page +- added patch to fix vipw race +- updated vipw to edit /etc/shadow and /etc/gshadow, if appropriate +- added patch to disassociate login from tty, session, and pgrp + +* Tue Feb 06 2001 Erik Troan +- fixed problem w/ empty extended partitions +- added patch to fix the date in the more man page +- set OPT to pass optimization flags to make rather then RPM_OPT_FLAG +- fixed fdisk -l /Proc/partitions parsing +- updated to 2.10s + +* Tue Jan 23 2001 Preston Brown +- danish translations added + +* Mon Jan 15 2001 Nalin Dahyabhai +- fix segfault in login in btmp patch (#24025) + +* Mon Dec 11 2000 Oliver Paukstadt +- ported to s390 + +* Wed Nov 01 2000 Florian La Roche +- update to 2.10p +- update patch37 to newer fdisk version + +* Mon Oct 9 2000 Jeff Johnson +- update to 2.10o +- fdformat: fixed to work with kernel 2.4.0test6 (Marek Wojtowicz) +- login: not installed suid +- getopt: by default install aux files in /usr/share/misc +- update to 2.10n: +- added blockdev.8 +- change to elvtune (andrea) +- fixed overrun in agetty (vii@penguinpowered.com) +- shutdown: prefer umounting by mount point (rgooch) +- fdisk: added plan9 +- fdisk: remove empty links in chain of extended partitions +- hwclock: handle both /dev/rtc and /dev/efirtc (Bill Nottingham) +- script: added -f (flush) option (Ivan Schreter) +- script: added -q (quiet) option (Per Andreas Buer) +- getopt: updated to version 1.1.0 (Frodo Looijaard) +- Czech messages (Jiri Pavlovsky) +- login.1 man page had not /var/spool/mail path (#16998). +- sln.8 man page (but not executable) included (#10601). +- teach fdisk 0xde(Dell), 0xee(EFI GPT), 0xef(EFI FAT) partitions (#17610). + +* Wed Aug 30 2000 Matt Wilson +- rebuild to cope with glibc locale binary incompatibility, again + +* Mon Aug 14 2000 Jeff Johnson +- setfdprm should open with O_WRONLY, not 3. + +* Fri Aug 11 2000 Jeff Johnson +- fdformat should open with O_WRONLY, not 3. + +* Fri Jul 21 2000 Nalin Dahyabhai +- make 'look' look in /usr/share/dict + +* Fri Jul 21 2000 Bill Nottingham +- put /usr/local/sbin:/usr/local/bin in root's path + +* Wed Jul 19 2000 Jakub Jelinek +- rebuild to cope with glibc locale binary incompatibility + +* Thu Jul 13 2000 Prospector +- automatic rebuild + +* Mon Jul 10 2000 Bill Nottingham +- enable hwclock to use /dev/efirtc on ia64 (gettext is fun. :( ) + +* Mon Jul 3 2000 Bill Nottingham +- move cfdisk to /usr/sbin, it depends on /usr stuff +- add rescuept + +* Fri Jun 23 2000 Bernhard Rosenkraenzer +- point more at the correct path to vi (for "v"), Bug #10882 + +* Sun Jun 4 2000 Jeff Johnson +- FHS packaging changes. + +* Thu Jun 1 2000 Nalin Dahyabhai +- modify PAM setup to use system-auth + +* Mon May 1 2000 Bill Nottingham +- eek, where did login go? (specfile tweaks) + +* Mon Apr 17 2000 Bernhard Rosenkraenzer +- 2.10k +- fix compilation with current glibc + +* Tue Mar 21 2000 Bernhard Rosenkraenzer +- 2.10h + +* Tue Mar 7 2000 Jeff Johnson +- rebuild for sparc baud rates > 38400. + +* Sat Mar 4 2000 Matt Wilson +- use snprintf - not sprintf - when doing + sprintf ("%%s\n", _("Some string")) to avoid overflows and + segfaults. + +* Mon Feb 21 2000 Jeff Johnson +- raw control file was /dev/raw, now /dev/rawctl. +- raw access files were /dev/raw*, now /dev/raw/raw*. + +* Thu Feb 17 2000 Erik Troan +- -v argument to mkswap wasn't working + +* Thu Feb 10 2000 Jakub Jelinek +- Recognize 0xfd on Sun disklabels as RAID + +* Tue Feb 8 2000 Bill Nottingham +- more lives in /bin, and was linked against /usr/lib/libnurses. Bad. + +* Thu Feb 03 2000 Jakub Jelinek +- update to 2.10f +- fix issues in the new realpath code, avoid leaking memory + +* Tue Feb 01 2000 Cristian Gafton +- rebuild to fix dependencies +- add NFSv3 patches + +* Fri Jan 28 2000 Bill Nottingham +- don't require csh + +* Mon Jan 24 2000 Nalin Dahyabhai +- update to 2.10e +- add rename + +* Thu Jan 20 2000 Jeff Johnson +- strip newlines in logger input. + +* Mon Jan 10 2000 Jeff Johnson +- rebuild with correct ncurses libs. + +* Tue Dec 7 1999 Matt Wilson +- updated to util-linux 2.10c +- deprecated IMAP login mail notification patch17 +- deprecated raw patch22 +- depricated readprofile patch24 + +* Tue Dec 7 1999 Bill Nottingham +- add patch for readprofile + +* Thu Nov 18 1999 Michael K. Johnson +- tunelp should come from util-linux + +* Tue Nov 9 1999 Jakub Jelinek +- kbdrate cannot use /dev/port on sparc. + +* Wed Nov 3 1999 Jakub Jelinek +- fix kbdrate on sparc. + +* Wed Oct 27 1999 Bill Nottingham +- ship hwclock on alpha. + +* Tue Oct 5 1999 Bill Nottingham +- don't ship symlinks to rdev if we don't ship rdev. + +* Tue Sep 07 1999 Cristian Gafton +- add rawIO support from sct + +* Mon Aug 30 1999 Preston Brown +- don't display "new mail" message when the only piece of mail is from IMAP + +* Fri Aug 27 1999 Michael K. Johnson +- kbdrate is now a console program + +* Thu Aug 26 1999 Jeff Johnson +- hostid is now in sh-utils. On sparc, install hostid as sunhostid (#4581). +- update to 2.9w: +- Updated mount.8 (Yann Droneaud) +- Improved makefiles +- Fixed flaw in fdisk + +* Tue Aug 10 1999 Jeff Johnson +- tsort is now in textutils. + +* Wed Aug 4 1999 Bill Nottingham +- turn off setuid bit on login. Again. :( + +* Tue Aug 3 1999 Peter Jones, +- hostid script for sparc (#3803). + +* Tue Aug 03 1999 Christian 'Dr. Disk' Hechelmann +- added locale message catalogs to %%file +- added patch for non-root build +- vigr.8 and /usr/lib/getopt man-page was missing from file list +- /etc/fdprm really is a config file + +* Fri Jul 23 1999 Jeff Johnson +- update to 2.9v: +- cfdisk no longer believes the kernel's HDGETGEO + (and may be able to partition a 2 TB disk) + +* Fri Jul 16 1999 Jeff Johnson +- update to 2.9u: +- Czech more.help and messages (Jiri Pavlovsky) +- Japanese messages (Daisuke Yamashita) +- fdisk fix (Klaus G. Wagner) +- mount fix (Hirokazu Takahashi) +- agetty: enable hardware flow control (Thorsten Kranzkowski) +- minor cfdisk improvements +- fdisk no longer accepts a default device +- Makefile fix + +* Tue Jul 6 1999 Jeff Johnson +- update to 2.9t: +- national language support for hwclock +- Japanese messages (both by Daisuke Yamashita) +- German messages and some misc i18n fixes (Elrond) +- Czech messages (Jiri Pavlovsky) +- wall fixed for /dev/pts/xx ttys +- make last and wall use getutent() (Sascha Schumann) + [Maybe this is bad: last reading all of wtmp may be too slow. + Revert in case people complain.] +- documented UUID= and LABEL= in fstab.5 +- added some partition types +- swapon: warn only if verbose + +* Fri Jun 25 1999 Jeff Johnson +- update to 2.9s. + +* Sat May 29 1999 Jeff Johnson +- fix mkswap sets incorrect bits on sparc64 (#3140). + +* Thu Apr 15 1999 Jeff Johnson +- on sparc64 random ioctls on clock interface cause kernel messages. + +* Thu Apr 15 1999 Jeff Johnson +- improved raid patch (H.J. Lu). + +* Wed Apr 14 1999 Michael K. Johnson +- added patch for smartraid controllers + +* Sat Apr 10 1999 Cristian Gafton +- fix logging problems caused by setproctitle and PAM interaction + (#2045) + +* Wed Mar 31 1999 Jeff Johnson +- include docs and examples for sfdisk (#1164) + +* Mon Mar 29 1999 Matt Wilson +- rtc is not working properly on alpha, we can't use hwclock yet. + +* Fri Mar 26 1999 Cristian Gafton +- add patch to make mkswap more 64 bit friendly... Patch from + eranian@hpl.hp.com (ahem!) + +* Thu Mar 25 1999 Jeff Johnson +- include sfdisk (#1164) +- fix write (#1784) +- use positive logic in spec file (ifarch rather than ifnarch). +- (re)-use 1st matching utmp slot if search by mypid not found. +- update to 2.9o +- lastb wants bad logins in wtmp clone /var/run/btmp (#884) + +* Thu Mar 25 1999 Jakub Jelinek +- if hwclock is to be compiled on sparc, + it must actually work. Also, it should obsolete + clock, otherwise it clashes. +- limit the swap size in mkswap for 2.2.1+ kernels + by the actual maximum size kernel can handle. +- fix kbdrate on sparc, patch by J. S. Connell + + +* Wed Mar 24 1999 Matt Wilson +- added pam_console back into pam.d/login + +* Tue Mar 23 1999 Matt Wilson +- updated to 2.9i +- added hwclock for sparcs and alpha + +* Mon Mar 22 1999 Erik Troan +- added vigr to file list + +* Sun Mar 21 1999 Cristian Gafton +- auto rebuild in the new build environment (release 12) + +* Thu Mar 18 1999 Cristian Gafton +- remove most of the ifnarch arm stuff + +* Mon Mar 15 1999 Michael Johnson +- added pam_console.so to /etc/pam.d/login + +* Thu Feb 4 1999 Michael K. Johnson +- .perms patch to login to make it retain root in parent process + for pam_close_session to work correctly + +* Tue Jan 12 1999 Jeff Johnson +- strip fdisk in buildroot correctly (#718) + +* Mon Jan 11 1999 Cristian Gafton +- have fdisk compiled on sparc and arm + +* Mon Jan 11 1999 Erik Troan +- added beos partition type to fdisk + +* Wed Dec 30 1998 Cristian Gafton +- incorporate fdisk on all arches + +* Sat Dec 5 1998 Jeff Johnson +- restore PAM functionality at end of login (Bug #201) + +* Thu Dec 03 1998 Cristian Gafton +- patch top build on the arm without PAM and related utilities, for now. +- build hwclock only on intel + +* Wed Nov 18 1998 Cristian Gafton +- upgraded to version 2.9 + +* Thu Oct 29 1998 Bill Nottingham +- build for Raw Hide (slang-1.2.2) +- patch kbdrate wackiness so it builds with egcs + +* Tue Oct 13 1998 Erik Troan +- patched more to use termcap + +* Mon Oct 12 1998 Erik Troan +- added warning about alpha/bsd label starting cylinder + +* Mon Sep 21 1998 Erik Troan +- use sigsetjmp/siglongjmp in more rather then sig'less versions + +* Fri Sep 11 1998 Jeff Johnson +- explicit attrs for setuid/setgid programs + +* Thu Aug 27 1998 Cristian Gafton +- sln is now included in glibc + +* Sun Aug 23 1998 Jeff Johnson +- add cbm1581 floppy definitions (problem #787) + +* Mon Jun 29 1998 Jeff Johnson +- remove /etc/nologin at end of shutdown/halt. + +* Fri Jun 19 1998 Jeff Johnson +- add mount/losetup. + +* Thu Jun 18 1998 Jeff Johnson +- update to 2.8 with 2.8b clean up. hostid now defunct? + +* Mon Jun 01 1998 David S. Miller +- "more" now works properly on sparc + +* Sat May 02 1998 Jeff Johnson +- Fix "fdisk -l" fault on mounted cdrom. (prob #513) + +* Fri Apr 24 1998 Prospector System +- translations modified for de, fr, tr + +* Sat Apr 11 1998 Cristian Gafton +- manhattan rebuild + +* Mon Dec 29 1997 Erik Troan +- more didn't suspend properly on glibc +- use proper tc*() calls rather then ioctl's + +* Sun Dec 21 1997 Cristian Gafton +- fixed a security problem in chfn and chsh accepting too + long gecos fields + +* Fri Dec 19 1997 Mike Wangsmo +- removed "." from default path + +* Tue Dec 02 1997 Cristian Gafton +- added (again) the vipw patch + +* Wed Oct 22 1997 Michael Fulbright +- minor cleanups for glibc 2.1 + +* Fri Oct 17 1997 Michael Fulbright +- added vfat32 filesystem type to list recognized by fdisk + +* Fri Oct 10 1997 Erik Troan +- don't build clock on the alpha +- don't install chkdupexe + +* Thu Oct 02 1997 Michael K. Johnson +- Update to new pam standard. +- BuildRoot. + +* Thu Sep 25 1997 Cristian Gafton +- added rootok and setproctitle patches +- updated pam config files for chfn and chsh + +* Tue Sep 02 1997 Erik Troan +- updated MCONFIG to automatically determine the architecture +- added glibc header hacks to fdisk code +- rdev is only available on the intel + +* Fri Jul 18 1997 Erik Troan +- update to util-linux 2.7, fixed login problems + +* Wed Jun 25 1997 Erik Troan +- Merged Red Hat changes into main util-linux source, updated package to + development util-linux (nearly 2.7). + +* Tue Apr 22 1997 Michael K. Johnson +- LOG_AUTH --> LOG_AUTHPRIV in login and shutdown + +* Mon Mar 03 1997 Michael K. Johnson +- Moved to new pam and from pam.conf to pam.d + +* Tue Feb 25 1997 Michael K. Johnson +- pam.patch differentiated between different kinds of bad logins. + In particular, "user does not exist" and "bad password" were treated + differently. This was a minor security hole.