VirtualBox

source: vbox/trunk/src/VBox/Runtime/r3/posix/fs-posix.cpp

Last change on this file was 98103, checked in by vboxsync, 16 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 13.1 KB
Line 
1/* $Id: fs-posix.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * IPRT - File System, Linux.
4 */
5
6/*
7 * Copyright (C) 2006-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#define LOG_GROUP RTLOGGROUP_FS
42#include <sys/statvfs.h>
43#include <errno.h>
44#include <stdio.h>
45#ifdef RT_OS_LINUX
46# include <mntent.h>
47#endif
48#if defined(RT_OS_DARWIN) || defined(RT_OS_FREEBSD)
49# include <sys/mount.h>
50#endif
51
52#include <iprt/fs.h>
53#include "internal/iprt.h"
54
55#include <iprt/assert.h>
56#include <iprt/errcore.h>
57#include <iprt/log.h>
58#include <iprt/string.h>
59#include "internal/fs.h"
60#include "internal/path.h"
61
62
63
64RTR3DECL(int) RTFsQuerySizes(const char *pszFsPath, RTFOFF *pcbTotal, RTFOFF *pcbFree,
65 uint32_t *pcbBlock, uint32_t *pcbSector)
66{
67 /*
68 * Validate input.
69 */
70 AssertPtrReturn(pszFsPath, VERR_INVALID_POINTER);
71 AssertReturn(*pszFsPath != '\0', VERR_INVALID_PARAMETER);
72
73 /*
74 * Convert the path and query the information.
75 */
76 char const *pszNativeFsPath;
77 int rc = rtPathToNative(&pszNativeFsPath, pszFsPath, NULL);
78 if (RT_SUCCESS(rc))
79 {
80 /** @todo I'm not quite sure if statvfs was properly specified by SuS, I have to check my own
81 * implementation and FreeBSD before this can eventually be promoted to posix. */
82 struct statvfs StatVFS;
83 RT_ZERO(StatVFS);
84 if (!statvfs(pszNativeFsPath, &StatVFS))
85 {
86 /*
87 * Calc the returned values.
88 */
89 if (pcbTotal)
90 *pcbTotal = (RTFOFF)StatVFS.f_blocks * StatVFS.f_frsize;
91 if (pcbFree)
92 *pcbFree = (RTFOFF)StatVFS.f_bavail * StatVFS.f_frsize;
93 if (pcbBlock)
94 *pcbBlock = StatVFS.f_frsize;
95 /* no idea how to get the sector... */
96 if (pcbSector)
97 *pcbSector = 512;
98 }
99 else
100 rc = RTErrConvertFromErrno(errno);
101 rtPathFreeNative(pszNativeFsPath, pszFsPath);
102 }
103
104 LogFlow(("RTFsQuerySizes(%p:{%s}, %p:{%RTfoff}, %p:{%RTfoff}, %p:{%RX32}, %p:{%RX32}): returns %Rrc\n",
105 pszFsPath, pszFsPath, pcbTotal, pcbTotal ? *pcbTotal : 0, pcbFree, pcbFree ? *pcbFree : 0,
106 pcbBlock, pcbBlock ? *pcbBlock : 0, pcbSector, pcbSector ? *pcbSector : 0, rc));
107 return rc;
108}
109
110
111RTR3DECL(int) RTFsQuerySerial(const char *pszFsPath, uint32_t *pu32Serial)
112{
113 /*
114 * Validate input.
115 */
116 AssertPtrReturn(pszFsPath, VERR_INVALID_POINTER);
117 AssertReturn(*pszFsPath != '\0', VERR_INVALID_PARAMETER);
118 AssertPtrReturn(pu32Serial, VERR_INVALID_POINTER);
119
120 /*
121 * Convert the path and query the stats.
122 * We're simply return the device id.
123 */
124 char const *pszNativeFsPath;
125 int rc = rtPathToNative(&pszNativeFsPath, pszFsPath, NULL);
126 if (RT_SUCCESS(rc))
127 {
128 struct stat Stat;
129 if (!stat(pszNativeFsPath, &Stat))
130 {
131 if (pu32Serial)
132 *pu32Serial = (uint32_t)Stat.st_dev;
133 }
134 else
135 rc = RTErrConvertFromErrno(errno);
136 rtPathFreeNative(pszNativeFsPath, pszFsPath);
137 }
138 LogFlow(("RTFsQuerySerial(%p:{%s}, %p:{%RX32}: returns %Rrc\n",
139 pszFsPath, pszFsPath, pu32Serial, pu32Serial ? *pu32Serial : 0, rc));
140 return rc;
141}
142
143
144RTR3DECL(int) RTFsQueryProperties(const char *pszFsPath, PRTFSPROPERTIES pProperties)
145{
146 /*
147 * Validate.
148 */
149 AssertPtrReturn(pszFsPath, VERR_INVALID_POINTER);
150 AssertReturn(*pszFsPath != '\0', VERR_INVALID_PARAMETER);
151 AssertPtrReturn(pProperties, VERR_INVALID_POINTER);
152
153 /*
154 * Convert the path and query the information.
155 */
156 char const *pszNativeFsPath;
157 int rc = rtPathToNative(&pszNativeFsPath, pszFsPath, NULL);
158 if (RT_SUCCESS(rc))
159 {
160 struct statvfs StatVFS;
161 RT_ZERO(StatVFS);
162 if (!statvfs(pszNativeFsPath, &StatVFS))
163 {
164 /*
165 * Calc/fake the returned values.
166 */
167 pProperties->cbMaxComponent = StatVFS.f_namemax;
168#if defined(RT_OS_OS2) || defined(RT_OS_WINDOWS)
169 pProperties->fCaseSensitive = false;
170#else
171 pProperties->fCaseSensitive = true;
172#endif
173 pProperties->fCompressed = false;
174 pProperties->fFileCompression = false;
175 pProperties->fReadOnly = !!(StatVFS.f_flag & ST_RDONLY);
176 pProperties->fRemote = false;
177 pProperties->fSupportsUnicode = true;
178 }
179 else
180 rc = RTErrConvertFromErrno(errno);
181 rtPathFreeNative(pszNativeFsPath, pszFsPath);
182 }
183
184 LogFlow(("RTFsQueryProperties(%p:{%s}, %p:{.cbMaxComponent=%u, .fReadOnly=%RTbool}): returns %Rrc\n",
185 pszFsPath, pszFsPath, pProperties, pProperties->cbMaxComponent, pProperties->fReadOnly, rc));
186 return rc;
187}
188
189
190RTR3DECL(bool) RTFsIsCaseSensitive(const char *pszFsPath)
191{
192 RT_NOREF_PV(pszFsPath);
193#if defined(RT_OS_OS2) || defined(RT_OS_WINDOWS)
194 return false;
195#else
196 return true;
197#endif
198}
199
200
201RTR3DECL(int) RTFsQueryType(const char *pszFsPath, PRTFSTYPE penmType)
202{
203 *penmType = RTFSTYPE_UNKNOWN;
204
205 /*
206 * Validate input.
207 */
208 AssertPtrReturn(pszFsPath, VERR_INVALID_POINTER);
209 AssertReturn(*pszFsPath, VERR_INVALID_PARAMETER);
210
211 /*
212 * Convert the path and query the stats.
213 * We're simply return the device id.
214 */
215 char const *pszNativeFsPath;
216 int rc = rtPathToNative(&pszNativeFsPath, pszFsPath, NULL);
217 if (RT_SUCCESS(rc))
218 {
219 struct stat Stat;
220 if (!stat(pszNativeFsPath, &Stat))
221 {
222#if defined(RT_OS_LINUX)
223 FILE *mounted = setmntent("/proc/mounts", "r");
224 if (!mounted)
225 mounted = setmntent("/etc/mtab", "r");
226 if (mounted)
227 {
228 char szBuf[1024];
229 struct stat mntStat;
230 struct mntent mntEnt;
231 while (getmntent_r(mounted, &mntEnt, szBuf, sizeof(szBuf)))
232 {
233 if (!stat(mntEnt.mnt_dir, &mntStat))
234 {
235 if (mntStat.st_dev == Stat.st_dev)
236 {
237 if (!strcmp("ext4", mntEnt.mnt_type))
238 *penmType = RTFSTYPE_EXT4;
239 else if (!strcmp("ext3", mntEnt.mnt_type))
240 *penmType = RTFSTYPE_EXT3;
241 else if (!strcmp("ext2", mntEnt.mnt_type))
242 *penmType = RTFSTYPE_EXT2;
243 else if (!strcmp("jfs", mntEnt.mnt_type))
244 *penmType = RTFSTYPE_JFS;
245 else if (!strcmp("xfs", mntEnt.mnt_type))
246 *penmType = RTFSTYPE_XFS;
247 else if (!strcmp("btrfs", mntEnt.mnt_type))
248 *penmType = RTFSTYPE_BTRFS;
249 else if ( !strcmp("vfat", mntEnt.mnt_type)
250 || !strcmp("msdos", mntEnt.mnt_type))
251 *penmType = RTFSTYPE_FAT;
252 else if (!strcmp("ntfs", mntEnt.mnt_type))
253 *penmType = RTFSTYPE_NTFS;
254 else if (!strcmp("hpfs", mntEnt.mnt_type))
255 *penmType = RTFSTYPE_HPFS;
256 else if (!strcmp("ufs", mntEnt.mnt_type))
257 *penmType = RTFSTYPE_UFS;
258 else if (!strcmp("tmpfs", mntEnt.mnt_type))
259 *penmType = RTFSTYPE_TMPFS;
260 else if (!strcmp("hfsplus", mntEnt.mnt_type))
261 *penmType = RTFSTYPE_HFS;
262 else if (!strcmp("udf", mntEnt.mnt_type))
263 *penmType = RTFSTYPE_UDF;
264 else if (!strcmp("iso9660", mntEnt.mnt_type))
265 *penmType = RTFSTYPE_ISO9660;
266 else if (!strcmp("smbfs", mntEnt.mnt_type))
267 *penmType = RTFSTYPE_SMBFS;
268 else if (!strcmp("cifs", mntEnt.mnt_type))
269 *penmType = RTFSTYPE_CIFS;
270 else if (!strcmp("nfs", mntEnt.mnt_type))
271 *penmType = RTFSTYPE_NFS;
272 else if (!strcmp("nfs4", mntEnt.mnt_type))
273 *penmType = RTFSTYPE_NFS;
274 else if (!strcmp("ocfs2", mntEnt.mnt_type))
275 *penmType = RTFSTYPE_OCFS2;
276 else if (!strcmp("sysfs", mntEnt.mnt_type))
277 *penmType = RTFSTYPE_SYSFS;
278 else if (!strcmp("proc", mntEnt.mnt_type))
279 *penmType = RTFSTYPE_PROC;
280 else if ( !strcmp("fuse", mntEnt.mnt_type)
281 || !strncmp("fuse.", mntEnt.mnt_type, 5)
282 || !strcmp("fuseblk", mntEnt.mnt_type))
283 *penmType = RTFSTYPE_FUSE;
284 else
285 {
286 /* sometimes there are more than one entry for the same partition */
287 continue;
288 }
289 break;
290 }
291 }
292 }
293 endmntent(mounted);
294 }
295
296#elif defined(RT_OS_SOLARIS)
297 /*
298 * Home directories are normally loopback mounted in Solaris 11 (st_fstype=="lofs")
299 * so statvfs(2) is needed to get the underlying file system information.
300 */
301 struct statvfs statvfsBuf;
302 if (!statvfs(pszNativeFsPath, &statvfsBuf))
303 {
304 if (!strcmp("zfs", statvfsBuf.f_basetype))
305 *penmType = RTFSTYPE_ZFS;
306 else if (!strcmp("ufs", statvfsBuf.f_basetype))
307 *penmType = RTFSTYPE_UFS;
308 else if (!strcmp("nfs", statvfsBuf.f_basetype))
309 *penmType = RTFSTYPE_NFS;
310 }
311
312#elif defined(RT_OS_DARWIN) || defined(RT_OS_FREEBSD)
313 struct statfs statfsBuf;
314 if (!statfs(pszNativeFsPath, &statfsBuf))
315 {
316 if (!strcmp("hfs", statfsBuf.f_fstypename))
317 *penmType = RTFSTYPE_HFS;
318 else if (!strcmp("apfs", statfsBuf.f_fstypename)) /** @todo verify apfs signature. */
319 *penmType = RTFSTYPE_APFS;
320 else if ( !strcmp("fat", statfsBuf.f_fstypename)
321 || !strcmp("msdos", statfsBuf.f_fstypename))
322 *penmType = RTFSTYPE_FAT;
323 else if (!strcmp("ntfs", statfsBuf.f_fstypename))
324 *penmType = RTFSTYPE_NTFS;
325 else if (!strcmp("autofs", statfsBuf.f_fstypename))
326 *penmType = RTFSTYPE_AUTOFS;
327 else if (!strcmp("devfs", statfsBuf.f_fstypename))
328 *penmType = RTFSTYPE_DEVFS;
329 else if (!strcmp("nfs", statfsBuf.f_fstypename))
330 *penmType = RTFSTYPE_NFS;
331 else if (!strcmp("ufs", statfsBuf.f_fstypename))
332 *penmType = RTFSTYPE_UFS;
333 else if (!strcmp("zfs", statfsBuf.f_fstypename))
334 *penmType = RTFSTYPE_ZFS;
335 }
336 else
337 rc = RTErrConvertFromErrno(errno);
338#endif
339 }
340 else
341 rc = RTErrConvertFromErrno(errno);
342 rtPathFreeNative(pszNativeFsPath, pszFsPath);
343 }
344
345 return rc;
346}
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use