diff --git a/dom/system/OSFileConstants.cpp b/dom/system/OSFileConstants.cpp index 6033741d4e5..ded54b7f503 100644 --- a/dom/system/OSFileConstants.cpp +++ b/dom/system/OSFileConstants.cpp @@ -380,6 +380,13 @@ static dom::ConstantSpec gLibcProperties[] = { "OSFILE_OFFSETOF_DIRENT_D_TYPE", INT_TO_JSVAL(offsetof (struct dirent, d_type)) }, #endif // defined(DT_UNKNOWN) + // Under MacOS X, |dirfd| is a macro rather than a function, so we + // need a little help to get it to work +#if defined(dirfd) + { "OSFILE_SIZEOF_DIR", INT_TO_JSVAL(sizeof (DIR)) }, + + { "OSFILE_OFFSETOF_DIR_DD_FD", INT_TO_JSVAL(offsetof (DIR, __dd_fd)) }, +#endif // Defining |stat| diff --git a/toolkit/components/osfile/osfile_unix_back.jsm b/toolkit/components/osfile/osfile_unix_back.jsm index 7a56ac7ab0d..720b7186b12 100644 --- a/toolkit/components/osfile/osfile_unix_back.jsm +++ b/toolkit/components/osfile/osfile_unix_back.jsm @@ -108,19 +108,6 @@ Types.time_t = Types.intn_t(OS.Constants.libc.OSFILE_SIZEOF_TIME_T).withName("time_t"); - Types.DIR = - new Type("DIR", - ctypes.StructType("DIR")); - - Types.null_or_DIR_ptr = - Types.DIR.out_ptr.withName("null_or_DIR*"); - Types.null_or_DIR_ptr.importFromC = function importFromC(dir) { - if (dir == null || dir.isNull()) { - return null; - } - return ctypes.CDataFinalizer(dir, _close_dir); - }; - // Structure |dirent| // Building this type is rather complicated, as its layout varies between // variants of Unix. For this reason, we rely on a number of constants @@ -175,6 +162,37 @@ Types.stat = stat.getType(); } + // Structure |DIR| + if ("OSFILE_SIZEOF_DIR" in OS.Constants.libc) { + // On platforms for which we need to access the fields of DIR + // directly (e.g. because certain functions are implemented + // as macros), we need to define DIR as a hollow structure. + let DIR = new OS.Shared.HollowStructure( + "DIR", + OS.Constants.libc.OSFILE_SIZEOF_DIR); + + DIR.add_field_at( + OS.Constants.libc.OSFILE_OFFSETOF_DIR_DD_FD, + "dd_fd", + Types.fd.implementation); + + Types.DIR = DIR.getType(); + } else { + // On other platforms, we keep DIR as a blackbox + Types.DIR = + new Type("DIR", + ctypes.StructType("DIR")); + } + + Types.null_or_DIR_ptr = + Types.DIR.out_ptr.withName("null_or_DIR*"); + Types.null_or_DIR_ptr.importFromC = function importFromC(dir) { + if (dir == null || dir.isNull()) { + return null; + } + return ctypes.CDataFinalizer(dir, _close_dir); + }; + // Declare libc functions as functions of |OS.Unix.File| // Finalizer-related functions @@ -241,10 +259,19 @@ /*return*/ Types.negativeone_or_fd, /*fd*/ Types.fd); - UnixFile.dirfd = - declareFFI("dirfd", ctypes.default_abi, - /*return*/ Types.negativeone_or_fd, - /*dir*/ Types.null_or_DIR_ptr); + if ("OSFILE_SIZEOF_DIR" in OS.Constants.libc) { + // On platforms for which |dirfd| is a macro + UnixFile.dirfd = + function dirfd(DIRp) { + return Types.DIR.in_ptr.implementation(DIRp).contents.dd_fd; + }; + } else { + // On platforms for which |dirfd| is a function + UnixFile.dirfd = + declareFFI("dirfd", ctypes.default_abi, + /*return*/ Types.negativeone_or_fd, + /*dir*/ Types.DIR.in_ptr); + } UnixFile.chdir = declareFFI("chdir", ctypes.default_abi,