File: readdir_r.c

package info (click to toggle)
libc-sparc 5.3.12-2
  • links: PTS
  • area: main
  • in suites: hamm
  • size: 18,664 kB
  • ctags: 53,237
  • sloc: ansic: 181,379; asm: 5,080; makefile: 3,340; lex: 521; sh: 439; yacc: 401; awk: 28
file content (69 lines) | stat: -rw-r--r-- 1,529 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#include <dirent.h>
#include <string.h>
#include <errno.h>
#include <sys/syscall.h>

#include "../dirstream.h"

/*
 * readdir fills up the buffer with the readdir system call. it also
 * gives a third parameter (currently ignored, but should be 1) that
 * can with a future kernel be enhanced to be the number of entries
 * to be gotten.
 */
#ifdef __ELF__
#pragma weak readdir_r = __libc_readdir_r
#endif

int
__libc_readdir_r (DIR * dir, struct dirent * entry, struct dirent ** ret)
{
  int result;

  if (!dir || !entry || !ret || !*ret) {
    return EBADF;
  }

  if (dir->dd_size <= dir->dd_nextloc)
  {
    /* read dir->dd_max bytes of directory entries. */
      __asm__ volatile ("mov %1, %%g1\n\t"
			"mov %2, %%o0\n\t"
			"mov %3, %%o1\n\t"
			"mov %4, %%o3\n\t"
			"t 0x10\n\t"
			"bcc 1f\n\t"
			"or %%g0, %%o0, %0\n\t"
			"sub %%g0, %%o0, %0\n\t"
			"1:\n\t"
			: "r=" (result)
			: "0" (SYS_getdents), "r" (dir->dd_fd),
			  "r" ((long) dir->dd_buf), "r" (dir->dd_max));
      
    /* We assume we have getdents (). */
    dir->dd_getdents = have_getdents;
    if (result <= 0)
    {
      result = -result;

      *ret = NULL;
      return result;
    }

    dir->dd_size = result;
    dir->dd_nextloc = 0;
  }

  /* We copy the dirent entry to entry. */
  memcpy (entry, ((char *)dir->dd_buf) + dir->dd_nextloc,
	sizeof(struct dirent));
  *ret = entry;

  /* Am I right? H.J. */
  dir->dd_nextloc += entry->d_reclen;

  /* We have to save the next offset here. */
  dir->dd_nextoff = entry->d_off;

  return 0;
}