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`
<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>
#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"
HomeSetupFlags flags,
HomeSetup *setup) {
+ _cleanup_free_ char *chost = NULL, *cservice = NULL, *cdir = NULL, *chost_and_service = NULL, *j = NULL;
char **pw;
int r;
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;
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");
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;
}
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;
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;
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 {
/* 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);