VirtualBox

source: vbox/trunk/src/VBox/Runtime/r3/posix/symlink-posix.cpp@ 76878

Last change on this file since 76878 was 76553, checked in by vboxsync, 6 years ago

scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.1 KB
Line 
1/* $Id: symlink-posix.cpp 76553 2019-01-01 01:45:53Z vboxsync $ */
2/** @file
3 * IPRT - Symbolic Links, POSIX.
4 */
5
6/*
7 * Copyright (C) 2010-2019 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*********************************************************************************************************************************
29* Header Files *
30*********************************************************************************************************************************/
31#define LOG_GROUP RTLOGGROUP_SYMLINK
32
33#include <errno.h>
34#include <sys/stat.h>
35#include <unistd.h>
36
37#include <iprt/symlink.h>
38
39#include <iprt/assert.h>
40#include <iprt/err.h>
41#include <iprt/log.h>
42#include <iprt/mem.h>
43#include <iprt/string.h>
44#include "internal/path.h"
45
46
47
48RTDECL(bool) RTSymlinkExists(const char *pszSymlink)
49{
50 bool fRc = false;
51 char const *pszNativeSymlink;
52 int rc = rtPathToNative(&pszNativeSymlink, pszSymlink, NULL);
53 if (RT_SUCCESS(rc))
54 {
55 struct stat s;
56 fRc = !lstat(pszNativeSymlink, &s)
57 && S_ISLNK(s.st_mode);
58
59 rtPathFreeNative(pszNativeSymlink, pszSymlink);
60 }
61
62 LogFlow(("RTSymlinkExists(%p={%s}): returns %RTbool\n", pszSymlink, pszSymlink, fRc));
63 return fRc;
64}
65
66
67RTDECL(bool) RTSymlinkIsDangling(const char *pszSymlink)
68{
69 bool fRc = false;
70 char const *pszNativeSymlink;
71 int rc = rtPathToNative(&pszNativeSymlink, pszSymlink, NULL);
72 if (RT_SUCCESS(rc))
73 {
74 struct stat s;
75 fRc = !lstat(pszNativeSymlink, &s)
76 && S_ISLNK(s.st_mode);
77 if (fRc)
78 {
79 errno = 0;
80 fRc = stat(pszNativeSymlink, &s) != 0
81 && ( errno == ENOENT
82 || errno == ENOTDIR
83 || errno == ELOOP);
84 }
85
86 rtPathFreeNative(pszNativeSymlink, pszSymlink);
87 }
88
89 LogFlow(("RTSymlinkIsDangling(%p={%s}): returns %RTbool\n", pszSymlink, pszSymlink, fRc));
90 return fRc;
91}
92
93
94RTDECL(int) RTSymlinkCreate(const char *pszSymlink, const char *pszTarget, RTSYMLINKTYPE enmType, uint32_t fCreate)
95{
96 RT_NOREF_PV(fCreate);
97
98 /*
99 * Validate the input.
100 */
101 AssertReturn(enmType > RTSYMLINKTYPE_INVALID && enmType < RTSYMLINKTYPE_END, VERR_INVALID_PARAMETER);
102 AssertPtrReturn(pszSymlink, VERR_INVALID_POINTER);
103 AssertPtrReturn(pszTarget, VERR_INVALID_POINTER);
104
105 /*
106 * Convert the paths.
107 */
108 char const *pszNativeSymlink;
109 int rc = rtPathToNative(&pszNativeSymlink, pszSymlink, NULL);
110 if (RT_SUCCESS(rc))
111 {
112 const char *pszNativeTarget;
113 rc = rtPathToNative(&pszNativeTarget, pszTarget, NULL);
114 if (RT_SUCCESS(rc))
115 {
116 /*
117 * Create the link.
118 */
119 if (symlink(pszNativeTarget, pszNativeSymlink) == 0)
120 rc = VINF_SUCCESS;
121 else
122 rc = RTErrConvertFromErrno(errno);
123
124 rtPathFreeNative(pszNativeTarget, pszTarget);
125 }
126 rtPathFreeNative(pszNativeSymlink, pszSymlink);
127 }
128
129 LogFlow(("RTSymlinkCreate(%p={%s}, %p={%s}, %d, %#x): returns %Rrc\n", pszSymlink, pszSymlink, pszTarget, pszTarget, enmType, fCreate, rc));
130 return rc;
131}
132
133
134RTDECL(int) RTSymlinkDelete(const char *pszSymlink, uint32_t fDelete)
135{
136 RT_NOREF_PV(fDelete);
137
138 char const *pszNativeSymlink;
139 int rc = rtPathToNative(&pszNativeSymlink, pszSymlink, NULL);
140 if (RT_SUCCESS(rc))
141 {
142 struct stat s;
143 if (!lstat(pszNativeSymlink, &s))
144 {
145 if (S_ISLNK(s.st_mode))
146 {
147 if (unlink(pszNativeSymlink) == 0)
148 rc = VINF_SUCCESS;
149 else
150 rc = RTErrConvertFromErrno(errno);
151 }
152 else
153 rc = VERR_NOT_SYMLINK;
154 }
155 else
156 rc = RTErrConvertFromErrno(errno);
157 rtPathFreeNative(pszNativeSymlink, pszSymlink);
158 }
159
160 LogFlow(("RTSymlinkDelete(%p={%s}, #%x): returns %Rrc\n", pszSymlink, pszSymlink, fDelete, rc));
161 return rc;
162}
163
164
165RTDECL(int) RTSymlinkRead(const char *pszSymlink, char *pszTarget, size_t cbTarget, uint32_t fRead)
166{
167 RT_NOREF_PV(fRead);
168
169 char *pszMyTarget;
170 int rc = RTSymlinkReadA(pszSymlink, &pszMyTarget);
171 if (RT_SUCCESS(rc))
172 {
173 rc = RTStrCopy(pszTarget, cbTarget, pszMyTarget);
174 RTStrFree(pszMyTarget);
175 }
176 LogFlow(("RTSymlinkRead(%p={%s}): returns %Rrc\n", pszSymlink, pszSymlink, rc));
177 return rc;
178}
179
180
181RTDECL(int) RTSymlinkReadA(const char *pszSymlink, char **ppszTarget)
182{
183 AssertPtr(ppszTarget);
184 char const *pszNativeSymlink;
185 int rc = rtPathToNative(&pszNativeSymlink, pszSymlink, NULL);
186 if (RT_SUCCESS(rc))
187 {
188 /* Guess the initial buffer size. */
189 ssize_t cbBuf;
190 struct stat s;
191 if (!lstat(pszNativeSymlink, &s))
192 cbBuf = RT_MAX(RT_ALIGN_Z(s.st_size, 64), 64);
193 else
194 cbBuf = 1024;
195
196 /* Read loop that grows the buffer. */
197 char *pszBuf = NULL;
198 for (;;)
199 {
200 RTMemTmpFree(pszBuf);
201 pszBuf = (char *)RTMemTmpAlloc(cbBuf);
202 if (pszBuf)
203 {
204 ssize_t cbReturned = readlink(pszNativeSymlink, pszBuf, cbBuf);
205 if (cbReturned >= cbBuf)
206 {
207 /* Increase the buffer size and try again */
208 cbBuf *= 2;
209 continue;
210 }
211
212 if (cbReturned > 0)
213 {
214 pszBuf[cbReturned] = '\0';
215 rc = rtPathFromNativeDup(ppszTarget, pszBuf, pszSymlink);
216 }
217 else if (errno == EINVAL)
218 rc = VERR_NOT_SYMLINK;
219 else
220 rc = RTErrConvertFromErrno(errno);
221 }
222 else
223 rc = VERR_NO_TMP_MEMORY;
224 break;
225 } /* for loop */
226
227 RTMemTmpFree(pszBuf);
228 rtPathFreeNative(pszNativeSymlink, pszSymlink);
229 }
230
231 if (RT_SUCCESS(rc))
232 LogFlow(("RTSymlinkReadA(%p={%s},%p): returns %Rrc *ppszTarget=%p:{%s}\n", pszSymlink, pszSymlink, ppszTarget, rc, *ppszTarget, *ppszTarget));
233 else
234 LogFlow(("RTSymlinkReadA(%p={%s},%p): returns %Rrc\n", pszSymlink, pszSymlink, ppszTarget, rc));
235 return rc;
236}
237
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette