1/*
2 * Copyright 2002-2013, Axel D��rfler, axeld@pinc-software.de.
3 * Distributed under the terms of the MIT License.
4 */
5
6
7#include <errno.h>
8#include <unistd.h>
9
10#include <errno_private.h>
11#include <syscalls.h>
12#include <syscall_utils.h>
13
14
15ssize_t
16readlink(const char *path, char *buffer, size_t bufferSize)
17{
18	return readlinkat(AT_FDCWD, path, buffer, bufferSize);
19}
20
21
22ssize_t
23readlinkat(int fd, const char *path, char *buffer, size_t bufferSize)
24{
25	size_t linkLen = bufferSize;
26	status_t status = _kern_read_link(fd, path, buffer, &linkLen);
27	if (status < B_OK) {
28		__set_errno(status);
29		return -1;
30	}
31
32	// If the buffer is big enough, null-terminate the string. That's not
33	// required by the standard, but helps non-conforming apps.
34	if (linkLen < bufferSize)
35		buffer[linkLen] = '\0';
36
37	// _kern_read_link() returns the length of the link, but readlinkat() is
38	// supposed to return the number of bytes placed into buffer. If the
39	// buffer is larger than the link contents, then linkLen is the number
40	// of bytes written to the buffer. Otherwise, bufferSize bytes will have
41	// been written.
42	return min_c(linkLen, bufferSize);
43}
44
45
46int
47symlink(const char *toPath, const char *symlinkPath)
48{
49	int status = _kern_create_symlink(-1, symlinkPath, toPath, 0);
50
51	RETURN_AND_SET_ERRNO(status);
52}
53
54
55int
56symlinkat(const char *toPath, int fd, const char *symlinkPath)
57{
58	RETURN_AND_SET_ERRNO(_kern_create_symlink(fd, symlinkPath, toPath, 0));
59}
60
61
62int
63unlink(const char *path)
64{
65	int status = _kern_unlink(-1, path);
66
67	RETURN_AND_SET_ERRNO(status);
68}
69
70
71int
72unlinkat(int fd, const char *path, int flag)
73{
74	if ((flag & AT_REMOVEDIR) != 0)
75		RETURN_AND_SET_ERRNO(_kern_remove_dir(fd, path));
76	else
77		RETURN_AND_SET_ERRNO(_kern_unlink(fd, path));
78}
79
80
81int
82link(const char *toPath, const char *linkPath)
83{
84	int status = _kern_create_link(-1, linkPath, -1, toPath, true);
85	// Haiku -> POSIX error mapping
86	if (status == B_UNSUPPORTED)
87		status = EPERM;
88
89	RETURN_AND_SET_ERRNO(status);
90}
91
92
93int
94linkat(int toFD, const char *toPath, int linkFD, const char *linkPath, int flag)
95{
96	RETURN_AND_SET_ERRNO(_kern_create_link(linkFD, linkPath, toFD, toPath,
97		(flag & AT_SYMLINK_FOLLOW) != 0));
98}
99
100