2 Unix SMB/CIFS implementation.
4 Copyright (C) Stefan (metze) Metzmacher 2003
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.
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.
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/>.
21 #include "smbd/smbd.h"
22 #include "../lib/util/util_pw.h"
23 #include "system/passwd.h"
24 #include "passdb/lookup_sid.h"
25 #include "libsmb/libsmb.h"
28 #define DBGC_CLASS DBGC_QUOTA
30 static uint64_t limit_nt2unix(uint64_t in
, uint64_t bsize
)
32 uint64_t ret
= (uint64_t)0;
34 ret
= (uint64_t)(in
/bsize
);
36 /* we have to make sure that a overflow didn't set NO_LIMIT */
40 if (in
== SMB_NTQUOTAS_NO_LIMIT
)
41 ret
= SMB_QUOTAS_NO_LIMIT
;
42 else if (in
== SMB_NTQUOTAS_NO_SPACE
)
43 ret
= SMB_QUOTAS_NO_SPACE
;
44 else if (in
== SMB_NTQUOTAS_NO_ENTRY
)
45 ret
= SMB_QUOTAS_NO_LIMIT
;
50 static uint64_t limit_unix2nt(uint64_t in
, uint64_t bsize
)
52 uint64_t ret
= (uint64_t)0;
54 ret
= (uint64_t)(in
*bsize
);
59 static uint64_t limit_blk2inodes(uint64_t in
)
61 uint64_t ret
= (uint64_t)0;
63 ret
= (uint64_t)(in
/2);
65 if (ret
== 0 && in
!= 0)
71 NTSTATUS
vfs_get_ntquota(files_struct
*fsp
, enum SMB_QUOTA_TYPE qtype
,
72 struct dom_sid
*psid
, SMB_NTQUOTA_STRUCT
*qt
)
77 struct smb_filename
*smb_fname_cwd
= NULL
;
82 if (!fsp
|| !fsp
->conn
|| !qt
) {
83 return NT_STATUS_INTERNAL_ERROR
;
90 if (psid
&& !sid_to_uid(psid
, &id
.uid
)) {
91 DEBUG(0,("sid_to_uid: failed, SID[%s]\n",
92 sid_string_dbg(psid
)));
93 return NT_STATUS_NO_SUCH_USER
;
96 smb_fname_cwd
= synthetic_smb_fname(talloc_tos(),
101 if (smb_fname_cwd
== NULL
) {
102 return NT_STATUS_NO_MEMORY
;
105 ret
= SMB_VFS_GET_QUOTA(fsp
->conn
, smb_fname_cwd
, qtype
, id
, &D
);
109 TALLOC_FREE(smb_fname_cwd
);
110 if (saved_errno
!= 0) {
118 return map_nt_error_from_unix(errno
);
121 qt
->usedspace
= (uint64_t)D
.curblocks
*D
.bsize
;
122 qt
->softlim
= limit_unix2nt(D
.softlimit
, D
.bsize
);
123 qt
->hardlim
= limit_unix2nt(D
.hardlimit
, D
.bsize
);
124 qt
->qflags
= D
.qflags
;
129 int vfs_set_ntquota(files_struct
*fsp
, enum SMB_QUOTA_TYPE qtype
, struct dom_sid
*psid
, SMB_NTQUOTA_STRUCT
*qt
)
136 if (!fsp
||!fsp
->conn
||!qt
)
141 D
.bsize
= (uint64_t)QUOTABLOCK_SIZE
;
143 D
.softlimit
= limit_nt2unix(qt
->softlim
,D
.bsize
);
144 D
.hardlimit
= limit_nt2unix(qt
->hardlim
,D
.bsize
);
145 D
.qflags
= qt
->qflags
;
147 D
.isoftlimit
= limit_blk2inodes(D
.softlimit
);
148 D
.ihardlimit
= limit_blk2inodes(D
.hardlimit
);
150 if (psid
&& !sid_to_uid(psid
, &id
.uid
)) {
151 DEBUG(0,("sid_to_uid: failed, SID[%s]\n",
152 sid_string_dbg(psid
)));
155 ret
= SMB_VFS_SET_QUOTA(fsp
->conn
, qtype
, id
, &D
);
160 static bool already_in_quota_list(SMB_NTQUOTA_LIST
*qt_list
, uid_t uid
)
162 SMB_NTQUOTA_LIST
*tmp_list
= NULL
;
167 for (tmp_list
=qt_list
;tmp_list
!=NULL
;tmp_list
=tmp_list
->next
) {
168 if (tmp_list
->uid
== uid
) {
176 int vfs_get_user_ntquota_list(files_struct
*fsp
, SMB_NTQUOTA_LIST
**qt_list
)
179 TALLOC_CTX
*mem_ctx
= NULL
;
181 if (!fsp
||!fsp
->conn
||!qt_list
)
186 if ((mem_ctx
=talloc_init("SMB_USER_QUOTA_LIST"))==NULL
) {
187 DEBUG(0,("talloc_init() failed\n"));
192 while ((usr
= getpwent()) != NULL
) {
193 SMB_NTQUOTA_STRUCT tmp_qt
;
194 SMB_NTQUOTA_LIST
*tmp_list_ent
;
200 if (already_in_quota_list((*qt_list
),usr
->pw_uid
)) {
201 DEBUG(5,("record for uid[%ld] already in the list\n",(long)usr
->pw_uid
));
205 uid_to_sid(&sid
, usr
->pw_uid
);
208 vfs_get_ntquota(fsp
, SMB_USER_QUOTA_TYPE
, &sid
, &tmp_qt
);
209 if (!NT_STATUS_IS_OK(status
)) {
210 DEBUG(5, ("failed getting quota for uid[%ld] - %s\n",
211 (long)usr
->pw_uid
, nt_errstr(status
)));
214 if (tmp_qt
.softlim
== 0 && tmp_qt
.hardlim
== 0) {
215 DEBUG(5,("no quota entry for sid[%s] path[%s]\n",
216 sid_string_dbg(&sid
),
217 fsp
->conn
->connectpath
));
221 DEBUG(15,("quota entry for id[%s] path[%s]\n",
222 sid_string_dbg(&sid
), fsp
->conn
->connectpath
));
224 if ((tmp_list_ent
=talloc_zero(mem_ctx
,SMB_NTQUOTA_LIST
))==NULL
) {
225 DEBUG(0,("TALLOC_ZERO() failed\n"));
227 talloc_destroy(mem_ctx
);
231 if ((tmp_list_ent
->quotas
=talloc_zero(mem_ctx
,SMB_NTQUOTA_STRUCT
))==NULL
) {
232 DEBUG(0,("TALLOC_ZERO() failed\n"));
234 talloc_destroy(mem_ctx
);
238 tmp_list_ent
->uid
= usr
->pw_uid
;
239 memcpy(tmp_list_ent
->quotas
,&tmp_qt
,sizeof(tmp_qt
));
240 tmp_list_ent
->mem_ctx
= mem_ctx
;
242 DLIST_ADD((*qt_list
),tmp_list_ent
);
247 if (*qt_list
== NULL
) {
248 TALLOC_FREE(mem_ctx
);
253 static int quota_handle_destructor(SMB_NTQUOTA_HANDLE
*handle
)
255 free_ntquota_list(&handle
->quota_list
);
259 void *init_quota_handle(TALLOC_CTX
*mem_ctx
)
261 SMB_NTQUOTA_HANDLE
*qt_handle
;
266 qt_handle
= talloc_zero(mem_ctx
,SMB_NTQUOTA_HANDLE
);
267 if (qt_handle
==NULL
) {
268 DEBUG(0,("TALLOC_ZERO() failed\n"));
272 talloc_set_destructor(qt_handle
, quota_handle_destructor
);
273 return (void *)qt_handle
;