Line data Source code
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 : #include "system/filesys.h" 24 : #include "smbd/smbd.h" 25 : 26 : #if defined(DARWINOS) 27 : #include <sys/attr.h> 28 : 29 : static int darwin_fs_capabilities(const char * path) 30 : { 31 : int caps = 0; 32 : vol_capabilities_attr_t *vcaps; 33 : struct attrlist attrlist; 34 : char attrbuf[sizeof(u_int32_t) + sizeof(vol_capabilities_attr_t)]; 35 : 36 : #define FORMAT_CAP(vinfo, cap) \ 37 : ( ((vinfo)->valid[VOL_CAPABILITIES_FORMAT] & (cap)) && \ 38 : ((vinfo)->capabilities[VOL_CAPABILITIES_FORMAT] & (cap)) ) 39 : 40 : #define INTERFACE_CAP(vinfo, cap) \ 41 : ( ((vinfo)->valid[VOL_CAPABILITIES_INTERFACES] & (cap)) && \ 42 : ((vinfo)->capabilities[VOL_CAPABILITIES_INTERFACES] & (cap)) ) 43 : 44 : ZERO_STRUCT(attrlist); 45 : attrlist.bitmapcount = ATTR_BIT_MAP_COUNT; 46 : attrlist.volattr = ATTR_VOL_CAPABILITIES; 47 : 48 : if (getattrlist(path, &attrlist, attrbuf, sizeof(attrbuf), 0) != 0) { 49 : DEBUG(0, ("getattrlist for %s capabilities failed: %s\n", 50 : path, strerror(errno))); 51 : /* Return no capabilities on failure. */ 52 : return 0; 53 : } 54 : 55 : vcaps = 56 : (vol_capabilities_attr_t *)(attrbuf + sizeof(u_int32_t)); 57 : 58 : if (FORMAT_CAP(vcaps, VOL_CAP_FMT_SPARSE_FILES)) { 59 : caps |= FILE_SUPPORTS_SPARSE_FILES; 60 : } 61 : 62 : if (FORMAT_CAP(vcaps, VOL_CAP_FMT_CASE_SENSITIVE)) { 63 : caps |= FILE_CASE_SENSITIVE_SEARCH; 64 : } 65 : 66 : if (FORMAT_CAP(vcaps, VOL_CAP_FMT_CASE_PRESERVING)) { 67 : caps |= FILE_CASE_PRESERVED_NAMES; 68 : } 69 : 70 : if (INTERFACE_CAP(vcaps, VOL_CAP_INT_EXTENDED_SECURITY)) { 71 : caps |= FILE_PERSISTENT_ACLS; 72 : } 73 : 74 : return caps; 75 : } 76 : #endif /* DARWINOS */ 77 : 78 : #if defined(BSD_STYLE_STATVFS) 79 : static int bsd_statvfs(const char *path, struct vfs_statvfs_struct *statbuf) 80 : { 81 : struct statfs sbuf; 82 : int ret; 83 : 84 : ret = statfs(path, &sbuf); 85 : if (ret == 0) { 86 : statbuf->OptimalTransferSize = sbuf.f_iosize; 87 : statbuf->BlockSize = sbuf.f_bsize; 88 : statbuf->TotalBlocks = sbuf.f_blocks; 89 : statbuf->BlocksAvail = sbuf.f_bfree; 90 : statbuf->UserBlocksAvail = sbuf.f_bavail; 91 : statbuf->TotalFileNodes = sbuf.f_files; 92 : statbuf->FreeFileNodes = sbuf.f_ffree; 93 : statbuf->FsIdentifier = 94 : (((uint64_t) sbuf.f_fsid.val[0] << 32) & 0xffffffff00000000LL) | 95 : (uint64_t) sbuf.f_fsid.val[1]; 96 : #ifdef DARWINOS 97 : statbuf->FsCapabilities = darwin_fs_capabilities(sbuf.f_mntonname); 98 : #else 99 : /* Try to extrapolate some of the fs flags into the 100 : * capabilities 101 : */ 102 : statbuf->FsCapabilities = 103 : FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES; 104 : #ifdef MNT_ACLS 105 : if (sbuf.f_flags & MNT_ACLS) 106 : statbuf->FsCapabilities |= FILE_PERSISTENT_ACLS; 107 : #endif 108 : #endif 109 : if (sbuf.f_flags & MNT_QUOTA) 110 : statbuf->FsCapabilities |= FILE_VOLUME_QUOTAS; 111 : if (sbuf.f_flags & MNT_RDONLY) 112 : statbuf->FsCapabilities |= FILE_READ_ONLY_VOLUME; 113 : } 114 : 115 : return ret; 116 : } 117 : #elif defined(STAT_STATVFS) && defined(HAVE_FSID_INT) 118 30712 : static int posix_statvfs(const char *path, struct vfs_statvfs_struct *statbuf) 119 : { 120 474 : struct statvfs statvfs_buf; 121 474 : int result; 122 : 123 30712 : result = statvfs(path, &statvfs_buf); 124 : 125 30712 : if (!result) { 126 : /* statvfs bsize is not the statfs bsize, the naming is terrible, 127 : * see bug 11810 */ 128 30712 : statbuf->OptimalTransferSize = statvfs_buf.f_bsize; 129 30712 : statbuf->BlockSize = statvfs_buf.f_frsize; 130 30712 : statbuf->TotalBlocks = statvfs_buf.f_blocks; 131 30712 : statbuf->BlocksAvail = statvfs_buf.f_bfree; 132 30712 : statbuf->UserBlocksAvail = statvfs_buf.f_bavail; 133 30712 : statbuf->TotalFileNodes = statvfs_buf.f_files; 134 30712 : statbuf->FreeFileNodes = statvfs_buf.f_ffree; 135 30712 : statbuf->FsIdentifier = statvfs_buf.f_fsid; 136 : /* Try to extrapolate some of the fs flags into the 137 : * capabilities 138 : */ 139 30712 : statbuf->FsCapabilities = 140 : FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES; 141 : #ifdef ST_QUOTA 142 : if (statvfs_buf.f_flag & ST_QUOTA) 143 : statbuf->FsCapabilities |= FILE_VOLUME_QUOTAS; 144 : #endif 145 30712 : if (statvfs_buf.f_flag & ST_RDONLY) 146 0 : statbuf->FsCapabilities |= FILE_READ_ONLY_VOLUME; 147 : 148 : #if defined(HAVE_FALLOC_FL_PUNCH_HOLE) && defined(HAVE_LSEEK_HOLE_DATA) 149 : /* 150 : * Only flag sparse file support if ZERO_DATA can be used to 151 : * deallocate blocks, and SEEK_HOLE / SEEK_DATA can be used 152 : * to provide QUERY_ALLOCATED_RANGES information. 153 : */ 154 30712 : statbuf->FsCapabilities |= FILE_SUPPORTS_SPARSE_FILES; 155 : #endif 156 : } 157 30712 : return result; 158 : } 159 : #endif 160 : 161 : /* 162 : sys_statvfs() is an abstraction layer over system-dependent statvfs()/statfs() 163 : for particular POSIX systems. Due to controversy of what is considered more important 164 : between LSB and FreeBSD/POSIX.1 (IEEE Std 1003.1-2001) we need to abstract the interface 165 : so that particular OS would use its preferred interface. 166 : */ 167 30712 : int sys_statvfs(const char *path, struct vfs_statvfs_struct *statbuf) 168 : { 169 : #if defined(BSD_STYLE_STATVFS) 170 : return bsd_statvfs(path, statbuf); 171 : #elif defined(STAT_STATVFS) && defined(HAVE_FSID_INT) 172 30712 : return posix_statvfs(path, statbuf); 173 : #else 174 : /* BB change this to return invalid level */ 175 : #ifdef EOPNOTSUPP 176 : return EOPNOTSUPP; 177 : #else 178 : return -1; 179 : #endif /* EOPNOTSUPP */ 180 : #endif /* LINUX */ 181 : 182 : }