forked from OSchip/llvm-project
[libc] Add implementation of functions stat, fstat and lstat.
All supporting type and macro definitions have also been added. Reviewed By: lntue Differential Revision: https://reviews.llvm.org/D134262
This commit is contained in:
parent
f6e7ad5604
commit
e310f8bddf
|
@ -277,7 +277,8 @@ def SysResourceAPI : PublicAPI<"sys/resource.h"> {
|
|||
}
|
||||
|
||||
def SysStatAPI : PublicAPI<"sys/stat.h"> {
|
||||
let Types = ["mode_t"];
|
||||
let Types = ["mode_t", "dev_t", "ino_t", "nlink_t", "uid_t", "gid_t", "off_t",
|
||||
"struct timespec", "blksize_t", "blkcnt_t", "struct stat"];
|
||||
}
|
||||
|
||||
def SysSendfileAPI : PublicAPI<"sys/sendfile.h"> {
|
||||
|
|
|
@ -113,8 +113,11 @@ set(TARGET_LIBC_ENTRYPOINTS
|
|||
libc.src.sys.stat.chmod
|
||||
libc.src.sys.stat.fchmod
|
||||
libc.src.sys.stat.fchmodat
|
||||
libc.src.sys.stat.fstat
|
||||
libc.src.sys.stat.lstat
|
||||
libc.src.sys.stat.mkdir
|
||||
libc.src.sys.stat.mkdirat
|
||||
libc.src.sys.stat.stat
|
||||
|
||||
# sys/utsname.h entrypoints
|
||||
libc.src.sys.utsname.uname
|
||||
|
|
|
@ -222,6 +222,7 @@ add_gen_header(
|
|||
.llvm_libc_common_h
|
||||
.llvm-libc-macros.sys_stat_macros
|
||||
.llvm-libc-types.mode_t
|
||||
.llvm-libc-types.struct_stat
|
||||
)
|
||||
|
||||
add_gen_header(
|
||||
|
|
|
@ -62,6 +62,15 @@
|
|||
#define S_ISUID 04000
|
||||
#define S_ISGID 02000
|
||||
|
||||
// File type flags
|
||||
#define S_IFMT 0170000
|
||||
#define S_IFDIR 0040000
|
||||
#define S_IFCHR 0020000
|
||||
#define S_IFBLK 0060000
|
||||
#define S_IFREG 0100000
|
||||
#define S_FIFO 0010000
|
||||
#define S_IFLNK 0120000
|
||||
|
||||
// Special directory FD to indicate that the path argument to
|
||||
// openat is relative to the current directory.
|
||||
#define AT_FDCWD -100
|
||||
|
@ -70,6 +79,13 @@
|
|||
// has to perform the equivalent of "rmdir" on the path argument.
|
||||
#define AT_REMOVEDIR 0x200
|
||||
|
||||
// Special flag for functions like lstat to convey that symlinks
|
||||
// should not be followed.
|
||||
#define AT_SYMLINK_NOFOLLOW 0x100
|
||||
|
||||
// Allow empty relative pathname.
|
||||
#define AT_EMPTY_PATH 0x1000
|
||||
|
||||
// Values of SYS_fcntl commands.
|
||||
#define F_DUPFD 0
|
||||
#define F_GETFD 1
|
||||
|
|
|
@ -9,10 +9,13 @@ add_header(__pthread_tss_dtor_t HDR __pthread_tss_dtor_t.h)
|
|||
add_header(__qsortcompare_t HDR __qsortcompare_t.h)
|
||||
add_header(__sighandler_t HDR __sighandler_t.h)
|
||||
add_header(__thread_type HDR __thread_type.h)
|
||||
add_header(blkcnt_t HDR blkcnt_t.h)
|
||||
add_header(blksize_t HDR blksize_t.h)
|
||||
add_header(cnd_t HDR cnd_t.h)
|
||||
add_header(cookie_io_functions_t HDR cookie_io_functions_t.h DEPENDS .off64_t)
|
||||
add_header(double_t HDR double_t.h)
|
||||
add_header(DIR HDR DIR.h)
|
||||
add_header(dev_t HDR dev_t.h)
|
||||
add_header(div_t HDR div_t.h)
|
||||
add_header(ldiv_t HDR ldiv_t.h)
|
||||
add_header(lldiv_t HDR lldiv_t.h)
|
||||
|
@ -20,10 +23,13 @@ add_header(FILE HDR FILE.h)
|
|||
add_header(fenv_t HDR fenv_t.h)
|
||||
add_header(fexcept_t HDR fexcept_t.h)
|
||||
add_header(float_t HDR float_t.h)
|
||||
add_header(gid_t HDR gid_t.h)
|
||||
add_header(uid_t HDR uid_t.h)
|
||||
add_header(imaxdiv_t HDR imaxdiv_t.h)
|
||||
add_header(ino_t HDR ino_t.h)
|
||||
add_header(mode_t HDR mode_t.h)
|
||||
add_header(mtx_t HDR mtx_t.h DEPENDS .__futex_word .__mutex_type)
|
||||
add_header(nlink_t HDR nlink_t.h)
|
||||
add_header(off_t HDR off_t.h)
|
||||
add_header(once_flag HDR once_flag.h DEPENDS .__futex_word)
|
||||
add_header(pthread_attr_t HDR pthread_attr_t.h DEPENDS .size_t)
|
||||
|
@ -36,11 +42,19 @@ add_header(struct_rlimit HDR struct_rlimit.h DEPENDS .rlim_t)
|
|||
add_header(ssize_t HDR ssize_t.h)
|
||||
add_header(struct_dirent HDR struct_dirent.h DEPENDS .ino_t .off_t)
|
||||
add_header(struct_sigaction HDR struct_sigaction.h)
|
||||
add_header(time_t HDR time_t.h)
|
||||
add_header(struct_timespec HDR struct_timespec.h DEPENDS .time_t)
|
||||
add_header(
|
||||
struct_stat
|
||||
HDR struct_stat.h
|
||||
DEPENDS
|
||||
.dev_t .ino_t .mode_t .nlink_t .uid_t .gid_t .off_t .struct_timespec
|
||||
.blksize_t .blkcnt_t
|
||||
)
|
||||
add_header(struct_tm HDR struct_tm.h)
|
||||
add_header(struct_utsname HDR struct_utsname.h)
|
||||
add_header(thrd_start_t HDR thrd_start_t.h)
|
||||
add_header(thrd_t HDR thrd_t.h DEPENDS .__thread_type)
|
||||
add_header(time_t HDR time_t.h)
|
||||
add_header(tss_t HDR tss_t.h)
|
||||
add_header(tss_dtor_t HDR tss_dtor_t.h)
|
||||
add_header(__atexithandler_t HDR __atexithandler_t.h)
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
//===-- Definition of blkcnt_t type ---------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef __LLVM_LIBC_TYPES_BLKCNT_T_H__
|
||||
#define __LLVM_LIBC_TYPES_BLKCNT_T_H__
|
||||
|
||||
typedef __INTPTR_TYPE__ blkcnt_t;
|
||||
|
||||
#endif // __LLVM_LIBC_TYPES_BLKCNT_T_H__
|
|
@ -0,0 +1,14 @@
|
|||
//===-- Definition of blksize_t type --------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef __LLVM_LIBC_TYPES_BLKSIZE_T_H__
|
||||
#define __LLVM_LIBC_TYPES_BLKSIZE_T_H__
|
||||
|
||||
typedef __INTPTR_TYPE__ blksize_t;
|
||||
|
||||
#endif // __LLVM_LIBC_TYPES_BLKSIZE_T_H__
|
|
@ -0,0 +1,14 @@
|
|||
//===-- Definition of dev_t type ------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef __LLVM_LIBC_TYPES_DEV_T_H__
|
||||
#define __LLVM_LIBC_TYPES_DEV_T_H__
|
||||
|
||||
typedef __UINT64_TYPE__ dev_t;
|
||||
|
||||
#endif // __LLVM_LIBC_TYPES_DEV_T_H__
|
|
@ -0,0 +1,14 @@
|
|||
//===-- Definition of gid_t type ------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef __LLVM_LIBC_TYPES_GID_T_H__
|
||||
#define __LLVM_LIBC_TYPES_GID_T_H__
|
||||
|
||||
typedef __UINT32_TYPE__ gid_t;
|
||||
|
||||
#endif // __LLVM_LIBC_TYPES_GID_T_H__
|
|
@ -1,4 +1,4 @@
|
|||
//===-- Definition of type ino_t ------------------------------------------===//
|
||||
//===-- Definition of ino_t type ------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
|
@ -9,6 +9,6 @@
|
|||
#ifndef __LLVM_LIBC_TYPES_INO_T_H__
|
||||
#define __LLVM_LIBC_TYPES_INO_T_H__
|
||||
|
||||
typedef unsigned long ino_t;
|
||||
typedef __UINTPTR_TYPE__ ino_t;
|
||||
|
||||
#endif // __LLVM_LIBC_TYPES_INO_T_H__
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
//===-- Definition of nlink_t type ----------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef __LLVM_LIBC_TYPES_NLINK_T_H__
|
||||
#define __LLVM_LIBC_TYPES_NLINK_T_H__
|
||||
|
||||
typedef __UINTPTR_TYPE__ nlink_t;
|
||||
|
||||
#endif // __LLVM_LIBC_TYPES_NLINK_T_H__
|
|
@ -0,0 +1,39 @@
|
|||
//===-- Definition of struct stat -----------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef __LLVM_LIBC_TYPES_STRUCT_STAT_H__
|
||||
#define __LLVM_LIBC_TYPES_STRUCT_STAT_H__
|
||||
|
||||
#include <llvm-libc-types/blkcnt_t.h>
|
||||
#include <llvm-libc-types/blksize_t.h>
|
||||
#include <llvm-libc-types/dev_t.h>
|
||||
#include <llvm-libc-types/gid_t.h>
|
||||
#include <llvm-libc-types/ino_t.h>
|
||||
#include <llvm-libc-types/mode_t.h>
|
||||
#include <llvm-libc-types/nlink_t.h>
|
||||
#include <llvm-libc-types/off_t.h>
|
||||
#include <llvm-libc-types/struct_timespec.h>
|
||||
#include <llvm-libc-types/uid_t.h>
|
||||
|
||||
struct stat {
|
||||
dev_t st_dev;
|
||||
ino_t st_ino;
|
||||
mode_t st_mode;
|
||||
nlink_t st_nlink;
|
||||
uid_t st_uid;
|
||||
gid_t st_gid;
|
||||
dev_t st_rdev;
|
||||
off_t st_size;
|
||||
struct timespec st_atim;
|
||||
struct timespec st_mtim;
|
||||
struct timespec st_ctim;
|
||||
blksize_t st_blksize;
|
||||
blkcnt_t st_blocks;
|
||||
};
|
||||
|
||||
#endif // __LLVM_LIBC_TYPES_STRUCT_STAT_H__
|
|
@ -0,0 +1,19 @@
|
|||
//===-- Definition of struct timespec -------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef __LLVM_LIBC_TYPES_TIMESPEC_H__
|
||||
#define __LLVM_LIBC_TYPES_TIMESPEC_H__
|
||||
|
||||
#include <llvm-libc-types/time_t.h>
|
||||
|
||||
struct timespec {
|
||||
time_t tv_sec;
|
||||
long tv_nsec;
|
||||
};
|
||||
|
||||
#endif // __LLVM_LIBC_TYPES_TIMESPEC_H__
|
|
@ -9,6 +9,6 @@
|
|||
#ifndef __LLVM_LIBC_TYPES_TIME_T_H__
|
||||
#define __LLVM_LIBC_TYPES_TIME_T_H__
|
||||
|
||||
typedef long time_t;
|
||||
typedef __INTPTR_TYPE__ time_t;
|
||||
|
||||
#endif // __LLVM_LIBC_TYPES_TIME_T_H__
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
//===-- Definition of uid_t type ------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef __LLVM_LIBC_TYPES_UID_T_H__
|
||||
#define __LLVM_LIBC_TYPES_UID_T_H__
|
||||
|
||||
typedef __UINT32_TYPE__ uid_t;
|
||||
|
||||
#endif // __LLVM_LIBC_TYPES_UID_T_H__
|
|
@ -16,6 +16,18 @@ def PThreadKeyT : NamedType<"pthread_key_t">;
|
|||
def PThreadKeyTPtr : PtrType<PThreadKeyT>;
|
||||
|
||||
def InoT : NamedType<"ino_t">;
|
||||
def UidT : NamedType<"uid_t">;
|
||||
def GidT : NamedType<"gid_t">;
|
||||
def DevT : NamedType<"dev_t">;
|
||||
def BlkSizeT : NamedType<"blksize_t">;
|
||||
def BlkCntT : NamedType<"blkcnt_t">;
|
||||
def NLinkT : NamedType<"nlink_t">;
|
||||
def TimeSpec : NamedType<"struct timespec">;
|
||||
|
||||
def StatType : NamedType<"struct stat">;
|
||||
def StatTypePtr : PtrType<StatType>;
|
||||
def RestrictedStatTypePtr : RestrictedPtrType<StatType>;
|
||||
|
||||
def DIR : NamedType<"DIR">;
|
||||
def DIRPtr : PtrType<DIR>;
|
||||
def DIRRestrictedPtr : RestrictedPtrType<DIR>;
|
||||
|
@ -491,7 +503,7 @@ def POSIX : StandardSpec<"POSIX"> {
|
|||
HeaderSpec SysStat = HeaderSpec<
|
||||
"sys/stat.h",
|
||||
[], // Macros
|
||||
[ModeTType], // Types
|
||||
[ModeTType, DevT, InoT, UidT, GidT, TimeSpec, BlkSizeT, BlkCntT, OffTType, NLinkT, StatType], // Types
|
||||
[], // Enumerations
|
||||
[
|
||||
FunctionSpec<
|
||||
|
@ -509,6 +521,16 @@ def POSIX : StandardSpec<"POSIX"> {
|
|||
RetValSpec<IntType>,
|
||||
[ArgSpec<IntType>, ArgSpec<ConstCharPtr>, ArgSpec<ModeTType>, ArgSpec<IntType>]
|
||||
>,
|
||||
FunctionSpec<
|
||||
"fstat",
|
||||
RetValSpec<IntType>,
|
||||
[ArgSpec<IntType>, ArgSpec<StatTypePtr>]
|
||||
>,
|
||||
FunctionSpec<
|
||||
"lstat",
|
||||
RetValSpec<IntType>,
|
||||
[ArgSpec<ConstRestrictedCharPtr>, ArgSpec<RestrictedStatTypePtr>]
|
||||
>,
|
||||
FunctionSpec<
|
||||
"mkdir",
|
||||
RetValSpec<IntType>,
|
||||
|
@ -519,6 +541,11 @@ def POSIX : StandardSpec<"POSIX"> {
|
|||
RetValSpec<IntType>,
|
||||
[ArgSpec<IntType>, ArgSpec<ConstCharPtr>, ArgSpec<ModeTType>]
|
||||
>,
|
||||
FunctionSpec<
|
||||
"stat",
|
||||
RetValSpec<IntType>,
|
||||
[ArgSpec<ConstRestrictedCharPtr>, ArgSpec<RestrictedStatTypePtr>]
|
||||
>,
|
||||
]
|
||||
>;
|
||||
|
||||
|
|
|
@ -23,6 +23,20 @@ add_entrypoint_object(
|
|||
.${LIBC_TARGET_OS}.fchmod
|
||||
)
|
||||
|
||||
add_entrypoint_object(
|
||||
fstat
|
||||
ALIAS
|
||||
DEPENDS
|
||||
.${LIBC_TARGET_OS}.fstat
|
||||
)
|
||||
|
||||
add_entrypoint_object(
|
||||
lstat
|
||||
ALIAS
|
||||
DEPENDS
|
||||
.${LIBC_TARGET_OS}.lstat
|
||||
)
|
||||
|
||||
add_entrypoint_object(
|
||||
mkdir
|
||||
ALIAS
|
||||
|
@ -36,3 +50,10 @@ add_entrypoint_object(
|
|||
DEPENDS
|
||||
.${LIBC_TARGET_OS}.mkdirat
|
||||
)
|
||||
|
||||
add_entrypoint_object(
|
||||
stat
|
||||
ALIAS
|
||||
DEPENDS
|
||||
.${LIBC_TARGET_OS}.stat
|
||||
)
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
//===-- Implementation header for fstat -------------------------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIBC_SRC_SYS_STAT_FSTAT_H
|
||||
#define LLVM_LIBC_SRC_SYS_STAT_FSTAT_H
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
namespace __llvm_libc {
|
||||
|
||||
int fstat(int fd, struct stat *statbuf);
|
||||
|
||||
} // namespace __llvm_libc
|
||||
|
||||
#endif // LLVM_LIBC_SRC_SYS_STAT_FSTAT_H
|
|
@ -64,3 +64,50 @@ add_entrypoint_object(
|
|||
libc.src.__support.OSUtil.osutil
|
||||
libc.src.errno.errno
|
||||
)
|
||||
|
||||
add_header_library(
|
||||
kernel_statx
|
||||
HDRS
|
||||
kernel_statx.h
|
||||
DEPENDS
|
||||
libc.include.sys_stat
|
||||
libc.include.sys_syscall
|
||||
libc.src.__support.OSUtil.osutil
|
||||
libc.src.errno.errno
|
||||
)
|
||||
|
||||
add_entrypoint_object(
|
||||
stat
|
||||
SRCS
|
||||
stat.cpp
|
||||
HDRS
|
||||
../stat.h
|
||||
DEPENDS
|
||||
.kernel_statx
|
||||
libc.include.fcntl
|
||||
libc.include.sys_stat
|
||||
)
|
||||
|
||||
add_entrypoint_object(
|
||||
lstat
|
||||
SRCS
|
||||
lstat.cpp
|
||||
HDRS
|
||||
../lstat.h
|
||||
DEPENDS
|
||||
.kernel_statx
|
||||
libc.include.fcntl
|
||||
libc.include.sys_stat
|
||||
)
|
||||
|
||||
add_entrypoint_object(
|
||||
fstat
|
||||
SRCS
|
||||
fstat.cpp
|
||||
HDRS
|
||||
../fstat.h
|
||||
DEPENDS
|
||||
.kernel_statx
|
||||
libc.include.fcntl
|
||||
libc.include.sys_stat
|
||||
)
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
//===-- Linux implementation of fstat -------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "src/sys/stat/fstat.h"
|
||||
#include "kernel_statx.h"
|
||||
|
||||
#include "src/__support/common.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
namespace __llvm_libc {
|
||||
|
||||
LLVM_LIBC_FUNCTION(int, fstat, (int fd, struct stat *statbuf)) {
|
||||
return statx(fd, "", AT_EMPTY_PATH, statbuf);
|
||||
}
|
||||
|
||||
} // namespace __llvm_libc
|
|
@ -0,0 +1,105 @@
|
|||
//===-- Wrapper over SYS_statx syscall ------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIBC_SRC_SYS_STAT_LINUX_STATX_H
|
||||
#define LLVM_LIBC_SRC_SYS_STAT_LINUX_STATX_H
|
||||
|
||||
#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/syscall.h> // For syscall numbers.
|
||||
|
||||
// It is safe to include this kernel header as it is designed to be
|
||||
// included from user programs without causing any name pollution.
|
||||
#include <linux/kdev_t.h>
|
||||
|
||||
namespace {
|
||||
|
||||
// The type definitions in the internal namespace match kernel's definition of
|
||||
// the statx_timestamp and statx types in linux/stat.h. We define equivalent
|
||||
// types here instead of including that header file to avoid name mixup between
|
||||
// linux/stat.h and the libc's stat.h.
|
||||
struct statx_timestamp {
|
||||
int64_t tv_sec;
|
||||
uint32_t tv_nsec;
|
||||
int32_t __reserved;
|
||||
};
|
||||
|
||||
struct statx_buf {
|
||||
uint32_t stx_mask; // What results were written
|
||||
uint32_t stx_blksize; // Preferred general I/O size
|
||||
uint64_t stx_attributes; // Flags conveying information about the file
|
||||
uint32_t stx_nlink; // Number of hard links
|
||||
uint32_t stx_uid; // User ID of owner
|
||||
uint32_t stx_gid; // Group ID of owner
|
||||
uint16_t stx_mode; // File mode
|
||||
uint16_t __spare0[1];
|
||||
uint64_t stx_ino; // Inode number
|
||||
uint64_t stx_size; // File size
|
||||
uint64_t stx_blocks; // Number of 512-byte blocks allocated
|
||||
uint64_t stx_attributes_mask; // Mask to show what's supported in
|
||||
// stx_attributes
|
||||
struct statx_timestamp stx_atime; // Last access time
|
||||
struct statx_timestamp stx_btime; // File creation time
|
||||
struct statx_timestamp stx_ctime; // Last attribute change time
|
||||
struct statx_timestamp stx_mtime; // Last data modification time
|
||||
uint32_t stx_rdev_major; // Device ID of special file
|
||||
uint32_t stx_rdev_minor;
|
||||
uint32_t stx_dev_major; // ID of device containing file
|
||||
uint32_t stx_dev_minor;
|
||||
uint64_t stx_mnt_id;
|
||||
uint64_t __spare2;
|
||||
uint64_t __spare3[12]; // Spare space for future expansion
|
||||
};
|
||||
|
||||
// The below mask value is based on the definition of a similarly
|
||||
// named macro in linux/stat.h. When this flag is passed for the
|
||||
// mask argument to the statx syscall, all fields except the
|
||||
// stx_btime field will be filled in.
|
||||
constexpr unsigned int STATX_BASIC_STATS_MASK = 0x7FF;
|
||||
|
||||
} // Anonymous namespace
|
||||
|
||||
namespace __llvm_libc {
|
||||
|
||||
inline int statx(int dirfd, const char *__restrict path, int flags,
|
||||
struct stat *__restrict statbuf) {
|
||||
// We make a statx syscall and copy out the result into the |statbuf|.
|
||||
::statx_buf xbuf;
|
||||
long ret =
|
||||
syscall(SYS_statx, dirfd, path, flags, ::STATX_BASIC_STATS_MASK, &xbuf);
|
||||
if (ret < 0) {
|
||||
errno = -ret;
|
||||
return -1;
|
||||
}
|
||||
|
||||
statbuf->st_dev = MKDEV(xbuf.stx_dev_major, xbuf.stx_dev_minor);
|
||||
statbuf->st_ino = xbuf.stx_ino;
|
||||
statbuf->st_mode = xbuf.stx_mode;
|
||||
statbuf->st_nlink = xbuf.stx_nlink;
|
||||
statbuf->st_uid = xbuf.stx_uid;
|
||||
statbuf->st_gid = xbuf.stx_gid;
|
||||
statbuf->st_rdev = MKDEV(xbuf.stx_rdev_major, xbuf.stx_rdev_minor);
|
||||
statbuf->st_size = xbuf.stx_size;
|
||||
statbuf->st_atim.tv_sec = xbuf.stx_atime.tv_sec;
|
||||
statbuf->st_atim.tv_nsec = xbuf.stx_atime.tv_nsec;
|
||||
statbuf->st_mtim.tv_sec = xbuf.stx_mtime.tv_sec;
|
||||
statbuf->st_mtim.tv_nsec = xbuf.stx_mtime.tv_nsec;
|
||||
statbuf->st_ctim.tv_sec = xbuf.stx_ctime.tv_sec;
|
||||
statbuf->st_ctim.tv_nsec = xbuf.stx_ctime.tv_nsec;
|
||||
statbuf->st_blksize = xbuf.stx_blksize;
|
||||
statbuf->st_blocks = xbuf.stx_blocks;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace __llvm_libc
|
||||
|
||||
#endif // LLVM_LIBC_SRC_SYS_STAT_LINUX_STATX_H
|
|
@ -0,0 +1,26 @@
|
|||
//===-- Linux implementation of lstat -------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "src/sys/stat/lstat.h"
|
||||
#include "kernel_statx.h"
|
||||
|
||||
#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
|
||||
#include "src/__support/common.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
namespace __llvm_libc {
|
||||
|
||||
LLVM_LIBC_FUNCTION(int, lstat,
|
||||
(const char *__restrict path,
|
||||
struct stat *__restrict statbuf)) {
|
||||
return statx(AT_FDCWD, path, AT_SYMLINK_NOFOLLOW, statbuf);
|
||||
}
|
||||
|
||||
} // namespace __llvm_libc
|
|
@ -0,0 +1,25 @@
|
|||
//===-- Linux implementation of stat --------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "src/sys/stat/stat.h"
|
||||
#include "kernel_statx.h"
|
||||
|
||||
#include "src/__support/common.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
namespace __llvm_libc {
|
||||
|
||||
LLVM_LIBC_FUNCTION(int, stat,
|
||||
(const char *__restrict path,
|
||||
struct stat *__restrict statbuf)) {
|
||||
return statx(AT_FDCWD, path, 0, statbuf);
|
||||
}
|
||||
|
||||
} // namespace __llvm_libc
|
|
@ -0,0 +1,20 @@
|
|||
//===-- Implementation header for lstat -------------------------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIBC_SRC_SYS_STAT_LSTAT_H
|
||||
#define LLVM_LIBC_SRC_SYS_STAT_LSTAT_H
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
namespace __llvm_libc {
|
||||
|
||||
int lstat(const char *__restrict path, struct stat *__restrict statbuf);
|
||||
|
||||
} // namespace __llvm_libc
|
||||
|
||||
#endif // LLVM_LIBC_SRC_SYS_STAT_LSTAT_H
|
|
@ -0,0 +1,20 @@
|
|||
//===-- Implementation header for stat --------------------------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIBC_SRC_SYS_STAT_STAT_H
|
||||
#define LLVM_LIBC_SRC_SYS_STAT_STAT_H
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
namespace __llvm_libc {
|
||||
|
||||
int stat(const char *__restrict path, struct stat *__restrict statbuf);
|
||||
|
||||
} // namespace __llvm_libc
|
||||
|
||||
#endif // LLVM_LIBC_SRC_SYS_STAT_STAT_H
|
|
@ -63,3 +63,51 @@ add_libc_unittest(
|
|||
libc.src.sys.stat.mkdirat
|
||||
libc.src.unistd.rmdir
|
||||
)
|
||||
|
||||
add_libc_unittest(
|
||||
stat_test
|
||||
SUITE
|
||||
libc_sys_stat_unittests
|
||||
SRCS
|
||||
stat_test.cpp
|
||||
DEPENDS
|
||||
libc.include.errno
|
||||
libc.include.fcntl
|
||||
libc.include.sys_stat
|
||||
libc.src.sys.stat.stat
|
||||
libc.src.fcntl.open
|
||||
libc.src.unistd.close
|
||||
libc.src.unistd.unlink
|
||||
)
|
||||
|
||||
add_libc_unittest(
|
||||
lstat_test
|
||||
SUITE
|
||||
libc_sys_stat_unittests
|
||||
SRCS
|
||||
lstat_test.cpp
|
||||
DEPENDS
|
||||
libc.include.errno
|
||||
libc.include.fcntl
|
||||
libc.include.sys_stat
|
||||
libc.src.sys.stat.lstat
|
||||
libc.src.fcntl.open
|
||||
libc.src.unistd.close
|
||||
libc.src.unistd.unlink
|
||||
)
|
||||
|
||||
add_libc_unittest(
|
||||
fstat_test
|
||||
SUITE
|
||||
libc_sys_stat_unittests
|
||||
SRCS
|
||||
fstat_test.cpp
|
||||
DEPENDS
|
||||
libc.include.errno
|
||||
libc.include.fcntl
|
||||
libc.include.sys_stat
|
||||
libc.src.sys.stat.fstat
|
||||
libc.src.fcntl.open
|
||||
libc.src.unistd.close
|
||||
libc.src.unistd.unlink
|
||||
)
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
//===-- Unittests for fstat -----------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "src/fcntl/open.h"
|
||||
#include "src/sys/stat/fstat.h"
|
||||
#include "src/unistd/close.h"
|
||||
#include "src/unistd/unlink.h"
|
||||
#include "test/ErrnoSetterMatcher.h"
|
||||
#include "utils/UnitTest/Test.h"
|
||||
#include "utils/testutils/FDReader.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
TEST(LlvmLibcFStatTest, CreatAndReadMode) {
|
||||
using __llvm_libc::testing::ErrnoSetterMatcher::Fails;
|
||||
using __llvm_libc::testing::ErrnoSetterMatcher::Succeeds;
|
||||
|
||||
// The test file is initially writable. We open it for writing and ensure
|
||||
// that it indeed can be opened for writing. Next, we close the file and
|
||||
// make it readonly using chmod. We test that chmod actually succeeded by
|
||||
// trying to open the file for writing and failing.
|
||||
constexpr const char *TEST_FILE = "testdata/fstat.test";
|
||||
errno = 0;
|
||||
|
||||
int fd = __llvm_libc::open(TEST_FILE, O_CREAT | O_WRONLY, S_IRWXU);
|
||||
ASSERT_GT(fd, 0);
|
||||
ASSERT_EQ(errno, 0);
|
||||
|
||||
struct stat statbuf;
|
||||
ASSERT_THAT(__llvm_libc::fstat(fd, &statbuf), Succeeds(0));
|
||||
|
||||
ASSERT_EQ(int(statbuf.st_mode), int(S_IRWXU | S_IFREG));
|
||||
|
||||
ASSERT_THAT(__llvm_libc::close(fd), Succeeds(0));
|
||||
ASSERT_THAT(__llvm_libc::unlink(TEST_FILE), Succeeds(0));
|
||||
}
|
||||
|
||||
TEST(LlvmLibcFStatTest, NonExistentFile) {
|
||||
errno = 0;
|
||||
using __llvm_libc::testing::ErrnoSetterMatcher::Fails;
|
||||
struct stat statbuf;
|
||||
ASSERT_THAT(__llvm_libc::fstat(-1, &statbuf), Fails(EBADF));
|
||||
errno = 0;
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
//===-- Unittests for lstat -----------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "src/fcntl/open.h"
|
||||
#include "src/sys/stat/lstat.h"
|
||||
#include "src/unistd/close.h"
|
||||
#include "src/unistd/unlink.h"
|
||||
#include "test/ErrnoSetterMatcher.h"
|
||||
#include "utils/UnitTest/Test.h"
|
||||
#include "utils/testutils/FDReader.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
TEST(LlvmLibcLStatTest, CreatAndReadMode) {
|
||||
using __llvm_libc::testing::ErrnoSetterMatcher::Fails;
|
||||
using __llvm_libc::testing::ErrnoSetterMatcher::Succeeds;
|
||||
|
||||
// The test file is initially writable. We open it for writing and ensure
|
||||
// that it indeed can be opened for writing. Next, we close the file and
|
||||
// make it readonly using chmod. We test that chmod actually succeeded by
|
||||
// trying to open the file for writing and failing.
|
||||
constexpr const char *TEST_FILE = "testdata/lstat.test";
|
||||
errno = 0;
|
||||
|
||||
int fd = __llvm_libc::open(TEST_FILE, O_CREAT | O_WRONLY, S_IRWXU);
|
||||
ASSERT_GT(fd, 0);
|
||||
ASSERT_EQ(errno, 0);
|
||||
ASSERT_THAT(__llvm_libc::close(fd), Succeeds(0));
|
||||
|
||||
struct stat statbuf;
|
||||
ASSERT_THAT(__llvm_libc::lstat(TEST_FILE, &statbuf), Succeeds(0));
|
||||
|
||||
ASSERT_EQ(int(statbuf.st_mode), int(S_IRWXU | S_IFREG));
|
||||
|
||||
ASSERT_THAT(__llvm_libc::unlink(TEST_FILE), Succeeds(0));
|
||||
}
|
||||
|
||||
TEST(LlvmLibcLStatTest, NonExistentFile) {
|
||||
errno = 0;
|
||||
using __llvm_libc::testing::ErrnoSetterMatcher::Fails;
|
||||
struct stat statbuf;
|
||||
ASSERT_THAT(__llvm_libc::lstat("non-existent-file", &statbuf), Fails(ENOENT));
|
||||
errno = 0;
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
//===-- Unittests for stat ------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "src/fcntl/open.h"
|
||||
#include "src/sys/stat/stat.h"
|
||||
#include "src/unistd/close.h"
|
||||
#include "src/unistd/unlink.h"
|
||||
#include "test/ErrnoSetterMatcher.h"
|
||||
#include "utils/UnitTest/Test.h"
|
||||
#include "utils/testutils/FDReader.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
TEST(LlvmLibcStatTest, CreatAndReadMode) {
|
||||
using __llvm_libc::testing::ErrnoSetterMatcher::Fails;
|
||||
using __llvm_libc::testing::ErrnoSetterMatcher::Succeeds;
|
||||
|
||||
// The test file is initially writable. We open it for writing and ensure
|
||||
// that it indeed can be opened for writing. Next, we close the file and
|
||||
// make it readonly using chmod. We test that chmod actually succeeded by
|
||||
// trying to open the file for writing and failing.
|
||||
constexpr const char *TEST_FILE = "testdata/stat.test";
|
||||
errno = 0;
|
||||
|
||||
int fd = __llvm_libc::open(TEST_FILE, O_CREAT | O_WRONLY, S_IRWXU);
|
||||
ASSERT_GT(fd, 0);
|
||||
ASSERT_EQ(errno, 0);
|
||||
ASSERT_THAT(__llvm_libc::close(fd), Succeeds(0));
|
||||
|
||||
struct stat statbuf;
|
||||
ASSERT_THAT(__llvm_libc::stat(TEST_FILE, &statbuf), Succeeds(0));
|
||||
|
||||
ASSERT_EQ(int(statbuf.st_mode), int(S_IRWXU | S_IFREG));
|
||||
|
||||
ASSERT_THAT(__llvm_libc::unlink(TEST_FILE), Succeeds(0));
|
||||
}
|
||||
|
||||
TEST(LlvmLibcStatTest, NonExistentFile) {
|
||||
errno = 0;
|
||||
using __llvm_libc::testing::ErrnoSetterMatcher::Fails;
|
||||
struct stat statbuf;
|
||||
ASSERT_THAT(__llvm_libc::stat("non-existent-file", &statbuf), Fails(ENOENT));
|
||||
errno = 0;
|
||||
}
|
Loading…
Reference in New Issue