1 /***
2 *drivfree.c - Get the size of a disk
3 *
4 * Copyright (c) Microsoft Corporation. All rights reserved.
5 *
6 *Purpose:
7 * This file has _getdiskfree()
8 *
9 *******************************************************************************/
10
11 #include <corecrt_internal.h>
12 #include <direct.h>
13
14
15
16 // Gets the size information for the given drive. The 'drive_number' must be a
17 // number, 1 through 26, corresponding to drives A: through Z:. Returns zero on
18 // success; a system error code on failure.
_getdiskfree(unsigned const drive_number,_diskfree_t * const result)19 extern "C" unsigned __cdecl _getdiskfree(
20 unsigned const drive_number,
21 _diskfree_t* const result
22 )
23 {
24 _VALIDATE_RETURN(result != nullptr, EINVAL, ERROR_INVALID_PARAMETER);
25 _VALIDATE_RETURN(drive_number <= 26, EINVAL, ERROR_INVALID_PARAMETER);
26
27 *result = _diskfree_t();
28
29 wchar_t drive_name_buffer[4] = { '_', ':', '\\', '\0' };
30
31 wchar_t const* const drive_name = drive_number == 0
32 ? nullptr
33 : drive_name_buffer;
34
35 if (drive_number != 0)
36 {
37 drive_name_buffer[0] = static_cast<wchar_t>(drive_number) + static_cast<wchar_t>(L'A' - 1);
38 }
39
40 static_assert(sizeof(result->sectors_per_cluster) == sizeof(DWORD), "Unexpected sizeof long");
41
42 if (!GetDiskFreeSpaceW(drive_name,
43 reinterpret_cast<LPDWORD>(&result->sectors_per_cluster),
44 reinterpret_cast<LPDWORD>(&result->bytes_per_sector),
45 reinterpret_cast<LPDWORD>(&result->avail_clusters),
46 reinterpret_cast<LPDWORD>(&result->total_clusters)))
47 {
48 int const os_error = GetLastError();
49 errno = __acrt_errno_from_os_error(os_error);
50
51 return os_error;
52 }
53
54 return 0;
55 }
56