60
60
#endif
61
61
62
62
#if defined(__APPLE__ )
63
- # include <copyfile.h>
64
63
# include <sys/sysctl.h>
65
64
#elif defined(__linux__ ) && !defined(FICLONE )
66
65
# include <sys/ioctl.h>
@@ -143,6 +142,18 @@ extern char *mkdtemp(char *template); /* See issue #740 on AIX < 7 */
143
142
while (0)
144
143
145
144
145
+ static int uv__fs_close (int fd ) {
146
+ int rc ;
147
+
148
+ rc = close (fd );
149
+ if (rc == -1 )
150
+ if (errno == EINTR || errno == EINPROGRESS )
151
+ rc = 0 ; /* The close is in progress, not an error. */
152
+
153
+ return rc ;
154
+ }
155
+
156
+
146
157
static ssize_t uv__fs_fsync (uv_fs_t * req ) {
147
158
#if defined(__APPLE__ )
148
159
/* Apple's fdatasync and fsync explicitly do NOT flush the drive write cache
@@ -351,7 +362,7 @@ static int uv__fs_scandir_sort(UV_CONST_DIRENT** a, UV_CONST_DIRENT** b) {
351
362
352
363
353
364
static ssize_t uv__fs_scandir (uv_fs_t * req ) {
354
- uv__dirent_t * * dents ;
365
+ uv__dirent_t * * dents ;
355
366
int n ;
356
367
357
368
dents = NULL ;
@@ -375,6 +386,87 @@ static ssize_t uv__fs_scandir(uv_fs_t* req) {
375
386
return n ;
376
387
}
377
388
389
+ static int uv__fs_opendir (uv_fs_t * req ) {
390
+ uv_dir_t * dir ;
391
+
392
+ dir = uv__malloc (sizeof (* dir ));
393
+ if (dir == NULL )
394
+ goto error ;
395
+
396
+ dir -> dir = opendir (req -> path );
397
+ if (dir -> dir == NULL )
398
+ goto error ;
399
+
400
+ req -> ptr = dir ;
401
+ return 0 ;
402
+
403
+ error :
404
+ uv__free (dir );
405
+ req -> ptr = NULL ;
406
+ return -1 ;
407
+ }
408
+
409
+ static int uv__fs_readdir (uv_fs_t * req ) {
410
+ uv_dir_t * dir ;
411
+ uv_dirent_t * dirent ;
412
+ struct dirent * res ;
413
+ unsigned int dirent_idx ;
414
+ unsigned int i ;
415
+
416
+ dir = req -> ptr ;
417
+ dirent_idx = 0 ;
418
+
419
+ while (dirent_idx < dir -> nentries ) {
420
+ /* readdir() returns NULL on end of directory, as well as on error. errno
421
+ is used to differentiate between the two conditions. */
422
+ errno = 0 ;
423
+ res = readdir (dir -> dir );
424
+
425
+ if (res == NULL ) {
426
+ if (errno != 0 )
427
+ goto error ;
428
+ break ;
429
+ }
430
+
431
+ if (strcmp (res -> d_name , "." ) == 0 || strcmp (res -> d_name , ".." ) == 0 )
432
+ continue ;
433
+
434
+ dirent = & dir -> dirents [dirent_idx ];
435
+ dirent -> name = uv__strdup (res -> d_name );
436
+
437
+ if (dirent -> name == NULL )
438
+ goto error ;
439
+
440
+ dirent -> type = uv__fs_get_dirent_type (res );
441
+ ++ dirent_idx ;
442
+ }
443
+
444
+ return dirent_idx ;
445
+
446
+ error :
447
+ for (i = 0 ; i < dirent_idx ; ++ i ) {
448
+ uv__free ((char * ) dir -> dirents [i ].name );
449
+ dir -> dirents [i ].name = NULL ;
450
+ }
451
+
452
+ return -1 ;
453
+ }
454
+
455
+ static int uv__fs_closedir (uv_fs_t * req ) {
456
+ uv_dir_t * dir ;
457
+
458
+ dir = req -> ptr ;
459
+
460
+ if (dir -> dir != NULL ) {
461
+ closedir (dir -> dir );
462
+ dir -> dir = NULL ;
463
+ }
464
+
465
+ uv__free (req -> ptr );
466
+ req -> ptr = NULL ;
467
+ return 0 ;
468
+ }
469
+
378
470
#if defined(_POSIX_PATH_MAX )
379
471
# define UV__FS_PATH_MAX _POSIX_PATH_MAX
380
472
#elif defined(PATH_MAX )
@@ -808,45 +900,6 @@ static ssize_t uv__fs_write(uv_fs_t* req) {
808
900
}
809
901
810
902
static ssize_t uv__fs_copyfile (uv_fs_t * req ) {
811
- #if defined(__APPLE__ ) && !TARGET_OS_IPHONE
812
- /* On macOS, use the native copyfile(3). */
813
- static int can_clone ;
814
- copyfile_flags_t flags ;
815
- char buf [64 ];
816
- size_t len ;
817
- int major ;
818
-
819
- flags = COPYFILE_ALL ;
820
-
821
- if (req -> flags & UV_FS_COPYFILE_EXCL )
822
- flags |= COPYFILE_EXCL ;
823
-
824
- /* Check OS version. Cloning is only supported on macOS >= 10.12. */
825
- if (req -> flags & UV_FS_COPYFILE_FICLONE_FORCE ) {
826
- if (can_clone == 0 ) {
827
- len = sizeof (buf );
828
- if (sysctlbyname ("kern.osrelease" , buf , & len , NULL , 0 ))
829
- return UV__ERR (errno );
830
-
831
- if (1 != sscanf (buf , "%d" , & major ))
832
- abort ();
833
-
834
- can_clone = -1 + 2 * (major >= 16 ); /* macOS >= 10.12 */
835
- }
836
-
837
- if (can_clone < 0 )
838
- return UV_ENOSYS ;
839
- }
840
-
841
- /* copyfile() simply ignores COPYFILE_CLONE if it's not supported. */
842
- if (req -> flags & UV_FS_COPYFILE_FICLONE )
843
- flags |= 1 << 24 ; /* COPYFILE_CLONE */
844
-
845
- if (req -> flags & UV_FS_COPYFILE_FICLONE_FORCE )
846
- flags |= 1 << 25 ; /* COPYFILE_CLONE_FORCE */
847
-
848
- return copyfile (req -> path , req -> new_path , NULL , flags );
849
- #else
850
903
uv_fs_t fs_req ;
851
904
uv_file srcfd ;
852
905
uv_file dstfd ;
@@ -973,7 +1026,6 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) {
973
1026
974
1027
errno = UV__ERR (result );
975
1028
return -1 ;
976
- #endif
977
1029
}
978
1030
979
1031
static void uv__to_stat (struct stat * src , uv_stat_t * dst ) {
@@ -1249,7 +1301,7 @@ static void uv__fs_work(struct uv__work* w) {
1249
1301
X (ACCESS , access (req -> path , req -> flags ));
1250
1302
X (CHMOD , chmod (req -> path , req -> mode ));
1251
1303
X (CHOWN , chown (req -> path , req -> uid , req -> gid ));
1252
- X (CLOSE , close (req -> file ));
1304
+ X (CLOSE , uv__fs_close (req -> file ));
1253
1305
X (COPYFILE , uv__fs_copyfile (req ));
1254
1306
X (FCHMOD , fchmod (req -> file , req -> mode ));
1255
1307
X (FCHOWN , fchown (req -> file , req -> uid , req -> gid ));
@@ -1266,6 +1318,9 @@ static void uv__fs_work(struct uv__work* w) {
1266
1318
X (OPEN , uv__fs_open (req ));
1267
1319
X (READ , uv__fs_read (req ));
1268
1320
X (SCANDIR , uv__fs_scandir (req ));
1321
+ X (OPENDIR , uv__fs_opendir (req ));
1322
+ X (READDIR , uv__fs_readdir (req ));
1323
+ X (CLOSEDIR , uv__fs_closedir (req ));
1269
1324
X (READLINK , uv__fs_readlink (req ));
1270
1325
X (REALPATH , uv__fs_realpath (req ));
1271
1326
X (RENAME , rename (req -> path , req -> new_path ));
@@ -1536,6 +1591,40 @@ int uv_fs_scandir(uv_loop_t* loop,
1536
1591
POST ;
1537
1592
}
1538
1593
1594
+ int uv_fs_opendir (uv_loop_t * loop ,
1595
+ uv_fs_t * req ,
1596
+ const char * path ,
1597
+ uv_fs_cb cb ) {
1598
+ INIT (OPENDIR );
1599
+ PATH ;
1600
+ POST ;
1601
+ }
1602
+
1603
+ int uv_fs_readdir (uv_loop_t * loop ,
1604
+ uv_fs_t * req ,
1605
+ uv_dir_t * dir ,
1606
+ uv_fs_cb cb ) {
1607
+ INIT (READDIR );
1608
+
1609
+ if (dir == NULL || dir -> dir == NULL || dir -> dirents == NULL )
1610
+ return UV_EINVAL ;
1611
+
1612
+ req -> ptr = dir ;
1613
+ POST ;
1614
+ }
1615
+
1616
+ int uv_fs_closedir (uv_loop_t * loop ,
1617
+ uv_fs_t * req ,
1618
+ uv_dir_t * dir ,
1619
+ uv_fs_cb cb ) {
1620
+ INIT (CLOSEDIR );
1621
+
1622
+ if (dir == NULL )
1623
+ return UV_EINVAL ;
1624
+
1625
+ req -> ptr = dir ;
1626
+ POST ;
1627
+ }
1539
1628
1540
1629
int uv_fs_readlink (uv_loop_t * loop ,
1541
1630
uv_fs_t * req ,
@@ -1676,14 +1765,17 @@ void uv_fs_req_cleanup(uv_fs_t* req) {
1676
1765
req -> path = NULL ;
1677
1766
req -> new_path = NULL ;
1678
1767
1768
+ if (req -> fs_type == UV_FS_READDIR && req -> ptr != NULL )
1769
+ uv__fs_readdir_cleanup (req );
1770
+
1679
1771
if (req -> fs_type == UV_FS_SCANDIR && req -> ptr != NULL )
1680
1772
uv__fs_scandir_cleanup (req );
1681
1773
1682
1774
if (req -> bufs != req -> bufsml )
1683
1775
uv__free (req -> bufs );
1684
1776
req -> bufs = NULL ;
1685
1777
1686
- if (req -> ptr != & req -> statbuf )
1778
+ if (req -> fs_type != UV_FS_OPENDIR && req -> ptr != & req -> statbuf )
1687
1779
uv__free (req -> ptr );
1688
1780
req -> ptr = NULL ;
1689
1781
}
0 commit comments