VirtualBox

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

Last change on this file since 71280 was 69795, checked in by vboxsync, 7 years ago

IPRT: file mode changing on NT + RTChMod command.

  • Reimplemented RTFileSetMode for NT.
  • Implemented RTPathSetMode for NT.
  • Reimplemented RTDirRelPathSetMode for NT.
  • Started on a testcase command: RTChMode
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 25.5 KB
Line 
1/* $Id: dirrel-r3-nt.cpp 69795 2017-11-21 16:29:49Z 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
190RTDECL(int) RTDirRelDirOpen(RTDIR hDir, const char *pszDir, RTDIR *phDir)
191{
192 return RTDirRelDirOpenFiltered(hDir, pszDir, RTDIRFILTER_NONE, 0 /*fFlags*/, phDir);
193}
194
195
196RTDECL(int) RTDirRelDirOpenFiltered(RTDIR hDir, const char *pszDirAndFilter, RTDIRFILTER enmFilter,
197 uint32_t fFlags, RTDIR *phDir)
198{
199 PRTDIRINTERNAL pThis = hDir;
200 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
201 AssertReturn(pThis->u32Magic == RTDIR_MAGIC, VERR_INVALID_HANDLE);
202
203 /*
204 * Convert and normalize the path.
205 */
206 UNICODE_STRING NtName;
207 HANDLE hRoot = pThis->hDir;
208 int rc = RTNtPathRelativeFromUtf8(&NtName, &hRoot, pszDirAndFilter, RTDIRREL_NT_GET_ASCENT(pThis),
209 pThis->enmInfoClass == FileMaximumInformation);
210 if (RT_SUCCESS(rc))
211 {
212 rc = rtDirOpenRelativeOrHandle(phDir, pszDirAndFilter, enmFilter, fFlags, (uintptr_t)hRoot, &NtName);
213 RTNtPathFree(&NtName, NULL);
214 }
215 return rc;
216}
217
218
219RTDECL(int) RTDirRelDirCreate(RTDIR hDir, const char *pszRelPath, RTFMODE fMode, uint32_t fCreate, RTDIR *phSubDir)
220{
221 PRTDIRINTERNAL pThis = hDir;
222 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
223 AssertReturn(pThis->u32Magic == RTDIR_MAGIC, VERR_INVALID_HANDLE);
224 AssertReturn(!(fCreate & ~RTDIRCREATE_FLAGS_VALID_MASK), VERR_INVALID_FLAGS);
225 fMode = rtFsModeNormalize(fMode, pszRelPath, 0);
226 AssertReturn(rtFsModeIsValidPermissions(fMode), VERR_INVALID_FMODE);
227 AssertPtrNullReturn(phSubDir, VERR_INVALID_POINTER);
228
229 /*
230 * Convert and normalize the path.
231 */
232 UNICODE_STRING NtName;
233 HANDLE hRoot = pThis->hDir;
234 int rc = RTNtPathRelativeFromUtf8(&NtName, &hRoot, pszRelPath, RTDIRREL_NT_GET_ASCENT(pThis),
235 pThis->enmInfoClass == FileMaximumInformation);
236 if (RT_SUCCESS(rc))
237 {
238 HANDLE hNewDir = RTNT_INVALID_HANDLE_VALUE;
239 IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
240 OBJECT_ATTRIBUTES ObjAttr;
241 InitializeObjectAttributes(&ObjAttr, &NtName, 0 /*fAttrib*/, hRoot, NULL);
242
243 ULONG fDirAttribs = (fCreate & RTFS_DOS_MASK_NT) >> RTFS_DOS_SHIFT;
244 if (!(fCreate & RTDIRCREATE_FLAGS_NOT_CONTENT_INDEXED_DONT_SET))
245 fDirAttribs |= FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
246 if (!fDirAttribs)
247 fDirAttribs = FILE_ATTRIBUTE_NORMAL;
248
249 NTSTATUS rcNt = NtCreateFile(&hNewDir,
250 phSubDir
251 ? FILE_WRITE_ATTRIBUTES | FILE_READ_ATTRIBUTES | FILE_LIST_DIRECTORY | FILE_TRAVERSE | SYNCHRONIZE
252 : SYNCHRONIZE,
253 &ObjAttr,
254 &Ios,
255 NULL /*AllocationSize*/,
256 fDirAttribs,
257 FILE_SHARE_READ | FILE_SHARE_WRITE,
258 FILE_CREATE,
259 FILE_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT,
260 NULL /*EaBuffer*/,
261 0 /*EaLength*/);
262
263 /* Just in case someone takes offence at FILE_ATTRIBUTE_NOT_CONTENT_INDEXED. */
264 if ( ( rcNt == STATUS_INVALID_PARAMETER
265 || rcNt == STATUS_INVALID_PARAMETER_7)
266 && (fDirAttribs & FILE_ATTRIBUTE_NOT_CONTENT_INDEXED)
267 && (fCreate & RTDIRCREATE_FLAGS_NOT_CONTENT_INDEXED_NOT_CRITICAL) )
268 {
269 fDirAttribs &= ~FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
270 if (!fDirAttribs)
271 fDirAttribs = FILE_ATTRIBUTE_NORMAL;
272 rcNt = NtCreateFile(&hNewDir,
273 phSubDir
274 ? FILE_WRITE_ATTRIBUTES | FILE_READ_ATTRIBUTES | FILE_LIST_DIRECTORY | FILE_TRAVERSE | SYNCHRONIZE
275 : SYNCHRONIZE,
276 &ObjAttr,
277 &Ios,
278 NULL /*AllocationSize*/,
279 fDirAttribs,
280 FILE_SHARE_READ | FILE_SHARE_WRITE,
281 FILE_CREATE,
282 FILE_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT,
283 NULL /*EaBuffer*/,
284 0 /*EaLength*/);
285 }
286
287 if (NT_SUCCESS(rcNt))
288 {
289 if (!phSubDir)
290 {
291 NtClose(hNewDir);
292 rc = VINF_SUCCESS;
293 }
294 else
295 {
296 rc = rtDirOpenRelativeOrHandle(phSubDir, pszRelPath, RTDIRFILTER_NONE, 0 /*fFlags*/,
297 (uintptr_t)hNewDir, NULL /*pvNativeRelative*/);
298 if (RT_FAILURE(rc))
299 NtClose(hNewDir);
300 }
301 }
302 else
303 rc = RTErrConvertFromNtStatus(rcNt);
304 RTNtPathFree(&NtName, NULL);
305 }
306 return rc;
307}
308
309
310RTDECL(int) RTDirRelDirRemove(RTDIR hDir, const char *pszRelPath)
311{
312 PRTDIRINTERNAL pThis = hDir;
313 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
314 AssertReturn(pThis->u32Magic == RTDIR_MAGIC, VERR_INVALID_HANDLE);
315
316 /*
317 * Convert and normalize the path.
318 */
319 UNICODE_STRING NtName;
320 HANDLE hRoot = pThis->hDir;
321 int rc = RTNtPathRelativeFromUtf8(&NtName, &hRoot, pszRelPath, RTDIRREL_NT_GET_ASCENT(pThis),
322 pThis->enmInfoClass == FileMaximumInformation);
323 if (RT_SUCCESS(rc))
324 {
325 HANDLE hSubDir = RTNT_INVALID_HANDLE_VALUE;
326 IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
327 OBJECT_ATTRIBUTES ObjAttr;
328 InitializeObjectAttributes(&ObjAttr, &NtName, 0 /*fAttrib*/, hRoot, NULL);
329
330 NTSTATUS rcNt = NtCreateFile(&hSubDir,
331 DELETE | SYNCHRONIZE,
332 &ObjAttr,
333 &Ios,
334 NULL /*AllocationSize*/,
335 FILE_ATTRIBUTE_NORMAL,
336 FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
337 FILE_OPEN,
338 FILE_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_REPARSE_POINT,
339 NULL /*EaBuffer*/,
340 0 /*EaLength*/);
341 if (NT_SUCCESS(rcNt))
342 {
343 FILE_DISPOSITION_INFORMATION DispInfo;
344 DispInfo.DeleteFile = TRUE;
345 RTNT_IO_STATUS_BLOCK_REINIT(&Ios);
346 rcNt = NtSetInformationFile(hSubDir, &Ios, &DispInfo, sizeof(DispInfo), FileDispositionInformation);
347
348 NTSTATUS rcNt2 = NtClose(hSubDir);
349 if (!NT_SUCCESS(rcNt2) && NT_SUCCESS(rcNt))
350 rcNt = rcNt2;
351 }
352
353 if (NT_SUCCESS(rcNt))
354 rc = VINF_SUCCESS;
355 else
356 rc = RTErrConvertFromNtStatus(rcNt);
357
358 RTNtPathFree(&NtName, NULL);
359 }
360 return rc;
361}
362
363
364/*
365 *
366 * RTPath stuff.
367 * RTPath stuff.
368 * RTPath stuff.
369 *
370 *
371 */
372
373
374RTDECL(int) RTDirRelPathQueryInfo(RTDIR hDir, const char *pszRelPath, PRTFSOBJINFO pObjInfo,
375 RTFSOBJATTRADD enmAddAttr, uint32_t fFlags)
376{
377 PRTDIRINTERNAL pThis = hDir;
378 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
379 AssertReturn(pThis->u32Magic == RTDIR_MAGIC, VERR_INVALID_HANDLE);
380
381 /*
382 * Validate and convert flags.
383 */
384 UNICODE_STRING NtName;
385 HANDLE hRoot = pThis->hDir;
386 int rc = RTNtPathRelativeFromUtf8(&NtName, &hRoot, pszRelPath, RTDIRREL_NT_GET_ASCENT(pThis),
387 pThis->enmInfoClass == FileMaximumInformation);
388 if (RT_SUCCESS(rc))
389 {
390 rc = rtPathNtQueryInfoWorker(hRoot, &NtName, pObjInfo, enmAddAttr, fFlags, pszRelPath);
391 RTNtPathFree(&NtName, NULL);
392 }
393 return rc;
394}
395
396
397/**
398 * Changes the mode flags of a file system object relative to @a hDir.
399 *
400 * The API requires at least one of the mode flag sets (Unix/Dos) to
401 * be set. The type is ignored.
402 *
403 * @returns IPRT status code.
404 * @param hDir The directory @a pszRelPath is relative to.
405 * @param pszRelPath The relative path to the file system object.
406 * @param fMode The new file mode, see @ref grp_rt_fs for details.
407 * @param fFlags RTPATH_F_ON_LINK or RTPATH_F_FOLLOW_LINK.
408 *
409 * @sa RTPathSetMode
410 */
411RTDECL(int) RTDirRelPathSetMode(RTDIR hDir, const char *pszRelPath, RTFMODE fMode, uint32_t fFlags)
412{
413 PRTDIRINTERNAL pThis = hDir;
414 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
415 AssertReturn(pThis->u32Magic == RTDIR_MAGIC, VERR_INVALID_HANDLE);
416 fMode = rtFsModeNormalize(fMode, pszRelPath, 0);
417 AssertReturn(rtFsModeIsValidPermissions(fMode), VERR_INVALID_FMODE);
418 AssertMsgReturn(RTPATH_F_IS_VALID(fFlags, 0), ("%#x\n", fFlags), VERR_INVALID_FLAGS);
419
420 /*
421 * Convert and normalize the path.
422 */
423 UNICODE_STRING NtName;
424 HANDLE hRoot = pThis->hDir;
425 int rc = RTNtPathRelativeFromUtf8(&NtName, &hRoot, pszRelPath, RTDIRREL_NT_GET_ASCENT(pThis),
426 pThis->enmInfoClass == FileMaximumInformation);
427 if (RT_SUCCESS(rc))
428 {
429 HANDLE hSubDir = RTNT_INVALID_HANDLE_VALUE;
430 IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
431 OBJECT_ATTRIBUTES ObjAttr;
432 InitializeObjectAttributes(&ObjAttr, &NtName, 0 /*fAttrib*/, hRoot, NULL);
433
434 ULONG fOpenOptions = FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_REPARSE_POINT;
435 if (fFlags & RTPATH_F_ON_LINK)
436 fOpenOptions |= FILE_OPEN_REPARSE_POINT;
437 NTSTATUS rcNt = NtCreateFile(&hSubDir,
438 FILE_WRITE_ATTRIBUTES | SYNCHRONIZE,
439 &ObjAttr,
440 &Ios,
441 NULL /*AllocationSize*/,
442 FILE_ATTRIBUTE_NORMAL,
443 FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
444 FILE_OPEN,
445 fOpenOptions,
446 NULL /*EaBuffer*/,
447 0 /*EaLength*/);
448 if (NT_SUCCESS(rcNt))
449 {
450 rc = rtNtFileSetModeWorker(hSubDir, fMode);
451
452 rcNt = NtClose(hSubDir);
453 if (!NT_SUCCESS(rcNt) && RT_SUCCESS(rc))
454 rc = RTErrConvertFromNtStatus(rcNt);
455 }
456 else
457 rc = RTErrConvertFromNtStatus(rcNt);
458
459 RTNtPathFree(&NtName, NULL);
460 }
461 return rc;
462}
463
464
465/**
466 * Changes one or more of the timestamps associated of file system object
467 * relative to @a hDir.
468 *
469 * @returns IPRT status code.
470 * @param hDir The directory @a pszRelPath is relative to.
471 * @param pszRelPath The relative path to the file system object.
472 * @param pAccessTime Pointer to the new access time.
473 * @param pModificationTime Pointer to the new modification time.
474 * @param pChangeTime Pointer to the new change time. NULL if not to be changed.
475 * @param pBirthTime Pointer to the new time of birth. NULL if not to be changed.
476 * @param fFlags RTPATH_F_ON_LINK or RTPATH_F_FOLLOW_LINK.
477 *
478 * @remark The file system might not implement all these time attributes,
479 * the API will ignore the ones which aren't supported.
480 *
481 * @remark The file system might not implement the time resolution
482 * employed by this interface, the time will be chopped to fit.
483 *
484 * @remark The file system may update the change time even if it's
485 * not specified.
486 *
487 * @remark POSIX can only set Access & Modification and will always set both.
488 *
489 * @sa RTPathSetTimesEx
490 */
491RTDECL(int) RTDirRelPathSetTimes(RTDIR hDir, const char *pszRelPath, PCRTTIMESPEC pAccessTime, PCRTTIMESPEC pModificationTime,
492 PCRTTIMESPEC pChangeTime, PCRTTIMESPEC pBirthTime, uint32_t fFlags)
493{
494 PRTDIRINTERNAL pThis = hDir;
495 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
496 AssertReturn(pThis->u32Magic == RTDIR_MAGIC, VERR_INVALID_HANDLE);
497
498 char szPath[RTPATH_MAX];
499 int rc = rtDirRelBuildFullPath(pThis, szPath, sizeof(szPath), pszRelPath);
500 if (RT_SUCCESS(rc))
501 {
502RTAssertMsg2("DBG: RTDirRelPathSetTimes(%s)...\n", szPath);
503 rc = RTPathSetTimesEx(szPath, pAccessTime, pModificationTime, pChangeTime, pBirthTime, fFlags);
504 }
505 return rc;
506}
507
508
509/**
510 * Changes the owner and/or group of a file system object relative to @a hDir.
511 *
512 * @returns IPRT status code.
513 * @param hDir The directory @a pszRelPath is relative to.
514 * @param pszRelPath The relative path to the file system object.
515 * @param uid The new file owner user id. Pass NIL_RTUID to leave
516 * this unchanged.
517 * @param gid The new group id. Pass NIL_RTGID to leave this
518 * unchanged.
519 * @param fFlags RTPATH_F_ON_LINK or RTPATH_F_FOLLOW_LINK.
520 *
521 * @sa RTPathSetOwnerEx
522 */
523RTDECL(int) RTDirRelPathSetOwner(RTDIR hDir, const char *pszRelPath, uint32_t uid, uint32_t gid, uint32_t fFlags)
524{
525 PRTDIRINTERNAL pThis = hDir;
526 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
527 AssertReturn(pThis->u32Magic == RTDIR_MAGIC, VERR_INVALID_HANDLE);
528
529 char szPath[RTPATH_MAX];
530 int rc = rtDirRelBuildFullPath(pThis, szPath, sizeof(szPath), pszRelPath);
531 if (RT_SUCCESS(rc))
532 {
533RTAssertMsg2("DBG: RTDirRelPathSetOwner(%s)...\n", szPath);
534#ifndef RT_OS_WINDOWS
535 rc = RTPathSetOwnerEx(szPath, uid, gid, fFlags);
536#else
537 rc = VERR_NOT_IMPLEMENTED;
538 RT_NOREF(uid, gid, fFlags);
539#endif
540 }
541 return rc;
542}
543
544
545/**
546 * Renames a directory relative path within a filesystem.
547 *
548 * This will rename symbolic links. If RTPATHRENAME_FLAGS_REPLACE is used and
549 * pszDst is a symbolic link, it will be replaced and not its target.
550 *
551 * @returns IPRT status code.
552 * @param hDirSrc The directory the source path is relative to.
553 * @param pszSrc The source path, relative to @a hDirSrc.
554 * @param hDirSrc The directory the destination path is relative to.
555 * @param pszDst The destination path, relative to @a hDirDst.
556 * @param fRename Rename flags, RTPATHRENAME_FLAGS_XXX.
557 *
558 * @sa RTPathRename
559 */
560RTDECL(int) RTDirRelPathRename(RTDIR hDirSrc, const char *pszSrc, RTDIR hDirDst, const char *pszDst, unsigned fRename)
561{
562 PRTDIRINTERNAL pThis = hDirSrc;
563 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
564 AssertReturn(pThis->u32Magic == RTDIR_MAGIC, VERR_INVALID_HANDLE);
565
566 PRTDIRINTERNAL pThat = hDirDst;
567 if (pThat != pThis)
568 {
569 AssertPtrReturn(pThat, VERR_INVALID_HANDLE);
570 AssertReturn(pThat->u32Magic != RTDIR_MAGIC, VERR_INVALID_HANDLE);
571 }
572
573 char szSrcPath[RTPATH_MAX];
574 int rc = rtDirRelBuildFullPath(pThis, szSrcPath, sizeof(szSrcPath), pszSrc);
575 if (RT_SUCCESS(rc))
576 {
577 char szDstPath[RTPATH_MAX];
578 rc = rtDirRelBuildFullPath(pThis, szDstPath, sizeof(szDstPath), pszDst);
579 if (RT_SUCCESS(rc))
580 {
581RTAssertMsg2("DBG: RTDirRelPathRename(%s,%s)...\n", szSrcPath, szDstPath);
582 rc = RTPathRename(szSrcPath, szDstPath, fRename);
583 }
584 }
585 return rc;
586}
587
588
589/**
590 * Removes the last component of the directory relative path.
591 *
592 * @returns IPRT status code.
593 * @param hDir The directory @a pszRelPath is relative to.
594 * @param pszRelPath The relative path to the file system object.
595 * @param fUnlink Unlink flags, RTPATHUNLINK_FLAGS_XXX.
596 *
597 * @sa RTPathUnlink
598 */
599RTDECL(int) RTDirRelPathUnlink(RTDIR hDir, const char *pszRelPath, uint32_t fUnlink)
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: RTDirRelPathUnlink(%s)...\n", szPath);
610 rc = RTPathUnlink(szPath, fUnlink);
611 }
612 return rc;
613}
614
615
616/*
617 *
618 * RTSymlink stuff.
619 * RTSymlink stuff.
620 * RTSymlink stuff.
621 *
622 *
623 */
624
625
626/**
627 * Creates a symbolic link (@a pszSymlink) relative to @a hDir targeting @a
628 * pszTarget.
629 *
630 * @returns IPRT status code.
631 * @param hDir The directory @a pszSymlink is relative to.
632 * @param pszSymlink The relative path of the symbolic link.
633 * @param pszTarget The path to the symbolic link target. This is
634 * relative to @a pszSymlink or an absolute path.
635 * @param enmType The symbolic link type. For Windows compatability
636 * it is very important to set this correctly. When
637 * RTSYMLINKTYPE_UNKNOWN is used, the API will try
638 * make a guess and may attempt query information
639 * about @a pszTarget in the process.
640 * @param fCreate Create flags, RTSYMLINKCREATE_FLAGS_XXX.
641 *
642 * @sa RTSymlinkCreate
643 */
644RTDECL(int) RTDirRelSymlinkCreate(RTDIR hDir, const char *pszSymlink, const char *pszTarget,
645 RTSYMLINKTYPE enmType, uint32_t fCreate)
646{
647 PRTDIRINTERNAL pThis = hDir;
648 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
649 AssertReturn(pThis->u32Magic == RTDIR_MAGIC, VERR_INVALID_HANDLE);
650
651 char szPath[RTPATH_MAX];
652 int rc = rtDirRelBuildFullPath(pThis, szPath, sizeof(szPath), pszSymlink);
653 if (RT_SUCCESS(rc))
654 {
655RTAssertMsg2("DBG: RTDirRelSymlinkCreate(%s)...\n", szPath);
656 rc = RTSymlinkCreate(szPath, pszTarget, enmType, fCreate);
657 }
658 return rc;
659}
660
661
662/**
663 * Read the symlink target relative to @a hDir.
664 *
665 * @returns IPRT status code.
666 * @retval VERR_NOT_SYMLINK if @a pszSymlink does not specify a symbolic link.
667 * @retval VERR_BUFFER_OVERFLOW if the link is larger than @a cbTarget. The
668 * buffer will contain what all we managed to read, fully terminated
669 * if @a cbTarget > 0.
670 *
671 * @param hDir The directory @a pszSymlink is relative to.
672 * @param pszSymlink The relative path to the symbolic link that should
673 * be read.
674 * @param pszTarget The target buffer.
675 * @param cbTarget The size of the target buffer.
676 * @param fRead Read flags, RTSYMLINKREAD_FLAGS_XXX.
677 *
678 * @sa RTSymlinkRead
679 */
680RTDECL(int) RTDirRelSymlinkRead(RTDIR hDir, const char *pszSymlink, char *pszTarget, size_t cbTarget, uint32_t fRead)
681{
682 PRTDIRINTERNAL pThis = hDir;
683 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
684 AssertReturn(pThis->u32Magic == RTDIR_MAGIC, VERR_INVALID_HANDLE);
685
686 char szPath[RTPATH_MAX];
687 int rc = rtDirRelBuildFullPath(pThis, szPath, sizeof(szPath), pszSymlink);
688 if (RT_SUCCESS(rc))
689 {
690RTAssertMsg2("DBG: RTDirRelSymlinkRead(%s)...\n", szPath);
691 rc = RTSymlinkRead(szPath, pszTarget, cbTarget, fRead);
692 }
693 return rc;
694}
695
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