VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/checksum/manifest2.cpp@ 34407

Last change on this file since 34407 was 34385, checked in by vboxsync, 14 years ago

Build fix.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 21.9 KB
Line 
1/* $Id: manifest2.cpp 34385 2010-11-25 16:29:32Z vboxsync $ */
2/** @file
3 * IPRT - Manifest, the core.
4 */
5
6/*
7 * Copyright (C) 2010 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#include "internal/iprt.h"
32#include <iprt/manifest.h>
33
34#include <iprt/asm.h>
35#include <iprt/assert.h>
36#include <iprt/err.h>
37#include <iprt/mem.h>
38#include <iprt/string.h>
39#include <iprt/vfs.h>
40
41#include "internal/magics.h"
42
43
44/*******************************************************************************
45* Structures and Typedefs *
46*******************************************************************************/
47/**
48 * Manifest attribute.
49 *
50 * Used both for entries and manifest attributes.
51 */
52typedef struct RTMANIFESTATTR
53{
54 /** The string space core (szName). */
55 RTSTRSPACECORE StrCore;
56 /** The property value. */
57 char *pszValue;
58 /** The attribute type if applicable, RTMANIFEST_ATTR_UNKNOWN if not. */
59 uint32_t fType;
60 /** The normalized property name that StrCore::pszString points at. */
61 char szName[1];
62} RTMANIFESTATTR;
63/** Pointer to a manifest attribute. */
64typedef RTMANIFESTATTR *PRTMANIFESTATTR;
65
66
67/**
68 * Manifest entry.
69 */
70typedef struct RTMANIFESTENTRY
71{
72 /** The string space core (szName). */
73 RTSTRSPACECORE StrCore;
74 /** The entry attributes (hashes, checksums, size, etc) -
75 * RTMANIFESTATTR. */
76 RTSTRSPACE Attributes;
77 /** The normalized entry name that StrCore::pszString points at. */
78 char szName[1];
79} RTMANIFESTENTRY;
80/** Pointer to a manifest entry. */
81typedef RTMANIFESTENTRY *PRTMANIFESTENTRY;
82
83
84/**
85 * Manifest handle data.
86 */
87typedef struct RTMANIFESTINT
88{
89 /** Magic value (RTMANIFEST_MAGIC). */
90 uint32_t u32Magic;
91 /** The number of references to this manifest. */
92 uint32_t volatile cRefs;
93 /** Manifest attributes - RTMANIFESTATTR. */
94 RTSTRSPACE Attributes;
95 /** String space of the entries covered by this manifest -
96 * RTMANIFESTENTRY. */
97 RTSTRSPACE Entries;
98} RTMANIFESTINT;
99
100/** The value of RTMANIFESTINT::u32Magic. */
101#define RTMANIFEST_MAGIC UINT32_C(0x99998866)
102
103
104/**
105 * Creates an empty manifest.
106 *
107 * @returns IPRT status code.
108 * @param fFlags Flags, MBZ.
109 * @param phManifest Where to return the handle to the manifest.
110 */
111RTDECL(int) RTManifestCreate(uint32_t fFlags, PRTMANIFEST phManifest)
112{
113 AssertReturn(!fFlags, VERR_INVALID_PARAMETER);
114 AssertPtr(phManifest);
115
116 RTMANIFESTINT *pThis = (RTMANIFESTINT *)RTMemAlloc(sizeof(*pThis));
117 if (!pThis)
118 return VERR_NO_MEMORY;
119
120 pThis->u32Magic = RTMANIFEST_MAGIC;
121 pThis->cRefs = 1;
122 pThis->Attributes = NULL;
123 pThis->Entries = NULL;
124
125 *phManifest = pThis;
126 return VINF_SUCCESS;
127}
128
129/**
130 * Retains a reference to the manifest handle.
131 *
132 * @returns The new reference count, UINT32_MAX if the handle is invalid.
133 * @param hManifest The handle to retain.
134 */
135RTDECL(uint32_t) RTManifestRetain(RTMANIFEST hManifest)
136{
137 RTMANIFESTINT *pThis = hManifest;
138 AssertPtrReturn(pThis, UINT32_MAX);
139 AssertReturn(pThis->u32Magic == RTMANIFEST_MAGIC, UINT32_MAX);
140
141 uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs);
142 Assert(cRefs > 1 && cRefs < _1M);
143
144 return cRefs;
145}
146
147
148/**
149 * @callback_method_impl{FNRTSTRSPACECALLBACK, Destroys RTMANIFESTATTR.}
150 */
151static DECLCALLBACK(int) rtManifestDestroyAttribute(PRTSTRSPACECORE pStr, void *pvUser)
152{
153 PRTMANIFESTATTR pAttr = RT_FROM_MEMBER(pStr, RTMANIFESTATTR, StrCore);
154 RTStrFree(pAttr->pszValue);
155 pAttr->pszValue = NULL;
156 RTMemFree(pAttr);
157 return 0;
158}
159
160
161/**
162 * @callback_method_impl{FNRTSTRSPACECALLBACK, Destroys RTMANIFESTENTRY.}
163 */
164static DECLCALLBACK(int) rtManifestDestroyEntry(PRTSTRSPACECORE pStr, void *pvUser)
165{
166 PRTMANIFESTENTRY pEntry = RT_FROM_MEMBER(pStr, RTMANIFESTENTRY, StrCore);
167 RTStrSpaceDestroy(&pEntry->Attributes, rtManifestDestroyAttribute, pvUser);
168 RTMemFree(pEntry);
169 return 0;
170}
171
172
173/**
174 * Releases a reference to the manifest handle.
175 *
176 * @returns The new reference count, 0 if free. UINT32_MAX is returned if the
177 * handle is invalid.
178 * @param hManifest The handle to release.
179 * NIL is quietly ignored (returns 0).
180 */
181RTDECL(uint32_t) RTManifestRelease(RTMANIFEST hManifest)
182{
183 RTMANIFESTINT *pThis = hManifest;
184 if (pThis == NIL_RTMANIFEST)
185 return 0;
186 AssertPtrReturn(pThis, UINT32_MAX);
187 AssertReturn(pThis->u32Magic == RTMANIFEST_MAGIC, UINT32_MAX);
188
189 uint32_t cRefs = ASMAtomicDecU32(&pThis->cRefs);
190 Assert(cRefs < _1M);
191 if (!cRefs)
192 {
193 ASMAtomicWriteU32(&pThis->u32Magic, ~RTMANIFEST_MAGIC);
194 RTStrSpaceDestroy(&pThis->Attributes, rtManifestDestroyAttribute, pThis);
195 RTStrSpaceDestroy(&pThis->Entries, rtManifestDestroyEntry, pThis);
196 RTMemFree(pThis);
197 }
198
199 return cRefs;
200}
201
202
203/**
204 * Creates a duplicate of the specified manifest.
205 *
206 * @returns IPRT status code
207 * @param hManifestSrc The manifest to clone.
208 * @param phManifestDst Where to store the handle to the duplicate.
209 */
210RTDECL(int) RTManifestDup(RTMANIFEST hManifestSrc, PRTMANIFEST phManifestDst)
211{
212 RTMANIFESTINT *pThis = hManifestSrc;
213 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
214 AssertReturn(pThis->u32Magic == RTMANIFEST_MAGIC, VERR_INVALID_HANDLE);
215 AssertPtr(phManifestDst);
216
217
218 /** @todo implement cloning. */
219
220 return VERR_NOT_IMPLEMENTED;
221}
222
223
224/**
225 * Compares two manifests for equality.
226 *
227 * @returns true if equals, false if not.
228 * @param hManifest1 The first manifest.
229 * @param hManifest2 The second manifest.
230 * @param papszIgnoreEntries Entries to ignore. Ends with a NULL entry.
231 * @param papszIgnoreAttrs Attributes to ignore. Ends with a NULL entry.
232 */
233RTDECL(int) RTManifestEqualsEx(RTMANIFEST hManifest1, RTMANIFEST hManifest2, const char * const *papszIgnoreEntries,
234 const char * const *papszIgnoreAttr)
235{
236 RTMANIFESTINT *pThis1 = hManifest1;
237 RTMANIFESTINT *pThis2 = hManifest1;
238 if (pThis1 != NIL_RTMANIFEST)
239 {
240 AssertPtrReturn(pThis1, false);
241 AssertReturn(pThis1->u32Magic == RTMANIFEST_MAGIC, false);
242 }
243 if (pThis2 != NIL_RTMANIFEST)
244 {
245 AssertPtrReturn(pThis2, false);
246 AssertReturn(pThis2->u32Magic == RTMANIFEST_MAGIC, false);
247 }
248
249 /*
250 * The simple cases.
251 */
252 if (pThis1 == pThis2)
253 return true;
254 if (pThis1 == NIL_RTMANIFEST || pThis2 == NIL_RTMANIFEST)
255 return false;
256
257 /*
258 *
259 */
260
261
262 /** @todo implement comparing. */
263
264 return VERR_NOT_IMPLEMENTED;
265}
266
267
268/**
269 * Compares two manifests for equality.
270 *
271 * @returns true if equals, false if not.
272 * @param hManifest1 The first manifest.
273 * @param hManifest2 The second manifest.
274 */
275RTDECL(int) RTManifestEquals(RTMANIFEST hManifest1, RTMANIFEST hManifest2)
276{
277 return RTManifestEqualsEx(hManifest1, hManifest2, NULL /*papszIgnoreEntries*/, NULL /*papszIgnoreAttrs*/);
278}
279
280
281/**
282 * Worker common to RTManifestSetAttr and RTManifestEntrySetAttr.
283 *
284 * @returns IPRT status code.
285 * @param pAttributes The attribute container.
286 * @param pszAttr The name of the attribute to add.
287 * @param pszValue The value string.
288 * @param fType The attribute type type.
289 */
290static int rtManifestSetAttrWorker(PRTSTRSPACE pAttributes, const char *pszAttr, const char *pszValue, uint32_t fType)
291{
292 char *pszValueCopy;
293 int rc = RTStrDupEx(&pszValueCopy, pszValue);
294 if (RT_FAILURE(rc))
295 return rc;
296
297 /*
298 * Does the attribute exist already?
299 */
300 AssertCompileMemberOffset(RTMANIFESTATTR, StrCore, 0);
301 PRTMANIFESTATTR pAttr = (PRTMANIFESTATTR)RTStrSpaceGet(pAttributes, pszAttr);
302 if (pAttr)
303 {
304 RTStrFree(pAttr->pszValue);
305 pAttr->pszValue = pszValueCopy;
306 pAttr->fType = fType;
307 }
308 else
309 {
310 size_t cbName = strlen(pszAttr) + 1;
311 pAttr = (PRTMANIFESTATTR)RTMemAllocVar(RT_OFFSETOF(RTMANIFESTATTR, szName[cbName]));
312 if (!pAttr)
313 {
314 RTStrFree(pszValueCopy);
315 return VERR_NO_MEMORY;
316 }
317 memcpy(pAttr->szName, pszAttr, cbName);
318 pAttr->StrCore.pszString = pAttr->szName;
319 pAttr->StrCore.cchString = cbName - 1;
320 pAttr->pszValue = pszValueCopy;
321 pAttr->fType = fType;
322 if (RT_UNLIKELY(!RTStrSpaceInsert(pAttributes, &pAttr->StrCore)))
323 {
324 AssertFailed();
325 RTStrFree(pszValueCopy);
326 RTMemFree(pAttr);
327 return VERR_INTERNAL_ERROR_4;
328 }
329 }
330
331 return VINF_SUCCESS;
332}
333
334
335/**
336 * Sets a manifest attribute.
337 *
338 * @returns IPRT status code.
339 * @param hManifest The manifest handle.
340 * @param pszAttr The attribute name. If this already exists,
341 * its value will be replaced.
342 * @param pszValue The value string.
343 * @param fType The attribute type, pass
344 * RTMANIFEST_ATTR_UNKNOWN if not known.
345 */
346RTDECL(int) RTManifestSetAttr(RTMANIFEST hManifest, const char *pszAttr, const char *pszValue, uint32_t fType)
347{
348 RTMANIFESTINT *pThis = hManifest;
349 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
350 AssertReturn(pThis->u32Magic == RTMANIFEST_MAGIC, VERR_INVALID_HANDLE);
351 AssertPtr(pszAttr);
352 AssertPtr(pszValue);
353 AssertReturn(RT_IS_POWER_OF_TWO(fType) && fType < RTMANIFEST_ATTR_END, VERR_INVALID_PARAMETER);
354
355 return rtManifestSetAttrWorker(&pThis->Attributes, pszAttr, pszValue, fType);
356}
357
358
359/**
360 * Worker common to RTManifestUnsetAttr and RTManifestEntryUnsetAttr.
361 *
362 * @returns IPRT status code.
363 * @param pAttributes The attribute container.
364 * @param pszAttr The name of the attribute to remove.
365 */
366static int rtManifestUnsetAttrWorker(PRTSTRSPACE pAttributes, const char *pszAttr)
367{
368 PRTSTRSPACECORE pStrCore = RTStrSpaceRemove(pAttributes, pszAttr);
369 if (!pStrCore)
370 return VWRN_NOT_FOUND;
371 rtManifestDestroyAttribute(pStrCore, NULL);
372 return VINF_SUCCESS;
373}
374
375
376/**
377 * Unsets (removes) a manifest attribute if it exists.
378 *
379 * @returns IPRT status code.
380 * @retval VWRN_NOT_FOUND if not found.
381 *
382 * @param hManifest The manifest handle.
383 * @param pszAttr The attribute name.
384 */
385RTDECL(int) RTManifestUnsetAttr(RTMANIFEST hManifest, const char *pszAttr)
386{
387 RTMANIFESTINT *pThis = hManifest;
388 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
389 AssertReturn(pThis->u32Magic == RTMANIFEST_MAGIC, VERR_INVALID_HANDLE);
390 AssertPtr(pszAttr);
391
392 return rtManifestUnsetAttrWorker(&pThis->Attributes, pszAttr);
393}
394
395
396/**
397 * Validates the name entry.
398 *
399 * @returns IPRT status code.
400 * @param pszEntry The entry name to validate.
401 * @param pfNeedNormalization Where to return whether it needs normalization
402 * or not. Optional.
403 * @param pcchEntry Where to return the length. Optional.
404 */
405static int rtManifestValidateNameEntry(const char *pszEntry, bool *pfNeedNormalization, size_t *pcchEntry)
406{
407 int rc;
408 bool fNeedNormalization = false;
409 const char *pszCur = pszEntry;
410
411 for (;;)
412 {
413 RTUNICP uc;
414 rc = RTStrGetCpEx(&pszCur, &uc);
415 if (RT_FAILURE(rc))
416 break;
417 if (!uc)
418 break;
419 if (uc == '\\')
420 fNeedNormalization = true;
421 else if (uc < 32 || uc == ':' || uc == '(' || uc == ')')
422 {
423 rc = VERR_INVALID_NAME;
424 break;
425 }
426 }
427
428 if (pfNeedNormalization)
429 *pfNeedNormalization = fNeedNormalization;
430 if (pcchEntry)
431 *pcchEntry = pszCur - pszEntry - 1;
432 return rc;
433}
434
435
436/**
437 * Normalizes a entry name.
438 *
439 * @param pszEntry The entry name to normalize.
440 */
441static void rtManifestNormalizeEntry(char *pszEntry)
442{
443 char ch;
444 while ((ch = *pszEntry))
445 {
446 if (ch == '\\')
447 *pszEntry = '/';
448 pszEntry++;
449 }
450}
451
452
453/**
454 * Gets an entry.
455 *
456 * @returns IPRT status code.
457 * @param pThis The manifest to work with.
458 * @param pszEntry The entry name.
459 * @param fNeedNormalization Whether rtManifestValidateNameEntry said it
460 * needed normalization.
461 * @param cchEntry The length of the name.
462 * @param ppEntry Where to return the entry pointer on success.
463 */
464static int rtManifestGetEntry(RTMANIFESTINT *pThis, const char *pszEntry, bool fNeedNormalization, size_t cchEntry,
465 PRTMANIFESTENTRY *ppEntry)
466{
467 PRTMANIFESTENTRY pEntry;
468
469 AssertCompileMemberOffset(RTMANIFESTATTR, StrCore, 0);
470 if (!fNeedNormalization)
471 pEntry = (PRTMANIFESTENTRY)RTStrSpaceGet(&pThis->Entries, pszEntry);
472 else
473 {
474 char *pszCopy = (char *)RTMemTmpAlloc(cchEntry + 1);
475 if (RT_UNLIKELY(!pszCopy))
476 return VERR_NO_TMP_MEMORY;
477 memcpy(pszCopy, pszEntry, cchEntry + 1);
478 rtManifestNormalizeEntry(pszCopy);
479
480 pEntry = (PRTMANIFESTENTRY)RTStrSpaceGet(&pThis->Entries, pszCopy);
481 RTMemTmpFree(pszCopy);
482 }
483
484 *ppEntry = pEntry;
485 return pEntry ? VINF_SUCCESS : VERR_NOT_FOUND;
486}
487
488
489/**
490 * Sets an attribute of a manifest entry.
491 *
492 * @returns IPRT status code.
493 * @param hManifest The manifest handle.
494 * @param pszEntry The entry name. This will automatically be
495 * added if there was no previous call to
496 * RTManifestEntryAdd for this name. See
497 * RTManifestEntryAdd for the entry name rules.
498 * @param pszAttr The attribute name. If this already exists,
499 * its value will be replaced.
500 * @param pszValue The value string.
501 * @param fType The attribute type, pass
502 * RTMANIFEST_ATTR_UNKNOWN if not known.
503 */
504RTDECL(int) RTManifestEntrySetAttr(RTMANIFEST hManifest, const char *pszEntry, const char *pszAttr,
505 const char *pszValue, uint32_t fType)
506{
507 RTMANIFESTINT *pThis = hManifest;
508 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
509 AssertReturn(pThis->u32Magic == RTMANIFEST_MAGIC, VERR_INVALID_HANDLE);
510 AssertPtr(pszEntry);
511 AssertPtr(pszAttr);
512 AssertPtr(pszValue);
513 AssertReturn(RT_IS_POWER_OF_TWO(fType) && fType < RTMANIFEST_ATTR_END, VERR_INVALID_PARAMETER);
514
515 bool fNeedNormalization;
516 size_t cchEntry;
517 int rc = rtManifestValidateNameEntry(pszEntry, &fNeedNormalization, &cchEntry);
518 AssertRCReturn(rc, rc);
519
520 /*
521 * Resolve the entry, adding one if necessary.
522 */
523 PRTMANIFESTENTRY pEntry;
524 rc = rtManifestGetEntry(pThis, pszEntry, fNeedNormalization, cchEntry, &pEntry);
525 if (rc == VERR_NOT_FOUND)
526 {
527 pEntry = (PRTMANIFESTENTRY)RTMemAlloc(RT_OFFSETOF(RTMANIFESTENTRY, szName[cchEntry + 1]));
528 if (!pEntry)
529 return VERR_NO_MEMORY;
530
531 pEntry->StrCore.cchString = cchEntry;
532 pEntry->StrCore.pszString = pEntry->szName;
533 pEntry->Attributes = NULL;
534 memcpy(pEntry->szName, pszEntry, cchEntry + 1);
535 if (fNeedNormalization)
536 rtManifestNormalizeEntry(pEntry->szName);
537
538 if (!RTStrSpaceInsert(&pThis->Entries, &pEntry->StrCore))
539 {
540 RTMemFree(pEntry);
541 return VERR_INTERNAL_ERROR_4;
542 }
543 }
544 else if (RT_FAILURE(rc))
545 return rc;
546
547 return rtManifestSetAttrWorker(&pEntry->Attributes, pszAttr, pszValue, fType);
548}
549
550
551/**
552 * Unsets (removes) an attribute of a manifest entry if they both exist.
553 *
554 * @returns IPRT status code.
555 * @retval VWRN_NOT_FOUND if not found.
556 *
557 * @param hManifest The manifest handle.
558 * @param pszEntry The entry name.
559 * @param pszAttr The attribute name.
560 */
561RTDECL(int) RTManifestEntryUnsetAttr(RTMANIFEST hManifest, const char *pszEntry, const char *pszAttr)
562{
563 RTMANIFESTINT *pThis = hManifest;
564 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
565 AssertReturn(pThis->u32Magic == RTMANIFEST_MAGIC, VERR_INVALID_HANDLE);
566 AssertPtr(pszEntry);
567 AssertPtr(pszAttr);
568
569 bool fNeedNormalization;
570 size_t cchEntry;
571 int rc = rtManifestValidateNameEntry(pszEntry, &fNeedNormalization, &cchEntry);
572 AssertRCReturn(rc, rc);
573
574 /*
575 * Resolve the entry and hand it over to the worker.
576 */
577 PRTMANIFESTENTRY pEntry;
578 rc = rtManifestGetEntry(pThis, pszEntry, fNeedNormalization, cchEntry, &pEntry);
579 if (RT_SUCCESS(rc))
580 rc = rtManifestUnsetAttrWorker(&pEntry->Attributes, pszAttr);
581 return rc;
582}
583
584
585/**
586 * Adds a new entry to a manifest.
587 *
588 * The entry name rules:
589 * - The entry name can contain any character defined by unicode, except
590 * control characters, ':', '(' and ')'. The exceptions are mainly there
591 * because of uncertainty around how various formats handles these.
592 * - It is considered case sensitive.
593 * - Forward (unix) and backward (dos) slashes are considered path
594 * separators and converted to forward slashes.
595 *
596 * @returns IPRT status code.
597 * @retval VWRN_ALREADY_EXISTS if the entry already exists.
598 *
599 * @param hManifest The manifest handle.
600 * @param pszEntry The entry name (UTF-8).
601 *
602 * @remarks Some manifest formats will not be able to store an entry without
603 * any attributes. So, this is just here in case it comes in handy
604 * when dealing with formats which can.
605 */
606RTDECL(int) RTManifestEntryAdd(RTMANIFEST hManifest, const char *pszEntry)
607{
608 RTMANIFESTINT *pThis = hManifest;
609 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
610 AssertReturn(pThis->u32Magic == RTMANIFEST_MAGIC, VERR_INVALID_HANDLE);
611 AssertPtr(pszEntry);
612
613 bool fNeedNormalization;
614 size_t cchEntry;
615 int rc = rtManifestValidateNameEntry(pszEntry, &fNeedNormalization, &cchEntry);
616 AssertRCReturn(rc, rc);
617
618 /*
619 * Only add one if it does not already exist.
620 */
621 PRTMANIFESTENTRY pEntry;
622 rc = rtManifestGetEntry(pThis, pszEntry, fNeedNormalization, cchEntry, &pEntry);
623 if (rc == VERR_NOT_FOUND)
624 {
625 pEntry = (PRTMANIFESTENTRY)RTMemAlloc(RT_OFFSETOF(RTMANIFESTENTRY, szName[cchEntry + 1]));
626 if (pEntry)
627 {
628 pEntry->StrCore.cchString = cchEntry;
629 pEntry->StrCore.pszString = pEntry->szName;
630 pEntry->Attributes = NULL;
631 memcpy(pEntry->szName, pszEntry, cchEntry + 1);
632 if (fNeedNormalization)
633 rtManifestNormalizeEntry(pEntry->szName);
634
635 if (RTStrSpaceInsert(&pThis->Entries, &pEntry->StrCore))
636 rc = VINF_SUCCESS;
637 else
638 {
639 RTMemFree(pEntry);
640 rc = VERR_INTERNAL_ERROR_4;
641 }
642 }
643 else
644 rc = VERR_NO_MEMORY;
645 }
646 else if (RT_SUCCESS(rc))
647 rc = VWRN_ALREADY_EXISTS;
648
649 return rc;
650}
651
652
653/**
654 * Removes an entry.
655 *
656 * @returns IPRT status code.
657 * @param hManifest The manifest handle.
658 * @param pszEntry The entry name.
659 */
660RTDECL(int) RTManifestEntryRemove(RTMANIFEST hManifest, const char *pszEntry)
661{
662 RTMANIFESTINT *pThis = hManifest;
663 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
664 AssertReturn(pThis->u32Magic == RTMANIFEST_MAGIC, VERR_INVALID_HANDLE);
665 AssertPtr(pszEntry);
666
667 bool fNeedNormalization;
668 size_t cchEntry;
669 int rc = rtManifestValidateNameEntry(pszEntry, &fNeedNormalization, &cchEntry);
670 AssertRCReturn(rc, rc);
671
672 /*
673 * Only add one if it does not already exist.
674 */
675 PRTMANIFESTENTRY pEntry;
676 rc = rtManifestGetEntry(pThis, pszEntry, fNeedNormalization, cchEntry, &pEntry);
677 if (RT_SUCCESS(rc))
678 {
679 PRTSTRSPACECORE pStrCore = RTStrSpaceRemove(&pThis->Entries, pEntry->StrCore.pszString);
680 AssertReturn(pStrCore, VERR_INTERNAL_ERROR_3);
681 rtManifestDestroyEntry(pStrCore, pThis);
682 }
683
684 return rc;
685}
686
687
688/**
689 * Reads in a "standard" manifest.
690 *
691 * This reads the format used by OVF, the distinfo in FreeBSD ports, and
692 * others.
693 *
694 * @returns IPRT status code.
695 * @param hManifest The handle to the manifest where to add the
696 * manifest that's read in.
697 * @param hVfsIos The I/O stream to read the manifest from.
698 */
699RTDECL(int) RTManifestReadStandard(RTMANIFEST hManifest, RTVFSIOSTREAM hVfsIos)
700{
701 return VERR_NOT_IMPLEMENTED;
702}
703
704
705/**
706 * Writes a "standard" manifest.
707 *
708 * This writes the format used by OVF, the distinfo in FreeBSD ports, and
709 * others.
710 *
711 * @returns IPRT status code.
712 * @param hManifest The handle to the manifest where to add the
713 * manifest that's read in.
714 * @param hVfsIos The I/O stream to read the manifest from.
715 */
716RTDECL(int) RTManifestWriteStandard(RTMANIFEST hManifest, RTVFSIOSTREAM hVfsIos)
717{
718 return VERR_NOT_IMPLEMENTED;
719}
720
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette