VirtualBox

source: vbox/trunk/src/VBox/Runtime/r3/posix/path2-posix.cpp@ 103795

Last change on this file since 103795 was 98103, checked in by vboxsync, 23 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 11.8 KB
Line 
1/* $Id: path2-posix.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * IPRT - Path Manipulation, POSIX, Part 2 - RTPathQueryInfo.
4 */
5
6/*
7 * Copyright (C) 2006-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * The contents of this file may alternatively be used under the terms
26 * of the Common Development and Distribution License Version 1.0
27 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
28 * in the VirtualBox distribution, in which case the provisions of the
29 * CDDL are applicable instead of those of the GPL.
30 *
31 * You may elect to license modified versions of this file under the
32 * terms and conditions of either the GPL or the CDDL or both.
33 *
34 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
35 */
36
37
38/*********************************************************************************************************************************
39* Header Files *
40*********************************************************************************************************************************/
41#define LOG_GROUP RTLOGGROUP_PATH
42#include <stdlib.h>
43#include <limits.h>
44#include <errno.h>
45#include <unistd.h>
46#include <sys/stat.h>
47#include <sys/time.h>
48#include <stdio.h>
49#include <sys/types.h>
50
51#include <iprt/path.h>
52#include <iprt/env.h>
53#include <iprt/assert.h>
54#include <iprt/string.h>
55#include <iprt/err.h>
56#include <iprt/log.h>
57#include "internal/path.h"
58#include "internal/process.h"
59#include "internal/fs.h"
60
61
62RTR3DECL(int) RTPathQueryInfo(const char *pszPath, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAdditionalAttribs)
63{
64 return RTPathQueryInfoEx(pszPath, pObjInfo, enmAdditionalAttribs, RTPATH_F_ON_LINK);
65}
66
67
68RTR3DECL(int) RTPathQueryInfoEx(const char *pszPath, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAdditionalAttribs, uint32_t fFlags)
69{
70 /*
71 * Validate input.
72 */
73 AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
74 AssertReturn(*pszPath, VERR_INVALID_PARAMETER);
75 AssertPtrReturn(pObjInfo, VERR_INVALID_POINTER);
76 AssertMsgReturn( enmAdditionalAttribs >= RTFSOBJATTRADD_NOTHING
77 && enmAdditionalAttribs <= RTFSOBJATTRADD_LAST,
78 ("Invalid enmAdditionalAttribs=%p\n", enmAdditionalAttribs),
79 VERR_INVALID_PARAMETER);
80 AssertMsgReturn(RTPATH_F_IS_VALID(fFlags, 0), ("%#x\n", fFlags), VERR_INVALID_PARAMETER);
81
82 /*
83 * Convert the filename.
84 */
85 char const *pszNativePath;
86 int rc = rtPathToNative(&pszNativePath, pszPath, NULL);
87 if (RT_SUCCESS(rc))
88 {
89 struct stat Stat;
90 if (fFlags & RTPATH_F_FOLLOW_LINK)
91 rc = stat(pszNativePath, &Stat);
92 else
93 rc = lstat(pszNativePath, &Stat); /** @todo how doesn't have lstat again? */
94 if (!rc)
95 {
96 rtFsConvertStatToObjInfo(pObjInfo, &Stat, pszPath, 0);
97 switch (enmAdditionalAttribs)
98 {
99 case RTFSOBJATTRADD_NOTHING:
100 case RTFSOBJATTRADD_UNIX:
101 Assert(pObjInfo->Attr.enmAdditional == RTFSOBJATTRADD_UNIX);
102 break;
103
104 case RTFSOBJATTRADD_UNIX_OWNER:
105 rtFsObjInfoAttrSetUnixOwner(pObjInfo, Stat.st_uid);
106 break;
107
108 case RTFSOBJATTRADD_UNIX_GROUP:
109 rtFsObjInfoAttrSetUnixGroup(pObjInfo, Stat.st_gid);
110 break;
111
112 case RTFSOBJATTRADD_EASIZE:
113 /** @todo Use SGI extended attribute interface to query EA info. */
114 pObjInfo->Attr.enmAdditional = RTFSOBJATTRADD_EASIZE;
115 pObjInfo->Attr.u.EASize.cb = 0;
116 break;
117
118 default:
119 AssertMsgFailed(("Impossible!\n"));
120 return VERR_INTERNAL_ERROR;
121 }
122 }
123 else
124 rc = RTErrConvertFromErrno(errno);
125 rtPathFreeNative(pszNativePath, pszPath);
126 }
127
128 LogFlow(("RTPathQueryInfoEx(%p:{%s}, pObjInfo=%p, %d): returns %Rrc\n",
129 pszPath, pszPath, pObjInfo, enmAdditionalAttribs, rc));
130 return rc;
131}
132
133
134RTR3DECL(int) RTPathSetTimes(const char *pszPath, PCRTTIMESPEC pAccessTime, PCRTTIMESPEC pModificationTime,
135 PCRTTIMESPEC pChangeTime, PCRTTIMESPEC pBirthTime)
136{
137 return RTPathSetTimesEx(pszPath, pAccessTime, pModificationTime, pChangeTime, pBirthTime, RTPATH_F_ON_LINK);
138}
139
140
141RTR3DECL(int) RTPathSetTimesEx(const char *pszPath, PCRTTIMESPEC pAccessTime, PCRTTIMESPEC pModificationTime,
142 PCRTTIMESPEC pChangeTime, PCRTTIMESPEC pBirthTime, uint32_t fFlags)
143{
144 /*
145 * Validate input.
146 */
147 AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
148 AssertReturn(*pszPath, VERR_INVALID_PARAMETER);
149 AssertPtrNullReturn(pAccessTime, VERR_INVALID_POINTER);
150 AssertPtrNullReturn(pModificationTime, VERR_INVALID_POINTER);
151 AssertPtrNullReturn(pChangeTime, VERR_INVALID_POINTER);
152 AssertPtrNullReturn(pBirthTime, VERR_INVALID_POINTER);
153 AssertMsgReturn(RTPATH_F_IS_VALID(fFlags, 0), ("%#x\n", fFlags), VERR_INVALID_PARAMETER);
154
155 /*
156 * Convert the paths.
157 */
158 char const *pszNativePath;
159 int rc = rtPathToNative(&pszNativePath, pszPath, NULL);
160 if (RT_SUCCESS(rc))
161 {
162 RTFSOBJINFO ObjInfo;
163
164 /*
165 * If it's a no-op, we'll only verify the existance of the file.
166 */
167 if (!pAccessTime && !pModificationTime)
168 rc = RTPathQueryInfoEx(pszPath, &ObjInfo, RTFSOBJATTRADD_NOTHING, fFlags);
169 else
170 {
171 /*
172 * Convert the input to timeval, getting the missing one if necessary,
173 * and call the API which does the change.
174 */
175 struct timeval aTimevals[2];
176 if (pAccessTime && pModificationTime)
177 {
178 RTTimeSpecGetTimeval(pAccessTime, &aTimevals[0]);
179 RTTimeSpecGetTimeval(pModificationTime, &aTimevals[1]);
180 }
181 else
182 {
183 rc = RTPathQueryInfoEx(pszPath, &ObjInfo, RTFSOBJATTRADD_UNIX, fFlags);
184 if (RT_SUCCESS(rc))
185 {
186 RTTimeSpecGetTimeval(pAccessTime ? pAccessTime : &ObjInfo.AccessTime, &aTimevals[0]);
187 RTTimeSpecGetTimeval(pModificationTime ? pModificationTime : &ObjInfo.ModificationTime, &aTimevals[1]);
188 }
189 else
190 Log(("RTPathSetTimes('%s',%p,%p,,): RTPathQueryInfo failed with %Rrc\n",
191 pszPath, pAccessTime, pModificationTime, rc));
192 }
193 if (RT_SUCCESS(rc))
194 {
195 if (fFlags & RTPATH_F_FOLLOW_LINK)
196 {
197 if (utimes(pszNativePath, aTimevals))
198 rc = RTErrConvertFromErrno(errno);
199 }
200#if (defined(RT_OS_DARWIN) && MAC_OS_X_VERSION_MIN_REQUIRED >= 1050) \
201 || defined(RT_OS_FREEBSD) \
202 || defined(RT_OS_LINUX) \
203 || defined(RT_OS_OS2) /** @todo who really has lutimes? */
204 else
205 {
206 if (lutimes(pszNativePath, aTimevals))
207 {
208 /* If lutimes is not supported (e.g. linux < 2.6.22), try fall back on utimes: */
209 if (errno != ENOSYS)
210 rc = RTErrConvertFromErrno(errno);
211 else
212 {
213 if (pAccessTime && pModificationTime)
214 rc = RTPathQueryInfoEx(pszPath, &ObjInfo, RTFSOBJATTRADD_UNIX, fFlags);
215 if (RT_SUCCESS(rc) && !RTFS_IS_SYMLINK(ObjInfo.Attr.fMode))
216 {
217 if (utimes(pszNativePath, aTimevals))
218 rc = RTErrConvertFromErrno(errno);
219 }
220 else
221 rc = VERR_NOT_SUPPORTED;
222 }
223 }
224 }
225#else
226 else
227 {
228 if (pAccessTime && pModificationTime)
229 rc = RTPathQueryInfoEx(pszPath, &ObjInfo, RTFSOBJATTRADD_UNIX, fFlags);
230 if (RT_SUCCESS(rc) && RTFS_IS_SYMLINK(ObjInfo.Attr.fMode))
231 rc = VERR_NS_SYMLINK_SET_TIME;
232 else if (RT_SUCCESS(rc))
233 {
234 if (utimes(pszNativePath, aTimevals))
235 rc = RTErrConvertFromErrno(errno);
236 }
237 }
238#endif
239 if (RT_FAILURE(rc))
240 Log(("RTPathSetTimes('%s',%p,%p,,): failed with %Rrc and errno=%d\n",
241 pszPath, pAccessTime, pModificationTime, rc, errno));
242 }
243 }
244 rtPathFreeNative(pszNativePath, pszPath);
245 }
246
247 LogFlow(("RTPathSetTimes(%p:{%s}, %p:{%RDtimespec}, %p:{%RDtimespec}, %p:{%RDtimespec}, %p:{%RDtimespec}): return %Rrc\n",
248 pszPath, pszPath, pAccessTime, pAccessTime, pModificationTime, pModificationTime,
249 pChangeTime, pChangeTime, pBirthTime, pBirthTime, rc));
250 return rc;
251}
252
253
254RTR3DECL(int) RTPathSetOwner(const char *pszPath, uint32_t uid, uint32_t gid)
255{
256 return RTPathSetOwnerEx(pszPath, uid, gid, RTPATH_F_ON_LINK);
257}
258
259
260RTR3DECL(int) RTPathSetOwnerEx(const char *pszPath, uint32_t uid, uint32_t gid, uint32_t fFlags)
261{
262 /*
263 * Validate input.
264 */
265 AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
266 AssertReturn(*pszPath, VERR_INVALID_PARAMETER);
267 AssertMsgReturn(RTPATH_F_IS_VALID(fFlags, 0), ("%#x\n", fFlags), VERR_INVALID_PARAMETER);
268 uid_t uidNative = uid != NIL_RTUID ? (uid_t)uid : (uid_t)-1;
269 AssertReturn(uid == uidNative, VERR_INVALID_PARAMETER);
270 gid_t gidNative = gid != NIL_RTGID ? (gid_t)gid : (uid_t)-1;
271 AssertReturn(gid == gidNative, VERR_INVALID_PARAMETER);
272
273 /*
274 * Convert the path.
275 */
276 char const *pszNativePath;
277 int rc = rtPathToNative(&pszNativePath, pszPath, NULL);
278 if (RT_SUCCESS(rc))
279 {
280 if (fFlags & RTPATH_F_FOLLOW_LINK)
281 {
282 if (chown(pszNativePath, uidNative, gidNative))
283 rc = RTErrConvertFromErrno(errno);
284 }
285#if 1
286 else
287 {
288 if (lchown(pszNativePath, uidNative, gidNative))
289 rc = RTErrConvertFromErrno(errno);
290 }
291#else
292 else
293 {
294 RTFSOBJINFO ObjInfo;
295 rc = RTPathQueryInfoEx(pszPath, &ObjInfo, RTFSOBJATTRADD_UNIX, fFlags);
296 if (RT_SUCCESS(rc) && RTFS_IS_SYMLINK(ObjInfo.Attr.fMode))
297 rc = VERR_NS_SYMLINK_CHANGE_OWNER;
298 else if (RT_SUCCESS(rc))
299 {
300 if (lchown(pszNativePath, uidNative, gidNative))
301 rc = RTErrConvertFromErrno(errno);
302 }
303 }
304#endif
305 if (RT_FAILURE(rc))
306 Log(("RTPathSetOwnerEx('%s',%d,%d): failed with %Rrc and errno=%d\n",
307 pszPath, uid, gid, rc, errno));
308
309 rtPathFreeNative(pszNativePath, pszPath);
310 }
311
312 LogFlow(("RTPathSetOwnerEx(%p:{%s}, uid=%d, gid=%d): return %Rrc\n",
313 pszPath, pszPath, uid, gid, rc));
314 return rc;
315}
316
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