VirtualBox

source: vbox/trunk/src/VBox/Runtime/r3/nt/dirrel-r3-nt.cpp@ 99122

Last change on this file since 99122 was 98103, checked in by vboxsync, 2 years ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 28.8 KB
Line 
1/* $Id: dirrel-r3-nt.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * IPRT - Directory relative base APIs, NT implementation
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_DIR
42#include <iprt/dir.h>
43#include "internal-r3-nt.h"
44
45#include <iprt/assert.h>
46#include <iprt/file.h>
47#include <iprt/err.h>
48#include <iprt/path.h>
49#include <iprt/string.h>
50#include <iprt/symlink.h>
51#include <iprt/utf16.h>
52#include "internal/dir.h"
53#include "internal/file.h"
54#include "internal/fs.h"
55#include "internal/path.h"
56
57
58/*********************************************************************************************************************************
59* Defined Constants And Macros *
60*********************************************************************************************************************************/
61/** Getst the RTNTPATHRELATIVEASCENT value for RTNtPathRelativeFromUtf8. */
62#define RTDIRREL_NT_GET_ASCENT(a_pThis) \
63 ( !(pThis->fFlags & RTDIR_F_DENY_ASCENT) ? kRTNtPathRelativeAscent_Allow : kRTNtPathRelativeAscent_Fail )
64
65
66
67/**
68 * Helper that builds a full path for a directory relative path.
69 *
70 * @returns IPRT status code.
71 * @param pThis The directory.
72 * @param pszPathDst The destination buffer.
73 * @param cbPathDst The size of the destination buffer.
74 * @param pszRelPath The relative path.
75 */
76static int rtDirRelBuildFullPath(PRTDIRINTERNAL pThis, char *pszPathDst, size_t cbPathDst, const char *pszRelPath)
77{
78 AssertMsgReturn(!RTPathStartsWithRoot(pszRelPath), ("pszRelPath='%s'\n", pszRelPath), VERR_PATH_IS_NOT_RELATIVE);
79
80 /*
81 * Let's hope we can avoid checking for ascension.
82 *
83 * Note! We don't take symbolic links into account here. That can be
84 * done later if desired.
85 */
86 if ( !(pThis->fFlags & RTDIR_F_DENY_ASCENT)
87 || strstr(pszRelPath, "..") == NULL)
88 {
89 size_t const cchRelPath = strlen(pszRelPath);
90 size_t const cchDirPath = pThis->cchPath;
91 if (cchDirPath + cchRelPath < cbPathDst)
92 {
93 memcpy(pszPathDst, pThis->pszPath, cchDirPath);
94 memcpy(&pszPathDst[cchDirPath], pszRelPath, cchRelPath);
95 pszPathDst[cchDirPath + cchRelPath] = '\0';
96 return VINF_SUCCESS;
97 }
98 return VERR_FILENAME_TOO_LONG;
99 }
100
101 /*
102 * Calc the absolute path using the directory as a base, then check if the result
103 * still starts with the full directory path.
104 *
105 * This ASSUMES that pThis->pszPath is an absolute path.
106 */
107 int rc = RTPathAbsEx(pThis->pszPath, pszRelPath, RTPATH_STR_F_STYLE_HOST, pszPathDst, &cbPathDst);
108 if (RT_SUCCESS(rc))
109 {
110 if (RTPathStartsWith(pszPathDst, pThis->pszPath))
111 return VINF_SUCCESS;
112 return VERR_PATH_NOT_FOUND;
113 }
114 return rc;
115}
116
117
118/*
119 *
120 *
121 * RTFile stuff.
122 * RTFile stuff.
123 * RTFile stuff.
124 *
125 *
126 */
127
128
129RTDECL(int) RTDirRelFileOpen(RTDIR hDir, const char *pszRelFilename, uint64_t fOpen, PRTFILE phFile)
130{
131 PRTDIRINTERNAL pThis = hDir;
132 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
133 AssertReturn(pThis->u32Magic == RTDIR_MAGIC, VERR_INVALID_HANDLE);
134
135 /*
136 * Validate and convert flags.
137 */
138 uint32_t fDesiredAccess;
139 uint32_t fObjAttribs;
140 uint32_t fFileAttribs;
141 uint32_t fShareAccess;
142 uint32_t fCreateDisposition;
143 uint32_t fCreateOptions;
144 int rc = rtFileNtValidateAndConvertFlags(fOpen, &fDesiredAccess, &fObjAttribs, &fFileAttribs,
145 &fShareAccess, &fCreateDisposition, &fCreateOptions);
146 if (RT_SUCCESS(rc))
147 {
148 /*
149 * Convert and normalize the path.
150 */
151 UNICODE_STRING NtName;
152 HANDLE hRoot = pThis->hDir;
153 rc = RTNtPathRelativeFromUtf8(&NtName, &hRoot, pszRelFilename, RTDIRREL_NT_GET_ASCENT(pThis),
154 pThis->enmInfoClass == FileMaximumInformation);
155 if (RT_SUCCESS(rc))
156 {
157 HANDLE hFile = RTNT_INVALID_HANDLE_VALUE;
158 IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
159 OBJECT_ATTRIBUTES ObjAttr;
160 InitializeObjectAttributes(&ObjAttr, &NtName, fObjAttribs, hRoot, NULL /*pSecDesc*/);
161
162 NTSTATUS rcNt = NtCreateFile(&hFile,
163 fDesiredAccess,
164 &ObjAttr,
165 &Ios,
166 NULL /* AllocationSize*/,
167 fFileAttribs,
168 fShareAccess,
169 fCreateDisposition,
170 fCreateOptions,
171 NULL /*EaBuffer*/,
172 0 /*EaLength*/);
173 if (NT_SUCCESS(rcNt))
174 {
175 rc = RTFileFromNative(phFile, (uintptr_t)hFile);
176 if (RT_FAILURE(rc))
177 NtClose(hFile);
178 }
179 else
180 rc = RTErrConvertFromNtStatus(rcNt);
181 RTNtPathFree(&NtName, NULL);
182 }
183 }
184 return rc;
185}
186
187
188
189/*
190 *
191 *
192 * RTDir stuff.
193 * RTDir stuff.
194 * RTDir stuff.
195 *
196 *
197 */
198
199
200/**
201 * Helper for cooking up a path string for rtDirOpenRelativeOrHandle.
202 *
203 * @returns IPRT status code.
204 * @param pszDst The destination buffer.
205 * @param cbDst The size of the destination buffer.
206 * @param pThis The directory this is relative to.
207 * @param pNtPath The NT path with a possibly relative path.
208 * @param fRelative Whether @a pNtPath is relative or not.
209 * @param pszPath The input path.
210 */
211static int rtDirRelJoinPathForDirOpen(char *pszDst, size_t cbDst, PRTDIRINTERNAL pThis,
212 PUNICODE_STRING pNtPath, bool fRelative, const char *pszPath)
213{
214 int rc;
215 if (fRelative)
216 {
217 size_t cchRel = 0;
218 rc = RTUtf16CalcUtf8LenEx(pNtPath->Buffer, pNtPath->Length / sizeof(RTUTF16), &cchRel);
219 AssertRC(rc);
220 if (RT_SUCCESS(rc))
221 {
222 if (pThis->cchPath + cchRel < cbDst)
223 {
224 size_t cchBase = pThis->cchPath;
225 memcpy(pszDst, pThis->pszPath, cchBase);
226 pszDst += cchBase;
227 cbDst -= cchBase;
228 rc = RTUtf16ToUtf8Ex(pNtPath->Buffer, pNtPath->Length / sizeof(RTUTF16), &pszDst, cbDst, NULL);
229 }
230 else
231 rc = VERR_FILENAME_TOO_LONG;
232 }
233 }
234 else
235 {
236 /** @todo would be better to convert pNtName to DOS/WIN path here,
237 * as it is absolute and doesn't need stuff resolved. */
238 rc = RTPathJoin(pszDst, cbDst, pThis->pszPath, pszPath);
239 }
240 return rc;
241}
242
243RTDECL(int) RTDirRelDirOpen(RTDIR hDir, const char *pszDir, RTDIR *phDir)
244{
245 return RTDirRelDirOpenFiltered(hDir, pszDir, RTDIRFILTER_NONE, 0 /*fFlags*/, phDir);
246}
247
248
249RTDECL(int) RTDirRelDirOpenFiltered(RTDIR hDir, const char *pszDirAndFilter, RTDIRFILTER enmFilter,
250 uint32_t fFlags, RTDIR *phDir)
251{
252 PRTDIRINTERNAL pThis = hDir;
253 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
254 AssertReturn(pThis->u32Magic == RTDIR_MAGIC, VERR_INVALID_HANDLE);
255
256 /*
257 * Convert and normalize the path.
258 */
259 UNICODE_STRING NtName;
260 HANDLE hRoot = pThis->hDir;
261 int rc = RTNtPathRelativeFromUtf8(&NtName, &hRoot, pszDirAndFilter, RTDIRREL_NT_GET_ASCENT(pThis),
262 pThis->enmInfoClass == FileMaximumInformation);
263 if (RT_SUCCESS(rc))
264 {
265 char szAbsDirAndFilter[RTPATH_MAX];
266 rc = rtDirRelJoinPathForDirOpen(szAbsDirAndFilter, sizeof(szAbsDirAndFilter), pThis,
267 &NtName, hRoot != NULL, pszDirAndFilter);
268 if (RT_SUCCESS(rc))
269 {
270 /* Drop the filter from the NT name. */
271 switch (enmFilter)
272 {
273 case RTDIRFILTER_NONE:
274 break;
275 case RTDIRFILTER_WINNT:
276 case RTDIRFILTER_UNIX:
277 case RTDIRFILTER_UNIX_UPCASED:
278 {
279 size_t cwc = NtName.Length / sizeof(RTUTF16);
280 while ( cwc > 0
281 && NtName.Buffer[cwc - 1] != '\\')
282 cwc--;
283 NtName.Buffer[cwc] = '\0';
284 NtName.Length = (uint16_t)(cwc * sizeof(RTUTF16));
285 break;
286 }
287 default:
288 AssertFailedBreak();
289 }
290
291 rc = rtDirOpenRelativeOrHandle(phDir, szAbsDirAndFilter, enmFilter, fFlags, (uintptr_t)hRoot, &NtName);
292 }
293 RTNtPathFree(&NtName, NULL);
294 }
295 return rc;
296}
297
298
299RTDECL(int) RTDirRelDirCreate(RTDIR hDir, const char *pszRelPath, RTFMODE fMode, uint32_t fCreate, RTDIR *phSubDir)
300{
301 PRTDIRINTERNAL pThis = hDir;
302 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
303 AssertReturn(pThis->u32Magic == RTDIR_MAGIC, VERR_INVALID_HANDLE);
304 AssertReturn(!(fCreate & ~RTDIRCREATE_FLAGS_VALID_MASK), VERR_INVALID_FLAGS);
305 fMode = rtFsModeNormalize(fMode, pszRelPath, 0, RTFS_TYPE_DIRECTORY);
306 AssertReturn(rtFsModeIsValidPermissions(fMode), VERR_INVALID_FMODE);
307 AssertPtrNullReturn(phSubDir, VERR_INVALID_POINTER);
308
309 /*
310 * Convert and normalize the path.
311 */
312 UNICODE_STRING NtName;
313 HANDLE hRoot = pThis->hDir;
314 int rc = RTNtPathRelativeFromUtf8(&NtName, &hRoot, pszRelPath, RTDIRREL_NT_GET_ASCENT(pThis),
315 pThis->enmInfoClass == FileMaximumInformation);
316 if (RT_SUCCESS(rc))
317 {
318 HANDLE hNewDir = RTNT_INVALID_HANDLE_VALUE;
319 IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
320 OBJECT_ATTRIBUTES ObjAttr;
321 InitializeObjectAttributes(&ObjAttr, &NtName, 0 /*fAttrib*/, hRoot, NULL);
322
323 ULONG fDirAttribs = (fCreate & RTFS_DOS_MASK_NT) >> RTFS_DOS_SHIFT;
324 if (!(fCreate & RTDIRCREATE_FLAGS_NOT_CONTENT_INDEXED_DONT_SET))
325 fDirAttribs |= FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
326 if (!fDirAttribs)
327 fDirAttribs = FILE_ATTRIBUTE_NORMAL;
328
329 NTSTATUS rcNt = NtCreateFile(&hNewDir,
330 phSubDir
331 ? FILE_WRITE_ATTRIBUTES | FILE_READ_ATTRIBUTES | FILE_LIST_DIRECTORY | FILE_TRAVERSE | SYNCHRONIZE
332 : SYNCHRONIZE,
333 &ObjAttr,
334 &Ios,
335 NULL /*AllocationSize*/,
336 fDirAttribs,
337 FILE_SHARE_READ | FILE_SHARE_WRITE,
338 FILE_CREATE,
339 FILE_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT,
340 NULL /*EaBuffer*/,
341 0 /*EaLength*/);
342
343 /* Just in case someone takes offence at FILE_ATTRIBUTE_NOT_CONTENT_INDEXED. */
344 if ( ( rcNt == STATUS_INVALID_PARAMETER
345 || rcNt == STATUS_INVALID_PARAMETER_7)
346 && (fDirAttribs & FILE_ATTRIBUTE_NOT_CONTENT_INDEXED)
347 && (fCreate & RTDIRCREATE_FLAGS_NOT_CONTENT_INDEXED_NOT_CRITICAL) )
348 {
349 fDirAttribs &= ~FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
350 if (!fDirAttribs)
351 fDirAttribs = FILE_ATTRIBUTE_NORMAL;
352 rcNt = NtCreateFile(&hNewDir,
353 phSubDir
354 ? FILE_WRITE_ATTRIBUTES | FILE_READ_ATTRIBUTES | FILE_LIST_DIRECTORY | FILE_TRAVERSE | SYNCHRONIZE
355 : SYNCHRONIZE,
356 &ObjAttr,
357 &Ios,
358 NULL /*AllocationSize*/,
359 fDirAttribs,
360 FILE_SHARE_READ | FILE_SHARE_WRITE,
361 FILE_CREATE,
362 FILE_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT,
363 NULL /*EaBuffer*/,
364 0 /*EaLength*/);
365 }
366
367 if (NT_SUCCESS(rcNt))
368 {
369 if (!phSubDir)
370 {
371 NtClose(hNewDir);
372 rc = VINF_SUCCESS;
373 }
374 else
375 {
376 char szAbsDirAndFilter[RTPATH_MAX];
377 rc = rtDirRelJoinPathForDirOpen(szAbsDirAndFilter, sizeof(szAbsDirAndFilter), pThis,
378 &NtName, hRoot != NULL, pszRelPath);
379 if (RT_SUCCESS(rc))
380 rc = rtDirOpenRelativeOrHandle(phSubDir, pszRelPath, RTDIRFILTER_NONE, 0 /*fFlags*/,
381 (uintptr_t)hNewDir, NULL /*pvNativeRelative*/);
382 if (RT_FAILURE(rc))
383 NtClose(hNewDir);
384 }
385 }
386 else
387 rc = RTErrConvertFromNtStatus(rcNt);
388 RTNtPathFree(&NtName, NULL);
389 }
390 return rc;
391}
392
393
394RTDECL(int) RTDirRelDirRemove(RTDIR hDir, const char *pszRelPath)
395{
396 PRTDIRINTERNAL pThis = hDir;
397 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
398 AssertReturn(pThis->u32Magic == RTDIR_MAGIC, VERR_INVALID_HANDLE);
399
400 /*
401 * Convert and normalize the path.
402 */
403 UNICODE_STRING NtName;
404 HANDLE hRoot = pThis->hDir;
405 int rc = RTNtPathRelativeFromUtf8(&NtName, &hRoot, pszRelPath, RTDIRREL_NT_GET_ASCENT(pThis),
406 pThis->enmInfoClass == FileMaximumInformation);
407 if (RT_SUCCESS(rc))
408 {
409 HANDLE hSubDir = RTNT_INVALID_HANDLE_VALUE;
410 IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
411 OBJECT_ATTRIBUTES ObjAttr;
412 InitializeObjectAttributes(&ObjAttr, &NtName, 0 /*fAttrib*/, hRoot, NULL);
413
414 NTSTATUS rcNt = NtCreateFile(&hSubDir,
415 DELETE | SYNCHRONIZE,
416 &ObjAttr,
417 &Ios,
418 NULL /*AllocationSize*/,
419 FILE_ATTRIBUTE_NORMAL,
420 FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
421 FILE_OPEN,
422 FILE_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_REPARSE_POINT,
423 NULL /*EaBuffer*/,
424 0 /*EaLength*/);
425 if (NT_SUCCESS(rcNt))
426 {
427 FILE_DISPOSITION_INFORMATION DispInfo;
428 DispInfo.DeleteFile = TRUE;
429 RTNT_IO_STATUS_BLOCK_REINIT(&Ios);
430 rcNt = NtSetInformationFile(hSubDir, &Ios, &DispInfo, sizeof(DispInfo), FileDispositionInformation);
431
432 NTSTATUS rcNt2 = NtClose(hSubDir);
433 if (!NT_SUCCESS(rcNt2) && NT_SUCCESS(rcNt))
434 rcNt = rcNt2;
435 }
436
437 if (NT_SUCCESS(rcNt))
438 rc = VINF_SUCCESS;
439 else
440 rc = RTErrConvertFromNtStatus(rcNt);
441
442 RTNtPathFree(&NtName, NULL);
443 }
444 return rc;
445}
446
447
448/*
449 *
450 * RTPath stuff.
451 * RTPath stuff.
452 * RTPath stuff.
453 *
454 *
455 */
456
457
458RTDECL(int) RTDirRelPathQueryInfo(RTDIR hDir, const char *pszRelPath, PRTFSOBJINFO pObjInfo,
459 RTFSOBJATTRADD enmAddAttr, uint32_t fFlags)
460{
461 PRTDIRINTERNAL pThis = hDir;
462 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
463 AssertReturn(pThis->u32Magic == RTDIR_MAGIC, VERR_INVALID_HANDLE);
464
465 /*
466 * Validate and convert flags.
467 */
468 UNICODE_STRING NtName;
469 HANDLE hRoot = pThis->hDir;
470 int rc = RTNtPathRelativeFromUtf8(&NtName, &hRoot, pszRelPath, RTDIRREL_NT_GET_ASCENT(pThis),
471 pThis->enmInfoClass == FileMaximumInformation);
472 if (RT_SUCCESS(rc))
473 {
474 if (NtName.Length != 0 || hRoot == NULL)
475 rc = rtPathNtQueryInfoWorker(hRoot, &NtName, pObjInfo, enmAddAttr, fFlags, pszRelPath);
476 else
477 rc = RTDirQueryInfo(hDir, pObjInfo, enmAddAttr);
478 RTNtPathFree(&NtName, NULL);
479 }
480 return rc;
481}
482
483
484/**
485 * Changes the mode flags of a file system object relative to @a hDir.
486 *
487 * The API requires at least one of the mode flag sets (Unix/Dos) to
488 * be set. The type is ignored.
489 *
490 * @returns IPRT status code.
491 * @param hDir The directory @a pszRelPath is relative to.
492 * @param pszRelPath The relative path to the file system object.
493 * @param fMode The new file mode, see @ref grp_rt_fs for details.
494 * @param fFlags RTPATH_F_ON_LINK or RTPATH_F_FOLLOW_LINK.
495 *
496 * @sa RTPathSetMode
497 */
498RTDECL(int) RTDirRelPathSetMode(RTDIR hDir, const char *pszRelPath, RTFMODE fMode, uint32_t fFlags)
499{
500 PRTDIRINTERNAL pThis = hDir;
501 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
502 AssertReturn(pThis->u32Magic == RTDIR_MAGIC, VERR_INVALID_HANDLE);
503 fMode = rtFsModeNormalize(fMode, pszRelPath, 0, 0);
504 AssertReturn(rtFsModeIsValidPermissions(fMode), VERR_INVALID_FMODE);
505 AssertMsgReturn(RTPATH_F_IS_VALID(fFlags, 0), ("%#x\n", fFlags), VERR_INVALID_FLAGS);
506
507 /*
508 * Convert and normalize the path.
509 */
510 UNICODE_STRING NtName;
511 HANDLE hRoot = pThis->hDir;
512 int rc = RTNtPathRelativeFromUtf8(&NtName, &hRoot, pszRelPath, RTDIRREL_NT_GET_ASCENT(pThis),
513 pThis->enmInfoClass == FileMaximumInformation);
514 if (RT_SUCCESS(rc))
515 {
516 HANDLE hSubDir = RTNT_INVALID_HANDLE_VALUE;
517 IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
518 OBJECT_ATTRIBUTES ObjAttr;
519 InitializeObjectAttributes(&ObjAttr, &NtName, 0 /*fAttrib*/, hRoot, NULL);
520
521 ULONG fOpenOptions = FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_REPARSE_POINT;
522 if (fFlags & RTPATH_F_ON_LINK)
523 fOpenOptions |= FILE_OPEN_REPARSE_POINT;
524 NTSTATUS rcNt = NtCreateFile(&hSubDir,
525 FILE_WRITE_ATTRIBUTES | SYNCHRONIZE,
526 &ObjAttr,
527 &Ios,
528 NULL /*AllocationSize*/,
529 FILE_ATTRIBUTE_NORMAL,
530 FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
531 FILE_OPEN,
532 fOpenOptions,
533 NULL /*EaBuffer*/,
534 0 /*EaLength*/);
535 if (NT_SUCCESS(rcNt))
536 {
537 rc = rtNtFileSetModeWorker(hSubDir, fMode);
538
539 rcNt = NtClose(hSubDir);
540 if (!NT_SUCCESS(rcNt) && RT_SUCCESS(rc))
541 rc = RTErrConvertFromNtStatus(rcNt);
542 }
543 else
544 rc = RTErrConvertFromNtStatus(rcNt);
545
546 RTNtPathFree(&NtName, NULL);
547 }
548 return rc;
549}
550
551
552/**
553 * Changes one or more of the timestamps associated of file system object
554 * relative to @a hDir.
555 *
556 * @returns IPRT status code.
557 * @param hDir The directory @a pszRelPath is relative to.
558 * @param pszRelPath The relative path to the file system object.
559 * @param pAccessTime Pointer to the new access time.
560 * @param pModificationTime Pointer to the new modification time.
561 * @param pChangeTime Pointer to the new change time. NULL if not to be changed.
562 * @param pBirthTime Pointer to the new time of birth. NULL if not to be changed.
563 * @param fFlags RTPATH_F_ON_LINK or RTPATH_F_FOLLOW_LINK.
564 *
565 * @remark The file system might not implement all these time attributes,
566 * the API will ignore the ones which aren't supported.
567 *
568 * @remark The file system might not implement the time resolution
569 * employed by this interface, the time will be chopped to fit.
570 *
571 * @remark The file system may update the change time even if it's
572 * not specified.
573 *
574 * @remark POSIX can only set Access & Modification and will always set both.
575 *
576 * @sa RTPathSetTimesEx
577 */
578RTDECL(int) RTDirRelPathSetTimes(RTDIR hDir, const char *pszRelPath, PCRTTIMESPEC pAccessTime, PCRTTIMESPEC pModificationTime,
579 PCRTTIMESPEC pChangeTime, PCRTTIMESPEC pBirthTime, uint32_t fFlags)
580{
581 PRTDIRINTERNAL pThis = hDir;
582 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
583 AssertReturn(pThis->u32Magic == RTDIR_MAGIC, VERR_INVALID_HANDLE);
584
585 char szPath[RTPATH_MAX];
586 int rc = rtDirRelBuildFullPath(pThis, szPath, sizeof(szPath), pszRelPath);
587 if (RT_SUCCESS(rc))
588 {
589RTAssertMsg2("DBG: RTDirRelPathSetTimes(%s)...\n", szPath);
590 rc = RTPathSetTimesEx(szPath, pAccessTime, pModificationTime, pChangeTime, pBirthTime, fFlags);
591 }
592 return rc;
593}
594
595
596/**
597 * Changes the owner and/or group of a file system object relative to @a hDir.
598 *
599 * @returns IPRT status code.
600 * @param hDir The directory @a pszRelPath is relative to.
601 * @param pszRelPath The relative path to the file system object.
602 * @param uid The new file owner user id. Pass NIL_RTUID to leave
603 * this unchanged.
604 * @param gid The new group id. Pass NIL_RTGID to leave this
605 * unchanged.
606 * @param fFlags RTPATH_F_ON_LINK or RTPATH_F_FOLLOW_LINK.
607 *
608 * @sa RTPathSetOwnerEx
609 */
610RTDECL(int) RTDirRelPathSetOwner(RTDIR hDir, const char *pszRelPath, uint32_t uid, uint32_t gid, uint32_t fFlags)
611{
612 PRTDIRINTERNAL pThis = hDir;
613 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
614 AssertReturn(pThis->u32Magic == RTDIR_MAGIC, VERR_INVALID_HANDLE);
615
616 char szPath[RTPATH_MAX];
617 int rc = rtDirRelBuildFullPath(pThis, szPath, sizeof(szPath), pszRelPath);
618 if (RT_SUCCESS(rc))
619 {
620RTAssertMsg2("DBG: RTDirRelPathSetOwner(%s)...\n", szPath);
621#ifndef RT_OS_WINDOWS
622 rc = RTPathSetOwnerEx(szPath, uid, gid, fFlags);
623#else
624 rc = VERR_NOT_IMPLEMENTED;
625 RT_NOREF(uid, gid, fFlags);
626#endif
627 }
628 return rc;
629}
630
631
632/**
633 * Renames a directory relative path within a filesystem.
634 *
635 * This will rename symbolic links. If RTPATHRENAME_FLAGS_REPLACE is used and
636 * pszDst is a symbolic link, it will be replaced and not its target.
637 *
638 * @returns IPRT status code.
639 * @param hDirSrc The directory the source path is relative to.
640 * @param pszSrc The source path, relative to @a hDirSrc.
641 * @param hDirSrc The directory the destination path is relative to.
642 * @param pszDst The destination path, relative to @a hDirDst.
643 * @param fRename Rename flags, RTPATHRENAME_FLAGS_XXX.
644 *
645 * @sa RTPathRename
646 */
647RTDECL(int) RTDirRelPathRename(RTDIR hDirSrc, const char *pszSrc, RTDIR hDirDst, const char *pszDst, unsigned fRename)
648{
649 PRTDIRINTERNAL pThis = hDirSrc;
650 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
651 AssertReturn(pThis->u32Magic == RTDIR_MAGIC, VERR_INVALID_HANDLE);
652
653 PRTDIRINTERNAL pThat = hDirDst;
654 if (pThat != pThis)
655 {
656 AssertPtrReturn(pThat, VERR_INVALID_HANDLE);
657 AssertReturn(pThat->u32Magic != RTDIR_MAGIC, VERR_INVALID_HANDLE);
658 }
659
660 char szSrcPath[RTPATH_MAX];
661 int rc = rtDirRelBuildFullPath(pThis, szSrcPath, sizeof(szSrcPath), pszSrc);
662 if (RT_SUCCESS(rc))
663 {
664 char szDstPath[RTPATH_MAX];
665 rc = rtDirRelBuildFullPath(pThis, szDstPath, sizeof(szDstPath), pszDst);
666 if (RT_SUCCESS(rc))
667 {
668RTAssertMsg2("DBG: RTDirRelPathRename(%s,%s)...\n", szSrcPath, szDstPath);
669 rc = RTPathRename(szSrcPath, szDstPath, fRename);
670 }
671 }
672 return rc;
673}
674
675
676/**
677 * Removes the last component of the directory relative path.
678 *
679 * @returns IPRT status code.
680 * @param hDir The directory @a pszRelPath is relative to.
681 * @param pszRelPath The relative path to the file system object.
682 * @param fUnlink Unlink flags, RTPATHUNLINK_FLAGS_XXX.
683 *
684 * @sa RTPathUnlink
685 */
686RTDECL(int) RTDirRelPathUnlink(RTDIR hDir, const char *pszRelPath, uint32_t fUnlink)
687{
688 PRTDIRINTERNAL pThis = hDir;
689 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
690 AssertReturn(pThis->u32Magic == RTDIR_MAGIC, VERR_INVALID_HANDLE);
691
692 char szPath[RTPATH_MAX];
693 int rc = rtDirRelBuildFullPath(pThis, szPath, sizeof(szPath), pszRelPath);
694 if (RT_SUCCESS(rc))
695 {
696RTAssertMsg2("DBG: RTDirRelPathUnlink(%s)...\n", szPath);
697 rc = RTPathUnlink(szPath, fUnlink);
698 }
699 return rc;
700}
701
702
703/*
704 *
705 * RTSymlink stuff.
706 * RTSymlink stuff.
707 * RTSymlink stuff.
708 *
709 *
710 */
711
712
713/**
714 * Creates a symbolic link (@a pszSymlink) relative to @a hDir targeting @a
715 * pszTarget.
716 *
717 * @returns IPRT status code.
718 * @param hDir The directory @a pszSymlink is relative to.
719 * @param pszSymlink The relative path of the symbolic link.
720 * @param pszTarget The path to the symbolic link target. This is
721 * relative to @a pszSymlink or an absolute path.
722 * @param enmType The symbolic link type. For Windows compatability
723 * it is very important to set this correctly. When
724 * RTSYMLINKTYPE_UNKNOWN is used, the API will try
725 * make a guess and may attempt query information
726 * about @a pszTarget in the process.
727 * @param fCreate Create flags, RTSYMLINKCREATE_FLAGS_XXX.
728 *
729 * @sa RTSymlinkCreate
730 */
731RTDECL(int) RTDirRelSymlinkCreate(RTDIR hDir, const char *pszSymlink, const char *pszTarget,
732 RTSYMLINKTYPE enmType, uint32_t fCreate)
733{
734 PRTDIRINTERNAL pThis = hDir;
735 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
736 AssertReturn(pThis->u32Magic == RTDIR_MAGIC, VERR_INVALID_HANDLE);
737
738 char szPath[RTPATH_MAX];
739 int rc = rtDirRelBuildFullPath(pThis, szPath, sizeof(szPath), pszSymlink);
740 if (RT_SUCCESS(rc))
741 {
742RTAssertMsg2("DBG: RTDirRelSymlinkCreate(%s)...\n", szPath);
743 rc = RTSymlinkCreate(szPath, pszTarget, enmType, fCreate);
744 }
745 return rc;
746}
747
748
749/**
750 * Read the symlink target relative to @a hDir.
751 *
752 * @returns IPRT status code.
753 * @retval VERR_NOT_SYMLINK if @a pszSymlink does not specify a symbolic link.
754 * @retval VERR_BUFFER_OVERFLOW if the link is larger than @a cbTarget. The
755 * buffer will contain what all we managed to read, fully terminated
756 * if @a cbTarget > 0.
757 *
758 * @param hDir The directory @a pszSymlink is relative to.
759 * @param pszSymlink The relative path to the symbolic link that should
760 * be read.
761 * @param pszTarget The target buffer.
762 * @param cbTarget The size of the target buffer.
763 * @param fRead Read flags, RTSYMLINKREAD_FLAGS_XXX.
764 *
765 * @sa RTSymlinkRead
766 */
767RTDECL(int) RTDirRelSymlinkRead(RTDIR hDir, const char *pszSymlink, char *pszTarget, size_t cbTarget, uint32_t fRead)
768{
769 PRTDIRINTERNAL pThis = hDir;
770 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
771 AssertReturn(pThis->u32Magic == RTDIR_MAGIC, VERR_INVALID_HANDLE);
772
773 char szPath[RTPATH_MAX];
774 int rc = rtDirRelBuildFullPath(pThis, szPath, sizeof(szPath), pszSymlink);
775 if (RT_SUCCESS(rc))
776 {
777RTAssertMsg2("DBG: RTDirRelSymlinkRead(%s)...\n", szPath);
778 rc = RTSymlinkRead(szPath, pszTarget, cbTarget, fRead);
779 }
780 return rc;
781}
782
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