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>
30 // do we actually need this on other platforms. We don't seem to be using anything from there
31 #include <sys/mount.h>
35 #include <sys/types.h>
36 #include <sys/statvfs.h>
37 #define statfs statvfs
38 #if STATVFS64_PROTOTYPE_BROKEN
39 typedef statvfs_t pal_statfs;
40 #else // STATVFS64_PROTOTYPE_BROKEN
41 typedef struct statvfs pal_statfs;
42 #endif // STATVFS64_PROTOTYPE_BROKEN
44 typedef struct statfs pal_statfs;
45 #endif // HAVE_STATVFS
47 SET_DEFAULT_DEBUG_CHANNEL(FILE);
61 LPCWSTR lpDirectoryName,
62 LPDWORD lpSectorsPerCluster,
63 LPDWORD lpBytesPerSector,
64 LPDWORD lpNumberOfFreeClusters, /* Caller will ignore output value */
65 LPDWORD lpTotalNumberOfClusters) /* Caller will ignore output value */
68 pal_statfs fsInfoBuffer;
70 DWORD dwLastError = NO_ERROR;
71 PathCharString dirNameBufferPathString;
76 PERF_ENTRY(GetDiskFreeSpaceW);
77 ENTRY( "GetDiskFreeSpaceW( lpDirectoryName=%p (%S), lpSectorsPerCluster=%p,"
78 "lpBytesPerSector=%p, lpNumberOfFreeClusters=%p, "
79 "lpTotalNumberOfClusters=%p )\n", lpDirectoryName ? lpDirectoryName :
80 W16_NULLSTRING, lpDirectoryName ? lpDirectoryName :
81 W16_NULLSTRING, lpSectorsPerCluster, lpBytesPerSector,
82 lpNumberOfFreeClusters, lpTotalNumberOfClusters );
85 if ( !lpSectorsPerCluster )
87 ERROR( "lpSectorsPerCluster cannot be NULL!\n" );
88 dwLastError = ERROR_INVALID_PARAMETER;
91 if ( !lpBytesPerSector )
93 ERROR( "lpBytesPerSector cannot be NULL!\n" );
94 dwLastError = ERROR_INVALID_PARAMETER;
97 if ( lpNumberOfFreeClusters || lpTotalNumberOfClusters )
99 TRACE("GetDiskFreeSpaceW is ignoring lpNumberOfFreeClusters"
100 " and lpTotalNumberOfClusters\n" );
102 if ( lpDirectoryName && PAL_wcslen( lpDirectoryName ) == 0 )
104 ERROR( "lpDirectoryName is empty.\n" );
105 dwLastError = ERROR_INVALID_PARAMETER;
109 /* Fusion uses this API to round file sizes up to their actual size
110 on-disk based on the BytesPerSector * SectorsPerCluster.
111 The intent is to avoid computing the sum of all file sizes in the
112 cache just in bytes and not account for the cluster-sized slop, when
113 determining if the cache is too large or not. */
115 if ( lpDirectoryName )
117 length = (PAL_wcslen(lpDirectoryName)+1) * 3;
118 dirNameBuffer = dirNameBufferPathString.OpenStringBuffer(length);
119 if (NULL == dirNameBuffer)
121 dwLastError = ERROR_NOT_ENOUGH_MEMORY;
125 size = WideCharToMultiByte( CP_ACP, 0, lpDirectoryName, -1,
126 dirNameBuffer,length, 0, 0 );
127 dirNameBufferPathString.CloseBuffer(size);
130 FILEDosToUnixPathA( dirNameBuffer );
131 statfsRetVal = statfs( dirNameBuffer, &fsInfoBuffer );
135 ASSERT( "Unable to convert the lpDirectoryName to multibyte.\n" );
136 dwLastError = ERROR_INTERNAL_ERROR;
142 statfsRetVal = statfs( "/", &fsInfoBuffer );
145 if ( statfsRetVal == 0 )
147 *lpBytesPerSector = fsInfoBuffer.f_bsize;
148 *lpSectorsPerCluster = 1;
153 if ( errno == ENOTDIR || errno == ENOENT )
155 FILEGetProperNotFoundError( dirNameBuffer, &dwLastError );
158 dwLastError = FILEGetLastErrorFromErrno();
159 if ( ERROR_INTERNAL_ERROR == dwLastError )
161 ASSERT("statfs() not expected to fail with errno:%d (%s)\n",
162 errno, strerror(errno));
166 TRACE("statfs() failed, errno:%d (%s)\n", errno, strerror(errno));
171 if ( NO_ERROR != dwLastError )
173 SetLastError( dwLastError );
176 LOGEXIT( "GetDiskFreeSpace returning %s.\n", bRetVal == TRUE ? "TRUE" : "FALSE" );
177 PERF_EXIT(GetDiskFreeSpaceW);