|
1 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
2 * License, v. 2.0. If a copy of the MPL was not distributed with this file, |
|
3 * You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
4 |
|
5 { |
|
6 if (typeof Components != "undefined") { |
|
7 // We do not wish osfile_unix_back.jsm to be used directly as a main thread |
|
8 // module yet. When time comes, it will be loaded by a combination of |
|
9 // a main thread front-end/worker thread implementation that makes sure |
|
10 // that we are not executing synchronous IO code in the main thread. |
|
11 |
|
12 throw new Error("osfile_unix_back.jsm cannot be used from the main thread yet"); |
|
13 } |
|
14 (function(exports) { |
|
15 "use strict"; |
|
16 if (exports.OS && exports.OS.Unix && exports.OS.Unix.File) { |
|
17 return; // Avoid double initialization |
|
18 } |
|
19 |
|
20 let SharedAll = |
|
21 require("resource://gre/modules/osfile/osfile_shared_allthreads.jsm"); |
|
22 let SysAll = |
|
23 require("resource://gre/modules/osfile/osfile_unix_allthreads.jsm"); |
|
24 let LOG = SharedAll.LOG.bind(SharedAll, "Unix", "back"); |
|
25 let libc = SysAll.libc; |
|
26 let Const = SharedAll.Constants.libc; |
|
27 |
|
28 /** |
|
29 * Initialize the Unix module. |
|
30 * |
|
31 * @param {function=} declareFFI |
|
32 */ |
|
33 // FIXME: Both |init| and |aDeclareFFI| are deprecated, we should remove them |
|
34 let init = function init(aDeclareFFI) { |
|
35 let declareFFI; |
|
36 if (aDeclareFFI) { |
|
37 declareFFI = aDeclareFFI.bind(null, libc); |
|
38 } else { |
|
39 declareFFI = SysAll.declareFFI; |
|
40 } |
|
41 let declareLazyFFI = SharedAll.declareLazyFFI; |
|
42 |
|
43 // Initialize types that require additional OS-specific |
|
44 // support - either finalization or matching against |
|
45 // OS-specific constants. |
|
46 let Type = Object.create(SysAll.Type); |
|
47 let SysFile = exports.OS.Unix.File = { Type: Type }; |
|
48 |
|
49 /** |
|
50 * A file descriptor. |
|
51 */ |
|
52 Type.fd = Type.int.withName("fd"); |
|
53 Type.fd.importFromC = function importFromC(fd_int) { |
|
54 return ctypes.CDataFinalizer(fd_int, SysFile._close); |
|
55 }; |
|
56 |
|
57 |
|
58 /** |
|
59 * A C integer holding -1 in case of error or a file descriptor |
|
60 * in case of success. |
|
61 */ |
|
62 Type.negativeone_or_fd = Type.fd.withName("negativeone_or_fd"); |
|
63 Type.negativeone_or_fd.importFromC = |
|
64 function importFromC(fd_int) { |
|
65 if (fd_int == -1) { |
|
66 return -1; |
|
67 } |
|
68 return ctypes.CDataFinalizer(fd_int, SysFile._close); |
|
69 }; |
|
70 |
|
71 /** |
|
72 * A C integer holding -1 in case of error or a meaningless value |
|
73 * in case of success. |
|
74 */ |
|
75 Type.negativeone_or_nothing = |
|
76 Type.int.withName("negativeone_or_nothing"); |
|
77 |
|
78 /** |
|
79 * A C integer holding -1 in case of error or a positive integer |
|
80 * in case of success. |
|
81 */ |
|
82 Type.negativeone_or_ssize_t = |
|
83 Type.ssize_t.withName("negativeone_or_ssize_t"); |
|
84 |
|
85 /** |
|
86 * Various libc integer types |
|
87 */ |
|
88 Type.mode_t = |
|
89 Type.intn_t(Const.OSFILE_SIZEOF_MODE_T).withName("mode_t"); |
|
90 Type.uid_t = |
|
91 Type.intn_t(Const.OSFILE_SIZEOF_UID_T).withName("uid_t"); |
|
92 Type.gid_t = |
|
93 Type.intn_t(Const.OSFILE_SIZEOF_GID_T).withName("gid_t"); |
|
94 |
|
95 /** |
|
96 * Type |time_t| |
|
97 */ |
|
98 Type.time_t = |
|
99 Type.intn_t(Const.OSFILE_SIZEOF_TIME_T).withName("time_t"); |
|
100 |
|
101 // Structure |dirent| |
|
102 // Building this type is rather complicated, as its layout varies between |
|
103 // variants of Unix. For this reason, we rely on a number of constants |
|
104 // (computed in C from the C data structures) that give us the layout. |
|
105 // The structure we compute looks like |
|
106 // { int8_t[...] before_d_type; // ignored content |
|
107 // int8_t d_type ; |
|
108 // int8_t[...] before_d_name; // ignored content |
|
109 // char[...] d_name; |
|
110 // }; |
|
111 { |
|
112 let d_name_extra_size = 0; |
|
113 if (Const.OSFILE_SIZEOF_DIRENT_D_NAME < 8) { |
|
114 // d_name is defined like "char d_name[1];" on some platforms |
|
115 // (e.g. Solaris), we need to give it more size for our structure. |
|
116 d_name_extra_size = 256; |
|
117 } |
|
118 |
|
119 let dirent = new SharedAll.HollowStructure("dirent", |
|
120 Const.OSFILE_SIZEOF_DIRENT + d_name_extra_size); |
|
121 if (Const.OSFILE_OFFSETOF_DIRENT_D_TYPE != undefined) { |
|
122 // |dirent| doesn't have d_type on some platforms (e.g. Solaris). |
|
123 dirent.add_field_at(Const.OSFILE_OFFSETOF_DIRENT_D_TYPE, |
|
124 "d_type", ctypes.uint8_t); |
|
125 } |
|
126 dirent.add_field_at(Const.OSFILE_OFFSETOF_DIRENT_D_NAME, |
|
127 "d_name", ctypes.ArrayType(ctypes.char, |
|
128 Const.OSFILE_SIZEOF_DIRENT_D_NAME + d_name_extra_size)); |
|
129 |
|
130 // We now have built |dirent|. |
|
131 Type.dirent = dirent.getType(); |
|
132 } |
|
133 Type.null_or_dirent_ptr = |
|
134 new SharedAll.Type("null_of_dirent", |
|
135 Type.dirent.out_ptr.implementation); |
|
136 |
|
137 // Structure |stat| |
|
138 // Same technique |
|
139 { |
|
140 let stat = new SharedAll.HollowStructure("stat", |
|
141 Const.OSFILE_SIZEOF_STAT); |
|
142 stat.add_field_at(Const.OSFILE_OFFSETOF_STAT_ST_MODE, |
|
143 "st_mode", Type.mode_t.implementation); |
|
144 stat.add_field_at(Const.OSFILE_OFFSETOF_STAT_ST_UID, |
|
145 "st_uid", Type.uid_t.implementation); |
|
146 stat.add_field_at(Const.OSFILE_OFFSETOF_STAT_ST_GID, |
|
147 "st_gid", Type.gid_t.implementation); |
|
148 |
|
149 // Here, things get complicated with different data structures. |
|
150 // Some platforms have |time_t st_atime| and some platforms have |
|
151 // |timespec st_atimespec|. However, since |timespec| starts with |
|
152 // a |time_t|, followed by nanoseconds, we just cheat and pretend |
|
153 // that everybody has |time_t st_atime|, possibly followed by padding |
|
154 stat.add_field_at(Const.OSFILE_OFFSETOF_STAT_ST_ATIME, |
|
155 "st_atime", Type.time_t.implementation); |
|
156 stat.add_field_at(Const.OSFILE_OFFSETOF_STAT_ST_MTIME, |
|
157 "st_mtime", Type.time_t.implementation); |
|
158 stat.add_field_at(Const.OSFILE_OFFSETOF_STAT_ST_CTIME, |
|
159 "st_ctime", Type.time_t.implementation); |
|
160 |
|
161 // To complicate further, MacOS and some BSDs have a field |birthtime| |
|
162 if ("OSFILE_OFFSETOF_STAT_ST_BIRTHTIME" in Const) { |
|
163 stat.add_field_at(Const.OSFILE_OFFSETOF_STAT_ST_BIRTHTIME, |
|
164 "st_birthtime", Type.time_t.implementation); |
|
165 } |
|
166 |
|
167 stat.add_field_at(Const.OSFILE_OFFSETOF_STAT_ST_SIZE, |
|
168 "st_size", Type.off_t.implementation); |
|
169 Type.stat = stat.getType(); |
|
170 } |
|
171 |
|
172 // Structure |DIR| |
|
173 if ("OSFILE_SIZEOF_DIR" in Const) { |
|
174 // On platforms for which we need to access the fields of DIR |
|
175 // directly (e.g. because certain functions are implemented |
|
176 // as macros), we need to define DIR as a hollow structure. |
|
177 let DIR = new SharedAll.HollowStructure( |
|
178 "DIR", |
|
179 Const.OSFILE_SIZEOF_DIR); |
|
180 |
|
181 DIR.add_field_at( |
|
182 Const.OSFILE_OFFSETOF_DIR_DD_FD, |
|
183 "dd_fd", |
|
184 Type.fd.implementation); |
|
185 |
|
186 Type.DIR = DIR.getType(); |
|
187 } else { |
|
188 // On other platforms, we keep DIR as a blackbox |
|
189 Type.DIR = |
|
190 new SharedAll.Type("DIR", |
|
191 ctypes.StructType("DIR")); |
|
192 } |
|
193 |
|
194 Type.null_or_DIR_ptr = |
|
195 Type.DIR.out_ptr.withName("null_or_DIR*"); |
|
196 Type.null_or_DIR_ptr.importFromC = function importFromC(dir) { |
|
197 if (dir == null || dir.isNull()) { |
|
198 return null; |
|
199 } |
|
200 return ctypes.CDataFinalizer(dir, SysFile._close_dir); |
|
201 }; |
|
202 |
|
203 // Structure |timeval| |
|
204 { |
|
205 let timeval = new SharedAll.HollowStructure( |
|
206 "timeval", |
|
207 Const.OSFILE_SIZEOF_TIMEVAL); |
|
208 timeval.add_field_at( |
|
209 Const.OSFILE_OFFSETOF_TIMEVAL_TV_SEC, |
|
210 "tv_sec", |
|
211 Type.long.implementation); |
|
212 timeval.add_field_at( |
|
213 Const.OSFILE_OFFSETOF_TIMEVAL_TV_USEC, |
|
214 "tv_usec", |
|
215 Type.long.implementation); |
|
216 Type.timeval = timeval.getType(); |
|
217 Type.timevals = new SharedAll.Type("two timevals", |
|
218 ctypes.ArrayType(Type.timeval.implementation, 2)); |
|
219 } |
|
220 |
|
221 // Types fsblkcnt_t and fsfilcnt_t, used by structure |statvfs| |
|
222 Type.fsblkcnt_t = |
|
223 Type.uintn_t(Const.OSFILE_SIZEOF_FSBLKCNT_T).withName("fsblkcnt_t"); |
|
224 |
|
225 // Structure |statvfs| |
|
226 // Use an hollow structure |
|
227 { |
|
228 let statvfs = new SharedAll.HollowStructure("statvfs", |
|
229 Const.OSFILE_SIZEOF_STATVFS); |
|
230 |
|
231 statvfs.add_field_at(Const.OSFILE_OFFSETOF_STATVFS_F_BSIZE, |
|
232 "f_bsize", Type.unsigned_long.implementation); |
|
233 statvfs.add_field_at(Const.OSFILE_OFFSETOF_STATVFS_F_BAVAIL, |
|
234 "f_bavail", Type.fsblkcnt_t.implementation); |
|
235 |
|
236 Type.statvfs = statvfs.getType(); |
|
237 } |
|
238 |
|
239 // Declare libc functions as functions of |OS.Unix.File| |
|
240 |
|
241 // Finalizer-related functions |
|
242 libc.declareLazy(SysFile, "_close", |
|
243 "close", ctypes.default_abi, |
|
244 /*return */ctypes.int, |
|
245 /*fd*/ ctypes.int); |
|
246 |
|
247 SysFile.close = function close(fd) { |
|
248 // Detach the finalizer and call |_close|. |
|
249 return fd.dispose(); |
|
250 }; |
|
251 |
|
252 libc.declareLazy(SysFile, "_close_dir", |
|
253 "closedir", ctypes.default_abi, |
|
254 /*return */ctypes.int, |
|
255 /*dirp*/ Type.DIR.in_ptr.implementation); |
|
256 |
|
257 SysFile.closedir = function closedir(fd) { |
|
258 // Detach the finalizer and call |_close_dir|. |
|
259 return fd.dispose(); |
|
260 }; |
|
261 |
|
262 { |
|
263 // Symbol free() is special. |
|
264 // We override the definition of free() on several platforms. |
|
265 let default_lib = new SharedAll.Library("default_lib", |
|
266 "a.out"); |
|
267 try { |
|
268 // On platforms for which we override free(), nspr defines |
|
269 // a special library name "a.out" that will resolve to the |
|
270 // correct implementation free(). |
|
271 |
|
272 default_lib.declareLazy(SysFile, "free", |
|
273 "free", ctypes.default_abi, |
|
274 /*return*/ ctypes.void_t, |
|
275 /*ptr*/ ctypes.voidptr_t); |
|
276 |
|
277 } catch (ex) { |
|
278 // We don't have an a.out library or a.out doesn't contain free. |
|
279 // Either way, use the ordinary libc free. |
|
280 |
|
281 libc.declareLazy(SysFile, "free", |
|
282 "free", ctypes.default_abi, |
|
283 /*return*/ ctypes.void_t, |
|
284 /*ptr*/ ctypes.voidptr_t); |
|
285 } |
|
286 } |
|
287 |
|
288 |
|
289 // Other functions |
|
290 libc.declareLazyFFI(SysFile, "access", |
|
291 "access", ctypes.default_abi, |
|
292 /*return*/ Type.negativeone_or_nothing, |
|
293 /*path*/ Type.path, |
|
294 /*mode*/ Type.int); |
|
295 |
|
296 libc.declareLazyFFI(SysFile, "chdir", |
|
297 "chdir", ctypes.default_abi, |
|
298 /*return*/ Type.negativeone_or_nothing, |
|
299 /*path*/ Type.path); |
|
300 |
|
301 libc.declareLazyFFI(SysFile, "chmod", |
|
302 "chmod", ctypes.default_abi, |
|
303 /*return*/ Type.negativeone_or_nothing, |
|
304 /*path*/ Type.path, |
|
305 /*mode*/ Type.mode_t); |
|
306 |
|
307 libc.declareLazyFFI(SysFile, "chown", |
|
308 "chown", ctypes.default_abi, |
|
309 /*return*/ Type.negativeone_or_nothing, |
|
310 /*path*/ Type.path, |
|
311 /*uid*/ Type.uid_t, |
|
312 /*gid*/ Type.gid_t); |
|
313 |
|
314 libc.declareLazyFFI(SysFile, "copyfile", |
|
315 "copyfile", ctypes.default_abi, |
|
316 /*return*/ Type.negativeone_or_nothing, |
|
317 /*source*/ Type.path, |
|
318 /*dest*/ Type.path, |
|
319 /*state*/ Type.void_t.in_ptr, // Ignored atm |
|
320 /*flags*/ Type.uint32_t); |
|
321 |
|
322 libc.declareLazyFFI(SysFile, "dup", |
|
323 "dup", ctypes.default_abi, |
|
324 /*return*/ Type.negativeone_or_fd, |
|
325 /*fd*/ Type.fd); |
|
326 |
|
327 if ("OSFILE_SIZEOF_DIR" in Const) { |
|
328 // On platforms for which |dirfd| is a macro |
|
329 SysFile.dirfd = |
|
330 function dirfd(DIRp) { |
|
331 return Type.DIR.in_ptr.implementation(DIRp).contents.dd_fd; |
|
332 }; |
|
333 } else { |
|
334 // On platforms for which |dirfd| is a function |
|
335 libc.declareLazyFFI(SysFile, "dirfd", |
|
336 "dirfd", ctypes.default_abi, |
|
337 /*return*/ Type.negativeone_or_fd, |
|
338 /*dir*/ Type.DIR.in_ptr); |
|
339 } |
|
340 |
|
341 libc.declareLazyFFI(SysFile, "chdir", |
|
342 "chdir", ctypes.default_abi, |
|
343 /*return*/ Type.negativeone_or_nothing, |
|
344 /*path*/ Type.path); |
|
345 |
|
346 libc.declareLazyFFI(SysFile, "fchdir", |
|
347 "fchdir", ctypes.default_abi, |
|
348 /*return*/ Type.negativeone_or_nothing, |
|
349 /*fd*/ Type.fd); |
|
350 |
|
351 libc.declareLazyFFI(SysFile, "fchmod", |
|
352 "fchmod", ctypes.default_abi, |
|
353 /*return*/ Type.negativeone_or_nothing, |
|
354 /*fd*/ Type.fd, |
|
355 /*mode*/ Type.mode_t); |
|
356 |
|
357 libc.declareLazyFFI(SysFile, "fchown", |
|
358 "fchown", ctypes.default_abi, |
|
359 /*return*/ Type.negativeone_or_nothing, |
|
360 /*fd*/ Type.fd, |
|
361 /*uid_t*/ Type.uid_t, |
|
362 /*gid_t*/ Type.gid_t); |
|
363 |
|
364 libc.declareLazyFFI(SysFile, "fsync", |
|
365 "fsync", ctypes.default_abi, |
|
366 /*return*/ Type.negativeone_or_nothing, |
|
367 /*fd*/ Type.fd); |
|
368 |
|
369 libc.declareLazyFFI(SysFile, "getcwd", |
|
370 "getcwd", ctypes.default_abi, |
|
371 /*return*/ Type.out_path, |
|
372 /*buf*/ Type.out_path, |
|
373 /*size*/ Type.size_t); |
|
374 |
|
375 libc.declareLazyFFI(SysFile, "getwd", |
|
376 "getwd", ctypes.default_abi, |
|
377 /*return*/ Type.out_path, |
|
378 /*buf*/ Type.out_path); |
|
379 |
|
380 // Two variants of |getwd| which allocate the memory |
|
381 // dynamically. |
|
382 |
|
383 // Linux/Android version |
|
384 libc.declareLazyFFI(SysFile, "get_current_dir_name", |
|
385 "get_current_dir_name", ctypes.default_abi, |
|
386 /*return*/ Type.out_path.releaseWithLazy(() => |
|
387 SysFile.free |
|
388 )); |
|
389 |
|
390 // MacOS/BSD version (will return NULL on Linux/Android) |
|
391 libc.declareLazyFFI(SysFile, "getwd_auto", |
|
392 "getwd", ctypes.default_abi, |
|
393 /*return*/ Type.out_path.releaseWithLazy(() => |
|
394 SysFile.free |
|
395 ), |
|
396 /*buf*/ Type.void_t.out_ptr); |
|
397 |
|
398 libc.declareLazyFFI(SysFile, "fdatasync", |
|
399 "fdatasync", ctypes.default_abi, |
|
400 /*return*/ Type.negativeone_or_nothing, |
|
401 /*fd*/ Type.fd); // Note: MacOS/BSD-specific |
|
402 |
|
403 libc.declareLazyFFI(SysFile, "ftruncate", |
|
404 "ftruncate", ctypes.default_abi, |
|
405 /*return*/ Type.negativeone_or_nothing, |
|
406 /*fd*/ Type.fd, |
|
407 /*length*/ Type.off_t); |
|
408 |
|
409 |
|
410 libc.declareLazyFFI(SysFile, "lchown", |
|
411 "lchown", ctypes.default_abi, |
|
412 /*return*/ Type.negativeone_or_nothing, |
|
413 /*path*/ Type.path, |
|
414 /*uid_t*/ Type.uid_t, |
|
415 /*gid_t*/ Type.gid_t); |
|
416 |
|
417 libc.declareLazyFFI(SysFile, "link", |
|
418 "link", ctypes.default_abi, |
|
419 /*return*/ Type.negativeone_or_nothing, |
|
420 /*source*/ Type.path, |
|
421 /*dest*/ Type.path); |
|
422 |
|
423 libc.declareLazyFFI(SysFile, "lseek", |
|
424 "lseek", ctypes.default_abi, |
|
425 /*return*/ Type.off_t, |
|
426 /*fd*/ Type.fd, |
|
427 /*offset*/ Type.off_t, |
|
428 /*whence*/ Type.int); |
|
429 |
|
430 libc.declareLazyFFI(SysFile, "mkdir", |
|
431 "mkdir", ctypes.default_abi, |
|
432 /*return*/ Type.int, |
|
433 /*path*/ Type.path, |
|
434 /*mode*/ Type.int); |
|
435 |
|
436 libc.declareLazyFFI(SysFile, "mkstemp", |
|
437 "mkstemp", ctypes.default_abi, |
|
438 /*return*/ Type.fd, |
|
439 /*template*/ Type.out_path); |
|
440 |
|
441 libc.declareLazyFFI(SysFile, "open", |
|
442 "open", ctypes.default_abi, |
|
443 /*return*/ Type.negativeone_or_fd, |
|
444 /*path*/ Type.path, |
|
445 /*oflags*/ Type.int, |
|
446 /*mode*/ Type.int); |
|
447 |
|
448 if (OS.Constants.Sys.Name == "NetBSD") { |
|
449 libc.declareLazyFFI(SysFile, "opendir", |
|
450 "__opendir30", ctypes.default_abi, |
|
451 /*return*/ Type.null_or_DIR_ptr, |
|
452 /*path*/ Type.path); |
|
453 } else { |
|
454 libc.declareLazyFFI(SysFile, "opendir", |
|
455 "opendir", ctypes.default_abi, |
|
456 /*return*/ Type.null_or_DIR_ptr, |
|
457 /*path*/ Type.path); |
|
458 } |
|
459 |
|
460 libc.declareLazyFFI(SysFile, "pread", |
|
461 "pread", ctypes.default_abi, |
|
462 /*return*/ Type.negativeone_or_ssize_t, |
|
463 /*fd*/ Type.fd, |
|
464 /*buf*/ Type.void_t.out_ptr, |
|
465 /*nbytes*/ Type.size_t, |
|
466 /*offset*/ Type.off_t); |
|
467 |
|
468 libc.declareLazyFFI(SysFile, "pwrite", |
|
469 "pwrite", ctypes.default_abi, |
|
470 /*return*/ Type.negativeone_or_ssize_t, |
|
471 /*fd*/ Type.fd, |
|
472 /*buf*/ Type.void_t.in_ptr, |
|
473 /*nbytes*/ Type.size_t, |
|
474 /*offset*/ Type.off_t); |
|
475 |
|
476 libc.declareLazyFFI(SysFile, "read", |
|
477 "read", ctypes.default_abi, |
|
478 /*return*/Type.negativeone_or_ssize_t, |
|
479 /*fd*/ Type.fd, |
|
480 /*buf*/ Type.void_t.out_ptr, |
|
481 /*nbytes*/Type.size_t); |
|
482 |
|
483 libc.declareLazyFFI(SysFile, "posix_fadvise", |
|
484 "posix_fadvise", ctypes.default_abi, |
|
485 /*return*/ Type.int, |
|
486 /*fd*/ Type.fd, |
|
487 /*offset*/ Type.off_t, |
|
488 /*len*/ Type.off_t, |
|
489 /*advise*/ Type.int); |
|
490 |
|
491 if (Const._DARWIN_FEATURE_64_BIT_INODE) { |
|
492 // Special case for MacOS X 10.5+ |
|
493 // Symbol name "readdir" still exists but is used for a |
|
494 // deprecated function that does not match the |
|
495 // constants of |Const|. |
|
496 libc.declareLazyFFI(SysFile, "readdir", |
|
497 "readdir$INODE64", ctypes.default_abi, |
|
498 /*return*/ Type.null_or_dirent_ptr, |
|
499 /*dir*/ Type.DIR.in_ptr); // For MacOS X |
|
500 } else if (OS.Constants.Sys.Name == "NetBSD") { |
|
501 libc.declareLazyFFI(SysFile, "readdir", |
|
502 "__readdir30", ctypes.default_abi, |
|
503 /*return*/Type.null_or_dirent_ptr, |
|
504 /*dir*/ Type.DIR.in_ptr); // Other Unices |
|
505 } else { |
|
506 libc.declareLazyFFI(SysFile, "readdir", |
|
507 "readdir", ctypes.default_abi, |
|
508 /*return*/Type.null_or_dirent_ptr, |
|
509 /*dir*/ Type.DIR.in_ptr); // Other Unices |
|
510 } |
|
511 |
|
512 libc.declareLazyFFI(SysFile, "rename", |
|
513 "rename", ctypes.default_abi, |
|
514 /*return*/ Type.negativeone_or_nothing, |
|
515 /*old*/ Type.path, |
|
516 /*new*/ Type.path); |
|
517 |
|
518 libc.declareLazyFFI(SysFile, "rmdir", |
|
519 "rmdir", ctypes.default_abi, |
|
520 /*return*/ Type.int, |
|
521 /*path*/ Type.path); |
|
522 |
|
523 libc.declareLazyFFI(SysFile, "splice", |
|
524 "splice", ctypes.default_abi, |
|
525 /*return*/ Type.long, |
|
526 /*fd_in*/ Type.fd, |
|
527 /*off_in*/ Type.off_t.in_ptr, |
|
528 /*fd_out*/ Type.fd, |
|
529 /*off_out*/Type.off_t.in_ptr, |
|
530 /*len*/ Type.size_t, |
|
531 /*flags*/ Type.unsigned_int); // Linux/Android-specific |
|
532 |
|
533 libc.declareLazyFFI(SysFile, "statvfs", |
|
534 "statvfs", ctypes.default_abi, |
|
535 /*return*/ Type.negativeone_or_nothing, |
|
536 /*path*/ Type.path, |
|
537 /*buf*/ Type.statvfs.out_ptr); |
|
538 |
|
539 libc.declareLazyFFI(SysFile, "symlink", |
|
540 "symlink", ctypes.default_abi, |
|
541 /*return*/ Type.negativeone_or_nothing, |
|
542 /*source*/ Type.path, |
|
543 /*dest*/ Type.path); |
|
544 |
|
545 libc.declareLazyFFI(SysFile, "truncate", |
|
546 "truncate", ctypes.default_abi, |
|
547 /*return*/Type.negativeone_or_nothing, |
|
548 /*path*/ Type.path, |
|
549 /*length*/ Type.off_t); |
|
550 |
|
551 libc.declareLazyFFI(SysFile, "unlink", |
|
552 "unlink", ctypes.default_abi, |
|
553 /*return*/ Type.negativeone_or_nothing, |
|
554 /*path*/ Type.path); |
|
555 |
|
556 libc.declareLazyFFI(SysFile, "write", |
|
557 "write", ctypes.default_abi, |
|
558 /*return*/ Type.negativeone_or_ssize_t, |
|
559 /*fd*/ Type.fd, |
|
560 /*buf*/ Type.void_t.in_ptr, |
|
561 /*nbytes*/ Type.size_t); |
|
562 |
|
563 // Weird cases that require special treatment |
|
564 |
|
565 // OSes use a variety of hacks to differentiate between |
|
566 // 32-bits and 64-bits versions of |stat|, |lstat|, |fstat|. |
|
567 if (Const._DARWIN_FEATURE_64_BIT_INODE) { |
|
568 // MacOS X 64-bits |
|
569 libc.declareLazyFFI(SysFile, "stat", |
|
570 "stat$INODE64", ctypes.default_abi, |
|
571 /*return*/ Type.negativeone_or_nothing, |
|
572 /*path*/ Type.path, |
|
573 /*buf*/ Type.stat.out_ptr |
|
574 ); |
|
575 libc.declareLazyFFI(SysFile, "lstat", |
|
576 "lstat$INODE64", ctypes.default_abi, |
|
577 /*return*/ Type.negativeone_or_nothing, |
|
578 /*path*/ Type.path, |
|
579 /*buf*/ Type.stat.out_ptr |
|
580 ); |
|
581 libc.declareLazyFFI(SysFile, "fstat", |
|
582 "fstat$INODE64", ctypes.default_abi, |
|
583 /*return*/ Type.negativeone_or_nothing, |
|
584 /*path*/ Type.fd, |
|
585 /*buf*/ Type.stat.out_ptr |
|
586 ); |
|
587 } else if (Const._STAT_VER != undefined) { |
|
588 const ver = Const._STAT_VER; |
|
589 let xstat_name, lxstat_name, fxstat_name; |
|
590 if (OS.Constants.Sys.Name == "SunOS") { |
|
591 // Solaris |
|
592 xstat_name = "_xstat"; |
|
593 lxstat_name = "_lxstat"; |
|
594 fxstat_name = "_fxstat"; |
|
595 } else { |
|
596 // Linux, all widths |
|
597 xstat_name = "__xstat"; |
|
598 lxstat_name = "__lxstat"; |
|
599 fxstat_name = "__fxstat"; |
|
600 } |
|
601 |
|
602 let Stat = {}; |
|
603 libc.declareLazyFFI(Stat, "xstat", |
|
604 xstat_name, ctypes.default_abi, |
|
605 /*return*/ Type.negativeone_or_nothing, |
|
606 /*_stat_ver*/ Type.int, |
|
607 /*path*/ Type.path, |
|
608 /*buf*/ Type.stat.out_ptr); |
|
609 libc.declareLazyFFI(Stat, "lxstat", |
|
610 lxstat_name, ctypes.default_abi, |
|
611 /*return*/ Type.negativeone_or_nothing, |
|
612 /*_stat_ver*/ Type.int, |
|
613 /*path*/ Type.path, |
|
614 /*buf*/ Type.stat.out_ptr); |
|
615 libc.declareLazyFFI(Stat, "fxstat", |
|
616 fxstat_name, ctypes.default_abi, |
|
617 /*return*/ Type.negativeone_or_nothing, |
|
618 /*_stat_ver*/ Type.int, |
|
619 /*fd*/ Type.fd, |
|
620 /*buf*/ Type.stat.out_ptr); |
|
621 |
|
622 |
|
623 SysFile.stat = function stat(path, buf) { |
|
624 return Stat.xstat(ver, path, buf); |
|
625 }; |
|
626 |
|
627 SysFile.lstat = function lstat(path, buf) { |
|
628 return Stat.lxstat(ver, path, buf); |
|
629 }; |
|
630 |
|
631 SysFile.fstat = function fstat(fd, buf) { |
|
632 return Stat.fxstat(ver, fd, buf); |
|
633 }; |
|
634 } else if (OS.Constants.Sys.Name == "NetBSD") { |
|
635 // NetBSD 5.0 and newer |
|
636 libc.declareLazyFFI(SysFile, "stat", |
|
637 "__stat50", ctypes.default_abi, |
|
638 /*return*/ Type.negativeone_or_nothing, |
|
639 /*path*/ Type.path, |
|
640 /*buf*/ Type.stat.out_ptr |
|
641 ); |
|
642 libc.declareLazyFFI(SysFile, "lstat", |
|
643 "__lstat50", ctypes.default_abi, |
|
644 /*return*/ Type.negativeone_or_nothing, |
|
645 /*path*/ Type.path, |
|
646 /*buf*/ Type.stat.out_ptr |
|
647 ); |
|
648 libc.declareLazyFFI(SysFile, "fstat", |
|
649 "__fstat50", ctypes.default_abi, |
|
650 /*return*/ Type.negativeone_or_nothing, |
|
651 /*fd*/ Type.fd, |
|
652 /*buf*/ Type.stat.out_ptr |
|
653 ); |
|
654 } else { |
|
655 // Mac OS X 32-bits, other Unix |
|
656 libc.declareLazyFFI(SysFile, "stat", |
|
657 "stat", ctypes.default_abi, |
|
658 /*return*/ Type.negativeone_or_nothing, |
|
659 /*path*/ Type.path, |
|
660 /*buf*/ Type.stat.out_ptr |
|
661 ); |
|
662 libc.declareLazyFFI(SysFile, "lstat", |
|
663 "lstat", ctypes.default_abi, |
|
664 /*return*/ Type.negativeone_or_nothing, |
|
665 /*path*/ Type.path, |
|
666 /*buf*/ Type.stat.out_ptr |
|
667 ); |
|
668 libc.declareLazyFFI(SysFile, "fstat", |
|
669 "fstat", ctypes.default_abi, |
|
670 /*return*/ Type.negativeone_or_nothing, |
|
671 /*fd*/ Type.fd, |
|
672 /*buf*/ Type.stat.out_ptr |
|
673 ); |
|
674 } |
|
675 |
|
676 // We cannot make a C array of CDataFinalizer, so |
|
677 // pipe cannot be directly defined as a C function. |
|
678 |
|
679 let Pipe = {}; |
|
680 libc.declareLazyFFI(Pipe, "_pipe", |
|
681 "pipe", ctypes.default_abi, |
|
682 /*return*/ Type.negativeone_or_nothing, |
|
683 /*fds*/ new SharedAll.Type("two file descriptors", |
|
684 ctypes.ArrayType(ctypes.int, 2))); |
|
685 |
|
686 // A shared per-thread buffer used to communicate with |pipe| |
|
687 let _pipebuf = new (ctypes.ArrayType(ctypes.int, 2))(); |
|
688 |
|
689 SysFile.pipe = function pipe(array) { |
|
690 let result = Pipe._pipe(_pipebuf); |
|
691 if (result == -1) { |
|
692 return result; |
|
693 } |
|
694 array[0] = ctypes.CDataFinalizer(_pipebuf[0], SysFile._close); |
|
695 array[1] = ctypes.CDataFinalizer(_pipebuf[1], SysFile._close); |
|
696 return result; |
|
697 }; |
|
698 |
|
699 if (OS.Constants.Sys.Name == "NetBSD") { |
|
700 libc.declareLazyFFI(SysFile, "utimes", |
|
701 "__utimes50", ctypes.default_abi, |
|
702 /*return*/ Type.negativeone_or_nothing, |
|
703 /*path*/ Type.path, |
|
704 /*timeval[2]*/ Type.timevals.out_ptr |
|
705 ); |
|
706 } else { |
|
707 libc.declareLazyFFI(SysFile, "utimes", |
|
708 "utimes", ctypes.default_abi, |
|
709 /*return*/ Type.negativeone_or_nothing, |
|
710 /*path*/ Type.path, |
|
711 /*timeval[2]*/ Type.timevals.out_ptr |
|
712 ); |
|
713 } |
|
714 if (OS.Constants.Sys.Name == "NetBSD") { |
|
715 libc.declareLazyFFI(SysFile, "futimes", |
|
716 "__futimes50", ctypes.default_abi, |
|
717 /*return*/ Type.negativeone_or_nothing, |
|
718 /*fd*/ Type.fd, |
|
719 /*timeval[2]*/ Type.timevals.out_ptr |
|
720 ); |
|
721 } else { |
|
722 libc.declareLazyFFI(SysFile, "futimes", |
|
723 "futimes", ctypes.default_abi, |
|
724 /*return*/ Type.negativeone_or_nothing, |
|
725 /*fd*/ Type.fd, |
|
726 /*timeval[2]*/ Type.timevals.out_ptr |
|
727 ); |
|
728 } |
|
729 }; |
|
730 |
|
731 exports.OS.Unix = { |
|
732 File: { |
|
733 _init: init |
|
734 } |
|
735 }; |
|
736 })(this); |
|
737 } |