forked from dotnet/corefx
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpal_mount.cpp
More file actions
128 lines (110 loc) · 3.37 KB
/
pal_mount.cpp
File metadata and controls
128 lines (110 loc) · 3.37 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
#include "pal_config.h"
#include "pal_mount.h"
#include "pal_utilities.h"
#include <assert.h>
#include <string.h>
#include <errno.h>
// Check if we should use getmntinfo or /proc/mounts
#if HAVE_MNTINFO
#include <sys/mount.h>
#else
#include <sys/statfs.h>
#include <mntent.h>
#define STRING_BUFFER_SIZE 8192
#endif
static int32_t GetMountInfo(MountPointFound onFound)
{
#if HAVE_MNTINFO
// getmntinfo returns pointers to OS-internal structs, so we don't need to worry about free'ing the object
struct statfs* mounts = nullptr;
int count = getmntinfo(&mounts, 0);
for (int32_t i = 0; i < count; i++)
{
onFound(mounts[i].f_mntonname);
}
return 0;
}
#else
int result = -1;
FILE* fp = setmntent("/proc/mounts", MNTOPT_RO);
if (fp != nullptr)
{
// The _r version of getmntent needs all buffers to be passed in; however, we don't know how big of a string
// buffer we will need, so pick something that seems like it will be big enough.
char buffer[STRING_BUFFER_SIZE] = {};
mntent entry;
while (getmntent_r(fp, &entry, buffer, STRING_BUFFER_SIZE) != nullptr)
{
onFound(entry.mnt_dir);
}
result = endmntent(fp);
assert(result == 1); // documented to always return 1
result =
0; // We need to standardize a success return code between our implementations, so settle on 0 for success
}
return result;
}
#endif
extern "C" int32_t GetAllMountPoints(MountPointFound onFound)
{
return GetMountInfo(onFound);
}
extern "C" int32_t GetSpaceInfoForMountPoint(const char* name, MountPointInformation* mpi)
{
assert(name != nullptr);
assert(mpi != nullptr);
struct statfs stats = {};
int result = statfs(name, &stats);
if (result == 0)
{
// Note that these have signed integer types on some platforms but musn't be negative.
// Also, upcast here (some platforms have smaller types) to 64-bit before multiplying to
// avoid overflow.
uint64_t bsize = UnsignedCast(stats.f_bsize);
uint64_t bavail = UnsignedCast(stats.f_bavail);
uint64_t bfree = UnsignedCast(stats.f_bfree);
uint64_t blocks = UnsignedCast(stats.f_blocks);
mpi->AvailableFreeSpace = bsize * bavail;
mpi->TotalFreeSpace = bsize * bfree;
mpi->TotalSize = bsize * blocks;
}
else
{
*mpi = {};
}
return result;
}
extern "C" int32_t
GetFormatInfoForMountPoint(const char* name, char* formatNameBuffer, int32_t bufferLength, int64_t* formatType)
{
assert((formatNameBuffer != nullptr) && (formatType != nullptr));
assert(bufferLength > 0);
struct statfs stats;
int result = statfs(name, &stats);
if (result == 0)
{
#if HAVE_STATFS_FSTYPENAME
if (bufferLength < MFSNAMELEN)
{
result = ERANGE;
*formatType = 0;
}
else
{
SafeStringCopy(formatNameBuffer, bufferLength, stats.f_fstypename);
*formatType = -1;
}
#else
assert(formatType != nullptr);
*formatType = stats.f_type;
SafeStringCopy(formatNameBuffer, bufferLength, "");
#endif
}
else
{
*formatType = 0;
}
return result;
}