|
root / lang / dune / patches / readdir.c
readdir.c C 110 lines 2.4 KB
  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
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
/*
 * readdir.c - illumos/Solaris compatible version for dune
 *
 * This file replaces otherlibs/stdune/dune_filesystem_stubs/readdir.c
 * in dune to fix compilation on illumos/Solaris where struct dirent
 * does not have d_type field.
 *
 * Apply by copying this file to:
 *   dune-X.Y.Z/otherlibs/stdune/dune_filesystem_stubs/readdir.c
 *
 * For opam's bundled dune-local:
 *   opam-X.Y.Z/src_ext/dune-local/otherlibs/stdune/dune_filesystem_stubs/readdir.c
 */

#include <caml/alloc.h>
#include <caml/memory.h>
#include <caml/mlvalues.h>
#include <caml/unixsupport.h>

#include <errno.h>

#ifndef _WIN32

#include <caml/signals.h>

#include <errno.h>
#include <sys/types.h>
#include <dirent.h>

/* illumos/Solaris compatibility - d_type not in struct dirent */
#ifndef DT_UNKNOWN
#define DT_UNKNOWN 0
#define DT_FIFO    1
#define DT_CHR     2
#define DT_DIR     4
#define DT_BLK     6
#define DT_REG     8
#define DT_LNK    10
#define DT_SOCK   12
#define DT_WHT    14
#define ILLUMOS_NO_DTYPE 1
#endif

typedef struct dirent directory_entry;

value val_file_type(int typ) {
  switch(typ)
    {
#ifndef __HAIKU__
   case DT_REG:
      return Val_int(0);
    case DT_DIR:
      return Val_int(1);
    case DT_CHR:
      return Val_int(2);
    case DT_BLK:
      return Val_int(3);
    case DT_LNK:
      return Val_int(4);
    case DT_FIFO:
      return Val_int(5);
    case DT_SOCK:
      return Val_int(6);
    case DT_UNKNOWN:
      return Val_int(7);
#endif
    default:
      return Val_int(7);
    }
}

CAMLprim value caml__dune_filesystem_stubs__readdir(value vd)
{
  CAMLparam1(vd);
  CAMLlocal2(v_filename, v_tuple);

  DIR * d;
  directory_entry * e;
  d = DIR_Val(vd);
  if (d == (DIR *) NULL) unix_error(EBADF, "readdir", Nothing);
  caml_enter_blocking_section();
  errno = 0;
  e = readdir((DIR *) d);
  caml_leave_blocking_section();
  if (e == (directory_entry *) NULL) {
    if(errno == 0) {
      CAMLreturn(Val_int(0));
    } else {
      uerror("readdir", Nothing);
    }
  }
  v_filename = caml_copy_string(e->d_name);
  v_tuple = caml_alloc_small(2, 0);
  Field(v_tuple, 0) = v_filename;
#if defined(__HAIKU__) || defined(ILLUMOS_NO_DTYPE)
  /* illumos/Solaris don't have d_type, always return unknown */
  Field(v_tuple, 1) = Val_int(7);
#else
  Field(v_tuple, 1) = val_file_type(e->d_type);
#endif
  CAMLreturn(v_tuple);
}

#else
CAMLprim value caml__dune_filesystem_stubs__readdir(value vd)
{
  unix_error(ENOSYS, "readdir", Nothing);
}
#endif