/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ /* * Copyright (c) 2008 INRIA * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation; * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Authors: Mathieu Lacage */ #include "system-path.h" #include "fatal-error.h" #include "assert.h" #include "log.h" #include "ns3/core-config.h" #include #include #include #if defined (HAVE_DIRENT_H) and defined (HAVE_SYS_TYPES_H) #define HAVE_OPENDIR #include #include #endif #if defined (HAVE_SYS_STAT_H) and defined (HAVE_SYS_TYPES_H) #define HAVE_MKDIR_H #include #include #endif #include #ifdef __APPLE__ #include #endif /* __APPLE__ */ #ifdef __FreeBSD__ #include #include #endif #ifdef __linux__ #include #endif #if defined (__win32__) #define SYSTEM_PATH_SEP "\\" #else #define SYSTEM_PATH_SEP "/" #endif NS_LOG_COMPONENT_DEFINE ("SystemPath"); namespace ns3 { namespace SystemPath { std::string Dirname (std::string path) { NS_LOG_FUNCTION (path); std::list elements = Split (path); std::list::const_iterator last = elements.end(); last--; return Join (elements.begin (), last); } std::string FindSelfDirectory (void) { /** * This function returns the path to the running $PREFIX. * Mac OS X: _NSGetExecutablePath() (man 3 dyld) * Linux: readlink /proc/self/exe * Solaris: getexecname() * FreeBSD: sysctl CTL_KERN KERN_PROC KERN_PROC_PATHNAME -1 * BSD with procfs: readlink /proc/curproc/file * Windows: GetModuleFileName() with hModule = NULL */ NS_LOG_FUNCTION_NOARGS (); std::string filename; #if defined(__linux__) { ssize_t size = 1024; char *buffer = (char*)malloc (size); memset (buffer, 0, size); int status; while (true) { status = readlink("/proc/self/exe", buffer, size); if (status != 1 || (status == -1 && errno != ENAMETOOLONG)) { break; } size *= 2; free (buffer); buffer = (char*)malloc (size); memset (buffer, 0, size); } if (status == -1) { NS_FATAL_ERROR ("Oops, could not find self directory."); } filename = buffer; free (buffer); } #elif defined (__win32__) { // XXX: untested. it should work if code is compiled with // LPTSTR = char * DWORD size = 1024; LPTSTR lpFilename = (LPTSTR) malloc (sizeof(TCHAR) * size); DWORD status = GetModuleFilename (0, lpFilename, size); while (status == size) { size = size * 2; free (lpFilename); lpFilename = (LPTSTR) malloc (sizeof(TCHAR) * size); status = GetModuleFilename (0, lpFilename, size); } NS_ASSERT (status != 0); filename = lpFilename; free (lpFilename); } #elif defined (__APPLE__) { uint32_t bufsize = 1024; char *buffer = (char *) malloc (bufsize); NS_ASSERT (buffer != 0); int status = _NSGetExecutablePath (buffer, &bufsize); if (status == -1) { free (buffer); buffer = (char *) malloc (bufsize); status = _NSGetExecutablePath (buffer, &bufsize); } NS_ASSERT (status == 0); filename = buffer; free (buffer); } #elif defined (__FreeBSD__) { int mib[4]; size_t bufSize = 1024; char *buf = (char *) malloc(bufSize); mib[0] = CTL_KERN; mib[1] = KERN_PROC; mib[2] = KERN_PROC_PATHNAME; mib[3] = -1; sysctl(mib, 4, buf, &bufSize, NULL, 0); filename = buf; } #endif return Dirname (filename); } std::string Append (std::string left, std::string right) { // removing trailing separators from 'left' NS_LOG_FUNCTION (left << right); while (true) { std::string::size_type lastSep = left.rfind (SYSTEM_PATH_SEP); if (lastSep != left.size () - 1) { break; } left = left.substr (0, left.size () - 1); } std::string retval = left + SYSTEM_PATH_SEP + right; return retval; } std::list Split (std::string path) { NS_LOG_FUNCTION (path); std::list retval; std::string::size_type current = 0, next = 0; next = path.find (SYSTEM_PATH_SEP, current); while (next != std::string::npos) { std::string item = path.substr (current, next - current); retval.push_back (item); current = next + 1; next = path.find (SYSTEM_PATH_SEP, current); } std::string item = path.substr (current, next - current); retval.push_back (item); return retval; } std::string Join (std::list::const_iterator begin, std::list::const_iterator end) { NS_LOG_FUNCTION (&begin << &end); std::string retval = ""; for (std::list::const_iterator i = begin; i != end; i++) { if (i == begin) { retval = *i; } else { retval = retval + SYSTEM_PATH_SEP + *i; } } return retval; } std::list ReadFiles (std::string path) { NS_LOG_FUNCTION (path); std::list files; #if defined HAVE_OPENDIR DIR *dp = opendir (path.c_str ()); if (dp == NULL) { NS_FATAL_ERROR ("Could not open directory=" << path); } struct dirent *de = readdir (dp); while (de != 0) { files.push_back (de->d_name); de = readdir (dp); } closedir (dp); #elif defined (HAVE_FIND_FIRST_FILE) // XXX: untested HANDLE hFind; WIN32_FIND_DATA fileData; hFind = FindFirstFile (path.c_str (), &FindFileData); if (hFind == INVALID_HANDLE_VALUE) { NS_FATAL_ERROR ("Could not open directory=" << path); } do { files.push_back (fileData.cFileName); } while (FindNextFile (hFind, &fileData)); FindClose(hFind); #else #error "No support for reading a directory on this platform" #endif return files; } std::string MakeTemporaryDirectoryName (void) { NS_LOG_FUNCTION_NOARGS (); char *path = NULL; path = getenv ("TMP"); if (path == NULL) { path = getenv ("TEMP"); if (path == NULL) { path = const_cast ("/tmp"); } } // // Just in case the user wants to go back and find the output, we give // a hint as to which dir we created by including a time hint. // time_t now = time (NULL); struct tm *tm_now = localtime (&now); // // But we also randomize the name in case there are multiple users doing // this at the same time // srand (time (0)); long int n = rand (); // // The final path to the directory is going to look something like // // /tmp/ns3-14.30.29.32767 // // The first segment comes from one of the temporary directory env // variables or /tmp if not found. The directory name starts with an // identifier telling folks who is making all of the temp directories // and then the local time (in this case 14.30.29 -- which is 2:30 and // 29 seconds PM). // std::ostringstream oss; oss << path << SYSTEM_PATH_SEP << "ns-3." << tm_now->tm_hour << "." << tm_now->tm_min << "." << tm_now->tm_sec << "." << n; return oss.str (); } void MakeDirectories (std::string path) { NS_LOG_FUNCTION (path); std::list elements = Split (path); for (std::list::const_iterator i = elements.begin (); i != elements.end (); ++i) { std::string tmp = Join (elements.begin (), i); #if defined(HAVE_MKDIR_H) if (mkdir (tmp.c_str (), S_IRWXU)) { NS_LOG_ERROR ("failed creating directory " << tmp); } #endif } #if defined(HAVE_MKDIR_H) if (mkdir (path.c_str (), S_IRWXU)) { NS_LOG_ERROR ("failed creating directory " << path); } #endif } } // namespace SystemPath } // namespace ns3