VirtualBox

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

Last change on this file since 34079 was 33426, checked in by vboxsync, 14 years ago

iprt/symlink.h: Initial code (only tested on linux).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 6.8 KB
Line 
1/* $Id: symlink-posix.cpp 33426 2010-10-25 14:32:38Z vboxsync $ */
2/** @file
3 * IPRT - Symbolic Links, POSIX.
4 */
5
6/*
7 * Copyright (C) 2010 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)
95{
96 /*
97 * Validate the input.
98 */
99 AssertReturn(enmType > RTSYMLINKTYPE_INVALID && enmType < RTSYMLINKTYPE_END, VERR_INVALID_PARAMETER);
100 AssertPtrReturn(pszSymlink, VERR_INVALID_POINTER);
101 AssertPtrReturn(pszTarget, VERR_INVALID_POINTER);
102
103 /*
104 * Convert the paths.
105 */
106 char const *pszNativeSymlink;
107 int rc = rtPathToNative(&pszNativeSymlink, pszSymlink, NULL);
108 if (RT_SUCCESS(rc))
109 {
110 const char *pszNativeTarget;
111 rc = rtPathToNative(&pszNativeTarget, pszTarget, NULL);
112 if (RT_SUCCESS(rc))
113 {
114 /*
115 * Create the link.
116 */
117 if (symlink(pszNativeTarget, pszNativeSymlink) == 0)
118 rc = VINF_SUCCESS;
119 else
120 rc = RTErrConvertFromErrno(errno);
121
122 rtPathFreeNative(pszNativeTarget, pszTarget);
123 }
124 rtPathFreeNative(pszNativeSymlink, pszSymlink);
125 }
126
127 LogFlow(("RTSymlinkCreate(%p={%s}, %p={%s}, %d): returns %Rrc\n", pszSymlink, pszSymlink, pszTarget, pszTarget, enmType, rc));
128 return rc;
129}
130
131
132RTDECL(int) RTSymlinkDelete(const char *pszSymlink)
133{
134 char const *pszNativeSymlink;
135 int rc = rtPathToNative(&pszNativeSymlink, pszSymlink, NULL);
136 if (RT_SUCCESS(rc))
137 {
138 struct stat s;
139 if (!lstat(pszNativeSymlink, &s))
140 {
141 if (S_ISLNK(s.st_mode))
142 {
143 if (unlink(pszNativeSymlink) == 0)
144 rc = VINF_SUCCESS;
145 else
146 rc = RTErrConvertFromErrno(errno);
147 }
148 else
149 rc = VERR_NOT_SYMLINK;
150 }
151 else
152 rc = RTErrConvertFromErrno(errno);
153 rtPathFreeNative(pszNativeSymlink, pszSymlink);
154 }
155
156 LogFlow(("RTSymlinkDelete(%p={%s}): returns %Rrc\n", pszSymlink, pszSymlink, rc));
157 return rc;
158}
159
160
161RTDECL(int) RTSymlinkRead(const char *pszSymlink, char *pszTarget, size_t cbTarget)
162{
163 char *pszMyTarget;
164 int rc = RTSymlinkReadA(pszSymlink, &pszMyTarget);
165 if (RT_SUCCESS(rc))
166 {
167 rc = RTStrCopy(pszTarget, cbTarget, pszMyTarget);
168 RTStrFree(pszMyTarget);
169 }
170 LogFlow(("RTSymlinkRead(%p={%s}): returns %Rrc\n", pszSymlink, pszSymlink, rc));
171 return rc;
172}
173
174
175RTDECL(int) RTSymlinkReadA(const char *pszSymlink, char **ppszTarget)
176{
177 AssertPtr(ppszTarget);
178 char const *pszNativeSymlink;
179 int rc = rtPathToNative(&pszNativeSymlink, pszSymlink, NULL);
180 if (RT_SUCCESS(rc))
181 {
182 /* Guess the initial buffer size. */
183 ssize_t cbBuf;
184 struct stat s;
185 if (!lstat(pszNativeSymlink, &s))
186 cbBuf = RT_MIN(RT_ALIGN_Z(s.st_size, 64), 64);
187 else
188 cbBuf = 1024;
189
190 /* Read loop that grows the buffer. */
191 char *pszBuf = NULL;
192 for (;;)
193 {
194 RTMemTmpFree(pszBuf);
195 pszBuf = (char *)RTMemTmpAlloc(cbBuf);
196 if (pszBuf)
197 {
198 ssize_t cbReturned = readlink(pszNativeSymlink, pszBuf, cbBuf);
199 if (cbReturned >= cbBuf)
200 {
201 /* Increase the buffer size and try again */
202 cbBuf *= 2;
203 continue;
204 }
205
206 if (cbReturned > 0)
207 {
208 pszBuf[cbReturned] = '\0';
209 rc = rtPathFromNativeDup(ppszTarget, pszBuf, pszSymlink);
210 }
211 else if (errno == EINVAL)
212 rc = VERR_NOT_SYMLINK;
213 else
214 rc = RTErrConvertFromErrno(errno);
215 }
216 else
217 rc = VERR_NO_TMP_MEMORY;
218 break;
219 } /* for loop */
220
221 RTMemTmpFree(pszBuf);
222 rtPathFreeNative(pszNativeSymlink, pszSymlink);
223 }
224
225 if (RT_SUCCESS(rc))
226 LogFlow(("RTSymlinkReadA(%p={%s},%p): returns %Rrc *ppszTarget=%p:{%s}\n", pszSymlink, pszSymlink, ppszTarget, rc, *ppszTarget, *ppszTarget));
227 else
228 LogFlow(("RTSymlinkReadA(%p={%s},%p): returns %Rrc\n", pszSymlink, pszSymlink, ppszTarget, rc));
229 return rc;
230}
231
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