mirror of
https://github.com/amadvance/snapraid.git
synced 2026-10-12 02:10:54 +00:00
176 lines
5.4 KiB
C
176 lines
5.4 KiB
C
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
// Copyright (C) 2026 Andrea Mazzoleni
|
|
|
|
#ifndef __UNIX_H
|
|
#define __UNIX_H
|
|
|
|
#ifdef __linux__
|
|
#define HAVE_LINUX_DEVICE 1 /**< In Linux enables special device support. */
|
|
#define HAVE_DIRECT_IO 1 /**< Support O_DIRECT in open(). */
|
|
#include <sys/syscall.h>
|
|
#include <sched.h>
|
|
#endif
|
|
|
|
#define SYSLOG "syslog"
|
|
|
|
#define OS_LVL_CRITICAL LOG_CRIT
|
|
#define OS_LVL_ERROR LOG_ERR
|
|
#define OS_LVL_WARNING LOG_WARNING
|
|
#define OS_LVL_INFO LOG_INFO
|
|
#define OS_LVL_DEBUG LOG_DEBUG
|
|
|
|
#if !HAVE_STRUCT_DIRENT_D_TYPE
|
|
/* without d_type these values are internal markers populated from lstat(). */
|
|
#ifndef DT_UNKNOWN
|
|
#define DT_UNKNOWN 0
|
|
#endif
|
|
#ifndef DT_DIR
|
|
#define DT_DIR 4
|
|
#endif
|
|
#ifndef DT_REG
|
|
#define DT_REG 8
|
|
#endif
|
|
#ifndef DT_LNK
|
|
#define DT_LNK 10
|
|
#endif
|
|
#endif
|
|
|
|
/* implement close_range for glibc 2.33 or earlier */
|
|
#if defined(__linux__) && !defined(HAVE_CLOSE_RANGE)
|
|
#ifndef __NR_close_range
|
|
#define __NR_close_range 436
|
|
#endif
|
|
#define close_range close_range_impl
|
|
static inline int close_range_impl(unsigned int first, unsigned int last, unsigned int flags)
|
|
{
|
|
return (int)syscall(__NR_close_range, first, last, flags);
|
|
}
|
|
#define HAVE_CLOSE_RANGE 1
|
|
#endif
|
|
|
|
#ifndef WEXITSTATUS
|
|
#define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
|
|
#endif
|
|
#ifndef WIFEXITED
|
|
#define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
|
|
#endif
|
|
|
|
#define FOPEN_TEXT ""
|
|
#define FOPEN_BINARY ""
|
|
|
|
#define O_BINARY 0 /**< Not used in Unix. */
|
|
#define O_SEQUENTIAL 0 /**< In Unix posix_fadvise() shall be used. */
|
|
|
|
/**
|
|
* If nanoseconds are not supported, we report the special STAT_NSEC_INVALID value,
|
|
* to mark that it's undefined.
|
|
*/
|
|
#define STAT_NSEC_INVALID -1
|
|
|
|
/* check if we have nanoseconds support */
|
|
#if HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
|
|
#define STAT_NSEC(st) ((int)(st)->st_mtim.tv_nsec) /* Linux */
|
|
#elif HAVE_STRUCT_STAT_ST_MTIMENSEC
|
|
#define STAT_NSEC(st) ((int)(st)->st_mtimensec) /* NetBSD */
|
|
#elif HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC
|
|
#define STAT_NSEC(st) ((int)(st)->st_mtimespec.tv_nsec) /* FreeBSD, Mac OS X */
|
|
#else
|
|
#define STAT_NSEC(st) STAT_NSEC_INVALID
|
|
#endif
|
|
|
|
#if HAVE_POSIX_FADVISE
|
|
/**
|
|
* Wrapper around posix_fadvise() that handles ENOENT by converting it to
|
|
* ENOSYS.
|
|
*
|
|
* Why can posix_fadvise() return ENOENT?
|
|
*
|
|
* According to POSIX and the Linux kernel's standard fadvise64 implementation
|
|
* (mm/fadvise.c), posix_fadvise() should only return EBADF (bad file
|
|
* descriptor), ESPIPE (fd refers to a pipe or FIFO), or EINVAL (invalid
|
|
* advice value or arguments). ENOENT is never generated by the kernel's
|
|
* generic path.
|
|
*
|
|
* However, the VFS layer allows individual filesystems to provide their own
|
|
* .fadvise() method, which is called instead of (or in addition to) the
|
|
* generic implementation. Certain filesystem drivers can return ENOENT in
|
|
* this method for reasons that are completely unrelated to the file not
|
|
* existing (the file is clearly open, we have a valid fd):
|
|
*
|
|
* - NFS: A stale NFS inode can be revalidated against the server while
|
|
* fadvise is being processed. If the server-side file has been removed or
|
|
* renamed, the revalidation discovers the inode is gone and returns
|
|
* -ENOENT, even though the client still holds an open file descriptor.
|
|
*
|
|
* - FUSE-based filesystems (mergerfs, sshfs, rclone, etc.): The FUSE daemon
|
|
* receives the fadvise request and may forward it to an underlying backend.
|
|
* If that backend cannot find the file (e.g., the backing path has changed,
|
|
* the FUSE daemon is partially initialised, or the daemon translates the
|
|
* request and the target layer returns an error), the daemon may return
|
|
* ENOENT to the kernel.
|
|
*
|
|
* - Overlayfs (used by Docker, Podman, LXC): The overlayfs .fadvise()
|
|
* implementation delegates to the lower or upper layer. If the lookup
|
|
* through the overlay stack fails to find the real inode (e.g., the upper
|
|
* directory entry is absent and the lower copy is in a weird state), the
|
|
* delegation can return ENOENT.
|
|
*
|
|
* - Other network or virtual filesystems: Any out-of-tree or in-tree
|
|
* filesystem that implements .fadvise() and performs a path or inode
|
|
* lookup as part of processing the hint can propagate ENOENT if that
|
|
* internal lookup fails.
|
|
*
|
|
* Because posix_fadvise() is always an advisory hint, it never affects
|
|
* correctness, only performance, it is safe to treat unexpected errors,
|
|
* including ENOENT, as "not supported" (ENOSYS) and continue.
|
|
*/
|
|
int posix_fadvise_wrapper(int fd, off_t offset, off_t len, int advice);
|
|
#endif
|
|
|
|
#if !HAVE_EACCESS
|
|
/**
|
|
* Check effective user's permissions for a file.
|
|
* Conceptually identical to access(), but uses the effective UID/GID.
|
|
*/
|
|
int eaccess(const char* pathname, int mode);
|
|
#endif
|
|
|
|
/**
|
|
* Open a file with the O_NOATIME flag to avoid to update the access time.
|
|
*/
|
|
int open_noatime(const char* file, int flags);
|
|
|
|
/**
|
|
* Check if the specified file is hidden.
|
|
*/
|
|
int dirent_hidden(struct dirent* dd);
|
|
|
|
/**
|
|
* Return a description of the file type.
|
|
*/
|
|
const char* stat_desc(struct stat* st);
|
|
|
|
/**
|
|
* Return the alignment requirement for direct IO.
|
|
*/
|
|
size_t direct_size(void);
|
|
|
|
/****************************************************************************/
|
|
/* thread */
|
|
|
|
#if HAVE_PTHREAD_H
|
|
#include <pthread.h>
|
|
#endif
|
|
|
|
#if HAVE_PTHREAD
|
|
#define HAVE_THREAD 1
|
|
typedef pthread_t thread_id_t;
|
|
typedef pthread_mutex_t thread_mutex_t;
|
|
typedef pthread_cond_t thread_cond_t;
|
|
typedef pthread_key_t thread_key_t;
|
|
typedef pthread_rwlock_t thread_rwlock_t;
|
|
#endif
|
|
|
|
#endif
|
|
|