/src/samba/source3/lib/sysquotas_linux.c
Line | Count | Source (jump to first uncovered line) |
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 | 0 | #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 | 0 | { |
42 | 0 | int ret = -1; |
43 | 0 | uint32_t qflags = 0; |
44 | 0 | struct dqblk D; |
45 | 0 | uint64_t bsize = (uint64_t)QUOTABLOCK_SIZE; |
46 | |
|
47 | 0 | if (!path || !bdev || !dp) { |
48 | 0 | smb_panic("sys_get_vfs_quota: called with NULL pointer"); |
49 | 0 | } |
50 | | |
51 | 0 | ZERO_STRUCT(*dp); |
52 | 0 | dp->qtype = qtype; |
53 | |
|
54 | 0 | ZERO_STRUCT(D); |
55 | |
|
56 | 0 | switch (qtype) { |
57 | 0 | case SMB_USER_QUOTA_TYPE: |
58 | 0 | DEBUG(10, ("sys_get_vfs_quota: path[%s] bdev[%s] " |
59 | 0 | "SMB_USER_QUOTA_TYPE uid[%u]\n", |
60 | 0 | path, bdev, (unsigned)id.uid)); |
61 | |
|
62 | 0 | if ((ret = quotactl(QCMD(Q_GETQUOTA, USRQUOTA), bdev, |
63 | 0 | id.uid, (caddr_t)&D))) { |
64 | 0 | return ret; |
65 | 0 | } |
66 | | |
67 | 0 | break; |
68 | 0 | case SMB_GROUP_QUOTA_TYPE: |
69 | 0 | DEBUG(10, ("sys_get_vfs_quota: path[%s] bdev[%s] " |
70 | 0 | "SMB_GROUP_QUOTA_TYPE gid[%u]\n", |
71 | 0 | path, bdev, (unsigned)id.gid)); |
72 | |
|
73 | 0 | if ((ret = quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), bdev, |
74 | 0 | id.gid, (caddr_t)&D))) { |
75 | 0 | return ret; |
76 | 0 | } |
77 | | |
78 | 0 | break; |
79 | 0 | case SMB_USER_FS_QUOTA_TYPE: |
80 | 0 | DEBUG(10, ("sys_get_vfs_quota: path[%s] bdev[%s] " |
81 | 0 | "SMB_USER_FS_QUOTA_TYPE (uid[%u])\n", |
82 | 0 | path, bdev, (unsigned)geteuid())); |
83 | |
|
84 | 0 | if ((ret = quotactl(QCMD(Q_GETQUOTA, USRQUOTA), bdev, |
85 | 0 | geteuid(), (caddr_t)&D)) == 0) { |
86 | 0 | qflags |= QUOTAS_DENY_DISK; |
87 | 0 | } |
88 | |
|
89 | 0 | ret = 0; |
90 | |
|
91 | 0 | break; |
92 | 0 | case SMB_GROUP_FS_QUOTA_TYPE: |
93 | 0 | DEBUG(10, ("sys_get_vfs_quota: path[%s] bdev[%s] " |
94 | 0 | "SMB_GROUP_FS_QUOTA_TYPE (gid[%u])\n", |
95 | 0 | path, bdev, (unsigned)getegid())); |
96 | |
|
97 | 0 | if ((ret = quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), bdev, |
98 | 0 | getegid(), (caddr_t)&D)) == 0) { |
99 | 0 | qflags |= QUOTAS_DENY_DISK; |
100 | 0 | } |
101 | |
|
102 | 0 | ret = 0; |
103 | 0 | break; |
104 | 0 | default: |
105 | 0 | errno = ENOSYS; |
106 | 0 | return -1; |
107 | 0 | } |
108 | | |
109 | 0 | dp->bsize = bsize; |
110 | 0 | dp->softlimit = (uint64_t)D.dqb_bsoftlimit; |
111 | 0 | dp->hardlimit = (uint64_t)D.dqb_bhardlimit; |
112 | 0 | dp->ihardlimit = (uint64_t)D.dqb_ihardlimit; |
113 | 0 | dp->isoftlimit = (uint64_t)D.dqb_isoftlimit; |
114 | 0 | dp->curinodes = (uint64_t)D.dqb_curinodes; |
115 | 0 | dp->curblocks = (uint64_t)D.dqb_curspace/bsize; |
116 | | |
117 | |
|
118 | 0 | dp->qflags = qflags; |
119 | |
|
120 | 0 | return ret; |
121 | 0 | } |
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 | 0 | { |
129 | 0 | int ret = -1; |
130 | 0 | struct dqblk D; |
131 | 0 | uint64_t bsize = (uint64_t)QUOTABLOCK_SIZE; |
132 | 0 | bool cur_enf, new_enf; |
133 | |
|
134 | 0 | if (!path || !bdev || !dp) { |
135 | 0 | smb_panic("sys_set_vfs_quota: called with NULL pointer"); |
136 | 0 | } |
137 | | |
138 | 0 | ZERO_STRUCT(D); |
139 | |
|
140 | 0 | if (bsize == dp->bsize) { |
141 | 0 | D.dqb_bsoftlimit = dp->softlimit; |
142 | 0 | D.dqb_bhardlimit = dp->hardlimit; |
143 | 0 | } else { |
144 | 0 | D.dqb_bsoftlimit = (dp->softlimit*dp->bsize)/bsize; |
145 | 0 | D.dqb_bhardlimit = (dp->hardlimit*dp->bsize)/bsize; |
146 | 0 | } |
147 | 0 | D.dqb_ihardlimit = dp->ihardlimit; |
148 | 0 | D.dqb_isoftlimit = dp->isoftlimit; |
149 | 0 | D.dqb_valid = QIF_LIMITS; |
150 | |
|
151 | 0 | switch (qtype) { |
152 | 0 | case SMB_USER_QUOTA_TYPE: |
153 | 0 | DEBUG(10, ("sys_set_vfs_quota: path[%s] bdev[%s] " |
154 | 0 | "SMB_USER_QUOTA_TYPE uid[%u]\n", |
155 | 0 | path, bdev, (unsigned)id.uid)); |
156 | |
|
157 | 0 | ret = quotactl(QCMD(Q_SETQUOTA,USRQUOTA), bdev, id.uid, (caddr_t)&D); |
158 | 0 | break; |
159 | 0 | case SMB_GROUP_QUOTA_TYPE: |
160 | 0 | DEBUG(10, ("sys_set_vfs_quota: path[%s] bdev[%s] " |
161 | 0 | "SMB_GROUP_QUOTA_TYPE gid[%u]\n", |
162 | 0 | path, bdev, (unsigned)id.gid)); |
163 | |
|
164 | 0 | ret = quotactl(QCMD(Q_SETQUOTA,GRPQUOTA), bdev, id.gid, (caddr_t)&D); |
165 | 0 | break; |
166 | 0 | case SMB_USER_FS_QUOTA_TYPE: |
167 | 0 | DEBUG(10, ("sys_set_vfs_quota: path[%s] bdev[%s] " |
168 | 0 | "SMB_USER_FS_QUOTA_TYPE (uid[%u])\n", |
169 | 0 | path, bdev, (unsigned)geteuid())); |
170 | |
|
171 | 0 | ret = quotactl(QCMD(Q_GETQUOTA, USRQUOTA), bdev, |
172 | 0 | geteuid(), (caddr_t)&D); |
173 | 0 | cur_enf = (ret == 0); |
174 | 0 | 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 | 0 | if (cur_enf == new_enf) { |
180 | 0 | ret = 0; |
181 | 0 | } else { |
182 | 0 | errno = EPERM; |
183 | 0 | ret = -1; |
184 | 0 | } |
185 | |
|
186 | 0 | break; |
187 | 0 | case SMB_GROUP_FS_QUOTA_TYPE: |
188 | 0 | DEBUG(10, ("sys_set_vfs_quota: path[%s] bdev[%s] " |
189 | 0 | "SMB_GROUP_FS_QUOTA_TYPE (gid[%u])\n", |
190 | 0 | path, bdev, (unsigned)getegid())); |
191 | |
|
192 | 0 | ret = quotactl(QCMD(Q_GETQUOTA, GRPQUOTA), bdev, |
193 | 0 | getegid(), (caddr_t)&D); |
194 | 0 | cur_enf = (ret == 0); |
195 | 0 | 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 | 0 | if (cur_enf == new_enf) { |
201 | 0 | ret = 0; |
202 | 0 | } else { |
203 | 0 | errno = EPERM; |
204 | 0 | ret = -1; |
205 | 0 | } |
206 | |
|
207 | 0 | break; |
208 | 0 | default: |
209 | 0 | errno = ENOSYS; |
210 | 0 | return -1; |
211 | 0 | } |
212 | | |
213 | 0 | return ret; |
214 | 0 | } |
215 | | |
216 | | #else /* HAVE_QUOTACTL_LINUX */ |
217 | | void dummy_sysquotas_linux(void); |
218 | | |
219 | | void dummy_sysquotas_linux(void){} |
220 | | #endif /* HAVE_QUOTACTL_LINUX */ |