GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/clientctx.h
Date: 2024-04-21 02:33:16
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