/* SPDX-License-Identifier: LGPL-2.1-or-later */ #pragma once #include #include "user-record.h" typedef enum OperationType { OPERATION_ACQUIRE, /* enqueued on AcquireHome() */ OPERATION_RELEASE, /* enqueued on ReleaseHome() */ OPERATION_LOCK_ALL, /* enqueued on LockAllHomes() */ OPERATION_DEACTIVATE_ALL, /* enqueued on DeactivateAllHomes() */ OPERATION_PIPE_EOF, /* enqueued when we see EOF on the per-home reference pipes */ OPERATION_DEACTIVATE_FORCE, /* enqueued on hard $HOME unplug */ OPERATION_IMMEDIATE, /* this is never enqueued, it's just a marker we immediately started executing an operation without enqueuing anything first. */ _OPERATION_MAX, _OPERATION_INVALID = -1, } OperationType; /* Encapsulates an operation on one or more home directories. This has two uses: * * 1) For queuing an operation when we need to execute one for some reason but there's already one being * executed. * * 2) When executing an operation without enqueuing it first (OPERATION_IMMEDIATE) * * Note that a single operation object can encapsulate operations on multiple home directories. This is used * for the LockAllHomes() operation, which is one operation but applies to all homes at once. In case the * operation applies to multiple homes the reference counter is increased once for each, and thus the * operation is fully completed only after it reached zero again. * * The object (optionally) contains a reference of the D-Bus message triggering the operation, which is * replied to when the operation is fully completed, i.e. when n_ref reaches zero. */ typedef struct Operation { unsigned n_ref; OperationType type; sd_bus_message *message; UserRecord *secret; int send_fd; /* pipe fd for AcquireHome() which is taken already when we start the operation */ int result; /* < 0 if not completed yet, == 0 on failure, > 0 on success */ sd_bus_error error; int ret; } Operation; Operation *operation_new(OperationType type, sd_bus_message *m); Operation *operation_ref(Operation *operation); Operation *operation_unref(Operation *operation); DEFINE_TRIVIAL_CLEANUP_FUNC(Operation*, operation_unref); void operation_result(Operation *o, int ret, const sd_bus_error *error); static inline Operation* operation_result_unref(Operation *o, int ret, const sd_bus_error *error) { if (!o) return NULL; operation_result(o, ret, error); return operation_unref(o); }