summaryrefslogtreecommitdiffstats
path: root/util.cxx
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 /util.cxx
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.
Diffstat (limited to 'util.cxx')
-rw-r--r--util.cxx199
1 files changed, 199 insertions, 0 deletions
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;
+}