Directory: | cvmfs/ |
---|---|
File: | cvmfs/clientctx.h |
Date: | 2025-02-09 02:34:19 |
Exec | Total | Coverage | |
---|---|---|---|
Lines: | 21 | 21 | 100.0% |
Branches: | 5 | 6 | 83.3% |
Line | Branch | Exec | Source |
---|---|---|---|
1 | /** | ||
2 | * This file is part of the CernVM File System. | ||
3 | */ | ||
4 | |||
5 | #ifndef CVMFS_CLIENTCTX_H_ | ||
6 | #define CVMFS_CLIENTCTX_H_ | ||
7 | |||
8 | #include <pthread.h> | ||
9 | #include <unistd.h> | ||
10 | |||
11 | #include <cassert> | ||
12 | #include <vector> | ||
13 | |||
14 | class InterruptCue; | ||
15 | |||
16 | /** | ||
17 | * A client context associates a file system call with the uid, gid, and pid | ||
18 | * of the calling process and an InterruptCue of the file system request. | ||
19 | * For the library, the calling process is just the current process and | ||
20 | * user, the InterruptCue is the default one. | ||
21 | * For the Fuse module, the uid and gid are provided by fuse, the pid | ||
22 | * can be figured out from the system. The InterruptCue is the FuseInterruptCue | ||
23 | * defined in cvmfs.cc. A client context is used to download files with the | ||
24 | * credentials of the caller and to interrupt a download if the file system | ||
25 | * request got canceled. | ||
26 | * | ||
27 | * A ClientCtx encapulates thread-local storage. It can be set somewhere at the | ||
28 | * beginning of a file system call and used anywhere during the processing of | ||
29 | * the call. It is a singleton. | ||
30 | */ | ||
31 | class ClientCtx { | ||
32 | public: | ||
33 | struct ThreadLocalStorage { | ||
34 | 9 | ThreadLocalStorage(uid_t u, gid_t g, pid_t p, InterruptCue *ic) | |
35 | 9 | : uid(u), gid(g), pid(p), interrupt_cue(ic), is_set(true) { } | |
36 | uid_t uid; | ||
37 | gid_t gid; | ||
38 | pid_t pid; | ||
39 | InterruptCue *interrupt_cue; ///< A non-owning pointer | ||
40 | bool is_set; ///< either not yet set or deliberately unset | ||
41 | }; | ||
42 | |||
43 | static ClientCtx *GetInstance(); | ||
44 | static void CleanupInstance(); | ||
45 | ~ClientCtx(); | ||
46 | |||
47 | void Set(uid_t uid, gid_t gid, pid_t pid, InterruptCue *ic); | ||
48 | void Unset(); | ||
49 | void Get(uid_t *uid, gid_t *gid, pid_t *pid, InterruptCue **ic); | ||
50 | bool IsSet(); | ||
51 | |||
52 | private: | ||
53 | static ClientCtx *instance_; | ||
54 | static void TlsDestructor(void *data); | ||
55 | |||
56 | ClientCtx(); | ||
57 | |||
58 | pthread_key_t thread_local_storage_; | ||
59 | pthread_mutex_t *lock_tls_blocks_; | ||
60 | std::vector<ThreadLocalStorage *> tls_blocks_; | ||
61 | }; | ||
62 | |||
63 | /** | ||
64 | * RAII form of the ClientCtx. On construction, automatically sets the context | ||
65 | * via the constructor; on destruction, restores to the previous values. | ||
66 | * | ||
67 | * Meant to be allocated on the stack. | ||
68 | */ | ||
69 | class ClientCtxGuard { | ||
70 | public: | ||
71 | 36 | ClientCtxGuard(uid_t uid, gid_t gid, pid_t pid, InterruptCue *ic) | |
72 | 36 | : set_on_construction_(false) | |
73 | 36 | , old_uid_(-1) | |
74 | 36 | , old_gid_(-1) | |
75 | 36 | , old_pid_(-1) | |
76 | 36 | , old_interrupt_cue_(NULL) | |
77 | { | ||
78 | // Implementation guarantees old_ctx is not null. | ||
79 | 36 | ClientCtx *old_ctx = ClientCtx::GetInstance(); | |
80 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
|
36 | assert(old_ctx); |
81 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 2 taken 35 times.
|
36 | if (old_ctx->IsSet()) { |
82 | 1 | set_on_construction_ = true; | |
83 | 1 | old_ctx->Get(&old_uid_, &old_gid_, &old_pid_, &old_interrupt_cue_); | |
84 | } | ||
85 | 36 | old_ctx->Set(uid, gid, pid, ic); | |
86 | 36 | } | |
87 | |||
88 | 36 | ~ClientCtxGuard() { | |
89 | 36 | ClientCtx *ctx = ClientCtx::GetInstance(); | |
90 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 35 times.
|
36 | if (set_on_construction_) { |
91 | 1 | ctx->Set(old_uid_, old_gid_, old_pid_, old_interrupt_cue_); | |
92 | } else { | ||
93 | 35 | ctx->Unset(); | |
94 | } | ||
95 | 36 | } | |
96 | |||
97 | private: | ||
98 | bool set_on_construction_; | ||
99 | uid_t old_uid_; | ||
100 | gid_t old_gid_; | ||
101 | pid_t old_pid_; | ||
102 | InterruptCue *old_interrupt_cue_; | ||
103 | }; | ||
104 | |||
105 | #endif // CVMFS_CLIENTCTX_H_ | ||
106 |