* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. */
+#define _GNU_SOURCE
+
#include "main_restore.hpp"
#include "fs_helpers.hpp"
#include "main_context.hpp"
#include "os_ops.hpp"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
#include <filesystem>
#include <fstream>
+#include <string>
+#include <utility>
#undef LOG_TAG
#define LOG_TAG "SESSIOND"
#include <dlog.h>
-/* TODO: without some sort of lock, restoration is racy, since in case the "real" sessiond
- * manages to start before the restore-only version is done, they could both be trying to
- * mount the same fixed-size subsession. */
+using namespace std::string_literals;
+
+std::string get_restoration_lock_filename(int uid)
+{
+ return "/run/sessiond-restore-"s + std::to_string(uid) + ".lock";
+}
+
static int restoration_lock(int uid)
{
- return -1;
+ const auto filename = get_restoration_lock_filename(uid);
+ const int fd = open(filename.c_str(), O_CREAT | O_WRONLY, 0600);
+ if (fd == -1)
+ return -1;
+
+ struct flock f;
+ f.l_type = F_WRLCK;
+ f.l_whence = SEEK_SET;
+ f.l_start = 0;
+ f.l_len = 0;
+ f.l_pid = 0;
+
+ if (fcntl (fd, F_OFD_SETLKW, &f) < 0) {
+ close(fd);
+ return -1;
+ }
+
+ return fd;
}
static void restoration_unlock(int fd)
{
+ /* OFD locks don't need F_UNLCK, it's enough to just close. */
+ close(fd);
}
static void restore_user_session(const fs::path& user_home_dir)