1/* 2 Unix SMB/CIFS implementation. 3 System QUOTA function wrappers for XFS 4 Copyright (C) Stefan (metze) Metzmacher 2003 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 3 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program. If not, see <http://www.gnu.org/licenses/>. 18*/ 19 20 21#include "includes.h" 22 23#undef DBGC_CLASS 24#define DBGC_CLASS DBGC_QUOTA 25 26#ifndef HAVE_SYS_QUOTAS 27#ifdef HAVE_XFS_QUOTAS 28#undef HAVE_XFS_QUOTAS 29#endif 30#endif 31 32#ifdef HAVE_XFS_QUOTAS 33 34#ifdef HAVE_LINUX_XFS_QUOTAS 35#include "samba_linux_quota.h" 36#ifdef HAVE_LINUX_DQBLK_XFS_H 37#include <linux/dqblk_xfs.h> 38#endif 39#define HAVE_GROUP_QUOTA 40#else /* IRIX */ 41#include <sys/quota.h> 42#endif 43 44/* on IRIX */ 45#ifndef Q_XQUOTAON 46#define Q_XQUOTAON Q_QUOTAON 47#endif /* Q_XQUOTAON */ 48#ifndef Q_XQUOTAOFF 49#define Q_XQUOTAOFF Q_QUOTAOFF 50#endif /* Q_XQUOTAOFF */ 51#ifndef Q_XGETQSTAT 52#define Q_XGETQSTAT Q_GETQSTAT 53#endif /* Q_XGETQSTAT */ 54 55/* currently doesn't support Group and Project quotas on IRIX 56 */ 57 58#ifndef QCMD 59#define QCMD(x,y) x 60#endif 61 62/* 63 * IRIX has BBSIZE in <sys/param.h> 64 */ 65#ifndef BBSHIFT 66#define BBSHIFT 9 67#endif /* BBSHIFT */ 68#ifndef BBSIZE 69#define BBSIZE (1<<BBSHIFT) 70#endif /* BBSIZE */ 71 72/**************************************************************************** 73 Abstract out the XFS Quota Manager quota get call. 74****************************************************************************/ 75int sys_get_xfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp) 76{ 77 int ret = -1; 78 uint32 qflags = 0; 79 uint64_t bsize = (uint64_t)BBSIZE; 80 struct fs_disk_quota D; 81 struct fs_quota_stat F; 82 ZERO_STRUCT(D); 83 ZERO_STRUCT(F); 84 85 if (!bdev||!dp) 86 smb_panic("sys_get_xfs_quota: called with NULL pointer"); 87 88 ZERO_STRUCT(*dp); 89 dp->qtype = qtype; 90 91 switch (qtype) { 92 case SMB_USER_QUOTA_TYPE: 93 DEBUG(10,("sys_get_xfs_quota: path[%s] bdev[%s] SMB_USER_QUOTA_TYPE uid[%u]\n", 94 path, bdev, (unsigned)id.uid)); 95 96 if ((ret=quotactl(QCMD(Q_XGETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D))) 97 return ret; 98 break; 99#ifdef HAVE_GROUP_QUOTA 100 case SMB_GROUP_QUOTA_TYPE: 101 DEBUG(10,("sys_get_xfs_quota: path[%s] bdev[%s] SMB_GROUP_QUOTA_TYPE gid[%u]\n", 102 path, bdev, (unsigned)id.gid)); 103 104 if ((ret=quotactl(QCMD(Q_XGETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D))) 105 return ret; 106 break; 107#endif /* HAVE_GROUP_QUOTA */ 108 case SMB_USER_FS_QUOTA_TYPE: 109 DEBUG(10,("sys_get_xfs_quota: path[%s] bdev[%s] SMB_USER_FS_QUOTA_TYPE (uid[%u])\n", 110 path, bdev, (unsigned)id.uid)); 111 112 quotactl(QCMD(Q_XGETQSTAT,USRQUOTA), bdev, -1, (caddr_t)&F); 113 114 if (F.qs_flags & XFS_QUOTA_UDQ_ENFD) { 115 qflags |= QUOTAS_DENY_DISK; 116 } 117 else if (F.qs_flags & XFS_QUOTA_UDQ_ACCT) { 118 qflags |= QUOTAS_ENABLED; 119 } 120 121 ret = 0; 122 123 break; 124#ifdef HAVE_GROUP_QUOTA 125 case SMB_GROUP_FS_QUOTA_TYPE: 126 DEBUG(10,("sys_get_xfs_quota: path[%s] bdev[%s] SMB_GROUP_FS_QUOTA_TYPE (gid[%u])\n", 127 path, bdev, (unsigned)id.gid)); 128 129 quotactl(QCMD(Q_XGETQSTAT,GRPQUOTA), bdev, -1, (caddr_t)&F); 130 131 if (F.qs_flags & XFS_QUOTA_GDQ_ENFD) { 132 qflags |= QUOTAS_DENY_DISK; 133 } 134 else if (F.qs_flags & XFS_QUOTA_GDQ_ACCT) { 135 qflags |= QUOTAS_ENABLED; 136 } 137 138 ret = 0; 139 140 break; 141#endif /* HAVE_GROUP_QUOTA */ 142 default: 143 errno = ENOSYS; 144 return -1; 145 } 146 147 dp->bsize = bsize; 148 dp->softlimit = (uint64_t)D.d_blk_softlimit; 149 dp->hardlimit = (uint64_t)D.d_blk_hardlimit; 150 dp->ihardlimit = (uint64_t)D.d_ino_hardlimit; 151 dp->isoftlimit = (uint64_t)D.d_ino_softlimit; 152 dp->curinodes = (uint64_t)D.d_icount; 153 dp->curblocks = (uint64_t)D.d_bcount; 154 dp->qflags = qflags; 155 156 return ret; 157} 158 159/**************************************************************************** 160 Abstract out the XFS Quota Manager quota set call. 161****************************************************************************/ 162int sys_set_xfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp) 163{ 164 int ret = -1; 165 uint32 qflags = 0; 166 uint64_t bsize = (uint64_t)BBSIZE; 167 struct fs_disk_quota D; 168 struct fs_quota_stat F; 169 int q_on = 0; 170 int q_off = 0; 171 ZERO_STRUCT(D); 172 ZERO_STRUCT(F); 173 174 if (!bdev||!dp) 175 smb_panic("sys_set_xfs_quota: called with NULL pointer"); 176 177 if (bsize == dp->bsize) { 178 D.d_blk_softlimit = dp->softlimit; 179 D.d_blk_hardlimit = dp->hardlimit; 180 D.d_ino_hardlimit = dp->ihardlimit; 181 D.d_ino_softlimit = dp->isoftlimit; 182 } else { 183 D.d_blk_softlimit = (dp->softlimit*dp->bsize)/bsize; 184 D.d_blk_hardlimit = (dp->hardlimit*dp->bsize)/bsize; 185 D.d_ino_hardlimit = (dp->ihardlimit*dp->bsize)/bsize; 186 D.d_ino_softlimit = (dp->isoftlimit*dp->bsize)/bsize; 187 } 188 189 qflags = dp->qflags; 190 191 switch (qtype) { 192 case SMB_USER_QUOTA_TYPE: 193 DEBUG(10,("sys_set_xfs_quota: path[%s] bdev[%s] SMB_USER_QUOTA_TYPE uid[%u]\n", 194 path, bdev, (unsigned)id.uid)); 195 196 D.d_fieldmask |= FS_DQ_LIMIT_MASK; 197 ret = quotactl(QCMD(Q_XSETQLIM,USRQUOTA), bdev, id.uid, (caddr_t)&D); 198 break; 199#ifdef HAVE_GROUP_QUOTA 200 case SMB_GROUP_QUOTA_TYPE: 201 DEBUG(10,("sys_set_xfs_quota: path[%s] bdev[%s] SMB_GROUP_QUOTA_TYPE gid[%u]\n", 202 path, bdev, (unsigned)id.gid)); 203 204 D.d_fieldmask |= FS_DQ_LIMIT_MASK; 205 ret = quotactl(QCMD(Q_XSETQLIM,GRPQUOTA), bdev, id.gid, (caddr_t)&D); 206 break; 207#endif /* HAVE_GROUP_QUOTA */ 208 case SMB_USER_FS_QUOTA_TYPE: 209 DEBUG(10,("sys_set_xfs_quota: path[%s] bdev[%s] SMB_USER_FS_QUOTA_TYPE (uid[%u])\n", 210 path, bdev, (unsigned)id.uid)); 211 212 quotactl(QCMD(Q_XGETQSTAT,USRQUOTA), bdev, -1, (caddr_t)&F); 213 214 if (qflags & QUOTAS_DENY_DISK) { 215 if (!(F.qs_flags & XFS_QUOTA_UDQ_ENFD)) 216 q_on |= XFS_QUOTA_UDQ_ENFD; 217 if (!(F.qs_flags & XFS_QUOTA_UDQ_ACCT)) 218 q_on |= XFS_QUOTA_UDQ_ACCT; 219 220 if (q_on != 0) { 221 ret = quotactl(QCMD(Q_XQUOTAON,USRQUOTA),bdev, -1, (caddr_t)&q_on); 222 } else { 223 ret = 0; 224 } 225 226 } else if (qflags & QUOTAS_ENABLED) { 227 if (F.qs_flags & XFS_QUOTA_UDQ_ENFD) 228 q_off |= XFS_QUOTA_UDQ_ENFD; 229 230 if (q_off != 0) { 231 ret = quotactl(QCMD(Q_XQUOTAOFF,USRQUOTA),bdev, -1, (caddr_t)&q_off); 232 } else { 233 ret = 0; 234 } 235 236 if (!(F.qs_flags & XFS_QUOTA_UDQ_ACCT)) 237 q_on |= XFS_QUOTA_UDQ_ACCT; 238 239 if (q_on != 0) { 240 ret = quotactl(QCMD(Q_XQUOTAON,USRQUOTA),bdev, -1, (caddr_t)&q_on); 241 } else { 242 ret = 0; 243 } 244 } else { 245#if 0 246 /* Switch on XFS_QUOTA_UDQ_ACCT didn't work! 247 * only swittching off XFS_QUOTA_UDQ_ACCT work 248 */ 249 if (F.qs_flags & XFS_QUOTA_UDQ_ENFD) 250 q_off |= XFS_QUOTA_UDQ_ENFD; 251 if (F.qs_flags & XFS_QUOTA_UDQ_ACCT) 252 q_off |= XFS_QUOTA_UDQ_ACCT; 253 254 if (q_off !=0) { 255 ret = quotactl(QCMD(Q_XQUOTAOFF,USRQUOTA),bdev, -1, (caddr_t)&q_off); 256 } else { 257 ret = 0; 258 } 259#else 260 ret = -1; 261#endif 262 } 263 264 break; 265#ifdef HAVE_GROUP_QUOTA 266 case SMB_GROUP_FS_QUOTA_TYPE: 267 DEBUG(10,("sys_set_xfs_quota: path[%s] bdev[%s] SMB_GROUP_FS_QUOTA_TYPE (gid[%u])\n", 268 path, bdev, (unsigned)id.gid)); 269 270 quotactl(QCMD(Q_XGETQSTAT,GRPQUOTA), bdev, -1, (caddr_t)&F); 271 272 if (qflags & QUOTAS_DENY_DISK) { 273 if (!(F.qs_flags & XFS_QUOTA_GDQ_ENFD)) 274 q_on |= XFS_QUOTA_GDQ_ENFD; 275 if (!(F.qs_flags & XFS_QUOTA_GDQ_ACCT)) 276 q_on |= XFS_QUOTA_GDQ_ACCT; 277 278 if (q_on != 0) { 279 ret = quotactl(QCMD(Q_XQUOTAON,GRPQUOTA),bdev, -1, (caddr_t)&q_on); 280 } else { 281 ret = 0; 282 } 283 284 } else if (qflags & QUOTAS_ENABLED) { 285 if (F.qs_flags & XFS_QUOTA_GDQ_ENFD) 286 q_off |= XFS_QUOTA_GDQ_ENFD; 287 288 if (q_off != 0) { 289 ret = quotactl(QCMD(Q_XQUOTAOFF,GRPQUOTA),bdev, -1, (caddr_t)&q_off); 290 } else { 291 ret = 0; 292 } 293 294 if (!(F.qs_flags & XFS_QUOTA_GDQ_ACCT)) 295 q_on |= XFS_QUOTA_GDQ_ACCT; 296 297 if (q_on != 0) { 298 ret = quotactl(QCMD(Q_XQUOTAON,GRPQUOTA),bdev, -1, (caddr_t)&q_on); 299 } else { 300 ret = 0; 301 } 302 } else { 303#if 0 304 /* Switch on XFS_QUOTA_UDQ_ACCT didn't work! 305 * only swittching off XFS_QUOTA_UDQ_ACCT work 306 */ 307 if (F.qs_flags & XFS_QUOTA_GDQ_ENFD) 308 q_off |= XFS_QUOTA_GDQ_ENFD; 309 if (F.qs_flags & XFS_QUOTA_GDQ_ACCT) 310 q_off |= XFS_QUOTA_GDQ_ACCT; 311 312 if (q_off !=0) { 313 ret = quotactl(QCMD(Q_XQUOTAOFF,GRPQUOTA),bdev, -1, (caddr_t)&q_off); 314 } else { 315 ret = 0; 316 } 317#else 318 ret = -1; 319#endif 320 } 321 322 break; 323#endif /* HAVE_GROUP_QUOTA */ 324 default: 325 errno = ENOSYS; 326 return -1; 327 } 328 329 return ret; 330} 331 332#else /* HAVE_XFS_QUOTAS */ 333 void dummy_sysquotas_xfs(void); 334 335 void dummy_sysquotas_xfs(void){} 336#endif /* HAVE_XFS_QUOTAS */ 337