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