lib/util: Standardize use of st_[acm]time ns
[samba.git] / source3 / lib / sysquotas_linux.c
1 /* 
2    Unix SMB/CIFS implementation.
3    System QUOTA function wrappers for LINUX
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_LINUX
28 #undef HAVE_QUOTACTL_LINUX
29 #endif
30 #endif
31
32 #ifdef HAVE_QUOTACTL_LINUX
33
34 #include <sys/quota.h>
35
36 /****************************************************************************
37  Linux quota get calls.
38 ****************************************************************************/
39 int sys_get_vfs_quota(const char *path, const char *bdev,
40                       enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
41 {
42         int ret = -1;
43         uint32_t qflags = 0;
44         struct dqblk D;
45         uint64_t bsize = (uint64_t)QUOTABLOCK_SIZE;
46
47         if (!path || !bdev || !dp) {
48                 smb_panic("sys_get_vfs_quota: called with NULL pointer");
49         }
50
51         ZERO_STRUCT(*dp);
52         dp->qtype = qtype;
53
54         ZERO_STRUCT(D);
55
56         switch (qtype) {
57                 case SMB_USER_QUOTA_TYPE:
58                         DEBUG(10, ("sys_get_vfs_quota: path[%s] bdev[%s] "
59                                    "SMB_USER_QUOTA_TYPE uid[%u]\n",
60                                    path, bdev, (unsigned)id.uid));
61
62                         if ((ret = quotactl(QCMD(Q_GETQUOTA, USRQUOTA), bdev,
63                                             id.uid, (caddr_t)&D))) {
64                                 return ret;
65                         }
66
67                         break;
68                 case SMB_GROUP_QUOTA_TYPE:
69                         DEBUG(10, ("sys_get_vfs_quota: path[%s] bdev[%s] "
70                                    "SMB_GROUP_QUOTA_TYPE gid[%u]\n",
71                                    path, bdev, (unsigned)id.gid));
72
73                         if ((ret = quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), bdev,
74                                             id.gid, (caddr_t)&D))) {
75                                 return ret;
76                         }
77
78                         break;
79                 case SMB_USER_FS_QUOTA_TYPE:
80                         DEBUG(10, ("sys_get_vfs_quota: path[%s] bdev[%s] "
81                                    "SMB_USER_FS_QUOTA_TYPE (uid[%u])\n",
82                                    path, bdev, (unsigned)geteuid()));
83
84                         if ((ret = quotactl(QCMD(Q_GETQUOTA, USRQUOTA), bdev,
85                                             geteuid(), (caddr_t)&D)) == 0) {
86                                 qflags |= QUOTAS_DENY_DISK;
87                         }
88
89                         ret = 0;
90
91                         break;
92                 case SMB_GROUP_FS_QUOTA_TYPE:
93                         DEBUG(10, ("sys_get_vfs_quota: path[%s] bdev[%s] "
94                                    "SMB_GROUP_FS_QUOTA_TYPE (gid[%u])\n",
95                                    path, bdev, (unsigned)getegid()));
96
97                         if ((ret = quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), bdev,
98                                             getegid(), (caddr_t)&D)) == 0) {
99                                 qflags |= QUOTAS_DENY_DISK;
100                         }
101
102                         ret = 0;
103                         break;
104                 default:
105                         errno = ENOSYS;
106                         return -1;
107         }
108
109         dp->bsize = bsize;
110         dp->softlimit = (uint64_t)D.dqb_bsoftlimit;
111         dp->hardlimit = (uint64_t)D.dqb_bhardlimit;
112         dp->ihardlimit = (uint64_t)D.dqb_ihardlimit;
113         dp->isoftlimit = (uint64_t)D.dqb_isoftlimit;
114         dp->curinodes = (uint64_t)D.dqb_curinodes;
115         dp->curblocks = (uint64_t)D.dqb_curspace/bsize;
116
117
118         dp->qflags = qflags;
119
120         return ret;
121 }
122
123 /****************************************************************************
124  Linux quota set calls.
125 ****************************************************************************/
126 int sys_set_vfs_quota(const char *path, const char *bdev,
127                       enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp)
128 {
129         int ret = -1;
130         struct dqblk D;
131         uint64_t bsize = (uint64_t)QUOTABLOCK_SIZE;
132         bool cur_enf, new_enf;
133
134         if (!path || !bdev || !dp) {
135                 smb_panic("sys_set_vfs_quota: called with NULL pointer");
136         }
137
138         ZERO_STRUCT(D);
139
140         if (bsize == dp->bsize) {
141                 D.dqb_bsoftlimit = dp->softlimit;
142                 D.dqb_bhardlimit = dp->hardlimit;
143         } else {
144                 D.dqb_bsoftlimit = (dp->softlimit*dp->bsize)/bsize;
145                 D.dqb_bhardlimit = (dp->hardlimit*dp->bsize)/bsize;
146         }
147         D.dqb_ihardlimit = dp->ihardlimit;
148         D.dqb_isoftlimit = dp->isoftlimit;
149         D.dqb_valid = QIF_LIMITS;
150
151         switch (qtype) {
152                 case SMB_USER_QUOTA_TYPE:
153                         DEBUG(10, ("sys_set_vfs_quota: path[%s] bdev[%s] "
154                                    "SMB_USER_QUOTA_TYPE uid[%u]\n",
155                                    path, bdev, (unsigned)id.uid));
156
157                         ret = quotactl(QCMD(Q_SETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D);
158                         break;
159                 case SMB_GROUP_QUOTA_TYPE:
160                         DEBUG(10, ("sys_set_vfs_quota: path[%s] bdev[%s] "
161                                    "SMB_GROUP_QUOTA_TYPE gid[%u]\n",
162                                    path, bdev, (unsigned)id.gid));
163
164                         ret = quotactl(QCMD(Q_SETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D);
165                         break;
166                 case SMB_USER_FS_QUOTA_TYPE:
167                         DEBUG(10, ("sys_set_vfs_quota: path[%s] bdev[%s] "
168                                    "SMB_USER_FS_QUOTA_TYPE (uid[%u])\n",
169                                    path, bdev, (unsigned)geteuid()));
170
171                         ret = quotactl(QCMD(Q_GETQUOTA, USRQUOTA), bdev,
172                                        geteuid(), (caddr_t)&D);
173                         cur_enf = (ret == 0);
174                         new_enf = ((dp->qflags & QUOTAS_DENY_DISK) != 0);
175                         /* We're not changing quota enforcement, so return
176                          * success
177                          * IFF the wanted state is identical to the current
178                          * state */
179                         if (cur_enf == new_enf) {
180                                 ret = 0;
181                         } else {
182                                 errno = EPERM;
183                                 ret = -1;
184                         }
185
186                         break;
187                 case SMB_GROUP_FS_QUOTA_TYPE:
188                         DEBUG(10, ("sys_set_vfs_quota: path[%s] bdev[%s] "
189                                    "SMB_GROUP_FS_QUOTA_TYPE (gid[%u])\n",
190                                    path, bdev, (unsigned)getegid()));
191
192                         ret = quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), bdev,
193                                        getegid(), (caddr_t)&D);
194                         cur_enf = (ret == 0);
195                         new_enf = ((dp->qflags & QUOTAS_DENY_DISK) != 0);
196                         /* We're not changing quota enforcement, so return
197                          * success
198                          * IFF the wanted state is identical to the current
199                          * state */
200                         if (cur_enf == new_enf) {
201                                 ret = 0;
202                         } else {
203                                 errno = EPERM;
204                                 ret = -1;
205                         }
206
207                         break;
208                 default:
209                         errno = ENOSYS;
210                         return -1;
211         }
212
213         return ret;
214 }
215
216 #else /* HAVE_QUOTACTL_LINUX */
217  void dummy_sysquotas_linux(void);
218
219  void dummy_sysquotas_linux(void){}
220 #endif /* HAVE_QUOTACTL_LINUX */