VirtualBox

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

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