A Discrete-Event Network Simulator
API
system-path.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2008 INRIA
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Authors: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
19  */
20 #include "system-path.h"
21 #include "fatal-error.h"
22 #include "assert.h"
23 #include "log.h"
24 #include "ns3/core-config.h"
25 #include <cstdlib>
26 #include <cerrno>
27 #include <cstring>
28 
29 
30 #if defined (HAVE_DIRENT_H) && defined (HAVE_SYS_TYPES_H)
31 
32 #define HAVE_OPENDIR
33 #include <sys/types.h>
34 #include <dirent.h>
35 #endif
36 #if defined (HAVE_SYS_STAT_H) && defined (HAVE_SYS_TYPES_H)
37 
38 #define HAVE_MKDIR_H
39 #include <sys/types.h>
40 #include <sys/stat.h>
41 #endif
42 #include <sstream>
43 #ifdef __APPLE__
44 #include <mach-o/dyld.h>
45 #endif /* __APPLE__ */
46 
47 #ifdef __FreeBSD__
48 #include <sys/types.h>
49 #include <sys/sysctl.h>
50 #endif
51 
52 #ifdef __linux__
53 #include <unistd.h>
54 #endif
55 
60 #if defined (__win32__)
61 #define SYSTEM_PATH_SEP "\\"
62 #else
63 #define SYSTEM_PATH_SEP "/"
64 #endif
65 
72 namespace ns3 {
73 
74 NS_LOG_COMPONENT_DEFINE ("SystemPath");
75 
76 namespace SystemPath {
77 
88 std::string Dirname (std::string path)
89 {
90  NS_LOG_FUNCTION (path);
91  std::list<std::string> elements = Split (path);
92  std::list<std::string>::const_iterator last = elements.end();
93  last--;
94  return Join (elements.begin (), last);
95 }
96 
97 std::string FindSelfDirectory (void)
98 {
109  std::string filename;
110 #if defined(__linux__)
111  {
112  ssize_t size = 1024;
113  char *buffer = (char*)malloc (size);
114  memset (buffer, 0, size);
115  int status;
116  while (true)
117  {
118  status = readlink("/proc/self/exe", buffer, size);
119  if (status != 1 || (status == -1 && errno != ENAMETOOLONG))
120  {
121  break;
122  }
123  size *= 2;
124  free (buffer);
125  buffer = (char*)malloc (size);
126  memset (buffer, 0, size);
127  }
128  if (status == -1)
129  {
130  NS_FATAL_ERROR ("Oops, could not find self directory.");
131  }
132  filename = buffer;
133  free (buffer);
134  }
135 #elif defined (__win32__)
136  {
140  DWORD size = 1024;
141  LPTSTR lpFilename = (LPTSTR) malloc (sizeof(TCHAR) * size);
142  DWORD status = GetModuleFilename (0, lpFilename, size);
143  while (status == size)
144  {
145  size = size * 2;
146  free (lpFilename);
147  lpFilename = (LPTSTR) malloc (sizeof(TCHAR) * size);
148  status = GetModuleFilename (0, lpFilename, size);
149  }
150  NS_ASSERT (status != 0);
151  filename = lpFilename;
152  free (lpFilename);
153  }
154 #elif defined (__APPLE__)
155  {
156  uint32_t bufsize = 1024;
157  char *buffer = (char *) malloc (bufsize);
158  NS_ASSERT (buffer != 0);
159  int status = _NSGetExecutablePath (buffer, &bufsize);
160  if (status == -1)
161  {
162  free (buffer);
163  buffer = (char *) malloc (bufsize);
164  status = _NSGetExecutablePath (buffer, &bufsize);
165  }
166  NS_ASSERT (status == 0);
167  filename = buffer;
168  free (buffer);
169  }
170 #elif defined (__FreeBSD__)
171  {
172  int mib[4];
173  std::size_t bufSize = 1024;
174  char *buf = (char *) malloc(bufSize);
175 
176  mib[0] = CTL_KERN;
177  mib[1] = KERN_PROC;
178  mib[2] = KERN_PROC_PATHNAME;
179  mib[3] = -1;
180 
181  sysctl(mib, 4, buf, &bufSize, NULL, 0);
182  filename = buf;
183  }
184 #endif
185  return Dirname (filename);
186 }
187 
188 std::string Append (std::string left, std::string right)
189 {
190  // removing trailing separators from 'left'
191  NS_LOG_FUNCTION (left << right);
192  while (true)
193  {
194  std::string::size_type lastSep = left.rfind (SYSTEM_PATH_SEP);
195  if (lastSep != left.size () - 1)
196  {
197  break;
198  }
199  left = left.substr (0, left.size () - 1);
200  }
201  std::string retval = left + SYSTEM_PATH_SEP + right;
202  return retval;
203 }
204 
205 std::list<std::string> Split (std::string path)
206 {
207  NS_LOG_FUNCTION (path);
208  std::list<std::string> retval;
209  std::string::size_type current = 0, next = 0;
210  next = path.find (SYSTEM_PATH_SEP, current);
211  while (next != std::string::npos)
212  {
213  std::string item = path.substr (current, next - current);
214  retval.push_back (item);
215  current = next + 1;
216  next = path.find (SYSTEM_PATH_SEP, current);
217  }
218  std::string item = path.substr (current, next - current);
219  retval.push_back (item);
220  return retval;
221 }
222 
223 std::string Join (std::list<std::string>::const_iterator begin,
224  std::list<std::string>::const_iterator end)
225 {
226  NS_LOG_FUNCTION (&begin << &end);
227  std::string retval = "";
228  for (std::list<std::string>::const_iterator i = begin; i != end; i++)
229  {
230  if (i == begin)
231  {
232  retval = *i;
233  }
234  else
235  {
236  retval = retval + SYSTEM_PATH_SEP + *i;
237  }
238  }
239  return retval;
240 }
241 
242 std::list<std::string> ReadFiles (std::string path)
243 {
244  NS_LOG_FUNCTION (path);
245  std::list<std::string> files;
246 #if defined HAVE_OPENDIR
247  DIR *dp = opendir (path.c_str ());
248  if (dp == NULL)
249  {
250  NS_FATAL_ERROR ("Could not open directory=" << path);
251  }
252  struct dirent *de = readdir (dp);
253  while (de != 0)
254  {
255  files.push_back (de->d_name);
256  de = readdir (dp);
257  }
258  closedir (dp);
259 #elif defined (HAVE_FIND_FIRST_FILE)
260 
261  HANDLE hFind;
262  WIN32_FIND_DATA fileData;
263 
264  hFind = FindFirstFile (path.c_str (), &FindFileData);
265  if (hFind == INVALID_HANDLE_VALUE)
266  {
267  NS_FATAL_ERROR ("Could not open directory=" << path);
268  }
269  do
270  {
271  files.push_back (fileData.cFileName);
272  } while (FindNextFile (hFind, &fileData));
273  FindClose(hFind);
274 #else
275 #error "No support for reading a directory on this platform"
276 #endif
277  return files;
278 }
279 
280 std::string
282 {
284  char *path = NULL;
285 
286  path = getenv ("TMP");
287  if (path == NULL)
288  {
289  path = getenv ("TEMP");
290  if (path == NULL)
291  {
292  path = const_cast<char *> ("/tmp");
293  }
294  }
295 
296  //
297  // Just in case the user wants to go back and find the output, we give
298  // a hint as to which dir we created by including a time hint.
299  //
300  time_t now = time (NULL);
301  struct tm *tm_now = localtime (&now);
302  //
303  // But we also randomize the name in case there are multiple users doing
304  // this at the same time
305  //
306  srand (time (0));
307  long int n = rand ();
308 
309  //
310  // The final path to the directory is going to look something like
311  //
312  // /tmp/ns3-14.30.29.32767
313  //
314  // The first segment comes from one of the temporary directory env
315  // variables or /tmp if not found. The directory name starts with an
316  // identifier telling folks who is making all of the temp directories
317  // and then the local time (in this case 14.30.29 -- which is 2:30 and
318  // 29 seconds PM).
319  //
320  std::ostringstream oss;
321  oss << path << SYSTEM_PATH_SEP << "ns-3." << tm_now->tm_hour << "."
322  << tm_now->tm_min << "." << tm_now->tm_sec << "." << n;
323 
324  return oss.str ();
325 }
326 
327 void
328 MakeDirectories (std::string path)
329 {
330  NS_LOG_FUNCTION (path);
331 
332  // Make sure all directories on the path exist
333  std::list<std::string> elements = Split (path);
334  auto i = elements.begin ();
335  while (i != elements.end ())
336  {
337  if (*i == "")
338  {
339  NS_LOG_LOGIC ("skipping empty directory name");
340  ++i;
341  continue;
342  }
343  NS_LOG_LOGIC ("creating directory " << *i);
344  ++i; // Now points to one past the directory we want to create
345  std::string tmp = Join (elements.begin (), i);
346  bool makeDirErr = false;
347 
348 #if defined(HAVE_MKDIR_H)
349  makeDirErr = mkdir (tmp.c_str (), S_IRWXU);
350 #endif
351 
352  if (makeDirErr)
353  {
354  NS_LOG_ERROR ("failed creating directory " << tmp);
355  }
356  }
357 }
358 
359 } // namespace SystemPath
360 
361 } // namespace ns3
NS_FATAL_x macro definitions.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file...
Definition: assert.h:67
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:162
#define NS_LOG_FUNCTION_NOARGS()
Output the name of the function.
std::list< std::string > Split(std::string path)
Split a file system path into directories according to the local path separator.
Definition: system-path.cc:205
ns3::SystemPath declarations.
std::string Join(std::list< std::string >::const_iterator begin, std::list< std::string >::const_iterator end)
Join a list of file system path directories into a single file system path.
Definition: system-path.cc:223
NS_ASSERT() and NS_ASSERT_MSG() macro definitions.
std::string MakeTemporaryDirectoryName(void)
Get the name of a temporary directory.
Definition: system-path.cc:281
std::list< std::string > ReadFiles(std::string path)
Get the list of files located in a file system directory.
Definition: system-path.cc:242
std::string Dirname(std::string path)
Get the directory path for a file.
Definition: system-path.cc:88
Every class exported by the ns3 library is enclosed in the ns3 namespace.
NS_LOG_LOGIC("Net device "<< nd<< " is not bridged")
void MakeDirectories(std::string path)
Create all the directories leading to path.
Definition: system-path.cc:328
std::string FindSelfDirectory(void)
Get the file system path to the current executable.
Definition: system-path.cc:97
std::string Append(std::string left, std::string right)
Join two file system path elements.
Definition: system-path.cc:188
#define SYSTEM_PATH_SEP
System-specific path separator used between directory names.
Definition: system-path.cc:63
#define NS_LOG_ERROR(msg)
Use NS_LOG to output a message of level LOG_ERROR.
Definition: log.h:254
Debug message logging.