GCC Code Coverage Report
Directory: cvmfs/ Exec Total Coverage
File: cvmfs/util/mmap_file.cc Lines: 27 40 67.5 %
Date: 2019-02-03 02:48:13 Branches: 11 22 50.0 %

Line Branch Exec Source
1
/**
2
 * This file is part of the CernVM File System.
3
 *
4
 * Some common functions.
5
 */
6
7
#ifndef __STDC_FORMAT_MACROS
8
#define __STDC_FORMAT_MACROS
9
#endif
10
11
#include "cvmfs_config.h"
12
#include "mmap_file.h"
13
14
#include <errno.h>
15
#include <fcntl.h>
16
#include <sys/mman.h>
17
#include <unistd.h>
18
19
#include <cassert>
20
21
#include "logging.h"
22
#include "platform.h"
23
24
using namespace std;  // NOLINT
25
26
#ifdef CVMFS_NAMESPACE_GUARD
27
namespace CVMFS_NAMESPACE_GUARD {
28
#endif
29
30
31
908
MemoryMappedFile::MemoryMappedFile(const std::string &file_path) :
32
  file_path_(file_path),
33
  file_descriptor_(-1),
34
  mapped_file_(NULL),
35
  mapped_size_(0),
36
908
  mapped_(false) {}
37
38
908
MemoryMappedFile::~MemoryMappedFile() {
39
908
  if (IsMapped()) {
40
    Unmap();
41
  }
42
}
43
44
908
bool MemoryMappedFile::Map() {
45
908
  assert(!mapped_);
46
47
  // open the file
48
  int fd;
49
908
  if ((fd = open(file_path_.c_str(), O_RDONLY, 0)) == -1) {
50
    LogCvmfs(kLogUtility, kLogStderr, "failed to open %s (%d)",
51
             file_path_.c_str(), errno);
52
    return false;
53
  }
54
55
  // get file size
56
  platform_stat64 filesize;
57
908
  if (platform_fstat(fd, &filesize) != 0) {
58
    LogCvmfs(kLogUtility, kLogStderr, "failed to fstat %s (%d)",
59
             file_path_.c_str(), errno);
60
    close(fd);
61
    return false;
62
  }
63
64
  // check if the file is empty and 'pretend' that the file is mapped
65
  // --> buffer will then look like a buffer without any size...
66
908
  void *mapping = NULL;
67
908
  if (filesize.st_size > 0) {
68
    // map the given file into memory
69
908
    mapping = mmap(NULL, filesize.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
70
908
    if (mapping == MAP_FAILED) {
71
      LogCvmfs(kLogUtility, kLogStderr, "failed to mmap %s (file size: %d) "
72
                                        "(errno: %d)",
73
                file_path_.c_str(),
74
                filesize.st_size,
75
                errno);
76
      close(fd);
77
      return false;
78
    }
79
  }
80
81
  // save results
82
908
  mapped_file_     = static_cast<unsigned char*>(mapping);
83
908
  file_descriptor_ = fd;
84
908
  mapped_size_     = filesize.st_size;
85
908
  mapped_          = true;
86
908
  LogCvmfs(kLogUtility, kLogVerboseMsg, "mmap'ed %s", file_path_.c_str());
87
908
  return true;
88
}
89
90
908
void MemoryMappedFile::Unmap() {
91
908
  assert(mapped_);
92
93
908
  if (mapped_file_ == NULL) {
94
    return;
95
  }
96
97
  // unmap the previously mapped file
98

908
  if ((munmap(static_cast<void*>(mapped_file_), mapped_size_) != 0) ||
99
      (close(file_descriptor_) != 0))
100
  {
101
    LogCvmfs(kLogUtility, kLogStderr, "failed to unmap %s", file_path_.c_str());
102
    const bool munmap_failed = false;
103
    assert(munmap_failed);
104
  }
105
106
  // reset (resettable) data
107
908
  mapped_file_     = NULL;
108
908
  file_descriptor_ = -1;
109
908
  mapped_size_     = 0;
110
908
  mapped_          = false;
111
908
  LogCvmfs(kLogUtility, kLogVerboseMsg, "munmap'ed %s", file_path_.c_str());
112
}
113
114
#ifdef CVMFS_NAMESPACE_GUARD
115
}  // namespace CVMFS_NAMESPACE_GUARD
116
#endif