#ifndef INCLUDE_path_h__
#define INCLUDE_path_h__
#include "common.h"
#include "posix.h"
#include "buffer.h"
#include "vector.h"
#include "git2/sys/path.h"
extern char *git_path_dirname(const char *path);
extern int git_path_dirname_r(git_buf *buffer, const char *path);
extern char *git_path_basename(const char *path);
extern int git_path_basename_r(git_buf *buffer, const char *path);
extern size_t git_path_basename_offset(git_buf *buffer);
extern const char *git_path_topdir(const char *path);
extern int git_path_root(const char *path);
extern int git_path_to_dir(git_buf *path);
extern void git_path_string_to_dir(char* path, size_t size);
GIT_INLINE(int) git_path_is_dot_or_dotdot(const char *name)
{
return (name[0] == '.' &&
(name[1] == '\0' ||
(name[1] == '.' && name[2] == '\0')));
}
#ifdef GIT_WIN32
GIT_INLINE(int) git_path_is_dot_or_dotdotW(const wchar_t *name)
{
return (name[0] == L'.' &&
(name[1] == L'\0' ||
(name[1] == L'.' && name[2] == L'\0')));
}
#define git_path_is_absolute(p) \
(git__isalpha((p)[0]) && (p)[1] == ':' && ((p)[2] == '\\' || (p)[2] == '/'))
#define git_path_is_dirsep(p) \
((p) == '/' || (p) == '\\')
GIT_INLINE(void) git_path_mkposix(char *path)
{
while (*path) {
if (*path == '\\')
*path = '/';
path++;
}
}
#else
# define git_path_mkposix(p)
#define git_path_is_absolute(p) \
((p)[0] == '/')
#define git_path_is_dirsep(p) \
((p) == '/')
#endif
GIT_INLINE(int) git_path_is_relative(const char *p)
{
return (p[0] == '.' && (p[1] == '/' || (p[1] == '.' && p[2] == '/')));
}
GIT_INLINE(int) git_path_at_end_of_segment(const char *p)
{
return !*p || *p == '/';
}
extern int git__percent_decode(git_buf *decoded_out, const char *input);
extern int git_path_fromurl(git_buf *local_path_out, const char *file_url);
extern bool git_path_exists(const char *path);
extern bool git_path_isdir(const char *path);
extern bool git_path_isfile(const char *path);
extern bool git_path_islink(const char *path);
extern bool git_path_is_empty_dir(const char *path);
extern int git_path_lstat(const char *path, struct stat *st);
extern bool git_path_contains(git_buf *dir, const char *item);
extern bool git_path_contains_dir(git_buf *parent, const char *subdir);
extern size_t git_path_common_dirlen(const char *one, const char *two);
extern int git_path_make_relative(git_buf *path, const char *parent);
extern bool git_path_contains_file(git_buf *dir, const char *file);
extern int git_path_join_unrooted(
git_buf *path_out, const char *path, const char *base, ssize_t *root_at);
extern void git_path_squash_slashes(git_buf *path);
extern int git_path_prettify(git_buf *path_out, const char *path, const char *base);
extern int git_path_prettify_dir(git_buf *path_out, const char *path, const char *base);
extern int git_path_find_dir(git_buf *dir, const char *path, const char *base);
extern int git_path_resolve_relative(git_buf *path, size_t ceiling);
extern int git_path_apply_relative(git_buf *target, const char *relpath);
enum {
GIT_PATH_DIR_IGNORE_CASE = (1u << 0),
GIT_PATH_DIR_PRECOMPOSE_UNICODE = (1u << 1),
GIT_PATH_DIR_INCLUDE_DOT_AND_DOTDOT = (1u << 2),
};
extern int git_path_direach(
git_buf *pathbuf,
uint32_t flags,
int (*callback)(void *payload, git_buf *path),
void *payload);
extern int git_path_cmp(
const char *name1, size_t len1, int isdir1,
const char *name2, size_t len2, int isdir2,
int (*compare)(const char *, const char *, size_t));
extern int git_path_walk_up(
git_buf *pathbuf,
const char *ceiling,
int (*callback)(void *payload, const char *path),
void *payload);
enum { GIT_PATH_NOTEQUAL = 0, GIT_PATH_EQUAL = 1, GIT_PATH_PREFIX = 2 };
GIT_INLINE(int) git_path_equal_or_prefixed(
const char *parent,
const char *child,
ssize_t *prefixlen)
{
const char *p = parent, *c = child;
int lastslash = 0;
while (*p && *c) {
lastslash = (*p == '/');
if (*p++ != *c++)
return GIT_PATH_NOTEQUAL;
}
if (*p != '\0')
return GIT_PATH_NOTEQUAL;
if (*c == '\0') {
if (prefixlen)
*prefixlen = p - parent;
return GIT_PATH_EQUAL;
}
if (*c == '/' || lastslash) {
if (prefixlen)
*prefixlen = (p - parent) - lastslash;
return GIT_PATH_PREFIX;
}
return GIT_PATH_NOTEQUAL;
}
extern int git_path_set_error(
int errno_value, const char *path, const char *action);
extern bool git_path_has_non_ascii(const char *path, size_t pathlen);
#define GIT_PATH_REPO_ENCODING "UTF-8"
#ifdef __APPLE__
#define GIT_PATH_NATIVE_ENCODING "UTF-8-MAC"
#else
#define GIT_PATH_NATIVE_ENCODING "UTF-8"
#endif
#ifdef GIT_USE_ICONV
#include <iconv.h>
typedef struct {
iconv_t map;
git_buf buf;
} git_path_iconv_t;
#define GIT_PATH_ICONV_INIT { (iconv_t)-1, GIT_BUF_INIT }
extern int git_path_iconv_init_precompose(git_path_iconv_t *ic);
extern void git_path_iconv_clear(git_path_iconv_t *ic);
extern int git_path_iconv(git_path_iconv_t *ic, const char **in, size_t *inlen);
#endif
extern bool git_path_does_fs_decompose_unicode(const char *root);
typedef struct git_path_diriter git_path_diriter;
#if defined(GIT_WIN32) && !defined(__MINGW32__)
struct git_path_diriter
{
git_win32_path path;
size_t parent_len;
git_buf path_utf8;
size_t parent_utf8_len;
HANDLE handle;
unsigned int flags;
WIN32_FIND_DATAW current;
unsigned int needs_next;
};
#define GIT_PATH_DIRITER_INIT { {0}, 0, GIT_BUF_INIT, 0, INVALID_HANDLE_VALUE }
#else
struct git_path_diriter
{
git_buf path;
size_t parent_len;
unsigned int flags;
DIR *dir;
#ifdef GIT_USE_ICONV
git_path_iconv_t ic;
#endif
};
#define GIT_PATH_DIRITER_INIT { GIT_BUF_INIT }
#endif
extern int git_path_diriter_init(
git_path_diriter *diriter,
const char *path,
unsigned int flags);
extern int git_path_diriter_next(git_path_diriter *diriter);
extern int git_path_diriter_filename(
const char **out,
size_t *out_len,
git_path_diriter *diriter);
extern int git_path_diriter_fullpath(
const char **out,
size_t *out_len,
git_path_diriter *diriter);
extern int git_path_diriter_stat(struct stat *out, git_path_diriter *diriter);
extern void git_path_diriter_free(git_path_diriter *diriter);
extern int git_path_dirload(
git_vector *contents,
const char *path,
size_t prefix_len,
uint32_t flags);
extern bool git_path_is_local_file_url(const char *file_url);
extern int git_path_from_url_or_path(git_buf *local_path_out, const char *url_or_path);
#define GIT_PATH_REJECT_TRAVERSAL (1 << 0)
#define GIT_PATH_REJECT_DOT_GIT (1 << 1)
#define GIT_PATH_REJECT_SLASH (1 << 2)
#define GIT_PATH_REJECT_BACKSLASH (1 << 3)
#define GIT_PATH_REJECT_TRAILING_DOT (1 << 4)
#define GIT_PATH_REJECT_TRAILING_SPACE (1 << 5)
#define GIT_PATH_REJECT_TRAILING_COLON (1 << 6)
#define GIT_PATH_REJECT_DOS_PATHS (1 << 7)
#define GIT_PATH_REJECT_NT_CHARS (1 << 8)
#define GIT_PATH_REJECT_DOT_GIT_LITERAL (1 << 9)
#define GIT_PATH_REJECT_DOT_GIT_HFS (1 << 10)
#define GIT_PATH_REJECT_DOT_GIT_NTFS (1 << 11)
#ifdef GIT_WIN32
# define GIT_PATH_REJECT_FILESYSTEM_DEFAULTS \
GIT_PATH_REJECT_TRAVERSAL | \
GIT_PATH_REJECT_BACKSLASH | \
GIT_PATH_REJECT_TRAILING_DOT | \
GIT_PATH_REJECT_TRAILING_SPACE | \
GIT_PATH_REJECT_TRAILING_COLON | \
GIT_PATH_REJECT_DOS_PATHS | \
GIT_PATH_REJECT_NT_CHARS
#else
# define GIT_PATH_REJECT_FILESYSTEM_DEFAULTS \
GIT_PATH_REJECT_TRAVERSAL
#endif
#define GIT_PATH_REJECT_WORKDIR_DEFAULTS \
GIT_PATH_REJECT_FILESYSTEM_DEFAULTS | GIT_PATH_REJECT_DOT_GIT
#define GIT_PATH_REJECT_INDEX_DEFAULTS \
GIT_PATH_REJECT_TRAVERSAL | GIT_PATH_REJECT_DOT_GIT
extern bool git_path_isvalid(
git_repository *repo,
const char *path,
uint16_t mode,
unsigned int flags);
int git_path_normalize_slashes(git_buf *out, const char *path);
#endif