ns-3 Direct Code Execution
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
dce-dirent.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2011 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  * Author: Frederic Urbani <frederic.urbani@inria.fr>
19  *
20  */
21 #include "dce-dirent.h"
22 #include "dce-fcntl.h"
23 #include "dce-unistd.h"
24 #include "unix-fd.h"
25 #include "unix-file-fd.h"
26 #include "file-usage.h"
27 #include "process.h"
28 #include "utils.h"
29 #include "unix-fd.h"
30 #include "ns3/log.h"
31 #include "errno.h"
32 #include "dce-stdlib.h"
33 #include <string.h>
34 
35 NS_LOG_COMPONENT_DEFINE ("DceDirent");
36 
38 {
39  int fd; /* File descriptor. */
40 };
41 
42 namespace ns3 {
43 void
44 remove_dir (DIR *d, Thread *current)
45 {
46  bool found = false;
47  for (std::vector<DIR*>::iterator i = current->process->openDirs.begin ();
48  i != current->process->openDirs.end (); ++i)
49  {
50  if (*i == d)
51  {
52  current->process->openDirs.erase (i);
53  found = true;
54  break;
55  }
56  }
57  if (!found)
58  {
59  // not found
60  NS_FATAL_ERROR ("invalid DIR * closed=" << d);
61  }
62 }
63 
64 int dce_internalClosedir (DIR *dirp, struct Thread *cur)
65 {
66  struct my__dirstream *ds = (struct my__dirstream *) dirp;
67  int saveFd = -1;
68 
69  if (cur)
70  {
71  saveFd = ds->fd;
72  if (saveFd >= 0)
73  {
74  cur->err = EBADF;
75  return -1;
76  }
77  int realFd = getRealFd (-saveFd, cur);
78  if (realFd < 0)
79  {
80  ds->fd = saveFd;
81  cur->err = EBADF;
82  return 0;
83  }
84  ds->fd = realFd;
85  }
86  else
87  {
88  ds->fd = -1;
89  }
90  int ret = closedir (dirp);
91  if (cur)
92  {
93  if (ret == 0)
94  {
95  dce_close (-saveFd);
96  ds->fd = saveFd;
97  remove_dir (dirp, cur);
98  }
99  else
100  {
101  cur->err = errno;
102  }
103  }
104  return ret;
105 }
106 }
107 
108 using namespace ns3;
109 
110 DIR * dce_opendir (const char *name)
111 {
112  NS_LOG_FUNCTION (Current () << UtilsGetNodeId () << name);
113  NS_ASSERT (Current () != 0);
114  Thread *current = Current ();
115  int fd = dce_open (name, O_DIRECTORY, 0);
116  if (fd == -1)
117  {
118  current->err = errno;
119  return 0;
120  }
121  DIR *res = dce_fdopendir (fd);
122  if (res == 0)
123  {
124  dce_close (fd);
125  }
126  return res;
127 }
128 DIR * dce_fdopendir (int fd)
129 {
130  NS_LOG_FUNCTION (Current () << UtilsGetNodeId () << fd);
131  NS_ASSERT (Current () != 0);
132  Thread *current = Current ();
133 
134  // no need to create or truncate. Just need to seek if needed.
135  DIR *res = opendir ("/");
136  if (res == 0)
137  {
138  current->err = errno;
139  return 0;
140  }
141  struct my__dirstream *ds = (struct my__dirstream *) res;
142  close (ds->fd);
143  ds->fd = -fd;
144  current->process->openDirs.push_back (res);
145 
146  return res;
147 }
148 
149 struct dirent * dce_readdir (DIR *dirp)
150 {
151  NS_LOG_FUNCTION (Current () << UtilsGetNodeId ());
152  NS_ASSERT (Current () != 0);
153  Thread *current = Current ();
154  struct my__dirstream *ds = (struct my__dirstream *) dirp;
155  int saveFd = ds->fd;
156  if (saveFd >= 0)
157  {
158  current->err = EBADF;
159  return 0;
160  }
161  int realFd = getRealFd (-saveFd, current);
162  if (realFd < 0)
163  {
164  ds->fd = saveFd;
165  current->err = EBADF;
166  return 0;
167  }
168  ds->fd = realFd;
169  struct dirent *ret = readdir (dirp);
170  ds->fd = saveFd;
171 
172  return ret;
173 }
174 
175 int dce_readdir_r (DIR *dirp, struct dirent *entry, struct dirent **result)
176 {
177  NS_LOG_FUNCTION (Current () << UtilsGetNodeId ());
178  NS_ASSERT (Current () != 0);
179  Thread *current = Current ();
180  struct my__dirstream *ds = (struct my__dirstream *) dirp;
181 
182  int saveFd = ds->fd;
183  if (saveFd >= 0)
184  {
185  current->err = EBADF;
186  return -1;
187  }
188  int realFd = getRealFd (-saveFd, current);
189  if (realFd < 0)
190  {
191  ds->fd = saveFd;
192  current->err = EBADF;
193  return -1;
194  }
195  ds->fd = realFd;
196  int ret = readdir_r (dirp, entry, result);
197  ds->fd = saveFd;
198 
199  return ret;
200 }
201 int dce_closedir (DIR *dirp)
202 {
203  NS_LOG_FUNCTION (Current () << UtilsGetNodeId ());
204  NS_ASSERT (Current () != 0);
205  Thread *current = Current ();
206  return dce_internalClosedir (dirp, current);
207 }
208 int dce_dirfd (DIR *dirp)
209 {
210  NS_LOG_FUNCTION (Current () << UtilsGetNodeId ());
211  NS_ASSERT (Current () != 0);
212  Thread *current = Current ();
213  current->err = ENOTSUP;
214  return -1;
215 }
216 void dce_rewinddir (DIR *dirp)
217 {
218  NS_LOG_FUNCTION (Current () << UtilsGetNodeId ());
219  NS_ASSERT (Current () != 0);
220  Thread *current = Current ();
221  struct my__dirstream *ds = (struct my__dirstream *) dirp;
222 
223  int saveFd = ds->fd;
224  if (saveFd >= 0)
225  {
226  return;
227  }
228  int realFd = getRealFd (-saveFd, current);
229  if (realFd < 0)
230  {
231  ds->fd = saveFd;
232  return;
233  }
234  ds->fd = realFd;
235  rewinddir (dirp);
236  ds->fd = saveFd;
237 }
238 int dce_scandir (const char *dirp, struct dirent ***namelist,
239  int (*filter)(const struct dirent *),
240  int (*compar)(const struct dirent **, const struct dirent **))
241 {
242  NS_LOG_FUNCTION (Current () << UtilsGetNodeId ());
243  NS_ASSERT (Current () != 0);
244 
245  std::string vPath = UtilsGetRealFilePath (std::string (dirp));
246 
247  struct dirent **nl = 0;
248  int ret = scandir (vPath.c_str (), &nl, filter, compar);
249 
250  if ((ret > 0) && nl)
251  {
252  // Realloc !
253  struct dirent **res = 0;
254  size_t direntMiniSize = 0;
255 
256  if (namelist)
257  {
258  res = (struct dirent **) dce_malloc (sizeof (struct dirent *) * ret);
259  }
260  {
261  struct dirent tmp;
262  direntMiniSize = sizeof (tmp.d_ino) + sizeof (tmp.d_off)
263  + sizeof (tmp.d_reclen) + sizeof (tmp.d_type);
264  }
265  for (int i = 0; i < ret ; i++)
266  {
267  struct dirent *src = nl [i];
268  struct dirent *copy = 0;
269  if (namelist)
270  {
271  size_t direntSize = direntMiniSize + _D_ALLOC_NAMLEN (src);
272  copy = (struct dirent *) dce_malloc (direntSize);
273  memcpy (copy, src, direntSize);
274  res [i] = copy;
275  }
276  free (src);
277  }
278  free (nl);
279  if (namelist)
280  {
281  *namelist = res;
282  }
283  }
284 
285  return ret;
286 }