| // Copyright 2021 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <errno.h> |
| #include <lib/fdio/fdio.h> |
| #include <stdint.h> |
| #include <sys/stat.h> |
| #include <sys/statx.h> |
| #include <unistd.h> |
| |
| #include <algorithm> |
| #include <cerrno> |
| |
| #include "private.h" |
| |
| int statx(int dirfd, const char *pathname, int flags, unsigned int mask, struct statx *buf) { |
| struct stat s; |
| |
| if (buf == nullptr || pathname == nullptr) { |
| return ERRNO(EFAULT); |
| } |
| |
| if (pathname[0] == '\0') { |
| return ERRNO(EINVAL); |
| } |
| |
| int ret = fstatat(dirfd, pathname, &s, 0); |
| if (ret != 0) { |
| return ret; |
| } |
| |
| // Fill up the necessary fields for statx from stat. |
| memset(buf, 0, sizeof(struct statx)); |
| |
| if (mask & STATX_MODE) { |
| buf->stx_mode = s.st_mode; |
| buf->stx_mask |= STATX_MODE; |
| } |
| |
| if (mask & STATX_INO) { |
| buf->stx_ino = s.st_ino; |
| buf->stx_mask |= STATX_INO; |
| } |
| |
| if (mask & STATX_SIZE) { |
| buf->stx_size = s.st_size; |
| buf->stx_mask |= STATX_SIZE; |
| } |
| |
| buf->stx_blksize = s.st_blksize; |
| |
| if (mask & STATX_BLOCKS) { |
| // stx_blocks are blocks of size 512. |
| buf->stx_blocks = s.st_blocks * VNATTR_BLKSIZE / 512; |
| buf->stx_mask |= STATX_BLOCKS; |
| } |
| |
| if (mask & STATX_NLINK) { |
| buf->stx_nlink = s.st_nlink; |
| buf->stx_mask |= STATX_NLINK; |
| } |
| |
| if (mask & STATX_BTIME) { |
| buf->stx_btime.tv_sec = s.st_ctim.tv_sec; |
| buf->stx_btime.tv_nsec = s.st_ctim.tv_nsec; |
| buf->stx_mask |= STATX_BTIME; |
| } |
| |
| if (mask & STATX_MTIME) { |
| buf->stx_mtime.tv_sec = s.st_mtim.tv_sec; |
| buf->stx_mtime.tv_nsec = s.st_mtim.tv_nsec; |
| buf->stx_mask |= STATX_MTIME; |
| } |
| |
| return 0; |
| } |