1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 #pragma once
3 
4 #include <sd-bus.h>
5 
6 #include "user-record.h"
7 
8 typedef enum OperationType {
9         OPERATION_ACQUIRE,           /* enqueued on AcquireHome() */
10         OPERATION_RELEASE,           /* enqueued on ReleaseHome() */
11         OPERATION_LOCK_ALL,          /* enqueued on LockAllHomes() */
12         OPERATION_DEACTIVATE_ALL,    /* enqueued on DeactivateAllHomes() */
13         OPERATION_PIPE_EOF,          /* enqueued when we see EOF on the per-home reference pipes */
14         OPERATION_DEACTIVATE_FORCE,  /* enqueued on hard $HOME unplug */
15         OPERATION_IMMEDIATE,         /* this is never enqueued, it's just a marker we immediately started executing an operation without enqueuing anything first. */
16         _OPERATION_MAX,
17         _OPERATION_INVALID = -EINVAL,
18 } OperationType;
19 
20 /* Encapsulates an operation on one or more home directories. This has two uses:
21  *
22  *     1) For queuing an operation when we need to execute one for some reason but there's already one being
23  *        executed.
24  *
25  *     2) When executing an operation without enqueuing it first (OPERATION_IMMEDIATE)
26  *
27  * Note that a single operation object can encapsulate operations on multiple home directories. This is used
28  * for the LockAllHomes() operation, which is one operation but applies to all homes at once. In case the
29  * operation applies to multiple homes the reference counter is increased once for each, and thus the
30  * operation is fully completed only after it reached zero again.
31  *
32  * The object (optionally) contains a reference of the D-Bus message triggering the operation, which is
33  * replied to when the operation is fully completed, i.e. when n_ref reaches zero.
34  */
35 
36 typedef struct Operation {
37         unsigned n_ref;
38         OperationType type;
39         sd_bus_message *message;
40 
41         UserRecord *secret;
42         int send_fd;   /* pipe fd for AcquireHome() which is taken already when we start the operation */
43 
44         int result;    /* < 0 if not completed yet, == 0 on failure, > 0 on success */
45         sd_bus_error error;
46         int ret;
47 } Operation;
48 
49 Operation *operation_new(OperationType type, sd_bus_message *m);
50 Operation *operation_ref(Operation *operation);
51 Operation *operation_unref(Operation *operation);
52 
53 DEFINE_TRIVIAL_CLEANUP_FUNC(Operation*, operation_unref);
54 
55 void operation_result(Operation *o, int ret, const sd_bus_error *error);
56 
operation_result_unref(Operation * o,int ret,const sd_bus_error * error)57 static inline Operation* operation_result_unref(Operation *o, int ret, const sd_bus_error *error) {
58         if (!o)
59                 return NULL;
60 
61         operation_result(o, ret, error);
62         return operation_unref(o);
63 }
64