summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/USER_RECORD.md4
-rw-r--r--man/homectl.xml7
-rw-r--r--src/home/homework-cifs.c32
-rw-r--r--src/home/homework.c2
-rw-r--r--src/home/homework.h5
5 files changed, 43 insertions, 7 deletions
diff --git a/docs/USER_RECORD.md b/docs/USER_RECORD.md
index 6b607dfd45..6710b00c0c 100644
--- a/docs/USER_RECORD.md
+++ b/docs/USER_RECORD.md
@@ -411,7 +411,9 @@ useful when `cifs` is used as storage mechanism for the user's home directory,
see above.
`cifsService` → A string indicating the Windows File Share service (CIFS) to
-mount as home directory of the user on login.
+mount as home directory of the user on login. Should be in format
+`//<host>/<service>/<directory/…>`. The directory part is optional. If missing
+the top-level directory of the CIFS share is used.
`imagePath` → A string with an absolute file system path to the file, directory
or block device to use for storage backing the home directory. If the `luks`
diff --git a/man/homectl.xml b/man/homectl.xml
index c2b1ec6c9b..f670566593 100644
--- a/man/homectl.xml
+++ b/man/homectl.xml
@@ -690,8 +690,11 @@
<term><option>--cifs-service=</option><replaceable>SERVICE</replaceable></term>
<listitem><para>Configures the Windows File Sharing (CIFS) domain and user to associate with the home
- directory/user account, as well as the file share ("service") to mount as directory. The latter is used when
- <literal>cifs</literal> storage is selected.</para></listitem>
+ directory/user account, as well as the file share ("service") to mount as directory. The latter is
+ used when <literal>cifs</literal> storage is selected. The file share should be specified in format
+ <literal>//<replaceable>host</replaceable>/<replaceable>share</replaceable>/<replaceable>directory/…</replaceable></literal>. The
+ directory part is optional — if not specified the home directory will be placed in the top-level
+ directory of the share.</para></listitem>
</varlistentry>
<varlistentry>
diff --git a/src/home/homework-cifs.c b/src/home/homework-cifs.c
index b920053163..55b8c2588d 100644
--- a/src/home/homework-cifs.c
+++ b/src/home/homework-cifs.c
@@ -7,6 +7,7 @@
#include "fs-util.h"
#include "homework-cifs.h"
#include "homework-mount.h"
+#include "mkdir.h"
#include "mount-util.h"
#include "process-util.h"
#include "stat-util.h"
@@ -18,6 +19,7 @@ int home_setup_cifs(
HomeSetupFlags flags,
HomeSetup *setup) {
+ _cleanup_free_ char *chost = NULL, *cservice = NULL, *cdir = NULL, *chost_and_service = NULL, *j = NULL;
char **pw;
int r;
@@ -38,6 +40,15 @@ int home_setup_cifs(
if (!h->cifs_service)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "User record lacks CIFS service, refusing.");
+ r = parse_cifs_service(h->cifs_service, &chost, &cservice, &cdir);
+ if (r < 0)
+ return log_error_errno(r, "Failed parse CIFS service specification: %m");
+
+ /* Just the host and service part, without the directory */
+ chost_and_service = strjoin("//", chost, "/", cservice);
+ if (!chost_and_service)
+ return log_oom();
+
r = home_unshare_and_mkdir();
if (r < 0)
return r;
@@ -78,7 +89,7 @@ int home_setup_cifs(
if (r == 0) {
/* Child */
execl("/bin/mount", "/bin/mount", "-n", "-t", "cifs",
- h->cifs_service, HOME_RUNTIME_WORK_DIR,
+ chost_and_service, HOME_RUNTIME_WORK_DIR,
"-o", options, NULL);
log_error_errno(errno, "Failed to execute mount: %m");
@@ -104,10 +115,23 @@ int home_setup_cifs(
if (r < 0)
return r;
- setup->root_fd = open(HOME_RUNTIME_WORK_DIR, O_RDONLY|O_CLOEXEC|O_DIRECTORY|O_NOFOLLOW);
+ if (cdir) {
+ j = path_join(HOME_RUNTIME_WORK_DIR, cdir);
+ if (!j)
+ return log_oom();
+
+ if (FLAGS_SET(flags, HOME_SETUP_CIFS_MKDIR)) {
+ r = mkdir_p(j, 0700);
+ if (r < 0)
+ return log_error_errno(r, "Failed to create CIFS subdirectory: %m");
+ }
+ }
+
+ setup->root_fd = open(j ?: HOME_RUNTIME_WORK_DIR, O_RDONLY|O_CLOEXEC|O_DIRECTORY|O_NOFOLLOW);
if (setup->root_fd < 0)
return log_error_errno(errno, "Failed to open home directory: %m");
+ setup->mount_suffix = TAKE_PTR(cdir);
return 0;
}
@@ -139,7 +163,7 @@ int home_activate_cifs(
setup->root_fd = safe_close(setup->root_fd);
- r = home_move_mount(NULL, hd);
+ r = home_move_mount(setup->mount_suffix, hd);
if (r < 0)
return r;
@@ -171,7 +195,7 @@ int home_create_cifs(UserRecord *h, HomeSetup *setup, UserRecord **ret_home) {
return log_error_errno(errno, "Unable to detect whether /sbin/mount.cifs exists: %m");
}
- r = home_setup_cifs(h, 0, setup);
+ r = home_setup_cifs(h, HOME_SETUP_CIFS_MKDIR, setup);
if (r < 0)
return r;
diff --git a/src/home/homework.c b/src/home/homework.c
index cfc0c945de..8ffed82742 100644
--- a/src/home/homework.c
+++ b/src/home/homework.c
@@ -365,6 +365,8 @@ int home_setup_done(HomeSetup *setup) {
if (setup->do_drop_caches)
drop_caches_now();
+ setup->mount_suffix = mfree(setup->mount_suffix);
+
return r;
}
diff --git a/src/home/homework.h b/src/home/homework.h
index 1fa5a1e37a..08d97b8261 100644
--- a/src/home/homework.h
+++ b/src/home/homework.h
@@ -37,6 +37,8 @@ typedef struct HomeSetup {
uint64_t partition_offset;
uint64_t partition_size;
+
+ char *mount_suffix; /* The directory to use as home dir is this path below /run/systemd/user-home-mount */
} HomeSetup;
typedef struct PasswordCache {
@@ -66,6 +68,9 @@ static inline bool password_cache_contains(const PasswordCache *cache, const cha
/* Various flags for the operation of setting up a home directory */
typedef enum HomeSetupFlags {
HOME_SETUP_ALREADY_ACTIVATED = 1 << 0, /* Open an already activated home, rather than activate it afresh */
+
+ /* CIFS backend: */
+ HOME_SETUP_CIFS_MKDIR = 1 << 1, /* Create CIFS subdir when missing */
} HomeSetupFlags;
int home_setup_done(HomeSetup *setup);