summaryrefslogtreecommitdiffstats
path: root/cache.cxx
blob: 90d5835676e58c044110cf9673fb48f8e51ff927 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
// systemtap cache manager
// Copyright (C) 2006-2007 Red Hat Inc.
//
// This file is part of systemtap, and is free software.  You can
// redistribute it and/or modify it under the terms of the GNU General
// Public License (GPL); either version 2, or (at your option) any
// later version.


#include "session.h"
#include "cache.h"
#include "util.h"
#include <cerrno>
#include <string>
#include <fstream>
#include <cstring>

extern "C" {
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
}

using namespace std;


void
add_to_cache(systemtap_session& s)
{
  string module_src_path = s.tmpdir + "/" + s.module_name + ".ko";
  if (s.verbose > 1)
    clog << "Copying " << module_src_path << " to " << s.hash_path << endl;
  if (copy_file(module_src_path.c_str(), s.hash_path.c_str()) != 0)
    {
      cerr << "Copy failed (\"" << module_src_path << "\" to \""
	   << s.hash_path << "\"): " << strerror(errno) << endl;
      return;
    }

  string c_dest_path = s.hash_path;
  if (c_dest_path.rfind(".ko") == (c_dest_path.size() - 3))
    c_dest_path.resize(c_dest_path.size() - 3);
  c_dest_path += ".c";

  if (s.verbose > 1)
    clog << "Copying " << s.translated_source << " to " << c_dest_path
	 << endl;
  if (copy_file(s.translated_source.c_str(), c_dest_path.c_str()) != 0)
    {
      cerr << "Copy failed (\"" << s.translated_source << "\" to \""
	   << c_dest_path << "\"): " << strerror(errno) << endl;
    }
}


bool
get_from_cache(systemtap_session& s)
{
  string module_dest_path = s.tmpdir + "/" + s.module_name + ".ko";
  string c_src_path = s.hash_path;
  int fd_module, fd_c;

  if (c_src_path.rfind(".ko") == (c_src_path.size() - 3))
    c_src_path.resize(c_src_path.size() - 3);
  c_src_path += ".c";

  // See if module exists
  fd_module = open(s.hash_path.c_str(), O_RDONLY);
  if (fd_module == -1)
    {
      // It isn't in cache.
      return false;
    }

  // See if C file exists.
  fd_c = open(c_src_path.c_str(), O_RDONLY);
  if (fd_c == -1)
    {
      // The module is there, but the C file isn't.  Cleanup and
      // return.
      close(fd_module);
      unlink(s.hash_path.c_str());
      return false;
    }

  // Copy the cached C file to the destination
  if (copy_file(c_src_path.c_str(), s.translated_source.c_str()) != 0)
    {
      cerr << "Copy failed (\"" << c_src_path << "\" to \""
	   << s.translated_source << "\"): " << strerror(errno) << endl;
      close(fd_module);
      close(fd_c);
      return false;
    }

  // Copy the cached module to the destination (if needed)
  if (s.last_pass != 3)
    {
      if (copy_file(s.hash_path.c_str(), module_dest_path.c_str()) != 0)
        {
	  cerr << "Copy failed (\"" << s.hash_path << "\" to \""
	       << module_dest_path << "\"): " << strerror(errno) << endl;
	  unlink(c_src_path.c_str());
	  close(fd_module);
	  close(fd_c);
	  return false;
	}
    }

  // We're done with these file handles.
  close(fd_module);
  close(fd_c);

  // To preserve semantics (since this will happen if we're not
  // caching), display the C source if the last pass is 3.
  if (s.last_pass == 3)
    {
      ifstream i (s.translated_source.c_str());
      cout << i.rdbuf();
    }
  // And similarly, display probe module name for -p4.
  if (s.last_pass == 4)
    cout << s.hash_path << endl;

  // If everything worked, tell the user.  We need to do this here,
  // since if copying the cached C file works, but copying the cached
  // module fails, we remove the cached C file and let the C file get
  // regenerated.
  if (s.verbose)
    {
      clog << "Pass 3: using cached " << c_src_path << endl;
      if (s.last_pass != 3)
	clog << "Pass 4: using cached " << s.hash_path << endl;
    }

  return true;
}