VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/vfs/vfsiosmisc.cpp@ 106579

Last change on this file since 106579 was 106061, checked in by vboxsync, 3 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.7 KB
Line 
1/* $Id: vfsiosmisc.cpp 106061 2024-09-16 14:03:52Z vboxsync $ */
2/** @file
3 * IPRT - Virtual File System, Misc I/O Stream Operations.
4 */
5
6/*
7 * Copyright (C) 2010-2024 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * The contents of this file may alternatively be used under the terms
26 * of the Common Development and Distribution License Version 1.0
27 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
28 * in the VirtualBox distribution, in which case the provisions of the
29 * CDDL are applicable instead of those of the GPL.
30 *
31 * You may elect to license modified versions of this file under the
32 * terms and conditions of either the GPL or the CDDL or both.
33 *
34 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
35 */
36
37
38/*********************************************************************************************************************************
39* Header Files *
40*********************************************************************************************************************************/
41#include <iprt/vfs.h>
42#include <iprt/vfslowlevel.h>
43
44#include <iprt/err.h>
45#include <iprt/mem.h>
46#include <iprt/string.h>
47
48
49
50RTDECL(int) RTVfsIoStrmValidateUtf8Encoding(RTVFSIOSTREAM hVfsIos, uint32_t fFlags, PRTFOFF poffError)
51{
52 /*
53 * Validate input.
54 */
55 if (poffError)
56 {
57 AssertPtrReturn(poffError, VINF_SUCCESS);
58 *poffError = 0;
59 }
60 AssertReturn(!(fFlags & ~RTVFS_VALIDATE_UTF8_VALID_MASK), VERR_INVALID_PARAMETER);
61
62 /*
63 * The loop.
64 */
65 char achBuf[1024 + 1];
66 size_t cbUsed = 0;
67 int rc;
68 for (;;)
69 {
70 /*
71 * Fill the buffer
72 */
73 size_t cbRead = 0;
74 rc = RTVfsIoStrmRead(hVfsIos, &achBuf[cbUsed], sizeof(achBuf) - cbUsed - 1, true /*fBlocking*/, &cbRead);
75 if (RT_FAILURE(rc))
76 break;
77 cbUsed += cbRead;
78 if (!cbUsed)
79 {
80 Assert(rc == VINF_EOF);
81 break;
82 }
83 achBuf[sizeof(achBuf) - 1] = '\0';
84
85 /*
86 * Process the data in the buffer, maybe leaving the final chars till
87 * the next round.
88 */
89 const char *pszCur = achBuf;
90 size_t offEnd = rc == VINF_EOF
91 ? cbUsed
92 : cbUsed >= 7
93 ? cbUsed - 7
94 : 0;
95 size_t off;
96 while ((off = (pszCur - &achBuf[0])) < offEnd)
97 {
98 RTUNICP uc;
99 rc = RTStrGetCpEx(&pszCur, &uc);
100 if (RT_FAILURE(rc))
101 break;
102 if (!uc)
103 {
104 if (fFlags & RTVFS_VALIDATE_UTF8_NO_NULL)
105 {
106 rc = VERR_INVALID_UTF8_ENCODING;
107 break;
108 }
109 }
110 else if (uc > 0x10ffff)
111 {
112 if (fFlags & RTVFS_VALIDATE_UTF8_BY_RTC_3629)
113 {
114 rc = VERR_INVALID_UTF8_ENCODING;
115 break;
116 }
117 }
118 }
119
120 if (RT_FAILURE(rc))
121 break;
122
123 if (off < cbUsed)
124 {
125 cbUsed -= off;
126 memmove(achBuf, pszCur, cbUsed);
127 }
128 }
129
130 /*
131 * Set the offset on failure.
132 */
133 if (poffError && RT_FAILURE(rc))
134 {
135 /** @todo r=andy Implement this? */
136 }
137
138 return rc == VINF_EOF ? VINF_SUCCESS : rc;
139}
140
141
142/** Header size. */
143#define READ_ALL_HEADER_SIZE 0x20
144/** The header magic. It's followed by the size (both size_t). */
145#define READ_ALL_HEADER_MAGIC UINT32_C(0x11223355)
146
147RTDECL(int) RTVfsIoStrmReadAll(RTVFSIOSTREAM hVfsIos, void **ppvBuf, size_t *pcbBuf)
148{
149 /*
150 * Try query the object information and in case the stream has a known
151 * size we could use for guidance.
152 */
153 RTFSOBJINFO ObjInfo;
154 int rc = RTVfsIoStrmQueryInfo(hVfsIos, &ObjInfo, RTFSOBJATTRADD_NOTHING);
155 size_t cbAllocated = RT_SUCCESS(rc) && ObjInfo.cbObject > 0 && ObjInfo.cbObject < _1G
156 ? (size_t)ObjInfo.cbObject + 1 : _16K;
157 cbAllocated += READ_ALL_HEADER_SIZE;
158 void *pvBuf = RTMemAlloc(cbAllocated);
159 if (pvBuf)
160 {
161 memset(pvBuf, 0xfe, READ_ALL_HEADER_SIZE);
162 size_t off = 0;
163 for (;;)
164 {
165 /*
166 * Handle buffer growing and detecting the end of it all.
167 */
168 size_t cbToRead = cbAllocated - off - READ_ALL_HEADER_SIZE - 1;
169 if (!cbToRead)
170 {
171 /* The end? */
172 uint8_t bIgn;
173 size_t cbIgn;
174 rc = RTVfsIoStrmRead(hVfsIos, &bIgn, 0, true /*fBlocking*/, &cbIgn);
175 if (rc == VINF_EOF)
176 break;
177
178 /* Grow the buffer. */
179 cbAllocated -= READ_ALL_HEADER_SIZE - 1;
180 cbAllocated = RT_MAX(RT_MIN(cbAllocated, _32M), _1K);
181 cbAllocated = RT_ALIGN_Z(cbAllocated, _4K);
182 cbAllocated += READ_ALL_HEADER_SIZE + 1;
183
184 void *pvNew = RTMemRealloc(pvBuf, cbAllocated);
185 AssertBreakStmt(pvNew, rc = VERR_NO_MEMORY);
186 pvBuf = pvNew;
187
188 cbToRead = cbAllocated - off - READ_ALL_HEADER_SIZE - 1;
189 }
190 Assert(cbToRead < cbAllocated);
191
192 /*
193 * Read.
194 */
195 size_t cbActual;
196 rc = RTVfsIoStrmRead(hVfsIos, (uint8_t *)pvBuf + READ_ALL_HEADER_SIZE + off, cbToRead,
197 true /*fBlocking*/, &cbActual);
198 if (RT_FAILURE(rc))
199 break;
200 Assert(cbActual > 0 || (cbActual == 0 && rc == VINF_EOF));
201 Assert(cbActual <= cbToRead);
202 off += cbActual;
203 if (rc == VINF_EOF)
204 break;
205 }
206 Assert(rc != VERR_EOF);
207 if (RT_SUCCESS(rc))
208 {
209 ((size_t *)pvBuf)[0] = READ_ALL_HEADER_MAGIC;
210 ((size_t *)pvBuf)[1] = off;
211 ((uint8_t *)pvBuf)[READ_ALL_HEADER_SIZE + off] = 0;
212
213 *ppvBuf = (uint8_t *)pvBuf + READ_ALL_HEADER_SIZE;
214 *pcbBuf = off;
215 return VINF_SUCCESS;
216 }
217
218 RTMemFree(pvBuf);
219 }
220 else
221 rc = VERR_NO_MEMORY;
222 *ppvBuf = NULL;
223 *pcbBuf = 0;
224 return rc;
225}
226
227
228RTDECL(void) RTVfsIoStrmReadAllFree(void *pvBuf, size_t cbBuf)
229{
230 AssertPtrReturnVoid(pvBuf);
231
232 /* Spool back to the start of the header. */
233 pvBuf = (uint8_t *)pvBuf - READ_ALL_HEADER_SIZE;
234
235 /* Make sure the caller isn't messing with us. Hardcoded, but works. */
236 Assert(((size_t *)pvBuf)[0] == READ_ALL_HEADER_MAGIC);
237 Assert(((size_t *)pvBuf)[1] == cbBuf); RT_NOREF_PV(cbBuf);
238
239 /* Free it. */
240 RTMemFree(pvBuf);
241}
242
243
244RTDECL(int) RTVfsFileReadAll(RTVFSFILE hVfsFile, void **ppvBuf, size_t *pcbBuf)
245{
246 RTVFSIOSTREAM hVfsIos = RTVfsFileToIoStream(hVfsFile);
247 int rc = RTVfsIoStrmReadAll(hVfsIos, ppvBuf, pcbBuf);
248 RTVfsIoStrmRelease(hVfsIos);
249 return rc;
250}
251
252
253RTDECL(void) RTVfsFileReadAllFree(void *pvBuf, size_t cbBuf)
254{
255 RTVfsIoStrmReadAllFree(pvBuf, cbBuf);
256}
257
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