VirtualBox

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

Last change on this file since 73531 was 71888, checked in by vboxsync, 7 years ago

RTDirRelPathQueryInfo/nt: Optimization for empty relative path.

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