summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordsmith <dsmith>2006-10-23 22:09:51 +0000
committerdsmith <dsmith>2006-10-23 22:09:51 +0000
commit1b78aef5258d6681b6224c5a8e8e623449ccc11e (patch)
tree3912f9b3d5f34a8e8252e0529185441f4f8a0233
parent0884d54a236c30dc2585a6b76e5846e44e54138d (diff)
downloadsystemtap-steved-1b78aef5258d6681b6224c5a8e8e623449ccc11e.tar.gz
systemtap-steved-1b78aef5258d6681b6224c5a8e8e623449ccc11e.tar.xz
systemtap-steved-1b78aef5258d6681b6224c5a8e8e623449ccc11e.zip
2006-10-23 David Smith <dsmith@redhat.com>
* main.cxx (printscript): New function containing code moved from main(). (main): Added code to create cache directory, call function to generate hash, and see if we can use cached source/module. If pass 4 is actually run to produce a new module, we call add_to_cache() to cache the result. * session.h (struct systemtap_session): Added hash/cache session data. * cache.cxx: New file handling adding/getting files from the cache. * cache.h: New header file for cache.cxx. * hash.cxx: New file containing C++ wrapper for routines in mdfour.c and the find_hash function which computes the hash file name for an input script. * hash.h: New header file for hash.cxx. * mdfour.c: New file containing MD4 hash code. * mdfour.h: New header file for mdfour.c. * util.cxx: New file containing several utility functions used by the caching code. * util.h: New header file for util.cxx. * Makefile.am: Added new C/C++ files. * Makefile.in: Regenerated.
-rw-r--r--ChangeLog25
-rw-r--r--Makefile.am3
-rw-r--r--Makefile.in67
-rw-r--r--cache.cxx113
-rw-r--r--cache.h2
-rw-r--r--hash.cxx168
-rw-r--r--hash.h34
-rw-r--r--main.cxx192
-rw-r--r--mdfour.c218
-rw-r--r--mdfour.h39
-rw-r--r--session.h6
-rw-r--r--util.cxx199
-rw-r--r--util.h13
13 files changed, 1019 insertions, 60 deletions
diff --git a/ChangeLog b/ChangeLog
index 958ca0c2..b5f76da1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,28 @@
+2006-10-23 David Smith <dsmith@redhat.com>
+
+ * main.cxx (printscript): New function containing code moved from
+ main().
+ (main): Added code to create cache directory, call function to
+ generate hash, and see if we can use cached source/module. If
+ pass 4 is actually run to produce a new module, we call
+ add_to_cache() to cache the result.
+ * session.h (struct systemtap_session): Added hash/cache session
+ data.
+ * cache.cxx: New file handling adding/getting files from the
+ cache.
+ * cache.h: New header file for cache.cxx.
+ * hash.cxx: New file containing C++ wrapper for routines in
+ mdfour.c and the find_hash function which computes the hash file
+ name for an input script.
+ * hash.h: New header file for hash.cxx.
+ * mdfour.c: New file containing MD4 hash code.
+ * mdfour.h: New header file for mdfour.c.
+ * util.cxx: New file containing several utility functions used by
+ the caching code.
+ * util.h: New header file for util.cxx.
+ * Makefile.am: Added new C/C++ files.
+ * Makefile.in: Regenerated.
+
2006-10-23 Li Guanglei <guanglei@cn.ibm.com>
* configure.ac, Makefile.am: add lket-b2a.1.in
* Makefile.in, configure: regenreated
diff --git a/Makefile.am b/Makefile.am
index 1ab03071..72a78608 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -15,7 +15,8 @@ dist_man_MANS = stap.1 stapprobes.5 stapfuncs.5 stapex.5 lket.5 lket-b2a.1 man/s
bin_PROGRAMS = stap staprun
stap_SOURCES = main.cxx \
parse.cxx staptree.cxx elaborate.cxx translate.cxx \
- tapsets.cxx buildrun.cxx loc2c.c
+ tapsets.cxx buildrun.cxx loc2c.c hash.cxx mdfour.c \
+ cache.cxx util.cxx
stap_LDADD = @stap_LIBS@
stap_CXXFLAGS = -Werror $(AM_CXXFLAGS)
diff --git a/Makefile.in b/Makefile.in
index d55a8369..ee174e9c 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -94,7 +94,9 @@ loc2c_test_DEPENDENCIES = $(am__DEPENDENCIES_1)
am_stap_OBJECTS = stap-main.$(OBJEXT) stap-parse.$(OBJEXT) \
stap-staptree.$(OBJEXT) stap-elaborate.$(OBJEXT) \
stap-translate.$(OBJEXT) stap-tapsets.$(OBJEXT) \
- stap-buildrun.$(OBJEXT) stap-loc2c.$(OBJEXT)
+ stap-buildrun.$(OBJEXT) stap-loc2c.$(OBJEXT) \
+ stap-hash.$(OBJEXT) stap-mdfour.$(OBJEXT) stap-cache.$(OBJEXT) \
+ stap-util.$(OBJEXT)
stap_OBJECTS = $(am_stap_OBJECTS)
am_staprun_OBJECTS = stpd.$(OBJEXT) librelay.$(OBJEXT)
staprun_OBJECTS = $(am_staprun_OBJECTS)
@@ -247,7 +249,8 @@ AM_CXXFLAGS = -Wall
dist_man_MANS = stap.1 stapprobes.5 stapfuncs.5 stapex.5 lket.5 lket-b2a.1 man/stapprobes.iosched.5 man/stapprobes.netdev.5 man/stapprobes.nfs.5 man/stapprobes.nfsd.5 man/stapprobes.pagefault.5 man/stapprobes.process.5 man/stapprobes.rpc.5 man/stapprobes.scsi.5 man/stapprobes.signal.5 man/stapprobes.tcp.5 man/stapprobes.udp.5
stap_SOURCES = main.cxx \
parse.cxx staptree.cxx elaborate.cxx translate.cxx \
- tapsets.cxx buildrun.cxx loc2c.c
+ tapsets.cxx buildrun.cxx loc2c.c hash.cxx mdfour.c \
+ cache.cxx util.cxx
stap_LDADD = @stap_LIBS@
stap_CXXFLAGS = -Werror $(AM_CXXFLAGS)
@@ -433,13 +436,17 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/loc2c_test-loc2c-test.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/loc2c_test-loc2c.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap-buildrun.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap-cache.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap-elaborate.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap-hash.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap-loc2c.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap-main.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap-mdfour.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap-parse.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap-staptree.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap-tapsets.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap-translate.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stap-util.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stpd.Po@am__quote@
.c.o:
@@ -498,6 +505,20 @@ stap-loc2c.obj: loc2c.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o stap-loc2c.obj `if test -f 'loc2c.c'; then $(CYGPATH_W) 'loc2c.c'; else $(CYGPATH_W) '$(srcdir)/loc2c.c'; fi`
+stap-mdfour.o: mdfour.c
+@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT stap-mdfour.o -MD -MP -MF "$(DEPDIR)/stap-mdfour.Tpo" -c -o stap-mdfour.o `test -f 'mdfour.c' || echo '$(srcdir)/'`mdfour.c; \
+@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/stap-mdfour.Tpo" "$(DEPDIR)/stap-mdfour.Po"; else rm -f "$(DEPDIR)/stap-mdfour.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='mdfour.c' object='stap-mdfour.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o stap-mdfour.o `test -f 'mdfour.c' || echo '$(srcdir)/'`mdfour.c
+
+stap-mdfour.obj: mdfour.c
+@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT stap-mdfour.obj -MD -MP -MF "$(DEPDIR)/stap-mdfour.Tpo" -c -o stap-mdfour.obj `if test -f 'mdfour.c'; then $(CYGPATH_W) 'mdfour.c'; else $(CYGPATH_W) '$(srcdir)/mdfour.c'; fi`; \
+@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/stap-mdfour.Tpo" "$(DEPDIR)/stap-mdfour.Po"; else rm -f "$(DEPDIR)/stap-mdfour.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='mdfour.c' object='stap-mdfour.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o stap-mdfour.obj `if test -f 'mdfour.c'; then $(CYGPATH_W) 'mdfour.c'; else $(CYGPATH_W) '$(srcdir)/mdfour.c'; fi`
+
stpd.o: runtime/stpd/stpd.c
@am__fastdepCC_TRUE@ if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT stpd.o -MD -MP -MF "$(DEPDIR)/stpd.Tpo" -c -o stpd.o `test -f 'runtime/stpd/stpd.c' || echo '$(srcdir)/'`runtime/stpd/stpd.c; \
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/stpd.Tpo" "$(DEPDIR)/stpd.Po"; else rm -f "$(DEPDIR)/stpd.Tpo"; exit 1; fi
@@ -637,6 +658,48 @@ stap-buildrun.obj: buildrun.cxx
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='buildrun.cxx' object='stap-buildrun.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-buildrun.obj `if test -f 'buildrun.cxx'; then $(CYGPATH_W) 'buildrun.cxx'; else $(CYGPATH_W) '$(srcdir)/buildrun.cxx'; fi`
+
+stap-hash.o: hash.cxx
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-hash.o -MD -MP -MF "$(DEPDIR)/stap-hash.Tpo" -c -o stap-hash.o `test -f 'hash.cxx' || echo '$(srcdir)/'`hash.cxx; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/stap-hash.Tpo" "$(DEPDIR)/stap-hash.Po"; else rm -f "$(DEPDIR)/stap-hash.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='hash.cxx' object='stap-hash.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-hash.o `test -f 'hash.cxx' || echo '$(srcdir)/'`hash.cxx
+
+stap-hash.obj: hash.cxx
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-hash.obj -MD -MP -MF "$(DEPDIR)/stap-hash.Tpo" -c -o stap-hash.obj `if test -f 'hash.cxx'; then $(CYGPATH_W) 'hash.cxx'; else $(CYGPATH_W) '$(srcdir)/hash.cxx'; fi`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/stap-hash.Tpo" "$(DEPDIR)/stap-hash.Po"; else rm -f "$(DEPDIR)/stap-hash.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='hash.cxx' object='stap-hash.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-hash.obj `if test -f 'hash.cxx'; then $(CYGPATH_W) 'hash.cxx'; else $(CYGPATH_W) '$(srcdir)/hash.cxx'; fi`
+
+stap-cache.o: cache.cxx
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-cache.o -MD -MP -MF "$(DEPDIR)/stap-cache.Tpo" -c -o stap-cache.o `test -f 'cache.cxx' || echo '$(srcdir)/'`cache.cxx; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/stap-cache.Tpo" "$(DEPDIR)/stap-cache.Po"; else rm -f "$(DEPDIR)/stap-cache.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='cache.cxx' object='stap-cache.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-cache.o `test -f 'cache.cxx' || echo '$(srcdir)/'`cache.cxx
+
+stap-cache.obj: cache.cxx
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-cache.obj -MD -MP -MF "$(DEPDIR)/stap-cache.Tpo" -c -o stap-cache.obj `if test -f 'cache.cxx'; then $(CYGPATH_W) 'cache.cxx'; else $(CYGPATH_W) '$(srcdir)/cache.cxx'; fi`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/stap-cache.Tpo" "$(DEPDIR)/stap-cache.Po"; else rm -f "$(DEPDIR)/stap-cache.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='cache.cxx' object='stap-cache.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-cache.obj `if test -f 'cache.cxx'; then $(CYGPATH_W) 'cache.cxx'; else $(CYGPATH_W) '$(srcdir)/cache.cxx'; fi`
+
+stap-util.o: util.cxx
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-util.o -MD -MP -MF "$(DEPDIR)/stap-util.Tpo" -c -o stap-util.o `test -f 'util.cxx' || echo '$(srcdir)/'`util.cxx; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/stap-util.Tpo" "$(DEPDIR)/stap-util.Po"; else rm -f "$(DEPDIR)/stap-util.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='util.cxx' object='stap-util.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-util.o `test -f 'util.cxx' || echo '$(srcdir)/'`util.cxx
+
+stap-util.obj: util.cxx
+@am__fastdepCXX_TRUE@ if $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -MT stap-util.obj -MD -MP -MF "$(DEPDIR)/stap-util.Tpo" -c -o stap-util.obj `if test -f 'util.cxx'; then $(CYGPATH_W) 'util.cxx'; else $(CYGPATH_W) '$(srcdir)/util.cxx'; fi`; \
+@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/stap-util.Tpo" "$(DEPDIR)/stap-util.Po"; else rm -f "$(DEPDIR)/stap-util.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='util.cxx' object='stap-util.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(stap_CPPFLAGS) $(CPPFLAGS) $(stap_CXXFLAGS) $(CXXFLAGS) -c -o stap-util.obj `if test -f 'util.cxx'; then $(CYGPATH_W) 'util.cxx'; else $(CYGPATH_W) '$(srcdir)/util.cxx'; fi`
uninstall-info-am:
install-man1: $(man1_MANS) $(man_MANS)
@$(NORMAL_INSTALL)
diff --git a/cache.cxx b/cache.cxx
new file mode 100644
index 00000000..0bbc8416
--- /dev/null
+++ b/cache.cxx
@@ -0,0 +1,113 @@
+#include "session.h"
+#include "cache.h"
+#include "util.h"
+#include <cerrno>
+#include <string>
+
+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;
+ }
+ }
+
+ // 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;
+ }
+
+ close(fd_module);
+ close(fd_c);
+ return true;
+}
diff --git a/cache.h b/cache.h
new file mode 100644
index 00000000..9c171c42
--- /dev/null
+++ b/cache.h
@@ -0,0 +1,2 @@
+void add_to_cache(systemtap_session& s);
+bool get_from_cache(systemtap_session& s);
diff --git a/hash.cxx b/hash.cxx
new file mode 100644
index 00000000..26a8ee6f
--- /dev/null
+++ b/hash.cxx
@@ -0,0 +1,168 @@
+// Copyright (C) Andrew Tridgell 2002 (original file)
+// Copyright (C) 2006 Red Hat Inc. (systemtap changes)
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+#include "config.h"
+#include "session.h"
+#include "hash.h"
+#include "util.h"
+#include <sstream>
+#include <iomanip>
+#include <cerrno>
+
+extern "C" {
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+}
+
+using namespace std;
+
+void
+hash::start()
+{
+ mdfour_begin(&md4);
+}
+
+
+void
+hash::add(const unsigned char *buffer, size_t size)
+{
+ mdfour_update(&md4, buffer, size);
+}
+
+
+void
+hash::result(string& r)
+{
+ ostringstream rstream;
+ unsigned char sum[16];
+
+ mdfour_update(&md4, NULL, 0);
+ mdfour_result(&md4, sum);
+
+ for (int i=0; i<16; i++)
+ {
+ rstream << hex << setfill('0') << setw(2) << (unsigned)sum[i];
+ }
+ rstream << "_" << setw(0) << dec << (unsigned)md4.totalN;
+ r = rstream.str();
+}
+
+
+// Grabbed from linux/module.h kernel include.
+#define MODULE_NAME_LEN (64 - sizeof(unsigned long))
+
+void
+find_hash (systemtap_session& s, const string& script)
+{
+ hash h;
+ int nlevels = 1;
+ struct stat st;
+
+ // We use a N level subdir for the cache path. Let N be adjustable.
+ const char *s_n;
+ if ((s_n = getenv("SYSTEMTAP_NLEVELS")))
+ {
+ nlevels = atoi(s_n);
+ if (nlevels < 1) nlevels = 1;
+ if (nlevels > 8) nlevels = 8;
+ }
+
+ // Hash getuid. This really shouldn't be necessary (since who you
+ // are doesn't change the generated output), but the hash gets used
+ // as the module name. If two different users try to run the same
+ // script at the same time, we need something to differentiate the
+ // module name.
+ h.add(getuid());
+
+ // Hash kernel release and arch.
+ h.add(s.kernel_release);
+ h.add(s.architecture);
+
+ // Hash user-specified arguments (that change the generated module).
+ for (unsigned i = 0; i < s.macros.size(); i++)
+ h.add(s.macros[i]);
+
+ // Hash runtime path (that gets added in as "-I path").
+ h.add(s.runtime_path);
+
+ // Hash compiler path, size, and mtime. We're just going to assume
+ // we'll be using gcc, which should be correct most of the time.
+ string gcc_path;
+ if (find_executable("gcc", gcc_path))
+ {
+ if (stat(gcc_path.c_str(), &st) == 0)
+ {
+ h.add(gcc_path);
+ h.add(st.st_size);
+ h.add(st.st_mtime);
+ }
+ }
+
+ // Hash the systemtap size and mtime. We could use VERSION/DATE,
+ // but when developing systemtap that doesn't work well (since you
+ // can compile systemtap multiple times in 1 day). Since we don't
+ // know exactly where we're getting run from, we'll use
+ // /proc/self/exe.
+ if (stat("/proc/self/exe", &st) == 0)
+ {
+ h.add(st.st_size);
+ h.add(st.st_mtime);
+ }
+
+ // Add in pass 2 script output.
+ h.add(script);
+
+ // Use a N level subdir for the cache path to reduce the impact on
+ // filesystems which are slow for large directories.
+ string hashdir = s.cache_path;
+ string result;
+ h.result(result);
+
+ for (int i = 0; i < nlevels; i++)
+ {
+ hashdir += string("/") + result[i*2] + result[i*2 + 1];
+ if (create_dir(hashdir.c_str()) != 0)
+ {
+ cerr << "Warning: failed to create cache directory (\""
+ << hashdir + "\"): " << strerror(errno) << endl;
+ cerr << "Disabling cache support." << endl;
+ s.use_cache = false;
+ return;
+ }
+ }
+
+ // Update module name to be 'stap_{hash start}'. '{hash start}'
+ // must not be too long. This shouldn't happen, since the maximum
+ // size of a hash is 32 fixed chars + 1 (for the '_') + a max of 11.
+ s.module_name = "stap_" + result;
+ if (s.module_name.size() >= (MODULE_NAME_LEN - 1))
+ s.module_name.resize(MODULE_NAME_LEN - 1);
+
+ // 'ccache' would use a hash path of something like:
+ // s.hash_path = hashdir + "/" + result.substr(nlevels);
+ // which would look like:
+ // ~/.stap_cache/A/B/CDEFGHIJKLMNOPQRSTUVWXYZABCDEF_XXX
+ //
+ // We're using the following so that the module can be used straight
+ // from the cache if desired. This ends up looking like this:
+ // ~/.stap_cache/A/B/stap_ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEF_XXX.ko
+ s.hash_path = hashdir + "/" + s.module_name + ".ko";
+
+ // Update C source name with new module_name.
+ s.translated_source = string(s.tmpdir) + "/" + s.module_name + ".c";
+}
diff --git a/hash.h b/hash.h
new file mode 100644
index 00000000..e923fee4
--- /dev/null
+++ b/hash.h
@@ -0,0 +1,34 @@
+#include <string>
+
+extern "C" {
+#include <string.h>
+#include <mdfour.h>
+}
+
+class hash
+{
+private:
+ struct mdfour md4;
+
+public:
+ hash() { start(); }
+
+ void start();
+
+ void add(const unsigned char *buffer, size_t size);
+ void add(const int x) { add((const unsigned char *)&x, sizeof(x)); }
+ void add(const long x) { add((const unsigned char *)&x, sizeof(x)); }
+ void add(const long long x) { add((const unsigned char *)&x, sizeof(x)); }
+ void add(const unsigned int x) { add((const unsigned char *)&x, sizeof(x)); }
+ void add(const unsigned long x) { add((const unsigned char *)&x,
+ sizeof(x)); }
+ void add(const unsigned long long x) { add((const unsigned char *)&x,
+ sizeof(x)); }
+ void add(const char *s) { add((const unsigned char *)s, strlen(s)); }
+ void add(const std::string& s) { add((const unsigned char *)s.c_str(),
+ s.length()); }
+
+ void result(std::string& r);
+};
+
+void find_hash (systemtap_session& s, const std::string& script);
diff --git a/main.cxx b/main.cxx
index 12cca4c7..f5faf1bf 100644
--- a/main.cxx
+++ b/main.cxx
@@ -15,6 +15,9 @@
#include "translate.h"
#include "buildrun.h"
#include "session.h"
+#include "hash.h"
+#include "cache.h"
+#include "util.h"
#include <iostream>
#include <fstream>
@@ -113,6 +116,65 @@ stringify(T t)
}
+static void
+printscript(systemtap_session& s, ostream& o)
+{
+ if (s.globals.size() > 0)
+ o << "# globals" << endl;
+ for (unsigned i=0; i<s.globals.size(); i++)
+ {
+ vardecl* v = s.globals[i];
+ v->printsig (o);
+ o << endl;
+ }
+
+ if (s.functions.size() > 0)
+ o << "# functions" << endl;
+ for (unsigned i=0; i<s.functions.size(); i++)
+ {
+ functiondecl* f = s.functions[i];
+ f->printsig (o);
+ o << endl;
+ if (f->locals.size() > 0)
+ o << " # locals" << endl;
+ for (unsigned j=0; j<f->locals.size(); j++)
+ {
+ vardecl* v = f->locals[j];
+ o << " ";
+ v->printsig (o);
+ o << endl;
+ }
+ if (s.verbose)
+ {
+ f->body->print (o);
+ o << endl;
+ }
+ }
+
+ if (s.probes.size() > 0)
+ o << "# probes" << endl;
+ for (unsigned i=0; i<s.probes.size(); i++)
+ {
+ derived_probe* p = s.probes[i];
+ p->printsig (o);
+ o << endl;
+ if (p->locals.size() > 0)
+ o << " # locals" << endl;
+ for (unsigned j=0; j<p->locals.size(); j++)
+ {
+ vardecl* v = p->locals[j];
+ o << " ";
+ v->printsig (o);
+ o << endl;
+ }
+ if (s.verbose)
+ {
+ p->body->print (o);
+ o << endl;
+ }
+ }
+}
+
int
main (int argc, char * const argv [])
{
@@ -140,6 +202,7 @@ main (int argc, char * const argv [])
s.target_pid = 0;
s.merge=true;
s.perfmon=0;
+ s.use_cache = true;
const char* s_p = getenv ("SYSTEMTAP_TAPSET");
if (s_p != NULL)
@@ -159,6 +222,33 @@ main (int argc, char * const argv [])
else
s.runtime_path = string(PKGDATADIR) + "/runtime";
+ const char* s_d = getenv ("SYSTEMTAP_DIR");
+ if (s_d != NULL)
+ s.data_path = s_d;
+ else
+ s.data_path = get_home_directory() + string("/.systemtap");
+ if (create_dir(s.data_path.c_str()) == 1)
+ {
+ const char* e = strerror (errno);
+ cerr << "Warning: failed to create systemtap data directory (\""
+ << s.data_path << "\"): " << e << endl;
+ cerr << "Disabling cache support." << endl;
+ s.use_cache = false;
+ }
+
+ if (s.use_cache)
+ {
+ s.cache_path = s.data_path + "/cache";
+ if (create_dir(s.cache_path.c_str()) == 1)
+ {
+ const char* e = strerror (errno);
+ cerr << "Warning: failed to create cache directory (\""
+ << s.cache_path << "\"): " << e << endl;
+ cerr << "Disabling cache support." << endl;
+ s.use_cache = false;
+ }
+ }
+
while (true)
{
int grc = getopt (argc, argv, "hVMvtp:I:e:o:R:r:m:kgc:x:D:bs:u");
@@ -216,6 +306,8 @@ main (int argc, char * const argv [])
case 'm':
s.module_name = string (optarg);
+ cerr << "Warning: using '-m' disables cache support." << endl;
+ s.use_cache = false;
break;
case 'r':
@@ -339,6 +431,10 @@ main (int argc, char * const argv [])
clog << "Created temporary directory \"" << s.tmpdir << "\"" << endl;
}
+ // Create the name of the C source file within the temporary
+ // directory.
+ s.translated_source = string(s.tmpdir) + "/" + s.module_name + ".c";
+
struct tms tms_before;
times (& tms_before);
struct timeval tv_before;
@@ -469,62 +565,7 @@ main (int argc, char * const argv [])
rc = semantic_pass (s);
if (rc == 0 && s.last_pass == 2)
- {
- if (s.globals.size() > 0)
- cout << "# globals" << endl;
- for (unsigned i=0; i<s.globals.size(); i++)
- {
- vardecl* v = s.globals[i];
- v->printsig (cout);
- cout << endl;
- }
-
- if (s.functions.size() > 0)
- cout << "# functions" << endl;
- for (unsigned i=0; i<s.functions.size(); i++)
- {
- functiondecl* f = s.functions[i];
- f->printsig (cout);
- cout << endl;
- if (f->locals.size() > 0)
- cout << " # locals" << endl;
- for (unsigned j=0; j<f->locals.size(); j++)
- {
- vardecl* v = f->locals[j];
- cout << " ";
- v->printsig (cout);
- cout << endl;
- }
- if (s.verbose)
- {
- f->body->print (cout);
- cout << endl;
- }
- }
-
- if (s.probes.size() > 0)
- cout << "# probes" << endl;
- for (unsigned i=0; i<s.probes.size(); i++)
- {
- derived_probe* p = s.probes[i];
- p->printsig (cout);
- cout << endl;
- if (p->locals.size() > 0)
- cout << " # locals" << endl;
- for (unsigned j=0; j<p->locals.size(); j++)
- {
- vardecl* v = p->locals[j];
- cout << " ";
- v->printsig (cout);
- cout << endl;
- }
- if (s.verbose)
- {
- p->body->print (cout);
- cout << endl;
- }
- }
- }
+ printscript(s, cout);
times (& tms_after);
gettimeofday (&tv_after, NULL);
@@ -540,6 +581,38 @@ main (int argc, char * const argv [])
cerr << "Pass 2: analysis failed. "
<< "Try again with more '-v' (verbose) options."
<< endl;
+ // Generate hash. There isn't any point in generating the hash
+ // if last_pass is 2, since we'll quit before using it.
+ else if (s.last_pass != 2 && s.use_cache)
+ {
+ ostringstream o;
+ unsigned saved_verbose;
+
+ // Make sure we're in verbose mode, so that printscript()
+ // will output function/probe bodies.
+ saved_verbose = s.verbose;
+ s.verbose = 3;
+
+ // Print script to 'o'
+ printscript(s, o);
+
+ // Restore original verbose mode setting.
+ s.verbose = saved_verbose;
+
+ // Generate hash
+ find_hash (s, o.str());
+
+ // See if we can use cached source/module.
+ if (get_from_cache(s))
+ {
+ // If our last pass isn't 5, we're done (since passes 3 and
+ // 4 just generate what we just pulled out of the cache).
+ if (s.last_pass < 5) goto cleanup;
+
+ // Short-circuit to pass 5.
+ goto pass_5;
+ }
+ }
if (rc || s.last_pass == 2) goto cleanup;
@@ -548,7 +621,6 @@ main (int argc, char * const argv [])
times (& tms_before);
gettimeofday (&tv_before, NULL);
- s.translated_source = string(s.tmpdir) + "/" + s.module_name + ".c";
rc = translate_pass (s);
if (rc == 0 && s.last_pass == 3)
@@ -590,11 +662,17 @@ main (int argc, char * const argv [])
cerr << "Pass 4: compilation failed. "
<< "Try again with more '-v' (verbose) options."
<< endl;
+ else if (s.use_cache)
+ {
+ // Update cache.
+ add_to_cache(s);
+ }
// XXX: what to do if rc==0 && last_pass == 4? dump .ko file to stdout?
if (rc || s.last_pass == 4) goto cleanup;
// PASS 5: RUN
+pass_5:
times (& tms_before);
gettimeofday (&tv_before, NULL);
// NB: this message is a judgement call. The other passes don't emit
diff --git a/mdfour.c b/mdfour.c
new file mode 100644
index 00000000..d33925ad
--- /dev/null
+++ b/mdfour.c
@@ -0,0 +1,218 @@
+/*
+ a implementation of MD4 designed for use in the SMB authentication protocol
+ Copyright (C) Andrew Tridgell 1997-1998.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include "mdfour.h"
+
+/* NOTE: This code makes no attempt to be fast!
+
+ It assumes that a int is at least 32 bits long
+*/
+
+static struct mdfour *m;
+
+#define MASK32 (0xffffffff)
+
+#define F(X,Y,Z) ((((X)&(Y)) | ((~(X))&(Z))))
+#define G(X,Y,Z) ((((X)&(Y)) | ((X)&(Z)) | ((Y)&(Z))))
+#define H(X,Y,Z) (((X)^(Y)^(Z)))
+#define lshift(x,s) (((((x)<<(s))&MASK32) | (((x)>>(32-(s)))&MASK32)))
+
+#define ROUND1(a,b,c,d,k,s) a = lshift((a + F(b,c,d) + M[k])&MASK32, s)
+#define ROUND2(a,b,c,d,k,s) a = lshift((a + G(b,c,d) + M[k] + 0x5A827999)&MASK32,s)
+#define ROUND3(a,b,c,d,k,s) a = lshift((a + H(b,c,d) + M[k] + 0x6ED9EBA1)&MASK32,s)
+
+/* this applies md4 to 64 byte chunks */
+static void
+mdfour64(uint32_t *M)
+{
+ uint32_t AA, BB, CC, DD;
+ uint32_t A,B,C,D;
+
+ A = m->A; B = m->B; C = m->C; D = m->D;
+ AA = A; BB = B; CC = C; DD = D;
+
+ ROUND1(A,B,C,D, 0, 3); ROUND1(D,A,B,C, 1, 7);
+ ROUND1(C,D,A,B, 2, 11); ROUND1(B,C,D,A, 3, 19);
+ ROUND1(A,B,C,D, 4, 3); ROUND1(D,A,B,C, 5, 7);
+ ROUND1(C,D,A,B, 6, 11); ROUND1(B,C,D,A, 7, 19);
+ ROUND1(A,B,C,D, 8, 3); ROUND1(D,A,B,C, 9, 7);
+ ROUND1(C,D,A,B, 10, 11); ROUND1(B,C,D,A, 11, 19);
+ ROUND1(A,B,C,D, 12, 3); ROUND1(D,A,B,C, 13, 7);
+ ROUND1(C,D,A,B, 14, 11); ROUND1(B,C,D,A, 15, 19);
+
+
+ ROUND2(A,B,C,D, 0, 3); ROUND2(D,A,B,C, 4, 5);
+ ROUND2(C,D,A,B, 8, 9); ROUND2(B,C,D,A, 12, 13);
+ ROUND2(A,B,C,D, 1, 3); ROUND2(D,A,B,C, 5, 5);
+ ROUND2(C,D,A,B, 9, 9); ROUND2(B,C,D,A, 13, 13);
+ ROUND2(A,B,C,D, 2, 3); ROUND2(D,A,B,C, 6, 5);
+ ROUND2(C,D,A,B, 10, 9); ROUND2(B,C,D,A, 14, 13);
+ ROUND2(A,B,C,D, 3, 3); ROUND2(D,A,B,C, 7, 5);
+ ROUND2(C,D,A,B, 11, 9); ROUND2(B,C,D,A, 15, 13);
+
+ ROUND3(A,B,C,D, 0, 3); ROUND3(D,A,B,C, 8, 9);
+ ROUND3(C,D,A,B, 4, 11); ROUND3(B,C,D,A, 12, 15);
+ ROUND3(A,B,C,D, 2, 3); ROUND3(D,A,B,C, 10, 9);
+ ROUND3(C,D,A,B, 6, 11); ROUND3(B,C,D,A, 14, 15);
+ ROUND3(A,B,C,D, 1, 3); ROUND3(D,A,B,C, 9, 9);
+ ROUND3(C,D,A,B, 5, 11); ROUND3(B,C,D,A, 13, 15);
+ ROUND3(A,B,C,D, 3, 3); ROUND3(D,A,B,C, 11, 9);
+ ROUND3(C,D,A,B, 7, 11); ROUND3(B,C,D,A, 15, 15);
+
+ A += AA; B += BB;
+ C += CC; D += DD;
+
+ A &= MASK32; B &= MASK32;
+ C &= MASK32; D &= MASK32;
+
+ m->A = A; m->B = B; m->C = C; m->D = D;
+}
+
+static void
+copy64(uint32_t *M, const unsigned char *in)
+{
+ int i;
+
+ for (i=0;i<16;i++)
+ M[i] = (in[i*4+3]<<24) | (in[i*4+2]<<16) |
+ (in[i*4+1]<<8) | (in[i*4+0]<<0);
+}
+
+static void
+copy4(unsigned char *out,uint32_t x)
+{
+ out[0] = x&0xFF;
+ out[1] = (x>>8)&0xFF;
+ out[2] = (x>>16)&0xFF;
+ out[3] = (x>>24)&0xFF;
+}
+
+void
+mdfour_begin(struct mdfour *md)
+{
+ md->A = 0x67452301;
+ md->B = 0xefcdab89;
+ md->C = 0x98badcfe;
+ md->D = 0x10325476;
+ md->totalN = 0;
+ md->tail_len = 0;
+}
+
+
+static void
+mdfour_tail(const unsigned char *in, int n)
+{
+ unsigned char buf[128];
+ uint32_t M[16];
+ uint32_t b;
+
+ m->totalN += n;
+
+ b = m->totalN * 8;
+
+ memset(buf, 0, 128);
+ if (n) memcpy(buf, in, n);
+ buf[n] = 0x80;
+
+ if (n <= 55)
+ {
+ copy4(buf+56, b);
+ copy64(M, buf);
+ mdfour64(M);
+ }
+ else
+ {
+ copy4(buf+120, b);
+ copy64(M, buf);
+ mdfour64(M);
+ copy64(M, buf+64);
+ mdfour64(M);
+ }
+}
+
+void
+mdfour_update(struct mdfour *md, const unsigned char *in, int n)
+{
+ uint32_t M[16];
+
+ m = md;
+
+ if (in == NULL)
+ {
+ mdfour_tail(md->tail, md->tail_len);
+ return;
+ }
+
+ if (md->tail_len)
+ {
+ int len = 64 - md->tail_len;
+ if (len > n) len = n;
+ memcpy(md->tail+md->tail_len, in, len);
+ md->tail_len += len;
+ n -= len;
+ in += len;
+ if (md->tail_len == 64)
+ {
+ copy64(M, md->tail);
+ mdfour64(M);
+ m->totalN += 64;
+ md->tail_len = 0;
+ }
+ }
+
+ while (n >= 64)
+ {
+ copy64(M, in);
+ mdfour64(M);
+ in += 64;
+ n -= 64;
+ m->totalN += 64;
+ }
+
+ if (n)
+ {
+ memcpy(md->tail, in, n);
+ md->tail_len = n;
+ }
+}
+
+
+void
+mdfour_result(struct mdfour *md, unsigned char *out)
+{
+ m = md;
+
+ copy4(out, m->A);
+ copy4(out+4, m->B);
+ copy4(out+8, m->C);
+ copy4(out+12, m->D);
+}
+
+
+void
+mdfour(unsigned char *out, const unsigned char *in, int n)
+{
+ struct mdfour md;
+ mdfour_begin(&md);
+ mdfour_update(&md, in, n);
+ mdfour_update(&md, NULL, 0);
+ mdfour_result(&md, out);
+}
diff --git a/mdfour.h b/mdfour.h
new file mode 100644
index 00000000..223302ad
--- /dev/null
+++ b/mdfour.h
@@ -0,0 +1,39 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 1.9.
+ a implementation of MD4 designed for use in the SMB authentication protocol
+ Copyright (C) Andrew Tridgell 1997-1998.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <stdint.h>
+
+struct mdfour
+{
+ uint32_t A, B, C, D;
+ uint32_t totalN;
+ unsigned char tail[64];
+ unsigned tail_len;
+};
+
+void mdfour_begin(struct mdfour *md);
+void mdfour_update(struct mdfour *md, const unsigned char *in, int n);
+void mdfour_result(struct mdfour *md, unsigned char *out);
+void mdfour(unsigned char *out, const unsigned char *in, int n);
+
+
+
+
diff --git a/session.h b/session.h
index 75e13136..a60611d4 100644
--- a/session.h
+++ b/session.h
@@ -70,6 +70,7 @@ struct systemtap_session
std::string kernel_base_release;
std::string architecture;
std::string runtime_path;
+ std::string data_path;
std::string module_name;
std::string output_file;
std::string cmd;
@@ -85,6 +86,11 @@ struct systemtap_session
int buffer_size;
unsigned perfmon;
+ // Cache data
+ bool use_cache;
+ std::string cache_path;
+ std::string hash_path;
+
// temporary directory for module builds etc.
// hazardous - it is "rm -rf"'d at exit
std::string tmpdir;
diff --git a/util.cxx b/util.cxx
new file mode 100644
index 00000000..af953395
--- /dev/null
+++ b/util.cxx
@@ -0,0 +1,199 @@
+// Copyright (C) Andrew Tridgell 2002 (original file)
+// Copyright (C) 2006 Red Hat Inc. (systemtap changes)
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+#include "util.h"
+#include <stdexcept>
+#include <cerrno>
+
+extern "C" {
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <pwd.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <fcntl.h>
+}
+
+using namespace std;
+
+
+// Return current users home directory or die.
+const char *
+get_home_directory(void)
+{
+ const char *p = getenv("HOME");
+ if (p)
+ return p;
+
+ struct passwd *pwd = getpwuid(getuid());
+ if (pwd)
+ return pwd->pw_dir;
+
+ throw runtime_error("Unable to determine home directory");
+ return NULL;
+}
+
+
+// Copy a file. The copy is done via a temporary file and atomic
+// rename.
+int
+copy_file(const char *src, const char *dest)
+{
+ int fd1, fd2;
+ char buf[10240];
+ int n;
+ string tmp;
+ char *tmp_name;
+ mode_t mask;
+
+ // Open the src file.
+ fd1 = open(src, O_RDONLY);
+ if (fd1 == -1)
+ return -1;
+
+ // Open the temporary output file.
+ tmp = dest + string(".XXXXXX");
+ tmp_name = (char *)tmp.c_str();
+ fd2 = mkstemp(tmp_name);
+ if (fd2 == -1)
+ {
+ close(fd1);
+ return -1;
+ }
+
+ // Copy the src file to the temporary output file.
+ while ((n = read(fd1, buf, sizeof(buf))) > 0)
+ {
+ if (write(fd2, buf, n) != n)
+ {
+ close(fd2);
+ close(fd1);
+ unlink(tmp_name);
+ return -1;
+ }
+ }
+ close(fd1);
+
+ // Set the permissions on the temporary output file.
+ mask = umask(0);
+ fchmod(fd2, 0666 & ~mask);
+ umask(mask);
+
+ // Close the temporary output file. The close can fail on NFS if
+ // out of space.
+ if (close(fd2) == -1)
+ {
+ unlink(tmp_name);
+ return -1;
+ }
+
+ // Rename the temporary output file to the destination file.
+ unlink(dest);
+ if (rename(tmp_name, dest) == -1)
+ {
+ unlink(tmp_name);
+ return -1;
+ }
+
+ return 0;
+}
+
+
+// Make sure a directory exists.
+int
+create_dir(const char *dir)
+{
+ struct stat st;
+ if (stat(dir, &st) == 0)
+ {
+ if (S_ISDIR(st.st_mode))
+ return 0;
+ errno = ENOTDIR;
+ return 1;
+ }
+
+ if (mkdir(dir, 0777) != 0 && errno != EEXIST)
+ return 1;
+
+ return 0;
+}
+
+
+void
+tokenize(const string& str, vector<string>& tokens,
+ const string& delimiters = " ")
+{
+ // Skip delimiters at beginning.
+ string::size_type lastPos = str.find_first_not_of(delimiters, 0);
+ // Find first "non-delimiter".
+ string::size_type pos = str.find_first_of(delimiters, lastPos);
+
+ while (pos != string::npos || lastPos != string::npos)
+ {
+ // Found a token, add it to the vector.
+ tokens.push_back(str.substr(lastPos, pos - lastPos));
+ // Skip delimiters. Note the "not_of"
+ lastPos = str.find_first_not_of(delimiters, pos);
+ // Find next "non-delimiter"
+ pos = str.find_first_of(delimiters, lastPos);
+ }
+}
+
+
+// Find an executable by name in $PATH.
+bool
+find_executable(const char *name, string& retpath)
+{
+ const char *p;
+ string path;
+ vector<string> dirs;
+ struct stat st1, st2;
+
+ if (*name == '/')
+ {
+ retpath = name;
+ return true;
+ }
+
+ p = getenv("PATH");
+ if (!p)
+ return false;
+ path = p;
+
+ // Split PATH up.
+ tokenize(path, dirs, string(":"));
+
+ // Search the path looking for the first executable of the right name.
+ for (vector<string>::iterator i = dirs.begin(); i != dirs.end(); i++)
+ {
+ string fname = *i + "/" + name;
+ const char *f = fname.c_str();
+
+ // Look for a normal executable file.
+ if (access(f, X_OK) == 0
+ && lstat(f, &st1) == 0
+ && stat(f, &st2) == 0
+ && S_ISREG(st2.st_mode))
+ {
+ // Found it!
+ retpath = fname;
+ return true;
+ }
+ }
+
+ return false;
+}
diff --git a/util.h b/util.h
new file mode 100644
index 00000000..01f254c7
--- /dev/null
+++ b/util.h
@@ -0,0 +1,13 @@
+#include <string>
+#include <vector>
+
+const char *get_home_directory(void);
+
+int copy_file(const char *src, const char *dest);
+
+int create_dir(const char *dir);
+
+void tokenize(const std::string& str, std::vector<std::string>& tokens,
+ const std::string& delimiters);
+
+bool find_executable(const char *name, std::string& retpath);