1 | /* |
1 | /* |
2 | * libeio implementation |
2 | * libeio implementation |
3 | * |
3 | * |
4 | * Copyright (c) 2007,2008,2009,2010,2011,2012,2013,2016,2017 Marc Alexander Lehmann <libeio@schmorp.de> |
4 | * Copyright (c) 2007,2008,2009,2010,2011,2012,2013,2016,2017,2018,2019 Marc Alexander Lehmann <libeio@schmorp.de> |
5 | * All rights reserved. |
5 | * All rights reserved. |
6 | * |
6 | * |
7 | * Redistribution and use in source and binary forms, with or without modifica- |
7 | * Redistribution and use in source and binary forms, with or without modifica- |
8 | * tion, are permitted provided that the following conditions are met: |
8 | * tion, are permitted provided that the following conditions are met: |
9 | * |
9 | * |
… | |
… | |
329 | |
329 | |
330 | #ifndef O_CLOEXEC |
330 | #ifndef O_CLOEXEC |
331 | #define O_CLOEXEC 0 |
331 | #define O_CLOEXEC 0 |
332 | #endif |
332 | #endif |
333 | |
333 | |
|
|
334 | #ifndef O_NONBLOCK |
|
|
335 | #define O_NONBLOCK 0 |
|
|
336 | #endif |
|
|
337 | |
|
|
338 | #ifndef O_SEARCH |
|
|
339 | #define O_SEARCH O_RDONLY |
|
|
340 | #endif |
|
|
341 | |
|
|
342 | #ifndef O_DIRECTORY |
|
|
343 | #define O_DIRECTORY 0 |
|
|
344 | #endif |
|
|
345 | |
334 | #ifndef EIO_PATH_MIN |
346 | #ifndef EIO_PATH_MIN |
335 | # define EIO_PATH_MIN 8160 |
347 | # define EIO_PATH_MIN 8160 |
336 | #endif |
348 | #endif |
337 | |
349 | |
338 | #define EIO_PATH_MAX (PATH_MAX <= EIO_PATH_MIN ? EIO_PATH_MIN : PATH_MAX) |
350 | #define EIO_PATH_MAX (PATH_MAX <= EIO_PATH_MIN ? EIO_PATH_MIN : PATH_MAX) |
… | |
… | |
354 | struct etp_tmpbuf; |
366 | struct etp_tmpbuf; |
355 | |
367 | |
356 | #if _POSIX_VERSION >= 200809L |
368 | #if _POSIX_VERSION >= 200809L |
357 | #define HAVE_AT 1 |
369 | #define HAVE_AT 1 |
358 | #define WD2FD(wd) ((wd) ? (wd)->fd : AT_FDCWD) |
370 | #define WD2FD(wd) ((wd) ? (wd)->fd : AT_FDCWD) |
359 | #ifndef O_SEARCH |
|
|
360 | #define O_SEARCH O_RDONLY |
|
|
361 | #endif |
|
|
362 | #else |
371 | #else |
363 | #define HAVE_AT 0 |
372 | #define HAVE_AT 0 |
364 | static const char *wd_expand (struct etp_tmpbuf *tmpbuf, eio_wd wd, const char *path); |
373 | static const char *wd_expand (struct etp_tmpbuf *tmpbuf, eio_wd wd, const char *path); |
365 | #endif |
374 | #endif |
366 | |
375 | |
… | |
… | |
893 | #if __GLIBC__ == 2 && __GLIBC_MINOR__ <= 7 |
902 | #if __GLIBC__ == 2 && __GLIBC_MINOR__ <= 7 |
894 | extern int mallopt (int, int); |
903 | extern int mallopt (int, int); |
895 | mallopt (-6, 238); /* http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=473812 */ |
904 | mallopt (-6, 238); /* http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=473812 */ |
896 | #endif |
905 | #endif |
897 | |
906 | |
|
|
907 | #ifndef MCL_ONFAULT |
|
|
908 | if (flags & EIO_MCL_ONFAULT) |
|
|
909 | return EIO_ERRNO (EINVAL, -1); |
|
|
910 | #define MCL_ONFAULT 4 |
|
|
911 | #endif |
|
|
912 | |
898 | if (EIO_MCL_CURRENT != MCL_CURRENT |
913 | if (EIO_MCL_CURRENT != MCL_CURRENT |
899 | || EIO_MCL_FUTURE != MCL_FUTURE) |
914 | || EIO_MCL_FUTURE != MCL_FUTURE |
|
|
915 | || EIO_MCL_ONFAULT != MCL_ONFAULT) |
900 | { |
916 | { |
901 | flags = 0 |
917 | flags = 0 |
902 | | (flags & EIO_MCL_CURRENT ? MCL_CURRENT : 0) |
918 | | (flags & EIO_MCL_CURRENT ? MCL_CURRENT : 0) |
903 | | (flags & EIO_MCL_FUTURE ? MCL_FUTURE : 0); |
919 | | (flags & EIO_MCL_FUTURE ? MCL_FUTURE : 0) |
|
|
920 | | (flags & EIO_MCL_ONFAULT ? MCL_ONFAULT : 0) |
|
|
921 | ; |
904 | } |
922 | } |
905 | |
923 | |
906 | return mlockall (flags); |
924 | return mlockall (flags); |
907 | } |
925 | } |
908 | #endif |
926 | #endif |
… | |
… | |
1395 | return; |
1413 | return; |
1396 | } |
1414 | } |
1397 | } |
1415 | } |
1398 | #else |
1416 | #else |
1399 | #if HAVE_AT |
1417 | #if HAVE_AT |
1400 | if (req->wd) |
|
|
1401 | { |
1418 | { |
1402 | int fd = openat (WD2FD (req->wd), req->ptr1, O_CLOEXEC | O_SEARCH | O_DIRECTORY); |
1419 | int fd = openat (WD2FD (req->wd), req->ptr1, O_CLOEXEC | O_SEARCH | O_DIRECTORY | O_NONBLOCK); |
1403 | |
1420 | |
1404 | if (fd < 0) |
1421 | if (fd < 0) |
|
|
1422 | return; |
|
|
1423 | |
|
|
1424 | dirp = fdopendir (fd); |
|
|
1425 | |
|
|
1426 | if (!dirp) |
|
|
1427 | { |
|
|
1428 | silent_close (fd); |
1405 | return; |
1429 | return; |
1406 | |
|
|
1407 | dirp = fdopendir (fd); |
|
|
1408 | |
|
|
1409 | if (!dirp) |
|
|
1410 | silent_close (fd); |
|
|
1411 | } |
1430 | } |
1412 | else |
1431 | } |
1413 | dirp = opendir (req->ptr1); |
|
|
1414 | #else |
1432 | #else |
1415 | dirp = opendir (wd_expand (&self->tmpbuf, req->wd, req->ptr1)); |
1433 | dirp = opendir (wd_expand (&self->tmpbuf, req->wd, req->ptr1)); |
|
|
1434 | |
|
|
1435 | if (!dirp) |
|
|
1436 | return; |
1416 | #endif |
1437 | #endif |
1417 | |
|
|
1418 | if (!dirp) |
|
|
1419 | return; |
|
|
1420 | #endif |
1438 | #endif |
1421 | |
1439 | |
1422 | if (req->flags & EIO_FLAG_PTR1_FREE) |
1440 | if (req->flags & EIO_FLAG_PTR1_FREE) |
1423 | free (req->ptr1); |
1441 | free (req->ptr1); |
1424 | |
1442 | |
… | |
… | |
1621 | /* keep the absolute path in string form at all times */ |
1639 | /* keep the absolute path in string form at all times */ |
1622 | /* fuck yeah. */ |
1640 | /* fuck yeah. */ |
1623 | |
1641 | |
1624 | #if !HAVE_AT |
1642 | #if !HAVE_AT |
1625 | |
1643 | |
1626 | /* a bit like realpath, but usually faster because it doesn'T have to return */ |
1644 | /* a bit like realpath, but usually faster because it doesn't have to return */ |
1627 | /* an absolute or canonical path */ |
1645 | /* an absolute or canonical path */ |
1628 | static const char * |
1646 | static const char * |
1629 | wd_expand (struct etp_tmpbuf *tmpbuf, eio_wd wd, const char *path) |
1647 | wd_expand (struct etp_tmpbuf *tmpbuf, eio_wd wd, const char *path) |
1630 | { |
1648 | { |
1631 | if (!wd || *path == '/') |
1649 | if (!wd || *path == '/') |
… | |
… | |
1659 | |
1677 | |
1660 | if (len < 0) |
1678 | if (len < 0) |
1661 | return EIO_INVALID_WD; |
1679 | return EIO_INVALID_WD; |
1662 | |
1680 | |
1663 | #if HAVE_AT |
1681 | #if HAVE_AT |
1664 | fd = openat (WD2FD (wd), path, O_CLOEXEC | O_SEARCH | O_DIRECTORY); |
1682 | fd = openat (WD2FD (wd), path, O_CLOEXEC | O_SEARCH | O_DIRECTORY | O_NONBLOCK); |
|
|
1683 | |
|
|
1684 | /* 0 is a valid fd, but we use it for EIO_CWD, so in the very unlikely */ |
|
|
1685 | /* case of fd 0 being available (almost certainly an a pplication bug) */ |
|
|
1686 | /* make sure we use another fd value */ |
|
|
1687 | #if EIO_CWD |
|
|
1688 | error EIO_CWD must be 0 |
|
|
1689 | #endif |
|
|
1690 | if (ecb_expect_false (fd == 0)) |
|
|
1691 | { |
|
|
1692 | int fd2 = fcntl (fd, F_DUPFD_CLOEXEC ? F_DUPFD_CLOEXEC : F_DUPFD); |
|
|
1693 | fcntl (fd2, F_SETFD, FD_CLOEXEC); |
|
|
1694 | eio__close (fd); |
|
|
1695 | fd = fd2; |
|
|
1696 | } |
1665 | |
1697 | |
1666 | if (fd < 0) |
1698 | if (fd < 0) |
1667 | return EIO_INVALID_WD; |
1699 | return EIO_INVALID_WD; |
1668 | #endif |
1700 | #endif |
1669 | |
1701 | |
… | |
… | |
1681 | } |
1713 | } |
1682 | |
1714 | |
1683 | eio_wd |
1715 | eio_wd |
1684 | eio_wd_open_sync (eio_wd wd, const char *path) |
1716 | eio_wd_open_sync (eio_wd wd, const char *path) |
1685 | { |
1717 | { |
1686 | struct etp_tmpbuf tmpbuf = { }; |
1718 | struct etp_tmpbuf tmpbuf = { 0 }; |
1687 | wd = eio__wd_open_sync (&tmpbuf, wd, path); |
1719 | wd = eio__wd_open_sync (&tmpbuf, wd, path); |
1688 | free (tmpbuf.ptr); |
1720 | free (tmpbuf.ptr); |
1689 | |
1721 | |
1690 | return wd; |
1722 | return wd; |
1691 | } |
1723 | } |
… | |
… | |
1720 | /* they forgot these */ |
1752 | /* they forgot these */ |
1721 | |
1753 | |
1722 | static int |
1754 | static int |
1723 | eio__truncateat (int dirfd, const char *path, off_t length) |
1755 | eio__truncateat (int dirfd, const char *path, off_t length) |
1724 | { |
1756 | { |
1725 | int fd = openat (dirfd, path, O_WRONLY | O_CLOEXEC); |
1757 | int fd = openat (dirfd, path, O_WRONLY | O_CLOEXEC | O_NONBLOCK); |
1726 | int res; |
1758 | int res; |
1727 | |
1759 | |
1728 | if (fd < 0) |
1760 | if (fd < 0) |
1729 | return fd; |
1761 | return fd; |
1730 | |
1762 | |
… | |
… | |
1734 | } |
1766 | } |
1735 | |
1767 | |
1736 | static int |
1768 | static int |
1737 | eio__statvfsat (int dirfd, const char *path, struct statvfs *buf) |
1769 | eio__statvfsat (int dirfd, const char *path, struct statvfs *buf) |
1738 | { |
1770 | { |
1739 | int fd = openat (dirfd, path, O_SEARCH | O_CLOEXEC); |
1771 | int fd = openat (dirfd, path, O_SEARCH | O_CLOEXEC | O_NONBLOCK); |
1740 | int res; |
1772 | int res; |
1741 | |
1773 | |
1742 | if (fd < 0) |
1774 | if (fd < 0) |
1743 | return fd; |
1775 | return fd; |
1744 | |
1776 | |
… | |
… | |
1906 | |
1938 | |
1907 | case EIO_UNLINK: req->result = unlinkat (dirfd, req->ptr1, 0); break; |
1939 | case EIO_UNLINK: req->result = unlinkat (dirfd, req->ptr1, 0); break; |
1908 | case EIO_RMDIR: /* complications arise because "." cannot be removed, so we might have to expand */ |
1940 | case EIO_RMDIR: /* complications arise because "." cannot be removed, so we might have to expand */ |
1909 | req->result = req->wd && SINGLEDOT (req->ptr1) |
1941 | req->result = req->wd && SINGLEDOT (req->ptr1) |
1910 | ? rmdir (req->wd->str) |
1942 | ? rmdir (req->wd->str) |
1911 | : unlinkat (dirfd, req->ptr1, AT_REMOVEDIR); break; |
1943 | : unlinkat (dirfd, req->ptr1, AT_REMOVEDIR); break; |
1912 | case EIO_MKDIR: req->result = mkdirat (dirfd, req->ptr1, (mode_t)req->int2); break; |
1944 | case EIO_MKDIR: req->result = mkdirat (dirfd, req->ptr1, (mode_t)req->int2); break; |
1913 | case EIO_RENAME: req->result = eio__renameat2 ( |
1945 | case EIO_RENAME: req->result = eio__renameat2 ( |
1914 | dirfd, |
1946 | dirfd, |
1915 | /* complications arise because "." cannot be renamed, so we might have to expand */ |
1947 | /* complications arise because "." cannot be renamed, so we might have to expand */ |
1916 | req->wd && SINGLEDOT (req->ptr1) ? req->wd->str : req->ptr1, |
1948 | req->wd && SINGLEDOT (req->ptr1) ? req->wd->str : req->ptr1, |
… | |
… | |
2409 | eio_sendfile_sync (int ofd, int ifd, off_t offset, size_t count) |
2441 | eio_sendfile_sync (int ofd, int ifd, off_t offset, size_t count) |
2410 | { |
2442 | { |
2411 | return eio__sendfile (ofd, ifd, offset, count); |
2443 | return eio__sendfile (ofd, ifd, offset, count); |
2412 | } |
2444 | } |
2413 | |
2445 | |
|
|
2446 | int eio_mlockall_sync (int flags) |
|
|
2447 | { |
|
|
2448 | return eio__mlockall (flags); |
|
|
2449 | } |
|
|
2450 | |