<!--
SPDX-FileCopyrightText: 1991 - 1994, Julianne Frances Haugh
SPDX-FileCopyrightText: 2007 - 2011, Nicolas François
+ SPDX-FileCopyrightText: 2025 - 2026, Hadi Chokr
SPDX-License-Identifier: BSD-3-Clause
-->
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook V4.5//EN"
regardless of any configuration file settings.
</para>
<para>
- Note: this feature works only if the underlying filesystem supports
- Btrfs subvolumes.
+ If the parent directory of the user's home directory is
+ <emphasis>not</emphasis> on a Btrfs filesystem,
+ <command>useradd</command> will <emphasis>not</emphasis> create a
+ subvolume.
+ Instead, it creates a regular directory,
+ prints a warning to standard error,
+ and logs the event via syslog at level
+ <constant>LOG_WARN</constant>.
+ The user account is still created successfully.
+ </para>
+ <para>
+ If the filesystem type cannot be determined (e.g., because of
+ insufficient permissions, an I/O error,
+ or a
+ <citerefentry>
+ <refentrytitle>statfs</refentrytitle>
+ <manvolnum>2</manvolnum>
+ </citerefentry>
+ failure),
+ <command>useradd</command> treats this as a fatal error:
+ the home directory is not created,
+ the command exits with a non‑zero status
+ (<literal>E_HOMEDIR</literal>, 12),
+ and an error message is printed.
</para>
</listitem>
</varlistentry>
-/*
- * SPDX-FileCopyrightText: 1991 - 1994, Julianne Frances Haugh
- * SPDX-FileCopyrightText: 1996 - 2000, Marek Michałkiewicz
- * SPDX-FileCopyrightText: 2000 - 2006, Tomasz Kłoczko
- * SPDX-FileCopyrightText: 2007 - 2012, Nicolas François
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
+// SPDX-FileCopyrightText: 1991-1994, Julianne Frances Haugh
+// SPDX-FileCopyrightText: 1996-2000, Marek Michałkiewicz
+// SPDX-FileCopyrightText: 2000-2006, Tomasz Kłoczko
+// SPDX-FileCopyrightText: 2007-2012, Nicolas François
+// SPDX-FileCopyrightText: 2025-2026, Hadi Chokr
+// SPDX-FileCopyrightText: 2026, Alejandro Colomar <alx@kernel.org>
+// SPDX-License-Identifier: BSD-3-Clause
+
#include "config.h"
owner root:root.
*/
for (cp = strtok(bhome, "/"); cp != NULL; cp = strtok(NULL, "/")) {
+ bool dir_created;
+
/* Avoid turning a relative path into an absolute path. */
if (strprefix(bhome, "/") || !streq(path, ""))
strcat(path, "/");
continue;
}
- /* Check if parent directory is BTRFS, fail if requesting
- subvolume but no BTRFS. The paths could be different by the
- trailing slash
- */
+ dir_created = false;
#if WITH_BTRFS
if (subvolflg && (strlen(prefix_user_home) - (int)strlen(path)) <= 1) {
char *btrfs_check = strdup(path);
free(btrfs_check);
if (!is_btrfs(&sfs)) {
fprintf(stderr,
- _("%s: home directory \"%s\" must be mounted on BTRFS\n"),
- Prog, path);
- fail_exit(E_HOMEDIR, process_selinux);
+ _("%s: warning: \"%s\" is not on BTRFS; creating regular directory instead of subvolume\n"),
+ Prog, prefix_user_home);
+ } else {
+ if (btrfs_create_subvolume(path)) {
+ fprintf(stderr,
+ _("%s: failed to create BTRFS subvolume: %s\n"),
+ Prog, path);
+ fail_exit(E_HOMEDIR, process_selinux);
+ }
+ dir_created = true;
}
- // make subvolume to mount for user instead of directory
- if (btrfs_create_subvolume(path)) {
- fprintf(stderr,
- _("%s: failed to create BTRFS subvolume: %s\n"),
+ }
+#endif
+ if (!dir_created) {
+ if (mkdir(path, 0) != 0) {
+ fprintf(stderr, _("%s: cannot create directory %s\n"),
Prog, path);
fail_exit(E_HOMEDIR, process_selinux);
}
}
- else
-#endif
- if (mkdir(path, 0) != 0) {
- fprintf(stderr, _("%s: cannot create directory %s\n"),
- Prog, path);
- fail_exit(E_HOMEDIR, process_selinux);
- }
if (chown(path, 0, 0) < 0) {
fprintf(stderr,
_("%s: warning: chown on `%s' failed: %m\n"),