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