A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
system-path.cc
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 #if defined (HAVE_DIRENT_H) and defined (HAVE_SYS_TYPES_H)
29 #define HAVE_OPENDIR
30 #include <sys/types.h>
31 #include <dirent.h>
32 #endif
33 #if defined (HAVE_SYS_STAT_H) and defined (HAVE_SYS_TYPES_H)
34 #define HAVE_MKDIR_H
35 #include <sys/types.h>
36 #include <sys/stat.h>
37 #endif
38 #include <sstream>
39 #ifdef __APPLE__
40 #include <mach-o/dyld.h>
41 #endif /* __APPLE__ */
42 
43 #ifdef __FreeBSD__
44 #include <sys/types.h>
45 #include <sys/sysctl.h>
46 #endif
47 
48 #ifdef __linux__
49 #include <unistd.h>
50 #endif
51 
52 #if defined (__win32__)
53 #define SYSTEM_PATH_SEP "\\"
54 #else
55 #define SYSTEM_PATH_SEP "/"
56 #endif
57 
58 NS_LOG_COMPONENT_DEFINE ("SystemPath");
59 
60 namespace ns3 {
61 
62 namespace SystemPath {
63 
64 std::string Dirname (std::string path)
65 {
66  NS_LOG_FUNCTION (path);
67  std::list<std::string> elements = Split (path);
68  std::list<std::string>::const_iterator last = elements.end();
69  last--;
70  return Join (elements.begin (), last);
71 }
72 
73 std::string FindSelfDirectory (void)
74 {
85  std::string filename;
86 #if defined(__linux__)
87  {
88  ssize_t size = 1024;
89  char *buffer = (char*)malloc (size);
90  memset (buffer, 0, size);
91  int status;
92  while (true)
93  {
94  status = readlink("/proc/self/exe", buffer, size);
95  if (status != 1 || (status == -1 && errno != ENAMETOOLONG))
96  {
97  break;
98  }
99  size *= 2;
100  free (buffer);
101  buffer = (char*)malloc (size);
102  memset (buffer, 0, size);
103  }
104  if (status == -1)
105  {
106  NS_FATAL_ERROR ("Oops, could not find self directory.");
107  }
108  filename = buffer;
109  free (buffer);
110  }
111 #elif defined (__win32__)
112  {
113  // XXX: untested. it should work if code is compiled with
114  // LPTSTR = char *
115  DWORD size = 1024;
116  LPTSTR lpFilename = (LPTSTR) malloc (sizeof(TCHAR) * size);
117  DWORD status = GetModuleFilename (0, lpFilename, size);
118  while (status == size)
119  {
120  size = size * 2;
121  free (lpFilename);
122  lpFilename = (LPTSTR) malloc (sizeof(TCHAR) * size);
123  status = GetModuleFilename (0, lpFilename, size);
124  }
125  NS_ASSERT (status != 0);
126  filename = lpFilename;
127  free (lpFilename);
128  }
129 #elif defined (__APPLE__)
130  {
131  uint32_t bufsize = 1024;
132  char *buffer = (char *) malloc (bufsize);
133  NS_ASSERT (buffer != 0);
134  int status = _NSGetExecutablePath (buffer, &bufsize);
135  if (status == -1)
136  {
137  free (buffer);
138  buffer = (char *) malloc (bufsize);
139  status = _NSGetExecutablePath (buffer, &bufsize);
140  }
141  NS_ASSERT (status == 0);
142  filename = buffer;
143  free (buffer);
144  }
145 #elif defined (__FreeBSD__)
146  {
147  int mib[4];
148  size_t bufSize = 1024;
149  char *buf = (char *) malloc(bufSize);
150 
151  mib[0] = CTL_KERN;
152  mib[1] = KERN_PROC;
153  mib[2] = KERN_PROC_PATHNAME;
154  mib[3] = -1;
155 
156  sysctl(mib, 4, buf, &bufSize, NULL, 0);
157  filename = buf;
158  }
159 #endif
160  return Dirname (filename);
161 }
162 
163 std::string Append (std::string left, std::string right)
164 {
165  // removing trailing separators from 'left'
166  NS_LOG_FUNCTION (left << right);
167  while (true)
168  {
169  std::string::size_type lastSep = left.rfind (SYSTEM_PATH_SEP);
170  if (lastSep != left.size () - 1)
171  {
172  break;
173  }
174  left = left.substr (0, left.size () - 1);
175  }
176  std::string retval = left + SYSTEM_PATH_SEP + right;
177  return retval;
178 }
179 
180 std::list<std::string> Split (std::string path)
181 {
182  NS_LOG_FUNCTION (path);
183  std::list<std::string> retval;
184  std::string::size_type current = 0, next = 0;
185  next = path.find (SYSTEM_PATH_SEP, current);
186  while (next != std::string::npos)
187  {
188  std::string item = path.substr (current, next - current);
189  retval.push_back (item);
190  current = next + 1;
191  next = path.find (SYSTEM_PATH_SEP, current);
192  }
193  std::string item = path.substr (current, next - current);
194  retval.push_back (item);
195  return retval;
196 }
197 
198 std::string Join (std::list<std::string>::const_iterator begin,
199  std::list<std::string>::const_iterator end)
200 {
201  NS_LOG_FUNCTION (&begin << &end);
202  std::string retval = "";
203  for (std::list<std::string>::const_iterator i = begin; i != end; i++)
204  {
205  if (i == begin)
206  {
207  retval = *i;
208  }
209  else
210  {
211  retval = retval + SYSTEM_PATH_SEP + *i;
212  }
213  }
214  return retval;
215 }
216 
217 std::list<std::string> ReadFiles (std::string path)
218 {
219  NS_LOG_FUNCTION (path);
220  std::list<std::string> files;
221 #if defined HAVE_OPENDIR
222  DIR *dp = opendir (path.c_str ());
223  if (dp == NULL)
224  {
225  NS_FATAL_ERROR ("Could not open directory=" << path);
226  }
227  struct dirent *de = readdir (dp);
228  while (de != 0)
229  {
230  files.push_back (de->d_name);
231  de = readdir (dp);
232  }
233  closedir (dp);
234 #elif defined (HAVE_FIND_FIRST_FILE)
235  // XXX: untested
236  HANDLE hFind;
237  WIN32_FIND_DATA fileData;
238 
239  hFind = FindFirstFile (path.c_str (), &FindFileData);
240  if (hFind == INVALID_HANDLE_VALUE)
241  {
242  NS_FATAL_ERROR ("Could not open directory=" << path);
243  }
244  do
245  {
246  files.push_back (fileData.cFileName);
247  } while (FindNextFile (hFind, &fileData));
248  FindClose(hFind);
249 #else
250 #error "No support for reading a directory on this platform"
251 #endif
252  return files;
253 }
254 
255 std::string
257 {
259  char *path = NULL;
260 
261  path = getenv ("TMP");
262  if (path == NULL)
263  {
264  path = getenv ("TEMP");
265  if (path == NULL)
266  {
267  path = const_cast<char *> ("/tmp");
268  }
269  }
270 
271  //
272  // Just in case the user wants to go back and find the output, we give
273  // a hint as to which dir we created by including a time hint.
274  //
275  time_t now = time (NULL);
276  struct tm *tm_now = localtime (&now);
277  //
278  // But we also randomize the name in case there are multiple users doing
279  // this at the same time
280  //
281  srand (time (0));
282  long int n = rand ();
283 
284  //
285  // The final path to the directory is going to look something like
286  //
287  // /tmp/ns3-14.30.29.32767
288  //
289  // The first segment comes from one of the temporary directory env
290  // variables or /tmp if not found. The directory name starts with an
291  // identifier telling folks who is making all of the temp directories
292  // and then the local time (in this case 14.30.29 -- which is 2:30 and
293  // 29 seconds PM).
294  //
295  std::ostringstream oss;
296  oss << path << SYSTEM_PATH_SEP << "ns-3." << tm_now->tm_hour << "."
297  << tm_now->tm_min << "." << tm_now->tm_sec << "." << n;
298 
299  return oss.str ();
300 }
301 
302 void
303 MakeDirectories (std::string path)
304 {
305  NS_LOG_FUNCTION (path);
306  std::list<std::string> elements = Split (path);
307  for (std::list<std::string>::const_iterator i = elements.begin (); i != elements.end (); ++i)
308  {
309  std::string tmp = Join (elements.begin (), i);
310 #if defined(HAVE_MKDIR_H)
311  mkdir (tmp.c_str (), S_IRWXU);
312 #endif
313  }
314 #if defined(HAVE_MKDIR_H)
315  mkdir (path.c_str (), S_IRWXU);
316 #endif
317 
318 }
319 
320 } // namespace SystemPath
321 
322 } // namespace ns3
#define NS_LOG_FUNCTION(parameters)
Definition: log.h:311
#define NS_ASSERT(condition)
Definition: assert.h:64
#define NS_LOG_COMPONENT_DEFINE(name)
Definition: log.h:122
void MakeDirectories(std::string path)
Definition: system-path.cc:303
#define NS_LOG_FUNCTION_NOARGS()
Definition: log.h:275
#define NS_FATAL_ERROR(msg)
fatal error handling
Definition: fatal-error.h:72
std::string Join(std::list< std::string >::const_iterator begin, std::list< std::string >::const_iterator end)
Definition: system-path.cc:198
std::list< std::string > ReadFiles(std::string path)
Definition: system-path.cc:217
std::string FindSelfDirectory(void)
Definition: system-path.cc:73
std::string Append(std::string left, std::string right)
Definition: system-path.cc:163
std::string MakeTemporaryDirectoryName(void)
Definition: system-path.cc:256
std::list< std::string > Split(std::string path)
Definition: system-path.cc:180