/src/samba/source3/lib/sysquotas_4A.c
Line | Count | Source |
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_t 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 | | ret = 0; |
108 | | break; |
109 | | #ifdef HAVE_GROUP_QUOTA |
110 | | case SMB_GROUP_QUOTA_TYPE: |
111 | | DEBUG(10,("sys_get_vfs_quota: path[%s] bdev[%s] SMB_GROUP_QUOTA_TYPE gid[%u]\n", |
112 | | path, bdev, (unsigned)id.gid)); |
113 | | |
114 | | if ((ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), (caddr_t)bdev, id.gid, (void *)&D))&&errno != EDQUOT) { |
115 | | return ret; |
116 | | } |
117 | | |
118 | | ret = 0; |
119 | | break; |
120 | | #endif /* HAVE_GROUP_QUOTA */ |
121 | | case SMB_USER_FS_QUOTA_TYPE: |
122 | | id.uid = getuid(); |
123 | | |
124 | | DEBUG(10,("sys_get_vfs_quota: path[%s] bdev[%s] SMB_USER_FS_QUOTA_TYPE (uid[%u])\n", |
125 | | path, (caddr_t)bdev, (unsigned)id.uid)); |
126 | | |
127 | | if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), (caddr_t)bdev, id.uid, (void *)&D))==0) { |
128 | | qflags |= QUOTAS_DENY_DISK; |
129 | | } |
130 | | |
131 | | ret = 0; |
132 | | break; |
133 | | #ifdef HAVE_GROUP_QUOTA |
134 | | case SMB_GROUP_FS_QUOTA_TYPE: |
135 | | id.gid = getgid(); |
136 | | |
137 | | DEBUG(10,("sys_get_vfs_quota: path[%s] bdev[%s] SMB_GROUP_FS_QUOTA_TYPE (gid[%u])\n", |
138 | | path, bdev, (unsigned)id.gid)); |
139 | | |
140 | | if ((ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), (caddr_t)bdev, id.gid, (void *)&D))==0) { |
141 | | qflags |= QUOTAS_DENY_DISK; |
142 | | } |
143 | | |
144 | | ret = 0; |
145 | | break; |
146 | | #endif /* HAVE_GROUP_QUOTA */ |
147 | | default: |
148 | | errno = ENOSYS; |
149 | | return -1; |
150 | | } |
151 | | |
152 | | dp->bsize = bsize; |
153 | | dp->softlimit = (uint64_t)D.dqb_bsoftlimit; |
154 | | dp->hardlimit = (uint64_t)D.dqb_bhardlimit; |
155 | | dp->ihardlimit = (uint64_t)D.dqb_ihardlimit; |
156 | | dp->isoftlimit = (uint64_t)D.dqb_isoftlimit; |
157 | | dp->curinodes = (uint64_t)D.dqb_curinodes; |
158 | | dp->curblocks = (uint64_t)D.dqb_curblocks; |
159 | | |
160 | | |
161 | | dp->qflags = qflags; |
162 | | |
163 | | return ret; |
164 | | } |
165 | | |
166 | | /**************************************************************************** |
167 | | Abstract out the quotactl_4A set calls. |
168 | | ****************************************************************************/ |
169 | | int sys_set_vfs_quota(const char *path, const char *bdev, enum SMB_QUOTA_TYPE qtype, unid_t id, SMB_DISK_QUOTA *dp) |
170 | | { |
171 | | int ret = -1; |
172 | | uint32_t qflags = 0; |
173 | | uint32_t oldqflags = 0; |
174 | | struct dqblk D; |
175 | | uint64_t bsize = (uint64_t)QUOTABLOCK_SIZE; |
176 | | |
177 | | ZERO_STRUCT(D); |
178 | | |
179 | | if (bsize == dp->bsize) { |
180 | | D.dqb_bsoftlimit = dp->softlimit; |
181 | | D.dqb_bhardlimit = dp->hardlimit; |
182 | | D.dqb_ihardlimit = dp->ihardlimit; |
183 | | D.dqb_isoftlimit = dp->isoftlimit; |
184 | | } else { |
185 | | D.dqb_bsoftlimit = (dp->softlimit*dp->bsize)/bsize; |
186 | | D.dqb_bhardlimit = (dp->hardlimit*dp->bsize)/bsize; |
187 | | D.dqb_ihardlimit = (dp->ihardlimit*dp->bsize)/bsize; |
188 | | D.dqb_isoftlimit = (dp->isoftlimit*dp->bsize)/bsize; |
189 | | } |
190 | | |
191 | | qflags = dp->qflags; |
192 | | |
193 | | switch (qtype) { |
194 | | case SMB_USER_QUOTA_TYPE: |
195 | | DEBUG(10,("sys_set_vfs_quota: path[%s] bdev[%s] SMB_USER_QUOTA_TYPE uid[%u]\n", |
196 | | path, bdev, (unsigned)id.uid)); |
197 | | |
198 | | ret = quotactl(QCMD(Q_SETQLIM,USRQUOTA), (caddr_t)bdev, id.uid, (void *)&D); |
199 | | break; |
200 | | #ifdef HAVE_GROUP_QUOTA |
201 | | case SMB_GROUP_QUOTA_TYPE: |
202 | | DEBUG(10,("sys_set_vfs_quota: path[%s] bdev[%s] SMB_GROUP_QUOTA_TYPE gid[%u]\n", |
203 | | path, bdev, (unsigned)id.gid)); |
204 | | |
205 | | ret = quotactl(QCMD(Q_SETQLIM,GRPQUOTA), (caddr_t)bdev, id.gid, (void *)&D); |
206 | | break; |
207 | | #endif /* HAVE_GROUP_QUOTA */ |
208 | | case SMB_USER_FS_QUOTA_TYPE: |
209 | | /* this stuff didn't work as it should: |
210 | | * switching on/off quota via quotactl() |
211 | | * didn't work! |
212 | | * So we just return 0 |
213 | | * --metze |
214 | | * |
215 | | * On HPUX we didn't have the mount path, |
216 | | * we need to fix sys_path_to_bdev() |
217 | | * |
218 | | */ |
219 | | id.uid = getuid(); |
220 | | DEBUG(10,("sys_set_vfs_quota: path[%s] bdev[%s] SMB_USER_FS_QUOTA_TYPE (uid[%u])\n", |
221 | | path, bdev, (unsigned)id.uid)); |
222 | | |
223 | | if ((ret = quotactl(QCMD(Q_GETQUOTA,USRQUOTA), (caddr_t)bdev, id.uid, (void *)&D))==0) { |
224 | | oldqflags |= QUOTAS_DENY_DISK; |
225 | | } |
226 | | |
227 | | if (oldqflags == qflags) { |
228 | | ret = 0; |
229 | | } else { |
230 | | ret = -1; |
231 | | } |
232 | | break; |
233 | | #ifdef HAVE_GROUP_QUOTA |
234 | | case SMB_GROUP_FS_QUOTA_TYPE: |
235 | | /* this stuff didn't work as it should: |
236 | | * switching on/off quota via quotactl() |
237 | | * didn't work! |
238 | | * So we just return 0 |
239 | | * --metze |
240 | | * |
241 | | * On HPUX we didn't have the mount path, |
242 | | * we need to fix sys_path_to_bdev() |
243 | | * |
244 | | */ |
245 | | id.gid = getgid(); |
246 | | DEBUG(10,("sys_set_vfs_quota: path[%s] bdev[%s] SMB_GROUP_FS_QUOTA_TYPE (gid[%u])\n", |
247 | | path, bdev, (unsigned)id.gid)); |
248 | | |
249 | | if ((ret = quotactl(QCMD(Q_GETQUOTA,GRPQUOTA), (caddr_t)bdev, id.gid, (void *)&D))==0) { |
250 | | oldqflags |= QUOTAS_DENY_DISK; |
251 | | } |
252 | | |
253 | | if (oldqflags == qflags) { |
254 | | ret = 0; |
255 | | } else { |
256 | | ret = -1; |
257 | | } |
258 | | break; |
259 | | #endif /* HAVE_GROUP_QUOTA */ |
260 | | default: |
261 | | errno = ENOSYS; |
262 | | return -1; |
263 | | } |
264 | | |
265 | | return ret; |
266 | | } |
267 | | |
268 | | #else /* HAVE_QUOTACTL_4A */ |
269 | | void dummy_sysquotas_4A(void); |
270 | | |
271 | 0 | void dummy_sysquotas_4A(void){} |
272 | | #endif /* HAVE_QUOTACTL_4A */ |