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