1 /*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "berberis/kernel_api/unistd_emulation.h"
18
19 #include <fcntl.h> // AT_FDCWD, AT_SYMLINK_NOFOLLOW
20
21 #include <cerrno>
22 #include <cstring> // memcpy
23
24 #include "berberis/kernel_api/main_executable_real_path_emulation.h"
25
26 namespace berberis {
27
ReadLinkAtForGuest(int dirfd,const char * path,char * buf,size_t buf_size)28 ssize_t ReadLinkAtForGuest(int dirfd, const char* path, char* buf, size_t buf_size) {
29 const char* real_path = TryReadLinkToMainExecutableRealPath(path);
30 if (!real_path) {
31 return readlinkat(dirfd, path, buf, buf_size);
32 }
33 // readlink have quite unusual semantic WRT handling of buffer length. readlink should not add
34 // terminating null byte if it doesn't fit in the buffer, so can't use strlcpy. readlink should
35 // return the number of bytes placed in buffer thus strncpy doesn't help.
36 size_t real_path_len = strlen(real_path);
37 if (real_path_len + 1 > buf_size) {
38 memcpy(buf, real_path, buf_size);
39 return buf_size;
40 }
41 memcpy(buf, real_path, real_path_len + 1);
42 return real_path_len;
43 }
44
ReadLinkForGuest(const char * path,char * buf,size_t buf_size)45 ssize_t ReadLinkForGuest(const char* path, char* buf, size_t buf_size) {
46 return ReadLinkAtForGuest(AT_FDCWD, path, buf, buf_size);
47 }
48
49 } // namespace berberis
50