VirtualBox

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

Last change on this file was 101109, checked in by vboxsync, 8 months ago

IPRT: Fixing assertions (from r158845) related to VFS pfnRead/pfnWrite operations.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.6 KB
Line 
1/* $Id: vfsiosmisc.cpp 101109 2023-09-13 14:20:17Z vboxsync $ */
2/** @file
3 * IPRT - Virtual File System, Misc I/O Stream Operations.
4 */
5
6/*
7 * Copyright (C) 2010-2023 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 (off < cbUsed)
121 {
122 cbUsed -= off;
123 memmove(achBuf, pszCur, cbUsed);
124 }
125 }
126
127 /*
128 * Set the offset on failure.
129 */
130 if (poffError && RT_FAILURE(rc))
131 {
132 }
133
134 return rc == VINF_EOF ? VINF_SUCCESS : rc;
135}
136
137
138/** Header size. */
139#define READ_ALL_HEADER_SIZE 0x20
140/** The header magic. It's followed by the size (both size_t). */
141#define READ_ALL_HEADER_MAGIC UINT32_C(0x11223355)
142
143RTDECL(int) RTVfsIoStrmReadAll(RTVFSIOSTREAM hVfsIos, void **ppvBuf, size_t *pcbBuf)
144{
145 /*
146 * Try query the object information and in case the stream has a known
147 * size we could use for guidance.
148 */
149 RTFSOBJINFO ObjInfo;
150 int rc = RTVfsIoStrmQueryInfo(hVfsIos, &ObjInfo, RTFSOBJATTRADD_NOTHING);
151 size_t cbAllocated = RT_SUCCESS(rc) && ObjInfo.cbObject > 0 && ObjInfo.cbObject < _1G
152 ? (size_t)ObjInfo.cbObject + 1 : _16K;
153 cbAllocated += READ_ALL_HEADER_SIZE;
154 void *pvBuf = RTMemAlloc(cbAllocated);
155 if (pvBuf)
156 {
157 memset(pvBuf, 0xfe, READ_ALL_HEADER_SIZE);
158 size_t off = 0;
159 for (;;)
160 {
161 /*
162 * Handle buffer growing and detecting the end of it all.
163 */
164 size_t cbToRead = cbAllocated - off - READ_ALL_HEADER_SIZE - 1;
165 if (!cbToRead)
166 {
167 /* The end? */
168 uint8_t bIgn;
169 size_t cbIgn;
170 rc = RTVfsIoStrmRead(hVfsIos, &bIgn, 0, true /*fBlocking*/, &cbIgn);
171 if (rc == VINF_EOF)
172 break;
173
174 /* Grow the buffer. */
175 cbAllocated -= READ_ALL_HEADER_SIZE - 1;
176 cbAllocated = RT_MAX(RT_MIN(cbAllocated, _32M), _1K);
177 cbAllocated = RT_ALIGN_Z(cbAllocated, _4K);
178 cbAllocated += READ_ALL_HEADER_SIZE + 1;
179
180 void *pvNew = RTMemRealloc(pvBuf, cbAllocated);
181 AssertBreakStmt(pvNew, rc = VERR_NO_MEMORY);
182 pvBuf = pvNew;
183
184 cbToRead = cbAllocated - off - READ_ALL_HEADER_SIZE - 1;
185 }
186 Assert(cbToRead < cbAllocated);
187
188 /*
189 * Read.
190 */
191 size_t cbActual;
192 rc = RTVfsIoStrmRead(hVfsIos, (uint8_t *)pvBuf + READ_ALL_HEADER_SIZE + off, cbToRead,
193 true /*fBlocking*/, &cbActual);
194 if (RT_FAILURE(rc))
195 break;
196 Assert(cbActual > 0 || (cbActual == 0 && rc == VINF_EOF));
197 Assert(cbActual <= cbToRead);
198 off += cbActual;
199 if (rc == VINF_EOF)
200 break;
201 }
202 Assert(rc != VERR_EOF);
203 if (RT_SUCCESS(rc))
204 {
205 ((size_t *)pvBuf)[0] = READ_ALL_HEADER_MAGIC;
206 ((size_t *)pvBuf)[1] = off;
207 ((uint8_t *)pvBuf)[READ_ALL_HEADER_SIZE + off] = 0;
208
209 *ppvBuf = (uint8_t *)pvBuf + READ_ALL_HEADER_SIZE;
210 *pcbBuf = off;
211 return VINF_SUCCESS;
212 }
213
214 RTMemFree(pvBuf);
215 }
216 else
217 rc = VERR_NO_MEMORY;
218 *ppvBuf = NULL;
219 *pcbBuf = 0;
220 return rc;
221}
222
223
224RTDECL(void) RTVfsIoStrmReadAllFree(void *pvBuf, size_t cbBuf)
225{
226 AssertPtrReturnVoid(pvBuf);
227
228 /* Spool back to the start of the header. */
229 pvBuf = (uint8_t *)pvBuf - READ_ALL_HEADER_SIZE;
230
231 /* Make sure the caller isn't messing with us. Hardcoded, but works. */
232 Assert(((size_t *)pvBuf)[0] == READ_ALL_HEADER_MAGIC);
233 Assert(((size_t *)pvBuf)[1] == cbBuf); RT_NOREF_PV(cbBuf);
234
235 /* Free it. */
236 RTMemFree(pvBuf);
237}
238
239
240RTDECL(int) RTVfsFileReadAll(RTVFSFILE hVfsFile, void **ppvBuf, size_t *pcbBuf)
241{
242 RTVFSIOSTREAM hVfsIos = RTVfsFileToIoStream(hVfsFile);
243 int rc = RTVfsIoStrmReadAll(hVfsIos, ppvBuf, pcbBuf);
244 RTVfsIoStrmRelease(hVfsIos);
245 return rc;
246}
247
248
249RTDECL(void) RTVfsFileReadAllFree(void *pvBuf, size_t cbBuf)
250{
251 RTVfsIoStrmReadAllFree(pvBuf, cbBuf);
252}
253
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use