GCC Code Coverage Report
Directory: cvmfs/ Exec Total Coverage
File: cvmfs/clientctx.h Lines: 17 17 100.0 %
Date: 2019-02-03 02:48:13 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
/**
15
 * A client context associates a file system call with the uid, gid, and pid
16
 * of the calling process.  For the library, that's the current process and
17
 * user.  For the Fuse module, the uid and gid are provided by fuse, the pid
18
 * can be figured out from the system. A client context is used to download
19
 * files with the credentials of the caller.
20
 *
21
 * A ClientCtx encapulates thread-local storage.  It can be set somewhere at the
22
 * beginning of a file system call and used anywhere during the processing of
23
 * the call.  It is a singleton.
24
 */
25
class ClientCtx {
26
 public:
27
  struct ThreadLocalStorage {
28
8
    ThreadLocalStorage(uid_t u, gid_t g, pid_t p)
29
8
      : uid(u), gid(g), pid(p), is_set(true) { }
30
    uid_t uid;
31
    gid_t gid;
32
    pid_t pid;
33
    bool is_set;  ///< either not yet set or deliberately unset
34
  };
35
36
  static ClientCtx *GetInstance();
37
  static void CleanupInstance();
38
  ~ClientCtx();
39
40
  void Set(uid_t uid, gid_t gid, pid_t pid);
41
  void Unset();
42
  void Get(uid_t *uid, gid_t *gid, pid_t *pid);
43
  bool IsSet();
44
45
 private:
46
  static ClientCtx *instance_;
47
  static void TlsDestructor(void *data);
48
49
  ClientCtx();
50
51
  pthread_key_t thread_local_storage_;
52
  pthread_mutex_t *lock_tls_blocks_;
53
  std::vector<ThreadLocalStorage *> tls_blocks_;
54
};
55
56
/**
57
 * RAII form of the ClientCtx.  On construction, automatically sets the context
58
 * via the constructor; on destruction, restores to the previous values.
59
 *
60
 * Meant to be allocated on the stack.
61
 */
62
class ClientCtxGuard {
63
 public:
64
34
  ClientCtxGuard(uid_t uid, gid_t gid, pid_t pid)
65
    : set_on_construction_(false)
66
    , old_uid_(-1)
67
    , old_gid_(-1)
68
34
    , old_pid_(-1)
69
  {
70
    // Implementation guarantees old_ctx is not null.
71
34
    ClientCtx *old_ctx = ClientCtx::GetInstance();
72
34
    assert(old_ctx);
73
34
    if (old_ctx->IsSet()) {
74
1
      set_on_construction_ = true;
75
1
      old_ctx->Get(&old_uid_, &old_gid_, &old_pid_);
76
    }
77
34
    old_ctx->Set(uid, gid, pid);
78
34
  }
79
80
34
  ~ClientCtxGuard() {
81
34
    ClientCtx *ctx = ClientCtx::GetInstance();
82
34
    if (set_on_construction_) {
83
1
      ctx->Set(old_uid_, old_gid_, old_pid_);
84
    } else {
85
33
      ctx->Unset();
86
    }
87
34
  }
88
89
 private:
90
  bool set_on_construction_;
91
  uid_t old_uid_;
92
  gid_t old_gid_;
93
  pid_t old_pid_;
94
};
95
96
#endif  // CVMFS_CLIENTCTX_H_