xref: /haiku/src/system/libroot/posix/unistd/link.c (revision cbe0a0c436162d78cc3f92a305b64918c839d079)
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 
15 ssize_t
16 readlink(const char *path, char *buffer, size_t bufferSize)
17 {
18 	return readlinkat(AT_FDCWD, path, buffer, bufferSize);
19 }
20 
21 
22 ssize_t
23 readlinkat(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 
46 int
47 symlink(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 
55 int
56 symlinkat(const char *toPath, int fd, const char *symlinkPath)
57 {
58 	RETURN_AND_SET_ERRNO(_kern_create_symlink(fd, symlinkPath, toPath, 0));
59 }
60 
61 
62 int
63 unlink(const char *path)
64 {
65 	int status = _kern_unlink(-1, path);
66 
67 	RETURN_AND_SET_ERRNO(status);
68 }
69 
70 
71 int
72 unlinkat(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 
81 int
82 link(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 
93 int
94 linkat(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