VirtualBox

source: vbox/trunk/src/VBox/Runtime/r3/win/fs-win.cpp@ 28918

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

iprt: dropped RT_DONT_CONVERT_FILENAMES, we've never needed it so far...

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 9.1 KB
Line 
1/* $Id: fs-win.cpp 28918 2010-04-29 18:30:09Z vboxsync $ */
2/** @file
3 * IPRT - File System, Win32.
4 */
5
6/*
7 * Copyright (C) 2006-2007 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_FS
32#include <windows.h>
33
34#include <iprt/fs.h>
35#include <iprt/path.h>
36#include <iprt/string.h>
37#include <iprt/param.h>
38#include <iprt/err.h>
39#include <iprt/log.h>
40#include <iprt/assert.h>
41#include "internal/fs.h"
42
43
44/**
45 * Checks quickly if this is an correct root specification.
46 * Root specs ends with a slash of some kind.
47 *
48 * @returns indicator.
49 * @param pszFsPath Path to check.
50 */
51static bool rtFsIsRoot(const char *pszFsPath)
52{
53 /*
54 * UNC has exactly two slashes..
55 *
56 * Anything else starting with slashe(s) requires
57 * expansion and will have to take the long road.
58 */
59 if (RTPATH_IS_SLASH(pszFsPath[0]))
60 {
61 if ( !RTPATH_IS_SLASH(pszFsPath[1])
62 || RTPATH_IS_SLASH(pszFsPath[2]))
63 return false;
64
65 /* end of machine name */
66 const char *pszSlash = strpbrk(pszFsPath + 2, "\\/");
67 if (!pszSlash)
68 return false;
69
70 /* end of service name. */
71 pszSlash = strpbrk(pszSlash + 1, "\\/");
72 if (!pszSlash)
73 return false;
74
75 return pszSlash[1] == '\0';
76 }
77
78 /*
79 * Ok the other alternative is driver letter.
80 */
81 return pszFsPath[0] >= 'A' && pszFsPath[0] <= 'Z'
82 && pszFsPath[1] == ':'
83 && RTPATH_IS_SLASH(pszFsPath[2])
84 && !pszFsPath[3];
85}
86
87
88
89/**
90 * Finds the root of the specified volume.
91 *
92 * @returns iprt status code.
93 * @param pszFsPath Path within the filesystem. Verified as one byte or more.
94 * @param ppwszFsRoot Where to store the returned string. Free with rtFsFreeRoot(),
95 */
96static int rtFsGetRoot(const char *pszFsPath, PRTUTF16 *ppwszFsRoot)
97{
98 /*
99 * Do straight forward stuff first,
100 */
101 if (rtFsIsRoot(pszFsPath))
102 return RTStrToUtf16(pszFsPath, ppwszFsRoot);
103
104 /*
105 * Expand and add slash (if required).
106 */
107 char szFullPath[RTPATH_MAX];
108 int rc = RTPathAbs(pszFsPath, szFullPath, sizeof(szFullPath));
109 if (RT_FAILURE(rc))
110 return rc;
111 size_t cb = strlen(szFullPath);
112 if (!RTPATH_IS_SLASH(szFullPath[cb - 1]))
113 {
114 AssertReturn(cb + 1 < RTPATH_MAX, VERR_FILENAME_TOO_LONG);
115 szFullPath[cb] = '\\';
116 szFullPath[++cb] = '\0';
117 }
118
119 /*
120 * Convert the path.
121 */
122 rc = RTStrToUtf16(szFullPath, ppwszFsRoot);
123 if (RT_FAILURE(rc))
124 return rc == VERR_BUFFER_OVERFLOW ? VERR_FILENAME_TOO_LONG : rc;
125
126 /*
127 * Walk the path until our proper API is happy or there is no more path left.
128 */
129 PRTUTF16 pwszStart = *ppwszFsRoot;
130 if (!GetVolumeInformationW(pwszStart, NULL, 0, NULL, NULL, 0, NULL, 0))
131 {
132 PRTUTF16 pwszEnd = pwszStart + RTUtf16Len(pwszStart);
133 PRTUTF16 pwszMin = pwszStart + 2;
134 do
135 {
136 /* Strip off the last path component. */
137 while (pwszEnd-- > pwszMin)
138 if (RTPATH_IS_SLASH(*pwszEnd))
139 break;
140 AssertReturn(pwszEnd >= pwszMin, VERR_INTERNAL_ERROR); /* leaks, but that's irrelevant for an internal error. */
141 pwszEnd[1] = '\0';
142 } while (!GetVolumeInformationW(pwszStart, NULL, 0, NULL, NULL, 0, NULL, 0));
143 }
144
145 return VINF_SUCCESS;
146}
147
148/**
149 * Frees string returned by rtFsGetRoot().
150 */
151static void rtFsFreeRoot(PRTUTF16 pwszFsRoot)
152{
153 RTUtf16Free(pwszFsRoot);
154}
155
156
157RTR3DECL(int) RTFsQuerySizes(const char *pszFsPath, RTFOFF *pcbTotal, RTFOFF *pcbFree,
158 uint32_t *pcbBlock, uint32_t *pcbSector)
159{
160 /*
161 * Validate & get valid root path.
162 */
163 AssertMsgReturn(VALID_PTR(pszFsPath) && *pszFsPath, ("%p", pszFsPath), VERR_INVALID_PARAMETER);
164 PRTUTF16 pwszFsRoot;
165 int rc = rtFsGetRoot(pszFsPath, &pwszFsRoot);
166 if (RT_FAILURE(rc))
167 return rc;
168
169 /*
170 * Free and total.
171 */
172 if (pcbTotal || pcbFree)
173 {
174 ULARGE_INTEGER cbTotal;
175 ULARGE_INTEGER cbFree;
176 if (GetDiskFreeSpaceExW(pwszFsRoot, &cbFree, &cbTotal, NULL))
177 {
178 if (pcbTotal)
179 *pcbTotal = cbTotal.QuadPart;
180 if (pcbFree)
181 *pcbFree = cbFree.QuadPart;
182 }
183 else
184 {
185 DWORD Err = GetLastError();
186 rc = RTErrConvertFromWin32(Err);
187 Log(("RTFsQuerySizes(%s,): GetDiskFreeSpaceEx failed with lasterr %d (%Rrc)\n",
188 pszFsPath, Err, rc));
189 }
190 }
191
192 /*
193 * Block and sector size.
194 */
195 if ( RT_SUCCESS(rc)
196 && (pcbBlock || pcbSector))
197 {
198 DWORD dwDummy1, dwDummy2;
199 DWORD cbSector;
200 DWORD cSectorsPerCluster;
201 if (GetDiskFreeSpaceW(pwszFsRoot, &cSectorsPerCluster, &cbSector, &dwDummy1, &dwDummy2))
202 {
203 if (pcbBlock)
204 *pcbBlock = cbSector * cSectorsPerCluster;
205 if (pcbSector)
206 *pcbSector = cbSector;
207 }
208 else
209 {
210 DWORD Err = GetLastError();
211 rc = RTErrConvertFromWin32(Err);
212 Log(("RTFsQuerySizes(%s,): GetDiskFreeSpace failed with lasterr %d (%Rrc)\n",
213 pszFsPath, Err, rc));
214 }
215 }
216
217 rtFsFreeRoot(pwszFsRoot);
218 return rc;
219}
220
221
222/**
223 * Query the serial number of a filesystem.
224 *
225 * @returns iprt status code.
226 * @param pszFsPath Path within the mounted filesystem.
227 * @param pu32Serial Where to store the serial number.
228 */
229RTR3DECL(int) RTFsQuerySerial(const char *pszFsPath, uint32_t *pu32Serial)
230{
231 /*
232 * Validate & get valid root path.
233 */
234 AssertMsgReturn(VALID_PTR(pszFsPath) && *pszFsPath, ("%p", pszFsPath), VERR_INVALID_PARAMETER);
235 AssertMsgReturn(VALID_PTR(pu32Serial), ("%p", pu32Serial), VERR_INVALID_PARAMETER);
236 PRTUTF16 pwszFsRoot;
237 int rc = rtFsGetRoot(pszFsPath, &pwszFsRoot);
238 if (RT_FAILURE(rc))
239 return rc;
240
241 /*
242 * Do work.
243 */
244 DWORD dwMaxName;
245 DWORD dwFlags;
246 DWORD dwSerial;
247 if (GetVolumeInformationW(pwszFsRoot, NULL, 0, &dwSerial, &dwMaxName, &dwFlags, NULL, 0))
248 *pu32Serial = dwSerial;
249 else
250 {
251 DWORD Err = GetLastError();
252 rc = RTErrConvertFromWin32(Err);
253 Log(("RTFsQuerySizes(%s,): GetDiskFreeSpaceEx failed with lasterr %d (%Rrc)\n",
254 pszFsPath, Err, rc));
255 }
256
257 RTUtf16Free(pwszFsRoot);
258 return rc;
259}
260
261
262/**
263 * Query the properties of a mounted filesystem.
264 *
265 * @returns iprt status code.
266 * @param pszFsPath Path within the mounted filesystem.
267 * @param pProperties Where to store the properties.
268 */
269RTR3DECL(int) RTFsQueryProperties(const char *pszFsPath, PRTFSPROPERTIES pProperties)
270{
271 /*
272 * Validate & get valid root path.
273 */
274 AssertMsgReturn(VALID_PTR(pszFsPath) && *pszFsPath, ("%p", pszFsPath), VERR_INVALID_PARAMETER);
275 AssertMsgReturn(VALID_PTR(pProperties), ("%p", pProperties), VERR_INVALID_PARAMETER);
276 PRTUTF16 pwszFsRoot;
277 int rc = rtFsGetRoot(pszFsPath, &pwszFsRoot);
278 if (RT_FAILURE(rc))
279 return rc;
280
281 /*
282 * Do work.
283 */
284 DWORD dwMaxName;
285 DWORD dwFlags;
286 DWORD dwSerial;
287 if (GetVolumeInformationW(pwszFsRoot, NULL, 0, &dwSerial, &dwMaxName, &dwFlags, NULL, 0))
288 {
289 memset(pProperties, 0, sizeof(*pProperties));
290 pProperties->cbMaxComponent = dwMaxName;
291 pProperties->fFileCompression = !!(dwFlags & FILE_FILE_COMPRESSION);
292 pProperties->fCompressed = !!(dwFlags & FILE_VOLUME_IS_COMPRESSED);
293 pProperties->fReadOnly = !!(dwFlags & FILE_READ_ONLY_VOLUME);
294 pProperties->fSupportsUnicode = !!(dwFlags & FILE_UNICODE_ON_DISK);
295 pProperties->fCaseSensitive = false; /* win32 is case preserving only */
296 pProperties->fRemote = false; /* no idea yet */
297 }
298 else
299 {
300 DWORD Err = GetLastError();
301 rc = RTErrConvertFromWin32(Err);
302 Log(("RTFsQuerySizes(%s,): GetVolumeInformation failed with lasterr %d (%Rrc)\n",
303 pszFsPath, Err, rc));
304 }
305
306 RTUtf16Free(pwszFsRoot);
307 return rc;
308}
309
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