s3-talloc Change TALLOC_P() to talloc()
[nivanova/samba-autobuild/.git] / source3 / lib / sysquotas_4A.c
1 /* 
2    Unix SMB/CIFS implementation.
3    System QUOTA function wrappers for QUOTACTL_4A
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_QUOTACTL_4A
28 #undef HAVE_QUOTACTL_4A
29 #endif
30 #endif
31
32 #ifdef HAVE_QUOTACTL_4A
33 /* long quotactl(int cmd, char *special, qid_t id, caddr_t addr) */
34 /* this is used by: HPUX,IRIX */
35
36 #ifdef HAVE_SYS_TYPES_H
37 #include <sys/types.h>
38 #endif
39
40 #ifdef HAVE_ASM_TYPES_H
41 #include <asm/types.h>
42 #endif
43
44 #ifdef HAVE_SYS_QUOTA_H
45 #include <sys/quota.h>
46 #endif
47
48 #ifndef Q_SETQLIM
49 #define Q_SETQLIM Q_SETQUOTA
50 #endif
51
52 #ifndef QCMD
53 #define QCMD(x,y) x
54 #endif
55
56 #ifndef QCMD
57 #define QCMD(x,y) x
58 #endif
59
60 #ifdef GRPQUOTA
61 #define HAVE_GROUP_QUOTA
62 #endif
63
64 #ifndef QUOTABLOCK_SIZE
65 #define QUOTABLOCK_SIZE DEV_BSIZE
66 #endif
67
68 #ifdef HAVE_DQB_FSOFTLIMIT
69 #define dqb_isoftlimit  dqb_fsoftlimit
70 #define dqb_ihardlimit  dqb_fhardlimit
71 #define dqb_curinodes   dqb_curfiles
72 #endif
73
74 #ifdef INITQFNAMES
75 #define USERQUOTAFILE_EXTENSION ".user"
76 #else
77 #define USERQUOTAFILE_EXTENSION ""
78 #endif
79
80 #if !defined(QUOTAFILENAME) && defined(QFILENAME)
81 #define QUOTAFILENAME QFILENAME
82 #endif
83
84 /****************************************************************************
85  Abstract out the quotactl_4A get calls.
86 ****************************************************************************/
87 int sys_get_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
88 {
89         int ret = -1;
90         uint32 qflags = 0;
91         struct dqblk D;
92         uint64_t bsize = (uint64_t)QUOTABLOCK_SIZE;
93
94         ZERO_STRUCT(D);
95         ZERO_STRUCT(*dp);
96         dp->qtype = qtype;
97
98         switch (qtype) {
99                 case SMB_USER_QUOTA_TYPE:
100                         DEBUG(10,("sys_get_vfs_quota: path[%s] bdev[%s] SMB_USER_QUOTA_TYPE uid[%u]\n",
101                                 path, bdev, (unsigned)id.uid));
102
103                         if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), (caddr_t)bdev, id.uid, (void *)&D))&&errno != EDQUOT) {
104                                 return ret;
105                         }
106
107                         if ((D.dqb_curblocks==0)&&
108                                 (D.dqb_bsoftlimit==0)&&
109                                 (D.dqb_bhardlimit==0)) {
110                                 /* the upper layer functions don't want empty quota records...*/
111                                 return -1;
112                         }
113
114                         break;
115 #ifdef HAVE_GROUP_QUOTA
116                 case SMB_GROUP_QUOTA_TYPE:
117                         DEBUG(10,("sys_get_vfs_quota: path[%s] bdev[%s] SMB_GROUP_QUOTA_TYPE gid[%u]\n",
118                                 path, bdev, (unsigned)id.gid));
119
120                         if ((ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), (caddr_t)bdev, id.gid, (void *)&D))&&errno != EDQUOT) {
121                                 return ret;
122                         }
123
124                         if ((D.dqb_curblocks==0)&&
125                                 (D.dqb_bsoftlimit==0)&&
126                                 (D.dqb_bhardlimit==0)) {
127                                 /* the upper layer functions don't want empty quota records...*/
128                                 return -1;
129                         }
130
131                         break;
132 #endif /* HAVE_GROUP_QUOTA */
133                 case SMB_USER_FS_QUOTA_TYPE:
134                         id.uid = getuid();
135
136                         DEBUG(10,("sys_get_vfs_quota: path[%s] bdev[%s] SMB_USER_FS_QUOTA_TYPE (uid[%u])\n",
137                                 path, (caddr_t)bdev, (unsigned)id.uid));
138
139                         if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), (caddr_t)bdev, id.uid, (void *)&D))==0) {
140                                 qflags |= QUOTAS_DENY_DISK;
141                         }
142
143                         ret = 0;
144                         break;
145 #ifdef HAVE_GROUP_QUOTA
146                 case SMB_GROUP_FS_QUOTA_TYPE:
147                         id.gid = getgid();
148
149                         DEBUG(10,("sys_get_vfs_quota: path[%s] bdev[%s] SMB_GROUP_FS_QUOTA_TYPE (gid[%u])\n",
150                                 path, bdev, (unsigned)id.gid));
151
152                         if ((ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), (caddr_t)bdev, id.gid, (void *)&D))==0) {
153                                 qflags |= QUOTAS_DENY_DISK;
154                         }
155
156                         ret = 0;
157                         break;
158 #endif /* HAVE_GROUP_QUOTA */
159                 default:
160                         errno = ENOSYS;
161                         return -1;
162         }
163
164         dp->bsize = bsize;
165         dp->softlimit = (uint64_t)D.dqb_bsoftlimit;
166         dp->hardlimit = (uint64_t)D.dqb_bhardlimit;
167         dp->ihardlimit = (uint64_t)D.dqb_ihardlimit;
168         dp->isoftlimit = (uint64_t)D.dqb_isoftlimit;
169         dp->curinodes = (uint64_t)D.dqb_curinodes;
170         dp->curblocks = (uint64_t)D.dqb_curblocks;
171
172
173         dp->qflags = qflags;
174
175         return ret;
176 }
177
178 /****************************************************************************
179  Abstract out the quotactl_4A set calls.
180 ****************************************************************************/
181 int sys_set_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
182 {
183         int ret = -1;
184         uint32 qflags = 0;
185         uint32 oldqflags = 0;
186         struct dqblk D;
187         uint64_t bsize = (uint64_t)QUOTABLOCK_SIZE;
188
189         ZERO_STRUCT(D);
190
191         if (bsize == dp->bsize) {
192                 D.dqb_bsoftlimit = dp->softlimit;
193                 D.dqb_bhardlimit = dp->hardlimit;
194                 D.dqb_ihardlimit = dp->ihardlimit;
195                 D.dqb_isoftlimit = dp->isoftlimit;
196         } else {
197                 D.dqb_bsoftlimit = (dp->softlimit*dp->bsize)/bsize;
198                 D.dqb_bhardlimit = (dp->hardlimit*dp->bsize)/bsize;
199                 D.dqb_ihardlimit = (dp->ihardlimit*dp->bsize)/bsize;
200                 D.dqb_isoftlimit = (dp->isoftlimit*dp->bsize)/bsize;
201         }
202
203         qflags = dp->qflags;
204
205         switch (qtype) {
206                 case SMB_USER_QUOTA_TYPE:
207                         DEBUG(10,("sys_set_vfs_quota: path[%s] bdev[%s] SMB_USER_QUOTA_TYPE uid[%u]\n",
208                                 path, bdev, (unsigned)id.uid));
209
210                         ret = quotactl(QCMD(Q_SETQLIM,USRQUOTA), (caddr_t)bdev, id.uid, (void *)&D);
211                         break;
212 #ifdef HAVE_GROUP_QUOTA
213                 case SMB_GROUP_QUOTA_TYPE:
214                         DEBUG(10,("sys_set_vfs_quota: path[%s] bdev[%s] SMB_GROUP_QUOTA_TYPE gid[%u]\n",
215                                 path, bdev, (unsigned)id.gid));
216
217                         ret = quotactl(QCMD(Q_SETQLIM,GRPQUOTA), (caddr_t)bdev, id.gid, (void *)&D);
218                         break;
219 #endif /* HAVE_GROUP_QUOTA */
220                 case SMB_USER_FS_QUOTA_TYPE:
221                         /* this stuff didn't work as it should:
222                          * switching on/off quota via quotactl()
223                          * didn't work!
224                          * So we just return 0
225                          * --metze
226                          * 
227                          * On HPUX we didn't have the mount path,
228                          * we need to fix sys_path_to_bdev()
229                          *
230                          */
231                         id.uid = getuid();
232                         DEBUG(10,("sys_set_vfs_quota: path[%s] bdev[%s] SMB_USER_FS_QUOTA_TYPE (uid[%u])\n",
233                                 path, bdev, (unsigned)id.uid));
234
235 #if 0
236                         ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), (caddr_t)bdev, id.uid, (void *)&D);
237
238                         if ((qflags&QUOTAS_DENY_DISK)||(qflags&QUOTAS_ENABLED)) {
239                                 if (ret == 0) {
240                                         char *quota_file = NULL;
241                                         
242                                         asprintf(&quota_file,"/%s/%s%s",path, QUOTAFILENAME,USERQUOTAFILE_EXTENSION);
243                                         if (quota_file == NULL) {
244                                                 DEBUG(0,("asprintf() failed!\n"));
245                                                 errno = ENOMEM;
246                                                 return -1;
247                                         }
248                                         
249                                         ret = quotactl(QCMD(Q_QUOTAON,USRQUOTA), (caddr_t)bdev, -1,(void *)quota_file);
250                                 } else {
251                                         ret = 0;        
252                                 }
253                         } else {
254                                 if (ret != 0) {
255                                         /* turn off */
256                                         ret = quotactl(QCMD(Q_QUOTAOFF,USRQUOTA), (caddr_t)bdev, -1, (void *)0);        
257                                 } else {
258                                         ret = 0;
259                                 }               
260                         }
261
262                         DEBUG(0,("sys_set_vfs_quota: ret(%d) errno(%d)[%s] uid(%d) bdev[%s]\n",
263                                 ret,errno,strerror(errno),id.uid,bdev));
264 #else
265                         if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), (caddr_t)bdev, id.uid, (void *)&D))==0) {
266                                 oldqflags |= QUOTAS_DENY_DISK;
267                         }
268
269                         if (oldqflags == qflags) {
270                                 ret = 0;
271                         } else {
272                                 ret = -1;
273                         }
274 #endif
275                         break;
276 #ifdef HAVE_GROUP_QUOTA
277                 case SMB_GROUP_FS_QUOTA_TYPE:
278                         /* this stuff didn't work as it should:
279                          * switching on/off quota via quotactl()
280                          * didn't work!
281                          * So we just return 0
282                          * --metze
283                          * 
284                          * On HPUX we didn't have the mount path,
285                          * we need to fix sys_path_to_bdev()
286                          *
287                          */
288                         id.gid = getgid();
289                         DEBUG(10,("sys_set_vfs_quota: path[%s] bdev[%s] SMB_GROUP_FS_QUOTA_TYPE (gid[%u])\n",
290                                 path, bdev, (unsigned)id.gid));
291
292 #if 0
293                         ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), bdev, id, (void *)&D);
294
295                         if ((qflags&QUOTAS_DENY_DISK)||(qflags&QUOTAS_ENABLED)) {
296                                 if (ret == 0) {
297                                         char *quota_file = NULL;
298                                         
299                                         asprintf(&quota_file,"/%s/%s%s",path, QUOTAFILENAME,GROUPQUOTAFILE_EXTENSION);
300                                         if (quota_file == NULL) {
301                                                 DEBUG(0,("asprintf() failed!\n"));
302                                                 errno = ENOMEM;
303                                                 return -1;
304                                         }
305                                         
306                                         ret = quotactl(QCMD(Q_QUOTAON,GRPQUOTA), (caddr_t)bdev, -1,(void *)quota_file);
307                                 } else {
308                                         ret = 0;        
309                                 }
310                         } else {
311                                 if (ret != 0) {
312                                         /* turn off */
313                                         ret = quotactl(QCMD(Q_QUOTAOFF,GRPQUOTA), (caddr_t)bdev, -1, (void *)0);        
314                                 } else {
315                                         ret = 0;
316                                 }               
317                         }
318
319                         DEBUG(0,("sys_set_vfs_quota: ret(%d) errno(%d)[%s] uid(%d) bdev[%s]\n",
320                                 ret,errno,strerror(errno),id.gid,bdev));
321 #else
322                         if ((ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), (caddr_t)bdev, id.gid, (void *)&D))==0) {
323                                 oldqflags |= QUOTAS_DENY_DISK;
324                         }
325
326                         if (oldqflags == qflags) {
327                                 ret = 0;
328                         } else {
329                                 ret = -1;
330                         }
331 #endif
332                         break;
333 #endif /* HAVE_GROUP_QUOTA */
334                 default:
335                         errno = ENOSYS;
336                         return -1;
337         }
338
339         return ret;
340 }
341
342 #else /* HAVE_QUOTACTL_4A */
343  void dummy_sysquotas_4A(void);
344
345  void dummy_sysquotas_4A(void){}
346 #endif /* HAVE_QUOTACTL_4A */