1/* 2 Unix SMB/CIFS implementation. 3 VFS API's statvfs abstraction 4 Copyright (C) Alexander Bokovoy 2005 5 Copyright (C) Steve French 2005 6 Copyright (C) James Peach 2006 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 3 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program. If not, see <http://www.gnu.org/licenses/>. 20*/ 21 22#include "includes.h" 23 24#if defined(LINUX) && defined(HAVE_FSID_INT) 25static int linux_statvfs(const char *path, vfs_statvfs_struct *statbuf) 26{ 27 struct statvfs statvfs_buf; 28 int result; 29 30 result = statvfs(path, &statvfs_buf); 31 32 if (!result) { 33 statbuf->OptimalTransferSize = statvfs_buf.f_frsize; 34 statbuf->BlockSize = statvfs_buf.f_bsize; 35 statbuf->TotalBlocks = statvfs_buf.f_blocks; 36 statbuf->BlocksAvail = statvfs_buf.f_bfree; 37 statbuf->UserBlocksAvail = statvfs_buf.f_bavail; 38 statbuf->TotalFileNodes = statvfs_buf.f_files; 39 statbuf->FreeFileNodes = statvfs_buf.f_ffree; 40 statbuf->FsIdentifier = statvfs_buf.f_fsid; 41 42 /* Good defaults for Linux filesystems are case sensitive 43 * and case preserving. 44 */ 45 statbuf->FsCapabilities = 46 FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES; 47 } 48 return result; 49} 50#endif 51 52#if defined(DARWINOS) 53 54#include <sys/attr.h> 55 56static int darwin_fs_capabilities(const char * path) 57{ 58 int caps = 0; 59 vol_capabilities_attr_t *vcaps; 60 struct attrlist attrlist; 61 char attrbuf[sizeof(u_int32_t) + sizeof(vol_capabilities_attr_t)]; 62 63#define FORMAT_CAP(vinfo, cap) \ 64 ( ((vinfo)->valid[VOL_CAPABILITIES_FORMAT] & (cap)) && \ 65 ((vinfo)->capabilities[VOL_CAPABILITIES_FORMAT] & (cap)) ) 66 67#define INTERFACE_CAP(vinfo, cap) \ 68 ( ((vinfo)->valid[VOL_CAPABILITIES_INTERFACES] & (cap)) && \ 69 ((vinfo)->capabilities[VOL_CAPABILITIES_INTERFACES] & (cap)) ) 70 71 ZERO_STRUCT(attrlist); 72 attrlist.bitmapcount = ATTR_BIT_MAP_COUNT; 73 attrlist.volattr = ATTR_VOL_CAPABILITIES; 74 75 if (getattrlist(path, &attrlist, attrbuf, sizeof(attrbuf), 0) != 0) { 76 DEBUG(0, ("getattrlist for %s capabilities failed: %s\n", 77 path, strerror(errno))); 78 /* Return no capabilities on failure. */ 79 return 0; 80 } 81 82 vcaps = 83 (vol_capabilities_attr_t *)(attrbuf + sizeof(u_int32_t)); 84 85 if (FORMAT_CAP(vcaps, VOL_CAP_FMT_SPARSE_FILES)) { 86 caps |= FILE_SUPPORTS_SPARSE_FILES; 87 } 88 89 if (FORMAT_CAP(vcaps, VOL_CAP_FMT_CASE_SENSITIVE)) { 90 caps |= FILE_CASE_SENSITIVE_SEARCH; 91 } 92 93 if (FORMAT_CAP(vcaps, VOL_CAP_FMT_CASE_PRESERVING)) { 94 caps |= FILE_CASE_PRESERVED_NAMES; 95 } 96 97 if (INTERFACE_CAP(vcaps, VOL_CAP_INT_EXTENDED_SECURITY)) { 98 caps |= FILE_PERSISTENT_ACLS; 99 } 100 101 return caps; 102} 103 104static int darwin_statvfs(const char *path, vfs_statvfs_struct *statbuf) 105{ 106 struct statfs sbuf; 107 int ret; 108 109 ret = statfs(path, &sbuf); 110 if (ret != 0) { 111 return ret; 112 } 113 114 statbuf->OptimalTransferSize = sbuf.f_iosize; 115 statbuf->BlockSize = sbuf.f_bsize; 116 statbuf->TotalBlocks = sbuf.f_blocks; 117 statbuf->BlocksAvail = sbuf.f_bfree; 118 statbuf->UserBlocksAvail = sbuf.f_bavail; 119 statbuf->TotalFileNodes = sbuf.f_files; 120 statbuf->FreeFileNodes = sbuf.f_ffree; 121 statbuf->FsIdentifier = *(uint64_t *)(&sbuf.f_fsid); /* Ick. */ 122 statbuf->FsCapabilities = darwin_fs_capabilities(sbuf.f_mntonname); 123 124 return 0; 125} 126#endif 127 128/* 129 sys_statvfs() is an abstraction layer over system-dependent statvfs()/statfs() 130 for particular POSIX systems. Due to controversy of what is considered more important 131 between LSB and FreeBSD/POSIX.1 (IEEE Std 1003.1-2001) we need to abstract the interface 132 so that particular OS would use its preffered interface. 133*/ 134int sys_statvfs(const char *path, vfs_statvfs_struct *statbuf) 135{ 136#if defined(LINUX) && defined(HAVE_FSID_INT) 137 return linux_statvfs(path, statbuf); 138#elif defined(DARWINOS) 139 return darwin_statvfs(path, statbuf); 140#else 141 /* BB change this to return invalid level */ 142#ifdef EOPNOTSUPP 143 return EOPNOTSUPP; 144#else 145 return -1; 146#endif /* EOPNOTSUPP */ 147#endif /* LINUX */ 148 149} 150