#include "includes.h"
#if defined(LINUX) && defined(HAVE_FSID_INT)
static int linux_statvfs(const char *path, vfs_statvfs_struct *statbuf)
{
struct statvfs statvfs_buf;
int result;
result = statvfs(path, &statvfs_buf);
if (!result) {
statbuf->OptimalTransferSize = statvfs_buf.f_frsize;
statbuf->BlockSize = statvfs_buf.f_bsize;
statbuf->TotalBlocks = statvfs_buf.f_blocks;
statbuf->BlocksAvail = statvfs_buf.f_bfree;
statbuf->UserBlocksAvail = statvfs_buf.f_bavail;
statbuf->TotalFileNodes = statvfs_buf.f_files;
statbuf->FreeFileNodes = statvfs_buf.f_ffree;
statbuf->FsIdentifier = statvfs_buf.f_fsid;
statbuf->FsCapabilities =
FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVING_NAMES;
}
return result;
}
#endif
#if defined(DARWINOS)
#include <sys/attr.h>
static int darwin_fs_capabilities(const char * path)
{
int caps = 0;
vol_capabilities_attr_t *vcaps;
struct attrlist attrlist;
char attrbuf[sizeof(u_int32_t) + sizeof(vol_capabilities_attr_t)];
#define FORMAT_CAP(vinfo, cap) \
( ((vinfo)->valid[VOL_CAPABILITIES_FORMAT] & (cap)) && \
((vinfo)->capabilities[VOL_CAPABILITIES_FORMAT] & (cap)) )
#define INTERFACE_CAP(vinfo, cap) \
( ((vinfo)->valid[VOL_CAPABILITIES_INTERFACES] & (cap)) && \
((vinfo)->capabilities[VOL_CAPABILITIES_INTERFACES] & (cap)) )
ZERO_STRUCT(attrlist);
attrlist.bitmapcount = ATTR_BIT_MAP_COUNT;
attrlist.volattr = ATTR_VOL_CAPABILITIES;
if (getattrlist(path, &attrlist, attrbuf, sizeof(attrbuf), 0) != 0) {
DEBUG(0, ("getattrlist for %s capabilities failed: %s\n",
path, strerror(errno)));
return 0;
}
vcaps =
(vol_capabilities_attr_t *)(attrbuf + sizeof(u_int32_t));
if (FORMAT_CAP(vcaps, VOL_CAP_FMT_SPARSE_FILES)) {
caps |= FILE_SUPPORTS_SPARSE_FILES;
}
if (FORMAT_CAP(vcaps, VOL_CAP_FMT_CASE_SENSITIVE)) {
caps |= FILE_CASE_SENSITIVE_SEARCH;
}
if (FORMAT_CAP(vcaps, VOL_CAP_FMT_CASE_PRESERVING)) {
caps |= FILE_CASE_PRESERVED_NAMES;
}
if (INTERFACE_CAP(vcaps, VOL_CAP_INT_EXTENDED_SECURITY)) {
caps |= FILE_PERSISTENT_ACLS;
}
if (INTERFACE_CAP(vcaps, VOL_CAP_INT_NAMEDSTREAMS) &&
INTERFACE_CAP(vcaps, VOL_CAP_INT_EXTENDED_ATTR)) {
caps |= FILE_NAMED_STREAMS;
}
return caps;
}
static int darwin_statvfs(const char *path, vfs_statvfs_struct *statbuf)
{
struct statfs sbuf;
int ret;
ret = statfs(path, &sbuf);
if (ret != 0) {
return ret;
}
statbuf->OptimalTransferSize = sbuf.f_iosize;
statbuf->BlockSize = sbuf.f_bsize;
statbuf->TotalBlocks = sbuf.f_blocks;
statbuf->BlocksAvail = sbuf.f_bfree;
statbuf->UserBlocksAvail = sbuf.f_bavail;
statbuf->TotalFileNodes = sbuf.f_files;
statbuf->FreeFileNodes = sbuf.f_ffree;
statbuf->FsIdentifier = *(SMB_BIG_UINT *)(&sbuf.f_fsid);
statbuf->FsCapabilities = darwin_fs_capabilities(sbuf.f_mntonname);
return 0;
}
#endif
int sys_statvfs(const char *path, vfs_statvfs_struct *statbuf)
{
#if defined(LINUX) && defined(HAVE_FSID_INT)
return linux_statvfs(path, statbuf);
#elif defined(DARWINOS)
return darwin_statvfs(path, statbuf);
#else
errno = ENOSYS;
return -1;
#endif
}