| 1596 | } |
| 1597 | |
| 1598 | int do_open_nofollow(const char *pathname, int flags) |
| 1599 | { |
| 1600 | #ifndef O_NOFOLLOW |
| 1601 | STRUCT_STAT f_st, l_st; |
| 1602 | #endif |
| 1603 | int fd; |
| 1604 | |
| 1605 | if (flags != O_RDONLY) { |
| 1606 | RETURN_ERROR_IF(dry_run, 0); |
| 1607 | RETURN_ERROR_IF_RO_OR_LO; |
| 1608 | #ifndef O_NOFOLLOW |
| 1609 | /* This function doesn't support write attempts w/o O_NOFOLLOW. */ |
| 1610 | errno = EINVAL; |
| 1611 | return -1; |
| 1612 | #endif |
| 1613 | } |
| 1614 | |
| 1615 | #ifdef O_NOATIME |
| 1616 | if (open_noatime) |
| 1617 | flags |= O_NOATIME; |
| 1618 | #endif |
| 1619 | |
| 1620 | #ifdef O_NOFOLLOW |
| 1621 | fd = open(pathname, flags|O_NOFOLLOW); |
| 1622 | #else |
| 1623 | if (do_lstat(pathname, &l_st) < 0) |
| 1624 | return -1; |
| 1625 | if (S_ISLNK(l_st.st_mode)) { |
| 1626 | errno = ELOOP; |
| 1627 | return -1; |
| 1628 | } |
| 1629 | if ((fd = open(pathname, flags)) < 0) |
| 1630 | return fd; |
| 1631 | if (do_fstat(fd, &f_st) < 0) { |
| 1632 | close_and_return_error: |
| 1633 | { |
| 1634 | int save_errno = errno; |
| 1635 | close(fd); |
| 1636 | errno = save_errno; |
| 1637 | } |
| 1638 | return -1; |
| 1639 | } |
| 1640 | if (l_st.st_dev != f_st.st_dev || l_st.st_ino != f_st.st_ino) { |
| 1641 | errno = EINVAL; |
| 1642 | goto close_and_return_error; |
| 1643 | } |
| 1644 | #endif |
| 1645 | |
| 1646 | return fd; |
| 1647 | } |
| 1648 | |
| 1649 | /* |
| 1650 | open a file relative to a base directory. The basedir can be NULL, |
no test coverage detected