Util-Linux package development
 help / color / mirror / Atom feed
* Re: [PATCH 0/3] Consistent shell resolution across util-linux
From: Alessandro Ratti @ 2025-11-26 12:40 UTC (permalink / raw)
  To: Karel Zak; +Cc: util-linux, thomas, Alessandro Ratti
In-Reply-To: <wrmeywniicltshcczypjo7or6hnds7wkkgaaiizbsvvzkwaab6@minsmj74e6wm>

On Wed, 26 Nov 2025 at 12:51, Karel Zak <kzak@redhat.com> wrote:
>
>
>  Hi Alessandro,
>
>  thanks!
>
> On Sun, Nov 23, 2025 at 04:32:43PM +0100, Alessandro Ratti wrote:
> > This patch series addresses inconsistent default shell handling across
> > util-linux tools, which caused user-reported data loss when script(1)
> > defaulted to /bin/sh without respecting the user's configured shell.
> >
> > The series:
> > 1. Introduces ul_default_shell() for consistent shell resolution
> > 2. Updates interactive tools to use the new function
> > 3. Standardizes _PATH_BSHELL usage in security-sensitive tools
> >
> > This implements the solution discussed in:
> > https://github.com/util-linux/util-linux/issues/3865
>
> How about creating a pull request on GitHub? It will help us with the
> review, etc.

Thanks. I opened a PR on GitHub [1] as you suggested.
I’d be grateful for any feedback or pointers on the review.

Thank you for your time and consideration.

Best regards
Alessandro

[1]: https://github.com/util-linux/util-linux/pull/3876

^ permalink raw reply

* Re: [PATCH 0/3] Consistent shell resolution across util-linux
From: Karel Zak @ 2025-11-26 11:51 UTC (permalink / raw)
  To: Alessandro Ratti; +Cc: util-linux, thomas
In-Reply-To: <20251123153246.1056874-1-alessandro@0x65c.net>


 Hi Alessandro,

 thanks!

On Sun, Nov 23, 2025 at 04:32:43PM +0100, Alessandro Ratti wrote:
> This patch series addresses inconsistent default shell handling across
> util-linux tools, which caused user-reported data loss when script(1)
> defaulted to /bin/sh without respecting the user's configured shell.
> 
> The series:
> 1. Introduces ul_default_shell() for consistent shell resolution
> 2. Updates interactive tools to use the new function
> 3. Standardizes _PATH_BSHELL usage in security-sensitive tools
> 
> This implements the solution discussed in:
> https://github.com/util-linux/util-linux/issues/3865

How about creating a pull request on GitHub? It will help us with the
review, etc.

(I can do it if, for some reason, you don't want to use GitHub, but
it's always better if the author does it themselves.)

    Karel

-- 
 Karel Zak  <kzak@redhat.com>
 http://karelzak.blogspot.com


^ permalink raw reply

* [PATCH 3/3] login-utils, sys-utils: use _PATH_BSHELL consistently
From: Alessandro Ratti @ 2025-11-23 15:32 UTC (permalink / raw)
  To: util-linux; +Cc: kzak, thomas, Alessandro Ratti
In-Reply-To: <20251123153246.1056874-1-alessandro@0x65c.net>

Remove local DEFAULT_SHELL definitions and hardcoded "/bin/sh" strings
in favor of the standard _PATH_BSHELL macro from <paths.h>. This
provides consistency across the codebase while following libc
conventions.

These tools already perform their own passwd lookups and only need a
fallback value, so they don't require the full ul_default_shell()
resolution logic.

Affected tools:
- su(1): already checks pw_shell validity
- sulogin(8): emergency login with explicit shell handling
- setpriv(1): already has passwd entry for environment setup

Signed-off-by: Alessandro Ratti <alessandro@0x65c.net>
---
 login-utils/su-common.c | 5 +----
 login-utils/sulogin.c   | 9 +++++----
 sys-utils/setpriv.c     | 6 ++----
 3 files changed, 8 insertions(+), 12 deletions(-)

diff --git a/login-utils/su-common.c b/login-utils/su-common.c
index 4d54eab31..c6232ce7a 100644
--- a/login-utils/su-common.c
+++ b/login-utils/su-common.c
@@ -105,9 +105,6 @@ UL_DEBUG_DEFINE_MASKNAMES(su) = UL_DEBUG_EMPTY_MASKNAMES;
 
 #define is_pam_failure(_rc)	((_rc) != PAM_SUCCESS)
 
-/* The shell to run if none is given in the user's passwd entry.  */
-#define DEFAULT_SHELL "/bin/sh"
-
 /* The user to become if none is specified.  */
 #define DEFAULT_USER "root"
 
@@ -1167,7 +1164,7 @@ int su_main(int argc, char **argv, int mode)
 	su->old_user = xgetlogin();
 
 	if (!su->pwd->pw_shell || !*su->pwd->pw_shell)
-		su->pwd->pw_shell = DEFAULT_SHELL;
+		su->pwd->pw_shell = _PATH_BSHELL;
 
 	if (use_supp && !use_gid)
 		su->pwd->pw_gid = groups[0];
diff --git a/login-utils/sulogin.c b/login-utils/sulogin.c
index eb4609db6..c546cc7c1 100644
--- a/login-utils/sulogin.c
+++ b/login-utils/sulogin.c
@@ -34,6 +34,7 @@
 #include <fcntl.h>
 #include <signal.h>
 #include <pwd.h>
+#include <paths.h>
 #include <shadow.h>
 #include <termios.h>
 #include <errno.h>
@@ -892,7 +893,7 @@ static void sushell(struct passwd *pwd, struct console *con)
 		if (pwd->pw_shell[0])
 			su_shell = pwd->pw_shell;
 		else
-			su_shell = "/bin/sh";
+			su_shell = _PATH_BSHELL;
 	}
 	if ((p = strrchr(su_shell, '/')) == NULL)
 		p = su_shell;
@@ -941,9 +942,9 @@ static void sushell(struct passwd *pwd, struct console *con)
 	execl(su_shell, shell, (char *)NULL);
 	warn(_("failed to execute %s"), su_shell);
 
-	xsetenv("SHELL", "/bin/sh", 1);
-	execl("/bin/sh", profile ? "-sh" : "sh", (char *)NULL);
-	warn(_("failed to execute %s"), "/bin/sh");
+	xsetenv("SHELL", _PATH_BSHELL, 1);
+	execl(_PATH_BSHELL, profile ? "-sh" : "sh", (char *)NULL);
+	warn(_("failed to execute %s"), _PATH_BSHELL);
 }
 
 #ifdef HAVE_LIBSELINUX
diff --git a/sys-utils/setpriv.c b/sys-utils/setpriv.c
index c218be8e5..505d1ee5b 100644
--- a/sys-utils/setpriv.c
+++ b/sys-utils/setpriv.c
@@ -30,6 +30,7 @@
 #include <sys/prctl.h>
 #include <sys/types.h>
 #include <unistd.h>
+#include <paths.h>
 
 #include "all-io.h"
 #include "c.h"
@@ -56,9 +57,6 @@
 
 #define SETPRIV_EXIT_PRIVERR 127	/* how we exit when we fail to set privs */
 
-/* The shell to set SHELL env.variable if none is given in the user's passwd entry.  */
-#define DEFAULT_SHELL "/bin/sh"
-
 static gid_t get_group(const char *s, const char *err);
 
 enum cap_type {
@@ -741,7 +739,7 @@ static void do_reset_environ(struct passwd *pw)
 	if (pw->pw_shell && *pw->pw_shell)
 		xsetenv("SHELL", pw->pw_shell, 1);
 	else
-		xsetenv("SHELL", DEFAULT_SHELL, 1);
+		xsetenv("SHELL", _PATH_BSHELL, 1);
 
 	xsetenv("HOME", pw->pw_dir, 1);
 	xsetenv("USER", pw->pw_name, 1);
-- 
2.51.1


^ permalink raw reply related

* [PATCH 2/3] *: use ul_default_shell() for interactive shell spawning
From: Alessandro Ratti @ 2025-11-23 15:32 UTC (permalink / raw)
  To: util-linux; +Cc: kzak, thomas, Alessandro Ratti
In-Reply-To: <20251123153246.1056874-1-alessandro@0x65c.net>

Update tools that spawn interactive shells to use ul_default_shell()
for consistent shell resolution. This ensures these tools respect both
$SHELL and the user's configured shell from the passwd database before
falling back to _PATH_BSHELL.

Affected tools:
- script(1): fixes history truncation when invoked without $SHELL
- scriptlive(1): consistent with script(1) behavior
- flock(1): for -c command execution
- more(1): for shell escape feature
- exec_shell (used by unshare(1) and nsenter(1))

This change addresses user reports of data loss due to tools defaulting
to /bin/sh instead of the user's configured shell, particularly affecting
command history with different HISTSIZE configurations.

Addresses: https://github.com/util-linux/util-linux/issues/3865
Signed-off-by: Alessandro Ratti <alessandro@0x65c.net>
---
 lib/exec_shell.c        | 8 ++------
 sys-utils/flock.c       | 8 +++++---
 term-utils/script.c     | 5 ++---
 term-utils/scriptlive.c | 5 ++---
 text-utils/more.c       | 4 ++--
 5 files changed, 13 insertions(+), 17 deletions(-)

diff --git a/lib/exec_shell.c b/lib/exec_shell.c
index ffe65f006..8f10ea4df 100644
--- a/lib/exec_shell.c
+++ b/lib/exec_shell.c
@@ -26,19 +26,15 @@
 #include "xalloc.h"
 
 #include "exec_shell.h"
-
-#define DEFAULT_SHELL "/bin/sh"
+#include "shells.h"
 
 void __attribute__((__noreturn__)) exec_shell(void)
 {
-	const char *shell = getenv("SHELL");
+	const char *shell = ul_default_shell(0, NULL);
 	char *shellc;
 	const char *shell_basename;
 	char *arg0;
 
-	if (!shell)
-		shell = DEFAULT_SHELL;
-
 	shellc = xstrdup(shell);
 	shell_basename = basename(shellc);
 	xasprintf(&arg0, "-%s", shell_basename);
diff --git a/sys-utils/flock.c b/sys-utils/flock.c
index fe1a71f72..a6883ac77 100644
--- a/sys-utils/flock.c
+++ b/sys-utils/flock.c
@@ -47,6 +47,7 @@
 #include "closestream.h"
 #include "monotonic.h"
 #include "timer.h"
+#include "shells.h"
 
 #ifndef F_OFD_GETLK
 #define F_OFD_GETLK	36
@@ -207,6 +208,8 @@ int main(int argc, char *argv[])
 	int conflict_exit_code = 1;
 	char **cmd_argv = NULL, *sh_c_argv[4];
 	const char *filename = NULL;
+	const char *shell = NULL;
+
 	enum {
 		OPT_VERBOSE = CHAR_MAX + 1,
 		OPT_FCNTL,
@@ -237,6 +240,7 @@ int main(int argc, char *argv[])
 	bindtextdomain(PACKAGE, LOCALEDIR);
 	textdomain(PACKAGE);
 	close_stdout_atexit();
+	shell = ul_default_shell(0, NULL); /* Used for -c command execution */
 
 	strutils_set_exitcode(EX_USAGE);
 
@@ -327,9 +331,7 @@ int main(int argc, char *argv[])
 				     _("%s requires exactly one command argument"),
 				     argv[optind + 1]);
 			cmd_argv = sh_c_argv;
-			cmd_argv[0] = getenv("SHELL");
-			if (!cmd_argv[0] || !*cmd_argv[0])
-				cmd_argv[0] = _PATH_BSHELL;
+			cmd_argv[0] = (char *)shell;
 			cmd_argv[1] = "-c";
 			cmd_argv[2] = argv[optind + 2];
 			cmd_argv[3] = NULL;
diff --git a/term-utils/script.c b/term-utils/script.c
index ff7f4409f..4e302347f 100644
--- a/term-utils/script.c
+++ b/term-utils/script.c
@@ -70,6 +70,7 @@
 #include "signames.h"
 #include "pty-session.h"
 #include "debug.h"
+#include "shells.h"
 
 static UL_DEBUG_DEFINE_MASK(script);
 UL_DEBUG_DEFINE_MASKNAMES(script) = UL_DEBUG_EMPTY_MASKNAMES;
@@ -966,9 +967,7 @@ int main(int argc, char **argv)
 			log_associate(&ctl, &ctl.in, timingfile, format);
 	}
 
-	shell = getenv("SHELL");
-	if (!shell)
-		shell = _PATH_BSHELL;
+	shell = ul_default_shell(0, NULL);
 
 	ctl.pty = ul_new_pty(ctl.isterm);
 	if (!ctl.pty)
diff --git a/term-utils/scriptlive.c b/term-utils/scriptlive.c
index e4a3434ed..6ac685506 100644
--- a/term-utils/scriptlive.c
+++ b/term-utils/scriptlive.c
@@ -38,6 +38,7 @@
 #include "pty-session.h"
 #include "script-playutils.h"
 #include "monotonic.h"
+#include "shells.h"
 
 
 #define SCRIPT_MIN_DELAY 0.0001		/* from original scriptreplay.pl */
@@ -281,9 +282,7 @@ main(int argc, char *argv[])
 		replay_set_delay_max(ss.setup, &maxdelay);
 	replay_set_delay_min(ss.setup, &mindelay);
 
-	shell = getenv("SHELL");
-	if (shell == NULL)
-		shell = _PATH_BSHELL;
+	shell = ul_default_shell(0, NULL);
 
 	fprintf(stdout, _(">>> scriptlive: Starting your typescript execution by %s.\n"),
 			command ? command : shell);
diff --git a/text-utils/more.c b/text-utils/more.c
index 4980aef4c..4e3cae565 100644
--- a/text-utils/more.c
+++ b/text-utils/more.c
@@ -89,6 +89,7 @@
 #include "widechar.h"
 #include "closestream.h"
 #include "env.h"
+#include "shells.h"
 
 #ifdef TEST_PROGRAM
 # define NON_INTERACTIVE_MORE 1
@@ -2110,8 +2111,7 @@ static void initterm(struct more_control *ctl)
 	if ((ctl->backspace_ch = tigetstr(TERM_BACKSPACE)) == NULL)
 		ctl->backspace_ch = BACKSPACE;
 
-	if ((ctl->shell = getenv("SHELL")) == NULL)
-		ctl->shell = _PATH_BSHELL;
+	ctl->shell = (char *)ul_default_shell(0, NULL);
 }
 
 int main(int argc, char **argv)
-- 
2.51.1


^ permalink raw reply related

* [PATCH 1/3] lib: introduce ul_default_shell() for consistent shell resolution
From: Alessandro Ratti @ 2025-11-23 15:32 UTC (permalink / raw)
  To: util-linux; +Cc: kzak, thomas, Alessandro Ratti
In-Reply-To: <20251123153246.1056874-1-alessandro@0x65c.net>

Add a new ul_default_shell() function to provide consistent shell
resolution across util-linux tools. The function follows a priority
order: $SHELL environment variable, user's shell from passwd database,
and finally _PATH_BSHELL as fallback.

The function supports flags to control its behavior:
- UL_SHELL_NOENV: skip $SHELL environment variable check
- UL_SHELL_NOPWD: skip passwd database lookup

This addresses the issue where tools like script(1) would default to
/bin/sh without respecting the user's configured shell, potentially
causing data loss.

Addresses: https://github.com/util-linux/util-linux/issues/3865
Suggested-by: Karel Zak <kzak@redhat.com>
Suggested-by: Thomas Weißschuh <thomas@t-8ch.de>
Signed-off-by: Alessandro Ratti <alessandro@0x65c.net>
---
 include/shells.h  |  6 ++++++
 lib/Makemodule.am |  1 +
 lib/shells.c      | 26 ++++++++++++++++++++++++++
 3 files changed, 33 insertions(+)

diff --git a/include/shells.h b/include/shells.h
index c770a13ba..eca2b4187 100644
--- a/include/shells.h
+++ b/include/shells.h
@@ -4,7 +4,13 @@
 #ifndef UTIL_LINUX_SHELLS_H
 #define UTIL_LINUX_SHELLS_H
 
+#define UL_SHELL_NOENV  (1 << 0)
+#define UL_SHELL_NOPWD  (1 << 1)
+
 extern void print_shells(FILE *out, const char *format);
 extern int is_known_shell(const char *shell_name);
 
+struct passwd;
+const char *ul_default_shell(int flags, const struct passwd *pw);
+
 #endif /* UTIL_LINUX_SHELLS_H */
diff --git a/lib/Makemodule.am b/lib/Makemodule.am
index a9da57734..1d598faa2 100644
--- a/lib/Makemodule.am
+++ b/lib/Makemodule.am
@@ -49,6 +49,7 @@ libcommon_la_SOURCES = \
 if LINUX
 libcommon_la_SOURCES += \
 	lib/linux_version.c \
+	lib/shells.c \
 	lib/loopdev.c
 endif
 
diff --git a/lib/shells.c b/lib/shells.c
index 13f293c5e..ef2aecd0f 100644
--- a/lib/shells.c
+++ b/lib/shells.c
@@ -1,6 +1,11 @@
 /*
  * SPDX-License-Identifier: GPL-2.0-or-later
  */
+#include <sys/types.h>
+#include <pwd.h>
+#include <stdlib.h>
+#include <paths.h>
+#include <unistd.h>
 #include <sys/syslog.h>
 #if defined (HAVE_LIBECONF) && defined (USE_VENDORDIR)
 #include <libeconf.h>
@@ -116,3 +121,24 @@ extern int is_known_shell(const char *shell_name)
 #endif
 	return ret;
 }
+
+const char *ul_default_shell(int flags, const struct passwd *pw)
+{
+	const char *shell = NULL;
+
+	if (!(flags & UL_SHELL_NOENV)) {
+		shell = getenv("SHELL");
+		if (shell && *shell)
+			return shell;
+	}
+	if (!(flags & UL_SHELL_NOPWD)) {
+		if (!pw)
+			pw = getpwuid(getuid());
+		if (pw)
+			shell = pw->pw_shell;
+		if (shell && *shell)
+			return shell;
+	}
+
+	return _PATH_BSHELL;
+}
-- 
2.51.1


^ permalink raw reply related

* [PATCH 0/3] Consistent shell resolution across util-linux
From: Alessandro Ratti @ 2025-11-23 15:32 UTC (permalink / raw)
  To: util-linux; +Cc: kzak, thomas, Alessandro Ratti

This patch series addresses inconsistent default shell handling across
util-linux tools, which caused user-reported data loss when script(1)
defaulted to /bin/sh without respecting the user's configured shell.

The series:
1. Introduces ul_default_shell() for consistent shell resolution
2. Updates interactive tools to use the new function
3. Standardizes _PATH_BSHELL usage in security-sensitive tools

This implements the solution discussed in:
https://github.com/util-linux/util-linux/issues/3865

Alessandro Ratti (3):
  lib: introduce ul_default_shell() for consistent shell resolution
  *: use ul_default_shell() for interactive shell spawning
  login-utils, sys-utils: use _PATH_BSHELL consistently

 include/shells.h        |  6 ++++++
 lib/Makemodule.am       |  1 +
 lib/exec_shell.c        |  8 ++------
 lib/shells.c            | 26 ++++++++++++++++++++++++++
 login-utils/su-common.c |  5 +----
 login-utils/sulogin.c   |  9 +++++----
 sys-utils/flock.c       |  8 +++++---
 sys-utils/setpriv.c     |  6 ++----
 term-utils/script.c     |  5 ++---
 term-utils/scriptlive.c |  5 ++---
 text-utils/more.c       |  4 ++--
 11 files changed, 54 insertions(+), 29 deletions(-)

-- 
2.51.1


^ permalink raw reply

* [PATCH] treewide: consistently use tabs for indentation where it is the rule
From: Benno Schulenberg @ 2025-11-17  9:50 UTC (permalink / raw)
  To: util-linux

Also unwrap a line, delete two blank lines, and improve three comments.

Signed-off-by: Benno Schulenberg <bensberg@telfort.nl>
---
 disk-utils/blockdev.c          |  20 ++--
 disk-utils/cfdisk.c            |   8 +-
 disk-utils/fdformat.c          |   2 +-
 disk-utils/fdisk-menu.c        |  10 +-
 disk-utils/fdisk.c             |   6 +-
 disk-utils/mkfs.bfs.c          |   2 +-
 disk-utils/mkfs.cramfs.c       |   6 +-
 disk-utils/mkswap.c            |   3 +-
 disk-utils/sfdisk.c            |   4 +-
 lib/buffer.c                   |   2 +-
 lib/env.c                      |  86 ++++++++---------
 lib/fileeq.c                   |   2 +-
 lib/ismounted.c                |  32 +++---
 lib/logindefs.c                |  46 ++++-----
 lib/loopdev.c                  |  38 ++++----
 lib/procfs.c                   |   4 +-
 lib/pty-session.c              |   6 +-
 lib/shells.c                   |  54 +++++------
 lib/strutils.c                 | 148 ++++++++++++++--------------
 lib/sysfs.c                    | 171 ++++++++++++++++-----------------
 lib/timer.c                    |   2 +-
 login-utils/login.c            |   4 +-
 login-utils/sulogin-consoles.c |  10 +-
 misc-utils/findmnt.c           |  16 +--
 misc-utils/lastlog2.c          |   7 +-
 misc-utils/lsblk-devtree.c     |  16 +--
 misc-utils/rename.c            |   4 +-
 sys-utils/ipcrm.c              |   2 +-
 sys-utils/ldattach.c           |   6 +-
 sys-utils/losetup.c            |   2 +-
 sys-utils/lscpu-topology.c     |   2 +-
 sys-utils/lsns.c               |  16 +--
 sys-utils/swapoff.c            |   2 +-
 sys-utils/tunelp.c             |   4 +-
 sys-utils/unshare.c            |  16 +--
 sys-utils/zramctl.c            |   6 +-
 term-utils/agetty.c            |  14 +--
 term-utils/mesg.c              |   4 +-
 term-utils/script.c            |   2 +-
 term-utils/scriptreplay.c      |   4 +-
 text-utils/col.c               |  65 ++++++-------
 text-utils/hexdump-display.c   |   4 +-
 text-utils/hexdump-parse.c     |  10 +-
 text-utils/hexdump.c           |   2 +-
 44 files changed, 433 insertions(+), 437 deletions(-)

diff --git a/disk-utils/blockdev.c b/disk-utils/blockdev.c
index 55b47acf6..3ef74aa22 100644
--- a/disk-utils/blockdev.c
+++ b/disk-utils/blockdev.c
@@ -140,7 +140,7 @@ static const struct bdc bdcms[] =
 		.argname = "<bytes>",
 		.argtype = ARG_INT,
 		.flags = FL_NORESULT,
-	        .help = N_("set blocksize on file descriptor opening the block device")
+		.help = N_("set blocksize on file descriptor opening the block device")
 	},{
 		IOCTL_ENTRY(BLKGETSIZE),
 		.name = "--getsize",
@@ -210,23 +210,23 @@ static void __attribute__((__noreturn__)) usage(void)
 
 	fputs(USAGE_HEADER, stdout);
 	fprintf(stdout, _(
-	         " %1$s [-v|-q] commands devices\n"
-	         " %1$s --report [devices]\n"
-	         " %1$s -h|-V\n"
-		), program_invocation_short_name);
+	          " %1$s [-v|-q] commands devices\n"
+	          " %1$s --report [devices]\n"
+	          " %1$s -h|-V\n"
+	       ), program_invocation_short_name);
 
 	fputs(USAGE_SEPARATOR, stdout);
-	fputsln(  _("Call block device ioctls from the command line."), stdout);
+	fputsln(_("Call block device ioctls from the command line."), stdout);
 
 	fputs(USAGE_OPTIONS, stdout);
-	fputsln(  _(" -q             quiet mode"), stdout);
-	fputsln(  _(" -v             verbose mode"), stdout);
-	fputsln(  _("     --report   print report for specified (or all) devices"), stdout);
+	fputsln(_(" -q             quiet mode"), stdout);
+	fputsln(_(" -v             verbose mode"), stdout);
+	fputsln(_("     --report   print report for specified (or all) devices"), stdout);
 	fputs(USAGE_SEPARATOR, stdout);
 	fprintf(stdout, USAGE_HELP_OPTIONS(16));
 
 	fputs(USAGE_SEPARATOR, stdout);
-	fputsln(  _("Available commands:"), stdout);
+	fputsln(_("Available commands:"), stdout);
 	fprintf(stdout, _(" %-25s get size in 512-byte sectors\n"), "--getsz");
 	for (i = 0; i < ARRAY_SIZE(bdcms); i++) {
 		if (bdcms[i].argname)
diff --git a/disk-utils/cfdisk.c b/disk-utils/cfdisk.c
index e4e16001e..e2f1cd74d 100644
--- a/disk-utils/cfdisk.c
+++ b/disk-utils/cfdisk.c
@@ -1760,7 +1760,7 @@ static int ui_refresh(struct cfdisk *cf)
 {
 	struct fdisk_label *lb;
 	char *id = NULL;
-        uint64_t bytes = fdisk_get_nsectors(cf->cxt) * fdisk_get_sector_size(cf->cxt);
+	uint64_t bytes = fdisk_get_nsectors(cf->cxt) * fdisk_get_sector_size(cf->cxt);
 	char *strsz;
 
 	if (!ui_enabled)
@@ -2783,9 +2783,9 @@ int main(int argc, char *argv[])
 			if (optarg)
 				colormode = colormode_or_err(optarg);
 			break;
-                case 'r':
-                        read_only = 1;
-                        break;
+		case 'r':
+			read_only = 1;
+			break;
 		case 'V':
 			print_version(EXIT_SUCCESS);
 		case 'z':
diff --git a/disk-utils/fdformat.c b/disk-utils/fdformat.c
index 49cb51d8a..04e414a53 100644
--- a/disk-utils/fdformat.c
+++ b/disk-utils/fdformat.c
@@ -164,7 +164,7 @@ static void __attribute__((__noreturn__)) usage(void)
 	fputs(_(" -f, --from <N>    start at the track N (default 0)\n"), out);
 	fputs(_(" -t, --to <N>      stop at the track N\n"), out);
 	fputs(_(" -r, --repair <N>  try to repair tracks failed during\n"
-                "                     the verification (max N retries)\n"), out);
+		"                     the verification (max N retries)\n"), out);
 	fputs(_(" -n, --no-verify   disable the verification after the format\n"), out);
 
 	fputs(USAGE_SEPARATOR, out);
diff --git a/disk-utils/fdisk-menu.c b/disk-utils/fdisk-menu.c
index 707394d4e..f3c9f154e 100644
--- a/disk-utils/fdisk-menu.c
+++ b/disk-utils/fdisk-menu.c
@@ -499,9 +499,9 @@ static int script_read(struct fdisk_context *cxt)
 		fdisk_warnx(cxt, _("Failed to apply script %s"), filename);
 		fdisk_warnx(cxt, _("Resetting fdisk!"));
 		rc = fdisk_reassign_device(cxt);
-                if (rc == 0 && !fdisk_has_label(cxt)) {
-                        fdisk_info(cxt, _("Device does not contain a recognized partition table."));
-                        rc = fdisk_create_disklabel(cxt, NULL);
+		if (rc == 0 && !fdisk_has_label(cxt)) {
+			fdisk_info(cxt, _("Device does not contain a recognized partition table."));
+			rc = fdisk_create_disklabel(cxt, NULL);
 		}
 	} else
 		fdisk_info(cxt, _("Script successfully applied."));
@@ -751,8 +751,8 @@ static int gpt_menu_cb(struct fdisk_context **cxt0,
 		case 'i':
 			return fdisk_set_disklabel_id(cxt);
 		case 'l':
-	                rc =  fdisk_ask_number(cxt, 1, fdisk_get_npartitions(cxt),
-	                                ~(uint32_t)0, _("New maximum entries"), &length);
+			rc =  fdisk_ask_number(cxt, 1, fdisk_get_npartitions(cxt),
+			                       ~(uint32_t)0, _("New maximum entries"), &length);
 			if (rc)
 				return rc;
 			return fdisk_gpt_set_npartitions(cxt, (uint32_t) length);
diff --git a/disk-utils/fdisk.c b/disk-utils/fdisk.c
index 72feed587..f44a4899e 100644
--- a/disk-utils/fdisk.c
+++ b/disk-utils/fdisk.c
@@ -494,11 +494,11 @@ static struct fdisk_parttype *ask_partition_type(struct fdisk_context *cxt, int
 	*canceled = 0;
 
 	if (fdisk_label_has_parttypes_shortcuts(lb))
-		 q = fdisk_label_has_code_parttypes(lb) ?
+		q = fdisk_label_has_code_parttypes(lb) ?
 			_("Hex code or alias (type L to list all): ") :
 			_("Partition type or alias (type L to list all): ");
 	else
-	        q = fdisk_label_has_code_parttypes(lb) ?
+		q = fdisk_label_has_code_parttypes(lb) ?
 			_("Hex code (type L to list all codes): ") :
 			_("Partition type (type L to list all types): ");
 	do {
@@ -523,7 +523,7 @@ static struct fdisk_parttype *ask_partition_type(struct fdisk_context *cxt, int
 				fdisk_info(cxt, _("Failed to parse '%s' partition type."), buf);
 			return t;
 		}
-        } while (1);
+	} while (1);
 
 	return NULL;
 }
diff --git a/disk-utils/mkfs.bfs.c b/disk-utils/mkfs.bfs.c
index 30c28d9e7..838fb59b4 100644
--- a/disk-utils/mkfs.bfs.c
+++ b/disk-utils/mkfs.bfs.c
@@ -184,7 +184,7 @@ int main(int argc, char **argv)
 			/* when called via mkfs we may get options c,l,v */
 			break;
 
-                case OPT_LOCK:
+		case OPT_LOCK:
 			lockmode = "1";
 			if (optarg) {
 				if (*optarg == '=')
diff --git a/disk-utils/mkfs.cramfs.c b/disk-utils/mkfs.cramfs.c
index a91016d26..0b1695e77 100644
--- a/disk-utils/mkfs.cramfs.c
+++ b/disk-utils/mkfs.cramfs.c
@@ -764,9 +764,9 @@ int main(int argc, char **argv)
 			fslen_ub += (image_length + 3); /* 3 is for padding */
 			break;
 		case 'l':
-                        lockmode = "1";
+			lockmode = "1";
 			if (optarg) {
-                                if (*optarg == '=')
+				if (*optarg == '=')
 					optarg++;
 				lockmode = optarg;
 			}
@@ -810,7 +810,7 @@ int main(int argc, char **argv)
 	if (fd < 0)
 		err(MKFS_EX_USAGE, _("cannot open %s"), outfile);
 
-        if (blkdev_lock(fd, outfile, lockmode) != 0)
+	if (blkdev_lock(fd, outfile, lockmode) != 0)
 		exit(MKFS_EX_ERROR);
 
 	root_entry = xcalloc(1, sizeof(struct entry));
diff --git a/disk-utils/mkswap.c b/disk-utils/mkswap.c
index 3cb7a043b..17ec1603f 100644
--- a/disk-utils/mkswap.c
+++ b/disk-utils/mkswap.c
@@ -800,8 +800,7 @@ int main(int argc, char **argv)
 	deinit_signature_page(&ctl);
 
 #ifdef HAVE_LIBSELINUX
-	if ((ctl.file || S_ISREG(ctl.devstat.st_mode)) &&
-            is_selinux_enabled() > 0) {
+	if ((ctl.file || S_ISREG(ctl.devstat.st_mode)) && is_selinux_enabled() > 0) {
 		const char *context_string;
 		char *oldcontext;
 		context_t newcontext;
diff --git a/disk-utils/sfdisk.c b/disk-utils/sfdisk.c
index b691cb084..aeab826c2 100644
--- a/disk-utils/sfdisk.c
+++ b/disk-utils/sfdisk.c
@@ -478,7 +478,7 @@ static int move_partition_data(struct sfdisk *sf, size_t partno, struct fdisk_pa
 			fdisk_info(sf->cxt, _(" typescript file: %s"), typescript);
 		printf(_("  start sector: (from/to) %ju / %ju\n"), (uintmax_t) from, (uintmax_t) to);
 		printf(_("  sectors: %ju\n"), (uintmax_t) nsectors);
-	        printf(_("  step size: %zu bytes\n"), step_bytes);
+		printf(_("  step size: %zu bytes\n"), step_bytes);
 		putchar('\n');
 		fflush(stdout);
 
@@ -602,7 +602,7 @@ static int move_partition_data(struct sfdisk *sf, size_t partno, struct fdisk_pa
 					i + 1, nsectors,
 					100.0 / ((double) nsectors/(i+1)));
 			fflush(stdout);
-                        fputc('\r', stdout);
+			fputc('\r', stdout);
 
 		}
 next:
diff --git a/lib/buffer.c b/lib/buffer.c
index bdc4744bc..76aefe950 100644
--- a/lib/buffer.c
+++ b/lib/buffer.c
@@ -303,6 +303,6 @@ int main(void)
 
 	ul_buffer_free_data(&buf);
 
-        return EXIT_SUCCESS;
+	return EXIT_SUCCESS;
 }
 #endif /* TEST_PROGRAM_BUFFER */
diff --git a/lib/env.c b/lib/env.c
index 039fad0dc..e5e66337f 100644
--- a/lib/env.c
+++ b/lib/env.c
@@ -27,28 +27,28 @@ extern char **environ;
 #endif
 
 static char * const forbid[] = {
-        "BASH_ENV=",    /* GNU creeping featurism strikes again... */
-        "ENV=",
-        "HOME=",
-        "IFS=",
-        "KRB_CONF=",
-        "LD_",          /* anything with the LD_ prefix */
-        "LIBPATH=",
-        "MAIL=",
-        "NLSPATH=",
-        "PATH=",
-        "SHELL=",
-        "SHLIB_PATH=",
-        (char *) 0
+	"BASH_ENV=",    /* GNU creeping featurism strikes again... */
+	"ENV=",
+	"HOME=",
+	"IFS=",
+	"KRB_CONF=",
+	"LD_",	  /* anything with the LD_ prefix */
+	"LIBPATH=",
+	"MAIL=",
+	"NLSPATH=",
+	"PATH=",
+	"SHELL=",
+	"SHLIB_PATH=",
+	(char *) 0
 };
 
 /* these are allowed, but with no slashes inside
    (to work around security problems in GNU gettext) */
 static char * const noslash[] = {
-        "LANG=",
-        "LANGUAGE=",
-        "LC_",          /* anything with the LC_ prefix */
-        (char *) 0
+	"LANG=",
+	"LANGUAGE=",
+	"LC_",	  /* anything with the LC_ prefix */
+	(char *) 0
 };
 
 
@@ -218,39 +218,39 @@ void env_list_free(struct ul_env_list *ls)
  */
 void __sanitize_env(struct ul_env_list **org)
 {
-        char **envp = environ;
-        char * const *bad;
-        char **cur;
-        int last = 0;
+	char **envp = environ;
+	char * const *bad;
+	char **cur;
+	int last = 0;
 
-        for (cur = envp; *cur; cur++)
-                last++;
+	for (cur = envp; *cur; cur++)
+		last++;
 
-        for (cur = envp; *cur; cur++) {
-                for (bad = forbid; *bad; bad++) {
-                        if (strncmp(*cur, *bad, strlen(*bad)) == 0) {
+	for (cur = envp; *cur; cur++) {
+		for (bad = forbid; *bad; bad++) {
+			if (strncmp(*cur, *bad, strlen(*bad)) == 0) {
 				if (org)
 					*org = env_list_add_from_string(*org, *cur);
-                                last = ul_remove_entry(envp, cur - envp, last);
-                                cur--;
-                                break;
-                        }
-                }
-        }
+				last = ul_remove_entry(envp, cur - envp, last);
+				cur--;
+				break;
+			}
+		}
+	}
 
-        for (cur = envp; *cur; cur++) {
-                for (bad = noslash; *bad; bad++) {
-                        if (strncmp(*cur, *bad, strlen(*bad)) != 0)
-                                continue;
-                        if (!strchr(*cur, '/'))
-                                continue;  /* OK */
+	for (cur = envp; *cur; cur++) {
+		for (bad = noslash; *bad; bad++) {
+			if (strncmp(*cur, *bad, strlen(*bad)) != 0)
+				continue;
+			if (!strchr(*cur, '/'))
+				continue;  /* OK */
 			if (org)
 				*org = env_list_add_from_string(*org, *cur);
-                        last = ul_remove_entry(envp, cur - envp, last);
-                        cur--;
-                        break;
-                }
-        }
+			last = ul_remove_entry(envp, cur - envp, last);
+			cur--;
+			break;
+		}
+	}
 }
 
 void sanitize_env(void)
diff --git a/lib/fileeq.c b/lib/fileeq.c
index ffd208962..762619563 100644
--- a/lib/fileeq.c
+++ b/lib/fileeq.c
@@ -335,7 +335,7 @@ static int get_fd(struct ul_fileeq *eq, struct ul_fileeq_data *data, off_t *off)
 			return data->fd;
 
 #if defined(POSIX_FADV_SEQUENTIAL) && defined(HAVE_POSIX_FADVISE)
-	        ignore_result( posix_fadvise(data->fd, o, 0, POSIX_FADV_SEQUENTIAL) );
+		ignore_result( posix_fadvise(data->fd, o, 0, POSIX_FADV_SEQUENTIAL) );
 #endif
 		if (o) {
 			DBG(DATA, ul_debugobj(data, "lseek off=%ju", (uintmax_t) o));
diff --git a/lib/ismounted.c b/lib/ismounted.c
index ae5327c90..28ddc0d58 100644
--- a/lib/ismounted.c
+++ b/lib/ismounted.c
@@ -216,31 +216,31 @@ static int check_getmntinfo(const char *file, int *mount_flags,
 				  char *mtpt, int mtlen)
 {
 	struct statfs *mp;
-        int    len, n;
-        const  char   *s1;
+	int    len, n;
+	const  char   *s1;
 	char	*s2;
 
-        n = getmntinfo(&mp, MNT_NOWAIT);
-        if (n == 0)
+	n = getmntinfo(&mp, MNT_NOWAIT);
+	if (n == 0)
 		return errno;
 
-        len = sizeof(_PATH_DEV) - 1;
-        s1 = file;
-        if (strncmp(_PATH_DEV, s1, len) == 0)
-                s1 += len;
+	len = sizeof(_PATH_DEV) - 1;
+	s1 = file;
+	if (strncmp(_PATH_DEV, s1, len) == 0)
+		s1 += len;
 
 	*mount_flags = 0;
-        while (--n >= 0) {
-                s2 = mp->f_mntfromname;
-                if (strncmp(_PATH_DEV, s2, len) == 0) {
-                        s2 += len - 1;
-                        *s2 = 'r';
-                }
-                if (strcmp(s1, s2) == 0 || strcmp(s1, &s2[1]) == 0) {
+	while (--n >= 0) {
+		s2 = mp->f_mntfromname;
+		if (strncmp(_PATH_DEV, s2, len) == 0) {
+			s2 += len - 1;
+			*s2 = 'r';
+		}
+		if (strcmp(s1, s2) == 0 || strcmp(s1, &s2[1]) == 0) {
 			*mount_flags = MF_MOUNTED;
 			break;
 		}
-                ++mp;
+		++mp;
 	}
 	if (mtpt && n >= 0)
 		xstrncpy(mtpt, mp->f_mntonname, mtlen);
diff --git a/lib/logindefs.c b/lib/logindefs.c
index 079f2dabf..3da5911d1 100644
--- a/lib/logindefs.c
+++ b/lib/logindefs.c
@@ -253,7 +253,7 @@ static void load_defaults(void)
 	econf_err error;
 
 	if (file != NULL)
-	        free_getlogindefs_data();
+		free_getlogindefs_data();
 
 #ifdef HAVE_ECONF_READCONFIG
 	error = econf_readConfig(&file, NULL,
@@ -282,10 +282,10 @@ void logindefs_load_file(const char *filename)
 	xasprintf(&path, _PATH_VENDORDIR"/%s", filename);
 
 	if (!econf_readFile(&file_l, path, "= \t", "#")) {
-	        if (file == NULL)
-		        file = file_l;
-	        else if (!econf_mergeFiles(&file_m, file, file_l)) {
-		        econf_free(file);
+		if (file == NULL)
+			file = file_l;
+		else if (!econf_mergeFiles(&file_m, file, file_l)) {
+			econf_free(file);
 			file = file_m;
 			econf_free(file_l);
 		}
@@ -296,10 +296,10 @@ void logindefs_load_file(const char *filename)
 	xasprintf(&path, "/etc/%s", filename);
 
 	if (!econf_readFile(&file_l, path, "= \t", "#")) {
-	        if (file == NULL)
-		        file = file_l;
-	        else if (!econf_mergeFiles(&file_m, file, file_l)) {
-	                econf_free(file);
+		if (file == NULL)
+			file = file_l;
+		else if (!econf_mergeFiles(&file_m, file, file_l)) {
+			econf_free(file);
 			file = file_m;
 			econf_free(file_l);
 		}
@@ -319,18 +319,18 @@ void logindefs_load_file(const char *filename)
 
 int getlogindefs_bool(const char *name, int dflt)
 {
-        bool value;
+	bool value;
 	econf_err error;
 
 	if (!file)
-	        load_defaults();
+		load_defaults();
 
 	if (!file)
 		return dflt;
 
 	if ((error = econf_getBoolValue(file, NULL, name, &value))) {
-	        if (error != ECONF_NOKEY)
-	                syslog(LOG_NOTICE, _("couldn't fetch %s: %s"), name,
+		if (error != ECONF_NOKEY)
+			syslog(LOG_NOTICE, _("couldn't fetch %s: %s"), name,
 			       econf_errString(error));
 		return dflt;
 	}
@@ -343,14 +343,14 @@ unsigned long getlogindefs_num(const char *name, unsigned long dflt)
 	econf_err error;
 
 	if (!file)
-	        load_defaults();
+		load_defaults();
 
 	if (!file)
 		return dflt;
 
 	if ((error = econf_getUInt64Value(file, NULL, name, &value))) {
-	        if (error != ECONF_NOKEY)
-		        syslog(LOG_NOTICE, _("couldn't fetch %s: %s"), name,
+		if (error != ECONF_NOKEY)
+			syslog(LOG_NOTICE, _("couldn't fetch %s: %s"), name,
 			       econf_errString(error));
 		return dflt;
 	}
@@ -365,19 +365,19 @@ unsigned long getlogindefs_num(const char *name, unsigned long dflt)
  */
 const char *getlogindefs_str(const char *name, const char *dflt)
 {
-        char *value;
+	char *value;
 	econf_err error;
 
 	if (!file)
-	        load_defaults();
+		load_defaults();
 
 	if (!file)
 		return dflt;
 
 	if ((error = econf_getStringValue(file, NULL, name, &value))) {
-	        if (error != ECONF_NOKEY)
-		  syslog(LOG_NOTICE, _("couldn't fetch %s: %s"), name,
-			 econf_errString(error));
+		if (error != ECONF_NOKEY)
+			syslog(LOG_NOTICE, _("couldn't fetch %s: %s"), name,
+			       econf_errString(error));
 		return dflt;
 	}
 	if (value)
@@ -591,10 +591,10 @@ int main(int argc, char *argv[])
 				NULL};
 
 		for (i = 0; keys[i] != NULL; i++) {
-		  	char *value = NULL;
+			char *value = NULL;
 
 			econf_getStringValue(file, NULL, keys[i], &value);
-		        printf ("%s: $%s: '%s'\n", argv[1], keys[i], value);
+			printf ("%s: $%s: '%s'\n", argv[1], keys[i], value);
 		}
 
 		econf_free (file);
diff --git a/lib/loopdev.c b/lib/loopdev.c
index efc997f87..6b27e451f 100644
--- a/lib/loopdev.c
+++ b/lib/loopdev.c
@@ -326,7 +326,7 @@ static int __loopcxt_get_fd(struct loopdev_cxt *lc, mode_t mode)
 		lc->fd = open(lc->device, lc->mode | O_CLOEXEC);
 		DBG(CXT, ul_debugobj(lc, "open %s [%s]: %m", lc->device,
 				mode == O_RDONLY ? "ro" :
-			        mode == O_RDWR ? "rw" : "??"));
+				mode == O_RDWR ? "rw" : "??"));
 
 		if (lc->fd < 0 && old >= 0) {
 			/* restore original on error */
@@ -1661,28 +1661,28 @@ int loopcxt_detach_device(struct loopdev_cxt *lc)
 
 int loopcxt_remove_device(struct loopdev_cxt *lc)
 {
-       int rc = -EINVAL;
-       int ctl, nr = -1;
+	int rc = -EINVAL;
+	int ctl, nr = -1;
 
-       if (!(lc->flags & LOOPDEV_FL_CONTROL)) {
-               rc = -ENOSYS;
-               goto done;
-       }
+	if (!(lc->flags & LOOPDEV_FL_CONTROL)) {
+		rc = -ENOSYS;
+		goto done;
+	}
 
-       rc = loopcxt_get_device_nr(lc, &nr);
-       if (rc)
-               goto done;
+	rc = loopcxt_get_device_nr(lc, &nr);
+	if (rc)
+		goto done;
 
-       ctl = open(_PATH_DEV_LOOPCTL, O_RDWR|O_CLOEXEC);
-       if (ctl >= 0) {
-               DBG(CXT, ul_debugobj(lc, "remove_device %d", nr));
-               rc = ioctl(ctl, LOOP_CTL_REMOVE, nr);
-               close(ctl);
-       }
-       lc->control_ok = rc >= 0 ? 1 : 0;
+	ctl = open(_PATH_DEV_LOOPCTL, O_RDWR|O_CLOEXEC);
+	if (ctl >= 0) {
+		DBG(CXT, ul_debugobj(lc, "remove_device %d", nr));
+		rc = ioctl(ctl, LOOP_CTL_REMOVE, nr);
+		close(ctl);
+	}
+	lc->control_ok = rc >= 0 ? 1 : 0;
 done:
-       DBG(CXT, ul_debugobj(lc, "remove_device done [rc=%d]", rc));
-       return rc;
+	DBG(CXT, ul_debugobj(lc, "remove_device done [rc=%d]", rc));
+	return rc;
 }
 
 int loopcxt_add_device(struct loopdev_cxt *lc)
diff --git a/lib/procfs.c b/lib/procfs.c
index 47cc8eea2..3499c684b 100644
--- a/lib/procfs.c
+++ b/lib/procfs.c
@@ -477,7 +477,7 @@ static int test_tasks(int argc, char *argv[], const char *prefix)
 		printf(" %d", tid);
 
 	printf("\n");
-        ul_unref_path(pc);
+	ul_unref_path(pc);
 	return EXIT_SUCCESS;
 }
 
@@ -502,7 +502,7 @@ static int test_fds(int argc, char *argv[], const char *prefix)
 		printf(" %d", fd);
 
 	fputc('\n', stdout);
-        ul_unref_path(pc);
+	ul_unref_path(pc);
 	return EXIT_SUCCESS;
 }
 
diff --git a/lib/pty-session.c b/lib/pty-session.c
index e9db4988b..b3e41e0c8 100644
--- a/lib/pty-session.c
+++ b/lib/pty-session.c
@@ -169,7 +169,7 @@ int ul_pty_setup(struct ul_pty *pty)
 	sigprocmask(0, NULL, &pty->orgsig);
 
 	if (pty->isterm) {
-	        DBG(SETUP, ul_debugobj(pty, "create for terminal"));
+		DBG(SETUP, ul_debugobj(pty, "create for terminal"));
 
 		/* original setting of the current terminal */
 		if (tcgetattr(STDIN_FILENO, &pty->stdin_attrs) != 0) {
@@ -594,9 +594,9 @@ static int handle_signal(struct ul_pty *pty, int fd)
 	case SIGQUIT:
 		DBG(SIG, ul_debugobj(pty, " get signal SIG{TERM,INT,QUIT}"));
 		pty->delivered_signal = info.ssi_signo;
-                /* Child termination is going to generate SIGCHLD (see above) */
+		/* Child termination is going to generate SIGCHLD (see above) */
 		if (pty->child > 0)
-	                kill(pty->child, SIGTERM);
+			kill(pty->child, SIGTERM);
 
 		if (pty->callbacks.log_signal)
 			rc = pty->callbacks.log_signal(pty->callback_data,
diff --git a/lib/shells.c b/lib/shells.c
index 13f293c5e..6f9cd71a9 100644
--- a/lib/shells.c
+++ b/lib/shells.c
@@ -39,34 +39,34 @@ static econf_file *open_etc_shells(void)
 extern void print_shells(FILE *out, const char *format)
 {
 #if defined (HAVE_LIBECONF) && defined (USE_VENDORDIR)
-        size_t size = 0;
-        econf_err error;
-        char **keys = NULL;
-        econf_file *key_file = open_etc_shells();
+	size_t size = 0;
+	econf_err error;
+	char **keys = NULL;
+	econf_file *key_file = open_etc_shells();
 
 	if (!key_file)
 	  return;
 
-        error = econf_getKeys(key_file, NULL, &size, &keys);
-        if (error) {
-                econf_free(key_file);
-                errx(EXIT_FAILURE,
-                  _("Cannot evaluate entries in shells files: %s"),
-                  econf_errString(error));
-        }
+	error = econf_getKeys(key_file, NULL, &size, &keys);
+	if (error) {
+		econf_free(key_file);
+		errx(EXIT_FAILURE,
+		  _("Cannot evaluate entries in shells files: %s"),
+		  econf_errString(error));
+	}
 
-        for (size_t i = 0; i < size; i++) {
-	        fprintf(out, format, keys[i]);
-        }
-        econf_free(keys);
-        econf_free(key_file);
+	for (size_t i = 0; i < size; i++) {
+		fprintf(out, format, keys[i]);
+	}
+	econf_free(keys);
+	econf_free(key_file);
 #else
-        char *s;
+	char *s;
 
 	setusershell();
-        while ((s = getusershell()))
-	        fprintf(out, format, s);
-        endusershell();
+	while ((s = getusershell()))
+		fprintf(out, format, s);
+	endusershell();
 #endif
 }
 
@@ -86,19 +86,19 @@ extern int is_known_shell(const char *shell_name)
 #if defined (HAVE_LIBECONF) && defined (USE_VENDORDIR)
 	char *val = NULL;
 	econf_err error;
-        econf_file *key_file = open_etc_shells();
+	econf_file *key_file = open_etc_shells();
 
 	if (!key_file)
-	  return 0;
+		return 0;
 
 	error = econf_getStringValue (key_file, NULL, shell_name, &val);
 	if (error) {
-	        if (error != ECONF_NOKEY)
-		       syslog(LOG_ALERT,
-		               _("Cannot evaluate entries in shells files: %s"),
-			      econf_errString(error));
+		if (error != ECONF_NOKEY)
+			syslog(LOG_ALERT,
+			       _("Cannot evaluate entries in shells files: %s"),
+			       econf_errString(error));
 	} else
-	        ret = 1;
+		ret = 1;
 
 	free(val);
 	econf_free(key_file);
diff --git a/lib/strutils.c b/lib/strutils.c
index a3b1376e3..72d0352c8 100644
--- a/lib/strutils.c
+++ b/lib/strutils.c
@@ -281,20 +281,20 @@ int ul_parse_switch(const char *arg, ...)
 #ifndef HAVE_MEMPCPY
 void *mempcpy(void *restrict dest, const void *restrict src, size_t n)
 {
-    return ((char *)memcpy(dest, src, n)) + n;
+	return ((char *)memcpy(dest, src, n)) + n;
 }
 #endif
 
 #ifndef HAVE_STRNLEN
 size_t strnlen(const char *s, size_t maxlen)
 {
-        size_t i;
+	size_t i;
 
-        for (i = 0; i < maxlen; i++) {
-                if (s[i] == '\0')
-                        return i;
-        }
-        return maxlen;
+	for (i = 0; i < maxlen; i++) {
+		if (s[i] == '\0')
+			return i;
+	}
+	return maxlen;
 }
 #endif
 
@@ -980,38 +980,38 @@ int streq_paths(const char *a, const char *b)
 /* concatenate two strings to a new string, the size of the second string is limited by @b */
 char *ul_strnconcat(const char *s, const char *suffix, size_t b)
 {
-        size_t a;
-        char *r;
+	size_t a;
+	char *r;
 
-        if (!s && !suffix)
-                return strdup("");
-        if (!s)
-                return strndup(suffix, b);
-        if (!suffix)
-                return strdup(s);
+	if (!s && !suffix)
+		return strdup("");
+	if (!s)
+		return strndup(suffix, b);
+	if (!suffix)
+		return strdup(s);
 
-        assert(s);
-        assert(suffix);
+	assert(s);
+	assert(suffix);
 
-        a = strlen(s);
-        if (b > ((size_t) -1) - a)
-                return NULL;
+	a = strlen(s);
+	if (b > ((size_t) -1) - a)
+		return NULL;
 
-        r = malloc(a + b + 1);
-        if (!r)
-                return NULL;
+	r = malloc(a + b + 1);
+	if (!r)
+		return NULL;
 
-        memcpy(r, s, a);
-        memcpy(r + a, suffix, b);
-        r[a+b] = 0;
+	memcpy(r, s, a);
+	memcpy(r + a, suffix, b);
+	r[a+b] = 0;
 
-        return r;
+	return r;
 }
 
 /* concatenate two strings to a new string */
 char *ul_strconcat(const char *s, const char *suffix)
 {
-        return ul_strnconcat(s, suffix, suffix ? strlen(suffix) : 0);
+	return ul_strnconcat(s, suffix, suffix ? strlen(suffix) : 0);
 }
 
 /* concatenate @s and string defined by @format to a new string */
@@ -1088,20 +1088,20 @@ extern int ul_strvfappend(char **a, const char *format, va_list ap)
 
 static size_t strcspn_escaped(const char *s, const char *reject)
 {
-        int escaped = 0;
-        int n;
+	int escaped = 0;
+	int n;
 
-        for (n=0; s[n]; n++) {
-                if (escaped)
-                        escaped = 0;
-                else if (s[n] == '\\')
-                        escaped = 1;
-                else if (strchr(reject, s[n]))
-                        break;
-        }
+	for (n=0; s[n]; n++) {
+		if (escaped)
+			escaped = 0;
+		else if (s[n] == '\\')
+			escaped = 1;
+		else if (strchr(reject, s[n]))
+			break;
+	}
 
-        /* if s ends in \, return index of previous char */
-        return n - escaped;
+	/* if s ends in \, return index of previous char */
+	return n - escaped;
 }
 
 /*
@@ -1138,46 +1138,46 @@ char *ul_strchr_escaped(const char *s, int c)
 /* Split a string into words. */
 const char *ul_split(const char **state, size_t *l, const char *separator, int quoted)
 {
-        const char *current;
+	const char *current;
 
-        current = *state;
+	current = *state;
 
-        if (!*current) {
-                assert(**state == '\0');
-                return NULL;
-        }
+	if (!*current) {
+		assert(**state == '\0');
+		return NULL;
+	}
 
-        current += strspn(current, separator);
-        if (!*current) {
-                *state = current;
-                return NULL;
-        }
+	current += strspn(current, separator);
+	if (!*current) {
+		*state = current;
+		return NULL;
+	}
 
-        if (quoted && strchr("\'\"", *current)) {
-                char quotechars[2] = {*current, '\0'};
+	if (quoted && strchr("\'\"", *current)) {
+		char quotechars[2] = {*current, '\0'};
 
-                *l = strcspn_escaped(current + 1, quotechars);
-                if (current[*l + 1] == '\0' || current[*l + 1] != quotechars[0] ||
-                    (current[*l + 2] && !strchr(separator, current[*l + 2]))) {
-                        /* right quote missing or garbage at the end */
-                        *state = current;
-                        return NULL;
-                }
-                *state = current++ + *l + 2;
-        } else if (quoted) {
-                *l = strcspn_escaped(current, separator);
-                if (current[*l] && !strchr(separator, current[*l])) {
-                        /* unfinished escape */
-                        *state = current;
-                        return NULL;
-                }
-                *state = current + *l;
-        } else {
-                *l = strcspn(current, separator);
-                *state = current + *l;
-        }
+		*l = strcspn_escaped(current + 1, quotechars);
+		if (current[*l + 1] == '\0' || current[*l + 1] != quotechars[0] ||
+		    (current[*l + 2] && !strchr(separator, current[*l + 2]))) {
+			/* right quote missing or garbage at the end */
+			*state = current;
+			return NULL;
+		}
+		*state = current++ + *l + 2;
+	} else if (quoted) {
+		*l = strcspn_escaped(current, separator);
+		if (current[*l] && !strchr(separator, current[*l])) {
+			/* unfinished escape */
+			*state = current;
+			return NULL;
+		}
+		*state = current + *l;
+	} else {
+		*l = strcspn(current, separator);
+		*state = current + *l;
+	}
 
-        return current;
+	return current;
 }
 
 /* Rewind file pointer forward to new line.  */
diff --git a/lib/sysfs.c b/lib/sysfs.c
index c888617b7..13977ee5b 100644
--- a/lib/sysfs.c
+++ b/lib/sysfs.c
@@ -183,7 +183,7 @@ char *sysfs_blkdev_get_name(struct path_cxt *pc, char *buf, size_t bufsiz)
 	char *name;
 	ssize_t	sz;
 
-        /* read /sys/dev/block/<maj:min> link */
+	/* read /sys/dev/block/<maj:min> link */
 	sz = ul_path_readlink(pc, link, sizeof(link), NULL);
 	if (sz < 0)
 		return NULL;
@@ -522,29 +522,29 @@ int sysfs_blkdev_is_removable(struct path_cxt *pc)
 }
 
 static int get_dm_wholedisk(struct path_cxt *pc, char *diskname,
-                size_t len, dev_t *diskdevno)
+                            size_t len, dev_t *diskdevno)
 {
-    int rc = 0;
-    char *name;
+	int rc = 0;
+	char *name;
 
-    /* Note, sysfs_blkdev_get_slave() returns the first slave only,
-     * if there is more slaves, then return NULL
-     */
-    name = sysfs_blkdev_get_slave(pc);
-    if (!name)
-        return -1;
+	/* Note: sysfs_blkdev_get_slave() returns the first slave only;
+	 * if there are more slaves, it returns NULL.
+	 */
+	name = sysfs_blkdev_get_slave(pc);
+	if (!name)
+		return -1;
 
-    if (diskname && len)
-        xstrncpy(diskname, name, len);
+	if (diskname && len)
+		xstrncpy(diskname, name, len);
 
-    if (diskdevno) {
-        *diskdevno = __sysfs_devname_to_devno(ul_path_get_prefix(pc), name, NULL);
-        if (!*diskdevno)
-            rc = -1;
-    }
+	if (diskdevno) {
+		*diskdevno = __sysfs_devname_to_devno(ul_path_get_prefix(pc), name, NULL);
+		if (!*diskdevno)
+			rc = -1;
+	}
 
-    free(name);
-    return rc;
+	free(name);
+	return rc;
 }
 
 /*
@@ -556,85 +556,84 @@ int sysfs_blkdev_get_wholedisk(	struct path_cxt *pc,
 				size_t len,
 				dev_t *diskdevno)
 {
-    int is_part = 0;
+	int is_part = 0;
 
-    if (!pc)
-        return -1;
+	if (!pc)
+		return -1;
 
-    is_part = ul_path_access(pc, F_OK, "partition") == 0;
-    if (!is_part) {
-        /*
-         * Extra case for partitions mapped by device-mapper.
-         *
-         * All regular partitions (added by BLKPG ioctl or kernel PT
-         * parser) have the /sys/.../partition file. The partitions
-         * mapped by DM don't have such file, but they have "part"
-         * prefix in DM UUID.
-         */
-        char *uuid = NULL, *tmp, *prefix;
+	is_part = ul_path_access(pc, F_OK, "partition") == 0;
+	if (!is_part) {
+		/*
+		 * Extra case for partitions mapped by device-mapper.
+		 *
+		 * All regular partitions (added by BLKPG ioctl or kernel PT
+		 * parser) have the /sys/.../partition file. The partitions
+		 * mapped by DM don't have such file, but they have "part"
+		 * prefix in DM UUID.
+		 */
+		char *uuid = NULL, *tmp, *prefix;
 
-	ul_path_read_string(pc, &uuid, "dm/uuid");
-	tmp = uuid;
-	prefix = uuid ? strsep(&tmp, "-") : NULL;
+		ul_path_read_string(pc, &uuid, "dm/uuid");
+		tmp = uuid;
+		prefix = uuid ? strsep(&tmp, "-") : NULL;
 
-        if (prefix && c_strncasecmp(prefix, "part", 4) == 0)
-            is_part = 1;
-        free(uuid);
+		if (prefix && c_strncasecmp(prefix, "part", 4) == 0)
+			is_part = 1;
+		free(uuid);
 
-        if (is_part &&
-            get_dm_wholedisk(pc, diskname, len, diskdevno) == 0)
-            /*
-             * partitioned device, mapped by DM
-             */
-            goto done;
+		if (is_part &&
+			get_dm_wholedisk(pc, diskname, len, diskdevno) == 0)
+			/*
+			 * partitioned device, mapped by DM
+			 */
+			goto done;
 
-        is_part = 0;
-    }
+		is_part = 0;
+	}
 
-    if (!is_part) {
-        /*
-         * unpartitioned device
-         */
-        if (diskname && !sysfs_blkdev_get_name(pc, diskname, len))
-            goto err;
-        if (diskdevno)
-            *diskdevno = sysfs_blkdev_get_devno(pc);
+	if (!is_part) {
+		/*
+		 * unpartitioned device
+		 */
+		if (diskname && !sysfs_blkdev_get_name(pc, diskname, len))
+			goto err;
+		if (diskdevno)
+			*diskdevno = sysfs_blkdev_get_devno(pc);
+	} else {
+		/*
+		 * partitioned device
+		 *  - readlink /sys/dev/block/8:1   = ../../block/sda/sda1
+		 *  - dirname  ../../block/sda/sda1 = ../../block/sda
+		 *  - basename ../../block/sda	  = sda
+		 */
+		char linkpath[PATH_MAX];
+		char *name;
+		ssize_t	linklen;
 
-    } else {
-        /*
-         * partitioned device
-         *  - readlink /sys/dev/block/8:1   = ../../block/sda/sda1
-         *  - dirname  ../../block/sda/sda1 = ../../block/sda
-         *  - basename ../../block/sda      = sda
-         */
-        char linkpath[PATH_MAX];
-        char *name;
-	ssize_t	linklen;
+		linklen = ul_path_readlink(pc, linkpath, sizeof(linkpath), NULL);
+		if (linklen < 0)
+			goto err;
 
-	linklen = ul_path_readlink(pc, linkpath, sizeof(linkpath), NULL);
-        if (linklen < 0)
-            goto err;
+		stripoff_last_component(linkpath);	  /* dirname */
+		name = stripoff_last_component(linkpath);   /* basename */
+		if (!name)
+			goto err;
 
-        stripoff_last_component(linkpath);      /* dirname */
-        name = stripoff_last_component(linkpath);   /* basename */
-        if (!name)
-            goto err;
+		sysfs_devname_sys_to_dev(name);
+		if (diskname && len)
+			xstrncpy(diskname, name, len);
 
-	sysfs_devname_sys_to_dev(name);
-        if (diskname && len)
-            xstrncpy(diskname, name, len);
-
-        if (diskdevno) {
-            *diskdevno = __sysfs_devname_to_devno(ul_path_get_prefix(pc), name, NULL);
-            if (!*diskdevno)
-                goto err;
-        }
-    }
+		if (diskdevno) {
+			*diskdevno = __sysfs_devname_to_devno(ul_path_get_prefix(pc), name, NULL);
+			if (!*diskdevno)
+				goto err;
+		}
+	}
 
 done:
-    return 0;
+	return 0;
 err:
-    return -1;
+	return -1;
 }
 
 int sysfs_devno_to_wholedisk(dev_t devno, char *diskname,
@@ -790,7 +789,7 @@ char *sysfs_blkdev_scsi_host_strdup_attribute(struct path_cxt *pc,
 		return NULL;
 
 	if (!(f = fopen(buf, "r" UL_CLOEXECSTR)))
-                return NULL;
+		return NULL;
 
 	rc = fscanf(f, "%1023[^\n]", buf);
 	fclose(f);
@@ -1093,7 +1092,7 @@ char *sysfs_chrdev_devno_to_devname(dev_t devno, char *buf, size_t bufsiz)
 	if (!pc)
 		return NULL;
 
-        /* read /sys/dev/char/<maj:min> link */
+	/* read /sys/dev/char/<maj:min> link */
 	sz = ul_path_readlink(pc, link, sizeof(link), NULL);
 	ul_unref_path(pc);
 
diff --git a/lib/timer.c b/lib/timer.c
index cfa18f6fd..2f7e90cd4 100644
--- a/lib/timer.c
+++ b/lib/timer.c
@@ -92,7 +92,7 @@ int setup_timer(struct ul_timer *timer,
 void cancel_timer(struct ul_timer *timer)
 {
 	setitimer(ITIMER_REAL, &timer->old_timer, NULL);
-        sigaction(SIGALRM, &timer->old_sa, NULL);
+	sigaction(SIGALRM, &timer->old_sa, NULL);
 
 }
 #endif /* !HAVE_TIMER_CREATE */
diff --git a/login-utils/login.c b/login-utils/login.c
index 402e17820..d847b81e7 100644
--- a/login-utils/login.c
+++ b/login-utils/login.c
@@ -1303,8 +1303,8 @@ static void load_credentials(struct login_context *cxt) {
 	struct path_cxt *pc;
 
 	env = safe_getenv("CREDENTIALS_DIRECTORY");
-        if (!env)
-                return;
+	if (!env)
+		return;
 
 	pc = ul_new_path("%s", env);
 	if (!pc) {
diff --git a/login-utils/sulogin-consoles.c b/login-utils/sulogin-consoles.c
index 93eeab111..7faf19da1 100644
--- a/login-utils/sulogin-consoles.c
+++ b/login-utils/sulogin-consoles.c
@@ -124,7 +124,7 @@ void emergency_do_mounts(void)
 	if (stat("/dev", &xt) == 0
 	    && rt.st_dev == xt.st_dev
 	    && mount("devtmpfs", "/dev", "devtmpfs",
-		     MS_RELATIME, "mode=0755,nr_inodes=0") == 0) {
+	             MS_RELATIME, "mode=0755,nr_inodes=0") == 0) {
 
 		emergency_flags |= MNT_DEVTMPFS;
 		mknod("/dev/console", S_IFCHR|S_IRUSR|S_IWUSR,
@@ -249,9 +249,9 @@ char* scandev(DIR *dir, const dev_t comparedev)
 			    "/dev/char/%u:%u", major(comparedev), minor(comparedev))) > 0 &&
 	    (size_t)len < sizeof(path)) {
 
-	    name = realpath(path, NULL);
-	    if (name)
-		    goto out;
+		name = realpath(path, NULL);
+		if (name)
+			goto out;
 	}
 
 	fd = dirfd(dir);
@@ -771,7 +771,7 @@ console:
 fallback:
 	if (fallback >= 0) {
 		const char *name;
-	        char *n;
+		char *n;
 		struct console *console;
 
 		if (device && *device != '\0')
diff --git a/misc-utils/findmnt.c b/misc-utils/findmnt.c
index 78511dca7..f1526bcad 100644
--- a/misc-utils/findmnt.c
+++ b/misc-utils/findmnt.c
@@ -812,14 +812,14 @@ static char *get_tabdiff_data(struct libmnt_fs *old_fs,
 		break;
 	case COL_OLD_OPTIONS:
 		if (old_fs && (change == MNT_TABDIFF_REMOUNT ||
-			       change == MNT_TABDIFF_UMOUNT)
+		               change == MNT_TABDIFF_UMOUNT)
 		           && mnt_fs_get_options(old_fs))
 			str = xstrdup(mnt_fs_get_options(old_fs));
 		break;
 	case COL_OLD_TARGET:
 		if (old_fs && (change == MNT_TABDIFF_MOVE ||
-			       change == MNT_TABDIFF_UMOUNT)
-			   && mnt_fs_get_target(old_fs))
+		               change == MNT_TABDIFF_UMOUNT)
+		           && mnt_fs_get_target(old_fs))
 			str = xstrdup(mnt_fs_get_target(old_fs));
 		break;
 	default:
@@ -1519,10 +1519,10 @@ static void __attribute__((__noreturn__)) usage(void)
 
 	fputs(USAGE_HEADER, out);
 	fprintf(out, _(
-	" %1$s [options]\n"
-	" %1$s [options] <device> | <mountpoint>\n"
-	" %1$s [options] <device> <mountpoint>\n"
-	" %1$s [options] [--source <device>] [--target <path> | --mountpoint <dir>]\n"),
+		" %1$s [options]\n"
+		" %1$s [options] <device> | <mountpoint>\n"
+		" %1$s [options] <device> <mountpoint>\n"
+		" %1$s [options] [--source <device>] [--target <path> | --mountpoint <dir>]\n"),
 		program_invocation_short_name);
 
 	fputs(USAGE_SEPARATOR, out);
@@ -1677,7 +1677,7 @@ static struct libscols_table *init_scols_table(struct findmnt *findmnt)
 						scols_wrapzero_nextchunk,
 						NULL);
 		if ((flags & FL_JSON) || use_filter)
-	                scols_column_set_json_type(cl, get_column_json_type(id, fl, NULL,
+			scols_column_set_json_type(cl, get_column_json_type(id, fl, NULL,
 									    flags));
 	}
 
diff --git a/misc-utils/lastlog2.c b/misc-utils/lastlog2.c
index e973b5461..be33f2ae3 100644
--- a/misc-utils/lastlog2.c
+++ b/misc-utils/lastlog2.c
@@ -68,10 +68,9 @@ static int print_entry(const char *user, int64_t ll_time,
 	/* Print only if newer than t days */
 	if (tflg && ((time (NULL) - ll_time) > t_days))
 		return 0;
-        /* this is necessary if you compile this on architectures with
-           a 32bit time_t type. */
-        time_t t_time = ll_time;
-        tm = localtime_r(&t_time, &tm_buf);
+	/* This is needed on architectures with a 32bit time_t type. */
+	time_t t_time = ll_time;
+	tm = localtime_r(&t_time, &tm_buf);
 	if (tm == NULL)
 		datep = "(unknown)";
 	else {
diff --git a/misc-utils/lsblk-devtree.c b/misc-utils/lsblk-devtree.c
index 07f67b4da..5e9d38da1 100644
--- a/misc-utils/lsblk-devtree.c
+++ b/misc-utils/lsblk-devtree.c
@@ -160,7 +160,7 @@ int lsblk_device_new_dependence(struct lsblk_device *parent, struct lsblk_device
 	dp->parent = parent;
 	list_add_tail(&dp->ls_parents, &child->parents);
 
-        DBG(DEV, ul_debugobj(parent, "add dependence 0x%p [%s->%s]", dp, parent->name, child->name));
+	DBG(DEV, ul_debugobj(parent, "add dependence 0x%p [%s->%s]", dp, parent->name, child->name));
 
 	return 0;
 }
@@ -307,16 +307,16 @@ int lsblk_devtree_add_root(struct lsblk_devtree *tr, struct lsblk_device *dev)
 	/* We don't increment reference counter for tr->roots list. The primary
 	 * reference is tr->devices */
 
-        DBG(TREE, ul_debugobj(tr, "add root device 0x%p [%s]", dev, dev->name));
-        list_add_tail(&dev->ls_roots, &tr->roots);
+	DBG(TREE, ul_debugobj(tr, "add root device 0x%p [%s]", dev, dev->name));
+	list_add_tail(&dev->ls_roots, &tr->roots);
 	return 0;
 }
 
 int lsblk_devtree_remove_root(struct lsblk_devtree *tr __attribute__((unused)),
 			      struct lsblk_device *dev)
 {
-        DBG(TREE, ul_debugobj(tr, "remove root device 0x%p [%s]", dev, dev->name));
-        list_del_init(&dev->ls_roots);
+	DBG(TREE, ul_debugobj(tr, "remove root device 0x%p [%s]", dev, dev->name));
+	list_del_init(&dev->ls_roots);
 
 	return 0;
 }
@@ -343,8 +343,8 @@ int lsblk_devtree_add_device(struct lsblk_devtree *tr, struct lsblk_device *dev)
 {
 	lsblk_ref_device(dev);
 
-        DBG(TREE, ul_debugobj(tr, "add device 0x%p [%s]", dev, dev->name));
-        list_add_tail(&dev->ls_devices, &tr->devices);
+	DBG(TREE, ul_debugobj(tr, "add device 0x%p [%s]", dev, dev->name));
+	list_add_tail(&dev->ls_devices, &tr->devices);
 	return 0;
 }
 
@@ -398,7 +398,7 @@ struct lsblk_device *lsblk_devtree_get_device(struct lsblk_devtree *tr, const ch
 
 int lsblk_devtree_remove_device(struct lsblk_devtree *tr, struct lsblk_device *dev)
 {
-        DBG(TREE, ul_debugobj(tr, "remove device 0x%p [%s]", dev, dev->name));
+	DBG(TREE, ul_debugobj(tr, "remove device 0x%p [%s]", dev, dev->name));
 
 	if (!lsblk_devtree_has_device(tr, dev))
 		return 1;
diff --git a/misc-utils/rename.c b/misc-utils/rename.c
index d7bf4c5d7..629c48840 100644
--- a/misc-utils/rename.c
+++ b/misc-utils/rename.c
@@ -147,8 +147,8 @@ static int do_symlink(char *from, char *to, char *s, int verbose, int noact,
 	ssize_t ssz;
 	struct stat sb;
 
-	if ( faccessat(AT_FDCWD, s, F_OK, AT_SYMLINK_NOFOLLOW) != 0 &&
-	     errno != EINVAL )
+	if (faccessat(AT_FDCWD, s, F_OK, AT_SYMLINK_NOFOLLOW) != 0 &&
+	    errno != EINVAL )
 	   /* Skip if AT_SYMLINK_NOFOLLOW is not supported; lstat() below will
 	      detect the access error */
 	{
diff --git a/sys-utils/ipcrm.c b/sys-utils/ipcrm.c
index 8e38f8d61..740d4f3c6 100644
--- a/sys-utils/ipcrm.c
+++ b/sys-utils/ipcrm.c
@@ -78,7 +78,7 @@ static void __attribute__((__noreturn__)) usage(void)
 
 static int remove_id(int type, int iskey, int id)
 {
-        int ret;
+	int ret;
 	char *errmsg;
 	/* needed to delete semaphores */
 	union semun arg;
diff --git a/sys-utils/ldattach.c b/sys-utils/ldattach.c
index 0bc97c903..eba8da126 100644
--- a/sys-utils/ldattach.c
+++ b/sys-utils/ldattach.c
@@ -304,9 +304,9 @@ int main(int argc, char **argv)
 		{"help", no_argument, NULL, 'h'},
 		{"version", no_argument, NULL, 'V'},
 		{"debug", no_argument, NULL, 'd'},
-	        {"intro-command", required_argument, NULL, 'c'},
-	        {"pause", required_argument, NULL, 'p'},
-	        {"mtu", required_argument, NULL, 'm'},
+		{"intro-command", required_argument, NULL, 'c'},
+		{"pause", required_argument, NULL, 'p'},
+		{"mtu", required_argument, NULL, 'm'},
 		{NULL, 0, NULL, 0}
 	};
 
diff --git a/sys-utils/losetup.c b/sys-utils/losetup.c
index 7da0ebbd0..aac495aee 100644
--- a/sys-utils/losetup.c
+++ b/sys-utils/losetup.c
@@ -830,7 +830,7 @@ int main(int argc, char **argv)
 		case OPT_SIZELIMIT:			/* --sizelimit */
 			sizelimit = strtosize_or_err(optarg, _("failed to parse size"));
 			flags |= LOOPDEV_FL_SIZELIMIT;
-                        break;
+			break;
 
 		case 'h':
 			usage();
diff --git a/sys-utils/lscpu-topology.c b/sys-utils/lscpu-topology.c
index 6e0782f64..460ba449b 100644
--- a/sys-utils/lscpu-topology.c
+++ b/sys-utils/lscpu-topology.c
@@ -465,7 +465,7 @@ static int read_caches(struct lscpu_cxt *cxt, struct lscpu_cpu *cpu)
 		if (ul_path_readf_s32(sys, &level, "cpu%d/cache/index%zu/level", num, i) != 0)
 			continue;
 		if (ul_path_readf_buffer(sys, buf, sizeof(buf),
-                                        "cpu%d/cache/index%zu/type", num, i) <= 0)
+		                         "cpu%d/cache/index%zu/type", num, i) <= 0)
 			continue;
 
 		if (id == -1)
diff --git a/sys-utils/lsns.c b/sys-utils/lsns.c
index 2e887e802..2fb4977f9 100644
--- a/sys-utils/lsns.c
+++ b/sys-utils/lsns.c
@@ -1593,16 +1593,16 @@ static void __attribute__((__noreturn__)) usage(void)
 
 static void __attribute__((__noreturn__)) list_colunms(struct lsns *ls)
 {
-   struct libscols_table *col_tb = xcolumn_list_table_new("lsns-columns", stdout, ls->raw, ls->json);
+	struct libscols_table *col_tb = xcolumn_list_table_new("lsns-columns", stdout, ls->raw, ls->json);
 
-   for (size_t i = 0; i < ARRAY_SIZE(infos); i++)
-           xcolumn_list_table_append_line(col_tb, infos[i].name,
-					  infos[i].json_type, NULL,
-					  _(infos[i].help));
-   scols_print_table(col_tb);
-   scols_unref_table(col_tb);
+	for (size_t i = 0; i < ARRAY_SIZE(infos); i++)
+		xcolumn_list_table_append_line(col_tb, infos[i].name,
+					       infos[i].json_type, NULL,
+					       _(infos[i].help));
+	scols_print_table(col_tb);
+	scols_unref_table(col_tb);
 
-   exit(EXIT_SUCCESS);
+	exit(EXIT_SUCCESS);
 }
 
 static int stat_self_ns (const char *ns, struct stat *st)
diff --git a/sys-utils/swapoff.c b/sys-utils/swapoff.c
index 21c8e1ee8..152d1e11b 100644
--- a/sys-utils/swapoff.c
+++ b/sys-utils/swapoff.c
@@ -96,7 +96,7 @@ static char *resolve_swapfile_tag(const char *name, const char *value)
 
 static int do_swapoff(const char *orig_special, int quiet, int canonic)
 {
-        const char *special = orig_special;
+	 const char *special = orig_special;
 	char *buf = NULL;
 	int rc = SWAPOFF_EX_OK;
 
diff --git a/sys-utils/tunelp.c b/sys-utils/tunelp.c
index 2201f81ce..c6ee0c6bb 100644
--- a/sys-utils/tunelp.c
+++ b/sys-utils/tunelp.c
@@ -247,7 +247,7 @@ int main(int argc, char **argv)
 	/* Need to open O_NONBLOCK in case ABORTOPEN is already set
 	 * and printer is off or off-line or in an error condition.
 	 * Otherwise we would abort...
-         */
+	 */
 	if (fd < 0)
 		err(EXIT_FAILURE, "%s", filename);
 
@@ -265,7 +265,7 @@ int main(int argc, char **argv)
 	 */
 	if (LPGETIRQ >= 0x0600 && ioctl(fd, LPGETIRQ, &irq) < 0
 	    && errno == EINVAL)
-	        /* We don't understand the new ioctls */
+		/* We don't understand the new ioctls */
 		offset = 0x0600;
 
 	cmds = cmdst;
diff --git a/sys-utils/unshare.c b/sys-utils/unshare.c
index 11aeae48e..7b177e618 100644
--- a/sys-utils/unshare.c
+++ b/sys-utils/unshare.c
@@ -1038,7 +1038,7 @@ int main(int argc, char *argv[])
 				kill_child_signo = SIGKILL;
 			}
 			break;
-                case OPT_KEEPCAPS:
+		case OPT_KEEPCAPS:
 			keepcaps = 1;
 			cap_last_cap(); /* Force last cap to be cached before we fork. */
 			break;
@@ -1056,11 +1056,11 @@ int main(int argc, char *argv[])
 		case 'w':
 			newdir = optarg;
 			break;
-                case OPT_MONOTONIC:
+		case OPT_MONOTONIC:
 			monotonic = strtos64_or_err(optarg, _("failed to parse monotonic offset"));
 			force_monotonic = 1;
 			break;
-                case OPT_BOOTTIME:
+		case OPT_BOOTTIME:
 			boottime = strtos64_or_err(optarg, _("failed to parse boottime offset"));
 			force_boottime = 1;
 			break;
@@ -1206,13 +1206,13 @@ int main(int argc, char *argv[])
 #endif
 	}
 
-        if (mapuser != (uid_t) -1 && !usermap)
+	if (mapuser != (uid_t) -1 && !usermap)
 		map_id(_PATH_PROC_UIDMAP, mapuser, real_euid);
 
-        /* Since Linux 3.19 unprivileged writing of /proc/self/gid_map
-         * has been disabled unless /proc/self/setgroups is written
-         * first to permanently disable the ability to call setgroups
-         * in that user namespace. */
+	/* Since Linux 3.19 unprivileged writing of /proc/self/gid_map
+	 * has been disabled unless /proc/self/setgroups is written
+	 * first to permanently disable the ability to call setgroups
+	 * in that user namespace. */
 	if (mapgroup != (gid_t) -1 && !groupmap) {
 		if (setgrpcmd == SETGROUPS_ALLOW)
 			errx(EXIT_FAILURE, _("options --setgroups=allow and "
diff --git a/sys-utils/zramctl.c b/sys-utils/zramctl.c
index 057e4a3c0..a890d1b9d 100644
--- a/sys-utils/zramctl.c
+++ b/sys-utils/zramctl.c
@@ -224,7 +224,7 @@ static int zram_wait_initialized(struct zram *z)
 	/* Wait up to 3 seconds. */
 	r = sd_event_add_time_relative(event, NULL, CLOCK_BOOTTIME, 3 * 1000 * 1000, 0, NULL, (void*) (intptr_t) (-ETIMEDOUT));
 	if (r < 0)
-	        return r;
+		return r;
 
 	/* Check if the device is already initialized. */
 #if HAVE_DECL_SD_DEVICE_OPEN
@@ -277,7 +277,7 @@ static int zram_lock(struct zram *z, int operation)
 #if HAVE_DECL_SD_DEVICE_OPEN
 	if (z->device) {
 		fd = sd_device_open(z->device, O_RDONLY|O_CLOEXEC|O_NONBLOCK|O_NOCTTY);
-	        if (fd < 0)
+		if (fd < 0)
 			return fd;
 	} else {
 #endif
@@ -909,7 +909,7 @@ int main(int argc, char **argv)
 		if (outarg && string_add_to_idarray(outarg,
 					columns, ARRAY_SIZE(columns),
 					&ncolumns, column_name_to_id) < 0)
-	                return EXIT_FAILURE;
+			return EXIT_FAILURE;
 
 		if (optind < argc) {
 			zram = new_zram(argv[optind++]);
diff --git a/term-utils/agetty.c b/term-utils/agetty.c
index f4d720448..d3b650023 100644
--- a/term-utils/agetty.c
+++ b/term-utils/agetty.c
@@ -1706,8 +1706,8 @@ static int issuefile_read_stream(struct issue *ie, FILE *f, struct options *op,
 static int issuedir_read(struct issue *ie, const char *dirname,
 			 struct options *op, struct termios *tp)
 {
-        int dd, nfiles, i;
-        struct dirent **namelist = NULL;
+	int dd, nfiles, i;
+	struct dirent **namelist = NULL;
 
 	dd = open(dirname, O_RDONLY|O_CLOEXEC|O_DIRECTORY);
 	if (dd < 0)
@@ -1943,9 +1943,9 @@ skip:
 	struct list_head *current = NULL;
 	char *name = NULL;
 
-        /* Reading all issue files and concatinating all contents to one content.
-         * The ordering rules are defineded in:
-         * https://github.com/uapi-group/specifications/blob/main/specs/configuration_files_specification.md
+	/* Reading all issue files and concatinating all contents to one content.
+	 * The ordering rules are defineded in:
+	 * https://github.com/uapi-group/specifications/blob/main/specs/configuration_files_specification.md
 	 *
 	 * Note that _PATH_RUNSTATEDIR (/run) is always read by ul_configs_file_list().
 	 */
@@ -3120,8 +3120,8 @@ static void load_credentials(struct options *op) {
 	struct path_cxt *pc;
 
 	env = safe_getenv("CREDENTIALS_DIRECTORY");
-        if (!env)
-                return;
+	if (!env)
+		return;
 
 	pc = ul_new_path("%s", env);
 	if (!pc) {
diff --git a/term-utils/mesg.c b/term-utils/mesg.c
index 3ff3b9e04..e51f659a6 100644
--- a/term-utils/mesg.c
+++ b/term-utils/mesg.c
@@ -173,8 +173,8 @@ int main(int argc, char *argv[])
 	case RPMATCH_INVALID:
 		warnx(_("invalid argument: %s"), argv[0]);
 		errtryhelp(EXIT_FAILURE);
-        default:
-                abort();
+	default:
+		abort();
 	}
 	close(fd);
 	return ret;
diff --git a/term-utils/script.c b/term-utils/script.c
index ff7f4409f..c4f23ca48 100644
--- a/term-utils/script.c
+++ b/term-utils/script.c
@@ -1079,7 +1079,7 @@ int main(int argc, char **argv)
 			log_info(&ctl, "INPUT_LOG", "%s", infile);
 	}
 
-        /* this is the main loop */
+	/* this is the main loop */
 	rc = ul_pty_proxy_master(ctl.pty);
 
 	/* all done; cleanup and kill */
diff --git a/term-utils/scriptreplay.c b/term-utils/scriptreplay.c
index 7e1eec7db..3efcd3015 100644
--- a/term-utils/scriptreplay.c
+++ b/term-utils/scriptreplay.c
@@ -175,8 +175,8 @@ main(int argc, char *argv[])
 	char streams[6] = {0};		/* IOSI - in, out, signal,info */
 	const char *log_out = NULL,
 	           *log_in = NULL,
-		   *log_io = NULL,
-		   *log_tm = NULL;
+	           *log_io = NULL,
+	           *log_tm = NULL;
 	double divi = 1;
 	int diviopt = FALSE, idx;
 	int ch, rc = 0, crmode = REPLAY_CRMODE_AUTO, summary = 0;
diff --git a/text-utils/col.c b/text-utils/col.c
index 5866d7d0e..ddf2a6109 100644
--- a/text-utils/col.c
+++ b/text-utils/col.c
@@ -601,45 +601,44 @@ static void free_line_allocations(struct col_alloc *root)
 
 static void process_char(struct col_ctl *ctl, struct col_lines *lns)
 {
-                /* Deal printable characters */
-                if (!iswgraph(lns->ch) && handle_not_graphic(ctl, lns))
-                        return;
+	/* Deal with non-printable characters. */
+	if (!iswgraph(lns->ch) && handle_not_graphic(ctl, lns))
+		return;
 
-                /* Must stuff ch in a line - are we at the right one? */
-                if ((size_t)lns->cur_line != lns->this_line - lns->adjust)
-                        update_cur_line(ctl, lns);
+	/* Must stuff ch in a line - are we at the right one? */
+	if ((size_t)lns->cur_line != lns->this_line - lns->adjust)
+		update_cur_line(ctl, lns);
 
-                /* Does line buffer need to grow? */
-                if (ctl->l->l_lsize <= ctl->l->l_line_len + 1) {
-                        size_t need;
+	/* Does line buffer need to grow? */
+	if (ctl->l->l_lsize <= ctl->l->l_line_len + 1) {
+		size_t need;
 
-                        need = ctl->l->l_lsize ? ctl->l->l_lsize * 2 : NALLOC;
-                        ctl->l->l_line = xrealloc(ctl->l->l_line, need * sizeof(struct col_char));
-                        ctl->l->l_lsize = need;
-                }
+		need = ctl->l->l_lsize ? ctl->l->l_lsize * 2 : NALLOC;
+		ctl->l->l_line = xrealloc(ctl->l->l_line, need * sizeof(struct col_char));
+		ctl->l->l_lsize = need;
+	}
 
-                /* Store character */
-                lns->c = &ctl->l->l_line[ctl->l->l_line_len++];
-                lns->c->c_char = lns->ch;
-                lns->c->c_set = lns->cur_set;
+	/* Store character */
+	lns->c = &ctl->l->l_line[ctl->l->l_line_len++];
+	lns->c->c_char = lns->ch;
+	lns->c->c_set = lns->cur_set;
 
-                if (0 < lns->cur_col)
-                        lns->c->c_column = lns->cur_col;
-                else
-                        lns->c->c_column = 0;
-                lns->c->c_width = wcwidth(lns->ch);
-
-                /*
-                 * If things are put in out of order, they will need sorting
-                 * when it is flushed.
-                 */
-                if (lns->cur_col < ctl->l->l_max_col)
-                        ctl->l->l_needs_sort = 1;
-                else
-                        ctl->l->l_max_col = lns->cur_col;
-                if (0 < lns->c->c_width)
-                        lns->cur_col += lns->c->c_width;
+	if (0 < lns->cur_col)
+		lns->c->c_column = lns->cur_col;
+	else
+		lns->c->c_column = 0;
+	lns->c->c_width = wcwidth(lns->ch);
 
+	/*
+	 * If things are put in out of order, they will need sorting
+	 * when it is flushed.
+	 */
+	if (lns->cur_col < ctl->l->l_max_col)
+		ctl->l->l_needs_sort = 1;
+	else
+		ctl->l->l_max_col = lns->cur_col;
+	if (0 < lns->c->c_width)
+		lns->cur_col += lns->c->c_width;
 }
 
 int main(int argc, char **argv)
diff --git a/text-utils/hexdump-display.c b/text-utils/hexdump-display.c
index c865127c8..b605cad44 100644
--- a/text-utils/hexdump-display.c
+++ b/text-utils/hexdump-display.c
@@ -448,7 +448,7 @@ doskip(const char *fname, int statok, struct hexdump *hex)
 
 	if (statok) {
 		if (fstat(fileno(stdin), &sbuf))
-		        err(EXIT_FAILURE, "%s", fname);
+			err(EXIT_FAILURE, "%s", fname);
 		if (S_ISREG(sbuf.st_mode) && hex->skip > sbuf.st_size) {
 		  /* If size valid and skip >= size */
 			hex->skip -= sbuf.st_size;
@@ -458,7 +458,7 @@ doskip(const char *fname, int statok, struct hexdump *hex)
 	}
 	/* sbuf may be undefined here - do not test it */
 	if (fseek(stdin, hex->skip, SEEK_SET))
-	        err(EXIT_FAILURE, "%s", fname);
+		err(EXIT_FAILURE, "%s", fname);
 	address += hex->skip;
 	hex->skip = 0;
 }
diff --git a/text-utils/hexdump-parse.c b/text-utils/hexdump-parse.c
index 018013e5e..efc39c3b3 100644
--- a/text-utils/hexdump-parse.c
+++ b/text-utils/hexdump-parse.c
@@ -52,22 +52,22 @@ static struct list_head *color_fmt(char *cfmt, int bcnt);
 
 static void __attribute__ ((__noreturn__)) badcnt(const char *s)
 {
-        errx(EXIT_FAILURE, _("bad byte count for conversion character %s"), s);
+	errx(EXIT_FAILURE, _("bad byte count for conversion character %s"), s);
 }
 
 static void __attribute__ ((__noreturn__)) badsfmt(void)
 {
-        errx(EXIT_FAILURE, _("%%s requires a precision or a byte count"));
+	errx(EXIT_FAILURE, _("%%s requires a precision or a byte count"));
 }
 
 static void __attribute__ ((__noreturn__)) badfmt(const char *fmt)
 {
-        errx(EXIT_FAILURE, _("bad format {%s}"), fmt);
+	errx(EXIT_FAILURE, _("bad format {%s}"), fmt);
 }
 
 static void __attribute__ ((__noreturn__)) badconv(const char *ch)
 {
-        errx(EXIT_FAILURE, _("bad conversion character %%%s"), ch);
+	errx(EXIT_FAILURE, _("bad conversion character %%%s"), ch);
 }
 
 #define first_letter(s,f) strchr(f, *(s))
@@ -81,7 +81,7 @@ void addfile(char *name, struct hexdump *hex)
 	size_t n = 0;
 
 	if ((fp = fopen(name, "r")) == NULL)
-	        err(EXIT_FAILURE, _("can't read %s"), name);
+		err(EXIT_FAILURE, _("can't read %s"), name);
 
 	while (getline(&buf, &n, fp) != -1) {
 		fmt = buf;
diff --git a/text-utils/hexdump.c b/text-utils/hexdump.c
index 60bf6f94b..ba8d5e1f6 100644
--- a/text-utils/hexdump.c
+++ b/text-utils/hexdump.c
@@ -116,7 +116,7 @@ parse_args(int argc, char **argv, struct hexdump *hex)
 			colormode = UL_COLORMODE_AUTO;
 			if (optarg)
 				colormode = colormode_or_err(optarg);
-                        break;
+			break;
 		case 'n':
 			hex->length = strtosize_or_err(optarg, _("failed to parse length"));
 			break;
-- 
2.51.2


^ permalink raw reply related

* [PATCH 1/2] losetup: snip --verbose from bash-completion, and 'v' from options string
From: Benno Schulenberg @ 2025-11-15 10:35 UTC (permalink / raw)
  To: util-linux

This should have been part of commit 7e27c81597 from two weeks ago.

Signed-off-by: Benno Schulenberg <bensberg@telfort.nl>
---
 bash-completion/losetup | 1 -
 sys-utils/losetup.c     | 2 +-
 2 files changed, 1 insertion(+), 2 deletions(-)

diff --git a/bash-completion/losetup b/bash-completion/losetup
index 2d314c111..bf1591fbf 100644
--- a/bash-completion/losetup
+++ b/bash-completion/losetup
@@ -59,7 +59,6 @@ _losetup_module()
 				--read-only
 				--remove
 				--show
-				--verbose
 				--direct-io
 				--loop-ref
 				--sector-size
diff --git a/sys-utils/losetup.c b/sys-utils/losetup.c
index 7da0ebbd0..fe30d70da 100644
--- a/sys-utils/losetup.c
+++ b/sys-utils/losetup.c
@@ -751,7 +751,7 @@ int main(int argc, char **argv)
 	if (loopcxt_init(&lc, 0))
 		err(EXIT_FAILURE, _("failed to initialize loopcxt"));
 
-	while ((c = getopt_long(argc, argv, "ab:cdDfhj:JlLno:O:PrvV",
+	while ((c = getopt_long(argc, argv, "ab:cdDfhj:JlLno:O:PrV",
 				longopts, NULL)) != -1) {
 
 		err_exclusive_options(c, longopts, excl, excl_st);
-- 
2.51.2


^ permalink raw reply related

* [PATCH 2/2] chmem: do not word a configuration failure as an instruction to the user
From: Benno Schulenberg @ 2025-11-15 10:35 UTC (permalink / raw)
  To: util-linux; +Cc: Sumanth Korikkar
In-Reply-To: <20251115103504.6360-1-bensberg@telfort.nl>

When the current machine does not support configuring/deconfiguring
memory, simply report that it cannot be done, instead of seemingly
telling the user to skip the configuring/deconfiguring.

Also, there is no need to mention `chmem` in the message: mentioning
just the recommended option (-e or -d) is enough.  Also, consistently
terminate all four messages with a period.

This improves upon commit ab2e709600 ("chmem: improve messages").

CC: Sumanth Korikkar <sumanthk@linux.ibm.com>
Signed-off-by: Benno Schulenberg <bensberg@telfort.nl>
---
 sys-utils/chmem.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/sys-utils/chmem.c b/sys-utils/chmem.c
index 6ec66bb6b..dcec888d1 100644
--- a/sys-utils/chmem.c
+++ b/sys-utils/chmem.c
@@ -325,10 +325,10 @@ static int chmem_config_size(struct chmem_desc *desc, int configure)
 	if (!desc->have_memconfig) {
 		if (configure)
 			fprintf(stdout,
-				_("Skip configuration. Use chmem -e instead.\n"));
+				_("Cannot configure. Use -e instead.\n"));
 		else
 			fprintf(stdout,
-				_("Skip deconfiguration. Use chmem -d instead\n"));
+				_("Cannot deconfigure. Use -d instead.\n"));
 		return -1;
 	}
 	size = desc->size;
@@ -363,10 +363,10 @@ static int chmem_config_range(struct chmem_desc *desc, int configure)
 	if (!desc->have_memconfig) {
 		if (configure)
 			fprintf(stdout,
-				_("Skip configuration. Use chmem -e instead.\n"));
+				_("Cannot configure. Use -e instead.\n"));
 		else
 			fprintf(stdout,
-				_("Skip deconfiguration. Use chmem -d instead\n"));
+				_("Cannot deconfigure. Use -d instead.\n"));
 		return -1;
 	}
 	todo = desc->end - desc->start + 1;
-- 
2.51.2


^ permalink raw reply related

* Re: Fwd: lsclocks and tai
From: Thomas Weißschuh @ 2025-11-13 15:51 UTC (permalink / raw)
  To: Sami Kerola; +Cc: util-linux
In-Reply-To: <CAG27Bk33x9ztXSX7AJb_=5QVJRY3ir0ZppMSOgVUS0XnagrvFw@mail.gmail.com>

Hi Sami,

On 2025-11-04 13:58:35+0000, Sami Kerola wrote:
> Meanwhile. There was a workplace discussion about TAI and I noticed
> unexpected lsclock.
> 
> $ lsclocks -o ISO_TIME,NAME | grep tai && TZ=right/UTC date --iso=ns
> 2025-11-04T13:58:14.176151344+00:00 tai
> 2025-11-04T13:57:47,177638531+00:00
> 
> One would hope above timings always match. If I force the timezone for
> the lsclock output will match, but this has downside of all the other
> listings use TAI zone.

I can't really follow what you mean with this. The only difference is
the printed time and that is expected, as TAI is (currently) 37 seconds
behind UTC.

> $ TZ=right/UTC lsclocks -o ISO_TIME,NAME | grep tai && TZ=right/UTC
> date --iso=ns
> 
> Perhaps the realtime outputs to use local time, and TAI to be always
> right/UTC. Any thoughts?

TAI does not have any timezone at all. Realtime does have one. For PTP
and RTC clocks it may depend on circumstances. Currently everything uses
+00:00 for consistency.


Thomas

^ permalink raw reply

* Experimental pager: lsp
From: Dirk Gouders @ 2025-11-08 22:41 UTC (permalink / raw)
  To: util-linux

Hello,

some time ago (in May), I talked to Karel and he told me it would be OK
for him if I write in util-linux about a terminal pager I am working on.
Hopefully some of the experts here will find it interesting
enough and the time to play with it and give some feedback.

The pager's name is lsp - list pages (or least significant pager).
Perhaps somewhat unlucky, because of "Language Server Protocol", but
when I started it and searched the web I didn't realize any name
collisions.

Anyway, you will certainly ask "Who needs just another pager?".
I implemented some features I was always missing in other pagers:

- On window resizes, reload manual pages to fit the new window size.
- Manual pages refer to others: allow to navigate to them.
  (And offer such links only if those manual pages exist on the running
   system, i.e. validate those references.)
- Allow to open other manual pages and to switch among all opened files.

Besides these "musts", I implemented a 3-level TOC mode that allows for
faster (or a different way of) navigation in large manual pages.

Further, an apropos buffer can be created to have all manual pages
available and be able to visit them.

Another nuance is the positioning of search matches: when I walk through
git logs, I often want to move commit-wise and ideally have the
commits starting in the first line.  In lsp I search for "^commit",
press ^l twice and from then on 'n' navigates to the next commit,
positioning it to the first line.

A latest feature that I implemented is the possibility to restart the
parent process (currently only git).  I find this useful when I do
`git diff` before adding changes and realize whitespace changes or other
small nits.  I then keep the diff-session, correct those nits in my
editor and in the diff-session just press 'r' to see those changes.

Finally, the negative part: lsp currently has no raw mode, i.e. it uses
ncurses and does all interpretation of SGR and backspace sequences.
Raw mode is the next thing I want to realize.


In case you are interested, lsp can be found at:

https://github.com/dgouders/lsp

Please use the next branch that has some recent fixes.

If you use Gentoo, lsp can be found in the GURU repo.

But manual installation isn't that hard, because ncurses is lsp's single
dependency, besides meson for installation.

Thank you and pardon in case you feel disturbed by this,

Dirk

^ permalink raw reply

* Re: [PATCH 1/2] lscpu-arm: Allow externally sourced model name.
From: Paul Benoit @ 2025-11-07 21:45 UTC (permalink / raw)
  To: Jeremy Linton, util-linux
In-Reply-To: <935fd521-508a-4f66-9ece-7ccf2eea61b9@arm.com>

On 7/11/2025 6:22 PM, Jeremy Linton wrote:
> Hi,
> 
> On 7/11/25 4:16 PM, Paul Benoit wrote:
>> When there isn't an entry for the model name in the id_part table(s),
>> attempt to get the machine name from /sys/bus/soc/devices/soc0/machine
>> to use as the model name.  This mechanism allows lscpu to use the
>> model/machine name provided via the ARM SMC support code rather than via
>> hard-coded lscpu tables.
> 
> Since this is suppose to be synced with the DMI data, and is sourced 
> from the firmware would it make more sense to replace the BIOS name with 
> it?

I was recently reminded that the SMC CC SOC_ID Name
(/sys/bus/soc/devices/soc0/machine) and BIOS name could be from 2
different organizations, and may not always resemble each other.

> 
> 
>>
>> This code was tested by removing the "Ampere-1a" entry from the
>> ampere-part table and verifying that lscpu displayed the correct machine
>> name obtained via the ARM SMC interface to Trusted Firmware.  The
>> "Ampere-1a" entry will be permanently removed by a separate patch.
>>
>> Signed-off-by: Paul Benoit <paul@os.amperecomputing.com>
>> ---
>>   sys-utils/lscpu-arm.c | 35 ++++++++++++++++++++++++++++++++---
>>   sys-utils/lscpu.h     |  1 +
>>   2 files changed, 33 insertions(+), 3 deletions(-)
>>
>> diff --git a/sys-utils/lscpu-arm.c b/sys-utils/lscpu-arm.c
>> index 8745599d4..a46106bcb 100644
>> --- a/sys-utils/lscpu-arm.c
>> +++ b/sys-utils/lscpu-arm.c
>> @@ -388,7 +388,10 @@ int is_arm(struct lscpu_cxt *cxt)
>>   static int arm_ids_decode(struct lscpu_cputype *ct)
>>   {
>>       int impl, part, j;
>> +    unsigned int i;
>>       const struct id_part *parts = NULL;
>> +    FILE *fd;
>> +    char machinename[BUFSIZ] = "";
>>       impl = parse_implementer_id(ct);
>>       if (impl <= 0)
>> @@ -406,11 +409,11 @@ static int arm_ids_decode(struct lscpu_cputype *ct)
>>       /* decode model */
>>       if (!parts)
>> -        goto done;
>> +        goto try_machinename;
>>       part = parse_model_id(ct);
>>       if (part <= 0)
>> -        goto done;
>> +        goto try_machinename;
>>       for (j = 0; parts[j].id != -1; j++) {
>>           if (parts[j].id == part) {
>> @@ -419,7 +422,33 @@ static int arm_ids_decode(struct lscpu_cputype *ct)
>>               break;
>>           }
>>       }
>> -done:
>> +
>> +try_machinename:
>> +
>> +    /*
>> +     * If the Model name was not found in the lscpu 'id_part' tables, 
>> see
>> +     * if there is a Machine name associated with the SOC.  This name 
>> may
>> +     * have been set via either SOC specific support code, or obtained
>> +     * via an ARM SMC CC call into Trusted Firmware.
>> +     */
>> +    if (!ct->modelname) {
>> +        fd = ul_path_fopen(NULL, "r", _PATH_SOC_MACHINENAME);
>> +        if (fd) {
>> +            if (!fgets(machinename, sizeof(machinename), fd))
>> +                machinename[0] = '\0';
>> +            fclose(fd);
>> +
>> +            /* Replace newline with string terminator */
>> +            for (i = 0; i < strlen(machinename); i++) {
>> +                if (machinename[i] == '\n')
>> +                    machinename[i] = '\0';
>> +            }
>> +
>> +            if (strnlen(machinename, sizeof(machinename)))
>> +                ct->modelname = xstrdup(machinename);
>> +        }
>> +    }
>> +
>>       return 0;
>>   }
>> diff --git a/sys-utils/lscpu.h b/sys-utils/lscpu.h
>> index bd7b64cc5..581602f70 100644
>> --- a/sys-utils/lscpu.h
>> +++ b/sys-utils/lscpu.h
>> @@ -46,6 +46,7 @@ UL_DEBUG_DECLARE_MASK(lscpu);
>>   #define _PATH_SYS_NODE        _PATH_SYS_SYSTEM "/node"
>>   #define _PATH_SYS_DMI        "/sys/firmware/dmi/tables/DMI"
>>   #define _PATH_ACPI_PPTT        "/sys/firmware/acpi/tables/PPTT"
>> +#define _PATH_SOC_MACHINENAME    "/sys/bus/soc/devices/soc0/machine"
>>   struct lscpu_cache {
>>       int        id;        /* unique identifier */
> 


^ permalink raw reply

* Re: [PATCH 2/2] lscpu-arm: Remove the "Ampere-1a" part.
From: Paul Benoit @ 2025-11-07 21:26 UTC (permalink / raw)
  To: Karel Zak, Jeremy Linton; +Cc: util-linux
In-Reply-To: <muus4f4qyxjt3af2nxjois2twuvbfnbf37glsyiptslb4orglf@rnvwiszoffgl>

On 7/15/2025 5:19 AM, Karel Zak wrote:
> On Mon, Jul 14, 2025 at 03:48:50PM -0500, Jeremy Linton wrote:
>> On 7/14/25 7:16 AM, Karel Zak wrote:
>>> On Fri, Jul 11, 2025 at 02:16:48PM -0700, Paul Benoit wrote:
>>>> Remove the "Ampere-1a" part.  On newer Ampere Computing systems, the
>>>> system/model name will be obtained from /sys/bus/soc/devices/soc0/machine,
>>>> that is populated with the ARM SMC CC SOC_ID Name.
>>>
>>> If I understand correctly, there are old systems without
>>> /sys/.../soc0/machine, right? The change will remove Ampere-1a from
>>> the lscpu output. This sounds backward incompatible.
>>
>> Thats a good point, but as I understand it, Ampere hasn't been happy with
>> the string that is there.
> 
> We can update the string to make them happy.
> 
>> If its OK to break whatever scripts/etc might depend on it at the moment,
>> why not just update the string.
>>
>> Then invert the check so that the /sys/bus entry is preferred?
> 
> I still do not understand how a per-CPU identifier can be replaced by
> one soc0 path. What if there is soc1, soc2, etc.?

Yes, I agree that /sys/bus/soc/devices/soc0/machine shouldn't be used
for processors/cpus in soc1..socn unless all physical SOCs are mapped by
soc0.  My recollection is that I only saw the one /sys/bus/devices/soc0
on an SMC compliant system with 2 SOCs.  The smccc_soc_init routine is
what calls soc_device_register once.  The support code for other ARM
SOCs call soc_device_register from a *_probe routine (run once per
SOC?).  As per my other reply in this thread today,
/sys/bus/soc/devices/soc0/machine will only be used for a SMC CC
compliant SOC.

> 
> Anyway, using /sys/bus as the primary source and the hardcoded id_part[]
> array as a fallback seems better than removing anything from id_part[]
> and relying on /sys/bus only.
> 
>      Karel
> 


^ permalink raw reply

* Re: [PATCH 2/2] lscpu-arm: Remove the "Ampere-1a" part.
From: Paul Benoit @ 2025-11-07 20:48 UTC (permalink / raw)
  To: Jeremy Linton, Karel Zak; +Cc: util-linux
In-Reply-To: <fb54d607-dccc-419f-b92c-7bc8514213a6@arm.com>

Thanks for your input Jeremy and Karel.

I apologize for taking so long to get back to this project.

On 7/14/2025 4:48 PM, Jeremy Linton wrote:
> On 7/14/25 7:16 AM, Karel Zak wrote:
>> On Fri, Jul 11, 2025 at 02:16:48PM -0700, Paul Benoit wrote:
>>> Remove the "Ampere-1a" part.  On newer Ampere Computing systems, the
>>> system/model name will be obtained from /sys/bus/soc/devices/soc0/ 
>>> machine,
>>> that is populated with the ARM SMC CC SOC_ID Name.
>>
>> If I understand correctly, there are old systems without
>> /sys/.../soc0/machine, right? The change will remove Ampere-1a from
>> the lscpu output. This sounds backward incompatible.
> 
> Thats a good point, but as I understand it, Ampere hasn't been happy 
> with the string that is there.
> 
> If its OK to break whatever scripts/etc might depend on it at the 
> moment, why not just update the string.

For SOCs using SMC CC compliant firmware, I do like that having lscpu
use /sys/bus/soc/devices/soc0/machine means that the name for a new
SMC SOC would be displayed without needing to update the lscpu part(s)
table.  Though, I'm concerned that the SMC CC SOC_ID Name won't always
be a direct mapping to a processor/cpu name.  Especially for a SOC that
contains a mix of BIG/little, performance/efficiency, and/or special
purpose cores.  When all the cores of a SOC are the same, then it is
probably ok to equate the SMC CC SOC_ID Name with the processor/cpu part 
name.

For SMC CC compliant SOCs, perhaps it makes more sense to have lscpu
display the /sys/bus/soc/devices/soc0/machine value as a new
"SOC_ID Name" value in a manner similar to the "BIOS Model name"?  Would
changes be required to lscpu to select such a "SOC_ID Name" field from
the lscpu command line, or would it be sufficient to only display this
SOC_ID Name field in lscpu modes where the detailed/complete
cpu/processor information is displayed?  If lscpu were to display the
/sys/bus/soc/devices/soc0/machines value as "SOC_ID Name", then the
Ampere cpus/processor names would need to continue to come from the
lscpu part(s) table. Though, The existing names in the "ampere_part"
table would still need to change.

> 
> Then invert the check so that the /sys/bus entry is preferred?

Prior to my V1 lscpu patch, when I first made some lscpu changes as a
way to test the SMC CC SOC_ID Name kernel changes, I had originally been
checking for /sys/bus/soc/devices/soc0/machine before looking for an
entry in the part(s) table.  My concern with that was for the non-SMC
SOCs, for which there was both a part(s) table entry and
/sys/bus/soc/devices/soc0/machine was set.  If the string in the part(s)
table was not the same as the /sys/bus/soc/devices/soc0/machine string,
lscpu would then be displaying a different string than it had in the
past.  That is why my V1 patch switched to using the
/sys/bus/soc/devices/soc0/machine value only if there wasn't an entry
in the part(s) table.  A way to reduce the risk, of now using
/sys/bus/soc/devices/soc0/machine instead of the part(s) table entry for
a non-SMC SOC, would be for lscpu to only use the
/sys/bus/soc/devices/soc0/machine value if the value of
/sys/devices/soc0/soc_id starts with "jep106:".
Documentation/ABI/testing/sysfs-devices-soc in the Linux kernel tree
says
     "On many of ARM based silicon with SMCCC v1.2+ compliant firmware
     this will contain the SOC ID appended to the family attribute
     to ensure there is no conflict in this namespace across various
     vendors. The format is "jep106:XXYY:ZZZZ" where XX is identity
     code, YY is continuation code and ZZZZ is the SOC ID."

A search of the Linux kernel code confirms that only
drivers/firmware/smccc/soc_id.c is generating/using the "jep106:"
string.

^ permalink raw reply

* Re: `losetup --remove` is confusing, and misuse silently fails
From: Benno Schulenberg @ 2025-11-07 11:21 UTC (permalink / raw)
  To: Karel Zak; +Cc: Util-Linux
In-Reply-To: <pdmvdt2cdvr57pwsyz3g7eehtyni2e5zfnz76mhf5rcsjwcfmm@kf7ergmarrsi>


[-- Attachment #1.1: Type: text/plain, Size: 905 bytes --]


Op 07-11-2025 om 11:16 schreef Karel Zak:
> On Mon, Nov 03, 2025 at 03:42:50PM +0100, Benno Schulenberg wrote:
>> For translatability, the above should be like:
>>
>> 	fprintf(stderr, _("%s: options %s and %s cannot be combined"), ...);
> 
> Yes, I know. The problem is that we need an extra buffer in the case
> of the short-only option. I have updated the pull request to make it
> more elegant. Now it uses:
> 
>      errx(OPTUTILS_EXIT_CODE,
>          _("options %s%s and %s%s cannot be combined"),
>          ....


That wil work.  Thanks!


In the commit message it says for NEW:

     $ losetup --remove --detach loop0
     losetup: options --detach and --remove cannot be combined.

But the actual error message is:

     losetup: options --remove and --detach cannot be combined

(the options in the order as on the command line and without a period).


Benno


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

^ permalink raw reply

* Re: `losetup --remove` is confusing, and misuse silently fails
From: Karel Zak @ 2025-11-07 10:16 UTC (permalink / raw)
  To: Benno Schulenberg; +Cc: Util-Linux
In-Reply-To: <7b928196-6485-4514-a336-5c403652a0c3@telfort.nl>

On Mon, Nov 03, 2025 at 03:42:50PM +0100, Benno Schulenberg wrote:
> 
> Op 03-11-2025 om 13:49 schreef Karel Zak:
> > >    # ./losetup --remove --find --all
> > >    losetup: options --remove and --find cannot be combined
> > Implemented:
> >      https://github.com/util-linux/util-linux/pull/3835
> 
> Thanks!  However...
> 
> 	fprintf(stderr, _("%s: options "), program_invocation_short_name);
> 	ul_print_option(stderr, status[e], opts);
> 	fputs(_(" and "), stderr);
> 	ul_print_option(stderr, c, opts);
> 	fputs(_(" cannot be combined.\n"), stderr);
> 
> For translatability, the above should be like:
> 
> 	fprintf(stderr, _("%s: options %s and %s cannot be combined"), ...);
> 
> 
> See for example `info gettext prep prep`, saying that translatable strings
> should be entire sentences.

Yes, I know. The problem is that we need an extra buffer in the case
of the short-only option. I have updated the pull request to make it
more elegant. Now it uses:

    errx(OPTUTILS_EXIT_CODE,
        _("options %s%s and %s%s cannot be combined"),
        ....

so it's just one string.

    Karel




-- 
 Karel Zak  <kzak@redhat.com>
 http://karelzak.blogspot.com


^ permalink raw reply

* [PATCH v2 2/3] losetup: remove the --verbose flag, as it doesn't actually do anything
From: Benno Schulenberg @ 2025-11-05  7:15 UTC (permalink / raw)
  To: util-linux

Fourteen years ago, commit c7e0925def rewrote the `losetup` tool,
removing all references to the 'verbose' variable.  Three years
later, commit 60cb2c3720 removed the line 'verbose = 1' because
the compiler complained that the variable was set but never used.

Signed-off-by: Benno Schulenberg <bensberg@telfort.nl>

---
V2: Remove --verbose also from bash-completion and getopt_long() call.

---
 bash-completion/losetup  | 1 -
 sys-utils/losetup.8.adoc | 3 ---
 sys-utils/losetup.c      | 6 +-----
 3 files changed, 1 insertion(+), 9 deletions(-)

diff --git a/bash-completion/losetup b/bash-completion/losetup
index 783d966c7..2eedcd767 100644
--- a/bash-completion/losetup
+++ b/bash-completion/losetup
@@ -59,7 +59,6 @@ _losetup_module()
 				--read-only
 				--remove
 				--show
-				--verbose
 				--json
 				--list
 				--noheadings
diff --git a/sys-utils/losetup.8.adoc b/sys-utils/losetup.8.adoc
index f51710af8..131ebfa56 100644
--- a/sys-utils/losetup.8.adoc
+++ b/sys-utils/losetup.8.adoc
@@ -106,9 +106,6 @@ Set up a read-only loop device.
 *--direct-io*[**=on**|*off*]::
 Enable or disable direct I/O for the backing file. The default is *off*. Specifying either *--direct-io* or *--direct-io=on* will enable it. But, *--direct-io=off* can be provided to explicitly turn it off.
 
-*-v*, *--verbose*::
-Verbose mode.
-
 *-l*, *--list*::
 If a loop device or the *-a* option is specified, print the default columns for either the specified loop device or all loop devices; the default is to print info about all devices. See also *--output*, *--noheadings*, *--raw*, and *--json*.
 
diff --git a/sys-utils/losetup.c b/sys-utils/losetup.c
index 2a3257473..fe30d70da 100644
--- a/sys-utils/losetup.c
+++ b/sys-utils/losetup.c
@@ -501,7 +501,6 @@ static void __attribute__((__noreturn__)) usage(void)
 	fputs(_("     --direct-io[=<on|off>]    open backing file with O_DIRECT\n"), out);
 	fputs(_("     --loop-ref <string>       loop device reference\n"), out);
 	fputs(_("     --show                    print device name after setup (with -f)\n"), out);
-	fputs(_(" -v, --verbose                 verbose mode\n"), out);
 
 	/* output options */
 	fputs(USAGE_SEPARATOR, out);
@@ -730,7 +729,6 @@ int main(int argc, char **argv)
 		{ "raw",          no_argument,       NULL, OPT_RAW       },
 		{ "loop-ref",     required_argument, NULL, OPT_REF,      },
 		{ "show",         no_argument,       NULL, OPT_SHOW      },
-		{ "verbose",      no_argument,       NULL, 'v'           },
 		{ "version",      no_argument,       NULL, 'V'           },
 		{ "remove",       no_argument,       NULL, OPT_REMOVE    },
 		{ NULL, 0, NULL, 0 }
@@ -753,7 +751,7 @@ int main(int argc, char **argv)
 	if (loopcxt_init(&lc, 0))
 		err(EXIT_FAILURE, _("failed to initialize loopcxt"));
 
-	while ((c = getopt_long(argc, argv, "ab:cdDfhj:JlLno:O:PrvV",
+	while ((c = getopt_long(argc, argv, "ab:cdDfhj:JlLno:O:PrV",
 				longopts, NULL)) != -1) {
 
 		err_exclusive_options(c, longopts, excl, excl_st);
@@ -829,8 +827,6 @@ int main(int argc, char **argv)
 			if (use_dio)
 				lo_flags |= LO_FLAGS_DIRECT_IO;
 			break;
-		case 'v':
-			break;
 		case OPT_SIZELIMIT:			/* --sizelimit */
 			sizelimit = strtosize_or_err(optarg, _("failed to parse size"));
 			flags |= LOOPDEV_FL_SIZELIMIT;
-- 
2.51.2


^ permalink raw reply related

* Fwd: lsclocks and tai
From: Sami Kerola @ 2025-11-04 13:58 UTC (permalink / raw)
  To: util-linux
In-Reply-To: <CAG27Bk3UdZkP8e8dYuKgpowODu3+1KWg1hqLZDf5o832YWuxVA@mail.gmail.com>

Hello Karel and other,

It's been a while since I have been active with util-linux. Everything
is ok, just work & life keeps me busy. Perhaps someday in future
things change (when retiring and there's more time for fun).

Meanwhile. There was a workplace discussion about TAI and I noticed
unexpected lsclock.

$ lsclocks -o ISO_TIME,NAME | grep tai && TZ=right/UTC date --iso=ns
2025-11-04T13:58:14.176151344+00:00 tai
2025-11-04T13:57:47,177638531+00:00

One would hope above timings always match. If I force the timezone for
the lsclock output will match, but this has downside of all the other
listings use TAI zone.

$ TZ=right/UTC lsclocks -o ISO_TIME,NAME | grep tai && TZ=right/UTC
date --iso=ns

Perhaps the realtime outputs to use local time, and TAI to be always
right/UTC. Any thoughts?

-- 
Sami Kerola
https://kerolasa.iki.fi/

^ permalink raw reply

* Re: `losetup --remove` is confusing, and misuse silently fails
From: Benno Schulenberg @ 2025-11-03 14:42 UTC (permalink / raw)
  To: Karel Zak; +Cc: Util-Linux
In-Reply-To: <dexp4ooy65b2la7ujbpnp5itphzzriwg57uz2cvkt4grn3b7bv@7nzd6wye2vjt>


[-- Attachment #1.1: Type: text/plain, Size: 724 bytes --]


Op 03-11-2025 om 13:49 schreef Karel Zak:
>>    # ./losetup --remove --find --all
>>    losetup: options --remove and --find cannot be combined
>   
> Implemented:
>      https://github.com/util-linux/util-linux/pull/3835

Thanks!  However...

	fprintf(stderr, _("%s: options "), program_invocation_short_name);
	ul_print_option(stderr, status[e], opts);
	fputs(_(" and "), stderr);
	ul_print_option(stderr, c, opts);
	fputs(_(" cannot be combined.\n"), stderr);

For translatability, the above should be like:

	fprintf(stderr, _("%s: options %s and %s cannot be combined"), ...);


See for example `info gettext prep prep`, saying that translatable strings
should be entire sentences.


Benno


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]

^ permalink raw reply

* Re: reflink utils
From: Masatake YAMATO @ 2025-11-03 13:55 UTC (permalink / raw)
  To: dick; +Cc: util-linux
In-Reply-To: <176198657938.2807.15997469587039898204@routi.mrns.nl>

Hi,

> Hi,
> 
> I've created some tools to work with reflinks (FICLONERANGE) which I'd
> like to include in the util-linux project.
> 
> Reflinks can be used to share equal blocks between files. Cloning a
> block using reflinks will not copy any data saving I/O and disk wear/
> space.
> 
> First tool is blkdiff which takes two files, a base file and a new file. 
> Then it creates both a delta file and an index, the delta file contains
> the different blocks in new file compared to the base file and an index
> file which contains the block indexes in either the base file or the
> delta file so the new file can be constructed from that.
> 
> This is a bit similar to rdiff from librsync but uses fixed block sizes
> and doesn't require the chunks to be in the same order. FICLONERANGE
> only allows you to clone blocks of the filesystems block size.
> 
> The next tool is blkpatch which uses the base, index and delta file to
> construct new file using reflinks.
> 
> I've also created blkcat which concatenates the blocks from all supplied
> files using reflinks into a single file with the idea to use this as a
> basefile to deduplicate files on a filesystem.
> 
> I think reflinks, or at least FICLONERANGE is linux specific so
> util-linux would be a good fit. Reflinks are currently supported (AFAIK)
> for BtrFS and XFS.
> 
> I'd love to know:
> 
> - can/should I contribute these to util-linux?
> - are blkdiff, blkpatch and blkcat good names?
> - what's required more? I can image I need to add some man pages etc.

I have contributed to the util-linux project on multiple occasions.

I hope my commit 
https://github.com/util-linux/util-linux/pull/2627/commits/0d5f67b29ce487e9cfff7c8b16aa8f9e7c0e2d10
helps you. This may be one of the smallet commit that added a new
command to util-linux.

See also the commits added after the commit:
https://github.com/util-linux/util-linux/pulls?q=is%3Apr+is%3Aclosed+exch
They fixed my mistakes.

Masatake YAMATO


^ permalink raw reply

* Re: reflink utils
From: Karel Zak @ 2025-11-03 13:36 UTC (permalink / raw)
  To: Dick Marinus; +Cc: util-linux
In-Reply-To: <176198657938.2807.15997469587039898204@routi.mrns.nl>


 Hi Dick,

On Sat, Nov 01, 2025 at 09:42:59AM +0100, Dick Marinus wrote:
> I've created some tools to work with reflinks (FICLONERANGE) which I'd
> like to include in the util-linux project.
> 
> Reflinks can be used to share equal blocks between files. Cloning a
> block using reflinks will not copy any data saving I/O and disk wear/
> space.

Yes, we already support "hardlink --reflink" for this purpose.

> First tool is blkdiff which takes two files, a base file and a new file. 
> Then it creates both a delta file and an index, the delta file contains
> the different blocks in new file compared to the base file and an index
> file which contains the block indexes in either the base file or the
> delta file so the new file can be constructed from that.
> 
> This is a bit similar to rdiff from librsync but uses fixed block sizes
> and doesn't require the chunks to be in the same order. FICLONERANGE
> only allows you to clone blocks of the filesystems block size.
> 
> The next tool is blkpatch which uses the base, index and delta file to
> construct new file using reflinks.
> 
> I've also created blkcat which concatenates the blocks from all supplied
> files using reflinks into a single file with the idea to use this as a
> basefile to deduplicate files on a filesystem.
> 
> I think reflinks, or at least FICLONERANGE is linux specific so
> util-linux would be a good fit. Reflinks are currently supported (AFAIK)
> for BtrFS and XFS.
> 
> I'd love to know:
> 
> - can/should I contribute these to util-linux?

The first thing I always ask is if the functionality can be added to
an existing tool. In your case, the idea is so original that I don't
see anything we can integrate it into.

> - are blkdiff, blkpatch and blkcat good names?

The "blk" prefix makes it seem like it's for block devices instead of files.

How about following the ioctl name and using one tool that supports
more commands, like:

  ficlone diff
  ficlone patch
  ficlone cat

The issue is that users might not be familiar with ioctl, so "ficlone"
might not appeal to them. 

Perhaps use "reflink" as a name. Then you will have a generic tool,
and you can add features like "reflink copy" or "reflink status," etc.

> - what's required more? I can image I need to add some man pages etc.

Yes, man pages, bash-completion scripts, and ideally some tests, but
don't waste time on man pages, etc., before the code is ready to
merge.

> I already found the Documentation/howto-contribute.txt which I would
> use to contribute these utilities. GPL-2 is fine with me.

It's best to create a draft pull request on GitHub so we can all play
with it, review it, etc.

    Karel

-- 
 Karel Zak  <kzak@redhat.com>
 http://karelzak.blogspot.com


^ permalink raw reply

* Re: [PATCH 2/3] losetup: remove the --verbose flag, as it doesn't actually do anything
From: Karel Zak @ 2025-11-03 12:59 UTC (permalink / raw)
  To: Benno Schulenberg; +Cc: util-linux
In-Reply-To: <65268166-345b-45af-961c-43e9778fcb50@telfort.nl>

On Wed, Oct 29, 2025 at 12:07:03PM +0100, Benno Schulenberg wrote:
> Or, instead of removing it, make it again do something?  Like
> reporting which devices were detached when option -D is used?

You can turn on debug output if you need really detailed info.

Not sure if keeping verbose output is necessary. I think people
usually just run "losetup" (without any options) or "lsblk" to check
things. Everyone does that ;-)

I'll apply your patches; it's good enough for now.

    Karel

-- 
 Karel Zak  <kzak@redhat.com>
 http://karelzak.blogspot.com


^ permalink raw reply

* Re: [PATCH] wdctl: remove -d option leftover
From: Karel Zak @ 2025-11-03 12:52 UTC (permalink / raw)
  To: Munehisa Kamata; +Cc: util-linux, adanaila
In-Reply-To: <20251028195417.3569126-1-kamatam@amazon.com>

On Tue, Oct 28, 2025 at 12:54:17PM -0700, Munehisa Kamata wrote:
>  sys-utils/wdctl.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)

Good catch. Applied, thanks!

    Karel

-- 
 Karel Zak  <kzak@redhat.com>
 http://karelzak.blogspot.com


^ permalink raw reply

* Re: `losetup --remove` is confusing, and misuse silently fails
From: Karel Zak @ 2025-11-03 12:49 UTC (permalink / raw)
  To: Benno Schulenberg; +Cc: Util-Linux
In-Reply-To: <8c27aa14-495b-42f9-8ab6-6456daa1daa4@telfort.nl>

On Tue, Oct 21, 2025 at 03:49:01PM +0200, Benno Schulenberg wrote:
> >   # ./losetup --remove --detach loop0
> >   losetup: mutually exclusive arguments: --detach-all --all --set-capacity --detach --find --associated --remove
> 
> Nnn...  My next report was going to be about this.  :) 

 :-)

> About too verbose
> and therefore confusing feedback.  The user did not specify --detach-all,
> nor --all, nor --set-capacity, nor --find, nor --associated.  Thus it is
> confusing to see them mentioned in the error message.
> 
> It would be much nicer if the routine that checks for conflicting options
> would just print the first two incompatible ones of the options that were
> actually given.  For example:
> 
>   # ./losetup --remove --find --all
>   losetup: options --remove and --find cannot be combined
 
Implemented:
    https://github.com/util-linux/util-linux/pull/3835


   Karel


-- 
 Karel Zak  <kzak@redhat.com>
 http://karelzak.blogspot.com


^ permalink raw reply

* reflink utils
From: Dick Marinus @ 2025-11-01  8:58 UTC (permalink / raw)
  To: util-linux
In-Reply-To: <176198657938.2807.15997469587039898204@routi.mrns.nl>

Hi,

I've created some tools to work with reflinks (FICLONERANGE) which I'd
like to include in the util-linux project.

Reflinks can be used to share equal blocks between files. Cloning a
block using reflinks will not copy any data saving I/O and disk wear/
space.

First tool is blkdiff which takes two files, a base file and a new file. 
Then it creates both a delta file and an index, the delta file contains
the different blocks in new file compared to the base file and an index
file which contains the block indexes in either the base file or the
delta file so the new file can be constructed from that.

This is a bit similar to rdiff from librsync but uses fixed block sizes
and doesn't require the chunks to be in the same order. FICLONERANGE
only allows you to clone blocks of the filesystems block size.

The next tool is blkpatch which uses the base, index and delta file to
construct new file using reflinks.

I've also created blkcat which concatenates the blocks from all supplied
files using reflinks into a single file with the idea to use this as a
basefile to deduplicate files on a filesystem.

I think reflinks, or at least FICLONERANGE is linux specific so
util-linux would be a good fit. Reflinks are currently supported (AFAIK)
for BtrFS and XFS.

I'd love to know:

- can/should I contribute these to util-linux?
- are blkdiff, blkpatch and blkcat good names?
- what's required more? I can image I need to add some man pages etc.

I already found the Documentation/howto-contribute.txt which I would
use to contribute these utilities. GPL-2 is fine with me.

Kind Regards,
Dick

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox