ns-3 Direct Code Execution
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
dce-stdio.cc
Go to the documentation of this file.
1 #include "dce-stdio.h"
2 #include "dce-stdarg.h"
3 #include "dce-fcntl.h"
4 #include "dce-unistd.h"
5 #include "dce-stdlib.h"
6 #include "sys/dce-stat.h"
7 #include "process.h"
8 #include "utils.h"
9 #include "unix-fd.h"
10 #include "ns3/log.h"
11 #include <errno.h>
12 #include <fcntl.h>
13 #include <stdlib.h>
14 #include <dlfcn.h>
15 #include <sys/mman.h>
16 #include <libio.h>
17 #include <string.h>
18 
19 NS_LOG_COMPONENT_DEFINE ("DceStdio");
20 
21 using namespace ns3;
22 
23 namespace {
24 
26 {
27  size_t dummy0;
28  size_t dummy1;
29  void *functions[12];
30  void *__read;
31  void *__write;
32  void *__seek;
33  void *__close;
34  void *__stat;
35  void *__showmanyc;
36  void *__imbue;
37 };
39 {
40  _IO_FILE file;
42 };
43 
44 ssize_t my_read (_IO_FILE *file, void *buffer, ssize_t size)
45 {
46  ssize_t data_read = dce_read (file->_fileno, buffer, size);
47  if (data_read == -1)
48  {
49  errno = Current ()->err;
50  }
51  return data_read;
52 }
53 ssize_t my_write (_IO_FILE *file, const void *buffer, ssize_t size)
54 {
55  ssize_t data_written = dce_write (file->_fileno, buffer, size);
56  if (data_written == -1)
57  {
58  errno = Current ()->err;
59  }
60  if (file->_offset >= 0)
61  {
62  file->_offset += data_written;
63  }
64  return data_written;
65 }
66 off64_t my_seek (_IO_FILE *file, off64_t where, int whence)
67 {
68  off64_t result = dce_lseek (file->_fileno, where, whence);
69  if (result == -1)
70  {
71  errno = Current ()->err;
72  }
73  return result;
74 }
75 int my_close (_IO_FILE *file)
76 {
77  int result = dce_close (file->_fileno);
78  if (result == -1)
79  {
80  errno = Current ()->err;
81  }
82  return result;
83 }
84 int my_close_unconditional (_IO_FILE *file)
85 {
86  return 0;
87 }
88 int my_write_unconditional (_IO_FILE *file)
89 {
90  errno = EBADF;
91  return -1;
92 }
93 off64_t my_seek_unconditional (_IO_FILE *file, off64_t where, int whence)
94 {
95  return -1;
96 }
97 int my_stat (_IO_FILE *file, void *buf)
98 {
99  int result = dce_fstat64 (file->_fileno, (struct stat64 *)buf);
100  if (result == -1)
101  {
102  errno = Current ()->err;
103  }
104  return result;
105 }
106 bool mode_seek_start (const char *mode)
107 {
108  return *mode != 'a';
109 }
110 bool mode_truncate (const char *mode)
111 {
112  return *mode == 'w';
113 }
114 bool mode_create (const char *mode)
115 {
116  return *mode != 'r';
117 }
118 bool mode_valid (const char *mode)
119 {
120  while (*mode != 0)
121  {
122  switch (*mode)
123  {
124  case 'a':
125  case 'r':
126  case 'w':
127  case '+':
128  case 'b':
129  break;
130  default:
131  return false;
132  break;
133  }
134  mode++;
135  }
136  return true;
137 }
138 int mode_posix_flags (const char *mode)
139 {
140  int mode_flag = 0;
141  int posix_flags = 0;
142  switch (*mode)
143  {
144  case 'r':
145  mode_flag |= O_RDONLY;
146  break;
147  case 'w':
148  mode_flag |= O_WRONLY;
149  posix_flags |= O_CREAT | O_TRUNC;
150  break;
151  case 'a':
152  mode_flag |= O_WRONLY;
153  posix_flags |= O_CREAT | O_APPEND;
154  break;
155  }
156  mode++;
157  while (*mode != 0)
158  {
159  if (*mode == '+')
160  {
161  mode_flag = O_RDWR;
162  }
163  mode++;
164  }
165  posix_flags |= mode_flag;
166  return posix_flags;
167 }
168 void mode_setup (FILE *file, int fd, const char *mode)
169 {
170  if (mode_seek_start (mode))
171  {
172  dce_lseek (fd, 0, SEEK_SET);
173  dce_fseek (file, 0, SEEK_SET);
174  }
175  else
176  {
177  dce_lseek (fd, 0, SEEK_END);
178  dce_fseek (file, 0, SEEK_END);
179  }
180 }
181 
182 } // namespace
183 
184 FILE * dce_fdopen (int fildes, const char *mode)
185 {
186  NS_LOG_FUNCTION (Current () << UtilsGetNodeId () << fildes << mode);
187  NS_ASSERT (Current () != 0);
188  Thread *current = Current ();
189  // no need to create or truncate. Just need to seek if needed.
190  FILE *file = fopen ("/dev/null", mode);
191  if (file == 0)
192  {
193  current->err = errno;
194  return 0;
195  }
196  struct my_IO_FILE_plus *fp = (struct my_IO_FILE_plus *)file;
197  static struct my_IO_jump_t vtable;
198  memcpy (&vtable, fp->vtable, sizeof(struct my_IO_jump_t));
199  vtable.__read = (void*)my_read;
200  vtable.__write = (void*)my_write;
201  vtable.__seek = (void*)my_seek;
202  vtable.__close = (void*)my_close;
203  vtable.__stat = (void*)my_stat;
204  fp->vtable = &vtable;
205  close (file->_fileno);
206  file->_fileno = fildes;
207  current->process->openStreams.push_back (file);
208  dce_fseek (file, dce_lseek (fildes, 0, SEEK_CUR), SEEK_SET);
209 
210  return file;
211 }
212 
213 FILE * dce_fopen64 (const char *path, const char *mode)
214 {
215  NS_LOG_FUNCTION (Current () << UtilsGetNodeId () << path << mode);
216  NS_ASSERT (Current () != 0);
217  Thread *current = Current ();
218  if (!mode_valid (mode))
219  {
220  current->err = EINVAL;
221  return 0;
222  }
223  int fd = dce_open (path, mode_posix_flags (mode) | O_LARGEFILE, 0666 & ~(current->process->uMask));
224  if (fd == -1)
225  {
226  current->err = errno;
227  return 0;
228  }
229  FILE *file = dce_fdopen (fd, mode);
230  if (file == 0)
231  {
232  return 0;
233  }
234  mode_setup (file, fd, mode);
235  return file;
236 }
237 FILE * dce_fopen (const char *path, const char *mode)
238 {
239  NS_LOG_FUNCTION (Current () << UtilsGetNodeId () << path << mode);
240  NS_ASSERT (Current () != 0);
241  Thread *current = Current ();
242  if (!mode_valid (mode))
243  {
244  current->err = EINVAL;
245  return 0;
246  }
247  int fd = dce_open (path, mode_posix_flags (mode), 0666 & ~(current->process->uMask));
248  if (fd == -1)
249  {
250  current->err = errno;
251  return 0;
252  }
253  FILE *file = dce_fdopen (fd, mode);
254  if (file == 0)
255  {
256  return 0;
257  }
258  mode_setup (file, fd, mode);
259  return file;
260 }
261 FILE * dce_freopen (const char *path, const char *mode, FILE *stream)
262 {
263  NS_LOG_FUNCTION (Current () << UtilsGetNodeId () << path << mode << stream);
264  NS_ASSERT (Current () != 0);
265  Thread *current = Current ();
266  if (!mode_valid (mode))
267  {
268  current->err = EINVAL;
269  return 0;
270  }
271  int oldFd = stream->_fileno;
272  stream->_fileno = -1;
273  stream = freopen ("/dev/null", mode, stream);
274  if (stream == 0)
275  {
276  stream->_fileno = oldFd;
277  current->err = errno;
278  return 0;
279  }
280  struct my_IO_FILE_plus *fp = (struct my_IO_FILE_plus *)stream;
281  static struct my_IO_jump_t vtable;
282  memcpy (&vtable, fp->vtable, sizeof(struct my_IO_jump_t));
283  vtable.__read = (void*)my_read;
284  vtable.__write = (void*)my_write;
285  vtable.__seek = (void*)my_seek;
286  vtable.__close = (void*)my_close;
287  vtable.__stat = (void*)my_stat;
288  fp->vtable = &vtable;
289 
290  int fd = dce_open (path, mode_posix_flags (mode), ~0);
291  if (fd == -1)
292  {
293  dce_close (oldFd);
294  fclose (stream);
295  current->err = errno;
296  return 0;
297  }
298  dce_close (oldFd);
299  stream->_fileno = fd;
300  mode_setup (stream, fd, mode);
301  return stream;
302 }
303 int dce_fcloseall (void)
304 {
305  NS_LOG_FUNCTION (Current () << UtilsGetNodeId ());
306  NS_ASSERT (Current () != 0);
307  struct Process *process = Current ()->process;
308  bool error = false;
309  for (uint32_t i = 0; i < process->openStreams.size (); i++)
310  {
311  int status = dce_fclose (process->openStreams[i]);
312  if (status != 0)
313  {
314  error = true;
315  }
316  }
317  return error ? EOF : 0;
318 }
319 static void
320 remove_stream (FILE *fp)
321 {
322  Thread *current = Current ();
323  bool found = false;
324  for (std::vector<FILE*>::iterator i = current->process->openStreams.begin ();
325  i != current->process->openStreams.end (); ++i)
326  {
327  if (*i == fp)
328  {
329  current->process->openStreams.erase (i);
330  found = true;
331  break;
332  }
333  }
334  if (!found)
335  {
336  // not found
337  NS_FATAL_ERROR ("invalid FILE * closed=" << fp);
338  }
339 }
340 int dce_fclose_unconditional (FILE *file)
341 {
342  // Note: it is important here not to call the Current function here
343  // because we need to be able to run this function even if there is no context.
344  // For example, this is why we have no call to NS_LOG_FUNCTION (Current () ...);
345  struct my_IO_FILE_plus *fp = (struct my_IO_FILE_plus *)file;
346  static struct my_IO_jump_t vtable;
347  memcpy (&vtable, fp->vtable, sizeof(struct my_IO_jump_t));
348  vtable.__close = (void*)my_close_unconditional;
349  vtable.__write = (void*)my_write_unconditional;
350  vtable.__seek = (void*)my_seek_unconditional;
351  fp->vtable = &vtable;
352  fclose (file);
353  return 0;
354 }
355 int dce_fclose_onexec (FILE *file)
356 {
357  // Note: it is important here not to call the Current function here
358  // because we need to be able to run this function even if there is no context.
359  // For example, this is why we have no call to NS_LOG_FUNCTION (Current () ...);
360  struct my_IO_FILE_plus *fp = (struct my_IO_FILE_plus *)file;
361  static struct my_IO_jump_t vtable;
362  memcpy (&vtable, fp->vtable, sizeof(struct my_IO_jump_t));
363  vtable.__close = (void*)my_close_unconditional;
364  fp->vtable = &vtable;
365  fclose (file);
366  return 0;
367 }
368 int dce_fclose (FILE *fp)
369 {
370  NS_LOG_FUNCTION (Current () << UtilsGetNodeId () << fp);
371  NS_ASSERT (Current () != 0);
372  Thread *current = Current ();
373 
374  if ((current->process->pstdout && fp == *current->process->pstdout)
375  || (current->process->pstdin && fp == *current->process->pstderr)
376  || (current->process->pstdin && fp == *current->process->pstdin))
377  {
378  return 0;
379  }
380 
381  remove_stream (fp);
382 
383  int status = fclose (fp);
384  NS_LOG_DEBUG ("fclose=" << status << " errno=" << errno);
385  if (status != 0)
386  {
387  current->err = errno;
388  return status;
389  }
390  return status;
391 }
392 size_t dce_fread (void *ptr, size_t size, size_t nmemb, FILE *stream)
393 {
394  NS_LOG_FUNCTION (Current () << UtilsGetNodeId () << ptr << size << nmemb << stream);
395  NS_ASSERT (Current () != 0);
396  // Note: I believe that fread does not set errno ever
397  size_t status = fread (ptr, size, nmemb, stream);
398  return status;
399 }
400 size_t dce_fwrite (const void *ptr, size_t size, size_t nmemb, FILE *stream)
401 {
402  NS_LOG_FUNCTION (Current () << UtilsGetNodeId () << ptr << size << nmemb << stream);
403  NS_ASSERT (Current () != 0);
404  // Note: I believe that fwrite does not set errno ever
405  size_t status = fwrite (ptr, size, nmemb, stream);
406  return status;
407 }
408 int dce_fflush (FILE *stream)
409 {
410  NS_LOG_FUNCTION (Current () << UtilsGetNodeId () << stream);
411  NS_ASSERT (Current () != 0);
412  Thread *current = Current ();
413  if (stream == 0)
414  {
415  // only flush the streams of the current process
416  for (std::vector<FILE *>::const_iterator i = current->process->openStreams.begin ();
417  i != current->process->openStreams.end (); ++i)
418  {
419  int status = fflush (*i);
420  if (status != 0)
421  {
422  current->err = errno;
423  return status;
424  }
425  }
426  }
427  else
428  {
429  int status = fflush (stream);
430  if (status != 0)
431  {
432  current->err = errno;
433  return status;
434  }
435  }
436  return 0;
437 }
438 void dce_clearerr (FILE *stream)
439 {
440  NS_LOG_FUNCTION (Current () << UtilsGetNodeId () << stream);
441  NS_ASSERT (Current () != 0);
442  clearerr (stream);
443 }
444 int dce_feof (FILE *stream)
445 {
446  NS_LOG_FUNCTION (Current () << UtilsGetNodeId () << stream);
447  NS_ASSERT (Current () != 0);
448  int status = feof (stream);
449  return status;
450 }
451 int dce_ferror (FILE *stream)
452 {
453  NS_LOG_FUNCTION (Current () << UtilsGetNodeId () << stream);
454  NS_ASSERT (Current () != 0);
455  int status = ferror (stream);
456  return status;
457 }
458 int dce_fileno (FILE *stream)
459 {
460  NS_LOG_FUNCTION (Current () << UtilsGetNodeId () << stream);
461  NS_ASSERT (Current () != 0);
462  Thread *current = Current ();
463  int status = fileno (stream);
464  if (status == -1)
465  {
466  current->err = errno;
467  return -1;
468  }
469  return status;
470 }
471 
472 // stdio.h
473 int dce_printf (const char *format, ...)
474 {
475  NS_LOG_FUNCTION (Current () << UtilsGetNodeId () << format);
476  NS_ASSERT (Current () != 0);
477 
478  va_list vl;
479  va_start (vl, format);
480  int status = vfprintf (*Current ()->process->pstdout, format, vl);
481  va_end (vl);
482  return status;
483 }
484 // stdarg.h
485 int dce_vprintf (const char *format, va_list ap)
486 {
487  NS_LOG_FUNCTION (Current () << UtilsGetNodeId () << format);
488  NS_ASSERT (Current () != 0);
489  // Note: I don't believe that this function sets errno
490  int status = vfprintf (*Current ()->process->pstdout, format, ap);
491  return status;
492 }
493 
494 int dce_getchar (void)
495 {
496  NS_LOG_FUNCTION (Current () << UtilsGetNodeId ());
497  NS_ASSERT (Current () != 0);
498  return fgetc (*Current ()->process->pstdin);
499 }
500 
501 int dce__IO_getc (FILE *stream)
502 {
503  NS_LOG_FUNCTION (Current () << UtilsGetNodeId ());
504  NS_ASSERT (Current () != 0);
505  return fgetc (stream);
506 }
507 
508 int dce_putchar (int __c)
509 {
510  NS_LOG_FUNCTION (Current () << UtilsGetNodeId () << (char)__c);
511  NS_ASSERT (Current () != 0);
512  return fputc (__c, *Current ()->process->pstdout);
513 }
514 
515 int dce__IO_putc (int __c, FILE *__stream)
516 {
517  NS_LOG_FUNCTION (Current () << UtilsGetNodeId () << (char)__c);
518  NS_ASSERT (Current () != 0);
519  return fputc (__c, __stream);
520 }
521 
522 int dce_puts (const char *__s)
523 {
524  NS_LOG_FUNCTION (Current () << UtilsGetNodeId () << __s);
525  NS_ASSERT (Current () != 0);
526  int ret = fputs (__s, *Current ()->process->pstdout);
527  if (ret < 0)
528  {
529  return ret;
530  }
531  fputc ('\n', *Current ()->process->pstdout);
532  return ret;
533 }
534 
535 int dce_fputc (int c, FILE *stream)
536 {
537  NS_LOG_FUNCTION (Current () << UtilsGetNodeId () << c << stream);
538  NS_ASSERT (Current () != 0);
539  // Note: I don't believe that this function sets errno
540  int status = fputc (c, stream);
541  return status;
542 }
543 int dce_fgetc (FILE *stream)
544 {
545  NS_LOG_FUNCTION (Current () << UtilsGetNodeId () << stream);
546  NS_ASSERT (Current () != 0);
547  // Note: I don't believe that this function sets errno
548  int status = fgetc (stream);
549  return status;
550 }
551 int dce_fputs (const char *s, FILE *stream)
552 {
553  NS_LOG_FUNCTION (Current () << UtilsGetNodeId () << s << stream);
554  NS_ASSERT (Current () != 0);
555  // Note: I don't believe that this function sets errno
556  int status = fputs (s, stream);
557  return status;
558 }
559 char* dce_fgets (char *s, int size, FILE *stream)
560 {
561  NS_LOG_FUNCTION (Current () << UtilsGetNodeId () << s << size << stream);
562  NS_ASSERT (Current () != 0);
563  // Note: I don't believe that this function sets errno
564  char *status = fgets (s, size, stream);
565  return status;
566 }
567 int dce_ungetc (int c, FILE *stream)
568 {
569  NS_LOG_FUNCTION (Current () << UtilsGetNodeId () << c << stream);
570  NS_ASSERT (Current () != 0);
571  // Note: I don't believe that this function sets errno
572  int status = ungetc (c, stream);
573  return status;
574 }
575 int dce_fseek (FILE *stream, long offset, int whence)
576 {
577  NS_LOG_FUNCTION (Current () << UtilsGetNodeId () << stream << offset << whence);
578  NS_ASSERT (Current () != 0);
579  Thread *current = Current ();
580  int status = fseek (stream, offset, whence);
581  if (status == -1)
582  {
583  current->err = errno;
584  return -1;
585  }
586  return status;
587 }
588 int dce_fseeko (FILE *stream, off_t offset, int whence)
589 {
590  NS_LOG_FUNCTION (Current () << UtilsGetNodeId () << stream << offset << whence);
591  NS_ASSERT (Current () != 0);
592  Thread *current = Current ();
593  int status = fseeko (stream, offset, whence);
594  if (status == -1)
595  {
596  current->err = errno;
597  return -1;
598  }
599  return status;
600 }
601 long dce_ftell (FILE *stream)
602 {
603  NS_LOG_FUNCTION (Current () << UtilsGetNodeId () << stream);
604  NS_ASSERT (Current () != 0);
605  Thread *current = Current ();
606  long status = ftell (stream);
607  if (status == -1)
608  {
609  current->err = errno;
610  return -1;
611  }
612  return status;
613 }
614 off_t dce_ftello (FILE *stream)
615 {
616  NS_LOG_FUNCTION (Current () << UtilsGetNodeId () << stream);
617  NS_ASSERT (Current () != 0);
618  Thread *current = Current ();
619  off_t status = ftello (stream);
620  if (status == -1)
621  {
622  current->err = errno;
623  return -1;
624  }
625  return status;
626 }
627 int dce_fgetpos (FILE *stream, fpos_t *pos)
628 {
629  NS_LOG_FUNCTION (Current () << UtilsGetNodeId () << stream << pos);
630  NS_ASSERT (Current () != 0);
631  Thread *current = Current ();
632  int status = fgetpos (stream, pos);
633  if (status == -1)
634  {
635  current->err = errno;
636  return -1;
637  }
638  return status;
639 }
640 int dce_fsetpos (FILE *stream, const fpos_t *pos)
641 {
642  NS_LOG_FUNCTION (Current () << UtilsGetNodeId () << stream << pos);
643  NS_ASSERT (Current () != 0);
644  Thread *current = Current ();
645  int status = fsetpos (stream, pos);
646  if (status == -1)
647  {
648  current->err = errno;
649  return -1;
650  }
651  return status;
652 }
653 
654 void dce_rewind (FILE *stream)
655 {
656  NS_LOG_FUNCTION (Current () << UtilsGetNodeId () << stream);
657  NS_ASSERT (Current () != 0);
658  rewind (stream);
659 }
660 int dce_setvbuf (FILE *stream, char *buf, int mode, size_t size)
661 {
662  NS_LOG_FUNCTION (Current () << UtilsGetNodeId () << stream << ((void*)buf) << mode << size);
663  NS_ASSERT (Current () != 0);
664  Thread *current = Current ();
665  int status = setvbuf (stream, buf, mode, size);
666  if (status == -1)
667  {
668  current->err = errno;
669  return -1;
670  }
671  return status;
672 }
673 
674 void dce_setbuf (FILE *stream, char *buf)
675 {
676  dce_setvbuf (stream, buf, buf ? _IOFBF : _IONBF, BUFSIZ);
677 }
678 
679 void dce_setbuffer (FILE *stream, char *buf, size_t size)
680 {
681  dce_setvbuf (stream, buf, buf ? _IOFBF : _IONBF, size);
682 }
683 
684 void dce_setlinebuf (FILE *stream)
685 {
686  dce_setvbuf (stream, (char *) NULL, _IOLBF, 0);
687 }
688 
689 int dce_remove (const char *pathname)
690 {
691  NS_LOG_FUNCTION (Current () << UtilsGetNodeId () << pathname);
692  NS_ASSERT (Current () != 0);
693  Thread *current = Current ();
694  if (std::string (pathname) == "")
695  {
696  current->err = ENOENT;
697  return -1;
698  }
699  std::string fullpath = UtilsGetRealFilePath (pathname);
700  int status = ::remove (fullpath.c_str ());
701  if (status == -1)
702  {
703  current->err = errno;
704  }
705  return status;
706 }
707 
708 void dce_perror (const char *s)
709 {
710  NS_LOG_FUNCTION (Current () << UtilsGetNodeId ());
711  NS_ASSERT (Current () != 0);
712 
713  fprintf (*Current ()->process->pstderr, "%s: %s\n", s, strerror (*__errno_location ()));
714 }
715 
716 int dce___printf_chk (int __flag, __const char *__restrict __format, ...)
717 {
718  NS_LOG_FUNCTION (Current () << UtilsGetNodeId ());
719  NS_ASSERT (Current () != 0);
720 
721  va_list ap;
722  va_start (ap, __format);
723  int retval = vfprintf (*Current ()->process->pstdout, __format, ap);
724  va_end (ap);
725  return retval;
726 }
727 
728 int dce___vfprintf_chk (FILE *__restrict __stream, int __flag,
729  __const char *__restrict __format, _G_va_list __ap)
730 {
731  NS_LOG_FUNCTION (Current () << UtilsGetNodeId ());
732  NS_ASSERT (Current () != 0);
733 
734  return vfprintf (__stream, __format, __ap);
735 }
736 
737 int dce___fprintf_chk (FILE *__restrict __stream, int __flag,
738  __const char *__restrict __format, ...)
739 {
740  NS_LOG_FUNCTION (Current () << UtilsGetNodeId ());
741  NS_ASSERT (Current () != 0);
742 
743  va_list ap;
744  va_start (ap, __format);
745  int retval = vfprintf (__stream, __format, ap);
746  va_end (ap);
747  return retval;
748 }
749 
750 int dce___snprintf_chk (char *__restrict __s, size_t __n, int __flag,
751  size_t __slen, __const char *__restrict __format, ...)
752 {
753  NS_LOG_FUNCTION (Current () << UtilsGetNodeId ());
754  NS_ASSERT (Current () != 0);
755 
756  va_list ap;
757  va_start (ap, __format);
758  int retval = vsnprintf (__s, __n, __format, ap);
759  va_end (ap);
760  return retval;
761 }
762 int dce___vsnprintf_chk (char *__restrict __s, size_t __n, int __flag,
763  size_t __slen,
764  __const char *__restrict __format, _G_va_list __ap)
765 {
766  NS_LOG_FUNCTION (Current () << UtilsGetNodeId ());
767  NS_ASSERT (Current () != 0);
768 
769  int retval = vsnprintf (__s, __n, __format, __ap);
770  return retval;
771 }
772 void dce___fpurge (FILE *stream)
773 {
774  NS_LOG_FUNCTION (Current () << UtilsGetNodeId () << stream);
775  NS_ASSERT (Current () != 0);
776  __fpurge (stream);
777 }
778 size_t dce___fpending (FILE *stream)
779 {
780  NS_LOG_FUNCTION (Current () << UtilsGetNodeId ());
781  NS_ASSERT (Current () != 0);
782  size_t ret = __fpending (stream);
783  return ret;
784 }
785 int dce_asprintf (char **strp, const char *fmt, ...)
786 {
787  va_list ap;
788  va_start (ap, fmt);
789 
790  return dce_vasprintf (strp, fmt, ap);
791 }
792 
793 int dce_vasprintf (char **strp, const char *fmt, va_list ap)
794 {
795  NS_LOG_FUNCTION (Current () << UtilsGetNodeId ());
796  NS_ASSERT (Current () != 0);
797 
798  char *res = 0;
799  int ret = 0;
800 
801  if (!strp || !fmt)
802  {
803  Current ()->err = ENOMEM;
804  return -1;
805  }
806 
807  ret = vasprintf (&res, fmt, ap);
808 
809  if (ret > 0)
810  {
811  char *tmp = (char*) dce_malloc (ret);
812 
813  if (tmp)
814  {
815  memcpy (tmp, res, ret);
816 
817  *strp = tmp;
818  free (res);
819 
820  return ret;
821  }
822  free (res);
823  Current ()->err = ENOMEM;
824  return -1;
825  }
826  Current ()->err = errno;
827 
828  return ret;
829 }
830 int dce_vsnprintf (char *s, size_t si, const char *f, va_list ap)
831 {
832  return ::vsnprintf (s, si, f, ap);
833 }