1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
15 Implementation of the disk information functions.
23 #include "pal/palinternal.h"
24 #include "pal/dbgmsg.h"
26 #include "pal/stackstring.hpp"
28 #include <sys/param.h>
29 #include <sys/mount.h>
32 #include <sys/types.h>
33 #include <sys/statvfs.h>
34 #define statfs statvfs
35 #if STATVFS64_PROTOTYPE_BROKEN
36 typedef statvfs_t pal_statfs;
37 #else // STATVFS64_PROTOTYPE_BROKEN
38 typedef struct statvfs pal_statfs;
39 #endif // STATVFS64_PROTOTYPE_BROKEN
41 typedef struct statfs pal_statfs;
42 #endif // HAVE_STATVFS
44 SET_DEFAULT_DEBUG_CHANNEL(FILE);
58 LPCWSTR lpDirectoryName,
59 LPDWORD lpSectorsPerCluster,
60 LPDWORD lpBytesPerSector,
61 LPDWORD lpNumberOfFreeClusters, /* Caller will ignore output value */
62 LPDWORD lpTotalNumberOfClusters) /* Caller will ignore output value */
65 pal_statfs fsInfoBuffer;
67 DWORD dwLastError = NO_ERROR;
68 PathCharString dirNameBufferPathString;
73 PERF_ENTRY(GetDiskFreeSpaceW);
74 ENTRY( "GetDiskFreeSpaceW( lpDirectoryName=%p (%S), lpSectorsPerCluster=%p,"
75 "lpBytesPerSector=%p, lpNumberOfFreeClusters=%p, "
76 "lpTotalNumberOfClusters=%p )\n", lpDirectoryName ? lpDirectoryName :
77 W16_NULLSTRING, lpDirectoryName ? lpDirectoryName :
78 W16_NULLSTRING, lpSectorsPerCluster, lpBytesPerSector,
79 lpNumberOfFreeClusters, lpTotalNumberOfClusters );
82 if ( !lpSectorsPerCluster )
84 ERROR( "lpSectorsPerCluster cannot be NULL!\n" );
85 dwLastError = ERROR_INVALID_PARAMETER;
88 if ( !lpBytesPerSector )
90 ERROR( "lpBytesPerSector cannot be NULL!\n" );
91 dwLastError = ERROR_INVALID_PARAMETER;
94 if ( lpNumberOfFreeClusters || lpTotalNumberOfClusters )
96 TRACE("GetDiskFreeSpaceW is ignoring lpNumberOfFreeClusters"
97 " and lpTotalNumberOfClusters\n" );
99 if ( lpDirectoryName && PAL_wcslen( lpDirectoryName ) == 0 )
101 ERROR( "lpDirectoryName is empty.\n" );
102 dwLastError = ERROR_INVALID_PARAMETER;
106 /* Fusion uses this API to round file sizes up to their actual size
107 on-disk based on the BytesPerSector * SectorsPerCluster.
108 The intent is to avoid computing the sum of all file sizes in the
109 cache just in bytes and not account for the cluster-sized slop, when
110 determining if the cache is too large or not. */
112 if ( lpDirectoryName )
114 length = (PAL_wcslen(lpDirectoryName)+1) * 3;
115 dirNameBuffer = dirNameBufferPathString.OpenStringBuffer(length);
116 if (NULL == dirNameBuffer)
118 dwLastError = ERROR_NOT_ENOUGH_MEMORY;
122 size = WideCharToMultiByte( CP_ACP, 0, lpDirectoryName, -1,
123 dirNameBuffer,length, 0, 0 );
124 dirNameBufferPathString.CloseBuffer(size);
127 FILEDosToUnixPathA( dirNameBuffer );
128 statfsRetVal = statfs( dirNameBuffer, &fsInfoBuffer );
132 ASSERT( "Unable to convert the lpDirectoryName to multibyte.\n" );
133 dwLastError = ERROR_INTERNAL_ERROR;
139 statfsRetVal = statfs( "/", &fsInfoBuffer );
142 if ( statfsRetVal == 0 )
144 *lpBytesPerSector = fsInfoBuffer.f_bsize;
145 *lpSectorsPerCluster = 1;
150 if ( errno == ENOTDIR || errno == ENOENT )
152 FILEGetProperNotFoundError( dirNameBuffer, &dwLastError );
155 dwLastError = FILEGetLastErrorFromErrno();
156 if ( ERROR_INTERNAL_ERROR == dwLastError )
158 ASSERT("statfs() not expected to fail with errno:%d (%s)\n",
159 errno, strerror(errno));
163 TRACE("statfs() failed, errno:%d (%s)\n", errno, strerror(errno));
168 if ( NO_ERROR != dwLastError )
170 SetLastError( dwLastError );
173 LOGEXIT( "GetDiskFreeSpace returning %s.\n", bRetVal == TRUE ? "TRUE" : "FALSE" );
174 PERF_EXIT(GetDiskFreeSpaceW);