// SPDX-License-Identifier: GPL-2.0-only
/*
 *  ppm/src/util/path.h
 *
 *  Filesystem path helpers used across the store and transaction layers.
 *  Everything here is POSIX-only on purpose.
 *
 *  Copyright (C) 2026 Project Tick
 */

#ifndef PPM_UTIL_PATH_H
#define PPM_UTIL_PATH_H

#include <stddef.h>

#include <ppm/error.h>

/*
 * Create `path` and every missing parent component with mode `mode`.
 * `mode` is masked by the process umask, like mkdir(2). Existing
 * directories are not an error; existing non-directories are.
 */
ppm_error_t ppm_path_mkdirs(const char *path, unsigned mode);

/*
 * Recursively remove `path`. Symlinks are unlinked, not followed.
 * Returns PPM_OK if the path is already gone.
 */
ppm_error_t ppm_path_rmrf(const char *path);

/*
 * fsync the directory at `path` so that a rename(2) into or out of it
 * is durable across power loss. No-op if fsync is not meaningful for
 * the filesystem (e.g. it returns EINVAL); other errors propagate.
 */
ppm_error_t ppm_path_fsync_dir(const char *path);

/*
 * Build `<a>/<b>` into a freshly allocated buffer. Caller frees.
 * Either component may be empty; redundant slashes are collapsed.
 */
ppm_error_t ppm_path_join(const char *a, const char *b, char **out);

/*
 * True iff `path` exists and is a directory.
 */
int ppm_path_is_dir(const char *path);

/*
 * Portable fdatasync wrapper. Calls fdatasync(2) when available (detected by
 * configure), otherwise falls back to fsync(2). EINVAL and ENOTSUP are
 * silently ignored (filesystem may not support the operation).
 * Returns PPM_OK or PPM_ERR_IO.
 */
ppm_error_t ppm_path_fdatasync(int fd);

#endif /* PPM_UTIL_PATH_H */
